sna/glyphs: Improve handling of low bitdepth mask format conversions
We shouldn't just discard the mask if the user requests that we render the glyphs through a low bitdepth mask - and in doing so we should also be careful not to improve the bitdepth of that mask (since we don't take into account the extra quantisation desired). Testcase: render-glyphs Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
This commit is contained in:
parent
6d64063750
commit
b10ef9cf5c
|
|
@ -817,8 +817,8 @@ create_pixmap(struct sna *sna, ScreenPtr screen,
|
|||
datasize += adjust;
|
||||
}
|
||||
|
||||
DBG(("%s: allocating pixmap %dx%d, depth=%d, size=%ld\n",
|
||||
__FUNCTION__, width, height, depth, (long)datasize));
|
||||
DBG(("%s: allocating pixmap %dx%d, depth=%d/%d, size=%ld\n",
|
||||
__FUNCTION__, width, height, depth, bpp, (long)datasize));
|
||||
pixmap = AllocatePixmap(screen, datasize);
|
||||
if (!pixmap)
|
||||
return NullPixmap;
|
||||
|
|
@ -4091,7 +4091,7 @@ sna_pixmap_create_upload(ScreenPtr screen,
|
|||
assert(width);
|
||||
assert(height);
|
||||
|
||||
if (depth == 1)
|
||||
if (depth < 8)
|
||||
return create_pixmap(sna, screen, width, height, depth,
|
||||
CREATE_PIXMAP_USAGE_SCRATCH);
|
||||
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@
|
|||
#define NO_GLYPHS_VIA_MASK 0
|
||||
#define FORCE_SMALL_MASK 0 /* -1 = never, 1 = always */
|
||||
#define NO_GLYPHS_SLOW 0
|
||||
#define NO_DISCARD_MASK 0
|
||||
#define DISCARD_MASK 0 /* -1 = never, 1 = always */
|
||||
|
||||
#define CACHE_PICTURE_SIZE 1024
|
||||
#define GLYPH_MIN_SIZE 8
|
||||
|
|
@ -1094,6 +1094,9 @@ sna_glyph_get_image(GlyphPtr g, ScreenPtr s)
|
|||
|
||||
static inline bool use_small_mask(struct sna *sna, int16_t width, int16_t height, int depth)
|
||||
{
|
||||
if (depth < 8)
|
||||
return true;
|
||||
|
||||
if (FORCE_SMALL_MASK)
|
||||
return FORCE_SMALL_MASK > 0;
|
||||
|
||||
|
|
@ -1156,12 +1159,6 @@ glyphs_via_mask(struct sna *sna,
|
|||
src_x += box.x1 - list->xOff;
|
||||
src_y += box.y1 - list->yOff;
|
||||
|
||||
if (format->depth < 8) {
|
||||
format = PictureMatchFormat(screen, 8, PICT_a8);
|
||||
if (!format)
|
||||
return false;
|
||||
}
|
||||
|
||||
component_alpha = NeedsComponent(format->format);
|
||||
if (use_small_mask(sna, width, height, format->depth)) {
|
||||
pixman_image_t *mask_image;
|
||||
|
|
@ -1179,7 +1176,7 @@ use_small_mask:
|
|||
return false;
|
||||
|
||||
mask_image =
|
||||
pixman_image_create_bits(format->depth << 24 | format->format,
|
||||
pixman_image_create_bits(pixmap->drawable.bitsPerPixel << 24 | format->format,
|
||||
width, height,
|
||||
pixmap->devPrivate.ptr,
|
||||
pixmap->devKind);
|
||||
|
|
@ -1386,10 +1383,11 @@ next_image:
|
|||
DBG(("%s: atlas format=%08x, mask format=%08x\n",
|
||||
__FUNCTION__,
|
||||
(int)p->atlas->format,
|
||||
(int)(format->depth << 24 | format->format)));
|
||||
(int)mask->format));
|
||||
|
||||
memset(&tmp, 0, sizeof(tmp));
|
||||
if (p->atlas->format == (format->depth << 24 | format->format)) {
|
||||
if (p->atlas->format == mask->format ||
|
||||
alphaless(p->atlas->format) == mask->format) {
|
||||
ok = sna->render.composite(sna, PictOpAdd,
|
||||
p->atlas, NULL, mask,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
|
|
@ -1564,6 +1562,8 @@ skip_glyph:
|
|||
out:
|
||||
if (list_extents != stack_extents)
|
||||
free(list_extents);
|
||||
DBG(("%s: format=%08d, depth=%d\n",
|
||||
__FUNCTION__, format->format, format->depth));
|
||||
return format;
|
||||
}
|
||||
|
||||
|
|
@ -1573,24 +1573,34 @@ static bool can_discard_mask(uint8_t op, PicturePtr src, PictFormatPtr mask,
|
|||
PictFormatPtr g;
|
||||
uint32_t color;
|
||||
|
||||
if (NO_DISCARD_MASK)
|
||||
return false;
|
||||
if (DISCARD_MASK)
|
||||
return DISCARD_MASK > 0;
|
||||
|
||||
DBG(("%s: nlist=%d, mask=%08x, depth %d, op=%d (bounded? %d)\n",
|
||||
__FUNCTION__, nlist,
|
||||
mask ? (unsigned)mask->format : 0, mask ? mask->depth : 0,
|
||||
op, op_is_bounded(op)));
|
||||
|
||||
if (nlist == 1 && list->len == 1)
|
||||
return true;
|
||||
if (nlist == 1 && list->len == 1) {
|
||||
if (mask == list->format)
|
||||
return true;
|
||||
|
||||
if (!op_is_bounded(op))
|
||||
g = list->format;
|
||||
goto skip;
|
||||
}
|
||||
|
||||
if (!op_is_bounded(op)) {
|
||||
DBG(("%s: unbounded op, not discarding\n", __FUNCTION__));
|
||||
return false;
|
||||
}
|
||||
|
||||
/* No glyphs overlap and we are not performing a mask conversion. */
|
||||
g = glyphs_format(nlist, list, glyphs);
|
||||
if (mask == g)
|
||||
if (mask == g) {
|
||||
DBG(("%s: mask matches glyphs format, no conversion, so discard mask\n",
|
||||
__FUNCTION__));
|
||||
return true;
|
||||
}
|
||||
|
||||
DBG(("%s: preferred mask format %08x, depth %d\n",
|
||||
__FUNCTION__, g ? (unsigned)g->format : 0, g ? g->depth : 0));
|
||||
|
|
@ -1605,18 +1615,41 @@ static bool can_discard_mask(uint8_t op, PicturePtr src, PictFormatPtr mask,
|
|||
|
||||
list++;
|
||||
}
|
||||
|
||||
if (!sna_picture_is_solid(src, &color))
|
||||
return false;
|
||||
|
||||
return color >> 24 == 0xff;
|
||||
} else {
|
||||
if (PICT_FORMAT_A(mask->format) >= PICT_FORMAT_A(g->format))
|
||||
skip:
|
||||
if (mask->format == g->format)
|
||||
return true;
|
||||
|
||||
if (g->depth != 1)
|
||||
return false;
|
||||
}
|
||||
if (mask->format == alphaless(g->format))
|
||||
return true;
|
||||
|
||||
if (PICT_FORMAT_TYPE(g->format) == PICT_TYPE_A &&
|
||||
PICT_FORMAT_TYPE(mask->format) != PICT_TYPE_A)
|
||||
return true;
|
||||
|
||||
if (!sna_picture_is_solid(src, &color))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return color >> 24 == 0xff;
|
||||
static uint32_t pixman_format(PictFormatPtr short_format)
|
||||
{
|
||||
uint32_t bpp;
|
||||
|
||||
bpp = short_format->depth;
|
||||
if (bpp <= 1)
|
||||
bpp = 1;
|
||||
else if (bpp <= 8)
|
||||
bpp = 8;
|
||||
else if (bpp <= 16)
|
||||
bpp = 16;
|
||||
else
|
||||
bpp = 32;
|
||||
return bpp << 24 | short_format->format;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -1756,7 +1789,7 @@ next:
|
|||
if (sigtrap_get() == 0) {
|
||||
if (mask_format) {
|
||||
pixman_composite_glyphs(op, src_image, dst_image,
|
||||
mask_format->format | (mask_format->depth << 24),
|
||||
pixman_format(mask_format),
|
||||
src_x + src_dx + region.extents.x1 - dst_x,
|
||||
src_y + src_dy + region.extents.y1 - dst_y,
|
||||
region.extents.x1, region.extents.y1,
|
||||
|
|
@ -1815,10 +1848,10 @@ out:
|
|||
x, y,
|
||||
mask_format->depth,
|
||||
(long)mask_format->format,
|
||||
(long)(mask_format->depth << 24 | mask_format->format),
|
||||
(long)pixman_format(mask_format),
|
||||
NeedsComponent(mask_format->format)));
|
||||
mask_image =
|
||||
pixman_image_create_bits(mask_format->depth << 24 | mask_format->format,
|
||||
pixman_image_create_bits(pixman_format(mask_format),
|
||||
region.extents.x2 - region.extents.x1,
|
||||
region.extents.y2 - region.extents.y1,
|
||||
NULL, 0);
|
||||
|
|
@ -2086,12 +2119,6 @@ glyphs_via_image(struct sna *sna,
|
|||
src_x += box.x1 - list->xOff;
|
||||
src_y += box.y1 - list->yOff;
|
||||
|
||||
if (format->depth < 8) {
|
||||
format = PictureMatchFormat(screen, 8, PICT_a8);
|
||||
if (!format)
|
||||
return false;
|
||||
}
|
||||
|
||||
DBG(("%s: small mask [format=%lx, depth=%d, size=%d], rendering glyphs to upload buffer\n",
|
||||
__FUNCTION__, (unsigned long)format->format,
|
||||
format->depth, (uint32_t)width*height*format->depth));
|
||||
|
|
@ -2104,7 +2131,7 @@ glyphs_via_image(struct sna *sna,
|
|||
return false;
|
||||
|
||||
mask_image =
|
||||
pixman_image_create_bits(format->depth << 24 | format->format,
|
||||
pixman_image_create_bits(pixmap->drawable.bitsPerPixel << 24 | format->format,
|
||||
width, height,
|
||||
pixmap->devPrivate.ptr,
|
||||
pixmap->devKind);
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ sna_format_for_depth(int depth)
|
|||
{
|
||||
switch (depth) {
|
||||
case 1: return PICT_a1;
|
||||
case 4: return PICT_a4;
|
||||
case 4: return PICT_x4a4;
|
||||
case 8: return PICT_a8;
|
||||
case 15: return PICT_x1r5g5b5;
|
||||
case 16: return PICT_r5g6b5;
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ render-copyarea
|
|||
render-copyarea-mask
|
||||
render-copyarea-size
|
||||
render-copy-alphaless
|
||||
render-glyphs
|
||||
mixed-stress
|
||||
lowlevel-blt-bench
|
||||
vsync.avi
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ stress_TESTS = \
|
|||
DrawSegments \
|
||||
cursor-test \
|
||||
render-fill \
|
||||
render-glyphs \
|
||||
render-trapezoid \
|
||||
render-trapezoid-image \
|
||||
render-fill-copy \
|
||||
|
|
|
|||
|
|
@ -0,0 +1,441 @@
|
|||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <X11/Xutil.h> /* for XDestroyImage */
|
||||
#include <pixman.h> /* for pixman blt functions */
|
||||
|
||||
#include "test.h"
|
||||
|
||||
static const XRenderColor colors[] = {
|
||||
/* red, green, blue, alpha */
|
||||
{ 0 },
|
||||
{ 0, 0, 0, 0xffff },
|
||||
{ 0xffff, 0, 0, 0xffff },
|
||||
{ 0, 0xffff, 0, 0xffff },
|
||||
{ 0, 0, 0xffff, 0xffff },
|
||||
{ 0xffff, 0xffff, 0xffff, 0xffff },
|
||||
};
|
||||
|
||||
static struct clip {
|
||||
void *func;
|
||||
} clips[] = {
|
||||
{ NULL },
|
||||
};
|
||||
|
||||
static int _x_error_occurred;
|
||||
|
||||
static int
|
||||
_check_error_handler(Display *display,
|
||||
XErrorEvent *event)
|
||||
{
|
||||
_x_error_occurred = 1;
|
||||
return False; /* ignored */
|
||||
}
|
||||
|
||||
static void clear(struct test_display *dpy,
|
||||
struct test_target *tt,
|
||||
const XRenderColor *c)
|
||||
{
|
||||
XRenderFillRectangle(dpy->dpy, PictOpClear, tt->picture, c,
|
||||
0, 0, tt->width, tt->height);
|
||||
}
|
||||
|
||||
static bool check_op(struct test_display *dpy, int op, struct test_target *tt)
|
||||
{
|
||||
XRenderColor render_color = {0};
|
||||
|
||||
XSync(dpy->dpy, True);
|
||||
_x_error_occurred = 0;
|
||||
|
||||
XRenderFillRectangle(dpy->dpy, op,
|
||||
tt->picture, &render_color,
|
||||
0, 0, 0, 0);
|
||||
|
||||
XSync(dpy->dpy, True);
|
||||
return _x_error_occurred == 0;
|
||||
}
|
||||
|
||||
struct glyph_iter {
|
||||
enum {
|
||||
GLYPHS, OP, DST, SRC, MASK, CLIP,
|
||||
} stage;
|
||||
|
||||
int glyph_format;
|
||||
int op;
|
||||
int dst_color;
|
||||
int src_color;
|
||||
int mask_format;
|
||||
int clip;
|
||||
|
||||
struct {
|
||||
struct test_display *dpy;
|
||||
struct test_target tt;
|
||||
GlyphSet glyphset;
|
||||
Picture src;
|
||||
XRenderPictFormat *mask_format;
|
||||
} ref, out;
|
||||
};
|
||||
|
||||
static void glyph_iter_init(struct glyph_iter *gi,
|
||||
struct test *t, enum target target)
|
||||
{
|
||||
memset(gi, 0, sizeof(*gi));
|
||||
|
||||
gi->out.dpy = &t->out;
|
||||
test_target_create_render(&t->out, target, &gi->out.tt);
|
||||
|
||||
gi->ref.dpy = &t->ref;
|
||||
test_target_create_render(&t->ref, target, &gi->ref.tt);
|
||||
|
||||
gi->stage = GLYPHS;
|
||||
gi->glyph_format = -1;
|
||||
gi->op = -1;
|
||||
gi->dst_color = -1;
|
||||
gi->src_color = -1;
|
||||
gi->mask_format = -1;
|
||||
gi->clip = -1;
|
||||
}
|
||||
|
||||
static void render_clear(char *image, int image_size, int bpp)
|
||||
{
|
||||
memset(image, 0, image_size);
|
||||
}
|
||||
|
||||
static void render_black(char *image, int image_size, int bpp)
|
||||
{
|
||||
if (bpp == 4) {
|
||||
uint32_t *p = (uint32_t *)image;
|
||||
image_size /= 4;
|
||||
while (image_size--)
|
||||
*p++ = 0x000000ff;
|
||||
} else
|
||||
memset(image, 0x55, image_size);
|
||||
}
|
||||
|
||||
static void render_green(char *image, int image_size, int bpp)
|
||||
{
|
||||
if (bpp == 4) {
|
||||
uint32_t *p = (uint32_t *)image;
|
||||
image_size /= 4;
|
||||
while (image_size--)
|
||||
*p++ = 0xffff0000;
|
||||
} else
|
||||
memset(image, 0xaa, image_size);
|
||||
}
|
||||
|
||||
static void render_white(char *image, int image_size, int bpp)
|
||||
{
|
||||
memset(image, 0xff, image_size);
|
||||
}
|
||||
|
||||
static GlyphSet create_glyphs(Display *dpy, int format_id)
|
||||
{
|
||||
#define N_GLYPHS 4
|
||||
XRenderPictFormat *format;
|
||||
XGlyphInfo glyph = { 8, 8, 0, 0, 8, 0 };
|
||||
char image[4*8*8];
|
||||
GlyphSet glyphset;
|
||||
Glyph gid;
|
||||
int image_size;
|
||||
int bpp;
|
||||
int n;
|
||||
|
||||
format = XRenderFindStandardFormat(dpy, format_id);
|
||||
if (format == NULL)
|
||||
return 0;
|
||||
|
||||
switch (format_id) {
|
||||
case PictStandardARGB32:
|
||||
case PictStandardRGB24:
|
||||
image_size = 4 * 8 * 8;
|
||||
bpp = 4;
|
||||
break;
|
||||
case PictStandardA8:
|
||||
case PictStandardA4:
|
||||
image_size = 8 * 8;
|
||||
bpp = 1;
|
||||
break;
|
||||
case PictStandardA1:
|
||||
image_size = 8;
|
||||
bpp = 0;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
glyphset = XRenderCreateGlyphSet(dpy, format);
|
||||
for (n = 0; n < N_GLYPHS; n++) {
|
||||
gid = n;
|
||||
|
||||
switch (n) {
|
||||
case 0: render_clear(image, image_size, bpp); break;
|
||||
case 1: render_black(image, image_size, bpp); break;
|
||||
case 2: render_green(image, image_size, bpp); break;
|
||||
case 3: render_white(image, image_size, bpp); break;
|
||||
}
|
||||
|
||||
XRenderAddGlyphs(dpy, glyphset,
|
||||
&gid, &glyph, 1, image, image_size);
|
||||
}
|
||||
|
||||
return glyphset;
|
||||
}
|
||||
|
||||
static const char *glyph_name(int n)
|
||||
{
|
||||
switch (n) {
|
||||
case 0: return "clear";
|
||||
case 1: return "black";
|
||||
case 2: return "green";
|
||||
case 3: return "white";
|
||||
default: return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
static bool glyph_iter_next(struct glyph_iter *gi)
|
||||
{
|
||||
restart:
|
||||
if (gi->stage == GLYPHS) {
|
||||
if (++gi->glyph_format == PictStandardNUM)
|
||||
return false;
|
||||
|
||||
if (gi->out.glyphset)
|
||||
XRenderFreeGlyphSet(gi->out.dpy->dpy,
|
||||
gi->out.glyphset);
|
||||
gi->out.glyphset = create_glyphs(gi->out.dpy->dpy,
|
||||
gi->glyph_format);
|
||||
|
||||
if (gi->ref.glyphset)
|
||||
XRenderFreeGlyphSet(gi->ref.dpy->dpy,
|
||||
gi->ref.glyphset);
|
||||
gi->ref.glyphset = create_glyphs(gi->ref.dpy->dpy,
|
||||
gi->glyph_format);
|
||||
|
||||
gi->stage++;
|
||||
}
|
||||
|
||||
if (gi->stage == OP) {
|
||||
do {
|
||||
if (++gi->op == 255)
|
||||
goto reset_op;
|
||||
} while (!check_op(gi->out.dpy, gi->op, &gi->out.tt) ||
|
||||
!check_op(gi->ref.dpy, gi->op, &gi->ref.tt));
|
||||
|
||||
gi->stage++;
|
||||
}
|
||||
|
||||
if (gi->stage == DST) {
|
||||
if (++gi->dst_color == ARRAY_SIZE(colors))
|
||||
goto reset_dst;
|
||||
|
||||
gi->stage++;
|
||||
}
|
||||
|
||||
if (gi->stage == SRC) {
|
||||
if (++gi->src_color == ARRAY_SIZE(colors))
|
||||
goto reset_src;
|
||||
|
||||
if (gi->ref.src)
|
||||
XRenderFreePicture(gi->ref.dpy->dpy, gi->ref.src);
|
||||
gi->ref.src = XRenderCreateSolidFill(gi->ref.dpy->dpy,
|
||||
&colors[gi->src_color]);
|
||||
|
||||
if (gi->out.src)
|
||||
XRenderFreePicture(gi->out.dpy->dpy, gi->out.src);
|
||||
gi->out.src = XRenderCreateSolidFill(gi->out.dpy->dpy,
|
||||
&colors[gi->src_color]);
|
||||
|
||||
gi->stage++;
|
||||
}
|
||||
|
||||
if (gi->stage == MASK) {
|
||||
if (++gi->mask_format > PictStandardNUM)
|
||||
goto reset_mask;
|
||||
|
||||
if (gi->mask_format == PictStandardRGB24)
|
||||
gi->mask_format++;
|
||||
|
||||
if (gi->mask_format < PictStandardNUM) {
|
||||
gi->out.mask_format = XRenderFindStandardFormat(gi->out.dpy->dpy,
|
||||
gi->mask_format);
|
||||
gi->ref.mask_format = XRenderFindStandardFormat(gi->ref.dpy->dpy,
|
||||
gi->mask_format);
|
||||
} else {
|
||||
gi->out.mask_format = NULL;
|
||||
gi->ref.mask_format = NULL;
|
||||
}
|
||||
|
||||
gi->stage++;
|
||||
}
|
||||
|
||||
if (gi->stage == CLIP) {
|
||||
if (++gi->clip == ARRAY_SIZE(clips))
|
||||
goto reset_clip;
|
||||
|
||||
gi->stage++;
|
||||
}
|
||||
|
||||
gi->stage--;
|
||||
return true;
|
||||
|
||||
reset_op:
|
||||
gi->op = -1;
|
||||
reset_dst:
|
||||
gi->dst_color = -1;
|
||||
reset_src:
|
||||
gi->src_color = -1;
|
||||
reset_mask:
|
||||
gi->mask_format = -1;
|
||||
reset_clip:
|
||||
gi->clip = -1;
|
||||
gi->stage--;
|
||||
goto restart;
|
||||
}
|
||||
|
||||
static void glyph_iter_fini(struct glyph_iter *gi)
|
||||
{
|
||||
if (gi->out.glyphset)
|
||||
XRenderFreeGlyphSet (gi->out.dpy->dpy, gi->out.glyphset);
|
||||
if (gi->ref.glyphset)
|
||||
XRenderFreeGlyphSet (gi->ref.dpy->dpy, gi->ref.glyphset);
|
||||
|
||||
test_target_destroy_render(gi->out.dpy, &gi->out.tt);
|
||||
test_target_destroy_render(gi->ref.dpy, &gi->ref.tt);
|
||||
}
|
||||
|
||||
static const char *stdformat_to_str(int id)
|
||||
{
|
||||
switch (id) {
|
||||
case PictStandardARGB32: return "ARGB32";
|
||||
case PictStandardRGB24: return "RGB24";
|
||||
case PictStandardA8: return "A8";
|
||||
case PictStandardA4: return "A4";
|
||||
case PictStandardA1: return "A1";
|
||||
default: return "none";
|
||||
}
|
||||
}
|
||||
|
||||
static char *glyph_iter_to_string(struct glyph_iter *gi,
|
||||
const char *format,
|
||||
...)
|
||||
{
|
||||
static char buf[100];
|
||||
va_list ap;
|
||||
int len;
|
||||
|
||||
len = sprintf(buf, "glyphs=%s, op=%d, dst=%08x, src=%08x, mask=%s",
|
||||
stdformat_to_str(gi->glyph_format), gi->op,
|
||||
xrender_color(&colors[gi->dst_color]),
|
||||
xrender_color(&colors[gi->src_color]),
|
||||
stdformat_to_str(gi->mask_format));
|
||||
|
||||
if (format) {
|
||||
buf[len++] = ' ';
|
||||
va_start(ap, format);
|
||||
vsprintf(buf+len, format, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
static void single(struct test *t, enum target target)
|
||||
{
|
||||
struct glyph_iter gi;
|
||||
int n;
|
||||
|
||||
printf("Testing single glyph (%s): ", test_target_name(target));
|
||||
fflush(stdout);
|
||||
|
||||
glyph_iter_init(&gi, t, target);
|
||||
while (glyph_iter_next(&gi)) {
|
||||
XGlyphElt8 elt;
|
||||
char id[N_GLYPHS];
|
||||
|
||||
for (n = 0; n < N_GLYPHS; n++) {
|
||||
id[n] = n;
|
||||
|
||||
elt.chars = &id[n];
|
||||
elt.nchars = 1;
|
||||
elt.xOff = 0;
|
||||
elt.yOff = 0;
|
||||
|
||||
clear(gi.out.dpy, &gi.out.tt, &colors[gi.dst_color]);
|
||||
elt.glyphset = gi.out.glyphset;
|
||||
XRenderCompositeText8 (gi.out.dpy->dpy, gi.op,
|
||||
gi.out.src,
|
||||
gi.out.tt.picture,
|
||||
gi.out.mask_format,
|
||||
0, 0,
|
||||
0, 8,
|
||||
&elt, 1);
|
||||
|
||||
clear(gi.ref.dpy, &gi.ref.tt, &colors[gi.dst_color]);
|
||||
elt.glyphset = gi.ref.glyphset;
|
||||
XRenderCompositeText8 (gi.ref.dpy->dpy, gi.op,
|
||||
gi.ref.src,
|
||||
gi.ref.tt.picture,
|
||||
gi.ref.mask_format,
|
||||
0, 0,
|
||||
0, 8,
|
||||
&elt, 1);
|
||||
test_compare(t,
|
||||
gi.out.tt.draw, gi.out.tt.format,
|
||||
gi.ref.tt.draw, gi.ref.tt.format,
|
||||
0, 0, gi.out.tt.width, gi.out.tt.height,
|
||||
glyph_iter_to_string(&gi,
|
||||
"glyph=%s",
|
||||
glyph_name(n)));
|
||||
}
|
||||
|
||||
elt.chars = &id[0];
|
||||
elt.nchars = n;
|
||||
clear(gi.out.dpy, &gi.out.tt, &colors[gi.dst_color]);
|
||||
elt.glyphset = gi.out.glyphset;
|
||||
XRenderCompositeText8 (gi.out.dpy->dpy, gi.op,
|
||||
gi.out.src,
|
||||
gi.out.tt.picture,
|
||||
gi.out.mask_format,
|
||||
0, 0,
|
||||
0, 8,
|
||||
&elt, 1);
|
||||
|
||||
clear(gi.ref.dpy, &gi.ref.tt, &colors[gi.dst_color]);
|
||||
elt.glyphset = gi.ref.glyphset;
|
||||
XRenderCompositeText8 (gi.ref.dpy->dpy, gi.op,
|
||||
gi.ref.src,
|
||||
gi.ref.tt.picture,
|
||||
gi.ref.mask_format,
|
||||
0, 0,
|
||||
0, 8,
|
||||
&elt, 1);
|
||||
test_compare(t,
|
||||
gi.out.tt.draw, gi.out.tt.format,
|
||||
gi.ref.tt.draw, gi.ref.tt.format,
|
||||
0, 0, gi.out.tt.width, gi.out.tt.height,
|
||||
glyph_iter_to_string(&gi, "all"));
|
||||
}
|
||||
glyph_iter_fini(&gi);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
struct test test;
|
||||
int t;
|
||||
|
||||
test_init(&test, argc, argv);
|
||||
XSetErrorHandler(_check_error_handler);
|
||||
|
||||
for (t = TARGET_FIRST; t <= TARGET_LAST; t++) {
|
||||
single(&test, t);
|
||||
//overlapping(&test, t);
|
||||
//gap(&test, t);
|
||||
//mixed(&test, t);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -107,6 +107,15 @@ static inline uint32_t color(uint8_t red, uint8_t green, uint8_t blue, uint8_t a
|
|||
return alpha << 24 | ra >> 8 << 16 | ga >> 8 << 8 | ba >> 8;
|
||||
}
|
||||
|
||||
static inline uint32_t xrender_color(const XRenderColor *c)
|
||||
{
|
||||
uint32_t ra = c->red * c->alpha;
|
||||
uint32_t ga = c->green * c->alpha;
|
||||
uint32_t ba = c->blue * c->alpha;
|
||||
|
||||
return c->alpha >> 8 << 24 | ra >> 24 << 16 | ga >> 24 << 8 | ba >> 24;
|
||||
}
|
||||
|
||||
void test_timer_start(struct test_display *t, struct timespec *tv);
|
||||
double test_timer_stop(struct test_display *t, struct timespec *tv);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue