gallium: add type parameter to create_fence_fd
[mesa.git] / src / gallium / state_trackers / dri / dri_helpers.c
index b3a2cb78f9c3e309e214cfdaebaba593f4a32da2..f1501bfb81531944df51cca21ac2c50c0979be97 100644 (file)
  */
 
 #include <dlfcn.h>
-#include "dri_context.h"
-#include "dri_screen.h"
-#include "pipe/p_screen.h"
 #include "util/u_memory.h"
+#include "pipe/p_screen.h"
+#include "state_tracker/st_texture.h"
+#include "state_tracker/st_context.h"
+#include "state_tracker/st_cb_fbo.h"
+#include "main/texobj.h"
+
+#include "dri_helpers.h"
 
 static bool
 dri2_is_opencl_interop_loaded_locked(struct dri_screen *screen)
@@ -86,13 +90,13 @@ static unsigned dri2_fence_get_caps(__DRIscreen *_screen)
 static void *
 dri2_create_fence(__DRIcontext *_ctx)
 {
-   struct pipe_context *ctx = dri_context(_ctx)->st->pipe;
+   struct st_context_iface *stapi = dri_context(_ctx)->st;
    struct dri2_fence *fence = CALLOC_STRUCT(dri2_fence);
 
    if (!fence)
       return NULL;
 
-   ctx->flush(ctx, &fence->pipe_fence, 0);
+   stapi->flush(stapi, 0, &fence->pipe_fence);
 
    if (!fence->pipe_fence) {
       FREE(fence);
@@ -106,16 +110,16 @@ dri2_create_fence(__DRIcontext *_ctx)
 static void *
 dri2_create_fence_fd(__DRIcontext *_ctx, int fd)
 {
-   struct pipe_context *ctx = dri_context(_ctx)->st->pipe;
+   struct st_context_iface *stapi = dri_context(_ctx)->st;
+   struct pipe_context *ctx = stapi->pipe;
    struct dri2_fence *fence = CALLOC_STRUCT(dri2_fence);
 
    if (fd == -1) {
       /* exporting driver created fence, flush: */
-      ctx->flush(ctx, &fence->pipe_fence,
-                 PIPE_FLUSH_DEFERRED | PIPE_FLUSH_FENCE_FD);
+      stapi->flush(stapi, ST_FLUSH_FENCE_FD, &fence->pipe_fence);
    } else {
       /* importing a foreign fence fd: */
-      ctx->create_fence_fd(ctx, &fence->pipe_fence, fd);
+      ctx->create_fence_fd(ctx, &fence->pipe_fence, fd, PIPE_FD_TYPE_NATIVE_SYNC);
    }
    if (!fence->pipe_fence) {
       FREE(fence);
@@ -227,4 +231,158 @@ const __DRI2fenceExtension dri2FenceExtension = {
    .get_fence_fd = dri2_get_fence_fd,
 };
 
+__DRIimage *
+dri2_lookup_egl_image(struct dri_screen *screen, void *handle)
+{
+   const __DRIimageLookupExtension *loader = screen->sPriv->dri2.image;
+   __DRIimage *img;
+
+   if (!loader->lookupEGLImage)
+      return NULL;
+
+   img = loader->lookupEGLImage(screen->sPriv,
+                               handle, screen->sPriv->loaderPrivate);
+
+   return img;
+}
+
+__DRIimage *
+dri2_create_image_from_renderbuffer2(__DRIcontext *context,
+                                    int renderbuffer, void *loaderPrivate,
+                                     unsigned *error)
+{
+   struct gl_context *ctx = ((struct st_context *)dri_context(context)->st)->ctx;
+   struct gl_renderbuffer *rb;
+   struct pipe_resource *tex;
+   __DRIimage *img;
+
+   /* Section 3.9 (EGLImage Specification and Management) of the EGL 1.5
+    * specification says:
+    *
+    *   "If target is EGL_GL_RENDERBUFFER and buffer is not the name of a
+    *    renderbuffer object, or if buffer is the name of a multisampled
+    *    renderbuffer object, the error EGL_BAD_PARAMETER is generated."
+    *
+    *   "If target is EGL_GL_TEXTURE_2D , EGL_GL_TEXTURE_CUBE_MAP_*,
+    *    EGL_GL_RENDERBUFFER or EGL_GL_TEXTURE_3D and buffer refers to the
+    *    default GL texture object (0) for the corresponding GL target, the
+    *    error EGL_BAD_PARAMETER is generated."
+    *   (rely on _mesa_lookup_renderbuffer returning NULL in this case)
+    */
+   rb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
+   if (!rb || rb->NumSamples > 0) {
+      *error = __DRI_IMAGE_ERROR_BAD_PARAMETER;
+      return NULL;
+   }
+
+   tex = st_get_renderbuffer_resource(rb);
+   if (!tex) {
+      *error = __DRI_IMAGE_ERROR_BAD_PARAMETER;
+      return NULL;
+   }
+
+   img = CALLOC_STRUCT(__DRIimageRec);
+   if (!img) {
+      *error = __DRI_IMAGE_ERROR_BAD_ALLOC;
+      return NULL;
+   }
+
+   img->dri_format = driGLFormatToImageFormat(rb->Format);
+   img->loader_private = loaderPrivate;
+
+   if (img->dri_format == __DRI_IMAGE_FORMAT_NONE) {
+      *error = __DRI_IMAGE_ERROR_BAD_PARAMETER;
+      free(img);
+      return NULL;
+   }
+
+   pipe_resource_reference(&img->texture, tex);
+
+   *error = __DRI_IMAGE_ERROR_SUCCESS;
+   return img;
+}
+
+__DRIimage *
+dri2_create_image_from_renderbuffer(__DRIcontext *context,
+                                   int renderbuffer, void *loaderPrivate)
+{
+   unsigned error;
+   return dri2_create_image_from_renderbuffer2(context, renderbuffer,
+                                               loaderPrivate, &error);
+}
+
+void
+dri2_destroy_image(__DRIimage *img)
+{
+   pipe_resource_reference(&img->texture, NULL);
+   FREE(img);
+}
+
+
+__DRIimage *
+dri2_create_from_texture(__DRIcontext *context, int target, unsigned texture,
+                         int depth, int level, unsigned *error,
+                         void *loaderPrivate)
+{
+   __DRIimage *img;
+   struct gl_context *ctx = ((struct st_context *)dri_context(context)->st)->ctx;
+   struct gl_texture_object *obj;
+   struct pipe_resource *tex;
+   GLuint face = 0;
+
+   obj = _mesa_lookup_texture(ctx, texture);
+   if (!obj || obj->Target != target) {
+      *error = __DRI_IMAGE_ERROR_BAD_PARAMETER;
+      return NULL;
+   }
+
+   tex = st_get_texobj_resource(obj);
+   if (!tex) {
+      *error = __DRI_IMAGE_ERROR_BAD_PARAMETER;
+      return NULL;
+   }
+
+   if (target == GL_TEXTURE_CUBE_MAP)
+      face = depth;
+
+   _mesa_test_texobj_completeness(ctx, obj);
+   if (!obj->_BaseComplete || (level > 0 && !obj->_MipmapComplete)) {
+      *error = __DRI_IMAGE_ERROR_BAD_PARAMETER;
+      return NULL;
+   }
+
+   if (level < obj->BaseLevel || level > obj->_MaxLevel) {
+      *error = __DRI_IMAGE_ERROR_BAD_MATCH;
+      return NULL;
+   }
+
+   if (target == GL_TEXTURE_3D && obj->Image[face][level]->Depth < depth) {
+      *error = __DRI_IMAGE_ERROR_BAD_MATCH;
+      return NULL;
+   }
+
+   img = CALLOC_STRUCT(__DRIimageRec);
+   if (!img) {
+      *error = __DRI_IMAGE_ERROR_BAD_ALLOC;
+      return NULL;
+   }
+
+   img->level = level;
+   img->layer = depth;
+   img->dri_format = driGLFormatToImageFormat(obj->Image[face][level]->TexFormat);
+
+   img->loader_private = loaderPrivate;
+
+   if (img->dri_format == __DRI_IMAGE_FORMAT_NONE) {
+      *error = __DRI_IMAGE_ERROR_BAD_PARAMETER;
+      free(img);
+      return NULL;
+   }
+
+   pipe_resource_reference(&img->texture, tex);
+
+   *error = __DRI_IMAGE_ERROR_SUCCESS;
+   return img;
+}
+
 /* vim: set sw=3 ts=8 sts=3 expandtab: */