X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fstate_tracker%2Fst_cb_texture.c;h=e34fd09dcb753f468310695d74e11f2668d30e6d;hb=1975208919a273018a2cda87e765870c5f86d01f;hp=0c518a7e031e0e53d2f5186918243f7a948594ec;hpb=8cdfd1219a2d13d252a8691ee6dddb0d773bdc77;p=mesa.git diff --git a/src/mesa/state_tracker/st_cb_texture.c b/src/mesa/state_tracker/st_cb_texture.c index 0c518a7e031..e34fd09dcb7 100644 --- a/src/mesa/state_tracker/st_cb_texture.c +++ b/src/mesa/state_tracker/st_cb_texture.c @@ -27,9 +27,6 @@ #include "main/mfeatures.h" #include "main/bufferobj.h" -#if FEATURE_convolve -#include "main/convolve.h" -#endif #include "main/enums.h" #include "main/fbobject.h" #include "main/formats.h" @@ -47,12 +44,11 @@ #include "state_tracker/st_debug.h" #include "state_tracker/st_context.h" #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_format.h" -#include "state_tracker/st_public.h" #include "state_tracker/st_texture.h" #include "state_tracker/st_gen_mipmap.h" -#include "state_tracker/st_inlines.h" #include "state_tracker/st_atom.h" #include "pipe/p_context.h" @@ -63,6 +59,7 @@ #include "util/u_blit.h" #include "util/u_format.h" #include "util/u_surface.h" +#include "util/u_sampler.h" #include "util/u_math.h" @@ -120,12 +117,21 @@ static void st_DeleteTextureObject(GLcontext *ctx, struct gl_texture_object *texObj) { + struct st_context *st = st_context(ctx); struct st_texture_object *stObj = st_texture_object(texObj); if (stObj->pt) - pipe_texture_reference(&stObj->pt, NULL); - if (stObj->sampler_view) + pipe_resource_reference(&stObj->pt, NULL); + if (stObj->sampler_view) { + if (stObj->sampler_view->context != st->pipe) { + /* Take "ownership" of this texture sampler view by setting + * its context pointer to this context. This avoids potential + * crashes when the texture object is shared among contexts + * and the original/owner context has already been destroyed. + */ + stObj->sampler_view->context = st->pipe; + } pipe_sampler_view_reference(&stObj->sampler_view, NULL); - + } _mesa_delete_texture_object(ctx, texObj); } @@ -139,7 +145,7 @@ st_FreeTextureImageData(GLcontext * ctx, struct gl_texture_image *texImage) DBG("%s\n", __FUNCTION__); if (stImage->pt) { - pipe_texture_reference(&stImage->pt, NULL); + pipe_resource_reference(&stImage->pt, NULL); } if (texImage->Data) { @@ -200,110 +206,142 @@ do_memcpy(void *dest, const void *src, size_t n) /** - * Return default texture usage bitmask for the given texture format. + * Return default texture resource binding bitmask for the given format. */ static GLuint -default_usage(enum pipe_format fmt) +default_bindings(struct st_context *st, enum pipe_format format) { - GLuint usage = PIPE_TEXTURE_USAGE_SAMPLER; - if (util_format_is_depth_or_stencil(fmt)) - usage |= PIPE_TEXTURE_USAGE_DEPTH_STENCIL; + 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)) + bindings = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_DEPTH_STENCIL; else - usage |= PIPE_TEXTURE_USAGE_RENDER_TARGET; - return usage; + bindings = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET; + + if (screen->is_format_supported(screen, format, target, bindings, geom)) + return bindings; + else + return PIPE_BIND_SAMPLER_VIEW; +} + + +/** Return number of image dimensions (1, 2 or 3) for a texture target. */ +static GLuint +get_texture_dims(GLenum target) +{ + switch (target) { + case GL_TEXTURE_1D: + case GL_TEXTURE_1D_ARRAY_EXT: + return 1; + case GL_TEXTURE_2D: + case GL_TEXTURE_CUBE_MAP_ARB: + case GL_TEXTURE_RECTANGLE_NV: + case GL_TEXTURE_2D_ARRAY_EXT: + return 2; + case GL_TEXTURE_3D: + return 3; + default: + assert(0 && "invalid texture target in get_texture_dims()"); + return 1; + } } /** - * Allocate a pipe_texture object for the given st_texture_object using - * the given st_texture_image to guess the mipmap size/levels. + * Try to allocate a pipe_resource object for the given st_texture_object. * - * [comments...] - * Otherwise, store it in memory if (Border != 0) or (any dimension == - * 1). - * - * Otherwise, if max_level >= level >= min_level, create texture with - * space for images from min_level down to max_level. + * We use the given st_texture_image as a clue to determine the size of the + * mipmap image at level=0. * - * Otherwise, create texture with space for images from (level 0)..(1x1). - * Consider pruning this texture at a validation if the saving is worth it. + * \return GL_TRUE for success, GL_FALSE if out of memory. */ -static void +static GLboolean guess_and_alloc_texture(struct st_context *st, struct st_texture_object *stObj, const struct st_texture_image *stImage) { - GLuint firstLevel; - GLuint lastLevel; - GLuint width = stImage->base.Width2; /* size w/out border */ - GLuint height = stImage->base.Height2; - GLuint depth = stImage->base.Depth2; - GLuint i, usage; + const GLuint dims = get_texture_dims(stObj->base.Target); + GLuint level, lastLevel, width, height, depth; + GLuint bindings; enum pipe_format fmt; DBG("%s\n", __FUNCTION__); assert(!stObj->pt); - if (stObj->pt && - (GLint) stImage->level > stObj->base.BaseLevel && - (stImage->base.Width == 1 || - (stObj->base.Target != GL_TEXTURE_1D && - stImage->base.Height == 1) || - (stObj->base.Target == GL_TEXTURE_3D && - stImage->base.Depth == 1))) - return; - - /* If this image disrespects BaseLevel, allocate from level zero. - * Usually BaseLevel == 0, so it's unlikely to happen. - */ - if ((GLint) stImage->level < stObj->base.BaseLevel) - firstLevel = 0; - else - firstLevel = stObj->base.BaseLevel; + 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); - /* Figure out image dimensions at start level. + /* Depending on the image's size, we can't always make a guess here. */ - for (i = stImage->level; i > firstLevel; i--) { + 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; + } + } + + /* 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--; + } - if (width == 0 || height == 0 || depth == 0) { - /* no texture needed */ - return; - } + assert(level == 0); + + /* At this point, (width x height x depth) is the expected size of + * the level=0 mipmap image. + */ - /* Guess a reasonable value for lastLevel. This is probably going - * to be wrong fairly often and might mean that we have to look at - * resizable buffers, or require that buffers implement lazy - * pagetable arrangements. + /* Guess a reasonable value for lastLevel. With OpenGL we have no + * idea how many mipmap levels will be in a texture until we start + * to render with it. Make an educated guess here but be prepared + * to re-allocating a texture buffer with space for more (or fewer) + * mipmap levels later. */ if ((stObj->base.MinFilter == GL_NEAREST || stObj->base.MinFilter == GL_LINEAR || stImage->base._BaseFormat == GL_DEPTH_COMPONENT || stImage->base._BaseFormat == GL_DEPTH_STENCIL_EXT) && !stObj->base.GenerateMipmap && - stImage->level == firstLevel) { + stImage->level == 0) { /* only alloc space for a single mipmap level */ - lastLevel = firstLevel; + lastLevel = 0; } else { /* alloc space for a full mipmap */ GLuint l2width = util_logbase2(width); GLuint l2height = util_logbase2(height); GLuint l2depth = util_logbase2(depth); - lastLevel = firstLevel + MAX2(MAX2(l2width, l2height), l2depth); + lastLevel = MAX2(MAX2(l2width, l2height), l2depth); } + /* Save the level=0 dimensions */ + stObj->width0 = width; + stObj->height0 = height; + stObj->depth0 = depth; + fmt = st_mesa_format_to_pipe_format(stImage->base.TexFormat); - usage = default_usage(fmt); + bindings = default_bindings(st, fmt); stObj->pt = st_texture_create(st, gl_target_to_pipe(stObj->base.Target), @@ -312,11 +350,11 @@ guess_and_alloc_texture(struct st_context *st, width, height, depth, - usage); + bindings); - stObj->pipe = st->pipe; + DBG("%s returning %d\n", __FUNCTION__, (stObj->pt != NULL)); - DBG("%s - success\n", __FUNCTION__); + return stObj->pt != NULL; } @@ -375,11 +413,14 @@ compress_with_blit(GLcontext * ctx, { const GLuint dstImageOffsets[1] = {0}; struct st_texture_image *stImage = st_texture_image(texImage); - struct pipe_context *pipe = ctx->st->pipe; + 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_texture templ; - struct pipe_texture *src_tex; + 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; struct pipe_transfer *tex_xfer; void *map; @@ -392,7 +433,7 @@ compress_with_blit(GLcontext * ctx, /* get destination surface (in the compressed texture) */ dst_surface = screen->get_tex_surface(screen, stImage->pt, stImage->face, stImage->level, 0, - PIPE_BUFFER_USAGE_GPU_WRITE); + PIPE_BIND_BLIT_DESTINATION); if (!dst_surface) { /* can't render into this format (or other problem) */ return GL_FALSE; @@ -414,19 +455,20 @@ compress_with_blit(GLcontext * ctx, templ.height0 = height; templ.depth0 = 1; templ.last_level = 0; - templ.tex_usage = PIPE_TEXTURE_USAGE_SAMPLER; - src_tex = screen->texture_create(screen, &templ); + 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 = st_cond_flush_get_tex_transfer(st_context(ctx), src_tex, + tex_xfer = pipe_get_transfer(st_context(ctx)->pipe, src_tex, 0, 0, 0, /* face, level are zero */ PIPE_TRANSFER_WRITE, 0, 0, width, height); /* x, y, w, h */ - map = pipe->transfer_map(pipe, tex_xfer); + map = pipe_transfer_map(pipe, tex_xfer); _mesa_texstore(ctx, 2, GL_RGBA, mesa_format, map, /* dest ptr */ @@ -438,12 +480,19 @@ compress_with_blit(GLcontext * ctx, pixels, /* source data */ unpack); /* source data packing */ - pipe->transfer_unmap(pipe, tex_xfer); - pipe->tex_transfer_destroy(pipe, tex_xfer); + 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(ctx->st->blit, - src_tex, /* pipe_texture (src) */ + 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) */ @@ -454,7 +503,8 @@ compress_with_blit(GLcontext * ctx, PIPE_TEX_MIPFILTER_NEAREST); pipe_surface_reference(&dst_surface, NULL); - pipe_texture_reference(&src_tex, NULL); + pipe_resource_reference(&src_tex, NULL); + pipe_sampler_view_reference(&src_view, NULL); return GL_TRUE; } @@ -476,11 +526,10 @@ st_TexImage(GLcontext * ctx, struct gl_texture_image *texImage, GLsizei imageSize, GLboolean compressed_src) { - struct pipe_screen *screen = ctx->st->pipe->screen; + 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); - GLint postConvWidth, postConvHeight; - GLint texelBytes, sizeInBytes; GLuint dstRowStride = 0; struct gl_pixelstore_attrib unpackNB; enum pipe_transfer_usage transfer_usage = 0; @@ -488,6 +537,12 @@ st_TexImage(GLcontext * ctx, DBG("%s target %s level %d %dx%dx%d border %d\n", __FUNCTION__, _mesa_lookup_enum_by_nr(target), level, width, height, depth, border); + /* The Mesa/Gallium state tracker does not implement the imaging extensions + * such as convolution. + */ + assert(!ctx->Extensions.ARB_imaging); + assert(!ctx->Extensions.EXT_convolution); + /* switch to "normal" */ if (stObj->surface_based) { _mesa_clear_texture_object(ctx, texObj); @@ -504,44 +559,22 @@ st_TexImage(GLcontext * ctx, texImage->Border = 0; border = 0; } - - postConvWidth = width; - postConvHeight = height; + else { + assert(texImage->Width == width); + assert(texImage->Height == height); + assert(texImage->Depth == depth); + } stImage->face = _mesa_tex_target_to_face(target); stImage->level = level; -#if FEATURE_convolve - if (ctx->_ImageTransferState & IMAGE_CONVOLUTION_BIT) { - _mesa_adjust_image_for_convolution(ctx, dims, &postConvWidth, - &postConvHeight); - } -#endif - _mesa_set_fetch_functions(texImage, dims); - if (_mesa_is_format_compressed(texImage->TexFormat)) { - /* must be a compressed format */ - texelBytes = 0; - } - else { - texelBytes = _mesa_get_format_bytes(texImage->TexFormat); - - /* Minimum pitch of 32 bytes */ - if (postConvWidth * texelBytes < 32) { - postConvWidth = 32 / texelBytes; - texImage->RowStride = postConvWidth; - } - - /* we'll set RowStride elsewhere when the texture is a "mapped" state */ - /*assert(texImage->RowStride == postConvWidth);*/ - } - /* Release the reference to a potentially orphaned buffer. * Release any old malloced memory. */ if (stImage->pt) { - pipe_texture_reference(&stImage->pt, NULL); + pipe_resource_reference(&stImage->pt, NULL); assert(!texImage->Data); } else if (texImage->Data) { @@ -553,14 +586,13 @@ st_TexImage(GLcontext * ctx, * mipmap. If so, free the old mipmap. */ if (stObj->pt) { - if (stObj->teximage_realloc || - level > (GLint) stObj->pt->last_level || + if (level > (GLint) stObj->pt->last_level || !st_texture_match_image(stObj->pt, &stImage->base, stImage->face, stImage->level)) { DBG("release it\n"); - pipe_texture_reference(&stObj->pt, NULL); + pipe_resource_reference(&stObj->pt, NULL); assert(!stObj->pt); - stObj->teximage_realloc = FALSE; + pipe_sampler_view_reference(&stObj->sampler_view, NULL); } } @@ -570,14 +602,12 @@ st_TexImage(GLcontext * ctx, } if (!stObj->pt) { - guess_and_alloc_texture(ctx->st, stObj, stImage); - if (!stObj->pt) { + if (!guess_and_alloc_texture(st, stObj, stImage)) { /* Probably out of memory. * Try flushing any pending rendering, then retry. */ - st_finish(ctx->st); - guess_and_alloc_texture(ctx->st, stObj, stImage); - if (!stObj->pt) { + st_finish(st); + if (!guess_and_alloc_texture(st, stObj, stImage)) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage"); return; } @@ -586,20 +616,26 @@ st_TexImage(GLcontext * ctx, assert(!stImage->pt); + /* Check if this texture image can live inside the texture object's buffer. + * If so, store the image there. Otherwise the image will temporarily live + * in its own buffer. + */ if (stObj->pt && st_texture_match_image(stObj->pt, &stImage->base, - stImage->face, stImage->level)) { + stImage->face, stImage->level)) { - pipe_texture_reference(&stImage->pt, stObj->pt); + pipe_resource_reference(&stImage->pt, stObj->pt); assert(stImage->pt); } if (!stImage->pt) DBG("XXX: Image did not fit into texture - storing in local memory!\n"); - /* st_CopyTexImage calls this function with pixels == NULL, with - * the expectation that the texture will be set up but nothing - * more will be done. This is where those calls return: + /* Pixel data may come from regular user memory or a PBO. For the later, + * do bounds checking and map the PBO to read pixels data from it. + * + * XXX we should try to use a GPU-accelerated path to copy the image data + * from the PBO to the texture. */ if (compressed_src) { pixels = _mesa_validate_pbo_compressed_teximage(ctx, imageSize, pixels, @@ -612,10 +648,6 @@ st_TexImage(GLcontext * ctx, pixels, unpack, "glTexImage"); } - /* Note: we can't check for pixels==NULL until after we've allocated - * memory for the texture. - */ - /* See if we can do texture compression with a blit/render. */ if (!compressed_src && @@ -624,7 +656,7 @@ st_TexImage(GLcontext * ctx, screen->is_format_supported(screen, stImage->pt->format, stImage->pt->target, - PIPE_TEXTURE_USAGE_RENDER_TARGET, 0)) { + PIPE_BIND_RENDER_TARGET, 0)) { if (!pixels) goto done; @@ -634,36 +666,30 @@ st_TexImage(GLcontext * ctx, } } + /* + * Prepare to store the texture data. Either map the gallium texture buffer + * memory or malloc space for it. + */ if (stImage->pt) { + /* Store the image in the gallium texture memory buffer */ if (format == GL_DEPTH_COMPONENT && util_format_is_depth_and_stencil(stImage->pt->format)) transfer_usage = PIPE_TRANSFER_READ_WRITE; else transfer_usage = PIPE_TRANSFER_WRITE; - texImage->Data = st_texture_image_map(ctx->st, stImage, 0, - transfer_usage, 0, 0, - stImage->base.Width, - stImage->base.Height); + texImage->Data = st_texture_image_map(st, stImage, 0, + transfer_usage, 0, 0, width, height); if(stImage->transfer) dstRowStride = stImage->transfer->stride; } else { /* Allocate regular memory and store the image there temporarily. */ - if (_mesa_is_format_compressed(texImage->TexFormat)) { - sizeInBytes = _mesa_format_image_size(texImage->TexFormat, - texImage->Width, - texImage->Height, - texImage->Depth); - dstRowStride = _mesa_format_row_stride(texImage->TexFormat, width); - assert(dims != 3); - } - else { - dstRowStride = postConvWidth * texelBytes; - sizeInBytes = depth * dstRowStride * postConvHeight; - } + GLuint imageSize = _mesa_format_image_size(texImage->TexFormat, + width, height, depth); + dstRowStride = _mesa_format_row_stride(texImage->TexFormat, width); - texImage->Data = _mesa_align_malloc(sizeInBytes, 16); + texImage->Data = _mesa_align_malloc(imageSize, 16); } if (!texImage->Data) { @@ -671,33 +697,33 @@ st_TexImage(GLcontext * ctx, return; } - if (!pixels) + if (!pixels) { + /* We've allocated texture memory, but have no pixel data - all done. */ goto done; + } DBG("Upload image %dx%dx%d row_len %x pitch %x\n", - width, height, depth, width * texelBytes, dstRowStride); + width, height, depth, width, dstRowStride); - /* Copy data. Would like to know when it's ok for us to eg. use - * the blitter to copy. Or, use the hardware to do the format - * conversion and copy: + /* Copy user texture image into the texture buffer. */ if (compressed_src) { - const GLuint srcImageStride = _mesa_format_row_stride(texImage->TexFormat, width); - if(dstRowStride == srcImageStride) + const GLuint srcRowStride = + _mesa_format_row_stride(texImage->TexFormat, width); + if (dstRowStride == srcRowStride) { memcpy(texImage->Data, pixels, imageSize); - else - { + } + else { char *dst = texImage->Data; const char *src = pixels; GLuint i, bw, bh, lines; _mesa_get_format_block_size(texImage->TexFormat, &bw, &bh); lines = (height + bh - 1) / bh; - for(i = 0; i < lines; ++i) - { - memcpy(dst, src, srcImageStride); + for (i = 0; i < lines; ++i) { + memcpy(dst, src, srcRowStride); dst += dstRowStride; - src += srcImageStride; + src += srcRowStride; } } } @@ -722,12 +748,11 @@ st_TexImage(GLcontext * ctx, if (stImage->pt && i + 1 < depth) { /* unmap this slice */ - st_texture_image_unmap(ctx->st, stImage); + st_texture_image_unmap(st, stImage); /* map next slice of 3D texture */ - texImage->Data = st_texture_image_map(ctx->st, stImage, i + 1, + texImage->Data = st_texture_image_map(st, stImage, i + 1, transfer_usage, 0, 0, - stImage->base.Width, - stImage->base.Height); + width, height); src += srcImageStride; } } @@ -737,7 +762,7 @@ done: _mesa_unmap_teximage_pbo(ctx, unpack); if (stImage->pt && texImage->Data) { - st_texture_image_unmap(ctx->st, stImage); + st_texture_image_unmap(st, stImage); texImage->Data = NULL; } } @@ -814,17 +839,24 @@ decompress_with_blit(GLcontext * ctx, GLenum target, GLint level, struct gl_texture_object *texObj, struct gl_texture_image *texImage) { - struct pipe_context *pipe = ctx->st->pipe; + struct st_context *st = st_context(ctx); + struct pipe_context *pipe = st->pipe; struct pipe_screen *screen = pipe->screen; struct st_texture_image *stImage = st_texture_image(texImage); + struct st_texture_object *stObj = st_texture_object(texObj); + struct pipe_sampler_view *src_view = + st_get_texture_sampler_view(stObj, pipe); const GLuint width = texImage->Width; const GLuint height = texImage->Height; struct pipe_surface *dst_surface; - struct pipe_texture *dst_texture; + struct pipe_resource *dst_texture; struct pipe_transfer *tex_xfer; + unsigned bind = (PIPE_BIND_BLIT_DESTINATION | + PIPE_BIND_RENDER_TARGET | /* util_blit may choose to render */ + PIPE_BIND_TRANSFER_READ); /* create temp / dest surface */ - if (!util_create_rgba_surface(screen, width, height, + if (!util_create_rgba_surface(screen, width, height, bind, &dst_texture, &dst_surface)) { _mesa_problem(ctx, "util_create_rgba_surface() failed " "in decompress_with_blit()"); @@ -832,8 +864,8 @@ decompress_with_blit(GLcontext * ctx, GLenum target, GLint level, } /* blit/render/decompress */ - util_blit_pixels_tex(ctx->st->blit, - stImage->pt, /* pipe_texture (src) */ + util_blit_pixels_tex(st->blit, + src_view, /* pipe_resource (src) */ 0, 0, /* src x0, y0 */ width, height, /* src x1, y1 */ dst_surface, /* pipe_surface (dst) */ @@ -843,7 +875,7 @@ decompress_with_blit(GLcontext * ctx, GLenum target, GLint level, PIPE_TEX_MIPFILTER_NEAREST); /* map the dst_surface so we can read from it */ - tex_xfer = st_cond_flush_get_tex_transfer(st_context(ctx), + tex_xfer = pipe_get_transfer(st_context(ctx)->pipe, dst_texture, 0, 0, 0, PIPE_TRANSFER_READ, 0, 0, width, height); @@ -854,7 +886,7 @@ decompress_with_blit(GLcontext * ctx, GLenum target, GLint level, if (st_equal_formats(stImage->pt->format, format, type)) { /* memcpy */ const uint bytesPerRow = width * util_format_get_blocksize(stImage->pt->format); - ubyte *map = pipe->transfer_map(pipe, tex_xfer); + ubyte *map = pipe_transfer_map(pipe, tex_xfer); GLuint row; for (row = 0; row < height; row++) { GLvoid *dest = _mesa_image_address2d(&ctx->Pack, pixels, width, @@ -862,7 +894,7 @@ decompress_with_blit(GLcontext * ctx, GLenum target, GLint level, memcpy(dest, map, bytesPerRow); map += tex_xfer->stride; } - pipe->transfer_unmap(pipe, tex_xfer); + pipe_transfer_unmap(pipe, tex_xfer); } else { /* format translation via floats */ @@ -886,6 +918,8 @@ decompress_with_blit(GLcontext * ctx, GLenum target, GLint level, _mesa_unmap_pbo_dest(ctx, &ctx->Pack); + pipe->transfer_destroy(pipe, tex_xfer); + /* destroy the temp / dest surface */ util_destroy_rgba_surface(dst_texture, dst_surface); } @@ -902,6 +936,7 @@ st_get_tex_image(GLcontext * ctx, GLenum target, GLint level, struct gl_texture_object *texObj, struct gl_texture_image *texImage, GLboolean compressed_dst) { + struct st_context *st = st_context(ctx); struct st_texture_image *stImage = st_texture_image(texImage); const GLuint dstImageStride = _mesa_image_image_stride(&ctx->Pack, texImage->Width, texImage->Height, @@ -910,7 +945,7 @@ st_get_tex_image(GLcontext * ctx, GLenum target, GLint level, GLubyte *dest; if (stImage->pt && - util_format_is_compressed(stImage->pt->format) && + util_format_is_s3tc(stImage->pt->format) && !compressed_dst) { /* Need to decompress the texture. * We'll do this by rendering a textured quad. @@ -926,16 +961,14 @@ st_get_tex_image(GLcontext * ctx, GLenum target, GLint level, /* Image is stored in hardware format in a buffer managed by the * kernel. Need to explicitly map and unmap it. */ - unsigned face = _mesa_tex_target_to_face(target); - - st_teximage_flush_before_map(ctx->st, stImage->pt, face, level, - PIPE_TRANSFER_READ); - - texImage->Data = st_texture_image_map(ctx->st, stImage, 0, + texImage->Data = st_texture_image_map(st, stImage, 0, PIPE_TRANSFER_READ, 0, 0, stImage->base.Width, stImage->base.Height); - texImage->RowStride = stImage->transfer->stride / util_format_get_blocksize(stImage->pt->format); + /* compute stride in texels from stride in bytes */ + texImage->RowStride = stImage->transfer->stride + * util_format_get_blockwidth(stImage->pt->format) + / util_format_get_blocksize(stImage->pt->format); } else { /* Otherwise, the image should actually be stored in @@ -966,9 +999,9 @@ st_get_tex_image(GLcontext * ctx, GLenum target, GLint level, if (stImage->pt && i + 1 < depth) { /* unmap this slice */ - st_texture_image_unmap(ctx->st, stImage); + st_texture_image_unmap(st, stImage); /* map next slice of 3D texture */ - texImage->Data = st_texture_image_map(ctx->st, stImage, i + 1, + texImage->Data = st_texture_image_map(st, stImage, i + 1, PIPE_TRANSFER_READ, 0, 0, stImage->base.Width, stImage->base.Height); @@ -980,7 +1013,7 @@ st_get_tex_image(GLcontext * ctx, GLenum target, GLint level, /* Unmap */ if (stImage->pt) { - st_texture_image_unmap(ctx->st, stImage); + st_texture_image_unmap(st, stImage); texImage->Data = NULL; } } @@ -1018,7 +1051,8 @@ st_TexSubimage(GLcontext *ctx, GLint dims, GLenum target, GLint level, struct gl_texture_object *texObj, struct gl_texture_image *texImage) { - struct pipe_screen *screen = ctx->st->pipe->screen; + 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 = @@ -1045,7 +1079,7 @@ st_TexSubimage(GLcontext *ctx, GLint dims, GLenum target, GLint level, screen->is_format_supported(screen, stImage->pt->format, stImage->pt->target, - PIPE_TEXTURE_USAGE_RENDER_TARGET, 0)) { + PIPE_BIND_RENDER_TARGET, 0)) { if (compress_with_blit(ctx, target, level, xoffset, yoffset, zoffset, width, height, depth, @@ -1058,17 +1092,13 @@ st_TexSubimage(GLcontext *ctx, GLint dims, GLenum target, GLint level, * from uploading the buffer under us. */ if (stImage->pt) { - unsigned face = _mesa_tex_target_to_face(target); - if (format == GL_DEPTH_COMPONENT && util_format_is_depth_and_stencil(stImage->pt->format)) transfer_usage = PIPE_TRANSFER_READ_WRITE; else transfer_usage = PIPE_TRANSFER_WRITE; - st_teximage_flush_before_map(ctx->st, stImage->pt, face, level, - transfer_usage); - texImage->Data = st_texture_image_map(ctx->st, stImage, zoffset, + texImage->Data = st_texture_image_map(st, stImage, zoffset, transfer_usage, xoffset, yoffset, width, height); @@ -1096,9 +1126,9 @@ st_TexSubimage(GLcontext *ctx, GLint dims, GLenum target, GLint level, if (stImage->pt && i + 1 < depth) { /* unmap this slice */ - st_texture_image_unmap(ctx->st, stImage); + st_texture_image_unmap(st, stImage); /* map next slice of 3D texture */ - texImage->Data = st_texture_image_map(ctx->st, stImage, + texImage->Data = st_texture_image_map(st, stImage, zoffset + i + 1, transfer_usage, xoffset, yoffset, @@ -1111,7 +1141,7 @@ done: _mesa_unmap_teximage_pbo(ctx, packing); if (stImage->pt && texImage->Data) { - st_texture_image_unmap(ctx->st, stImage); + st_texture_image_unmap(st, stImage); texImage->Data = NULL; } } @@ -1182,18 +1212,17 @@ st_CompressedTexSubImage2D(GLcontext *ctx, GLenum target, GLint level, struct gl_texture_object *texObj, struct gl_texture_image *texImage) { + struct st_context *st = st_context(ctx); struct st_texture_image *stImage = st_texture_image(texImage); int srcBlockStride; int dstBlockStride; int y; - enum pipe_format pformat= stImage->pt->format; + enum pipe_format pformat; if (stImage->pt) { - unsigned face = _mesa_tex_target_to_face(target); + pformat = stImage->pt->format; - st_teximage_flush_before_map(ctx->st, stImage->pt, face, level, - PIPE_TRANSFER_WRITE); - texImage->Data = st_texture_image_map(ctx->st, stImage, 0, + texImage->Data = st_texture_image_map(st, stImage, 0, PIPE_TRANSFER_WRITE, xoffset, yoffset, width, height); @@ -1225,7 +1254,7 @@ st_CompressedTexSubImage2D(GLcontext *ctx, GLenum target, GLint level, } if (stImage->pt) { - st_texture_image_unmap(ctx->st, stImage); + st_texture_image_unmap(st, stImage); texImage->Data = NULL; } } @@ -1261,7 +1290,8 @@ fallback_copy_texsubimage(GLcontext *ctx, GLenum target, GLint level, GLint srcX, GLint srcY, GLsizei width, GLsizei height) { - struct pipe_context *pipe = ctx->st->pipe; + struct st_context *st = st_context(ctx); + struct pipe_context *pipe = st->pipe; struct pipe_transfer *src_trans; GLvoid *texDest; enum pipe_transfer_usage transfer_usage; @@ -1275,7 +1305,7 @@ fallback_copy_texsubimage(GLcontext *ctx, GLenum target, GLint level, srcY = strb->Base.Height - srcY - height; } - src_trans = st_cond_flush_get_tex_transfer( st_context(ctx), + src_trans = pipe_get_transfer(st_context(ctx)->pipe, strb->texture, 0, 0, 0, PIPE_TRANSFER_READ, @@ -1289,10 +1319,7 @@ fallback_copy_texsubimage(GLcontext *ctx, GLenum target, GLint level, else transfer_usage = PIPE_TRANSFER_WRITE; - st_teximage_flush_before_map(ctx->st, stImage->pt, 0, 0, - transfer_usage); - - texDest = st_texture_image_map(ctx->st, stImage, 0, transfer_usage, + texDest = st_texture_image_map(st, stImage, 0, transfer_usage, destX, destY, width, height); if (baseFormat == GL_DEPTH_COMPONENT || @@ -1367,8 +1394,8 @@ fallback_copy_texsubimage(GLcontext *ctx, GLenum target, GLint level, free(tempSrc); } - st_texture_image_unmap(ctx->st, stImage); - pipe->tex_transfer_destroy(pipe, src_trans); + st_texture_image_unmap(st, stImage); + pipe->transfer_destroy(pipe, src_trans); } @@ -1457,14 +1484,14 @@ st_copy_texsubimage(GLcontext *ctx, &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; struct gl_texture_object *texObj = _mesa_select_tex_object(ctx, texUnit, target); - struct st_texture_object *stObj = st_texture_object(texObj); struct gl_texture_image *texImage = _mesa_select_tex_image(ctx, texObj, target, level); struct st_texture_image *stImage = st_texture_image(texImage); const GLenum texBaseFormat = texImage->_BaseFormat; struct gl_framebuffer *fb = ctx->ReadBuffer; struct st_renderbuffer *strb; - struct pipe_context *pipe = ctx->st->pipe; + struct st_context *st = st_context(ctx); + struct pipe_context *pipe = st->pipe; struct pipe_screen *screen = pipe->screen; enum pipe_format dest_format, src_format; GLboolean use_fallback = GL_TRUE; @@ -1473,12 +1500,9 @@ st_copy_texsubimage(GLcontext *ctx, struct pipe_surface *dest_surface = NULL; GLboolean do_flip = (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP); - /* any rendering in progress must flushed before we grab the fb image */ - st_flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL); - /* make sure finalize_textures has been called? */ - if (0) st_validate_state(ctx->st); + if (0) st_validate_state(st); /* determine if copying depth or color data */ if (texBaseFormat == GL_DEPTH_COMPONENT || @@ -1545,8 +1569,7 @@ st_copy_texsubimage(GLcontext *ctx, if (ctx->_ImageTransferState == 0x0) { - if (pipe->surface_copy && - matching_base_formats && + if (matching_base_formats && src_format == dest_format && !do_flip) { @@ -1555,7 +1578,7 @@ st_copy_texsubimage(GLcontext *ctx, dest_surface = screen->get_tex_surface(screen, stImage->pt, stImage->face, stImage->level, destZ, - PIPE_BUFFER_USAGE_GPU_WRITE); + PIPE_BIND_BLIT_DESTINATION); /* for surface_copy(), y=0=top, always */ pipe->surface_copy(pipe, @@ -1574,11 +1597,11 @@ st_copy_texsubimage(GLcontext *ctx, texBaseFormat != GL_DEPTH_STENCIL && screen->is_format_supported(screen, src_format, PIPE_TEXTURE_2D, - PIPE_TEXTURE_USAGE_SAMPLER, + PIPE_BIND_SAMPLER_VIEW, 0) && screen->is_format_supported(screen, dest_format, PIPE_TEXTURE_2D, - PIPE_TEXTURE_USAGE_RENDER_TARGET, + PIPE_BIND_RENDER_TARGET, 0)) { /* draw textured quad to do the copy */ GLint srcY0, srcY1; @@ -1586,7 +1609,7 @@ st_copy_texsubimage(GLcontext *ctx, dest_surface = screen->get_tex_surface(screen, stImage->pt, stImage->face, stImage->level, destZ, - PIPE_BUFFER_USAGE_GPU_WRITE); + PIPE_BIND_BLIT_DESTINATION); if (do_flip) { srcY1 = strb->Base.Height - srcY - height; @@ -1596,9 +1619,9 @@ st_copy_texsubimage(GLcontext *ctx, srcY0 = srcY; srcY1 = srcY0 + height; } - util_blit_pixels_writemask(ctx->st->blit, + util_blit_pixels_writemask(st->blit, strb->surface, - st_renderbuffer_get_sampler_view(strb, pipe), + st_get_renderbuffer_sampler_view(strb, pipe), srcX, srcY0, srcX + width, srcY1, dest_surface, @@ -1712,28 +1735,37 @@ st_CopyTexSubImage3D(GLcontext * ctx, GLenum target, GLint level, } +/** + * Copy image data from stImage into the texture object 'stObj' at level + * 'dstLevel'. + */ static void copy_image_data_to_texture(struct st_context *st, struct st_texture_object *stObj, GLuint dstLevel, struct st_texture_image *stImage) { + /* debug checks */ + { + const struct gl_texture_image *dstImage = + stObj->base.Image[stImage->face][stImage->level]; + assert(dstImage); + assert(dstImage->Width == stImage->base.Width); + assert(dstImage->Height == stImage->base.Height); + assert(dstImage->Depth == stImage->base.Depth); + } + if (stImage->pt) { /* Copy potentially with the blitter: */ st_texture_image_copy(st->pipe, stObj->pt, dstLevel, /* dest texture, level */ - stImage->pt, /* src texture */ + stImage->pt, stImage->level, /* src texture, level */ stImage->face); - pipe_texture_reference(&stImage->pt, NULL); + pipe_resource_reference(&stImage->pt, NULL); } else if (stImage->base.Data) { - /* More straightforward upload. - */ - st_teximage_flush_before_map(st, stObj->pt, stImage->face, dstLevel, - PIPE_TRANSFER_WRITE); - st_texture_image_data(st, stObj->pt, stImage->face, @@ -1748,7 +1780,7 @@ copy_image_data_to_texture(struct st_context *st, stImage->base.Data = NULL; } - pipe_texture_reference(&stImage->pt, stObj->pt); + pipe_resource_reference(&stImage->pt, stObj->pt); } @@ -1760,15 +1792,14 @@ copy_image_data_to_texture(struct st_context *st, GLboolean st_finalize_texture(GLcontext *ctx, struct pipe_context *pipe, - struct gl_texture_object *tObj, - GLboolean *needFlush) + struct gl_texture_object *tObj) { + struct st_context *st = st_context(ctx); struct st_texture_object *stObj = st_texture_object(tObj); const GLuint nr_faces = (stObj->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1; - GLuint blockSize, face; + GLuint face; struct st_texture_image *firstImage; - - *needFlush = GL_FALSE; + enum pipe_format firstImageFormat; if (stObj->base._Complete) { /* The texture is complete and we know exactly how many mipmap levels @@ -1781,10 +1812,11 @@ st_finalize_texture(GLcontext *ctx, stObj->base.MinFilter == GL_NEAREST) stObj->lastLevel = stObj->base.BaseLevel; else - stObj->lastLevel = stObj->base._MaxLevel - stObj->base.BaseLevel; + stObj->lastLevel = stObj->base._MaxLevel; } firstImage = st_texture_image(stObj->base.Image[0][stObj->base.BaseLevel]); + assert(firstImage); /* If both firstImage and stObj point to a texture which can contain * all active images, favour firstImage. Note that because of the @@ -1794,45 +1826,46 @@ st_finalize_texture(GLcontext *ctx, if (firstImage->pt && firstImage->pt != stObj->pt && firstImage->pt->last_level >= stObj->lastLevel) { - pipe_texture_reference(&stObj->pt, firstImage->pt); + pipe_resource_reference(&stObj->pt, firstImage->pt); + pipe_sampler_view_reference(&stObj->sampler_view, NULL); } - /* bytes per pixel block (blocks are usually 1x1) */ - blockSize = _mesa_get_format_bytes(firstImage->base.TexFormat); + /* Find gallium format for the Mesa texture */ + firstImageFormat = st_mesa_format_to_pipe_format(firstImage->base.TexFormat); /* If we already have a gallium texture, check that it matches the texture * object's format, target, size, num_levels, etc. */ if (stObj->pt) { - const enum pipe_format fmt = - st_mesa_format_to_pipe_format(firstImage->base.TexFormat); if (stObj->pt->target != gl_target_to_pipe(stObj->base.Target) || - stObj->pt->format != fmt || + stObj->pt->format != firstImageFormat || stObj->pt->last_level < stObj->lastLevel || - stObj->pt->width0 != firstImage->base.Width2 || - stObj->pt->height0 != firstImage->base.Height2 || - stObj->pt->depth0 != firstImage->base.Depth2) + stObj->pt->width0 != stObj->width0 || + stObj->pt->height0 != stObj->height0 || + stObj->pt->depth0 != stObj->depth0) { - pipe_texture_reference(&stObj->pt, NULL); - ctx->st->dirty.st |= ST_NEW_FRAMEBUFFER; + /* The gallium texture does not match the Mesa texture so delete the + * gallium texture now. We'll make a new one below. + */ + pipe_resource_reference(&stObj->pt, NULL); + pipe_sampler_view_reference(&stObj->sampler_view, NULL); + st->dirty.st |= ST_NEW_FRAMEBUFFER; } } /* May need to create a new gallium texture: */ if (!stObj->pt) { - const enum pipe_format fmt = - st_mesa_format_to_pipe_format(firstImage->base.TexFormat); - GLuint usage = default_usage(fmt); + GLuint bindings = default_bindings(st, firstImageFormat); - stObj->pt = st_texture_create(ctx->st, + stObj->pt = st_texture_create(st, gl_target_to_pipe(stObj->base.Target), - fmt, + firstImageFormat, stObj->lastLevel, - firstImage->base.Width2, - firstImage->base.Height2, - firstImage->base.Depth2, - usage); + stObj->width0, + stObj->height0, + stObj->depth0, + bindings); if (!stObj->pt) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage"); @@ -1844,15 +1877,14 @@ st_finalize_texture(GLcontext *ctx, */ for (face = 0; face < nr_faces; face++) { GLuint level; - for (level = 0; level <= stObj->lastLevel; level++) { + for (level = stObj->base.BaseLevel; level <= stObj->lastLevel; level++) { struct st_texture_image *stImage = - st_texture_image(stObj->base.Image[face][stObj->base.BaseLevel + level]); + st_texture_image(stObj->base.Image[face][level]); /* Need to import images in main memory or held in other textures. */ if (stImage && stObj->pt != stImage->pt) { - copy_image_data_to_texture(ctx->st, stObj, level, stImage); - *needFlush = GL_TRUE; + copy_image_data_to_texture(st, stObj, level, stImage); } } }