intel: Refactor intel_update_renderbuffers()
authorChad Versace <chad@chad-versace.us>
Fri, 3 Jun 2011 23:14:25 +0000 (16:14 -0700)
committerChad Versace <chad@chad-versace.us>
Wed, 8 Jun 2011 17:06:40 +0000 (10:06 -0700)
Extract the code that queries DRI2 to obtain the DRIdrawable's buffers
into intel_query_dri2_buffers_no_separate_stencil().

Extract the code that assigns the DRI buffer's DRM region to the
corresponding renderbuffer into
intel_process_dri2_buffer_no_separate_stencil().

Rationale
---------
The next commit enables intel_update_renderbuffers() to query for separate
stencil and hiz buffers. Without separating the separate-stencil and
no-separate-stencil paths, intel_update_renderbuffers() degenerates into
an impenetrable labyrinth of if-trees.

CC: Ian Romanick <idr@freedesktop.org>
CC: Kristian Høgsberg <krh@bitplanet.net>
Acked-by: Eric Anholt <eric@anholt.net>
Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
Signed-off-by: Chad Versace <chad@chad-versace.us>
src/mesa/drivers/dri/intel/intel_context.c

index 0259891be34d0983d7a6e71e28910cc6960956dc..3460e679e41b76ddaea51bae9e9758005708962b 100644 (file)
@@ -227,18 +227,27 @@ intel_bits_per_pixel(const struct intel_renderbuffer *rb)
    return _mesa_get_format_bytes(rb->Base.Format) * 8;
 }
 
+static void
+intel_query_dri2_buffers_no_separate_stencil(struct intel_context *intel,
+                                            __DRIdrawable *drawable,
+                                            __DRIbuffer **buffers,
+                                            int *count);
+
+static void
+intel_process_dri2_buffer_no_separate_stencil(struct intel_context *intel,
+                                             __DRIdrawable *drawable,
+                                             __DRIbuffer *buffer,
+                                             struct intel_renderbuffer *rb,
+                                             const char *buffer_name);
+
 void
 intel_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable)
 {
    struct gl_framebuffer *fb = drawable->driverPrivate;
    struct intel_renderbuffer *rb;
-   struct intel_region *region, *depth_region;
    struct intel_context *intel = context->driverPrivate;
-   struct intel_renderbuffer *front_rb, *back_rb, *depth_rb, *stencil_rb;
    __DRIbuffer *buffers = NULL;
-   __DRIscreen *screen;
    int i, count;
-   unsigned int attachments[10];
    const char *region_name;
 
    /* If we're rendering to the fake front buffer, make sure all the
@@ -260,70 +269,12 @@ intel_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable)
    if (unlikely(INTEL_DEBUG & DEBUG_DRI))
       fprintf(stderr, "enter %s, drawable %p\n", __func__, drawable);
 
-   screen = intel->intelScreen->driScrnPriv;
-
-   if (screen->dri2.loader
-       && (screen->dri2.loader->base.version > 2)
-       && (screen->dri2.loader->getBuffersWithFormat != NULL)) {
-
-      front_rb = intel_get_renderbuffer(fb, BUFFER_FRONT_LEFT);
-      back_rb = intel_get_renderbuffer(fb, BUFFER_BACK_LEFT);
-      depth_rb = intel_get_renderbuffer(fb, BUFFER_DEPTH);
-      stencil_rb = intel_get_renderbuffer(fb, BUFFER_STENCIL);
-
-      i = 0;
-      if ((intel->is_front_buffer_rendering ||
-          intel->is_front_buffer_reading ||
-          !back_rb) && front_rb) {
-        attachments[i++] = __DRI_BUFFER_FRONT_LEFT;
-        attachments[i++] = intel_bits_per_pixel(front_rb);
-      }
-
-      if (back_rb) {
-        attachments[i++] = __DRI_BUFFER_BACK_LEFT;
-        attachments[i++] = intel_bits_per_pixel(back_rb);
-      }
-
-      if ((depth_rb != NULL) && (stencil_rb != NULL)) {
-        attachments[i++] = __DRI_BUFFER_DEPTH_STENCIL;
-        attachments[i++] = intel_bits_per_pixel(depth_rb);
-      } else if (depth_rb != NULL) {
-        attachments[i++] = __DRI_BUFFER_DEPTH;
-        attachments[i++] = intel_bits_per_pixel(depth_rb);
-      } else if (stencil_rb != NULL) {
-        attachments[i++] = __DRI_BUFFER_STENCIL;
-        attachments[i++] = intel_bits_per_pixel(stencil_rb);
-      }
-
-      buffers =
-        (*screen->dri2.loader->getBuffersWithFormat)(drawable,
-                                                     &drawable->w,
-                                                     &drawable->h,
-                                                     attachments, i / 2,
-                                                     &count,
-                                                     drawable->loaderPrivate);
-   } else if (screen->dri2.loader) {
-      i = 0;
-      if (intel_get_renderbuffer(fb, BUFFER_FRONT_LEFT))
-        attachments[i++] = __DRI_BUFFER_FRONT_LEFT;
-      if (intel_get_renderbuffer(fb, BUFFER_BACK_LEFT))
-        attachments[i++] = __DRI_BUFFER_BACK_LEFT;
-      if (intel_get_renderbuffer(fb, BUFFER_DEPTH))
-        attachments[i++] = __DRI_BUFFER_DEPTH;
-      if (intel_get_renderbuffer(fb, BUFFER_STENCIL))
-        attachments[i++] = __DRI_BUFFER_STENCIL;
-
-      buffers = (*screen->dri2.loader->getBuffers)(drawable,
-                                                  &drawable->w,
-                                                  &drawable->h,
-                                                  attachments, i,
-                                                  &count,
-                                                  drawable->loaderPrivate);
-   }
-
    if (buffers == NULL)
       return;
 
+   intel_query_dri2_buffers_no_separate_stencil(intel, drawable, &buffers,
+                                               &count);
+
    drawable->x = 0;
    drawable->y = 0;
    drawable->backX = 0;
@@ -339,7 +290,6 @@ intel_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable)
    drawable->pBackClipRects[0].x2 = drawable->w;
    drawable->pBackClipRects[0].y2 = drawable->h;
 
-   depth_region = NULL;
    for (i = 0; i < count; i++) {
        switch (buffers[i].attachment) {
        case __DRI_BUFFER_FRONT_LEFT:
@@ -380,51 +330,9 @@ intel_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable)
           return;
        }
 
-       if (rb == NULL)
-         continue;
-
-       if (rb->region && rb->region->name == buffers[i].name)
-            continue;
-
-       if (unlikely(INTEL_DEBUG & DEBUG_DRI))
-         fprintf(stderr,
-                 "attaching buffer %d, at %d, cpp %d, pitch %d\n",
-                 buffers[i].name, buffers[i].attachment,
-                 buffers[i].cpp, buffers[i].pitch);
-       
-       if (buffers[i].attachment == __DRI_BUFFER_STENCIL && depth_region) {
-         if (unlikely(INTEL_DEBUG & DEBUG_DRI))
-            fprintf(stderr, "(reusing depth buffer as stencil)\n");
-         intel_region_reference(&region, depth_region);
-       }
-       else
-          region = intel_region_alloc_for_handle(intel->intelScreen,
-                                                buffers[i].cpp,
-                                                drawable->w,
-                                                drawable->h,
-                                                buffers[i].pitch / buffers[i].cpp,
-                                                buffers[i].name,
-                                                region_name);
-
-       if (buffers[i].attachment == __DRI_BUFFER_DEPTH)
-         depth_region = region;
-
-       intel_renderbuffer_set_region(intel, rb, region);
-       intel_region_release(&region);
-
-       if (buffers[i].attachment == __DRI_BUFFER_DEPTH_STENCIL) {
-         rb = intel_get_renderbuffer(fb, BUFFER_STENCIL);
-         if (rb != NULL) {
-            struct intel_region *stencil_region = NULL;
-
-            if (rb->region && rb->region->name == buffers[i].name)
-                  continue;
-
-            intel_region_reference(&stencil_region, region);
-            intel_renderbuffer_set_region(intel, rb, stencil_region);
-            intel_region_release(&stencil_region);
-         }
-       }
+      intel_process_dri2_buffer_no_separate_stencil(intel, drawable,
+                                                   &buffers[i], rb,
+                                                   region_name);
    }
 
    driUpdateFramebufferSize(&intel->ctx, drawable);
@@ -1023,3 +931,196 @@ intelMakeCurrent(__DRIcontext * driContextPriv,
 
    return GL_TRUE;
 }
+
+/**
+ * \brief Query DRI2 to obtain a DRIdrawable's buffers.
+ *
+ * To determine which DRI buffers to request, examine the renderbuffers
+ * attached to the drawable's framebuffer. Then request the buffers with
+ * DRI2GetBuffers() or DRI2GetBuffersWithFormat().
+ *
+ * This is called from intel_update_renderbuffers(). It is used only if either
+ * the hardware or the X driver lacks separate stencil support.
+ *
+ * \param drawable      Drawable whose buffers are queried.
+ * \param buffers       [out] List of buffers returned by DRI2 query.
+ * \param buffer_count  [out] Number of buffers returned.
+ *
+ * \see intel_update_renderbuffers()
+ * \see DRI2GetBuffers()
+ * \see DRI2GetBuffersWithFormat()
+ */
+static void
+intel_query_dri2_buffers_no_separate_stencil(struct intel_context *intel,
+                                            __DRIdrawable *drawable,
+                                            __DRIbuffer **buffers,
+                                            int *buffer_count)
+{
+   assert(!intel->must_use_separate_stencil);
+
+   __DRIscreen *screen = intel->intelScreen->driScrnPriv;
+   struct gl_framebuffer *fb = drawable->driverPrivate;
+
+   if (screen->dri2.loader
+       && screen->dri2.loader->base.version > 2
+       && screen->dri2.loader->getBuffersWithFormat != NULL) {
+
+      int i = 0;
+      const int max_attachments = 4;
+      unsigned *attachments = calloc(2 * max_attachments, sizeof(unsigned));
+
+      struct intel_renderbuffer *front_rb;
+      struct intel_renderbuffer *back_rb;
+      struct intel_renderbuffer *depth_rb;
+      struct intel_renderbuffer *stencil_rb;
+
+      front_rb = intel_get_renderbuffer(fb, BUFFER_FRONT_LEFT);
+      back_rb = intel_get_renderbuffer(fb, BUFFER_BACK_LEFT);
+      depth_rb = intel_get_renderbuffer(fb, BUFFER_DEPTH);
+      stencil_rb = intel_get_renderbuffer(fb, BUFFER_STENCIL);
+
+      if ((intel->is_front_buffer_rendering ||
+          intel->is_front_buffer_reading ||
+          !back_rb) && front_rb) {
+        attachments[i++] = __DRI_BUFFER_FRONT_LEFT;
+        attachments[i++] = intel_bits_per_pixel(front_rb);
+      }
+
+      if (back_rb) {
+        attachments[i++] = __DRI_BUFFER_BACK_LEFT;
+        attachments[i++] = intel_bits_per_pixel(back_rb);
+      }
+
+      if (depth_rb && stencil_rb) {
+        attachments[i++] = __DRI_BUFFER_DEPTH_STENCIL;
+        attachments[i++] = intel_bits_per_pixel(depth_rb);
+      } else if (depth_rb) {
+        attachments[i++] = __DRI_BUFFER_DEPTH;
+        attachments[i++] = intel_bits_per_pixel(depth_rb);
+      } else if (stencil_rb) {
+        attachments[i++] = __DRI_BUFFER_STENCIL;
+        attachments[i++] = intel_bits_per_pixel(stencil_rb);
+      }
+
+      assert(i <= 2 * max_attachments);
+
+      *buffers = screen->dri2.loader->getBuffersWithFormat(drawable,
+                                                          &drawable->w,
+                                                          &drawable->h,
+                                                          attachments, i / 2,
+                                                          buffer_count,
+                                                          drawable->loaderPrivate);
+      free(attachments);
+
+   } else if (screen->dri2.loader) {
+
+      int i = 0;
+      const int max_attachments = 4;
+      unsigned *attachments = calloc(max_attachments, sizeof(unsigned));
+
+      if (intel_get_renderbuffer(fb, BUFFER_FRONT_LEFT))
+        attachments[i++] = __DRI_BUFFER_FRONT_LEFT;
+      if (intel_get_renderbuffer(fb, BUFFER_BACK_LEFT))
+        attachments[i++] = __DRI_BUFFER_BACK_LEFT;
+      if (intel_get_renderbuffer(fb, BUFFER_DEPTH))
+        attachments[i++] = __DRI_BUFFER_DEPTH;
+      if (intel_get_renderbuffer(fb, BUFFER_STENCIL))
+        attachments[i++] = __DRI_BUFFER_STENCIL;
+
+      assert(i <= max_attachments);
+
+      *buffers = screen->dri2.loader->getBuffersWithFormat(drawable,
+                                                          &drawable->w,
+                                                          &drawable->h,
+                                                          attachments, i,
+                                                          buffer_count,
+                                                          drawable->loaderPrivate);
+      free(attachments);
+
+   } else {
+      *buffers = NULL;
+      *buffer_count = 0;
+   }
+}
+
+/**
+ * \brief Assign a DRI buffer's DRM region to a renderbuffer.
+ *
+ * This is called from intel_update_renderbuffers().  It is used only if
+ * either the hardware or the X driver lacks separate stencil support.
+ *
+ * \par Note:
+ *    DRI buffers whose attachment point is DRI2BufferStencil or
+ *    DRI2BufferDepthStencil are handled as special cases.
+ *
+ * \param buffer_name is a human readable name, such as "dri2 front buffer",
+ *        that is passed to intel_region_alloc_for_handle().
+ *
+ * \see intel_update_renderbuffers()
+ * \see intel_region_alloc_for_handle()
+ * \see intel_renderbuffer_set_region()
+ */
+static void
+intel_process_dri2_buffer_no_separate_stencil(struct intel_context *intel,
+                                             __DRIdrawable *drawable,
+                                             __DRIbuffer *buffer,
+                                             struct intel_renderbuffer *rb,
+                                             const char *buffer_name)
+{
+   assert(!intel->must_use_separate_stencil);
+
+   struct gl_framebuffer *fb = drawable->driverPrivate;
+   struct intel_region *region = NULL;
+   struct intel_renderbuffer *depth_rb = NULL;
+
+   if (!rb)
+      return;
+
+   if (rb->region && rb->region->name == buffer->name)
+      return;
+
+   if (unlikely(INTEL_DEBUG & DEBUG_DRI)) {
+      fprintf(stderr,
+             "attaching buffer %d, at %d, cpp %d, pitch %d\n",
+             buffer->name, buffer->attachment,
+             buffer->cpp, buffer->pitch);
+   }
+
+   bool identify_depth_and_stencil = false;
+   if (buffer->attachment == __DRI_BUFFER_STENCIL) {
+      struct intel_renderbuffer *depth_rb =
+        intel_get_renderbuffer(fb, BUFFER_DEPTH);
+      identify_depth_and_stencil = depth_rb && depth_rb->region;
+   }
+
+   if (identify_depth_and_stencil) {
+      if (unlikely(INTEL_DEBUG & DEBUG_DRI)) {
+        fprintf(stderr, "(reusing depth buffer as stencil)\n");
+      }
+      intel_region_reference(&region, depth_rb->region);
+   } else {
+      region = intel_region_alloc_for_handle(intel->intelScreen,
+                                            buffer->cpp,
+                                            drawable->w,
+                                            drawable->h,
+                                            buffer->pitch / buffer->cpp,
+                                            buffer->name,
+                                            buffer_name);
+   }
+
+   intel_renderbuffer_set_region(intel, rb, region);
+   intel_region_release(&region);
+
+   if (buffer->attachment == __DRI_BUFFER_DEPTH_STENCIL) {
+      struct intel_renderbuffer *stencil_rb =
+        intel_get_renderbuffer(fb, BUFFER_STENCIL);
+
+      if (!stencil_rb)
+        return;
+
+      if (stencil_rb->region && stencil_rb->region->name == buffer->name)
+        return;
+
+      intel_renderbuffer_set_region(intel, stencil_rb, region);
+   }
+}