st/mesa: overhaul vertex/fragment sampler and sampler views.

This fixes piglits fragment-and-vertex-texturing test on llvmpipe for me.

I've no idea if someone had another plan for this that is smarter than what
I've done here, but what I've basically done is

split fragment and vertex sampler and sampler_view setup function, factor
out the common chunks of both.

side-cleanups:
drop st->state.sampler_list - unused
don't update border color if we have no border color.

should fix https://bugs.freedesktop.org/show_bug.cgi?id=35849

Signed-off-by: Dave Airlie <airlied@redhat.com>
Reviewed-by: Brian Paul <brianp@vmware.com>
This commit is contained in:
Dave Airlie 2011-05-14 18:04:08 +10:00
parent bc16c73407
commit c9aa3bbda4
4 changed files with 228 additions and 157 deletions

View File

@ -120,14 +120,110 @@ gl_filter_to_img_filter(GLenum filter)
}
}
static void convert_sampler(struct st_context *st,
struct pipe_sampler_state *sampler,
GLuint texUnit)
{
struct gl_texture_object *texobj;
struct gl_sampler_object *msamp;
static void
update_samplers(struct st_context *st)
texobj = st->ctx->Texture.Unit[texUnit]._Current;
if (!texobj) {
texobj = st_get_default_texture(st);
}
msamp = _mesa_get_samplerobj(st->ctx, texUnit);
sampler->wrap_s = gl_wrap_xlate(msamp->WrapS);
sampler->wrap_t = gl_wrap_xlate(msamp->WrapT);
sampler->wrap_r = gl_wrap_xlate(msamp->WrapR);
sampler->min_img_filter = gl_filter_to_img_filter(msamp->MinFilter);
sampler->min_mip_filter = gl_filter_to_mip_filter(msamp->MinFilter);
sampler->mag_img_filter = gl_filter_to_img_filter(msamp->MagFilter);
if (texobj->Target != GL_TEXTURE_RECTANGLE_ARB)
sampler->normalized_coords = 1;
sampler->lod_bias = st->ctx->Texture.Unit[texUnit].LodBias +
msamp->LodBias;
sampler->min_lod = CLAMP(msamp->MinLod,
0.0f,
(GLfloat) texobj->MaxLevel - texobj->BaseLevel);
sampler->max_lod = MIN2((GLfloat) texobj->MaxLevel - texobj->BaseLevel,
msamp->MaxLod);
if (sampler->max_lod < sampler->min_lod) {
/* The GL spec doesn't seem to specify what to do in this case.
* Swap the values.
*/
float tmp = sampler->max_lod;
sampler->max_lod = sampler->min_lod;
sampler->min_lod = tmp;
assert(sampler->min_lod <= sampler->max_lod);
}
if (msamp->BorderColor.ui[0] ||
msamp->BorderColor.ui[1] ||
msamp->BorderColor.ui[2] ||
msamp->BorderColor.ui[3]) {
struct gl_texture_image *teximg;
teximg = texobj->Image[0][texobj->BaseLevel];
st_translate_color(msamp->BorderColor.f,
teximg ? teximg->_BaseFormat : GL_RGBA,
sampler->border_color);
}
sampler->max_anisotropy = (msamp->MaxAnisotropy == 1.0 ?
0 : (GLuint) msamp->MaxAnisotropy);
/* only care about ARB_shadow, not SGI shadow */
if (msamp->CompareMode == GL_COMPARE_R_TO_TEXTURE) {
sampler->compare_mode = PIPE_TEX_COMPARE_R_TO_TEXTURE;
sampler->compare_func
= st_compare_func_to_pipe(msamp->CompareFunc);
}
sampler->seamless_cube_map =
st->ctx->Texture.CubeMapSeamless || msamp->CubeMapSeamless;
}
static void
update_vertex_samplers(struct st_context *st)
{
struct gl_vertex_program *vprog = st->ctx->VertexProgram._Current;
GLuint su;
st->state.num_vertex_samplers = 0;
/* loop over sampler units (aka tex image units) */
for (su = 0; su < st->ctx->Const.MaxVertexTextureImageUnits; su++) {
struct pipe_sampler_state *sampler = st->state.vertex_samplers + su;
memset(sampler, 0, sizeof(*sampler));
if (vprog->Base.SamplersUsed & (1 << su)) {
GLuint texUnit;
texUnit = vprog->Base.SamplerUnits[su];
convert_sampler(st, sampler, texUnit);
st->state.num_vertex_samplers = su + 1;
cso_single_vertex_sampler(st->cso_context, su, sampler);
} else {
cso_single_vertex_sampler(st->cso_context, su, NULL);
}
}
cso_single_vertex_sampler_done(st->cso_context);
}
static void
update_fragment_samplers(struct st_context *st)
{
struct gl_fragment_program *fprog = st->ctx->FragmentProgram._Current;
const GLbitfield samplersUsed = (vprog->Base.SamplersUsed |
fprog->Base.SamplersUsed);
GLuint su;
st->state.num_samplers = 0;
@ -138,95 +234,33 @@ update_samplers(struct st_context *st)
memset(sampler, 0, sizeof(*sampler));
if (samplersUsed & (1 << su)) {
struct gl_texture_object *texobj;
struct gl_texture_image *teximg;
struct gl_sampler_object *msamp;
if (fprog->Base.SamplersUsed & (1 << su)) {
GLuint texUnit;
if (fprog->Base.SamplersUsed & (1 << su))
texUnit = fprog->Base.SamplerUnits[su];
else
texUnit = vprog->Base.SamplerUnits[su];
texUnit = fprog->Base.SamplerUnits[su];
texobj = st->ctx->Texture.Unit[texUnit]._Current;
if (!texobj) {
texobj = st_get_default_texture(st);
}
teximg = texobj->Image[0][texobj->BaseLevel];
msamp = _mesa_get_samplerobj(st->ctx, texUnit);
sampler->wrap_s = gl_wrap_xlate(msamp->WrapS);
sampler->wrap_t = gl_wrap_xlate(msamp->WrapT);
sampler->wrap_r = gl_wrap_xlate(msamp->WrapR);
sampler->min_img_filter = gl_filter_to_img_filter(msamp->MinFilter);
sampler->min_mip_filter = gl_filter_to_mip_filter(msamp->MinFilter);
sampler->mag_img_filter = gl_filter_to_img_filter(msamp->MagFilter);
if (texobj->Target != GL_TEXTURE_RECTANGLE_ARB)
sampler->normalized_coords = 1;
sampler->lod_bias = st->ctx->Texture.Unit[texUnit].LodBias +
msamp->LodBias;
sampler->min_lod = CLAMP(msamp->MinLod,
0.0f,
(GLfloat) texobj->MaxLevel - texobj->BaseLevel);
sampler->max_lod = MIN2((GLfloat) texobj->MaxLevel - texobj->BaseLevel,
msamp->MaxLod);
if (sampler->max_lod < sampler->min_lod) {
/* The GL spec doesn't seem to specify what to do in this case.
* Swap the values.
*/
float tmp = sampler->max_lod;
sampler->max_lod = sampler->min_lod;
sampler->min_lod = tmp;
assert(sampler->min_lod <= sampler->max_lod);
}
st_translate_color(msamp->BorderColor.f,
teximg ? teximg->_BaseFormat : GL_RGBA,
sampler->border_color);
sampler->max_anisotropy = (msamp->MaxAnisotropy == 1.0 ?
0 : (GLuint) msamp->MaxAnisotropy);
/* only care about ARB_shadow, not SGI shadow */
if (msamp->CompareMode == GL_COMPARE_R_TO_TEXTURE) {
sampler->compare_mode = PIPE_TEX_COMPARE_R_TO_TEXTURE;
sampler->compare_func
= st_compare_func_to_pipe(msamp->CompareFunc);
}
sampler->seamless_cube_map =
st->ctx->Texture.CubeMapSeamless || msamp->CubeMapSeamless;
convert_sampler(st, sampler, texUnit);
st->state.num_samplers = su + 1;
/*printf("%s su=%u non-null\n", __FUNCTION__, su);*/
cso_single_sampler(st->cso_context, su, sampler);
if (su < st->ctx->Const.MaxVertexTextureImageUnits) {
cso_single_vertex_sampler(st->cso_context, su, sampler);
}
}
else {
/*printf("%s su=%u null\n", __FUNCTION__, su);*/
cso_single_sampler(st->cso_context, su, NULL);
if (su < st->ctx->Const.MaxVertexTextureImageUnits) {
cso_single_vertex_sampler(st->cso_context, su, NULL);
}
}
}
cso_single_sampler_done(st->cso_context);
if (st->ctx->Const.MaxVertexTextureImageUnits > 0) {
cso_single_vertex_sampler_done(st->cso_context);
}
}
static void
update_samplers(struct st_context *st)
{
update_fragment_samplers(st);
update_vertex_samplers(st);
}
const struct st_tracked_state st_update_sampler = {
"st_update_sampler", /* name */

View File

@ -182,15 +182,114 @@ st_get_texture_sampler_view_from_stobj(struct st_texture_object *stObj,
return stObj->sampler_view;
}
static void
update_textures(struct st_context *st)
static GLboolean
update_single_texture(struct st_context *st, struct pipe_sampler_view **sampler_view,
GLuint texUnit)
{
struct pipe_context *pipe = st->pipe;
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(st->ctx, texUnit);
texObj = st->ctx->Texture.Unit[texUnit]._Current;
if (!texObj) {
texObj = st_get_default_texture(st);
samp = &texObj->Sampler;
}
stObj = st_texture_object(texObj);
retval = st_finalize_texture(st->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
* 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;
}
static void
update_vertex_textures(struct st_context *st)
{
struct gl_vertex_program *vprog = st->ctx->VertexProgram._Current;
GLuint su;
st->state.num_vertex_textures = 0;
/* loop over sampler units (aka tex image units) */
for (su = 0; su < st->ctx->Const.MaxTextureImageUnits; su++) {
struct pipe_sampler_view *sampler_view = NULL;
if (vprog->Base.SamplersUsed & (1 << su)) {
GLboolean retval;
GLuint texUnit;
texUnit = vprog->Base.SamplerUnits[su];
retval = update_single_texture(st, &sampler_view, texUnit);
if (retval == GL_FALSE)
continue;
st->state.num_vertex_textures = su + 1;
}
pipe_sampler_view_reference(&st->state.sampler_vertex_views[su], sampler_view);
}
if (st->ctx->Const.MaxVertexTextureImageUnits > 0) {
GLuint numUnits = MIN2(st->state.num_vertex_textures,
st->ctx->Const.MaxVertexTextureImageUnits);
cso_set_vertex_sampler_views(st->cso_context,
numUnits,
st->state.sampler_vertex_views);
}
}
static void
update_fragment_textures(struct st_context *st)
{
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;
@ -198,74 +297,17 @@ update_textures(struct st_context *st)
/* loop over sampler units (aka tex image units) */
for (su = 0; su < st->ctx->Const.MaxTextureImageUnits; su++) {
struct pipe_sampler_view *sampler_view = NULL;
enum pipe_format st_view_format;
if (samplersUsed & (1 << su)) {
struct gl_texture_object *texObj;
struct st_texture_object *stObj;
if (fprog->Base.SamplersUsed & (1 << su)) {
GLboolean retval;
GLuint texUnit;
const struct gl_sampler_object *samp;
if (fprog->Base.SamplersUsed & (1 << su))
texUnit = fprog->Base.SamplerUnits[su];
else
texUnit = vprog->Base.SamplerUnits[su];
texUnit = fprog->Base.SamplerUnits[su];
samp = _mesa_get_samplerobj(st->ctx, texUnit);
texObj = st->ctx->Texture.Unit[texUnit]._Current;
if (!texObj) {
texObj = st_get_default_texture(st);
samp = &texObj->Sampler;
}
stObj = st_texture_object(texObj);
retval = st_finalize_texture(st->ctx, st->pipe, texObj);
if (!retval) {
/* out of mem */
continue;
}
/* 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
* 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;
}
retval = update_single_texture(st, &sampler_view, texUnit);
if (retval == GL_FALSE)
continue;
st->state.num_textures = su + 1;
/* 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);
}
pipe_sampler_view_reference(&st->state.sampler_views[su], sampler_view);
}
@ -273,16 +315,14 @@ update_textures(struct st_context *st)
cso_set_fragment_sampler_views(st->cso_context,
st->state.num_textures,
st->state.sampler_views);
if (st->ctx->Const.MaxVertexTextureImageUnits > 0) {
GLuint numUnits = MIN2(st->state.num_textures,
st->ctx->Const.MaxVertexTextureImageUnits);
cso_set_vertex_sampler_views(st->cso_context,
numUnits,
st->state.sampler_views);
}
}
static void
update_textures(struct st_context *st)
{
update_fragment_textures(st);
update_vertex_textures(st);
}
const struct st_tracked_state st_update_texture = {
"st_update_texture", /* name */
@ -293,9 +333,6 @@ const struct st_tracked_state st_update_texture = {
update_textures /* update */
};
static void
finalize_textures(struct st_context *st)
{

View File

@ -133,9 +133,6 @@ st_create_context_priv( struct gl_context *ctx, struct pipe_context *pipe )
else
st->internal_target = PIPE_TEXTURE_RECT;
for (i = 0; i < PIPE_MAX_SAMPLERS; i++)
st->state.sampler_list[i] = &st->state.samplers[i];
for (i = 0; i < 3; i++) {
memset(&st->velems_util_draw[i], 0, sizeof(struct pipe_vertex_element));
st->velems_util_draw[i].src_offset = i * 4 * sizeof(float);

View File

@ -90,7 +90,7 @@ struct st_context
struct pipe_depth_stencil_alpha_state depth_stencil;
struct pipe_rasterizer_state rasterizer;
struct pipe_sampler_state samplers[PIPE_MAX_SAMPLERS];
struct pipe_sampler_state *sampler_list[PIPE_MAX_SAMPLERS];
struct pipe_sampler_state vertex_samplers[PIPE_MAX_VERTEX_SAMPLERS];
struct pipe_clip_state clip;
struct {
void *ptr;
@ -98,12 +98,15 @@ struct st_context
} constants[PIPE_SHADER_TYPES];
struct pipe_framebuffer_state framebuffer;
struct pipe_sampler_view *sampler_views[PIPE_MAX_SAMPLERS];
struct pipe_sampler_view *sampler_vertex_views[PIPE_MAX_VERTEX_SAMPLERS];
struct pipe_scissor_state scissor;
struct pipe_viewport_state viewport;
unsigned sample_mask;
GLuint num_samplers;
GLuint num_vertex_samplers;
GLuint num_textures;
GLuint num_vertex_textures;
GLuint poly_stipple[32]; /**< In OpenGL's bottom-to-top order */
} state;