graphics/: Fix an oversight in the implementation of per-window framebuffers. It is true that redraw callbacks can be supporessed for all cases ... EXCEPT ONE: When the window is resized to a larger size, then the newly exposed territory must be drawn for the first time.

This commit is contained in:
Gregory Nutt 2019-05-16 09:18:33 -06:00
parent 4676470dd7
commit a40ef12895
14 changed files with 287 additions and 170 deletions

View file

@ -12,7 +12,7 @@
<h1><big><font color="#3c34ec">
<i>NX Graphics Subsystem</i>
</font></big></h1>
<p>Last Updated: May 9, 2019</p>
<p>Last Updated: May 16, 2019</p>
</td>
</tr>
</table>
@ -3775,6 +3775,11 @@ int nxcursor_setposition(NXHANDLE hnd, FAR const struct nxgl_point_s *pos);
If this option is selected, then the system will redraw the exposed portion of the window from the backup framebuffer without intervention of the window applications.
This greatly reduces the complexity of the application and performance of the window at the expense of increased memory usage.
</p>
<p>
An exception is the case when the window is resized to a wider and/or taller size.
In that case, the redraw callback will till occur.
It is necessary in that case to provide new graphic content for the extended window area.
</p>
<p>
Redraw requests in other cases are also suppressed: Changes to window position, size, etc.
</p>

View file

@ -62,7 +62,17 @@ config NX_RAMBACKED
Redraw requests in other cases are also suppressed: Changes to window
position, size, etc. As a consequence, some manual updates will be
required when certain events occurr (like removing a toolbar from a
required when certain events occur (like removing a toolbar from a
window).
An exception is the case when the window is resized to a wider and/or
taller size. In that case, the redraw callback will till occur.
It is necessary in that case to provide new graphic content for the
extended window area.
Redraw requests in other cases are also suppressed: Changes to window
position, size, etc. As a consequence, some manual updates will be
required when certain events occur (like removing a toolbar from a
window).
NOTE: A significant amount of RAM, usually external SDRAM, may be

View file

@ -131,7 +131,7 @@ static void nxbe_clipmoveobscured(FAR struct nxbe_clipops_s *cops,
struct nxgl_rect_s dst;
nxgl_rectoffset(&dst, rect, info->offset.x, info->offset.y);
nxmu_redrawreq(info->wnd, &dst);
nxmu_redraw(info->wnd, &dst);
}
/****************************************************************************
@ -168,7 +168,7 @@ static void nxbe_clipmovedest(FAR struct nxbe_clipops_s *cops,
{
if (!nxgl_nullrect(&nonintersecting[i]))
{
nxmu_redrawreq(dstdata->wnd, &nonintersecting[i]);
nxmu_redraw(dstdata->wnd, &nonintersecting[i]);
}
}

View file

@ -140,6 +140,6 @@ void nxbe_raise(FAR struct nxbe_window_s *wnd)
* that it is not obscured by another window
*/
nxmu_redrawreq(wnd, &wnd->bounds);
nxmu_redraw(wnd, &wnd->bounds);
}
}

View file

@ -72,7 +72,7 @@ static void nxbe_clipredraw(FAR struct nxbe_clipops_s *cops,
FAR struct nxbe_window_s *wnd = ((struct nxbe_redraw_s *)cops)->wnd;
if (wnd)
{
nxmu_redrawreq(wnd, rect);
nxmu_redraw(wnd, rect);
}
}

View file

@ -64,6 +64,10 @@
# define MIN(a,b) ((a < b) ? a : b)
#endif
#ifndef MAX
# define MAX(a,b) ((a > b) ? a : b)
#endif
/****************************************************************************
* Private Functions
****************************************************************************/
@ -88,9 +92,11 @@ static void nxbe_realloc(FAR struct nxbe_window_s *wnd,
FAR nxgl_mxpixel_t *newfb;
FAR uint8_t *src;
FAR uint8_t *dest;
struct nxgl_rect_s bounds;
nxgl_coord_t minheight;
nxgl_coord_t newwidth;
nxgl_coord_t newheight;
nxgl_coord_t oldwidth;
nxgl_coord_t oldheight;
nxgl_coord_t row;
size_t newfbsize;
@ -112,10 +118,12 @@ static void nxbe_realloc(FAR struct nxbe_window_s *wnd,
if (NXBE_ISRAMBACKED(wnd))
{
oldwidth = oldbounds->pt2.x - oldbounds->pt1.x + 1;
oldheight = oldbounds->pt2.y - oldbounds->pt1.y + 1;
newwidth = wnd->bounds.pt2.x - wnd->bounds.pt1.x + 1;
newheight = wnd->bounds.pt2.y - wnd->bounds.pt1.y + 1;
bpp = wnd->be->plane[0].pinfo.bpp;
newstride = (bpp * newwidth + 7) >> 3;
newfbsize = newstride * newheight;
@ -205,6 +213,42 @@ static void nxbe_realloc(FAR struct nxbe_window_s *wnd,
#endif
wnd->stride = newstride;
wnd->fbmem = newfb;
/* If the window became wider, then send a message requesting an update
* of the new territory on the right.
*/
if (oldwidth < newwidth)
{
/* Get a bounding box in device coordinates */
bounds.pt1.x = wnd->bounds.pt1.x + oldwidth;
bounds.pt1.y = wnd->bounds.pt1.y;
bounds.pt2.x = wnd->bounds.pt2.x;
bounds.pt2.y = wnd->bounds.pt2.y + MIN(oldheight, newheight) - 1;
/* Send the redraw request */
nxmu_redrawreq(wnd, &bounds);
}
/* If the window became taller, then send a message requesting an update
* of the new territory at the bottom.
*/
if (oldheight < newheight)
{
/* Get a bounding box in device coordinates */
bounds.pt1.x = wnd->bounds.pt1.x;
bounds.pt1.y = wnd->bounds.pt1.y + oldheight;
bounds.pt2.x = wnd->bounds.pt2.x;
bounds.pt2.y = wnd->bounds.pt2.y;
/* Send the redraw request */
nxmu_redrawreq(wnd, &bounds);
}
}
}
#else
@ -246,6 +290,12 @@ void nxbe_setsize(FAR struct nxbe_window_s *wnd,
nxgl_rectintersect(&wnd->bounds, &wnd->bounds, &wnd->be->bkgd.bounds);
/* Report the new size/position. The application needs to know the new
* size before getting redraw requests.
*/
nxmu_reportposition(wnd);
/* Re-allocate the per-window framebuffer memory for the new window size. */
nxbe_realloc(wnd, &bounds);
@ -257,10 +307,6 @@ void nxbe_setsize(FAR struct nxbe_window_s *wnd,
nxgl_rectunion(&bounds, &bounds, &wnd->bounds);
/* Report the new size/position */
nxmu_reportposition(wnd);
/* Then redraw this window AND all windows below it. Having resized the
* window, we may have exposed previoulsy obscured portions of windows
* below this one.

View file

@ -105,7 +105,7 @@ void nxbe_show_window(FAR struct nxbe_window_s *wnd)
* that it is not obscured by another window. Just redraw it.
*/
nxmu_redrawreq(wnd, &wnd->bounds);
nxmu_redraw(wnd, &wnd->bounds);
}
}

View file

@ -33,7 +33,7 @@
#
############################################################################
CSRCS += nxmu_kbdin.c nxmu_mouse.c nxmu_openwindow.c nxmu_redrawreq.c
CSRCS += nxmu_kbdin.c nxmu_mouse.c nxmu_openwindow.c nxmu_redraw.c
CSRCS += nxmu_releasebkgd.c nxmu_requestbkgd.c nxmu_reportposition.c
CSRCS += nxmu_sendclient.c nxmu_sendclientwindow.c nxmu_server.c
CSRCS += nxmu_start.c

View file

@ -205,13 +205,28 @@ void nxmu_reportposition(FAR struct nxbe_window_s *wnd);
* Name: nxmu_redrawreq
*
* Description:
* Request the client that has this window to redraw the rectangular region.
* Send a message to the client requesting that it to redraw the rectangular
* region in the window.
*
****************************************************************************/
void nxmu_redrawreq(FAR struct nxbe_window_s *wnd,
FAR const struct nxgl_rect_s *rect);
/****************************************************************************
* Name: nxmu_redraw
*
* Description:
* Redraw client window data. This may involve either sending a message
* to the client requesting that it redraw a region of the window. Or, in
* the base that the window supports a per-window framebuffer, this might
* amount to an immediate redraw from the framebuffer.
*
****************************************************************************/
void nxmu_redraw(FAR struct nxbe_window_s *wnd,
FAR const struct nxgl_rect_s *rect);
/****************************************************************************
* Name: nxmu_mouseinit
*

195
graphics/nxmu/nxmu_redraw.c Normal file
View file

@ -0,0 +1,195 @@
/****************************************************************************
* graphics/nxmu/nxmu_redraw.c
*
* Copyright (C) 2008-2009, 2011-2012, 2019 Gregory Nutt. All rights
* reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <stdbool.h>
#include <errno.h>
#include <debug.h>
#include <nuttx/nx/nx.h>
#include "nxmu.h"
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: nxmu_redraw_pwfb
*
* Description:
* Redraw into the per-window framebuffer
*
****************************************************************************/
#ifdef CONFIG_NX_RAMBACKED
static inline void nxmu_redraw_pwfb(FAR struct nxbe_window_s *wnd,
FAR const struct nxgl_rect_s *rect)
{
FAR const void *src[CONFIG_NX_NPLANES];
struct nxgl_rect_s wndrect;
struct nxgl_point_s origin;
unsigned int bpp;
/* Put the rectangle back relative to the window */
nxgl_rectoffset(&wndrect, rect,
-wnd->bounds.pt1.x, -wnd->bounds.pt1.y);
/* Get the source of address of the rectangle in the framebuffer. */
bpp = wnd->be->plane[0].pinfo.bpp;
src[0] = (FAR const void *)((FAR uint8_t *)wnd->fbmem +
wndrect.pt1.y * wnd->stride +
((bpp * wndrect.pt1.x) >> 3));
/* For resolutions less than 8-bits, the starting pixel will be contained
* in the byte pointed to by src[0]but may not be properly aligned for the
* transfer. We fix this by modifying the origin.
*/
origin.x = wndrect.pt1.x;
origin.y = wndrect.pt1.y;
switch (bpp)
{
#ifndef CONFIG_NX_DISABLE_1BPP
case 1: /* 1 bit per pixel */
{
origin.x &= ~7;
}
break;
#endif
#ifndef CONFIG_NX_DISABLE_2BPP
case 2: /* 2 bits per pixel */
{
origin.x &= ~3;
}
break;
#endif
#ifndef CONFIG_NX_DISABLE_4BPP
case 4: /* 4 bits per pixel */
{
origin.x &= ~1;
}
break;
#endif
default:
break;
}
/* And render the bitmap into device graphics memory */
nxbe_flush(wnd, &wndrect, src, &origin, wnd->stride);
}
#endif
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: nxmu_redrawreq
*
* Description:
* Send a message to the client requesting that it to redraw the rectangular
* region in the window.
*
****************************************************************************/
void nxmu_redrawreq(FAR struct nxbe_window_s *wnd,
FAR const struct nxgl_rect_s *rect)
{
struct nxclimsg_redraw_s outmsg;
/* Send the client redraw message */
outmsg.msgid = NX_CLIMSG_REDRAW;
outmsg.wnd = wnd;
outmsg.more = false;
nxgl_rectoffset(&outmsg.rect, rect,
-wnd->bounds.pt1.x, -wnd->bounds.pt1.y);
(void)nxmu_sendclientwindow(wnd, &outmsg,
sizeof(struct nxclimsg_redraw_s));
}
/****************************************************************************
* Name: nxmu_redraw
*
* Description:
* Redraw client window data. This may involve either sending a message
* to the client requesting that it redraw a region of the window. Or, in
* the base that the window supports a per-window framebuffer, this might
* amount to an immediate redraw from the framebuffer.
*
****************************************************************************/
void nxmu_redraw(FAR struct nxbe_window_s *wnd,
FAR const struct nxgl_rect_s *rect)
{
/* Don't update hidden windows */
if (!NXBE_ISHIDDEN(wnd))
{
#ifdef CONFIG_NX_RAMBACKED
/* If this window supports a pre-window frame buffer, then we can just
* update the device content from that framebuffer.
*/
if (NXBE_ISRAMBACKED(wnd))
{
nxmu_redraw_pwfb(wnd, rect);
}
/* Otherwise, send a message to the client requesting an update of the
* affected region in the window.
*/
else
#endif
{
nxmu_redrawreq(wnd, rect);
}
}
}

View file

@ -1,154 +0,0 @@
/****************************************************************************
* graphics/nxmu/nxmu_redrawreq.c
*
* Copyright (C) 2008-2009, 2011-2012, 2019 Gregory Nutt. All rights
* reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <stdbool.h>
#include <errno.h>
#include <debug.h>
#include <nuttx/nx/nx.h>
#include "nxmu.h"
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: nxmu_redrawreq
*
* Description:
* Request the client that has this window to redraw the rectangular region.
*
****************************************************************************/
void nxmu_redrawreq(FAR struct nxbe_window_s *wnd,
FAR const struct nxgl_rect_s *rect)
{
#ifdef CONFIG_NX_RAMBACKED
/* If this window supports a pre-window frame buffer, then we can just
* update the device content from that framebuffer.
*/
if (NXBE_ISRAMBACKED(wnd) && !NXBE_ISHIDDEN(wnd))
{
/* But don't update hidden windows */
if (!NXBE_ISHIDDEN(wnd))
{
FAR const void *src[CONFIG_NX_NPLANES];
struct nxgl_rect_s wndrect;
struct nxgl_point_s origin;
unsigned int bpp;
/* Put the rectangle back relative to the window */
nxgl_rectoffset(&wndrect, rect,
-wnd->bounds.pt1.x, -wnd->bounds.pt1.y);
/* Get the source of address of the rectangle in the framebuffer. */
bpp = wnd->be->plane[0].pinfo.bpp;
src[0] = (FAR const void *)
((FAR uint8_t *)wnd->fbmem +
wndrect.pt1.y * wnd->stride +
((bpp * wndrect.pt1.x) >> 3));
/* For resolutions less than 8-bits, the starting pixel will be
* contained in the byte pointed to by src[0]but may not be
* properly aligned for the transfer. We fix this by modifying
* the origin.
*/
origin.x = wndrect.pt1.x;
origin.y = wndrect.pt1.y;
switch (bpp)
{
#ifndef CONFIG_NX_DISABLE_1BPP
case 1: /* 1 bit per pixel */
{
origin.x &= ~7;
}
break;
#endif
#ifndef CONFIG_NX_DISABLE_2BPP
case 2: /* 2 bits per pixel */
{
origin.x &= ~3;
}
break;
#endif
#ifndef CONFIG_NX_DISABLE_4BPP
case 4: /* 4 bits per pixel */
{
origin.x &= ~1;
}
break;
#endif
default:
break;
}
/* And render the bitmap into device graphics memory */
nxbe_flush(wnd, &wndrect, src, &origin, wnd->stride);
}
}
else
#endif
{
struct nxclimsg_redraw_s outmsg;
/* Send the client redraw message */
outmsg.msgid = NX_CLIMSG_REDRAW;
outmsg.wnd = wnd;
outmsg.more = false;
nxgl_rectoffset(&outmsg.rect, rect,
-wnd->bounds.pt1.x, -wnd->bounds.pt1.y);
(void)nxmu_sendclientwindow(wnd, &outmsg,
sizeof(struct nxclimsg_redraw_s));
}
}

View file

@ -80,5 +80,5 @@ void nxmu_releasebkgd(FAR struct nxmu_state_s *nxmu)
/* Redraw the background window */
nxmu_redrawreq(&be->bkgd, &be->bkgd.bounds);
nxmu_redraw(&be->bkgd, &be->bkgd.bounds);
}

View file

@ -89,7 +89,7 @@ void nxmu_requestbkgd(FAR struct nxmu_conn_s *conn,
/* Redraw the background window */
nxmu_redrawreq(&be->bkgd, &be->bkgd.bounds);
nxmu_redraw(&be->bkgd, &be->bkgd.bounds);
#ifdef CONFIG_NX_XYINPUT
/* Provide the mouse settings */

View file

@ -551,7 +551,7 @@ int nx_runinstance(FAR const char *mqname, FAR NX_DRIVERTYPE *dev)
case NX_SVRMSG_REDRAWREQ: /* Request re-drawing of rectangular region */
{
FAR struct nxsvrmsg_redrawreq_s *redrawmsg = (FAR struct nxsvrmsg_redrawreq_s *)buffer;
nxmu_redrawreq(redrawmsg->wnd, &redrawmsg->rect);
nxmu_redraw(redrawmsg->wnd, &redrawmsg->rect);
}
break;