egl: replace _eglInitDriver() with a simple variable
[mesa.git] / src / egl / drivers / dri2 / egl_dri2.c
index f42ba6687f59c24150326fd623d3f87793e6c47c..2114077470e48ed8cacde258100e2ba092a8d948 100644 (file)
@@ -1768,6 +1768,7 @@ dri2_make_current(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *dsurf,
    _EGLSurface *tmp_dsurf, *tmp_rsurf;
    __DRIdrawable *ddraw, *rdraw;
    __DRIcontext *cctx;
+   EGLint egl_error = EGL_SUCCESS;
 
    if (!dri2_dpy)
       return _eglError(EGL_NOT_INITIALIZED, "eglMakeCurrent");
@@ -1802,17 +1803,20 @@ dri2_make_current(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *dsurf,
 
    if (cctx || ddraw || rdraw) {
       if (!dri2_dpy->core->bindContext(cctx, ddraw, rdraw)) {
+         _EGLContext *tmp_ctx;
+
+         /* dri2_dpy->core->bindContext failed. We cannot tell for sure why, but
+          * setting the error to EGL_BAD_MATCH is surely better than leaving it
+          * as EGL_SUCCESS.
+          */
+         egl_error = EGL_BAD_MATCH;
+
          /* undo the previous _eglBindContext */
          _eglBindContext(old_ctx, old_dsurf, old_rsurf, &ctx, &tmp_dsurf, &tmp_rsurf);
          assert(&dri2_ctx->base == ctx &&
                 tmp_dsurf == dsurf &&
                 tmp_rsurf == rsurf);
 
-         if (old_dsurf && _eglSurfaceInSharedBufferMode(old_dsurf) &&
-             old_dri2_dpy->vtbl->set_shared_buffer_mode) {
-            old_dri2_dpy->vtbl->set_shared_buffer_mode(old_disp, old_dsurf, true);
-         }
-
          _eglPutSurface(dsurf);
          _eglPutSurface(rsurf);
          _eglPutContext(ctx);
@@ -1821,14 +1825,41 @@ dri2_make_current(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *dsurf,
          _eglPutSurface(old_rsurf);
          _eglPutContext(old_ctx);
 
-         /* dri2_dpy->core->bindContext failed. We cannot tell for sure why, but
-          * setting the error to EGL_BAD_MATCH is surely better than leaving it
-          * as EGL_SUCCESS.
+         ddraw = (old_dsurf) ? dri2_dpy->vtbl->get_dri_drawable(old_dsurf) : NULL;
+         rdraw = (old_rsurf) ? dri2_dpy->vtbl->get_dri_drawable(old_rsurf) : NULL;
+         cctx = (old_ctx) ? dri2_egl_context(old_ctx)->dri_context : NULL;
+
+         /* undo the previous dri2_dpy->core->unbindContext */
+         if (dri2_dpy->core->bindContext(cctx, ddraw, rdraw)) {
+            if (old_dsurf && _eglSurfaceInSharedBufferMode(old_dsurf) &&
+                old_dri2_dpy->vtbl->set_shared_buffer_mode) {
+               old_dri2_dpy->vtbl->set_shared_buffer_mode(old_disp, old_dsurf, true);
+            }
+
+            return _eglError(egl_error, "eglMakeCurrent");
+         }
+
+         /* We cannot restore the same state as it was before calling
+          * eglMakeCurrent() and the spec isn't clear about what to do. We
+          * can prevent EGL from calling into the DRI driver with no DRI
+          * context bound.
           */
-         return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
-      }
+         dsurf = rsurf = NULL;
+         ctx = NULL;
 
-      dri2_dpy->ref_count++;
+         _eglBindContext(ctx, dsurf, rsurf, &tmp_ctx, &tmp_dsurf, &tmp_rsurf);
+         assert(tmp_ctx == old_ctx && tmp_dsurf == old_dsurf &&
+                tmp_rsurf == old_rsurf);
+
+         _eglLog(_EGL_WARNING, "DRI2: failed to rebind the previous context");
+      } else {
+         /* dri2_dpy->core->bindContext succeeded, so take a reference on the
+          * dri2_dpy. This prevents dri2_dpy from being reinitialized when a
+          * EGLDisplay is terminated and then initialized again while a
+          * context is still bound. See dri2_intitialize() for a more in depth
+          * explanation. */
+         dri2_dpy->ref_count++;
+      }
    }
 
    dri2_destroy_surface(drv, disp, old_dsurf);
@@ -1839,6 +1870,9 @@ dri2_make_current(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *dsurf,
       dri2_display_release(old_disp);
    }
 
+   if (egl_error != EGL_SUCCESS)
+      return _eglError(egl_error, "eglMakeCurrent");
+
    if (dsurf && _eglSurfaceHasMutableRenderBuffer(dsurf) &&
        dri2_dpy->vtbl->set_shared_buffer_mode) {
       /* Always update the shared buffer mode. This is obviously needed when
@@ -3640,62 +3674,56 @@ dri2_interop_export_object(_EGLDisplay *disp, _EGLContext *ctx,
    return dri2_dpy->interop->export_object(dri2_ctx->dri_context, in, out);
 }
 
-/**
- * This is the main entrypoint into the driver, called by libEGL.
- * Gets an _EGLDriver object and init its dispatch table.
- */
-void
-_eglInitDriver(_EGLDriver *dri2_drv)
-{
-   dri2_drv->Initialize = dri2_initialize;
-   dri2_drv->Terminate = dri2_terminate;
-   dri2_drv->CreateContext = dri2_create_context;
-   dri2_drv->DestroyContext = dri2_destroy_context;
-   dri2_drv->MakeCurrent = dri2_make_current;
-   dri2_drv->CreateWindowSurface = dri2_create_window_surface;
-   dri2_drv->CreatePixmapSurface = dri2_create_pixmap_surface;
-   dri2_drv->CreatePbufferSurface = dri2_create_pbuffer_surface;
-   dri2_drv->DestroySurface = dri2_destroy_surface;
-   dri2_drv->GetProcAddress = dri2_get_proc_address;
-   dri2_drv->WaitClient = dri2_wait_client;
-   dri2_drv->WaitNative = dri2_wait_native;
-   dri2_drv->BindTexImage = dri2_bind_tex_image;
-   dri2_drv->ReleaseTexImage = dri2_release_tex_image;
-   dri2_drv->SwapInterval = dri2_swap_interval;
-   dri2_drv->SwapBuffers = dri2_swap_buffers;
-   dri2_drv->SwapBuffersWithDamageEXT = dri2_swap_buffers_with_damage;
-   dri2_drv->SwapBuffersRegionNOK = dri2_swap_buffers_region;
-   dri2_drv->SetDamageRegion = dri2_set_damage_region;
-   dri2_drv->PostSubBufferNV = dri2_post_sub_buffer;
-   dri2_drv->CopyBuffers = dri2_copy_buffers,
-   dri2_drv->QueryBufferAge = dri2_query_buffer_age;
-   dri2_drv->CreateImageKHR = dri2_create_image;
-   dri2_drv->DestroyImageKHR = dri2_destroy_image_khr;
-   dri2_drv->CreateWaylandBufferFromImageWL = dri2_create_wayland_buffer_from_image;
-   dri2_drv->QuerySurface = dri2_query_surface;
-   dri2_drv->QueryDriverName = dri2_query_driver_name;
-   dri2_drv->QueryDriverConfig = dri2_query_driver_config;
+_EGLDriver _eglDriver = {
+   .Initialize = dri2_initialize,
+   .Terminate = dri2_terminate,
+   .CreateContext = dri2_create_context,
+   .DestroyContext = dri2_destroy_context,
+   .MakeCurrent = dri2_make_current,
+   .CreateWindowSurface = dri2_create_window_surface,
+   .CreatePixmapSurface = dri2_create_pixmap_surface,
+   .CreatePbufferSurface = dri2_create_pbuffer_surface,
+   .DestroySurface = dri2_destroy_surface,
+   .GetProcAddress = dri2_get_proc_address,
+   .WaitClient = dri2_wait_client,
+   .WaitNative = dri2_wait_native,
+   .BindTexImage = dri2_bind_tex_image,
+   .ReleaseTexImage = dri2_release_tex_image,
+   .SwapInterval = dri2_swap_interval,
+   .SwapBuffers = dri2_swap_buffers,
+   .SwapBuffersWithDamageEXT = dri2_swap_buffers_with_damage,
+   .SwapBuffersRegionNOK = dri2_swap_buffers_region,
+   .SetDamageRegion = dri2_set_damage_region,
+   .PostSubBufferNV = dri2_post_sub_buffer,
+   .CopyBuffers = dri2_copy_buffers,
+   .QueryBufferAge = dri2_query_buffer_age,
+   .CreateImageKHR = dri2_create_image,
+   .DestroyImageKHR = dri2_destroy_image_khr,
+   .CreateWaylandBufferFromImageWL = dri2_create_wayland_buffer_from_image,
+   .QuerySurface = dri2_query_surface,
+   .QueryDriverName = dri2_query_driver_name,
+   .QueryDriverConfig = dri2_query_driver_config,
 #ifdef HAVE_LIBDRM
-   dri2_drv->CreateDRMImageMESA = dri2_create_drm_image_mesa;
-   dri2_drv->ExportDRMImageMESA = dri2_export_drm_image_mesa;
-   dri2_drv->ExportDMABUFImageQueryMESA = dri2_export_dma_buf_image_query_mesa;
-   dri2_drv->ExportDMABUFImageMESA = dri2_export_dma_buf_image_mesa;
-   dri2_drv->QueryDmaBufFormatsEXT = dri2_query_dma_buf_formats;
-   dri2_drv->QueryDmaBufModifiersEXT = dri2_query_dma_buf_modifiers;
+   .CreateDRMImageMESA = dri2_create_drm_image_mesa,
+   .ExportDRMImageMESA = dri2_export_drm_image_mesa,
+   .ExportDMABUFImageQueryMESA = dri2_export_dma_buf_image_query_mesa,
+   .ExportDMABUFImageMESA = dri2_export_dma_buf_image_mesa,
+   .QueryDmaBufFormatsEXT = dri2_query_dma_buf_formats,
+   .QueryDmaBufModifiersEXT = dri2_query_dma_buf_modifiers,
 #endif
 #ifdef HAVE_WAYLAND_PLATFORM
-   dri2_drv->BindWaylandDisplayWL = dri2_bind_wayland_display_wl;
-   dri2_drv->UnbindWaylandDisplayWL = dri2_unbind_wayland_display_wl;
-   dri2_drv->QueryWaylandBufferWL = dri2_query_wayland_buffer_wl;
+   .BindWaylandDisplayWL = dri2_bind_wayland_display_wl,
+   .UnbindWaylandDisplayWL = dri2_unbind_wayland_display_wl,
+   .QueryWaylandBufferWL = dri2_query_wayland_buffer_wl,
 #endif
-   dri2_drv->GetSyncValuesCHROMIUM = dri2_get_sync_values_chromium;
-   dri2_drv->CreateSyncKHR = dri2_create_sync;
-   dri2_drv->ClientWaitSyncKHR = dri2_client_wait_sync;
-   dri2_drv->SignalSyncKHR = dri2_signal_sync;
-   dri2_drv->WaitSyncKHR = dri2_server_wait_sync;
-   dri2_drv->DestroySyncKHR = dri2_destroy_sync;
-   dri2_drv->GLInteropQueryDeviceInfo = dri2_interop_query_device_info;
-   dri2_drv->GLInteropExportObject = dri2_interop_export_object;
-   dri2_drv->DupNativeFenceFDANDROID = dri2_dup_native_fence_fd;
-   dri2_drv->SetBlobCacheFuncsANDROID = dri2_set_blob_cache_funcs;
-}
+   .GetSyncValuesCHROMIUM = dri2_get_sync_values_chromium,
+   .CreateSyncKHR = dri2_create_sync,
+   .ClientWaitSyncKHR = dri2_client_wait_sync,
+   .SignalSyncKHR = dri2_signal_sync,
+   .WaitSyncKHR = dri2_server_wait_sync,
+   .DestroySyncKHR = dri2_destroy_sync,
+   .GLInteropQueryDeviceInfo = dri2_interop_query_device_info,
+   .GLInteropExportObject = dri2_interop_export_object,
+   .DupNativeFenceFDANDROID = dri2_dup_native_fence_fd,
+   .SetBlobCacheFuncsANDROID = dri2_set_blob_cache_funcs,
+};