summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/glamor_glyphblt.c140
1 files changed, 140 insertions, 0 deletions
diff --git a/src/glamor_glyphblt.c b/src/glamor_glyphblt.c
index 35be282..ca92100 100644
--- a/src/glamor_glyphblt.c
+++ b/src/glamor_glyphblt.c
@@ -27,6 +27,143 @@
*/
#include "glamor_priv.h"
+#include <dixfontstr.h>
+
+static Bool
+glamor_poly_glyph_blt_pixels(DrawablePtr drawable, GCPtr gc,
+ int x, int y, unsigned int nglyph,
+ CharInfoPtr *ppci)
+{
+ ScreenPtr screen = drawable->pScreen;
+ glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
+ PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable);
+ glamor_pixmap_private *pixmap_priv;
+ int off_x, off_y;
+ GLfloat xscale, yscale;
+ float color[4];
+ unsigned long fg_pixel = gc->fgPixel;
+ char *vbo_offset;
+ RegionPtr clip;
+ int num_points, max_points;
+ float *points = NULL;
+ glamor_gl_dispatch *dispatch;
+
+ x += drawable->x;
+ y += drawable->y;
+
+ if (gc->fillStyle != FillSolid) {
+ glamor_fallback("gc fillstyle not solid\n");
+ return FALSE;
+ }
+
+ pixmap_priv = glamor_get_pixmap_private(pixmap);
+ if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
+ return FALSE;
+
+ dispatch = glamor_get_dispatch(glamor_priv);
+ if (!glamor_set_alu(dispatch, gc->alu)) {
+ if (gc->alu == GXclear)
+ fg_pixel = 0;
+ else {
+ glamor_fallback("unsupported alu %x\n", gc->alu);
+ glamor_put_dispatch(glamor_priv);
+ return FALSE;
+ }
+ }
+
+ if (!glamor_set_planemask(pixmap, gc->planemask)) {
+ glamor_fallback("Failed to set planemask in %s.\n", __FUNCTION__);
+ glamor_put_dispatch(glamor_priv);
+ return FALSE;
+ }
+
+ glamor_get_drawable_deltas(drawable, pixmap, &off_x, &off_y);
+
+ glamor_set_destination_pixmap_priv_nc(pixmap_priv);
+ pixmap_priv_get_dest_scale(pixmap_priv, &xscale, &yscale);
+
+ dispatch->glUseProgram(glamor_priv->solid_prog);
+
+ glamor_get_rgba_from_pixel(fg_pixel,
+ &color[0], &color[1], &color[2], &color[3],
+ format_for_pixmap(pixmap));
+ dispatch->glUniform4fv(glamor_priv->solid_color_uniform_location, 1, color);
+
+ clip = fbGetCompositeClip(gc);
+
+ dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
+
+ max_points = 500;
+ num_points = 0;
+ while (nglyph--) {
+ CharInfoPtr charinfo = *ppci++;
+ int w = GLYPHWIDTHPIXELS(charinfo);
+ int h = GLYPHHEIGHTPIXELS(charinfo);
+ uint8_t *glyphbits = FONTGLYPHBITS(NULL, charinfo);
+
+ if (w && h) {
+ int glyph_x = x + charinfo->metrics.leftSideBearing;
+ int glyph_y = y - charinfo->metrics.ascent;
+ int glyph_stride = GLYPHWIDTHBYTESPADDED(charinfo);
+ int xx, yy;
+
+ for (yy = 0; yy < h; yy++) {
+ uint8_t *glyph_row = glyphbits + glyph_stride * yy;
+ for (xx = 0; xx < w; xx++) {
+ int pt_x_i = glyph_x + xx;
+ int pt_y_i = glyph_y + yy;
+ float pt_x_f, pt_y_f;
+ if (!(glyph_row[xx / 8] & (1 << xx % 8)))
+ continue;
+
+ if (!RegionContainsPoint(clip, pt_x_i, pt_y_i, NULL))
+ continue;
+
+ if (!num_points) {
+ points = glamor_get_vbo_space(screen,
+ max_points * 2 * sizeof(float),
+ &vbo_offset);
+
+ dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT,
+ GL_FALSE, 2 * sizeof(float),
+ vbo_offset);
+ }
+
+ pt_x_f = v_from_x_coord_x(xscale, pt_x_i + off_x + 0.5);
+ if (glamor_priv->yInverted)
+ pt_y_f = v_from_x_coord_y_inverted(yscale, pt_y_i + off_y + 0.5);
+ else
+ pt_y_f = v_from_x_coord_y(yscale, pt_y_i + off_y + 0.5);
+
+ points[num_points * 2 + 0] = pt_x_f;
+ points[num_points * 2 + 1] = pt_y_f;
+ num_points++;
+
+ if (num_points == max_points) {
+ glamor_put_vbo_space(screen);
+ dispatch->glDrawArrays(GL_POINTS, 0, num_points);
+ num_points = 0;
+ }
+ }
+ }
+ }
+
+ x += charinfo->metrics.characterWidth;
+ }
+
+ if (num_points) {
+ glamor_put_vbo_space(screen);
+ dispatch->glDrawArrays(GL_POINTS, 0, num_points);
+ }
+
+ dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
+ dispatch->glBindBuffer(GL_ARRAY_BUFFER, 0);
+ dispatch->glUseProgram(0);
+
+ glamor_put_dispatch(glamor_priv);
+
+ return TRUE;
+}
static Bool
_glamor_image_glyph_blt(DrawablePtr pDrawable, GCPtr pGC,
@@ -63,6 +200,9 @@ _glamor_poly_glyph_blt(DrawablePtr pDrawable, GCPtr pGC,
int x, int y, unsigned int nglyph,
CharInfoPtr * ppci, pointer pglyphBase, Bool fallback)
{
+ if (glamor_poly_glyph_blt_pixels(pDrawable, pGC, x, y, nglyph, ppci))
+ return TRUE;
+
if (!fallback
&& glamor_ddx_fallback_check_pixmap(pDrawable)
&& glamor_ddx_fallback_check_gc(pGC))