From 279e8d264109303f0e8248ab4c3703c71f65983f Mon Sep 17 00:00:00 2001 From: Alexander Monakov Date: Mon, 4 Nov 2013 01:34:32 +0400 Subject: [PATCH] i965: implement blit path for PBO glDrawPixels This patch implements accelerated path for glDrawPixels from a PBO in i965. The code follows what intel_pixel_read, intel_pixel_copy, intel_pixel_bitmap and intel_tex_image are doing. Piglit quick.tests show no regressions. In my testing on IVB, performance improvement is huge (about 30x, didn't measure exactly) since generic path goes via _mesa_unpack_color_span_float, memcpy, extract_float_rgba. Signed-off-by: Alexander Monakov Reviewed-by: Kenneth Graunke --- src/mesa/drivers/dri/i965/intel_pixel.c | 5 + src/mesa/drivers/dri/i965/intel_pixel_draw.c | 115 +++++++++++++++++++ 2 files changed, 120 insertions(+) diff --git a/src/mesa/drivers/dri/i965/intel_pixel.c b/src/mesa/drivers/dri/i965/intel_pixel.c index 623f4f46fdc..fc70381a969 100644 --- a/src/mesa/drivers/dri/i965/intel_pixel.c +++ b/src/mesa/drivers/dri/i965/intel_pixel.c @@ -115,6 +115,11 @@ 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_draw.c b/src/mesa/drivers/dri/i965/intel_pixel_draw.c index af618a29ad2..477586e1f05 100644 --- a/src/mesa/drivers/dri/i965/intel_pixel_draw.c +++ b/src/mesa/drivers/dri/i965/intel_pixel_draw.c @@ -29,14 +29,115 @@ #include "main/enums.h" #include "main/image.h" #include "main/mtypes.h" +#include "main/condrender.h" +#include "main/fbobject.h" #include "main/teximage.h" #include "main/texobj.h" #include "main/texstate.h" +#include "main/bufferobj.h" #include "swrast/swrast.h" #include "drivers/common/meta.h" #include "brw_context.h" +#include "intel_screen.h" +#include "intel_blit.h" +#include "intel_buffers.h" +#include "intel_fbo.h" +#include "intel_mipmap_tree.h" +#include "intel_regions.h" #include "intel_pixel.h" +#include "intel_buffer_objects.h" + +#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; + drm_intel_bo *src_buffer; + + DBG("%s\n", __FUNCTION__); + + if (!intel_check_blit_fragment_ops(ctx, false)) + return false; + + if (ctx->DrawBuffer->_NumColorDrawBuffers != 1) { + DBG("%s: fallback due to MRT\n", __FUNCTION__); + return false; + } + + struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[0]; + struct intel_renderbuffer *irb = intel_renderbuffer(rb); + + if (!_mesa_format_matches_format_and_type(irb->mt->format, format, type, + false)) { + DBG("%s: bad format for blit\n", __FUNCTION__); + return false; + } + + if (unpack->SwapBytes || unpack->LsbFirst || + unpack->SkipPixels || unpack->SkipRows) { + DBG("%s: bad packing params\n", __FUNCTION__); + 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); + + intel_prepare_render(brw); + + src_buffer = intel_bufferobj_buffer(brw, src, + src_offset, width * height * + irb->mt->cpp); + + struct intel_mipmap_tree *pbo_mt = + intel_miptree_create_for_bo(brw, + src_buffer, + irb->mt->format, + src_offset, + width, height, + src_stride, I915_TILING_NONE); + 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", __FUNCTION__); + intel_miptree_release(&pbo_mt); + return false; + } + + intel_miptree_release(&pbo_mt); + + if (ctx->Query.CurrentOcclusionObject) + ctx->Query.CurrentOcclusionObject->Result += width * height; + + intel_check_front_buffer_rendering(brw); + + DBG("%s: success\n", __FUNCTION__); + return true; +} void intelDrawPixels(struct gl_context * ctx, @@ -47,12 +148,26 @@ intelDrawPixels(struct gl_context * ctx, const struct gl_pixelstore_attrib *unpack, const GLvoid * pixels) { + struct brw_context *brw = brw_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; } + if (_mesa_is_bufferobj(unpack->BufferObj)) { + if (do_blit_drawpixels(ctx, x, y, width, height, format, type, unpack, + pixels)) { + return; + } + + perf_debug("%s: fallback to generic code in PBO case\n", __FUNCTION__); + } + _mesa_meta_DrawPixels(ctx, x, y, width, height, format, type, unpack, pixels); } -- 2.30.2