Signed-off-by: Topi Pohjolainen <topi.pohjolai...@intel.com> --- src/mesa/drivers/dri/i965/intel_tex.h | 8 + src/mesa/drivers/dri/i965/intel_tex_subimage.c | 194 +++++++++++++++++++++++++ 2 files changed, 202 insertions(+)
diff --git a/src/mesa/drivers/dri/i965/intel_tex.h b/src/mesa/drivers/dri/i965/intel_tex.h index 376f075..c7d0937 100644 --- a/src/mesa/drivers/dri/i965/intel_tex.h +++ b/src/mesa/drivers/dri/i965/intel_tex.h @@ -65,6 +65,14 @@ intel_texsubimage_tiled_memcpy(struct gl_context *ctx, bool for_glTexImage); bool +intel_texsubimage_gpu_copy(struct brw_context *brw, GLuint dims, + struct gl_texture_image *tex_image, + unsigned x, unsigned y, unsigned z, + unsigned w, unsigned h, unsigned d, + GLenum format, GLenum type, const void *pixels, + const struct gl_pixelstore_attrib *packing); + +bool intel_gettexsubimage_tiled_memcpy(struct gl_context *ctx, struct gl_texture_image *texImage, GLint xoffset, GLint yofset, diff --git a/src/mesa/drivers/dri/i965/intel_tex_subimage.c b/src/mesa/drivers/dri/i965/intel_tex_subimage.c index b7e52bc..f999a93 100644 --- a/src/mesa/drivers/dri/i965/intel_tex_subimage.c +++ b/src/mesa/drivers/dri/i965/intel_tex_subimage.c @@ -24,6 +24,7 @@ */ #include "main/bufferobj.h" +#include "main/glformats.h" #include "main/image.h" #include "main/macros.h" #include "main/mtypes.h" @@ -34,8 +35,10 @@ #include "main/enums.h" #include "drivers/common/meta.h" +#include "brw_blorp.h" #include "brw_context.h" #include "intel_batchbuffer.h" +#include "intel_buffer_objects.h" #include "intel_tex.h" #include "intel_mipmap_tree.h" #include "intel_blit.h" @@ -43,6 +46,197 @@ #define FILE_DEBUG_FLAG DEBUG_TEXTURE +static drm_intel_bo * +intel_texsubimage_get_src_as_bo(struct brw_context *brw, unsigned dims, + struct gl_texture_image *tex_image, + unsigned w, unsigned h, unsigned d, + GLenum format, GLenum type, const void *pixels, + const struct gl_pixelstore_attrib *packing) +{ + /* Account for SKIP_PIXELS, SKIP_ROWS, ALIGNMENT, and SKIP_IMAGES */ + const uint32_t first_pixel = _mesa_image_offset(dims, packing, w, h, + format, type, 0, 0, 0); + const uint32_t last_pixel = _mesa_image_offset(dims, packing, w, h, + format, type, + d - 1, h - 1, w); + const uint32_t size = last_pixel - first_pixel; + + drm_intel_bo * const bo = + drm_intel_bo_alloc(brw->bufmgr, "tmp_tex_subimage_src", size, 64); + + if (bo == NULL) { + perf_debug("intel_texsubimage: temp bo creation failed: size = %u\n", + size); + return false; + } + + if (drm_intel_bo_subdata(bo, 0, size, pixels + first_pixel)) { + perf_debug("intel_texsubimage: temp bo upload failed\n"); + drm_intel_bo_unreference(bo); + return NULL; + } + + return bo; +} + +static uint32_t +intel_texsubimage_get_src_offset(unsigned dims, unsigned w, unsigned h, + GLenum format, GLenum type, + const void *pixels, + const struct gl_pixelstore_attrib *packing) +{ + /* Account for SKIP_PIXELS, SKIP_ROWS, ALIGNMENT, and SKIP_IMAGES */ + const uint32_t first_pixel = _mesa_image_offset(dims, packing, w, h, + format, type, 0, 0, 0); + + /* In case of buffer object source 'pixels' represents offset in bytes. */ + return first_pixel + (intptr_t)pixels; +} + +/* Consider all the restrictions and determine the format of the source. */ +static mesa_format +intel_texsubimage_check_upload(struct brw_context *brw, + const struct gl_texture_image *tex_image, + unsigned h, GLenum format, GLenum type, + const struct gl_pixelstore_attrib *packing) +{ + /* TODO: Add support for buffer object upload 1D alignment or perhaps use + * flat 2D source. + */ + if (tex_image->TexObject->Target == GL_TEXTURE_1D_ARRAY) { + perf_debug("intel_texsubimage: 1D_ARRAY not supported\n"); + return MESA_FORMAT_NONE; + } + + if (brw->ctx._ImageTransferState) + return MESA_FORMAT_NONE; + + if (packing->SwapBytes || packing->LsbFirst || packing->Invert) { + perf_debug("intel_texsubimage: unsupported gl_pixelstore_attrib\n"); + return MESA_FORMAT_NONE; + } + + /* TODO: This can be easily supported as blit manually offsets miptree + * for each slice. + */ + if (packing->ImageHeight != 0) { + perf_debug("intel_texsubimage: _attrib::ImageHeight not supported\n"); + return MESA_FORMAT_NONE; + } + + if (packing->RowLength != 0) { + perf_debug("intel_texsubimage: _attrib::RowLength not supported\n"); + return MESA_FORMAT_NONE; + } + + if (format != GL_RED && + format != GL_RG && + format != GL_RGB && + format != GL_RGBA && + format != GL_ALPHA) { + perf_debug("intel_texsubimage: %s not supported", + _mesa_enum_to_string(format)); + return MESA_FORMAT_NONE; + } + + const mesa_format src_mesa_format = + _mesa_tex_format_from_format_and_type(&brw->ctx, format, type); + if (src_mesa_format == MESA_FORMAT_NONE) + return MESA_FORMAT_NONE; + + if (!brw->format_supported_as_render_target[tex_image->TexFormat]) { + perf_debug("intel_texsubimage: can't use %s as render target\n", + _mesa_get_format_name(tex_image->TexFormat)); + return MESA_FORMAT_NONE; + } + + return src_mesa_format; +} + +bool +intel_texsubimage_gpu_copy(struct brw_context *brw, GLuint dims, + struct gl_texture_image *tex_image, + unsigned x, unsigned y, unsigned z, + unsigned w, unsigned h, unsigned d, + GLenum format, GLenum type, const void *pixels, + const struct gl_pixelstore_attrib *packing) +{ + const bool is_src_bo = _mesa_is_bufferobj(packing->BufferObj); + struct intel_texture_image *intel_image = intel_texture_image(tex_image); + + /* Make sure there is something to upload. */ + if (pixels == NULL && !is_src_bo) + return false; + + const mesa_format src_mesa_format = intel_texsubimage_check_upload( + brw, tex_image, h, format, type, packing); + if (src_mesa_format == MESA_FORMAT_NONE) + return MESA_FORMAT_NONE; + + const uint32_t offset = is_src_bo ? + intel_texsubimage_get_src_offset(dims, w, h, format, type, pixels, + packing) : 0; + const uint32_t stride = _mesa_image_row_stride(packing, w, format, type); + const unsigned level = tex_image->Level + tex_image->TexObject->MinLevel; + const unsigned start_layer = + tex_image->TexObject->MinLayer + tex_image->Face + z; + + assert(level <= intel_image->mt->last_level); + assert(start_layer + d <= intel_image->mt->level[level].depth); + + drm_intel_bo * const src_bo = is_src_bo ? + intel_buffer_object(packing->BufferObj)->buffer : + intel_texsubimage_get_src_as_bo(brw, dims, tex_image, w, h, d, + format, type, pixels, packing); + if (src_bo == NULL) + return false; + + bool result = false; + + /* Blit slice-by-slice creating a single-slice miptree for each layer. This + * way the alignment in the source buffer object does not need to meet the + * hw requirements. + */ + for (unsigned i = 0; i < d; ++i) { + /* Wrap the source buffer object with a miptree. */ + struct intel_mipmap_tree *src_mt = intel_miptree_create_for_bo( + brw, src_bo, src_mesa_format, + offset + i * h * stride, + w, h, 1, stride, 0); + if (!src_mt) { + perf_debug("intel_texsubimage: miptree creation for src failed\n"); + goto err; + } + + /* In case exact match is needed, copy using equivalent UINT formats + * preventing hardware from changing presentation for SNORM -1. + */ + if (src_mt->format == intel_image->mt->format) { + brw_blorp_copy_miptrees(brw, src_mt, 0, 0, + intel_image->mt, level, start_layer + i, + 0, 0, x, y, w, h); + } else { + brw_blorp_blit_miptrees(brw, src_mt, 0, 0, + src_mesa_format, SWIZZLE_XYZW, + intel_image->mt, level, start_layer + i, + intel_image->mt->format, + 0, 0, w, h, + x, y, x + w, y + h, + GL_NEAREST, false, false, false, false); + } + + intel_miptree_release(&src_mt); + } + + result = true; + +err: + if (!is_src_bo) + drm_intel_bo_unreference(src_bo); + + return result; +} + /** * \brief A fast path for glTexImage and glTexSubImage. * -- 2.5.5 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev