Mesa (master): intel: Add support for ARB_copy_buffer.

Eric Anholt anholt at kemper.freedesktop.org
Fri Aug 28 00:56:53 UTC 2009


Module: Mesa
Branch: master
Commit: 60b072d49fd2a1b2bf59442ae7209379152b1500
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=60b072d49fd2a1b2bf59442ae7209379152b1500

Author: Eric Anholt <eric at anholt.net>
Date:   Thu Aug 27 16:53:50 2009 -0700

intel: Add support for ARB_copy_buffer.

Passes glean's bufferObject test for this extension.

---

 src/mesa/drivers/dri/intel/intel_buffer_objects.c |   93 ++++++++++++++++++++-
 src/mesa/drivers/dri/intel/intel_extensions.c     |    2 +
 2 files changed, 93 insertions(+), 2 deletions(-)

diff --git a/src/mesa/drivers/dri/intel/intel_buffer_objects.c b/src/mesa/drivers/dri/intel/intel_buffer_objects.c
index 9600557..a740397 100644
--- a/src/mesa/drivers/dri/intel/intel_buffer_objects.c
+++ b/src/mesa/drivers/dri/intel/intel_buffer_objects.c
@@ -28,9 +28,11 @@
 
 #include "main/imports.h"
 #include "main/mtypes.h"
+#include "main/macros.h"
 #include "main/bufferobj.h"
 
 #include "intel_context.h"
+#include "intel_blit.h"
 #include "intel_buffer_objects.h"
 #include "intel_batchbuffer.h"
 #include "intel_regions.h"
@@ -243,8 +245,10 @@ intel_bufferobj_map(GLcontext * ctx,
       return obj->Pointer;
    }
 
-   if (!read_only)
-      intelFlush(ctx);
+   /* Flush any existing batchbuffer that might have written to this
+    * buffer.
+    */
+   intelFlush(ctx);
 
    if (intel_obj->region)
       intel_bufferobj_cow(intel, intel_obj);
@@ -325,6 +329,90 @@ intel_bufferobj_buffer(struct intel_context *intel,
    return intel_obj->buffer;
 }
 
+static void
+intel_bufferobj_copy_subdata(GLcontext *ctx,
+			     struct gl_buffer_object *src,
+			     struct gl_buffer_object *dst,
+			     GLintptr read_offset, GLintptr write_offset,
+			     GLsizeiptr size)
+{
+   struct intel_context *intel = intel_context(ctx);
+   struct intel_buffer_object *intel_src = intel_buffer_object(src);
+   struct intel_buffer_object *intel_dst = intel_buffer_object(dst);
+   drm_intel_bo *src_bo, *dst_bo;
+   GLuint pitch, height;
+
+   if (size == 0)
+      return;
+
+   /* If we're in system memory, just map and memcpy. */
+   if (intel_src->sys_buffer || intel_dst->sys_buffer) {
+      /* The same buffer may be used, but note that regions copied may
+       * not overlap.
+       */
+      if (src == dst) {
+	 char *ptr = intel_bufferobj_map(ctx, GL_COPY_WRITE_BUFFER,
+					 GL_READ_WRITE, dst);
+	 memcpy(ptr + write_offset, ptr + read_offset, size);
+	 intel_bufferobj_unmap(ctx, GL_COPY_WRITE_BUFFER, dst);
+      } else {
+	 const char *src_ptr;
+	 char *dst_ptr;
+
+	 src_ptr =  intel_bufferobj_map(ctx, GL_COPY_READ_BUFFER,
+					GL_READ_ONLY, src);
+	 dst_ptr =  intel_bufferobj_map(ctx, GL_COPY_WRITE_BUFFER,
+					GL_WRITE_ONLY, dst);
+
+	 memcpy(dst_ptr + write_offset, src_ptr + read_offset, size);
+
+	 intel_bufferobj_unmap(ctx, GL_COPY_READ_BUFFER, src);
+	 intel_bufferobj_unmap(ctx, GL_COPY_WRITE_BUFFER, dst);
+      }
+   }
+
+   /* Otherwise, we have real BOs, so blit them.  We don't have a memmove-type
+    * blit like some other hardware, so we'll do a rectangular blit covering
+    * a large space, then emit a scanline blit at the end to cover the last
+    * if we need.
+    */
+
+   dst_bo = intel_bufferobj_buffer(intel, intel_dst, INTEL_WRITE_PART);
+   src_bo = intel_bufferobj_buffer(intel, intel_src, INTEL_READ);
+
+   /* The pitch is a signed value. */
+   pitch = MIN2(size, (1 << 15) - 1);
+   height = size / pitch;
+   intelEmitCopyBlit(intel, 1,
+		     pitch, src_bo, read_offset, I915_TILING_NONE,
+		     pitch, dst_bo, write_offset, I915_TILING_NONE,
+		     0, 0, /* src x/y */
+		     0, 0, /* dst x/y */
+		     pitch, height, /* w, h */
+		     GL_COPY);
+
+   read_offset += pitch * height;
+   write_offset += pitch * height;
+   size -= pitch * height;
+   assert (size < (1 << 15));
+   if (size != 0) {
+      intelEmitCopyBlit(intel, 1,
+			size, src_bo, read_offset, I915_TILING_NONE,
+			size, dst_bo, write_offset, I915_TILING_NONE,
+			0, 0, /* src x/y */
+			0, 0, /* dst x/y */
+			size, 1, /* w, h */
+			GL_COPY);
+   }
+
+   /* Since we've emitted some blits to buffers that will (likely) be used
+    * in rendering operations in other cache domains in this batch, emit a
+    * flush.  Once again, we wish for a domain tracker in libdrm to cover
+    * usage inside of a batchbuffer.
+    */
+   intel_batchbuffer_emit_mi_flush(intel->batch);
+}
+
 void
 intelInitBufferObjectFuncs(struct dd_function_table *functions)
 {
@@ -335,4 +423,5 @@ intelInitBufferObjectFuncs(struct dd_function_table *functions)
    functions->GetBufferSubData = intel_bufferobj_get_subdata;
    functions->MapBuffer = intel_bufferobj_map;
    functions->UnmapBuffer = intel_bufferobj_unmap;
+   functions->CopyBufferSubData = intel_bufferobj_copy_subdata;
 }
diff --git a/src/mesa/drivers/dri/intel/intel_extensions.c b/src/mesa/drivers/dri/intel/intel_extensions.c
index 9f90ef0..ff9ad5a 100644
--- a/src/mesa/drivers/dri/intel/intel_extensions.c
+++ b/src/mesa/drivers/dri/intel/intel_extensions.c
@@ -30,6 +30,7 @@
 #include "intel_extensions.h"
 
 
+#define need_GL_ARB_copy_buffer
 #define need_GL_ARB_framebuffer_object
 #define need_GL_ARB_occlusion_query
 #define need_GL_ARB_point_parameters
@@ -69,6 +70,7 @@
  * i965_dri.
  */
 static const struct dri_extension card_extensions[] = {
+   { "GL_ARB_copy_buffer",                GL_ARB_copy_buffer_functions },
    { "GL_ARB_half_float_pixel",           NULL },
    { "GL_ARB_multitexture",               NULL },
    { "GL_ARB_point_parameters",           GL_ARB_point_parameters_functions },




More information about the mesa-commit mailing list