[PATCH 06/13] glamor: Add accelerated stipple support
Keith Packard
keithp at keithp.com
Mon May 5 15:02:13 PDT 2014
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.
Signed-off-by: Keith Packard <keithp at keithp.com>
---
glamor/glamor_core.c | 58 ++++++++++++++++++++++++++++++++++++++++
glamor/glamor_priv.h | 5 ++++
glamor/glamor_program.c | 35 ++++++++++++++----------
glamor/glamor_transform.c | 68 ++++++++++++++++++++++++++++++++++++++++++++---
4 files changed, 149 insertions(+), 17 deletions(-)
diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c
index 9d941d7..26eb867 100644
--- a/glamor/glamor_core.c
+++ b/glamor/glamor_core.c
@@ -326,6 +326,56 @@ 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_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,7 +446,11 @@ 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 +484,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 +510,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;
diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h
index e438f7f..a26a758 100644
--- a/glamor/glamor_priv.h
+++ b/glamor/glamor_priv.h
@@ -570,6 +570,8 @@ typedef enum glamor_pixmap_status {
typedef struct {
PixmapPtr dash;
+ PixmapPtr stipple;
+ DamagePtr stipple_damage;
} glamor_gc_private;
extern DevPrivateKeyRec glamor_gc_private_key;
@@ -687,6 +689,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);
diff --git a/glamor/glamor_program.c b/glamor/glamor_program.c
index 0e3e94d..ba9333e 100644
--- a/glamor/glamor_program.c
+++ b/glamor/glamor_program.c
@@ -51,42 +51,49 @@ 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);
}
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 {
diff --git a/glamor/glamor_transform.c b/glamor/glamor_transform.c
index d6ba564..87f8dda 100644
--- a/glamor/glamor_transform.c
+++ b/glamor/glamor_transform.c
@@ -198,6 +198,60 @@ 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, 0);
+ 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 +259,19 @@ glamor_set_stippled(PixmapPtr pixmap,
GLint offset_uniform,
GLint size_uniform)
{
- if (!glamor_set_solid(pixmap, gc, TRUE, fg_uniform))
+ PixmapPtr stipple;
+
+ stipple = glamor_get_stipple_pixmap(gc);
+ if (!stipple)
return FALSE;
- if (!glamor_set_texture(pixmap, gc->stipple, gc->patOrg.x, gc->patOrg.y, offset_uniform, size_uniform))
+ if (!glamor_set_solid(pixmap, gc, TRUE, fg_uniform))
return FALSE;
- return TRUE;
+ return glamor_set_texture(pixmap,
+ stipple,
+ -gc->patOrg.x,
+ -gc->patOrg.y,
+ offset_uniform,
+ size_uniform);
}
--
2.0.0.rc0
More information about the xorg-devel
mailing list