diff options
Diffstat (limited to 'src/mesa/state_tracker/st_cb_texture.c')
-rw-r--r-- | src/mesa/state_tracker/st_cb_texture.c | 345 |
1 files changed, 132 insertions, 213 deletions
diff --git a/src/mesa/state_tracker/st_cb_texture.c b/src/mesa/state_tracker/st_cb_texture.c index 866426a754..9d5eb113ff 100644 --- a/src/mesa/state_tracker/st_cb_texture.c +++ b/src/mesa/state_tracker/st_cb_texture.c @@ -35,6 +35,7 @@ #include "main/macros.h" #include "main/mipmap.h" #include "main/pack.h" +#include "main/pbo.h" #include "main/pixeltransfer.h" #include "main/texcompress.h" #include "main/texfetch.h" @@ -74,19 +75,18 @@ gl_target_to_pipe(GLenum target) switch (target) { case GL_TEXTURE_1D: return PIPE_TEXTURE_1D; - case GL_TEXTURE_2D: return PIPE_TEXTURE_2D; - case GL_TEXTURE_RECTANGLE_NV: return PIPE_TEXTURE_RECT; - case GL_TEXTURE_3D: return PIPE_TEXTURE_3D; - case GL_TEXTURE_CUBE_MAP_ARB: return PIPE_TEXTURE_CUBE; - + case GL_TEXTURE_1D_ARRAY_EXT: + return PIPE_TEXTURE_1D_ARRAY; + case GL_TEXTURE_2D_ARRAY_EXT: + return PIPE_TEXTURE_2D_ARRAY; default: assert(0); return 0; @@ -217,7 +217,6 @@ default_bindings(struct st_context *st, enum pipe_format format) { struct pipe_screen *screen = st->pipe->screen; const unsigned target = PIPE_TEXTURE_2D; - const unsigned geom = 0x0; unsigned bindings; if (util_format_is_depth_or_stencil(format)) @@ -225,10 +224,17 @@ default_bindings(struct st_context *st, enum pipe_format format) else bindings = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET; - if (screen->is_format_supported(screen, format, target, 0, bindings, geom)) + if (screen->is_format_supported(screen, format, target, 0, bindings)) return bindings; - else - return PIPE_BIND_SAMPLER_VIEW; + else { + /* Try non-sRGB. */ + format = util_format_linear(format); + + if (screen->is_format_supported(screen, format, target, 0, bindings)) + return bindings; + else + return PIPE_BIND_SAMPLER_VIEW; + } } @@ -261,6 +267,55 @@ get_texture_dims(GLenum target) /** + * Given the size of a mipmap image, try to compute the size of the level=0 + * mipmap image. + * + * Note that this isn't always accurate for odd-sized, non-POW textures. + * For example, if level=1 and width=40 then the level=0 width may be 80 or 81. + * + * \return GL_TRUE for success, GL_FALSE for failure + */ +static GLboolean +guess_base_level_size(GLenum target, + GLuint width, GLuint height, GLuint depth, GLuint level, + GLuint *width0, GLuint *height0, GLuint *depth0) +{ + const GLuint dims = get_texture_dims(target); + + assert(width >= 1); + assert(height >= 1); + assert(depth >= 1); + + if (level > 0) { + /* Depending on the image's size, we can't always make a guess here */ + if ((dims >= 1 && width == 1) || + (dims >= 2 && height == 1) || + (dims >= 3 && depth == 1)) { + /* we can't determine the image size at level=0 */ + return GL_FALSE; + } + + /* grow the image size until we hit level = 0 */ + while (level > 0) { + if (width > 1) + width <<= 1; + if (height > 1) + height <<= 1; + if (depth > 1) + depth <<= 1; + level--; + } + } + + *width0 = width; + *height0 = height; + *depth0 = depth; + + return GL_TRUE; +} + + +/** * Try to allocate a pipe_resource object for the given st_texture_object. * * We use the given st_texture_image as a clue to determine the size of the @@ -273,50 +328,27 @@ guess_and_alloc_texture(struct st_context *st, struct st_texture_object *stObj, const struct st_texture_image *stImage) { - const GLuint dims = get_texture_dims(stObj->base.Target); - GLuint level, lastLevel, width, height, depth; + GLuint lastLevel, width, height, depth; GLuint bindings; + GLuint ptWidth, ptHeight, ptDepth, ptLayers; enum pipe_format fmt; DBG("%s\n", __FUNCTION__); assert(!stObj->pt); - level = stImage->level; - width = stImage->base.Width2; /* size w/out border */ - height = stImage->base.Height2; - depth = stImage->base.Depth2; - - assert(width > 0); - assert(height > 0); - assert(depth > 0); - - /* Depending on the image's size, we can't always make a guess here. - */ - if (level > 0) { - if ( (dims >= 1 && width == 1) || - (dims >= 2 && height == 1) || - (dims >= 3 && depth == 1) ) { - /* we can't determine the image size at level=0 */ - stObj->width0 = stObj->height0 = stObj->depth0 = 0; - /* this is not an out of memory error */ - return GL_TRUE; - } + if (!guess_base_level_size(stObj->base.Target, + stImage->base.Width2, + stImage->base.Height2, + stImage->base.Depth2, + stImage->level, + &width, &height, &depth)) { + /* we can't determine the image size at level=0 */ + stObj->width0 = stObj->height0 = stObj->depth0 = 0; + /* this is not an out of memory error */ + return GL_TRUE; } - /* grow the image size until we hit level = 0 */ - while (level > 0) { - if (width != 1) - width <<= 1; - if (height != 1) - height <<= 1; - if (depth != 1) - depth <<= 1; - level--; - } - - assert(level == 0); - /* At this point, (width x height x depth) is the expected size of * the level=0 mipmap image. */ @@ -353,13 +385,18 @@ guess_and_alloc_texture(struct st_context *st, bindings = default_bindings(st, fmt); + st_gl_texture_dims_to_pipe_dims(stObj->base.Target, + width, height, depth, + &ptWidth, &ptHeight, &ptDepth, &ptLayers); + stObj->pt = st_texture_create(st, gl_target_to_pipe(stObj->base.Target), fmt, lastLevel, - width, - height, - depth, + ptWidth, + ptHeight, + ptDepth, + ptLayers, bindings); DBG("%s returning %d\n", __FUNCTION__, (stObj->pt != NULL)); @@ -407,125 +444,6 @@ strip_texture_border(GLint border, /** - * Try to do texture compression via rendering. If the Gallium driver - * can render into a compressed surface this will allow us to do texture - * compression. - * \return GL_TRUE for success, GL_FALSE for failure - */ -static GLboolean -compress_with_blit(struct gl_context * ctx, - GLenum target, GLint level, - GLint xoffset, GLint yoffset, GLint zoffset, - GLint width, GLint height, GLint depth, - GLenum format, GLenum type, const void *pixels, - const struct gl_pixelstore_attrib *unpack, - struct gl_texture_image *texImage) -{ - const GLuint dstImageOffsets[1] = {0}; - struct st_texture_image *stImage = st_texture_image(texImage); - struct st_context *st = st_context(ctx); - struct pipe_context *pipe = st->pipe; - struct pipe_screen *screen = pipe->screen; - gl_format mesa_format; - struct pipe_resource templ; - struct pipe_resource *src_tex; - struct pipe_sampler_view view_templ; - struct pipe_sampler_view *src_view; - struct pipe_surface *dst_surface, surf_tmpl; - struct pipe_transfer *tex_xfer; - void *map; - - if (!stImage->pt) { - /* XXX: Can this happen? Should we assert? */ - return GL_FALSE; - } - - /* get destination surface (in the compressed texture) */ - memset(&surf_tmpl, 0, sizeof(surf_tmpl)); - surf_tmpl.format = stImage->pt->format; - surf_tmpl.usage = PIPE_BIND_RENDER_TARGET; - surf_tmpl.u.tex.level = stImage->level; - surf_tmpl.u.tex.first_layer = stImage->face; - surf_tmpl.u.tex.last_layer = stImage->face; - dst_surface = pipe->create_surface(pipe, stImage->pt, &surf_tmpl); - if (!dst_surface) { - /* can't render into this format (or other problem) */ - return GL_FALSE; - } - - /* Choose format for the temporary RGBA texture image. - */ - mesa_format = st_ChooseTextureFormat(ctx, GL_RGBA, format, type); - assert(mesa_format); - if (!mesa_format) - return GL_FALSE; - - /* Create the temporary source texture - */ - memset(&templ, 0, sizeof(templ)); - templ.target = st->internal_target; - templ.format = st_mesa_format_to_pipe_format(mesa_format); - templ.width0 = width; - templ.height0 = height; - templ.depth0 = 1; - templ.array_size = 1; - templ.last_level = 0; - templ.usage = PIPE_USAGE_DEFAULT; - templ.bind = PIPE_BIND_SAMPLER_VIEW; - src_tex = screen->resource_create(screen, &templ); - - if (!src_tex) - return GL_FALSE; - - /* Put user's tex data into the temporary texture - */ - tex_xfer = pipe_get_transfer(st_context(ctx)->pipe, src_tex, - 0, 0, /* layer, level are zero */ - PIPE_TRANSFER_WRITE, - 0, 0, width, height); /* x, y, w, h */ - map = pipe_transfer_map(pipe, tex_xfer); - - _mesa_texstore(ctx, 2, GL_RGBA, mesa_format, - map, /* dest ptr */ - 0, 0, 0, /* dest x/y/z offset */ - tex_xfer->stride, /* dest row stride (bytes) */ - dstImageOffsets, /* image offsets (for 3D only) */ - width, height, 1, /* size */ - format, type, /* source format/type */ - pixels, /* source data */ - unpack); /* source data packing */ - - pipe_transfer_unmap(pipe, tex_xfer); - pipe->transfer_destroy(pipe, tex_xfer); - - /* Create temporary sampler view */ - u_sampler_view_default_template(&view_templ, - src_tex, - src_tex->format); - src_view = pipe->create_sampler_view(pipe, src_tex, &view_templ); - - - /* copy / compress image */ - util_blit_pixels_tex(st->blit, - src_view, /* sampler view (src) */ - 0, 0, /* src x0, y0 */ - width, height, /* src x1, y1 */ - dst_surface, /* pipe_surface (dst) */ - xoffset, yoffset, /* dst x0, y0 */ - xoffset + width, /* dst x1 */ - yoffset + height, /* dst y1 */ - 0.0, /* z */ - PIPE_TEX_MIPFILTER_NEAREST); - - pipe_surface_reference(&dst_surface, NULL); - pipe_resource_reference(&src_tex, NULL); - pipe_sampler_view_reference(&src_view, NULL); - - return GL_TRUE; -} - - -/** * Do glTexImage1/2/3D(). */ static void @@ -542,7 +460,6 @@ st_TexImage(struct gl_context * ctx, GLsizei imageSize, GLboolean compressed_src) { struct st_context *st = st_context(ctx); - struct pipe_screen *screen = st->pipe->screen; struct st_texture_object *stObj = st_texture_object(texObj); struct st_texture_image *stImage = st_texture_image(texImage); GLuint dstRowStride = 0; @@ -669,22 +586,10 @@ st_TexImage(struct gl_context * ctx, pixels, unpack, "glTexImage"); } - /* See if we can do texture compression with a blit/render. - */ - if (!compressed_src && - !ctx->Mesa_DXTn && - _mesa_is_format_compressed(texImage->TexFormat) && - screen->is_format_supported(screen, - stImage->pt->format, - stImage->pt->target, 0, - PIPE_BIND_RENDER_TARGET, 0)) { - if (!pixels) - goto done; - - if (compress_with_blit(ctx, target, level, 0, 0, 0, width, height, depth, - format, type, pixels, unpack, texImage)) { - goto done; - } + /* for a 1D array upload the image as a series of layer with height = 1 */ + if (target == GL_TEXTURE_1D_ARRAY) { + depth = height; + height = 1; } /* @@ -918,6 +823,7 @@ decompress_with_blit(struct gl_context * ctx, GLenum target, GLint level, else { /* format translation via floats */ GLuint row; + enum pipe_format format = util_format_linear(dst_texture->format); for (row = 0; row < height; row++) { const GLbitfield transferOps = 0x0; /* bypassed for glGetTexImage() */ GLfloat rgba[4 * MAX_WIDTH]; @@ -928,7 +834,8 @@ decompress_with_blit(struct gl_context * ctx, GLenum target, GLint level, debug_printf("%s: fallback format translation\n", __FUNCTION__); /* get float[4] rgba row from surface */ - pipe_get_tile_rgba(pipe, tex_xfer, 0, row, width, 1, rgba); + pipe_get_tile_rgba_format(pipe, tex_xfer, 0, row, width, 1, + format, rgba); _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) rgba, format, type, dest, &ctx->Pack, transferOps); @@ -1073,7 +980,6 @@ st_TexSubimage(struct gl_context *ctx, GLint dims, GLenum target, GLint level, struct gl_texture_image *texImage) { struct st_context *st = st_context(ctx); - struct pipe_screen *screen = st->pipe->screen; struct st_texture_image *stImage = st_texture_image(texImage); GLuint dstRowStride; const GLuint srcImageStride = @@ -1093,20 +999,10 @@ st_TexSubimage(struct gl_context *ctx, GLint dims, GLenum target, GLint level, if (!pixels) return; - /* See if we can do texture compression with a blit/render. - */ - if (!ctx->Mesa_DXTn && - _mesa_is_format_compressed(texImage->TexFormat) && - screen->is_format_supported(screen, - stImage->pt->format, - stImage->pt->target, 0, - PIPE_BIND_RENDER_TARGET, 0)) { - if (compress_with_blit(ctx, target, level, - xoffset, yoffset, zoffset, - width, height, depth, - format, type, pixels, packing, texImage)) { - goto done; - } + /* for a 1D array upload the image as a series of layer with height = 1 */ + if (target == GL_TEXTURE_1D_ARRAY) { + depth = height; + height = 1; } /* Map buffer if necessary. Need to lock to prevent other contexts @@ -1387,7 +1283,9 @@ fallback_copy_texsubimage(struct gl_context *ctx, GLenum target, GLint level, /* XXX this usually involves a lot of int/float conversion. * try to avoid that someday. */ - pipe_get_tile_rgba(pipe, src_trans, 0, 0, width, height, tempSrc); + pipe_get_tile_rgba_format(pipe, src_trans, 0, 0, width, height, + util_format_linear(strb->texture->format), + tempSrc); /* Store into texture memory. * Note that this does some special things such as pixel transfer @@ -1528,6 +1426,9 @@ st_copy_texsubimage(struct gl_context *ctx, if (texBaseFormat == GL_DEPTH_COMPONENT || texBaseFormat == GL_DEPTH_STENCIL) { strb = st_renderbuffer(fb->_DepthBuffer); + if (strb->Base.Wrapped) { + strb = st_renderbuffer(strb->Base.Wrapped); + } } else { /* texBaseFormat == GL_RGB, GL_RGBA, GL_ALPHA, etc */ @@ -1621,17 +1522,15 @@ st_copy_texsubimage(struct gl_context *ctx, texBaseFormat != GL_DEPTH_STENCIL && screen->is_format_supported(screen, src_format, PIPE_TEXTURE_2D, sample_count, - PIPE_BIND_SAMPLER_VIEW, - 0) && + PIPE_BIND_SAMPLER_VIEW) && screen->is_format_supported(screen, dest_format, PIPE_TEXTURE_2D, 0, - PIPE_BIND_RENDER_TARGET, - 0)) { + PIPE_BIND_RENDER_TARGET)) { /* draw textured quad to do the copy */ GLint srcY0, srcY1; struct pipe_surface surf_tmpl; memset(&surf_tmpl, 0, sizeof(surf_tmpl)); - surf_tmpl.format = stImage->pt->format; + surf_tmpl.format = util_format_linear(stImage->pt->format); surf_tmpl.usage = PIPE_BIND_RENDER_TARGET; surf_tmpl.u.tex.level = stImage->level; surf_tmpl.u.tex.first_layer = stImage->face + destZ; @@ -1831,6 +1730,7 @@ st_finalize_texture(struct gl_context *ctx, GLuint face; struct st_texture_image *firstImage; enum pipe_format firstImageFormat; + GLuint ptWidth, ptHeight, ptDepth, ptLayers; if (stObj->base._Complete) { /* The texture is complete and we know exactly how many mipmap levels @@ -1855,9 +1755,8 @@ st_finalize_texture(struct gl_context *ctx, * will match. */ if (firstImage->pt && - stObj->pt && firstImage->pt != stObj->pt && - firstImage->pt->last_level >= stObj->pt->last_level) { + (!stObj->pt || firstImage->pt->last_level >= stObj->pt->last_level)) { pipe_resource_reference(&stObj->pt, firstImage->pt); pipe_sampler_view_reference(&stObj->sampler_view, NULL); } @@ -1865,6 +1764,24 @@ st_finalize_texture(struct gl_context *ctx, /* Find gallium format for the Mesa texture */ firstImageFormat = st_mesa_format_to_pipe_format(firstImage->base.TexFormat); + /* Find size of level=0 Gallium mipmap image, plus number of texture layers */ + { + GLuint width, height, depth; + if (!guess_base_level_size(stObj->base.Target, + firstImage->base.Width2, + firstImage->base.Height2, + firstImage->base.Depth2, + stObj->base.BaseLevel, + &width, &height, &depth)) { + width = stObj->width0; + height = stObj->height0; + depth = stObj->depth0; + } + /* convert GL dims to Gallium dims */ + st_gl_texture_dims_to_pipe_dims(stObj->base.Target, width, height, depth, + &ptWidth, &ptHeight, &ptDepth, &ptLayers); + } + /* If we already have a gallium texture, check that it matches the texture * object's format, target, size, num_levels, etc. */ @@ -1872,9 +1789,10 @@ st_finalize_texture(struct gl_context *ctx, if (stObj->pt->target != gl_target_to_pipe(stObj->base.Target) || !st_sampler_compat_formats(stObj->pt->format, firstImageFormat) || stObj->pt->last_level < stObj->lastLevel || - stObj->pt->width0 != stObj->width0 || - stObj->pt->height0 != stObj->height0 || - stObj->pt->depth0 != stObj->depth0) + stObj->pt->width0 != ptWidth || + stObj->pt->height0 != ptHeight || + stObj->pt->depth0 != ptDepth || + stObj->pt->array_size != ptLayers) { /* The gallium texture does not match the Mesa texture so delete the * gallium texture now. We'll make a new one below. @@ -1894,9 +1812,10 @@ st_finalize_texture(struct gl_context *ctx, gl_target_to_pipe(stObj->base.Target), firstImageFormat, stObj->lastLevel, - stObj->width0, - stObj->height0, - stObj->depth0, + ptWidth, + ptHeight, + ptDepth, + ptLayers, bindings); if (!stObj->pt) { |