1 /* 2 * Copyright 2009 Intel Corporation 3 * Copyright 1998 Keith Packard 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the "Software"), 7 * to deal in the Software without restriction, including without limitation 8 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 * and/or sell copies of the Software, and to permit persons to whom the 10 * Software is furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice (including the next 13 * paragraph) shall be included in all copies or substantial portions of the 14 * Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 22 * IN THE SOFTWARE. 23 * 24 * Authors: 25 * Zhigang Gong <zhigang.gong (at) gmail.com> 26 * 27 */ 28 29 #include "glamor_priv.h" 30 #include <dixfontstr.h> 31 #include "glamor_transform.h" 32 33 static const glamor_facet glamor_facet_poly_glyph_blt = { 34 .name = "poly_glyph_blt", 35 .vs_vars = "in vec2 primitive;\n", 36 .vs_exec = (" vec2 pos = vec2(0,0);\n" 37 GLAMOR_DEFAULT_POINT_SIZE 38 GLAMOR_POS(gl_Position, primitive)), 39 }; 40 41 static Bool 42 glamor_poly_glyph_blt_gl(DrawablePtr drawable, GCPtr gc, 43 int start_x, int y, unsigned int nglyph, 44 CharInfoPtr *ppci, void *pglyph_base) 45 { 46 ScreenPtr screen = drawable->pScreen; 47 glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); 48 PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); 49 glamor_pixmap_private *pixmap_priv; 50 glamor_program *prog; 51 RegionPtr clip = gc->pCompositeClip; 52 int box_index; 53 Bool ret = FALSE; 54 55 pixmap_priv = glamor_get_pixmap_private(pixmap); 56 if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) 57 goto bail; 58 59 glamor_make_current(glamor_priv); 60 61 prog = glamor_use_program_fill(pixmap, gc, 62 &glamor_priv->poly_glyph_blt_progs, 63 &glamor_facet_poly_glyph_blt); 64 if (!prog) 65 goto bail; 66 67 glEnableVertexAttribArray(GLAMOR_VERTEX_POS); 68 69 start_x += drawable->x; 70 y += drawable->y; 71 72 glamor_pixmap_loop(pixmap_priv, box_index) { 73 int x; 74 int n; 75 int num_points, max_points; 76 INT16 *points = NULL; 77 int off_x, off_y; 78 char *vbo_offset; 79 80 if (!glamor_set_destination_drawable(drawable, box_index, FALSE, TRUE, 81 prog->matrix_uniform, &off_x, &off_y)) 82 goto bail; 83 84 max_points = 500; 85 num_points = 0; 86 x = start_x; 87 for (n = 0; n < nglyph; n++) { 88 CharInfoPtr charinfo = ppci[n]; 89 int w = GLYPHWIDTHPIXELS(charinfo); 90 int h = GLYPHHEIGHTPIXELS(charinfo); 91 uint8_t *glyphbits = FONTGLYPHBITS(NULL, charinfo); 92 93 if (w > 0 && h > 0) { 94 int glyph_x = x + charinfo->metrics.leftSideBearing; 95 int glyph_y = y - charinfo->metrics.ascent; 96 int glyph_stride = GLYPHWIDTHBYTESPADDED(charinfo); 97 int xx, yy; 98 99 for (yy = 0; yy < h; yy++) { 100 uint8_t *glyph = glyphbits; 101 for (xx = 0; xx < w; glyph += ((xx&7) == 7), xx++) { 102 int pt_x_i = glyph_x + xx; 103 int pt_y_i = glyph_y + yy; 104 105 #if BITMAP_BIT_ORDER == MSBFirst 106 if (!(*glyph & (128 >> (xx & 7)))) 107 #else 108 if (!(*glyph & (1 << (xx & 7)))) 109 #endif 110 continue; 111 112 if (!RegionContainsPoint(clip, pt_x_i, pt_y_i, NULL)) 113 continue; 114 115 if (!num_points) { 116 points = glamor_get_vbo_space(screen, 117 max_points * 118 (2 * sizeof (INT16)), 119 &vbo_offset); 120 121 glVertexAttribPointer(GLAMOR_VERTEX_POS, 122 2, GL_SHORT, 123 GL_FALSE, 0, vbo_offset); 124 } 125 126 *points++ = pt_x_i; 127 *points++ = pt_y_i; 128 num_points++; 129 130 if (num_points == max_points) { 131 glamor_put_vbo_space(screen); 132 glDrawArrays(GL_POINTS, 0, num_points); 133 num_points = 0; 134 } 135 } 136 glyphbits += glyph_stride; 137 } 138 } 139 x += charinfo->metrics.characterWidth; 140 } 141 142 if (num_points) { 143 glamor_put_vbo_space(screen); 144 glDrawArrays(GL_POINTS, 0, num_points); 145 } 146 } 147 148 ret = TRUE; 149 150 bail: 151 glDisableVertexAttribArray(GLAMOR_VERTEX_POS); 152 153 return ret; 154 } 155 156 void 157 glamor_poly_glyph_blt(DrawablePtr drawable, GCPtr gc, 158 int start_x, int y, unsigned int nglyph, 159 CharInfoPtr *ppci, void *pglyph_base) 160 { 161 if (glamor_poly_glyph_blt_gl(drawable, gc, start_x, y, nglyph, ppci, 162 pglyph_base)) 163 return; 164 miPolyGlyphBlt(drawable, gc, start_x, y, nglyph, 165 ppci, pglyph_base); 166 } 167 168 static Bool 169 glamor_push_pixels_gl(GCPtr gc, PixmapPtr bitmap, 170 DrawablePtr drawable, int w, int h, int x, int y) 171 { 172 ScreenPtr screen = drawable->pScreen; 173 glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); 174 PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); 175 glamor_pixmap_private *pixmap_priv; 176 uint8_t *bitmap_data = bitmap->devPrivate.ptr; 177 int bitmap_stride = bitmap->devKind; 178 glamor_program *prog; 179 RegionPtr clip = gc->pCompositeClip; 180 int box_index; 181 int yy, xx; 182 int num_points; 183 INT16 *points = NULL; 184 char *vbo_offset; 185 Bool ret = FALSE; 186 187 if (w * h > MAXINT / (2 * sizeof(float))) 188 goto bail; 189 190 pixmap_priv = glamor_get_pixmap_private(pixmap); 191 if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) 192 goto bail; 193 194 glamor_make_current(glamor_priv); 195 196 prog = glamor_use_program_fill(pixmap, gc, 197 &glamor_priv->poly_glyph_blt_progs, 198 &glamor_facet_poly_glyph_blt); 199 if (!prog) 200 goto bail; 201 202 glEnableVertexAttribArray(GLAMOR_VERTEX_POS); 203 204 points = glamor_get_vbo_space(screen, w * h * sizeof(INT16) * 2, 205 &vbo_offset); 206 num_points = 0; 207 208 /* Note that because fb sets miTranslate in the GC, our incoming X 209 * and Y are in screen coordinate space (same for spans, but not 210 * other operations). 211 */ 212 213 for (yy = 0; yy < h; yy++) { 214 uint8_t *bitmap_row = bitmap_data + yy * bitmap_stride; 215 for (xx = 0; xx < w; xx++) { 216 #if BITMAP_BIT_ORDER == MSBFirst 217 if (bitmap_row[xx / 8] & (128 >> xx % 8) && 218 #else 219 if (bitmap_row[xx / 8] & (1 << xx % 8) && 220 #endif 221 RegionContainsPoint(clip, 222 x + xx, 223 y + yy, 224 NULL)) { 225 *points++ = x + xx; 226 *points++ = y + yy; 227 num_points++; 228 } 229 } 230 } 231 glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_SHORT, 232 GL_FALSE, 0, vbo_offset); 233 234 glamor_put_vbo_space(screen); 235 236 glamor_pixmap_loop(pixmap_priv, box_index) { 237 if (!glamor_set_destination_drawable(drawable, box_index, FALSE, TRUE, 238 prog->matrix_uniform, NULL, NULL)) 239 goto bail; 240 241 glDrawArrays(GL_POINTS, 0, num_points); 242 } 243 244 ret = TRUE; 245 246 bail: 247 glDisableVertexAttribArray(GLAMOR_VERTEX_POS); 248 249 return ret; 250 } 251 252 void 253 glamor_push_pixels(GCPtr pGC, PixmapPtr pBitmap, 254 DrawablePtr pDrawable, int w, int h, int x, int y) 255 { 256 if (glamor_push_pixels_gl(pGC, pBitmap, pDrawable, w, h, x, y)) 257 return; 258 259 miPushPixels(pGC, pBitmap, pDrawable, w, h, x, y); 260 } 261