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