Implement anti-aliasing in the NuttX graphics line drawing
This commit is contained in:
parent
4bcd13eabd
commit
83f26091f4
18
TODO
18
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
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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)
|
||||
|
224
libnx/nxglib/nxglib_rgbblend.c
Normal file
224
libnx/nxglib/nxglib_rgbblend.c
Normal 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
|
Loading…
Reference in New Issue
Block a user