graphics/: Correct logic for copy of bit maps with resolution less than 8 bits from the per-window framebuffer to the device.

This commit is contained in:
Gregory Nutt 2019-03-18 09:44:38 -06:00
parent 22f9ec6abb
commit 10b73fde9d
9 changed files with 196 additions and 46 deletions

24
TODO
View File

@ -1,4 +1,4 @@
NuttX TODO List (Last updated March 15, 2019) NuttX TODO List (Last updated March 18, 2019)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
This file summarizes known NuttX bugs, limitations, inconsistencies with This file summarizes known NuttX bugs, limitations, inconsistencies with
@ -24,7 +24,7 @@ nuttx/:
(2) Other drivers (drivers/) (2) Other drivers (drivers/)
(9) Libraries (libs/libc/, libs/libm/) (9) Libraries (libs/libc/, libs/libm/)
(12) File system/Generic drivers (fs/, drivers/) (12) File system/Generic drivers (fs/, drivers/)
(9) Graphics Subsystem (graphics/) (10) Graphics Subsystem (graphics/)
(1) Build system / Toolchains (1) Build system / Toolchains
(3) Linux/Cywgin simulation (arch/sim) (3) Linux/Cywgin simulation (arch/sim)
(5) ARM (arch/arm/) (5) ARM (arch/arm/)
@ -2450,6 +2450,26 @@ o Graphics Subsystem (graphics/)
depth. If such a beast ever shows up, then this priority would be depth. If such a beast ever shows up, then this priority would be
higher. higher.
Title: INCOMPLATE PLANAR COLOR SUPPORT
Description: The original NX design included support for planar colors,
i.e,. for devices that provide separate framebuffers for each
color component. Planar graphics hard was common some years
back but is rarely encountered today. In fact, I am not aware
of any MCU that implements planar framebuffers.
Support for planar colors is, however, unverified and
incomplete. In fact, many recent changes explicitly assume a
single color plane: Planar colors are specified by a array
of components; some recent logic uses only component [0],
ignoring the possible existence of other color componet frames.
Completely removing planar color support is one reasonable
options; it is not likely that NuttX will encounter planar
color hardware and this would greatly simplify the logic and
eliminate inconsistencies in the immplementation.
Status: Open
Priority: Low. There is no problem other than one of aesthetics.
o Build system o Build system
^^^^^^^^^^^^ ^^^^^^^^^^^^

View File

@ -62,7 +62,12 @@ config NX_RAMBACKED
window at the expense of increased memory usage. window at the expense of increased memory usage.
Redraw requests in other cases are also suppressed: Changes to window Redraw requests in other cases are also suppressed: Changes to window
position, size, etc. position, size, etc. As a consequence, some manual updates will be
required when certain events occurr (like removing a toolbar from a
window)
NOTE: A significant amount of RAM, usually external SDRAM, is
required to run this demo.
config NX_BGCOLOR config NX_BGCOLOR
hex "Initial background color" hex "Initial background color"

View File

@ -179,16 +179,11 @@ static inline void nxbe_filltrapezoid_pwfb(FAR struct nxbe_window_s *wnd,
FAR const struct nxgl_trapezoid_s *trap, FAR const struct nxgl_trapezoid_s *trap,
nxgl_mxpixel_t color[CONFIG_NX_NPLANES]) nxgl_mxpixel_t color[CONFIG_NX_NPLANES])
{ {
FAR const void *src[CONFIG_NX_NPLANES];
struct nxgl_trapezoid_s reltrap; struct nxgl_trapezoid_s reltrap;
struct nxgl_rect_s relbounds; struct nxgl_rect_s relbounds;
FAR const void *src[CONFIG_NX_NPLANES] = struct nxgl_point_s origin;
{ unsigned int bpp;
(FAR const void *)wnd->fbmem
};
struct nxgl_point_s origin =
{
0, 0
};
/* Both the rectangle that we receive here are in abolute device /* Both the rectangle that we receive here are in abolute device
* coordinates. We need to restore both to windows relative coordinates. * coordinates. We need to restore both to windows relative coordinates.
@ -207,7 +202,55 @@ static inline void nxbe_filltrapezoid_pwfb(FAR struct nxbe_window_s *wnd,
wnd->be->plane[0].pwfb.filltrapezoid(wnd, &reltrap, &relbounds, wnd->be->plane[0].pwfb.filltrapezoid(wnd, &reltrap, &relbounds,
color[0]); color[0]);
/* Copy the portion of the per-window framebuffer in the bounding box /* Get the source of address of the trapezoid bounding box in the
* framebuffer.
*/
bpp = wnd->be->plane[0].pinfo.bpp;
src[0] = (FAR const void *)
((FAR uint8_t *)wnd->fbmem +
relbounds.pt1.y * wnd->stride +
((bpp * relbounds.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 = relbounds.pt1.x;
origin.y = relbounds.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;
}
/* Copy the portion of the per-window framebuffer in the bounding box
* to the device graphics memory. * to the device graphics memory.
*/ */

View File

@ -294,14 +294,11 @@ static inline void nxbe_move_pwfb(FAR struct nxbe_window_s *wnd,
FAR const struct nxgl_rect_s *rect, FAR const struct nxgl_rect_s *rect,
FAR const struct nxgl_point_s *offset) FAR const struct nxgl_point_s *offset)
{ {
FAR const void *src[CONFIG_NX_NPLANES];
struct nxgl_point_s destpos; struct nxgl_point_s destpos;
struct nxgl_point_s origin;
struct nxgl_rect_s srcrect; struct nxgl_rect_s srcrect;
struct nxgl_rect_s destrect; struct nxgl_rect_s destrect;
FAR const void *src[CONFIG_NX_NPLANES];
FAR const struct nxgl_point_s origin =
{
0, 0
};
unsigned int bpp; unsigned int bpp;
/* The rectangle that we receive here is in abolute device coordinates. We /* The rectangle that we receive here is in abolute device coordinates. We
@ -330,23 +327,54 @@ static inline void nxbe_move_pwfb(FAR struct nxbe_window_s *wnd,
nxgl_rectoffset(&destrect, &srcrect, offset->x, offset->y); nxgl_rectoffset(&destrect, &srcrect, offset->x, offset->y);
/* Update the physical device by just copying the rectangle from the /* Get the source of address of the moved rectangle in the framebuffer. */
* framebuffer to the device graphics memory.
*
* Get the source of address of the moved rectangle in the framebuffer.
* REVISIT: 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.
*/
bpp = wnd->be->plane[0].pinfo.bpp; bpp = wnd->be->plane[0].pinfo.bpp;
src[0] = (FAR void *) src[0] = (FAR const void *)
((FAR uint8_t *)wnd->fbmem + ((FAR uint8_t *)wnd->fbmem +
destrect.pt1.y * wnd->stride + destrect.pt1.y * wnd->stride +
((bpp * destrect.pt1.x) >> 3)); ((bpp * destrect.pt1.x) >> 3));
/* Then transfer the rectangle to the destination rectangle in the /* For resolutions less than 8-bits, the starting pixel will be contained
* device memory. * 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 = destrect.pt1.x;
origin.y = destrect.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;
}
/* Update the physical device by just copying the rectangle from the
* framebuffer to the destination rectangle device graphics memory.
*/ */
nxbe_bitmap_dev(wnd, &destrect, src, &origin, wnd->stride); nxbe_bitmap_dev(wnd, &destrect, src, &origin, wnd->stride);

View File

@ -69,21 +69,62 @@ void nxmu_redrawreq(FAR struct nxbe_window_s *wnd,
if (NXBE_ISRAMBACKED(wnd)) if (NXBE_ISRAMBACKED(wnd))
{ {
FAR const void *src[CONFIG_NX_NPLANES];
struct nxgl_rect_s wndrect; struct nxgl_rect_s wndrect;
FAR const void *src[CONFIG_NX_NPLANES] = struct nxgl_point_s origin;
{ unsigned int bpp;
(FAR const void *)wnd->fbmem
};
struct nxgl_point_s origin =
{
0, 0
};
/* Put the rectangle back relative to the window */ /* Put the rectangle back relative to the window */
nxgl_rectoffset(&wndrect, rect, nxgl_rectoffset(&wndrect, rect,
-wnd->bounds.pt1.x, -wnd->bounds.pt1.y); -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 */ /* And render the bitmap */
nxbe_bitmap_dev(wnd, &wndrect, src, &origin, wnd->stride); nxbe_bitmap_dev(wnd, &wndrect, src, &origin, wnd->stride);

View File

@ -72,14 +72,23 @@
#define NXBE_WINDOW_BLOCKED (1 << 0) /* The window is blocked and will not #define NXBE_WINDOW_BLOCKED (1 << 0) /* The window is blocked and will not
* receive further input. */ * receive further input. */
#define NXBE_WINDOW_RAMBACKED (1 << 1) /* Window is backed by a framebuffer */ #define NXBE_WINDOW_FRAMED (1 << 1) /* Framed (NxTK) Window */
#define NXBE_WINDOW_RAMBACKED (1 << 2) /* Window is backed by a framebuffer */
/* Valid user flags for different window types */
#ifdef CONFIG_NX_RAMBACKED #ifdef CONFIG_NX_RAMBACKED
# define NXBE_WINDOW_USER NXBE_WINDOW_RAMBACKED # define NX_WINDOW_USER NXBE_WINDOW_RAMBACKED
# define NXTK_WINDOW_USER (NXBE_WINDOW_FRAMED | NXBE_WINDOW_RAMBACKED)
# define NXBE_WINDOW_USER (NXBE_WINDOW_FRAMED | NXBE_WINDOW_RAMBACKED)
#else #else
# define NXBE_WINDOW_USER 0 # define NX_WINDOW_USER 0
# define NXTK_WINDOW_USER NXBE_WINDOW_FRAMED
# define NXBE_WINDOW_USER NXBE_WINDOW_FRAMED
#endif #endif
/* Helpful flag macros */
#define NXBE_ISBLOCKED(wnd) \ #define NXBE_ISBLOCKED(wnd) \
(((wnd)->flags & NXBE_WINDOW_BLOCKED) != 0) (((wnd)->flags & NXBE_WINDOW_BLOCKED) != 0)
#define NXBE_SETBLOCKED(wnd) \ #define NXBE_SETBLOCKED(wnd) \
@ -87,6 +96,13 @@
#define NXBE_CLRBLOCKED(wnd) \ #define NXBE_CLRBLOCKED(wnd) \
do { (wnd)->flags &= ~NXBE_WINDOW_BLOCKED; } while (0) do { (wnd)->flags &= ~NXBE_WINDOW_BLOCKED; } while (0)
#define NXBE_ISFRAMED(wnd) \
(((wnd)->flags & NXBE_WINDOW_FRAMED) != 0)
#define NXBE_SETFRAMED(wnd) \
do { (wnd)->flags |= NXBE_WINDOW_FRAMED; } while (0)
#define NXBE_CLRFRAMED(wnd) \
do { (wnd)->flags &= ~NXBE_WINDOW_FRAMED; } while (0)
#define NXBE_ISRAMBACKED(wnd) \ #define NXBE_ISRAMBACKED(wnd) \
(((wnd)->flags & NXBE_WINDOW_RAMBACKED) != 0) (((wnd)->flags & NXBE_WINDOW_RAMBACKED) != 0)
#define NXBE_SETRAMBACKED(wnd) \ #define NXBE_SETRAMBACKED(wnd) \

View File

@ -80,7 +80,7 @@ NXWINDOW nx_openwindow(NXHANDLE handle, uint8_t flags,
int ret; int ret;
#ifdef CONFIG_DEBUG_FEATURES #ifdef CONFIG_DEBUG_FEATURES
if (!handle || !cb) if (handle == NULL || cb == NULL || (flags & ~NX_WINDOW_USER) != 0)
{ {
set_errno(EINVAL); set_errno(EINVAL);
return NULL; return NULL;

View File

@ -109,7 +109,7 @@ NXTKWINDOW nxtk_openwindow(NXHANDLE handle, uint8_t flags,
int ret; int ret;
#ifdef CONFIG_DEBUG_FEATURES #ifdef CONFIG_DEBUG_FEATURES
if (handle == NULL || cb == NULL) if (handle == NULL || cb == NULL || (flags & ~NXTK_WINDOW_USER) != 0)
{ {
set_errno(EINVAL); set_errno(EINVAL);
return NULL; return NULL;
@ -134,8 +134,8 @@ NXTKWINDOW nxtk_openwindow(NXHANDLE handle, uint8_t flags,
/* Then let nx_constructwindow do the rest */ /* Then let nx_constructwindow do the rest */
ret = nx_constructwindow(handle, (NXWINDOW)&fwnd->wnd, flags, &g_nxtkcb, ret = nx_constructwindow(handle, (NXWINDOW)&fwnd->wnd,
NULL); flags | NXBE_WINDOW_FRAMED, &g_nxtkcb, NULL);
if (ret < 0) if (ret < 0)
{ {
/* An error occurred, the window has been freed */ /* An error occurred, the window has been freed */

View File

@ -99,9 +99,6 @@ int nxtk_setsize(NXTKWINDOW hfwnd, FAR const struct nxgl_size_s *size)
* callbacks. Normally the frame is updated with every redraw callback. * callbacks. Normally the frame is updated with every redraw callback.
* However, as a minimum, the frame only has to but updated after the * However, as a minimum, the frame only has to but updated after the
* window or toolbar sizes change. * window or toolbar sizes change.
*
* REVISIT: Since this works for RAM backed windows, it should work for
* all windows. Why not simplify?
*/ */
if (ret >= 0 && NXBE_ISRAMBACKED(&fwnd->wnd)) if (ret >= 0 && NXBE_ISRAMBACKED(&fwnd->wnd))