st/dri: Implement DRI image extension.
authorChia-I Wu <olv@lunarg.com>
Tue, 6 Apr 2010 10:55:40 +0000 (18:55 +0800)
committerChia-I Wu <olv@lunarg.com>
Tue, 6 Apr 2010 11:32:27 +0000 (19:32 +0800)
src/gallium/state_trackers/dri/common/dri_st_api.c
src/gallium/state_trackers/dri/common/dri_st_api.h
src/gallium/state_trackers/dri/drm/dri2.c
src/gallium/state_trackers/dri/drm/dri2.h

index 1a5259c68ba4b3bfb3201408f0a8e79478ebdf28..561e6aa3b626ce2e10ca73b134ca102e32ab9e6e 100644 (file)
@@ -224,6 +224,31 @@ _dri_put_st_api(void)
    }
 }
 
+static boolean
+dri_st_manager_get_egl_image(struct st_manager *smapi,
+                             struct st_egl_image *stimg)
+{
+   __DRIimage *img = NULL;
+
+#ifndef __NOT_HAVE_DRM_H
+   if (!__dri1_api_hooks) {
+      struct dri_context *ctx = (struct dri_context *)
+         stimg->stctxi->st_manager_private;
+      img = dri2_lookup_egl_image(ctx, stimg->egl_image);
+   }
+#endif
+   if (!img)
+      return FALSE;
+
+   stimg->texture = NULL;
+   pipe_texture_reference(&stimg->texture, img->texture);
+   stimg->face = img->face;
+   stimg->level = img->level;
+   stimg->zslice = img->zslice;
+
+   return TRUE;
+}
+
 /**
  * Create a state tracker manager from the given screen.
  */
@@ -235,6 +260,7 @@ dri_create_st_manager(struct dri_screen *screen)
    smapi = CALLOC_STRUCT(st_manager);
    if (smapi) {
       smapi->screen = screen->pipe_screen;
+      smapi->get_egl_image = dri_st_manager_get_egl_image;
       _dri_get_st_api();
    }
 
index 99a217bfa79c008601b5081848468da104a1dbac..f41c1c6674c88dc6b6c4382c3d6ab7b8f7349076 100644 (file)
 struct dri_screen;
 struct dri_drawable;
 
+struct __DRIimageRec {
+   struct pipe_texture *texture;
+   unsigned face;
+   unsigned level;
+   unsigned zslice;
+
+   void *loader_private;
+};
+
 struct st_api *
 dri_get_st_api(void);
 
index c632f0fe4f365ca2c71c3b561a1d203747c441c5..420ff0ee59e64e6ca1d1f326e6d0d91ad7ba37c8 100644 (file)
@@ -352,6 +352,110 @@ dri2_flush_frontbuffer(struct dri_drawable *drawable,
    }
 }
 
+__DRIimage *
+dri2_lookup_egl_image(struct dri_context *ctx, void *handle)
+{
+   __DRIimageLookupExtension *loader = ctx->sPriv->dri2.image;
+   __DRIimage *img;
+
+   if (!loader->lookupEGLImage)
+      return NULL;
+
+   img = loader->lookupEGLImage(ctx->cPriv, handle, ctx->cPriv->loaderPrivate);
+
+   return img;
+}
+
+static __DRIimage *
+dri2_create_image_from_name(__DRIcontext *context,
+                            int width, int height, int format,
+                            int name, int pitch, void *loaderPrivate)
+{
+   struct dri_screen *screen = dri_screen(context->driScreenPriv);
+   __DRIimage *img;
+   struct pipe_texture templ;
+   struct winsys_handle whandle;
+   unsigned tex_usage;
+   enum pipe_format pf;
+
+   tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET | PIPE_TEXTURE_USAGE_SAMPLER;
+
+   switch (format) {
+   case __DRI_IMAGE_FORMAT_RGB565:
+      pf = PIPE_FORMAT_B5G6R5_UNORM;
+      break;
+   case __DRI_IMAGE_FORMAT_XRGB8888:
+      pf = PIPE_FORMAT_B8G8R8X8_UNORM;
+      break;
+   case __DRI_IMAGE_FORMAT_ARGB8888:
+      pf = PIPE_FORMAT_B8G8R8A8_UNORM;
+      break;
+   default:
+      pf = PIPE_FORMAT_NONE;
+      break;
+   }
+   if (pf == PIPE_FORMAT_NONE)
+      return NULL;
+
+   img = CALLOC_STRUCT(__DRIimageRec);
+   if (!img)
+      return NULL;
+
+   memset(&templ, 0, sizeof(templ));
+   templ.tex_usage = tex_usage;
+   templ.format = pf;
+   templ.target = PIPE_TEXTURE_2D;
+   templ.last_level = 0;
+   templ.width0 = width;
+   templ.height0 = height;
+   templ.depth0 = 1;
+
+   memset(&whandle, 0, sizeof(whandle));
+   whandle.handle = name;
+   whandle.stride = pitch * util_format_get_blocksize(pf);
+
+   img->texture = screen->pipe_screen->texture_from_handle(screen->pipe_screen,
+         &templ, &whandle);
+   if (!img->texture) {
+      FREE(img);
+      return NULL;
+   }
+
+   img->face = 0;
+   img->level = 0;
+   img->zslice = 0;
+   img->loader_private = loaderPrivate;
+
+   return img;
+}
+
+static __DRIimage *
+dri2_create_image_from_renderbuffer(__DRIcontext *context,
+                                   int renderbuffer, void *loaderPrivate)
+{
+   struct dri_context *ctx = dri_context(context->driverPrivate);
+
+   if (!ctx->st->get_resource_for_egl_image)
+      return NULL;
+
+   /* TODO */
+   return NULL;
+}
+
+static void
+dri2_destroy_image(__DRIimage *img)
+{
+   pipe_texture_reference(&img->texture, NULL);
+   FREE(img);
+}
+
+static struct __DRIimageExtensionRec dri2ImageExtension = {
+    { __DRI_IMAGE, __DRI_IMAGE_VERSION },
+    dri2_create_image_from_name,
+    dri2_create_image_from_renderbuffer,
+    dri2_destroy_image,
+};
+
 /*
  * Backend function init_screen.
  */
@@ -364,6 +468,7 @@ static const __DRIextension *dri_screen_extensions[] = {
    &driMediaStreamCounterExtension.base,
    &dri2TexBufferExtension.base,
    &dri2FlushExtension.base,
+   &dri2ImageExtension.base,
    NULL
 };
 
index 379963431fb84dc2ce436471440e6114c27c0bdd..5b28850000b70bd23d2cea57c511e5f959dae4a3 100644 (file)
@@ -43,4 +43,7 @@ dri2_allocate_textures(struct dri_drawable *drawable,
                        const enum st_attachment_type *statts,
                        unsigned count);
 
+__DRIimage *
+dri2_lookup_egl_image(struct dri_context *ctx, void *handle);
+
 #endif /* DRI2_H */