/** * Create a texture handle from a texture unit. */ static GLuint64 st_create_texture_handle_from_unit(struct st_context *st, struct gl_program *prog, GLuint texUnit) { struct pipe_context *pipe = st->pipe; struct pipe_sampler_view *view; struct pipe_sampler_state sampler = {0}; st_update_single_texture(st, &view, texUnit, prog->sh.data->Version >= 130); if (!view) return 0; if (view->target != PIPE_BUFFER) st_convert_sampler_from_unit(st, &sampler, texUnit); assert(st->ctx->Texture.Unit[texUnit]._Current); return pipe->create_texture_handle(pipe, view, &sampler); }
static void update_textures(struct st_context *st, enum pipe_shader_type shader_stage, const struct gl_program *prog, struct pipe_sampler_view **sampler_views, unsigned *out_num_textures) { const GLuint old_max = *out_num_textures; GLbitfield samplers_used = prog->SamplersUsed; GLbitfield texel_fetch_samplers = prog->info.textures_used_by_txf; GLbitfield free_slots = ~prog->SamplersUsed; GLbitfield external_samplers_used = prog->ExternalSamplersUsed; GLuint unit; if (samplers_used == 0x0 && old_max == 0) return; unsigned num_textures = 0; /* prog->sh.data is NULL if it's ARB_fragment_program */ bool glsl130 = (prog->sh.data ? prog->sh.data->Version : 0) >= 130; /* loop over sampler units (aka tex image units) */ for (unit = 0; samplers_used || unit < old_max; unit++, samplers_used >>= 1, texel_fetch_samplers >>= 1) { struct pipe_sampler_view *sampler_view = NULL; if (samplers_used & 1) { const GLuint texUnit = prog->SamplerUnits[unit]; /* The EXT_texture_sRGB_decode extension says: * * "The conversion of sRGB color space components to linear color * space is always performed if the texel lookup function is one * of the texelFetch builtin functions. * * Otherwise, if the texel lookup function is one of the texture * builtin functions or one of the texture gather functions, the * conversion of sRGB color space components to linear color space * is controlled by the TEXTURE_SRGB_DECODE_EXT parameter. * * If the TEXTURE_SRGB_DECODE_EXT parameter is DECODE_EXT, the * conversion of sRGB color space components to linear color space * is performed. * * If the TEXTURE_SRGB_DECODE_EXT parameter is SKIP_DECODE_EXT, * the value is returned without decoding. However, if the texture * is also [statically] accessed with a texelFetch function, then * the result of texture builtin functions and/or texture gather * functions may be returned with decoding or without decoding." * * Note: the "statically" will be added to the language per * https://cvs.khronos.org/bugzilla/show_bug.cgi?id=14934 * * So we simply ignore the setting entirely for samplers that are * (statically) accessed with a texelFetch function. */ st_update_single_texture(st, &sampler_view, texUnit, glsl130, texel_fetch_samplers & 1); num_textures = unit + 1; } pipe_sampler_view_reference(&(sampler_views[unit]), sampler_view); } /* For any external samplers with multiplaner YUV, stuff the additional * sampler views we need at the end. * * Trying to cache the sampler view in the stObj looks painful, so just * re-create the sampler view for the extra planes each time. Main use * case is video playback (ie. fps games wouldn't be using this) so I * guess no point to try to optimize this feature. */ while (unlikely(external_samplers_used)) { GLuint unit = u_bit_scan(&external_samplers_used); GLuint extra = 0; struct st_texture_object *stObj = st_get_texture_object(st->ctx, prog, unit); struct pipe_sampler_view tmpl; if (!stObj) continue; /* use original view as template: */ tmpl = *sampler_views[unit]; switch (st_get_view_format(stObj)) { case PIPE_FORMAT_NV12: /* we need one additional R8G8 view: */ tmpl.format = PIPE_FORMAT_RG88_UNORM; tmpl.swizzle_g = PIPE_SWIZZLE_Y; /* tmpl from Y plane is R8 */ extra = u_bit_scan(&free_slots); sampler_views[extra] = st->pipe->create_sampler_view(st->pipe, stObj->pt->next, &tmpl); break; case PIPE_FORMAT_IYUV: /* we need two additional R8 views: */ tmpl.format = PIPE_FORMAT_R8_UNORM; extra = u_bit_scan(&free_slots); sampler_views[extra] = st->pipe->create_sampler_view(st->pipe, stObj->pt->next, &tmpl); extra = u_bit_scan(&free_slots); sampler_views[extra] = st->pipe->create_sampler_view(st->pipe, stObj->pt->next->next, &tmpl); break; default: break; } num_textures = MAX2(num_textures, extra + 1); } cso_set_sampler_views(st->cso_context, shader_stage, num_textures, sampler_views); *out_num_textures = num_textures; }