Add exception handle for multithread case.
[platform/upstream/mesa.git] / src / egl / drivers / dri2 / egl_dri2.c
index 8e2767a..d04ed54 100644 (file)
@@ -826,6 +826,13 @@ dri2_load_driver_common(_EGLDisplay *disp,
    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
    const __DRIextension **extensions;
 
+   /*This exception only happen in multithread case, when _eglAtExit is *
+    *called and disp is freed in main thread.                           */
+   if (dri2_dpy == NULL) {
+      _eglLog(_EGL_FATAL, "DRI2: disp is freed");
+      return EGL_FALSE;
+   }
+
    extensions = dri2_open_driver(disp);
    if (!extensions)
       return EGL_FALSE;
@@ -1207,6 +1214,12 @@ dri2_initialize(_EGLDisplay *disp)
    case _EGL_PLATFORM_ANDROID:
       ret = dri2_initialize_android(disp);
       break;
+
+#ifdef HAVE_TIZEN_PLATFORM
+   case _EGL_PLATFORM_TIZEN:
+      ret = dri2_initialize_tizen(disp);
+      break;
+#endif
    default:
       unreachable("Callers ensure we cannot get here.");
       return EGL_FALSE;
@@ -1282,6 +1295,12 @@ dri2_display_destroy(_EGLDisplay *disp)
    case _EGL_PLATFORM_WAYLAND:
       dri2_teardown_wayland(dri2_dpy);
       break;
+
+#ifdef HAVE_TIZEN_PLATFORM
+   case _EGL_PLATFORM_TIZEN:
+      dri2_teardown_tizen(disp);
+      break;
+#endif
    default:
       /* TODO: add teardown for other platforms */
       break;
@@ -3470,6 +3489,94 @@ dri2_query_wayland_buffer_wl(_EGLDisplay *disp, struct wl_resource *buffer_resou
 }
 #endif
 
+#ifdef HAVE_TIZEN_PLATFORM
+static EGLBoolean
+tizen_bind_wayland_display_wl(_EGLDisplay *disp,
+                              struct wl_display *wl_dpy)
+{
+   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
+
+   (void) wl_dpy;
+
+   if (!dri2_dpy->tpl_display)
+     return EGL_FALSE;
+
+   if (!tpl_display_get_native_handle(dri2_dpy->tpl_display))
+     return EGL_FALSE;
+
+   return EGL_TRUE;
+}
+
+static EGLBoolean
+tizen_unbind_wayland_display_wl(_EGLDisplay *disp,
+                                struct wl_display *wl_dpy)
+{
+   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
+
+   (void) wl_dpy;
+
+   if (!dri2_dpy->tpl_display)
+     return EGL_FALSE;
+
+   if (!tpl_display_get_native_handle(dri2_dpy->tpl_display))
+     return EGL_FALSE;
+
+   return EGL_TRUE;
+}
+
+static EGLBoolean
+tizen_query_wayland_buffer_wl(_EGLDisplay *disp,
+                              struct wl_resource *buffer_resource,
+                              EGLint attribute, EGLint *value)
+{
+   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
+   tbm_format tbm_format = 0;
+   int width = 0, height = 0;
+   tpl_result_t res;
+
+   if (!dri2_dpy->tpl_display)
+     return EGL_FALSE;
+
+   if (!tpl_display_get_native_handle(dri2_dpy->tpl_display))
+     return EGL_FALSE;
+
+   res = tpl_display_get_native_pixmap_info(dri2_dpy->tpl_display,
+                                            (tpl_handle_t)buffer_resource,
+                                            &width, &height, &tbm_format);
+   if (res != TPL_ERROR_NONE)
+     return EGL_FALSE;
+
+   switch (attribute) {
+   case EGL_TEXTURE_FORMAT:
+      switch (tbm_format) {
+      case TBM_FORMAT_ARGB8888:
+         *value = EGL_TEXTURE_RGBA;
+         return EGL_TRUE;
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wswitch"
+      case TBM_FORMAT_XRGB8888:
+      case TBM_FORMAT_RGB565:
+#pragma GCC diagnostic pop
+         *value = EGL_TEXTURE_RGB;
+         return EGL_TRUE;
+      default:
+         break;
+      }
+      break;
+   case EGL_WIDTH:
+      *value = width;
+      return EGL_TRUE;
+   case EGL_HEIGHT:
+      *value = height;
+      return EGL_TRUE;
+   default:
+      break;
+   }
+
+   return EGL_FALSE;
+}
+#endif
+
 static void
 dri2_egl_ref_sync(struct dri2_egl_sync *sync)
 {
@@ -3485,10 +3592,17 @@ dri2_egl_unref_sync(struct dri2_egl_display *dri2_dpy,
       case EGL_SYNC_REUSABLE_KHR:
          cnd_destroy(&dri2_sync->cond);
          break;
+#ifdef HAVE_TIZEN_PLATFORM
+      case EGL_SYNC_NATIVE_FENCE_TIZEN:
+         if (dri2_sync->base.SyncFd != EGL_NO_NATIVE_FENCE_FD_TIZEN)
+            close(dri2_sync->base.SyncFd);
+         break;
+#else
       case EGL_SYNC_NATIVE_FENCE_ANDROID:
          if (dri2_sync->base.SyncFd != EGL_NO_NATIVE_FENCE_FD_ANDROID)
             close(dri2_sync->base.SyncFd);
          break;
+#endif
       default:
          break;
       }
@@ -3576,7 +3690,8 @@ dri2_create_sync(_EGLDisplay *disp, EGLenum type, const EGLAttrib *attrib_list)
       dri2_sync->base.SyncStatus = EGL_UNSIGNALED_KHR;
       break;
 
-   case EGL_SYNC_NATIVE_FENCE_ANDROID:
+#ifdef HAVE_TIZEN_PLATFORM
+   case EGL_SYNC_NATIVE_FENCE_TIZEN:
       if (dri2_dpy->fence->create_fence_fd) {
          dri2_sync->fence = dri2_dpy->fence->create_fence_fd(
                                     dri2_ctx->dri_context,
@@ -3588,6 +3703,20 @@ dri2_create_sync(_EGLDisplay *disp, EGLenum type, const EGLAttrib *attrib_list)
       }
       break;
    }
+#else
+   case EGL_SYNC_NATIVE_FENCE_ANDROID:
+      if (dri2_dpy->fence->create_fence_fd) {
+         dri2_sync->fence = dri2_dpy->fence->create_fence_fd(
+                                    dri2_ctx->dri_context,
+                                    dri2_sync->base.SyncFd);
+      }
+      if (!dri2_sync->fence) {
+         _eglError(EGL_BAD_ATTRIBUTE, "eglCreateSyncKHR");
+         free(dri2_sync);
+         return NULL;
+      }
+      break;
+#endif
 
    p_atomic_set(&dri2_sync->refcount, 1);
    mtx_unlock(&dri2_dpy->lock);
@@ -3660,6 +3789,31 @@ dri2_dup_native_fence_fd(_EGLDisplay *disp, _EGLSync *sync)
    return os_dupfd_cloexec(sync->SyncFd);
 }
 
+static EGLint
+dri2_dup_native_fence_fd_tizen(_EGLDisplay *dpy, _EGLSync *sync)
+{
+   struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
+   struct dri2_egl_sync *dri2_sync = dri2_egl_sync(sync);
+
+   assert(sync->Type == EGL_SYNC_NATIVE_FENCE_TIZEN);
+
+   if (sync->SyncFd == EGL_NO_NATIVE_FENCE_FD_TIZEN) {
+      /* try to retrieve the actual native fence fd.. if rendering is
+       * not flushed this will just return -1, aka NO_NATIVE_FENCE_FD:
+       */
+      sync->SyncFd = dri2_dpy->fence->get_fence_fd(dri2_dpy->dri_screen,
+                                                   dri2_sync->fence);
+   }
+
+   if (sync->SyncFd == EGL_NO_NATIVE_FENCE_FD_TIZEN) {
+      /* if native fence fd still not created, return an error: */
+      _eglError(EGL_BAD_PARAMETER, "eglDupNativeFenceFDTIZEN");
+      return EGL_NO_NATIVE_FENCE_FD_TIZEN;
+   }
+
+   return dup(sync->SyncFd);
+}
+
 static void
 dri2_set_blob_cache_funcs(_EGLDisplay *disp,
                           EGLSetBlobFuncANDROID set,
@@ -3695,7 +3849,11 @@ dri2_client_wait_sync(_EGLDisplay *disp, _EGLSync *sync,
 
    switch (sync->Type) {
    case EGL_SYNC_FENCE_KHR:
+#ifdef HAVE_TIZEN_PLATFORM
+   case EGL_SYNC_NATIVE_FENCE_TIZEN:
+#else
    case EGL_SYNC_NATIVE_FENCE_ANDROID:
+#endif
    case EGL_SYNC_CL_EVENT_KHR:
       if (dri2_dpy->fence->client_wait_sync(dri2_ctx ? dri2_ctx->dri_context : NULL,
                                          dri2_sync->fence, wait_flags,
@@ -3884,6 +4042,11 @@ const _EGLDriver _eglDriver = {
    .UnbindWaylandDisplayWL = dri2_unbind_wayland_display_wl,
    .QueryWaylandBufferWL = dri2_query_wayland_buffer_wl,
 #endif
+#ifdef HAVE_TIZEN_PLATFORM
+   .BindWaylandDisplayWL = tizen_bind_wayland_display_wl,
+   .UnbindWaylandDisplayWL = tizen_unbind_wayland_display_wl,
+   .QueryWaylandBufferWL = tizen_query_wayland_buffer_wl,
+ #endif
    .GetSyncValuesCHROMIUM = dri2_get_sync_values_chromium,
    .GetMscRateANGLE = dri2_get_msc_rate_angle,
    .CreateSyncKHR = dri2_create_sync,
@@ -3895,5 +4058,6 @@ const _EGLDriver _eglDriver = {
    .GLInteropExportObject = dri2_interop_export_object,
    .GLInteropFlushObjects = dri2_interop_flush_objects,
    .DupNativeFenceFDANDROID = dri2_dup_native_fence_fd,
+   .DupNativeFenceFDTIZEN = dri2_dup_native_fence_fd_tizen,
    .SetBlobCacheFuncsANDROID = dri2_set_blob_cache_funcs,
 };