~ubuntu-branches/ubuntu/trusty/xorg-server-lts-xenial/trusty-updates

« back to all changes in this revision

Viewing changes to glamor/glamor_composite_glyphs.c

  • Committer: Package Import Robot
  • Author(s): Timo Aaltonen
  • Date: 2016-05-03 14:02:21 UTC
  • Revision ID: package-import@ubuntu.com-20160503140221-722b5oen8it4o8h1
Tags: upstream-1.18.3
ImportĀ upstreamĀ versionĀ 1.18.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright Ā© 2014 Keith Packard
 
3
 *
 
4
 * Permission to use, copy, modify, distribute, and sell this software and its
 
5
 * documentation for any purpose is hereby granted without fee, provided that
 
6
 * the above copyright notice appear in all copies and that both that copyright
 
7
 * notice and this permission notice appear in supporting documentation, and
 
8
 * that the name of the copyright holders not be used in advertising or
 
9
 * publicity pertaining to distribution of the software without specific,
 
10
 * written prior permission.  The copyright holders make no representations
 
11
 * about the suitability of this software for any purpose.  It is provided "as
 
12
 * is" without express or implied warranty.
 
13
 *
 
14
 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 
15
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
 
16
 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
 
17
 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
 
18
 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
 
19
 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
 
20
 * OF THIS SOFTWARE.
 
21
 */
 
22
#include <stdlib.h>
 
23
#include "Xprintf.h"
 
24
 
 
25
#include "glamor_priv.h"
 
26
#include "glamor_transform.h"
 
27
#include "glamor_transfer.h"
 
28
 
 
29
#include <mipict.h>
 
30
 
 
31
#define DEFAULT_ATLAS_DIM       1024
 
32
 
 
33
static DevPrivateKeyRec        glamor_glyph_private_key;
 
34
 
 
35
struct glamor_glyph_private {
 
36
    int16_t     x;
 
37
    int16_t     y;
 
38
    uint32_t    serial;
 
39
};
 
40
 
 
41
struct glamor_glyph_atlas {
 
42
    PixmapPtr           atlas;
 
43
    PictFormatPtr       format;
 
44
    int                 x, y;
 
45
    int                 row_height;
 
46
    int                 nglyph;
 
47
    uint32_t            serial;
 
48
};
 
49
 
 
50
static inline struct glamor_glyph_private *glamor_get_glyph_private(PixmapPtr pixmap) {
 
51
    return dixLookupPrivate(&pixmap->devPrivates, &glamor_glyph_private_key);
 
52
}
 
53
 
 
54
static inline void
 
55
glamor_copy_glyph(PixmapPtr     glyph_pixmap,
 
56
                  DrawablePtr   atlas_draw,
 
57
                  int16_t x,
 
58
                  int16_t y)
 
59
{
 
60
    DrawablePtr glyph_draw = &glyph_pixmap->drawable;
 
61
    BoxRec      box = {
 
62
        .x1 = 0,
 
63
        .y1 = 0,
 
64
        .x2 = glyph_draw->width,
 
65
        .y2 = glyph_draw->height,
 
66
    };
 
67
    PixmapPtr upload_pixmap = glyph_pixmap;
 
68
 
 
69
    if (glyph_pixmap->drawable.bitsPerPixel != atlas_draw->bitsPerPixel) {
 
70
 
 
71
        /* If we're dealing with 1-bit glyphs, we copy them to a
 
72
         * temporary 8-bit pixmap and upload them from there, since
 
73
         * that's what GL can handle.
 
74
         */
 
75
        ScreenPtr       screen = atlas_draw->pScreen;
 
76
        GCPtr           scratch_gc;
 
77
        ChangeGCVal     changes[2];
 
78
 
 
79
        upload_pixmap = glamor_create_pixmap(screen,
 
80
                                             glyph_draw->width,
 
81
                                             glyph_draw->height,
 
82
                                             atlas_draw->depth,
 
83
                                             GLAMOR_CREATE_PIXMAP_CPU);
 
84
        if (!upload_pixmap)
 
85
            return;
 
86
 
 
87
        scratch_gc = GetScratchGC(upload_pixmap->drawable.depth, screen);
 
88
        if (!scratch_gc) {
 
89
            glamor_destroy_pixmap(upload_pixmap);
 
90
            return;
 
91
        }
 
92
        changes[0].val = 0xff;
 
93
        changes[1].val = 0x00;
 
94
        if (ChangeGC(NullClient, scratch_gc,
 
95
                     GCForeground|GCBackground, changes) != Success) {
 
96
            glamor_destroy_pixmap(upload_pixmap);
 
97
            FreeScratchGC(scratch_gc);
 
98
            return;
 
99
        }
 
100
        ValidateGC(&upload_pixmap->drawable, scratch_gc);
 
101
 
 
102
        (*scratch_gc->ops->CopyPlane)(glyph_draw,
 
103
                                      &upload_pixmap->drawable,
 
104
                                      scratch_gc,
 
105
                                      0, 0,
 
106
                                      glyph_draw->width,
 
107
                                      glyph_draw->height,
 
108
                                      0, 0, 0x1);
 
109
    }
 
110
    glamor_upload_boxes((PixmapPtr) atlas_draw,
 
111
                        &box, 1,
 
112
                        0, 0,
 
113
                        x, y,
 
114
                        upload_pixmap->devPrivate.ptr,
 
115
                        upload_pixmap->devKind);
 
116
 
 
117
    if (upload_pixmap != glyph_pixmap)
 
118
        glamor_destroy_pixmap(upload_pixmap);
 
119
}
 
120
 
 
121
static Bool
 
122
glamor_glyph_atlas_init(ScreenPtr screen, struct glamor_glyph_atlas *atlas)
 
123
{
 
124
    glamor_screen_private       *glamor_priv = glamor_get_screen_private(screen);
 
125
    PictFormatPtr               format = atlas->format;
 
126
 
 
127
    atlas->atlas = glamor_create_pixmap(screen, glamor_priv->glyph_atlas_dim,
 
128
                                        glamor_priv->glyph_atlas_dim, format->depth,
 
129
                                        GLAMOR_CREATE_FBO_NO_FBO);
 
130
    if (!glamor_pixmap_has_fbo(atlas->atlas)) {
 
131
        glamor_destroy_pixmap(atlas->atlas);
 
132
        atlas->atlas = NULL;
 
133
    }
 
134
    atlas->x = 0;
 
135
    atlas->y = 0;
 
136
    atlas->row_height = 0;
 
137
    atlas->serial++;
 
138
    atlas->nglyph = 0;
 
139
    return TRUE;
 
140
}
 
141
 
 
142
static Bool
 
143
glamor_glyph_can_add(struct glamor_glyph_atlas *atlas, int dim, DrawablePtr glyph_draw)
 
144
{
 
145
    /* Step down */
 
146
    if (atlas->x + glyph_draw->width > dim) {
 
147
        atlas->x = 0;
 
148
        atlas->y += atlas->row_height;
 
149
        atlas->row_height = 0;
 
150
    }
 
151
 
 
152
    /* Check for overfull */
 
153
    if (atlas->y + glyph_draw->height > dim)
 
154
        return FALSE;
 
155
 
 
156
    return TRUE;
 
157
}
 
158
 
 
159
static Bool
 
160
glamor_glyph_add(struct glamor_glyph_atlas *atlas, DrawablePtr glyph_draw)
 
161
{
 
162
    PixmapPtr                   glyph_pixmap = (PixmapPtr) glyph_draw;
 
163
    struct glamor_glyph_private *glyph_priv = glamor_get_glyph_private(glyph_pixmap);
 
164
 
 
165
    glamor_copy_glyph(glyph_pixmap, &atlas->atlas->drawable, atlas->x, atlas->y);
 
166
 
 
167
    glyph_priv->x = atlas->x;
 
168
    glyph_priv->y = atlas->y;
 
169
    glyph_priv->serial = atlas->serial;
 
170
 
 
171
    atlas->x += glyph_draw->width;
 
172
    if (atlas->row_height < glyph_draw->height)
 
173
        atlas->row_height = glyph_draw->height;
 
174
 
 
175
    atlas->nglyph++;
 
176
 
 
177
    return TRUE;
 
178
}
 
179
 
 
180
static const glamor_facet glamor_facet_composite_glyphs_130 = {
 
181
    .name = "composite_glyphs",
 
182
    .version = 130,
 
183
    .vs_vars = ("attribute vec4 primitive;\n"
 
184
                "attribute vec2 source;\n"
 
185
                "varying vec2 glyph_pos;\n"),
 
186
    .vs_exec = ("       vec2 pos = primitive.zw * vec2(gl_VertexID&1, (gl_VertexID&2)>>1);\n"
 
187
                GLAMOR_POS(gl_Position, (primitive.xy + pos))
 
188
                "       glyph_pos = (source + pos) * ATLAS_DIM_INV;\n"),
 
189
    .fs_vars = ("varying vec2 glyph_pos;\n"
 
190
                "out vec4 color0;\n"
 
191
                "out vec4 color1;\n"),
 
192
    .fs_exec = ("       vec4 mask = texture2D(atlas, glyph_pos);\n"),
 
193
    .source_name = "source",
 
194
    .locations = glamor_program_location_atlas,
 
195
};
 
196
 
 
197
static const glamor_facet glamor_facet_composite_glyphs_120 = {
 
198
    .name = "composite_glyphs",
 
199
    .vs_vars = ("attribute vec2 primitive;\n"
 
200
                "attribute vec2 source;\n"
 
201
                "varying vec2 glyph_pos;\n"),
 
202
    .vs_exec = (GLAMOR_POS(gl_Position, primitive)
 
203
                "       glyph_pos = source.xy * ATLAS_DIM_INV;\n"),
 
204
    .fs_vars = ("varying vec2 glyph_pos;\n"),
 
205
    .fs_exec = ("       vec4 mask = texture2D(atlas, glyph_pos);\n"),
 
206
    .source_name = "source",
 
207
    .locations = glamor_program_location_atlas,
 
208
};
 
209
 
 
210
static inline Bool
 
211
glamor_glyph_use_130(glamor_screen_private *glamor_priv) {
 
212
    return glamor_priv->glsl_version >= 130;
 
213
}
 
214
 
 
215
static Bool
 
216
glamor_glyphs_init_facet(ScreenPtr screen)
 
217
{
 
218
    glamor_screen_private       *glamor_priv = glamor_get_screen_private(screen);
 
219
 
 
220
    return asprintf(&glamor_priv->glyph_defines, "#define ATLAS_DIM_INV %20.18f\n", 1.0/glamor_priv->glyph_atlas_dim) > 0;
 
221
}
 
222
 
 
223
static void
 
224
glamor_glyphs_fini_facet(ScreenPtr screen)
 
225
{
 
226
    glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
 
227
 
 
228
    free(glamor_priv->glyph_defines);
 
229
}
 
230
 
 
231
static void
 
232
glamor_glyphs_flush(CARD8 op, PicturePtr src, PicturePtr dst,
 
233
                   glamor_program *prog,
 
234
                   struct glamor_glyph_atlas *atlas, int nglyph)
 
235
{
 
236
    DrawablePtr drawable = dst->pDrawable;
 
237
    glamor_screen_private *glamor_priv = glamor_get_screen_private(drawable->pScreen);
 
238
    PixmapPtr atlas_pixmap = atlas->atlas;
 
239
    glamor_pixmap_private *atlas_priv = glamor_get_pixmap_private(atlas_pixmap);
 
240
    glamor_pixmap_fbo *atlas_fbo = glamor_pixmap_fbo_at(atlas_priv, 0);
 
241
    PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable);
 
242
    glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap);
 
243
    int box_index;
 
244
    int off_x, off_y;
 
245
 
 
246
    glamor_put_vbo_space(drawable->pScreen);
 
247
 
 
248
    glEnable(GL_SCISSOR_TEST);
 
249
    glActiveTexture(GL_TEXTURE1);
 
250
    glBindTexture(GL_TEXTURE_2D, atlas_fbo->tex);
 
251
 
 
252
    for (;;) {
 
253
        if (!glamor_use_program_render(prog, op, src, dst))
 
254
            break;
 
255
 
 
256
        glUniform1i(prog->atlas_uniform, 1);
 
257
 
 
258
        glamor_pixmap_loop(pixmap_priv, box_index) {
 
259
            BoxPtr box = RegionRects(dst->pCompositeClip);
 
260
            int nbox = RegionNumRects(dst->pCompositeClip);
 
261
 
 
262
            glamor_set_destination_drawable(drawable, box_index, TRUE, FALSE,
 
263
                                            prog->matrix_uniform,
 
264
                                            &off_x, &off_y);
 
265
 
 
266
            /* Run over the clip list, drawing the glyphs
 
267
             * in each box
 
268
             */
 
269
 
 
270
            while (nbox--) {
 
271
                glScissor(box->x1 + off_x,
 
272
                          box->y1 + off_y,
 
273
                          box->x2 - box->x1,
 
274
                          box->y2 - box->y1);
 
275
                box++;
 
276
 
 
277
                if (glamor_glyph_use_130(glamor_priv))
 
278
                    glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, nglyph);
 
279
                else
 
280
                    glamor_glDrawArrays_GL_QUADS(glamor_priv, nglyph);
 
281
            }
 
282
        }
 
283
        if (prog->alpha != glamor_program_alpha_ca_first)
 
284
            break;
 
285
        prog++;
 
286
    }
 
287
 
 
288
    glDisable(GL_SCISSOR_TEST);
 
289
 
 
290
    if (glamor_glyph_use_130(glamor_priv)) {
 
291
        glVertexAttribDivisor(GLAMOR_VERTEX_SOURCE, 0);
 
292
        glVertexAttribDivisor(GLAMOR_VERTEX_POS, 0);
 
293
    }
 
294
    glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
 
295
    glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
 
296
    glDisable(GL_BLEND);
 
297
}
 
298
 
 
299
static GLshort *
 
300
glamor_glyph_start(ScreenPtr screen, int count)
 
301
{
 
302
    glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
 
303
    GLshort *v;
 
304
    char *vbo_offset;
 
305
 
 
306
    /* Set up the vertex buffers for the font and destination */
 
307
 
 
308
    if (glamor_glyph_use_130(glamor_priv)) {
 
309
        v = glamor_get_vbo_space(screen, count * (6 * sizeof (GLshort)), &vbo_offset);
 
310
 
 
311
        glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
 
312
        glVertexAttribDivisor(GLAMOR_VERTEX_POS, 1);
 
313
        glVertexAttribPointer(GLAMOR_VERTEX_POS, 4, GL_SHORT, GL_FALSE,
 
314
                              6 * sizeof (GLshort), vbo_offset);
 
315
 
 
316
        glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
 
317
        glVertexAttribDivisor(GLAMOR_VERTEX_SOURCE, 1);
 
318
        glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_SHORT, GL_FALSE,
 
319
                              6 * sizeof (GLshort), vbo_offset + 4 * sizeof (GLshort));
 
320
    } else {
 
321
        v = glamor_get_vbo_space(screen, count * (16 * sizeof (GLshort)), &vbo_offset);
 
322
 
 
323
        glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
 
324
        glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_SHORT, GL_FALSE,
 
325
                              4 * sizeof (GLshort), vbo_offset);
 
326
 
 
327
        glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
 
328
        glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_SHORT, GL_FALSE,
 
329
                              4 * sizeof (GLshort), vbo_offset + 2 * sizeof (GLshort));
 
330
    }
 
331
    return v;
 
332
}
 
333
 
 
334
static inline struct glamor_glyph_atlas *
 
335
glamor_atlas_for_glyph(glamor_screen_private *glamor_priv, DrawablePtr drawable)
 
336
{
 
337
    if (drawable->depth == 32)
 
338
        return glamor_priv->glyph_atlas_argb;
 
339
    else
 
340
        return glamor_priv->glyph_atlas_a;
 
341
}
 
342
 
 
343
void
 
344
glamor_composite_glyphs(CARD8 op,
 
345
                        PicturePtr src,
 
346
                        PicturePtr dst,
 
347
                        PictFormatPtr glyph_format,
 
348
                        INT16 x_src,
 
349
                        INT16 y_src, int nlist, GlyphListPtr list,
 
350
                        GlyphPtr *glyphs)
 
351
{
 
352
    int glyphs_queued;
 
353
    GLshort *v = NULL;
 
354
    DrawablePtr drawable = dst->pDrawable;
 
355
    ScreenPtr screen = drawable->pScreen;
 
356
    glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
 
357
    glamor_program *prog = NULL;
 
358
    glamor_program_render       *glyphs_program = &glamor_priv->glyphs_program;
 
359
    struct glamor_glyph_atlas    *glyph_atlas = NULL;
 
360
    int x = 0, y = 0;
 
361
    int n;
 
362
    int glyph_atlas_dim = glamor_priv->glyph_atlas_dim;
 
363
    int glyph_max_dim = glamor_priv->glyph_max_dim;
 
364
    int nglyph = 0;
 
365
    int screen_num = screen->myNum;
 
366
 
 
367
    for (n = 0; n < nlist; n++)
 
368
        nglyph += list[n].len;
 
369
 
 
370
    glamor_make_current(glamor_priv);
 
371
 
 
372
    glyphs_queued = 0;
 
373
 
 
374
    while (nlist--) {
 
375
        x += list->xOff;
 
376
        y += list->yOff;
 
377
        n = list->len;
 
378
        list++;
 
379
        while (n--) {
 
380
            GlyphPtr glyph = *glyphs++;
 
381
 
 
382
            /* Glyph not empty?
 
383
             */
 
384
            if (glyph->info.width && glyph->info.height) {
 
385
                PicturePtr glyph_pict = GlyphPicture(glyph)[screen_num];
 
386
                DrawablePtr glyph_draw = glyph_pict->pDrawable;
 
387
 
 
388
                /* Need to draw with slow path?
 
389
                 */
 
390
                if (_X_UNLIKELY(glyph_draw->width > glyph_max_dim ||
 
391
                                glyph_draw->height > glyph_max_dim ||
 
392
                                !glamor_pixmap_is_memory((PixmapPtr)glyph_draw)))
 
393
                {
 
394
                    if (glyphs_queued) {
 
395
                        glamor_glyphs_flush(op, src, dst, prog, glyph_atlas, glyphs_queued);
 
396
                        glyphs_queued = 0;
 
397
                    }
 
398
                bail_one:
 
399
                    glamor_composite(op, src, glyph_pict, dst,
 
400
                                     x_src + (x - glyph->info.x), (y - glyph->info.y),
 
401
                                     0, 0,
 
402
                                     x - glyph->info.x, y - glyph->info.y,
 
403
                                     glyph_draw->width, glyph_draw->height);
 
404
                } else {
 
405
                    struct glamor_glyph_private *glyph_priv = glamor_get_glyph_private((PixmapPtr)(glyph_draw));
 
406
                    struct glamor_glyph_atlas *next_atlas = glamor_atlas_for_glyph(glamor_priv, glyph_draw);
 
407
 
 
408
                    /* Switching source glyph format?
 
409
                     */
 
410
                    if (_X_UNLIKELY(next_atlas != glyph_atlas)) {
 
411
                        if (glyphs_queued) {
 
412
                            glamor_glyphs_flush(op, src, dst, prog, glyph_atlas, glyphs_queued);
 
413
                            glyphs_queued = 0;
 
414
                        }
 
415
                        glyph_atlas = next_atlas;
 
416
                    }
 
417
 
 
418
                    /* Glyph not cached in current atlas?
 
419
                     */
 
420
                    if (_X_UNLIKELY(glyph_priv->serial != glyph_atlas->serial)) {
 
421
                        if (!glamor_glyph_can_add(glyph_atlas, glyph_atlas_dim, glyph_draw)) {
 
422
                            if (glyphs_queued) {
 
423
                                glamor_glyphs_flush(op, src, dst, prog, glyph_atlas, glyphs_queued);
 
424
                                glyphs_queued = 0;
 
425
                            }
 
426
                            if (glyph_atlas->atlas) {
 
427
                                (*screen->DestroyPixmap)(glyph_atlas->atlas);
 
428
                                glyph_atlas->atlas = NULL;
 
429
                            }
 
430
                        }
 
431
                        if (!glyph_atlas->atlas) {
 
432
                            glamor_glyph_atlas_init(screen, glyph_atlas);
 
433
                            if (!glyph_atlas->atlas)
 
434
                                goto bail_one;
 
435
                        }
 
436
                        glamor_glyph_add(glyph_atlas, glyph_draw);
 
437
                    }
 
438
 
 
439
                    /* First glyph in the current atlas?
 
440
                     */
 
441
                    if (_X_UNLIKELY(glyphs_queued == 0)) {
 
442
                        if (glamor_glyph_use_130(glamor_priv))
 
443
                            prog = glamor_setup_program_render(op, src, glyph_pict, dst,
 
444
                                                               glyphs_program,
 
445
                                                               &glamor_facet_composite_glyphs_130,
 
446
                                                               glamor_priv->glyph_defines);
 
447
                        else
 
448
                            prog = glamor_setup_program_render(op, src, glyph_pict, dst,
 
449
                                                               glyphs_program,
 
450
                                                               &glamor_facet_composite_glyphs_120,
 
451
                                                               glamor_priv->glyph_defines);
 
452
                        if (!prog)
 
453
                            goto bail_one;
 
454
                        v = glamor_glyph_start(screen, nglyph);
 
455
                    }
 
456
 
 
457
                    /* Add the glyph
 
458
                     */
 
459
 
 
460
                    glyphs_queued++;
 
461
                    if (_X_LIKELY(glamor_glyph_use_130(glamor_priv))) {
 
462
                        v[0] = x - glyph->info.x;
 
463
                        v[1] = y - glyph->info.y;
 
464
                        v[2] = glyph_draw->width;
 
465
                        v[3] = glyph_draw->height;
 
466
                        v[4] = glyph_priv->x;
 
467
                        v[5] = glyph_priv->y;
 
468
                        v += 6;
 
469
                    } else {
 
470
                        v[0] = x - glyph->info.x;
 
471
                        v[1] = y - glyph->info.y;
 
472
                        v[2] = glyph_priv->x;
 
473
                        v[3] = glyph_priv->y;
 
474
                        v += 4;
 
475
 
 
476
                        v[0] = x - glyph->info.x + glyph_draw->width;
 
477
                        v[1] = y - glyph->info.y;
 
478
                        v[2] = glyph_priv->x + glyph_draw->width;
 
479
                        v[3] = glyph_priv->y;
 
480
                        v += 4;
 
481
 
 
482
                        v[0] = x - glyph->info.x + glyph_draw->width;
 
483
                        v[1] = y - glyph->info.y + glyph_draw->height;
 
484
                        v[2] = glyph_priv->x + glyph_draw->width;
 
485
                        v[3] = glyph_priv->y + glyph_draw->height;
 
486
                        v += 4;
 
487
 
 
488
                        v[0] = x - glyph->info.x;
 
489
                        v[1] = y - glyph->info.y + glyph_draw->height;
 
490
                        v[2] = glyph_priv->x;
 
491
                        v[3] = glyph_priv->y + glyph_draw->height;
 
492
                        v += 4;
 
493
                    }
 
494
                }
 
495
            }
 
496
            x += glyph->info.xOff;
 
497
            y += glyph->info.yOff;
 
498
            nglyph--;
 
499
        }
 
500
    }
 
501
 
 
502
    if (glyphs_queued)
 
503
        glamor_glyphs_flush(op, src, dst, prog, glyph_atlas, glyphs_queued);
 
504
 
 
505
    return;
 
506
}
 
507
 
 
508
static struct glamor_glyph_atlas *
 
509
glamor_alloc_glyph_atlas(ScreenPtr screen, int depth, CARD32 f)
 
510
{
 
511
    PictFormatPtr               format;
 
512
    struct glamor_glyph_atlas    *glyph_atlas;
 
513
 
 
514
    format = PictureMatchFormat(screen, depth, f);
 
515
    if (!format)
 
516
        return NULL;
 
517
    glyph_atlas = calloc (1, sizeof (struct glamor_glyph_atlas));
 
518
    if (!glyph_atlas)
 
519
        return NULL;
 
520
    glyph_atlas->format = format;
 
521
    glyph_atlas->serial = 1;
 
522
 
 
523
    return glyph_atlas;
 
524
}
 
525
 
 
526
Bool
 
527
glamor_composite_glyphs_init(ScreenPtr screen)
 
528
{
 
529
    glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
 
530
 
 
531
    if (!dixRegisterPrivateKey(&glamor_glyph_private_key, PRIVATE_PIXMAP, sizeof (struct glamor_glyph_private)))
 
532
        return FALSE;
 
533
 
 
534
    /* Make glyph atlases of a reasonable size, but no larger than the maximum
 
535
     * supported by the hardware
 
536
     */
 
537
    glamor_priv->glyph_atlas_dim = MIN(DEFAULT_ATLAS_DIM, glamor_priv->max_fbo_size);
 
538
 
 
539
    /* Don't stick huge glyphs in the atlases */
 
540
    glamor_priv->glyph_max_dim = glamor_priv->glyph_atlas_dim / 8;
 
541
 
 
542
    glamor_priv->glyph_atlas_a = glamor_alloc_glyph_atlas(screen, 8, PICT_a8);
 
543
    if (!glamor_priv->glyph_atlas_a)
 
544
        return FALSE;
 
545
    glamor_priv->glyph_atlas_argb = glamor_alloc_glyph_atlas(screen, 32, PICT_a8r8g8b8);
 
546
    if (!glamor_priv->glyph_atlas_argb) {
 
547
        free (glamor_priv->glyph_atlas_a);
 
548
        return FALSE;
 
549
    }
 
550
    if (!glamor_glyphs_init_facet(screen))
 
551
        return FALSE;
 
552
    return TRUE;
 
553
}
 
554
 
 
555
static void
 
556
glamor_free_glyph_atlas(struct glamor_glyph_atlas *atlas)
 
557
{
 
558
    if (!atlas)
 
559
        return;
 
560
    if (atlas->atlas)
 
561
        FreePicture(atlas->atlas, 0);
 
562
    free (atlas);
 
563
}
 
564
 
 
565
void
 
566
glamor_composite_glyphs_fini(ScreenPtr screen)
 
567
{
 
568
    glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
 
569
 
 
570
    glamor_glyphs_fini_facet(screen);
 
571
    glamor_free_glyph_atlas(glamor_priv->glyph_atlas_a);
 
572
    glamor_free_glyph_atlas(glamor_priv->glyph_atlas_argb);
 
573
}