static void finalize_textures(struct st_context *st) { struct gl_context *ctx = st->ctx; struct gl_fragment_program *fprog = ctx->FragmentProgram._Current; const GLboolean prev_missing_textures = st->missing_textures; GLuint su; st->missing_textures = GL_FALSE; for (su = 0; su < ctx->Const.MaxTextureCoordUnits; su++) { if (fprog->Base.SamplersUsed & (1 << su)) { const GLuint texUnit = fprog->Base.SamplerUnits[su]; struct gl_texture_object *texObj = ctx->Texture.Unit[texUnit]._Current; if (texObj) { GLboolean retval; retval = st_finalize_texture(ctx, st->pipe, texObj); if (!retval) { /* out of mem */ st->missing_textures = GL_TRUE; continue; } } } } if (prev_missing_textures != st->missing_textures) st->dirty.st |= ST_NEW_FRAGMENT_PROGRAM; }
static void update_textures(struct st_context *st) { struct gl_vertex_program *vprog = st->ctx->VertexProgram._Current; struct gl_fragment_program *fprog = st->ctx->FragmentProgram._Current; const GLbitfield samplersUsed = (vprog->Base.SamplersUsed | fprog->Base.SamplersUsed); GLuint su; st->state.num_textures = 0; /* loop over sampler units (aka tex image units) */ for (su = 0; su < st->ctx->Const.MaxTextureImageUnits; su++) { struct pipe_texture *pt = NULL; if (samplersUsed & (1 << su)) { struct gl_texture_object *texObj; struct st_texture_object *stObj; GLboolean flush, retval; GLuint texUnit; if (fprog->Base.SamplersUsed & (1 << su)) texUnit = fprog->Base.SamplerUnits[su]; else texUnit = vprog->Base.SamplerUnits[su]; texObj = st->ctx->Texture.Unit[texUnit]._Current; if (!texObj) { texObj = st_get_default_texture(st); } stObj = st_texture_object(texObj); retval = st_finalize_texture(st->ctx, st->pipe, texObj, &flush); if (!retval) { /* out of mem */ continue; } st->state.num_textures = su + 1; pt = st_get_stobj_texture(stObj); } /* if (pt) { printf("%s su=%u non-null\n", __FUNCTION__, su); } else { printf("%s su=%u null\n", __FUNCTION__, su); } */ pipe_texture_reference(&st->state.sampler_texture[su], pt); } cso_set_sampler_textures(st->cso_context, st->state.num_textures, st->state.sampler_texture); }
static GLboolean update_single_texture(struct st_context *st, struct pipe_sampler_view **sampler_view, GLuint texUnit) { struct pipe_context *pipe = st->pipe; struct gl_context *ctx = st->ctx; const struct gl_sampler_object *samp; struct gl_texture_object *texObj; struct st_texture_object *stObj; enum pipe_format view_format; GLboolean retval; samp = _mesa_get_samplerobj(ctx, texUnit); texObj = ctx->Texture.Unit[texUnit]._Current; if (!texObj) { texObj = _mesa_get_fallback_texture(ctx, TEXTURE_2D_INDEX); samp = &texObj->Sampler; } stObj = st_texture_object(texObj); retval = st_finalize_texture(ctx, st->pipe, texObj); if (!retval) { /* out of mem */ return GL_FALSE; } /* Determine the format of the texture sampler view */ if (texObj->Target == GL_TEXTURE_BUFFER) { view_format = st_mesa_format_to_pipe_format(stObj->base._BufferObjectFormat); } else { view_format = stObj->pt->format; /* If sRGB decoding is off, use the linear format */ if (samp->sRGBDecode == GL_SKIP_DECODE_EXT) { view_format = util_format_linear(view_format); } } /* if sampler view has changed dereference it */ if (stObj->sampler_view) { if (check_sampler_swizzle(stObj->sampler_view, stObj->base._Swizzle, stObj->base.DepthMode) || (view_format != stObj->sampler_view->format) || stObj->base.BaseLevel != stObj->sampler_view->u.tex.first_level) { pipe_sampler_view_reference(&stObj->sampler_view, NULL); } } *sampler_view = st_get_texture_sampler_view_from_stobj(stObj, pipe, samp, view_format); return GL_TRUE; }
static GLboolean update_single_texture(struct st_context *st, struct pipe_sampler_view **sampler_view, GLuint texUnit, unsigned glsl_version) { struct gl_context *ctx = st->ctx; const struct gl_sampler_object *samp; struct gl_texture_object *texObj; struct st_texture_object *stObj; enum pipe_format view_format; GLboolean retval; samp = _mesa_get_samplerobj(ctx, texUnit); texObj = ctx->Texture.Unit[texUnit]._Current; if (!texObj) { texObj = _mesa_get_fallback_texture(ctx, TEXTURE_2D_INDEX); samp = &texObj->Sampler; } stObj = st_texture_object(texObj); retval = st_finalize_texture(ctx, st->pipe, texObj); if (!retval) { /* out of mem */ return GL_FALSE; } /* Determine the format of the texture sampler view */ if (texObj->Target == GL_TEXTURE_BUFFER) { view_format = st_mesa_format_to_pipe_format(st, stObj->base._BufferObjectFormat); } else { view_format = stObj->surface_based ? stObj->surface_format : stObj->pt->format; /* If sRGB decoding is off, use the linear format */ if (samp->sRGBDecode == GL_SKIP_DECODE_EXT) { view_format = util_format_linear(view_format); } } *sampler_view = st_get_texture_sampler_view_from_stobj(st, stObj, view_format, glsl_version); return GL_TRUE; }
static GLboolean update_single_texture(struct st_context *st, struct pipe_sampler_view **sampler_view, GLuint texUnit, unsigned glsl_version) { struct gl_context *ctx = st->ctx; const struct gl_sampler_object *samp; struct gl_texture_object *texObj; struct st_texture_object *stObj; GLboolean retval; samp = _mesa_get_samplerobj(ctx, texUnit); texObj = ctx->Texture.Unit[texUnit]._Current; if (!texObj) { texObj = _mesa_get_fallback_texture(ctx, TEXTURE_2D_INDEX); samp = &texObj->Sampler; } stObj = st_texture_object(texObj); retval = st_finalize_texture(ctx, st->pipe, texObj); if (!retval) { /* out of mem */ return GL_FALSE; } /* Check a few pieces of state outside the texture object to see if we * need to force revalidation. */ if (stObj->prev_glsl_version != glsl_version || stObj->prev_sRGBDecode != samp->sRGBDecode) { st_texture_release_all_sampler_views(st, stObj); stObj->prev_glsl_version = glsl_version; stObj->prev_sRGBDecode = samp->sRGBDecode; } if (texObj->TargetIndex == TEXTURE_EXTERNAL_INDEX && stObj->pt->screen->resource_changed) stObj->pt->screen->resource_changed(stObj->pt->screen, stObj->pt); *sampler_view = st_get_texture_sampler_view_from_stobj(st, stObj, samp, glsl_version); return GL_TRUE; }
/** * Called by ctx->Driver.RenderTexture */ static void st_render_texture(struct gl_context *ctx, struct gl_framebuffer *fb, struct gl_renderbuffer_attachment *att) { struct st_context *st = st_context(ctx); struct pipe_context *pipe = st->pipe; struct gl_renderbuffer *rb = att->Renderbuffer; struct st_renderbuffer *strb = st_renderbuffer(rb); struct pipe_resource *pt; if (!st_finalize_texture(ctx, pipe, att->Texture)) return; pt = st_get_texobj_resource(att->Texture); assert(pt); /* point renderbuffer at texobject */ strb->is_rtt = TRUE; strb->rtt_face = att->CubeMapFace; strb->rtt_slice = att->Zoffset; strb->rtt_layered = att->Layered; pipe_resource_reference(&strb->texture, pt); pipe_surface_release(pipe, &strb->surface); st_update_renderbuffer_surface(st, strb); strb->Base.Format = st_pipe_format_to_mesa_format(pt->format); /* Invalidate buffer state so that the pipe's framebuffer state * gets updated. * That's where the new renderbuffer (which we just created) gets * passed to the pipe as a (color/depth) render target. */ st_invalidate_state(ctx, _NEW_BUFFERS); /* Need to trigger a call to update_framebuffer() since we just * attached a new renderbuffer. */ ctx->NewState |= _NEW_BUFFERS; }
/** * Get a pipe_sampler_view object from a texture unit. */ void st_update_single_texture(struct st_context *st, struct pipe_sampler_view **sampler_view, GLuint texUnit, bool glsl130_or_later, bool ignore_srgb_decode) { struct gl_context *ctx = st->ctx; const struct gl_sampler_object *samp; struct gl_texture_object *texObj; struct st_texture_object *stObj; samp = _mesa_get_samplerobj(ctx, texUnit); texObj = ctx->Texture.Unit[texUnit]._Current; assert(texObj); stObj = st_texture_object(texObj); if (unlikely(texObj->Target == GL_TEXTURE_BUFFER)) { *sampler_view = st_get_buffer_sampler_view_from_stobj(st, stObj); return; } if (!st_finalize_texture(ctx, st->pipe, texObj, 0) || !stObj->pt) { /* out of mem */ *sampler_view = NULL; return; } if (texObj->TargetIndex == TEXTURE_EXTERNAL_INDEX && stObj->pt->screen->resource_changed) stObj->pt->screen->resource_changed(stObj->pt->screen, stObj->pt); *sampler_view = st_get_texture_sampler_view_from_stobj(st, stObj, samp, glsl130_or_later, ignore_srgb_decode); }
/** * Called via ctx->Driver.GenerateMipmap(). */ void st_generate_mipmap(struct gl_context *ctx, GLenum target, struct gl_texture_object *texObj) { struct st_context *st = st_context(ctx); struct st_texture_object *stObj = st_texture_object(texObj); struct pipe_resource *pt = st_get_texobj_resource(texObj); const uint baseLevel = texObj->BaseLevel; uint lastLevel, first_layer, last_layer; uint dstLevel; if (!pt) return; /* not sure if this ultimately actually should work, but we're not supporting multisampled textures yet. */ assert(pt->nr_samples < 2); /* find expected last mipmap level to generate*/ lastLevel = compute_num_levels(ctx, texObj, target) - 1; if (lastLevel == 0) return; /* The texture isn't in a "complete" state yet so set the expected * lastLevel here, since it won't get done in st_finalize_texture(). */ stObj->lastLevel = lastLevel; if (pt->last_level < lastLevel) { /* The current gallium texture doesn't have space for all the * mipmap levels we need to generate. So allocate a new texture. */ struct pipe_resource *oldTex = stObj->pt; /* create new texture with space for more levels */ stObj->pt = st_texture_create(st, oldTex->target, oldTex->format, lastLevel, oldTex->width0, oldTex->height0, oldTex->depth0, oldTex->array_size, 0, oldTex->bind); /* This will copy the old texture's base image into the new texture * which we just allocated. */ st_finalize_texture(ctx, st->pipe, texObj); /* release the old tex (will likely be freed too) */ pipe_resource_reference(&oldTex, NULL); st_texture_release_all_sampler_views(stObj); } else { /* Make sure that the base texture image data is present in the * texture buffer. */ st_finalize_texture(ctx, st->pipe, texObj); } pt = stObj->pt; assert(pt->last_level >= lastLevel); if (pt->target == PIPE_TEXTURE_CUBE) { first_layer = last_layer = _mesa_tex_target_to_face(target); } else { first_layer = 0; last_layer = util_max_layer(pt, baseLevel); } /* Try to generate the mipmap by rendering/texturing. If that fails, * use the software fallback. */ if (!util_gen_mipmap(st->pipe, pt, pt->format, baseLevel, lastLevel, first_layer, last_layer, PIPE_TEX_FILTER_LINEAR)) { _mesa_generate_mipmap(ctx, target, texObj); } /* Fill in the Mesa gl_texture_image fields */ for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) { const uint srcLevel = dstLevel - 1; const struct gl_texture_image *srcImage = _mesa_get_tex_image(ctx, texObj, target, srcLevel); struct gl_texture_image *dstImage; struct st_texture_image *stImage; uint border = srcImage->Border; uint dstWidth, dstHeight, dstDepth; dstWidth = u_minify(pt->width0, dstLevel); if (texObj->Target == GL_TEXTURE_1D_ARRAY) { dstHeight = pt->array_size; } else { dstHeight = u_minify(pt->height0, dstLevel); } if (texObj->Target == GL_TEXTURE_2D_ARRAY || texObj->Target == GL_TEXTURE_CUBE_MAP_ARRAY) { dstDepth = pt->array_size; } else { dstDepth = u_minify(pt->depth0, dstLevel); } dstImage = _mesa_get_tex_image(ctx, texObj, target, dstLevel); if (!dstImage) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps"); return; } /* Free old image data */ ctx->Driver.FreeTextureImageBuffer(ctx, dstImage); /* initialize new image */ _mesa_init_teximage_fields(ctx, dstImage, dstWidth, dstHeight, dstDepth, border, srcImage->InternalFormat, srcImage->TexFormat); stImage = st_texture_image(dstImage); pipe_resource_reference(&stImage->pt, pt); } }
/** * Called by ctx->Driver.RenderTexture */ static void st_render_texture(struct gl_context *ctx, struct gl_framebuffer *fb, struct gl_renderbuffer_attachment *att) { struct st_context *st = st_context(ctx); struct pipe_context *pipe = st->pipe; struct st_renderbuffer *strb; struct gl_renderbuffer *rb; struct pipe_resource *pt; struct st_texture_object *stObj; const struct gl_texture_image *texImage; struct pipe_surface surf_tmpl; if (!st_finalize_texture(ctx, pipe, att->Texture)) return; pt = st_get_texobj_resource(att->Texture); assert(pt); /* get pointer to texture image we're rendeing to */ texImage = _mesa_get_attachment_teximage(att); /* create new renderbuffer which wraps the texture image. * Use the texture's name as the renderbuffer's name so that we have * something that's non-zero (to determine vertical orientation) and * possibly helpful for debugging. */ rb = st_new_renderbuffer(ctx, att->Texture->Name); if (!rb) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glFramebufferTexture()"); return; } _mesa_reference_renderbuffer(&att->Renderbuffer, rb); assert(rb->RefCount == 1); rb->AllocStorage = NULL; /* should not get called */ strb = st_renderbuffer(rb); assert(strb->Base.RefCount > 0); /* get the texture for the texture object */ stObj = st_texture_object(att->Texture); /* point renderbuffer at texobject */ strb->rtt = stObj; strb->rtt_level = att->TextureLevel; strb->rtt_face = att->CubeMapFace; strb->rtt_slice = att->Zoffset; rb->Width = texImage->Width2; rb->Height = texImage->Height2; rb->_BaseFormat = texImage->_BaseFormat; rb->InternalFormat = texImage->InternalFormat; pipe_resource_reference( &strb->texture, pt ); pipe_surface_release(pipe, &strb->surface); assert(strb->rtt_level <= strb->texture->last_level); /* new surface for rendering into the texture */ memset(&surf_tmpl, 0, sizeof(surf_tmpl)); surf_tmpl.format = ctx->Color.sRGBEnabled ? strb->texture->format : util_format_linear(strb->texture->format); surf_tmpl.usage = PIPE_BIND_RENDER_TARGET; surf_tmpl.u.tex.level = strb->rtt_level; surf_tmpl.u.tex.first_layer = strb->rtt_face + strb->rtt_slice; surf_tmpl.u.tex.last_layer = strb->rtt_face + strb->rtt_slice; strb->surface = pipe->create_surface(pipe, strb->texture, &surf_tmpl); strb->Base.Format = st_pipe_format_to_mesa_format(pt->format); /* Invalidate buffer state so that the pipe's framebuffer state * gets updated. * That's where the new renderbuffer (which we just created) gets * passed to the pipe as a (color/depth) render target. */ st_invalidate_state(ctx, _NEW_BUFFERS); /* Need to trigger a call to update_framebuffer() since we just * attached a new renderbuffer. */ ctx->NewState |= _NEW_BUFFERS; }
static void st_bind_images(struct st_context *st, struct gl_shader *shader, unsigned shader_type) { unsigned i; struct pipe_image_view images[MAX_IMAGE_UNIFORMS]; struct gl_program_constants *c; if (!shader || !st->pipe->set_shader_images) return; c = &st->ctx->Const.Program[shader->Stage]; for (i = 0; i < shader->NumImages; i++) { struct gl_image_unit *u = &st->ctx->ImageUnits[shader->ImageUnits[i]]; struct st_texture_object *stObj = st_texture_object(u->TexObj); struct pipe_image_view *img = &images[i]; if (!_mesa_is_image_unit_valid(st->ctx, u) || !st_finalize_texture(st->ctx, st->pipe, u->TexObj) || !stObj->pt) { memset(img, 0, sizeof(*img)); continue; } img->resource = stObj->pt; img->format = st_mesa_format_to_pipe_format(st, u->_ActualFormat); switch (u->Access) { case GL_READ_ONLY: img->access = PIPE_IMAGE_ACCESS_READ; break; case GL_WRITE_ONLY: img->access = PIPE_IMAGE_ACCESS_WRITE; break; case GL_READ_WRITE: img->access = PIPE_IMAGE_ACCESS_READ_WRITE; break; default: unreachable("bad gl_image_unit::Access"); } if (stObj->pt->target == PIPE_BUFFER) { unsigned base, size; unsigned f, n; const struct util_format_description *desc = util_format_description(img->format); base = stObj->base.BufferOffset; assert(base < stObj->pt->width0); size = MIN2(stObj->pt->width0 - base, (unsigned)stObj->base.BufferSize); f = (base / (desc->block.bits / 8)) * desc->block.width; n = (size / (desc->block.bits / 8)) * desc->block.width; assert(n > 0); img->u.buf.first_element = f; img->u.buf.last_element = f + (n - 1); } else { img->u.tex.level = u->Level + stObj->base.MinLevel; if (stObj->pt->target == PIPE_TEXTURE_3D) { if (u->Layered) { img->u.tex.first_layer = 0; img->u.tex.last_layer = u_minify(stObj->pt->depth0, img->u.tex.level) - 1; } else { img->u.tex.first_layer = u->_Layer; img->u.tex.last_layer = u->_Layer; } } else { img->u.tex.first_layer = u->_Layer + stObj->base.MinLayer; img->u.tex.last_layer = u->_Layer + stObj->base.MinLayer; if (u->Layered && img->resource->array_size > 1) { if (stObj->base.Immutable) img->u.tex.last_layer += stObj->base.NumLayers - 1; else img->u.tex.last_layer += img->resource->array_size - 1; } } } } cso_set_shader_images(st->cso_context, shader_type, 0, shader->NumImages, images); /* clear out any stale shader images */ if (shader->NumImages < c->MaxImageUniforms) cso_set_shader_images( st->cso_context, shader_type, shader->NumImages, c->MaxImageUniforms - shader->NumImages, NULL); }
/** * Called by ctx->Driver.RenderTexture */ static void st_render_texture(struct gl_context *ctx, struct gl_framebuffer *fb, struct gl_renderbuffer_attachment *att) { struct st_context *st = st_context(ctx); struct pipe_context *pipe = st->pipe; struct gl_renderbuffer *rb = att->Renderbuffer; struct st_renderbuffer *strb = st_renderbuffer(rb); struct pipe_resource *pt; struct st_texture_object *stObj; const struct gl_texture_image *texImage; struct pipe_surface surf_tmpl; if (!st_finalize_texture(ctx, pipe, att->Texture)) return; pt = st_get_texobj_resource(att->Texture); assert(pt); /* get pointer to texture image we're rendeing to */ texImage = _mesa_get_attachment_teximage(att); /* get the texture for the texture object */ stObj = st_texture_object(att->Texture); /* point renderbuffer at texobject */ strb->rtt = stObj; strb->rtt_level = att->TextureLevel; strb->rtt_face = att->CubeMapFace; strb->rtt_slice = att->Zoffset; pipe_resource_reference( &strb->texture, pt ); pipe_surface_release(pipe, &strb->surface); assert(strb->rtt_level <= strb->texture->last_level); /* new surface for rendering into the texture */ memset(&surf_tmpl, 0, sizeof(surf_tmpl)); surf_tmpl.format = ctx->Color.sRGBEnabled ? strb->texture->format : util_format_linear(strb->texture->format); surf_tmpl.u.tex.level = strb->rtt_level; surf_tmpl.u.tex.first_layer = strb->rtt_face + strb->rtt_slice; surf_tmpl.u.tex.last_layer = strb->rtt_face + strb->rtt_slice; strb->surface = pipe->create_surface(pipe, strb->texture, &surf_tmpl); strb->Base.Format = st_pipe_format_to_mesa_format(pt->format); /* Invalidate buffer state so that the pipe's framebuffer state * gets updated. * That's where the new renderbuffer (which we just created) gets * passed to the pipe as a (color/depth) render target. */ st_invalidate_state(ctx, _NEW_BUFFERS); /* Need to trigger a call to update_framebuffer() since we just * attached a new renderbuffer. */ ctx->NewState |= _NEW_BUFFERS; }
/** * Called via ctx->Driver.GenerateMipmap(). */ void st_generate_mipmap(struct gl_context *ctx, GLenum target, struct gl_texture_object *texObj) { struct st_context *st = st_context(ctx); struct st_texture_object *stObj = st_texture_object(texObj); struct pipe_resource *pt = st_get_texobj_resource(texObj); const uint baseLevel = texObj->BaseLevel; enum pipe_format format; uint lastLevel, first_layer, last_layer; if (!pt) return; /* not sure if this ultimately actually should work, but we're not supporting multisampled textures yet. */ assert(pt->nr_samples < 2); /* find expected last mipmap level to generate*/ lastLevel = compute_num_levels(ctx, texObj, target) - 1; if (lastLevel == 0) return; st_flush_bitmap_cache(st); st_invalidate_readpix_cache(st); /* The texture isn't in a "complete" state yet so set the expected * lastLevel here, since it won't get done in st_finalize_texture(). */ stObj->lastLevel = lastLevel; if (!texObj->Immutable) { const GLboolean genSave = texObj->GenerateMipmap; /* Temporarily set GenerateMipmap to true so that allocate_full_mipmap() * makes the right decision about full mipmap allocation. */ texObj->GenerateMipmap = GL_TRUE; _mesa_prepare_mipmap_levels(ctx, texObj, baseLevel, lastLevel); texObj->GenerateMipmap = genSave; /* At this point, memory for all the texture levels has been * allocated. However, the base level image may be in one resource * while the subsequent/smaller levels may be in another resource. * Finalizing the texture will copy the base images from the former * resource to the latter. * * After this, we'll have all mipmap levels in one resource. */ st_finalize_texture(ctx, st->pipe, texObj); } pt = stObj->pt; if (!pt) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "mipmap generation"); return; } assert(pt->last_level >= lastLevel); if (pt->target == PIPE_TEXTURE_CUBE) { first_layer = last_layer = _mesa_tex_target_to_face(target); } else { first_layer = 0; last_layer = util_max_layer(pt, baseLevel); } if (stObj->surface_based) format = stObj->surface_format; else format = pt->format; /* First see if the driver supports hardware mipmap generation, * if not then generate the mipmap by rendering/texturing. * If that fails, use the software fallback. */ if (!st->pipe->screen->get_param(st->pipe->screen, PIPE_CAP_GENERATE_MIPMAP) || !st->pipe->generate_mipmap(st->pipe, pt, format, baseLevel, lastLevel, first_layer, last_layer)) { if (!util_gen_mipmap(st->pipe, pt, format, baseLevel, lastLevel, first_layer, last_layer, PIPE_TEX_FILTER_LINEAR)) { _mesa_generate_mipmap(ctx, target, texObj); } } }
/** * Convert a gl_image_unit object to a pipe_image_view object. */ void st_convert_image(const struct st_context *st, const struct gl_image_unit *u, struct pipe_image_view *img) { struct st_texture_object *stObj = st_texture_object(u->TexObj); img->format = st_mesa_format_to_pipe_format(st, u->_ActualFormat); switch (u->Access) { case GL_READ_ONLY: img->access = PIPE_IMAGE_ACCESS_READ; break; case GL_WRITE_ONLY: img->access = PIPE_IMAGE_ACCESS_WRITE; break; case GL_READ_WRITE: img->access = PIPE_IMAGE_ACCESS_READ_WRITE; break; default: unreachable("bad gl_image_unit::Access"); } if (stObj->base.Target == GL_TEXTURE_BUFFER) { struct st_buffer_object *stbuf = st_buffer_object(stObj->base.BufferObject); unsigned base, size; if (!stbuf || !stbuf->buffer) { memset(img, 0, sizeof(*img)); return; } struct pipe_resource *buf = stbuf->buffer; base = stObj->base.BufferOffset; assert(base < buf->width0); size = MIN2(buf->width0 - base, (unsigned)stObj->base.BufferSize); img->resource = stbuf->buffer; img->u.buf.offset = base; img->u.buf.size = size; } else { if (!st_finalize_texture(st->ctx, st->pipe, u->TexObj, 0) || !stObj->pt) { memset(img, 0, sizeof(*img)); return; } img->resource = stObj->pt; img->u.tex.level = u->Level + stObj->base.MinLevel; if (stObj->pt->target == PIPE_TEXTURE_3D) { if (u->Layered) { img->u.tex.first_layer = 0; img->u.tex.last_layer = u_minify(stObj->pt->depth0, img->u.tex.level) - 1; } else { img->u.tex.first_layer = u->_Layer; img->u.tex.last_layer = u->_Layer; } } else { img->u.tex.first_layer = u->_Layer + stObj->base.MinLayer; img->u.tex.last_layer = u->_Layer + stObj->base.MinLayer; if (u->Layered && img->resource->array_size > 1) { if (stObj->base.Immutable) img->u.tex.last_layer += stObj->base.NumLayers - 1; else img->u.tex.last_layer += img->resource->array_size - 1; } } } }
static GLboolean update_single_texture(struct st_context *st, struct pipe_sampler_view **sampler_view, GLuint texUnit) { struct pipe_context *pipe = st->pipe; struct gl_context *ctx = st->ctx; const struct gl_sampler_object *samp; struct gl_texture_object *texObj; struct st_texture_object *stObj; enum pipe_format st_view_format; GLboolean retval; samp = _mesa_get_samplerobj(ctx, texUnit); texObj = ctx->Texture.Unit[texUnit]._Current; if (!texObj) { texObj = _mesa_get_fallback_texture(ctx, TEXTURE_2D_INDEX); samp = &texObj->Sampler; } stObj = st_texture_object(texObj); retval = st_finalize_texture(ctx, st->pipe, texObj); if (!retval) { /* out of mem */ return GL_FALSE; } /* Determine the format of the texture sampler view */ st_view_format = stObj->pt->format; { const struct st_texture_image *firstImage = st_texture_image(stObj->base.Image[0][stObj->base.BaseLevel]); const gl_format texFormat = firstImage->base.TexFormat; enum pipe_format firstImageFormat = st_mesa_format_to_pipe_format(texFormat); if ((samp->sRGBDecode == GL_SKIP_DECODE_EXT) && (_mesa_get_format_color_encoding(texFormat) == GL_SRGB)) { /* Don't do sRGB->RGB conversion. Interpret the texture data as * linear values. */ const gl_format linearFormat = _mesa_get_srgb_format_linear(texFormat); firstImageFormat = st_mesa_format_to_pipe_format(linearFormat); } if (firstImageFormat != stObj->pt->format) st_view_format = firstImageFormat; } /* if sampler view has changed dereference it */ if (stObj->sampler_view) { if (check_sampler_swizzle(stObj->sampler_view, stObj->base._Swizzle, samp->DepthMode) || (st_view_format != stObj->sampler_view->format) || stObj->base.BaseLevel != stObj->sampler_view->u.tex.first_level) { pipe_sampler_view_reference(&stObj->sampler_view, NULL); } } *sampler_view = st_get_texture_sampler_view_from_stobj(stObj, pipe, samp, st_view_format); return GL_TRUE; }