Similar to the mechanism used by ReadPixels, use blorp for better format handling than the existing blitter-only paths. --- src/mesa/drivers/dri/i965/intel_pixel.c | 5 - src/mesa/drivers/dri/i965/intel_pixel.h | 9 +- src/mesa/drivers/dri/i965/intel_pixel_bitmap.c | 3 + src/mesa/drivers/dri/i965/intel_pixel_draw.c | 122 ++-------------- src/mesa/drivers/dri/i965/intel_pixel_pbo.c | 192 +++++++++++++++++++++++++ 5 files changed, 216 insertions(+), 115 deletions(-)
diff --git a/src/mesa/drivers/dri/i965/intel_pixel.c b/src/mesa/drivers/dri/i965/intel_pixel.c index c69c3cc7dc..e3b6e749f4 100644 --- a/src/mesa/drivers/dri/i965/intel_pixel.c +++ b/src/mesa/drivers/dri/i965/intel_pixel.c @@ -113,11 +113,6 @@ 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.h b/src/mesa/drivers/dri/i965/intel_pixel.h index c3d90d3297..0cdd773bfa 100644 --- a/src/mesa/drivers/dri/i965/intel_pixel.h +++ b/src/mesa/drivers/dri/i965/intel_pixel.h @@ -30,7 +30,7 @@ void intelInitPixelFuncs(struct dd_function_table *functions); bool intel_check_blit_fragment_ops(struct gl_context * ctx, - bool src_alpha_is_one); + bool src_alpha_is_one); void intelReadPixels(struct gl_context * ctx, GLint x, GLint y, @@ -65,4 +65,11 @@ bool intel_readpixels_pbo(struct gl_context * ctx, const struct gl_pixelstore_attrib *pack, GLvoid *pixels); +bool intel_drawpixels_pbo(struct gl_context *ctx, + GLint x, GLint y, + GLsizei width, GLsizei height, + GLenum format, GLenum type, + const struct gl_pixelstore_attrib *pack, + const GLvoid *pixels); + #endif diff --git a/src/mesa/drivers/dri/i965/intel_pixel_bitmap.c b/src/mesa/drivers/dri/i965/intel_pixel_bitmap.c index 8d467adc56..fafb4c99a7 100644 --- a/src/mesa/drivers/dri/i965/intel_pixel_bitmap.c +++ b/src/mesa/drivers/dri/i965/intel_pixel_bitmap.c @@ -242,6 +242,9 @@ do_blit_bitmap( struct gl_context *ctx, if (!intel_check_blit_fragment_ops(ctx, tmpColor[3] == 1.0F)) return false; + if (ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F) + return false; + /* Clip to buffer bounds and scissor. */ if (!_mesa_clip_to_region(fb->_Xmin, fb->_Ymin, fb->_Xmax, fb->_Ymax, diff --git a/src/mesa/drivers/dri/i965/intel_pixel_draw.c b/src/mesa/drivers/dri/i965/intel_pixel_draw.c index 519e059672..12a7a57937 100644 --- a/src/mesa/drivers/dri/i965/intel_pixel_draw.c +++ b/src/mesa/drivers/dri/i965/intel_pixel_draw.c @@ -47,101 +47,6 @@ #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; - struct brw_bo *src_buffer; - - DBG("%s\n", __func__); - - if (!intel_check_blit_fragment_ops(ctx, false)) - return false; - - if (ctx->DrawBuffer->_NumColorDrawBuffers != 1) { - DBG("%s: fallback due to MRT\n", __func__); - return false; - } - - intel_prepare_render(brw); - - struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[0]; - struct intel_renderbuffer *irb = intel_renderbuffer(rb); - - mesa_format src_format = _mesa_format_from_format_and_type(format, type); - if (_mesa_format_is_mesa_array_format(src_format)) - src_format = _mesa_format_from_array_format(src_format); - mesa_format dst_format = irb->mt->format; - - /* We can safely discard sRGB encode/decode for the DrawPixels interface */ - src_format = _mesa_get_srgb_format_linear(src_format); - dst_format = _mesa_get_srgb_format_linear(dst_format); - - if (!intel_miptree_blit_compatible_formats(src_format, dst_format)) { - DBG("%s: bad format for blit\n", __func__); - return false; - } - - if (unpack->SwapBytes || unpack->LsbFirst || - unpack->SkipPixels || unpack->SkipRows) { - DBG("%s: bad packing params\n", __func__); - 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); - - src_buffer = intel_bufferobj_buffer(brw, src, src_offset, - height * src_stride, false); - - struct intel_mipmap_tree *pbo_mt = - intel_miptree_create_for_bo(brw, - src_buffer, - irb->mt->format, - src_offset, - width, height, 1, - src_stride, - 0); - 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", __func__); - intel_miptree_release(&pbo_mt); - return false; - } - - intel_miptree_release(&pbo_mt); - - if (ctx->Query.CurrentOcclusionObject) - ctx->Query.CurrentOcclusionObject->Result += width * height; - - DBG("%s: success\n", __func__); - return true; -} - void intelDrawPixels(struct gl_context * ctx, GLint x, GLint y, @@ -156,21 +61,20 @@ intelDrawPixels(struct gl_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; - } + intel_prepare_render(brw); - if (_mesa_is_bufferobj(unpack->BufferObj)) { - if (do_blit_drawpixels(ctx, x, y, width, height, format, type, unpack, - pixels)) { - return; - } + if (intel_drawpixels_pbo(ctx, + x, y, width, height, + format, type, unpack, pixels)) + return; - perf_debug("%s: fallback to generic code in PBO case\n", __func__); - } + perf_debug("%s: fallback to generic code%s\n", + __func__, _mesa_is_bufferobj(unpack->BufferObj) ? " for PBO" :""); - _mesa_meta_DrawPixels(ctx, x, y, width, height, format, type, - unpack, pixels); + if (format == GL_STENCIL_INDEX) + _swrast_DrawPixels(ctx, x, y, width, height, + format, type, unpack, pixels); + else + _mesa_meta_DrawPixels(ctx, x, y, width, height, + format, type, unpack, pixels); } diff --git a/src/mesa/drivers/dri/i965/intel_pixel_pbo.c b/src/mesa/drivers/dri/i965/intel_pixel_pbo.c index 4e212ee92f..a503481148 100644 --- a/src/mesa/drivers/dri/i965/intel_pixel_pbo.c +++ b/src/mesa/drivers/dri/i965/intel_pixel_pbo.c @@ -21,6 +21,7 @@ * IN THE SOFTWARE. */ +#include "main/blend.h" #include "main/enums.h" #include "main/mtypes.h" #include "main/macros.h" @@ -250,3 +251,194 @@ err_dst_buffer: brw_bo_unreference(dst_buffer); return ok; } + +bool +intel_drawpixels_pbo(struct gl_context *ctx, + GLint x, GLint y, + GLsizei width, GLsizei height, + GLenum format, GLenum type, + const struct gl_pixelstore_attrib *pack, + const GLvoid *pixels) +{ + struct brw_context *brw = brw_context(ctx); + bool ok = false; + + if (!intel_check_blit_fragment_ops(ctx, false)) + return false; + + struct gl_renderbuffer *rb; + switch (format) { + case GL_STENCIL_INDEX: + rb = ctx->ReadBuffer->Attachment[BUFFER_STENCIL].Renderbuffer; + break; + case GL_DEPTH_COMPONENT: + case GL_DEPTH_STENCIL_EXT: + rb = ctx->ReadBuffer->Attachment[BUFFER_DEPTH].Renderbuffer; + break; + case GL_COLOR_INDEX: + rb = NULL; + break; + default: + if (ctx->DrawBuffer->_NumColorDrawBuffers != 1) { + DBG("%s: fallback due to MRT\n", __func__); + return false; + } + + if ((type == GL_FLOAT || type == GL_HALF_FLOAT) && + _mesa_get_clamp_fragment_color(ctx, ctx->DrawBuffer)) { + return false; + } + + /* all other formats should be color formats */ + rb = ctx->DrawBuffer->_ColorReadBuffer; + break; + } + if (!rb) + return false; + + if (pack->SwapBytes || pack->LsbFirst) { + DBG("%s: bad packing params\n", __func__); + return false; + } + + struct intel_renderbuffer *irb = intel_renderbuffer(rb); + struct intel_mipmap_tree *dst = irb->mt; + if (format == GL_STENCIL_INDEX && dst->stencil_mt) + dst = dst->stencil_mt; + if (!brw->mesa_format_supports_render[dst->format]) + return false; + + if (need_signed_unsigned_int_conversion(dst->format, format, type)) + return false; + + mesa_format src_format = _mesa_format_from_format_and_type(format, type); + if (_mesa_format_is_mesa_array_format(src_format)) + src_format = _mesa_format_from_array_format(src_format); + src_format = _mesa_get_srgb_format_linear(src_format); + + if (!brw->screen->mesa_format_supports_texture[src_format]) + return false; + + if (_mesa_need_rgb_to_luminance_conversion(format, rb->_BaseFormat)) + return false; + + bool src_flip = false; + int src_stride = _mesa_image_row_stride(pack, width, format, type); + if (pack->Invert) { + src_stride = -src_stride; + src_flip = true; + } + + int bpp = _mesa_bytes_per_pixel(format, type); + pixels += pack->SkipRows * src_stride + pack->SkipPixels * bpp; + int src_size = src_stride * (height - 1) + width * bpp; + assert(src_stride % bpp == 0); + + struct brw_bo *src_buffer; + int src_offset; + if (_mesa_is_bufferobj(pack->BufferObj)) { + src_offset = (GLintptr)pixels; + src_buffer = intel_bufferobj_buffer(brw, + intel_buffer_object(pack->BufferObj), + src_offset, + src_size, + true); + } else if (brw_bo_busy(dst->bo)) { + src_offset = 0; + src_buffer = brw_bo_alloc(brw->bufmgr, "drawpixels", src_size, 0); + if (!src_buffer) + return false; + + void *map = brw_bo_map(brw, src_buffer, MAP_WRITE); + if (!map) + goto err_src_buffer; + + memcpy(map, pixels, src_size); + brw_bo_unmap(src_buffer); + } else { + src_offset = (GLintptr)pixels & 4095; + src_buffer = brw_bo_alloc_userptr(brw->bufmgr, "drawpixels(userptr)", + (void *)((GLintptr)pixels & -4096), + ALIGN(src_size + src_offset, 4096), 0); + } + if (!src_buffer) + return false; + + struct intel_mipmap_tree *src = + intel_miptree_create_for_bo(brw, + src_buffer, + src_format, + src_offset, + width, height, 1, + src_stride, + MIPTREE_LAYOUT_FOR_TEXTURE | + MIPTREE_LAYOUT_TILING_NONE | + MIPTREE_LAYOUT_DISABLE_AUX); + if (!src) + goto err_src_buffer; + + if (!rb->Name) { + src_flip = !src_flip; + y = rb->Height - y - height; + } + + assert(src->surf.tiling == ISL_TILING_LINEAR); + if (ctx->Pixel.ZoomX != 1. || ctx->Pixel.ZoomY != 1. || + !intel_miptree_blit(brw, + src, 0, 0, 0, 0, src_flip, + dst, irb->mt_level, irb->mt_layer, x, y, false, + width, height, GL_COPY)) { + mesa_format dst_format = irb->Base.Base.Format; + + /* blorp restrictions; see try_blorp_blit() */ + switch (format) { + case GL_STENCIL_INDEX: + if (src_format != dst_format) + goto err_src_mt; + + /* fallthrough */ + case GL_DEPTH_COMPONENT: + case GL_DEPTH_STENCIL_EXT: + if ((src_format == MESA_FORMAT_Z24_UNORM_X8_UINT) != + (dst_format == MESA_FORMAT_Z24_UNORM_X8_UINT)) + goto err_src_mt; + + if (_mesa_get_format_base_format(src_format) == GL_DEPTH_STENCIL || + _mesa_get_format_base_format(dst_format) == GL_DEPTH_STENCIL) + goto err_src_mt; + + src_format = MESA_FORMAT_NONE; + dst_format = MESA_FORMAT_NONE; + break; + + default: + break; + } + + brw_blorp_blit_miptrees(brw, + src, 0, 0, src_format, SWIZZLE_XYZW, + dst, irb->mt_level, irb->mt_layer, dst_format, + 0, 0, width, height, + x, y, + x + width * ctx->Pixel.ZoomX, + y + height * ctx->Pixel.ZoomY, + GL_NEAREST, false, src_flip, + false, false); + } + + if (src_buffer->userptr) { + intel_batchbuffer_flush(brw); + brw_bo_wait_rendering(src_buffer); + } + + if (ctx->Query.CurrentOcclusionObject) + ctx->Query.CurrentOcclusionObject->Result += width * height; + + ok = true; +err_src_mt: + intel_miptree_release(&src); +err_src_buffer: + if (!_mesa_is_bufferobj(pack->BufferObj)) + brw_bo_unreference(src_buffer); + return ok; +} -- 2.13.3 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev