st/dri: Track drawable context bindings
[mesa.git] / src / gallium / state_trackers / dri / drm / dri2.c
index 47005c17e2bd600ee370a43db5cf9458701a7abb..0181588096defeff826bdddcd2f8107096d3702b 100644 (file)
@@ -38,6 +38,7 @@
 #include "dri_screen.h"
 #include "dri_context.h"
 #include "dri_drawable.h"
+#include "dri2_buffer.h"
 
 /**
  * DRI2 flush extension.
@@ -51,7 +52,7 @@ static void
 dri2_invalidate_drawable(__DRIdrawable *dPriv)
 {
    struct dri_drawable *drawable = dri_drawable(dPriv);
-   struct dri_context *ctx = dri_context(dPriv->driContextPriv);
+   struct dri_context *ctx = drawable->context;
 
    dri2InvalidateDrawable(dPriv);
    drawable->dPriv->lastStamp = *drawable->dPriv->pStamp;
@@ -195,11 +196,12 @@ dri2_drawable_process_buffers(struct dri_drawable *drawable,
       pipe_resource_reference(&drawable->textures[i], NULL);
 
    memset(&templ, 0, sizeof(templ));
-   templ.target = PIPE_TEXTURE_2D;
+   templ.target = screen->target;
    templ.last_level = 0;
    templ.width0 = dri_drawable->w;
    templ.height0 = dri_drawable->h;
    templ.depth0 = 1;
+   templ.array_size = 1;
 
    memset(&whandle, 0, sizeof(whandle));
 
@@ -258,6 +260,91 @@ dri2_drawable_process_buffers(struct dri_drawable *drawable,
    memcpy(drawable->old, buffers, sizeof(__DRIbuffer) * count);
 }
 
+static __DRIbuffer *
+dri2_allocate_buffer(__DRIscreen *sPriv,
+                     unsigned attachment, unsigned format,
+                     int width, int height)
+{
+   struct dri_screen *screen = dri_screen(sPriv);
+   struct dri2_buffer *buffer;
+   struct pipe_resource templ;
+   enum st_attachment_type statt;
+   enum pipe_format pf;
+   unsigned bind;
+   struct winsys_handle whandle;
+
+   switch (attachment) {
+      case __DRI_BUFFER_FRONT_LEFT:
+      case __DRI_BUFFER_FAKE_FRONT_LEFT:
+         statt = ST_ATTACHMENT_FRONT_LEFT;
+         bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
+         break;
+      case __DRI_BUFFER_BACK_LEFT:
+         statt = ST_ATTACHMENT_BACK_LEFT;
+         bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
+         break;
+      case __DRI_BUFFER_DEPTH:
+      case __DRI_BUFFER_DEPTH_STENCIL:
+      case __DRI_BUFFER_STENCIL:
+            statt = ST_ATTACHMENT_DEPTH_STENCIL;
+            bind = PIPE_BIND_DEPTH_STENCIL; /* XXX sampler? */
+         break;
+      default:
+         statt = ST_ATTACHMENT_INVALID;
+         break;
+   }
+
+   switch (format) {
+      case 32:
+         pf = PIPE_FORMAT_B8G8R8X8_UNORM;
+         break;
+      case 16:
+         pf = PIPE_FORMAT_Z16_UNORM;
+         break;
+      default:
+         return NULL;
+   }
+
+   buffer = CALLOC_STRUCT(dri2_buffer);
+   if (!buffer)
+      return NULL;
+
+   memset(&templ, 0, sizeof(templ));
+   templ.bind = bind;
+   templ.format = pf;
+   templ.target = PIPE_TEXTURE_2D;
+   templ.last_level = 0;
+   templ.width0 = width;
+   templ.height0 = height;
+   templ.depth0 = 1;
+
+   buffer->resource =
+      screen->base.screen->resource_create(screen->base.screen, &templ);
+   if (!buffer->resource)
+      return NULL;
+
+   memset(&whandle, 0, sizeof(whandle));
+   whandle.type = DRM_API_HANDLE_TYPE_SHARED;
+   screen->base.screen->resource_get_handle(screen->base.screen,
+         buffer->resource, &whandle);
+
+   buffer->base.attachment = attachment;
+   buffer->base.name = whandle.handle;
+   buffer->base.cpp = util_format_get_blocksize(pf);
+   buffer->base.pitch = whandle.stride;
+
+   return &buffer->base;
+}
+
+static void
+dri2_release_buffer(__DRIscreen *sPriv, __DRIbuffer *bPriv)
+{
+   struct dri2_buffer *buffer = dri2_buffer(bPriv);
+
+   pipe_resource_reference(&buffer->resource, NULL);
+   FREE(buffer);
+}
+
 /*
  * Backend functions for st_framebuffer interface.
  */
@@ -291,25 +378,26 @@ dri2_flush_frontbuffer(struct dri_drawable *drawable,
 }
 
 static __DRIimage *
-dri2_lookup_egl_image(struct dri_context *ctx, void *handle)
+dri2_lookup_egl_image(struct dri_screen *screen, void *handle)
 {
-   __DRIimageLookupExtension *loader = ctx->sPriv->dri2.image;
+   __DRIimageLookupExtension *loader = screen->sPriv->dri2.image;
    __DRIimage *img;
 
    if (!loader->lookupEGLImage)
       return NULL;
 
-   img = loader->lookupEGLImage(ctx->cPriv, handle, ctx->cPriv->loaderPrivate);
+   img = loader->lookupEGLImage(screen->sPriv,
+                               handle, screen->sPriv->loaderPrivate);
 
    return img;
 }
 
 static __DRIimage *
-dri2_create_image_from_name(__DRIcontext *context,
+dri2_create_image_from_name(__DRIscreen *_screen,
                             int width, int height, int format,
                             int name, int pitch, void *loaderPrivate)
 {
-   struct dri_screen *screen = dri_screen(context->driScreenPriv);
+   struct dri_screen *screen = dri_screen(_screen);
    __DRIimage *img;
    struct pipe_resource templ;
    struct winsys_handle whandle;
@@ -342,11 +430,12 @@ dri2_create_image_from_name(__DRIcontext *context,
    memset(&templ, 0, sizeof(templ));
    templ.bind = tex_usage;
    templ.format = pf;
-   templ.target = PIPE_TEXTURE_2D;
+   templ.target = screen->target;
    templ.last_level = 0;
    templ.width0 = width;
    templ.height0 = height;
    templ.depth0 = 1;
+   templ.array_size = 1;
 
    memset(&whandle, 0, sizeof(whandle));
    whandle.handle = name;
@@ -359,9 +448,8 @@ dri2_create_image_from_name(__DRIcontext *context,
       return NULL;
    }
 
-   img->face = 0;
    img->level = 0;
-   img->zslice = 0;
+   img->layer = 0;
    img->loader_private = loaderPrivate;
 
    return img;
@@ -371,7 +459,7 @@ static __DRIimage *
 dri2_create_image_from_renderbuffer(__DRIcontext *context,
                                    int renderbuffer, void *loaderPrivate)
 {
-   struct dri_context *ctx = dri_context(context->driverPrivate);
+   struct dri_context *ctx = dri_context(context);
 
    if (!ctx->st->get_resource_for_egl_image)
       return NULL;
@@ -380,6 +468,91 @@ dri2_create_image_from_renderbuffer(__DRIcontext *context,
    return NULL;
 }
 
+static __DRIimage *
+dri2_create_image(__DRIscreen *_screen,
+                   int width, int height, int format,
+                   unsigned int use, void *loaderPrivate)
+{
+   struct dri_screen *screen = dri_screen(_screen);
+   __DRIimage *img;
+   struct pipe_resource templ;
+   unsigned tex_usage;
+   enum pipe_format pf;
+
+   tex_usage = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
+
+   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.bind = tex_usage;
+   templ.format = pf;
+   templ.target = PIPE_TEXTURE_2D;
+   templ.last_level = 0;
+   templ.width0 = width;
+   templ.height0 = height;
+   templ.depth0 = 1;
+
+   img->texture = screen->base.screen->resource_create(screen->base.screen, &templ);
+   if (!img->texture) {
+      FREE(img);
+      return NULL;
+   }
+
+   img->level = 0;
+   img->layer = 0;
+
+   img->loader_private = loaderPrivate;
+   return img;
+}
+
+static GLboolean
+dri2_query_image(__DRIimage *image, int attrib, int *value)
+{
+   struct winsys_handle whandle;
+   memset(&whandle, 0, sizeof(whandle));
+
+   switch (attrib) {
+   case __DRI_IMAGE_ATTRIB_STRIDE:
+      image->texture->screen->resource_get_handle(image->texture->screen,
+            image->texture, &whandle);
+      *value = whandle.stride;
+      return GL_TRUE;
+   case __DRI_IMAGE_ATTRIB_HANDLE:
+      whandle.type = DRM_API_HANDLE_TYPE_KMS;
+      image->texture->screen->resource_get_handle(image->texture->screen,
+         image->texture, &whandle);
+      *value = whandle.handle;
+      return GL_TRUE;
+   case __DRI_IMAGE_ATTRIB_NAME:
+      whandle.type = DRM_API_HANDLE_TYPE_SHARED;
+      image->texture->screen->resource_get_handle(image->texture->screen,
+         image->texture, &whandle);
+      *value = whandle.handle;
+      return GL_TRUE;
+   default:
+      return GL_FALSE;
+   }
+}
+
 static void
 dri2_destroy_image(__DRIimage *img)
 {
@@ -392,6 +565,8 @@ static struct __DRIimageExtensionRec dri2ImageExtension = {
     dri2_create_image_from_name,
     dri2_create_image_from_renderbuffer,
     dri2_destroy_image,
+    dri2_create_image,
+    dri2_query_image,
 };
 
 /*
@@ -413,7 +588,7 @@ static const __DRIextension *dri_screen_extensions[] = {
 /**
  * This is the driver specific part of the createNewScreen entry point.
  *
- * Returns the __GLcontextModes supported by this driver.
+ * Returns the struct gl_config supported by this driver.
  */
 static const __DRIconfig **
 dri2_init_screen(__DRIscreen * sPriv)
@@ -439,8 +614,17 @@ dri2_init_screen(__DRIscreen * sPriv)
    if (!configs)
       goto fail;
 
+   sPriv->api_mask = 0;
+   if (screen->st_api->profile_mask & ST_PROFILE_DEFAULT_MASK)
+      sPriv->api_mask |= 1 << __DRI_API_OPENGL;
+   if (screen->st_api->profile_mask & ST_PROFILE_OPENGL_ES1_MASK)
+      sPriv->api_mask |= 1 << __DRI_API_GLES;
+   if (screen->st_api->profile_mask & ST_PROFILE_OPENGL_ES2_MASK)
+      sPriv->api_mask |= 1 << __DRI_API_GLES2;
+
    screen->auto_fake_front = dri_with_format(sPriv);
    screen->broken_invalidate = !sPriv->dri2.useInvalidate;
+   screen->lookup_egl_image = dri2_lookup_egl_image;
 
    return configs;
 fail:
@@ -450,7 +634,7 @@ fail:
 }
 
 static boolean
-dri2_create_context(gl_api api, const __GLcontextModes * visual,
+dri2_create_context(gl_api api, const struct gl_config * visual,
                     __DRIcontext * cPriv, void *sharedContextPrivate)
 {
    struct dri_context *ctx = NULL;
@@ -460,15 +644,13 @@ dri2_create_context(gl_api api, const __GLcontextModes * visual,
 
    ctx = cPriv->driverPrivate;
 
-   ctx->lookup_egl_image = dri2_lookup_egl_image;
-
    return TRUE;
 }
 
 static boolean
 dri2_create_buffer(__DRIscreen * sPriv,
                    __DRIdrawable * dPriv,
-                   const __GLcontextModes * visual, boolean isPixmap)
+                   const struct gl_config * visual, boolean isPixmap)
 {
    struct dri_drawable *drawable = NULL;
 
@@ -505,6 +687,9 @@ const struct __DriverAPIRec driDriverAPI = {
 
    .SwapBuffers = NULL,
    .CopySubBuffer = NULL,
+
+   .AllocateBuffer = dri2_allocate_buffer,
+   .ReleaseBuffer  = dri2_release_buffer,
 };
 
 /* This is the table of extensions that the loader will dlsym() for. */