glamor.c 36.7 KB
Newer Older
1
/*
2
 * Copyright © 2008,2011 Intel Corporation
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 *
 * Authors:
 *    Eric Anholt <eric@anholt.net>
25
 *    Zhigang Gong <zhigang.gong@linux.intel.com>
26
 *    Chad Versace <chad.versace@linux.intel.com>
27
28
 */

Emma Anholt's avatar
Emma Anholt committed
29
/** @file glamor.c
30
31
32
33
34
 * This file covers the initialization and teardown of glamor, and has various
 * functions not responsible for performing rendering.
 */

#include <stdlib.h>
35
#include <unistd.h>
Emma Anholt's avatar
Emma Anholt committed
36

37
#include "glamor_priv.h"
38
#include "mipict.h"
39

40
41
DevPrivateKeyRec glamor_screen_private_key;
DevPrivateKeyRec glamor_pixmap_private_key;
42
DevPrivateKeyRec glamor_gc_private_key;
43

44
45
46
47
48
49
50
51
52
53
54
55
56
glamor_screen_private *
glamor_get_screen_private(ScreenPtr screen)
{
    return (glamor_screen_private *)
        dixLookupPrivate(&screen->devPrivates, &glamor_screen_private_key);
}

void
glamor_set_screen_private(ScreenPtr screen, glamor_screen_private *priv)
{
    dixSetPrivate(&screen->devPrivates, &glamor_screen_private_key, priv);
}

57
58
59
60
61
62
63
64
65
66
67
68
69
70
/**
 * glamor_get_drawable_pixmap() returns a backing pixmap for a given drawable.
 *
 * @param drawable the drawable being requested.
 *
 * This function returns the backing pixmap for a drawable, whether it is a
 * redirected window, unredirected window, or already a pixmap.  Note that
 * coordinate translation is needed when drawing to the backing pixmap of a
 * redirected window, and the translation coordinates are provided by calling
 * exaGetOffscreenPixmap() on the drawable.
 */
PixmapPtr
glamor_get_drawable_pixmap(DrawablePtr drawable)
{
Emma Anholt's avatar
Emma Anholt committed
71
72
73
74
    if (drawable->type == DRAWABLE_WINDOW)
        return drawable->pScreen->GetWindowPixmap((WindowPtr) drawable);
    else
        return (PixmapPtr) drawable;
75
76
}

77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
static void
glamor_init_pixmap_private_small(PixmapPtr pixmap, glamor_pixmap_private *pixmap_priv)
{
    pixmap_priv->box.x1 = 0;
    pixmap_priv->box.x2 = pixmap->drawable.width;
    pixmap_priv->box.y1 = 0;
    pixmap_priv->box.y2 = pixmap->drawable.height;
    pixmap_priv->block_w = pixmap->drawable.width;
    pixmap_priv->block_h = pixmap->drawable.height;
    pixmap_priv->block_hcnt = 1;
    pixmap_priv->block_wcnt = 1;
    pixmap_priv->box_array = &pixmap_priv->box;
    pixmap_priv->fbo_array = &pixmap_priv->fbo;
}

92
93
94
_X_EXPORT void
glamor_set_pixmap_type(PixmapPtr pixmap, glamor_pixmap_type_t type)
{
Emma Anholt's avatar
Emma Anholt committed
95
96
    glamor_pixmap_private *pixmap_priv;

97
    pixmap_priv = glamor_get_pixmap_private(pixmap);
Emma Anholt's avatar
Emma Anholt committed
98
    pixmap_priv->type = type;
99
    glamor_init_pixmap_private_small(pixmap, pixmap_priv);
100
101
}

102
_X_EXPORT Bool
103
glamor_set_pixmap_texture(PixmapPtr pixmap, unsigned int tex)
104
{
Emma Anholt's avatar
Emma Anholt committed
105
106
107
108
109
110
111
112
    ScreenPtr screen = pixmap->drawable.pScreen;
    glamor_pixmap_private *pixmap_priv;
    glamor_screen_private *glamor_priv;
    glamor_pixmap_fbo *fbo;

    glamor_priv = glamor_get_screen_private(screen);
    pixmap_priv = glamor_get_pixmap_private(pixmap);

113
    if (pixmap_priv->fbo) {
Emma Anholt's avatar
Emma Anholt committed
114
        fbo = glamor_pixmap_detach_fbo(pixmap_priv);
115
        glamor_destroy_fbo(glamor_priv, fbo);
Emma Anholt's avatar
Emma Anholt committed
116
117
    }

118
119
120
    fbo = glamor_create_fbo_from_tex(glamor_priv, pixmap,
                                     pixmap->drawable.width,
                                     pixmap->drawable.height, tex, 0);
Emma Anholt's avatar
Emma Anholt committed
121
122
123

    if (fbo == NULL) {
        ErrorF("XXX fail to create fbo.\n");
124
        return FALSE;
Emma Anholt's avatar
Emma Anholt committed
125
126
127
    }

    glamor_pixmap_attach_fbo(pixmap, fbo);
128
129

    return TRUE;
130
131
}

132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
_X_EXPORT void
glamor_clear_pixmap(PixmapPtr pixmap)
{
    ScreenPtr screen = pixmap->drawable.pScreen;
    glamor_screen_private *glamor_priv;
    glamor_pixmap_private *pixmap_priv;
    const struct glamor_format *pixmap_format;

    glamor_priv = glamor_get_screen_private(screen);
    pixmap_priv = glamor_get_pixmap_private(pixmap);
    pixmap_format = glamor_format_for_pixmap(pixmap);

    assert(pixmap_priv->fbo != NULL);

    glamor_pixmap_clear_fbo(glamor_priv, pixmap_priv->fbo, pixmap_format);
}

149
150
151
152
153
uint32_t
glamor_get_pixmap_texture(PixmapPtr pixmap)
{
    glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap);

154
155
156
    if (!pixmap_priv)
        return 0;

157
158
159
    if (!pixmap_priv->fbo)
        return 0;

160
161
162
    if (pixmap_priv->type != GLAMOR_TEXTURE_ONLY)
        return 0;

163
    return pixmap_priv->fbo->tex;
164
165
}

166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
void
glamor_bind_texture(glamor_screen_private *glamor_priv, GLenum texture,
                    glamor_pixmap_fbo *fbo, Bool destination_red)
{
    glActiveTexture(texture);
    glBindTexture(GL_TEXTURE_2D, fbo->tex);

    /* If we're pulling data from a GL_RED texture, then whether we
     * want to make it an A,0,0,0 result or a 0,0,0,R result depends
     * on whether the destination is also a GL_RED texture.
     *
     * For GL_RED destinations, we need to leave the bits in the R
     * channel. For all other destinations, we need to clear out the R
     * channel so that it returns zero for R, G and B.
     *
     * Note that we're leaving the SWIZZLE_A value alone; for GL_RED
     * destinations, that means we'll actually be returning R,0,0,R,
     * but it doesn't matter as the bits in the alpha channel aren't
     * going anywhere.
     */

    /* Is the operand a GL_RED fbo?
     */

190
    if (fbo->is_red) {
191
192
193
194
195
196
197
198
199
200
        /* If destination is also GL_RED, then preserve the bits in
         * the R channel */

        if (destination_red)
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_RED);
        else
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_ZERO);
    }
}

201
PixmapPtr
202
glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth,
Emma Anholt's avatar
Emma Anholt committed
203
                     unsigned int usage)
204
{
Emma Anholt's avatar
Emma Anholt committed
205
206
207
    PixmapPtr pixmap;
    glamor_pixmap_private *pixmap_priv;
    glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
208
    glamor_pixmap_fbo *fbo = NULL;
Emma Anholt's avatar
Emma Anholt committed
209
210
211
212
213
214
    int pitch;

    if (w > 32767 || h > 32767)
        return NullPixmap;

    if ((usage == GLAMOR_CREATE_PIXMAP_CPU
215
216
217
         || (usage == CREATE_PIXMAP_USAGE_GLYPH_PICTURE &&
             w <= glamor_priv->glyph_max_dim &&
             h <= glamor_priv->glyph_max_dim)
Emma Anholt's avatar
Emma Anholt committed
218
         || (w == 0 && h == 0)
219
         || !glamor_priv->formats[depth].format))
Emma Anholt's avatar
Emma Anholt committed
220
221
222
223
        return fbCreatePixmap(screen, w, h, depth, usage);
    else
        pixmap = fbCreatePixmap(screen, 0, 0, depth, usage);

224
    pixmap_priv = glamor_get_pixmap_private(pixmap);
Emma Anholt's avatar
Emma Anholt committed
225

Julien Isorce's avatar
Julien Isorce committed
226
227
    pixmap_priv->is_cbcr = (usage == GLAMOR_CREATE_FORMAT_CBCR);

Emma Anholt's avatar
Emma Anholt committed
228
229
230
    pitch = (((w * pixmap->drawable.bitsPerPixel + 7) / 8) + 3) & ~3;
    screen->ModifyPixmapHeader(pixmap, w, h, 0, 0, pitch, NULL);

231
232
    pixmap_priv->type = GLAMOR_TEXTURE_ONLY;

233
    if (usage == GLAMOR_CREATE_PIXMAP_NO_TEXTURE) {
234
        glamor_init_pixmap_private_small(pixmap, pixmap_priv);
235
236
        return pixmap;
    }
237
    else if (usage == GLAMOR_CREATE_NO_LARGE ||
238
239
        glamor_check_fbo_size(glamor_priv, w, h))
    {
240
        glamor_init_pixmap_private_small(pixmap, pixmap_priv);
241
        fbo = glamor_create_fbo(glamor_priv, pixmap, w, h, usage);
242
243
    } else {
        int tile_size = glamor_priv->max_fbo_size;
244
245
        DEBUGF("Create LARGE pixmap %p width %d height %d, tile size %d\n",
               pixmap, w, h, tile_size);
246
        fbo = glamor_create_fbo_array(glamor_priv, pixmap, usage,
247
                                      tile_size, tile_size, pixmap_priv);
Emma Anholt's avatar
Emma Anholt committed
248
249
250
251
252
253
254
255
256
257
    }

    if (fbo == NULL) {
        fbDestroyPixmap(pixmap);
        return fbCreatePixmap(screen, w, h, depth, usage);
    }

    glamor_pixmap_attach_fbo(pixmap, fbo);

    return pixmap;
Zhigang Gong's avatar
Zhigang Gong committed
258
259
}

260
261
Bool
glamor_destroy_pixmap(PixmapPtr pixmap)
Zhigang Gong's avatar
Zhigang Gong committed
262
{
Emma Anholt's avatar
Emma Anholt committed
263
    if (pixmap->refcnt == 1) {
264
        glamor_pixmap_destroy_fbo(pixmap);
Emma Anholt's avatar
Emma Anholt committed
265
    }
266

Emma Anholt's avatar
Emma Anholt committed
267
    return fbDestroyPixmap(pixmap);
Zhigang Gong's avatar
Zhigang Gong committed
268
269
270
271
272
}

void
glamor_block_handler(ScreenPtr screen)
{
Emma Anholt's avatar
Emma Anholt committed
273
274
    glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);

275
    glamor_make_current(glamor_priv);
276
    glFlush();
277
}
Emma Anholt's avatar
Emma Anholt committed
278

279
static void
280
_glamor_block_handler(ScreenPtr screen, void *timeout)
281
{
282
283
    glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);

284
285
286
    glamor_make_current(glamor_priv);
    glFlush();

287
    screen->BlockHandler = glamor_priv->saved_procs.block_handler;
288
    screen->BlockHandler(screen, timeout);
289
290
    glamor_priv->saved_procs.block_handler = screen->BlockHandler;
    screen->BlockHandler = _glamor_block_handler;
291
292
}

Zhigang Gong's avatar
Zhigang Gong committed
293
static void
294
295
glamor_set_debug_level(int *debug_level)
{
Emma Anholt's avatar
Emma Anholt committed
296
297
298
299
300
301
302
    char *debug_level_string;

    debug_level_string = getenv("GLAMOR_DEBUG");
    if (debug_level_string
        && sscanf(debug_level_string, "%d", debug_level) == 1)
        return;
    *debug_level = 0;
303
304
305
306
}

int glamor_debug_level;

307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
void
glamor_gldrawarrays_quads_using_indices(glamor_screen_private *glamor_priv,
                                        unsigned count)
{
    unsigned i;

    /* For a single quad, don't bother with an index buffer. */
    if (count ==  1)
        goto fallback;

    if (glamor_priv->ib_size < count) {
        /* Basic GLES2 doesn't have any way to map buffer objects for
         * writing, but it's long past time for drivers to have
         * MapBufferRange.
         */
        if (!glamor_priv->has_map_buffer_range)
            goto fallback;

        /* Lazy create the buffer name, and only bind it once since
         * none of the glamor code binds it to anything else.
         */
        if (!glamor_priv->ib) {
            glGenBuffers(1, &glamor_priv->ib);
            glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, glamor_priv->ib);
        }

        /* For now, only support GL_UNSIGNED_SHORTs. */
        if (count > ((1 << 16) - 1) / 4) {
            goto fallback;
        } else {
            uint16_t *data;
            size_t size = count * 6 * sizeof(GLushort);

            glBufferData(GL_ELEMENT_ARRAY_BUFFER, size, NULL, GL_STATIC_DRAW);
            data = glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER,
                                    0, size,
                                    GL_MAP_WRITE_BIT |
                                    GL_MAP_INVALIDATE_BUFFER_BIT);
            for (i = 0; i < count; i++) {
                data[i * 6 + 0] = i * 4 + 0;
                data[i * 6 + 1] = i * 4 + 1;
                data[i * 6 + 2] = i * 4 + 2;
                data[i * 6 + 3] = i * 4 + 0;
                data[i * 6 + 4] = i * 4 + 2;
                data[i * 6 + 5] = i * 4 + 3;
            }
            glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);

            glamor_priv->ib_size = count;
            glamor_priv->ib_type = GL_UNSIGNED_SHORT;
        }
    }

    glDrawElements(GL_TRIANGLES, count * 6, glamor_priv->ib_type, NULL);
    return;

fallback:
    for (i = 0; i < count; i++)
        glDrawArrays(GL_TRIANGLE_FAN, i * 4, 4);
}


369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
static Bool
glamor_check_instruction_count(int gl_version)
{
    GLint max_native_alu_instructions;

    /* Avoid using glamor if the reported instructions limit is too low,
     * as this would cause glamor to fallback on sw due to large shaders
     * which ends up being unbearably slow.
     */
    if (gl_version < 30) {
        if (!epoxy_has_gl_extension("GL_ARB_fragment_program")) {
            ErrorF("GL_ARB_fragment_program required\n");
            return FALSE;
        }

        glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB,
                          GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB,
                          &max_native_alu_instructions);
        if (max_native_alu_instructions < GLAMOR_MIN_ALU_INSTRUCTIONS) {
            LogMessage(X_WARNING,
                       "glamor requires at least %d instructions (%d reported)\n",
                       GLAMOR_MIN_ALU_INSTRUCTIONS, max_native_alu_instructions);
            return FALSE;
        }
    }

    return TRUE;
}

398
399
400
401
402
403
404
405
406
407
static void GLAPIENTRY
glamor_debug_output_callback(GLenum source,
                             GLenum type,
                             GLuint id,
                             GLenum severity,
                             GLsizei length,
                             const GLchar *message,
                             const void *userParam)
{
    ScreenPtr screen = (void *)userParam;
408
409
410
411
412
413
414
    glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);

    if (glamor_priv->suppress_gl_out_of_memory_logging &&
        source == GL_DEBUG_SOURCE_API && type == GL_DEBUG_TYPE_ERROR) {
        return;
    }

415
416
417
418
419
420
421
422
423
424
425
    LogMessageVerb(X_ERROR, 0, "glamor%d: GL error: %*s\n",
               screen->myNum, length, message);
}

/**
 * Configures GL_ARB_debug_output to give us immediate callbacks when
 * GL errors occur, so that we can log them.
 */
static void
glamor_setup_debug_output(ScreenPtr screen)
{
426
427
    if (!epoxy_has_gl_extension("GL_KHR_debug") &&
        !epoxy_has_gl_extension("GL_ARB_debug_output"))
428
429
430
        return;

    glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
431
432
433
    /* Disable debugging messages other than GL API errors */
    glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, NULL,
                          GL_FALSE);
434
435
436
437
438
439
440
441
442
443
444
445
446
447
    glDebugMessageControl(GL_DEBUG_SOURCE_API,
                          GL_DEBUG_TYPE_ERROR,
                          GL_DONT_CARE,
                          0, NULL, GL_TRUE);
    glDebugMessageCallback(glamor_debug_output_callback,
                           screen);

    /* If KHR_debug is present, all debug output is disabled by
     * default on non-debug contexts.
     */
    if (epoxy_has_gl_extension("GL_KHR_debug"))
        glEnable(GL_DEBUG_OUTPUT);
}

448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
const struct glamor_format *
glamor_format_for_pixmap(PixmapPtr pixmap)
{
    ScreenPtr pScreen = pixmap->drawable.pScreen;
    glamor_screen_private *glamor_priv = glamor_get_screen_private(pScreen);
    glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap);

    if (pixmap_priv->is_cbcr)
        return &glamor_priv->cbcr_format;
    else
        return &glamor_priv->formats[pixmap->drawable.depth];
}

static void
glamor_add_format(ScreenPtr screen, int depth, CARD32 render_format,
                  GLenum internalformat, GLenum format, GLenum type)
{
    glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
    struct glamor_format *f = &glamor_priv->formats[depth];

    /* If we're trying to run on GLES, make sure that we get the read
     * formats that we're expecting, since glamor_transfer relies on
     * them matching to get data back out.  To avoid this limitation, we
     * would need to have a more general glReadPixels() path in
     * glamor_transfer that re-encoded the bits to the pixel format that
     * we intended after.
     *
     * Note that we can't just create a pixmap because we're in
     * screeninit.
     */
    if (glamor_priv->is_gles) {
        unsigned fbo, tex;
        int read_format, read_type;
        GLenum status;

        glGenTextures(1, &tex);
        glBindTexture(GL_TEXTURE_2D, tex);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
        glTexImage2D(GL_TEXTURE_2D, 0, internalformat, 1, 1, 0,
                     format, type, NULL);

        glGenFramebuffers(1, &fbo);
        glBindFramebuffer(GL_FRAMEBUFFER, fbo);
        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
                               GL_TEXTURE_2D, tex, 0);
        status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
        if (status != GL_FRAMEBUFFER_COMPLETE) {
            ErrorF("glamor: Test fbo for depth %d incomplete.  "
                   "Falling back to software.\n", depth);
            glDeleteTextures(1, &tex);
            glDeleteFramebuffers(1, &fbo);
            return;
        }

        glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &read_format);
        glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &read_type);

        glDeleteTextures(1, &tex);
        glDeleteFramebuffers(1, &fbo);

        if (format != read_format || type != read_type) {
            ErrorF("glamor: Implementation returned 0x%x/0x%x read format/type "
                   "for depth %d, expected 0x%x/0x%x.  "
                   "Falling back to software.\n",
                   read_format, read_type, depth, format, type);
            return;
        }
    }

    f->depth = depth;
    f->render_format = render_format;
    f->internalformat = internalformat;
    f->format = format;
    f->type = type;
}

/* Set up the GL format/types that glamor will use for the various depths
 *
 * X11's pixel data doesn't have channels, but to store our data in GL
 * we have to pick some sort of format to move X11 pixel data in and
 * out with in glamor_transfer.c.  For X11 core operations, other than
 * GL logic ops (non-GXcopy GC ops) what the driver chooses internally
 * doesn't matter as long as it doesn't drop any bits (we expect them
 * to generally expand, if anything).  For Render, we can expect
 * clients to tend to render with PictFormats matching our channel
 * layouts here since ultimately X11 pixels tend to end up on the
 * screen.  The render implementation will fall back to fb if the
 * channels don't match.
 *
 * Note that these formats don't affect what glamor_egl.c or
 * Xwayland's EGL layer choose for surfaces exposed through DRI or
 * scanout.  For now, those layers need to match what we're choosing
 * here, or channels will end up swizzled around.  Similarly, the
 * driver's visual masks also need to match what we're doing here.
 */
static void
glamor_setup_formats(ScreenPtr screen)
{
    glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);

    /* Prefer r8 textures since they're required by GLES3 and core,
     * only falling back to a8 if we can't do them.
     */
    if (glamor_priv->is_gles || epoxy_has_gl_extension("GL_ARB_texture_rg")) {
        glamor_add_format(screen, 8, PICT_a8,
                          GL_R8, GL_RED, GL_UNSIGNED_BYTE);
    } else {
        glamor_add_format(screen, 8, PICT_a8,
                          GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE);
    }

    if (glamor_priv->is_gles) {
        /* For 15bpp, GLES supports format/type RGBA/5551, rather than
         * bgra/1555_rev.  GL_EXT_bgra lets the impl say the color
         * read format/type is bgra/1555 even if we had to create it
         * with rgba/5551, with Mesa does.  That means we can't use
         * the same format/type for TexSubImage and readpixels.
         *
         * Instead, just store 16 bits using the trusted 565 path, and
         * disable render accel for now.
         */
        glamor_add_format(screen, 15, PICT_x1r5g5b5,
                          GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1);
    } else {
        glamor_add_format(screen, 15, PICT_x1r5g5b5,
                          GL_RGBA, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV);
    }

    glamor_add_format(screen, 16, PICT_r5g6b5,
                      GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5);

    if (glamor_priv->is_gles) {
        assert(X_BYTE_ORDER == X_LITTLE_ENDIAN);
        glamor_add_format(screen, 24, PICT_x8b8g8r8,
                          GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE);
        glamor_add_format(screen, 32, PICT_a8b8g8r8,
                          GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE);
    } else {
        glamor_add_format(screen, 24, PICT_x8r8g8b8,
                          GL_RGBA, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV);
        glamor_add_format(screen, 32, PICT_a8r8g8b8,
                          GL_RGBA, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV);
    }

    if (glamor_priv->is_gles) {
        glamor_add_format(screen, 30, PICT_x2b10g10r10,
                          GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV);
    } else {
        glamor_add_format(screen, 30, PICT_x2r10g10b10,
                          GL_RGB10_A2, GL_BGRA, GL_UNSIGNED_INT_2_10_10_10_REV);
    }

    glamor_priv->cbcr_format.depth = 16;
    glamor_priv->cbcr_format.internalformat = GL_RG8;
    glamor_priv->cbcr_format.format = GL_RG;
    glamor_priv->cbcr_format.type = GL_UNSIGNED_BYTE;
}

Emma Anholt's avatar
Emma Anholt committed
607
608
/** Set up glamor for an already-configured GL context. */
Bool
609
glamor_init(ScreenPtr screen, unsigned int flags)
Emma Anholt's avatar
Emma Anholt committed
610
{
Emma Anholt's avatar
Emma Anholt committed
611
612
    glamor_screen_private *glamor_priv;
    int gl_version;
613
    int glsl_major, glsl_minor;
614
    int max_viewport_size[2];
615
616
617
    const char *shading_version_string;
    int shading_version_offset;

Emma Anholt's avatar
Emma Anholt committed
618
    PictureScreenPtr ps = GetPictureScreenIfSet(screen);
619

Emma Anholt's avatar
Emma Anholt committed
620
621
622
623
624
625
626
627
    if (flags & ~GLAMOR_VALID_FLAGS) {
        ErrorF("glamor_init: Invalid flags %x\n", flags);
        return FALSE;
    }
    glamor_priv = calloc(1, sizeof(*glamor_priv));
    if (glamor_priv == NULL)
        return FALSE;

628
    glamor_priv->flags = flags;
Emma Anholt's avatar
Emma Anholt committed
629

630
    if (!dixRegisterPrivateKey(&glamor_screen_private_key, PRIVATE_SCREEN, 0)) {
Emma Anholt's avatar
Emma Anholt committed
631
632
633
        LogMessage(X_WARNING,
                   "glamor%d: Failed to allocate screen private\n",
                   screen->myNum);
634
        goto free_glamor_private;
Emma Anholt's avatar
Emma Anholt committed
635
636
637
638
    }

    glamor_set_screen_private(screen, glamor_priv);

639
640
    if (!dixRegisterPrivateKey(&glamor_pixmap_private_key, PRIVATE_PIXMAP,
                               sizeof(struct glamor_pixmap_private))) {
Emma Anholt's avatar
Emma Anholt committed
641
642
643
        LogMessage(X_WARNING,
                   "glamor%d: Failed to allocate pixmap private\n",
                   screen->myNum);
644
        goto free_glamor_private;
645
646
647
648
649
650
651
    }

    if (!dixRegisterPrivateKey(&glamor_gc_private_key, PRIVATE_GC,
                               sizeof (glamor_gc_private))) {
        LogMessage(X_WARNING,
                   "glamor%d: Failed to allocate gc private\n",
                   screen->myNum);
652
        goto free_glamor_private;
Emma Anholt's avatar
Emma Anholt committed
653
654
    }

655
656
657
    glamor_priv->saved_procs.close_screen = screen->CloseScreen;
    screen->CloseScreen = glamor_close_screen;

658
659
660
    glamor_priv->saved_procs.destroy_pixmap = screen->DestroyPixmap;
    screen->DestroyPixmap = glamor_destroy_pixmap;

661
662
663
664
665
666
667
668
669
670
671
    /* If we are using egl screen, call egl screen init to
     * register correct close screen function. */
    if (flags & GLAMOR_USE_EGL_SCREEN) {
        glamor_egl_screen_init(screen, &glamor_priv->ctx);
    } else {
        if (!glamor_glx_screen_init(&glamor_priv->ctx))
            goto fail;
    }

    glamor_make_current(glamor_priv);

672
673
    if (!epoxy_is_desktop_gl())
        glamor_priv->is_gles = TRUE;
674

675
    gl_version = epoxy_gl_version();
676

677
678
679
680
    /* assume a core profile if we are GL 3.1 and don't have ARB_compatibility */
    glamor_priv->is_core_profile =
        gl_version >= 31 && !epoxy_has_gl_extension("GL_ARB_compatibility");

681
682
683
684
685
686
687
688
    shading_version_string = (char *) glGetString(GL_SHADING_LANGUAGE_VERSION);

    if (!shading_version_string) {
        LogMessage(X_WARNING,
                   "glamor%d: Failed to get GLSL version\n",
                   screen->myNum);
        goto fail;
    }
689

690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
    shading_version_offset = 0;
    if (strncmp("OpenGL ES GLSL ES ", shading_version_string, 18) == 0)
        shading_version_offset = 18;

    if (sscanf(shading_version_string + shading_version_offset,
               "%i.%i",
               &glsl_major,
               &glsl_minor) != 2) {
        LogMessage(X_WARNING,
                   "glamor%d: Failed to parse GLSL version string %s\n",
                   screen->myNum, shading_version_string);
        goto fail;
    }
    glamor_priv->glsl_version = glsl_major * 100 + glsl_minor;

705
    if (glamor_priv->is_gles) {
706
707
708
709
710
711
712
713
714
        /* Force us back to the base version of our programs on an ES
         * context, anyway.  Basically glamor only uses desktop 1.20
         * or 1.30 currently.  1.30's new features are also present in
         * ES 3.0, but our glamor_program.c constructions use a lot of
         * compatibility features (to reduce the diff between 1.20 and
         * 1.30 programs).
         */
        glamor_priv->glsl_version = 120;
    }
715

716
717
718
719
720
721
722
723
724
725
726
727
728
    /* We'd like to require GL_ARB_map_buffer_range or
     * GL_OES_map_buffer_range, since it offers more information to
     * the driver than plain old glMapBuffer() or glBufferSubData().
     * It's been supported on Mesa on the desktop since 2009 and on
     * GLES2 since October 2012.  It's supported on Apple's iOS
     * drivers for SGX535 and A7, but apparently not on most Android
     * devices (the OES extension spec wasn't released until June
     * 2012).
     *
     * 82% of 0 A.D. players (desktop GL) submitting hardware reports
     * have support for it, with most of the ones lacking it being on
     * Windows with Intel 4-series (G45) graphics or older.
     */
729
    if (!glamor_priv->is_gles) {
730
731
        if (gl_version < 21) {
            ErrorF("Require OpenGL version 2.1 or later.\n");
732
733
            goto fail;
        }
734

735
736
737
738
739
740
        if (!glamor_priv->is_core_profile &&
            !epoxy_has_gl_extension("GL_ARB_texture_border_clamp")) {
            ErrorF("GL_ARB_texture_border_clamp required\n");
            goto fail;
        }

741
742
        if (!glamor_check_instruction_count(gl_version))
            goto fail;
743
744
745
746
747
748
749
750

        /* Glamor rendering assumes that platforms with GLSL 130+
         * have instanced arrays, but this is not always the case.
         * etnaviv offers GLSL 140 with OpenGL 2.1.
         */
        if (glamor_priv->glsl_version >= 130 &&
            !epoxy_has_gl_extension("GL_ARB_instanced_arrays"))
                glamor_priv->glsl_version = 120;
751
    } else {
752
        if (gl_version < 20) {
753
754
755
            ErrorF("Require Open GLES2.0 or later.\n");
            goto fail;
        }
756

757
        if (!epoxy_has_gl_extension("GL_EXT_texture_format_BGRA8888")) {
758
759
760
            ErrorF("GL_EXT_texture_format_BGRA8888 required\n");
            goto fail;
        }
761
762
763
764
765

        if (!epoxy_has_gl_extension("GL_OES_texture_border_clamp")) {
            ErrorF("GL_OES_texture_border_clamp required\n");
            goto fail;
        }
Emma Anholt's avatar
Emma Anholt committed
766
    }
767

768
769
770
771
772
773
    if (!epoxy_has_gl_extension("GL_ARB_vertex_array_object") &&
        !epoxy_has_gl_extension("GL_OES_vertex_array_object")) {
        ErrorF("GL_{ARB,OES}_vertex_array_object required\n");
        goto fail;
    }

774
    glamor_priv->has_rw_pbo = FALSE;
775
    if (!glamor_priv->is_gles)
776
777
        glamor_priv->has_rw_pbo = TRUE;

778
    glamor_priv->has_khr_debug = epoxy_has_gl_extension("GL_KHR_debug");
Emma Anholt's avatar
Emma Anholt committed
779
    glamor_priv->has_pack_invert =
780
        epoxy_has_gl_extension("GL_MESA_pack_invert");
Emma Anholt's avatar
Emma Anholt committed
781
    glamor_priv->has_fbo_blit =
782
        epoxy_has_gl_extension("GL_EXT_framebuffer_blit");
783
    glamor_priv->has_map_buffer_range =
784
785
        epoxy_has_gl_extension("GL_ARB_map_buffer_range") ||
        epoxy_has_gl_extension("GL_EXT_map_buffer_range");
Emma Anholt's avatar
Emma Anholt committed
786
    glamor_priv->has_buffer_storage =
787
        epoxy_has_gl_extension("GL_ARB_buffer_storage");
788
789
    glamor_priv->has_mesa_tile_raster_order =
        epoxy_has_gl_extension("GL_MESA_tile_raster_order");
790
791
    glamor_priv->has_nv_texture_barrier =
        epoxy_has_gl_extension("GL_NV_texture_barrier");
792
    glamor_priv->has_unpack_subimage =
793
        !glamor_priv->is_gles ||
794
795
796
        epoxy_gl_version() >= 30 ||
        epoxy_has_gl_extension("GL_EXT_unpack_subimage");
    glamor_priv->has_pack_subimage =
797
        !glamor_priv->is_gles ||
798
799
        epoxy_gl_version() >= 30 ||
        epoxy_has_gl_extension("GL_NV_pack_subimage");
800
    glamor_priv->has_dual_blend =
801
        glamor_priv->glsl_version >= 130 &&
802
        epoxy_has_gl_extension("GL_ARB_blend_func_extended");
803
804
805
    glamor_priv->has_clear_texture =
        epoxy_gl_version() >= 44 ||
        epoxy_has_gl_extension("GL_ARB_clear_texture");
806

807
808
    glamor_priv->can_copyplane = (gl_version >= 30);

809
810
    glamor_setup_debug_output(screen);

811
    glamor_priv->use_quads = !glamor_priv->is_gles &&
812
813
                             !glamor_priv->is_core_profile;

814
815
816
817
818
819
820
821
    /* Driver-specific hack: Avoid using GL_QUADS on VC4, where
     * they'll be emulated more expensively than we can with our
     * cached IB.
     */
    if (strstr((char *)glGetString(GL_VENDOR), "Broadcom") &&
        strstr((char *)glGetString(GL_RENDERER), "VC4"))
        glamor_priv->use_quads = FALSE;

822
    glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, &glamor_priv->max_fbo_size);
823
    glGetIntegerv(GL_MAX_TEXTURE_SIZE, &glamor_priv->max_fbo_size);
824
825
826
    glGetIntegerv(GL_MAX_VIEWPORT_DIMS, max_viewport_size);
    glamor_priv->max_fbo_size = MIN(glamor_priv->max_fbo_size, max_viewport_size[0]);
    glamor_priv->max_fbo_size = MIN(glamor_priv->max_fbo_size, max_viewport_size[1]);
827
#ifdef MAX_FBO_SIZE
Emma Anholt's avatar
Emma Anholt committed
828
    glamor_priv->max_fbo_size = MAX_FBO_SIZE;
829
#endif
830

831
832
    glamor_priv->has_texture_swizzle =
        (epoxy_has_gl_extension("GL_ARB_texture_swizzle") ||
833
         (glamor_priv->is_gles && gl_version >= 30));
834

835
    glamor_setup_formats(screen);
836

Emma Anholt's avatar
Emma Anholt committed
837
    glamor_set_debug_level(&glamor_debug_level);
838

839
840
841
    if (!glamor_font_init(screen))
        goto fail;

842
843
    glamor_priv->saved_procs.block_handler = screen->BlockHandler;
    screen->BlockHandler = _glamor_block_handler;
844

845
846
847
848
849
    if (!glamor_composite_glyphs_init(screen)) {
        ErrorF("Failed to initialize composite masks\n");
        goto fail;
    }

850
851
    glamor_priv->saved_procs.create_gc = screen->CreateGC;
    screen->CreateGC = glamor_create_gc;
852

853
854
    glamor_priv->saved_procs.create_pixmap = screen->CreatePixmap;
    screen->CreatePixmap = glamor_create_pixmap;
855

856
857
    glamor_priv->saved_procs.get_spans = screen->GetSpans;
    screen->GetSpans = glamor_get_spans;
858

859
860
    glamor_priv->saved_procs.get_image = screen->GetImage;
    screen->GetImage = glamor_get_image;
861

862
863
864
    glamor_priv->saved_procs.change_window_attributes =
        screen->ChangeWindowAttributes;
    screen->ChangeWindowAttributes = glamor_change_window_attributes;
865

866
867
    glamor_priv->saved_procs.copy_window = screen->CopyWindow;
    screen->CopyWindow = glamor_copy_window;
868

869
870
    glamor_priv->saved_procs.bitmap_to_region = screen->BitmapToRegion;
    screen->BitmapToRegion = glamor_bitmap_to_region;
871

872
873
    glamor_priv->saved_procs.composite = ps->Composite;
    ps->Composite = glamor_composite;
874

875
876
    glamor_priv->saved_procs.trapezoids = ps->Trapezoids;
    ps->Trapezoids = glamor_trapezoids;
Zhigang Gong's avatar
Zhigang Gong committed
877

878
879
    glamor_priv->saved_procs.triangles = ps->Triangles;
    ps->Triangles = glamor_triangles;
Zhigang Gong's avatar
Zhigang Gong committed
880

881
882
    glamor_priv->saved_procs.addtraps = ps->AddTraps;
    ps->AddTraps = glamor_add_traps;
883

Emma Anholt's avatar
Emma Anholt committed
884
    glamor_priv->saved_procs.composite_rects = ps->CompositeRects;
885
    ps->CompositeRects = glamor_composite_rectangles;
886

Emma Anholt's avatar
Emma Anholt committed
887
    glamor_priv->saved_procs.glyphs = ps->Glyphs;
888
    ps->Glyphs = glamor_composite_glyphs;
889

890
    glamor_init_vbo(screen);
Emma Anholt's avatar
Emma Anholt committed
891
892
    glamor_init_gradient_shader(screen);
    glamor_pixmap_init(screen);
893
    glamor_sync_init(screen);
894

Emma Anholt's avatar
Emma Anholt committed
895
    glamor_priv->screen = screen;
896

Emma Anholt's avatar
Emma Anholt committed
897
    return TRUE;
898

Emma Anholt's avatar
Emma Anholt committed
899
 fail:
900
901
902
903
904
    /* Restore default CloseScreen and DestroyPixmap handlers */
    screen->CloseScreen = glamor_priv->saved_procs.close_screen;
    screen->DestroyPixmap = glamor_priv->saved_procs.destroy_pixmap;

 free_glamor_private:
Emma Anholt's avatar
Emma Anholt committed
905
906
907
    free(glamor_priv);
    glamor_set_screen_private(screen, NULL);
    return FALSE;
Emma Anholt's avatar
Emma Anholt committed
908
909
}

910
911
912
static void
glamor_release_screen_priv(ScreenPtr screen)
{
Emma Anholt's avatar
Emma Anholt committed
913
    glamor_screen_private *glamor_priv;
914

Emma Anholt's avatar
Emma Anholt committed
915
    glamor_priv = glamor_get_screen_private(screen);
916
    glamor_fini_vbo(screen);
Emma Anholt's avatar
Emma Anholt committed
917
918
    glamor_pixmap_fini(screen);
    free(glamor_priv);
919

Emma Anholt's avatar
Emma Anholt committed
920
    glamor_set_screen_private(screen, NULL);
921
922
}

Zhigang Gong's avatar
Zhigang Gong committed
923
Bool
924
glamor_close_screen(ScreenPtr screen)
925
{
Emma Anholt's avatar
Emma Anholt committed
926
927
928
    glamor_screen_private *glamor_priv;
    PixmapPtr screen_pixmap;
    PictureScreenPtr ps = GetPictureScreenIfSet(screen);
929

Emma Anholt's avatar
Emma Anholt committed
930
    glamor_priv = glamor_get_screen_private(screen);
931
    glamor_sync_close(screen);
932
    glamor_composite_glyphs_fini(screen);
Emma Anholt's avatar
Emma Anholt committed
933
934
    screen->CloseScreen = glamor_priv->saved_procs.close_screen;

935
936
937
938
939
940
941
942
943
944
945
946
947
    screen->CreateGC = glamor_priv->saved_procs.create_gc;
    screen->CreatePixmap = glamor_priv->saved_procs.create_pixmap;
    screen->DestroyPixmap = glamor_priv->saved_procs.destroy_pixmap;
    screen->GetSpans = glamor_priv->saved_procs.get_spans;
    screen->ChangeWindowAttributes =
        glamor_priv->saved_procs.change_window_attributes;
    screen->CopyWindow = glamor_priv->saved_procs.copy_window;
    screen->BitmapToRegion = glamor_priv->saved_procs.bitmap_to_region;
    screen->BlockHandler = glamor_priv->saved_procs.block_handler;

    ps->Composite = glamor_priv->saved_procs.composite;
    ps->Trapezoids = glamor_priv->saved_procs.trapezoids;
    ps->Triangles = glamor_priv->saved_procs.triangles;
Emma Anholt's avatar
Emma Anholt committed
948
949
    ps->CompositeRects = glamor_priv->saved_procs.composite_rects;
    ps->Glyphs = glamor_priv->saved_procs.glyphs;
950

Emma Anholt's avatar
Emma Anholt committed
951
    screen_pixmap = screen->GetScreenPixmap(screen);
952
    glamor_pixmap_destroy_fbo(screen_pixmap);
Zhigang Gong's avatar
Zhigang Gong committed
953

Emma Anholt's avatar
Emma Anholt committed
954
    glamor_release_screen_priv(screen);
Zhigang Gong's avatar
Zhigang Gong committed
955

956
    return screen->CloseScreen(screen);
957
958
959
960
961
}

void
glamor_fini(ScreenPtr screen)
{
Emma Anholt's avatar
Emma Anholt committed
962
    /* Do nothing currently. */
963
}
Axel Davy's avatar
Axel Davy committed
964

Emma Anholt's avatar
Emma Anholt committed
965
966
void
glamor_enable_dri3(ScreenPtr screen)
Axel Davy's avatar
Axel Davy committed
967
{
Emma Anholt's avatar
Emma Anholt committed
968
969
970
    glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);

    glamor_priv->dri3_enabled = TRUE;
Axel Davy's avatar
Axel Davy committed
971
972
}

Emma Anholt's avatar
Emma Anholt committed
973
Bool
974
glamor_supports_pixmap_import_export(ScreenPtr screen)
Axel Davy's avatar
Axel Davy committed
975
{
Emma Anholt's avatar
Emma Anholt committed
976
977
978
    glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);

    return glamor_priv->dri3_enabled;
Axel Davy's avatar
Axel Davy committed
979
980
}

981
982
983
984
985
986
987
988
989
990
_X_EXPORT void
glamor_set_drawable_modifiers_func(ScreenPtr screen,
                                   GetDrawableModifiersFuncPtr func)
{
    glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);

    glamor_priv->get_drawable_modifiers = func;
}

_X_EXPORT Bool
991
992
glamor_get_drawable_modifiers(DrawablePtr draw, uint32_t format,
                              uint32_t *num_modifiers, uint64_t **modifiers)
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
{
    struct glamor_screen_private *glamor_priv =
        glamor_get_screen_private(draw->pScreen);

    if (glamor_priv->get_drawable_modifiers) {
        return glamor_priv->get_drawable_modifiers(draw, format,
                                                   num_modifiers, modifiers);
    }
    *num_modifiers = 0;
    *modifiers = NULL;
    return TRUE;
}

1006
1007
1008
1009
static int
_glamor_fds_from_pixmap(ScreenPtr screen, PixmapPtr pixmap, int *fds,
                        uint32_t *strides, uint32_t *offsets,
                        CARD32 *size, uint64_t *modifier)
Axel Davy's avatar
Axel Davy committed
1010
{
1011
    glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap);
Emma Anholt's avatar
Emma Anholt committed
1012
1013
1014
    glamor_screen_private *glamor_priv =
        glamor_get_screen_private(pixmap->drawable.pScreen);

1015
    if (!glamor_priv->dri3_enabled)
1016
        return 0;
Emma Anholt's avatar
Emma Anholt committed
1017
1018
1019
    switch (pixmap_priv->type) {
    case GLAMOR_TEXTURE_DRM:
    case GLAMOR_TEXTURE_ONLY:
1020
        if (!glamor_pixmap_ensure_fbo(pixmap, 0))
1021
            return 0;
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034

        if (modifier) {
            return glamor_egl_fds_from_pixmap(screen, pixmap, fds,
                                              strides, offsets,
                                              modifier);
        } else {
            CARD16 stride;

            fds[0] = glamor_egl_fd_from_pixmap(screen, pixmap, &stride, size);
            strides[0] = stride;

            return fds[0] >= 0;
        }
Emma Anholt's avatar
Emma Anholt committed
1035
1036
1037
    default:
        break;
    }
1038
    return 0;
Axel Davy's avatar
Axel Davy committed
1039
1040
}

1041
1042
1043
1044
1045
1046
1047
1048
1049
_X_EXPORT int
glamor_fds_from_pixmap(ScreenPtr screen, PixmapPtr pixmap, int *fds,
                       uint32_t *strides, uint32_t *offsets,
                       uint64_t *modifier)
{
    return _glamor_fds_from_pixmap(screen, pixmap, fds, strides, offsets,
                                   NULL, modifier);
}

1050
_X_EXPORT int
1051
1052
glamor_fd_from_pixmap(ScreenPtr screen,
                      PixmapPtr pixmap, CARD16 *stride, CARD32 *size)
1053
{
1054
    int fd;
1055
    int ret;
1056
    uint32_t stride32;
1057

1058
1059
1060
    ret = _glamor_fds_from_pixmap(screen, pixmap, &fd, &stride32, NULL, size,
                                  NULL);
    if (ret != 1)
1061
1062
        return -1;

1063
1064
    *stride = stride32;
    return fd;
1065
1066
1067
1068
1069
1070
1071
1072
}

_X_EXPORT int
glamor_shareable_fd_from_pixmap(ScreenPtr screen,
                                PixmapPtr pixmap, CARD16 *stride, CARD32 *size)
{
    unsigned orig_usage_hint = pixmap->usage_hint;
    int ret;
1073

1074
    /*
Alan Coopersmith's avatar
Alan Coopersmith committed
1075
     * The actual difference between a shareable and non-shareable buffer
1076
1077
1078
1079
1080
1081
1082
1083
1084
     * is decided 4 call levels deep in glamor_make_pixmap_exportable()
     * based on pixmap->usage_hint == CREATE_PIXMAP_USAGE_SHARED
     * 2 of those calls are also exported API, so we cannot just add a flag.
     */
    pixmap->usage_hint = CREATE_PIXMAP_USAGE_SHARED;

    ret = glamor_fd_from_pixmap(screen, pixmap, stride, size);

    pixmap->usage_hint = orig_usage_hint;
1085
1086
1087
    return ret;
}

Axel Davy's avatar
Axel Davy committed
1088
int
1089
glamor_name_from_pixmap(PixmapPtr pixmap, CARD16 *stride, CARD32 *size)
Axel Davy's avatar
Axel Davy committed
1090
{
1091
    glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap);
Emma Anholt's avatar
Emma Anholt committed
1092
1093
1094
1095

    switch (pixmap_priv->type) {
    case GLAMOR_TEXTURE_DRM:
    case GLAMOR_TEXTURE_ONLY:
1096
        if (!glamor_pixmap_ensure_fbo(pixmap, 0))
1097
            return -1;
1098
1099
        return glamor_egl_fd_name_from_pixmap(pixmap->drawable.pScreen,
                                              pixmap, stride, size);
Emma Anholt's avatar
Emma Anholt committed
1100
1101
1102
1103
    default:
        break;
    }
    return -1;
Axel Davy's avatar
Axel Davy committed
1104
}
Dave Airlie's avatar
Dave Airlie committed
1105
1106
1107
1108
1109
1110
1111
1112
1113

void
glamor_finish(ScreenPtr screen)
{
    glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);

    glamor_make_current(glamor_priv);
    glFinish();
}