summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/mesa/drivers/dri/i965/brw_blorp_blit.cpp88
-rw-r--r--src/mesa/drivers/dri/i965/brw_context.h8
-rw-r--r--src/mesa/drivers/dri/intel/intel_fbo.c30
-rw-r--r--src/mesa/drivers/dri/intel/intel_fbo.h4
-rw-r--r--src/mesa/drivers/dri/intel/intel_tex_copy.c32
5 files changed, 154 insertions, 8 deletions
diff --git a/src/mesa/drivers/dri/i965/brw_blorp_blit.cpp b/src/mesa/drivers/dri/i965/brw_blorp_blit.cpp
index bc7916a1bd4..f45bbbf4315 100644
--- a/src/mesa/drivers/dri/i965/brw_blorp_blit.cpp
+++ b/src/mesa/drivers/dri/i965/brw_blorp_blit.cpp
@@ -23,6 +23,7 @@
#include "main/teximage.h"
#include "main/fbobject.h"
+#include "main/renderbuffer.h"
#include "glsl/ralloc.h"
@@ -295,6 +296,93 @@ try_blorp_blit(struct intel_context *intel,
return true;
}
+bool
+brw_blorp_copytexsubimage(struct intel_context *intel,
+ struct gl_renderbuffer *src_rb,
+ struct gl_texture_image *dst_image,
+ int srcX0, int srcY0,
+ int dstX0, int dstY0,
+ int width, int height)
+{
+ struct gl_context *ctx = &intel->ctx;
+ struct intel_renderbuffer *src_irb = intel_renderbuffer(src_rb);
+ struct intel_renderbuffer *dst_irb;
+
+ /* BLORP is not supported before Gen6. */
+ if (intel->gen < 6)
+ return false;
+
+ /* Create a fake/wrapper renderbuffer to allow us to use do_blorp_blit(). */
+ dst_irb = intel_create_fake_renderbuffer_wrapper(intel, dst_image);
+ if (!dst_irb)
+ return false;
+
+ struct gl_renderbuffer *dst_rb = &dst_irb->Base.Base;
+
+ /* Unlike BlitFramebuffer, CopyTexSubImage doesn't have a buffer bit.
+ * It's only used by find_miptee() to decide whether to dereference the
+ * separate stencil miptree. In the case of packed depth/stencil, core
+ * Mesa hands us the depth attachment as src_rb (not stencil), so assume
+ * non-stencil for now. A buffer bit of 0 works for both color and depth.
+ */
+ GLbitfield buffer_bit = 0;
+
+ if (!formats_match(buffer_bit, src_irb, dst_irb)) {
+ _mesa_delete_renderbuffer(ctx, dst_rb);
+ return false;
+ }
+
+ /* Source clipping shouldn't be necessary, since copytexsubimage (in
+ * src/mesa/main/teximage.c) calls _mesa_clip_copytexsubimage() which
+ * takes care of it.
+ *
+ * Destination clipping shouldn't be necessary since the restrictions on
+ * glCopyTexSubImage prevent the user from specifying a destination rectangle
+ * that falls outside the bounds of the destination texture.
+ * See error_check_subtexture_dimensions().
+ */
+
+ int srcY1 = srcY0 + height;
+ int dstX1 = dstX0 + width;
+ int dstY1 = dstY0 + height;
+
+ /* Sync up the state of window system buffers. We need to do this before
+ * we go looking for the buffers.
+ */
+ intel_prepare_render(intel);
+
+ /* Account for the fact that in the system framebuffer, the origin is at
+ * the lower left.
+ */
+ bool mirror_y = false;
+ if (_mesa_is_winsys_fbo(ctx->ReadBuffer)) {
+ GLint tmp = src_rb->Height - srcY0;
+ srcY0 = src_rb->Height - srcY1;
+ srcY1 = tmp;
+ mirror_y = true;
+ }
+
+ do_blorp_blit(intel, buffer_bit, src_irb, dst_irb,
+ srcX0, srcY0, dstX0, dstY0, dstX1, dstY1, false, mirror_y);
+
+ /* If we're copying a packed depth stencil texture, the above do_blorp_blit
+ * copied depth (since buffer_bit != GL_STENCIL_BIT). Now copy stencil as
+ * well. There's no need to do a formats_match() check because the separate
+ * stencil buffer is always S8.
+ */
+ src_rb = ctx->ReadBuffer->Attachment[BUFFER_STENCIL].Renderbuffer;
+ if (_mesa_get_format_bits(dst_image->TexFormat, GL_STENCIL_BITS) > 0 &&
+ src_rb != NULL) {
+ src_irb = intel_renderbuffer(src_rb);
+ do_blorp_blit(intel, GL_STENCIL_BUFFER_BIT, src_irb, dst_irb,
+ srcX0, srcY0, dstX0, dstY0, dstX1, dstY1, false, mirror_y);
+ }
+
+ _mesa_delete_renderbuffer(ctx, dst_rb);
+ return true;
+}
+
+
GLbitfield
brw_blorp_framebuffer(struct intel_context *intel,
GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
diff --git a/src/mesa/drivers/dri/i965/brw_context.h b/src/mesa/drivers/dri/i965/brw_context.h
index 9affb7e5674..50956029590 100644
--- a/src/mesa/drivers/dri/i965/brw_context.h
+++ b/src/mesa/drivers/dri/i965/brw_context.h
@@ -1215,6 +1215,14 @@ brw_blorp_framebuffer(struct intel_context *intel,
GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
GLbitfield mask, GLenum filter);
+bool
+brw_blorp_copytexsubimage(struct intel_context *intel,
+ struct gl_renderbuffer *src_rb,
+ struct gl_texture_image *dst_image,
+ int srcX0, int srcY0,
+ int dstX0, int dstY0,
+ int width, int height);
+
/* gen6_multisample_state.c */
void
gen6_emit_3dstate_multisample(struct brw_context *brw,
diff --git a/src/mesa/drivers/dri/intel/intel_fbo.c b/src/mesa/drivers/dri/intel/intel_fbo.c
index 481080944dd..37ecbd1701d 100644
--- a/src/mesa/drivers/dri/intel/intel_fbo.c
+++ b/src/mesa/drivers/dri/intel/intel_fbo.c
@@ -531,6 +531,36 @@ intel_renderbuffer_update_wrapper(struct intel_context *intel,
return true;
}
+/**
+ * Create a fake intel_renderbuffer that wraps a gl_texture_image.
+ */
+struct intel_renderbuffer *
+intel_create_fake_renderbuffer_wrapper(struct intel_context *intel,
+ struct gl_texture_image *image)
+{
+ struct gl_context *ctx = &intel->ctx;
+ struct intel_renderbuffer *irb;
+ struct gl_renderbuffer *rb;
+
+ irb = CALLOC_STRUCT(intel_renderbuffer);
+ if (!irb) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "creating renderbuffer");
+ return NULL;
+ }
+
+ rb = &irb->Base.Base;
+
+ _mesa_init_renderbuffer(rb, 0);
+ rb->ClassID = INTEL_RB_CLASS;
+
+ if (!intel_renderbuffer_update_wrapper(intel, irb, image, image->Face)) {
+ intel_delete_renderbuffer(ctx, rb);
+ return NULL;
+ }
+
+ return irb;
+}
+
void
intel_renderbuffer_set_draw_offset(struct intel_renderbuffer *irb)
{
diff --git a/src/mesa/drivers/dri/intel/intel_fbo.h b/src/mesa/drivers/dri/intel/intel_fbo.h
index 9c48e9c1e8f..f135dead3ee 100644
--- a/src/mesa/drivers/dri/intel/intel_fbo.h
+++ b/src/mesa/drivers/dri/intel/intel_fbo.h
@@ -140,6 +140,10 @@ intel_create_wrapped_renderbuffer(struct gl_context * ctx,
int width, int height,
gl_format format);
+struct intel_renderbuffer *
+intel_create_fake_renderbuffer_wrapper(struct intel_context *intel,
+ struct gl_texture_image *image);
+
extern void
intel_fbo_init(struct intel_context *intel);
diff --git a/src/mesa/drivers/dri/intel/intel_tex_copy.c b/src/mesa/drivers/dri/intel/intel_tex_copy.c
index c9cbcf480d5..5acdb42c3ac 100644
--- a/src/mesa/drivers/dri/intel/intel_tex_copy.c
+++ b/src/mesa/drivers/dri/intel/intel_tex_copy.c
@@ -41,6 +41,9 @@
#include "intel_fbo.h"
#include "intel_tex.h"
#include "intel_blit.h"
+#ifndef I915
+#include "brw_context.h"
+#endif
#define FILE_DEBUG_FLAG DEBUG_TEXTURE
@@ -177,15 +180,28 @@ intelCopyTexSubImage(struct gl_context *ctx, GLuint dims,
GLint x, GLint y,
GLsizei width, GLsizei height)
{
- if (dims == 3 || !intel_copy_texsubimage(intel_context(ctx),
- intel_texture_image(texImage),
- xoffset, yoffset,
- intel_renderbuffer(rb), x, y, width, height)) {
- fallback_debug("%s - fallback to swrast\n", __FUNCTION__);
- _mesa_meta_CopyTexSubImage(ctx, dims, texImage,
- xoffset, yoffset, zoffset,
- rb, x, y, width, height);
+ struct intel_context *intel = intel_context(ctx);
+ if (dims != 3) {
+#ifndef I915
+ /* Try BLORP first. It can handle almost everything. */
+ if (brw_blorp_copytexsubimage(intel, rb, texImage, x, y,
+ xoffset, yoffset, width, height))
+ return;
+#endif
+
+ /* Next, try the BLT engine. */
+ if (intel_copy_texsubimage(intel_context(ctx),
+ intel_texture_image(texImage),
+ xoffset, yoffset,
+ intel_renderbuffer(rb), x, y, width, height))
+ return;
}
+
+ /* Finally, fall back to meta. This will likely be slow. */
+ fallback_debug("%s - fallback to swrast\n", __FUNCTION__);
+ _mesa_meta_CopyTexSubImage(ctx, dims, texImage,
+ xoffset, yoffset, zoffset,
+ rb, x, y, width, height);
}