wgl: Pass smapi explicitly to context creation
[platform/upstream/mesa.git] / src / egl / drivers / wgl / egl_wgl.c
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 <egldriver.h>
25 #include <egllog.h>
26 #include <eglcurrent.h>
27 #include <eglcontext.h>
28 #include <eglsurface.h>
29
30 #include "egl_wgl.h"
31
32 #include <stw_device.h>
33 #include <stw_pixelformat.h>
34 #include <stw_context.h>
35 #include <stw_framebuffer.h>
36 #include <stw_image.h>
37
38 #include <GL/wglext.h>
39
40 #include <pipe/p_screen.h>
41 #include <pipe/p_state.h>
42
43 #include <mapi/glapi/glapi.h>
44
45 static EGLBoolean
46 wgl_match_config(const _EGLConfig *conf, const _EGLConfig *criteria)
47 {
48    if (_eglCompareConfigs(conf, criteria, NULL, EGL_FALSE) != 0)
49       return EGL_FALSE;
50
51    if (!_eglMatchConfig(conf, criteria))
52       return EGL_FALSE;
53
54    return EGL_TRUE;
55 }
56
57 static struct wgl_egl_config *
58 wgl_add_config(_EGLDisplay *disp, const struct stw_pixelformat_info *stw_config, int id, EGLint surface_type)
59 {
60    struct wgl_egl_config *conf;
61    struct wgl_egl_display *wgl_dpy = wgl_egl_display(disp);
62    _EGLConfig base;
63    unsigned int double_buffer;
64    int wgl_shifts[4] = { -1, -1, -1, -1 };
65    unsigned int wgl_sizes[4] = { 0, 0, 0, 0 };
66    _EGLConfig *matching_config;
67    EGLint num_configs = 0;
68    EGLint config_id;
69
70    _eglInitConfig(&base, disp, id);
71
72    double_buffer = (stw_config->pfd.dwFlags & PFD_DOUBLEBUFFER) != 0;
73
74    if (stw_config->pfd.iPixelType != PFD_TYPE_RGBA)
75       return NULL;
76
77    wgl_sizes[0] = stw_config->pfd.cRedBits;
78    wgl_sizes[1] = stw_config->pfd.cGreenBits;
79    wgl_sizes[2] = stw_config->pfd.cBlueBits;
80    wgl_sizes[3] = stw_config->pfd.cAlphaBits;
81
82    base.RedSize = stw_config->pfd.cRedBits;
83    base.GreenSize = stw_config->pfd.cGreenBits;
84    base.BlueSize = stw_config->pfd.cBlueBits;
85    base.AlphaSize = stw_config->pfd.cAlphaBits;
86    base.BufferSize = stw_config->pfd.cColorBits;
87
88    wgl_shifts[0] = stw_config->pfd.cRedShift;
89    wgl_shifts[1] = stw_config->pfd.cGreenShift;
90    wgl_shifts[2] = stw_config->pfd.cBlueShift;
91    wgl_shifts[3] = stw_config->pfd.cAlphaShift;
92
93    if (stw_config->pfd.cAccumBits) {
94       /* Don't expose visuals with the accumulation buffer. */
95       return NULL;
96    }
97
98    base.MaxPbufferWidth = _EGL_MAX_PBUFFER_WIDTH;
99    base.MaxPbufferHeight = _EGL_MAX_PBUFFER_HEIGHT;
100
101    base.DepthSize = stw_config->pfd.cDepthBits;
102    base.StencilSize = stw_config->pfd.cStencilBits;
103    base.Samples = stw_config->stvis.samples;
104    base.SampleBuffers = base.Samples > 1;
105
106    base.NativeRenderable = EGL_TRUE;
107
108    if (surface_type & EGL_PBUFFER_BIT) {
109       base.BindToTextureRGB = stw_config->bindToTextureRGB;
110       if (base.AlphaSize > 0)
111          base.BindToTextureRGBA = stw_config->bindToTextureRGBA;
112    }
113
114    if (double_buffer) {
115       surface_type &= ~EGL_PIXMAP_BIT;
116    }
117
118    if (!(stw_config->pfd.dwFlags & PFD_DRAW_TO_WINDOW)) {
119       surface_type &= ~EGL_WINDOW_BIT;
120    }
121
122    if (!surface_type)
123       return NULL;
124
125    base.SurfaceType = surface_type;
126    base.RenderableType = disp->ClientAPIs;
127    base.Conformant = disp->ClientAPIs;
128
129    base.MinSwapInterval = 0;
130    base.MaxSwapInterval = 4;
131    base.YInvertedNOK = EGL_TRUE;
132
133    if (!_eglValidateConfig(&base, EGL_FALSE)) {
134       _eglLog(_EGL_DEBUG, "wgl: failed to validate config %d", id);
135       return NULL;
136    }
137
138    config_id = base.ConfigID;
139    base.ConfigID = EGL_DONT_CARE;
140    base.SurfaceType = EGL_DONT_CARE;
141    num_configs = _eglFilterArray(disp->Configs, (void **)&matching_config, 1,
142       (_EGLArrayForEach)wgl_match_config, &base);
143
144    if (num_configs == 1) {
145       conf = (struct wgl_egl_config *)matching_config;
146
147       if (!conf->stw_config[double_buffer])
148          conf->stw_config[double_buffer] = stw_config;
149       else
150          /* a similar config type is already added (unlikely) => discard */
151          return NULL;
152    }
153    else if (num_configs == 0) {
154       conf = calloc(1, sizeof * conf);
155       if (conf == NULL)
156          return NULL;
157
158       conf->stw_config[double_buffer] = stw_config;
159
160       memcpy(&conf->base, &base, sizeof base);
161       conf->base.SurfaceType = 0;
162       conf->base.ConfigID = config_id;
163
164       _eglLinkConfig(&conf->base);
165    }
166    else {
167       unreachable("duplicates should not be possible");
168       return NULL;
169    }
170
171    conf->base.SurfaceType |= surface_type;
172
173    return conf;
174 }
175
176 static EGLBoolean
177 wgl_add_configs(_EGLDisplay *disp)
178 {
179    unsigned int config_count = 0;
180    unsigned surface_type = EGL_PBUFFER_BIT | EGL_WINDOW_BIT;
181
182    // This is already a filtered set of what the driver supports,
183    // and there's no further filtering needed per-visual
184    for (unsigned i = 1; stw_pixelformat_get_info(i) != NULL; i++) {
185
186       struct wgl_egl_config *wgl_conf = wgl_add_config(disp, stw_pixelformat_get_info(i),
187          config_count + 1, surface_type);
188
189       if (wgl_conf) {
190          if (wgl_conf->base.ConfigID == config_count + 1)
191             config_count++;
192       }
193    }
194
195    return (config_count != 0);
196 }
197
198 static void
199 wgl_display_destroy(_EGLDisplay *disp)
200 {
201    free(disp);
202 }
203
204 static EGLBoolean
205 wgl_initialize_impl(_EGLDisplay *disp, HDC hdc)
206 {
207    struct wgl_egl_display *wgl_dpy;
208    const char* err;
209
210    wgl_dpy = calloc(1, sizeof * wgl_dpy);
211    if (!wgl_dpy)
212       return _eglError(EGL_BAD_ALLOC, "eglInitialize");
213
214    disp->DriverData = (void *)wgl_dpy;
215
216    if (!stw_init_screen(hdc)) {
217       err = "wgl: failed to initialize screen";
218       goto cleanup;
219    }
220
221    struct stw_device *stw_dev = stw_get_device();
222    wgl_dpy->screen = stw_dev->screen;
223    wgl_dpy->smapi = stw_dev->smapi;
224
225    disp->ClientAPIs = 0;
226    if (_eglIsApiValid(EGL_OPENGL_API))
227       disp->ClientAPIs |= EGL_OPENGL_BIT;
228    if (_eglIsApiValid(EGL_OPENGL_ES_API))
229       disp->ClientAPIs |= EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT | EGL_OPENGL_ES3_BIT_KHR;
230
231    disp->Extensions.KHR_no_config_context = EGL_TRUE;
232    disp->Extensions.KHR_surfaceless_context = EGL_TRUE;
233    disp->Extensions.MESA_query_driver = EGL_TRUE;
234
235    /* Report back to EGL the bitmask of priorities supported */
236    disp->Extensions.IMG_context_priority =
237       wgl_dpy->screen->get_param(wgl_dpy->screen, PIPE_CAP_CONTEXT_PRIORITY_MASK);
238
239    disp->Extensions.EXT_pixel_format_float = EGL_TRUE;
240
241    if (wgl_dpy->screen->is_format_supported(wgl_dpy->screen,
242          PIPE_FORMAT_B8G8R8A8_SRGB,
243          PIPE_TEXTURE_2D, 0, 0,
244          PIPE_BIND_RENDER_TARGET))
245       disp->Extensions.KHR_gl_colorspace = EGL_TRUE;
246
247    disp->Extensions.KHR_create_context = EGL_TRUE;
248
249    disp->Extensions.KHR_image_base = EGL_TRUE;
250    disp->Extensions.KHR_gl_renderbuffer_image = EGL_TRUE;
251    disp->Extensions.KHR_gl_texture_2D_image = EGL_TRUE;
252    disp->Extensions.KHR_gl_texture_cubemap_image = EGL_TRUE;
253    disp->Extensions.KHR_gl_texture_3D_image = EGL_TRUE;
254
255    if (!wgl_add_configs(disp)) {
256       err = "wgl: failed to add configs";
257       goto cleanup;
258    }
259
260    return EGL_TRUE;
261
262 cleanup:
263    wgl_display_destroy(disp);
264    return _eglError(EGL_NOT_INITIALIZED, err);
265 }
266
267 static EGLBoolean
268 wgl_initialize(_EGLDisplay *disp)
269 {
270    EGLBoolean ret = EGL_FALSE;
271    struct wgl_egl_display *wgl_dpy = wgl_egl_display(disp);
272
273    /* In the case where the application calls eglMakeCurrent(context1),
274     * eglTerminate, then eglInitialize again (without a call to eglReleaseThread
275     * or eglMakeCurrent(NULL) before that), wgl_dpy structure is still
276     * initialized, as we need it to be able to free context1 correctly.
277     *
278     * It would probably be safest to forcibly release the display with
279     * wgl_display_release, to make sure the display is reinitialized correctly.
280     * However, the EGL spec states that we need to keep a reference to the
281     * current context (so we cannot call wgl_make_current(NULL)), and therefore
282     * we would leak context1 as we would be missing the old display connection
283     * to free it up correctly.
284     */
285    if (wgl_dpy) {
286       wgl_dpy->ref_count++;
287       return EGL_TRUE;
288    }
289
290    switch (disp->Platform) {
291    case _EGL_PLATFORM_SURFACELESS:
292       ret = wgl_initialize_impl(disp, NULL);
293       break;
294    case _EGL_PLATFORM_WINDOWS:
295       ret = wgl_initialize_impl(disp, disp->PlatformDisplay);
296       break;
297    default:
298       unreachable("Callers ensure we cannot get here.");
299       return EGL_FALSE;
300    }
301
302    if (!ret)
303       return EGL_FALSE;
304
305    wgl_dpy = wgl_egl_display(disp);
306    wgl_dpy->ref_count++;
307
308    return EGL_TRUE;
309 }
310
311 /**
312  * Decrement display reference count, and free up display if necessary.
313  */
314 static void
315 wgl_display_release(_EGLDisplay *disp)
316 {
317    struct wgl_egl_display *wgl_dpy;
318
319    if (!disp)
320       return;
321
322    wgl_dpy = wgl_egl_display(disp);
323
324    assert(wgl_dpy->ref_count > 0);
325    wgl_dpy->ref_count--;
326
327    if (wgl_dpy->ref_count > 0)
328       return;
329
330    _eglCleanupDisplay(disp);
331    wgl_display_destroy(disp);
332 }
333
334 /**
335  * Called via eglTerminate(), drv->Terminate().
336  *
337  * This must be guaranteed to be called exactly once, even if eglTerminate is
338  * called many times (without a eglInitialize in between).
339  */
340 static EGLBoolean
341 wgl_terminate(_EGLDisplay *disp)
342 {
343    /* Release all non-current Context/Surfaces. */
344    _eglReleaseDisplayResources(disp);
345
346    wgl_display_release(disp);
347
348    return EGL_TRUE;
349 }
350
351 /**
352  * Called via eglCreateContext(), drv->CreateContext().
353  */
354 static _EGLContext *
355 wgl_create_context(_EGLDisplay *disp, _EGLConfig *conf,
356    _EGLContext *share_list, const EGLint *attrib_list)
357 {
358    struct wgl_egl_context *wgl_ctx;
359    struct wgl_egl_display *wgl_dpy = wgl_egl_display(disp);
360    struct wgl_egl_context *wgl_ctx_shared = wgl_egl_context(share_list);
361    struct stw_context *shared =
362       wgl_ctx_shared ? wgl_ctx_shared->ctx : NULL;
363    struct wgl_egl_config *wgl_config = wgl_egl_config(conf);
364    const struct stw_pixelformat_info *stw_config;
365
366    wgl_ctx = malloc(sizeof * wgl_ctx);
367    if (!wgl_ctx) {
368       _eglError(EGL_BAD_ALLOC, "eglCreateContext");
369       return NULL;
370    }
371
372    if (!_eglInitContext(&wgl_ctx->base, disp, conf, attrib_list))
373       goto cleanup;
374
375    /* The EGL_EXT_create_context_robustness spec says:
376     *
377     *    "Add to the eglCreateContext context creation errors: [...]
378     *
379     *     * If the reset notification behavior of <share_context> and the
380     *       newly created context are different then an EGL_BAD_MATCH error is
381     *       generated."
382     */
383    if (share_list && share_list->ResetNotificationStrategy !=
384       wgl_ctx->base.ResetNotificationStrategy) {
385       _eglError(EGL_BAD_MATCH, "eglCreateContext");
386       goto cleanup;
387    }
388
389    /* The EGL_KHR_create_context_no_error spec says:
390     *
391     *    "BAD_MATCH is generated if the value of EGL_CONTEXT_OPENGL_NO_ERROR_KHR
392     *    used to create <share_context> does not match the value of
393     *    EGL_CONTEXT_OPENGL_NO_ERROR_KHR for the context being created."
394     */
395    if (share_list && share_list->NoError != wgl_ctx->base.NoError) {
396       _eglError(EGL_BAD_MATCH, "eglCreateContext");
397       goto cleanup;
398    }
399
400    unsigned profile_mask = 0;
401    switch (wgl_ctx->base.ClientAPI) {
402    case EGL_OPENGL_ES_API:
403       profile_mask = WGL_CONTEXT_ES_PROFILE_BIT_EXT;
404       break;
405    case EGL_OPENGL_API:
406       if ((wgl_ctx->base.ClientMajorVersion >= 4
407          || (wgl_ctx->base.ClientMajorVersion == 3
408             && wgl_ctx->base.ClientMinorVersion >= 2))
409          && wgl_ctx->base.Profile == EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR)
410          profile_mask = WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
411       else if (wgl_ctx->base.ClientMajorVersion == 3 &&
412          wgl_ctx->base.ClientMinorVersion == 1)
413          profile_mask = WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
414       else
415          profile_mask = WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
416       break;
417    default:
418       _eglError(EGL_BAD_PARAMETER, "eglCreateContext");
419       free(wgl_ctx);
420       return NULL;
421    }
422
423    if (conf != NULL) {
424       /* The config chosen here isn't necessarily
425        * used for surfaces later.
426        * A pixmap surface will use the single config.
427        * This opportunity depends on disabling the
428        * doubleBufferMode check in
429        * src/mesa/main/context.c:check_compatible()
430        */
431       if (wgl_config->stw_config[1])
432          stw_config = wgl_config->stw_config[1];
433       else
434          stw_config = wgl_config->stw_config[0];
435    }
436    else
437       stw_config = NULL;
438
439    unsigned flags = 0;
440    if (wgl_ctx->base.Flags & EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR)
441       flags |= WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
442    if (wgl_ctx->base.Flags & EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR)
443       flags |= WGL_CONTEXT_DEBUG_BIT_ARB;
444    unsigned resetStrategy = WGL_NO_RESET_NOTIFICATION_ARB;
445    if (wgl_ctx->base.ResetNotificationStrategy != EGL_NO_RESET_NOTIFICATION)
446       resetStrategy = WGL_LOSE_CONTEXT_ON_RESET_ARB;
447    wgl_ctx->ctx = stw_create_context_attribs(disp->PlatformDisplay, 0, shared,
448       wgl_dpy->smapi,
449       wgl_ctx->base.ClientMajorVersion,
450       wgl_ctx->base.ClientMinorVersion,
451       flags,
452       profile_mask,
453       stw_config->iPixelFormat,
454       resetStrategy);
455
456    if (!wgl_ctx->ctx)
457       goto cleanup;
458
459    return &wgl_ctx->base;
460
461 cleanup:
462    free(wgl_ctx);
463    return NULL;
464 }
465
466 /**
467  * Called via eglDestroyContext(), drv->DestroyContext().
468  */
469 static EGLBoolean
470 wgl_destroy_context(_EGLDisplay *disp, _EGLContext *ctx)
471 {
472    struct wgl_egl_context *wgl_ctx = wgl_egl_context(ctx);
473    struct wgl_egl_display *wgl_dpy = wgl_egl_display(disp);
474
475    if (_eglPutContext(ctx)) {
476       stw_destroy_context(wgl_ctx->ctx);
477       free(wgl_ctx);
478    }
479
480    return EGL_TRUE;
481 }
482
483 static EGLBoolean
484 wgl_destroy_surface(_EGLDisplay *disp, _EGLSurface *surf)
485 {
486    struct wgl_egl_surface *wgl_surf = wgl_egl_surface(surf);
487
488    if (!_eglPutSurface(surf))
489       return EGL_TRUE;
490
491    if (wgl_surf->fb->owner == STW_FRAMEBUFFER_PBUFFER) {
492       DestroyWindow(wgl_surf->fb->hWnd);
493    } else {
494       struct stw_context *ctx = stw_current_context();
495       stw_framebuffer_lock(wgl_surf->fb);
496       stw_framebuffer_release_locked(wgl_surf->fb, ctx ? ctx->st : NULL);
497    }
498    return EGL_TRUE;
499 }
500
501 static void
502 wgl_gl_flush()
503 {
504    static void (*glFlush)(void);
505    static mtx_t glFlushMutex = _MTX_INITIALIZER_NP;
506
507    mtx_lock(&glFlushMutex);
508    if (!glFlush)
509       glFlush = _glapi_get_proc_address("glFlush");
510    mtx_unlock(&glFlushMutex);
511
512    /* if glFlush is not available things are horribly broken */
513    if (!glFlush) {
514       _eglLog(_EGL_WARNING, "wgl: failed to find glFlush entry point");
515       return;
516    }
517
518    glFlush();
519 }
520
521 /**
522  * Called via eglMakeCurrent(), drv->MakeCurrent().
523  */
524 static EGLBoolean
525 wgl_make_current(_EGLDisplay *disp, _EGLSurface *dsurf,
526    _EGLSurface *rsurf, _EGLContext *ctx)
527 {
528    struct wgl_egl_display *wgl_dpy = wgl_egl_display(disp);
529    struct wgl_egl_context *wgl_ctx = wgl_egl_context(ctx);
530    _EGLDisplay *old_disp = NULL;
531    struct wgl_egl_display *old_wgl_dpy = NULL;
532    _EGLContext *old_ctx;
533    _EGLSurface *old_dsurf, *old_rsurf;
534    _EGLSurface *tmp_dsurf, *tmp_rsurf;
535    struct stw_framebuffer *ddraw, *rdraw;
536    struct stw_context *cctx;
537    EGLint egl_error = EGL_SUCCESS;
538
539    if (!wgl_dpy)
540       return _eglError(EGL_NOT_INITIALIZED, "eglMakeCurrent");
541
542    /* make new bindings, set the EGL error otherwise */
543    if (!_eglBindContext(ctx, dsurf, rsurf, &old_ctx, &old_dsurf, &old_rsurf))
544       return EGL_FALSE;
545
546    if (old_ctx) {
547       struct stw_context *old_cctx = wgl_egl_context(old_ctx)->ctx;
548       old_disp = old_ctx->Resource.Display;
549       old_wgl_dpy = wgl_egl_display(old_disp);
550
551       /* flush before context switch */
552       wgl_gl_flush();
553
554 #if 0
555       if (old_dsurf)
556          wgl_surf_update_fence_fd(old_ctx, disp, old_dsurf);
557
558       /* Disable shared buffer mode */
559       if (old_dsurf && _eglSurfaceInSharedBufferMode(old_dsurf) &&
560          old_wgl_dpy->vtbl->set_shared_buffer_mode) {
561          old_wgl_dpy->vtbl->set_shared_buffer_mode(old_disp, old_dsurf, false);
562       }
563 #endif
564
565       stw_unbind_context(old_cctx);
566    }
567
568    ddraw = (dsurf) ? wgl_egl_surface(dsurf)->fb : NULL;
569    rdraw = (rsurf) ? wgl_egl_surface(rsurf)->fb : NULL;
570    cctx = (wgl_ctx) ? wgl_ctx->ctx : NULL;
571
572    if (cctx || ddraw || rdraw) {
573       if (!stw_make_current(ddraw, rdraw, cctx)) {
574          _EGLContext *tmp_ctx;
575
576          /* stw_make_current failed. We cannot tell for sure why, but
577           * setting the error to EGL_BAD_MATCH is surely better than leaving it
578           * as EGL_SUCCESS.
579           */
580          egl_error = EGL_BAD_MATCH;
581
582          /* undo the previous _eglBindContext */
583          _eglBindContext(old_ctx, old_dsurf, old_rsurf, &ctx, &tmp_dsurf, &tmp_rsurf);
584          assert(&wgl_ctx->base == ctx &&
585             tmp_dsurf == dsurf &&
586             tmp_rsurf == rsurf);
587
588          _eglPutSurface(dsurf);
589          _eglPutSurface(rsurf);
590          _eglPutContext(ctx);
591
592          _eglPutSurface(old_dsurf);
593          _eglPutSurface(old_rsurf);
594          _eglPutContext(old_ctx);
595
596          ddraw = (old_dsurf) ? wgl_egl_surface(old_dsurf)->fb : NULL;
597          rdraw = (old_rsurf) ? wgl_egl_surface(old_rsurf)->fb : NULL;
598          cctx = (old_ctx) ? wgl_egl_context(old_ctx)->ctx : NULL;
599
600          /* undo the previous wgl_dpy->core->unbindContext */
601          if (stw_make_current(ddraw, rdraw, cctx)) {
602 #if 0
603             if (old_dsurf && _eglSurfaceInSharedBufferMode(old_dsurf) &&
604                old_wgl_dpy->vtbl->set_shared_buffer_mode) {
605                old_wgl_dpy->vtbl->set_shared_buffer_mode(old_disp, old_dsurf, true);
606             }
607 #endif
608
609             return _eglError(egl_error, "eglMakeCurrent");
610          }
611
612          /* We cannot restore the same state as it was before calling
613           * eglMakeCurrent() and the spec isn't clear about what to do. We
614           * can prevent EGL from calling into the DRI driver with no DRI
615           * context bound.
616           */
617          dsurf = rsurf = NULL;
618          ctx = NULL;
619
620          _eglBindContext(ctx, dsurf, rsurf, &tmp_ctx, &tmp_dsurf, &tmp_rsurf);
621          assert(tmp_ctx == old_ctx && tmp_dsurf == old_dsurf &&
622             tmp_rsurf == old_rsurf);
623
624          _eglLog(_EGL_WARNING, "wgl: failed to rebind the previous context");
625       }
626       else {
627          /* wgl_dpy->core->bindContext succeeded, so take a reference on the
628           * wgl_dpy. This prevents wgl_dpy from being reinitialized when a
629           * EGLDisplay is terminated and then initialized again while a
630           * context is still bound. See wgl_intitialize() for a more in depth
631           * explanation. */
632          wgl_dpy->ref_count++;
633       }
634    }
635
636    wgl_destroy_surface(disp, old_dsurf);
637    wgl_destroy_surface(disp, old_rsurf);
638
639    if (old_ctx) {
640       wgl_destroy_context(disp, old_ctx);
641       wgl_display_release(old_disp);
642    }
643
644    if (egl_error != EGL_SUCCESS)
645       return _eglError(egl_error, "eglMakeCurrent");
646
647 #if 0
648    if (dsurf && _eglSurfaceHasMutableRenderBuffer(dsurf) &&
649       wgl_dpy->vtbl->set_shared_buffer_mode) {
650       /* Always update the shared buffer mode. This is obviously needed when
651        * the active EGL_RENDER_BUFFER is EGL_SINGLE_BUFFER. When
652        * EGL_RENDER_BUFFER is EGL_BACK_BUFFER, the update protects us in the
653        * case where external non-EGL API may have changed window's shared
654        * buffer mode since we last saw it.
655        */
656       bool mode = (dsurf->ActiveRenderBuffer == EGL_SINGLE_BUFFER);
657       wgl_dpy->vtbl->set_shared_buffer_mode(disp, dsurf, mode);
658    }
659 #endif
660
661    return EGL_TRUE;
662 }
663
664 static _EGLSurface*
665 wgl_create_window_surface(_EGLDisplay *disp, _EGLConfig *conf,
666                           void *native_window, const EGLint *attrib_list)
667 {
668    struct wgl_egl_config *wgl_conf = wgl_egl_config(conf);
669
670    struct wgl_egl_surface *wgl_surf = calloc(1, sizeof(*wgl_surf));
671    if (!wgl_surf)
672       return NULL;
673
674    if (!_eglInitSurface(&wgl_surf->base, disp, EGL_WINDOW_BIT, conf, attrib_list, native_window)) {
675       free(wgl_surf);
676       return NULL;
677    }
678
679    const struct stw_pixelformat_info *stw_conf = wgl_conf->stw_config[1] ?
680       wgl_conf->stw_config[1] : wgl_conf->stw_config[0];
681    wgl_surf->fb = stw_framebuffer_create(native_window, stw_conf->iPixelFormat, STW_FRAMEBUFFER_EGL_WINDOW);
682    if (!wgl_surf->fb) {
683       free(wgl_surf);
684       return NULL;
685    }
686
687    wgl_surf->fb->swap_interval = 1;
688    stw_framebuffer_unlock(wgl_surf->fb);
689
690    return &wgl_surf->base;
691 }
692
693 static _EGLSurface*
694 wgl_create_pbuffer_surface(_EGLDisplay *disp, _EGLConfig *conf,
695                            const EGLint *attrib_list)
696 {
697    struct wgl_egl_config *wgl_conf = wgl_egl_config(conf);
698
699    struct wgl_egl_surface *wgl_surf = calloc(1, sizeof(*wgl_surf));
700    if (!wgl_surf)
701       return NULL;
702
703    if (!_eglInitSurface(&wgl_surf->base, disp, EGL_PBUFFER_BIT, conf, attrib_list, NULL)) {
704       free(wgl_surf);
705       return NULL;
706    }
707
708    const struct stw_pixelformat_info *stw_conf = wgl_conf->stw_config[1] ?
709       wgl_conf->stw_config[1] : wgl_conf->stw_config[0];
710    wgl_surf->fb = stw_pbuffer_create(stw_conf->iPixelFormat, wgl_surf->base.Width, wgl_surf->base.Height);
711    if (!wgl_surf->fb) {
712       free(wgl_surf);
713       return NULL;
714    }
715
716    wgl_surf->fb->swap_interval = 1;
717    stw_framebuffer_unlock(wgl_surf->fb);
718
719    return &wgl_surf->base;
720 }
721
722 static EGLBoolean
723 wgl_query_surface(_EGLDisplay *disp, _EGLSurface *surf,
724                   EGLint attribute, EGLint *value)
725 {
726    struct wgl_egl_surface *wgl_surf = wgl_egl_surface(surf);
727    RECT client_rect;
728
729    switch (attribute) {
730    case EGL_WIDTH:
731    case EGL_HEIGHT:
732       if (GetClientRect(wgl_surf->fb->hWnd, &client_rect)) {
733          surf->Width = client_rect.right;
734          surf->Height = client_rect.bottom;
735       }
736       break;
737    default:
738       break;
739    }
740    return _eglQuerySurface(disp, surf, attribute, value);
741 }
742
743 static EGLBoolean
744 wgl_bind_tex_image(_EGLDisplay *disp, _EGLSurface *surf, EGLint buffer)
745 {
746    struct wgl_egl_surface *wgl_surf = wgl_egl_surface(surf);
747    enum st_attachment_type target = ST_TEXTURE_2D;
748
749    _EGLContext *ctx = _eglGetCurrentContext();
750    struct wgl_egl_context *wgl_ctx = wgl_egl_context(ctx);
751
752    if (!_eglBindTexImage(disp, surf, buffer))
753       return EGL_FALSE;
754
755    struct pipe_resource *pres = stw_get_framebuffer_resource(wgl_surf->fb->stfb, ST_ATTACHMENT_FRONT_LEFT);
756    enum pipe_format format = pres->format;
757
758    switch (surf->TextureFormat) {
759    case EGL_TEXTURE_RGB:
760       switch (format) {
761       case PIPE_FORMAT_R16G16B16A16_FLOAT:
762          format = PIPE_FORMAT_R16G16B16X16_FLOAT;
763          break;
764       case PIPE_FORMAT_B10G10R10A2_UNORM:
765          format = PIPE_FORMAT_B10G10R10X2_UNORM;
766          break;
767       case PIPE_FORMAT_R10G10B10A2_UNORM:
768          format = PIPE_FORMAT_R10G10B10X2_UNORM;
769          break;
770       case PIPE_FORMAT_BGRA8888_UNORM:
771          format = PIPE_FORMAT_BGRX8888_UNORM;
772          break;
773       case PIPE_FORMAT_ARGB8888_UNORM:
774          format = PIPE_FORMAT_XRGB8888_UNORM;
775          break;
776       default:
777          break;
778       }
779       break;
780    case EGL_TEXTURE_RGBA:
781       break;
782    default:
783       assert(!"Unexpected texture format in wgl_bind_tex_image()");
784    }
785
786    switch (surf->TextureTarget) {
787    case EGL_TEXTURE_2D:
788       break;
789    default:
790       assert(!"Unexpected texture target in wgl_bind_tex_image()");
791    }
792
793    wgl_ctx->ctx->st->teximage(wgl_ctx->ctx->st, target, 0, format, pres, false);
794
795    return EGL_TRUE;
796 }
797
798 static EGLBoolean
799 wgl_swap_interval(_EGLDisplay *disp, _EGLSurface *surf, EGLint interval)
800 {
801    struct wgl_egl_surface *wgl_surf = wgl_egl_surface(surf);
802    wgl_surf->fb->swap_interval = interval;
803    return EGL_TRUE;
804 }
805
806 static EGLBoolean
807 wgl_swap_buffers(_EGLDisplay *disp, _EGLSurface *draw)
808 {
809    struct wgl_egl_display *wgl_disp = wgl_egl_display(disp);
810    struct wgl_egl_surface *wgl_surf = wgl_egl_surface(draw);
811
812    stw_framebuffer_lock(wgl_surf->fb);
813    HDC hdc = GetDC(wgl_surf->fb->hWnd);
814    BOOL ret = stw_framebuffer_swap_locked(hdc, wgl_surf->fb);
815    ReleaseDC(wgl_surf->fb->hWnd, hdc);
816
817    return ret;
818 }
819
820 static EGLBoolean
821 wgl_wait_client(_EGLDisplay *disp, _EGLContext *ctx)
822 {
823    struct wgl_egl_context *wgl_ctx = wgl_egl_context(ctx);
824    struct pipe_fence_handle *fence = NULL;
825    wgl_ctx->ctx->st->flush(wgl_ctx->ctx->st, ST_FLUSH_END_OF_FRAME | ST_FLUSH_WAIT, &fence, NULL, NULL);
826    return EGL_TRUE;
827 }
828
829 static EGLBoolean
830 wgl_wait_native(EGLint engine)
831 {
832    if (engine != EGL_CORE_NATIVE_ENGINE)
833       return _eglError(EGL_BAD_PARAMETER, "eglWaitNative");
834    /* It's unclear what "native" means, but GDI is as good a guess as any */
835    GdiFlush();
836    return EGL_TRUE;
837 }
838
839 static EGLint
840 egl_error_from_stw_image_error(enum stw_image_error err)
841 {
842    switch (err) {
843    case STW_IMAGE_ERROR_SUCCESS:
844       return EGL_SUCCESS;
845    case STW_IMAGE_ERROR_BAD_ALLOC:
846       return EGL_BAD_ALLOC;
847    case STW_IMAGE_ERROR_BAD_MATCH:
848       return EGL_BAD_MATCH;
849    case STW_IMAGE_ERROR_BAD_PARAMETER:
850       return EGL_BAD_PARAMETER;
851    case STW_IMAGE_ERROR_BAD_ACCESS:
852       return EGL_BAD_ACCESS;
853    default:
854       assert(!"unknown stw_image_error code");
855       return EGL_BAD_ALLOC;
856    }
857 }
858
859 static _EGLImage *
860 wgl_create_image_khr_texture(_EGLDisplay *disp, _EGLContext *ctx,
861                                    EGLenum target,
862                                    EGLClientBuffer buffer,
863                                    const EGLint *attr_list)
864 {
865    struct wgl_egl_context *wgl_ctx = wgl_egl_context(ctx);
866    struct wgl_egl_image *wgl_img;
867    GLuint texture = (GLuint) (uintptr_t) buffer;
868    _EGLImageAttribs attrs;
869    GLuint depth;
870    GLenum gl_target;
871    enum stw_image_error error;
872
873    if (texture == 0) {
874       _eglError(EGL_BAD_PARAMETER, "wgl_create_image_khr");
875       return EGL_NO_IMAGE_KHR;
876    }
877
878    if (!_eglParseImageAttribList(&attrs, disp, attr_list))
879       return EGL_NO_IMAGE_KHR;
880
881    switch (target) {
882    case EGL_GL_TEXTURE_2D_KHR:
883       depth = 0;
884       gl_target = GL_TEXTURE_2D;
885       break;
886    case EGL_GL_TEXTURE_3D_KHR:
887       depth = attrs.GLTextureZOffset;
888       gl_target = GL_TEXTURE_3D;
889       break;
890    case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR:
891    case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR:
892    case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR:
893    case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR:
894    case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR:
895    case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR:
896       depth = target - EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR;
897       gl_target = GL_TEXTURE_CUBE_MAP;
898       break;
899    default:
900       unreachable("Unexpected target in wgl_create_image_khr_texture()");
901       return EGL_NO_IMAGE_KHR;
902    }
903
904    wgl_img = malloc(sizeof *wgl_img);
905    if (!wgl_img) {
906       _eglError(EGL_BAD_ALLOC, "wgl_create_image_khr");
907       return EGL_NO_IMAGE_KHR;
908    }
909
910    _eglInitImage(&wgl_img->base, disp);
911
912    wgl_img->img = stw_create_image_from_texture(wgl_ctx->ctx,
913                                                 gl_target,
914                                                 texture,
915                                                 depth,
916                                                 attrs.GLTextureLevel,
917                                                 &error);
918    assert(!!wgl_img->img == (error == STW_IMAGE_ERROR_SUCCESS));
919
920    if (!wgl_img->img) {
921       free(wgl_img);
922       _eglError(egl_error_from_stw_image_error(error), "wgl_create_image_khr");
923       return EGL_NO_IMAGE_KHR;
924    }
925    return &wgl_img->base;
926 }
927
928 static _EGLImage *
929 wgl_create_image_khr_renderbuffer(_EGLDisplay *disp, _EGLContext *ctx,
930                                    EGLClientBuffer buffer,
931                                    const EGLint *attr_list)
932 {
933    struct wgl_egl_context *wgl_ctx = wgl_egl_context(ctx);
934    struct wgl_egl_image *wgl_img;
935    GLuint renderbuffer = (GLuint) (uintptr_t) buffer;
936    enum stw_image_error error;
937
938    if (renderbuffer == 0) {
939       _eglError(EGL_BAD_PARAMETER, "wgl_create_image_khr");
940       return EGL_NO_IMAGE_KHR;
941    }
942
943    wgl_img = malloc(sizeof(*wgl_img));
944    if (!wgl_img) {
945       _eglError(EGL_BAD_ALLOC, "wgl_create_image");
946       return NULL;
947    }
948
949    _eglInitImage(&wgl_img->base, disp);
950
951    wgl_img->img = stw_create_image_from_renderbuffer(wgl_ctx->ctx, renderbuffer, &error);
952    assert(!!wgl_img->img == (error == STW_IMAGE_ERROR_SUCCESS));
953
954    if (!wgl_img->img) {
955       free(wgl_img);
956       _eglError(egl_error_from_stw_image_error(error), "wgl_create_image_khr");
957       return EGL_NO_IMAGE_KHR;
958    }
959
960    return &wgl_img->base;
961 }
962
963 static _EGLImage *
964 wgl_create_image_khr(_EGLDisplay *disp, _EGLContext *ctx, EGLenum target,
965                       EGLClientBuffer buffer, const EGLint *attr_list)
966 {
967    switch (target) {
968    case EGL_GL_TEXTURE_2D_KHR:
969    case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR:
970    case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR:
971    case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR:
972    case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR:
973    case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR:
974    case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR:
975    case EGL_GL_TEXTURE_3D_KHR:
976       return wgl_create_image_khr_texture(disp, ctx, target, buffer, attr_list);
977    case EGL_GL_RENDERBUFFER_KHR:
978       return wgl_create_image_khr_renderbuffer(disp, ctx, buffer, attr_list);
979    default:
980       _eglError(EGL_BAD_PARAMETER, "wgl_create_image_khr");
981       return EGL_NO_IMAGE_KHR;
982    }
983 }
984
985 static EGLBoolean
986 wgl_destroy_image_khr(_EGLDisplay *disp, _EGLImage *img)
987 {
988    struct wgl_egl_image *wgl_img = wgl_egl_image(img);
989    stw_destroy_image(wgl_img->img);
990    free(wgl_img);
991    return EGL_TRUE;
992 }
993
994 struct _egl_driver _eglDriver = {
995    .Initialize = wgl_initialize,
996    .Terminate = wgl_terminate,
997    .CreateContext = wgl_create_context,
998    .DestroyContext = wgl_destroy_context,
999    .MakeCurrent = wgl_make_current,
1000    .CreateWindowSurface = wgl_create_window_surface,
1001    .CreatePbufferSurface = wgl_create_pbuffer_surface,
1002    .DestroySurface = wgl_destroy_surface,
1003    .QuerySurface = wgl_query_surface,
1004    .BindTexImage = wgl_bind_tex_image,
1005    .ReleaseTexImage = _eglReleaseTexImage,
1006    .GetProcAddress = _glapi_get_proc_address,
1007    .SwapInterval = wgl_swap_interval,
1008    .SwapBuffers = wgl_swap_buffers,
1009    .WaitClient = wgl_wait_client,
1010    .WaitNative = wgl_wait_native,
1011    .CreateImageKHR = wgl_create_image_khr,
1012    .DestroyImageKHR = wgl_destroy_image_khr,
1013 };
1014