On Tue, Jan 31, 2017 at 06:13:45PM +0200, Topi Pohjolainen wrote: > v2: > - Fix return value (s/MESA_FORMAT_NONE/false/) (Anuj) > - Move _mesa_tex_format_from_format_and_type() just > in the end avoiding additional if-block (Anuj) > - Explain better the array alignment restriction (Anuj) > - Do not bail out in case of gl_pixelstore_attrib::ImageHeight, > it is handled by _mesa_image_offset() automatically (Ken).
This is actually wrong. I missed to take the adjusted height into account when iterating over individual layers. It looks that we are missing tests for this as I didn't regress anything. > - Support 1D_ARRAY by flipping depth, width and y, z (Ken). > > CC: Kenneth Graunke <kenn...@whitecape.org> > CC: Anuj Phogat <anuj.pho...@gmail.com> > 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 | 186 > +++++++++++++++++++++++++ > 2 files changed, 194 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 57c4c38..43e816b 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_fbo.h" > #include "intel_tex.h" > #include "intel_mipmap_tree.h" > @@ -44,6 +47,189 @@ > > #define FILE_DEBUG_FLAG DEBUG_TEXTURE > > +static drm_intel_bo * > +intel_texsubimage_get_src_as_bo(struct brw_context *brw, unsigned dims, > + 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) > +{ > + 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; > + } > + > + 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; > + } > + > + 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 _mesa_tex_format_from_format_and_type(&brw->ctx, format, type); > +} > + > +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 false; > + > + drm_intel_bo * const src_bo = is_src_bo ? > + intel_buffer_object(packing->BufferObj)->buffer : > + intel_texsubimage_get_src_as_bo(brw, dims, w, h, d, format, type, > + pixels, packing); > + if (src_bo == NULL) > + return false; > + > + const uint32_t offset = is_src_bo ? > + intel_texsubimage_get_src_offset(dims, w, h, format, type, pixels, > + packing) : 0; > + > + /* Now that source is offset to correct starting point, adjust the > + * given dimensions to treat 1D arrays as 2D. > + */ > + if (tex_image->TexObject->Target == GL_TEXTURE_1D_ARRAY) { > + assert(d == 1); > + assert(z == 0); > + d = h; > + h = 1; > + z = y; > + y = 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); > + > + bool result = false; > + > + /* Blit slice-by-slice creating a single-slice miptree for each layer. > Even > + * in case of linear buffers hardware wants image arrays to be aligned by > + * four rows. This way hardware only gets one image at a time and any > + * source alignment will do. > + */ > + for (unsigned i = 0; i < d; ++i) { > + 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