summaryrefslogtreecommitdiffstats
path: root/src/gallium
diff options
context:
space:
mode:
authorBen Skeggs <[email protected]>2008-03-21 00:11:25 +1100
committerBen Skeggs <[email protected]>2008-03-21 00:11:25 +1100
commitc7e9cb10937391c25a884fe62db91ea9b910d672 (patch)
tree42a854fef74df0d07421ebe466857260fe096e1a /src/gallium
parent62767cf2dd1006621ecd6023b15d65b5cff41dfa (diff)
parent122ed506f4b808503b230bade421018614dbe696 (diff)
Merge remote branch 'upstream/gallium-0.1' into nouveau-gallium-0.1
Diffstat (limited to 'src/gallium')
-rw-r--r--src/gallium/auxiliary/cso_cache/cso_context.c208
-rw-r--r--src/gallium/auxiliary/cso_cache/cso_context.h53
-rw-r--r--src/gallium/auxiliary/draw/draw_aaline.c1
-rw-r--r--src/gallium/auxiliary/draw/draw_pstipple.c2
-rw-r--r--src/gallium/auxiliary/util/p_debug.c59
-rw-r--r--src/gallium/auxiliary/util/u_blit.c135
-rw-r--r--src/gallium/auxiliary/util/u_blit.h5
-rw-r--r--src/gallium/auxiliary/util/u_gen_mipmap.c119
-rw-r--r--src/gallium/auxiliary/util/u_gen_mipmap.h6
-rw-r--r--src/gallium/auxiliary/util/u_handle_table.c2
-rw-r--r--src/gallium/drivers/cell/ppu/cell_texture.c3
-rw-r--r--src/gallium/drivers/i915simple/i915_texture.c3
-rw-r--r--src/gallium/drivers/i965simple/brw_tex_layout.c3
-rw-r--r--src/gallium/drivers/softpipe/sp_context.h2
-rw-r--r--src/gallium/drivers/softpipe/sp_prim_setup.c2
-rw-r--r--src/gallium/drivers/softpipe/sp_quad_stipple.c2
-rw-r--r--src/gallium/drivers/softpipe/sp_state_derived.c13
-rw-r--r--src/gallium/drivers/softpipe/sp_state_surface.c12
-rw-r--r--src/gallium/drivers/softpipe/sp_texture.c3
-rw-r--r--src/gallium/drivers/softpipe/sp_tile_cache.c1
-rw-r--r--src/gallium/include/pipe/p_context.h6
-rw-r--r--src/gallium/include/pipe/p_debug.h49
22 files changed, 510 insertions, 179 deletions
diff --git a/src/gallium/auxiliary/cso_cache/cso_context.c b/src/gallium/auxiliary/cso_cache/cso_context.c
index 294ac82281e..01fe2164478 100644
--- a/src/gallium/auxiliary/cso_cache/cso_context.c
+++ b/src/gallium/auxiliary/cso_cache/cso_context.c
@@ -52,11 +52,27 @@ struct cso_context {
void *samplers[PIPE_MAX_SAMPLERS];
unsigned nr_samplers;
- void *blend;
- void *depth_stencil;
- void *rasterizer;
- void *fragment_shader;
- void *vertex_shader;
+ void *samplers_saved[PIPE_MAX_SAMPLERS];
+ unsigned nr_samplers_saved;
+
+ struct pipe_texture *textures[PIPE_MAX_SAMPLERS];
+ uint nr_textures;
+
+ struct pipe_texture *textures_saved[PIPE_MAX_SAMPLERS];
+ uint nr_textures_saved;
+
+ /** Current and saved state.
+ * The saved state is used as a 1-deep stack.
+ */
+ void *blend, *blend_saved;
+ void *depth_stencil, *depth_stencil_saved;
+ void *rasterizer, *rasterizer_saved;
+ void *fragment_shader, *fragment_shader_saved;
+ void *vertex_shader, *vertex_shader_saved;
+
+ struct pipe_framebuffer_state fb, fb_saved;
+ struct pipe_viewport_state vp, vp_saved;
+ struct pipe_blend_color blend_color;
};
@@ -149,12 +165,23 @@ void cso_set_blend(struct cso_context *ctx,
}
}
-void cso_unset_blend(struct cso_context *ctx)
+void cso_save_blend(struct cso_context *ctx)
+{
+ assert(!ctx->blend_saved);
+ ctx->blend_saved = ctx->blend;
+}
+
+void cso_restore_blend(struct cso_context *ctx)
{
- ctx->blend = NULL;
+ if (ctx->blend != ctx->blend_saved) {
+ ctx->blend = ctx->blend_saved;
+ ctx->pipe->bind_blend_state(ctx->pipe, ctx->blend_saved);
+ }
+ ctx->blend_saved = NULL;
}
+
void cso_single_sampler(struct cso_context *ctx,
unsigned idx,
const struct pipe_sampler_state *templ)
@@ -190,9 +217,11 @@ void cso_single_sampler_done( struct cso_context *ctx )
{
unsigned i;
- for (i = 0; i < 8; i++)
- if (ctx->samplers[i] == NULL)
+ /* find highest non-null sampler */
+ for (i = PIPE_MAX_SAMPLERS; i > 0; i--) {
+ if (ctx->samplers[i - 1] != NULL)
break;
+ }
ctx->nr_samplers = i;
@@ -226,15 +255,50 @@ void cso_set_samplers( struct cso_context *ctx,
cso_single_sampler_done( ctx );
}
-void cso_unset_samplers( struct cso_context *ctx )
+void cso_save_samplers(struct cso_context *ctx)
+{
+ ctx->nr_samplers_saved = ctx->nr_samplers;
+ memcpy(ctx->samplers_saved, ctx->samplers, sizeof(ctx->samplers));
+}
+
+void cso_restore_samplers(struct cso_context *ctx)
+{
+ cso_set_samplers(ctx, ctx->nr_samplers_saved,
+ (const struct pipe_sampler_state **) ctx->samplers_saved);
+}
+
+
+void cso_set_sampler_textures( struct cso_context *ctx,
+ uint count,
+ struct pipe_texture **textures )
{
uint i;
- for (i = 0; i < ctx->nr_samplers; i++)
- ctx->samplers[i] = NULL;
+
+ ctx->nr_textures = count;
+
+ for (i = 0; i < count; i++)
+ ctx->textures[i] = textures[i];
+ for ( ; i < PIPE_MAX_SAMPLERS; i++)
+ ctx->textures[i] = NULL;
+
+ ctx->pipe->set_sampler_textures(ctx->pipe, count, textures);
+}
+
+void cso_save_sampler_textures( struct cso_context *ctx )
+{
+ ctx->nr_textures_saved = ctx->nr_textures;
+ memcpy(ctx->textures_saved, ctx->textures, sizeof(ctx->textures));
+}
+
+void cso_restore_sampler_textures( struct cso_context *ctx )
+{
+ cso_set_sampler_textures(ctx, ctx->nr_textures_saved, ctx->textures_saved);
+ ctx->nr_textures_saved = 0;
}
+
void cso_set_depth_stencil_alpha(struct cso_context *ctx,
const struct pipe_depth_stencil_alpha_state *templ)
{
@@ -267,15 +331,25 @@ void cso_set_depth_stencil_alpha(struct cso_context *ctx,
}
}
-void cso_unset_depth_stencil_alpha(struct cso_context *ctx)
+void cso_save_depth_stencil_alpha(struct cso_context *ctx)
{
- ctx->depth_stencil = NULL;
+ assert(!ctx->depth_stencil_saved);
+ ctx->depth_stencil_saved = ctx->depth_stencil;
+}
+
+void cso_restore_depth_stencil_alpha(struct cso_context *ctx)
+{
+ if (ctx->depth_stencil != ctx->depth_stencil_saved) {
+ ctx->depth_stencil = ctx->depth_stencil_saved;
+ ctx->pipe->bind_depth_stencil_alpha_state(ctx->pipe, ctx->depth_stencil_saved);
+ }
+ ctx->depth_stencil_saved = NULL;
}
void cso_set_rasterizer(struct cso_context *ctx,
- const struct pipe_rasterizer_state *templ)
+ const struct pipe_rasterizer_state *templ)
{
unsigned hash_key = cso_construct_key((void*)templ,
sizeof(struct pipe_rasterizer_state));
@@ -305,11 +379,20 @@ void cso_set_rasterizer(struct cso_context *ctx,
}
}
-void cso_unset_rasterizer(struct cso_context *ctx)
+void cso_save_rasterizer(struct cso_context *ctx)
{
- ctx->rasterizer = NULL;
+ assert(!ctx->rasterizer_saved);
+ ctx->rasterizer_saved = ctx->rasterizer;
}
+void cso_restore_rasterizer(struct cso_context *ctx)
+{
+ if (ctx->rasterizer != ctx->rasterizer_saved) {
+ ctx->rasterizer = ctx->rasterizer_saved;
+ ctx->pipe->bind_rasterizer_state(ctx->pipe, ctx->rasterizer_saved);
+ }
+ ctx->rasterizer_saved = NULL;
+}
void cso_set_fragment_shader(struct cso_context *ctx,
@@ -343,12 +426,24 @@ void cso_set_fragment_shader(struct cso_context *ctx,
}
}
-void cso_unset_fragment_shader(struct cso_context *ctx)
+void cso_save_fragment_shader(struct cso_context *ctx)
{
- ctx->fragment_shader = NULL;
+ assert(!ctx->fragment_shader_saved);
+ ctx->fragment_shader_saved = ctx->fragment_shader;
+}
+
+void cso_restore_fragment_shader(struct cso_context *ctx)
+{
+ assert(ctx->fragment_shader_saved);
+ if (ctx->fragment_shader_saved != ctx->fragment_shader) {
+ ctx->pipe->bind_fs_state(ctx->pipe, ctx->fragment_shader_saved);
+ ctx->fragment_shader = ctx->fragment_shader_saved;
+ }
+ ctx->fragment_shader_saved = NULL;
}
+
void cso_set_vertex_shader(struct cso_context *ctx,
const struct pipe_shader_state *templ)
{
@@ -380,7 +475,78 @@ void cso_set_vertex_shader(struct cso_context *ctx,
}
}
-void cso_unset_vertex_shader(struct cso_context *ctx)
+void cso_save_vertex_shader(struct cso_context *ctx)
+{
+ assert(!ctx->vertex_shader_saved);
+ ctx->vertex_shader_saved = ctx->vertex_shader;
+}
+
+void cso_restore_vertex_shader(struct cso_context *ctx)
+{
+ assert(ctx->vertex_shader_saved);
+ if (ctx->vertex_shader_saved != ctx->vertex_shader) {
+ ctx->pipe->bind_fs_state(ctx->pipe, ctx->vertex_shader_saved);
+ ctx->vertex_shader = ctx->vertex_shader_saved;
+ }
+ ctx->vertex_shader_saved = NULL;
+}
+
+
+
+void cso_set_framebuffer(struct cso_context *ctx,
+ const struct pipe_framebuffer_state *fb)
+{
+ if (memcmp(&ctx->fb, fb, sizeof(*fb))) {
+ ctx->fb = *fb;
+ ctx->pipe->set_framebuffer_state(ctx->pipe, fb);
+ }
+}
+
+void cso_save_framebuffer(struct cso_context *ctx)
+{
+ ctx->fb_saved = ctx->fb;
+}
+
+void cso_restore_framebuffer(struct cso_context *ctx)
+{
+ if (memcmp(&ctx->fb, &ctx->fb_saved, sizeof(ctx->fb))) {
+ ctx->fb = ctx->fb_saved;
+ ctx->pipe->set_framebuffer_state(ctx->pipe, &ctx->fb);
+ }
+}
+
+
+void cso_set_viewport(struct cso_context *ctx,
+ const struct pipe_viewport_state *vp)
+{
+ if (memcmp(&ctx->vp, vp, sizeof(*vp))) {
+ ctx->vp = *vp;
+ ctx->pipe->set_viewport_state(ctx->pipe, vp);
+ }
+}
+
+void cso_save_viewport(struct cso_context *ctx)
{
- ctx->vertex_shader = NULL;
+ ctx->vp_saved = ctx->vp;
+}
+
+
+void cso_restore_viewport(struct cso_context *ctx)
+{
+ if (memcmp(&ctx->vp, &ctx->vp_saved, sizeof(ctx->vp))) {
+ ctx->vp = ctx->vp_saved;
+ ctx->pipe->set_viewport_state(ctx->pipe, &ctx->vp);
+ }
+}
+
+
+
+
+void cso_set_blend_color(struct cso_context *ctx,
+ const struct pipe_blend_color *bc)
+{
+ if (memcmp(&ctx->blend_color, bc, sizeof(ctx->blend_color))) {
+ ctx->blend_color = *bc;
+ ctx->pipe->set_blend_color(ctx->pipe, bc);
+ }
}
diff --git a/src/gallium/auxiliary/cso_cache/cso_context.h b/src/gallium/auxiliary/cso_cache/cso_context.h
index 6aa619abf56..665e8d99110 100644
--- a/src/gallium/auxiliary/cso_cache/cso_context.h
+++ b/src/gallium/auxiliary/cso_cache/cso_context.h
@@ -41,27 +41,36 @@ struct cso_context;
struct cso_context *cso_create_context( struct pipe_context *pipe );
+void cso_destroy_context( struct cso_context *cso );
+
+
+
void cso_set_blend( struct cso_context *cso,
const struct pipe_blend_state *blend );
+void cso_save_blend(struct cso_context *cso);
+void cso_restore_blend(struct cso_context *cso);
+
-void cso_unset_blend(struct cso_context *cso);
void cso_set_depth_stencil_alpha( struct cso_context *cso,
const struct pipe_depth_stencil_alpha_state *dsa );
+void cso_save_depth_stencil_alpha(struct cso_context *cso);
+void cso_restore_depth_stencil_alpha(struct cso_context *cso);
+
-void cso_unset_depth_stencil_alpha( struct cso_context *cso );
void cso_set_rasterizer( struct cso_context *cso,
const struct pipe_rasterizer_state *rasterizer );
+void cso_save_rasterizer(struct cso_context *cso);
+void cso_restore_rasterizer(struct cso_context *cso);
+
-void cso_unset_rasterizer( struct cso_context *cso );
void cso_set_samplers( struct cso_context *cso,
unsigned count,
const struct pipe_sampler_state **states );
-
-void cso_unset_samplers( struct cso_context *cso );
-
+void cso_save_samplers(struct cso_context *cso);
+void cso_restore_samplers(struct cso_context *cso);
/* Alternate interface to support state trackers that like to modify
* samplers one at a time:
@@ -73,6 +82,15 @@ void cso_single_sampler( struct cso_context *cso,
void cso_single_sampler_done( struct cso_context *cso );
+
+void cso_set_sampler_textures( struct cso_context *cso,
+ uint count,
+ struct pipe_texture **textures );
+void cso_save_sampler_textures( struct cso_context *cso );
+void cso_restore_sampler_textures( struct cso_context *cso );
+
+
+
/* These aren't really sensible -- most of the time the api provides
* object semantics for shaders anyway, and the cases where it doesn't
* (eg mesa's internall-generated texenv programs), it will be up to
@@ -80,15 +98,32 @@ void cso_single_sampler_done( struct cso_context *cso );
*/
void cso_set_fragment_shader( struct cso_context *cso,
const struct pipe_shader_state *shader );
+void cso_save_fragment_shader(struct cso_context *cso);
+void cso_restore_fragment_shader(struct cso_context *cso);
+
-void cso_unset_fragment_shader( struct cso_context *cso );
void cso_set_vertex_shader( struct cso_context *cso,
const struct pipe_shader_state *shader );
+void cso_save_vertex_shader(struct cso_context *cso);
+void cso_restore_vertex_shader(struct cso_context *cso);
-void cso_unset_vertex_shader( struct cso_context *cso );
-void cso_destroy_context( struct cso_context *cso );
+
+void cso_set_framebuffer(struct cso_context *cso,
+ const struct pipe_framebuffer_state *fb);
+void cso_save_framebuffer(struct cso_context *cso);
+void cso_restore_framebuffer(struct cso_context *cso);
+
+
+void cso_set_viewport(struct cso_context *cso,
+ const struct pipe_viewport_state *vp);
+void cso_save_viewport(struct cso_context *cso);
+void cso_restore_viewport(struct cso_context *cso);
+
+
+void cso_set_blend_color(struct cso_context *cso,
+ const struct pipe_blend_color *bc);
#ifdef __cplusplus
diff --git a/src/gallium/auxiliary/draw/draw_aaline.c b/src/gallium/auxiliary/draw/draw_aaline.c
index f2b983374e6..b4fa6bd9670 100644
--- a/src/gallium/auxiliary/draw/draw_aaline.c
+++ b/src/gallium/auxiliary/draw/draw_aaline.c
@@ -410,6 +410,7 @@ aaline_create_texture(struct aaline_stage *aaline)
/* unmap */
pipe_surface_unmap(surface);
pipe_surface_reference(&surface, NULL);
+ pipe->texture_update(pipe, aaline->texture, 0, (1 << level));
}
}
diff --git a/src/gallium/auxiliary/draw/draw_pstipple.c b/src/gallium/auxiliary/draw/draw_pstipple.c
index 09d542002f0..9d154a68381 100644
--- a/src/gallium/auxiliary/draw/draw_pstipple.c
+++ b/src/gallium/auxiliary/draw/draw_pstipple.c
@@ -374,7 +374,7 @@ pstip_update_texture(struct pstip_stage *pstip)
/* unmap */
pipe_surface_unmap(surface);
pipe_surface_reference(&surface, NULL);
- pipe->texture_update(pipe, pstip->texture);
+ pipe->texture_update(pipe, pstip->texture, 0, 0x1);
}
diff --git a/src/gallium/auxiliary/util/p_debug.c b/src/gallium/auxiliary/util/p_debug.c
index bb84e8096d2..bd3a0221eaa 100644
--- a/src/gallium/auxiliary/util/p_debug.c
+++ b/src/gallium/auxiliary/util/p_debug.c
@@ -52,6 +52,9 @@ rpl_EngDebugPrint(const char *format, ...)
}
int rpl_vsnprintf(char *, size_t, const char *, va_list);
+int rpl_snprintf(char *str, size_t size, const char *format, ...);
+#define vsnprintf rpl_vsnprintf
+#define snprintf rpl_snprintf
#endif
@@ -181,3 +184,59 @@ void debug_mask_vprintf(uint32_t uuid, uint32_t what, const char *format, va_lis
if(mask & what)
debug_vprintf(format, ap);
}
+
+
+const char *
+debug_dump_enum(const struct debug_named_value *names,
+ unsigned long value)
+{
+ static char rest[256];
+
+ while(names->name) {
+ if(names->value == value)
+ return names->name;
+ ++names;
+ }
+
+ snprintf(rest, sizeof(rest), "0x%08x", value);
+ return rest;
+}
+
+
+const char *
+debug_dump_flags(const struct debug_named_value *names,
+ unsigned long value)
+{
+ static char output[4096];
+ static char rest[256];
+ int first = 1;
+
+ output[0] = '\0';
+
+ while(names->name) {
+ if((names->value & value) == names->value) {
+ if (!first)
+ strncat(output, "|", sizeof(output));
+ else
+ first = 0;
+ strncat(output, names->name, sizeof(output));
+ value &= ~names->value;
+ }
+ ++names;
+ }
+
+ if (value) {
+ if (!first)
+ strncat(output, "|", sizeof(output));
+ else
+ first = 0;
+
+ snprintf(rest, sizeof(rest), "0x%08x", value);
+ strncat(output, rest, sizeof(output));
+ }
+
+ if(first)
+ return "0";
+
+ return output;
+}
diff --git a/src/gallium/auxiliary/util/u_blit.c b/src/gallium/auxiliary/util/u_blit.c
index 4b4ab8185f2..d05dae3af8f 100644
--- a/src/gallium/auxiliary/util/u_blit.c
+++ b/src/gallium/auxiliary/util/u_blit.c
@@ -45,15 +45,18 @@
#include "util/u_blit.h"
#include "util/u_simple_shaders.h"
+#include "cso_cache/cso_context.h"
+
struct blit_state
{
struct pipe_context *pipe;
+ struct cso_context *cso;
- void *blend;
- void *depthstencil;
- void *rasterizer;
- void *samplers[2]; /* one for linear, one for nearest sampling */
+ struct pipe_blend_state blend;
+ struct pipe_depth_stencil_alpha_state depthstencil;
+ struct pipe_rasterizer_state rasterizer;
+ struct pipe_sampler_state sampler;
/*struct pipe_viewport_state viewport;*/
struct pipe_sampler_state *vs;
@@ -66,56 +69,44 @@ struct blit_state
* Intended to be created once and re-used for many blit() calls.
*/
struct blit_state *
-util_create_blit(struct pipe_context *pipe)
+util_create_blit(struct pipe_context *pipe, struct cso_context *cso)
{
- struct pipe_blend_state blend;
- struct pipe_depth_stencil_alpha_state depthstencil;
- struct pipe_rasterizer_state rasterizer;
struct blit_state *ctx;
- struct pipe_sampler_state sampler;
ctx = CALLOC_STRUCT(blit_state);
if (!ctx)
return NULL;
ctx->pipe = pipe;
+ ctx->cso = cso;
- /* we don't use blending, but need to set valid values */
- memset(&blend, 0, sizeof(blend));
- blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE;
- blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE;
- blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
- blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
- blend.colormask = PIPE_MASK_RGBA;
- ctx->blend = pipe->create_blend_state(pipe, &blend);
+ /* disabled blending/masking */
+ memset(&ctx->blend, 0, sizeof(ctx->blend));
+ ctx->blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE;
+ ctx->blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE;
+ ctx->blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
+ ctx->blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
+ ctx->blend.colormask = PIPE_MASK_RGBA;
- /* depth/stencil/alpha */
- memset(&depthstencil, 0, sizeof(depthstencil));
- ctx->depthstencil = pipe->create_depth_stencil_alpha_state(pipe, &depthstencil);
+ /* no-op depth/stencil/alpha */
+ memset(&ctx->depthstencil, 0, sizeof(ctx->depthstencil));
/* rasterizer */
- memset(&rasterizer, 0, sizeof(rasterizer));
- rasterizer.front_winding = PIPE_WINDING_CW;
- rasterizer.cull_mode = PIPE_WINDING_NONE;
- rasterizer.bypass_clipping = 1; /* bypasses viewport too */
- /*rasterizer.bypass_vs = 1;*/
- ctx->rasterizer = pipe->create_rasterizer_state(pipe, &rasterizer);
+ memset(&ctx->rasterizer, 0, sizeof(ctx->rasterizer));
+ ctx->rasterizer.front_winding = PIPE_WINDING_CW;
+ ctx->rasterizer.cull_mode = PIPE_WINDING_NONE;
+ ctx->rasterizer.bypass_clipping = 1; /* bypasses viewport too */
+ /*ctx->rasterizer.bypass_vs = 1;*/
/* samplers */
- memset(&sampler, 0, sizeof(sampler));
- sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
- sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
- sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
- sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
- sampler.min_img_filter = PIPE_TEX_MIPFILTER_NEAREST;
- sampler.mag_img_filter = PIPE_TEX_MIPFILTER_NEAREST;
- sampler.normalized_coords = 1;
- ctx->samplers[0] = pipe->create_sampler_state(pipe, &sampler);
-
- sampler.min_img_filter = PIPE_TEX_MIPFILTER_LINEAR;
- sampler.mag_img_filter = PIPE_TEX_MIPFILTER_LINEAR;
- ctx->samplers[1] = pipe->create_sampler_state(pipe, &sampler);
-
+ memset(&ctx->sampler, 0, sizeof(ctx->sampler));
+ ctx->sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ ctx->sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ ctx->sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ ctx->sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
+ ctx->sampler.min_img_filter = 0; /* set later */
+ ctx->sampler.mag_img_filter = 0; /* set later */
+ ctx->sampler.normalized_coords = 1;
#if 0
/* viewport */
@@ -153,12 +144,6 @@ util_destroy_blit(struct blit_state *ctx)
{
struct pipe_context *pipe = ctx->pipe;
- pipe->delete_blend_state(pipe, ctx->blend);
- pipe->delete_depth_stencil_alpha_state(pipe, ctx->depthstencil);
- pipe->delete_rasterizer_state(pipe, ctx->rasterizer);
- pipe->delete_sampler_state(pipe, ctx->samplers[0]);
- pipe->delete_sampler_state(pipe, ctx->samplers[1]);
-
pipe->delete_vs_state(pipe, ctx->vs);
pipe->delete_fs_state(pipe, ctx->fs);
@@ -236,17 +221,24 @@ util_blit_pixels(struct blit_state *ctx,
src, srcLeft, srcTop, /* src */
srcW, srcH); /* size */
- /* drawing dest */
- memset(&fb, 0, sizeof(fb));
- fb.num_cbufs = 1;
- fb.cbufs[0] = dst;
- pipe->set_framebuffer_state(pipe, &fb);
+ /* save state (restored below) */
+ cso_save_blend(ctx->cso);
+ cso_save_depth_stencil_alpha(ctx->cso);
+ cso_save_rasterizer(ctx->cso);
+ cso_save_samplers(ctx->cso);
+ cso_save_sampler_textures(ctx->cso);
+ cso_save_framebuffer(ctx->cso);
+
+ /* set misc state we care about */
+ cso_set_blend(ctx->cso, &ctx->blend);
+ cso_set_depth_stencil_alpha(ctx->cso, &ctx->depthstencil);
+ cso_set_rasterizer(ctx->cso, &ctx->rasterizer);
/* sampler */
- if (filter == PIPE_TEX_MIPFILTER_NEAREST)
- pipe->bind_sampler_states(pipe, 1, &ctx->samplers[0]);
- else
- pipe->bind_sampler_states(pipe, 1, &ctx->samplers[1]);
+ ctx->sampler.min_img_filter = filter;
+ ctx->sampler.mag_img_filter = filter;
+ cso_single_sampler(ctx->cso, 0, &ctx->sampler);
+ cso_single_sampler_done(ctx->cso);
/* texture */
pipe->set_sampler_textures(pipe, 1, &tex);
@@ -255,22 +247,29 @@ util_blit_pixels(struct blit_state *ctx,
pipe->bind_fs_state(pipe, ctx->fs);
pipe->bind_vs_state(pipe, ctx->vs);
- /* misc state */
- pipe->bind_blend_state(pipe, ctx->blend);
- pipe->bind_depth_stencil_alpha_state(pipe, ctx->depthstencil);
- pipe->bind_rasterizer_state(pipe, ctx->rasterizer);
+ /* drawing dest */
+ memset(&fb, 0, sizeof(fb));
+ fb.num_cbufs = 1;
+ fb.cbufs[0] = dst;
+ cso_set_framebuffer(ctx->cso, &fb);
/* draw quad */
- util_draw_texquad(pipe, dstX0, dstY0, dstX1, dstY1, z);
-
- /* unbind */
- pipe->set_sampler_textures(pipe, 0, NULL);
- pipe->bind_sampler_states(pipe, 0, NULL);
-
- /* free stuff */
+ util_draw_texquad(pipe,
+ (float)dstX0,
+ (float)dstY0,
+ (float)dstX1,
+ (float)dstY1, z);
+
+ /* restore state we changed */
+ cso_restore_blend(ctx->cso);
+ cso_restore_depth_stencil_alpha(ctx->cso);
+ cso_restore_rasterizer(ctx->cso);
+ cso_restore_samplers(ctx->cso);
+ cso_restore_sampler_textures(ctx->cso);
+ cso_restore_framebuffer(ctx->cso);
+
+ /* free the texture */
pipe_surface_reference(&texSurf, NULL);
screen->texture_release(screen, &tex);
-
- /* Note: caller must restore pipe/gallium state at this time */
}
diff --git a/src/gallium/auxiliary/util/u_blit.h b/src/gallium/auxiliary/util/u_blit.h
index a349be99ad8..61f1d9bb32a 100644
--- a/src/gallium/auxiliary/util/u_blit.h
+++ b/src/gallium/auxiliary/util/u_blit.h
@@ -30,15 +30,16 @@
#define U_BLIT_H
+
struct pipe_context;
struct pipe_surface;
+struct cso_context;
struct blit_state;
-
extern struct blit_state *
-util_create_blit(struct pipe_context *pipe);
+util_create_blit(struct pipe_context *pipe, struct cso_context *cso);
extern void
diff --git a/src/gallium/auxiliary/util/u_gen_mipmap.c b/src/gallium/auxiliary/util/u_gen_mipmap.c
index e18f8ab72ac..028b180a777 100644
--- a/src/gallium/auxiliary/util/u_gen_mipmap.c
+++ b/src/gallium/auxiliary/util/u_gen_mipmap.c
@@ -49,14 +49,18 @@
#include "tgsi/util/tgsi_dump.h"
#include "tgsi/util/tgsi_parse.h"
+#include "cso_cache/cso_context.h"
+
struct gen_mipmap_state
{
struct pipe_context *pipe;
+ struct cso_context *cso;
- void *blend;
- void *depthstencil;
- void *rasterizer;
+ struct pipe_blend_state blend;
+ struct pipe_depth_stencil_alpha_state depthstencil;
+ struct pipe_rasterizer_state rasterizer;
+ struct pipe_sampler_state sampler;
/*struct pipe_viewport_state viewport;*/
struct pipe_sampler_state *vs;
struct pipe_sampler_state *fs;
@@ -675,11 +679,9 @@ fallback_gen_mipmap(struct gen_mipmap_state *ctx,
* generate a mipmap.
*/
struct gen_mipmap_state *
-util_create_gen_mipmap(struct pipe_context *pipe)
+util_create_gen_mipmap(struct pipe_context *pipe,
+ struct cso_context *cso)
{
- struct pipe_blend_state blend;
- struct pipe_depth_stencil_alpha_state depthstencil;
- struct pipe_rasterizer_state rasterizer;
struct gen_mipmap_state *ctx;
ctx = CALLOC_STRUCT(gen_mipmap_state);
@@ -687,27 +689,36 @@ util_create_gen_mipmap(struct pipe_context *pipe)
return NULL;
ctx->pipe = pipe;
+ ctx->cso = cso;
- /* we don't use blending, but need to set valid values */
- memset(&blend, 0, sizeof(blend));
- blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE;
- blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE;
- blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
- blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
- blend.colormask = PIPE_MASK_RGBA;
- ctx->blend = pipe->create_blend_state(pipe, &blend);
+ /* disabled blending/masking */
+ memset(&ctx->blend, 0, sizeof(ctx->blend));
+ ctx->blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE;
+ ctx->blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE;
+ ctx->blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
+ ctx->blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
+ ctx->blend.colormask = PIPE_MASK_RGBA;
- /* depth/stencil/alpha */
- memset(&depthstencil, 0, sizeof(depthstencil));
- ctx->depthstencil = pipe->create_depth_stencil_alpha_state(pipe, &depthstencil);
+ /* no-op depth/stencil/alpha */
+ memset(&ctx->depthstencil, 0, sizeof(ctx->depthstencil));
/* rasterizer */
- memset(&rasterizer, 0, sizeof(rasterizer));
- rasterizer.front_winding = PIPE_WINDING_CW;
- rasterizer.cull_mode = PIPE_WINDING_NONE;
- rasterizer.bypass_clipping = 1; /* bypasses viewport too */
- //rasterizer.bypass_vs = 1;
- ctx->rasterizer = pipe->create_rasterizer_state(pipe, &rasterizer);
+ memset(&ctx->rasterizer, 0, sizeof(ctx->rasterizer));
+ ctx->rasterizer.front_winding = PIPE_WINDING_CW;
+ ctx->rasterizer.cull_mode = PIPE_WINDING_NONE;
+ ctx->rasterizer.bypass_clipping = 1; /* bypasses viewport too */
+ /*ctx->rasterizer.bypass_vs = 1;*/
+
+ /* sampler state */
+ memset(&ctx->sampler, 0, sizeof(ctx->sampler));
+ ctx->sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ ctx->sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ ctx->sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ ctx->sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NEAREST;
+ ctx->sampler.min_img_filter = PIPE_TEX_FILTER_LINEAR;
+ ctx->sampler.mag_img_filter = PIPE_TEX_FILTER_LINEAR;
+ ctx->sampler.normalized_coords = 1;
+
#if 0
/* viewport */
@@ -745,9 +756,6 @@ util_destroy_gen_mipmap(struct gen_mipmap_state *ctx)
{
struct pipe_context *pipe = ctx->pipe;
- pipe->delete_blend_state(pipe, ctx->blend);
- pipe->delete_depth_stencil_alpha_state(pipe, ctx->depthstencil);
- pipe->delete_rasterizer_state(pipe, ctx->rasterizer);
pipe->delete_vs_state(pipe, ctx->vs);
pipe->delete_fs_state(pipe, ctx->fs);
@@ -792,8 +800,6 @@ util_gen_mipmap(struct gen_mipmap_state *ctx,
struct pipe_context *pipe = ctx->pipe;
struct pipe_screen *screen = pipe->screen;
struct pipe_framebuffer_state fb;
- struct pipe_sampler_state sampler;
- void *sampler_cso;
uint dstLevel;
uint zslice = 0;
@@ -803,30 +809,29 @@ util_gen_mipmap(struct gen_mipmap_state *ctx,
return;
}
- /* init framebuffer state */
- memset(&fb, 0, sizeof(fb));
- fb.num_cbufs = 1;
-
- /* sampler state */
- memset(&sampler, 0, sizeof(sampler));
- sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
- sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
- sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
- sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NEAREST;
- sampler.min_img_filter = PIPE_TEX_FILTER_LINEAR;
- sampler.mag_img_filter = PIPE_TEX_FILTER_LINEAR;
- sampler.normalized_coords = 1;
+ /* save state (restored below) */
+ cso_save_blend(ctx->cso);
+ cso_save_depth_stencil_alpha(ctx->cso);
+ cso_save_rasterizer(ctx->cso);
+ cso_save_samplers(ctx->cso);
+ cso_save_sampler_textures(ctx->cso);
+ cso_save_framebuffer(ctx->cso);
/* bind our state */
- pipe->bind_blend_state(pipe, ctx->blend);
- pipe->bind_depth_stencil_alpha_state(pipe, ctx->depthstencil);
- pipe->bind_rasterizer_state(pipe, ctx->rasterizer);
+ cso_set_blend(ctx->cso, &ctx->blend);
+ cso_set_depth_stencil_alpha(ctx->cso, &ctx->depthstencil);
+ cso_set_rasterizer(ctx->cso, &ctx->rasterizer);
+
pipe->bind_vs_state(pipe, ctx->vs);
pipe->bind_fs_state(pipe, ctx->fs);
#if 0
pipe->set_viewport_state(pipe, &ctx->viewport);
#endif
+ /* init framebuffer state */
+ memset(&fb, 0, sizeof(fb));
+ fb.num_cbufs = 1;
+
/*
* XXX for small mipmap levels, it may be faster to use the software
* fallback path...
@@ -838,7 +843,7 @@ util_gen_mipmap(struct gen_mipmap_state *ctx,
* Setup framebuffer / dest surface
*/
fb.cbufs[0] = screen->get_tex_surface(screen, pt, face, dstLevel, zslice);
- pipe->set_framebuffer_state(pipe, &fb);
+ cso_set_framebuffer(ctx->cso, &fb);
/*
* Setup sampler state
@@ -847,11 +852,10 @@ util_gen_mipmap(struct gen_mipmap_state *ctx,
* has trouble with min clamping so we also set the lod_bias to
* try to work around that.
*/
- sampler.min_lod = sampler.max_lod = (float) srcLevel;
- sampler.lod_bias = (float) srcLevel;
- sampler_cso = pipe->create_sampler_state(pipe, &sampler);
- pipe->bind_sampler_states(pipe, 1, &sampler_cso);
-
+ ctx->sampler.min_lod = ctx->sampler.max_lod = (float) srcLevel;
+ ctx->sampler.lod_bias = (float) srcLevel;
+ cso_single_sampler(ctx->cso, 0, &ctx->sampler);
+ cso_single_sampler_done(ctx->cso);
#if 0
simple_viewport(pipe, pt->width[dstLevel], pt->height[dstLevel]);
#endif
@@ -868,10 +872,15 @@ util_gen_mipmap(struct gen_mipmap_state *ctx,
pipe->flush(pipe, PIPE_FLUSH_WAIT);
- /*pipe->texture_update(pipe, pt); not really needed */
-
- pipe->delete_sampler_state(pipe, sampler_cso);
+ /* need to signal that the texture has changed _after_ rendering to it */
+ pipe->texture_update(pipe, pt, face, (1 << dstLevel));
}
- /* Note: caller must restore pipe/gallium state at this time */
+ /* restore state we changed */
+ cso_restore_blend(ctx->cso);
+ cso_restore_depth_stencil_alpha(ctx->cso);
+ cso_restore_rasterizer(ctx->cso);
+ cso_restore_samplers(ctx->cso);
+ cso_restore_sampler_textures(ctx->cso);
+ cso_restore_framebuffer(ctx->cso);
}
diff --git a/src/gallium/auxiliary/util/u_gen_mipmap.h b/src/gallium/auxiliary/util/u_gen_mipmap.h
index 80496140a24..eeabf3bf075 100644
--- a/src/gallium/auxiliary/util/u_gen_mipmap.h
+++ b/src/gallium/auxiliary/util/u_gen_mipmap.h
@@ -31,11 +31,15 @@
#include "pipe/p_state.h"
+struct pipe_context;
+struct pipe_texture;
+struct cso_context;
+
struct gen_mipmap_state;
extern struct gen_mipmap_state *
-util_create_gen_mipmap(struct pipe_context *pipe);
+util_create_gen_mipmap(struct pipe_context *pipe, struct cso_context *cso);
extern void
diff --git a/src/gallium/auxiliary/util/u_handle_table.c b/src/gallium/auxiliary/util/u_handle_table.c
index 0bfb9e1b4ae..8b0f7fca4b1 100644
--- a/src/gallium/auxiliary/util/u_handle_table.c
+++ b/src/gallium/auxiliary/util/u_handle_table.c
@@ -248,7 +248,7 @@ handle_table_get_next_handle(struct handle_table *ht,
unsigned index;
for(index = handle; index < ht->size; ++index) {
- if(!ht->objects[index])
+ if(ht->objects[index])
return index + 1;
}
diff --git a/src/gallium/drivers/cell/ppu/cell_texture.c b/src/gallium/drivers/cell/ppu/cell_texture.c
index e235421107e..9c694e136d8 100644
--- a/src/gallium/drivers/cell/ppu/cell_texture.c
+++ b/src/gallium/drivers/cell/ppu/cell_texture.c
@@ -134,7 +134,8 @@ cell_texture_release_screen(struct pipe_screen *screen,
static void
-cell_texture_update(struct pipe_context *pipe, struct pipe_texture *texture)
+cell_texture_update(struct pipe_context *pipe, struct pipe_texture *texture,
+ uint face, uint levelsMask)
{
/* XXX TO DO: re-tile the texture data ... */
diff --git a/src/gallium/drivers/i915simple/i915_texture.c b/src/gallium/drivers/i915simple/i915_texture.c
index ef5adff550e..c39e747705b 100644
--- a/src/gallium/drivers/i915simple/i915_texture.c
+++ b/src/gallium/drivers/i915simple/i915_texture.c
@@ -542,7 +542,8 @@ i915_texture_release_screen(struct pipe_screen *screen,
static void
-i915_texture_update(struct pipe_context *pipe, struct pipe_texture *texture)
+i915_texture_update(struct pipe_context *pipe, struct pipe_texture *texture,
+ uint face, uint levelsMask)
{
/* no-op? */
}
diff --git a/src/gallium/drivers/i965simple/brw_tex_layout.c b/src/gallium/drivers/i965simple/brw_tex_layout.c
index b24ac87c378..b580f98204c 100644
--- a/src/gallium/drivers/i965simple/brw_tex_layout.c
+++ b/src/gallium/drivers/i965simple/brw_tex_layout.c
@@ -358,7 +358,8 @@ brw_texture_release_screen(struct pipe_screen *screen,
static void
-brw_texture_update(struct pipe_context *pipe, struct pipe_texture *texture)
+brw_texture_update(struct pipe_context *pipe, struct pipe_texture *texture,
+ uint face, uint levelsMask)
{
/* no-op? */
}
diff --git a/src/gallium/drivers/softpipe/sp_context.h b/src/gallium/drivers/softpipe/sp_context.h
index 19e6cfaf02e..31d7062dcc0 100644
--- a/src/gallium/drivers/softpipe/sp_context.h
+++ b/src/gallium/drivers/softpipe/sp_context.h
@@ -84,6 +84,8 @@ struct softpipe_context {
unsigned num_samplers;
unsigned num_textures;
+ uint fb_width, fb_height;
+
/* Counter for occlusion queries. Note this supports overlapping
* queries.
*/
diff --git a/src/gallium/drivers/softpipe/sp_prim_setup.c b/src/gallium/drivers/softpipe/sp_prim_setup.c
index 7aa9cf8e851..f2d6043e2ed 100644
--- a/src/gallium/drivers/softpipe/sp_prim_setup.c
+++ b/src/gallium/drivers/softpipe/sp_prim_setup.c
@@ -485,7 +485,7 @@ setup_fragcoord_coeff(struct setup_stage *setup, uint slot)
/*Y*/
if (setup->softpipe->rasterizer->origin_lower_left) {
/* y=0=bottom */
- const int winHeight = setup->softpipe->framebuffer.cbufs[0]->height;
+ const int winHeight = setup->softpipe->fb_height;
setup->coef[slot].a0[1] = (float) (winHeight - 1);
setup->coef[slot].dady[1] = -1.0;
}
diff --git a/src/gallium/drivers/softpipe/sp_quad_stipple.c b/src/gallium/drivers/softpipe/sp_quad_stipple.c
index 8660432259c..9a39249576b 100644
--- a/src/gallium/drivers/softpipe/sp_quad_stipple.c
+++ b/src/gallium/drivers/softpipe/sp_quad_stipple.c
@@ -25,7 +25,7 @@ stipple_quad(struct quad_stage *qs, struct quad_header *quad)
int y0, y1;
uint stipple0, stipple1;
if (softpipe->rasterizer->origin_lower_left) {
- y0 = softpipe->framebuffer.cbufs[0]->height - 1 - quad->y0;
+ y0 = softpipe->fb_height - 1 - quad->y0;
y1 = y0 - 1;
}
else {
diff --git a/src/gallium/drivers/softpipe/sp_state_derived.c b/src/gallium/drivers/softpipe/sp_state_derived.c
index 82cb31ece73..53b2056b8a6 100644
--- a/src/gallium/drivers/softpipe/sp_state_derived.c
+++ b/src/gallium/drivers/softpipe/sp_state_derived.c
@@ -171,17 +171,8 @@ softpipe_get_vbuf_vertex_info(struct softpipe_context *softpipe)
static void
compute_cliprect(struct softpipe_context *sp)
{
- unsigned surfWidth, surfHeight;
-
- if (sp->framebuffer.num_cbufs > 0) {
- surfWidth = sp->framebuffer.cbufs[0]->width;
- surfHeight = sp->framebuffer.cbufs[0]->height;
- }
- else {
- /* no surface? */
- surfWidth = sp->scissor.maxx;
- surfHeight = sp->scissor.maxy;
- }
+ uint surfWidth = sp->fb_width;
+ uint surfHeight = sp->fb_height;
if (sp->rasterizer->scissor) {
/* clip to scissor rect */
diff --git a/src/gallium/drivers/softpipe/sp_state_surface.c b/src/gallium/drivers/softpipe/sp_state_surface.c
index 124b18b7081..2f556844644 100644
--- a/src/gallium/drivers/softpipe/sp_state_surface.c
+++ b/src/gallium/drivers/softpipe/sp_state_surface.c
@@ -48,6 +48,9 @@ softpipe_set_framebuffer_state(struct pipe_context *pipe,
struct softpipe_context *sp = softpipe_context(pipe);
uint i;
+ /* updated below */
+ sp->fb_width = sp->fb_height = 0;
+
for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) {
/* check if changing cbuf */
if (sp->framebuffer.cbufs[i] != fb->cbufs[i]) {
@@ -60,6 +63,10 @@ softpipe_set_framebuffer_state(struct pipe_context *pipe,
/* update cache */
sp_tile_cache_set_surface(sp->cbuf_cache[i], fb->cbufs[i]);
}
+ if (fb->cbufs[i]) {
+ sp->fb_width = fb->cbufs[i]->width;
+ sp->fb_height = fb->cbufs[i]->height;
+ }
}
sp->framebuffer.num_cbufs = fb->num_cbufs;
@@ -74,6 +81,11 @@ softpipe_set_framebuffer_state(struct pipe_context *pipe,
/* update cache */
sp_tile_cache_set_surface(sp->zsbuf_cache, fb->zsbuf);
+
+ if (!sp->fb_width && fb->zsbuf) {
+ sp->fb_width = fb->zsbuf->width;
+ sp->fb_height = fb->zsbuf->height;
+ }
}
#if 0
diff --git a/src/gallium/drivers/softpipe/sp_texture.c b/src/gallium/drivers/softpipe/sp_texture.c
index 64bf353aa4a..a98b3b1a4a8 100644
--- a/src/gallium/drivers/softpipe/sp_texture.c
+++ b/src/gallium/drivers/softpipe/sp_texture.c
@@ -174,7 +174,8 @@ softpipe_get_tex_surface_screen(struct pipe_screen *screen,
static void
softpipe_texture_update(struct pipe_context *pipe,
- struct pipe_texture *texture)
+ struct pipe_texture *texture,
+ uint face, uint levelsMask)
{
struct softpipe_context *softpipe = softpipe_context(pipe);
uint unit;
diff --git a/src/gallium/drivers/softpipe/sp_tile_cache.c b/src/gallium/drivers/softpipe/sp_tile_cache.c
index 4caf2dd3fc9..19f71887e7e 100644
--- a/src/gallium/drivers/softpipe/sp_tile_cache.c
+++ b/src/gallium/drivers/softpipe/sp_tile_cache.c
@@ -156,6 +156,7 @@ sp_tile_cache_set_surface(struct softpipe_tile_cache *tc,
if (tc->surface_map) {
/*assert(tc->surface != ps);*/
pipe_surface_unmap(tc->surface);
+ tc->surface_map = NULL;
}
pipe_surface_reference(&tc->surface, ps);
diff --git a/src/gallium/include/pipe/p_context.h b/src/gallium/include/pipe/p_context.h
index b64948f0f3b..a3824601be9 100644
--- a/src/gallium/include/pipe/p_context.h
+++ b/src/gallium/include/pipe/p_context.h
@@ -192,12 +192,10 @@ struct pipe_context {
/**
* Called when texture data is changed.
- * Note: we could pass some hints about which mip levels or cube faces
- * have changed...
- * XXX this may go away - could pass a 'write' flag to get_tex_surface()
*/
void (*texture_update)(struct pipe_context *pipe,
- struct pipe_texture *texture);
+ struct pipe_texture *texture,
+ uint face, uint dirtyLevelsMask);
diff --git a/src/gallium/include/pipe/p_debug.h b/src/gallium/include/pipe/p_debug.h
index f3dfa062161..e924c1ef606 100644
--- a/src/gallium/include/pipe/p_debug.h
+++ b/src/gallium/include/pipe/p_debug.h
@@ -168,6 +168,55 @@ void debug_mask_vprintf(uint32_t uuid,
#endif
+/**
+ * Used by debug_dump_enum and debug_dump_flags to describe symbols.
+ */
+struct debug_named_value
+{
+ const char *name;
+ unsigned long value;
+};
+
+
+/**
+ * Some C pre-processor magic to simplify creating named values.
+ *
+ * Example:
+ * @code
+ * static const debug_named_value my_names[] = {
+ * DEBUG_NAMED_VALUE(MY_ENUM_VALUE_X),
+ * DEBUG_NAMED_VALUE(MY_ENUM_VALUE_Y),
+ * DEBUG_NAMED_VALUE(MY_ENUM_VALUE_Z),
+ * DEBUG_NAMED_VALUE_END
+ * };
+ *
+ * ...
+ * debug_printf("%s = %s\n",
+ * name,
+ * debug_dump_enum(my_names, my_value));
+ * ...
+ * @endcode
+ */
+#define DEBUG_NAMED_VALUE(__symbol) {#__symbol, (unsigned long)__symbol}
+#define DEBUG_NAMED_VALUE_END {NULL, 0}
+
+
+/**
+ * Convert a enum value to a string.
+ */
+const char *
+debug_dump_enum(const struct debug_named_value *names,
+ unsigned long value);
+
+
+/**
+ * Convert binary flags value to a string.
+ */
+const char *
+debug_dump_flags(const struct debug_named_value *names,
+ unsigned long value);
+
+
#ifdef __cplusplus
}
#endif