radeon: Implement __DRI_IMAGE and EGL_MESA_image_drm
authorJohann Rudloff <cypheon@googlemail.com>
Mon, 8 Nov 2010 19:43:55 +0000 (14:43 -0500)
committerAlex Deucher <alexdeucher@gmail.com>
Tue, 9 Nov 2010 00:59:53 +0000 (19:59 -0500)
src/mesa/drivers/dri/radeon/radeon_screen.c
src/mesa/drivers/dri/radeon/radeon_screen.h

index 450e33ef1348de734b16ef1c392c5ab541f031dd..1ea52f96d7e55a116522d59940af471f8a47b980 100644 (file)
@@ -41,12 +41,14 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "main/mtypes.h"
 #include "main/framebuffer.h"
 #include "main/renderbuffer.h"
+#include "main/fbobject.h"
 
 #define STANDALONE_MMIO
 #include "radeon_chipset.h"
 #include "radeon_macros.h"
 #include "radeon_screen.h"
 #include "radeon_common.h"
+#include "radeon_common_context.h"
 #if defined(RADEON_R100)
 #include "radeon_context.h"
 #include "radeon_tex.h"
@@ -398,6 +400,188 @@ static const struct __DRI2flushExtensionRec radeonFlushExtension = {
     dri2InvalidateDrawable,
 };
 
+static __DRIimage *
+radeon_create_image_from_name(__DRIcontext *context,
+                              int width, int height, int format,
+                              int name, int pitch, void *loaderPrivate)
+{
+   __DRIimage *image;
+   radeonContextPtr radeon = context->driverPrivate;
+
+   if (name == 0)
+      return NULL;
+
+   image = CALLOC(sizeof *image);
+   if (image == NULL)
+      return NULL;
+
+   switch (format) {
+   case __DRI_IMAGE_FORMAT_RGB565:
+      image->format = MESA_FORMAT_RGB565;
+      image->internal_format = GL_RGB;
+      image->data_type = GL_UNSIGNED_BYTE;
+      break;
+   case __DRI_IMAGE_FORMAT_XRGB8888:
+      image->format = MESA_FORMAT_XRGB8888;
+      image->internal_format = GL_RGB;
+      image->data_type = GL_UNSIGNED_BYTE;
+      break;
+   case __DRI_IMAGE_FORMAT_ARGB8888:
+      image->format = MESA_FORMAT_ARGB8888;
+      image->internal_format = GL_RGBA;
+      image->data_type = GL_UNSIGNED_BYTE;
+      break;
+   default:
+      free(image);
+      return NULL;
+   }
+
+   image->data = loaderPrivate;
+   image->cpp = _mesa_get_format_bytes(image->format);
+   image->width = width;
+   image->pitch = pitch;
+   image->height = height;
+
+   image->bo = radeon_bo_open(radeon->radeonScreen->bom,
+                              (uint32_t)name,
+                              image->pitch * image->height * image->cpp,
+                              0,
+                              RADEON_GEM_DOMAIN_VRAM,
+                              0);
+
+   if (image->bo == NULL) {
+      FREE(image);
+      return NULL;
+   }
+
+   return image;
+}
+
+static __DRIimage *
+radeon_create_image_from_renderbuffer(__DRIcontext *context,
+                                      int renderbuffer, void *loaderPrivate)
+{
+   __DRIimage *image;
+   radeonContextPtr radeon = context->driverPrivate;
+   struct gl_renderbuffer *rb;
+   struct radeon_renderbuffer *rrb;
+
+   rb = _mesa_lookup_renderbuffer(radeon->glCtx, renderbuffer);
+   if (!rb) {
+      _mesa_error(radeon->glCtx,
+                  GL_INVALID_OPERATION, "glRenderbufferExternalMESA");
+      return NULL;
+   }
+
+   rrb = radeon_renderbuffer(rb);
+   image = CALLOC(sizeof *image);
+   if (image == NULL)
+      return NULL;
+
+   image->internal_format = rb->InternalFormat;
+   image->format = rb->Format;
+   image->cpp = rrb->cpp;
+   image->data_type = rb->DataType;
+   image->data = loaderPrivate;
+   radeon_bo_ref(rrb->bo);
+   image->bo = rrb->bo;
+
+   image->width = rb->Width;
+   image->height = rb->Height;
+   image->pitch = rrb->pitch / image->cpp;
+
+   return image;
+}
+
+static void
+radeon_destroy_image(__DRIimage *image)
+{
+   radeon_bo_unref(image->bo);
+   FREE(image);
+}
+
+static __DRIimage *
+radeon_create_image(__DRIscreen *screen,
+                    int width, int height, int format,
+                    unsigned int use,
+                    void *loaderPrivate)
+{
+   __DRIimage *image;
+   radeonScreenPtr radeonScreen = screen->private;
+
+   image = CALLOC(sizeof *image);
+   if (image == NULL)
+      return NULL;
+
+   switch (format) {
+   case __DRI_IMAGE_FORMAT_RGB565:
+      image->format = MESA_FORMAT_RGB565;
+      image->internal_format = GL_RGB;
+      image->data_type = GL_UNSIGNED_BYTE;
+      break;
+   case __DRI_IMAGE_FORMAT_XRGB8888:
+      image->format = MESA_FORMAT_XRGB8888;
+      image->internal_format = GL_RGB;
+      image->data_type = GL_UNSIGNED_BYTE;
+      break;
+   case __DRI_IMAGE_FORMAT_ARGB8888:
+      image->format = MESA_FORMAT_ARGB8888;
+      image->internal_format = GL_RGBA;
+      image->data_type = GL_UNSIGNED_BYTE;
+      break;
+   default:
+      free(image);
+      return NULL;
+   }
+
+   image->data = loaderPrivate;
+   image->cpp = _mesa_get_format_bytes(image->format);
+   image->width = width;
+   image->height = height;
+   image->pitch = ((image->cpp * image->width + 255) & ~255) / image->cpp;
+
+   image->bo = radeon_bo_open(radeonScreen->bom,
+                              0,
+                              image->pitch * image->height * image->cpp,
+                              0,
+                              RADEON_GEM_DOMAIN_VRAM,
+                              0);
+
+   if (image->bo == NULL) {
+      FREE(image);
+      return NULL;
+   }
+
+   return image;
+}
+
+static GLboolean
+radeon_query_image(__DRIimage *image, int attrib, int *value)
+{
+   switch (attrib) {
+   case __DRI_IMAGE_ATTRIB_STRIDE:
+      *value = image->pitch * image->cpp;
+      return GL_TRUE;
+   case __DRI_IMAGE_ATTRIB_HANDLE:
+      *value = image->bo->handle;
+      return GL_TRUE;
+   case __DRI_IMAGE_ATTRIB_NAME:
+      radeon_gem_get_kernel_name(image->bo, (uint32_t *) value);
+      return GL_TRUE;
+   default:
+      return GL_FALSE;
+   }
+}
+
+static struct __DRIimageExtensionRec radeonImageExtension = {
+    { __DRI_IMAGE, __DRI_IMAGE_VERSION },
+   radeon_create_image_from_name,
+   radeon_create_image_from_renderbuffer,
+   radeon_destroy_image,
+   radeon_create_image,
+   radeon_query_image
+};
+
 static int radeon_set_screen_flags(radeonScreenPtr screen, int device_id)
 {
    screen->device_id = device_id;
@@ -1510,6 +1694,7 @@ radeonCreateScreen2(__DRIscreen *sPriv)
 #endif
 
    screen->extensions[i++] = &radeonFlushExtension.base;
+   screen->extensions[i++] = &radeonImageExtension.base;
 
    screen->extensions[i++] = NULL;
    sPriv->extensions = screen->extensions;
index 2b33201a538b00f720d983878506595f254cb329..417ebf3b067dc9f4c72b8c2f1c862f2bc76cb861 100644 (file)
@@ -121,6 +121,17 @@ typedef struct radeon_screen {
    GLint r7xx_bank_op;
 } radeonScreenRec, *radeonScreenPtr;
 
+struct __DRIimageRec {
+   struct radeon_bo *bo;
+   GLenum internal_format;
+   GLuint format;
+   GLenum data_type;
+   int width, height;  /* in pixels */
+   int pitch;          /* in pixels */
+   int cpp;
+   void *data;
+};
+
 #define IS_R100_CLASS(screen) \
        ((screen->chip_flags & RADEON_CLASS_MASK) == RADEON_CLASS_R100)
 #define IS_R200_CLASS(screen) \