summaryrefslogtreecommitdiffstats
path: root/src/mesa/state_tracker
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa/state_tracker')
-rw-r--r--src/mesa/state_tracker/st_atom_blend.c61
-rw-r--r--src/mesa/state_tracker/st_atom_clip.c7
-rw-r--r--src/mesa/state_tracker/st_atom_pixeltransfer.c2
-rw-r--r--src/mesa/state_tracker/st_atom_sampler.c152
-rw-r--r--src/mesa/state_tracker/st_atom_scissor.c17
-rw-r--r--src/mesa/state_tracker/st_atom_stipple.c11
-rw-r--r--src/mesa/state_tracker/st_atom_texture.c30
-rw-r--r--src/mesa/state_tracker/st_cb_drawpixels.c10
-rw-r--r--src/mesa/state_tracker/st_cb_texture.c7
-rw-r--r--src/mesa/state_tracker/st_cb_viewport.c15
-rw-r--r--src/mesa/state_tracker/st_context.h6
-rw-r--r--src/mesa/state_tracker/st_draw.c82
-rw-r--r--src/mesa/state_tracker/st_format.c122
-rw-r--r--src/mesa/state_tracker/st_format.h3
-rw-r--r--src/mesa/state_tracker/st_manager.c163
15 files changed, 423 insertions, 265 deletions
diff --git a/src/mesa/state_tracker/st_atom_blend.c b/src/mesa/state_tracker/st_atom_blend.c
index d1844e1066f..4c9a2b95ac3 100644
--- a/src/mesa/state_tracker/st_atom_blend.c
+++ b/src/mesa/state_tracker/st_atom_blend.c
@@ -156,7 +156,7 @@ translate_logicop(GLenum logicop)
* Figure out if colormasks are different per rt.
*/
static GLboolean
-colormask_per_rt(struct gl_context *ctx)
+colormask_per_rt(const struct gl_context *ctx)
{
/* a bit suboptimal have to compare lots of values */
unsigned i;
@@ -172,7 +172,7 @@ colormask_per_rt(struct gl_context *ctx)
* Figure out if blend enables/state are different per rt.
*/
static GLboolean
-blend_per_rt(struct gl_context *ctx)
+blend_per_rt(const struct gl_context *ctx)
{
if (ctx->Color.BlendEnabled &&
(ctx->Color.BlendEnabled != ((1 << ctx->Const.MaxDrawBuffers) - 1))) {
@@ -190,13 +190,14 @@ static void
update_blend( struct st_context *st )
{
struct pipe_blend_state *blend = &st->state.blend;
+ const struct gl_context *ctx = st->ctx;
unsigned num_state = 1;
unsigned i, j;
memset(blend, 0, sizeof(*blend));
- if (blend_per_rt(st->ctx) || colormask_per_rt(st->ctx)) {
- num_state = st->ctx->Const.MaxDrawBuffers;
+ if (blend_per_rt(ctx) || colormask_per_rt(ctx)) {
+ num_state = ctx->Const.MaxDrawBuffers;
blend->independent_blend_enable = 1;
}
/* Note it is impossible to correctly deal with EXT_blend_logic_op and
@@ -205,52 +206,52 @@ update_blend( struct st_context *st )
and separate alpha/rgb logicop/blend support respectively. Neither
possible in gallium nor most hardware. Assume these combinations
don't happen. */
- if (st->ctx->Color.ColorLogicOpEnabled ||
- (st->ctx->Color.BlendEnabled &&
- st->ctx->Color.Blend[0].EquationRGB == GL_LOGIC_OP)) {
+ if (ctx->Color.ColorLogicOpEnabled ||
+ (ctx->Color.BlendEnabled &&
+ ctx->Color.Blend[0].EquationRGB == GL_LOGIC_OP)) {
/* logicop enabled */
blend->logicop_enable = 1;
- blend->logicop_func = translate_logicop(st->ctx->Color.LogicOp);
+ blend->logicop_func = translate_logicop(ctx->Color.LogicOp);
}
- else if (st->ctx->Color.BlendEnabled) {
+ else if (ctx->Color.BlendEnabled) {
/* blending enabled */
for (i = 0, j = 0; i < num_state; i++) {
- blend->rt[i].blend_enable = (st->ctx->Color.BlendEnabled >> i) & 0x1;
+ blend->rt[i].blend_enable = (ctx->Color.BlendEnabled >> i) & 0x1;
- if (st->ctx->Extensions.ARB_draw_buffers_blend)
+ if (ctx->Extensions.ARB_draw_buffers_blend)
j = i;
blend->rt[i].rgb_func =
- translate_blend(st->ctx->Color.Blend[j].EquationRGB);
+ translate_blend(ctx->Color.Blend[j].EquationRGB);
- if (st->ctx->Color.Blend[i].EquationRGB == GL_MIN ||
- st->ctx->Color.Blend[i].EquationRGB == GL_MAX) {
+ if (ctx->Color.Blend[i].EquationRGB == GL_MIN ||
+ ctx->Color.Blend[i].EquationRGB == GL_MAX) {
/* Min/max are special */
blend->rt[i].rgb_src_factor = PIPE_BLENDFACTOR_ONE;
blend->rt[i].rgb_dst_factor = PIPE_BLENDFACTOR_ONE;
}
else {
blend->rt[i].rgb_src_factor =
- translate_blend(st->ctx->Color.Blend[j].SrcRGB);
+ translate_blend(ctx->Color.Blend[j].SrcRGB);
blend->rt[i].rgb_dst_factor =
- translate_blend(st->ctx->Color.Blend[j].DstRGB);
+ translate_blend(ctx->Color.Blend[j].DstRGB);
}
blend->rt[i].alpha_func =
- translate_blend(st->ctx->Color.Blend[j].EquationA);
+ translate_blend(ctx->Color.Blend[j].EquationA);
- if (st->ctx->Color.Blend[i].EquationA == GL_MIN ||
- st->ctx->Color.Blend[i].EquationA == GL_MAX) {
+ if (ctx->Color.Blend[i].EquationA == GL_MIN ||
+ ctx->Color.Blend[i].EquationA == GL_MAX) {
/* Min/max are special */
blend->rt[i].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
blend->rt[i].alpha_dst_factor = PIPE_BLENDFACTOR_ONE;
}
else {
blend->rt[i].alpha_src_factor =
- translate_blend(st->ctx->Color.Blend[j].SrcA);
+ translate_blend(ctx->Color.Blend[j].SrcA);
blend->rt[i].alpha_dst_factor =
- translate_blend(st->ctx->Color.Blend[j].DstA);
+ translate_blend(ctx->Color.Blend[j].DstA);
}
}
}
@@ -260,25 +261,25 @@ update_blend( struct st_context *st )
/* Colormask - maybe reverse these bits? */
for (i = 0; i < num_state; i++) {
- if (st->ctx->Color.ColorMask[i][0])
+ if (ctx->Color.ColorMask[i][0])
blend->rt[i].colormask |= PIPE_MASK_R;
- if (st->ctx->Color.ColorMask[i][1])
+ if (ctx->Color.ColorMask[i][1])
blend->rt[i].colormask |= PIPE_MASK_G;
- if (st->ctx->Color.ColorMask[i][2])
+ if (ctx->Color.ColorMask[i][2])
blend->rt[i].colormask |= PIPE_MASK_B;
- if (st->ctx->Color.ColorMask[i][3])
+ if (ctx->Color.ColorMask[i][3])
blend->rt[i].colormask |= PIPE_MASK_A;
}
- if (st->ctx->Color.DitherFlag)
+ if (ctx->Color.DitherFlag)
blend->dither = 1;
- if (st->ctx->Multisample.Enabled) {
+ if (ctx->Multisample.Enabled) {
/* unlike in gallium/d3d10 these operations are only performed
if msaa is enabled */
- if (st->ctx->Multisample.SampleAlphaToCoverage)
+ if (ctx->Multisample.SampleAlphaToCoverage)
blend->alpha_to_coverage = 1;
- if (st->ctx->Multisample.SampleAlphaToOne)
+ if (ctx->Multisample.SampleAlphaToOne)
blend->alpha_to_one = 1;
}
@@ -286,7 +287,7 @@ update_blend( struct st_context *st )
{
struct pipe_blend_color bc;
- COPY_4FV(bc.color, st->ctx->Color.BlendColorUnclamped);
+ COPY_4FV(bc.color, ctx->Color.BlendColorUnclamped);
cso_set_blend_color(st->cso_context, &bc);
}
}
diff --git a/src/mesa/state_tracker/st_atom_clip.c b/src/mesa/state_tracker/st_atom_clip.c
index 16f7aaae6f4..1330db843a6 100644
--- a/src/mesa/state_tracker/st_atom_clip.c
+++ b/src/mesa/state_tracker/st_atom_clip.c
@@ -43,20 +43,21 @@
static void update_clip( struct st_context *st )
{
struct pipe_clip_state clip;
+ const struct gl_context *ctx = st->ctx;
GLuint i;
memset(&clip, 0, sizeof(clip));
for (i = 0; i < PIPE_MAX_CLIP_PLANES; i++) {
- if (st->ctx->Transform.ClipPlanesEnabled & (1 << i)) {
+ if (ctx->Transform.ClipPlanesEnabled & (1 << i)) {
memcpy(clip.ucp[clip.nr],
- st->ctx->Transform._ClipUserPlane[i],
+ ctx->Transform._ClipUserPlane[i],
sizeof(clip.ucp[0]));
clip.nr++;
}
}
- clip.depth_clamp = st->ctx->Transform.DepthClamp != GL_FALSE;
+ clip.depth_clamp = ctx->Transform.DepthClamp != GL_FALSE;
if (memcmp(&clip, &st->state.clip, sizeof(clip)) != 0) {
st->state.clip = clip;
diff --git a/src/mesa/state_tracker/st_atom_pixeltransfer.c b/src/mesa/state_tracker/st_atom_pixeltransfer.c
index 95b706cb96c..1f833d28212 100644
--- a/src/mesa/state_tracker/st_atom_pixeltransfer.c
+++ b/src/mesa/state_tracker/st_atom_pixeltransfer.c
@@ -94,7 +94,7 @@ create_color_map_texture(struct gl_context *ctx)
const uint texSize = 256; /* simple, and usually perfect */
/* find an RGBA texture format */
- format = st_choose_format(pipe->screen, GL_RGBA,
+ format = st_choose_format(pipe->screen, GL_RGBA, GL_NONE, GL_NONE,
PIPE_TEXTURE_2D, 0, PIPE_BIND_SAMPLER_VIEW);
/* create texture for color map/table */
diff --git a/src/mesa/state_tracker/st_atom_sampler.c b/src/mesa/state_tracker/st_atom_sampler.c
index 06024ad2657..731338f9beb 100644
--- a/src/mesa/state_tracker/st_atom_sampler.c
+++ b/src/mesa/state_tracker/st_atom_sampler.c
@@ -120,87 +120,91 @@ gl_filter_to_img_filter(GLenum filter)
}
}
-static void convert_sampler(struct st_context *st,
- struct pipe_sampler_state *sampler,
- GLuint texUnit)
+
+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;
-
- texobj = st->ctx->Texture.Unit[texUnit]._Current;
- if (!texobj) {
- texobj = st_get_default_texture(st);
- }
-
- msamp = _mesa_get_samplerobj(st->ctx, texUnit);
-
- memset(sampler, 0, sizeof(*sampler));
- 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;
+ struct gl_texture_object *texobj;
+ struct gl_context *ctx = st->ctx;
+ struct gl_sampler_object *msamp;
+
+ texobj = ctx->Texture.Unit[texUnit]._Current;
+ if (!texobj) {
+ texobj = st_get_default_texture(st);
+ }
+
+ msamp = _mesa_get_samplerobj(ctx, texUnit);
+
+ memset(sampler, 0, sizeof(*sampler));
+ 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 = 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 =
+ ctx->Texture.CubeMapSeamless || msamp->CubeMapSeamless;
}
+
static void
update_vertex_samplers(struct st_context *st)
{
- struct gl_vertex_program *vprog = st->ctx->VertexProgram._Current;
+ const struct gl_context *ctx = st->ctx;
+ struct gl_vertex_program *vprog = 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++) {
+ for (su = 0; su < ctx->Const.MaxVertexTextureImageUnits; su++) {
struct pipe_sampler_state *sampler = st->state.vertex_samplers + su;
if (vprog->Base.SamplersUsed & (1 << su)) {
@@ -220,16 +224,18 @@ update_vertex_samplers(struct st_context *st)
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 struct gl_context *ctx = st->ctx;
+ struct gl_fragment_program *fprog = ctx->FragmentProgram._Current;
GLuint su;
st->state.num_samplers = 0;
/* loop over sampler units (aka tex image units) */
- for (su = 0; su < st->ctx->Const.MaxTextureImageUnits; su++) {
+ for (su = 0; su < ctx->Const.MaxTextureImageUnits; su++) {
struct pipe_sampler_state *sampler = st->state.samplers + su;
@@ -254,6 +260,7 @@ update_fragment_samplers(struct st_context *st)
cso_single_sampler_done(st->cso_context);
}
+
static void
update_samplers(struct st_context *st)
{
@@ -261,6 +268,7 @@ update_samplers(struct st_context *st)
update_vertex_samplers(st);
}
+
const struct st_tracked_state st_update_sampler = {
"st_update_sampler", /* name */
{ /* dirty */
diff --git a/src/mesa/state_tracker/st_atom_scissor.c b/src/mesa/state_tracker/st_atom_scissor.c
index 56b1383ae39..eb13877787b 100644
--- a/src/mesa/state_tracker/st_atom_scissor.c
+++ b/src/mesa/state_tracker/st_atom_scissor.c
@@ -44,7 +44,8 @@ static void
update_scissor( struct st_context *st )
{
struct pipe_scissor_state scissor;
- const struct gl_framebuffer *fb = st->ctx->DrawBuffer;
+ const struct gl_context *ctx = st->ctx;
+ const struct gl_framebuffer *fb = ctx->DrawBuffer;
GLint miny, maxy;
scissor.minx = 0;
@@ -52,15 +53,15 @@ update_scissor( struct st_context *st )
scissor.maxx = fb->Width;
scissor.maxy = fb->Height;
- if (st->ctx->Scissor.Enabled) {
+ if (ctx->Scissor.Enabled) {
/* need to be careful here with xmax or ymax < 0 */
- GLint xmax = MAX2(0, st->ctx->Scissor.X + st->ctx->Scissor.Width);
- GLint ymax = MAX2(0, st->ctx->Scissor.Y + st->ctx->Scissor.Height);
+ GLint xmax = MAX2(0, ctx->Scissor.X + ctx->Scissor.Width);
+ GLint ymax = MAX2(0, ctx->Scissor.Y + ctx->Scissor.Height);
- if (st->ctx->Scissor.X > (GLint)scissor.minx)
- scissor.minx = st->ctx->Scissor.X;
- if (st->ctx->Scissor.Y > (GLint)scissor.miny)
- scissor.miny = st->ctx->Scissor.Y;
+ if (ctx->Scissor.X > (GLint)scissor.minx)
+ scissor.minx = ctx->Scissor.X;
+ if (ctx->Scissor.Y > (GLint)scissor.miny)
+ scissor.miny = ctx->Scissor.Y;
if (xmax < (GLint) scissor.maxx)
scissor.maxx = xmax;
diff --git a/src/mesa/state_tracker/st_atom_stipple.c b/src/mesa/state_tracker/st_atom_stipple.c
index ecdd9f06f6a..b3e0dc7f1b0 100644
--- a/src/mesa/state_tracker/st_atom_stipple.c
+++ b/src/mesa/state_tracker/st_atom_stipple.c
@@ -64,17 +64,18 @@ invert_stipple(GLuint dest[32], const GLuint src[32], GLuint winHeight)
static void
update_stipple( struct st_context *st )
{
+ const struct gl_context *ctx = st->ctx;
const GLuint sz = sizeof(st->state.poly_stipple);
- assert(sz == sizeof(st->ctx->PolygonStipple));
+ assert(sz == sizeof(ctx->PolygonStipple));
- if (memcmp(st->state.poly_stipple, st->ctx->PolygonStipple, sz)) {
+ if (memcmp(st->state.poly_stipple, ctx->PolygonStipple, sz)) {
/* state has changed */
struct pipe_poly_stipple newStipple;
- memcpy(st->state.poly_stipple, st->ctx->PolygonStipple, sz);
+ memcpy(st->state.poly_stipple, ctx->PolygonStipple, sz);
- invert_stipple(newStipple.stipple, st->ctx->PolygonStipple,
- st->ctx->DrawBuffer->Height);
+ invert_stipple(newStipple.stipple, ctx->PolygonStipple,
+ ctx->DrawBuffer->Height);
st->pipe->set_polygon_stipple(st->pipe, &newStipple);
}
diff --git a/src/mesa/state_tracker/st_atom_texture.c b/src/mesa/state_tracker/st_atom_texture.c
index 072eb977ebb..800a9f1f0e0 100644
--- a/src/mesa/state_tracker/st_atom_texture.c
+++ b/src/mesa/state_tracker/st_atom_texture.c
@@ -187,15 +187,16 @@ update_single_texture(struct st_context *st, struct pipe_sampler_view **sampler_
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(st->ctx, texUnit);
+ samp = _mesa_get_samplerobj(ctx, texUnit);
- texObj = st->ctx->Texture.Unit[texUnit]._Current;
+ texObj = ctx->Texture.Unit[texUnit]._Current;
if (!texObj) {
texObj = st_get_default_texture(st);
@@ -203,7 +204,7 @@ update_single_texture(struct st_context *st, struct pipe_sampler_view **sampler_
}
stObj = st_texture_object(texObj);
- retval = st_finalize_texture(st->ctx, st->pipe, texObj);
+ retval = st_finalize_texture(ctx, st->pipe, texObj);
if (!retval) {
/* out of mem */
return GL_FALSE;
@@ -253,13 +254,14 @@ update_single_texture(struct st_context *st, struct pipe_sampler_view **sampler_
static void
update_vertex_textures(struct st_context *st)
{
- struct gl_vertex_program *vprog = st->ctx->VertexProgram._Current;
+ const struct gl_context *ctx = st->ctx;
+ struct gl_vertex_program *vprog = 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++) {
+ for (su = 0; su < ctx->Const.MaxTextureImageUnits; su++) {
struct pipe_sampler_view *sampler_view = NULL;
if (vprog->Base.SamplersUsed & (1 << su)) {
GLboolean retval;
@@ -277,9 +279,9 @@ update_vertex_textures(struct st_context *st)
pipe_sampler_view_reference(&st->state.sampler_vertex_views[su], sampler_view);
}
- if (st->ctx->Const.MaxVertexTextureImageUnits > 0) {
+ if (ctx->Const.MaxVertexTextureImageUnits > 0) {
GLuint numUnits = MIN2(st->state.num_vertex_textures,
- st->ctx->Const.MaxVertexTextureImageUnits);
+ ctx->Const.MaxVertexTextureImageUnits);
cso_set_vertex_sampler_views(st->cso_context,
numUnits,
st->state.sampler_vertex_views);
@@ -289,13 +291,14 @@ update_vertex_textures(struct st_context *st)
static void
update_fragment_textures(struct st_context *st)
{
- struct gl_fragment_program *fprog = st->ctx->FragmentProgram._Current;
+ const struct gl_context *ctx = st->ctx;
+ struct gl_fragment_program *fprog = ctx->FragmentProgram._Current;
GLuint su;
st->state.num_textures = 0;
/* loop over sampler units (aka tex image units) */
- for (su = 0; su < st->ctx->Const.MaxTextureImageUnits; su++) {
+ for (su = 0; su < ctx->Const.MaxTextureImageUnits; su++) {
struct pipe_sampler_view *sampler_view = NULL;
if (fprog->Base.SamplersUsed & (1 << su)) {
GLboolean retval;
@@ -338,22 +341,23 @@ const struct st_tracked_state st_update_vertex_texture = {
static void
finalize_textures(struct st_context *st)
{
- struct gl_fragment_program *fprog = st->ctx->FragmentProgram._Current;
+ 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 < st->ctx->Const.MaxTextureCoordUnits; su++) {
+ 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
- = st->ctx->Texture.Unit[texUnit]._Current;
+ = ctx->Texture.Unit[texUnit]._Current;
if (texObj) {
GLboolean retval;
- retval = st_finalize_texture(st->ctx, st->pipe, texObj);
+ retval = st_finalize_texture(ctx, st->pipe, texObj);
if (!retval) {
/* out of mem */
st->missing_textures = GL_TRUE;
diff --git a/src/mesa/state_tracker/st_cb_drawpixels.c b/src/mesa/state_tracker/st_cb_drawpixels.c
index 965fbcd1d9e..d61d7ac22be 100644
--- a/src/mesa/state_tracker/st_cb_drawpixels.c
+++ b/src/mesa/state_tracker/st_cb_drawpixels.c
@@ -989,8 +989,9 @@ st_DrawPixels(struct gl_context *ctx, GLint x, GLint y,
/* can we write to stencil if not fallback */
if (!pipe->screen->get_param(pipe->screen, PIPE_CAP_SHADER_STENCIL_EXPORT))
goto stencil_fallback;
-
+
tex_format = st_choose_format(st->pipe->screen, base_format(format),
+ GL_NONE, GL_NONE,
PIPE_TEXTURE_2D,
0, PIPE_BIND_SAMPLER_VIEW);
if (tex_format == PIPE_FORMAT_Z24_UNORM_S8_USCALED)
@@ -1399,13 +1400,14 @@ st_CopyPixels(struct gl_context *ctx, GLint srcx, GLint srcy,
/* srcFormat can't be used as a texture format */
if (type == GL_DEPTH) {
texFormat = st_choose_format(screen, GL_DEPTH_COMPONENT,
- st->internal_target, sample_count,
- PIPE_BIND_DEPTH_STENCIL);
+ GL_NONE, GL_NONE, st->internal_target,
+ sample_count, PIPE_BIND_DEPTH_STENCIL);
assert(texFormat != PIPE_FORMAT_NONE);
}
else {
/* default color format */
- texFormat = st_choose_format(screen, GL_RGBA, st->internal_target,
+ texFormat = st_choose_format(screen, GL_RGBA,
+ GL_NONE, GL_NONE, st->internal_target,
sample_count, PIPE_BIND_SAMPLER_VIEW);
assert(texFormat != PIPE_FORMAT_NONE);
}
diff --git a/src/mesa/state_tracker/st_cb_texture.c b/src/mesa/state_tracker/st_cb_texture.c
index 88f62902b25..6907cfc03cf 100644
--- a/src/mesa/state_tracker/st_cb_texture.c
+++ b/src/mesa/state_tracker/st_cb_texture.c
@@ -842,7 +842,7 @@ decompress_with_blit(struct gl_context * ctx, GLenum target, GLint level,
else {
/* format translation via floats */
GLuint row;
- enum pipe_format format = util_format_linear(dst_texture->format);
+ enum pipe_format pformat = util_format_linear(dst_texture->format);
for (row = 0; row < height; row++) {
const GLbitfield transferOps = 0x0; /* bypassed for glGetTexImage() */
GLfloat rgba[4 * MAX_WIDTH];
@@ -854,7 +854,7 @@ decompress_with_blit(struct gl_context * ctx, GLenum target, GLint level,
/* get float[4] rgba row from surface */
pipe_get_tile_rgba_format(pipe, tex_xfer, 0, row, width, 1,
- format, rgba);
+ pformat, rgba);
_mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) rgba, format,
type, dest, &ctx->Pack, transferOps);
@@ -1241,7 +1241,8 @@ fallback_copy_texsubimage(struct gl_context *ctx, GLenum target, GLint level,
src_trans = pipe_get_transfer(pipe,
strb->texture,
- 0, 0,
+ strb->rtt_level,
+ strb->rtt_face + strb->rtt_slice,
PIPE_TRANSFER_READ,
srcX, srcY,
width, height);
diff --git a/src/mesa/state_tracker/st_cb_viewport.c b/src/mesa/state_tracker/st_cb_viewport.c
index 049755e45c0..d4742eb897d 100644
--- a/src/mesa/state_tracker/st_cb_viewport.c
+++ b/src/mesa/state_tracker/st_cb_viewport.c
@@ -56,13 +56,20 @@ static void st_viewport(struct gl_context * ctx, GLint x, GLint y,
if (!st->invalidate_on_gl_viewport)
return;
+ /*
+ * Normally we'd want the state tracker manager to mark the drawables
+ * invalid only when needed. This will force the state tracker manager
+ * to revalidate the drawable, rather than just update the context with
+ * the latest cached drawable info.
+ */
+
stdraw = st_ws_framebuffer(st->ctx->DrawBuffer);
stread = st_ws_framebuffer(st->ctx->ReadBuffer);
- if (stdraw)
- p_atomic_set(&stdraw->revalidate, TRUE);
- if (stread && stread != stdraw)
- p_atomic_set(&stread->revalidate, TRUE);
+ if (stdraw && stdraw->iface)
+ stdraw->iface_stamp = p_atomic_read(&stdraw->iface->stamp) - 1;
+ if (stread && stread != stdraw && stread->iface)
+ stread->iface_stamp = p_atomic_read(&stread->iface->stamp) - 1;
}
void st_init_viewport_functions(struct dd_function_table *functions)
diff --git a/src/mesa/state_tracker/st_context.h b/src/mesa/state_tracker/st_context.h
index ff207039d78..0a322022149 100644
--- a/src/mesa/state_tracker/st_context.h
+++ b/src/mesa/state_tracker/st_context.h
@@ -204,6 +204,9 @@ struct st_context
/* Active render condition. */
struct pipe_query *render_condition;
unsigned condition_mode;
+
+ int32_t draw_stamp;
+ int32_t read_stamp;
};
@@ -227,7 +230,8 @@ struct st_framebuffer
struct st_framebuffer_iface *iface;
enum st_attachment_type statts[ST_ATTACHMENT_COUNT];
unsigned num_statts;
- int32_t revalidate;
+ int32_t stamp;
+ int32_t iface_stamp;
};
diff --git a/src/mesa/state_tracker/st_draw.c b/src/mesa/state_tracker/st_draw.c
index 56955d357b1..5040c6fa5ab 100644
--- a/src/mesa/state_tracker/st_draw.c
+++ b/src/mesa/state_tracker/st_draw.c
@@ -33,7 +33,7 @@
*
* We basically convert the VBO's vertex attribute/array information into
* Gallium vertex state, bind the vertex buffer objects and call
- * pipe->draw_elements(), pipe->draw_range_elements() or pipe->draw_arrays().
+ * pipe->draw_vbo().
*
* Authors:
* Keith Whitwell <[email protected]>
@@ -233,11 +233,26 @@ st_pipe_vertex_format(GLenum type, GLuint size, GLenum format,
}
+/**
+ * This is very similar to vbo_all_varyings_in_vbos() but we test
+ * the stride. See bug 38626.
+ */
+static GLboolean
+all_varyings_in_vbos(const struct gl_client_array *arrays[])
+{
+ GLuint i;
+
+ for (i = 0; i < VERT_ATTRIB_MAX; i++)
+ if (arrays[i]->StrideB && !_mesa_is_bufferobj(arrays[i]->BufferObj))
+ return GL_FALSE;
+
+ return GL_TRUE;
+}
+
/**
* Examine the active arrays to determine if we have interleaved
* vertex arrays all living in one VBO, or all living in user space.
- * \param userSpace returns whether the arrays are in user space.
*/
static GLboolean
is_interleaved_arrays(const struct st_vertex_program *vp,
@@ -247,8 +262,8 @@ is_interleaved_arrays(const struct st_vertex_program *vp,
GLuint attr;
const struct gl_buffer_object *firstBufObj = NULL;
GLint firstStride = -1;
- const GLubyte *client_addr = NULL;
- GLboolean user_memory = GL_FALSE;
+ const GLubyte *firstPtr = NULL;
+ GLboolean userSpaceBuffer = GL_FALSE;
for (attr = 0; attr < vpv->num_inputs; attr++) {
const GLuint mesaAttr = vp->index_to_input[attr];
@@ -256,37 +271,26 @@ is_interleaved_arrays(const struct st_vertex_program *vp,
const struct gl_buffer_object *bufObj = array->BufferObj;
const GLsizei stride = array->StrideB; /* in bytes */
- if (firstStride < 0) {
+ if (attr == 0) {
+ /* save info about the first array */
firstStride = stride;
- user_memory = !bufObj || !bufObj->Name;
- }
- else if (firstStride != stride) {
- return GL_FALSE;
- }
-
- if (!bufObj || !bufObj->Name) {
- /* Try to detect if the client-space arrays are
- * "close" to each other.
- */
- if (!user_memory) {
- return GL_FALSE;
- }
- if (!client_addr) {
- client_addr = array->Ptr;
- }
- else if (abs(array->Ptr - client_addr) > firstStride) {
- /* arrays start too far apart */
- return GL_FALSE;
- }
- }
- else if (!firstBufObj) {
- if (user_memory) {
- return GL_FALSE;
- }
+ firstPtr = array->Ptr;
firstBufObj = bufObj;
+ userSpaceBuffer = !bufObj || !bufObj->Name;
}
- else if (bufObj != firstBufObj) {
- return GL_FALSE;
+ else {
+ /* check if other arrays interleave with the first, in same buffer */
+ if (stride != firstStride)
+ return GL_FALSE; /* strides don't match */
+
+ if (bufObj != firstBufObj)
+ return GL_FALSE; /* arrays in different VBOs */
+
+ if (abs(array->Ptr - firstPtr) > firstStride)
+ return GL_FALSE; /* arrays start too far apart */
+
+ if ((!bufObj || !_mesa_is_bufferobj(bufObj)) != userSpaceBuffer)
+ return GL_FALSE; /* mix of VBO and user-space arrays */
}
}
@@ -510,6 +514,7 @@ setup_index_buffer(struct gl_context *ctx,
}
}
+
/**
* Prior to drawing, check that any uniforms referenced by the
* current shader have been set. If a uniform has not been set,
@@ -556,8 +561,8 @@ translate_prim(const struct gl_context *ctx, unsigned prim)
assert(GL_TRIANGLE_STRIP_ADJACENCY == PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY);
/* Avoid quadstrips if it's easy to do so:
- * Note: it's imporant to do the correct trimming if we change the prim type!
- * We do that wherever this function is called.
+ * Note: it's important to do the correct trimming if we change the
+ * prim type! We do that wherever this function is called.
*/
if (prim == GL_QUAD_STRIP &&
ctx->Light.ShadeModel != GL_FLAT &&
@@ -650,7 +655,8 @@ st_draw_vbo(struct gl_context *ctx,
struct pipe_draw_info info;
unsigned i, num_instances = 1;
GLboolean new_array =
- st->dirty.st && (st->dirty.mesa & (_NEW_ARRAY | _NEW_PROGRAM)) != 0;
+ st->dirty.st &&
+ (st->dirty.mesa & (_NEW_ARRAY | _NEW_PROGRAM | _NEW_BUFFER_OBJECT)) != 0;
/* Mesa core state should have been validated already */
assert(ctx->NewState == 0x0);
@@ -658,7 +664,7 @@ st_draw_vbo(struct gl_context *ctx,
if (ib) {
/* Gallium probably doesn't want this in some cases. */
if (!index_bounds_valid)
- if (!vbo_all_varyings_in_vbos(arrays))
+ if (!all_varyings_in_vbos(arrays))
vbo_get_minmax_index(ctx, prims, ib, &min_index, &max_index);
for (i = 0; i < nr_prims; i++) {
@@ -738,8 +744,8 @@ st_draw_vbo(struct gl_context *ctx,
}
}
- info.primitive_restart = st->ctx->Array.PrimitiveRestart;
- info.restart_index = st->ctx->Array.RestartIndex;
+ info.primitive_restart = ctx->Array.PrimitiveRestart;
+ info.restart_index = ctx->Array.RestartIndex;
/* do actual drawing */
for (i = 0; i < nr_prims; i++) {
diff --git a/src/mesa/state_tracker/st_format.c b/src/mesa/state_tracker/st_format.c
index 35835712547..fa5d8f5050a 100644
--- a/src/mesa/state_tracker/st_format.c
+++ b/src/mesa/state_tracker/st_format.c
@@ -608,7 +608,7 @@ struct format_mapping
* Multiple GL enums might map to multiple pipe_formats.
* The first pipe format in the list that's supported is the one that's chosen.
*/
-static struct format_mapping format_map[] = {
+static const struct format_mapping format_map[] = {
/* Basic RGB, RGBA formats */
{
{ GL_RGB10, GL_RGB10_A2, 0 },
@@ -616,7 +616,7 @@ static struct format_mapping format_map[] = {
},
{
{ 4, GL_RGBA, GL_RGBA8, 0 },
- { DEFAULT_RGBA_FORMATS, 0 }
+ { PIPE_FORMAT_R8G8B8A8_UNORM, DEFAULT_RGBA_FORMATS }
},
{
{ GL_BGRA, 0 },
@@ -624,7 +624,7 @@ static struct format_mapping format_map[] = {
},
{
{ 3, GL_RGB, GL_RGB8, 0 },
- { DEFAULT_RGB_FORMATS, 0 }
+ { DEFAULT_RGB_FORMATS }
},
{
{ GL_RGB12, GL_RGB16, GL_RGBA12, GL_RGBA16, 0 },
@@ -1108,7 +1108,7 @@ static struct format_mapping format_map[] = {
* Return first supported format from the given list.
*/
static enum pipe_format
-find_supported_format(struct pipe_screen *screen,
+find_supported_format(struct pipe_screen *screen,
const enum pipe_format formats[],
enum pipe_texture_target target,
unsigned sample_count,
@@ -1124,6 +1124,91 @@ find_supported_format(struct pipe_screen *screen,
return PIPE_FORMAT_NONE;
}
+struct exact_format_mapping
+{
+ GLenum format;
+ GLenum type;
+ enum pipe_format pformat;
+};
+
+static const struct exact_format_mapping rgba8888_tbl[] =
+{
+ { GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, PIPE_FORMAT_A8B8G8R8_UNORM },
+ { GL_ABGR_EXT, GL_UNSIGNED_INT_8_8_8_8_REV, PIPE_FORMAT_A8B8G8R8_UNORM },
+ { GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, PIPE_FORMAT_R8G8B8A8_UNORM },
+ { GL_ABGR_EXT, GL_UNSIGNED_INT_8_8_8_8, PIPE_FORMAT_R8G8B8A8_UNORM },
+ { GL_BGRA, GL_UNSIGNED_INT_8_8_8_8, PIPE_FORMAT_A8R8G8B8_UNORM },
+ { GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, PIPE_FORMAT_B8G8R8A8_UNORM },
+ { GL_RGBA, GL_UNSIGNED_BYTE, PIPE_FORMAT_R8G8B8A8_UNORM },
+ { GL_ABGR_EXT, GL_UNSIGNED_BYTE, PIPE_FORMAT_A8B8G8R8_UNORM },
+ { GL_BGRA, GL_UNSIGNED_BYTE, PIPE_FORMAT_B8G8R8A8_UNORM },
+ { 0, 0, 0 }
+};
+
+static const struct exact_format_mapping rgbx8888_tbl[] =
+{
+ { GL_BGRA, GL_UNSIGNED_INT_8_8_8_8, PIPE_FORMAT_X8R8G8B8_UNORM },
+ { GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, PIPE_FORMAT_B8G8R8X8_UNORM },
+ { GL_BGRA, GL_UNSIGNED_BYTE, PIPE_FORMAT_B8G8R8X8_UNORM },
+ /* No Mesa formats for these Gallium formats:
+ { GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, PIPE_FORMAT_X8B8G8R8_UNORM },
+ { GL_ABGR_EXT, GL_UNSIGNED_INT_8_8_8_8_REV, PIPE_FORMAT_X8B8G8R8_UNORM },
+ { GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, PIPE_FORMAT_R8G8B8X8_UNORM },
+ { GL_ABGR_EXT, GL_UNSIGNED_INT_8_8_8_8, PIPE_FORMAT_R8G8B8X8_UNORM },
+ { GL_RGBA, GL_UNSIGNED_BYTE, PIPE_FORMAT_R8G8B8X8_UNORM },
+ { GL_ABGR_EXT, GL_UNSIGNED_BYTE, PIPE_FORMAT_X8B8G8R8_UNORM },
+ */
+ { 0, 0, 0 }
+};
+
+static const struct exact_format_mapping rgba1010102_tbl[] =
+{
+ { GL_BGRA, GL_UNSIGNED_INT_2_10_10_10_REV, PIPE_FORMAT_B10G10R10A2_UNORM },
+ /* No Mesa formats for these Gallium formats:
+ { GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, PIPE_FORMAT_R10G10B10A2_UNORM },
+ { GL_ABGR_EXT, GL_UNSIGNED_INT_10_10_10_2, PIPE_FORMAT_R10G10B10A2_UNORM },
+ { GL_ABGR_EXT, GL_UNSIGNED_INT, PIPE_FORMAT_R10G10B10A2_UNORM },
+ */
+ { 0, 0, 0 }
+};
+
+/**
+ * If there is an exact pipe_format match for {internalFormat, format, type}
+ * return that, otherwise return PIPE_FORMAT_NONE so we can do fuzzy matching.
+ */
+static enum pipe_format
+find_exact_format(GLint internalFormat, GLenum format, GLenum type)
+{
+ uint i;
+ const struct exact_format_mapping* tbl;
+
+ if (format == GL_NONE || type == GL_NONE)
+ return PIPE_FORMAT_NONE;
+
+ switch (internalFormat) {
+ case 4:
+ case GL_RGBA:
+ case GL_RGBA8:
+ tbl = rgba8888_tbl;
+ break;
+ case 3:
+ case GL_RGB:
+ case GL_RGB8:
+ tbl = rgbx8888_tbl;
+ break;
+ case GL_RGB10_A2:
+ tbl = rgba1010102_tbl;
+ break;
+ default:
+ return PIPE_FORMAT_NONE;
+ }
+
+ for (i = 0; tbl[i].format; i++)
+ if (tbl[i].format == format && tbl[i].type == type)
+ return tbl[i].pformat;
+
+ return PIPE_FORMAT_NONE;
+}
/**
* Given an OpenGL internalFormat value for a texture or surface, return
@@ -1140,11 +1225,13 @@ find_supported_format(struct pipe_screen *screen,
*/
enum pipe_format
st_choose_format(struct pipe_screen *screen, GLenum internalFormat,
+ GLenum format, GLenum type,
enum pipe_texture_target target, unsigned sample_count,
unsigned bindings)
{
GET_CURRENT_CONTEXT(ctx); /* XXX this should be a function parameter */
int i, j;
+ enum pipe_format pf;
/* can't render to compressed formats at this time */
if (_mesa_is_compressed_format(ctx, internalFormat)
@@ -1152,6 +1239,13 @@ st_choose_format(struct pipe_screen *screen, GLenum internalFormat,
return PIPE_FORMAT_NONE;
}
+ /* search for exact matches */
+ pf = find_exact_format(internalFormat, format, type);
+ if (pf != PIPE_FORMAT_NONE &&
+ screen->is_format_supported(screen, pf,
+ target, sample_count, bindings))
+ return pf;
+
/* search table for internalFormat */
for (i = 0; i < Elements(format_map); i++) {
const struct format_mapping *mapping = &format_map[i];
@@ -1183,14 +1277,11 @@ st_choose_renderbuffer_format(struct pipe_screen *screen,
usage = PIPE_BIND_DEPTH_STENCIL;
else
usage = PIPE_BIND_RENDER_TARGET;
- return st_choose_format(screen, internalFormat, PIPE_TEXTURE_2D,
+ return st_choose_format(screen, internalFormat, GL_NONE, GL_NONE, PIPE_TEXTURE_2D,
sample_count, usage);
}
-/**
- * Called via ctx->Driver.chooseTextureFormat().
- */
gl_format
st_ChooseTextureFormat_renderable(struct gl_context *ctx, GLint internalFormat,
GLenum format, GLenum type, GLboolean renderable)
@@ -1206,20 +1297,19 @@ st_ChooseTextureFormat_renderable(struct gl_context *ctx, GLint internalFormat,
* that in advance. Specify potential render target flags now.
*/
bindings = PIPE_BIND_SAMPLER_VIEW;
- if (renderable == GL_TRUE) {
- if (_mesa_is_depth_format(internalFormat) ||
- _mesa_is_depth_or_stencil_format(internalFormat))
+ if (renderable) {
+ if (_mesa_is_depth_or_stencil_format(internalFormat))
bindings |= PIPE_BIND_DEPTH_STENCIL;
- else
+ else
bindings |= PIPE_BIND_RENDER_TARGET;
}
- pFormat = st_choose_format(screen, internalFormat,
+ pFormat = st_choose_format(screen, internalFormat, format, type,
PIPE_TEXTURE_2D, 0, bindings);
if (pFormat == PIPE_FORMAT_NONE) {
/* try choosing format again, this time without render target bindings */
- pFormat = st_choose_format(screen, internalFormat,
+ pFormat = st_choose_format(screen, internalFormat, format, type,
PIPE_TEXTURE_2D, 0, PIPE_BIND_SAMPLER_VIEW);
}
@@ -1231,6 +1321,10 @@ st_ChooseTextureFormat_renderable(struct gl_context *ctx, GLint internalFormat,
return st_pipe_format_to_mesa_format(pFormat);
}
+
+/**
+ * Called via ctx->Driver.ChooseTextureFormat().
+ */
gl_format
st_ChooseTextureFormat(struct gl_context *ctx, GLint internalFormat,
GLenum format, GLenum type)
diff --git a/src/mesa/state_tracker/st_format.h b/src/mesa/state_tracker/st_format.h
index 0fb570f6ee4..1c1f5965f66 100644
--- a/src/mesa/state_tracker/st_format.h
+++ b/src/mesa/state_tracker/st_format.h
@@ -52,8 +52,9 @@ st_pipe_format_to_mesa_format(enum pipe_format pipeFormat);
extern enum pipe_format
st_choose_format(struct pipe_screen *screen, GLenum internalFormat,
+ GLenum format, GLenum type,
enum pipe_texture_target target, unsigned sample_count,
- unsigned tex_usage);
+ unsigned bindings);
extern enum pipe_format
st_choose_renderbuffer_format(struct pipe_screen *screen,
diff --git a/src/mesa/state_tracker/st_manager.c b/src/mesa/state_tracker/st_manager.c
index a68544ddac7..a8c4b5c3f49 100644
--- a/src/mesa/state_tracker/st_manager.c
+++ b/src/mesa/state_tracker/st_manager.c
@@ -139,23 +139,64 @@ buffer_index_to_attachment(gl_buffer_index index)
}
/**
+ * Make sure a context picks up the latest cached state of the
+ * drawables it binds to.
+ */
+static void
+st_context_validate(struct st_context *st,
+ struct st_framebuffer *stdraw,
+ struct st_framebuffer *stread)
+{
+ if (stdraw && stdraw->stamp != st->draw_stamp) {
+ st->dirty.st |= ST_NEW_FRAMEBUFFER;
+ _mesa_resize_framebuffer(st->ctx, &stdraw->Base,
+ stdraw->Base.Width,
+ stdraw->Base.Height);
+ st->draw_stamp = stdraw->stamp;
+ }
+
+ if (stread && stread->stamp != st->read_stamp) {
+ if (stread != stdraw) {
+ st->dirty.st |= ST_NEW_FRAMEBUFFER;
+ _mesa_resize_framebuffer(st->ctx, &stread->Base,
+ stread->Base.Width,
+ stread->Base.Height);
+ }
+ st->read_stamp = stread->stamp;
+ }
+}
+
+/**
* Validate a framebuffer to make sure up-to-date pipe_textures are used.
+ * The context we need to pass in is s dummy context needed only to be
+ * able to get a pipe context to create pipe surfaces, and to have a
+ * context to call _mesa_resize_framebuffer():
+ * (That should probably be rethought, since those surfaces become
+ * drawable state, not context state, and can be freed by another pipe
+ * context).
*/
static void
-st_framebuffer_validate(struct st_framebuffer *stfb, struct st_context *st)
+st_framebuffer_validate(struct st_framebuffer *stfb,
+ struct st_context *st)
{
- struct pipe_context *pipe = st->pipe;
struct pipe_resource *textures[ST_ATTACHMENT_COUNT];
uint width, height;
unsigned i;
boolean changed = FALSE;
+ int32_t new_stamp = p_atomic_read(&stfb->iface->stamp);
- if (!p_atomic_read(&stfb->revalidate))
+ if (stfb->iface_stamp == new_stamp)
return;
/* validate the fb */
- if (!stfb->iface->validate(stfb->iface, stfb->statts, stfb->num_statts, textures))
- return;
+ do {
+ if (!stfb->iface->validate(stfb->iface, stfb->statts,
+ stfb->num_statts, textures))
+ return;
+
+ stfb->iface_stamp = new_stamp;
+ new_stamp = p_atomic_read(&stfb->iface->stamp);
+ } while(stfb->iface_stamp != new_stamp);
width = stfb->Base.Width;
height = stfb->Base.Height;
@@ -184,7 +225,7 @@ st_framebuffer_validate(struct st_framebuffer *stfb, struct st_context *st)
memset(&surf_tmpl, 0, sizeof(surf_tmpl));
u_surface_default_template(&surf_tmpl, textures[i],
PIPE_BIND_RENDER_TARGET);
- ps = pipe->create_surface(pipe, textures[i], &surf_tmpl);
+ ps = st->pipe->create_surface(st->pipe, textures[i], &surf_tmpl);
if (ps) {
pipe_surface_reference(&strb->surface, ps);
pipe_resource_reference(&strb->texture, ps->texture);
@@ -204,14 +245,9 @@ st_framebuffer_validate(struct st_framebuffer *stfb, struct st_context *st)
}
if (changed) {
- st->dirty.st |= ST_NEW_FRAMEBUFFER;
+ ++stfb->stamp;
_mesa_resize_framebuffer(st->ctx, &stfb->Base, width, height);
-
- assert(stfb->Base.Width == width);
- assert(stfb->Base.Height == height);
}
-
- p_atomic_set(&stfb->revalidate, FALSE);
}
/**
@@ -236,8 +272,7 @@ st_framebuffer_update_attachments(struct st_framebuffer *stfb)
st_visual_have_buffers(stfb->iface->visual, 1 << statt))
stfb->statts[stfb->num_statts++] = statt;
}
-
- p_atomic_set(&stfb->revalidate, TRUE);
+ stfb->stamp++;
}
/**
@@ -443,6 +478,7 @@ st_framebuffer_create(struct st_framebuffer_iface *stfbi)
&stfb->Base._ColorReadBufferIndex);
stfb->iface = stfbi;
+ stfb->iface_stamp = p_atomic_read(&stfbi->stamp) - 1;
/* add the color buffer */
idx = stfb->Base._ColorDrawBufferIndexes[0];
@@ -454,6 +490,7 @@ st_framebuffer_create(struct st_framebuffer_iface *stfbi)
st_framebuffer_add_renderbuffer(stfb, BUFFER_DEPTH);
st_framebuffer_add_renderbuffer(stfb, BUFFER_ACCUM);
+ stfb->stamp = 0;
st_framebuffer_update_attachments(stfb);
stfb->Base.Initialized = GL_TRUE;
@@ -473,31 +510,6 @@ st_framebuffer_reference(struct st_framebuffer **ptr,
}
static void
-st_context_notify_invalid_framebuffer(struct st_context_iface *stctxi,
- struct st_framebuffer_iface *stfbi)
-{
- struct st_context *st = (struct st_context *) stctxi;
- struct st_framebuffer *stfb;
-
- /* either draw or read winsys fb */
- stfb = st_ws_framebuffer(st->ctx->WinSysDrawBuffer);
- if (!stfb || stfb->iface != stfbi)
- stfb = st_ws_framebuffer(st->ctx->WinSysReadBuffer);
-
- if (stfb && stfb->iface == stfbi) {
- p_atomic_set(&stfb->revalidate, TRUE);
- }
- else {
- /* This function is probably getting called when we've detected a
- * change in a window's size but the currently bound context is
- * not bound to that window.
- * If the st_framebuffer_iface structure had a pointer to the
- * corresponding st_framebuffer we'd be able to handle this.
- */
- }
-}
-
-static void
st_context_flush(struct st_context_iface *stctxi, unsigned flags,
struct pipe_fence_handle **fence)
{
@@ -696,8 +708,6 @@ st_api_create_context(struct st_api *stapi, struct st_manager *smapi,
smapi->get_param(smapi, ST_MANAGER_BROKEN_INVALIDATE);
st->iface.destroy = st_context_destroy;
- st->iface.notify_invalid_framebuffer =
- st_context_notify_invalid_framebuffer;
st->iface.flush = st_context_flush;
st->iface.teximage = st_context_teximage;
st->iface.copy = st_context_copy;
@@ -707,38 +717,58 @@ st_api_create_context(struct st_api *stapi, struct st_manager *smapi,
return &st->iface;
}
+static struct st_context_iface *
+st_api_get_current(struct st_api *stapi)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct st_context *st = (ctx) ? ctx->st : NULL;
+
+ return (st) ? &st->iface : NULL;
+}
+
+static struct st_framebuffer *
+st_framebuffer_reuse_or_create(struct gl_framebuffer *fb,
+ struct st_framebuffer_iface *stfbi)
+{
+ struct st_framebuffer *cur = st_ws_framebuffer(fb), *stfb = NULL;
+
+ if (cur && cur->iface == stfbi) {
+ /* reuse the current stfb */
+ st_framebuffer_reference(&stfb, cur);
+ }
+ else {
+ /* create a new one */
+ stfb = st_framebuffer_create(stfbi);
+ }
+
+ return stfb;
+}
+
static boolean
st_api_make_current(struct st_api *stapi, struct st_context_iface *stctxi,
struct st_framebuffer_iface *stdrawi,
struct st_framebuffer_iface *streadi)
{
struct st_context *st = (struct st_context *) stctxi;
- struct st_framebuffer *stdraw, *stread, *stfb;
+ struct st_framebuffer *stdraw, *stread;
boolean ret;
_glapi_check_multithread();
if (st) {
- /* reuse/create the draw fb */
- stfb = st_ws_framebuffer(st->ctx->WinSysDrawBuffer);
- if (stfb && stfb->iface == stdrawi) {
- stdraw = NULL;
- st_framebuffer_reference(&stdraw, stfb);
+ /* reuse or create the draw fb */
+ stdraw = st_framebuffer_reuse_or_create(st->ctx->WinSysDrawBuffer,
+ stdrawi);
+ if (streadi != stdrawi) {
+ /* do the same for the read fb */
+ stread = st_framebuffer_reuse_or_create(st->ctx->WinSysReadBuffer,
+ streadi);
}
else {
- stdraw = st_framebuffer_create(stdrawi);
- }
-
- /* reuse/create the read fb */
- stfb = st_ws_framebuffer(st->ctx->WinSysReadBuffer);
- if (!stfb || stfb->iface != streadi)
- stfb = stdraw;
- if (stfb && stfb->iface == streadi) {
stread = NULL;
- st_framebuffer_reference(&stread, stfb);
- }
- else {
- stread = st_framebuffer_create(streadi);
+ /* reuse the draw fb for the read fb */
+ if (stdraw)
+ st_framebuffer_reference(&stread, stdraw);
}
if (stdraw && stread) {
@@ -757,6 +787,10 @@ st_api_make_current(struct st_api *stapi, struct st_context_iface *stctxi,
}
ret = _mesa_make_current(st->ctx, &stdraw->Base, &stread->Base);
+
+ st->draw_stamp = stdraw->stamp - 1;
+ st->read_stamp = stread->stamp - 1;
+ st_context_validate(st, stdraw, stread);
}
else {
struct gl_framebuffer *incomplete = _mesa_get_incomplete_framebuffer();
@@ -773,15 +807,6 @@ st_api_make_current(struct st_api *stapi, struct st_context_iface *stctxi,
return ret;
}
-static struct st_context_iface *
-st_api_get_current(struct st_api *stapi)
-{
- GET_CURRENT_CONTEXT(ctx);
- struct st_context *st = (ctx) ? ctx->st : NULL;
-
- return (st) ? &st->iface : NULL;
-}
-
static st_proc_t
st_api_get_proc_address(struct st_api *stapi, const char *procname)
{
@@ -857,6 +882,8 @@ st_manager_validate_framebuffers(struct st_context *st)
st_framebuffer_validate(stdraw, st);
if (stread && stread != stdraw)
st_framebuffer_validate(stread, st);
+
+ st_context_validate(st, stdraw, stread);
}
/**