diff options
-rw-r--r-- | src/mesa/drivers/dri/i965/brw_blorp_blit.cpp | 88 | ||||
-rw-r--r-- | src/mesa/drivers/dri/i965/brw_context.h | 8 | ||||
-rw-r--r-- | src/mesa/drivers/dri/intel/intel_fbo.c | 30 | ||||
-rw-r--r-- | src/mesa/drivers/dri/intel/intel_fbo.h | 4 | ||||
-rw-r--r-- | src/mesa/drivers/dri/intel/intel_tex_copy.c | 32 |
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); } |