xref: /aosp_15_r20/external/mesa3d/src/egl/drivers/wgl/egl_wgl.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright © Microsoft Corporation
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21  * IN THE SOFTWARE.
22  */
23 
24 #include "state_tracker/st_context.h"
25 
26 #include <eglcontext.h>
27 #include <eglcurrent.h>
28 #include <egldriver.h>
29 #include <egllog.h>
30 #include <eglsurface.h>
31 
32 #include "egl_wgl.h"
33 
34 #include <stw_context.h>
35 #include <stw_device.h>
36 #include <stw_ext_interop.h>
37 #include <stw_framebuffer.h>
38 #include <stw_image.h>
39 #include <stw_pixelformat.h>
40 #include <stw_winsys.h>
41 
42 #include <GL/wglext.h>
43 
44 #include <pipe/p_context.h>
45 #include <pipe/p_screen.h>
46 #include <pipe/p_state.h>
47 
48 #include "util/u_call_once.h"
49 #include <mapi/glapi/glapi.h>
50 
51 #include <GL/mesa_glinterop.h>
52 
53 static EGLBoolean
wgl_match_config(const _EGLConfig * conf,const _EGLConfig * criteria)54 wgl_match_config(const _EGLConfig *conf, const _EGLConfig *criteria)
55 {
56    if (_eglCompareConfigs(conf, criteria, NULL, EGL_FALSE) != 0)
57       return EGL_FALSE;
58 
59    if (!_eglMatchConfig(conf, criteria))
60       return EGL_FALSE;
61 
62    return EGL_TRUE;
63 }
64 
65 static struct wgl_egl_config *
wgl_add_config(_EGLDisplay * disp,const struct stw_pixelformat_info * stw_config,int id,EGLint surface_type)66 wgl_add_config(_EGLDisplay *disp, const struct stw_pixelformat_info *stw_config,
67                int id, EGLint surface_type)
68 {
69    struct wgl_egl_config *conf;
70    _EGLConfig base;
71    unsigned int double_buffer;
72    _EGLConfig *matching_config;
73    EGLint num_configs = 0;
74    EGLint config_id;
75 
76    _eglInitConfig(&base, disp, id);
77 
78    double_buffer = (stw_config->pfd.dwFlags & PFD_DOUBLEBUFFER) != 0;
79 
80    if (stw_config->pfd.iPixelType != PFD_TYPE_RGBA)
81       return NULL;
82 
83    base.RedSize = stw_config->pfd.cRedBits;
84    base.GreenSize = stw_config->pfd.cGreenBits;
85    base.BlueSize = stw_config->pfd.cBlueBits;
86    base.AlphaSize = stw_config->pfd.cAlphaBits;
87    base.BufferSize = stw_config->pfd.cColorBits;
88 
89    if (stw_config->pfd.cAccumBits) {
90       /* Don't expose visuals with the accumulation buffer. */
91       return NULL;
92    }
93 
94    base.MaxPbufferWidth = _EGL_MAX_PBUFFER_WIDTH;
95    base.MaxPbufferHeight = _EGL_MAX_PBUFFER_HEIGHT;
96 
97    base.DepthSize = stw_config->pfd.cDepthBits;
98    base.StencilSize = stw_config->pfd.cStencilBits;
99    base.Samples = stw_config->stvis.samples;
100    base.SampleBuffers = base.Samples > 1;
101 
102    base.NativeRenderable = EGL_TRUE;
103 
104    if (surface_type & EGL_PBUFFER_BIT) {
105       base.BindToTextureRGB = stw_config->bindToTextureRGB;
106       if (base.AlphaSize > 0)
107          base.BindToTextureRGBA = stw_config->bindToTextureRGBA;
108    }
109 
110    if (double_buffer) {
111       surface_type &= ~EGL_PIXMAP_BIT;
112    }
113 
114    if (!(stw_config->pfd.dwFlags & PFD_DRAW_TO_WINDOW)) {
115       surface_type &= ~EGL_WINDOW_BIT;
116    }
117 
118    if (!surface_type)
119       return NULL;
120 
121    base.SurfaceType = surface_type;
122    base.RenderableType = disp->ClientAPIs;
123    base.Conformant = disp->ClientAPIs;
124 
125    base.MinSwapInterval = 0;
126    base.MaxSwapInterval = 4;
127    base.YInvertedNOK = EGL_TRUE;
128 
129    if (!_eglValidateConfig(&base, EGL_FALSE)) {
130       _eglLog(_EGL_DEBUG, "wgl: failed to validate config %d", id);
131       return NULL;
132    }
133 
134    config_id = base.ConfigID;
135    base.ConfigID = EGL_DONT_CARE;
136    base.SurfaceType = EGL_DONT_CARE;
137    num_configs = _eglFilterArray(disp->Configs, (void **)&matching_config, 1,
138                                  (_EGLArrayForEach)wgl_match_config, &base);
139 
140    if (num_configs == 1) {
141       conf = (struct wgl_egl_config *)matching_config;
142 
143       if (!conf->stw_config[double_buffer])
144          conf->stw_config[double_buffer] = stw_config;
145       else
146          /* a similar config type is already added (unlikely) => discard */
147          return NULL;
148    } else if (num_configs == 0) {
149       conf = calloc(1, sizeof(*conf));
150       if (conf == NULL)
151          return NULL;
152 
153       conf->stw_config[double_buffer] = stw_config;
154 
155       memcpy(&conf->base, &base, sizeof base);
156       conf->base.SurfaceType = 0;
157       conf->base.ConfigID = config_id;
158 
159       _eglLinkConfig(&conf->base);
160    } else {
161       unreachable("duplicates should not be possible");
162       return NULL;
163    }
164 
165    conf->base.SurfaceType |= surface_type;
166 
167    return conf;
168 }
169 
170 static EGLBoolean
wgl_add_configs(_EGLDisplay * disp)171 wgl_add_configs(_EGLDisplay *disp)
172 {
173    unsigned int config_count = 0;
174    unsigned surface_type = EGL_PBUFFER_BIT | EGL_WINDOW_BIT;
175 
176    // This is already a filtered set of what the driver supports,
177    // and there's no further filtering needed per-visual
178    for (unsigned i = 1; stw_pixelformat_get_info(i) != NULL; i++) {
179 
180       struct wgl_egl_config *wgl_conf = wgl_add_config(
181          disp, stw_pixelformat_get_info(i), config_count + 1, surface_type);
182 
183       if (wgl_conf) {
184          if (wgl_conf->base.ConfigID == config_count + 1)
185             config_count++;
186       }
187    }
188 
189    return (config_count != 0);
190 }
191 
192 static void
wgl_display_destroy(_EGLDisplay * disp)193 wgl_display_destroy(_EGLDisplay *disp)
194 {
195    struct wgl_egl_display *wgl_dpy = wgl_egl_display(disp);
196 
197    st_screen_destroy(&wgl_dpy->base);
198    free(wgl_dpy);
199 }
200 
201 static int
wgl_egl_st_get_param(struct pipe_frontend_screen * fscreen,enum st_manager_param param)202 wgl_egl_st_get_param(struct pipe_frontend_screen *fscreen,
203                      enum st_manager_param param)
204 {
205    /* no-op */
206    return 0;
207 }
208 
209 static bool
wgl_get_egl_image(struct pipe_frontend_screen * fscreen,void * image,struct st_egl_image * out)210 wgl_get_egl_image(struct pipe_frontend_screen *fscreen, void *image,
211                   struct st_egl_image *out)
212 {
213    struct wgl_egl_image *wgl_img = (struct wgl_egl_image *)image;
214    stw_translate_image(wgl_img->img, out);
215    return true;
216 }
217 
218 static bool
wgl_validate_egl_image(struct pipe_frontend_screen * fscreen,void * image)219 wgl_validate_egl_image(struct pipe_frontend_screen *fscreen, void *image)
220 {
221    struct wgl_egl_display *wgl_dpy = (struct wgl_egl_display *)fscreen;
222    _EGLDisplay *disp = _eglLockDisplay(wgl_dpy->parent);
223    _EGLImage *img = _eglLookupImage(image, disp);
224    _eglUnlockDisplay(disp);
225 
226    if (img == NULL) {
227       _eglError(EGL_BAD_PARAMETER, "wgl_validate_egl_image");
228       return false;
229    }
230 
231    return true;
232 }
233 
234 static EGLBoolean
wgl_initialize_impl(_EGLDisplay * disp,HDC hdc)235 wgl_initialize_impl(_EGLDisplay *disp, HDC hdc)
236 {
237    struct wgl_egl_display *wgl_dpy;
238    const char *err;
239 
240    wgl_dpy = calloc(1, sizeof(*wgl_dpy));
241    if (!wgl_dpy)
242       return _eglError(EGL_BAD_ALLOC, "eglInitialize");
243 
244    disp->DriverData = (void *)wgl_dpy;
245    wgl_dpy->parent = disp;
246 
247    if (!stw_init_screen(hdc)) {
248       err = "wgl: failed to initialize screen";
249       goto cleanup;
250    }
251 
252    struct stw_device *stw_dev = stw_get_device();
253    wgl_dpy->screen = stw_dev->screen;
254 
255    wgl_dpy->base.screen = stw_dev->screen;
256    wgl_dpy->base.get_param = wgl_egl_st_get_param;
257    wgl_dpy->base.get_egl_image = wgl_get_egl_image;
258    wgl_dpy->base.validate_egl_image = wgl_validate_egl_image;
259 
260    disp->ClientAPIs = 0;
261    if (_eglIsApiValid(EGL_OPENGL_API))
262       disp->ClientAPIs |= EGL_OPENGL_BIT;
263    if (_eglIsApiValid(EGL_OPENGL_ES_API))
264       disp->ClientAPIs |=
265          EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT | EGL_OPENGL_ES3_BIT_KHR;
266 
267    disp->Extensions.KHR_no_config_context = EGL_TRUE;
268    disp->Extensions.KHR_surfaceless_context = EGL_TRUE;
269    disp->Extensions.MESA_query_driver = EGL_TRUE;
270 
271    /* Report back to EGL the bitmask of priorities supported */
272    disp->Extensions.IMG_context_priority = wgl_dpy->screen->get_param(
273       wgl_dpy->screen, PIPE_CAP_CONTEXT_PRIORITY_MASK);
274 
275    disp->Extensions.EXT_pixel_format_float = EGL_TRUE;
276 
277    if (wgl_dpy->screen->is_format_supported(
278           wgl_dpy->screen, PIPE_FORMAT_B8G8R8A8_SRGB, PIPE_TEXTURE_2D, 0, 0,
279           PIPE_BIND_RENDER_TARGET))
280       disp->Extensions.KHR_gl_colorspace = EGL_TRUE;
281 
282    disp->Extensions.KHR_create_context = EGL_TRUE;
283 
284    disp->Extensions.KHR_image_base = EGL_TRUE;
285    disp->Extensions.KHR_gl_renderbuffer_image = EGL_TRUE;
286    disp->Extensions.KHR_gl_texture_2D_image = EGL_TRUE;
287    disp->Extensions.KHR_gl_texture_cubemap_image = EGL_TRUE;
288    disp->Extensions.KHR_gl_texture_3D_image = EGL_TRUE;
289 
290    disp->Extensions.KHR_fence_sync = EGL_TRUE;
291    disp->Extensions.KHR_reusable_sync = EGL_TRUE;
292    disp->Extensions.KHR_wait_sync = EGL_TRUE;
293 
294    if (!wgl_add_configs(disp)) {
295       err = "wgl: failed to add configs";
296       goto cleanup;
297    }
298 
299    return EGL_TRUE;
300 
301 cleanup:
302    wgl_display_destroy(disp);
303    return _eglError(EGL_NOT_INITIALIZED, err);
304 }
305 
306 static EGLBoolean
wgl_initialize(_EGLDisplay * disp)307 wgl_initialize(_EGLDisplay *disp)
308 {
309    EGLBoolean ret = EGL_FALSE;
310    struct wgl_egl_display *wgl_dpy = wgl_egl_display(disp);
311 
312    /* In the case where the application calls eglMakeCurrent(context1),
313     * eglTerminate, then eglInitialize again (without a call to eglReleaseThread
314     * or eglMakeCurrent(NULL) before that), wgl_dpy structure is still
315     * initialized, as we need it to be able to free context1 correctly.
316     *
317     * It would probably be safest to forcibly release the display with
318     * wgl_display_release, to make sure the display is reinitialized correctly.
319     * However, the EGL spec states that we need to keep a reference to the
320     * current context (so we cannot call wgl_make_current(NULL)), and therefore
321     * we would leak context1 as we would be missing the old display connection
322     * to free it up correctly.
323     */
324    if (wgl_dpy) {
325       p_atomic_inc(&wgl_dpy->ref_count);
326       return EGL_TRUE;
327    }
328 
329    switch (disp->Platform) {
330    case _EGL_PLATFORM_SURFACELESS:
331       ret = wgl_initialize_impl(disp, NULL);
332       break;
333    case _EGL_PLATFORM_WINDOWS:
334       ret = wgl_initialize_impl(disp, disp->PlatformDisplay);
335       break;
336    default:
337       unreachable("Callers ensure we cannot get here.");
338       return EGL_FALSE;
339    }
340 
341    if (!ret)
342       return EGL_FALSE;
343 
344    wgl_dpy = wgl_egl_display(disp);
345    p_atomic_inc(&wgl_dpy->ref_count);
346 
347    return EGL_TRUE;
348 }
349 
350 /**
351  * Decrement display reference count, and free up display if necessary.
352  */
353 static void
wgl_display_release(_EGLDisplay * disp)354 wgl_display_release(_EGLDisplay *disp)
355 {
356    struct wgl_egl_display *wgl_dpy;
357 
358    if (!disp)
359       return;
360 
361    wgl_dpy = wgl_egl_display(disp);
362 
363    assert(wgl_dpy->ref_count > 0);
364    if (!p_atomic_dec_zero(&wgl_dpy->ref_count))
365       return;
366 
367    _eglCleanupDisplay(disp);
368    wgl_display_destroy(disp);
369 }
370 
371 /**
372  * Called via eglTerminate(), drv->Terminate().
373  *
374  * This must be guaranteed to be called exactly once, even if eglTerminate is
375  * called many times (without a eglInitialize in between).
376  */
377 static EGLBoolean
wgl_terminate(_EGLDisplay * disp)378 wgl_terminate(_EGLDisplay *disp)
379 {
380    /* Release all non-current Context/Surfaces. */
381    _eglReleaseDisplayResources(disp);
382 
383    wgl_display_release(disp);
384 
385    return EGL_TRUE;
386 }
387 
388 /**
389  * Called via eglCreateContext(), drv->CreateContext().
390  */
391 static _EGLContext *
wgl_create_context(_EGLDisplay * disp,_EGLConfig * conf,_EGLContext * share_list,const EGLint * attrib_list)392 wgl_create_context(_EGLDisplay *disp, _EGLConfig *conf, _EGLContext *share_list,
393                    const EGLint *attrib_list)
394 {
395    struct wgl_egl_context *wgl_ctx;
396    struct wgl_egl_display *wgl_dpy = wgl_egl_display(disp);
397    struct wgl_egl_context *wgl_ctx_shared = wgl_egl_context(share_list);
398    struct stw_context *shared = wgl_ctx_shared ? wgl_ctx_shared->ctx : NULL;
399    struct wgl_egl_config *wgl_config = wgl_egl_config(conf);
400    const struct stw_pixelformat_info *stw_config;
401 
402    wgl_ctx = malloc(sizeof(*wgl_ctx));
403    if (!wgl_ctx) {
404       _eglError(EGL_BAD_ALLOC, "eglCreateContext");
405       return NULL;
406    }
407 
408    if (!_eglInitContext(&wgl_ctx->base, disp, conf, share_list, attrib_list))
409       goto cleanup;
410 
411    unsigned profile_mask = 0;
412    switch (wgl_ctx->base.ClientAPI) {
413    case EGL_OPENGL_ES_API:
414       profile_mask = WGL_CONTEXT_ES_PROFILE_BIT_EXT;
415       break;
416    case EGL_OPENGL_API:
417       if ((wgl_ctx->base.ClientMajorVersion >= 4 ||
418            (wgl_ctx->base.ClientMajorVersion == 3 &&
419             wgl_ctx->base.ClientMinorVersion >= 2)) &&
420           wgl_ctx->base.Profile == EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR)
421          profile_mask = WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
422       else if (wgl_ctx->base.ClientMajorVersion == 3 &&
423                wgl_ctx->base.ClientMinorVersion == 1)
424          profile_mask = WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
425       else
426          profile_mask = WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
427       break;
428    default:
429       _eglError(EGL_BAD_PARAMETER, "eglCreateContext");
430       free(wgl_ctx);
431       return NULL;
432    }
433 
434    if (conf != NULL) {
435       /* The config chosen here isn't necessarily
436        * used for surfaces later.
437        * A pixmap surface will use the single config.
438        * This opportunity depends on disabling the
439        * doubleBufferMode check in
440        * src/mesa/main/context.c:check_compatible()
441        */
442       if (wgl_config->stw_config[1])
443          stw_config = wgl_config->stw_config[1];
444       else
445          stw_config = wgl_config->stw_config[0];
446    } else
447       stw_config = NULL;
448 
449    unsigned flags = 0;
450    if (wgl_ctx->base.Flags & EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR)
451       flags |= WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
452    if (wgl_ctx->base.Flags & EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR)
453       flags |= WGL_CONTEXT_DEBUG_BIT_ARB;
454    unsigned resetStrategy = WGL_NO_RESET_NOTIFICATION_ARB;
455    if (wgl_ctx->base.ResetNotificationStrategy != EGL_NO_RESET_NOTIFICATION)
456       resetStrategy = WGL_LOSE_CONTEXT_ON_RESET_ARB;
457    wgl_ctx->ctx = stw_create_context_attribs(
458       disp->PlatformDisplay, 0, shared, &wgl_dpy->base,
459       wgl_ctx->base.ClientMajorVersion, wgl_ctx->base.ClientMinorVersion, flags,
460       profile_mask, stw_config, resetStrategy);
461 
462    if (!wgl_ctx->ctx)
463       goto cleanup;
464 
465    return &wgl_ctx->base;
466 
467 cleanup:
468    free(wgl_ctx);
469    return NULL;
470 }
471 
472 /**
473  * Called via eglDestroyContext(), drv->DestroyContext().
474  */
475 static EGLBoolean
wgl_destroy_context(_EGLDisplay * disp,_EGLContext * ctx)476 wgl_destroy_context(_EGLDisplay *disp, _EGLContext *ctx)
477 {
478    struct wgl_egl_context *wgl_ctx = wgl_egl_context(ctx);
479 
480    if (_eglPutContext(ctx)) {
481       stw_destroy_context(wgl_ctx->ctx);
482       free(wgl_ctx);
483    }
484 
485    return EGL_TRUE;
486 }
487 
488 static EGLBoolean
wgl_destroy_surface(_EGLDisplay * disp,_EGLSurface * surf)489 wgl_destroy_surface(_EGLDisplay *disp, _EGLSurface *surf)
490 {
491    struct wgl_egl_surface *wgl_surf = wgl_egl_surface(surf);
492 
493    if (!_eglPutSurface(surf))
494       return EGL_TRUE;
495 
496    if (wgl_surf->fb->owner == STW_FRAMEBUFFER_PBUFFER) {
497       DestroyWindow(wgl_surf->fb->hWnd);
498    } else {
499       struct stw_context *ctx = stw_current_context();
500       stw_framebuffer_lock(wgl_surf->fb);
501       stw_framebuffer_release_locked(wgl_surf->fb, ctx ? ctx->st : NULL);
502    }
503    return EGL_TRUE;
504 }
505 
506 static void
wgl_gl_flush_get(_glapi_proc * glFlush)507 wgl_gl_flush_get(_glapi_proc *glFlush)
508 {
509    *glFlush = _glapi_get_proc_address("glFlush");
510 }
511 
512 static void
wgl_gl_flush()513 wgl_gl_flush()
514 {
515    static void (*glFlush)(void);
516    static util_once_flag once = UTIL_ONCE_FLAG_INIT;
517 
518    util_call_once_data(&once, (util_call_once_data_func)wgl_gl_flush_get,
519                        &glFlush);
520 
521    /* if glFlush is not available things are horribly broken */
522    if (!glFlush) {
523       _eglLog(_EGL_WARNING, "wgl: failed to find glFlush entry point");
524       return;
525    }
526 
527    glFlush();
528 }
529 
530 /**
531  * Called via eglMakeCurrent(), drv->MakeCurrent().
532  */
533 static EGLBoolean
wgl_make_current(_EGLDisplay * disp,_EGLSurface * dsurf,_EGLSurface * rsurf,_EGLContext * ctx)534 wgl_make_current(_EGLDisplay *disp, _EGLSurface *dsurf, _EGLSurface *rsurf,
535                  _EGLContext *ctx)
536 {
537    struct wgl_egl_display *wgl_dpy = wgl_egl_display(disp);
538    struct wgl_egl_context *wgl_ctx = wgl_egl_context(ctx);
539    _EGLDisplay *old_disp = NULL;
540    _EGLContext *old_ctx;
541    _EGLSurface *old_dsurf, *old_rsurf;
542    _EGLSurface *tmp_dsurf, *tmp_rsurf;
543    struct stw_framebuffer *ddraw, *rdraw;
544    struct stw_context *cctx;
545    EGLint egl_error = EGL_SUCCESS;
546 
547    if (!wgl_dpy)
548       return _eglError(EGL_NOT_INITIALIZED, "eglMakeCurrent");
549 
550    /* make new bindings, set the EGL error otherwise */
551    if (!_eglBindContext(ctx, dsurf, rsurf, &old_ctx, &old_dsurf, &old_rsurf))
552       return EGL_FALSE;
553 
554    if (old_ctx) {
555       struct stw_context *old_cctx = wgl_egl_context(old_ctx)->ctx;
556       old_disp = old_ctx->Resource.Display;
557 
558       /* flush before context switch */
559       wgl_gl_flush();
560 
561       stw_unbind_context(old_cctx);
562    }
563 
564    ddraw = (dsurf) ? wgl_egl_surface(dsurf)->fb : NULL;
565    rdraw = (rsurf) ? wgl_egl_surface(rsurf)->fb : NULL;
566    cctx = (wgl_ctx) ? wgl_ctx->ctx : NULL;
567 
568    if (cctx || ddraw || rdraw) {
569       if (!stw_make_current(ddraw, rdraw, cctx)) {
570          _EGLContext *tmp_ctx;
571 
572          /* stw_make_current failed. We cannot tell for sure why, but
573           * setting the error to EGL_BAD_MATCH is surely better than leaving it
574           * as EGL_SUCCESS.
575           */
576          egl_error = EGL_BAD_MATCH;
577 
578          /* undo the previous _eglBindContext */
579          _eglBindContext(old_ctx, old_dsurf, old_rsurf, &ctx, &tmp_dsurf,
580                          &tmp_rsurf);
581          assert(&wgl_ctx->base == ctx && tmp_dsurf == dsurf &&
582                 tmp_rsurf == rsurf);
583 
584          _eglPutSurface(dsurf);
585          _eglPutSurface(rsurf);
586          _eglPutContext(ctx);
587 
588          _eglPutSurface(old_dsurf);
589          _eglPutSurface(old_rsurf);
590          _eglPutContext(old_ctx);
591 
592          ddraw = (old_dsurf) ? wgl_egl_surface(old_dsurf)->fb : NULL;
593          rdraw = (old_rsurf) ? wgl_egl_surface(old_rsurf)->fb : NULL;
594          cctx = (old_ctx) ? wgl_egl_context(old_ctx)->ctx : NULL;
595 
596          /* undo the previous _eglBindContext */
597          if (stw_make_current(ddraw, rdraw, cctx)) {
598             return _eglError(egl_error, "eglMakeCurrent");
599          }
600 
601          /* We cannot restore the same state as it was before calling
602           * eglMakeCurrent() and the spec isn't clear about what to do. We
603           * can prevent EGL from calling into the DRI driver with no DRI
604           * context bound.
605           */
606          dsurf = rsurf = NULL;
607          ctx = NULL;
608 
609          _eglBindContext(ctx, dsurf, rsurf, &tmp_ctx, &tmp_dsurf, &tmp_rsurf);
610          assert(tmp_ctx == old_ctx && tmp_dsurf == old_dsurf &&
611                 tmp_rsurf == old_rsurf);
612 
613          _eglLog(_EGL_WARNING, "wgl: failed to rebind the previous context");
614       } else {
615          /* _eglBindContext succeeded, so take a reference on the
616           * wgl_dpy. This prevents wgl_dpy from being reinitialized when a
617           * EGLDisplay is terminated and then initialized again while a
618           * context is still bound. See wgl_initialize() for a more in depth
619           * explanation. */
620          p_atomic_inc(&wgl_dpy->ref_count);
621       }
622    }
623 
624    wgl_destroy_surface(disp, old_dsurf);
625    wgl_destroy_surface(disp, old_rsurf);
626 
627    if (old_ctx) {
628       wgl_destroy_context(disp, old_ctx);
629       wgl_display_release(old_disp);
630    }
631 
632    if (egl_error != EGL_SUCCESS)
633       return _eglError(egl_error, "eglMakeCurrent");
634 
635    return EGL_TRUE;
636 }
637 
638 static _EGLSurface *
wgl_create_window_surface(_EGLDisplay * disp,_EGLConfig * conf,void * native_window,const EGLint * attrib_list)639 wgl_create_window_surface(_EGLDisplay *disp, _EGLConfig *conf,
640                           void *native_window, const EGLint *attrib_list)
641 {
642    struct wgl_egl_display *wgl_dpy = wgl_egl_display(disp);
643    struct wgl_egl_config *wgl_conf = wgl_egl_config(conf);
644 
645    struct wgl_egl_surface *wgl_surf = calloc(1, sizeof(*wgl_surf));
646    if (!wgl_surf)
647       return NULL;
648 
649    if (!_eglInitSurface(&wgl_surf->base, disp, EGL_WINDOW_BIT, conf,
650                         attrib_list, native_window)) {
651       free(wgl_surf);
652       return NULL;
653    }
654 
655    const struct stw_pixelformat_info *stw_conf = wgl_conf->stw_config[1]
656                                                     ? wgl_conf->stw_config[1]
657                                                     : wgl_conf->stw_config[0];
658    wgl_surf->fb = stw_framebuffer_create(
659       native_window, stw_conf, STW_FRAMEBUFFER_EGL_WINDOW, &wgl_dpy->base);
660    if (!wgl_surf->fb) {
661       free(wgl_surf);
662       return NULL;
663    }
664 
665    wgl_surf->fb->swap_interval = 1;
666    stw_framebuffer_unlock(wgl_surf->fb);
667 
668    return &wgl_surf->base;
669 }
670 
671 static _EGLSurface *
wgl_create_pbuffer_surface(_EGLDisplay * disp,_EGLConfig * conf,const EGLint * attrib_list)672 wgl_create_pbuffer_surface(_EGLDisplay *disp, _EGLConfig *conf,
673                            const EGLint *attrib_list)
674 {
675    struct wgl_egl_display *wgl_dpy = wgl_egl_display(disp);
676    struct wgl_egl_config *wgl_conf = wgl_egl_config(conf);
677 
678    struct wgl_egl_surface *wgl_surf = calloc(1, sizeof(*wgl_surf));
679    if (!wgl_surf)
680       return NULL;
681 
682    if (!_eglInitSurface(&wgl_surf->base, disp, EGL_PBUFFER_BIT, conf,
683                         attrib_list, NULL)) {
684       free(wgl_surf);
685       return NULL;
686    }
687 
688    const struct stw_pixelformat_info *stw_conf = wgl_conf->stw_config[1]
689                                                     ? wgl_conf->stw_config[1]
690                                                     : wgl_conf->stw_config[0];
691    wgl_surf->fb = stw_pbuffer_create(stw_conf, wgl_surf->base.Width,
692                                      wgl_surf->base.Height, &wgl_dpy->base);
693    if (!wgl_surf->fb) {
694       free(wgl_surf);
695       return NULL;
696    }
697 
698    wgl_surf->fb->swap_interval = 1;
699    stw_framebuffer_unlock(wgl_surf->fb);
700 
701    return &wgl_surf->base;
702 }
703 
704 static EGLBoolean
wgl_query_surface(_EGLDisplay * disp,_EGLSurface * surf,EGLint attribute,EGLint * value)705 wgl_query_surface(_EGLDisplay *disp, _EGLSurface *surf, EGLint attribute,
706                   EGLint *value)
707 {
708    struct wgl_egl_surface *wgl_surf = wgl_egl_surface(surf);
709    RECT client_rect;
710 
711    switch (attribute) {
712    case EGL_WIDTH:
713    case EGL_HEIGHT:
714       if (GetClientRect(wgl_surf->fb->hWnd, &client_rect)) {
715          surf->Width = client_rect.right;
716          surf->Height = client_rect.bottom;
717       }
718       break;
719    default:
720       break;
721    }
722    return _eglQuerySurface(disp, surf, attribute, value);
723 }
724 
725 static EGLBoolean
wgl_bind_tex_image(_EGLDisplay * disp,_EGLSurface * surf,EGLint buffer)726 wgl_bind_tex_image(_EGLDisplay *disp, _EGLSurface *surf, EGLint buffer)
727 {
728    struct wgl_egl_surface *wgl_surf = wgl_egl_surface(surf);
729 
730    _EGLContext *ctx = _eglGetCurrentContext();
731    struct wgl_egl_context *wgl_ctx = wgl_egl_context(ctx);
732 
733    if (!_eglBindTexImage(disp, surf, buffer))
734       return EGL_FALSE;
735 
736    struct pipe_resource *pres = stw_get_framebuffer_resource(
737       wgl_surf->fb->drawable, ST_ATTACHMENT_FRONT_LEFT);
738    enum pipe_format format = pres->format;
739 
740    switch (surf->TextureFormat) {
741    case EGL_TEXTURE_RGB:
742       switch (format) {
743       case PIPE_FORMAT_R16G16B16A16_FLOAT:
744          format = PIPE_FORMAT_R16G16B16X16_FLOAT;
745          break;
746       case PIPE_FORMAT_B10G10R10A2_UNORM:
747          format = PIPE_FORMAT_B10G10R10X2_UNORM;
748          break;
749       case PIPE_FORMAT_R10G10B10A2_UNORM:
750          format = PIPE_FORMAT_R10G10B10X2_UNORM;
751          break;
752       case PIPE_FORMAT_BGRA8888_UNORM:
753          format = PIPE_FORMAT_BGRX8888_UNORM;
754          break;
755       case PIPE_FORMAT_ARGB8888_UNORM:
756          format = PIPE_FORMAT_XRGB8888_UNORM;
757          break;
758       default:
759          break;
760       }
761       break;
762    case EGL_TEXTURE_RGBA:
763       break;
764    default:
765       assert(!"Unexpected texture format in wgl_bind_tex_image()");
766    }
767 
768    switch (surf->TextureTarget) {
769    case EGL_TEXTURE_2D:
770       break;
771    default:
772       assert(!"Unexpected texture target in wgl_bind_tex_image()");
773    }
774 
775    st_context_teximage(wgl_ctx->ctx->st, GL_TEXTURE_2D, 0, format, pres, false);
776 
777    return EGL_TRUE;
778 }
779 
780 static EGLBoolean
wgl_swap_interval(_EGLDisplay * disp,_EGLSurface * surf,EGLint interval)781 wgl_swap_interval(_EGLDisplay *disp, _EGLSurface *surf, EGLint interval)
782 {
783    struct wgl_egl_surface *wgl_surf = wgl_egl_surface(surf);
784    wgl_surf->fb->swap_interval = interval;
785    return EGL_TRUE;
786 }
787 
788 static EGLBoolean
wgl_swap_buffers(_EGLDisplay * disp,_EGLSurface * draw)789 wgl_swap_buffers(_EGLDisplay *disp, _EGLSurface *draw)
790 {
791    struct wgl_egl_surface *wgl_surf = wgl_egl_surface(draw);
792 
793    stw_framebuffer_lock(wgl_surf->fb);
794    HDC hdc = GetDC(wgl_surf->fb->hWnd);
795    BOOL ret = stw_framebuffer_swap_locked(hdc, wgl_surf->fb);
796    ReleaseDC(wgl_surf->fb->hWnd, hdc);
797 
798    return ret;
799 }
800 
801 static EGLBoolean
wgl_wait_client(_EGLDisplay * disp,_EGLContext * ctx)802 wgl_wait_client(_EGLDisplay *disp, _EGLContext *ctx)
803 {
804    struct wgl_egl_context *wgl_ctx = wgl_egl_context(ctx);
805    struct pipe_fence_handle *fence = NULL;
806    st_context_flush(wgl_ctx->ctx->st, ST_FLUSH_END_OF_FRAME | ST_FLUSH_WAIT,
807                     &fence, NULL, NULL);
808    return EGL_TRUE;
809 }
810 
811 static EGLBoolean
wgl_wait_native(EGLint engine)812 wgl_wait_native(EGLint engine)
813 {
814    if (engine != EGL_CORE_NATIVE_ENGINE)
815       return _eglError(EGL_BAD_PARAMETER, "eglWaitNative");
816    /* It's unclear what "native" means, but GDI is as good a guess as any */
817    GdiFlush();
818    return EGL_TRUE;
819 }
820 
821 static EGLint
egl_error_from_stw_image_error(enum stw_image_error err)822 egl_error_from_stw_image_error(enum stw_image_error err)
823 {
824    switch (err) {
825    case STW_IMAGE_ERROR_SUCCESS:
826       return EGL_SUCCESS;
827    case STW_IMAGE_ERROR_BAD_ALLOC:
828       return EGL_BAD_ALLOC;
829    case STW_IMAGE_ERROR_BAD_MATCH:
830       return EGL_BAD_MATCH;
831    case STW_IMAGE_ERROR_BAD_PARAMETER:
832       return EGL_BAD_PARAMETER;
833    case STW_IMAGE_ERROR_BAD_ACCESS:
834       return EGL_BAD_ACCESS;
835    default:
836       assert(!"unknown stw_image_error code");
837       return EGL_BAD_ALLOC;
838    }
839 }
840 
841 static _EGLImage *
wgl_create_image_khr_texture(_EGLDisplay * disp,_EGLContext * ctx,EGLenum target,EGLClientBuffer buffer,const EGLint * attr_list)842 wgl_create_image_khr_texture(_EGLDisplay *disp, _EGLContext *ctx,
843                              EGLenum target, EGLClientBuffer buffer,
844                              const EGLint *attr_list)
845 {
846    struct wgl_egl_context *wgl_ctx = wgl_egl_context(ctx);
847    struct wgl_egl_image *wgl_img;
848    GLuint texture = (GLuint)(uintptr_t)buffer;
849    _EGLImageAttribs attrs;
850    GLuint depth;
851    GLenum gl_target;
852    enum stw_image_error error;
853 
854    if (texture == 0) {
855       _eglError(EGL_BAD_PARAMETER, "wgl_create_image_khr");
856       return EGL_NO_IMAGE_KHR;
857    }
858 
859    if (!_eglParseImageAttribList(&attrs, disp, attr_list))
860       return EGL_NO_IMAGE_KHR;
861 
862    switch (target) {
863    case EGL_GL_TEXTURE_2D_KHR:
864       depth = 0;
865       gl_target = GL_TEXTURE_2D;
866       break;
867    case EGL_GL_TEXTURE_3D_KHR:
868       depth = attrs.GLTextureZOffset;
869       gl_target = GL_TEXTURE_3D;
870       break;
871    case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR:
872    case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR:
873    case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR:
874    case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR:
875    case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR:
876    case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR:
877       depth = target - EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR;
878       gl_target = GL_TEXTURE_CUBE_MAP;
879       break;
880    default:
881       unreachable("Unexpected target in wgl_create_image_khr_texture()");
882       return EGL_NO_IMAGE_KHR;
883    }
884 
885    wgl_img = malloc(sizeof *wgl_img);
886    if (!wgl_img) {
887       _eglError(EGL_BAD_ALLOC, "wgl_create_image_khr");
888       return EGL_NO_IMAGE_KHR;
889    }
890 
891    _eglInitImage(&wgl_img->base, disp);
892 
893    wgl_img->img = stw_create_image_from_texture(
894       wgl_ctx->ctx, gl_target, texture, depth, attrs.GLTextureLevel, &error);
895    assert(!!wgl_img->img == (error == STW_IMAGE_ERROR_SUCCESS));
896 
897    if (!wgl_img->img) {
898       free(wgl_img);
899       _eglError(egl_error_from_stw_image_error(error), "wgl_create_image_khr");
900       return EGL_NO_IMAGE_KHR;
901    }
902    return &wgl_img->base;
903 }
904 
905 static _EGLImage *
wgl_create_image_khr_renderbuffer(_EGLDisplay * disp,_EGLContext * ctx,EGLClientBuffer buffer,const EGLint * attr_list)906 wgl_create_image_khr_renderbuffer(_EGLDisplay *disp, _EGLContext *ctx,
907                                   EGLClientBuffer buffer,
908                                   const EGLint *attr_list)
909 {
910    struct wgl_egl_context *wgl_ctx = wgl_egl_context(ctx);
911    struct wgl_egl_image *wgl_img;
912    GLuint renderbuffer = (GLuint)(uintptr_t)buffer;
913    enum stw_image_error error;
914 
915    if (renderbuffer == 0) {
916       _eglError(EGL_BAD_PARAMETER, "wgl_create_image_khr");
917       return EGL_NO_IMAGE_KHR;
918    }
919 
920    wgl_img = malloc(sizeof(*wgl_img));
921    if (!wgl_img) {
922       _eglError(EGL_BAD_ALLOC, "wgl_create_image");
923       return NULL;
924    }
925 
926    _eglInitImage(&wgl_img->base, disp);
927 
928    wgl_img->img =
929       stw_create_image_from_renderbuffer(wgl_ctx->ctx, renderbuffer, &error);
930    assert(!!wgl_img->img == (error == STW_IMAGE_ERROR_SUCCESS));
931 
932    if (!wgl_img->img) {
933       free(wgl_img);
934       _eglError(egl_error_from_stw_image_error(error), "wgl_create_image_khr");
935       return EGL_NO_IMAGE_KHR;
936    }
937 
938    return &wgl_img->base;
939 }
940 
941 static _EGLImage *
wgl_create_image_khr(_EGLDisplay * disp,_EGLContext * ctx,EGLenum target,EGLClientBuffer buffer,const EGLint * attr_list)942 wgl_create_image_khr(_EGLDisplay *disp, _EGLContext *ctx, EGLenum target,
943                      EGLClientBuffer buffer, const EGLint *attr_list)
944 {
945    switch (target) {
946    case EGL_GL_TEXTURE_2D_KHR:
947    case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR:
948    case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR:
949    case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR:
950    case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR:
951    case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR:
952    case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR:
953    case EGL_GL_TEXTURE_3D_KHR:
954       return wgl_create_image_khr_texture(disp, ctx, target, buffer, attr_list);
955    case EGL_GL_RENDERBUFFER_KHR:
956       return wgl_create_image_khr_renderbuffer(disp, ctx, buffer, attr_list);
957    default:
958       _eglError(EGL_BAD_PARAMETER, "wgl_create_image_khr");
959       return EGL_NO_IMAGE_KHR;
960    }
961 }
962 
963 static EGLBoolean
wgl_destroy_image_khr(_EGLDisplay * disp,_EGLImage * img)964 wgl_destroy_image_khr(_EGLDisplay *disp, _EGLImage *img)
965 {
966    struct wgl_egl_image *wgl_img = wgl_egl_image(img);
967    stw_destroy_image(wgl_img->img);
968    free(wgl_img);
969    return EGL_TRUE;
970 }
971 
972 static _EGLSync *
wgl_create_sync_khr(_EGLDisplay * disp,EGLenum type,const EGLAttrib * attrib_list)973 wgl_create_sync_khr(_EGLDisplay *disp, EGLenum type,
974                     const EGLAttrib *attrib_list)
975 {
976 
977    _EGLContext *ctx = _eglGetCurrentContext();
978    struct wgl_egl_context *wgl_ctx = wgl_egl_context(ctx);
979    struct wgl_egl_sync *wgl_sync;
980 
981    struct st_context *st = wgl_ctx ? wgl_ctx->ctx->st : NULL;
982 
983    wgl_sync = calloc(1, sizeof(struct wgl_egl_sync));
984    if (!wgl_sync) {
985       _eglError(EGL_BAD_ALLOC, "eglCreateSyncKHR");
986       return NULL;
987    }
988 
989    if (!_eglInitSync(&wgl_sync->base, disp, type, attrib_list)) {
990       free(wgl_sync);
991       return NULL;
992    }
993 
994    switch (type) {
995    case EGL_SYNC_FENCE_KHR:
996       st_context_flush(st, 0, &wgl_sync->fence, NULL, NULL);
997       if (!wgl_sync->fence) {
998          _eglError(EGL_BAD_ALLOC, "eglCreateSyncKHR");
999          free(wgl_sync);
1000          return NULL;
1001       }
1002       break;
1003 
1004    case EGL_SYNC_REUSABLE_KHR:
1005       wgl_sync->event = CreateEvent(NULL, true, false, NULL);
1006       if (!wgl_sync->event) {
1007          _eglError(EGL_BAD_ALLOC, "eglCreateSyncKHR");
1008          free(wgl_sync);
1009          return NULL;
1010       }
1011    }
1012 
1013    wgl_sync->refcount = 1;
1014    return &wgl_sync->base;
1015 }
1016 
1017 static void
wgl_egl_unref_sync(struct wgl_egl_display * wgl_dpy,struct wgl_egl_sync * wgl_sync)1018 wgl_egl_unref_sync(struct wgl_egl_display *wgl_dpy,
1019                    struct wgl_egl_sync *wgl_sync)
1020 {
1021    if (InterlockedDecrement((volatile LONG *)&wgl_sync->refcount) > 0)
1022       return;
1023 
1024    if (wgl_sync->fence)
1025       wgl_dpy->screen->fence_reference(wgl_dpy->screen, &wgl_sync->fence, NULL);
1026    if (wgl_sync->event)
1027       CloseHandle(wgl_sync->event);
1028    free(wgl_sync);
1029 }
1030 
1031 static EGLBoolean
wgl_destroy_sync_khr(_EGLDisplay * disp,_EGLSync * sync)1032 wgl_destroy_sync_khr(_EGLDisplay *disp, _EGLSync *sync)
1033 {
1034    struct wgl_egl_display *wgl_dpy = wgl_egl_display(disp);
1035    struct wgl_egl_sync *wgl_sync = wgl_egl_sync(sync);
1036    wgl_egl_unref_sync(wgl_dpy, wgl_sync);
1037    return EGL_TRUE;
1038 }
1039 
1040 static EGLint
wgl_client_wait_sync_khr(_EGLDisplay * disp,_EGLSync * sync,EGLint flags,EGLTime timeout)1041 wgl_client_wait_sync_khr(_EGLDisplay *disp, _EGLSync *sync, EGLint flags,
1042                          EGLTime timeout)
1043 {
1044    _EGLContext *ctx = _eglGetCurrentContext();
1045    struct wgl_egl_display *wgl_dpy = wgl_egl_display(disp);
1046    struct wgl_egl_context *wgl_ctx = wgl_egl_context(ctx);
1047    struct wgl_egl_sync *wgl_sync = wgl_egl_sync(sync);
1048 
1049    EGLint ret = EGL_CONDITION_SATISFIED_KHR;
1050 
1051    /* the sync object should take a reference while waiting */
1052    InterlockedIncrement((volatile LONG *)&wgl_sync->refcount);
1053 
1054    switch (sync->Type) {
1055    case EGL_SYNC_FENCE_KHR:
1056       if (wgl_dpy->screen->fence_finish(wgl_dpy->screen, NULL, wgl_sync->fence,
1057                                         timeout))
1058          wgl_sync->base.SyncStatus = EGL_SIGNALED_KHR;
1059       else
1060          ret = EGL_TIMEOUT_EXPIRED_KHR;
1061       break;
1062 
1063    case EGL_SYNC_REUSABLE_KHR:
1064       if (wgl_ctx && wgl_sync->base.SyncStatus == EGL_UNSIGNALED_KHR &&
1065           (flags & EGL_SYNC_FLUSH_COMMANDS_BIT_KHR)) {
1066          /* flush context if EGL_SYNC_FLUSH_COMMANDS_BIT_KHR is set */
1067          wgl_gl_flush();
1068       }
1069 
1070       DWORD wait_milliseconds = (timeout == EGL_FOREVER_KHR)
1071                                    ? INFINITE
1072                                    : (DWORD)(timeout / 1000000ull);
1073       DWORD wait_ret = WaitForSingleObject(wgl_sync->event, wait_milliseconds);
1074       switch (wait_ret) {
1075       case WAIT_OBJECT_0:
1076          assert(wgl_sync->base.SyncStatus == EGL_SIGNALED_KHR);
1077          break;
1078       case WAIT_TIMEOUT:
1079          assert(wgl_sync->base.SyncStatus == EGL_UNSIGNALED_KHR);
1080          ret = EGL_TIMEOUT_EXPIRED_KHR;
1081          break;
1082       default:
1083          _eglError(EGL_BAD_ACCESS, "eglClientWaitSyncKHR");
1084          ret = EGL_FALSE;
1085          break;
1086       }
1087       break;
1088    }
1089    wgl_egl_unref_sync(wgl_dpy, wgl_sync);
1090 
1091    return ret;
1092 }
1093 
1094 static EGLint
wgl_wait_sync_khr(_EGLDisplay * disp,_EGLSync * sync)1095 wgl_wait_sync_khr(_EGLDisplay *disp, _EGLSync *sync)
1096 {
1097    _EGLContext *ctx = _eglGetCurrentContext();
1098    struct wgl_egl_context *wgl_ctx = wgl_egl_context(ctx);
1099    struct wgl_egl_sync *wgl_sync = wgl_egl_sync(sync);
1100 
1101    if (!wgl_sync->fence)
1102       return EGL_TRUE;
1103 
1104    struct pipe_context *pipe = wgl_ctx->ctx->st->pipe;
1105    if (pipe->fence_server_sync)
1106       pipe->fence_server_sync(pipe, wgl_sync->fence);
1107 
1108    return EGL_TRUE;
1109 }
1110 
1111 static EGLBoolean
wgl_signal_sync_khr(_EGLDisplay * disp,_EGLSync * sync,EGLenum mode)1112 wgl_signal_sync_khr(_EGLDisplay *disp, _EGLSync *sync, EGLenum mode)
1113 {
1114    struct wgl_egl_sync *wgl_sync = wgl_egl_sync(sync);
1115 
1116    if (sync->Type != EGL_SYNC_REUSABLE_KHR)
1117       return _eglError(EGL_BAD_MATCH, "eglSignalSyncKHR");
1118 
1119    if (mode != EGL_SIGNALED_KHR && mode != EGL_UNSIGNALED_KHR)
1120       return _eglError(EGL_BAD_ATTRIBUTE, "eglSignalSyncKHR");
1121 
1122    wgl_sync->base.SyncStatus = mode;
1123 
1124    if (mode == EGL_SIGNALED_KHR) {
1125       if (!SetEvent(wgl_sync->event))
1126          return _eglError(EGL_BAD_ACCESS, "eglSignalSyncKHR");
1127    } else {
1128       if (!ResetEvent(wgl_sync->event))
1129          return _eglError(EGL_BAD_ACCESS, "eglSignalSyncKHR");
1130    }
1131 
1132    return EGL_TRUE;
1133 }
1134 
1135 static const char *
wgl_query_driver_name(_EGLDisplay * disp)1136 wgl_query_driver_name(_EGLDisplay *disp)
1137 {
1138    return stw_get_device()->stw_winsys->get_name();
1139 }
1140 
1141 static char *
wgl_query_driver_config(_EGLDisplay * disp)1142 wgl_query_driver_config(_EGLDisplay *disp)
1143 {
1144    return stw_get_config_xml();
1145 }
1146 
1147 static int
wgl_interop_query_device_info(_EGLDisplay * disp,_EGLContext * ctx,struct mesa_glinterop_device_info * out)1148 wgl_interop_query_device_info(_EGLDisplay *disp, _EGLContext *ctx,
1149                               struct mesa_glinterop_device_info *out)
1150 {
1151    struct wgl_egl_context *wgl_ctx = wgl_egl_context(ctx);
1152    return stw_interop_query_device_info(wgl_ctx->ctx, out);
1153 }
1154 
1155 static int
wgl_interop_export_object(_EGLDisplay * disp,_EGLContext * ctx,struct mesa_glinterop_export_in * in,struct mesa_glinterop_export_out * out)1156 wgl_interop_export_object(_EGLDisplay *disp, _EGLContext *ctx,
1157                           struct mesa_glinterop_export_in *in,
1158                           struct mesa_glinterop_export_out *out)
1159 {
1160    struct wgl_egl_context *wgl_ctx = wgl_egl_context(ctx);
1161    return stw_interop_export_object(wgl_ctx->ctx, in, out);
1162 }
1163 
1164 static int
wgl_interop_flush_objects(_EGLDisplay * disp,_EGLContext * ctx,unsigned count,struct mesa_glinterop_export_in * objects,struct mesa_glinterop_flush_out * out)1165 wgl_interop_flush_objects(_EGLDisplay *disp, _EGLContext *ctx, unsigned count,
1166                           struct mesa_glinterop_export_in *objects,
1167                           struct mesa_glinterop_flush_out *out)
1168 {
1169    struct wgl_egl_context *wgl_ctx = wgl_egl_context(ctx);
1170    return stw_interop_flush_objects(wgl_ctx->ctx, count, objects, out);
1171 }
1172 
1173 struct _egl_driver _eglDriver = {
1174    .Initialize = wgl_initialize,
1175    .Terminate = wgl_terminate,
1176    .CreateContext = wgl_create_context,
1177    .DestroyContext = wgl_destroy_context,
1178    .MakeCurrent = wgl_make_current,
1179    .CreateWindowSurface = wgl_create_window_surface,
1180    .CreatePbufferSurface = wgl_create_pbuffer_surface,
1181    .DestroySurface = wgl_destroy_surface,
1182    .QuerySurface = wgl_query_surface,
1183    .BindTexImage = wgl_bind_tex_image,
1184    .ReleaseTexImage = _eglReleaseTexImage,
1185    .SwapInterval = wgl_swap_interval,
1186    .SwapBuffers = wgl_swap_buffers,
1187    .WaitClient = wgl_wait_client,
1188    .WaitNative = wgl_wait_native,
1189    .CreateImageKHR = wgl_create_image_khr,
1190    .DestroyImageKHR = wgl_destroy_image_khr,
1191    .CreateSyncKHR = wgl_create_sync_khr,
1192    .DestroySyncKHR = wgl_destroy_sync_khr,
1193    .ClientWaitSyncKHR = wgl_client_wait_sync_khr,
1194    .WaitSyncKHR = wgl_wait_sync_khr,
1195    .SignalSyncKHR = wgl_signal_sync_khr,
1196    .QueryDriverName = wgl_query_driver_name,
1197    .QueryDriverConfig = wgl_query_driver_config,
1198    .GLInteropQueryDeviceInfo = wgl_interop_query_device_info,
1199    .GLInteropExportObject = wgl_interop_export_object,
1200    .GLInteropFlushObjects = wgl_interop_flush_objects,
1201 };
1202