1 #include "evas_gl_private.h"
3 static Evas_GL_Font_Texture_Pool_Allocation *_evas_gl_font_texture_pool_request(Evas_GL_Context *gc, int w, int h);
4 static void _evas_gl_font_texture_pool_relinquish(Evas_GL_Font_Texture_Pool_Allocation *fa);
5 static int _evas_gl_font_texture_pool_rect_find(Evas_GL_Font_Texture_Pool *fp, int w, int h, int *x, int *y);
8 evas_gl_font_texture_new(Evas_GL_Context *gc, RGBA_Font_Glyph *fg)
10 Evas_GL_Font_Texture *ft;
17 if (fg->ext_dat) return fg->ext_dat;
19 w = fg->glyph_out->bitmap.width;
20 h = fg->glyph_out->bitmap.rows;
22 if ((w == 0) || (h == 0)) return NULL;
23 ft = calloc(1, sizeof(Evas_GL_Font_Texture));
26 data = fg->glyph_out->bitmap.buffer;
27 j = fg->glyph_out->bitmap.pitch;
32 /* bug bug! glTexSubImage2D need a multiple of 4 pixels horizontally! :( */
33 nw = ((w + 3) / 4 ) * 4;
34 ndata = malloc(nw *h);
40 if (fg->glyph_out->bitmap.num_grays == 256)
45 for (y = 0; y < h; y++)
48 p2 = ndata + (nw * y);
49 for (x = 0; x < w; x++)
57 else if (fg->glyph_out->bitmap.num_grays == 0)
59 DATA8 *tmpbuf = NULL, *dp, *tp, bits;
61 const DATA8 bitrepl[2] = {0x0, 0xff};
69 for (y = 0; y < h; y++)
72 p2 = ndata + (nw * y);
74 dp = data + (y * fg->glyph_out->bitmap.pitch);
75 for (bi = 0; bi < w; bi += 8)
78 if ((w - bi) < 8) end = w - bi;
80 for (bj = 0; bj < end; bj++)
82 *tp = bitrepl[(bits >> (7 - bj)) & 0x1];
87 for (x = 0; x < w; x++)
98 /* where in pool texture does this live */
104 ft->alloc = _evas_gl_font_texture_pool_request(gc, ft->aw, ft->ah);
111 ft->x = ft->alloc->x;
112 ft->y = ft->alloc->y;
113 ft->pool = ft->alloc->pool;
114 ft->texture = ft->pool->texture;
115 if (ft->pool->rectangle)
117 glEnable(GL_TEXTURE_RECTANGLE_NV);
118 glBindTexture(GL_TEXTURE_RECTANGLE_NV, ft->texture);
119 glTexSubImage2D(GL_TEXTURE_RECTANGLE_NV, 0,
120 ft->x, ft->y, nw, ft->h,
121 GL_ALPHA, GL_UNSIGNED_BYTE, ndata);
125 glBindTexture(GL_TEXTURE_2D, ft->texture);
126 glTexSubImage2D(GL_TEXTURE_2D, 0,
127 ft->x, ft->y, nw, ft->h,
128 GL_ALPHA, GL_UNSIGNED_BYTE, ndata);
130 if (ndata) free(ndata);
133 if (gc->texture) gc->texture->references--;
136 gc->font_texture = ft->texture;
137 gc->font_texture_rectangle = ft->pool->rectangle;
138 gc->change.texture = 1;
139 if (ft->pool->rectangle)
143 ft->tx2 = ft->x + ft->w;
144 ft->ty2 = ft->y + ft->h;
148 ft->tx1 = (double)(ft->x ) / (double)(ft->pool->w);
149 ft->ty1 = (double)(ft->y ) / (double)(ft->pool->h);
150 ft->tx2 = (double)(ft->x + ft->w) / (double)(ft->pool->w);
151 ft->ty2 = (double)(ft->y + ft->h) / (double)(ft->pool->h);
158 evas_gl_font_texture_free(Evas_GL_Font_Texture *ft)
161 if (ft->gc->font_texture == ft->texture)
163 ft->gc->font_texture = 0;
164 ft->gc->change.texture = 1;
166 _evas_gl_font_texture_pool_relinquish(ft->alloc);
171 evas_gl_font_texture_draw(Evas_GL_Context *gc, void *surface, RGBA_Draw_Context *dc, RGBA_Font_Glyph *fg, int x, int y)
173 Evas_GL_Font_Texture *ft;
185 a = (dc->col.col >> 24) & 0xff;
187 r = (dc->col.col >> 16) & 0xff;
188 g = (dc->col.col >> 8 ) & 0xff;
189 b = (dc->col.col ) & 0xff;
190 /* have to un-premul the color - as we are using blend mode 2 (non-premul blend) */
194 evas_gl_common_context_color_set(gc, r, g, b, a);
196 evas_gl_common_context_clip_set(gc, 1,
197 dc->clip.x, dc->clip.y,
198 dc->clip.w, dc->clip.h);
200 evas_gl_common_context_clip_set(gc, 0,
202 evas_gl_common_context_blend_set(gc, 2);
203 evas_gl_common_context_read_buf_set(gc, GL_BACK);
204 evas_gl_common_context_write_buf_set(gc, GL_BACK);
207 evas_gl_common_context_font_texture_set(gc, ft);
210 glTexCoord2d(ft->tx1, ft->ty1); glVertex2i(x , y );
211 glTexCoord2d(ft->tx2, ft->ty1); glVertex2i(x + ft->w, y );
212 glTexCoord2d(ft->tx2, ft->ty2); glVertex2i(x + ft->w, y + ft->h);
213 glTexCoord2d(ft->tx1, ft->ty2); glVertex2i(x , y + ft->h);
218 static Evas_GL_Font_Texture_Pool_Allocation *
219 _evas_gl_font_texture_pool_request(Evas_GL_Context *gc, int w, int h)
222 Evas_GL_Font_Texture_Pool_Allocation *fa;
223 Evas_GL_Font_Texture_Pool *fp;
228 for (l = gc->tex_pool; l; l = l->next)
233 if (_evas_gl_font_texture_pool_rect_find(fp, w, h, &x, &y))
235 fa = calloc(1, sizeof(Evas_GL_Font_Texture_Pool_Allocation));
236 if (!fa) return NULL;
242 fp->allocations = evas_list_prepend(fp->allocations, fa);
243 if (evas_list_alloc_error())
252 /* need new font texture pool entry */
253 /* minimum size either minw x minh OR the size of glyph up to power 2 */
257 shift = 1; while (minw > shift) shift = shift << 1; minw = shift;
262 shift = 1; while (minh > shift) shift = shift << 1; minh = shift;
265 fp = calloc(1, sizeof(Evas_GL_Font_Texture_Pool));
266 if (!fp) return NULL;
267 gc->tex_pool = evas_list_append(gc->tex_pool, fp);
268 if (evas_list_alloc_error())
276 if (gc->ext.nv_texture_rectangle) fp->rectangle = 1;
278 /* we dont want this mipmapped if sgis_generate_mipmap will mipmap it */
279 if (gc->ext.sgis_generate_mipmap)
280 glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, GL_FALSE);
281 // glEnable(GL_TEXTURE_2D);
284 glEnable(GL_TEXTURE_RECTANGLE_NV);
285 glGenTextures(1, &(fp->texture));
286 /* FIXME check gl error */
288 glBindTexture(GL_TEXTURE_RECTANGLE_NV, fp->texture);
289 glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_WRAP_S, GL_REPEAT);
290 glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_WRAP_T, GL_REPEAT);
291 glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
292 glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
293 glTexImage2D(GL_TEXTURE_RECTANGLE_NV, 0,
294 GL_ALPHA4, fp->w, fp->h, 0,
295 GL_ALPHA, GL_UNSIGNED_BYTE, NULL);
296 /* FIXME check gl error */
300 glEnable(GL_TEXTURE_2D);
301 glGenTextures(1, &(fp->texture));
302 /* FIXME check gl error */
304 glBindTexture(GL_TEXTURE_2D, fp->texture);
305 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
306 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
307 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
308 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
309 glTexImage2D(GL_TEXTURE_2D, 0,
310 GL_ALPHA4, fp->w, fp->h, 0,
311 GL_ALPHA, GL_UNSIGNED_BYTE, NULL);
312 /* FIXME check gl error */
315 /* new allocation entirely */
316 fa = calloc(1, sizeof(Evas_GL_Font_Texture_Pool_Allocation));
319 gc->tex_pool = evas_list_remove(gc->tex_pool, fp);
320 glDeleteTextures(1, &(fp->texture));
329 fp->allocations = evas_list_prepend(fp->allocations, fa);
330 if (evas_list_alloc_error())
332 printf("alloc prob\n");
333 gc->tex_pool = evas_list_remove(gc->tex_pool, fp);
334 glDeleteTextures(1, &(fp->texture));
344 _evas_gl_font_texture_pool_relinquish(Evas_GL_Font_Texture_Pool_Allocation *fa)
346 fa->pool->allocations = evas_list_remove(fa->pool->allocations, fa);
347 fa->pool->references--;
348 if (fa->pool->references <= 0)
350 fa->pool->gc->tex_pool =
351 evas_list_remove(fa->pool->gc->tex_pool, fa->pool);
352 glDeleteTextures(1, &(fa->pool->texture));
359 _evas_gl_font_texture_pool_rect_find(Evas_GL_Font_Texture_Pool *fp,
365 if ((w > fp->w) || (h > fp->h)) return 0;
366 for (l = fp->allocations; l; l = l->next)
368 Evas_GL_Font_Texture_Pool_Allocation *fa;
376 if ((fa->x + fa->w + w) > fp->w) t1 = 0;
377 if ((fa->y + h) > fp->h) t1 = 0;
378 if ((fa->y + fa->h + h) > fp->h) t2 = 0;
379 if ((fa->x + w) > fp->w) t2 = 0;
394 for (l2 = fp->allocations; l2; l2 = l2->next)
396 Evas_GL_Font_Texture_Pool_Allocation *fa2;
399 /* dont do the rect we are just using as our offset */
400 if (l2 == l) continue;
406 if (RECTS_INTERSECT(tx, ty, tw, th, rx, ry, rw, rh))
436 for (l2 = fp->allocations; l2; l2 = l2->next)
438 Evas_GL_Font_Texture_Pool_Allocation *fa2;
441 /* dont do the rect we are just using as our offset */
442 if (l2 == l) continue;
443 /* hmmm crash here on mga... l2->data seems broken */
444 /* so far it looks like memory corruption, but i can't */
445 /* use valgrind to inspect any further due to the dri */
446 /* hardware stuff :( */
453 if (RECTS_INTERSECT(tx, ty, tw, th, rx, ry, rw, rh))