intel: Try using glCopyTexSubImage2D in _mesa_meta_BlitFramebuffer
In the case where glBlitFramebuffer is being used to copy to a texture without scaling it is faster if we can use the hardware to do a blit rather than having to do a texture render. In most of the drivers glCopyTexSubImage2D will use a blit so this patch makes it check for when glBlitFramebuffer is doing a simple copy and then divert to glCopyTexSubImage2D. This was originally proposed as an extension to the common meta-ops. However, it was rejected as using the BLT is only advantageous for Intel hardware. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=33934 Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
This commit is contained in:
parent
11b9f4439c
commit
c0ad70ae31
|
@ -34,6 +34,7 @@
|
|||
#include "main/framebuffer.h"
|
||||
#include "main/renderbuffer.h"
|
||||
#include "main/context.h"
|
||||
#include "main/teximage.h"
|
||||
#include "main/texrender.h"
|
||||
#include "drivers/common/meta.h"
|
||||
|
||||
|
@ -647,6 +648,84 @@ intel_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to do a glBlitFramebuffer using glCopyTexSubImage2D
|
||||
* We can do this when the dst renderbuffer is actually a texture and
|
||||
* there is no scaling, mirroring or scissoring.
|
||||
*
|
||||
* \return new buffer mask indicating the buffers left to blit using the
|
||||
* normal path.
|
||||
*/
|
||||
static GLbitfield
|
||||
intel_blit_framebuffer_copy_tex_sub_image(struct gl_context *ctx,
|
||||
GLint srcX0, GLint srcY0,
|
||||
GLint srcX1, GLint srcY1,
|
||||
GLint dstX0, GLint dstY0,
|
||||
GLint dstX1, GLint dstY1,
|
||||
GLbitfield mask, GLenum filter)
|
||||
{
|
||||
if (mask & GL_COLOR_BUFFER_BIT) {
|
||||
const struct gl_framebuffer *drawFb = ctx->DrawBuffer;
|
||||
const struct gl_framebuffer *readFb = ctx->ReadBuffer;
|
||||
const struct gl_renderbuffer_attachment *drawAtt =
|
||||
&drawFb->Attachment[drawFb->_ColorDrawBufferIndexes[0]];
|
||||
|
||||
/* If the source and destination are the same size with no
|
||||
mirroring, the rectangles are within the size of the
|
||||
texture and there is no scissor then we can use
|
||||
glCopyTexSubimage2D to implement the blit. This will end
|
||||
up as a fast hardware blit on some drivers */
|
||||
if (drawAtt && drawAtt->Texture &&
|
||||
srcX0 - srcX1 == dstX0 - dstX1 &&
|
||||
srcY0 - srcY1 == dstY0 - dstY1 &&
|
||||
srcX1 >= srcX0 &&
|
||||
srcY1 >= srcY0 &&
|
||||
srcX0 >= 0 && srcX1 <= readFb->Width &&
|
||||
srcY0 >= 0 && srcY1 <= readFb->Height &&
|
||||
dstX0 >= 0 && dstX1 <= drawFb->Width &&
|
||||
dstY0 >= 0 && dstY1 <= drawFb->Height &&
|
||||
!ctx->Scissor.Enabled) {
|
||||
const struct gl_texture_object *texObj = drawAtt->Texture;
|
||||
const GLuint dstLevel = drawAtt->TextureLevel;
|
||||
const GLenum target = texObj->Target;
|
||||
|
||||
struct gl_texture_image *texImage =
|
||||
_mesa_select_tex_image(ctx, texObj, target, dstLevel);
|
||||
GLenum internalFormat = texImage->InternalFormat;
|
||||
|
||||
if (intel_copy_texsubimage(intel_context(ctx), target,
|
||||
intel_texture_image(texImage),
|
||||
internalFormat,
|
||||
dstX0, dstY0,
|
||||
srcX0, srcY0,
|
||||
srcX1 - srcX0, /* width */
|
||||
srcY1 - srcY0))
|
||||
mask &= ~GL_COLOR_BUFFER_BIT;
|
||||
}
|
||||
}
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
static void
|
||||
intel_blit_framebuffer(struct gl_context *ctx,
|
||||
GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
|
||||
GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
|
||||
GLbitfield mask, GLenum filter)
|
||||
{
|
||||
/* Try faster, glCopyTexSubImage2D approach first which uses the BLT. */
|
||||
mask = intel_blit_framebuffer_copy_tex_sub_image(ctx,
|
||||
srcX0, srcY0, srcX1, srcY1,
|
||||
dstX0, dstY0, dstX1, dstY1,
|
||||
mask, filter);
|
||||
if (mask == 0x0)
|
||||
return;
|
||||
|
||||
_mesa_meta_BlitFramebuffer(ctx,
|
||||
srcX0, srcY0, srcX1, srcY1,
|
||||
dstX0, dstY0, dstX1, dstY1,
|
||||
mask, filter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Do one-time context initializations related to GL_EXT_framebuffer_object.
|
||||
|
@ -663,7 +742,7 @@ intel_fbo_init(struct intel_context *intel)
|
|||
intel->ctx.Driver.FinishRenderTexture = intel_finish_render_texture;
|
||||
intel->ctx.Driver.ResizeBuffers = intel_resize_buffers;
|
||||
intel->ctx.Driver.ValidateFramebuffer = intel_validate_framebuffer;
|
||||
intel->ctx.Driver.BlitFramebuffer = _mesa_meta_BlitFramebuffer;
|
||||
intel->ctx.Driver.BlitFramebuffer = intel_blit_framebuffer;
|
||||
|
||||
#if FEATURE_OES_EGL_image
|
||||
intel->ctx.Driver.EGLImageTargetRenderbufferStorage =
|
||||
|
|
|
@ -65,4 +65,12 @@ void intel_tex_unmap_images(struct intel_context *intel,
|
|||
|
||||
int intel_compressed_num_bytes(GLuint mesaFormat);
|
||||
|
||||
GLboolean intel_copy_texsubimage(struct intel_context *intel,
|
||||
GLenum target,
|
||||
struct intel_texture_image *intelImage,
|
||||
GLenum internalFormat,
|
||||
GLint dstx, GLint dsty,
|
||||
GLint x, GLint y,
|
||||
GLsizei width, GLsizei height);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -67,13 +67,13 @@ get_teximage_readbuffer(struct intel_context *intel, GLenum internalFormat)
|
|||
}
|
||||
|
||||
|
||||
static GLboolean
|
||||
do_copy_texsubimage(struct intel_context *intel,
|
||||
GLenum target,
|
||||
struct intel_texture_image *intelImage,
|
||||
GLenum internalFormat,
|
||||
GLint dstx, GLint dsty,
|
||||
GLint x, GLint y, GLsizei width, GLsizei height)
|
||||
GLboolean
|
||||
intel_copy_texsubimage(struct intel_context *intel,
|
||||
GLenum target,
|
||||
struct intel_texture_image *intelImage,
|
||||
GLenum internalFormat,
|
||||
GLint dstx, GLint dsty,
|
||||
GLint x, GLint y, GLsizei width, GLsizei height)
|
||||
{
|
||||
struct gl_context *ctx = &intel->ctx;
|
||||
struct intel_renderbuffer *irb;
|
||||
|
@ -191,9 +191,9 @@ intelCopyTexImage1D(struct gl_context * ctx, GLenum target, GLint level,
|
|||
&width, &height))
|
||||
return;
|
||||
|
||||
if (!do_copy_texsubimage(intel_context(ctx), target,
|
||||
intel_texture_image(texImage),
|
||||
internalFormat, 0, 0, x, y, width, height))
|
||||
if (!intel_copy_texsubimage(intel_context(ctx), target,
|
||||
intel_texture_image(texImage),
|
||||
internalFormat, 0, 0, x, y, width, height))
|
||||
goto fail;
|
||||
|
||||
return;
|
||||
|
@ -239,9 +239,9 @@ intelCopyTexImage2D(struct gl_context * ctx, GLenum target, GLint level,
|
|||
&width, &height))
|
||||
return;
|
||||
|
||||
if (!do_copy_texsubimage(intel_context(ctx), target,
|
||||
intel_texture_image(texImage),
|
||||
internalFormat, 0, 0, x, y, width, height))
|
||||
if (!intel_copy_texsubimage(intel_context(ctx), target,
|
||||
intel_texture_image(texImage),
|
||||
internalFormat, 0, 0, x, y, width, height))
|
||||
goto fail;
|
||||
|
||||
return;
|
||||
|
@ -269,9 +269,9 @@ intelCopyTexSubImage1D(struct gl_context * ctx, GLenum target, GLint level,
|
|||
/* Need to check texture is compatible with source format.
|
||||
*/
|
||||
|
||||
if (!do_copy_texsubimage(intel_context(ctx), target,
|
||||
intel_texture_image(texImage),
|
||||
internalFormat, xoffset, 0, x, y, width, 1)) {
|
||||
if (!intel_copy_texsubimage(intel_context(ctx), target,
|
||||
intel_texture_image(texImage),
|
||||
internalFormat, xoffset, 0, x, y, width, 1)) {
|
||||
fallback_debug("%s - fallback to swrast\n", __FUNCTION__);
|
||||
_mesa_meta_CopyTexSubImage1D(ctx, target, level, xoffset, x, y, width);
|
||||
}
|
||||
|
@ -293,11 +293,10 @@ intelCopyTexSubImage2D(struct gl_context * ctx, GLenum target, GLint level,
|
|||
/* Need to check texture is compatible with source format.
|
||||
*/
|
||||
|
||||
if (!do_copy_texsubimage(intel_context(ctx), target,
|
||||
intel_texture_image(texImage),
|
||||
internalFormat,
|
||||
xoffset, yoffset, x, y, width, height)) {
|
||||
|
||||
if (!intel_copy_texsubimage(intel_context(ctx), target,
|
||||
intel_texture_image(texImage),
|
||||
internalFormat,
|
||||
xoffset, yoffset, x, y, width, height)) {
|
||||
fallback_debug("%s - fallback to swrast\n", __FUNCTION__);
|
||||
_mesa_meta_CopyTexSubImage2D(ctx, target, level,
|
||||
xoffset, yoffset, x, y, width, height);
|
||||
|
|
Loading…
Reference in New Issue