diff mbox

[15/18] gallium: Add __DRIimageDriverExtension support to gallium

Message ID 1386984330-26074-16-git-send-email-keithp@keithp.com
State New, archived
Headers show

Commit Message

Keith Packard Dec. 14, 2013, 1:25 a.m. UTC
Provide the hook to pull textures out of __DRIimage structures and use them as
renderbuffers.

Signed-off-by: Keith Packard <keithp@keithp.com>
---
 src/gallium/state_trackers/dri/drm/dri2.c | 238 +++++++++++++++++++++++++++++-
 1 file changed, 230 insertions(+), 8 deletions(-)

Comments

Marek Olšák Dec. 14, 2013, 11:27 a.m. UTC | #1
Some of the code seems to be copy-pasted from
dri2_drawable_process_buffers. The MSAA color and depth-stencil
texture allocation could be moved to a common function.

Marek

On Sat, Dec 14, 2013 at 2:25 AM, Keith Packard <keithp@keithp.com> wrote:
> Provide the hook to pull textures out of __DRIimage structures and use them as
> renderbuffers.
>
> Signed-off-by: Keith Packard <keithp@keithp.com>
> ---
>  src/gallium/state_trackers/dri/drm/dri2.c | 238 +++++++++++++++++++++++++++++-
>  1 file changed, 230 insertions(+), 8 deletions(-)
>
> diff --git a/src/gallium/state_trackers/dri/drm/dri2.c b/src/gallium/state_trackers/dri/drm/dri2.c
> index 8ff77b3..03b93ae 100644
> --- a/src/gallium/state_trackers/dri/drm/dri2.c
> +++ b/src/gallium/state_trackers/dri/drm/dri2.c
> @@ -457,6 +457,219 @@ dri2_release_buffer(__DRIscreen *sPriv, __DRIbuffer *bPriv)
>     FREE(buffer);
>  }
>
> +static void
> +dri_image_allocate_textures(struct dri_context *ctx,
> +                       struct dri_drawable *drawable,
> +                       const enum st_attachment_type *statts,
> +                       unsigned statts_count)
> +{
> +   __DRIdrawable *dPriv = drawable->dPriv;
> +   __DRIscreen *sPriv = drawable->sPriv;
> +   struct dri_screen *screen = dri_screen(sPriv);
> +   unsigned int image_format = __DRI_IMAGE_FORMAT_NONE;
> +   uint32_t buffer_mask = 0;
> +   struct __DRIimageList images;
> +   boolean alloc_depthstencil = FALSE;
> +   int i, j;
> +   struct pipe_resource templ;
> +
> +   /* See if we need a depth-stencil buffer. */
> +   for (i = 0; i < statts_count; i++) {
> +      if (statts[i] == ST_ATTACHMENT_DEPTH_STENCIL) {
> +         alloc_depthstencil = TRUE;
> +         break;
> +      }
> +   }
> +
> +   /* Delete the resources we won't need. */
> +   for (i = 0; i < ST_ATTACHMENT_COUNT; i++) {
> +      /* Don't delete the depth-stencil buffer, we can reuse it. */
> +      if (i == ST_ATTACHMENT_DEPTH_STENCIL && alloc_depthstencil)
> +         continue;
> +
> +      pipe_resource_reference(&drawable->textures[i], NULL);
> +   }
> +
> +   if (drawable->stvis.samples > 1) {
> +      for (i = 0; i < ST_ATTACHMENT_COUNT; i++) {
> +         boolean del = TRUE;
> +
> +         /* Don't delete MSAA resources for the attachments which are enabled,
> +          * we can reuse them. */
> +         for (j = 0; j < statts_count; j++) {
> +            if (i == statts[j]) {
> +               del = FALSE;
> +               break;
> +            }
> +         }
> +
> +         if (del) {
> +            pipe_resource_reference(&drawable->msaa_textures[i], NULL);
> +         }
> +      }
> +   }
> +
> +   for (i = 0; i < statts_count; i++) {
> +      enum pipe_format pf;
> +      unsigned bind;
> +
> +      dri_drawable_get_format(drawable, statts[i], &pf, &bind);
> +      if (pf == PIPE_FORMAT_NONE)
> +         continue;
> +
> +      switch (pf) {
> +      case PIPE_FORMAT_B5G6R5_UNORM:
> +         image_format = __DRI_IMAGE_FORMAT_RGB565;
> +         break;
> +      case PIPE_FORMAT_B8G8R8X8_UNORM:
> +         image_format = __DRI_IMAGE_FORMAT_XRGB8888;
> +         break;
> +      case PIPE_FORMAT_B8G8R8A8_UNORM:
> +         image_format = __DRI_IMAGE_FORMAT_ARGB8888;
> +         break;
> +      case PIPE_FORMAT_R8G8B8A8_UNORM:
> +         image_format = __DRI_IMAGE_FORMAT_ABGR8888;
> +         break;
> +      default:
> +         image_format = __DRI_IMAGE_FORMAT_NONE;
> +         break;
> +      }
> +
> +      switch (statts[i]) {
> +      case ST_ATTACHMENT_FRONT_LEFT:
> +         buffer_mask |= __DRI_IMAGE_BUFFER_FRONT;
> +         break;
> +      case ST_ATTACHMENT_BACK_LEFT:
> +         buffer_mask |= __DRI_IMAGE_BUFFER_BACK;
> +         break;
> +      default:
> +         continue;
> +      }
> +   }
> +
> +   (*sPriv->image.loader->getBuffers) (dPriv,
> +                                       image_format,
> +                                       &dPriv->dri2.stamp,
> +                                       dPriv->loaderPrivate,
> +                                       buffer_mask,
> +                                       &images);
> +
> +   if (images.image_mask & __DRI_IMAGE_BUFFER_FRONT) {
> +      struct pipe_resource *texture = images.front->texture;
> +
> +      dPriv->w = texture->width0;
> +      dPriv->h = texture->height0;
> +
> +      pipe_resource_reference(&drawable->textures[ST_ATTACHMENT_FRONT_LEFT], texture);
> +   }
> +
> +   if (images.image_mask & __DRI_IMAGE_BUFFER_BACK) {
> +      struct pipe_resource *texture = images.back->texture;
> +
> +      dPriv->w = images.back->texture->width0;
> +      dPriv->h = images.back->texture->height0;
> +
> +      pipe_resource_reference(&drawable->textures[ST_ATTACHMENT_BACK_LEFT], texture);
> +   }
> +
> +   memset(&templ, 0, sizeof(templ));
> +   templ.target = screen->target;
> +   templ.last_level = 0;
> +   templ.width0 = dPriv->w;
> +   templ.height0 = dPriv->h;
> +   templ.depth0 = 1;
> +   templ.array_size = 1;
> +
> +   /* Allocate private MSAA colorbuffers. */
> +   if (drawable->stvis.samples > 1) {
> +      for (i = 0; i < statts_count; i++) {
> +         enum st_attachment_type att = statts[i];
> +
> +         if (att == ST_ATTACHMENT_DEPTH_STENCIL)
> +            continue;
> +
> +         if (drawable->textures[att]) {
> +            templ.format = drawable->textures[att]->format;
> +            templ.bind = drawable->textures[att]->bind;
> +            templ.nr_samples = drawable->stvis.samples;
> +
> +            /* Try to reuse the resource.
> +             * (the other resource parameters should be constant)
> +             */
> +            if (!drawable->msaa_textures[att] ||
> +                drawable->msaa_textures[att]->width0 != templ.width0 ||
> +                drawable->msaa_textures[att]->height0 != templ.height0) {
> +               /* Allocate a new one. */
> +               pipe_resource_reference(&drawable->msaa_textures[att], NULL);
> +
> +               drawable->msaa_textures[att] =
> +                  screen->base.screen->resource_create(screen->base.screen,
> +                                                       &templ);
> +               assert(drawable->msaa_textures[att]);
> +
> +               /* If there are any MSAA resources, we should initialize them
> +                * such that they contain the same data as the single-sample
> +                * resources we just got from the X server.
> +                *
> +                * The reason for this is that the state tracker (and
> +                * therefore the app) can access the MSAA resources only.
> +                * The single-sample resources are not exposed
> +                * to the state tracker.
> +                *
> +                */
> +               dri_pipe_blit(ctx->st->pipe,
> +                             drawable->msaa_textures[att],
> +                             drawable->textures[att]);
> +            }
> +         }
> +         else {
> +            pipe_resource_reference(&drawable->msaa_textures[att], NULL);
> +         }
> +      }
> +   }
> +
> +   /* Allocate a private depth-stencil buffer. */
> +   if (alloc_depthstencil) {
> +      enum st_attachment_type att = ST_ATTACHMENT_DEPTH_STENCIL;
> +      struct pipe_resource **zsbuf;
> +      enum pipe_format format;
> +      unsigned bind;
> +
> +      dri_drawable_get_format(drawable, att, &format, &bind);
> +
> +      if (format) {
> +         templ.format = format;
> +         templ.bind = bind;
> +
> +         if (drawable->stvis.samples > 1) {
> +            templ.nr_samples = drawable->stvis.samples;
> +            zsbuf = &drawable->msaa_textures[att];
> +         }
> +         else {
> +            templ.nr_samples = 0;
> +            zsbuf = &drawable->textures[att];
> +         }
> +
> +         /* Try to reuse the resource.
> +          * (the other resource parameters should be constant)
> +          */
> +         if (!*zsbuf ||
> +             (*zsbuf)->width0 != templ.width0 ||
> +             (*zsbuf)->height0 != templ.height0) {
> +            /* Allocate a new one. */
> +            pipe_resource_reference(zsbuf, NULL);
> +            *zsbuf = screen->base.screen->resource_create(screen->base.screen,
> +                                                          &templ);
> +            assert(*zsbuf);
> +         }
> +      }
> +      else {
> +         pipe_resource_reference(&drawable->msaa_textures[att], NULL);
> +         pipe_resource_reference(&drawable->textures[att], NULL);
> +      }
> +   }
> +}
> +
>  /*
>   * Backend functions for st_framebuffer interface.
>   */
> @@ -467,13 +680,18 @@ dri2_allocate_textures(struct dri_context *ctx,
>                         const enum st_attachment_type *statts,
>                         unsigned statts_count)
>  {
> -   __DRIbuffer *buffers;
> -   unsigned num_buffers = statts_count;
> -
> -   buffers = dri2_drawable_get_buffers(drawable, statts, &num_buffers);
> -   if (buffers)
> -      dri2_drawable_process_buffers(ctx, drawable, buffers, num_buffers,
> -                                    statts, statts_count);
> +   __DRIscreen *sPriv = drawable->sPriv;
> +
> +   if (sPriv->image.loader) {
> +      dri_image_allocate_textures(ctx, drawable, statts, statts_count);
> +   } else {
> +      __DRIbuffer *buffers;
> +      unsigned num_buffers = statts_count;
> +      buffers = dri2_drawable_get_buffers(drawable, statts, &num_buffers);
> +      if (buffers)
> +         dri2_drawable_process_buffers(ctx, drawable, buffers, num_buffers,
> +                                       statts, statts_count);
> +   }
>  }
>
>  static void
> @@ -482,6 +700,7 @@ dri2_flush_frontbuffer(struct dri_context *ctx,
>                         enum st_attachment_type statt)
>  {
>     __DRIdrawable *dri_drawable = drawable->dPriv;
> +   struct __DRIimageLoaderExtensionRec *image = drawable->sPriv->image.loader;
>     struct __DRIdri2LoaderExtensionRec *loader = drawable->sPriv->dri2.loader;
>     struct pipe_context *pipe = ctx->st->pipe;
>
> @@ -501,7 +720,9 @@ dri2_flush_frontbuffer(struct dri_context *ctx,
>
>     pipe->flush(pipe, NULL, 0);
>
> -   if (loader->flushFrontBuffer) {
> +   if (image->flushFrontBuffer) {
> +      image->flushFrontBuffer(dri_drawable, dri_drawable->loaderPrivate);
> +   } else if (loader->flushFrontBuffer) {
>        loader->flushFrontBuffer(dri_drawable, dri_drawable->loaderPrivate);
>     }
>  }
> @@ -1116,6 +1337,7 @@ const struct __DriverAPIRec driDriverAPI = {
>  /* This is the table of extensions that the loader will dlsym() for. */
>  PUBLIC const __DRIextension *__driDriverExtensions[] = {
>      &driCoreExtension.base,
> +    &driImageDriverExtension.base,
>      &driDRI2Extension.base,
>      &gallium_config_options.base,
>      NULL
> --
> 1.8.4.4
>
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel
Keith Packard Dec. 27, 2013, 8:27 p.m. UTC | #2
Marek Olšák <maraeo@gmail.com> writes:

> Some of the code seems to be copy-pasted from
> dri2_drawable_process_buffers. The MSAA color and depth-stencil
> texture allocation could be moved to a common function.

It's either that or plan on moving DRI2 to the image interface as well
at some point? As we'll have to keep DRI2 support around, it sure would
be nice to share the driver backend bits between DRI3 and DRI2?
Marek Olšák Jan. 3, 2014, 8:03 p.m. UTC | #3
On Fri, Dec 27, 2013 at 9:27 PM, Keith Packard <keithp@keithp.com> wrote:
> Marek Olšák <maraeo@gmail.com> writes:
>
>> Some of the code seems to be copy-pasted from
>> dri2_drawable_process_buffers. The MSAA color and depth-stencil
>> texture allocation could be moved to a common function.
>
> It's either that or plan on moving DRI2 to the image interface as well
> at some point? As we'll have to keep DRI2 support around, it sure would
> be nice to share the driver backend bits between DRI3 and DRI2?

Yes, but it would break the "new Mesa + old libGL without DRIimage"
combination. Not that I care much about that. It's up to you. I think
it would be good to do what the Intel Mesa driver does.

Marek
diff mbox

Patch

diff --git a/src/gallium/state_trackers/dri/drm/dri2.c b/src/gallium/state_trackers/dri/drm/dri2.c
index 8ff77b3..03b93ae 100644
--- a/src/gallium/state_trackers/dri/drm/dri2.c
+++ b/src/gallium/state_trackers/dri/drm/dri2.c
@@ -457,6 +457,219 @@  dri2_release_buffer(__DRIscreen *sPriv, __DRIbuffer *bPriv)
    FREE(buffer);
 }
 
+static void
+dri_image_allocate_textures(struct dri_context *ctx,
+                       struct dri_drawable *drawable,
+                       const enum st_attachment_type *statts,
+                       unsigned statts_count)
+{
+   __DRIdrawable *dPriv = drawable->dPriv;
+   __DRIscreen *sPriv = drawable->sPriv;
+   struct dri_screen *screen = dri_screen(sPriv);
+   unsigned int image_format = __DRI_IMAGE_FORMAT_NONE;
+   uint32_t buffer_mask = 0;
+   struct __DRIimageList images;
+   boolean alloc_depthstencil = FALSE;
+   int i, j;
+   struct pipe_resource templ;
+
+   /* See if we need a depth-stencil buffer. */
+   for (i = 0; i < statts_count; i++) {
+      if (statts[i] == ST_ATTACHMENT_DEPTH_STENCIL) {
+         alloc_depthstencil = TRUE;
+         break;
+      }
+   }
+
+   /* Delete the resources we won't need. */
+   for (i = 0; i < ST_ATTACHMENT_COUNT; i++) {
+      /* Don't delete the depth-stencil buffer, we can reuse it. */
+      if (i == ST_ATTACHMENT_DEPTH_STENCIL && alloc_depthstencil)
+         continue;
+
+      pipe_resource_reference(&drawable->textures[i], NULL);
+   }
+
+   if (drawable->stvis.samples > 1) {
+      for (i = 0; i < ST_ATTACHMENT_COUNT; i++) {
+         boolean del = TRUE;
+
+         /* Don't delete MSAA resources for the attachments which are enabled,
+          * we can reuse them. */
+         for (j = 0; j < statts_count; j++) {
+            if (i == statts[j]) {
+               del = FALSE;
+               break;
+            }
+         }
+
+         if (del) {
+            pipe_resource_reference(&drawable->msaa_textures[i], NULL);
+         }
+      }
+   }
+
+   for (i = 0; i < statts_count; i++) {
+      enum pipe_format pf;
+      unsigned bind;
+
+      dri_drawable_get_format(drawable, statts[i], &pf, &bind);
+      if (pf == PIPE_FORMAT_NONE)
+         continue;
+
+      switch (pf) {
+      case PIPE_FORMAT_B5G6R5_UNORM:
+         image_format = __DRI_IMAGE_FORMAT_RGB565;
+         break;
+      case PIPE_FORMAT_B8G8R8X8_UNORM:
+         image_format = __DRI_IMAGE_FORMAT_XRGB8888;
+         break;
+      case PIPE_FORMAT_B8G8R8A8_UNORM:
+         image_format = __DRI_IMAGE_FORMAT_ARGB8888;
+         break;
+      case PIPE_FORMAT_R8G8B8A8_UNORM:
+         image_format = __DRI_IMAGE_FORMAT_ABGR8888;
+         break;
+      default:
+         image_format = __DRI_IMAGE_FORMAT_NONE;
+         break;
+      }
+
+      switch (statts[i]) {
+      case ST_ATTACHMENT_FRONT_LEFT:
+         buffer_mask |= __DRI_IMAGE_BUFFER_FRONT;
+         break;
+      case ST_ATTACHMENT_BACK_LEFT:
+         buffer_mask |= __DRI_IMAGE_BUFFER_BACK;
+         break;
+      default:
+         continue;
+      }
+   }
+
+   (*sPriv->image.loader->getBuffers) (dPriv,
+                                       image_format,
+                                       &dPriv->dri2.stamp,
+                                       dPriv->loaderPrivate,
+                                       buffer_mask,
+                                       &images);
+
+   if (images.image_mask & __DRI_IMAGE_BUFFER_FRONT) {
+      struct pipe_resource *texture = images.front->texture;
+
+      dPriv->w = texture->width0;
+      dPriv->h = texture->height0;
+
+      pipe_resource_reference(&drawable->textures[ST_ATTACHMENT_FRONT_LEFT], texture);
+   }
+
+   if (images.image_mask & __DRI_IMAGE_BUFFER_BACK) {
+      struct pipe_resource *texture = images.back->texture;
+
+      dPriv->w = images.back->texture->width0;
+      dPriv->h = images.back->texture->height0;
+
+      pipe_resource_reference(&drawable->textures[ST_ATTACHMENT_BACK_LEFT], texture);
+   }
+
+   memset(&templ, 0, sizeof(templ));
+   templ.target = screen->target;
+   templ.last_level = 0;
+   templ.width0 = dPriv->w;
+   templ.height0 = dPriv->h;
+   templ.depth0 = 1;
+   templ.array_size = 1;
+
+   /* Allocate private MSAA colorbuffers. */
+   if (drawable->stvis.samples > 1) {
+      for (i = 0; i < statts_count; i++) {
+         enum st_attachment_type att = statts[i];
+
+         if (att == ST_ATTACHMENT_DEPTH_STENCIL)
+            continue;
+
+         if (drawable->textures[att]) {
+            templ.format = drawable->textures[att]->format;
+            templ.bind = drawable->textures[att]->bind;
+            templ.nr_samples = drawable->stvis.samples;
+
+            /* Try to reuse the resource.
+             * (the other resource parameters should be constant)
+             */
+            if (!drawable->msaa_textures[att] ||
+                drawable->msaa_textures[att]->width0 != templ.width0 ||
+                drawable->msaa_textures[att]->height0 != templ.height0) {
+               /* Allocate a new one. */
+               pipe_resource_reference(&drawable->msaa_textures[att], NULL);
+
+               drawable->msaa_textures[att] =
+                  screen->base.screen->resource_create(screen->base.screen,
+                                                       &templ);
+               assert(drawable->msaa_textures[att]);
+
+               /* If there are any MSAA resources, we should initialize them
+                * such that they contain the same data as the single-sample
+                * resources we just got from the X server.
+                *
+                * The reason for this is that the state tracker (and
+                * therefore the app) can access the MSAA resources only.
+                * The single-sample resources are not exposed
+                * to the state tracker.
+                *
+                */
+               dri_pipe_blit(ctx->st->pipe,
+                             drawable->msaa_textures[att],
+                             drawable->textures[att]);
+            }
+         }
+         else {
+            pipe_resource_reference(&drawable->msaa_textures[att], NULL);
+         }
+      }
+   }
+
+   /* Allocate a private depth-stencil buffer. */
+   if (alloc_depthstencil) {
+      enum st_attachment_type att = ST_ATTACHMENT_DEPTH_STENCIL;
+      struct pipe_resource **zsbuf;
+      enum pipe_format format;
+      unsigned bind;
+
+      dri_drawable_get_format(drawable, att, &format, &bind);
+
+      if (format) {
+         templ.format = format;
+         templ.bind = bind;
+
+         if (drawable->stvis.samples > 1) {
+            templ.nr_samples = drawable->stvis.samples;
+            zsbuf = &drawable->msaa_textures[att];
+         }
+         else {
+            templ.nr_samples = 0;
+            zsbuf = &drawable->textures[att];
+         }
+
+         /* Try to reuse the resource.
+          * (the other resource parameters should be constant)
+          */
+         if (!*zsbuf ||
+             (*zsbuf)->width0 != templ.width0 ||
+             (*zsbuf)->height0 != templ.height0) {
+            /* Allocate a new one. */
+            pipe_resource_reference(zsbuf, NULL);
+            *zsbuf = screen->base.screen->resource_create(screen->base.screen,
+                                                          &templ);
+            assert(*zsbuf);
+         }
+      }
+      else {
+         pipe_resource_reference(&drawable->msaa_textures[att], NULL);
+         pipe_resource_reference(&drawable->textures[att], NULL);
+      }
+   }
+}
+
 /*
  * Backend functions for st_framebuffer interface.
  */
@@ -467,13 +680,18 @@  dri2_allocate_textures(struct dri_context *ctx,
                        const enum st_attachment_type *statts,
                        unsigned statts_count)
 {
-   __DRIbuffer *buffers;
-   unsigned num_buffers = statts_count;
-
-   buffers = dri2_drawable_get_buffers(drawable, statts, &num_buffers);
-   if (buffers)
-      dri2_drawable_process_buffers(ctx, drawable, buffers, num_buffers,
-                                    statts, statts_count);
+   __DRIscreen *sPriv = drawable->sPriv;
+
+   if (sPriv->image.loader) {
+      dri_image_allocate_textures(ctx, drawable, statts, statts_count);
+   } else {
+      __DRIbuffer *buffers;
+      unsigned num_buffers = statts_count;
+      buffers = dri2_drawable_get_buffers(drawable, statts, &num_buffers);
+      if (buffers)
+         dri2_drawable_process_buffers(ctx, drawable, buffers, num_buffers,
+                                       statts, statts_count);
+   }
 }
 
 static void
@@ -482,6 +700,7 @@  dri2_flush_frontbuffer(struct dri_context *ctx,
                        enum st_attachment_type statt)
 {
    __DRIdrawable *dri_drawable = drawable->dPriv;
+   struct __DRIimageLoaderExtensionRec *image = drawable->sPriv->image.loader;
    struct __DRIdri2LoaderExtensionRec *loader = drawable->sPriv->dri2.loader;
    struct pipe_context *pipe = ctx->st->pipe;
 
@@ -501,7 +720,9 @@  dri2_flush_frontbuffer(struct dri_context *ctx,
 
    pipe->flush(pipe, NULL, 0);
 
-   if (loader->flushFrontBuffer) {
+   if (image->flushFrontBuffer) {
+      image->flushFrontBuffer(dri_drawable, dri_drawable->loaderPrivate);
+   } else if (loader->flushFrontBuffer) {
       loader->flushFrontBuffer(dri_drawable, dri_drawable->loaderPrivate);
    }
 }
@@ -1116,6 +1337,7 @@  const struct __DriverAPIRec driDriverAPI = {
 /* This is the table of extensions that the loader will dlsym() for. */
 PUBLIC const __DRIextension *__driDriverExtensions[] = {
     &driCoreExtension.base,
+    &driImageDriverExtension.base,
     &driDRI2Extension.base,
     &gallium_config_options.base,
     NULL