зеркало из https://github.com/mozilla/gecko-dev.git
Bug 111152 - Support native pixel formats. Patch by
james.turner@crocodile-clips.com, minor tweaks by me.
This commit is contained in:
Родитель
337129f6d3
Коммит
28adab5b9c
|
@ -43,7 +43,8 @@ struct _ArtRenderPriv {
|
|||
ArtRender *
|
||||
art_render_new (int x0, int y0, int x1, int y1,
|
||||
art_u8 *pixels, int rowstride,
|
||||
int n_chan, int depth, ArtAlphaType alpha_type,
|
||||
ArtDestinationPixelFormat pixf,
|
||||
ArtAlphaType alpha_type,
|
||||
ArtAlphaGamma *alphagamma)
|
||||
{
|
||||
ArtRenderPriv *priv;
|
||||
|
@ -51,7 +52,7 @@ art_render_new (int x0, int y0, int x1, int y1,
|
|||
|
||||
priv = art_new (ArtRenderPriv, 1);
|
||||
result = &priv->super;
|
||||
|
||||
/*
|
||||
if (n_chan > ART_MAX_CHAN)
|
||||
{
|
||||
art_warn ("art_render_new: n_chan = %d, exceeds %d max\n",
|
||||
|
@ -64,6 +65,7 @@ art_render_new (int x0, int y0, int x1, int y1,
|
|||
depth, ART_MAX_DEPTH);
|
||||
return NULL;
|
||||
}
|
||||
*/
|
||||
if (x0 >= x1)
|
||||
{
|
||||
art_warn ("art_render_new: x0 >= x1 (x0 = %d, x1 = %d)\n", x0, x1);
|
||||
|
@ -75,8 +77,14 @@ art_render_new (int x0, int y0, int x1, int y1,
|
|||
result->y1 = y1;
|
||||
result->pixels = pixels;
|
||||
result->rowstride = rowstride;
|
||||
result->n_chan = n_chan;
|
||||
result->depth = depth;
|
||||
|
||||
result->n_chan = 0;
|
||||
if (pixf & ART_PF_RGB_MASK)
|
||||
result->n_chan += 3;
|
||||
|
||||
result->depth = (pixf & ART_PF_CMP_SIZE_MASK) >> 8;
|
||||
result->pixel_format = pixf;
|
||||
|
||||
result->alpha_type = alpha_type;
|
||||
|
||||
result->clear = ART_FALSE;
|
||||
|
@ -189,9 +197,11 @@ art_render_clear_render_8 (ArtRenderCallback *self, ArtRender *render,
|
|||
}
|
||||
|
||||
ix = 0;
|
||||
for (i = 0; i < width; i++)
|
||||
for (i = 0; i < width; i++) {
|
||||
for (j = 0; j < n_ch; j++)
|
||||
dest[ix++] = color[j];
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
const ArtRenderCallback art_render_clear_rgb8_obj =
|
||||
|
@ -520,7 +530,10 @@ art_render_composite_8 (ArtRenderCallback *self, ArtRender *render,
|
|||
int n_chan = render->n_chan;
|
||||
ArtAlphaType alpha_type = render->alpha_type;
|
||||
int n_ch = n_chan + (alpha_type != ART_ALPHA_NONE);
|
||||
int dst_pixstride = n_ch;
|
||||
|
||||
/* extract the pixel size (in bits) and divide by 8 */
|
||||
int dst_pixstride = (render->pixel_format & ART_PF_PIXEL_SIZE_MASK) >> 8;
|
||||
|
||||
ArtAlphaType buf_alpha = render->buf_alpha;
|
||||
int buf_n_ch = n_chan + (buf_alpha != ART_ALPHA_NONE);
|
||||
int buf_pixstride = buf_n_ch;
|
||||
|
@ -643,10 +656,297 @@ const ArtRenderCallback art_render_composite_8_obj =
|
|||
art_render_nop_done
|
||||
};
|
||||
|
||||
|
||||
static void
|
||||
art_render_composite_rgb8 (ArtRenderCallback *self,
|
||||
ArtRender *render,
|
||||
art_u8 *dest, int y)
|
||||
{
|
||||
ArtRenderMaskRun *run = render->run;
|
||||
int n_run = render->n_run;
|
||||
int x0 = render->x0;
|
||||
int x;
|
||||
int run_x0, run_x1;
|
||||
art_u8 *alpha_buf = render->alpha_buf;
|
||||
art_u8 *image_buf = render->image_buf;
|
||||
int i, j;
|
||||
art_u32 tmp;
|
||||
art_u32 run_alpha;
|
||||
art_u32 alpha;
|
||||
int image_ix;
|
||||
|
||||
/* extract the pixel size (in bits) and divide by 8 */
|
||||
int dst_pixstride = (render->pixel_format & ART_PF_PIXEL_SIZE_MASK) >> 3 ;
|
||||
|
||||
int n_chan = 3;
|
||||
|
||||
ArtAlphaType buf_alpha = render->buf_alpha;
|
||||
int buf_n_ch = n_chan + (buf_alpha != ART_ALPHA_NONE);
|
||||
int buf_pixstride = buf_n_ch;
|
||||
art_u8 *bufptr;
|
||||
art_u32 src_alpha;
|
||||
art_u32 src_mul;
|
||||
art_u8 *dstptr;
|
||||
art_u32 dst_alpha;
|
||||
art_u32 dst_mul, dst_save_mul;
|
||||
|
||||
art_u32 src, dst;
|
||||
/* art_u32 tmp; */
|
||||
|
||||
image_ix = 0;
|
||||
for (i = 0; i < n_run - 1; i++)
|
||||
{
|
||||
run_x0 = run[i].x;
|
||||
run_x1 = run[i + 1].x;
|
||||
tmp = run[i].alpha;
|
||||
if (tmp < 0x10000)
|
||||
continue;
|
||||
|
||||
run_alpha = (tmp + (tmp >> 8) + (tmp >> 16) - 0x8000) >> 8; /* range [0 .. 0x10000] */
|
||||
bufptr = image_buf + (run_x0 - x0) * buf_pixstride;
|
||||
dstptr = dest + (run_x0 - x0) * dst_pixstride;
|
||||
|
||||
if (render->pixel_format & ART_PF_SWAP_ALPHA_MASK)
|
||||
dstptr++;
|
||||
|
||||
for (x = run_x0; x < run_x1; x++)
|
||||
{
|
||||
if (alpha_buf)
|
||||
{
|
||||
tmp = run_alpha * alpha_buf[x - x0] + 0x80;
|
||||
/* range 0x80 .. 0xff0080 */
|
||||
alpha = (tmp + (tmp >> 8) + (tmp >> 16)) >> 8;
|
||||
}
|
||||
else
|
||||
alpha = run_alpha;
|
||||
/* alpha is run_alpha * alpha_buf[x], range 0 .. 0x10000 */
|
||||
|
||||
/* convert (src pixel * alpha) to premul alpha form,
|
||||
store in src as 0..0xffff range */
|
||||
if (buf_alpha == ART_ALPHA_NONE)
|
||||
{
|
||||
src_alpha = alpha;
|
||||
src_mul = src_alpha;
|
||||
}
|
||||
else
|
||||
{
|
||||
tmp = alpha * bufptr[n_chan] + 0x80;
|
||||
/* range 0x80 .. 0xff0080 */
|
||||
src_alpha = (tmp + (tmp >> 8) + (tmp >> 16)) >> 8;
|
||||
|
||||
if (buf_alpha == ART_ALPHA_SEPARATE)
|
||||
src_mul = src_alpha;
|
||||
else /* buf_alpha == (ART_ALPHA_PREMUL) */
|
||||
src_mul = alpha;
|
||||
}
|
||||
/* src_alpha is the (alpha of the source pixel * alpha),
|
||||
range 0..0x10000 */
|
||||
|
||||
src_mul *= 0x101;
|
||||
|
||||
/* if (alpha_type == ART_ALPHA_NONE) */
|
||||
dst_alpha = 0x10000;
|
||||
dst_mul = dst_alpha;
|
||||
dst_mul *= 0x101;
|
||||
|
||||
dst_save_mul = 0xff;
|
||||
|
||||
/* unrolling damage */
|
||||
|
||||
src = (bufptr[0] * src_mul + 0x8000) >> 16;
|
||||
dst = (dstptr[0] * dst_mul + 0x8000) >> 16;
|
||||
tmp = ((dst * (0x10000 - src_alpha) + 0x8000) >> 16) + src;
|
||||
tmp &= 0x0000FFFF;
|
||||
dstptr[0] = (tmp * dst_save_mul + 0x8000) >> 16;
|
||||
|
||||
src = (bufptr[1] * src_mul + 0x8000) >> 16;
|
||||
dst = (dstptr[1] * dst_mul + 0x8000) >> 16;
|
||||
tmp = ((dst * (0x10000 - src_alpha) + 0x8000) >> 16) + src;
|
||||
tmp &= 0x0000FFFF;
|
||||
dstptr[1] = (tmp * dst_save_mul + 0x8000) >> 16;
|
||||
|
||||
src = (bufptr[2] * src_mul + 0x8000) >> 16;
|
||||
dst = (dstptr[2] * dst_mul + 0x8000) >> 16;
|
||||
tmp = ((dst * (0x10000 - src_alpha) + 0x8000) >> 16) + src;
|
||||
tmp &= 0x0000FFFF;
|
||||
dstptr[2] = (tmp * dst_save_mul + 0x8000) >> 16;
|
||||
|
||||
/* end of unrolled loop */
|
||||
|
||||
bufptr += buf_pixstride;
|
||||
dstptr += dst_pixstride;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const ArtRenderCallback art_render_composite_rgb8_obj =
|
||||
{
|
||||
art_render_composite_rgb8,
|
||||
art_render_nop_done
|
||||
};
|
||||
|
||||
static void
|
||||
art_render_composite_rgb5 (ArtRenderCallback *self,
|
||||
ArtRender *render,
|
||||
art_u8 *dest, int y)
|
||||
{
|
||||
ArtRenderMaskRun *run = render->run;
|
||||
int n_run = render->n_run;
|
||||
int x0 = render->x0;
|
||||
int x;
|
||||
int run_x0, run_x1;
|
||||
art_u8 *alpha_buf = render->alpha_buf;
|
||||
art_u8 *image_buf = render->image_buf;
|
||||
int i, j;
|
||||
art_u32 tmp;
|
||||
art_u32 run_alpha;
|
||||
art_u32 alpha;
|
||||
int image_ix;
|
||||
|
||||
int n_chan = 3;
|
||||
|
||||
ArtAlphaType buf_alpha = render->buf_alpha;
|
||||
int buf_n_ch = n_chan + (buf_alpha != ART_ALPHA_NONE);
|
||||
int buf_pixstride = buf_n_ch;
|
||||
art_u8 *bufptr;
|
||||
art_u32 src_alpha;
|
||||
art_u32 src_mul;
|
||||
|
||||
art_u16 *dstptr;
|
||||
art_u32 dst_alpha;
|
||||
art_u32 dst_mul, dst_save_mul;
|
||||
|
||||
art_u32 src, dst;
|
||||
|
||||
art_u16 dstval,
|
||||
result;
|
||||
|
||||
int
|
||||
redShift = 7,
|
||||
redMask = 0x7C00, /* bits 14 - 10 */
|
||||
greenShift = 2,
|
||||
greenMask = 0x03E0, /* bits 5 - 9 */
|
||||
blueMask = 0x001F; /* lowest 5 bits [0 - 4] */
|
||||
|
||||
if (render->pixel_format & ART_PF_GREEN_6_MASK) {
|
||||
redMask <<= 1; /* Red pushed left 1 */
|
||||
++redShift;
|
||||
greenMask += (1<<10); /* Extra bit for green */
|
||||
++greenShift;
|
||||
}
|
||||
|
||||
/* art_u32 tmp; */
|
||||
|
||||
image_ix = 0;
|
||||
for (i = 0; i < n_run - 1; i++)
|
||||
{
|
||||
run_x0 = run[i].x;
|
||||
run_x1 = run[i + 1].x;
|
||||
tmp = run[i].alpha;
|
||||
if (tmp < 0x10000)
|
||||
continue;
|
||||
|
||||
run_alpha = (tmp + (tmp >> 8) + (tmp >> 16) - 0x8000) >> 8; /* range [0 .. 0x10000] */
|
||||
bufptr = image_buf + (run_x0 - x0) * buf_pixstride;
|
||||
dstptr = ((art_u16*)dest) + (run_x0 - x0);
|
||||
|
||||
if (render->pixel_format & ART_PF_SWAP_ALPHA_MASK)
|
||||
dstptr++;
|
||||
|
||||
for (x = run_x0; x < run_x1; x++)
|
||||
{
|
||||
if (alpha_buf)
|
||||
{
|
||||
tmp = run_alpha * alpha_buf[x - x0] + 0x80;
|
||||
/* range 0x80 .. 0xff0080 */
|
||||
alpha = (tmp + (tmp >> 8) + (tmp >> 16)) >> 8;
|
||||
}
|
||||
else
|
||||
alpha = run_alpha;
|
||||
/* alpha is run_alpha * alpha_buf[x], range 0 .. 0x10000 */
|
||||
|
||||
/* convert (src pixel * alpha) to premul alpha form,
|
||||
store in src as 0..0xffff range */
|
||||
if (buf_alpha == ART_ALPHA_NONE)
|
||||
{
|
||||
src_alpha = alpha;
|
||||
src_mul = src_alpha;
|
||||
}
|
||||
else
|
||||
{
|
||||
tmp = alpha * bufptr[n_chan] + 0x80;
|
||||
/* range 0x80 .. 0xff0080 */
|
||||
src_alpha = (tmp + (tmp >> 8) + (tmp >> 16)) >> 8;
|
||||
|
||||
if (buf_alpha == ART_ALPHA_SEPARATE)
|
||||
src_mul = src_alpha;
|
||||
else /* buf_alpha == (ART_ALPHA_PREMUL) */
|
||||
src_mul = alpha;
|
||||
}
|
||||
/* src_alpha is the (alpha of the source pixel * alpha),
|
||||
range 0..0x10000 */
|
||||
|
||||
src_mul *= 0x101;
|
||||
|
||||
/* if (alpha_type == ART_ALPHA_NONE) */
|
||||
dst_alpha = 0x10000;
|
||||
dst_mul = dst_alpha;
|
||||
dst_mul *= 0x101;
|
||||
|
||||
dst_save_mul = 0xff;
|
||||
|
||||
/* unrolling damage */
|
||||
|
||||
dstval = *dstptr;
|
||||
|
||||
src = (bufptr[0] * src_mul + 0x8000) >> 16;
|
||||
dst = ( ( (dstval & redMask) >> redShift ) * dst_mul + 0x8000) >> 16;
|
||||
tmp = ((dst * (0x10000 - src_alpha) + 0x8000) >> 16) + src;
|
||||
tmp &= 0x0000FFFF;
|
||||
result = (((tmp * dst_save_mul + 0x8000) >> 16) << redShift) & redMask;
|
||||
|
||||
src = (bufptr[1] * src_mul + 0x8000) >> 16;
|
||||
dst = ( ((dstval & greenMask) >> greenShift) * dst_mul + 0x8000) >> 16;
|
||||
|
||||
tmp = ((dst * (0x10000 - src_alpha) + 0x8000) >> 16) + src;
|
||||
tmp &= 0x0000FFFF;
|
||||
result |= (((tmp * dst_save_mul + 0x8000) >> 16) << greenShift) & greenMask;
|
||||
|
||||
src = (bufptr[2] * src_mul + 0x8000) >> 16;
|
||||
dst = (((dstval & blueMask) << 3) * dst_mul + 0x8000) >> 16;
|
||||
tmp = ((dst * (0x10000 - src_alpha) + 0x8000) >> 16) + src;
|
||||
tmp &= 0x0000FFFF;
|
||||
result |= (((tmp * dst_save_mul + 0x8000) >> 16) >> 3) & blueMask;
|
||||
|
||||
*dstptr++ = result;
|
||||
|
||||
/* end of unrolled loop */
|
||||
|
||||
bufptr += buf_pixstride;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const ArtRenderCallback art_render_composite_rgb5_obj =
|
||||
{
|
||||
art_render_composite_rgb5,
|
||||
art_render_nop_done
|
||||
};
|
||||
|
||||
/* todo: inline */
|
||||
static ArtRenderCallback *
|
||||
art_render_choose_compositing_callback (ArtRender *render)
|
||||
{
|
||||
if (render->pixel_format & ART_PF_RGB_MASK) {
|
||||
if (render->depth == 8 && render->buf_depth == 8)
|
||||
return (ArtRenderCallback *)&art_render_composite_rgb8_obj;
|
||||
|
||||
if (render->depth == 5 && render->buf_depth == 8)
|
||||
return (ArtRenderCallback *)&art_render_composite_rgb5_obj;
|
||||
|
||||
art_die("We are scrwed.");
|
||||
|
||||
} else
|
||||
if (render->depth == 8 && render->buf_depth == 8)
|
||||
return (ArtRenderCallback *)&art_render_composite_8_obj;
|
||||
return (ArtRenderCallback *)&art_render_composite_obj;
|
||||
|
@ -1079,7 +1379,7 @@ art_render_image_solid_negotiate (ArtImageSource *self, ArtRender *render,
|
|||
|
||||
render_cbk = NULL;
|
||||
|
||||
if (render->depth == 8 && render->n_chan == 3 &&
|
||||
if (render->depth <= 8 && render->n_chan == 3 &&
|
||||
render->alpha_type == ART_ALPHA_NONE)
|
||||
{
|
||||
if (render->clear)
|
||||
|
@ -1091,7 +1391,7 @@ art_render_image_solid_negotiate (ArtImageSource *self, ArtRender *render,
|
|||
}
|
||||
if (render_cbk == NULL)
|
||||
{
|
||||
if (render->depth == 8)
|
||||
if (render->depth <= 8)
|
||||
{
|
||||
render_cbk = art_render_image_solid_rgb8;
|
||||
*p_buf_depth = 8;
|
||||
|
|
|
@ -73,6 +73,38 @@ typedef enum {
|
|||
ART_IMAGE_SOURCE_CAN_COMPOSITE = 2
|
||||
} ArtImageSourceFlags;
|
||||
|
||||
/* added by James Turner - note the hevay GL influence here :-) */
|
||||
|
||||
#define ART_PF_PIXEL_SIZE_MASK 0xFF /* bits 0 -> 7, pizel size in bits */
|
||||
#define ART_PF_CMP_SIZE_MASK 0xFF00 /* bits 8 -> 15, component size in bits */
|
||||
|
||||
#define ART_CMP_8_BIT 8 << 8
|
||||
#define ART_CMP_5_BIT 5 << 8
|
||||
#define ART_CMP_16_BIT 16 << 8
|
||||
|
||||
#define ART_PF_RGB_MASK 1 << 16
|
||||
#define ART_PF_ALPHA_MASK 1 << 17
|
||||
#define ART_PF_INDEXED_MASK 1 << 18
|
||||
/* alpha is before the first color component (MSB on big-endian) */
|
||||
#define ART_PF_SWAP_ALPHA_MASK 1 << 19
|
||||
#define ART_PF_GREEN_6_MASK 1 << 20
|
||||
|
||||
typedef enum {
|
||||
ART_PF_RGB8 = ART_PF_RGB_MASK | ART_CMP_8_BIT | 24, /* current default */
|
||||
ART_PF_RGB16 = ART_PF_RGB_MASK | ART_CMP_16_BIT | 48,
|
||||
ART_PF_RGBA8 = ART_PF_RGB_MASK | ART_PF_ALPHA_MASK | ART_CMP_8_BIT | 32,
|
||||
/* suprisingly common - needed for mac */
|
||||
ART_PF_ARGB8 = ART_PF_RGB_MASK | ART_PF_ALPHA_MASK | ART_PF_SWAP_ALPHA_MASK | ART_CMP_8_BIT | 32,
|
||||
ART_PF_555 = ART_PF_RGB_MASK | ART_CMP_5_BIT | 16,
|
||||
ART_PF_565 = ART_PF_RGB_MASK | ART_PF_GREEN_6_MASK | ART_CMP_5_BIT | 16,
|
||||
|
||||
/* highly questionable .... */
|
||||
ART_PF_INDEXED8 = ART_PF_INDEXED_MASK | 8
|
||||
|
||||
} ArtDestinationPixelFormat;
|
||||
|
||||
/* end of te pixel format damage */
|
||||
|
||||
struct _ArtRenderMaskRun {
|
||||
int x;
|
||||
int alpha;
|
||||
|
@ -109,6 +141,7 @@ struct _ArtRender {
|
|||
int n_chan;
|
||||
int depth;
|
||||
ArtAlphaType alpha_type;
|
||||
ArtDestinationPixelFormat pixel_format;
|
||||
|
||||
art_boolean clear;
|
||||
ArtPixMaxDepth clear_color[ART_MAX_CHAN + 1];
|
||||
|
@ -140,7 +173,8 @@ struct _ArtRender {
|
|||
ArtRender *
|
||||
art_render_new (int x0, int y0, int x1, int y1,
|
||||
art_u8 *pixels, int rowstride,
|
||||
int n_chan, int depth, ArtAlphaType alpha_type,
|
||||
ArtDestinationPixelFormat pixf,
|
||||
ArtAlphaType alpha_type,
|
||||
ArtAlphaGamma *alphagamma);
|
||||
|
||||
void
|
||||
|
|
|
@ -432,8 +432,8 @@ test_render_gradient (art_u8 *buf)
|
|||
vpath = randstar (50);
|
||||
svp = art_svp_from_vpath (vpath);
|
||||
|
||||
render = art_render_new (0, 0, 512, 512, buf, 512 * 3, 3, 8, ART_ALPHA_NONE,
|
||||
NULL);
|
||||
render = art_render_new (0, 0, 512, 512, buf, 512 * 3, ART_PF_RGB8,
|
||||
ART_ALPHA_NONE, NULL);
|
||||
art_render_svp (render, svp);
|
||||
art_render_gradient_linear (render, &gradient, ART_FILTER_NEAREST);
|
||||
art_render_invoke (render);
|
||||
|
@ -468,8 +468,8 @@ test_render_rad_gradient (art_u8 *buf)
|
|||
vpath = randstar (50);
|
||||
svp = art_svp_from_vpath (vpath);
|
||||
|
||||
render = art_render_new (0, 0, 512, 512, buf, 512 * 3, 3, 8, ART_ALPHA_NONE,
|
||||
NULL);
|
||||
render = art_render_new (0, 0, 512, 512, buf, 512 * 3, ART_PF_RGB8,
|
||||
ART_ALPHA_NONE, NULL);
|
||||
art_render_svp (render, svp);
|
||||
art_render_gradient_radial (render, &gradient, ART_FILTER_NEAREST);
|
||||
art_render_invoke (render);
|
||||
|
@ -494,7 +494,8 @@ test_gradient (void)
|
|||
{
|
||||
#define USE_RENDER
|
||||
#ifdef USE_RENDER
|
||||
render = art_render_new (0, 0, 512, 512, buf, 512 * 3, 3, 8, ART_ALPHA_NONE,
|
||||
render = art_render_new (0, 0, 512, 512, buf, 512 * 3, ART_PF_RGB8,
|
||||
ART_ALPHA_NONE,
|
||||
NULL);
|
||||
art_render_clear_rgb (render, 0xfff0c0);
|
||||
art_render_svp (render, svp);
|
||||
|
|
Загрузка…
Ссылка в новой задаче