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; }
static void st_vdpau_unmap_surface(struct gl_context *ctx, GLenum target, GLenum access, GLboolean output, struct gl_texture_object *texObj, struct gl_texture_image *texImage, const void *vdpSurface, GLuint index) { struct st_context *st = st_context(ctx); struct st_texture_object *stObj = st_texture_object(texObj); struct st_texture_image *stImage = st_texture_image(texImage); pipe_resource_reference(&stObj->pt, NULL); st_texture_release_all_sampler_views(st, stObj); pipe_resource_reference(&stImage->pt, NULL); _mesa_dirty_texobj(ctx, texObj); st_flush(st, NULL, 0); }
static void st_bind_surface(struct gl_context *ctx, GLenum target, struct gl_texture_object *texObj, struct gl_texture_image *texImage, struct pipe_surface *ps) { struct st_texture_object *stObj; struct st_texture_image *stImage; GLenum internalFormat; mesa_format texFormat; /* map pipe format to base format */ if (util_format_get_component_bits(ps->format, UTIL_FORMAT_COLORSPACE_RGB, 3) > 0) internalFormat = GL_RGBA; else internalFormat = GL_RGB; stObj = st_texture_object(texObj); stImage = st_texture_image(texImage); /* switch to surface based */ if (!stObj->surface_based) { _mesa_clear_texture_object(ctx, texObj); stObj->surface_based = GL_TRUE; } texFormat = st_pipe_format_to_mesa_format(ps->format); _mesa_init_teximage_fields(ctx, texImage, ps->width, ps->height, 1, 0, internalFormat, texFormat); /* FIXME create a non-default sampler view from the pipe_surface? */ pipe_resource_reference(&stObj->pt, ps->texture); st_texture_release_all_sampler_views(stObj); pipe_resource_reference(&stImage->pt, stObj->pt); stObj->width0 = ps->width; stObj->height0 = ps->height; stObj->depth0 = 1; stObj->surface_format = ps->format; _mesa_dirty_texobj(ctx, texObj); }
/** * 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); } }
static void st_bind_egl_image(struct gl_context *ctx, struct gl_texture_object *texObj, struct gl_texture_image *texImage, struct st_egl_image *stimg) { struct st_context *st = st_context(ctx); struct st_texture_object *stObj; struct st_texture_image *stImage; GLenum internalFormat; mesa_format texFormat; /* map pipe format to base format */ if (util_format_get_component_bits(stimg->format, UTIL_FORMAT_COLORSPACE_RGB, 3) > 0) internalFormat = GL_RGBA; else internalFormat = GL_RGB; stObj = st_texture_object(texObj); stImage = st_texture_image(texImage); /* switch to surface based */ if (!stObj->surface_based) { _mesa_clear_texture_object(ctx, texObj, NULL); stObj->surface_based = GL_TRUE; } texFormat = st_pipe_format_to_mesa_format(stimg->format); /* TODO RequiredTextureImageUnits should probably be reset back * to 1 somewhere if different texture is bound?? */ if (texFormat == MESA_FORMAT_NONE) { switch (stimg->format) { case PIPE_FORMAT_NV12: texFormat = MESA_FORMAT_R_UNORM8; texObj->RequiredTextureImageUnits = 2; break; case PIPE_FORMAT_IYUV: texFormat = MESA_FORMAT_R_UNORM8; texObj->RequiredTextureImageUnits = 3; break; default: unreachable("bad YUV format!"); } } _mesa_init_teximage_fields(ctx, texImage, stimg->texture->width0, stimg->texture->height0, 1, 0, internalFormat, texFormat); pipe_resource_reference(&stObj->pt, stimg->texture); st_texture_release_all_sampler_views(st, stObj); pipe_resource_reference(&stImage->pt, stObj->pt); stObj->surface_format = stimg->format; stObj->level_override = stimg->level; stObj->layer_override = stimg->layer; _mesa_dirty_texobj(ctx, texObj); }
static void st_vdpau_map_surface(struct gl_context *ctx, GLenum target, GLenum access, GLboolean output, struct gl_texture_object *texObj, struct gl_texture_image *texImage, const void *vdpSurface, GLuint index) { struct st_context *st = st_context(ctx); struct st_texture_object *stObj = st_texture_object(texObj); struct st_texture_image *stImage = st_texture_image(texImage); struct pipe_resource *res; struct pipe_sampler_view templ, **sampler_view; mesa_format texFormat; if (output) { res = st_vdpau_output_surface_dma_buf(ctx, vdpSurface); if (!res) res = st_vdpau_output_surface_gallium(ctx, vdpSurface); } else { res = st_vdpau_video_surface_dma_buf(ctx, vdpSurface, index); if (!res) res = st_vdpau_video_surface_gallium(ctx, vdpSurface, index); } if (!res) { _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUMapSurfacesNV"); return; } /* do we have different screen objects ? */ if (res->screen != st->pipe->screen) { _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUMapSurfacesNV"); return; } /* switch to surface based */ if (!stObj->surface_based) { _mesa_clear_texture_object(ctx, texObj); stObj->surface_based = GL_TRUE; } texFormat = st_pipe_format_to_mesa_format(res->format); _mesa_init_teximage_fields(ctx, texImage, res->width0, res->height0, 1, 0, GL_RGBA, texFormat); pipe_resource_reference(&stObj->pt, res); st_texture_release_all_sampler_views(st, stObj); pipe_resource_reference(&stImage->pt, res); u_sampler_view_default_template(&templ, res, res->format); templ.u.tex.first_layer = index & 1; templ.u.tex.last_layer = index & 1; templ.swizzle_r = GET_SWZ(stObj->base._Swizzle, 0); templ.swizzle_g = GET_SWZ(stObj->base._Swizzle, 1); templ.swizzle_b = GET_SWZ(stObj->base._Swizzle, 2); templ.swizzle_a = GET_SWZ(stObj->base._Swizzle, 3); sampler_view = st_texture_get_sampler_view(st, stObj); *sampler_view = st->pipe->create_sampler_view(st->pipe, res, &templ); stObj->surface_format = res->format; _mesa_dirty_texobj(ctx, texObj); }
static void st_vdpau_map_surface(struct gl_context *ctx, GLenum target, GLenum access, GLboolean output, struct gl_texture_object *texObj, struct gl_texture_image *texImage, const void *vdpSurface, GLuint index) { struct st_context *st = st_context(ctx); struct st_texture_object *stObj = st_texture_object(texObj); struct st_texture_image *stImage = st_texture_image(texImage); struct pipe_resource *res; mesa_format texFormat; uint layer_override = 0; if (output) { res = st_vdpau_output_surface_dma_buf(ctx, vdpSurface); if (!res) res = st_vdpau_output_surface_gallium(ctx, vdpSurface); } else { res = st_vdpau_video_surface_dma_buf(ctx, vdpSurface, index); if (!res) { res = st_vdpau_video_surface_gallium(ctx, vdpSurface, index); layer_override = index & 1; } } if (!res) { _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUMapSurfacesNV"); return; } /* do we have different screen objects ? */ if (res->screen != st->pipe->screen) { _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUMapSurfacesNV"); pipe_resource_reference(&res, NULL); return; } /* switch to surface based */ if (!stObj->surface_based) { _mesa_clear_texture_object(ctx, texObj); stObj->surface_based = GL_TRUE; } texFormat = st_pipe_format_to_mesa_format(res->format); _mesa_init_teximage_fields(ctx, texImage, res->width0, res->height0, 1, 0, GL_RGBA, texFormat); pipe_resource_reference(&stObj->pt, res); st_texture_release_all_sampler_views(st, stObj); pipe_resource_reference(&stImage->pt, res); stObj->surface_format = res->format; stObj->layer_override = layer_override; _mesa_dirty_texobj(ctx, texObj); pipe_resource_reference(&res, NULL); }