diff --git a/TODO b/TODO index 377c941f20..387f01d6db 100644 --- a/TODO +++ b/TODO @@ -1,4 +1,4 @@ -NuttX TODO List (Last updated June 24, 2015) +NuttX TODO List (Last updated July 14, 2015) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ This file summarizes known NuttX bugs, limitations, inconsistencies with @@ -20,7 +20,7 @@ nuttx/ (4) USB (drivers/usbdev, drivers/usbhost) (12) Libraries (libc/, libm/) (11) File system/Generic drivers (fs/, drivers/) - (8) Graphics subsystem (graphics/) + (7) Graphics subsystem (graphics/) (1) Pascal add-on (pcode/) (2) Build system / Toolchains (3) Linux/Cywgin simulation (arch/sim) @@ -1516,20 +1516,6 @@ o Graphics subsystem (graphics/) Status: Open Priority: Low, the need has not yet arisen. - Title: ANTI-ALIASING - Description: Needed for proper rendering. After some analysis, I believe - this change would only be required in the the trapezoid - rendering logic. Essentially, it would need to blend the - fractional pixels at ends of each run with the underlying - pixel. - - Hmmm.. graphics are sometimes erased by just redrawing them - with the background color. Would this approach leave ghost - images around where the erase image was? - Status: Open - Priority: Medium-ish. This would definitely improve graphics rendering - and line drawing. - Title: PER-WINDOW FRAMEBUFFERS Description: One of the most awkard things to handle in the NX windowing system is the re-draw callback. This is difficult because it diff --git a/graphics/Kconfig b/graphics/Kconfig index 2a59b0f356..608619c362 100644 --- a/graphics/Kconfig +++ b/graphics/Kconfig @@ -39,6 +39,14 @@ config NX_BGCOLOR logic would have to be extended if you want to support multiple color planes. +config NX_ANTIALIASING + bool "Anti-aliasing support" + default n + depends on (!NX_DISABLE_16BPP || !NX_DISABLE_24BPP || !NX_DISABLE_32BPP) && !NX_LCDDRIVER + ---help--- + Enable support for ant-alising when rendering lines as various + orientations. + config NX_WRITEONLY bool "Write-only Graphics Device" default y if NX_LCDDRIVER && LCD_NOGETRUN diff --git a/graphics/nxglib/fb/nxglib_filltrapezoid.c b/graphics/nxglib/fb/nxglib_filltrapezoid.c index e412fff8d9..789ae7cee1 100644 --- a/graphics/nxglib/fb/nxglib_filltrapezoid.c +++ b/graphics/nxglib/fb/nxglib_filltrapezoid.c @@ -1,7 +1,7 @@ /**************************************************************************** * graphics/nxglib/fb/nxglib_filltrapezoid.c * - * Copyright (C) 2008-2012 Gregory Nutt. All rights reserved. + * Copyright (C) 2008-2012, 2015 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -50,27 +50,12 @@ /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ +/* Make sure that this file is used in the proper context */ #ifndef NXGLIB_SUFFIX # error "NXGLIB_SUFFIX must be defined before including this header file" #endif -/**************************************************************************** - * Private Types - ****************************************************************************/ - -/**************************************************************************** - * Private Data - ****************************************************************************/ - -/**************************************************************************** - * Public Data - ****************************************************************************/ - -/**************************************************************************** - * Private Functions - ****************************************************************************/ - /**************************************************************************** * Public Functions ****************************************************************************/ @@ -191,6 +176,9 @@ void NXGL_FUNCNAME(nxgl_filltrapezoid,NXGLIB_SUFFIX)( while (nrows--) { +#ifdef CONFIG_NX_ANTIALIASING + b16_t frac; +#endif int ix1; int ix2; @@ -265,12 +253,43 @@ void NXGL_FUNCNAME(nxgl_filltrapezoid,NXGLIB_SUFFIX)( NXGL_MEMSET(dest, (NXGL_PIXEL_T)color, lnlen); } -#else +#else /* NXGLIB_BITSPERPIXEL < 8 */ + /* Then draw the run from (line + ix1) to (line + ix2) */ dest = line + NXGL_SCALEX(ix1); + +#ifdef CONFIG_NX_ANTIALIASING + + /* Perform blending on the first pixel of the row */ + + frac = b16ONE - b16frac(x1); + NXGL_BLEND(dest, (NXGL_PIXEL_T)color, frac); + dest += NXGL_SCALEX(1); + width--; + + if (width > 0) + { + /* Copy pixels between the first and last pixel of the row. */ + + if (width > 1) + { + NXGL_MEMSET(dest, (NXGL_PIXEL_T)color, width-1); + } + + /* And blend the final pixel */ + + dest += NXGL_SCALEX(width-1); + frac = b16frac(x2); + NXGL_BLEND(dest, (NXGL_PIXEL_T)color, frac); + } + +#else /* CONFIG_NX_ANTIALIASING */ + NXGL_MEMSET(dest, (NXGL_PIXEL_T)color, width); -#endif + +#endif /* CONFIG_NX_ANTIALIASING */ +#endif /* NXGLIB_BITSPERPIXEL < 8 */ } /* Move to the start of the next line */ diff --git a/graphics/nxglib/nxglib_bitblit.h b/graphics/nxglib/nxglib_bitblit.h index cffdc0018d..dbcd63b7f5 100644 --- a/graphics/nxglib/nxglib_bitblit.h +++ b/graphics/nxglib/nxglib_bitblit.h @@ -58,6 +58,13 @@ # error "NXGLIB_BITSPERPIXEL must be defined before including this header file" #endif +/* Anti-aliasing can only be supported for 16-, 24-, and 32-bit RGB types */ + +#if NXGLIB_BITSPERPIXEL < 16 +# undef CONFIG_NX_ANTIALIASING +#endif + + /* Set up bit blit macros for this BPP */ #if NXGLIB_BITSPERPIXEL == 1 @@ -90,20 +97,24 @@ # define NXGL_SCALEX(x) ((x) << 1) # define NXGL_PIXEL_T uint16_t +# define NXGL_BLENDER nxglib_rgb565_blend #elif NXGLIB_BITSPERPIXEL == 24 # define NXGL_SCALEX(x) (((x) << 1) + (x)) # define NXGL_PIXEL_T uint32_t +# define NXGL_BLENDER nxglib_rgb24_blend #elif NXGLIB_BITSPERPIXEL == 32 # define NXGL_SCALEX(x) ((x) << 2) # define NXGL_PIXEL_T uint32_t +# define NXGL_BLENDER nxglib_rgb24_blend #endif #if NXGLIB_BITSPERPIXEL < 8 + # define NXGL_SCALEX(x) ((x) >> NXGL_PIXELSHIFT) # define NXGL_REMAINDERX(x) ((x) & NXGL_PIXELMASK) # define NXGL_ALIGNDOWN(x) ((x) & ~NXGL_PIXELMASK) @@ -118,6 +129,7 @@ *_ptr++ = (value); \ } \ } + # define NXGL_MEMCPY(dest,src,width) \ { \ FAR uint8_t *_dptr = (FAR uint8_t*)(dest); \ @@ -130,6 +142,7 @@ } #elif NXGLIB_BITSPERPIXEL == 24 + # define NXGL_MEMSET(dest,value,width) \ { \ FAR uint8_t *_ptr = (FAR uint8_t*)(dest); \ @@ -141,6 +154,7 @@ *_ptr++ = (value) >> 16; \ } \ } + # define NXGL_MEMCPY(dest,src,width) \ { \ FAR uint8_t *_dptr = (FAR uint8_t*)(dest); \ @@ -153,7 +167,26 @@ *_dptr++ = *_sptr++; \ } \ } -#else + +#ifdef CONFIG_NX_ANTIALIASING + +# define NXGL_BLEND(dest,color1,frac) \ + { \ + FAR uint8_t *_dptr = (FAR uint8_t*)(dest); \ + uint32_t color2; \ + uint32_t blend; \ + color2 = ((uint32_t)_dptr[0] << 16) | \ + ((uint32_t)_dptr[1] << 8) | \ + (uint32_t)_dptr[2]; \ + blend = NXGL_BLENDER(color1, color2, frac); \ + *_dptr++ = (blend >> 16) & 0xff; \ + *_dptr++ = (blend >> 8) & 0xff; \ + *_dptr++ = blend & 0xff; \ + } + +#endif /* CONFIG_NX_ANTIALIASING */ +#else /* NXGLIB_BITSPERPIXEL == 16 || NXGLIB_BITSPERPIXEL == 32 */ + # define NXGL_MEMSET(dest,value,width) \ { \ FAR NXGL_PIXEL_T *_ptr = (FAR NXGL_PIXEL_T*)(dest); \ @@ -163,6 +196,7 @@ *_ptr++ = (value); \ } \ } + # define NXGL_MEMCPY(dest,src,width) \ { \ FAR NXGL_PIXEL_T *_dptr = (FAR NXGL_PIXEL_T*)(dest); \ @@ -173,7 +207,18 @@ *_dptr++ = *_sptr++; \ } \ } -#endif + +#ifdef CONFIG_NX_ANTIALIASING + +# define NXGL_BLEND(dest,color1,frac) \ + { \ + FAR NXGL_PIXEL_T *_dptr = (FAR NXGL_PIXEL_T*)(dest); \ + NXGL_PIXEL_T color2 = *_dptr; \ + *_dptr = NXGL_BLENDER(color1, color2, frac); \ + } + +#endif /* CONFIG_NX_ANTIALIASING */ +#endif /* NXGLIB_BITSPERPIXEL */ /* Form a function name by concatenating two strings */ diff --git a/include/nuttx/nx/nxglib.h b/include/nuttx/nx/nxglib.h index d29d261f8f..e0d3f6b846 100644 --- a/include/nuttx/nx/nxglib.h +++ b/include/nuttx/nx/nxglib.h @@ -770,13 +770,8 @@ void nxgl_circletraps(FAR const struct nxgl_point_s *center, * ****************************************************************************/ -#if !defined(CONFIG_NX_DISABLE_24BPP) || !defined(CONFIG_NX_DISABLE_32BPP) uint32_t nxglib_rgb24_blend(uint32_t color1, uint32_t color2, ub16_t frac1); -#endif - -#ifndef CONFIG_NX_DISABLE_16BPP uint16_t nxglib_rgb565_blend(uint16_t color1, uint16_t color2, ub16_t frac1); -#endif #undef EXTERN #if defined(__cplusplus) diff --git a/libnx/nxglib/nxglib_rgbblend.c b/libnx/nxglib/nxglib_rgbblend.c new file mode 100644 index 0000000000..c93ad1e7ce --- /dev/null +++ b/libnx/nxglib/nxglib_rgbblend.c @@ -0,0 +1,224 @@ +/**************************************************************************** + * libnx/nxglib/nxglib_runcopy.c + * + * Copyright (C) 2008-2011, 2013 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 +#include +#include + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxglib_rgb24_blend and nxglib_rgb565_blend + * + * Description: + * Blend a single RGB color component. This is *not* alpha blending: + * component2 is assumed to be opaque and "under" a semi-transparent + * component1. + * + * The frac1 value could be though as related to the 1/alpha value for + * component1. However, the background, component2, is always treated as though + * alpha == 1. + * + * This algorithm is used to handle endpoints as part of the + * implementation of anti-aliasing without transparency. + * + * Input Parameters: + * component1 - The semi-transparent, forground 8-bit color component + * component2 - The opaque, background color component + * frac1 - The fractional amount of component1 to blend into component2 + * + * Returned Value: + * The blended 8-bit color component. + * + ****************************************************************************/ + +static uint8_t nxglib_blend_component(uint8_t component1, uint8_t component2, + ub8_t frac1) +{ + uint16_t blend; + uint32_t blendb8; + + /* Use a uint32_t for the intermediate calculation. Due to rounding this + * value could exceed ub8MAX (0xffff == 255.999..). + * + * Hmm.. that might not actually be possible but this gives me piece of + * mind and there should not be any particular overhead on a 32-bit + * processor. + */ + + blendb8 = (uint32_t)((ub16_t)component1 * frac1) + + (uint32_t)((ub16_t)component2 * (b8ONE - frac1)) + + (uint32_t)b8HALF; + + /* Now we can snap it down to 16-bits and check for the overflow condition. */ + + blend = ub8toi(blendb8); + if (blend > 255) + { + blend = 255; + } + + /* Return the blended value */ + + return (uint8_t)blend; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxglib_rgb24_blend and nxglib_rgb565_blend + * + * Description: + * Blend a foreground color onto a background color. This is *not* alpha + * blending: color2 is assumed to be opaque and "under" a semi- + * transparent color1. + * + * The frac1 value could be though as related to the 1/alpha value for + * color1. However, the background, color2, is always treated as though + * alpha == 1. + * + * This algorithm is used to handle endpoints as part of the + * implementation of anti-aliasing without transparency. + * + * Input Parameters: + * color1 - The semi-transparent, forground color + * color2 - The opaque, background color + * frac1 - The fractional amount of color1 to blend into color2 + * + * Returned Value: + * The blended color, encoded just was the input color1 and color2 + * + ****************************************************************************/ + +#if !defined(CONFIG_NX_DISABLE_24BPP) || !defined(CONFIG_NX_DISABLE_32BPP) +uint32_t nxglib_rgb24_blend(uint32_t color1, uint32_t color2, ub16_t frac1) +{ + uint8_t r; + uint8_t g; + uint8_t b; + uint8_t bg; + ub8_t fracb8; + + /* Convert the fraction to ub8_t. We don't need that much precision to + * scale an 8-bit color component. + */ + + fracb8 = ub16toub8(frac1); + + /* Some limit checks. Rounding in the b16 to b8 conversion could cause + * the fraction exceed one; the loss of precision could cause small b16 + * values to convert to zero. + */ + + if (fracb8 >= b8ONE) + { + return color1; + } + else if (fracb8 == 0) + { + return color2; + } + + /* Separate and blend each component */ + + r = RGB24RED(color1); + bg = RGB24RED(color2); + r = nxglib_blend_component(r, bg, fracb8); + + g = RGB24GREEN(color1); + bg = RGB24GREEN(color2); + g = nxglib_blend_component(g, bg, fracb8); + + b = RGB24BLUE(color1); + bg = RGB24BLUE(color2); + b = nxglib_blend_component(b, bg, fracb8); + + /* Recombine and return the blended value */ + + return RGBTO24(r,g,b) ; +} +#endif + +#ifndef CONFIG_NX_DISABLE_16BPP +uint16_t nxglib_rgb565_blend(uint16_t color1, uint16_t color2, ub16_t frac1) +{ + uint8_t r; + uint8_t g; + uint8_t b; + uint8_t bg; + ub8_t fracb8; + + /* Convert the fraction to ub8_t. We don't need that much precision. */ + + fracb8 = ub16toub8(frac1); + + /* Some limit checks */ + + if (fracb8 >= b8ONE) + { + return color1; + } + else if (fracb8 == 0) + { + return color2; + } + + /* Separate and blend each component */ + + r = RGB16RED(color1); + bg = RGB16RED(color2); + r = nxglib_blend_component(r, bg, fracb8); + + g = RGB16GREEN(color1); + bg = RGB16GREEN(color2); + g = nxglib_blend_component(g, bg, fracb8); + + b = RGB16BLUE(color1); + bg = RGB16BLUE(color2); + b = nxglib_blend_component(b, bg, fracb8); + + /* Recombine and return the blended value */ + + return RGBTO24(r,g,b) ; +} +#endif