X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fstate_tracker%2Fst_cb_texture.c;h=7f07b741ee0e81908a327b3f3ce5afcc11d978d0;hb=f26eb36e8bc17b0ff047f114538bd2485c6a52ea;hp=f06814f9cd326db7abb1af2f46877f5c39492eb9;hpb=6dd839f23a8ee7b6853f7320a2715df44040b358;p=mesa.git diff --git a/src/mesa/state_tracker/st_cb_texture.c b/src/mesa/state_tracker/st_cb_texture.c index f06814f9cd3..7f07b741ee0 100644 --- a/src/mesa/state_tracker/st_cb_texture.c +++ b/src/mesa/state_tracker/st_cb_texture.c @@ -48,6 +48,7 @@ #include "state_tracker/st_cb_fbo.h" #include "state_tracker/st_cb_flush.h" #include "state_tracker/st_cb_texture.h" +#include "state_tracker/st_cb_bufferobjects.h" #include "state_tracker/st_format.h" #include "state_tracker/st_texture.h" #include "state_tracker/st_gen_mipmap.h" @@ -200,7 +201,7 @@ st_MapTextureImage(struct gl_context *ctx, if (mode & GL_MAP_INVALIDATE_RANGE_BIT) pipeMode |= PIPE_TRANSFER_DISCARD_RANGE; - map = st_texture_image_map(st, stImage, slice, pipeMode, x, y, w, h); + map = st_texture_image_map(st, stImage, pipeMode, x, y, slice, w, h, 1); if (map) { *mapOut = map; *rowStrideOut = stImage->transfer->stride; @@ -571,37 +572,68 @@ decompress_with_blit(struct gl_context * ctx, { struct st_context *st = st_context(ctx); struct pipe_context *pipe = st->pipe; - struct st_texture_image *stImage = st_texture_image(texImage); - struct st_texture_object *stObj = st_texture_object(texImage->TexObject); + struct pipe_screen *screen = pipe->screen; const GLuint width = texImage->Width; const GLuint height = texImage->Height; - struct pipe_resource *dst_texture; + const GLuint depth = texImage->Depth; + struct pipe_resource *src = st_texture_object(texImage->TexObject)->pt; + struct pipe_resource *dst; + struct pipe_resource dst_templ; + enum pipe_format pipe_format; + gl_format mesa_format; + GLenum gl_target = texImage->TexObject->Target; + enum pipe_texture_target pipe_target; struct pipe_blit_info blit; unsigned bind = (PIPE_BIND_RENDER_TARGET | PIPE_BIND_TRANSFER_READ); struct pipe_transfer *tex_xfer; ubyte *map; - /* create temp / dest surface */ - if (!util_create_rgba_texture(pipe, width, height, bind, - &dst_texture)) { - _mesa_problem(ctx, "util_create_rgba_texture() failed " - "in decompress_with_blit()"); + /* GetTexImage only returns a single face for cubemaps. */ + if (gl_target == GL_TEXTURE_CUBE_MAP) { + gl_target = GL_TEXTURE_2D; + } + + pipe_target = gl_target_to_pipe(gl_target); + + /* Find the best match for the format+type combo. */ + pipe_format = st_choose_format(pipe->screen, GL_RGBA8, format, type, + pipe_target, 0, bind); + if (pipe_format == PIPE_FORMAT_NONE) { + /* unable to get an rgba format!?! */ + _mesa_problem(ctx, "%s: cannot find a supported format", __func__); + return; + } + + /* create the destination texture */ + memset(&dst_templ, 0, sizeof(dst_templ)); + dst_templ.target = pipe_target; + dst_templ.format = pipe_format; + dst_templ.bind = bind; + dst_templ.usage = PIPE_USAGE_STAGING; + + st_gl_texture_dims_to_pipe_dims(gl_target, width, height, depth, + &dst_templ.width0, &dst_templ.height0, + &dst_templ.depth0, &dst_templ.array_size); + + dst = screen->resource_create(screen, &dst_templ); + if (!dst) { + _mesa_problem(ctx, "%s: cannot create a temporary texture", __func__); return; } - blit.src.resource = stObj->pt; + blit.src.resource = src; blit.src.level = texImage->Level; - blit.src.format = util_format_linear(stObj->pt->format); - blit.dst.resource = dst_texture; + blit.src.format = util_format_linear(src->format); + blit.dst.resource = dst; blit.dst.level = 0; - blit.dst.format = dst_texture->format; + blit.dst.format = dst->format; blit.src.box.x = blit.dst.box.x = 0; blit.src.box.y = blit.dst.box.y = 0; - blit.src.box.z = 0; /* XXX compressed array textures? */ + blit.src.box.z = texImage->Face; blit.dst.box.z = 0; blit.src.box.width = blit.dst.box.width = width; blit.src.box.height = blit.dst.box.height = height; - blit.src.box.depth = blit.dst.box.depth = 1; + blit.src.box.depth = blit.dst.box.depth = depth; blit.mask = PIPE_MASK_RGBA; blit.filter = PIPE_TEX_FILTER_NEAREST; blit.scissor_enable = FALSE; @@ -611,33 +643,38 @@ decompress_with_blit(struct gl_context * ctx, pixels = _mesa_map_pbo_dest(ctx, &ctx->Pack, pixels); - map = pipe_transfer_map(pipe, dst_texture, 0, 0, - PIPE_TRANSFER_READ, - 0, 0, width, height, &tex_xfer); + map = pipe_transfer_map_3d(pipe, dst, 0, PIPE_TRANSFER_READ, + 0, 0, 0, width, height, depth, &tex_xfer); if (!map) { goto end; } + mesa_format = st_pipe_format_to_mesa_format(pipe_format); + /* copy/pack data into user buffer */ - if (_mesa_format_matches_format_and_type(stImage->base.TexFormat, - format, type, + if (_mesa_format_matches_format_and_type(mesa_format, format, type, ctx->Pack.SwapBytes)) { /* memcpy */ - const uint bytesPerRow = width * util_format_get_blocksize(stImage->pt->format); - /* map the dst_surface so we can read from it */ - GLuint row; - for (row = 0; row < height; row++) { - GLvoid *dest = _mesa_image_address2d(&ctx->Pack, pixels, width, - height, format, type, row, 0); - memcpy(dest, map, bytesPerRow); - map += tex_xfer->stride; + const uint bytesPerRow = width * util_format_get_blocksize(pipe_format); + GLuint row, slice; + + for (slice = 0; slice < depth; slice++) { + ubyte *slice_map = map; + + for (row = 0; row < height; row++) { + GLvoid *dest = _mesa_image_address3d(&ctx->Pack, pixels, + width, height, format, + type, slice, row, 0); + memcpy(dest, slice_map, bytesPerRow); + slice_map += tex_xfer->stride; + } + map += tex_xfer->layer_stride; } - pipe_transfer_unmap(pipe, tex_xfer); } else { /* format translation via floats */ - GLuint row; - enum pipe_format pformat = util_format_linear(dst_texture->format); + GLuint row, slice; + enum pipe_format pformat = util_format_linear(dst->format); GLfloat *rgba; rgba = malloc(width * 4 * sizeof(GLfloat)); @@ -646,20 +683,24 @@ decompress_with_blit(struct gl_context * ctx, goto end; } - for (row = 0; row < height; row++) { - const GLbitfield transferOps = 0x0; /* bypassed for glGetTexImage() */ - GLvoid *dest = _mesa_image_address2d(&ctx->Pack, pixels, width, - height, format, type, row, 0); + for (slice = 0; slice < depth; slice++) { + for (row = 0; row < height; row++) { + const GLbitfield transferOps = 0x0; /* bypassed for glGetTexImage() */ + GLvoid *dest = _mesa_image_address3d(&ctx->Pack, pixels, + width, height, format, + type, slice, row, 0); - if (ST_DEBUG & DEBUG_FALLBACK) - debug_printf("%s: fallback format translation\n", __FUNCTION__); + if (ST_DEBUG & DEBUG_FALLBACK) + debug_printf("%s: fallback format translation\n", __FUNCTION__); - /* get float[4] rgba row from surface */ - pipe_get_tile_rgba_format(tex_xfer, map, 0, row, width, 1, - pformat, rgba); + /* get float[4] rgba row from surface */ + pipe_get_tile_rgba_format(tex_xfer, map, 0, row, width, 1, + pformat, rgba); - _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) rgba, format, - type, dest, &ctx->Pack, transferOps); + _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) rgba, format, + type, dest, &ctx->Pack, transferOps); + } + map += tex_xfer->layer_stride; } free(rgba); @@ -670,7 +711,7 @@ end: pipe_transfer_unmap(pipe, tex_xfer); _mesa_unmap_pbo_dest(ctx, &ctx->Pack); - pipe_resource_reference(&dst_texture, NULL); + pipe_resource_reference(&dst, NULL); } @@ -718,9 +759,12 @@ fallback_copy_texsubimage(struct gl_context *ctx, struct st_context *st = st_context(ctx); struct pipe_context *pipe = st->pipe; struct pipe_transfer *src_trans; - GLvoid *texDest; + GLubyte *texDest; enum pipe_transfer_usage transfer_usage; void *map; + unsigned dst_width = width; + unsigned dst_height = height; + unsigned dst_depth = 1; if (ST_DEBUG & DEBUG_FALLBACK) debug_printf("%s: fallback processing\n", __FUNCTION__); @@ -729,6 +773,14 @@ fallback_copy_texsubimage(struct gl_context *ctx, srcY = strb->Base.Height - srcY - height; } + if (stImage->pt->target == PIPE_TEXTURE_1D_ARRAY) { + /* Move y/height to z/depth for 1D array textures. */ + destZ = destY; + destY = 0; + dst_depth = dst_height; + dst_height = 1; + } + map = pipe_transfer_map(pipe, strb->texture, strb->rtt_level, @@ -744,9 +796,9 @@ fallback_copy_texsubimage(struct gl_context *ctx, else transfer_usage = PIPE_TRANSFER_WRITE; - /* XXX this used to ignore destZ param */ - texDest = st_texture_image_map(st, stImage, destZ, transfer_usage, - destX, destY, width, height); + texDest = st_texture_image_map(st, stImage, transfer_usage, + destX, destY, destZ, + dst_width, dst_height, dst_depth); if (baseFormat == GL_DEPTH_COMPONENT || baseFormat == GL_DEPTH_STENCIL) { @@ -774,8 +826,16 @@ fallback_copy_texsubimage(struct gl_context *ctx, if (scaleOrBias) { _mesa_scale_and_bias_depth_uint(ctx, width, data); } - pipe_put_tile_z(stImage->transfer, texDest, 0, row, width, 1, - data); + + if (stImage->pt->target == PIPE_TEXTURE_1D_ARRAY) { + pipe_put_tile_z(stImage->transfer, + texDest + row*stImage->transfer->layer_stride, + 0, 0, width, 1, data); + } + else { + pipe_put_tile_z(stImage->transfer, texDest, 0, row, width, 1, + data); + } } } else { @@ -791,7 +851,7 @@ fallback_copy_texsubimage(struct gl_context *ctx, if (tempSrc && texDest) { const GLint dims = 2; - const GLint dstRowStride = stImage->transfer->stride; + GLint dstRowStride; struct gl_texture_image *texImage = &stImage->base; struct gl_pixelstore_attrib unpack = ctx->DefaultPacking; @@ -799,6 +859,13 @@ fallback_copy_texsubimage(struct gl_context *ctx, unpack.Invert = GL_TRUE; } + if (stImage->pt->target == PIPE_TEXTURE_1D_ARRAY) { + dstRowStride = stImage->transfer->layer_stride; + } + else { + dstRowStride = stImage->transfer->stride; + } + /* get float/RGBA image from framebuffer */ /* XXX this usually involves a lot of int/float conversion. * try to avoid that someday. @@ -817,7 +884,7 @@ fallback_copy_texsubimage(struct gl_context *ctx, texImage->_BaseFormat, texImage->TexFormat, dstRowStride, - (GLubyte **) &texDest, + &texDest, width, height, 1, GL_RGBA, GL_FLOAT, tempSrc, /* src */ &unpack); @@ -900,6 +967,43 @@ compatible_src_dst_formats(struct gl_context *ctx, } +/** + * Do pipe->blit. Return FALSE if the blitting is unsupported + * for the given formats. + */ +static GLboolean +st_pipe_blit(struct pipe_context *pipe, struct pipe_blit_info *blit) +{ + struct pipe_screen *screen = pipe->screen; + unsigned dst_usage; + + if (util_format_is_depth_or_stencil(blit->dst.format)) { + dst_usage = PIPE_BIND_DEPTH_STENCIL; + } + else { + dst_usage = PIPE_BIND_RENDER_TARGET; + } + + /* try resource_copy_region in case the format is not supported + * for rendering */ + if (util_try_blit_via_copy_region(pipe, blit)) { + return GL_TRUE; /* done */ + } + + /* check the format support */ + if (!screen->is_format_supported(screen, blit->src.format, + PIPE_TEXTURE_2D, 0, + PIPE_BIND_SAMPLER_VIEW) || + !screen->is_format_supported(screen, blit->dst.format, + PIPE_TEXTURE_2D, 0, + dst_usage)) { + return GL_FALSE; + } + + pipe->blit(pipe, blit); + return GL_TRUE; +} + /** * Do a CopyTex[Sub]Image1/2/3D() using a hardware (blit) path if possible. @@ -922,13 +1026,13 @@ st_CopyTexSubImage(struct gl_context *ctx, GLuint dims, struct pipe_context *pipe = st->pipe; struct pipe_screen *screen = pipe->screen; enum pipe_format dest_format, src_format; - GLboolean matching_base_formats; - GLuint color_writemask, zs_writemask, sample_count; + GLuint color_writemask; struct pipe_surface *dest_surface = NULL; GLboolean do_flip = (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP); struct pipe_surface surf_tmpl; - unsigned int dst_usage; - GLint srcY0, srcY1; + unsigned dst_usage; + unsigned blit_mask; + GLint srcY0, srcY1, yStep; /* make sure finalize_textures has been called? */ @@ -939,12 +1043,6 @@ st_CopyTexSubImage(struct gl_context *ctx, GLuint dims, return; } - sample_count = strb->surface->texture->nr_samples; - /* I believe this would be legal, presumably would need to do a resolve - for color, and for depth/stencil spec says to just use one of the - depth/stencil samples per pixel? Need some transfer clarifications. */ - assert(sample_count < 2); - assert(strb); assert(strb->surface); assert(stImage->pt); @@ -952,79 +1050,143 @@ st_CopyTexSubImage(struct gl_context *ctx, GLuint dims, src_format = strb->surface->format; dest_format = stImage->pt->format; - /* - * Determine if the src framebuffer and dest texture have the same - * base format. We need this to detect a case such as the framebuffer - * being GL_RGBA but the texture being GL_RGB. If the actual hardware - * texture format stores RGBA we need to set A=1 (overriding the - * framebuffer's alpha values). We can't do that with the blit or - * textured-quad paths. - */ - matching_base_formats = - (_mesa_get_format_base_format(strb->Base.Format) == - _mesa_get_format_base_format(texImage->TexFormat)); + if (do_flip) { + srcY1 = strb->Base.Height - srcY - height; + srcY0 = srcY1 + height; + yStep = -1; + } + else { + srcY0 = srcY; + srcY1 = srcY0 + height; + yStep = 1; + } if (ctx->_ImageTransferState) { goto fallback; } - if (texImage->TexObject->Target == GL_TEXTURE_1D_ARRAY) { - /* 1D arrays might be thought of as 2D images but the actual layout - * might not be that way. At some points, we convert OpenGL's 1D - * array 'height' into gallium 'layers' and that prevents the blit - * utility code from doing the right thing. Simpy use the memcpy-based - * fallback. - */ + /* Compressed and subsampled textures aren't supported for blitting. */ + if (!util_format_is_plain(dest_format)) { goto fallback; } - if (matching_base_formats && - src_format == dest_format && - !do_flip) { - /* use surface_copy() / blit */ - struct pipe_box src_box; - unsigned dstLevel; + /* Set the blit writemask. */ + switch (texBaseFormat) { + case GL_DEPTH_STENCIL: + switch (strb->Base._BaseFormat) { + case GL_DEPTH_STENCIL: + blit_mask = PIPE_MASK_ZS; + break; + case GL_DEPTH_COMPONENT: + blit_mask = PIPE_MASK_Z; + break; + case GL_STENCIL_INDEX: + blit_mask = PIPE_MASK_S; + break; + default: + assert(0); + return; + } + dst_usage = PIPE_BIND_DEPTH_STENCIL; + break; + + case GL_DEPTH_COMPONENT: + blit_mask = PIPE_MASK_Z; + dst_usage = PIPE_BIND_DEPTH_STENCIL; + break; - u_box_2d_zslice(srcX, srcY, strb->surface->u.tex.first_layer, - width, height, &src_box); + default: + /* Colorbuffers. + * + * Determine if the src framebuffer and dest texture have the same + * base format. We need this to detect a case such as the framebuffer + * being GL_RGBA but the texture being GL_RGB. If the actual hardware + * texture format stores RGBA we need to set A=1 (overriding the + * framebuffer's alpha values). + * + * XXX util_blit_pixels doesn't support MSAA resolve, so always use + * pipe->blit + */ + if (texBaseFormat == strb->Base._BaseFormat || + strb->texture->nr_samples > 1) { + blit_mask = PIPE_MASK_RGBA; + } + else { + blit_mask = 0; + } + dst_usage = PIPE_BIND_RENDER_TARGET; + } + /* Blit the texture. + * This supports flipping, format conversions, and downsampling. + */ + if (blit_mask) { /* If stImage->pt is an independent image (not a pointer into a full * mipmap) stImage->pt.last_level will be zero and we need to use that * as the dest level. */ - dstLevel = MIN2(stImage->base.Level, stImage->pt->last_level); - - /* for resource_copy_region(), y=0=top, always */ - pipe->resource_copy_region(pipe, - /* dest */ - stImage->pt, - dstLevel, - destX, destY, destZ + stImage->base.Face, - /* src */ - strb->texture, - strb->surface->u.tex.level, - &src_box); + unsigned dstLevel = MIN2(stImage->base.Level, stImage->pt->last_level); + struct pipe_blit_info blit; + + memset(&blit, 0, sizeof(blit)); + blit.src.resource = strb->texture; + blit.src.format = src_format; + blit.src.level = strb->surface->u.tex.level; + blit.src.box.x = srcX; + blit.src.box.y = srcY0; + blit.src.box.z = strb->surface->u.tex.first_layer; + blit.src.box.width = width; + blit.src.box.height = srcY1 - srcY0; + blit.src.box.depth = 1; + blit.dst.resource = stImage->pt; + blit.dst.format = dest_format; + blit.dst.level = dstLevel; + blit.dst.box.x = destX; + blit.dst.box.y = destY; + blit.dst.box.z = stImage->base.Face + destZ; + blit.dst.box.width = width; + blit.dst.box.height = height; + blit.dst.box.depth = 1; + blit.mask = blit_mask; + blit.filter = PIPE_TEX_FILTER_NEAREST; + + /* 1D array textures need special treatment. + * Blit rows from the source to layers in the destination. */ + if (texImage->TexObject->Target == GL_TEXTURE_1D_ARRAY) { + int y, layer; + + for (y = srcY0, layer = 0; layer < height; y += yStep, layer++) { + blit.src.box.y = y; + blit.src.box.height = 1; + blit.dst.box.y = 0; + blit.dst.box.height = 1; + blit.dst.box.z = destY + layer; + + if (!st_pipe_blit(pipe, &blit)) { + goto fallback; + } + } + } + else { + /* All the other texture targets. */ + if (!st_pipe_blit(pipe, &blit)) { + goto fallback; + } + } return; } - if (texBaseFormat == GL_DEPTH_STENCIL) { + /* try u_blit */ + if (texImage->TexObject->Target == GL_TEXTURE_1D_ARRAY) { + /* u_blit cannot copy 1D array textures as required by CopyTexSubImage */ goto fallback; } - if (texBaseFormat == GL_DEPTH_COMPONENT) { - color_writemask = 0; - zs_writemask = BLIT_WRITEMASK_Z; - dst_usage = PIPE_BIND_DEPTH_STENCIL; - } - else { - color_writemask = compatible_src_dst_formats(ctx, &strb->Base, texImage); - zs_writemask = 0; - dst_usage = PIPE_BIND_RENDER_TARGET; - } + color_writemask = compatible_src_dst_formats(ctx, &strb->Base, texImage); - if ((!color_writemask && !zs_writemask) || + if (!color_writemask || !screen->is_format_supported(screen, src_format, - PIPE_TEXTURE_2D, sample_count, + PIPE_TEXTURE_2D, 0, PIPE_BIND_SAMPLER_VIEW) || !screen->is_format_supported(screen, dest_format, PIPE_TEXTURE_2D, 0, @@ -1032,23 +1194,8 @@ st_CopyTexSubImage(struct gl_context *ctx, GLuint dims, goto fallback; } - if (do_flip) { - srcY1 = strb->Base.Height - srcY - height; - srcY0 = srcY1 + height; - } - else { - srcY0 = srcY; - srcY1 = srcY0 + height; - } - - /* Disable conditional rendering. */ - if (st->render_condition) { - pipe->render_condition(pipe, NULL, 0); - } - memset(&surf_tmpl, 0, sizeof(surf_tmpl)); surf_tmpl.format = util_format_linear(stImage->pt->format); - surf_tmpl.usage = dst_usage; surf_tmpl.u.tex.level = stImage->base.Level; surf_tmpl.u.tex.first_layer = stImage->base.Face + destZ; surf_tmpl.u.tex.last_layer = stImage->base.Face + destZ; @@ -1065,15 +1212,8 @@ st_CopyTexSubImage(struct gl_context *ctx, GLuint dims, destX, destY, destX + width, destY + height, 0.0, PIPE_TEX_MIPFILTER_NEAREST, - color_writemask, zs_writemask); + color_writemask, 0); pipe_surface_reference(&dest_surface, NULL); - - /* Restore conditional rendering state. */ - if (st->render_condition) { - pipe->render_condition(pipe, st->render_condition, - st->condition_mode); - } - return; fallback: @@ -1182,6 +1322,20 @@ st_finalize_texture(struct gl_context *ctx, stObj->lastLevel = stObj->base._MaxLevel; } + if (tObj->Target == GL_TEXTURE_BUFFER) { + struct st_buffer_object *st_obj = st_buffer_object(tObj->BufferObject); + + if (st_obj->buffer != stObj->pt) { + pipe_resource_reference(&stObj->pt, st_obj->buffer); + pipe_sampler_view_release(st->pipe, &stObj->sampler_view); + stObj->width0 = stObj->pt->width0 / _mesa_get_format_bytes(tObj->_BufferObjectFormat); + stObj->height0 = 1; + stObj->depth0 = 1; + } + return GL_TRUE; + + } + firstImage = st_texture_image(stObj->base.Image[0][stObj->base.BaseLevel]); assert(firstImage);