1/*
2 * Copyright © 2008,2011 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 *
23 * Authors:
24 *    Eric Anholt <eric@anholt.net>
25 *    Zhigang Gong <zhigang.gong@linux.intel.com>
26 *    Chad Versace <chad.versace@linux.intel.com>
27 */
28
29/** @file glamor.c
30 * This file covers the initialization and teardown of glamor, and has various
31 * functions not responsible for performing rendering.
32 */
33
34#include <stdlib.h>
35#include <unistd.h>
36
37#include "glamor_priv.h"
38#include "mipict.h"
39
40DevPrivateKeyRec glamor_screen_private_key;
41DevPrivateKeyRec glamor_pixmap_private_key;
42DevPrivateKeyRec glamor_gc_private_key;
43
44glamor_screen_private *
45glamor_get_screen_private(ScreenPtr screen)
46{
47    return (glamor_screen_private *)
48        dixLookupPrivate(&screen->devPrivates, &glamor_screen_private_key);
49}
50
51void
52glamor_set_screen_private(ScreenPtr screen, glamor_screen_private *priv)
53{
54    dixSetPrivate(&screen->devPrivates, &glamor_screen_private_key, priv);
55}
56
57/**
58 * glamor_get_drawable_pixmap() returns a backing pixmap for a given drawable.
59 *
60 * @param drawable the drawable being requested.
61 *
62 * This function returns the backing pixmap for a drawable, whether it is a
63 * redirected window, unredirected window, or already a pixmap.  Note that
64 * coordinate translation is needed when drawing to the backing pixmap of a
65 * redirected window, and the translation coordinates are provided by calling
66 * exaGetOffscreenPixmap() on the drawable.
67 */
68PixmapPtr
69glamor_get_drawable_pixmap(DrawablePtr drawable)
70{
71    if (drawable->type == DRAWABLE_WINDOW)
72        return drawable->pScreen->GetWindowPixmap((WindowPtr) drawable);
73    else
74        return (PixmapPtr) drawable;
75}
76
77static void
78glamor_init_pixmap_private_small(PixmapPtr pixmap, glamor_pixmap_private *pixmap_priv)
79{
80    pixmap_priv->box.x1 = 0;
81    pixmap_priv->box.x2 = pixmap->drawable.width;
82    pixmap_priv->box.y1 = 0;
83    pixmap_priv->box.y2 = pixmap->drawable.height;
84    pixmap_priv->block_w = pixmap->drawable.width;
85    pixmap_priv->block_h = pixmap->drawable.height;
86    pixmap_priv->block_hcnt = 1;
87    pixmap_priv->block_wcnt = 1;
88    pixmap_priv->box_array = &pixmap_priv->box;
89    pixmap_priv->fbo_array = &pixmap_priv->fbo;
90}
91
92_X_EXPORT void
93glamor_set_pixmap_type(PixmapPtr pixmap, glamor_pixmap_type_t type)
94{
95    glamor_pixmap_private *pixmap_priv;
96
97    pixmap_priv = glamor_get_pixmap_private(pixmap);
98    pixmap_priv->type = type;
99    glamor_init_pixmap_private_small(pixmap, pixmap_priv);
100}
101
102_X_EXPORT Bool
103glamor_set_pixmap_texture(PixmapPtr pixmap, unsigned int tex)
104{
105    ScreenPtr screen = pixmap->drawable.pScreen;
106    glamor_pixmap_private *pixmap_priv;
107    glamor_screen_private *glamor_priv;
108    glamor_pixmap_fbo *fbo;
109
110    glamor_priv = glamor_get_screen_private(screen);
111    pixmap_priv = glamor_get_pixmap_private(pixmap);
112
113    if (pixmap_priv->fbo) {
114        fbo = glamor_pixmap_detach_fbo(pixmap_priv);
115        glamor_destroy_fbo(glamor_priv, fbo);
116    }
117
118    fbo = glamor_create_fbo_from_tex(glamor_priv, pixmap,
119                                     pixmap->drawable.width,
120                                     pixmap->drawable.height, tex, 0);
121
122    if (fbo == NULL) {
123        ErrorF("XXX fail to create fbo.\n");
124        return FALSE;
125    }
126
127    glamor_pixmap_attach_fbo(pixmap, fbo);
128
129    return TRUE;
130}
131
132_X_EXPORT void
133glamor_clear_pixmap(PixmapPtr pixmap)
134{
135    ScreenPtr screen = pixmap->drawable.pScreen;
136    glamor_screen_private *glamor_priv;
137    glamor_pixmap_private *pixmap_priv;
138    const struct glamor_format *pixmap_format;
139
140    glamor_priv = glamor_get_screen_private(screen);
141    pixmap_priv = glamor_get_pixmap_private(pixmap);
142    pixmap_format = glamor_format_for_pixmap(pixmap);
143
144    assert(pixmap_priv->fbo != NULL);
145
146    glamor_pixmap_clear_fbo(glamor_priv, pixmap_priv->fbo, pixmap_format);
147}
148
149uint32_t
150glamor_get_pixmap_texture(PixmapPtr pixmap)
151{
152    glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap);
153
154    if (!pixmap_priv)
155        return 0;
156
157    if (!pixmap_priv->fbo)
158        return 0;
159
160    if (pixmap_priv->type != GLAMOR_TEXTURE_ONLY)
161        return 0;
162
163    return pixmap_priv->fbo->tex;
164}
165
166void
167glamor_bind_texture(glamor_screen_private *glamor_priv, GLenum texture,
168                    glamor_pixmap_fbo *fbo, Bool destination_red)
169{
170    glActiveTexture(texture);
171    glBindTexture(GL_TEXTURE_2D, fbo->tex);
172
173    /* If we're pulling data from a GL_RED texture, then whether we
174     * want to make it an A,0,0,0 result or a 0,0,0,R result depends
175     * on whether the destination is also a GL_RED texture.
176     *
177     * For GL_RED destinations, we need to leave the bits in the R
178     * channel. For all other destinations, we need to clear out the R
179     * channel so that it returns zero for R, G and B.
180     *
181     * Note that we're leaving the SWIZZLE_A value alone; for GL_RED
182     * destinations, that means we'll actually be returning R,0,0,R,
183     * but it doesn't matter as the bits in the alpha channel aren't
184     * going anywhere.
185     */
186
187    /* Is the operand a GL_RED fbo?
188     */
189
190    if (fbo->is_red) {
191        /* If destination is also GL_RED, then preserve the bits in
192         * the R channel */
193
194        if (destination_red)
195            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_RED);
196        else
197            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_ZERO);
198    }
199}
200
201PixmapPtr
202glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth,
203                     unsigned int usage)
204{
205    PixmapPtr pixmap;
206    glamor_pixmap_private *pixmap_priv;
207    glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
208    glamor_pixmap_fbo *fbo = NULL;
209    int pitch;
210
211    if (w > 32767 || h > 32767)
212        return NullPixmap;
213
214    if ((usage == GLAMOR_CREATE_PIXMAP_CPU
215         || (usage == CREATE_PIXMAP_USAGE_GLYPH_PICTURE &&
216             w <= glamor_priv->glyph_max_dim &&
217             h <= glamor_priv->glyph_max_dim)
218         || (w == 0 && h == 0)
219         || !glamor_priv->formats[depth].rendering_supported))
220        return fbCreatePixmap(screen, w, h, depth, usage);
221    else
222        pixmap = fbCreatePixmap(screen, 0, 0, depth, usage);
223
224    pixmap_priv = glamor_get_pixmap_private(pixmap);
225
226    pixmap_priv->is_cbcr = (usage == GLAMOR_CREATE_FORMAT_CBCR);
227
228    pitch = (((w * pixmap->drawable.bitsPerPixel + 7) / 8) + 3) & ~3;
229    screen->ModifyPixmapHeader(pixmap, w, h, 0, 0, pitch, NULL);
230
231    pixmap_priv->type = GLAMOR_TEXTURE_ONLY;
232
233    if (usage == GLAMOR_CREATE_PIXMAP_NO_TEXTURE) {
234        glamor_init_pixmap_private_small(pixmap, pixmap_priv);
235        return pixmap;
236    }
237    else if (usage == GLAMOR_CREATE_NO_LARGE ||
238        glamor_check_fbo_size(glamor_priv, w, h))
239    {
240        glamor_init_pixmap_private_small(pixmap, pixmap_priv);
241        fbo = glamor_create_fbo(glamor_priv, pixmap, w, h, usage);
242    } else {
243        int tile_size = glamor_priv->max_fbo_size;
244        DEBUGF("Create LARGE pixmap %p width %d height %d, tile size %d\n",
245               pixmap, w, h, tile_size);
246        fbo = glamor_create_fbo_array(glamor_priv, pixmap, usage,
247                                      tile_size, tile_size, pixmap_priv);
248    }
249
250    if (fbo == NULL) {
251        fbDestroyPixmap(pixmap);
252        return fbCreatePixmap(screen, w, h, depth, usage);
253    }
254
255    glamor_pixmap_attach_fbo(pixmap, fbo);
256
257    return pixmap;
258}
259
260Bool
261glamor_destroy_pixmap(PixmapPtr pixmap)
262{
263    if (pixmap->refcnt == 1) {
264        glamor_pixmap_destroy_fbo(pixmap);
265    }
266
267    return fbDestroyPixmap(pixmap);
268}
269
270void
271glamor_block_handler(ScreenPtr screen)
272{
273    glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
274
275    glamor_make_current(glamor_priv);
276    glFlush();
277}
278
279static void
280_glamor_block_handler(ScreenPtr screen, void *timeout)
281{
282    glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
283
284    glamor_make_current(glamor_priv);
285    glFlush();
286
287    screen->BlockHandler = glamor_priv->saved_procs.block_handler;
288    screen->BlockHandler(screen, timeout);
289    glamor_priv->saved_procs.block_handler = screen->BlockHandler;
290    screen->BlockHandler = _glamor_block_handler;
291}
292
293static void
294glamor_set_debug_level(int *debug_level)
295{
296    char *debug_level_string;
297
298    debug_level_string = getenv("GLAMOR_DEBUG");
299    if (debug_level_string
300        && sscanf(debug_level_string, "%d", debug_level) == 1)
301        return;
302    *debug_level = 0;
303}
304
305int glamor_debug_level;
306
307void
308glamor_gldrawarrays_quads_using_indices(glamor_screen_private *glamor_priv,
309                                        unsigned count)
310{
311    unsigned i;
312
313    /* For a single quad, don't bother with an index buffer. */
314    if (count ==  1)
315        goto fallback;
316
317    if (glamor_priv->ib_size < count) {
318        /* Basic GLES2 doesn't have any way to map buffer objects for
319         * writing, but it's long past time for drivers to have
320         * MapBufferRange.
321         */
322        if (!glamor_priv->has_map_buffer_range)
323            goto fallback;
324
325        /* Lazy create the buffer name, and only bind it once since
326         * none of the glamor code binds it to anything else.
327         */
328        if (!glamor_priv->ib) {
329            glGenBuffers(1, &glamor_priv->ib);
330            glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, glamor_priv->ib);
331        }
332
333        /* For now, only support GL_UNSIGNED_SHORTs. */
334        if (count > ((1 << 16) - 1) / 4) {
335            goto fallback;
336        } else {
337            uint16_t *data;
338            size_t size = count * 6 * sizeof(GLushort);
339
340            glBufferData(GL_ELEMENT_ARRAY_BUFFER, size, NULL, GL_STATIC_DRAW);
341            data = glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER,
342                                    0, size,
343                                    GL_MAP_WRITE_BIT |
344                                    GL_MAP_INVALIDATE_BUFFER_BIT);
345            for (i = 0; i < count; i++) {
346                data[i * 6 + 0] = i * 4 + 0;
347                data[i * 6 + 1] = i * 4 + 1;
348                data[i * 6 + 2] = i * 4 + 2;
349                data[i * 6 + 3] = i * 4 + 0;
350                data[i * 6 + 4] = i * 4 + 2;
351                data[i * 6 + 5] = i * 4 + 3;
352            }
353            glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
354
355            glamor_priv->ib_size = count;
356            glamor_priv->ib_type = GL_UNSIGNED_SHORT;
357        }
358    }
359
360    glDrawElements(GL_TRIANGLES, count * 6, glamor_priv->ib_type, NULL);
361    return;
362
363fallback:
364    for (i = 0; i < count; i++)
365        glDrawArrays(GL_TRIANGLE_FAN, i * 4, 4);
366}
367
368
369static Bool
370glamor_check_instruction_count(int gl_version)
371{
372    GLint max_native_alu_instructions;
373
374    /* Avoid using glamor if the reported instructions limit is too low,
375     * as this would cause glamor to fallback on sw due to large shaders
376     * which ends up being unbearably slow.
377     */
378    if (gl_version < 30) {
379        if (!epoxy_has_gl_extension("GL_ARB_fragment_program")) {
380            ErrorF("GL_ARB_fragment_program required\n");
381            return FALSE;
382        }
383
384        glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB,
385                          GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB,
386                          &max_native_alu_instructions);
387        if (max_native_alu_instructions < GLAMOR_MIN_ALU_INSTRUCTIONS) {
388            LogMessage(X_WARNING,
389                       "glamor requires at least %d instructions (%d reported)\n",
390                       GLAMOR_MIN_ALU_INSTRUCTIONS, max_native_alu_instructions);
391            return FALSE;
392        }
393    }
394
395    return TRUE;
396}
397
398static void GLAPIENTRY
399glamor_debug_output_callback(GLenum source,
400                             GLenum type,
401                             GLuint id,
402                             GLenum severity,
403                             GLsizei length,
404                             const GLchar *message,
405                             const void *userParam)
406{
407    ScreenPtr screen = (void *)userParam;
408    glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
409
410    if (glamor_priv->suppress_gl_out_of_memory_logging &&
411        source == GL_DEBUG_SOURCE_API && type == GL_DEBUG_TYPE_ERROR) {
412        return;
413    }
414
415    LogMessageVerb(X_ERROR, 0, "glamor%d: GL error: %*s\n",
416               screen->myNum, length, message);
417    xorg_backtrace();
418}
419
420/**
421 * Configures GL_ARB_debug_output to give us immediate callbacks when
422 * GL errors occur, so that we can log them.
423 */
424static void
425glamor_setup_debug_output(ScreenPtr screen)
426{
427    if (!epoxy_has_gl_extension("GL_KHR_debug") &&
428        !epoxy_has_gl_extension("GL_ARB_debug_output"))
429        return;
430
431    glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
432    /* Disable debugging messages other than GL API errors */
433    glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, NULL,
434                          GL_FALSE);
435    glDebugMessageControl(GL_DEBUG_SOURCE_API,
436                          GL_DEBUG_TYPE_ERROR,
437                          GL_DONT_CARE,
438                          0, NULL, GL_TRUE);
439    glDebugMessageCallback(glamor_debug_output_callback,
440                           screen);
441
442    /* If KHR_debug is present, all debug output is disabled by
443     * default on non-debug contexts.
444     */
445    if (epoxy_has_gl_extension("GL_KHR_debug"))
446        glEnable(GL_DEBUG_OUTPUT);
447}
448
449const struct glamor_format *
450glamor_format_for_pixmap(PixmapPtr pixmap)
451{
452    ScreenPtr pScreen = pixmap->drawable.pScreen;
453    glamor_screen_private *glamor_priv = glamor_get_screen_private(pScreen);
454    glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap);
455
456    if (pixmap_priv->is_cbcr)
457        return &glamor_priv->cbcr_format;
458    else
459        return &glamor_priv->formats[pixmap->drawable.depth];
460}
461
462static void
463glamor_add_format(ScreenPtr screen, int depth, CARD32 render_format,
464                  GLenum internalformat, GLenum format, GLenum type,
465                  Bool rendering_supported)
466{
467    glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
468    struct glamor_format *f = &glamor_priv->formats[depth];
469
470    /* If we're trying to run on GLES, make sure that we get the read
471     * formats that we're expecting, since glamor_transfer relies on
472     * them matching to get data back out.  To avoid this limitation, we
473     * would need to have a more general glReadPixels() path in
474     * glamor_transfer that re-encoded the bits to the pixel format that
475     * we intended after.
476     *
477     * Note that we can't just create a pixmap because we're in
478     * screeninit.
479     */
480    if (rendering_supported && glamor_priv->is_gles) {
481        unsigned fbo, tex;
482        int read_format, read_type;
483        GLenum status;
484
485        glGenTextures(1, &tex);
486        glBindTexture(GL_TEXTURE_2D, tex);
487        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
488        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
489        glTexImage2D(GL_TEXTURE_2D, 0, internalformat, 1, 1, 0,
490                     format, type, NULL);
491
492        glGenFramebuffers(1, &fbo);
493        glBindFramebuffer(GL_FRAMEBUFFER, fbo);
494        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
495                               GL_TEXTURE_2D, tex, 0);
496        status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
497        if (status != GL_FRAMEBUFFER_COMPLETE) {
498            ErrorF("glamor: Test fbo for depth %d incomplete.  "
499                   "Falling back to software.\n", depth);
500            glDeleteTextures(1, &tex);
501            glDeleteFramebuffers(1, &fbo);
502            return;
503        }
504
505        glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &read_format);
506        glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &read_type);
507
508        glDeleteTextures(1, &tex);
509        glDeleteFramebuffers(1, &fbo);
510
511        if (format != read_format || type != read_type) {
512            ErrorF("glamor: Implementation returned 0x%x/0x%x read format/type "
513                   "for depth %d, expected 0x%x/0x%x.  "
514                   "Falling back to software.\n",
515                   read_format, read_type, depth, format, type);
516            return;
517        }
518    }
519
520    f->depth = depth;
521    f->render_format = render_format;
522    f->internalformat = internalformat;
523    f->format = format;
524    f->type = type;
525    f->rendering_supported = rendering_supported;
526}
527
528/* Set up the GL format/types that glamor will use for the various depths
529 *
530 * X11's pixel data doesn't have channels, but to store our data in GL
531 * we have to pick some sort of format to move X11 pixel data in and
532 * out with in glamor_transfer.c.  For X11 core operations, other than
533 * GL logic ops (non-GXcopy GC ops) what the driver chooses internally
534 * doesn't matter as long as it doesn't drop any bits (we expect them
535 * to generally expand, if anything).  For Render, we can expect
536 * clients to tend to render with PictFormats matching our channel
537 * layouts here since ultimately X11 pixels tend to end up on the
538 * screen.  The render implementation will fall back to fb if the
539 * channels don't match.
540 *
541 * Note that these formats don't affect what glamor_egl.c or
542 * Xwayland's EGL layer choose for surfaces exposed through DRI or
543 * scanout.  For now, those layers need to match what we're choosing
544 * here, or channels will end up swizzled around.  Similarly, the
545 * driver's visual masks also need to match what we're doing here.
546 */
547static void
548glamor_setup_formats(ScreenPtr screen)
549{
550    glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
551
552    /* Prefer r8 textures since they're required by GLES3 and core,
553     * only falling back to a8 if we can't do them.
554     */
555    if (glamor_priv->is_gles || epoxy_has_gl_extension("GL_ARB_texture_rg")) {
556        glamor_add_format(screen, 1, PICT_a1,
557                          GL_R8, GL_RED, GL_UNSIGNED_BYTE, FALSE);
558        glamor_add_format(screen, 8, PICT_a8,
559                          GL_R8, GL_RED, GL_UNSIGNED_BYTE, TRUE);
560    } else {
561        glamor_add_format(screen, 1, PICT_a1,
562                          GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE, FALSE);
563        glamor_add_format(screen, 8, PICT_a8,
564                          GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE, TRUE);
565    }
566
567    if (glamor_priv->is_gles) {
568        /* For 15bpp, GLES supports format/type RGBA/5551, rather than
569         * bgra/1555_rev.  GL_EXT_bgra lets the impl say the color
570         * read format/type is bgra/1555 even if we had to create it
571         * with rgba/5551, with Mesa does.  That means we can't use
572         * the same format/type for TexSubImage and readpixels.
573         *
574         * Instead, just store 16 bits using the trusted 565 path, and
575         * disable render accel for now.
576         */
577        glamor_add_format(screen, 15, PICT_x1r5g5b5,
578                          GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, TRUE);
579    } else {
580        glamor_add_format(screen, 15, PICT_x1r5g5b5,
581                          GL_RGBA, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, TRUE);
582    }
583
584    glamor_add_format(screen, 16, PICT_r5g6b5,
585                      GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, TRUE);
586
587    if (glamor_priv->is_gles) {
588        assert(X_BYTE_ORDER == X_LITTLE_ENDIAN);
589        glamor_add_format(screen, 24, PICT_x8r8g8b8,
590                          GL_BGRA, GL_BGRA, GL_UNSIGNED_BYTE, TRUE);
591        glamor_add_format(screen, 32, PICT_a8r8g8b8,
592                          GL_BGRA, GL_BGRA, GL_UNSIGNED_BYTE, TRUE);
593    } else {
594        glamor_add_format(screen, 24, PICT_x8r8g8b8,
595                          GL_RGBA, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, TRUE);
596        glamor_add_format(screen, 32, PICT_a8r8g8b8,
597                          GL_RGBA, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, TRUE);
598    }
599
600    if (glamor_priv->is_gles) {
601        glamor_add_format(screen, 30, PICT_x2b10g10r10,
602                          GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, TRUE);
603    } else {
604        glamor_add_format(screen, 30, PICT_x2r10g10b10,
605                          GL_RGB10_A2, GL_BGRA, GL_UNSIGNED_INT_2_10_10_10_REV, TRUE);
606    }
607
608    glamor_priv->cbcr_format.depth = 16;
609    glamor_priv->cbcr_format.internalformat = GL_RG8;
610    glamor_priv->cbcr_format.format = GL_RG;
611    glamor_priv->cbcr_format.type = GL_UNSIGNED_BYTE;
612    glamor_priv->cbcr_format.rendering_supported = TRUE;
613}
614
615/** Set up glamor for an already-configured GL context. */
616Bool
617glamor_init(ScreenPtr screen, unsigned int flags)
618{
619    glamor_screen_private *glamor_priv;
620    int gl_version;
621    int glsl_major, glsl_minor;
622    int max_viewport_size[2];
623    const char *shading_version_string;
624    int shading_version_offset;
625
626    PictureScreenPtr ps = GetPictureScreenIfSet(screen);
627
628    if (flags & ~GLAMOR_VALID_FLAGS) {
629        ErrorF("glamor_init: Invalid flags %x\n", flags);
630        return FALSE;
631    }
632    glamor_priv = calloc(1, sizeof(*glamor_priv));
633    if (glamor_priv == NULL)
634        return FALSE;
635
636    glamor_priv->flags = flags;
637
638    if (!dixRegisterPrivateKey(&glamor_screen_private_key, PRIVATE_SCREEN, 0)) {
639        LogMessage(X_WARNING,
640                   "glamor%d: Failed to allocate screen private\n",
641                   screen->myNum);
642        goto free_glamor_private;
643    }
644
645    glamor_set_screen_private(screen, glamor_priv);
646
647    if (!dixRegisterPrivateKey(&glamor_pixmap_private_key, PRIVATE_PIXMAP,
648                               sizeof(struct glamor_pixmap_private))) {
649        LogMessage(X_WARNING,
650                   "glamor%d: Failed to allocate pixmap private\n",
651                   screen->myNum);
652        goto free_glamor_private;
653    }
654
655    if (!dixRegisterPrivateKey(&glamor_gc_private_key, PRIVATE_GC,
656                               sizeof (glamor_gc_private))) {
657        LogMessage(X_WARNING,
658                   "glamor%d: Failed to allocate gc private\n",
659                   screen->myNum);
660        goto free_glamor_private;
661    }
662
663    glamor_priv->saved_procs.close_screen = screen->CloseScreen;
664    screen->CloseScreen = glamor_close_screen;
665
666    glamor_priv->saved_procs.destroy_pixmap = screen->DestroyPixmap;
667    screen->DestroyPixmap = glamor_destroy_pixmap;
668
669    /* If we are using egl screen, call egl screen init to
670     * register correct close screen function. */
671    if (flags & GLAMOR_USE_EGL_SCREEN) {
672        glamor_egl_screen_init(screen, &glamor_priv->ctx);
673    } else {
674        if (!glamor_glx_screen_init(&glamor_priv->ctx))
675            goto fail;
676    }
677
678    glamor_make_current(glamor_priv);
679
680    if (!epoxy_is_desktop_gl())
681        glamor_priv->is_gles = TRUE;
682
683    gl_version = epoxy_gl_version();
684
685    /* assume a core profile if we are GL 3.1 and don't have ARB_compatibility */
686    glamor_priv->is_core_profile =
687        gl_version >= 31 && !epoxy_has_gl_extension("GL_ARB_compatibility");
688
689    shading_version_string = (char *) glGetString(GL_SHADING_LANGUAGE_VERSION);
690
691    if (!shading_version_string) {
692        LogMessage(X_WARNING,
693                   "glamor%d: Failed to get GLSL version\n",
694                   screen->myNum);
695        goto fail;
696    }
697
698    shading_version_offset = 0;
699    if (strncmp("OpenGL ES GLSL ES ", shading_version_string, 18) == 0)
700        shading_version_offset = 18;
701
702    if (sscanf(shading_version_string + shading_version_offset,
703               "%i.%i",
704               &glsl_major,
705               &glsl_minor) != 2) {
706        LogMessage(X_WARNING,
707                   "glamor%d: Failed to parse GLSL version string %s\n",
708                   screen->myNum, shading_version_string);
709        goto fail;
710    }
711    glamor_priv->glsl_version = glsl_major * 100 + glsl_minor;
712
713    if (glamor_priv->is_gles) {
714        /* Force us back to the base version of our programs on an ES
715         * context, anyway.  Basically glamor only uses desktop 1.20
716         * or 1.30 currently.  1.30's new features are also present in
717         * ES 3.0, but our glamor_program.c constructions use a lot of
718         * compatibility features (to reduce the diff between 1.20 and
719         * 1.30 programs).
720         */
721        glamor_priv->glsl_version = 120;
722    }
723
724    /* We'd like to require GL_ARB_map_buffer_range or
725     * GL_OES_map_buffer_range, since it offers more information to
726     * the driver than plain old glMapBuffer() or glBufferSubData().
727     * It's been supported on Mesa on the desktop since 2009 and on
728     * GLES2 since October 2012.  It's supported on Apple's iOS
729     * drivers for SGX535 and A7, but apparently not on most Android
730     * devices (the OES extension spec wasn't released until June
731     * 2012).
732     *
733     * 82% of 0 A.D. players (desktop GL) submitting hardware reports
734     * have support for it, with most of the ones lacking it being on
735     * Windows with Intel 4-series (G45) graphics or older.
736     */
737    if (!glamor_priv->is_gles) {
738        if (gl_version < 21) {
739            ErrorF("Require OpenGL version 2.1 or later.\n");
740            goto fail;
741        }
742
743        if (!glamor_priv->is_core_profile &&
744            !epoxy_has_gl_extension("GL_ARB_texture_border_clamp")) {
745            ErrorF("GL_ARB_texture_border_clamp required\n");
746            goto fail;
747        }
748
749        if (!glamor_check_instruction_count(gl_version))
750            goto fail;
751
752        /* Glamor rendering assumes that platforms with GLSL 130+
753         * have instanced arrays, but this is not always the case.
754         * etnaviv offers GLSL 140 with OpenGL 2.1.
755         */
756        if (glamor_glsl_has_ints(glamor_priv) &&
757            !epoxy_has_gl_extension("GL_ARB_instanced_arrays"))
758                glamor_priv->glsl_version = 120;
759    } else {
760        if (gl_version < 20) {
761            ErrorF("Require Open GLES2.0 or later.\n");
762            goto fail;
763        }
764
765        if (!epoxy_has_gl_extension("GL_EXT_texture_format_BGRA8888")) {
766            ErrorF("GL_EXT_texture_format_BGRA8888 required\n");
767            goto fail;
768        }
769
770        if (!epoxy_has_gl_extension("GL_OES_texture_border_clamp")) {
771            ErrorF("GL_OES_texture_border_clamp required\n");
772            goto fail;
773        }
774    }
775
776    if (!epoxy_has_gl_extension("GL_ARB_vertex_array_object") &&
777        !epoxy_has_gl_extension("GL_OES_vertex_array_object")) {
778        ErrorF("GL_{ARB,OES}_vertex_array_object required\n");
779        goto fail;
780    }
781
782    if (!glamor_priv->is_gles && glamor_priv->glsl_version == 120 &&
783        epoxy_has_gl_extension("GL_ARB_instanced_arrays"))
784        glamor_priv->use_gpu_shader4 = epoxy_has_gl_extension("GL_EXT_gpu_shader4");
785
786    glamor_priv->has_rw_pbo = FALSE;
787    if (!glamor_priv->is_gles)
788        glamor_priv->has_rw_pbo = TRUE;
789
790    glamor_priv->has_khr_debug = epoxy_has_gl_extension("GL_KHR_debug");
791    glamor_priv->has_pack_invert =
792        epoxy_has_gl_extension("GL_MESA_pack_invert");
793    glamor_priv->has_fbo_blit =
794        epoxy_has_gl_extension("GL_EXT_framebuffer_blit");
795    glamor_priv->has_map_buffer_range =
796        epoxy_has_gl_extension("GL_ARB_map_buffer_range") ||
797        epoxy_has_gl_extension("GL_EXT_map_buffer_range");
798    glamor_priv->has_buffer_storage =
799        epoxy_has_gl_extension("GL_ARB_buffer_storage");
800    glamor_priv->has_mesa_tile_raster_order =
801        epoxy_has_gl_extension("GL_MESA_tile_raster_order");
802    glamor_priv->has_nv_texture_barrier =
803        epoxy_has_gl_extension("GL_NV_texture_barrier");
804    glamor_priv->has_unpack_subimage =
805        !glamor_priv->is_gles ||
806        epoxy_gl_version() >= 30 ||
807        epoxy_has_gl_extension("GL_EXT_unpack_subimage");
808    glamor_priv->has_pack_subimage =
809        !glamor_priv->is_gles ||
810        epoxy_gl_version() >= 30 ||
811        epoxy_has_gl_extension("GL_NV_pack_subimage");
812    glamor_priv->has_dual_blend =
813        glamor_glsl_has_ints(glamor_priv) &&
814        epoxy_has_gl_extension("GL_ARB_blend_func_extended");
815    glamor_priv->has_clear_texture =
816        epoxy_gl_version() >= 44 ||
817        epoxy_has_gl_extension("GL_ARB_clear_texture");
818
819    glamor_priv->can_copyplane = (gl_version >= 30);
820
821    glamor_setup_debug_output(screen);
822
823    glamor_priv->use_quads = !glamor_priv->is_gles &&
824                             !glamor_priv->is_core_profile;
825
826    /* Driver-specific hack: Avoid using GL_QUADS on VC4, where
827     * they'll be emulated more expensively than we can with our
828     * cached IB.
829     */
830    if (strstr((char *)glGetString(GL_VENDOR), "Broadcom") &&
831        (strstr((char *)glGetString(GL_RENDERER), "VC4") ||
832         strstr((char *)glGetString(GL_RENDERER), "V3D")))
833        glamor_priv->use_quads = FALSE;
834
835    glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, &glamor_priv->max_fbo_size);
836    glGetIntegerv(GL_MAX_TEXTURE_SIZE, &glamor_priv->max_fbo_size);
837    glGetIntegerv(GL_MAX_VIEWPORT_DIMS, max_viewport_size);
838    glamor_priv->max_fbo_size = MIN(glamor_priv->max_fbo_size, max_viewport_size[0]);
839    glamor_priv->max_fbo_size = MIN(glamor_priv->max_fbo_size, max_viewport_size[1]);
840#ifdef MAX_FBO_SIZE
841    glamor_priv->max_fbo_size = MAX_FBO_SIZE;
842#endif
843
844    glamor_priv->has_texture_swizzle =
845        (epoxy_has_gl_extension("GL_ARB_texture_swizzle") ||
846         (glamor_priv->is_gles && gl_version >= 30));
847
848    glamor_setup_formats(screen);
849
850    glamor_set_debug_level(&glamor_debug_level);
851
852    if (!glamor_font_init(screen))
853        goto fail;
854
855    glamor_priv->saved_procs.block_handler = screen->BlockHandler;
856    screen->BlockHandler = _glamor_block_handler;
857
858    if (!glamor_composite_glyphs_init(screen)) {
859        ErrorF("Failed to initialize composite masks\n");
860        goto fail;
861    }
862
863    glamor_priv->saved_procs.create_gc = screen->CreateGC;
864    screen->CreateGC = glamor_create_gc;
865
866    glamor_priv->saved_procs.create_pixmap = screen->CreatePixmap;
867    screen->CreatePixmap = glamor_create_pixmap;
868
869    glamor_priv->saved_procs.get_spans = screen->GetSpans;
870    screen->GetSpans = glamor_get_spans;
871
872    glamor_priv->saved_procs.get_image = screen->GetImage;
873    screen->GetImage = glamor_get_image;
874
875    glamor_priv->saved_procs.change_window_attributes =
876        screen->ChangeWindowAttributes;
877    screen->ChangeWindowAttributes = glamor_change_window_attributes;
878
879    glamor_priv->saved_procs.copy_window = screen->CopyWindow;
880    screen->CopyWindow = glamor_copy_window;
881
882    glamor_priv->saved_procs.bitmap_to_region = screen->BitmapToRegion;
883    screen->BitmapToRegion = glamor_bitmap_to_region;
884
885    glamor_priv->saved_procs.composite = ps->Composite;
886    ps->Composite = glamor_composite;
887
888    glamor_priv->saved_procs.trapezoids = ps->Trapezoids;
889    ps->Trapezoids = glamor_trapezoids;
890
891    glamor_priv->saved_procs.triangles = ps->Triangles;
892    ps->Triangles = glamor_triangles;
893
894    glamor_priv->saved_procs.addtraps = ps->AddTraps;
895    ps->AddTraps = glamor_add_traps;
896
897    glamor_priv->saved_procs.composite_rects = ps->CompositeRects;
898    ps->CompositeRects = glamor_composite_rectangles;
899
900    glamor_priv->saved_procs.glyphs = ps->Glyphs;
901    ps->Glyphs = glamor_composite_glyphs;
902
903    glamor_init_vbo(screen);
904    glamor_init_gradient_shader(screen);
905    glamor_pixmap_init(screen);
906    glamor_sync_init(screen);
907
908    glamor_priv->screen = screen;
909
910    return TRUE;
911
912 fail:
913    /* Restore default CloseScreen and DestroyPixmap handlers */
914    screen->CloseScreen = glamor_priv->saved_procs.close_screen;
915    screen->DestroyPixmap = glamor_priv->saved_procs.destroy_pixmap;
916
917 free_glamor_private:
918    free(glamor_priv);
919    glamor_set_screen_private(screen, NULL);
920    return FALSE;
921}
922
923static void
924glamor_release_screen_priv(ScreenPtr screen)
925{
926    glamor_screen_private *glamor_priv;
927
928    glamor_priv = glamor_get_screen_private(screen);
929    glamor_fini_vbo(screen);
930    glamor_pixmap_fini(screen);
931    free(glamor_priv);
932
933    glamor_set_screen_private(screen, NULL);
934}
935
936Bool
937glamor_close_screen(ScreenPtr screen)
938{
939    glamor_screen_private *glamor_priv;
940    PixmapPtr screen_pixmap;
941    PictureScreenPtr ps = GetPictureScreenIfSet(screen);
942
943    glamor_priv = glamor_get_screen_private(screen);
944    glamor_sync_close(screen);
945    glamor_composite_glyphs_fini(screen);
946    screen->CloseScreen = glamor_priv->saved_procs.close_screen;
947
948    screen->CreateGC = glamor_priv->saved_procs.create_gc;
949    screen->CreatePixmap = glamor_priv->saved_procs.create_pixmap;
950    screen->DestroyPixmap = glamor_priv->saved_procs.destroy_pixmap;
951    screen->GetSpans = glamor_priv->saved_procs.get_spans;
952    screen->ChangeWindowAttributes =
953        glamor_priv->saved_procs.change_window_attributes;
954    screen->CopyWindow = glamor_priv->saved_procs.copy_window;
955    screen->BitmapToRegion = glamor_priv->saved_procs.bitmap_to_region;
956    screen->BlockHandler = glamor_priv->saved_procs.block_handler;
957
958    ps->Composite = glamor_priv->saved_procs.composite;
959    ps->Trapezoids = glamor_priv->saved_procs.trapezoids;
960    ps->Triangles = glamor_priv->saved_procs.triangles;
961    ps->CompositeRects = glamor_priv->saved_procs.composite_rects;
962    ps->Glyphs = glamor_priv->saved_procs.glyphs;
963
964    screen_pixmap = screen->GetScreenPixmap(screen);
965    glamor_pixmap_destroy_fbo(screen_pixmap);
966
967    glamor_release_screen_priv(screen);
968
969    return screen->CloseScreen(screen);
970}
971
972void
973glamor_fini(ScreenPtr screen)
974{
975    /* Do nothing currently. */
976}
977
978void
979glamor_enable_dri3(ScreenPtr screen)
980{
981    glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
982
983    glamor_priv->dri3_enabled = TRUE;
984}
985
986Bool
987glamor_supports_pixmap_import_export(ScreenPtr screen)
988{
989    glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
990
991    return glamor_priv->dri3_enabled;
992}
993
994_X_EXPORT void
995glamor_set_drawable_modifiers_func(ScreenPtr screen,
996                                   GetDrawableModifiersFuncPtr func)
997{
998    glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
999
1000    glamor_priv->get_drawable_modifiers = func;
1001}
1002
1003_X_EXPORT Bool
1004glamor_get_drawable_modifiers(DrawablePtr draw, uint32_t format,
1005                              uint32_t *num_modifiers, uint64_t **modifiers)
1006{
1007    struct glamor_screen_private *glamor_priv =
1008        glamor_get_screen_private(draw->pScreen);
1009
1010    if (glamor_priv->get_drawable_modifiers) {
1011        return glamor_priv->get_drawable_modifiers(draw, format,
1012                                                   num_modifiers, modifiers);
1013    }
1014    *num_modifiers = 0;
1015    *modifiers = NULL;
1016    return TRUE;
1017}
1018
1019static int
1020_glamor_fds_from_pixmap(ScreenPtr screen, PixmapPtr pixmap, int *fds,
1021                        uint32_t *strides, uint32_t *offsets,
1022                        CARD32 *size, uint64_t *modifier)
1023{
1024    glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap);
1025    glamor_screen_private *glamor_priv =
1026        glamor_get_screen_private(pixmap->drawable.pScreen);
1027
1028    if (!glamor_priv->dri3_enabled)
1029        return 0;
1030    switch (pixmap_priv->type) {
1031    case GLAMOR_TEXTURE_DRM:
1032    case GLAMOR_TEXTURE_ONLY:
1033        if (!glamor_pixmap_ensure_fbo(pixmap, 0))
1034            return 0;
1035
1036        if (modifier) {
1037            return glamor_egl_fds_from_pixmap(screen, pixmap, fds,
1038                                              strides, offsets,
1039                                              modifier);
1040        } else {
1041            CARD16 stride;
1042
1043            fds[0] = glamor_egl_fd_from_pixmap(screen, pixmap, &stride, size);
1044            strides[0] = stride;
1045
1046            return fds[0] >= 0;
1047        }
1048    default:
1049        break;
1050    }
1051    return 0;
1052}
1053
1054_X_EXPORT int
1055glamor_fds_from_pixmap(ScreenPtr screen, PixmapPtr pixmap, int *fds,
1056                       uint32_t *strides, uint32_t *offsets,
1057                       uint64_t *modifier)
1058{
1059    return _glamor_fds_from_pixmap(screen, pixmap, fds, strides, offsets,
1060                                   NULL, modifier);
1061}
1062
1063_X_EXPORT int
1064glamor_fd_from_pixmap(ScreenPtr screen,
1065                      PixmapPtr pixmap, CARD16 *stride, CARD32 *size)
1066{
1067    int fd;
1068    int ret;
1069    uint32_t stride32;
1070
1071    ret = _glamor_fds_from_pixmap(screen, pixmap, &fd, &stride32, NULL, size,
1072                                  NULL);
1073    if (ret != 1)
1074        return -1;
1075
1076    *stride = stride32;
1077    return fd;
1078}
1079
1080_X_EXPORT int
1081glamor_shareable_fd_from_pixmap(ScreenPtr screen,
1082                                PixmapPtr pixmap, CARD16 *stride, CARD32 *size)
1083{
1084    unsigned orig_usage_hint = pixmap->usage_hint;
1085    int ret;
1086
1087    /*
1088     * The actual difference between a shareable and non-shareable buffer
1089     * is decided 4 call levels deep in glamor_make_pixmap_exportable()
1090     * based on pixmap->usage_hint == CREATE_PIXMAP_USAGE_SHARED
1091     * 2 of those calls are also exported API, so we cannot just add a flag.
1092     */
1093    pixmap->usage_hint = CREATE_PIXMAP_USAGE_SHARED;
1094
1095    ret = glamor_fd_from_pixmap(screen, pixmap, stride, size);
1096
1097    pixmap->usage_hint = orig_usage_hint;
1098    return ret;
1099}
1100
1101int
1102glamor_name_from_pixmap(PixmapPtr pixmap, CARD16 *stride, CARD32 *size)
1103{
1104    glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap);
1105
1106    switch (pixmap_priv->type) {
1107    case GLAMOR_TEXTURE_DRM:
1108    case GLAMOR_TEXTURE_ONLY:
1109        if (!glamor_pixmap_ensure_fbo(pixmap, 0))
1110            return -1;
1111        return glamor_egl_fd_name_from_pixmap(pixmap->drawable.pScreen,
1112                                              pixmap, stride, size);
1113    default:
1114        break;
1115    }
1116    return -1;
1117}
1118
1119void
1120glamor_finish(ScreenPtr screen)
1121{
1122    glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
1123
1124    glamor_make_current(glamor_priv);
1125    glFinish();
1126}
1127