glamor: Add accelerated stipple support
This copies the stipple to a 8bpp pixmap and uses that to paint the texture from. v2: Create deep stipple pixmap without GLAMOR_CREATE_FBO_NO_FBO v3: Fix stipple origin sign (matches tiles now). Track changes to original stipple with damage. This isn't required by the X spec, but java appears to depend on it, so we'll just do it. When Glamor switches to 8bpp bitmaps, we'll be able to render directly from them and not need this anymore. v4: Review comments from Eric: * Remove stray whitespace change * Avoid "large" pixmap for stipple by using GLAMOR_CREATE_NO_LARGE * Wrap to 80 columns v5: Don't crash when stipple damage tracker is destroyed The stipple damage tracker is automatically destroyed when the associated stipple pixmap is destroyed. When this happens, just clear the pointer from the GC rather than calling glamor_invalidate_stipple; that function would call DamageUnregister on the now invalid stipple damage pointer and crash. Signed-off-by: Keith Packard <keithp@keithp.com> Reviewed-by: Eric Anholt <eric@anholt.net>
This commit is contained in:
parent
d18f5801c9
commit
bd3b2c48f6
|
@ -326,6 +326,58 @@ GCOps glamor_gc_ops = {
|
|||
.PushPixels = glamor_push_pixels,
|
||||
};
|
||||
|
||||
/*
|
||||
* When the stipple is changed or drawn to, invalidate any
|
||||
* cached copy
|
||||
*/
|
||||
static void
|
||||
glamor_invalidate_stipple(GCPtr gc)
|
||||
{
|
||||
glamor_gc_private *gc_priv = glamor_get_gc_private(gc);
|
||||
|
||||
if (gc_priv->stipple) {
|
||||
if (gc_priv->stipple_damage)
|
||||
DamageUnregister(gc_priv->stipple_damage);
|
||||
glamor_destroy_pixmap(gc_priv->stipple);
|
||||
gc_priv->stipple = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
glamor_stipple_damage_report(DamagePtr damage, RegionPtr region,
|
||||
void *closure)
|
||||
{
|
||||
GCPtr gc = closure;
|
||||
|
||||
glamor_invalidate_stipple(gc);
|
||||
}
|
||||
|
||||
static void
|
||||
glamor_stipple_damage_destroy(DamagePtr damage, void *closure)
|
||||
{
|
||||
GCPtr gc = closure;
|
||||
glamor_gc_private *gc_priv = glamor_get_gc_private(gc);
|
||||
|
||||
gc_priv->stipple_damage = NULL;
|
||||
glamor_invalidate_stipple(gc);
|
||||
}
|
||||
|
||||
void
|
||||
glamor_track_stipple(GCPtr gc)
|
||||
{
|
||||
if (gc->stipple) {
|
||||
glamor_gc_private *gc_priv = glamor_get_gc_private(gc);
|
||||
|
||||
if (!gc_priv->stipple_damage)
|
||||
gc_priv->stipple_damage = DamageCreate(glamor_stipple_damage_report,
|
||||
glamor_stipple_damage_destroy,
|
||||
DamageReportNonEmpty,
|
||||
TRUE, gc->pScreen, gc);
|
||||
if (gc_priv->stipple_damage)
|
||||
DamageRegister(&gc->stipple->drawable, gc_priv->stipple_damage);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* uxa_validate_gc() sets the ops to glamor's implementations, which may be
|
||||
* accelerated or may sync the card and fall back to fb.
|
||||
|
@ -396,6 +448,9 @@ glamor_validate_gc(GCPtr gc, unsigned long changes, DrawablePtr drawable)
|
|||
changes &= ~GCTile;
|
||||
}
|
||||
|
||||
if (changes & GCStipple)
|
||||
glamor_invalidate_stipple(gc);
|
||||
|
||||
if (changes & GCStipple && gc->stipple) {
|
||||
/* We can't inline stipple handling like we do for GCTile because
|
||||
* it sets fbgc privates.
|
||||
|
@ -430,6 +485,9 @@ glamor_destroy_gc(GCPtr gc)
|
|||
glamor_destroy_pixmap(gc_priv->dash);
|
||||
gc_priv->dash = NULL;
|
||||
}
|
||||
glamor_invalidate_stipple(gc);
|
||||
if (gc_priv->stipple_damage)
|
||||
DamageDestroy(gc_priv->stipple_damage);
|
||||
miDestroyGC(gc);
|
||||
}
|
||||
|
||||
|
@ -453,6 +511,7 @@ glamor_create_gc(GCPtr gc)
|
|||
glamor_gc_private *gc_priv = glamor_get_gc_private(gc);
|
||||
|
||||
gc_priv->dash = NULL;
|
||||
gc_priv->stipple = NULL;
|
||||
if (!fbCreateGC(gc))
|
||||
return FALSE;
|
||||
|
||||
|
|
|
@ -567,6 +567,8 @@ typedef enum glamor_pixmap_status {
|
|||
|
||||
typedef struct {
|
||||
PixmapPtr dash;
|
||||
PixmapPtr stipple;
|
||||
DamagePtr stipple_damage;
|
||||
} glamor_gc_private;
|
||||
|
||||
extern DevPrivateKeyRec glamor_gc_private_key;
|
||||
|
@ -684,6 +686,9 @@ Bool glamor_set_alu(ScreenPtr screen, unsigned char alu);
|
|||
Bool glamor_set_planemask(PixmapPtr pixmap, unsigned long planemask);
|
||||
RegionPtr glamor_bitmap_to_region(PixmapPtr pixmap);
|
||||
|
||||
void
|
||||
glamor_track_stipple(GCPtr gc);
|
||||
|
||||
/* glamor_fill.c */
|
||||
Bool glamor_fill(DrawablePtr drawable,
|
||||
GCPtr gc, int x, int y, int width, int height, Bool fallback);
|
||||
|
|
|
@ -51,42 +51,51 @@ static const glamor_facet glamor_fill_tile = {
|
|||
.use = use_tile,
|
||||
};
|
||||
|
||||
#if 0
|
||||
static Bool
|
||||
use_stipple(PixmapPtr pixmap, GCPtr gc, glamor_program *prog)
|
||||
use_stipple(PixmapPtr pixmap, GCPtr gc, glamor_program *prog, void *arg)
|
||||
{
|
||||
return glamor_set_stippled(pixmap, gc, prog->fg_uniform, prog->fill_offset_uniform, prog->fill_size_uniform);
|
||||
return glamor_set_stippled(pixmap, gc, prog->fg_uniform,
|
||||
prog->fill_offset_uniform,
|
||||
prog->fill_size_uniform);
|
||||
}
|
||||
|
||||
static const glamor_facet glamor_fill_stipple = {
|
||||
.name = "stipple",
|
||||
.version = 130,
|
||||
.vs_exec = " fill_pos = fill_offset + primitive.xy + pos;\n";
|
||||
.fs_exec = (" if (texelFetch(sampler, ivec2(mod(fill_pos,fill_size)), 0).x == 0)\n"
|
||||
.vs_exec = " fill_pos = (fill_offset + primitive.xy + pos) / fill_size;\n",
|
||||
.fs_exec = (" float a = texture2D(sampler, fill_pos).w;\n"
|
||||
" if (a == 0.0)\n"
|
||||
" discard;\n"
|
||||
" gl_FragColor = fg;\n")
|
||||
.locations = glamor_program_location_fg | glamor_program_location_fill
|
||||
" gl_FragColor = fg;\n"),
|
||||
.locations = glamor_program_location_fg | glamor_program_location_fill,
|
||||
.use = use_stipple,
|
||||
};
|
||||
|
||||
static Bool
|
||||
use_opaque_stipple(PixmapPtr pixmap, GCPtr gc, glamor_program *prog, void *arg)
|
||||
{
|
||||
if (!use_stipple(pixmap, gc, prog, arg))
|
||||
return FALSE;
|
||||
glamor_set_color(pixmap, gc->bgPixel, prog->bg_uniform);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static const glamor_facet glamor_fill_opaque_stipple = {
|
||||
.name = "opaque_stipple",
|
||||
.version = 130,
|
||||
.vs_exec = " fill_pos = fill_offset + primitive.xy + pos;\n";
|
||||
.fs_exec = (" if (texelFetch(sampler, ivec2(mod(fill_pos,fill_size)), 0).x == 0)\n"
|
||||
.vs_exec = " fill_pos = (fill_offset + primitive.xy + pos) / fill_size;\n",
|
||||
.fs_exec = (" float a = texture2D(sampler, fill_pos).w;\n"
|
||||
" if (a == 0.0)\n"
|
||||
" gl_FragColor = bg;\n"
|
||||
" else\n"
|
||||
" gl_FragColor = fg;\n"),
|
||||
.locations = glamor_program_location_fg | glamor_program_location_bg | glamor_program_location_fill
|
||||
.locations = glamor_program_location_fg | glamor_program_location_bg | glamor_program_location_fill,
|
||||
.use = use_opaque_stipple
|
||||
};
|
||||
#endif
|
||||
|
||||
static const glamor_facet *glamor_facet_fill[4] = {
|
||||
&glamor_fill_solid,
|
||||
&glamor_fill_tile,
|
||||
NULL,
|
||||
NULL,
|
||||
&glamor_fill_stipple,
|
||||
&glamor_fill_opaque_stipple,
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
|
|
|
@ -198,6 +198,64 @@ glamor_set_tiled(PixmapPtr pixmap,
|
|||
size_uniform);
|
||||
}
|
||||
|
||||
static PixmapPtr
|
||||
glamor_get_stipple_pixmap(GCPtr gc)
|
||||
{
|
||||
glamor_gc_private *gc_priv = glamor_get_gc_private(gc);
|
||||
ScreenPtr screen = gc->pScreen;
|
||||
PixmapPtr bitmap;
|
||||
PixmapPtr pixmap;
|
||||
GCPtr scratch_gc;
|
||||
ChangeGCVal changes[2];
|
||||
|
||||
if (gc_priv->stipple)
|
||||
return gc_priv->stipple;
|
||||
|
||||
bitmap = gc->stipple;
|
||||
if (!bitmap)
|
||||
goto bail;
|
||||
|
||||
pixmap = glamor_create_pixmap(screen,
|
||||
bitmap->drawable.width,
|
||||
bitmap->drawable.height,
|
||||
8, GLAMOR_CREATE_NO_LARGE);
|
||||
if (!pixmap)
|
||||
goto bail;
|
||||
|
||||
scratch_gc = GetScratchGC(8, screen);
|
||||
if (!scratch_gc)
|
||||
goto bail_pixmap;
|
||||
|
||||
changes[0].val = 0xff;
|
||||
changes[1].val = 0x00;
|
||||
if (ChangeGC(NullClient, scratch_gc,
|
||||
GCForeground|GCBackground, changes) != Success)
|
||||
goto bail_gc;
|
||||
ValidateGC(&pixmap->drawable, scratch_gc);
|
||||
|
||||
(*scratch_gc->ops->CopyPlane)(&bitmap->drawable,
|
||||
&pixmap->drawable,
|
||||
scratch_gc,
|
||||
0, 0,
|
||||
bitmap->drawable.width,
|
||||
bitmap->drawable.height,
|
||||
0, 0, 0x1);
|
||||
|
||||
FreeScratchGC(scratch_gc);
|
||||
gc_priv->stipple = pixmap;
|
||||
|
||||
glamor_track_stipple(gc);
|
||||
|
||||
return pixmap;
|
||||
|
||||
bail_gc:
|
||||
FreeScratchGC(scratch_gc);
|
||||
bail_pixmap:
|
||||
glamor_destroy_pixmap(pixmap);
|
||||
bail:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Bool
|
||||
glamor_set_stippled(PixmapPtr pixmap,
|
||||
GCPtr gc,
|
||||
|
@ -205,11 +263,19 @@ glamor_set_stippled(PixmapPtr pixmap,
|
|||
GLint offset_uniform,
|
||||
GLint size_uniform)
|
||||
{
|
||||
PixmapPtr stipple;
|
||||
|
||||
stipple = glamor_get_stipple_pixmap(gc);
|
||||
if (!stipple)
|
||||
return FALSE;
|
||||
|
||||
if (!glamor_set_solid(pixmap, gc, TRUE, fg_uniform))
|
||||
return FALSE;
|
||||
|
||||
if (!glamor_set_texture(pixmap, gc->stipple, gc->patOrg.x, gc->patOrg.y, offset_uniform, size_uniform))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
return glamor_set_texture(pixmap,
|
||||
stipple,
|
||||
-gc->patOrg.x,
|
||||
-gc->patOrg.y,
|
||||
offset_uniform,
|
||||
size_uniform);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user