xref: /aosp_15_r20/external/mesa3d/src/glx/driwindows_glx.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker  * Copyright © 2014 Jon Turney
3*61046927SAndroid Build Coastguard Worker  *
4*61046927SAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining a
5*61046927SAndroid Build Coastguard Worker  * copy of this software and associated documentation files (the "Software"),
6*61046927SAndroid Build Coastguard Worker  * to deal in the Software without restriction, including without limitation
7*61046927SAndroid Build Coastguard Worker  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8*61046927SAndroid Build Coastguard Worker  * and/or sell copies of the Software, and to permit persons to whom the
9*61046927SAndroid Build Coastguard Worker  * Software is furnished to do so, subject to the following conditions:
10*61046927SAndroid Build Coastguard Worker  *
11*61046927SAndroid Build Coastguard Worker  * The above copyright notice and this permission notice (including the next
12*61046927SAndroid Build Coastguard Worker  * paragraph) shall be included in all copies or substantial portions of the
13*61046927SAndroid Build Coastguard Worker  * Software.
14*61046927SAndroid Build Coastguard Worker  *
15*61046927SAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16*61046927SAndroid Build Coastguard Worker  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17*61046927SAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18*61046927SAndroid Build Coastguard Worker  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19*61046927SAndroid Build Coastguard Worker  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20*61046927SAndroid Build Coastguard Worker  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21*61046927SAndroid Build Coastguard Worker  * IN THE SOFTWARE.
22*61046927SAndroid Build Coastguard Worker  */
23*61046927SAndroid Build Coastguard Worker 
24*61046927SAndroid Build Coastguard Worker #include "glxclient.h"
25*61046927SAndroid Build Coastguard Worker #include "glx_error.h"
26*61046927SAndroid Build Coastguard Worker #include "dri_common.h"
27*61046927SAndroid Build Coastguard Worker #include "util/macros.h"
28*61046927SAndroid Build Coastguard Worker #include "windows/xwindowsdri.h"
29*61046927SAndroid Build Coastguard Worker #include "windows/windowsgl.h"
30*61046927SAndroid Build Coastguard Worker 
31*61046927SAndroid Build Coastguard Worker struct driwindows_context
32*61046927SAndroid Build Coastguard Worker {
33*61046927SAndroid Build Coastguard Worker    struct glx_context base;
34*61046927SAndroid Build Coastguard Worker    windowsContext *windowsContext;
35*61046927SAndroid Build Coastguard Worker };
36*61046927SAndroid Build Coastguard Worker 
37*61046927SAndroid Build Coastguard Worker struct driwindows_config
38*61046927SAndroid Build Coastguard Worker {
39*61046927SAndroid Build Coastguard Worker    struct glx_config base;
40*61046927SAndroid Build Coastguard Worker    int pxfi;
41*61046927SAndroid Build Coastguard Worker };
42*61046927SAndroid Build Coastguard Worker 
43*61046927SAndroid Build Coastguard Worker struct driwindows_screen
44*61046927SAndroid Build Coastguard Worker {
45*61046927SAndroid Build Coastguard Worker    struct glx_screen base;
46*61046927SAndroid Build Coastguard Worker    __DRIscreen *driScreen;
47*61046927SAndroid Build Coastguard Worker    int event_base;
48*61046927SAndroid Build Coastguard Worker    Bool copySubBuffer;
49*61046927SAndroid Build Coastguard Worker };
50*61046927SAndroid Build Coastguard Worker 
51*61046927SAndroid Build Coastguard Worker struct driwindows_drawable
52*61046927SAndroid Build Coastguard Worker {
53*61046927SAndroid Build Coastguard Worker    __GLXDRIdrawable base;
54*61046927SAndroid Build Coastguard Worker    windowsDrawable *windowsDrawable;
55*61046927SAndroid Build Coastguard Worker };
56*61046927SAndroid Build Coastguard Worker 
57*61046927SAndroid Build Coastguard Worker /**
58*61046927SAndroid Build Coastguard Worker  * GLXDRI functions
59*61046927SAndroid Build Coastguard Worker  */
60*61046927SAndroid Build Coastguard Worker 
61*61046927SAndroid Build Coastguard Worker static void
driwindows_destroy_context(struct glx_context * context)62*61046927SAndroid Build Coastguard Worker driwindows_destroy_context(struct glx_context *context)
63*61046927SAndroid Build Coastguard Worker {
64*61046927SAndroid Build Coastguard Worker    struct driwindows_context *pcp = (struct driwindows_context *) context;
65*61046927SAndroid Build Coastguard Worker 
66*61046927SAndroid Build Coastguard Worker    driReleaseDrawables(&pcp->base);
67*61046927SAndroid Build Coastguard Worker 
68*61046927SAndroid Build Coastguard Worker    free((char *) context->extensions);
69*61046927SAndroid Build Coastguard Worker 
70*61046927SAndroid Build Coastguard Worker    windows_destroy_context(pcp->windowsContext);
71*61046927SAndroid Build Coastguard Worker 
72*61046927SAndroid Build Coastguard Worker    free(pcp);
73*61046927SAndroid Build Coastguard Worker }
74*61046927SAndroid Build Coastguard Worker 
75*61046927SAndroid Build Coastguard Worker static int
driwindows_bind_context(struct glx_context * context,GLXDrawable draw,GLXDrawable read)76*61046927SAndroid Build Coastguard Worker driwindows_bind_context(struct glx_context *context, GLXDrawable draw, GLXDrawable read)
77*61046927SAndroid Build Coastguard Worker {
78*61046927SAndroid Build Coastguard Worker    struct driwindows_context *pcp = (struct driwindows_context *) context;
79*61046927SAndroid Build Coastguard Worker    struct driwindows_drawable *pdraw, *pread;
80*61046927SAndroid Build Coastguard Worker 
81*61046927SAndroid Build Coastguard Worker    pdraw = (struct driwindows_drawable *) driFetchDrawable(context, draw);
82*61046927SAndroid Build Coastguard Worker    pread = (struct driwindows_drawable *) driFetchDrawable(context, read);
83*61046927SAndroid Build Coastguard Worker 
84*61046927SAndroid Build Coastguard Worker    driReleaseDrawables(&pcp->base);
85*61046927SAndroid Build Coastguard Worker 
86*61046927SAndroid Build Coastguard Worker    if (pdraw == NULL || pread == NULL)
87*61046927SAndroid Build Coastguard Worker       return GLXBadDrawable;
88*61046927SAndroid Build Coastguard Worker 
89*61046927SAndroid Build Coastguard Worker    if (windows_bind_context(pcp->windowsContext,
90*61046927SAndroid Build Coastguard Worker                            pdraw->windowsDrawable, pread->windowsDrawable))
91*61046927SAndroid Build Coastguard Worker       return Success;
92*61046927SAndroid Build Coastguard Worker 
93*61046927SAndroid Build Coastguard Worker    return GLXBadContext;
94*61046927SAndroid Build Coastguard Worker }
95*61046927SAndroid Build Coastguard Worker 
96*61046927SAndroid Build Coastguard Worker static void
driwindows_unbind_context(struct glx_context * context)97*61046927SAndroid Build Coastguard Worker driwindows_unbind_context(struct glx_context *context)
98*61046927SAndroid Build Coastguard Worker {
99*61046927SAndroid Build Coastguard Worker    struct driwindows_context *pcp = (struct driwindows_context *) context;
100*61046927SAndroid Build Coastguard Worker 
101*61046927SAndroid Build Coastguard Worker    windows_unbind_context(pcp->windowsContext);
102*61046927SAndroid Build Coastguard Worker }
103*61046927SAndroid Build Coastguard Worker 
104*61046927SAndroid Build Coastguard Worker static const struct glx_context_vtable driwindows_context_vtable = {
105*61046927SAndroid Build Coastguard Worker    .destroy             = driwindows_destroy_context,
106*61046927SAndroid Build Coastguard Worker    .bind                = driwindows_bind_context,
107*61046927SAndroid Build Coastguard Worker    .unbind              = driwindows_unbind_context,
108*61046927SAndroid Build Coastguard Worker    .wait_gl             = NULL,
109*61046927SAndroid Build Coastguard Worker    .wait_x              = NULL,
110*61046927SAndroid Build Coastguard Worker };
111*61046927SAndroid Build Coastguard Worker 
112*61046927SAndroid Build Coastguard Worker static struct glx_context *
driwindows_create_context(struct glx_screen * base,struct glx_config * config_base,struct glx_context * shareList,int renderType)113*61046927SAndroid Build Coastguard Worker driwindows_create_context(struct glx_screen *base,
114*61046927SAndroid Build Coastguard Worker                           struct glx_config *config_base,
115*61046927SAndroid Build Coastguard Worker                           struct glx_context *shareList, int renderType)
116*61046927SAndroid Build Coastguard Worker {
117*61046927SAndroid Build Coastguard Worker    struct driwindows_context *pcp, *pcp_shared;
118*61046927SAndroid Build Coastguard Worker    struct driwindows_config *config = (struct driwindows_config *) config_base;
119*61046927SAndroid Build Coastguard Worker    struct driwindows_screen *psc = (struct driwindows_screen *) base;
120*61046927SAndroid Build Coastguard Worker    windowsContext *shared = NULL;
121*61046927SAndroid Build Coastguard Worker 
122*61046927SAndroid Build Coastguard Worker    if (!psc->base.driScreen)
123*61046927SAndroid Build Coastguard Worker       return NULL;
124*61046927SAndroid Build Coastguard Worker 
125*61046927SAndroid Build Coastguard Worker    /* Check the renderType value */
126*61046927SAndroid Build Coastguard Worker    if (!validate_renderType_against_config(config_base, renderType))
127*61046927SAndroid Build Coastguard Worker        return NULL;
128*61046927SAndroid Build Coastguard Worker 
129*61046927SAndroid Build Coastguard Worker    if (shareList) {
130*61046927SAndroid Build Coastguard Worker       /* If the shareList context is not on this renderer, we cannot possibly
131*61046927SAndroid Build Coastguard Worker        * create a context that shares with it.
132*61046927SAndroid Build Coastguard Worker        */
133*61046927SAndroid Build Coastguard Worker       if (shareList->vtable->destroy != driwindows_destroy_context) {
134*61046927SAndroid Build Coastguard Worker          return NULL;
135*61046927SAndroid Build Coastguard Worker       }
136*61046927SAndroid Build Coastguard Worker 
137*61046927SAndroid Build Coastguard Worker       pcp_shared = (struct driwindows_context *) shareList;
138*61046927SAndroid Build Coastguard Worker       shared = pcp_shared->windowsContext;
139*61046927SAndroid Build Coastguard Worker    }
140*61046927SAndroid Build Coastguard Worker 
141*61046927SAndroid Build Coastguard Worker    pcp = calloc(1, sizeof *pcp);
142*61046927SAndroid Build Coastguard Worker    if (pcp == NULL)
143*61046927SAndroid Build Coastguard Worker       return NULL;
144*61046927SAndroid Build Coastguard Worker 
145*61046927SAndroid Build Coastguard Worker    if (!glx_context_init(&pcp->base, &psc->base, &config->base)) {
146*61046927SAndroid Build Coastguard Worker       free(pcp);
147*61046927SAndroid Build Coastguard Worker       return NULL;
148*61046927SAndroid Build Coastguard Worker    }
149*61046927SAndroid Build Coastguard Worker 
150*61046927SAndroid Build Coastguard Worker    pcp->base.renderType = renderType;
151*61046927SAndroid Build Coastguard Worker 
152*61046927SAndroid Build Coastguard Worker    InfoMessageF("visualID %x, fbConfigID %x -> pxfi %d\n", config_base->visualID, config_base->fbconfigID, config->pxfi);
153*61046927SAndroid Build Coastguard Worker 
154*61046927SAndroid Build Coastguard Worker    pcp->windowsContext = windows_create_context(config->pxfi, shared);
155*61046927SAndroid Build Coastguard Worker 
156*61046927SAndroid Build Coastguard Worker    if (!pcp->windowsContext) {
157*61046927SAndroid Build Coastguard Worker       free(pcp);
158*61046927SAndroid Build Coastguard Worker       return NULL;
159*61046927SAndroid Build Coastguard Worker    }
160*61046927SAndroid Build Coastguard Worker 
161*61046927SAndroid Build Coastguard Worker    pcp->base.vtable = &driwindows_context_vtable;
162*61046927SAndroid Build Coastguard Worker 
163*61046927SAndroid Build Coastguard Worker    return &pcp->base;
164*61046927SAndroid Build Coastguard Worker }
165*61046927SAndroid Build Coastguard Worker 
166*61046927SAndroid Build Coastguard Worker static struct glx_context *
driwindows_create_context_attribs(struct glx_screen * base,struct glx_config * config_base,struct glx_context * shareList,unsigned num_attribs,const uint32_t * attribs,unsigned * error)167*61046927SAndroid Build Coastguard Worker driwindows_create_context_attribs(struct glx_screen *base,
168*61046927SAndroid Build Coastguard Worker                                   struct glx_config *config_base,
169*61046927SAndroid Build Coastguard Worker                                   struct glx_context *shareList,
170*61046927SAndroid Build Coastguard Worker                                   unsigned num_attribs,
171*61046927SAndroid Build Coastguard Worker                                   const uint32_t *attribs,
172*61046927SAndroid Build Coastguard Worker                                   unsigned *error)
173*61046927SAndroid Build Coastguard Worker {
174*61046927SAndroid Build Coastguard Worker    struct driwindows_context *pcp, *pcp_shared;
175*61046927SAndroid Build Coastguard Worker    struct driwindows_config *config = (struct driwindows_config *) config_base;
176*61046927SAndroid Build Coastguard Worker    struct driwindows_screen *psc = (struct driwindows_screen *) base;
177*61046927SAndroid Build Coastguard Worker    windowsContext *shared = NULL;
178*61046927SAndroid Build Coastguard Worker 
179*61046927SAndroid Build Coastguard Worker    int i;
180*61046927SAndroid Build Coastguard Worker    uint32_t renderType = GLX_RGBA_TYPE;
181*61046927SAndroid Build Coastguard Worker 
182*61046927SAndroid Build Coastguard Worker    /* Extract renderType from attribs */
183*61046927SAndroid Build Coastguard Worker    for (i = 0; i < num_attribs; i++) {
184*61046927SAndroid Build Coastguard Worker       switch (attribs[i * 2]) {
185*61046927SAndroid Build Coastguard Worker       case GLX_RENDER_TYPE:
186*61046927SAndroid Build Coastguard Worker          renderType = attribs[i * 2 + 1];
187*61046927SAndroid Build Coastguard Worker          break;
188*61046927SAndroid Build Coastguard Worker       }
189*61046927SAndroid Build Coastguard Worker    }
190*61046927SAndroid Build Coastguard Worker 
191*61046927SAndroid Build Coastguard Worker    /*
192*61046927SAndroid Build Coastguard Worker      Perhaps we should map GLX tokens to WGL tokens, but they appear to have
193*61046927SAndroid Build Coastguard Worker      identical values, so far
194*61046927SAndroid Build Coastguard Worker    */
195*61046927SAndroid Build Coastguard Worker 
196*61046927SAndroid Build Coastguard Worker    if (!psc->base.driScreen || !config_base)
197*61046927SAndroid Build Coastguard Worker       return NULL;
198*61046927SAndroid Build Coastguard Worker 
199*61046927SAndroid Build Coastguard Worker    /* Check the renderType value */
200*61046927SAndroid Build Coastguard Worker    if (!validate_renderType_against_config(config_base, renderType)) {
201*61046927SAndroid Build Coastguard Worker        return NULL;
202*61046927SAndroid Build Coastguard Worker    }
203*61046927SAndroid Build Coastguard Worker 
204*61046927SAndroid Build Coastguard Worker    if (shareList) {
205*61046927SAndroid Build Coastguard Worker       /* If the shareList context is not on this renderer, we cannot possibly
206*61046927SAndroid Build Coastguard Worker        * create a context that shares with it.
207*61046927SAndroid Build Coastguard Worker        */
208*61046927SAndroid Build Coastguard Worker       if (shareList->vtable->destroy != driwindows_destroy_context) {
209*61046927SAndroid Build Coastguard Worker          return NULL;
210*61046927SAndroid Build Coastguard Worker       }
211*61046927SAndroid Build Coastguard Worker 
212*61046927SAndroid Build Coastguard Worker       pcp_shared = (struct driwindows_context *) shareList;
213*61046927SAndroid Build Coastguard Worker       shared = pcp_shared->windowsContext;
214*61046927SAndroid Build Coastguard Worker    }
215*61046927SAndroid Build Coastguard Worker 
216*61046927SAndroid Build Coastguard Worker    pcp = calloc(1, sizeof *pcp);
217*61046927SAndroid Build Coastguard Worker    if (pcp == NULL)
218*61046927SAndroid Build Coastguard Worker       return NULL;
219*61046927SAndroid Build Coastguard Worker 
220*61046927SAndroid Build Coastguard Worker    if (!glx_context_init(&pcp->base, &psc->base, &config->base)) {
221*61046927SAndroid Build Coastguard Worker       free(pcp);
222*61046927SAndroid Build Coastguard Worker       return NULL;
223*61046927SAndroid Build Coastguard Worker    }
224*61046927SAndroid Build Coastguard Worker 
225*61046927SAndroid Build Coastguard Worker    pcp->base.renderType = renderType;
226*61046927SAndroid Build Coastguard Worker 
227*61046927SAndroid Build Coastguard Worker    InfoMessageF("visualID %x, fbConfigID %x -> pxfi %d\n", config_base->visualID, config_base->fbconfigID, config->pxfi);
228*61046927SAndroid Build Coastguard Worker 
229*61046927SAndroid Build Coastguard Worker    pcp->windowsContext = windows_create_context_attribs(config->pxfi,
230*61046927SAndroid Build Coastguard Worker                                                       shared,
231*61046927SAndroid Build Coastguard Worker                                                       (const int *)attribs);
232*61046927SAndroid Build Coastguard Worker    if (pcp->windowsContext == NULL) {
233*61046927SAndroid Build Coastguard Worker       free(pcp);
234*61046927SAndroid Build Coastguard Worker       return NULL;
235*61046927SAndroid Build Coastguard Worker    }
236*61046927SAndroid Build Coastguard Worker 
237*61046927SAndroid Build Coastguard Worker    pcp->base.vtable = &driwindows_context_vtable;
238*61046927SAndroid Build Coastguard Worker 
239*61046927SAndroid Build Coastguard Worker    return &pcp->base;
240*61046927SAndroid Build Coastguard Worker }
241*61046927SAndroid Build Coastguard Worker 
242*61046927SAndroid Build Coastguard Worker static void
driwindowsDestroyDrawable(__GLXDRIdrawable * pdraw)243*61046927SAndroid Build Coastguard Worker driwindowsDestroyDrawable(__GLXDRIdrawable * pdraw)
244*61046927SAndroid Build Coastguard Worker {
245*61046927SAndroid Build Coastguard Worker    struct driwindows_drawable *pdp = (struct driwindows_drawable *) pdraw;
246*61046927SAndroid Build Coastguard Worker 
247*61046927SAndroid Build Coastguard Worker    windows_destroy_drawable(pdp->windowsDrawable);
248*61046927SAndroid Build Coastguard Worker 
249*61046927SAndroid Build Coastguard Worker    free(pdp);
250*61046927SAndroid Build Coastguard Worker }
251*61046927SAndroid Build Coastguard Worker 
252*61046927SAndroid Build Coastguard Worker static __GLXDRIdrawable *
driwindowsCreateDrawable(struct glx_screen * base,XID xDrawable,GLXDrawable drawable,int type,struct glx_config * modes)253*61046927SAndroid Build Coastguard Worker driwindowsCreateDrawable(struct glx_screen *base, XID xDrawable,
254*61046927SAndroid Build Coastguard Worker                          GLXDrawable drawable, int type,
255*61046927SAndroid Build Coastguard Worker                          struct glx_config *modes)
256*61046927SAndroid Build Coastguard Worker {
257*61046927SAndroid Build Coastguard Worker    struct driwindows_drawable *pdp;
258*61046927SAndroid Build Coastguard Worker    struct driwindows_screen *psc = (struct driwindows_screen *) base;
259*61046927SAndroid Build Coastguard Worker 
260*61046927SAndroid Build Coastguard Worker    pdp = calloc(1, sizeof(*pdp));
261*61046927SAndroid Build Coastguard Worker    if (!pdp)
262*61046927SAndroid Build Coastguard Worker       return NULL;
263*61046927SAndroid Build Coastguard Worker 
264*61046927SAndroid Build Coastguard Worker    pdp->base.xDrawable = xDrawable;
265*61046927SAndroid Build Coastguard Worker    pdp->base.drawable = drawable;
266*61046927SAndroid Build Coastguard Worker    pdp->base.psc = &psc->base;
267*61046927SAndroid Build Coastguard Worker 
268*61046927SAndroid Build Coastguard Worker    /*
269*61046927SAndroid Build Coastguard Worker       By this stage, the X drawable already exists, but the GLX drawable may
270*61046927SAndroid Build Coastguard Worker       not.
271*61046927SAndroid Build Coastguard Worker 
272*61046927SAndroid Build Coastguard Worker       Query the server with the XID to find the correct HWND, HPBUFFERARB or
273*61046927SAndroid Build Coastguard Worker       HBITMAP
274*61046927SAndroid Build Coastguard Worker    */
275*61046927SAndroid Build Coastguard Worker 
276*61046927SAndroid Build Coastguard Worker    unsigned int type;
277*61046927SAndroid Build Coastguard Worker    void *handle;
278*61046927SAndroid Build Coastguard Worker 
279*61046927SAndroid Build Coastguard Worker    if (!XWindowsDRIQueryDrawable(psc->base.dpy, base->scr, drawable, &type, &handle))
280*61046927SAndroid Build Coastguard Worker    {
281*61046927SAndroid Build Coastguard Worker       free(pdp);
282*61046927SAndroid Build Coastguard Worker       return NULL;
283*61046927SAndroid Build Coastguard Worker    }
284*61046927SAndroid Build Coastguard Worker 
285*61046927SAndroid Build Coastguard Worker    /* No handle found is a failure */
286*61046927SAndroid Build Coastguard Worker    if (!handle) {
287*61046927SAndroid Build Coastguard Worker       free(pdp);
288*61046927SAndroid Build Coastguard Worker       return NULL;
289*61046927SAndroid Build Coastguard Worker    }
290*61046927SAndroid Build Coastguard Worker 
291*61046927SAndroid Build Coastguard Worker    /* Create a new drawable */
292*61046927SAndroid Build Coastguard Worker    pdp->windowsDrawable = windows_create_drawable(type, handle);
293*61046927SAndroid Build Coastguard Worker 
294*61046927SAndroid Build Coastguard Worker    if (!pdp->windowsDrawable) {
295*61046927SAndroid Build Coastguard Worker       free(pdp);
296*61046927SAndroid Build Coastguard Worker       return NULL;
297*61046927SAndroid Build Coastguard Worker    }
298*61046927SAndroid Build Coastguard Worker 
299*61046927SAndroid Build Coastguard Worker    pdp->base.destroyDrawable = driwindowsDestroyDrawable;
300*61046927SAndroid Build Coastguard Worker 
301*61046927SAndroid Build Coastguard Worker    return &pdp->base;
302*61046927SAndroid Build Coastguard Worker }
303*61046927SAndroid Build Coastguard Worker 
304*61046927SAndroid Build Coastguard Worker static int64_t
driwindowsSwapBuffers(__GLXDRIdrawable * pdraw,int64_t target_msc,int64_t divisor,int64_t remainder,Bool flush)305*61046927SAndroid Build Coastguard Worker driwindowsSwapBuffers(__GLXDRIdrawable * pdraw,
306*61046927SAndroid Build Coastguard Worker                  int64_t target_msc, int64_t divisor, int64_t remainder,
307*61046927SAndroid Build Coastguard Worker                  Bool flush)
308*61046927SAndroid Build Coastguard Worker {
309*61046927SAndroid Build Coastguard Worker    struct driwindows_drawable *pdp = (struct driwindows_drawable *) pdraw;
310*61046927SAndroid Build Coastguard Worker 
311*61046927SAndroid Build Coastguard Worker    (void) target_msc;
312*61046927SAndroid Build Coastguard Worker    (void) divisor;
313*61046927SAndroid Build Coastguard Worker    (void) remainder;
314*61046927SAndroid Build Coastguard Worker 
315*61046927SAndroid Build Coastguard Worker    if (flush) {
316*61046927SAndroid Build Coastguard Worker       glFlush();
317*61046927SAndroid Build Coastguard Worker    }
318*61046927SAndroid Build Coastguard Worker 
319*61046927SAndroid Build Coastguard Worker    windows_swap_buffers(pdp->windowsDrawable);
320*61046927SAndroid Build Coastguard Worker 
321*61046927SAndroid Build Coastguard Worker    return 0;
322*61046927SAndroid Build Coastguard Worker }
323*61046927SAndroid Build Coastguard Worker 
324*61046927SAndroid Build Coastguard Worker static void
driwindowsCopySubBuffer(__GLXDRIdrawable * pdraw,int x,int y,int width,int height,Bool flush)325*61046927SAndroid Build Coastguard Worker driwindowsCopySubBuffer(__GLXDRIdrawable * pdraw,
326*61046927SAndroid Build Coastguard Worker                    int x, int y, int width, int height, Bool flush)
327*61046927SAndroid Build Coastguard Worker {
328*61046927SAndroid Build Coastguard Worker    struct driwindows_drawable *pdp = (struct driwindows_drawable *) pdraw;
329*61046927SAndroid Build Coastguard Worker 
330*61046927SAndroid Build Coastguard Worker    if (flush) {
331*61046927SAndroid Build Coastguard Worker       glFlush();
332*61046927SAndroid Build Coastguard Worker    }
333*61046927SAndroid Build Coastguard Worker 
334*61046927SAndroid Build Coastguard Worker    windows_copy_subbuffer(pdp->windowsDrawable, x, y, width, height);
335*61046927SAndroid Build Coastguard Worker }
336*61046927SAndroid Build Coastguard Worker 
337*61046927SAndroid Build Coastguard Worker static const struct glx_screen_vtable driwindows_screen_vtable = {
338*61046927SAndroid Build Coastguard Worker    .create_context         = driwindows_create_context,
339*61046927SAndroid Build Coastguard Worker    .create_context_attribs = driwindows_create_context_attribs,
340*61046927SAndroid Build Coastguard Worker    .query_renderer_integer = NULL,
341*61046927SAndroid Build Coastguard Worker    .query_renderer_string  = NULL,
342*61046927SAndroid Build Coastguard Worker };
343*61046927SAndroid Build Coastguard Worker 
344*61046927SAndroid Build Coastguard Worker static Bool
driwindowsBindExtensions(struct driwindows_screen * psc)345*61046927SAndroid Build Coastguard Worker driwindowsBindExtensions(struct driwindows_screen *psc)
346*61046927SAndroid Build Coastguard Worker {
347*61046927SAndroid Build Coastguard Worker    Bool result = 1;
348*61046927SAndroid Build Coastguard Worker 
349*61046927SAndroid Build Coastguard Worker    const struct
350*61046927SAndroid Build Coastguard Worker    {
351*61046927SAndroid Build Coastguard Worker       char *wglext;
352*61046927SAndroid Build Coastguard Worker       char *glxext;
353*61046927SAndroid Build Coastguard Worker       Bool mandatory;
354*61046927SAndroid Build Coastguard Worker    } extensionMap[] = {
355*61046927SAndroid Build Coastguard Worker       { "WGL_ARB_make_current_read", "GLX_SGI_make_current_read", 0 },
356*61046927SAndroid Build Coastguard Worker       { "WGL_EXT_swap_control", "GLX_SGI_swap_control", 0 },
357*61046927SAndroid Build Coastguard Worker       { "WGL_EXT_swap_control", "GLX_MESA_swap_control", 0 },
358*61046927SAndroid Build Coastguard Worker //      { "WGL_ARB_render_texture", "GLX_EXT_texture_from_pixmap", 0 },
359*61046927SAndroid Build Coastguard Worker // Not exactly equivalent, needs some more glue to be written
360*61046927SAndroid Build Coastguard Worker       { "WGL_ARB_pbuffer", "GLX_SGIX_pbuffer", 1 },
361*61046927SAndroid Build Coastguard Worker       { "WGL_ARB_multisample", "GLX_ARB_multisample", 1 },
362*61046927SAndroid Build Coastguard Worker       { "WGL_ARB_multisample", "GLX_SGIS_multisample", 1 },
363*61046927SAndroid Build Coastguard Worker       { "WGL_ARB_create_context", "GLX_ARB_create_context", 0 },
364*61046927SAndroid Build Coastguard Worker       { "WGL_ARB_create_context_profile", "GLX_ARB_create_context_profile", 0 },
365*61046927SAndroid Build Coastguard Worker       { "WGL_ARB_create_context_robustness", "GLX_ARB_create_context_robustness", 0 },
366*61046927SAndroid Build Coastguard Worker       { "WGL_EXT_create_context_es2_profile", "GLX_EXT_create_context_es2_profile", 0 },
367*61046927SAndroid Build Coastguard Worker    };
368*61046927SAndroid Build Coastguard Worker 
369*61046927SAndroid Build Coastguard Worker    char *wgl_extensions;
370*61046927SAndroid Build Coastguard Worker    char *gl_extensions;
371*61046927SAndroid Build Coastguard Worker    int i;
372*61046927SAndroid Build Coastguard Worker 
373*61046927SAndroid Build Coastguard Worker    windows_extensions(&gl_extensions, &wgl_extensions);
374*61046927SAndroid Build Coastguard Worker 
375*61046927SAndroid Build Coastguard Worker    for (i = 0; i < ARRAY_SIZE(extensionMap); i++) {
376*61046927SAndroid Build Coastguard Worker       if (strstr(wgl_extensions, extensionMap[i].wglext)) {
377*61046927SAndroid Build Coastguard Worker           __glXEnableDirectExtension(&psc->base, extensionMap[i].glxext);
378*61046927SAndroid Build Coastguard Worker           InfoMessageF("enabled %s\n", extensionMap[i].glxext);
379*61046927SAndroid Build Coastguard Worker       }
380*61046927SAndroid Build Coastguard Worker       else if (extensionMap[i].mandatory) {
381*61046927SAndroid Build Coastguard Worker          ErrorMessageF("required WGL extension %s is missing\n", extensionMap[i].wglext);
382*61046927SAndroid Build Coastguard Worker          result = 0;
383*61046927SAndroid Build Coastguard Worker       }
384*61046927SAndroid Build Coastguard Worker    }
385*61046927SAndroid Build Coastguard Worker 
386*61046927SAndroid Build Coastguard Worker    /*
387*61046927SAndroid Build Coastguard Worker        Because it pre-dates WGL_EXT_extensions_string, GL_WIN_swap_hint might
388*61046927SAndroid Build Coastguard Worker        only be in GL_EXTENSIONS
389*61046927SAndroid Build Coastguard Worker    */
390*61046927SAndroid Build Coastguard Worker    if (strstr(gl_extensions, "GL_WIN_swap_hint")) {
391*61046927SAndroid Build Coastguard Worker       psc->copySubBuffer = 1;
392*61046927SAndroid Build Coastguard Worker       __glXEnableDirectExtension(&psc->base, "GLX_MESA_copy_sub_buffer");
393*61046927SAndroid Build Coastguard Worker       InfoMessageF("enabled GLX_MESA_copy_sub_buffer\n");
394*61046927SAndroid Build Coastguard Worker    }
395*61046927SAndroid Build Coastguard Worker 
396*61046927SAndroid Build Coastguard Worker    free(gl_extensions);
397*61046927SAndroid Build Coastguard Worker    free(wgl_extensions);
398*61046927SAndroid Build Coastguard Worker 
399*61046927SAndroid Build Coastguard Worker    return result;
400*61046927SAndroid Build Coastguard Worker }
401*61046927SAndroid Build Coastguard Worker 
402*61046927SAndroid Build Coastguard Worker static struct glx_config *
driwindowsMapConfigs(struct glx_display * priv,int screen,struct glx_config * configs,struct glx_config * fbconfigs)403*61046927SAndroid Build Coastguard Worker driwindowsMapConfigs(struct glx_display *priv, int screen, struct glx_config *configs, struct glx_config *fbconfigs)
404*61046927SAndroid Build Coastguard Worker {
405*61046927SAndroid Build Coastguard Worker    struct glx_config head, *tail, *m;
406*61046927SAndroid Build Coastguard Worker 
407*61046927SAndroid Build Coastguard Worker    tail = &head;
408*61046927SAndroid Build Coastguard Worker    head.next = NULL;
409*61046927SAndroid Build Coastguard Worker 
410*61046927SAndroid Build Coastguard Worker    for (m = configs; m; m = m->next) {
411*61046927SAndroid Build Coastguard Worker       int fbconfigID = GLX_DONT_CARE;
412*61046927SAndroid Build Coastguard Worker       if (fbconfigs) {
413*61046927SAndroid Build Coastguard Worker          /*
414*61046927SAndroid Build Coastguard Worker            visuals have fbconfigID of GLX_DONT_CARE, so search for a fbconfig
415*61046927SAndroid Build Coastguard Worker            with matching visualID and get the fbconfigID from there
416*61046927SAndroid Build Coastguard Worker          */
417*61046927SAndroid Build Coastguard Worker          struct glx_config *f;
418*61046927SAndroid Build Coastguard Worker          for (f = fbconfigs; f; f = f->next) {
419*61046927SAndroid Build Coastguard Worker             if (f->visualID == m->visualID)
420*61046927SAndroid Build Coastguard Worker                fbconfigID = f->fbconfigID;
421*61046927SAndroid Build Coastguard Worker          }
422*61046927SAndroid Build Coastguard Worker       }
423*61046927SAndroid Build Coastguard Worker       else {
424*61046927SAndroid Build Coastguard Worker          fbconfigID = m->fbconfigID;
425*61046927SAndroid Build Coastguard Worker       }
426*61046927SAndroid Build Coastguard Worker 
427*61046927SAndroid Build Coastguard Worker       int pxfi;
428*61046927SAndroid Build Coastguard Worker       XWindowsDRIFBConfigToPixelFormat(priv->dpy, screen, fbconfigID, &pxfi);
429*61046927SAndroid Build Coastguard Worker       if (pxfi == 0)
430*61046927SAndroid Build Coastguard Worker          continue;
431*61046927SAndroid Build Coastguard Worker 
432*61046927SAndroid Build Coastguard Worker       struct driwindows_config *config = malloc(sizeof(*config));
433*61046927SAndroid Build Coastguard Worker 
434*61046927SAndroid Build Coastguard Worker       tail->next = &config->base;
435*61046927SAndroid Build Coastguard Worker       if (tail->next == NULL)
436*61046927SAndroid Build Coastguard Worker          continue;
437*61046927SAndroid Build Coastguard Worker 
438*61046927SAndroid Build Coastguard Worker       config->base = *m;
439*61046927SAndroid Build Coastguard Worker       config->pxfi = pxfi;
440*61046927SAndroid Build Coastguard Worker 
441*61046927SAndroid Build Coastguard Worker       tail = tail->next;
442*61046927SAndroid Build Coastguard Worker    }
443*61046927SAndroid Build Coastguard Worker 
444*61046927SAndroid Build Coastguard Worker    return head.next;
445*61046927SAndroid Build Coastguard Worker }
446*61046927SAndroid Build Coastguard Worker 
447*61046927SAndroid Build Coastguard Worker static struct glx_screen *
driwindowsCreateScreen(int screen,struct glx_display * priv,bool driver_name_is_inferred)448*61046927SAndroid Build Coastguard Worker driwindowsCreateScreen(int screen, struct glx_display *priv, bool driver_name_is_inferred)
449*61046927SAndroid Build Coastguard Worker {
450*61046927SAndroid Build Coastguard Worker    __GLXDRIscreen *psp;
451*61046927SAndroid Build Coastguard Worker    struct driwindows_screen *psc;
452*61046927SAndroid Build Coastguard Worker    struct glx_config *configs = NULL, *visuals = NULL;
453*61046927SAndroid Build Coastguard Worker    int directCapable;
454*61046927SAndroid Build Coastguard Worker    int eventBase, errorBase;
455*61046927SAndroid Build Coastguard Worker    int major, minor, patch;
456*61046927SAndroid Build Coastguard Worker 
457*61046927SAndroid Build Coastguard Worker    /* Verify server has Windows-DRI extension */
458*61046927SAndroid Build Coastguard Worker    if (!XWindowsDRIQueryExtension(dpy, &eventBase, &errorBase)) {
459*61046927SAndroid Build Coastguard Worker       ErrorMessageF("Windows-DRI extension not available\n");
460*61046927SAndroid Build Coastguard Worker       return NULL;
461*61046927SAndroid Build Coastguard Worker    }
462*61046927SAndroid Build Coastguard Worker 
463*61046927SAndroid Build Coastguard Worker    if (!XWindowsDRIQueryVersion(dpy, &major, &minor, &patch)) {
464*61046927SAndroid Build Coastguard Worker       ErrorMessageF("Fetching Windows-DRI extension version failed\n");
465*61046927SAndroid Build Coastguard Worker       return NULL;
466*61046927SAndroid Build Coastguard Worker    }
467*61046927SAndroid Build Coastguard Worker 
468*61046927SAndroid Build Coastguard Worker    if (!windows_check_renderer()) {
469*61046927SAndroid Build Coastguard Worker       ErrorMessageF("Windows-DRI extension disabled for GDI Generic renderer\n");
470*61046927SAndroid Build Coastguard Worker       return NULL;
471*61046927SAndroid Build Coastguard Worker    }
472*61046927SAndroid Build Coastguard Worker 
473*61046927SAndroid Build Coastguard Worker    psc = calloc(1, sizeof *psc);
474*61046927SAndroid Build Coastguard Worker    if (psc == NULL)
475*61046927SAndroid Build Coastguard Worker       return NULL;
476*61046927SAndroid Build Coastguard Worker 
477*61046927SAndroid Build Coastguard Worker    if (!glx_screen_init(&psc->base, screen, priv)) {
478*61046927SAndroid Build Coastguard Worker       free(psc);
479*61046927SAndroid Build Coastguard Worker       return NULL;
480*61046927SAndroid Build Coastguard Worker    }
481*61046927SAndroid Build Coastguard Worker 
482*61046927SAndroid Build Coastguard Worker    if (!XWindowsDRIQueryDirectRenderingCapable(psc->base.dpy, screen, &directCapable) ||
483*61046927SAndroid Build Coastguard Worker        !directCapable) {
484*61046927SAndroid Build Coastguard Worker       ErrorMessageF("Screen is not Windows-DRI capable\n");
485*61046927SAndroid Build Coastguard Worker       goto handle_error;
486*61046927SAndroid Build Coastguard Worker    }
487*61046927SAndroid Build Coastguard Worker 
488*61046927SAndroid Build Coastguard Worker    /* discover native supported extensions */
489*61046927SAndroid Build Coastguard Worker    if (!driwindowsBindExtensions(psc)) {
490*61046927SAndroid Build Coastguard Worker       goto handle_error;
491*61046927SAndroid Build Coastguard Worker    }
492*61046927SAndroid Build Coastguard Worker 
493*61046927SAndroid Build Coastguard Worker    /* Augment configs with pxfi information */
494*61046927SAndroid Build Coastguard Worker    configs = driwindowsMapConfigs(priv, screen, psc->base.configs, NULL);
495*61046927SAndroid Build Coastguard Worker    visuals = driwindowsMapConfigs(priv, screen, psc->base.visuals, configs);
496*61046927SAndroid Build Coastguard Worker 
497*61046927SAndroid Build Coastguard Worker    if (!configs || !visuals) {
498*61046927SAndroid Build Coastguard Worker        ErrorMessageF("No fbConfigs or visuals found\n");
499*61046927SAndroid Build Coastguard Worker        goto handle_error;
500*61046927SAndroid Build Coastguard Worker    }
501*61046927SAndroid Build Coastguard Worker 
502*61046927SAndroid Build Coastguard Worker    glx_config_destroy_list(psc->base.configs);
503*61046927SAndroid Build Coastguard Worker    psc->base.configs = configs;
504*61046927SAndroid Build Coastguard Worker    glx_config_destroy_list(psc->base.visuals);
505*61046927SAndroid Build Coastguard Worker    psc->base.visuals = visuals;
506*61046927SAndroid Build Coastguard Worker 
507*61046927SAndroid Build Coastguard Worker    psc->base.vtable = &driwindows_screen_vtable;
508*61046927SAndroid Build Coastguard Worker    psp = &psc->base.driScreen;
509*61046927SAndroid Build Coastguard Worker    psp->createDrawable = driwindowsCreateDrawable;
510*61046927SAndroid Build Coastguard Worker    psp->swapBuffers = driwindowsSwapBuffers;
511*61046927SAndroid Build Coastguard Worker 
512*61046927SAndroid Build Coastguard Worker    if (psc->copySubBuffer)
513*61046927SAndroid Build Coastguard Worker       psp->copySubBuffer = driwindowsCopySubBuffer;
514*61046927SAndroid Build Coastguard Worker 
515*61046927SAndroid Build Coastguard Worker    priv->driver = GLX_DRIVER_WINDOWS;
516*61046927SAndroid Build Coastguard Worker 
517*61046927SAndroid Build Coastguard Worker    return &psc->base;
518*61046927SAndroid Build Coastguard Worker 
519*61046927SAndroid Build Coastguard Worker handle_error:
520*61046927SAndroid Build Coastguard Worker    glx_screen_cleanup(&psc->base);
521*61046927SAndroid Build Coastguard Worker 
522*61046927SAndroid Build Coastguard Worker    return NULL;
523*61046927SAndroid Build Coastguard Worker }
524