[Mesa-dev] [PATCH 17/22] i965: Convert DrawPixels over to blorp

Chris Wilson chris at chris-wilson.co.uk
Sat Aug 5 09:40:09 UTC 2017


Similar to the mechanism used by ReadPixels, use blorp for better format
handling than the existing blitter-only paths.
---
 src/mesa/drivers/dri/i965/intel_pixel.c        |   5 -
 src/mesa/drivers/dri/i965/intel_pixel.h        |   9 +-
 src/mesa/drivers/dri/i965/intel_pixel_bitmap.c |   3 +
 src/mesa/drivers/dri/i965/intel_pixel_draw.c   | 122 ++--------------
 src/mesa/drivers/dri/i965/intel_pixel_pbo.c    | 192 +++++++++++++++++++++++++
 5 files changed, 216 insertions(+), 115 deletions(-)

diff --git a/src/mesa/drivers/dri/i965/intel_pixel.c b/src/mesa/drivers/dri/i965/intel_pixel.c
index c69c3cc7dc..e3b6e749f4 100644
--- a/src/mesa/drivers/dri/i965/intel_pixel.c
+++ b/src/mesa/drivers/dri/i965/intel_pixel.c
@@ -113,11 +113,6 @@ intel_check_blit_fragment_ops(struct gl_context * ctx, bool src_alpha_is_one)
       return false;
    }
 
-   if (ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F) {
-      DBG("fallback due to pixel zoom\n");
-      return false;
-   }
-
    if (ctx->RenderMode != GL_RENDER) {
       DBG("fallback due to render mode\n");
       return false;
diff --git a/src/mesa/drivers/dri/i965/intel_pixel.h b/src/mesa/drivers/dri/i965/intel_pixel.h
index c3d90d3297..0cdd773bfa 100644
--- a/src/mesa/drivers/dri/i965/intel_pixel.h
+++ b/src/mesa/drivers/dri/i965/intel_pixel.h
@@ -30,7 +30,7 @@
 
 void intelInitPixelFuncs(struct dd_function_table *functions);
 bool intel_check_blit_fragment_ops(struct gl_context * ctx,
-					bool src_alpha_is_one);
+                                   bool src_alpha_is_one);
 
 void intelReadPixels(struct gl_context * ctx,
                      GLint x, GLint y,
@@ -65,4 +65,11 @@ bool intel_readpixels_pbo(struct gl_context * ctx,
                           const struct gl_pixelstore_attrib *pack,
                           GLvoid *pixels);
 
+bool intel_drawpixels_pbo(struct gl_context *ctx,
+                          GLint x, GLint y,
+                          GLsizei width, GLsizei height,
+                          GLenum format, GLenum type,
+                          const struct gl_pixelstore_attrib *pack,
+                          const GLvoid *pixels);
+
 #endif
diff --git a/src/mesa/drivers/dri/i965/intel_pixel_bitmap.c b/src/mesa/drivers/dri/i965/intel_pixel_bitmap.c
index 8d467adc56..fafb4c99a7 100644
--- a/src/mesa/drivers/dri/i965/intel_pixel_bitmap.c
+++ b/src/mesa/drivers/dri/i965/intel_pixel_bitmap.c
@@ -242,6 +242,9 @@ do_blit_bitmap( struct gl_context *ctx,
    if (!intel_check_blit_fragment_ops(ctx, tmpColor[3] == 1.0F))
       return false;
 
+   if (ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F)
+      return false;
+
    /* Clip to buffer bounds and scissor. */
    if (!_mesa_clip_to_region(fb->_Xmin, fb->_Ymin,
 			     fb->_Xmax, fb->_Ymax,
diff --git a/src/mesa/drivers/dri/i965/intel_pixel_draw.c b/src/mesa/drivers/dri/i965/intel_pixel_draw.c
index 519e059672..12a7a57937 100644
--- a/src/mesa/drivers/dri/i965/intel_pixel_draw.c
+++ b/src/mesa/drivers/dri/i965/intel_pixel_draw.c
@@ -47,101 +47,6 @@
 
 #define FILE_DEBUG_FLAG DEBUG_PIXEL
 
-static bool
-do_blit_drawpixels(struct gl_context * ctx,
-		   GLint x, GLint y, GLsizei width, GLsizei height,
-		   GLenum format, GLenum type,
-		   const struct gl_pixelstore_attrib *unpack,
-		   const GLvoid * pixels)
-{
-   struct brw_context *brw = brw_context(ctx);
-   struct intel_buffer_object *src = intel_buffer_object(unpack->BufferObj);
-   GLuint src_offset;
-   struct brw_bo *src_buffer;
-
-   DBG("%s\n", __func__);
-
-   if (!intel_check_blit_fragment_ops(ctx, false))
-      return false;
-
-   if (ctx->DrawBuffer->_NumColorDrawBuffers != 1) {
-      DBG("%s: fallback due to MRT\n", __func__);
-      return false;
-   }
-
-   intel_prepare_render(brw);
-
-   struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[0];
-   struct intel_renderbuffer *irb = intel_renderbuffer(rb);
-
-   mesa_format src_format = _mesa_format_from_format_and_type(format, type);
-   if (_mesa_format_is_mesa_array_format(src_format))
-      src_format = _mesa_format_from_array_format(src_format);
-   mesa_format dst_format = irb->mt->format;
-
-   /* We can safely discard sRGB encode/decode for the DrawPixels interface */
-   src_format = _mesa_get_srgb_format_linear(src_format);
-   dst_format = _mesa_get_srgb_format_linear(dst_format);
-
-   if (!intel_miptree_blit_compatible_formats(src_format, dst_format)) {
-      DBG("%s: bad format for blit\n", __func__);
-      return false;
-   }
-
-   if (unpack->SwapBytes || unpack->LsbFirst ||
-       unpack->SkipPixels || unpack->SkipRows) {
-      DBG("%s: bad packing params\n", __func__);
-      return false;
-   }
-
-   int src_stride = _mesa_image_row_stride(unpack, width, format, type);
-   bool src_flip = false;
-   /* Mesa flips the src_stride for unpack->Invert, but we want our mt to have
-    * a normal src_stride.
-    */
-   if (unpack->Invert) {
-      src_stride = -src_stride;
-      src_flip = true;
-   }
-
-   src_offset = (GLintptr)pixels;
-   src_offset += _mesa_image_offset(2, unpack, width, height,
-				    format, type, 0, 0, 0);
-
-   src_buffer = intel_bufferobj_buffer(brw, src, src_offset,
-                                       height * src_stride, false);
-
-   struct intel_mipmap_tree *pbo_mt =
-      intel_miptree_create_for_bo(brw,
-                                  src_buffer,
-                                  irb->mt->format,
-                                  src_offset,
-                                  width, height, 1,
-                                  src_stride,
-                                  0);
-   if (!pbo_mt)
-      return false;
-
-   if (!intel_miptree_blit(brw,
-                           pbo_mt, 0, 0,
-                           0, 0, src_flip,
-                           irb->mt, irb->mt_level, irb->mt_layer,
-                           x, y, _mesa_is_winsys_fbo(ctx->DrawBuffer),
-                           width, height, GL_COPY)) {
-      DBG("%s: blit failed\n", __func__);
-      intel_miptree_release(&pbo_mt);
-      return false;
-   }
-
-   intel_miptree_release(&pbo_mt);
-
-   if (ctx->Query.CurrentOcclusionObject)
-      ctx->Query.CurrentOcclusionObject->Result += width * height;
-
-   DBG("%s: success\n", __func__);
-   return true;
-}
-
 void
 intelDrawPixels(struct gl_context * ctx,
                 GLint x, GLint y,
@@ -156,21 +61,20 @@ intelDrawPixels(struct gl_context * ctx,
    if (!_mesa_check_conditional_render(ctx))
       return;
 
-   if (format == GL_STENCIL_INDEX) {
-      _swrast_DrawPixels(ctx, x, y, width, height, format, type,
-                         unpack, pixels);
-      return;
-   }
+   intel_prepare_render(brw);
 
-   if (_mesa_is_bufferobj(unpack->BufferObj)) {
-      if (do_blit_drawpixels(ctx, x, y, width, height, format, type, unpack,
-			     pixels)) {
-	 return;
-      }
+   if (intel_drawpixels_pbo(ctx,
+                            x, y, width, height,
+                            format, type, unpack, pixels))
+      return;
 
-      perf_debug("%s: fallback to generic code in PBO case\n", __func__);
-   }
+   perf_debug("%s: fallback to generic code%s\n",
+              __func__, _mesa_is_bufferobj(unpack->BufferObj) ? " for PBO" :"");
 
-   _mesa_meta_DrawPixels(ctx, x, y, width, height, format, type,
-                         unpack, pixels);
+   if (format == GL_STENCIL_INDEX)
+      _swrast_DrawPixels(ctx, x, y, width, height,
+                         format, type, unpack, pixels);
+   else
+      _mesa_meta_DrawPixels(ctx, x, y, width, height,
+                            format, type, unpack, pixels);
 }
diff --git a/src/mesa/drivers/dri/i965/intel_pixel_pbo.c b/src/mesa/drivers/dri/i965/intel_pixel_pbo.c
index 4e212ee92f..a503481148 100644
--- a/src/mesa/drivers/dri/i965/intel_pixel_pbo.c
+++ b/src/mesa/drivers/dri/i965/intel_pixel_pbo.c
@@ -21,6 +21,7 @@
  * IN THE SOFTWARE.
  */
 
+#include "main/blend.h"
 #include "main/enums.h"
 #include "main/mtypes.h"
 #include "main/macros.h"
@@ -250,3 +251,194 @@ err_dst_buffer:
       brw_bo_unreference(dst_buffer);
    return ok;
 }
+
+bool
+intel_drawpixels_pbo(struct gl_context *ctx,
+                     GLint x, GLint y,
+                     GLsizei width, GLsizei height,
+                     GLenum format, GLenum type,
+                     const struct gl_pixelstore_attrib *pack,
+                     const GLvoid *pixels)
+{
+   struct brw_context *brw = brw_context(ctx);
+   bool ok = false;
+
+   if (!intel_check_blit_fragment_ops(ctx, false))
+      return false;
+
+   struct gl_renderbuffer *rb;
+   switch (format) {
+   case GL_STENCIL_INDEX:
+      rb = ctx->ReadBuffer->Attachment[BUFFER_STENCIL].Renderbuffer;
+      break;
+   case GL_DEPTH_COMPONENT:
+   case GL_DEPTH_STENCIL_EXT:
+      rb = ctx->ReadBuffer->Attachment[BUFFER_DEPTH].Renderbuffer;
+      break;
+   case GL_COLOR_INDEX:
+      rb = NULL;
+      break;
+   default:
+      if (ctx->DrawBuffer->_NumColorDrawBuffers != 1) {
+         DBG("%s: fallback due to MRT\n", __func__);
+         return false;
+      }
+
+      if ((type == GL_FLOAT || type == GL_HALF_FLOAT) &&
+          _mesa_get_clamp_fragment_color(ctx, ctx->DrawBuffer)) {
+         return false;
+      }
+
+      /* all other formats should be color formats */
+      rb = ctx->DrawBuffer->_ColorReadBuffer;
+      break;
+   }
+   if (!rb)
+      return false;
+
+   if (pack->SwapBytes || pack->LsbFirst) {
+      DBG("%s: bad packing params\n", __func__);
+      return false;
+   }
+
+   struct intel_renderbuffer *irb = intel_renderbuffer(rb);
+   struct intel_mipmap_tree *dst = irb->mt;
+   if (format == GL_STENCIL_INDEX && dst->stencil_mt)
+      dst = dst->stencil_mt;
+   if (!brw->mesa_format_supports_render[dst->format])
+      return false;
+
+   if (need_signed_unsigned_int_conversion(dst->format, format, type))
+      return false;
+
+   mesa_format src_format = _mesa_format_from_format_and_type(format, type);
+   if (_mesa_format_is_mesa_array_format(src_format))
+      src_format = _mesa_format_from_array_format(src_format);
+   src_format = _mesa_get_srgb_format_linear(src_format);
+
+   if (!brw->screen->mesa_format_supports_texture[src_format])
+      return false;
+
+   if (_mesa_need_rgb_to_luminance_conversion(format, rb->_BaseFormat))
+      return false;
+
+   bool src_flip = false;
+   int src_stride = _mesa_image_row_stride(pack, width, format, type);
+   if (pack->Invert) {
+      src_stride = -src_stride;
+      src_flip = true;
+   }
+
+   int bpp = _mesa_bytes_per_pixel(format, type);
+   pixels += pack->SkipRows * src_stride + pack->SkipPixels * bpp;
+   int src_size = src_stride * (height - 1) + width * bpp;
+   assert(src_stride % bpp == 0);
+
+   struct brw_bo *src_buffer;
+   int src_offset;
+   if (_mesa_is_bufferobj(pack->BufferObj)) {
+      src_offset = (GLintptr)pixels;
+      src_buffer = intel_bufferobj_buffer(brw,
+                                          intel_buffer_object(pack->BufferObj),
+                                          src_offset,
+                                          src_size,
+                                          true);
+   } else if (brw_bo_busy(dst->bo)) {
+      src_offset = 0;
+      src_buffer = brw_bo_alloc(brw->bufmgr, "drawpixels", src_size, 0);
+      if (!src_buffer)
+         return false;
+
+      void *map = brw_bo_map(brw, src_buffer, MAP_WRITE);
+      if (!map)
+         goto err_src_buffer;
+
+      memcpy(map, pixels, src_size);
+      brw_bo_unmap(src_buffer);
+   } else {
+      src_offset = (GLintptr)pixels & 4095;
+      src_buffer = brw_bo_alloc_userptr(brw->bufmgr, "drawpixels(userptr)",
+                                        (void *)((GLintptr)pixels & -4096),
+                                        ALIGN(src_size + src_offset, 4096), 0);
+   }
+   if (!src_buffer)
+      return false;
+
+   struct intel_mipmap_tree *src =
+      intel_miptree_create_for_bo(brw,
+                                  src_buffer,
+                                  src_format,
+                                  src_offset,
+                                  width, height, 1,
+                                  src_stride,
+                                  MIPTREE_LAYOUT_FOR_TEXTURE |
+                                  MIPTREE_LAYOUT_TILING_NONE |
+                                  MIPTREE_LAYOUT_DISABLE_AUX);
+   if (!src)
+      goto err_src_buffer;
+
+   if (!rb->Name) {
+      src_flip = !src_flip;
+      y = rb->Height - y - height;
+   }
+
+   assert(src->surf.tiling == ISL_TILING_LINEAR);
+   if (ctx->Pixel.ZoomX != 1. || ctx->Pixel.ZoomY != 1. ||
+       !intel_miptree_blit(brw,
+                           src, 0, 0, 0, 0, src_flip,
+                           dst, irb->mt_level, irb->mt_layer, x, y, false,
+                           width, height, GL_COPY)) {
+      mesa_format dst_format = irb->Base.Base.Format;
+
+      /* blorp restrictions; see try_blorp_blit() */
+      switch (format) {
+      case GL_STENCIL_INDEX:
+         if (src_format != dst_format)
+            goto err_src_mt;
+
+         /* fallthrough */
+      case GL_DEPTH_COMPONENT:
+      case GL_DEPTH_STENCIL_EXT:
+         if ((src_format == MESA_FORMAT_Z24_UNORM_X8_UINT) !=
+             (dst_format == MESA_FORMAT_Z24_UNORM_X8_UINT))
+            goto err_src_mt;
+
+         if (_mesa_get_format_base_format(src_format) == GL_DEPTH_STENCIL ||
+             _mesa_get_format_base_format(dst_format) == GL_DEPTH_STENCIL)
+            goto err_src_mt;
+
+         src_format = MESA_FORMAT_NONE;
+         dst_format = MESA_FORMAT_NONE;
+         break;
+
+      default:
+         break;
+      }
+
+      brw_blorp_blit_miptrees(brw,
+                              src, 0, 0, src_format, SWIZZLE_XYZW,
+                              dst, irb->mt_level, irb->mt_layer, dst_format,
+                              0, 0, width, height,
+                              x, y,
+                              x + width * ctx->Pixel.ZoomX,
+                              y + height * ctx->Pixel.ZoomY,
+                              GL_NEAREST, false, src_flip,
+                              false, false);
+   }
+
+   if (src_buffer->userptr) {
+      intel_batchbuffer_flush(brw);
+      brw_bo_wait_rendering(src_buffer);
+   }
+
+   if (ctx->Query.CurrentOcclusionObject)
+      ctx->Query.CurrentOcclusionObject->Result += width * height;
+
+   ok = true;
+err_src_mt:
+   intel_miptree_release(&src);
+err_src_buffer:
+   if (!_mesa_is_bufferobj(pack->BufferObj))
+      brw_bo_unreference(src_buffer);
+   return ok;
+}
-- 
2.13.3



More information about the mesa-dev mailing list