os: if inet_ntop() is available, use it for IPv4 addresses as well
[xserver.git] / glamor / glamor_glyphblt.c
blob4ab23b333c694ca6913415cfcdb5e49b7b84d650
1 /*
2 * Copyright © 2009 Intel Corporation
3 * Copyright © 1998 Keith Packard
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:
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.
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.
24 * Authors:
25 * Zhigang Gong <zhigang.gong@gmail.com>
29 #include "glamor_priv.h"
30 #include <dixfontstr.h>
31 #include "glamor_transform.h"
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)),
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)
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;
55 pixmap_priv = glamor_get_pixmap_private(pixmap);
56 if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
57 goto bail;
59 glamor_make_current(glamor_priv);
61 prog = glamor_use_program_fill(drawable, gc,
62 &glamor_priv->poly_glyph_blt_progs,
63 &glamor_facet_poly_glyph_blt);
64 if (!prog)
65 goto bail;
67 glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
69 start_x += drawable->x;
70 y += drawable->y;
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;
80 if (!glamor_set_destination_drawable(drawable, box_index, FALSE, TRUE,
81 prog->matrix_uniform, &off_x, &off_y))
82 goto bail;
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);
93 if (w && h) {
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;
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;
105 #if BITMAP_BIT_ORDER == MSBFirst
106 if (!(*glyph & (128 >> (xx & 7))))
107 #else
108 if (!(*glyph & (1 << (xx & 7))))
109 #endif
110 continue;
112 if (!RegionContainsPoint(clip, pt_x_i, pt_y_i, NULL))
113 continue;
115 if (!num_points) {
116 points = glamor_get_vbo_space(screen,
117 max_points *
118 (2 * sizeof (INT16)),
119 &vbo_offset);
121 glVertexAttribPointer(GLAMOR_VERTEX_POS,
122 2, GL_SHORT,
123 GL_FALSE, 0, vbo_offset);
126 *points++ = pt_x_i;
127 *points++ = pt_y_i;
128 num_points++;
130 if (num_points == max_points) {
131 glamor_put_vbo_space(screen);
132 glDrawArrays(GL_POINTS, 0, num_points);
133 num_points = 0;
136 glyphbits += glyph_stride;
139 x += charinfo->metrics.characterWidth;
142 if (num_points) {
143 glamor_put_vbo_space(screen);
144 glDrawArrays(GL_POINTS, 0, num_points);
148 ret = TRUE;
150 bail:
151 glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
153 return ret;
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)
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);
168 static Bool
169 glamor_push_pixels_gl(GCPtr gc, PixmapPtr bitmap,
170 DrawablePtr drawable, int w, int h, int x, int y)
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;
187 if (w * h > MAXINT / (2 * sizeof(float)))
188 goto bail;
190 pixmap_priv = glamor_get_pixmap_private(pixmap);
191 if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
192 goto bail;
194 glamor_make_current(glamor_priv);
196 prog = glamor_use_program_fill(drawable, gc,
197 &glamor_priv->poly_glyph_blt_progs,
198 &glamor_facet_poly_glyph_blt);
199 if (!prog)
200 goto bail;
202 glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
204 points = glamor_get_vbo_space(screen, w * h * sizeof(INT16) * 2,
205 &vbo_offset);
206 num_points = 0;
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).
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++;
231 glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_SHORT,
232 GL_FALSE, 0, vbo_offset);
234 glamor_put_vbo_space(screen);
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;
241 glDrawArrays(GL_POINTS, 0, num_points);
244 ret = TRUE;
246 bail:
247 glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
249 return ret;
252 void
253 glamor_push_pixels(GCPtr pGC, PixmapPtr pBitmap,
254 DrawablePtr pDrawable, int w, int h, int x, int y)
256 if (glamor_push_pixels_gl(pGC, pBitmap, pDrawable, w, h, x, y))
257 return;
259 miPushPixels(pGC, pBitmap, pDrawable, w, h, x, y);