Commit 59ef309e authored by Alexei Podtelezhnikov's avatar Alexei Podtelezhnikov

[graph] Reduce color conversions in the blender (part 2).

* graph/gblender.h (GBlenderBGR): Define color channel storage.
* graph/gblblit.c (GDST_CHANNELS): Redefined.
(GDST_READ): Merged into...
(GDST_PIX): Redefined.
* graph/gblany.h (*): Major revisions.
parent ab324d30
2021-01-21 Alexei Podtelezhnikov <apodtele@gmail.com>
[graph] Reduce color conversions in the blender (part 2).
* graph/gblender.h (GBlenderBGR): Define color channel storage.
* graph/gblblit.c (GDST_CHANNELS): Redefined.
(GDST_READ): Merged into...
(GDST_PIX): Redefined.
* graph/gblany.h (*): Major revisions.
2021-01-21 Alexei Podtelezhnikov <apodtele@gmail.com>
* graph/gblender.h (GBLENDER_CHANNEL_VARS): Squash reintroduced bug.
......
......@@ -8,10 +8,6 @@
#error "GDST_TYPE not defined"
#endif
#ifndef GDST_READ
#error "GDST_READ not defined"
#endif
#ifdef GBLENDER_STORE_BYTES
# ifndef GDST_STOREB
# error "GDST_STOREB not defined"
......@@ -53,9 +49,9 @@ GCONCAT( _gblender_spans_, GDST_TYPE )( int y,
grColor color = surface->color;
GBlender blender = surface->gblender;
GDST_PIX;
GDST_PIX( fore, &color );
GBLENDER_VARS(blender,pix);
GBLENDER_VARS( blender, fore );
unsigned char* dst_origin = surface->origin - y * surface->bitmap.pitch;
......@@ -73,9 +69,7 @@ GCONCAT( _gblender_spans_, GDST_TYPE )( int y,
else if ( a )
for ( ; w-- ; dst += GDST_INCR )
{
GBlenderPixel back;
GDST_READ(dst,back);
GDST_PIX( back, dst);
GBLENDER_LOOKUP( blender, back );
......@@ -97,9 +91,9 @@ GCONCAT( _gblender_blit_gray8_, GDST_TYPE )( GBlenderBlit blit,
{
GBlender blender = blit->blender;
GDST_PIX;
GDST_PIX( fore, &color );
GBLENDER_VARS(blender,pix);
GBLENDER_VARS( blender, fore );
int h = blit->height;
const unsigned char* src_line = blit->src_line + blit->src_x;
......@@ -125,9 +119,7 @@ GCONCAT( _gblender_blit_gray8_, GDST_TYPE )( GBlenderBlit blit,
}
else
{
GBlenderPixel back;
GDST_READ(dst,back);
GDST_PIX( back, dst );
GBLENDER_LOOKUP( blender, back );
......@@ -158,9 +150,9 @@ GCONCAT( _gblender_blit_hrgb_, GDST_TYPE )( GBlenderBlit blit,
{
GBlender blender = blit->blender;
GDST_CHANNELS;
GDST_CHANNELS( fore, &color );
GBLENDER_CHANNEL_VARS(blender,r,g,b);
GBLENDER_CHANNEL_VARS( blender, fore.r, fore.g, fore.b );
int h = blit->height;
const unsigned char* src_line = blit->src_line + blit->src_x*3;
......@@ -191,36 +183,15 @@ GCONCAT( _gblender_blit_hrgb_, GDST_TYPE )( GBlenderBlit blit,
}
else
{
GBlenderPixel back;
int pix_r, pix_g, pix_b;
GDST_READ(dst,back);
{
unsigned int back_r = (back >> 16) & 255;
GBLENDER_LOOKUP_R( blender, back_r );
pix_r = _grcells[ar];
}
{
unsigned int back_g = (back >> 8) & 255;
GDST_CHANNELS( back, dst );
GBLENDER_LOOKUP_G( blender, back_g );
GBLENDER_LOOKUP_R( blender, back.r );
pix_g = _ggcells[ag];
}
GBLENDER_LOOKUP_G( blender, back.g );
{
unsigned int back_b = (back) & 255;
GBLENDER_LOOKUP_B( blender, back.b );
GBLENDER_LOOKUP_B( blender, back_b );
pix_b = _gbcells[ab];
}
GDST_STOREC(dst,pix_r,pix_g,pix_b);
GDST_STOREC( dst, _grcells[ar], _ggcells[ag], _gbcells[ab] );
}
src += 3;
......@@ -243,9 +214,9 @@ GCONCAT( _gblender_blit_hbgr_, GDST_TYPE )( GBlenderBlit blit,
{
GBlender blender = blit->blender;
GDST_CHANNELS;
GDST_CHANNELS( fore, &color );
GBLENDER_CHANNEL_VARS(blender,r,g,b);
GBLENDER_CHANNEL_VARS( blender, fore.r, fore.g, fore.b );
int h = blit->height;
const unsigned char* src_line = blit->src_line + blit->src_x*3;
......@@ -276,36 +247,15 @@ GCONCAT( _gblender_blit_hbgr_, GDST_TYPE )( GBlenderBlit blit,
}
else
{
GBlenderPixel back;
int pix_r, pix_g, pix_b;
GDST_READ(dst,back);
{
unsigned int back_r = (back >> 16) & 255;
GBLENDER_LOOKUP_R( blender, back_r );
pix_r = _grcells[ar];
}
{
unsigned int back_g = (back >> 8) & 255;
GBLENDER_LOOKUP_G( blender, back_g );
GDST_CHANNELS( back, dst );
pix_g = _ggcells[ag];
}
GBLENDER_LOOKUP_R( blender, back.r );
{
unsigned int back_b = (back) & 255;
GBLENDER_LOOKUP_G( blender, back.g );
GBLENDER_LOOKUP_B( blender, back_b );
GBLENDER_LOOKUP_B( blender, back.b );
pix_b = _gbcells[ab];
}
GDST_STOREC(dst,pix_r,pix_g,pix_b);
GDST_STOREC( dst, _grcells[ar], _ggcells[ag], _gbcells[ab] );
}
src += 3;
......@@ -328,9 +278,9 @@ GCONCAT( _gblender_blit_vrgb_, GDST_TYPE )( GBlenderBlit blit,
{
GBlender blender = blit->blender;
GDST_CHANNELS;
GDST_CHANNELS( fore, &color );
GBLENDER_CHANNEL_VARS(blender,r,g,b);
GBLENDER_CHANNEL_VARS( blender, fore.r, fore.g, fore.b );
int h = blit->height;
int src_pitch = blit->src_pitch;
......@@ -362,36 +312,15 @@ GCONCAT( _gblender_blit_vrgb_, GDST_TYPE )( GBlenderBlit blit,
}
else
{
GBlenderPixel back;
int pix_r, pix_g, pix_b;
GDST_READ(dst,back);
{
unsigned int back_r = (back >> 16) & 255;
GBLENDER_LOOKUP_R( blender, back_r );
pix_r = _grcells[ar];
}
{
unsigned int back_g = (back >> 8) & 255;
GBLENDER_LOOKUP_G( blender, back_g );
pix_g = _ggcells[ag];
}
GDST_CHANNELS( back, dst );
{
unsigned int back_b = (back) & 255;
GBLENDER_LOOKUP_R( blender, back.r );
GBLENDER_LOOKUP_B( blender, back_b );
GBLENDER_LOOKUP_G( blender, back.g );
pix_b = _gbcells[ab];
}
GBLENDER_LOOKUP_B( blender, back.b );
GDST_STOREC(dst,pix_r,pix_g,pix_b);
GDST_STOREC( dst, _grcells[ar], _ggcells[ag], _gbcells[ab] );
}
src += 1;
......@@ -414,9 +343,9 @@ GCONCAT( _gblender_blit_vbgr_, GDST_TYPE )( GBlenderBlit blit,
{
GBlender blender = blit->blender;
GDST_CHANNELS;
GDST_CHANNELS( fore, &color );
GBLENDER_CHANNEL_VARS(blender,r,g,b);
GBLENDER_CHANNEL_VARS( blender, fore.r, fore.g, fore.b );
int h = blit->height;
int src_pitch = blit->src_pitch;
......@@ -448,36 +377,15 @@ GCONCAT( _gblender_blit_vbgr_, GDST_TYPE )( GBlenderBlit blit,
}
else
{
GBlenderPixel back;
int pix_r, pix_g, pix_b;
GDST_CHANNELS( back, dst );
GDST_READ(dst,back);
GBLENDER_LOOKUP_R( blender, back.r );
{
unsigned int back_r = (back >> 16) & 255;
GBLENDER_LOOKUP_G( blender, back.g );
GBLENDER_LOOKUP_R( blender, back_r );
GBLENDER_LOOKUP_B( blender, back.b );
pix_r = _grcells[ar];
}
{
unsigned int back_g = (back >> 8) & 255;
GBLENDER_LOOKUP_G( blender, back_g );
pix_g = _ggcells[ag];
}
{
unsigned int back_b = (back) & 255;
GBLENDER_LOOKUP_B( blender, back_b );
pix_b = _gbcells[ab];
}
GDST_STOREC(dst,pix_r,pix_g,pix_b);
GDST_STOREC( dst, _grcells[ar], _ggcells[ag], _gbcells[ab] );
}
src += 1;
......@@ -512,9 +420,7 @@ GCONCAT( _gblender_blit_bgra_, GDST_TYPE )( GBlenderBlit blit,
do
{
unsigned int pix_b = src[0];
unsigned int pix_g = src[1];
unsigned int pix_r = src[2];
GBlenderBGR pix = { src[0], src[1], src[2] };
unsigned int a = src[3];
......@@ -524,45 +430,38 @@ GCONCAT( _gblender_blit_bgra_, GDST_TYPE )( GBlenderBlit blit,
}
else if ( a == 255 )
{
GDST_STOREC(dst,pix_r,pix_g,pix_b);
GDST_STOREC( dst, pix.r, pix.g, pix.b );
}
else
{
GBlenderPixel back;
GDST_READ(dst,back);
unsigned int ba = 255 - a;
{
unsigned int ba = 255 - a;
unsigned int back_r = (back >> 16) & 255;
unsigned int back_g = (back >> 8) & 255;
unsigned int back_b = (back) & 255;
GDST_CHANNELS( back, dst );
#if 1 /* premultiplied blending without gamma correction */
pix_r = (back_r * ba / 255 + pix_r);
pix_g = (back_g * ba / 255 + pix_g);
pix_b = (back_b * ba / 255 + pix_b);
#if 1 /* premultiplied blending without gamma correction */
pix.r = ( back.r * ba / 255 + pix.r );
pix.g = ( back.g * ba / 255 + pix.g );
pix.b = ( back.b * ba / 255 + pix.b );
#else /* gamma-corrected blending */
const unsigned char* gamma_ramp_inv = blit->blender->gamma_ramp_inv;
const unsigned short* gamma_ramp = blit->blender->gamma_ramp;
const unsigned char* gamma_ramp_inv = blit->blender->gamma_ramp_inv;
const unsigned short* gamma_ramp = blit->blender->gamma_ramp;
back_r = gamma_ramp[back_r];
back_g = gamma_ramp[back_g];
back_b = gamma_ramp[back_b];
back.r = gamma_ramp[back.r];
back.g = gamma_ramp[back.g];
back.b = gamma_ramp[back.b];
/* premultiplication undone */
pix_r = gamma_ramp[pix_r * 255 / a];
pix_g = gamma_ramp[pix_g * 255 / a];
pix_b = gamma_ramp[pix_b * 255 / a];
/* premultiplication undone */
pix.r = gamma_ramp[pix.r * 255 / a];
pix.g = gamma_ramp[pix.g * 255 / a];
pix.b = gamma_ramp[pix.b * 255 / a];
pix_r = gamma_ramp_inv[(back_r * ba + pix_r * a + 127) / 255];
pix_g = gamma_ramp_inv[(back_g * ba + pix_g * a + 127) / 255];
pix_b = gamma_ramp_inv[(back_b * ba + pix_b * a + 127) / 255];
pix.r = gamma_ramp_inv[( back.r * ba + pix.r * a + 127 ) / 255];
pix.g = gamma_ramp_inv[( back.g * ba + pix.g * a + 127 ) / 255];
pix.b = gamma_ramp_inv[( back.b * ba + pix.b * a + 127 ) / 255];
#endif
}
GDST_STOREC(dst,pix_r,pix_g,pix_b);
GDST_STOREC( dst, pix.r, pix.g, pix.b );
}
src += 4;
......@@ -596,7 +495,6 @@ GCONCAT( blit_funcs_, GDST_TYPE )[GBLENDER_SOURCE_MAX] =
#undef GCONCAT
#undef GDST_TYPE
#undef GDST_INCR
#undef GDST_READ
#undef GDST_COPY
#undef GDST_STOREB
#undef GDST_STOREP
......
......@@ -84,11 +84,10 @@
#define GDST_TYPE rgb32
#define GDST_INCR 4
#define GDST_CHANNELS unsigned int b = color.value & 255, \
g = color.value >> 8 & 255, \
r = color.value >> 16 & 255
#define GDST_PIX unsigned int pix = color.value & 0xFFFFFF
#define GDST_READ(d,p) (p) = *(GBlenderPixel*)(d) & 0xFFFFFF
#define GDST_CHANNELS(p,d) GBlenderBGR p = { *(unsigned int*)(d) & 255, \
*(unsigned int*)(d) >> 8 & 255, \
*(unsigned int*)(d) >> 16 & 255 }
#define GDST_PIX(p,d) unsigned int p = *(GBlenderPixel*)(d) & 0xFFFFFF
#define GDST_COPY(d) *(GBlenderPixel*)(d) = color.value
#define GDST_STOREP(d,cells,a) *(GBlenderPixel*)(d) = (cells)[(a)]
#define GDST_STOREB(d,cells,a) \
......@@ -106,11 +105,10 @@
#define GDST_TYPE rgb24
#define GDST_INCR 3
#define GDST_CHANNELS unsigned int b = color.chroma[2], \
g = color.chroma[1], \
r = color.chroma[0]
#define GDST_PIX unsigned int pix = GRGB_PACK(color.chroma[0],color.chroma[1],color.chroma[2])
#define GDST_READ(d,p) (p) = GRGB_PACK((d)[0],(d)[1],(d)[2])
#define GDST_CHANNELS(p,d) GBlenderBGR p = { ((unsigned char*)(d))[2], \
((unsigned char*)(d))[1], \
((unsigned char*)(d))[0] }
#define GDST_PIX(p,d) unsigned int p = GRGB_PACK(((unsigned char*)(d))[0],((unsigned char*)(d))[1],((unsigned char*)(d))[2])
#define GDST_COPY(d) GDST_STORE3(d,color.chroma[0],color.chroma[1],color.chroma[2])
#define GDST_STOREC(d,r,g,b) GDST_STORE3(d,r,g,b)
......@@ -137,12 +135,10 @@
#define GDST_TYPE rgb565
#define GDST_INCR 2
#define GDST_CHANNELS unsigned int b = GRGB565_TO_BLUE(color.value), \
g = GRGB565_TO_GREEN(color.value), \
r = GRGB565_TO_RED(color.value)
#define GDST_PIX unsigned int pix = GRGB565_TO_RGB24(color.value)
#define GDST_READ(d,p) p = (GBlenderPixel)*(unsigned short*)(d); \
p = GRGB565_TO_RGB24(p)
#define GDST_CHANNELS(p,d) GBlenderBGR p = { GRGB565_TO_BLUE (*(unsigned short*)(d)), \
GRGB565_TO_GREEN(*(unsigned short*)(d)), \
GRGB565_TO_RED (*(unsigned short*)(d)) }
#define GDST_PIX(p,d) unsigned int p = GRGB565_TO_RGB24(*(unsigned short*)(d))
#define GDST_COPY(d) *(unsigned short*)(d) = (unsigned short)color.value
#define GDST_STOREB(d,cells,a) \
......@@ -167,12 +163,10 @@
*/
#define GDST_TYPE rgb555
#define GDST_INCR 2
#define GDST_CHANNELS unsigned int b = GRGB555_TO_BLUE(color.value), \
g = GRGB555_TO_GREEN(color.value), \
r = GRGB555_TO_RED(color.value)
#define GDST_PIX unsigned int pix = GRGB555_TO_RGB24(color.value)
#define GDST_READ(d,p) p = (GBlenderPixel)*(unsigned short*)(d); \
p = GRGB555_TO_RGB24(p)
#define GDST_CHANNELS(p,d) GBlenderBGR p = { GRGB555_TO_BLUE (*(unsigned short*)(d)), \
GRGB555_TO_GREEN(*(unsigned short*)(d)), \
GRGB555_TO_RED (*(unsigned short*)(d)) }
#define GDST_PIX(p,d) unsigned int p = GRGB555_TO_RGB24(*(unsigned short*)(d))
#define GDST_COPY(d) *(unsigned short*)(d) = (unsigned short)color.value
#define GDST_STOREB(d,cells,a) \
......@@ -197,11 +191,10 @@
*/
#define GDST_TYPE gray8
#define GDST_INCR 1
#define GDST_CHANNELS unsigned int b = color.value, \
g = color.value, \
r = color.value
#define GDST_PIX unsigned int pix = GGRAY8_TO_RGB24(color.value)
#define GDST_READ(d,p) (p) = GGRAY8_TO_RGB24((d)[0])
#define GDST_CHANNELS(p,d) GBlenderBGR p = { *(unsigned char*)(d), \
*(unsigned char*)(d), \
*(unsigned char*)(d) }
#define GDST_PIX(p,d) unsigned int p = GGRAY8_TO_RGB24(*(unsigned char*)(d))
#define GDST_COPY(d) *(d) = (unsigned char)color.value
#define GDST_STOREB(d,cells,a) \
......
......@@ -46,6 +46,13 @@
#endif
typedef struct
{
unsigned int b, g, r;
} GBlenderBGR;
typedef struct
{
GBlenderPixel background;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment