diff --git a/graphics/nxbe/nxbe_cursor.c b/graphics/nxbe/nxbe_cursor.c index 19ec96a3bb4..76139171445 100644 --- a/graphics/nxbe/nxbe_cursor.c +++ b/graphics/nxbe/nxbe_cursor.c @@ -89,32 +89,130 @@ static nxgl_mxcolor_t nxbe_map_color(FAR struct nxbe_state_s *be, int plane, } /**************************************************************************** - * Name: nxbe_cursor_update + * Name: nxbe_cursor_erasedev * * Description: - * Update the cursor region + * Erase the cursor region by writing the saved background to the graphics + * device memory. + * + * REVISIT: This is experimental logic. Its use is restricted to frame- + * buffer device drivers with resolution >= 8 bits-per-pixel. * * Input Parameters: - * be - The back-end state structure instance + * be - The back-end state structure instance + * plane - The color plane being drawn * * Returned Value: * None * ****************************************************************************/ -static void nxbe_cursor_update(FAR struct nxbe_state_s *be, int plane) +static void nxbe_cursor_erasedev(FAR struct nxbe_state_s *be, int plane) { struct nxgl_rect_s intersection; + struct nxgl_point_s origin; + FAR struct nxbe_plane_s *plane; + FAR uint8_t *fbmem; + FAR uint8_t *sline; + FAR uint8_t *dline; + FAR uint8_t *dstart; + FAR NXGL_PIXEL_T *src; + FAR NXGL_PIXEL_T *dest; + nxgl_coord_t width; + nxgl_coord_t height; + nxgl_coord_t sstride; + nxgl_coord_t dstride; + int row; + int col; + + /* Handle the case some or all of the cursor image is off of the display. */ + + nxgl_rectintersect(&intersction, &be->cursor.bounds, &be->backgd.bounds); + if (!nxgl_nullrect(&intersection)) + { + /* Get the width and the height of the images in pixels/rows */ + + width = be->cursor.bounds.pt2.x = be->cursor.bounds.pt1.x + 1; + height = be->cursor.bounds.pt2.y = be->cursor.bounds.pt1.xy + 1; + + /* Get the width of the images in bytes. */ + + sstride = NXGL_SCALEX(width); + + plane = &wnd->be->plane[0]; + dstride = plane->pinfo.stride; + + /* Get the origin position in the baclgroimd image */ + + nxgl_vectorsubtract(&origin, &intersectioni.pt1, &be->cursor.bounds.pt1); + + /* Get the source and destination addresses */ + + fbmem = (FAR uint8_t *)plane->pinfo.fbmem; + sline = be->cursor.buf + sstride * origin.y + NXGL_SCALEX(origin.y); + dline = (FAR uint8_t *)fbmem + dstride * be->cursor.bounds.pt1.y + + NXGL_SCALEX(be->cursor.bounds.pt1.x); + + /* Erase the old cursor position by copying the previous content */ + + /* Loop for each row */ + + for (row = 0; row < height; row++) + { + /* Reset to the beginning of the line */ + + src = (FAR NXGL_PIXEL_T *)sline; + dest = (FAR NXGL_PIXEL_T *)dline; + + /* Loop for each column */ + + for (col = 0; col < width; col++) + { + *dest++ = *src++; + } + + /* Update the row addresses to the next row */ + + sline += sstride; + dline += dstride; + } + } +} + +/**************************************************************************** + * Name: nxbe_cursor_drawdev + * + * Description: + * Update the cursor region directly in device memory. + * + * REVISIT: This is experimental logic. Its use is restricted to frame- + * buffer device drivers with resolution >= 8 bits-per-pixel. + * + * Input Parameters: + * be - The back-end state structure instance + * plane - The color plane being drawn + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void nxbe_cursor_drawdev(FAR struct nxbe_state_s *be, int plane) +{ + struct nxgl_rect_s intersection; + struct nxgl_point_s origin; FAR struct nxbe_plane_s *plane; - FAR unsigned int *sstride; - FAR unsigned int *dstride; FAR uint8_t *fbmem; FAR uint8_t *src; FAR uint8_t *sline; - FAR NXGL_PIXEL_T *dest; FAR uint8_t *dline; + FAR NXGL_PIXEL_T *dest; nxgl_coord_t width; nxgl_coord_t height; + nxgl_coord_t sstride; + nxgl_coord_t dstride; + nxgl_coord_t sshift; + int shift; int row; int col; @@ -135,8 +233,9 @@ static void nxbe_cursor_update(FAR struct nxbe_state_s *be, int plane) plane = &wnd->be->plane[0]; dstride = plane->pinfo.stride; - /* Erase the old cursor position */ -#warning Missing logic + /* Get the origin position in the cursor image */ + + nxgl_vectorsubtract(&origin, &intersectioni.pt1, &be->cursor.bounds.pt1); /* Update any cursor graphics on top of the device display to include * the modified cursor. @@ -146,70 +245,66 @@ static void nxbe_cursor_update(FAR struct nxbe_state_s *be, int plane) */ fbmem = (FAR uint8_t *)plane->pinfo.fbmem; - sline = be->cursor.image; + sline = be->cursor.image + sstride * origin.y + (origin.y >> 2); dline = (FAR uint8_t *)fbmem + dstride * be->cursor.bounds.pt1.y + - NXGL_SCALEX(be->cursor.bounds.pt1.x); + NXGL_SCALEX(be->cursor.bounds.pt1.x); + + sshift = (3 - (origin.y & 3)) << 1; /* MS first {0, 2, 4, 6} */ + + /* Loop for each row */ for (row = 0; row < height; row++) { - src = sline; - dest = (FAR NXGL_PIXEL_T *)dline; + /* Reset to the beginning of the line */ - for (col = 0; col < width; ) + src = sline; + dest = (FAR NXGL_PIXEL_T *)dline; + shift = sshift; + + /* Loop for each column */ + + for (col = 0; col < width; col++) { - /* Data is always packed MS first */ + /* Extract the 2-bit pixel. Data is always packed MS first. + * Shift for first pixel=6, shift for last pixel=0 + */ + + uint8_t spixel = (*src & >> shift) & 3 + + /* Skip over invisible pixels */ - uint8_t spixel = (*src & >> 6) & 3 if (pixel != 0) { *dest = nxbe_map_color(be, 0, spixel); } + /* Update to the next column */ + col++; dest++; - if (col < width) + /* Was that the last pixel in the byte? */ + + if (shift == 0) { - spixel = (*src & >> 4) & 3 - if (pixel != 0) - { - *dest = nxbe_map_color(be, 0, spixel); - } + /* Update source column addresses and reset the shift + * value + */ + + src++; + shift = 6; } + else + { + /* The shift value is one of {2, 4, 6}. Update the shift + * value following this order: 6, 4, 2, 0 + */ - col++; - dest++; - - if (col < width) - { - spixel = (*src & >> 2) & 3 - if (pixel != 0) - { - *dest = nxbe_map_color(be, 0, spixel); - } - } - - col++; - dest++; - - if (col < width) - { - spixel = *src & 3 - if (pixel != 0) - { - *dest = nxbe_map_color(be, 0, spixel); - } - } - - col++; - dest++; - - /* Update source column addresses */ - - src++; + shift = (shift - 2) & 6; + } } - /* Update the row addresses */ + /* Update the row addresses to the next row */ sline += sstride; dline += dstride; @@ -265,7 +360,8 @@ void nxbe_cursor_enable(FAR struct nxbe_state_s *be, bool enable) #ifdef CONFIG_NX_SWCURSOR /* For the software cursor, we need to update the cursor region */ - nxbe_cursor_update(be); + nxbe_cursor_erasedev(be, 0); + nxbe_cursor_drawdev(be, 0); #else /* For a hardware cursor, this would require some interaction with the * grahics device.