glamor_glyphblt.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  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@gmail.com>
  26. *
  27. */
  28. #include "glamor_priv.h"
  29. #include <dixfontstr.h>
  30. #include "glamor_transform.h"
  31. static const glamor_facet glamor_facet_poly_glyph_blt = {
  32. .name = "poly_glyph_blt",
  33. .vs_vars = "attribute vec2 primitive;\n",
  34. .vs_exec = (" vec2 pos = vec2(0,0);\n"
  35. GLAMOR_POS(gl_Position, primitive)),
  36. };
  37. static Bool
  38. glamor_poly_glyph_blt_gl(DrawablePtr drawable, GCPtr gc,
  39. int start_x, int y, unsigned int nglyph,
  40. CharInfoPtr *ppci, void *pglyph_base)
  41. {
  42. ScreenPtr screen = drawable->pScreen;
  43. glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
  44. PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable);
  45. glamor_pixmap_private *pixmap_priv;
  46. glamor_program *prog;
  47. RegionPtr clip = gc->pCompositeClip;
  48. int box_x, box_y;
  49. pixmap_priv = glamor_get_pixmap_private(pixmap);
  50. if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
  51. goto bail;
  52. glamor_make_current(glamor_priv);
  53. prog = glamor_use_program_fill(pixmap, gc, &glamor_priv->poly_glyph_blt_progs,
  54. &glamor_facet_poly_glyph_blt);
  55. if (!prog)
  56. goto bail_ctx;
  57. glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
  58. start_x += drawable->x;
  59. y += drawable->y;
  60. glamor_pixmap_loop(pixmap_priv, box_x, box_y) {
  61. int x;
  62. int n;
  63. int num_points, max_points;
  64. INT16 *points = NULL;
  65. int off_x, off_y;
  66. char *vbo_offset;
  67. glamor_set_destination_drawable(drawable, box_x, box_y, FALSE, TRUE, prog->matrix_uniform, &off_x, &off_y);
  68. max_points = 500;
  69. num_points = 0;
  70. x = start_x;
  71. for (n = 0; n < nglyph; n++) {
  72. CharInfoPtr charinfo = ppci[n];
  73. int w = GLYPHWIDTHPIXELS(charinfo);
  74. int h = GLYPHHEIGHTPIXELS(charinfo);
  75. uint8_t *glyphbits = FONTGLYPHBITS(NULL, charinfo);
  76. if (w && h) {
  77. int glyph_x = x + charinfo->metrics.leftSideBearing;
  78. int glyph_y = y - charinfo->metrics.ascent;
  79. int glyph_stride = GLYPHWIDTHBYTESPADDED(charinfo);
  80. int xx, yy;
  81. for (yy = 0; yy < h; yy++) {
  82. uint8_t *glyph = glyphbits;
  83. for (xx = 0; xx < w; glyph += ((xx&7) == 7), xx++) {
  84. int pt_x_i = glyph_x + xx;
  85. int pt_y_i = glyph_y + yy;
  86. if (!(*glyph & (1 << (xx & 7))))
  87. continue;
  88. if (!RegionContainsPoint(clip, pt_x_i, pt_y_i, NULL))
  89. continue;
  90. if (!num_points) {
  91. points = glamor_get_vbo_space(screen,
  92. max_points * (2 * sizeof (INT16)),
  93. &vbo_offset);
  94. glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_SHORT,
  95. GL_FALSE, 0, vbo_offset);
  96. }
  97. *points++ = pt_x_i;
  98. *points++ = pt_y_i;
  99. num_points++;
  100. if (num_points == max_points) {
  101. glamor_put_vbo_space(screen);
  102. glDrawArrays(GL_POINTS, 0, num_points);
  103. num_points = 0;
  104. }
  105. }
  106. glyphbits += glyph_stride;
  107. }
  108. }
  109. x += charinfo->metrics.characterWidth;
  110. }
  111. if (num_points) {
  112. glamor_put_vbo_space(screen);
  113. glDrawArrays(GL_POINTS, 0, num_points);
  114. }
  115. }
  116. glDisable(GL_COLOR_LOGIC_OP);
  117. glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
  118. return TRUE;
  119. bail_ctx:
  120. glDisable(GL_COLOR_LOGIC_OP);
  121. bail:
  122. return FALSE;
  123. }
  124. void
  125. glamor_poly_glyph_blt(DrawablePtr drawable, GCPtr gc,
  126. int start_x, int y, unsigned int nglyph,
  127. CharInfoPtr *ppci, void *pglyph_base)
  128. {
  129. if (glamor_poly_glyph_blt_gl(drawable, gc, start_x, y, nglyph, ppci, pglyph_base))
  130. return;
  131. miPolyGlyphBlt(drawable, gc, start_x, y, nglyph,
  132. ppci, pglyph_base);
  133. }
  134. Bool
  135. glamor_poly_glyph_blt_nf(DrawablePtr drawable, GCPtr gc,
  136. int start_x, int y, unsigned int nglyph,
  137. CharInfoPtr *ppci, void *pglyph_base)
  138. {
  139. if (glamor_poly_glyph_blt_gl(drawable, gc, start_x, y, nglyph, ppci, pglyph_base))
  140. return TRUE;
  141. if (glamor_ddx_fallback_check_pixmap(drawable) && glamor_ddx_fallback_check_gc(gc))
  142. return FALSE;
  143. miPolyGlyphBlt(drawable, gc, start_x, y, nglyph,
  144. ppci, pglyph_base);
  145. return TRUE;
  146. }
  147. Bool
  148. glamor_image_glyph_blt_nf(DrawablePtr drawable, GCPtr gc,
  149. int start_x, int y, unsigned int nglyph,
  150. CharInfoPtr *ppci, void *pglyph_base)
  151. {
  152. miImageGlyphBlt(drawable, gc, start_x, y, nglyph, ppci, pglyph_base);
  153. return TRUE;
  154. }
  155. static Bool
  156. glamor_push_pixels_points(GCPtr gc, PixmapPtr bitmap,
  157. DrawablePtr drawable, int w, int h, int x, int y)
  158. {
  159. ScreenPtr screen = drawable->pScreen;
  160. glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
  161. PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable);
  162. glamor_pixmap_private *pixmap_priv;
  163. uint8_t *bitmap_data = bitmap->devPrivate.ptr;
  164. int bitmap_stride = bitmap->devKind;
  165. int off_x, off_y;
  166. int yy, xx;
  167. GLfloat xscale, yscale;
  168. float color[4];
  169. unsigned long fg_pixel = gc->fgPixel;
  170. float *points, *next_point;
  171. int num_points = 0;
  172. char *vbo_offset;
  173. RegionPtr clip;
  174. if (w * h > MAXINT / (2 * sizeof(float)))
  175. return FALSE;
  176. if (gc->fillStyle != FillSolid) {
  177. glamor_fallback("gc fillstyle not solid\n");
  178. return FALSE;
  179. }
  180. pixmap_priv = glamor_get_pixmap_private(pixmap);
  181. if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
  182. return FALSE;
  183. glamor_make_current(glamor_priv);
  184. if (!glamor_set_alu(screen, gc->alu)) {
  185. if (gc->alu == GXclear)
  186. fg_pixel = 0;
  187. else {
  188. glamor_fallback("unsupported alu %x\n", gc->alu);
  189. return FALSE;
  190. }
  191. }
  192. if (!glamor_set_planemask(pixmap, gc->planemask)) {
  193. glamor_fallback("Failed to set planemask in %s.\n", __FUNCTION__);
  194. return FALSE;
  195. }
  196. glamor_get_drawable_deltas(drawable, pixmap, &off_x, &off_y);
  197. glamor_set_destination_pixmap_priv_nc(pixmap_priv);
  198. pixmap_priv_get_dest_scale(pixmap_priv, &xscale, &yscale);
  199. glUseProgram(glamor_priv->solid_prog);
  200. glamor_get_rgba_from_pixel(fg_pixel,
  201. &color[0], &color[1], &color[2], &color[3],
  202. format_for_pixmap(pixmap));
  203. glUniform4fv(glamor_priv->solid_color_uniform_location, 1, color);
  204. points = glamor_get_vbo_space(screen, w * h * sizeof(float) * 2,
  205. &vbo_offset);
  206. next_point = points;
  207. clip = fbGetCompositeClip(gc);
  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. for (yy = 0; yy < h; yy++) {
  213. uint8_t *bitmap_row = bitmap_data + yy * bitmap_stride;
  214. for (xx = 0; xx < w; xx++) {
  215. if (bitmap_row[xx / 8] & (1 << xx % 8) &&
  216. RegionContainsPoint(clip,
  217. x + xx,
  218. y + yy,
  219. NULL)) {
  220. next_point[0] = v_from_x_coord_x(xscale, x + xx + off_x + 0.5);
  221. if (glamor_priv->yInverted)
  222. next_point[1] = v_from_x_coord_y_inverted(yscale, y + yy + off_y + 0.5);
  223. else
  224. next_point[1] = v_from_x_coord_y(yscale, y + yy + off_y + 0.5);
  225. next_point += 2;
  226. num_points++;
  227. }
  228. }
  229. }
  230. glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT,
  231. GL_FALSE, 2 * sizeof(float),
  232. vbo_offset);
  233. glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
  234. glamor_put_vbo_space(screen);
  235. glDrawArrays(GL_POINTS, 0, num_points);
  236. glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
  237. return TRUE;
  238. }
  239. static Bool
  240. _glamor_push_pixels(GCPtr pGC, PixmapPtr pBitmap,
  241. DrawablePtr pDrawable, int w, int h, int x, int y,
  242. Bool fallback)
  243. {
  244. glamor_pixmap_private *pixmap_priv;
  245. if (!fallback && glamor_ddx_fallback_check_pixmap(pDrawable)
  246. && glamor_ddx_fallback_check_pixmap(&pBitmap->drawable)
  247. && glamor_ddx_fallback_check_gc(pGC))
  248. return FALSE;
  249. pixmap_priv = glamor_get_pixmap_private(pBitmap);
  250. if (pixmap_priv->type == GLAMOR_MEMORY) {
  251. if (glamor_push_pixels_points(pGC, pBitmap, pDrawable, w, h, x, y))
  252. return TRUE;
  253. }
  254. miPushPixels(pGC, pBitmap, pDrawable, w, h, x, y);
  255. return TRUE;
  256. }
  257. void
  258. glamor_push_pixels(GCPtr pGC, PixmapPtr pBitmap,
  259. DrawablePtr pDrawable, int w, int h, int x, int y)
  260. {
  261. _glamor_push_pixels(pGC, pBitmap, pDrawable, w, h, x, y, TRUE);
  262. }
  263. Bool
  264. glamor_push_pixels_nf(GCPtr pGC, PixmapPtr pBitmap,
  265. DrawablePtr pDrawable, int w, int h, int x, int y)
  266. {
  267. return _glamor_push_pixels(pGC, pBitmap, pDrawable, w, h, x, y, FALSE);
  268. }