aboutsummaryrefslogtreecommitdiff
path: root/xorg-server/glamor/glamor_glyphblt.c
diff options
context:
space:
mode:
authormarha <marha@users.sourceforge.net>2014-03-21 19:36:05 +0100
committermarha <marha@users.sourceforge.net>2014-03-21 19:36:05 +0100
commit41fea4472dec859ddec76bdfa7108ebec71de1e3 (patch)
tree385ccec6dc105acc75169122d4e0714046cfbbd5 /xorg-server/glamor/glamor_glyphblt.c
parentcd8b0d0de3fcb53f6d3ece8ce26d97aaab2c0914 (diff)
downloadvcxsrv-41fea4472dec859ddec76bdfa7108ebec71de1e3.tar.gz
vcxsrv-41fea4472dec859ddec76bdfa7108ebec71de1e3.tar.bz2
vcxsrv-41fea4472dec859ddec76bdfa7108ebec71de1e3.zip
xserver fontconfig libX11 libXext libxcb mesa git update 21 Mar 2014
xserver commit 4fb31e4824d46edc80bb49b4065152899faa5ac6 libxcb commit cb686b576739deea00180c54697c8b62b8419ae0 libX11 commit 8be4610939b833587954957f5963eb4191b43d19 libXext commit 11aad96bd689d54156064d2e81213dc827a689d1 fontconfig commit 5478192f379d784b421329e4bf72cc780818e467 mesa commit 8d8d0cb09eb8735a04fc36cc4d0e2dc9f9d460eb
Diffstat (limited to 'xorg-server/glamor/glamor_glyphblt.c')
-rw-r--r--xorg-server/glamor/glamor_glyphblt.c251
1 files changed, 251 insertions, 0 deletions
diff --git a/xorg-server/glamor/glamor_glyphblt.c b/xorg-server/glamor/glamor_glyphblt.c
index 6f754ce2b..a58cef907 100644
--- a/xorg-server/glamor/glamor_glyphblt.c
+++ b/xorg-server/glamor/glamor_glyphblt.c
@@ -27,6 +27,140 @@
*/
#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;
+
+ 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;
+
+ glamor_get_context(glamor_priv);
+ if (!glamor_set_alu(screen, gc->alu)) {
+ if (gc->alu == GXclear)
+ fg_pixel = 0;
+ else {
+ glamor_fallback("unsupported alu %x\n", gc->alu);
+ glamor_put_context(glamor_priv);
+ return FALSE;
+ }
+ }
+
+ if (!glamor_set_planemask(pixmap, gc->planemask)) {
+ glamor_fallback("Failed to set planemask in %s.\n", __FUNCTION__);
+ glamor_put_context(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);
+
+ glUseProgram(glamor_priv->solid_prog);
+
+ glamor_get_rgba_from_pixel(fg_pixel,
+ &color[0], &color[1], &color[2], &color[3],
+ format_for_pixmap(pixmap));
+ glUniform4fv(glamor_priv->solid_color_uniform_location, 1, color);
+
+ clip = fbGetCompositeClip(gc);
+
+ 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);
+
+ 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);
+ glDrawArrays(GL_POINTS, 0, num_points);
+ num_points = 0;
+ }
+ }
+ }
+ }
+
+ x += charinfo->metrics.characterWidth;
+ }
+
+ if (num_points) {
+ glamor_put_vbo_space(screen);
+ glDrawArrays(GL_POINTS, 0, num_points);
+ }
+
+ glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
+
+ glamor_put_context(glamor_priv);
+
+ return TRUE;
+}
static Bool
_glamor_image_glyph_blt(DrawablePtr pDrawable, GCPtr pGC,
@@ -64,6 +198,9 @@ _glamor_poly_glyph_blt(DrawablePtr pDrawable, GCPtr pGC,
int x, int y, unsigned int nglyph,
CharInfoPtr *ppci, void *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))
return FALSE;
@@ -91,15 +228,129 @@ glamor_poly_glyph_blt_nf(DrawablePtr pDrawable, GCPtr pGC,
}
static Bool
+glamor_push_pixels_points(GCPtr gc, PixmapPtr bitmap,
+ DrawablePtr drawable, int w, int h, int x, int y)
+{
+ 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;
+ uint8_t *bitmap_data = bitmap->devPrivate.ptr;
+ int bitmap_stride = bitmap->devKind;
+ int off_x, off_y;
+ int yy, xx;
+ GLfloat xscale, yscale;
+ float color[4];
+ unsigned long fg_pixel = gc->fgPixel;
+ float *points, *next_point;
+ int num_points = 0;
+ char *vbo_offset;
+ RegionPtr clip;
+
+ if (w * h > MAXINT / (2 * sizeof(float)))
+ return FALSE;
+
+ 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;
+
+ glamor_get_context(glamor_priv);
+ if (!glamor_set_alu(screen, gc->alu)) {
+ if (gc->alu == GXclear)
+ fg_pixel = 0;
+ else {
+ glamor_fallback("unsupported alu %x\n", gc->alu);
+ glamor_put_context(glamor_priv);
+ return FALSE;
+ }
+ }
+
+ if (!glamor_set_planemask(pixmap, gc->planemask)) {
+ glamor_fallback("Failed to set planemask in %s.\n", __FUNCTION__);
+ glamor_put_context(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);
+
+ glUseProgram(glamor_priv->solid_prog);
+
+ glamor_get_rgba_from_pixel(fg_pixel,
+ &color[0], &color[1], &color[2], &color[3],
+ format_for_pixmap(pixmap));
+ glUniform4fv(glamor_priv->solid_color_uniform_location, 1, color);
+
+ points = glamor_get_vbo_space(screen, w * h * sizeof(float) * 2,
+ &vbo_offset);
+ next_point = points;
+
+ clip = fbGetCompositeClip(gc);
+
+ /* Note that because fb sets miTranslate in the GC, our incoming X
+ * and Y are in screen coordinate space (same for spans, but not
+ * other operations).
+ */
+ for (yy = 0; yy < h; yy++) {
+ uint8_t *bitmap_row = bitmap_data + yy * bitmap_stride;
+ for (xx = 0; xx < w; xx++) {
+ if (bitmap_row[xx / 8] & (1 << xx % 8) &&
+ RegionContainsPoint(clip,
+ x + xx,
+ y + yy,
+ NULL)) {
+ next_point[0] = v_from_x_coord_x(xscale, x + xx + off_x + 0.5);
+ if (glamor_priv->yInverted)
+ next_point[1] = v_from_x_coord_y_inverted(yscale, y + yy + off_y + 0.5);
+ else
+ next_point[1] = v_from_x_coord_y(yscale, y + yy + off_y + 0.5);
+
+ next_point += 2;
+ num_points++;
+ }
+ }
+ }
+ glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT,
+ GL_FALSE, 2 * sizeof(float),
+ vbo_offset);
+ glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
+
+ glamor_put_vbo_space(screen);
+
+ glDrawArrays(GL_POINTS, 0, num_points);
+
+ glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
+
+ glamor_put_context(glamor_priv);
+
+ return TRUE;
+}
+
+static Bool
_glamor_push_pixels(GCPtr pGC, PixmapPtr pBitmap,
DrawablePtr pDrawable, int w, int h, int x, int y,
Bool fallback)
{
+ glamor_pixmap_private *pixmap_priv;
+
if (!fallback && glamor_ddx_fallback_check_pixmap(pDrawable)
&& glamor_ddx_fallback_check_pixmap(&pBitmap->drawable)
&& glamor_ddx_fallback_check_gc(pGC))
return FALSE;
+ pixmap_priv = glamor_get_pixmap_private(pBitmap);
+ if (pixmap_priv->type == GLAMOR_MEMORY) {
+ if (glamor_push_pixels_points(pGC, pBitmap, pDrawable, w, h, x, y))
+ return TRUE;
+ }
+
miPushPixels(pGC, pBitmap, pDrawable, w, h, x, y);
return TRUE;
}