• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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->caps.context_priority_mask;
273    disp->Extensions.NV_context_priority_realtime =
274       disp->Extensions.IMG_context_priority &
275       (1 << __EGL_CONTEXT_PRIORITY_REALTIME_BIT);
276 
277    disp->Extensions.EXT_pixel_format_float = EGL_TRUE;
278 
279    if (wgl_dpy->screen->is_format_supported(
280           wgl_dpy->screen, PIPE_FORMAT_B8G8R8A8_SRGB, PIPE_TEXTURE_2D, 0, 0,
281           PIPE_BIND_RENDER_TARGET))
282       disp->Extensions.KHR_gl_colorspace = EGL_TRUE;
283 
284    disp->Extensions.KHR_create_context = EGL_TRUE;
285 
286    disp->Extensions.KHR_image_base = EGL_TRUE;
287    disp->Extensions.KHR_gl_renderbuffer_image = EGL_TRUE;
288    disp->Extensions.KHR_gl_texture_2D_image = EGL_TRUE;
289    disp->Extensions.KHR_gl_texture_cubemap_image = EGL_TRUE;
290    disp->Extensions.KHR_gl_texture_3D_image = EGL_TRUE;
291 
292    disp->Extensions.KHR_fence_sync = EGL_TRUE;
293    disp->Extensions.KHR_reusable_sync = EGL_TRUE;
294    disp->Extensions.KHR_wait_sync = EGL_TRUE;
295 
296    if (!wgl_add_configs(disp)) {
297       err = "wgl: failed to add configs";
298       goto cleanup;
299    }
300 
301    return EGL_TRUE;
302 
303 cleanup:
304    wgl_display_destroy(disp);
305    return _eglError(EGL_NOT_INITIALIZED, err);
306 }
307 
308 static EGLBoolean
wgl_initialize(_EGLDisplay * disp)309 wgl_initialize(_EGLDisplay *disp)
310 {
311    EGLBoolean ret = EGL_FALSE;
312    struct wgl_egl_display *wgl_dpy = wgl_egl_display(disp);
313 
314    /* In the case where the application calls eglMakeCurrent(context1),
315     * eglTerminate, then eglInitialize again (without a call to eglReleaseThread
316     * or eglMakeCurrent(NULL) before that), wgl_dpy structure is still
317     * initialized, as we need it to be able to free context1 correctly.
318     *
319     * It would probably be safest to forcibly release the display with
320     * wgl_display_release, to make sure the display is reinitialized correctly.
321     * However, the EGL spec states that we need to keep a reference to the
322     * current context (so we cannot call wgl_make_current(NULL)), and therefore
323     * we would leak context1 as we would be missing the old display connection
324     * to free it up correctly.
325     */
326    if (wgl_dpy) {
327       p_atomic_inc(&wgl_dpy->ref_count);
328       return EGL_TRUE;
329    }
330 
331    switch (disp->Platform) {
332    case _EGL_PLATFORM_SURFACELESS:
333       ret = wgl_initialize_impl(disp, NULL);
334       break;
335    case _EGL_PLATFORM_WINDOWS:
336       ret = wgl_initialize_impl(disp, disp->PlatformDisplay);
337       break;
338    default:
339       unreachable("Callers ensure we cannot get here.");
340       return EGL_FALSE;
341    }
342 
343    if (!ret)
344       return EGL_FALSE;
345 
346    wgl_dpy = wgl_egl_display(disp);
347    p_atomic_inc(&wgl_dpy->ref_count);
348 
349    return EGL_TRUE;
350 }
351 
352 /**
353  * Decrement display reference count, and free up display if necessary.
354  */
355 static void
wgl_display_release(_EGLDisplay * disp)356 wgl_display_release(_EGLDisplay *disp)
357 {
358    struct wgl_egl_display *wgl_dpy;
359 
360    if (!disp)
361       return;
362 
363    wgl_dpy = wgl_egl_display(disp);
364 
365    assert(wgl_dpy->ref_count > 0);
366    if (!p_atomic_dec_zero(&wgl_dpy->ref_count))
367       return;
368 
369    _eglCleanupDisplay(disp);
370    wgl_display_destroy(disp);
371 }
372 
373 /**
374  * Called via eglTerminate(), drv->Terminate().
375  *
376  * This must be guaranteed to be called exactly once, even if eglTerminate is
377  * called many times (without a eglInitialize in between).
378  */
379 static EGLBoolean
wgl_terminate(_EGLDisplay * disp)380 wgl_terminate(_EGLDisplay *disp)
381 {
382    /* Release all non-current Context/Surfaces. */
383    _eglReleaseDisplayResources(disp);
384 
385    wgl_display_release(disp);
386 
387    return EGL_TRUE;
388 }
389 
390 /**
391  * Called via eglCreateContext(), drv->CreateContext().
392  */
393 static _EGLContext *
wgl_create_context(_EGLDisplay * disp,_EGLConfig * conf,_EGLContext * share_list,const EGLint * attrib_list)394 wgl_create_context(_EGLDisplay *disp, _EGLConfig *conf, _EGLContext *share_list,
395                    const EGLint *attrib_list)
396 {
397    struct wgl_egl_context *wgl_ctx;
398    struct wgl_egl_display *wgl_dpy = wgl_egl_display(disp);
399    struct wgl_egl_context *wgl_ctx_shared = wgl_egl_context(share_list);
400    struct stw_context *shared = wgl_ctx_shared ? wgl_ctx_shared->ctx : NULL;
401    struct wgl_egl_config *wgl_config = wgl_egl_config(conf);
402    const struct stw_pixelformat_info *stw_config;
403 
404    wgl_ctx = malloc(sizeof(*wgl_ctx));
405    if (!wgl_ctx) {
406       _eglError(EGL_BAD_ALLOC, "eglCreateContext");
407       return NULL;
408    }
409 
410    if (!_eglInitContext(&wgl_ctx->base, disp, conf, share_list, attrib_list))
411       goto cleanup;
412 
413    unsigned profile_mask = 0;
414    switch (wgl_ctx->base.ClientAPI) {
415    case EGL_OPENGL_ES_API:
416       profile_mask = WGL_CONTEXT_ES_PROFILE_BIT_EXT;
417       break;
418    case EGL_OPENGL_API:
419       if ((wgl_ctx->base.ClientMajorVersion >= 4 ||
420            (wgl_ctx->base.ClientMajorVersion == 3 &&
421             wgl_ctx->base.ClientMinorVersion >= 2)) &&
422           wgl_ctx->base.Profile == EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR)
423          profile_mask = WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
424       else if (wgl_ctx->base.ClientMajorVersion == 3 &&
425                wgl_ctx->base.ClientMinorVersion == 1)
426          profile_mask = WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
427       else
428          profile_mask = WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
429       break;
430    default:
431       _eglError(EGL_BAD_PARAMETER, "eglCreateContext");
432       free(wgl_ctx);
433       return NULL;
434    }
435 
436    if (conf != NULL) {
437       /* The config chosen here isn't necessarily
438        * used for surfaces later.
439        * A pixmap surface will use the single config.
440        * This opportunity depends on disabling the
441        * doubleBufferMode check in
442        * src/mesa/main/context.c:check_compatible()
443        */
444       if (wgl_config->stw_config[1])
445          stw_config = wgl_config->stw_config[1];
446       else
447          stw_config = wgl_config->stw_config[0];
448    } else
449       stw_config = NULL;
450 
451    unsigned flags = 0;
452    if (wgl_ctx->base.Flags & EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR)
453       flags |= WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
454    if (wgl_ctx->base.Flags & EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR)
455       flags |= WGL_CONTEXT_DEBUG_BIT_ARB;
456    unsigned resetStrategy = WGL_NO_RESET_NOTIFICATION_ARB;
457    if (wgl_ctx->base.ResetNotificationStrategy != EGL_NO_RESET_NOTIFICATION)
458       resetStrategy = WGL_LOSE_CONTEXT_ON_RESET_ARB;
459    wgl_ctx->ctx = stw_create_context_attribs(
460       disp->PlatformDisplay, 0, shared, &wgl_dpy->base,
461       wgl_ctx->base.ClientMajorVersion, wgl_ctx->base.ClientMinorVersion, flags,
462       profile_mask, stw_config, resetStrategy);
463 
464    if (!wgl_ctx->ctx)
465       goto cleanup;
466 
467    return &wgl_ctx->base;
468 
469 cleanup:
470    free(wgl_ctx);
471    return NULL;
472 }
473 
474 /**
475  * Called via eglDestroyContext(), drv->DestroyContext().
476  */
477 static EGLBoolean
wgl_destroy_context(_EGLDisplay * disp,_EGLContext * ctx)478 wgl_destroy_context(_EGLDisplay *disp, _EGLContext *ctx)
479 {
480    struct wgl_egl_context *wgl_ctx = wgl_egl_context(ctx);
481 
482    if (_eglPutContext(ctx)) {
483       stw_destroy_context(wgl_ctx->ctx);
484       free(wgl_ctx);
485    }
486 
487    return EGL_TRUE;
488 }
489 
490 static EGLBoolean
wgl_destroy_surface(_EGLDisplay * disp,_EGLSurface * surf)491 wgl_destroy_surface(_EGLDisplay *disp, _EGLSurface *surf)
492 {
493    struct wgl_egl_surface *wgl_surf = wgl_egl_surface(surf);
494 
495    if (!_eglPutSurface(surf))
496       return EGL_TRUE;
497 
498    if (wgl_surf->fb->owner == STW_FRAMEBUFFER_PBUFFER) {
499       DestroyWindow(wgl_surf->fb->hWnd);
500    } else {
501       struct stw_context *ctx = stw_current_context();
502       stw_framebuffer_lock(wgl_surf->fb);
503       stw_framebuffer_release_locked(wgl_surf->fb, ctx ? ctx->st : NULL);
504    }
505    return EGL_TRUE;
506 }
507 
508 static void
wgl_gl_flush_get(_glapi_proc * glFlush)509 wgl_gl_flush_get(_glapi_proc *glFlush)
510 {
511    *glFlush = _glapi_get_proc_address("glFlush");
512 }
513 
514 static void
wgl_gl_flush()515 wgl_gl_flush()
516 {
517    static void (*glFlush)(void);
518    static util_once_flag once = UTIL_ONCE_FLAG_INIT;
519 
520    util_call_once_data(&once, (util_call_once_data_func)wgl_gl_flush_get,
521                        &glFlush);
522 
523    /* if glFlush is not available things are horribly broken */
524    if (!glFlush) {
525       _eglLog(_EGL_WARNING, "wgl: failed to find glFlush entry point");
526       return;
527    }
528 
529    glFlush();
530 }
531 
532 /**
533  * Called via eglMakeCurrent(), drv->MakeCurrent().
534  */
535 static EGLBoolean
wgl_make_current(_EGLDisplay * disp,_EGLSurface * dsurf,_EGLSurface * rsurf,_EGLContext * ctx)536 wgl_make_current(_EGLDisplay *disp, _EGLSurface *dsurf, _EGLSurface *rsurf,
537                  _EGLContext *ctx)
538 {
539    struct wgl_egl_display *wgl_dpy = wgl_egl_display(disp);
540    struct wgl_egl_context *wgl_ctx = wgl_egl_context(ctx);
541    _EGLDisplay *old_disp = NULL;
542    _EGLContext *old_ctx;
543    _EGLSurface *old_dsurf, *old_rsurf;
544    _EGLSurface *tmp_dsurf, *tmp_rsurf;
545    struct stw_framebuffer *ddraw, *rdraw;
546    struct stw_context *cctx;
547    EGLint egl_error = EGL_SUCCESS;
548 
549    if (!wgl_dpy)
550       return _eglError(EGL_NOT_INITIALIZED, "eglMakeCurrent");
551 
552    /* make new bindings, set the EGL error otherwise */
553    if (!_eglBindContext(ctx, dsurf, rsurf, &old_ctx, &old_dsurf, &old_rsurf))
554       return EGL_FALSE;
555 
556    if (old_ctx) {
557       struct stw_context *old_cctx = wgl_egl_context(old_ctx)->ctx;
558       old_disp = old_ctx->Resource.Display;
559 
560       /* flush before context switch */
561       wgl_gl_flush();
562 
563       stw_unbind_context(old_cctx);
564    }
565 
566    ddraw = (dsurf) ? wgl_egl_surface(dsurf)->fb : NULL;
567    rdraw = (rsurf) ? wgl_egl_surface(rsurf)->fb : NULL;
568    cctx = (wgl_ctx) ? wgl_ctx->ctx : NULL;
569 
570    if (cctx || ddraw || rdraw) {
571       if (!stw_make_current(ddraw, rdraw, cctx)) {
572          _EGLContext *tmp_ctx;
573 
574          /* stw_make_current failed. We cannot tell for sure why, but
575           * setting the error to EGL_BAD_MATCH is surely better than leaving it
576           * as EGL_SUCCESS.
577           */
578          egl_error = EGL_BAD_MATCH;
579 
580          /* undo the previous _eglBindContext */
581          _eglBindContext(old_ctx, old_dsurf, old_rsurf, &ctx, &tmp_dsurf,
582                          &tmp_rsurf);
583          assert(&wgl_ctx->base == ctx && tmp_dsurf == dsurf &&
584                 tmp_rsurf == rsurf);
585 
586          _eglPutSurface(dsurf);
587          _eglPutSurface(rsurf);
588          _eglPutContext(ctx);
589 
590          _eglPutSurface(old_dsurf);
591          _eglPutSurface(old_rsurf);
592          _eglPutContext(old_ctx);
593 
594          ddraw = (old_dsurf) ? wgl_egl_surface(old_dsurf)->fb : NULL;
595          rdraw = (old_rsurf) ? wgl_egl_surface(old_rsurf)->fb : NULL;
596          cctx = (old_ctx) ? wgl_egl_context(old_ctx)->ctx : NULL;
597 
598          /* undo the previous _eglBindContext */
599          if (stw_make_current(ddraw, rdraw, cctx)) {
600             return _eglError(egl_error, "eglMakeCurrent");
601          }
602 
603          /* We cannot restore the same state as it was before calling
604           * eglMakeCurrent() and the spec isn't clear about what to do. We
605           * can prevent EGL from calling into the DRI driver with no DRI
606           * context bound.
607           */
608          dsurf = rsurf = NULL;
609          ctx = NULL;
610 
611          _eglBindContext(ctx, dsurf, rsurf, &tmp_ctx, &tmp_dsurf, &tmp_rsurf);
612          assert(tmp_ctx == old_ctx && tmp_dsurf == old_dsurf &&
613                 tmp_rsurf == old_rsurf);
614 
615          _eglLog(_EGL_WARNING, "wgl: failed to rebind the previous context");
616       } else {
617          /* _eglBindContext succeeded, so take a reference on the
618           * wgl_dpy. This prevents wgl_dpy from being reinitialized when a
619           * EGLDisplay is terminated and then initialized again while a
620           * context is still bound. See wgl_initialize() for a more in depth
621           * explanation. */
622          p_atomic_inc(&wgl_dpy->ref_count);
623       }
624    }
625 
626    wgl_destroy_surface(disp, old_dsurf);
627    wgl_destroy_surface(disp, old_rsurf);
628 
629    if (old_ctx) {
630       wgl_destroy_context(disp, old_ctx);
631       wgl_display_release(old_disp);
632    }
633 
634    if (egl_error != EGL_SUCCESS)
635       return _eglError(egl_error, "eglMakeCurrent");
636 
637    return EGL_TRUE;
638 }
639 
640 static _EGLSurface *
wgl_create_window_surface(_EGLDisplay * disp,_EGLConfig * conf,void * native_window,const EGLint * attrib_list)641 wgl_create_window_surface(_EGLDisplay *disp, _EGLConfig *conf,
642                           void *native_window, const EGLint *attrib_list)
643 {
644    struct wgl_egl_display *wgl_dpy = wgl_egl_display(disp);
645    struct wgl_egl_config *wgl_conf = wgl_egl_config(conf);
646 
647    struct wgl_egl_surface *wgl_surf = calloc(1, sizeof(*wgl_surf));
648    if (!wgl_surf)
649       return NULL;
650 
651    if (!_eglInitSurface(&wgl_surf->base, disp, EGL_WINDOW_BIT, conf,
652                         attrib_list, native_window)) {
653       free(wgl_surf);
654       return NULL;
655    }
656 
657    const struct stw_pixelformat_info *stw_conf = wgl_conf->stw_config[1]
658                                                     ? wgl_conf->stw_config[1]
659                                                     : wgl_conf->stw_config[0];
660    wgl_surf->fb = stw_framebuffer_create(
661       native_window, stw_conf, STW_FRAMEBUFFER_EGL_WINDOW, &wgl_dpy->base);
662    if (!wgl_surf->fb) {
663       free(wgl_surf);
664       return NULL;
665    }
666 
667    wgl_surf->fb->swap_interval = 1;
668    stw_framebuffer_unlock(wgl_surf->fb);
669 
670    return &wgl_surf->base;
671 }
672 
673 static _EGLSurface *
wgl_create_pbuffer_surface(_EGLDisplay * disp,_EGLConfig * conf,const EGLint * attrib_list)674 wgl_create_pbuffer_surface(_EGLDisplay *disp, _EGLConfig *conf,
675                            const EGLint *attrib_list)
676 {
677    struct wgl_egl_display *wgl_dpy = wgl_egl_display(disp);
678    struct wgl_egl_config *wgl_conf = wgl_egl_config(conf);
679 
680    struct wgl_egl_surface *wgl_surf = calloc(1, sizeof(*wgl_surf));
681    if (!wgl_surf)
682       return NULL;
683 
684    if (!_eglInitSurface(&wgl_surf->base, disp, EGL_PBUFFER_BIT, conf,
685                         attrib_list, NULL)) {
686       free(wgl_surf);
687       return NULL;
688    }
689 
690    const struct stw_pixelformat_info *stw_conf = wgl_conf->stw_config[1]
691                                                     ? wgl_conf->stw_config[1]
692                                                     : wgl_conf->stw_config[0];
693    wgl_surf->fb = stw_pbuffer_create(stw_conf, wgl_surf->base.Width,
694                                      wgl_surf->base.Height, &wgl_dpy->base);
695    if (!wgl_surf->fb) {
696       free(wgl_surf);
697       return NULL;
698    }
699 
700    wgl_surf->fb->swap_interval = 1;
701    stw_framebuffer_unlock(wgl_surf->fb);
702 
703    return &wgl_surf->base;
704 }
705 
706 static EGLBoolean
wgl_query_surface(_EGLDisplay * disp,_EGLSurface * surf,EGLint attribute,EGLint * value)707 wgl_query_surface(_EGLDisplay *disp, _EGLSurface *surf, EGLint attribute,
708                   EGLint *value)
709 {
710    struct wgl_egl_surface *wgl_surf = wgl_egl_surface(surf);
711    RECT client_rect;
712 
713    switch (attribute) {
714    case EGL_WIDTH:
715    case EGL_HEIGHT:
716       if (GetClientRect(wgl_surf->fb->hWnd, &client_rect)) {
717          surf->Width = client_rect.right;
718          surf->Height = client_rect.bottom;
719       }
720       break;
721    default:
722       break;
723    }
724    return _eglQuerySurface(disp, surf, attribute, value);
725 }
726 
727 static EGLBoolean
wgl_bind_tex_image(_EGLDisplay * disp,_EGLSurface * surf,EGLint buffer)728 wgl_bind_tex_image(_EGLDisplay *disp, _EGLSurface *surf, EGLint buffer)
729 {
730    struct wgl_egl_surface *wgl_surf = wgl_egl_surface(surf);
731 
732    _EGLContext *ctx = _eglGetCurrentContext();
733    struct wgl_egl_context *wgl_ctx = wgl_egl_context(ctx);
734 
735    if (!_eglBindTexImage(disp, surf, buffer))
736       return EGL_FALSE;
737 
738    struct pipe_resource *pres = stw_get_framebuffer_resource(
739       wgl_surf->fb->drawable, ST_ATTACHMENT_FRONT_LEFT);
740    enum pipe_format format = pres->format;
741 
742    switch (surf->TextureFormat) {
743    case EGL_TEXTURE_RGB:
744       switch (format) {
745       case PIPE_FORMAT_R16G16B16A16_FLOAT:
746          format = PIPE_FORMAT_R16G16B16X16_FLOAT;
747          break;
748       case PIPE_FORMAT_B10G10R10A2_UNORM:
749          format = PIPE_FORMAT_B10G10R10X2_UNORM;
750          break;
751       case PIPE_FORMAT_R10G10B10A2_UNORM:
752          format = PIPE_FORMAT_R10G10B10X2_UNORM;
753          break;
754       case PIPE_FORMAT_BGRA8888_UNORM:
755          format = PIPE_FORMAT_BGRX8888_UNORM;
756          break;
757       case PIPE_FORMAT_ARGB8888_UNORM:
758          format = PIPE_FORMAT_XRGB8888_UNORM;
759          break;
760       default:
761          break;
762       }
763       break;
764    case EGL_TEXTURE_RGBA:
765       break;
766    default:
767       assert(!"Unexpected texture format in wgl_bind_tex_image()");
768    }
769 
770    switch (surf->TextureTarget) {
771    case EGL_TEXTURE_2D:
772       break;
773    default:
774       assert(!"Unexpected texture target in wgl_bind_tex_image()");
775    }
776 
777    st_context_teximage(wgl_ctx->ctx->st, GL_TEXTURE_2D, 0, format, pres, false);
778 
779    return EGL_TRUE;
780 }
781 
782 static EGLBoolean
wgl_swap_interval(_EGLDisplay * disp,_EGLSurface * surf,EGLint interval)783 wgl_swap_interval(_EGLDisplay *disp, _EGLSurface *surf, EGLint interval)
784 {
785    struct wgl_egl_surface *wgl_surf = wgl_egl_surface(surf);
786    wgl_surf->fb->swap_interval = interval;
787    return EGL_TRUE;
788 }
789 
790 static EGLBoolean
wgl_swap_buffers(_EGLDisplay * disp,_EGLSurface * draw)791 wgl_swap_buffers(_EGLDisplay *disp, _EGLSurface *draw)
792 {
793    struct wgl_egl_surface *wgl_surf = wgl_egl_surface(draw);
794 
795    stw_framebuffer_lock(wgl_surf->fb);
796    HDC hdc = GetDC(wgl_surf->fb->hWnd);
797    BOOL ret = stw_framebuffer_swap_locked(hdc, wgl_surf->fb);
798    ReleaseDC(wgl_surf->fb->hWnd, hdc);
799 
800    return ret;
801 }
802 
803 static EGLBoolean
wgl_wait_client(_EGLDisplay * disp,_EGLContext * ctx)804 wgl_wait_client(_EGLDisplay *disp, _EGLContext *ctx)
805 {
806    struct wgl_egl_context *wgl_ctx = wgl_egl_context(ctx);
807    struct pipe_fence_handle *fence = NULL;
808    st_context_flush(wgl_ctx->ctx->st, ST_FLUSH_END_OF_FRAME | ST_FLUSH_WAIT,
809                     &fence, NULL, NULL);
810    return EGL_TRUE;
811 }
812 
813 static EGLBoolean
wgl_wait_native(EGLint engine)814 wgl_wait_native(EGLint engine)
815 {
816    if (engine != EGL_CORE_NATIVE_ENGINE)
817       return _eglError(EGL_BAD_PARAMETER, "eglWaitNative");
818    /* It's unclear what "native" means, but GDI is as good a guess as any */
819    GdiFlush();
820    return EGL_TRUE;
821 }
822 
823 static EGLint
egl_error_from_stw_image_error(enum stw_image_error err)824 egl_error_from_stw_image_error(enum stw_image_error err)
825 {
826    switch (err) {
827    case STW_IMAGE_ERROR_SUCCESS:
828       return EGL_SUCCESS;
829    case STW_IMAGE_ERROR_BAD_ALLOC:
830       return EGL_BAD_ALLOC;
831    case STW_IMAGE_ERROR_BAD_MATCH:
832       return EGL_BAD_MATCH;
833    case STW_IMAGE_ERROR_BAD_PARAMETER:
834       return EGL_BAD_PARAMETER;
835    case STW_IMAGE_ERROR_BAD_ACCESS:
836       return EGL_BAD_ACCESS;
837    default:
838       assert(!"unknown stw_image_error code");
839       return EGL_BAD_ALLOC;
840    }
841 }
842 
843 static _EGLImage *
wgl_create_image_khr_texture(_EGLDisplay * disp,_EGLContext * ctx,EGLenum target,EGLClientBuffer buffer,const EGLint * attr_list)844 wgl_create_image_khr_texture(_EGLDisplay *disp, _EGLContext *ctx,
845                              EGLenum target, EGLClientBuffer buffer,
846                              const EGLint *attr_list)
847 {
848    struct wgl_egl_context *wgl_ctx = wgl_egl_context(ctx);
849    struct wgl_egl_image *wgl_img;
850    GLuint texture = (GLuint)(uintptr_t)buffer;
851    _EGLImageAttribs attrs;
852    GLuint depth;
853    GLenum gl_target;
854    enum stw_image_error error;
855 
856    if (texture == 0) {
857       _eglError(EGL_BAD_PARAMETER, "wgl_create_image_khr");
858       return EGL_NO_IMAGE_KHR;
859    }
860 
861    if (!_eglParseImageAttribList(&attrs, disp, attr_list))
862       return EGL_NO_IMAGE_KHR;
863 
864    switch (target) {
865    case EGL_GL_TEXTURE_2D_KHR:
866       depth = 0;
867       gl_target = GL_TEXTURE_2D;
868       break;
869    case EGL_GL_TEXTURE_3D_KHR:
870       depth = attrs.GLTextureZOffset;
871       gl_target = GL_TEXTURE_3D;
872       break;
873    case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR:
874    case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR:
875    case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR:
876    case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR:
877    case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR:
878    case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR:
879       depth = target - EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR;
880       gl_target = GL_TEXTURE_CUBE_MAP;
881       break;
882    default:
883       unreachable("Unexpected target in wgl_create_image_khr_texture()");
884       return EGL_NO_IMAGE_KHR;
885    }
886 
887    wgl_img = malloc(sizeof *wgl_img);
888    if (!wgl_img) {
889       _eglError(EGL_BAD_ALLOC, "wgl_create_image_khr");
890       return EGL_NO_IMAGE_KHR;
891    }
892 
893    _eglInitImage(&wgl_img->base, disp);
894 
895    wgl_img->img = stw_create_image_from_texture(
896       wgl_ctx->ctx, gl_target, texture, depth, attrs.GLTextureLevel, &error);
897    assert(!!wgl_img->img == (error == STW_IMAGE_ERROR_SUCCESS));
898 
899    if (!wgl_img->img) {
900       free(wgl_img);
901       _eglError(egl_error_from_stw_image_error(error), "wgl_create_image_khr");
902       return EGL_NO_IMAGE_KHR;
903    }
904    return &wgl_img->base;
905 }
906 
907 static _EGLImage *
wgl_create_image_khr_renderbuffer(_EGLDisplay * disp,_EGLContext * ctx,EGLClientBuffer buffer,const EGLint * attr_list)908 wgl_create_image_khr_renderbuffer(_EGLDisplay *disp, _EGLContext *ctx,
909                                   EGLClientBuffer buffer,
910                                   const EGLint *attr_list)
911 {
912    struct wgl_egl_context *wgl_ctx = wgl_egl_context(ctx);
913    struct wgl_egl_image *wgl_img;
914    GLuint renderbuffer = (GLuint)(uintptr_t)buffer;
915    enum stw_image_error error;
916 
917    if (renderbuffer == 0) {
918       _eglError(EGL_BAD_PARAMETER, "wgl_create_image_khr");
919       return EGL_NO_IMAGE_KHR;
920    }
921 
922    wgl_img = malloc(sizeof(*wgl_img));
923    if (!wgl_img) {
924       _eglError(EGL_BAD_ALLOC, "wgl_create_image");
925       return NULL;
926    }
927 
928    _eglInitImage(&wgl_img->base, disp);
929 
930    wgl_img->img =
931       stw_create_image_from_renderbuffer(wgl_ctx->ctx, renderbuffer, &error);
932    assert(!!wgl_img->img == (error == STW_IMAGE_ERROR_SUCCESS));
933 
934    if (!wgl_img->img) {
935       free(wgl_img);
936       _eglError(egl_error_from_stw_image_error(error), "wgl_create_image_khr");
937       return EGL_NO_IMAGE_KHR;
938    }
939 
940    return &wgl_img->base;
941 }
942 
943 static _EGLImage *
wgl_create_image_khr(_EGLDisplay * disp,_EGLContext * ctx,EGLenum target,EGLClientBuffer buffer,const EGLint * attr_list)944 wgl_create_image_khr(_EGLDisplay *disp, _EGLContext *ctx, EGLenum target,
945                      EGLClientBuffer buffer, const EGLint *attr_list)
946 {
947    switch (target) {
948    case EGL_GL_TEXTURE_2D_KHR:
949    case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR:
950    case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR:
951    case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR:
952    case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR:
953    case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR:
954    case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR:
955    case EGL_GL_TEXTURE_3D_KHR:
956       return wgl_create_image_khr_texture(disp, ctx, target, buffer, attr_list);
957    case EGL_GL_RENDERBUFFER_KHR:
958       return wgl_create_image_khr_renderbuffer(disp, ctx, buffer, attr_list);
959    default:
960       _eglError(EGL_BAD_PARAMETER, "wgl_create_image_khr");
961       return EGL_NO_IMAGE_KHR;
962    }
963 }
964 
965 static EGLBoolean
wgl_destroy_image_khr(_EGLDisplay * disp,_EGLImage * img)966 wgl_destroy_image_khr(_EGLDisplay *disp, _EGLImage *img)
967 {
968    struct wgl_egl_image *wgl_img = wgl_egl_image(img);
969    stw_destroy_image(wgl_img->img);
970    free(wgl_img);
971    return EGL_TRUE;
972 }
973 
974 static _EGLSync *
wgl_create_sync_khr(_EGLDisplay * disp,EGLenum type,const EGLAttrib * attrib_list)975 wgl_create_sync_khr(_EGLDisplay *disp, EGLenum type,
976                     const EGLAttrib *attrib_list)
977 {
978 
979    _EGLContext *ctx = _eglGetCurrentContext();
980    struct wgl_egl_context *wgl_ctx = wgl_egl_context(ctx);
981    struct wgl_egl_sync *wgl_sync;
982 
983    struct st_context *st = wgl_ctx ? wgl_ctx->ctx->st : NULL;
984 
985    wgl_sync = calloc(1, sizeof(struct wgl_egl_sync));
986    if (!wgl_sync) {
987       _eglError(EGL_BAD_ALLOC, "eglCreateSyncKHR");
988       return NULL;
989    }
990 
991    if (!_eglInitSync(&wgl_sync->base, disp, type, attrib_list)) {
992       free(wgl_sync);
993       return NULL;
994    }
995 
996    switch (type) {
997    case EGL_SYNC_FENCE_KHR:
998       st_context_flush(st, 0, &wgl_sync->fence, NULL, NULL);
999       if (!wgl_sync->fence) {
1000          _eglError(EGL_BAD_ALLOC, "eglCreateSyncKHR");
1001          free(wgl_sync);
1002          return NULL;
1003       }
1004       break;
1005 
1006    case EGL_SYNC_REUSABLE_KHR:
1007       wgl_sync->event = CreateEvent(NULL, true, false, NULL);
1008       if (!wgl_sync->event) {
1009          _eglError(EGL_BAD_ALLOC, "eglCreateSyncKHR");
1010          free(wgl_sync);
1011          return NULL;
1012       }
1013    }
1014 
1015    wgl_sync->refcount = 1;
1016    return &wgl_sync->base;
1017 }
1018 
1019 static void
wgl_egl_unref_sync(struct wgl_egl_display * wgl_dpy,struct wgl_egl_sync * wgl_sync)1020 wgl_egl_unref_sync(struct wgl_egl_display *wgl_dpy,
1021                    struct wgl_egl_sync *wgl_sync)
1022 {
1023    if (InterlockedDecrement((volatile LONG *)&wgl_sync->refcount) > 0)
1024       return;
1025 
1026    if (wgl_sync->fence)
1027       wgl_dpy->screen->fence_reference(wgl_dpy->screen, &wgl_sync->fence, NULL);
1028    if (wgl_sync->event)
1029       CloseHandle(wgl_sync->event);
1030    free(wgl_sync);
1031 }
1032 
1033 static EGLBoolean
wgl_destroy_sync_khr(_EGLDisplay * disp,_EGLSync * sync)1034 wgl_destroy_sync_khr(_EGLDisplay *disp, _EGLSync *sync)
1035 {
1036    struct wgl_egl_display *wgl_dpy = wgl_egl_display(disp);
1037    struct wgl_egl_sync *wgl_sync = wgl_egl_sync(sync);
1038    wgl_egl_unref_sync(wgl_dpy, wgl_sync);
1039    return EGL_TRUE;
1040 }
1041 
1042 static EGLint
wgl_client_wait_sync_khr(_EGLDisplay * disp,_EGLSync * sync,EGLint flags,EGLTime timeout)1043 wgl_client_wait_sync_khr(_EGLDisplay *disp, _EGLSync *sync, EGLint flags,
1044                          EGLTime timeout)
1045 {
1046    _EGLContext *ctx = _eglGetCurrentContext();
1047    struct wgl_egl_display *wgl_dpy = wgl_egl_display(disp);
1048    struct wgl_egl_context *wgl_ctx = wgl_egl_context(ctx);
1049    struct wgl_egl_sync *wgl_sync = wgl_egl_sync(sync);
1050 
1051    EGLint ret = EGL_CONDITION_SATISFIED_KHR;
1052 
1053    /* the sync object should take a reference while waiting */
1054    InterlockedIncrement((volatile LONG *)&wgl_sync->refcount);
1055 
1056    switch (sync->Type) {
1057    case EGL_SYNC_FENCE_KHR:
1058       if (wgl_dpy->screen->fence_finish(wgl_dpy->screen, NULL, wgl_sync->fence,
1059                                         timeout))
1060          wgl_sync->base.SyncStatus = EGL_SIGNALED_KHR;
1061       else
1062          ret = EGL_TIMEOUT_EXPIRED_KHR;
1063       break;
1064 
1065    case EGL_SYNC_REUSABLE_KHR:
1066       if (wgl_ctx && wgl_sync->base.SyncStatus == EGL_UNSIGNALED_KHR &&
1067           (flags & EGL_SYNC_FLUSH_COMMANDS_BIT_KHR)) {
1068          /* flush context if EGL_SYNC_FLUSH_COMMANDS_BIT_KHR is set */
1069          wgl_gl_flush();
1070       }
1071 
1072       DWORD wait_milliseconds = (timeout == EGL_FOREVER_KHR)
1073                                    ? INFINITE
1074                                    : (DWORD)(timeout / 1000000ull);
1075       DWORD wait_ret = WaitForSingleObject(wgl_sync->event, wait_milliseconds);
1076       switch (wait_ret) {
1077       case WAIT_OBJECT_0:
1078          assert(wgl_sync->base.SyncStatus == EGL_SIGNALED_KHR);
1079          break;
1080       case WAIT_TIMEOUT:
1081          assert(wgl_sync->base.SyncStatus == EGL_UNSIGNALED_KHR);
1082          ret = EGL_TIMEOUT_EXPIRED_KHR;
1083          break;
1084       default:
1085          _eglError(EGL_BAD_ACCESS, "eglClientWaitSyncKHR");
1086          ret = EGL_FALSE;
1087          break;
1088       }
1089       break;
1090    }
1091    wgl_egl_unref_sync(wgl_dpy, wgl_sync);
1092 
1093    return ret;
1094 }
1095 
1096 static EGLint
wgl_wait_sync_khr(_EGLDisplay * disp,_EGLSync * sync)1097 wgl_wait_sync_khr(_EGLDisplay *disp, _EGLSync *sync)
1098 {
1099    _EGLContext *ctx = _eglGetCurrentContext();
1100    struct wgl_egl_context *wgl_ctx = wgl_egl_context(ctx);
1101    struct wgl_egl_sync *wgl_sync = wgl_egl_sync(sync);
1102 
1103    if (!wgl_sync->fence)
1104       return EGL_TRUE;
1105 
1106    struct pipe_context *pipe = wgl_ctx->ctx->st->pipe;
1107    if (pipe->fence_server_sync)
1108       pipe->fence_server_sync(pipe, wgl_sync->fence);
1109 
1110    return EGL_TRUE;
1111 }
1112 
1113 static EGLBoolean
wgl_signal_sync_khr(_EGLDisplay * disp,_EGLSync * sync,EGLenum mode)1114 wgl_signal_sync_khr(_EGLDisplay *disp, _EGLSync *sync, EGLenum mode)
1115 {
1116    struct wgl_egl_sync *wgl_sync = wgl_egl_sync(sync);
1117 
1118    if (sync->Type != EGL_SYNC_REUSABLE_KHR)
1119       return _eglError(EGL_BAD_MATCH, "eglSignalSyncKHR");
1120 
1121    if (mode != EGL_SIGNALED_KHR && mode != EGL_UNSIGNALED_KHR)
1122       return _eglError(EGL_BAD_ATTRIBUTE, "eglSignalSyncKHR");
1123 
1124    wgl_sync->base.SyncStatus = mode;
1125 
1126    if (mode == EGL_SIGNALED_KHR) {
1127       if (!SetEvent(wgl_sync->event))
1128          return _eglError(EGL_BAD_ACCESS, "eglSignalSyncKHR");
1129    } else {
1130       if (!ResetEvent(wgl_sync->event))
1131          return _eglError(EGL_BAD_ACCESS, "eglSignalSyncKHR");
1132    }
1133 
1134    return EGL_TRUE;
1135 }
1136 
1137 static const char *
wgl_query_driver_name(_EGLDisplay * disp)1138 wgl_query_driver_name(_EGLDisplay *disp)
1139 {
1140    return stw_get_device()->stw_winsys->get_name();
1141 }
1142 
1143 static char *
wgl_query_driver_config(_EGLDisplay * disp)1144 wgl_query_driver_config(_EGLDisplay *disp)
1145 {
1146    return stw_get_config_xml();
1147 }
1148 
1149 static int
wgl_interop_query_device_info(_EGLDisplay * disp,_EGLContext * ctx,struct mesa_glinterop_device_info * out)1150 wgl_interop_query_device_info(_EGLDisplay *disp, _EGLContext *ctx,
1151                               struct mesa_glinterop_device_info *out)
1152 {
1153    struct wgl_egl_context *wgl_ctx = wgl_egl_context(ctx);
1154    return stw_interop_query_device_info(wgl_ctx->ctx, out);
1155 }
1156 
1157 static int
wgl_interop_export_object(_EGLDisplay * disp,_EGLContext * ctx,struct mesa_glinterop_export_in * in,struct mesa_glinterop_export_out * out)1158 wgl_interop_export_object(_EGLDisplay *disp, _EGLContext *ctx,
1159                           struct mesa_glinterop_export_in *in,
1160                           struct mesa_glinterop_export_out *out)
1161 {
1162    struct wgl_egl_context *wgl_ctx = wgl_egl_context(ctx);
1163    return stw_interop_export_object(wgl_ctx->ctx, in, out);
1164 }
1165 
1166 static int
wgl_interop_flush_objects(_EGLDisplay * disp,_EGLContext * ctx,unsigned count,struct mesa_glinterop_export_in * objects,struct mesa_glinterop_flush_out * out)1167 wgl_interop_flush_objects(_EGLDisplay *disp, _EGLContext *ctx, unsigned count,
1168                           struct mesa_glinterop_export_in *objects,
1169                           struct mesa_glinterop_flush_out *out)
1170 {
1171    struct wgl_egl_context *wgl_ctx = wgl_egl_context(ctx);
1172    return stw_interop_flush_objects(wgl_ctx->ctx, count, objects, out);
1173 }
1174 
1175 struct _egl_driver _eglDriver = {
1176    .Initialize = wgl_initialize,
1177    .Terminate = wgl_terminate,
1178    .CreateContext = wgl_create_context,
1179    .DestroyContext = wgl_destroy_context,
1180    .MakeCurrent = wgl_make_current,
1181    .CreateWindowSurface = wgl_create_window_surface,
1182    .CreatePbufferSurface = wgl_create_pbuffer_surface,
1183    .DestroySurface = wgl_destroy_surface,
1184    .QuerySurface = wgl_query_surface,
1185    .BindTexImage = wgl_bind_tex_image,
1186    .ReleaseTexImage = _eglReleaseTexImage,
1187    .SwapInterval = wgl_swap_interval,
1188    .SwapBuffers = wgl_swap_buffers,
1189    .WaitClient = wgl_wait_client,
1190    .WaitNative = wgl_wait_native,
1191    .CreateImageKHR = wgl_create_image_khr,
1192    .DestroyImageKHR = wgl_destroy_image_khr,
1193    .CreateSyncKHR = wgl_create_sync_khr,
1194    .DestroySyncKHR = wgl_destroy_sync_khr,
1195    .ClientWaitSyncKHR = wgl_client_wait_sync_khr,
1196    .WaitSyncKHR = wgl_wait_sync_khr,
1197    .SignalSyncKHR = wgl_signal_sync_khr,
1198    .QueryDriverName = wgl_query_driver_name,
1199    .QueryDriverConfig = wgl_query_driver_config,
1200    .GLInteropQueryDeviceInfo = wgl_interop_query_device_info,
1201    .GLInteropExportObject = wgl_interop_export_object,
1202    .GLInteropFlushObjects = wgl_interop_flush_objects,
1203 };
1204