Implement anti-aliasing in the NuttX graphics line drawing

This commit is contained in:
Gregory Nutt 2015-07-14 10:17:42 -06:00
parent 4bcd13eabd
commit 83f26091f4
6 changed files with 319 additions and 42 deletions

18
TODO
View File

@ -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

View File

@ -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

View File

@ -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 <gnutt@nuttx.org>
*
* 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 */

View File

@ -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 */

View File

@ -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)

View File

@ -0,0 +1,224 @@
/****************************************************************************
* libnx/nxglib/nxglib_runcopy.c
*
* Copyright (C) 2008-2011, 2013 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 <stdint.h>
#include <fixedmath.h>
#include <nuttx/video/rgbcolors.h>
/****************************************************************************
* 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