X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fstate_tracker%2Fst_texture.c;h=d58803991a545690a7539ea36d13d659d1aace85;hb=d09a19bf6e09eb0c8908e9b5378962ac17bcbc4c;hp=63cfe5fc1633a3e563f9180ce45bf237233476d5;hpb=42330d929c3bdc953948294906c49ee693818b47;p=mesa.git diff --git a/src/mesa/state_tracker/st_texture.c b/src/mesa/state_tracker/st_texture.c index 63cfe5fc163..d58803991a5 100644 --- a/src/mesa/state_tracker/st_texture.c +++ b/src/mesa/state_tracker/st_texture.c @@ -30,7 +30,9 @@ #include "st_public.h" #include "st_texture.h" #include "st_cb_fbo.h" +#include "st_inlines.h" #include "main/enums.h" +#include "main/texobj.h" #include "main/teximage.h" #include "main/texstore.h" @@ -40,7 +42,6 @@ #include "pipe/p_context.h" #include "pipe/p_defines.h" #include "pipe/p_inlines.h" -#include "pipe/p_inlines.h" #include "util/u_rect.h" @@ -79,7 +80,6 @@ st_texture_create(struct st_context *st, GLuint width0, GLuint height0, GLuint depth0, - GLuint compress_byte, GLuint usage ) { struct pipe_texture pt, *newtex; @@ -102,23 +102,19 @@ st_texture_create(struct st_context *st, pt.width[0] = width0; pt.height[0] = height0; pt.depth[0] = depth0; - pt.compressed = compress_byte ? 1 : 0; pf_get_block(format, &pt.block); pt.tex_usage = usage; newtex = screen->texture_create(screen, &pt); - assert(!newtex || newtex->refcount == 1); + assert(!newtex || pipe_is_referenced(&newtex->reference)); return newtex; } /** - * Check if a texture image be pulled into a unified mipmap texture. - * This mirrors the completeness test in a lot of ways. - * - * Not sure whether I want to pass gl_texture_image here. + * Check if a texture image can be pulled into a unified mipmap texture. */ GLboolean st_texture_match_image(const struct pipe_texture *pt, @@ -130,13 +126,13 @@ st_texture_match_image(const struct pipe_texture *pt, if (image->Border) return GL_FALSE; - if (st_mesa_format_to_pipe_format(image->TexFormat->MesaFormat) != pt->format || - image->IsCompressed != pt->compressed) + /* Check if this image's format matches the established texture's format. + */ + if (st_mesa_format_to_pipe_format(image->TexFormat->MesaFormat) != pt->format) return GL_FALSE; - /* Test image dimensions against the base level image adjusted for - * minification. This will also catch images not present in the - * texture, changed targets, etc. + /* Test if this image's size matches what's expected in the + * established texture. */ if (image->Width != pt->width[level] || image->Height != pt->height[level] || @@ -191,19 +187,21 @@ st_texture_image_offset(const struct pipe_texture * pt, */ GLubyte * st_texture_image_map(struct st_context *st, struct st_texture_image *stImage, - GLuint zoffset, - GLuint flags ) + GLuint zoffset, enum pipe_transfer_usage usage, + GLuint x, GLuint y, GLuint w, GLuint h) { - struct pipe_screen *screen = st->pipe->screen; + struct pipe_context *pipe = st->pipe; + struct pipe_screen *screen = pipe->screen; struct pipe_texture *pt = stImage->pt; + DBG("%s \n", __FUNCTION__); - stImage->surface = screen->get_tex_surface(screen, pt, stImage->face, - stImage->level, zoffset, - flags); + stImage->transfer = st_no_flush_get_tex_transfer(st, pt, stImage->face, + stImage->level, zoffset, + usage, x, y, w, h); - if (stImage->surface) - return screen->surface_map(screen, stImage->surface, flags); + if (stImage->transfer) + return screen->transfer_map(screen, stImage->transfer); else return NULL; } @@ -217,9 +215,9 @@ st_texture_image_unmap(struct st_context *st, DBG("%s\n", __FUNCTION__); - screen->surface_unmap(screen, stImage->surface); + screen->transfer_unmap(screen, stImage->transfer); - pipe_surface_reference(&stImage->surface, NULL); + screen->tex_transfer_destroy(stImage->transfer); } @@ -234,13 +232,13 @@ st_texture_image_unmap(struct st_context *st, */ static void st_surface_data(struct pipe_context *pipe, - struct pipe_surface *dst, + struct pipe_transfer *dst, unsigned dstx, unsigned dsty, const void *src, unsigned src_stride, unsigned srcx, unsigned srcy, unsigned width, unsigned height) { struct pipe_screen *screen = pipe->screen; - void *map = screen->surface_map(screen, dst, PIPE_BUFFER_USAGE_CPU_WRITE); + void *map = screen->transfer_map(screen, dst); pipe_copy_rect(map, &dst->block, @@ -250,39 +248,43 @@ st_surface_data(struct pipe_context *pipe, src, src_stride, srcx, srcy); - screen->surface_unmap(screen, dst); + screen->transfer_unmap(screen, dst); } /* Upload data for a particular image. */ void -st_texture_image_data(struct pipe_context *pipe, +st_texture_image_data(struct st_context *st, struct pipe_texture *dst, GLuint face, GLuint level, void *src, GLuint src_row_stride, GLuint src_image_stride) { + struct pipe_context *pipe = st->pipe; struct pipe_screen *screen = pipe->screen; GLuint depth = dst->depth[level]; GLuint i; const GLubyte *srcUB = src; - struct pipe_surface *dst_surface; + struct pipe_transfer *dst_transfer; DBG("%s\n", __FUNCTION__); + for (i = 0; i < depth; i++) { - dst_surface = screen->get_tex_surface(screen, dst, face, level, i, - PIPE_BUFFER_USAGE_CPU_WRITE); + dst_transfer = st_no_flush_get_tex_transfer(st, dst, face, level, i, + PIPE_TRANSFER_WRITE, 0, 0, + dst->width[level], + dst->height[level]); - st_surface_data(pipe, dst_surface, + st_surface_data(pipe, dst_transfer, 0, 0, /* dstx, dsty */ srcUB, src_row_stride, 0, 0, /* source x, y */ dst->width[level], dst->height[level]); /* width, height */ - screen->tex_surface_release(screen, &dst_surface); + screen->tex_transfer_destroy(dst_transfer); srcUB += src_image_stride; } @@ -341,37 +343,106 @@ st_texture_image_copy(struct pipe_context *pipe, PIPE_BUFFER_USAGE_GPU_READ); pipe->surface_copy(pipe, - FALSE, dst_surface, 0, 0, /* destX, Y */ src_surface, 0, 0, /* srcX, Y */ width, height); - screen->tex_surface_release(screen, &src_surface); - screen->tex_surface_release(screen, &dst_surface); + pipe_surface_reference(&src_surface, NULL); + pipe_surface_reference(&dst_surface, NULL); } } -/** Bind a pipe surface for use as a texture image */ + +/** + * Bind a pipe surface to a texture object. After the call, + * the texture object is marked dirty and will be (re-)validated. + * + * If this is the first surface bound, the texture object is said to + * switch from normal to surface based. It will be cleared first in + * this case. + * + * \param ps pipe surface to be unbound + * \param target texture target + * \param level image level + * \param format internal format of the texture + */ int -st_set_teximage(struct pipe_texture *pt, int target) +st_bind_texture_surface(struct pipe_surface *ps, int target, int level, + enum pipe_format format) { GET_CURRENT_CONTEXT(ctx); const GLuint unit = ctx->Texture.CurrentUnit; struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; struct gl_texture_object *texObj; struct gl_texture_image *texImage; + struct st_texture_object *stObj; struct st_texture_image *stImage; - int internalFormat; + GLenum internalFormat; - switch (pt->format) { - case PIPE_FORMAT_A8R8G8B8_UNORM: - internalFormat = GL_RGBA8; + switch (target) { + case ST_TEXTURE_2D: + target = GL_TEXTURE_2D; + break; + case ST_TEXTURE_RECT: + target = GL_TEXTURE_RECTANGLE_ARB; break; default: return 0; - }; + } + + /* map pipe format to base format for now */ + if (pf_get_component_bits(format, PIPE_FORMAT_COMP_A) > 0) + internalFormat = GL_RGBA; + else + internalFormat = GL_RGB; + + texObj = _mesa_select_tex_object(ctx, texUnit, target); + _mesa_lock_texture(ctx, texObj); + + stObj = st_texture_object(texObj); + /* switch to surface based */ + if (!stObj->surface_based) { + _mesa_clear_texture_object(ctx, texObj); + stObj->surface_based = GL_TRUE; + } + + texImage = _mesa_get_tex_image(ctx, texObj, target, level); + stImage = st_texture_image(texImage); + + _mesa_init_teximage_fields(ctx, target, texImage, + ps->width, ps->height, 1, 0, internalFormat); + texImage->TexFormat = st_ChooseTextureFormat(ctx, internalFormat, + GL_RGBA, GL_UNSIGNED_BYTE); + _mesa_set_fetch_functions(texImage, 2); + pipe_texture_reference(&stImage->pt, ps->texture); + + _mesa_dirty_texobj(ctx, texObj, GL_TRUE); + _mesa_unlock_texture(ctx, texObj); + + return 1; +} + + +/** + * Unbind a pipe surface from a texture object. After the call, + * the texture object is marked dirty and will be (re-)validated. + * + * \param ps pipe surface to be unbound + * \param target texture target + * \param level image level + */ +int +st_unbind_texture_surface(struct pipe_surface *ps, int target, int level) +{ + GET_CURRENT_CONTEXT(ctx); + const GLuint unit = ctx->Texture.CurrentUnit; + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; + struct gl_texture_object *texObj; + struct gl_texture_image *texImage; + struct st_texture_object *stObj; + struct st_texture_image *stImage; switch (target) { case ST_TEXTURE_2D: @@ -385,21 +456,28 @@ st_set_teximage(struct pipe_texture *pt, int target) } texObj = _mesa_select_tex_object(ctx, texUnit, target); - texImage = _mesa_get_tex_image(ctx, texObj, target, 0); + + _mesa_lock_texture(ctx, texObj); + + texImage = _mesa_get_tex_image(ctx, texObj, target, level); + stObj = st_texture_object(texObj); stImage = st_texture_image(texImage); - - _mesa_init_teximage_fields(ctx, GL_TEXTURE_2D, texImage, pt->width[0], - pt->height[0], 1, 0, internalFormat); - texImage->TexFormat = st_ChooseTextureFormat(ctx, internalFormat, GL_RGBA, - GL_UNSIGNED_BYTE); - _mesa_set_fetch_functions(texImage, 2); + /* Make sure the pipe surface is still bound. The texture object is still + * considered surface based even if this is the last bound surface. */ + if (stImage->pt == ps->texture) { + pipe_texture_reference(&stImage->pt, NULL); + _mesa_clear_texture_image(ctx, texImage); - pipe_texture_reference(&stImage->pt, pt); + _mesa_dirty_texobj(ctx, texObj, GL_TRUE); + } + _mesa_unlock_texture(ctx, texObj); + return 1; } + /** Redirect rendering into stfb's surface to a texture image */ int st_bind_teximage(struct st_framebuffer *stfb, uint surfIndex, @@ -427,7 +505,7 @@ st_bind_teximage(struct st_framebuffer *stfb, uint surfIndex, } if (target == ST_TEXTURE_2D) { - texObj = texUnit->Current2D; + texObj = texUnit->CurrentTex[TEXTURE_2D_INDEX]; texImage = _mesa_get_tex_image(ctx, texObj, GL_TEXTURE_2D, level); stImage = st_texture_image(texImage); } @@ -486,3 +564,20 @@ st_release_teximage(struct st_framebuffer *stfb, uint surfIndex, return 1; } + +void +st_teximage_flush_before_map(struct st_context *st, + struct pipe_texture *pt, + unsigned int face, + unsigned int level, + enum pipe_transfer_usage usage) +{ + struct pipe_context *pipe = st->pipe; + unsigned referenced = + pipe->is_texture_referenced(pipe, pt, face, level); + + if (referenced && ((referenced & PIPE_REFERENCED_FOR_WRITE) || + usage == PIPE_TRANSFER_WRITE || + usage == PIPE_TRANSFER_READ_WRITE)) + st_flush(st, PIPE_FLUSH_RENDER_CACHE, NULL); +}