summaryrefslogtreecommitdiffstats
path: root/src/gallium/auxiliary/util
diff options
context:
space:
mode:
authorChristian König <[email protected]>2010-10-12 23:05:25 +0200
committerChristian König <[email protected]>2010-10-12 23:07:29 +0200
commit695cc370a280a637f411f5ff3877b3fd1c05e424 (patch)
tree69ae2a8fbecfa553faba59274688ffe11ee1a612 /src/gallium/auxiliary/util
parentf3e34ba6fba76870b1c91a27adb706d1b87aeec8 (diff)
parent48156b87bc9d3e09ec34372d69504a787332ea0b (diff)
Merge branch 'master' of ssh://git.freedesktop.org/git/mesa/mesa into pipe-video
Conflicts: configure.ac src/gallium/drivers/nvfx/Makefile src/gallium/include/pipe/p_defines.h src/gallium/include/pipe/p_screen.h src/gallium/include/state_tracker/dri1_api.h src/gallium/include/state_tracker/drm_api.h src/gallium/winsys/nouveau/drm/nouveau_drm_api.c
Diffstat (limited to 'src/gallium/auxiliary/util')
-rw-r--r--src/gallium/auxiliary/util/u_atomic.h47
-rw-r--r--src/gallium/auxiliary/util/u_bitmask.h3
-rw-r--r--src/gallium/auxiliary/util/u_blit.c240
-rw-r--r--src/gallium/auxiliary/util/u_blit.h22
-rw-r--r--src/gallium/auxiliary/util/u_blitter.c839
-rw-r--r--src/gallium/auxiliary/util/u_blitter.h139
-rw-r--r--src/gallium/auxiliary/util/u_box.h19
-rw-r--r--src/gallium/auxiliary/util/u_caps.c271
-rw-r--r--src/gallium/auxiliary/util/u_caps.h71
-rw-r--r--src/gallium/auxiliary/util/u_clear.h25
-rw-r--r--src/gallium/auxiliary/util/u_cpu_detect.c245
-rw-r--r--src/gallium/auxiliary/util/u_cpu_detect.h13
-rw-r--r--src/gallium/auxiliary/util/u_debug.c20
-rw-r--r--src/gallium/auxiliary/util/u_debug.h6
-rw-r--r--src/gallium/auxiliary/util/u_debug_describe.c81
-rw-r--r--src/gallium/auxiliary/util/u_debug_describe.h49
-rw-r--r--src/gallium/auxiliary/util/u_debug_refcnt.c181
-rw-r--r--src/gallium/auxiliary/util/u_debug_refcnt.h63
-rw-r--r--src/gallium/auxiliary/util/u_debug_symbol.c192
-rw-r--r--src/gallium/auxiliary/util/u_debug_symbol.h7
-rw-r--r--src/gallium/auxiliary/util/u_dirty_flags.h28
-rw-r--r--src/gallium/auxiliary/util/u_dirty_surfaces.h30
-rw-r--r--src/gallium/auxiliary/util/u_dl.h3
-rw-r--r--src/gallium/auxiliary/util/u_double_list.h17
-rw-r--r--src/gallium/auxiliary/util/u_draw.h139
-rw-r--r--src/gallium/auxiliary/util/u_draw_quad.c2
-rw-r--r--src/gallium/auxiliary/util/u_draw_quad.h6
-rw-r--r--src/gallium/auxiliary/util/u_dump.h6
-rw-r--r--src/gallium/auxiliary/util/u_dump_defines.c72
-rw-r--r--src/gallium/auxiliary/util/u_dump_state.c13
-rw-r--r--src/gallium/auxiliary/util/u_dynarray.h3
-rw-r--r--src/gallium/auxiliary/util/u_format.c73
-rw-r--r--src/gallium/auxiliary/util/u_format.h143
-rw-r--r--src/gallium/auxiliary/util/u_format_other.c15
-rw-r--r--src/gallium/auxiliary/util/u_format_pack.py3
-rwxr-xr-xsrc/gallium/auxiliary/util/u_format_parse.py2
-rw-r--r--src/gallium/auxiliary/util/u_format_s3tc.c4
-rw-r--r--src/gallium/auxiliary/util/u_format_srgb.py1
-rwxr-xr-xsrc/gallium/auxiliary/util/u_format_table.py5
-rw-r--r--src/gallium/auxiliary/util/u_framebuffer.c148
-rw-r--r--src/gallium/auxiliary/util/u_framebuffer.h54
-rw-r--r--src/gallium/auxiliary/util/u_gen_mipmap.c12
-rw-r--r--src/gallium/auxiliary/util/u_half.py8
-rw-r--r--src/gallium/auxiliary/util/u_index_modify.c127
-rw-r--r--src/gallium/auxiliary/util/u_index_modify.h41
-rw-r--r--src/gallium/auxiliary/util/u_inlines.h42
-rw-r--r--src/gallium/auxiliary/util/u_linear.h1
-rw-r--r--src/gallium/auxiliary/util/u_linkage.c149
-rw-r--r--src/gallium/auxiliary/util/u_linkage.h66
-rw-r--r--src/gallium/auxiliary/util/u_math.h37
-rw-r--r--src/gallium/auxiliary/util/u_mempool.c169
-rw-r--r--src/gallium/auxiliary/util/u_mempool.h87
-rw-r--r--src/gallium/auxiliary/util/u_network.c2
-rw-r--r--src/gallium/auxiliary/util/u_pack_color.h83
-rw-r--r--src/gallium/auxiliary/util/u_pointer.h23
-rw-r--r--src/gallium/auxiliary/util/u_prim.h60
-rw-r--r--src/gallium/auxiliary/util/u_rect.c207
-rw-r--r--src/gallium/auxiliary/util/u_rect.h77
-rw-r--r--src/gallium/auxiliary/util/u_simple_list.h2
-rw-r--r--src/gallium/auxiliary/util/u_simple_shaders.c20
-rw-r--r--src/gallium/auxiliary/util/u_simple_shaders.h7
-rw-r--r--src/gallium/auxiliary/util/u_split_prim.h114
-rw-r--r--src/gallium/auxiliary/util/u_sse.h28
-rw-r--r--src/gallium/auxiliary/util/u_staging.c117
-rw-r--r--src/gallium/auxiliary/util/u_staging.h63
-rw-r--r--src/gallium/auxiliary/util/u_surface.c257
-rw-r--r--src/gallium/auxiliary/util/u_surface.h44
-rw-r--r--src/gallium/auxiliary/util/u_surfaces.c105
-rw-r--r--src/gallium/auxiliary/util/u_surfaces.h48
-rw-r--r--src/gallium/auxiliary/util/u_tile.h3
-rw-r--r--src/gallium/auxiliary/util/u_transfer.c4
-rw-r--r--src/gallium/auxiliary/util/u_transfer.h1
-rw-r--r--src/gallium/auxiliary/util/u_upload_mgr.c2
-rw-r--r--src/gallium/auxiliary/util/u_upload_mgr.h5
74 files changed, 4077 insertions, 1234 deletions
diff --git a/src/gallium/auxiliary/util/u_atomic.h b/src/gallium/auxiliary/util/u_atomic.h
index a1568233906..8434491a421 100644
--- a/src/gallium/auxiliary/util/u_atomic.h
+++ b/src/gallium/auxiliary/util/u_atomic.h
@@ -29,6 +29,8 @@
#define PIPE_ATOMIC_ASM_MSVC_X86
#elif (defined(PIPE_CC_GCC) && defined(PIPE_ARCH_X86))
#define PIPE_ATOMIC_ASM_GCC_X86
+#elif (defined(PIPE_CC_GCC) && defined(PIPE_ARCH_X86_64))
+#define PIPE_ATOMIC_ASM_GCC_X86_64
#elif defined(PIPE_CC_GCC) && (PIPE_CC_GCC_VERSION >= 401)
#define PIPE_ATOMIC_GCC_INTRINSIC
#else
@@ -36,6 +38,51 @@
#endif
+#if defined(PIPE_ATOMIC_ASM_GCC_X86_64)
+#define PIPE_ATOMIC "GCC x86_64 assembly"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define p_atomic_set(_v, _i) (*(_v) = (_i))
+#define p_atomic_read(_v) (*(_v))
+
+static INLINE boolean
+p_atomic_dec_zero(int32_t *v)
+{
+ unsigned char c;
+
+ __asm__ __volatile__("lock; decl %0; sete %1":"+m"(*v), "=qm"(c)
+ ::"memory");
+
+ return c != 0;
+}
+
+static INLINE void
+p_atomic_inc(int32_t *v)
+{
+ __asm__ __volatile__("lock; incl %0":"+m"(*v));
+}
+
+static INLINE void
+p_atomic_dec(int32_t *v)
+{
+ __asm__ __volatile__("lock; decl %0":"+m"(*v));
+}
+
+static INLINE int32_t
+p_atomic_cmpxchg(int32_t *v, int32_t old, int32_t _new)
+{
+ return __sync_val_compare_and_swap(v, old, _new);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PIPE_ATOMIC_ASM_GCC_X86_64 */
+
#if defined(PIPE_ATOMIC_ASM_GCC_X86)
diff --git a/src/gallium/auxiliary/util/u_bitmask.h b/src/gallium/auxiliary/util/u_bitmask.h
index 87f1110296a..98b85ddecd5 100644
--- a/src/gallium/auxiliary/util/u_bitmask.h
+++ b/src/gallium/auxiliary/util/u_bitmask.h
@@ -36,6 +36,9 @@
#define U_HANDLE_BITMASK_H_
+#include "pipe/p_compiler.h"
+
+
#ifdef __cplusplus
extern "C" {
#endif
diff --git a/src/gallium/auxiliary/util/u_blit.c b/src/gallium/auxiliary/util/u_blit.c
index e45310b9bb7..dfb142b9e1c 100644
--- a/src/gallium/auxiliary/util/u_blit.c
+++ b/src/gallium/auxiliary/util/u_blit.c
@@ -47,8 +47,6 @@
#include "util/u_memory.h"
#include "util/u_sampler.h"
#include "util/u_simple_shaders.h"
-#include "util/u_surface.h"
-#include "util/u_rect.h"
#include "cso_cache/cso_context.h"
@@ -59,15 +57,18 @@ struct blit_state
struct cso_context *cso;
struct pipe_blend_state blend;
- struct pipe_depth_stencil_alpha_state depthstencil;
+ struct pipe_depth_stencil_alpha_state depthstencil_keep;
+ struct pipe_depth_stencil_alpha_state depthstencil_write;
struct pipe_rasterizer_state rasterizer;
struct pipe_sampler_state sampler;
struct pipe_viewport_state viewport;
struct pipe_clip_state clip;
struct pipe_vertex_element velem[2];
+ enum pipe_texture_target internal_target;
void *vs;
void *fs[TGSI_WRITEMASK_XYZW + 1];
+ void *fs_depth;
struct pipe_resource *vbuf; /**< quad vertices */
unsigned vbuf_slot;
@@ -98,12 +99,15 @@ util_create_blit(struct pipe_context *pipe, struct cso_context *cso)
ctx->blend.rt[0].colormask = PIPE_MASK_RGBA;
/* no-op depth/stencil/alpha */
- memset(&ctx->depthstencil, 0, sizeof(ctx->depthstencil));
+ memset(&ctx->depthstencil_keep, 0, sizeof(ctx->depthstencil_keep));
+ memset(&ctx->depthstencil_write, 0, sizeof(ctx->depthstencil_write));
+ ctx->depthstencil_write.depth.enabled = 1;
+ ctx->depthstencil_write.depth.writemask = 1;
+ ctx->depthstencil_write.depth.func = PIPE_FUNC_ALWAYS;
/* rasterizer */
memset(&ctx->rasterizer, 0, sizeof(ctx->rasterizer));
- ctx->rasterizer.front_winding = PIPE_WINDING_CW;
- ctx->rasterizer.cull_mode = PIPE_WINDING_NONE;
+ ctx->rasterizer.cull_face = PIPE_FACE_NONE;
ctx->rasterizer.gl_rasterization_rules = 1;
/* samplers */
@@ -114,7 +118,6 @@ util_create_blit(struct pipe_context *pipe, struct cso_context *cso)
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;
/* vertex elements state */
memset(&ctx->velem[0], 0, sizeof(ctx->velem[0]) * 2);
@@ -138,7 +141,8 @@ util_create_blit(struct pipe_context *pipe, struct cso_context *cso)
/* fragment shader */
ctx->fs[TGSI_WRITEMASK_XYZW] =
- util_make_fragment_tex_shader(pipe, TGSI_TEXTURE_2D);
+ util_make_fragment_tex_shader(pipe, TGSI_TEXTURE_2D,
+ TGSI_INTERPOLATE_LINEAR);
ctx->vbuf = NULL;
/* init vertex data that doesn't change */
@@ -148,6 +152,11 @@ util_create_blit(struct pipe_context *pipe, struct cso_context *cso)
ctx->vertices[i][1][3] = 1.0f; /* q */
}
+ if(pipe->screen->get_param(pipe->screen, PIPE_CAP_NPOT_TEXTURES))
+ ctx->internal_target = PIPE_TEXTURE_2D;
+ else
+ ctx->internal_target = PIPE_TEXTURE_RECT;
+
return ctx;
}
@@ -167,6 +176,9 @@ util_destroy_blit(struct blit_state *ctx)
if (ctx->fs[i])
pipe->delete_fs_state(pipe, ctx->fs[i]);
+ if (ctx->fs_depth)
+ pipe->delete_fs_state(pipe, ctx->fs_depth);
+
pipe_resource_reference(&ctx->vbuf, NULL);
FREE(ctx);
@@ -192,7 +204,6 @@ get_next_slot( struct blit_state *ctx )
return ctx->vbuf_slot++ * sizeof ctx->vertices;
}
-
@@ -275,14 +286,15 @@ regions_overlap(int srcX0, int srcY0,
* \param writemask controls which channels in the dest surface are sourced
* from the src surface. Disabled channels are sourced
* from (0,0,0,1).
- * XXX need some control over blitting Z and/or stencil.
+ * XXX need some control over blitting stencil.
*/
void
util_blit_pixels_writemask(struct blit_state *ctx,
- struct pipe_surface *src,
- struct pipe_sampler_view *src_sampler_view,
+ struct pipe_resource *src_tex,
+ struct pipe_subresource srcsub,
int srcX0, int srcY0,
int srcX1, int srcY1,
+ int srcZ0,
struct pipe_surface *dst,
int dstX0, int dstY0,
int dstX1, int dstY1,
@@ -292,23 +304,25 @@ util_blit_pixels_writemask(struct blit_state *ctx,
struct pipe_context *pipe = ctx->pipe;
struct pipe_screen *screen = pipe->screen;
struct pipe_sampler_view *sampler_view = NULL;
+ struct pipe_sampler_view sv_templ;
struct pipe_framebuffer_state fb;
const int srcW = abs(srcX1 - srcX0);
const int srcH = abs(srcY1 - srcY0);
unsigned offset;
- boolean overlap;
+ boolean overlap, dst_is_depth;
float s0, t0, s1, t1;
+ boolean normalized;
assert(filter == PIPE_TEX_MIPFILTER_NEAREST ||
filter == PIPE_TEX_MIPFILTER_LINEAR);
- assert(screen->is_format_supported(screen, src->format, PIPE_TEXTURE_2D,
- PIPE_BIND_SAMPLER_VIEW, 0));
- assert(screen->is_format_supported(screen, dst->format, PIPE_TEXTURE_2D,
- PIPE_BIND_RENDER_TARGET, 0));
+ assert(srcsub.level <= src_tex->last_level);
/* do the regions overlap? */
- overlap = util_same_surface(src, dst) &&
+ overlap = src_tex == dst->texture &&
+ dst->face == srcsub.face &&
+ dst->level == srcsub.level &&
+ dst->zslice == srcZ0 &&
regions_overlap(srcX0, srcY0, srcX1, srcY1,
dstX0, dstY0, dstX1, dstY1);
@@ -317,8 +331,7 @@ util_blit_pixels_writemask(struct blit_state *ctx,
* no overlapping.
* Filter mode should not matter since there's no stretching.
*/
- if (pipe->surface_copy &&
- dst->format == src->format &&
+ if (dst->format == src_tex->format &&
srcX0 < srcX1 &&
dstX0 < dstX1 &&
srcY0 < srcY1 &&
@@ -326,29 +339,36 @@ util_blit_pixels_writemask(struct blit_state *ctx,
(dstX1 - dstX0) == (srcX1 - srcX0) &&
(dstY1 - dstY0) == (srcY1 - srcY0) &&
!overlap) {
- pipe->surface_copy(pipe,
- dst, dstX0, dstY0, /* dest */
- src, srcX0, srcY0, /* src */
- srcW, srcH); /* size */
+ struct pipe_subresource subdst;
+ subdst.face = dst->face;
+ subdst.level = dst->level;
+ pipe->resource_copy_region(pipe,
+ dst->texture, subdst,
+ dstX0, dstY0, dst->zslice,/* dest */
+ src_tex, srcsub,
+ srcX0, srcY0, srcZ0,/* src */
+ srcW, srcH); /* size */
return;
}
-
- assert(screen->is_format_supported(screen, dst->format, PIPE_TEXTURE_2D,
- PIPE_BIND_RENDER_TARGET, 0));
/* Create a temporary texture when src and dest alias or when src
- * is anything other than a single-level 2d texture.
+ * is anything other than a 2d texture.
+ * XXX should just use appropriate shader to access 1d / 3d slice / cube face,
+ * much like the u_blitter code does (should be pretty trivial).
*
* This can still be improved upon.
*/
- if (util_same_surface(src, dst) ||
- src->texture->target != PIPE_TEXTURE_2D ||
- src->texture->last_level != 0)
+ if ((src_tex == dst->texture &&
+ dst->face == srcsub.face &&
+ dst->level == srcsub.level &&
+ dst->zslice == srcZ0) ||
+ (src_tex->target != PIPE_TEXTURE_2D &&
+ src_tex->target != PIPE_TEXTURE_RECT))
{
struct pipe_resource texTemp;
struct pipe_resource *tex;
struct pipe_sampler_view sv_templ;
- struct pipe_surface *texSurf;
+ struct pipe_subresource texsub;
const int srcLeft = MIN2(srcX0, srcX1);
const int srcTop = MIN2(srcY0, srcY1);
@@ -368,8 +388,8 @@ util_blit_pixels_writemask(struct blit_state *ctx,
/* create temp texture */
memset(&texTemp, 0, sizeof(texTemp));
- texTemp.target = PIPE_TEXTURE_2D;
- texTemp.format = src->format;
+ texTemp.target = ctx->internal_target;
+ texTemp.format = src_tex->format;
texTemp.last_level = 0;
texTemp.width0 = srcW;
texTemp.height0 = srcH;
@@ -380,50 +400,69 @@ util_blit_pixels_writemask(struct blit_state *ctx,
if (!tex)
return;
+ texsub.face = 0;
+ texsub.level = 0;
+ /* load temp texture */
+ pipe->resource_copy_region(pipe,
+ tex, texsub, 0, 0, 0, /* dest */
+ src_tex, srcsub, srcLeft, srcTop, srcZ0, /* src */
+ srcW, srcH); /* size */
+
+ normalized = tex->target != PIPE_TEXTURE_RECT;
+ if(normalized) {
+ s0 = 0.0f;
+ s1 = 1.0f;
+ t0 = 0.0f;
+ t1 = 1.0f;
+ }
+ else {
+ s0 = 0;
+ s1 = srcW;
+ t0 = 0;
+ t1 = srcH;
+ }
+
u_sampler_view_default_template(&sv_templ, tex, tex->format);
+ sampler_view = pipe->create_sampler_view(pipe, tex, &sv_templ);
- sampler_view = ctx->pipe->create_sampler_view(ctx->pipe, tex, &sv_templ);
if (!sampler_view) {
pipe_resource_reference(&tex, NULL);
return;
}
-
- texSurf = screen->get_tex_surface(screen, tex, 0, 0, 0,
- PIPE_BIND_BLIT_DESTINATION);
-
- /* load temp texture */
- if (pipe->surface_copy) {
- pipe->surface_copy(pipe,
- texSurf, 0, 0, /* dest */
- src, srcLeft, srcTop, /* src */
- srcW, srcH); /* size */
- } else {
- util_surface_copy(pipe, FALSE,
- texSurf, 0, 0, /* dest */
- src, srcLeft, srcTop, /* src */
- srcW, srcH); /* size */
- }
-
- /* free the surface, update the texture if necessary.
- */
- pipe_surface_reference(&texSurf, NULL);
- s0 = 0.0f;
- s1 = 1.0f;
- t0 = 0.0f;
- t1 = 1.0f;
-
pipe_resource_reference(&tex, NULL);
}
else {
- pipe_sampler_view_reference(&sampler_view, src_sampler_view);
- s0 = srcX0 / (float)src->texture->width0;
- s1 = srcX1 / (float)src->texture->width0;
- t0 = srcY0 / (float)src->texture->height0;
- t1 = srcY1 / (float)src->texture->height0;
+ u_sampler_view_default_template(&sv_templ, src_tex, src_tex->format);
+ sv_templ.first_level = sv_templ.last_level = srcsub.level;
+ sampler_view = pipe->create_sampler_view(pipe, src_tex, &sv_templ);
+
+ if (!sampler_view) {
+ return;
+ }
+
+ s0 = srcX0;
+ s1 = srcX1;
+ t0 = srcY0;
+ t1 = srcY1;
+ normalized = sampler_view->texture->target != PIPE_TEXTURE_RECT;
+ if(normalized)
+ {
+ s0 /= (float)(u_minify(sampler_view->texture->width0, srcsub.level));
+ s1 /= (float)(u_minify(sampler_view->texture->width0, srcsub.level));
+ t0 /= (float)(u_minify(sampler_view->texture->height0, srcsub.level));
+ t1 /= (float)(u_minify(sampler_view->texture->height0, srcsub.level));
+ }
}
-
+ dst_is_depth = util_format_is_depth_or_stencil(dst->format);
+ assert(screen->is_format_supported(screen, sampler_view->format, ctx->internal_target,
+ sampler_view->texture->nr_samples,
+ PIPE_BIND_SAMPLER_VIEW, 0));
+ assert(screen->is_format_supported(screen, dst->format, ctx->internal_target,
+ dst->texture->nr_samples,
+ dst_is_depth ? PIPE_BIND_DEPTH_STENCIL :
+ PIPE_BIND_RENDER_TARGET, 0));
/* save state (restored below) */
cso_save_blend(ctx->cso);
cso_save_depth_stencil_alpha(ctx->cso);
@@ -439,14 +478,20 @@ util_blit_pixels_writemask(struct blit_state *ctx,
/* set misc state we care about */
cso_set_blend(ctx->cso, &ctx->blend);
- cso_set_depth_stencil_alpha(ctx->cso, &ctx->depthstencil);
+ cso_set_depth_stencil_alpha(ctx->cso,
+ dst_is_depth ? &ctx->depthstencil_write :
+ &ctx->depthstencil_keep);
cso_set_rasterizer(ctx->cso, &ctx->rasterizer);
cso_set_clip(ctx->cso, &ctx->clip);
cso_set_vertex_elements(ctx->cso, 2, ctx->velem);
/* sampler */
+ ctx->sampler.normalized_coords = normalized;
ctx->sampler.min_img_filter = filter;
ctx->sampler.mag_img_filter = filter;
+ /* we've limited this already with the sampler view but you never know... */
+ ctx->sampler.min_lod = srcsub.level;
+ ctx->sampler.max_lod = srcsub.level;
cso_single_sampler(ctx->cso, 0, &ctx->sampler);
cso_single_sampler_done(ctx->cso);
@@ -464,21 +509,35 @@ util_blit_pixels_writemask(struct blit_state *ctx,
/* texture */
cso_set_fragment_sampler_views(ctx->cso, 1, &sampler_view);
- if (ctx->fs[writemask] == NULL)
- ctx->fs[writemask] =
- util_make_fragment_tex_shader_writemask(pipe, TGSI_TEXTURE_2D,
- writemask);
-
/* shaders */
- cso_set_fragment_shader_handle(ctx->cso, ctx->fs[writemask]);
+ if (dst_is_depth) {
+ if (ctx->fs_depth == NULL)
+ ctx->fs_depth =
+ util_make_fragment_tex_shader_writedepth(pipe, TGSI_TEXTURE_2D,
+ TGSI_INTERPOLATE_LINEAR);
+
+ cso_set_fragment_shader_handle(ctx->cso, ctx->fs_depth);
+ } else {
+ if (ctx->fs[writemask] == NULL)
+ ctx->fs[writemask] =
+ util_make_fragment_tex_shader_writemask(pipe, TGSI_TEXTURE_2D,
+ TGSI_INTERPOLATE_LINEAR,
+ writemask);
+
+ cso_set_fragment_shader_handle(ctx->cso, ctx->fs[writemask]);
+ }
cso_set_vertex_shader_handle(ctx->cso, ctx->vs);
/* drawing dest */
memset(&fb, 0, sizeof(fb));
fb.width = dst->width;
fb.height = dst->height;
- fb.nr_cbufs = 1;
- fb.cbufs[0] = dst;
+ if (dst_is_depth) {
+ fb.zsbuf = dst;
+ } else {
+ fb.nr_cbufs = 1;
+ fb.cbufs[0] = dst;
+ }
cso_set_framebuffer(ctx->cso, &fb);
/* draw quad */
@@ -515,18 +574,21 @@ util_blit_pixels_writemask(struct blit_state *ctx,
void
util_blit_pixels(struct blit_state *ctx,
- struct pipe_surface *src,
- struct pipe_sampler_view *src_sampler_view,
+ struct pipe_resource *src_tex,
+ struct pipe_subresource srcsub,
int srcX0, int srcY0,
int srcX1, int srcY1,
+ int srcZ,
struct pipe_surface *dst,
int dstX0, int dstY0,
int dstX1, int dstY1,
float z, uint filter )
{
- util_blit_pixels_writemask( ctx, src, src_sampler_view,
+ util_blit_pixels_writemask( ctx, src_tex,
+ srcsub,
srcX0, srcY0,
srcX1, srcY1,
+ srcZ,
dst,
dstX0, dstY0,
dstX1, dstY1,
@@ -548,7 +610,6 @@ void util_blit_flush( struct blit_state *ctx )
/**
* Copy pixel block from src texture to dst surface.
- * Overlapping regions are acceptable.
*
* XXX Should support selection of level.
* XXX need some control over blitting Z and/or stencil.
@@ -563,6 +624,7 @@ util_blit_pixels_tex(struct blit_state *ctx,
int dstX1, int dstY1,
float z, uint filter)
{
+ boolean normalized = src_sampler_view->texture->target != PIPE_TEXTURE_RECT;
struct pipe_framebuffer_state fb;
float s0, t0, s1, t1;
unsigned offset;
@@ -575,13 +637,22 @@ util_blit_pixels_tex(struct blit_state *ctx,
assert(tex->width0 != 0);
assert(tex->height0 != 0);
- s0 = srcX0 / (float)tex->width0;
- s1 = srcX1 / (float)tex->width0;
- t0 = srcY0 / (float)tex->height0;
- t1 = srcY1 / (float)tex->height0;
+ s0 = srcX0;
+ s1 = srcX1;
+ t0 = srcY0;
+ t1 = srcY1;
+
+ if(normalized)
+ {
+ s0 /= (float)tex->width0;
+ s1 /= (float)tex->width0;
+ t0 /= (float)tex->height0;
+ t1 /= (float)tex->height0;
+ }
assert(ctx->pipe->screen->is_format_supported(ctx->pipe->screen, dst->format,
PIPE_TEXTURE_2D,
+ dst->texture->nr_samples,
PIPE_BIND_RENDER_TARGET,
0));
@@ -599,12 +670,13 @@ util_blit_pixels_tex(struct blit_state *ctx,
/* set misc state we care about */
cso_set_blend(ctx->cso, &ctx->blend);
- cso_set_depth_stencil_alpha(ctx->cso, &ctx->depthstencil);
+ cso_set_depth_stencil_alpha(ctx->cso, &ctx->depthstencil_keep);
cso_set_rasterizer(ctx->cso, &ctx->rasterizer);
cso_set_clip(ctx->cso, &ctx->clip);
cso_set_vertex_elements(ctx->cso, 2, ctx->velem);
/* sampler */
+ ctx->sampler.normalized_coords = normalized;
ctx->sampler.min_img_filter = filter;
ctx->sampler.mag_img_filter = filter;
cso_single_sampler(ctx->cso, 0, &ctx->sampler);
diff --git a/src/gallium/auxiliary/util/u_blit.h b/src/gallium/auxiliary/util/u_blit.h
index 464ff9aaced..b8a0dfce13f 100644
--- a/src/gallium/auxiliary/util/u_blit.h
+++ b/src/gallium/auxiliary/util/u_blit.h
@@ -30,18 +30,20 @@
#define U_BLIT_H
+#include "pipe/p_compiler.h"
+
+
#ifdef __cplusplus
extern "C" {
#endif
+struct cso_context;
struct pipe_context;
-struct pipe_surface;
struct pipe_resource;
-struct cso_context;
-
-
-struct blit_state;
+struct pipe_sampler_view;
+struct pipe_subresource;
+struct pipe_surface;
extern struct blit_state *
@@ -52,10 +54,11 @@ util_destroy_blit(struct blit_state *ctx);
extern void
util_blit_pixels(struct blit_state *ctx,
- struct pipe_surface *src,
- struct pipe_sampler_view *src_sampler_view,
+ struct pipe_resource *src_tex,
+ struct pipe_subresource srcsub,
int srcX0, int srcY0,
int srcX1, int srcY1,
+ int srcZ0,
struct pipe_surface *dst,
int dstX0, int dstY0,
int dstX1, int dstY1,
@@ -63,10 +66,11 @@ util_blit_pixels(struct blit_state *ctx,
void
util_blit_pixels_writemask(struct blit_state *ctx,
- struct pipe_surface *src,
- struct pipe_sampler_view *src_sampler_view,
+ struct pipe_resource *src_tex,
+ struct pipe_subresource srcsub,
int srcX0, int srcY0,
int srcX1, int srcY1,
+ int srcZ0,
struct pipe_surface *dst,
int dstX0, int dstY0,
int dstX1, int dstY1,
diff --git a/src/gallium/auxiliary/util/u_blitter.c b/src/gallium/auxiliary/util/u_blitter.c
index 956aedc8a15..a163f93cb82 100644
--- a/src/gallium/auxiliary/util/u_blitter.c
+++ b/src/gallium/auxiliary/util/u_blitter.c
@@ -26,8 +26,8 @@
/**
* @file
- * Blitter utility to facilitate acceleration of the clear, surface_copy,
- * and surface_fill functions.
+ * Blitter utility to facilitate acceleration of the clear, clear_render_target, clear_depth_stencil
+ * resource_copy_region functions.
*
* @author Marek Olšák
*/
@@ -43,19 +43,17 @@
#include "util/u_math.h"
#include "util/u_blitter.h"
#include "util/u_draw_quad.h"
-#include "util/u_pack_color.h"
-#include "util/u_rect.h"
#include "util/u_sampler.h"
#include "util/u_simple_shaders.h"
+#include "util/u_surface.h"
#include "util/u_texture.h"
#define INVALID_PTR ((void*)~0)
struct blitter_context_priv
{
- struct blitter_context blitter;
+ struct blitter_context base;
- struct pipe_context *pipe; /**< pipe context */
struct pipe_resource *vbuf; /**< quad */
float vertices[4][2][4]; /**< {pos, color} or {pos, texcoord} */
@@ -69,8 +67,8 @@ struct blitter_context_priv
void *vs_tex; /**< Vertex shader which passes {pos, texcoord} to the output.*/
/* Fragment shaders. */
- /* FS which outputs a color to multiple color buffers. */
- void *fs_col[PIPE_MAX_COLOR_BUFS];
+ /* The shader at index i outputs color to color buffers 0,1,...,i-1. */
+ void *fs_col[PIPE_MAX_COLOR_BUFS+1];
/* FS which outputs a color from a texture,
where the index is PIPE_TEXTURE_* to be sampled. */
@@ -88,24 +86,36 @@ struct blitter_context_priv
void *dsa_write_depth_stencil;
void *dsa_write_depth_keep_stencil;
void *dsa_keep_depth_stencil;
+ void *dsa_keep_depth_write_stencil;
+ void *dsa_flush_depth_stencil;
void *velem_state;
/* Sampler state for clamping to a miplevel. */
- void *sampler_state[PIPE_MAX_TEXTURE_LEVELS];
+ void *sampler_state[PIPE_MAX_TEXTURE_LEVELS * 2];
/* Rasterizer state. */
void *rs_state;
- struct pipe_sampler_view *sampler_view;
-
/* Viewport state. */
struct pipe_viewport_state viewport;
/* Clip state. */
struct pipe_clip_state clip;
+
+ /* Destination surface dimensions. */
+ unsigned dst_width;
+ unsigned dst_height;
};
+static void blitter_draw_rectangle(struct blitter_context *blitter,
+ unsigned x, unsigned y,
+ unsigned width, unsigned height,
+ float depth,
+ enum blitter_attrib_type type,
+ const float attrib[4]);
+
+
struct blitter_context *util_blitter_create(struct pipe_context *pipe)
{
struct blitter_context_priv *ctx;
@@ -120,19 +130,20 @@ struct blitter_context *util_blitter_create(struct pipe_context *pipe)
if (!ctx)
return NULL;
- ctx->pipe = pipe;
+ ctx->base.pipe = pipe;
+ ctx->base.draw_rectangle = blitter_draw_rectangle;
/* init state objects for them to be considered invalid */
- ctx->blitter.saved_blend_state = INVALID_PTR;
- ctx->blitter.saved_dsa_state = INVALID_PTR;
- ctx->blitter.saved_rs_state = INVALID_PTR;
- ctx->blitter.saved_fs = INVALID_PTR;
- ctx->blitter.saved_vs = INVALID_PTR;
- ctx->blitter.saved_velem_state = INVALID_PTR;
- ctx->blitter.saved_fb_state.nr_cbufs = ~0;
- ctx->blitter.saved_num_sampler_views = ~0;
- ctx->blitter.saved_num_sampler_states = ~0;
- ctx->blitter.saved_num_vertex_buffers = ~0;
+ ctx->base.saved_blend_state = INVALID_PTR;
+ ctx->base.saved_dsa_state = INVALID_PTR;
+ ctx->base.saved_rs_state = INVALID_PTR;
+ ctx->base.saved_fs = INVALID_PTR;
+ ctx->base.saved_vs = INVALID_PTR;
+ ctx->base.saved_velem_state = INVALID_PTR;
+ ctx->base.saved_fb_state.nr_cbufs = ~0;
+ ctx->base.saved_num_sampler_views = ~0;
+ ctx->base.saved_num_sampler_states = ~0;
+ ctx->base.saved_num_vertex_buffers = ~0;
/* blend state objects */
memset(&blend, 0, sizeof(blend));
@@ -146,6 +157,10 @@ struct blitter_context *util_blitter_create(struct pipe_context *pipe)
ctx->dsa_keep_depth_stencil =
pipe->create_depth_stencil_alpha_state(pipe, &dsa);
+ dsa.depth.writemask = 1;
+ ctx->dsa_flush_depth_stencil =
+ pipe->create_depth_stencil_alpha_state(pipe, &dsa);
+
dsa.depth.enabled = 1;
dsa.depth.writemask = 1;
dsa.depth.func = PIPE_FUNC_ALWAYS;
@@ -161,8 +176,12 @@ struct blitter_context *util_blitter_create(struct pipe_context *pipe)
dsa.stencil[0].writemask = 0xff;
ctx->dsa_write_depth_stencil =
pipe->create_depth_stencil_alpha_state(pipe, &dsa);
- /* The DSA state objects which write depth and stencil are created
- * on-demand. */
+
+
+ dsa.depth.enabled = 0;
+ dsa.depth.writemask = 0;
+ ctx->dsa_keep_depth_write_stencil =
+ pipe->create_depth_stencil_alpha_state(pipe, &dsa);
/* sampler state */
sampler_state = &ctx->template_sampler_state;
@@ -175,8 +194,7 @@ struct blitter_context *util_blitter_create(struct pipe_context *pipe)
/* rasterizer state */
memset(&rs_state, 0, sizeof(rs_state));
- rs_state.front_winding = PIPE_WINDING_CW;
- rs_state.cull_mode = PIPE_WINDING_NONE;
+ rs_state.cull_face = PIPE_FACE_NONE;
rs_state.gl_rasterization_rules = 1;
rs_state.flatshade = 1;
ctx->rs_state = pipe->create_rasterizer_state(pipe, &rs_state);
@@ -216,17 +234,17 @@ struct blitter_context *util_blitter_create(struct pipe_context *pipe)
ctx->vertices[i][0][3] = 1; /*v.w*/
/* create the vertex buffer */
- ctx->vbuf = pipe_buffer_create(ctx->pipe->screen,
+ ctx->vbuf = pipe_buffer_create(ctx->base.pipe->screen,
PIPE_BIND_VERTEX_BUFFER,
sizeof(ctx->vertices));
- return &ctx->blitter;
+ return &ctx->base;
}
void util_blitter_destroy(struct blitter_context *blitter)
{
struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
- struct pipe_context *pipe = ctx->pipe;
+ struct pipe_context *pipe = blitter->pipe;
int i;
pipe->delete_blend_state(pipe, ctx->blend_write_color);
@@ -235,6 +253,8 @@ void util_blitter_destroy(struct blitter_context *blitter)
pipe->delete_depth_stencil_alpha_state(pipe,
ctx->dsa_write_depth_keep_stencil);
pipe->delete_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_stencil);
+ pipe->delete_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_write_stencil);
+ pipe->delete_depth_stencil_alpha_state(pipe, ctx->dsa_flush_depth_stencil);
pipe->delete_rasterizer_state(pipe, ctx->rs_state);
pipe->delete_vs_state(pipe, ctx->vs_col);
@@ -248,18 +268,14 @@ void util_blitter_destroy(struct blitter_context *blitter)
pipe->delete_fs_state(pipe, ctx->fs_texfetch_depth[i]);
}
- for (i = 0; i < PIPE_MAX_COLOR_BUFS && ctx->fs_col[i]; i++)
+ for (i = 0; i <= PIPE_MAX_COLOR_BUFS; i++)
if (ctx->fs_col[i])
pipe->delete_fs_state(pipe, ctx->fs_col[i]);
- for (i = 0; i < PIPE_MAX_TEXTURE_LEVELS; i++)
+ for (i = 0; i < PIPE_MAX_TEXTURE_LEVELS * 2; i++)
if (ctx->sampler_state[i])
pipe->delete_sampler_state(pipe, ctx->sampler_state[i]);
- if (ctx->sampler_view) {
- pipe_sampler_view_reference(&ctx->sampler_view, NULL);
- }
-
pipe_resource_reference(&ctx->vbuf, NULL);
FREE(ctx);
}
@@ -267,104 +283,117 @@ void util_blitter_destroy(struct blitter_context *blitter)
static void blitter_check_saved_CSOs(struct blitter_context_priv *ctx)
{
/* make sure these CSOs have been saved */
- assert(ctx->blitter.saved_blend_state != INVALID_PTR &&
- ctx->blitter.saved_dsa_state != INVALID_PTR &&
- ctx->blitter.saved_rs_state != INVALID_PTR &&
- ctx->blitter.saved_fs != INVALID_PTR &&
- ctx->blitter.saved_vs != INVALID_PTR &&
- ctx->blitter.saved_velem_state != INVALID_PTR);
+ assert(ctx->base.saved_blend_state != INVALID_PTR &&
+ ctx->base.saved_dsa_state != INVALID_PTR &&
+ ctx->base.saved_rs_state != INVALID_PTR &&
+ ctx->base.saved_fs != INVALID_PTR &&
+ ctx->base.saved_vs != INVALID_PTR &&
+ ctx->base.saved_velem_state != INVALID_PTR);
}
static void blitter_restore_CSOs(struct blitter_context_priv *ctx)
{
- struct pipe_context *pipe = ctx->pipe;
+ struct pipe_context *pipe = ctx->base.pipe;
+ unsigned i;
/* restore the state objects which are always required to be saved */
- pipe->bind_blend_state(pipe, ctx->blitter.saved_blend_state);
- pipe->bind_depth_stencil_alpha_state(pipe, ctx->blitter.saved_dsa_state);
- pipe->bind_rasterizer_state(pipe, ctx->blitter.saved_rs_state);
- pipe->bind_fs_state(pipe, ctx->blitter.saved_fs);
- pipe->bind_vs_state(pipe, ctx->blitter.saved_vs);
- pipe->bind_vertex_elements_state(pipe, ctx->blitter.saved_velem_state);
+ pipe->bind_blend_state(pipe, ctx->base.saved_blend_state);
+ pipe->bind_depth_stencil_alpha_state(pipe, ctx->base.saved_dsa_state);
+ pipe->bind_rasterizer_state(pipe, ctx->base.saved_rs_state);
+ pipe->bind_fs_state(pipe, ctx->base.saved_fs);
+ pipe->bind_vs_state(pipe, ctx->base.saved_vs);
+ pipe->bind_vertex_elements_state(pipe, ctx->base.saved_velem_state);
- ctx->blitter.saved_blend_state = INVALID_PTR;
- ctx->blitter.saved_dsa_state = INVALID_PTR;
- ctx->blitter.saved_rs_state = INVALID_PTR;
- ctx->blitter.saved_fs = INVALID_PTR;
- ctx->blitter.saved_vs = INVALID_PTR;
- ctx->blitter.saved_velem_state = INVALID_PTR;
+ ctx->base.saved_blend_state = INVALID_PTR;
+ ctx->base.saved_dsa_state = INVALID_PTR;
+ ctx->base.saved_rs_state = INVALID_PTR;
+ ctx->base.saved_fs = INVALID_PTR;
+ ctx->base.saved_vs = INVALID_PTR;
+ ctx->base.saved_velem_state = INVALID_PTR;
- pipe->set_stencil_ref(pipe, &ctx->blitter.saved_stencil_ref);
+ pipe->set_stencil_ref(pipe, &ctx->base.saved_stencil_ref);
- pipe->set_viewport_state(pipe, &ctx->blitter.saved_viewport);
- pipe->set_clip_state(pipe, &ctx->blitter.saved_clip);
+ pipe->set_viewport_state(pipe, &ctx->base.saved_viewport);
+ pipe->set_clip_state(pipe, &ctx->base.saved_clip);
/* restore the state objects which are required to be saved before copy/fill
*/
- if (ctx->blitter.saved_fb_state.nr_cbufs != ~0) {
- pipe->set_framebuffer_state(pipe, &ctx->blitter.saved_fb_state);
- ctx->blitter.saved_fb_state.nr_cbufs = ~0;
+ if (ctx->base.saved_fb_state.nr_cbufs != ~0) {
+ pipe->set_framebuffer_state(pipe, &ctx->base.saved_fb_state);
+ util_unreference_framebuffer_state(&ctx->base.saved_fb_state);
+ ctx->base.saved_fb_state.nr_cbufs = ~0;
}
- if (ctx->blitter.saved_num_sampler_states != ~0) {
+ if (ctx->base.saved_num_sampler_states != ~0) {
pipe->bind_fragment_sampler_states(pipe,
- ctx->blitter.saved_num_sampler_states,
- ctx->blitter.saved_sampler_states);
- ctx->blitter.saved_num_sampler_states = ~0;
+ ctx->base.saved_num_sampler_states,
+ ctx->base.saved_sampler_states);
+ ctx->base.saved_num_sampler_states = ~0;
}
- if (ctx->blitter.saved_num_sampler_views != ~0) {
+ if (ctx->base.saved_num_sampler_views != ~0) {
pipe->set_fragment_sampler_views(pipe,
- ctx->blitter.saved_num_sampler_views,
- ctx->blitter.saved_sampler_views);
- ctx->blitter.saved_num_sampler_views = ~0;
+ ctx->base.saved_num_sampler_views,
+ ctx->base.saved_sampler_views);
+
+ for (i = 0; i < ctx->base.saved_num_sampler_views; i++)
+ pipe_sampler_view_reference(&ctx->base.saved_sampler_views[i],
+ NULL);
+
+ ctx->base.saved_num_sampler_views = ~0;
}
- if (ctx->blitter.saved_num_vertex_buffers != ~0) {
+ if (ctx->base.saved_num_vertex_buffers != ~0) {
pipe->set_vertex_buffers(pipe,
- ctx->blitter.saved_num_vertex_buffers,
- ctx->blitter.saved_vertex_buffers);
- ctx->blitter.saved_num_vertex_buffers = ~0;
+ ctx->base.saved_num_vertex_buffers,
+ ctx->base.saved_vertex_buffers);
+
+ for (i = 0; i < ctx->base.saved_num_vertex_buffers; i++) {
+ if (ctx->base.saved_vertex_buffers[i].buffer) {
+ pipe_resource_reference(&ctx->base.saved_vertex_buffers[i].buffer,
+ NULL);
+ }
+ }
+ ctx->base.saved_num_vertex_buffers = ~0;
}
}
static void blitter_set_rectangle(struct blitter_context_priv *ctx,
unsigned x1, unsigned y1,
unsigned x2, unsigned y2,
- unsigned width, unsigned height,
float depth)
{
int i;
/* set vertex positions */
- ctx->vertices[0][0][0] = (float)x1 / width * 2.0f - 1.0f; /*v0.x*/
- ctx->vertices[0][0][1] = (float)y1 / height * 2.0f - 1.0f; /*v0.y*/
+ ctx->vertices[0][0][0] = (float)x1 / ctx->dst_width * 2.0f - 1.0f; /*v0.x*/
+ ctx->vertices[0][0][1] = (float)y1 / ctx->dst_height * 2.0f - 1.0f; /*v0.y*/
- ctx->vertices[1][0][0] = (float)x2 / width * 2.0f - 1.0f; /*v1.x*/
- ctx->vertices[1][0][1] = (float)y1 / height * 2.0f - 1.0f; /*v1.y*/
+ ctx->vertices[1][0][0] = (float)x2 / ctx->dst_width * 2.0f - 1.0f; /*v1.x*/
+ ctx->vertices[1][0][1] = (float)y1 / ctx->dst_height * 2.0f - 1.0f; /*v1.y*/
- ctx->vertices[2][0][0] = (float)x2 / width * 2.0f - 1.0f; /*v2.x*/
- ctx->vertices[2][0][1] = (float)y2 / height * 2.0f - 1.0f; /*v2.y*/
+ ctx->vertices[2][0][0] = (float)x2 / ctx->dst_width * 2.0f - 1.0f; /*v2.x*/
+ ctx->vertices[2][0][1] = (float)y2 / ctx->dst_height * 2.0f - 1.0f; /*v2.y*/
- ctx->vertices[3][0][0] = (float)x1 / width * 2.0f - 1.0f; /*v3.x*/
- ctx->vertices[3][0][1] = (float)y2 / height * 2.0f - 1.0f; /*v3.y*/
+ ctx->vertices[3][0][0] = (float)x1 / ctx->dst_width * 2.0f - 1.0f; /*v3.x*/
+ ctx->vertices[3][0][1] = (float)y2 / ctx->dst_height * 2.0f - 1.0f; /*v3.y*/
for (i = 0; i < 4; i++)
ctx->vertices[i][0][2] = depth; /*z*/
/* viewport */
- ctx->viewport.scale[0] = 0.5f * width;
- ctx->viewport.scale[1] = 0.5f * height;
+ ctx->viewport.scale[0] = 0.5f * ctx->dst_width;
+ ctx->viewport.scale[1] = 0.5f * ctx->dst_height;
ctx->viewport.scale[2] = 1.0f;
ctx->viewport.scale[3] = 1.0f;
- ctx->viewport.translate[0] = 0.5f * width;
- ctx->viewport.translate[1] = 0.5f * height;
+ ctx->viewport.translate[0] = 0.5f * ctx->dst_width;
+ ctx->viewport.translate[1] = 0.5f * ctx->dst_height;
ctx->viewport.translate[2] = 0.0f;
ctx->viewport.translate[3] = 0.0f;
- ctx->pipe->set_viewport_state(ctx->pipe, &ctx->viewport);
+ ctx->base.pipe->set_viewport_state(ctx->base.pipe, &ctx->viewport);
/* clip */
- ctx->pipe->set_clip_state(ctx->pipe, &ctx->clip);
+ ctx->base.pipe->set_clip_state(ctx->base.pipe, &ctx->clip);
}
static void blitter_set_clear_color(struct blitter_context_priv *ctx,
@@ -372,36 +401,72 @@ static void blitter_set_clear_color(struct blitter_context_priv *ctx,
{
int i;
- for (i = 0; i < 4; i++) {
- ctx->vertices[i][1][0] = rgba[0];
- ctx->vertices[i][1][1] = rgba[1];
- ctx->vertices[i][1][2] = rgba[2];
- ctx->vertices[i][1][3] = rgba[3];
+ if (rgba) {
+ for (i = 0; i < 4; i++) {
+ ctx->vertices[i][1][0] = rgba[0];
+ ctx->vertices[i][1][1] = rgba[1];
+ ctx->vertices[i][1][2] = rgba[2];
+ ctx->vertices[i][1][3] = rgba[3];
+ }
+ } else {
+ for (i = 0; i < 4; i++) {
+ ctx->vertices[i][1][0] = 0;
+ ctx->vertices[i][1][1] = 0;
+ ctx->vertices[i][1][2] = 0;
+ ctx->vertices[i][1][3] = 0;
+ }
}
}
-static void blitter_set_texcoords_2d(struct blitter_context_priv *ctx,
- struct pipe_surface *surf,
+static void get_texcoords(struct pipe_resource *src,
+ struct pipe_subresource subsrc,
unsigned x1, unsigned y1,
- unsigned x2, unsigned y2)
+ unsigned x2, unsigned y2,
+ boolean normalized, float out[4])
{
- int i;
- float s1 = x1 / (float)surf->width;
- float t1 = y1 / (float)surf->height;
- float s2 = x2 / (float)surf->width;
- float t2 = y2 / (float)surf->height;
-
- ctx->vertices[0][1][0] = s1; /*t0.s*/
- ctx->vertices[0][1][1] = t1; /*t0.t*/
+ if(normalized)
+ {
+ out[0] = x1 / (float)u_minify(src->width0, subsrc.level);
+ out[1] = y1 / (float)u_minify(src->height0, subsrc.level);
+ out[2] = x2 / (float)u_minify(src->width0, subsrc.level);
+ out[3] = y2 / (float)u_minify(src->height0, subsrc.level);
+ }
+ else
+ {
+ out[0] = x1;
+ out[1] = y1;
+ out[2] = x2;
+ out[3] = y2;
+ }
+}
- ctx->vertices[1][1][0] = s2; /*t1.s*/
- ctx->vertices[1][1][1] = t1; /*t1.t*/
+static void set_texcoords_in_vertices(const float coord[4],
+ float *out, unsigned stride)
+{
+ out[0] = coord[0]; /*t0.s*/
+ out[1] = coord[1]; /*t0.t*/
+ out += stride;
+ out[0] = coord[2]; /*t1.s*/
+ out[1] = coord[1]; /*t1.t*/
+ out += stride;
+ out[0] = coord[2]; /*t2.s*/
+ out[1] = coord[3]; /*t2.t*/
+ out += stride;
+ out[0] = coord[0]; /*t3.s*/
+ out[1] = coord[3]; /*t3.t*/
+}
- ctx->vertices[2][1][0] = s2; /*t2.s*/
- ctx->vertices[2][1][1] = t2; /*t2.t*/
+static void blitter_set_texcoords_2d(struct blitter_context_priv *ctx,
+ struct pipe_resource *src,
+ struct pipe_subresource subsrc,
+ unsigned x1, unsigned y1,
+ unsigned x2, unsigned y2)
+{
+ unsigned i;
+ float coord[4];
- ctx->vertices[3][1][0] = s1; /*t3.s*/
- ctx->vertices[3][1][1] = t2; /*t3.t*/
+ get_texcoords(src, subsrc, x1, y1, x2, y2, TRUE, coord);
+ set_texcoords_in_vertices(coord, &ctx->vertices[0][1][0], 8);
for (i = 0; i < 4; i++) {
ctx->vertices[i][1][2] = 0; /*r*/
@@ -410,42 +475,35 @@ static void blitter_set_texcoords_2d(struct blitter_context_priv *ctx,
}
static void blitter_set_texcoords_3d(struct blitter_context_priv *ctx,
- struct pipe_surface *surf,
+ struct pipe_resource *src,
+ struct pipe_subresource subsrc,
+ unsigned zslice,
unsigned x1, unsigned y1,
unsigned x2, unsigned y2)
{
int i;
- float depth = u_minify(surf->texture->depth0, surf->level);
- float r = surf->zslice / depth;
+ float r = zslice / (float)u_minify(src->depth0, subsrc.level);
- blitter_set_texcoords_2d(ctx, surf, x1, y1, x2, y2);
+ blitter_set_texcoords_2d(ctx, src, subsrc, x1, y1, x2, y2);
for (i = 0; i < 4; i++)
ctx->vertices[i][1][2] = r; /*r*/
}
static void blitter_set_texcoords_cube(struct blitter_context_priv *ctx,
- struct pipe_surface *surf,
+ struct pipe_resource *src,
+ struct pipe_subresource subsrc,
unsigned x1, unsigned y1,
unsigned x2, unsigned y2)
{
int i;
- float s1 = x1 / (float)surf->width;
- float t1 = y1 / (float)surf->height;
- float s2 = x2 / (float)surf->width;
- float t2 = y2 / (float)surf->height;
+ float coord[4];
float st[4][2];
- st[0][0] = s1;
- st[0][1] = t1;
- st[1][0] = s2;
- st[1][1] = t1;
- st[2][0] = s2;
- st[2][1] = t2;
- st[3][0] = s1;
- st[3][1] = t2;
+ get_texcoords(src, subsrc, x1, y1, x2, y2, TRUE, coord);
+ set_texcoords_in_vertices(coord, &st[0][0], 2);
- util_map_texcoords2d_onto_cubemap(surf->face,
+ util_map_texcoords2d_onto_cubemap(subsrc.face,
/* pointer, stride in floats */
&st[0][0], 2,
&ctx->vertices[0][1][0], 8);
@@ -454,9 +512,16 @@ static void blitter_set_texcoords_cube(struct blitter_context_priv *ctx,
ctx->vertices[i][1][3] = 1; /*q*/
}
+static void blitter_set_dst_dimensions(struct blitter_context_priv *ctx,
+ unsigned width, unsigned height)
+{
+ ctx->dst_width = width;
+ ctx->dst_height = height;
+}
+
static void blitter_draw_quad(struct blitter_context_priv *ctx)
{
- struct pipe_context *pipe = ctx->pipe;
+ struct pipe_context *pipe = ctx->base.pipe;
/* write vertices and draw them */
pipe_buffer_write(pipe, ctx->vbuf,
@@ -469,72 +534,79 @@ static void blitter_draw_quad(struct blitter_context_priv *ctx)
static INLINE
void **blitter_get_sampler_state(struct blitter_context_priv *ctx,
- int miplevel)
+ int miplevel, boolean normalized)
{
- struct pipe_context *pipe = ctx->pipe;
+ struct pipe_context *pipe = ctx->base.pipe;
struct pipe_sampler_state *sampler_state = &ctx->template_sampler_state;
assert(miplevel < PIPE_MAX_TEXTURE_LEVELS);
/* Create the sampler state on-demand. */
- if (!ctx->sampler_state[miplevel]) {
+ if (!ctx->sampler_state[miplevel * 2 + normalized]) {
sampler_state->lod_bias = miplevel;
sampler_state->min_lod = miplevel;
sampler_state->max_lod = miplevel;
+ sampler_state->normalized_coords = normalized;
- ctx->sampler_state[miplevel] = pipe->create_sampler_state(pipe,
+ ctx->sampler_state[miplevel * 2 + normalized] = pipe->create_sampler_state(pipe,
sampler_state);
}
/* Return void** so that it can be passed to bind_fragment_sampler_states
* directly. */
- return &ctx->sampler_state[miplevel];
+ return &ctx->sampler_state[miplevel * 2 + normalized];
}
static INLINE
void *blitter_get_fs_col(struct blitter_context_priv *ctx, unsigned num_cbufs)
{
- struct pipe_context *pipe = ctx->pipe;
- unsigned index = num_cbufs ? num_cbufs - 1 : 0;
+ struct pipe_context *pipe = ctx->base.pipe;
assert(num_cbufs <= PIPE_MAX_COLOR_BUFS);
- if (!ctx->fs_col[index])
- ctx->fs_col[index] =
+ if (!ctx->fs_col[num_cbufs])
+ ctx->fs_col[num_cbufs] =
util_make_fragment_clonecolor_shader(pipe, num_cbufs);
- return ctx->fs_col[index];
+ return ctx->fs_col[num_cbufs];
}
+/** Convert PIPE_TEXTURE_x to TGSI_TEXTURE_x */
+static unsigned
+pipe_tex_to_tgsi_tex(enum pipe_texture_target pipe_tex_target)
+{
+ switch (pipe_tex_target) {
+ case PIPE_TEXTURE_1D:
+ return TGSI_TEXTURE_1D;
+ case PIPE_TEXTURE_2D:
+ return TGSI_TEXTURE_2D;
+ case PIPE_TEXTURE_RECT:
+ return TGSI_TEXTURE_RECT;
+ case PIPE_TEXTURE_3D:
+ return TGSI_TEXTURE_3D;
+ case PIPE_TEXTURE_CUBE:
+ return TGSI_TEXTURE_CUBE;
+ default:
+ assert(0 && "unexpected texture target");
+ return TGSI_TEXTURE_UNKNOWN;
+ }
+}
+
+
static INLINE
void *blitter_get_fs_texfetch_col(struct blitter_context_priv *ctx,
unsigned tex_target)
{
- struct pipe_context *pipe = ctx->pipe;
+ struct pipe_context *pipe = ctx->base.pipe;
assert(tex_target < PIPE_MAX_TEXTURE_TYPES);
/* Create the fragment shader on-demand. */
if (!ctx->fs_texfetch_col[tex_target]) {
- switch (tex_target) {
- case PIPE_TEXTURE_1D:
- ctx->fs_texfetch_col[PIPE_TEXTURE_1D] =
- util_make_fragment_tex_shader(pipe, TGSI_TEXTURE_1D);
- break;
- case PIPE_TEXTURE_2D:
- ctx->fs_texfetch_col[PIPE_TEXTURE_2D] =
- util_make_fragment_tex_shader(pipe, TGSI_TEXTURE_2D);
- break;
- case PIPE_TEXTURE_3D:
- ctx->fs_texfetch_col[PIPE_TEXTURE_3D] =
- util_make_fragment_tex_shader(pipe, TGSI_TEXTURE_3D);
- break;
- case PIPE_TEXTURE_CUBE:
- ctx->fs_texfetch_col[PIPE_TEXTURE_CUBE] =
- util_make_fragment_tex_shader(pipe, TGSI_TEXTURE_CUBE);
- break;
- default:;
- }
+ unsigned tgsi_tex = pipe_tex_to_tgsi_tex(tex_target);
+
+ ctx->fs_texfetch_col[tex_target] =
+ util_make_fragment_tex_shader(pipe, tgsi_tex, TGSI_INTERPOLATE_LINEAR);
}
return ctx->fs_texfetch_col[tex_target];
@@ -544,36 +616,47 @@ static INLINE
void *blitter_get_fs_texfetch_depth(struct blitter_context_priv *ctx,
unsigned tex_target)
{
- struct pipe_context *pipe = ctx->pipe;
+ struct pipe_context *pipe = ctx->base.pipe;
assert(tex_target < PIPE_MAX_TEXTURE_TYPES);
/* Create the fragment shader on-demand. */
if (!ctx->fs_texfetch_depth[tex_target]) {
- switch (tex_target) {
- case PIPE_TEXTURE_1D:
- ctx->fs_texfetch_depth[PIPE_TEXTURE_1D] =
- util_make_fragment_tex_shader_writedepth(pipe, TGSI_TEXTURE_1D);
- break;
- case PIPE_TEXTURE_2D:
- ctx->fs_texfetch_depth[PIPE_TEXTURE_2D] =
- util_make_fragment_tex_shader_writedepth(pipe, TGSI_TEXTURE_2D);
- break;
- case PIPE_TEXTURE_3D:
- ctx->fs_texfetch_depth[PIPE_TEXTURE_3D] =
- util_make_fragment_tex_shader_writedepth(pipe, TGSI_TEXTURE_3D);
- break;
- case PIPE_TEXTURE_CUBE:
- ctx->fs_texfetch_depth[PIPE_TEXTURE_CUBE] =
- util_make_fragment_tex_shader_writedepth(pipe,TGSI_TEXTURE_CUBE);
- break;
- default:;
- }
+ unsigned tgsi_tex = pipe_tex_to_tgsi_tex(tex_target);
+
+ ctx->fs_texfetch_depth[tex_target] =
+ util_make_fragment_tex_shader_writedepth(pipe, tgsi_tex,
+ TGSI_INTERPOLATE_LINEAR);
}
return ctx->fs_texfetch_depth[tex_target];
}
+static void blitter_draw_rectangle(struct blitter_context *blitter,
+ unsigned x1, unsigned y1,
+ unsigned x2, unsigned y2,
+ float depth,
+ enum blitter_attrib_type type,
+ const float attrib[4])
+{
+ struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
+
+ switch (type) {
+ case UTIL_BLITTER_ATTRIB_COLOR:
+ blitter_set_clear_color(ctx, attrib);
+ break;
+
+ case UTIL_BLITTER_ATTRIB_TEXCOORD:
+ set_texcoords_in_vertices(attrib, &ctx->vertices[0][1][0], 8);
+ break;
+
+ default:;
+ }
+
+ blitter_set_rectangle(ctx, x1, y1, x2, y2, depth);
+ blitter_draw_quad(ctx);
+}
+
void util_blitter_clear(struct blitter_context *blitter,
unsigned width, unsigned height,
unsigned num_cbufs,
@@ -582,7 +665,7 @@ void util_blitter_clear(struct blitter_context *blitter,
double depth, unsigned stencil)
{
struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
- struct pipe_context *pipe = ctx->pipe;
+ struct pipe_context *pipe = ctx->base.pipe;
struct pipe_stencil_ref sr = { { 0 } };
assert(num_cbufs <= PIPE_MAX_COLOR_BUFS);
@@ -595,11 +678,19 @@ void util_blitter_clear(struct blitter_context *blitter,
else
pipe->bind_blend_state(pipe, ctx->blend_keep_color);
- if (clear_buffers & PIPE_CLEAR_DEPTHSTENCIL) {
+ if ((clear_buffers & PIPE_CLEAR_DEPTHSTENCIL) == PIPE_CLEAR_DEPTHSTENCIL) {
sr.ref_value[0] = stencil & 0xff;
pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_stencil);
pipe->set_stencil_ref(pipe, &sr);
}
+ else if (clear_buffers & PIPE_CLEAR_DEPTH) {
+ pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_keep_stencil);
+ }
+ else if (clear_buffers & PIPE_CLEAR_STENCIL) {
+ sr.ref_value[0] = stencil & 0xff;
+ pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_write_stencil);
+ pipe->set_stencil_ref(pipe, &sr);
+ }
else
pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil);
@@ -608,244 +699,284 @@ void util_blitter_clear(struct blitter_context *blitter,
pipe->bind_fs_state(pipe, blitter_get_fs_col(ctx, num_cbufs));
pipe->bind_vs_state(pipe, ctx->vs_col);
- blitter_set_clear_color(ctx, rgba);
- blitter_set_rectangle(ctx, 0, 0, width, height, width, height, depth);
- blitter_draw_quad(ctx);
+ blitter_set_dst_dimensions(ctx, width, height);
+ blitter->draw_rectangle(blitter, 0, 0, width, height, depth,
+ UTIL_BLITTER_ATTRIB_COLOR, rgba);
blitter_restore_CSOs(ctx);
}
-static boolean
-is_overlap(unsigned sx1, unsigned sx2, unsigned sy1, unsigned sy2,
- unsigned dx1, unsigned dx2, unsigned dy1, unsigned dy2)
+static
+boolean is_overlap(unsigned sx1, unsigned sx2, unsigned sy1, unsigned sy2,
+ unsigned dx1, unsigned dx2, unsigned dy1, unsigned dy2)
{
- if (sx1 >= dx2 || sx2 <= dx1 || sy1 >= dy2 || sy2 <= dy1) {
- return FALSE;
- } else {
- return TRUE;
- }
+ return sx1 < dx2 && sx2 > dx1 && sy1 < dy2 && sy2 > dy1;
}
-static void util_blitter_do_copy(struct blitter_context *blitter,
- struct pipe_surface *dst,
- unsigned dstx, unsigned dsty,
- struct pipe_surface *src,
- unsigned srcx, unsigned srcy,
- unsigned width, unsigned height,
- boolean is_depth)
+void util_blitter_copy_region(struct blitter_context *blitter,
+ struct pipe_resource *dst,
+ struct pipe_subresource subdst,
+ unsigned dstx, unsigned dsty, unsigned dstz,
+ struct pipe_resource *src,
+ struct pipe_subresource subsrc,
+ unsigned srcx, unsigned srcy, unsigned srcz,
+ unsigned width, unsigned height,
+ boolean ignore_stencil)
{
struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
- struct pipe_context *pipe = ctx->pipe;
+ struct pipe_context *pipe = ctx->base.pipe;
+ struct pipe_screen *screen = pipe->screen;
+ struct pipe_surface *dstsurf;
struct pipe_framebuffer_state fb_state;
struct pipe_sampler_view viewTempl, *view;
+ unsigned bind;
+ boolean is_stencil, is_depth;
+ boolean normalized;
+
+ /* Give up if textures are not set. */
+ assert(dst && src);
+ if (!dst || !src)
+ return;
+ /* Sanity checks. */
+ if (dst == src) {
+ assert(!is_overlap(srcx, srcx + width, srcy, srcy + height,
+ dstx, dstx + width, dsty, dsty + height));
+ } else {
+ assert(dst->format == src->format);
+ }
+ assert(src->target < PIPE_MAX_TEXTURE_TYPES);
+
+ /* Is this a ZS format? */
+ is_depth = util_format_get_component_bits(src->format, UTIL_FORMAT_COLORSPACE_ZS, 0) != 0;
+ is_stencil = util_format_get_component_bits(src->format, UTIL_FORMAT_COLORSPACE_ZS, 1) != 0;
+
+ if (is_depth || is_stencil)
+ bind = PIPE_BIND_DEPTH_STENCIL;
+ else
+ bind = PIPE_BIND_RENDER_TARGET;
+
+ /* Check if we can sample from and render to the surfaces. */
+ /* (assuming copying a stencil buffer is not possible) */
+ if ((!ignore_stencil && is_stencil) ||
+ !screen->is_format_supported(screen, dst->format, dst->target,
+ dst->nr_samples, bind, 0) ||
+ !screen->is_format_supported(screen, src->format, src->target,
+ src->nr_samples, PIPE_BIND_SAMPLER_VIEW, 0)) {
+ util_resource_copy_region(pipe, dst, subdst, dstx, dsty, dstz,
+ src, subsrc, srcx, srcy, srcz, width, height);
+ return;
+ }
+
+ /* Get surfaces. */
+ dstsurf = screen->get_tex_surface(screen, dst,
+ subdst.face, subdst.level, dstz,
+ bind);
+
+ /* Check whether the states are properly saved. */
+ blitter_check_saved_CSOs(ctx);
assert(blitter->saved_fb_state.nr_cbufs != ~0);
assert(blitter->saved_num_sampler_views != ~0);
assert(blitter->saved_num_sampler_states != ~0);
- assert(src->texture->target < PIPE_MAX_TEXTURE_TYPES);
- /* bind CSOs */
- fb_state.width = dst->width;
- fb_state.height = dst->height;
+ /* Initialize framebuffer state. */
+ fb_state.width = dstsurf->width;
+ fb_state.height = dstsurf->height;
if (is_depth) {
pipe->bind_blend_state(pipe, ctx->blend_keep_color);
pipe->bind_depth_stencil_alpha_state(pipe,
ctx->dsa_write_depth_keep_stencil);
pipe->bind_fs_state(pipe,
- blitter_get_fs_texfetch_depth(ctx, src->texture->target));
+ blitter_get_fs_texfetch_depth(ctx, src->target));
fb_state.nr_cbufs = 0;
- fb_state.zsbuf = dst;
+ fb_state.zsbuf = dstsurf;
} else {
pipe->bind_blend_state(pipe, ctx->blend_write_color);
pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil);
pipe->bind_fs_state(pipe,
- blitter_get_fs_texfetch_col(ctx, src->texture->target));
+ blitter_get_fs_texfetch_col(ctx, src->target));
fb_state.nr_cbufs = 1;
- fb_state.cbufs[0] = dst;
+ fb_state.cbufs[0] = dstsurf;
fb_state.zsbuf = 0;
}
- u_sampler_view_default_template(&viewTempl,
- src->texture,
- src->texture->format);
- view = pipe->create_sampler_view(pipe,
- src->texture,
- &viewTempl);
+ normalized = src->target != PIPE_TEXTURE_RECT;
- if (ctx->sampler_view) {
- pipe_sampler_view_reference(&ctx->sampler_view, NULL);
- }
- ctx->sampler_view = view;
+ /* Initialize sampler view. */
+ u_sampler_view_default_template(&viewTempl, src, src->format);
+ view = pipe->create_sampler_view(pipe, src, &viewTempl);
+ /* Set rasterizer state, shaders, and textures. */
pipe->bind_rasterizer_state(pipe, ctx->rs_state);
pipe->bind_vs_state(pipe, ctx->vs_tex);
pipe->bind_fragment_sampler_states(pipe, 1,
- blitter_get_sampler_state(ctx, src->level));
+ blitter_get_sampler_state(ctx, subsrc.level, normalized));
pipe->bind_vertex_elements_state(pipe, ctx->velem_state);
pipe->set_fragment_sampler_views(pipe, 1, &view);
pipe->set_framebuffer_state(pipe, &fb_state);
- /* set texture coordinates */
- switch (src->texture->target) {
+ blitter_set_dst_dimensions(ctx, dstsurf->width, dstsurf->height);
+
+ switch (src->target) {
+ /* Draw the quad with the draw_rectangle callback. */
case PIPE_TEXTURE_1D:
case PIPE_TEXTURE_2D:
- blitter_set_texcoords_2d(ctx, src, srcx, srcy,
- srcx+width, srcy+height);
+ case PIPE_TEXTURE_RECT:
+ {
+ /* Set texture coordinates. */
+ float coord[4];
+ get_texcoords(src, subsrc, srcx, srcy,
+ srcx+width, srcy+height, normalized, coord);
+
+ /* Draw. */
+ blitter->draw_rectangle(blitter, dstx, dsty, dstx+width, dsty+height, 0,
+ UTIL_BLITTER_ATTRIB_TEXCOORD, coord);
+ }
break;
+
+ /* Draw the quad with the generic codepath. */
case PIPE_TEXTURE_3D:
- blitter_set_texcoords_3d(ctx, src, srcx, srcy,
- srcx+width, srcy+height);
- break;
case PIPE_TEXTURE_CUBE:
- blitter_set_texcoords_cube(ctx, src, srcx, srcy,
- srcx+width, srcy+height);
+ /* Set texture coordinates. */
+ if (src->target == PIPE_TEXTURE_3D)
+ blitter_set_texcoords_3d(ctx, src, subsrc, srcz,
+ srcx, srcy, srcx+width, srcy+height);
+ else
+ blitter_set_texcoords_cube(ctx, src, subsrc,
+ srcx, srcy, srcx+width, srcy+height);
+
+ /* Draw. */
+ blitter_set_rectangle(ctx, dstx, dsty, dstx+width, dsty+height, 0);
+ blitter_draw_quad(ctx);
break;
+
default:
assert(0);
+ return;
}
- blitter_set_rectangle(ctx, dstx, dsty, dstx+width, dsty+height, dst->width, dst->height, 0);
- blitter_draw_quad(ctx);
+ blitter_restore_CSOs(ctx);
+ pipe_surface_reference(&dstsurf, NULL);
+ pipe_sampler_view_reference(&view, NULL);
}
-static void util_blitter_overlap_copy(struct blitter_context *blitter,
- struct pipe_surface *dst,
- unsigned dstx, unsigned dsty,
- struct pipe_surface *src,
- unsigned srcx, unsigned srcy,
- unsigned width, unsigned height)
+/* Clear a region of a color surface to a constant value. */
+void util_blitter_clear_render_target(struct blitter_context *blitter,
+ struct pipe_surface *dstsurf,
+ const float *rgba,
+ unsigned dstx, unsigned dsty,
+ unsigned width, unsigned height)
{
struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
- struct pipe_context *pipe = ctx->pipe;
- struct pipe_screen *screen = pipe->screen;
+ struct pipe_context *pipe = ctx->base.pipe;
+ struct pipe_framebuffer_state fb_state;
- struct pipe_resource texTemp;
- struct pipe_resource *texture;
- struct pipe_surface *tex_surf;
+ assert(dstsurf->texture);
+ if (!dstsurf->texture)
+ return;
- /* check whether the states are properly saved */
+ /* check the saved state */
blitter_check_saved_CSOs(ctx);
+ assert(blitter->saved_fb_state.nr_cbufs != ~0);
- memset(&texTemp, 0, sizeof(texTemp));
- texTemp.target = PIPE_TEXTURE_2D;
- texTemp.format = dst->texture->format; /* XXX verify supported by driver! */
- texTemp.last_level = 0;
- texTemp.width0 = width;
- texTemp.height0 = height;
- texTemp.depth0 = 1;
+ /* bind CSOs */
+ pipe->bind_blend_state(pipe, ctx->blend_write_color);
+ pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil);
+ pipe->bind_rasterizer_state(pipe, ctx->rs_state);
+ pipe->bind_fs_state(pipe, blitter_get_fs_col(ctx, 1));
+ pipe->bind_vs_state(pipe, ctx->vs_col);
+ pipe->bind_vertex_elements_state(pipe, ctx->velem_state);
- texture = screen->resource_create(screen, &texTemp);
- if (!texture)
- return;
+ /* set a framebuffer state */
+ fb_state.width = dstsurf->width;
+ fb_state.height = dstsurf->height;
+ fb_state.nr_cbufs = 1;
+ fb_state.cbufs[0] = dstsurf;
+ fb_state.zsbuf = 0;
+ pipe->set_framebuffer_state(pipe, &fb_state);
- tex_surf = screen->get_tex_surface(screen, texture, 0, 0, 0,
- PIPE_BIND_BLIT_SOURCE |
- PIPE_BIND_BLIT_DESTINATION);
-
- /* blit from the src to the temp */
- util_blitter_do_copy(blitter, tex_surf, 0, 0,
- src, srcx, srcy,
- width, height,
- FALSE);
- util_blitter_do_copy(blitter, dst, dstx, dsty,
- tex_surf, 0, 0,
- width, height,
- FALSE);
- pipe_surface_reference(&tex_surf, NULL);
- pipe_resource_reference(&texture, NULL);
+ blitter_set_dst_dimensions(ctx, dstsurf->width, dstsurf->height);
+ blitter->draw_rectangle(blitter, dstx, dsty, dstx+width, dsty+height, 0,
+ UTIL_BLITTER_ATTRIB_COLOR, rgba);
blitter_restore_CSOs(ctx);
}
-void util_blitter_copy(struct blitter_context *blitter,
- struct pipe_surface *dst,
- unsigned dstx, unsigned dsty,
- struct pipe_surface *src,
- unsigned srcx, unsigned srcy,
- unsigned width, unsigned height,
- boolean ignore_stencil)
+/* Clear a region of a depth stencil surface. */
+void util_blitter_clear_depth_stencil(struct blitter_context *blitter,
+ struct pipe_surface *dstsurf,
+ unsigned clear_flags,
+ double depth,
+ unsigned stencil,
+ unsigned dstx, unsigned dsty,
+ unsigned width, unsigned height)
{
struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
- struct pipe_context *pipe = ctx->pipe;
- struct pipe_screen *screen = pipe->screen;
- boolean is_stencil, is_depth;
- unsigned dst_tex_usage;
+ struct pipe_context *pipe = ctx->base.pipe;
+ struct pipe_framebuffer_state fb_state;
+ struct pipe_stencil_ref sr = { { 0 } };
- /* give up if textures are not set */
- assert(dst->texture && src->texture);
- if (!dst->texture || !src->texture)
+ assert(dstsurf->texture);
+ if (!dstsurf->texture)
return;
- if (dst->texture == src->texture) {
- if (is_overlap(srcx, srcx + width, srcy, srcy + height,
- dstx, dstx + width, dsty, dsty + height)) {
- util_blitter_overlap_copy(blitter, dst, dstx, dsty, src, srcx, srcy,
- width, height);
- return;
- }
- }
-
- is_depth = util_format_get_component_bits(src->format, UTIL_FORMAT_COLORSPACE_ZS, 0) != 0;
- is_stencil = util_format_get_component_bits(src->format, UTIL_FORMAT_COLORSPACE_ZS, 1) != 0;
- dst_tex_usage = is_depth || is_stencil ? PIPE_BIND_DEPTH_STENCIL :
- PIPE_BIND_RENDER_TARGET;
+ /* check the saved state */
+ blitter_check_saved_CSOs(ctx);
+ assert(blitter->saved_fb_state.nr_cbufs != ~0);
- /* check if we can sample from and render to the surfaces */
- /* (assuming copying a stencil buffer is not possible) */
- if ((!ignore_stencil && is_stencil) ||
- !screen->is_format_supported(screen, dst->format, dst->texture->target,
- dst_tex_usage, 0) ||
- !screen->is_format_supported(screen, src->format, src->texture->target,
- PIPE_BIND_SAMPLER_VIEW, 0)) {
- util_surface_copy(pipe, FALSE, dst, dstx, dsty, src, srcx, srcy,
- width, height);
- return;
+ /* bind CSOs */
+ pipe->bind_blend_state(pipe, ctx->blend_keep_color);
+ if ((clear_flags & PIPE_CLEAR_DEPTHSTENCIL) == PIPE_CLEAR_DEPTHSTENCIL) {
+ sr.ref_value[0] = stencil & 0xff;
+ pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_stencil);
+ pipe->set_stencil_ref(pipe, &sr);
+ }
+ else if (clear_flags & PIPE_CLEAR_DEPTH) {
+ pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_keep_stencil);
+ }
+ else if (clear_flags & PIPE_CLEAR_STENCIL) {
+ sr.ref_value[0] = stencil & 0xff;
+ pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_write_stencil);
+ pipe->set_stencil_ref(pipe, &sr);
}
+ else
+ /* hmm that should be illegal probably, or make it a no-op somewhere */
+ pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil);
- /* check whether the states are properly saved */
- blitter_check_saved_CSOs(ctx);
- util_blitter_do_copy(blitter,
- dst, dstx, dsty,
- src, srcx, srcy,
- width, height, is_depth);
+ pipe->bind_rasterizer_state(pipe, ctx->rs_state);
+ pipe->bind_fs_state(pipe, blitter_get_fs_col(ctx, 0));
+ pipe->bind_vs_state(pipe, ctx->vs_col);
+ pipe->bind_vertex_elements_state(pipe, ctx->velem_state);
+
+ /* set a framebuffer state */
+ fb_state.width = dstsurf->width;
+ fb_state.height = dstsurf->height;
+ fb_state.nr_cbufs = 0;
+ fb_state.cbufs[0] = 0;
+ fb_state.zsbuf = dstsurf;
+ pipe->set_framebuffer_state(pipe, &fb_state);
+
+ blitter_set_dst_dimensions(ctx, dstsurf->width, dstsurf->height);
+ blitter->draw_rectangle(blitter, dstx, dsty, dstx+width, dsty+height, depth,
+ UTIL_BLITTER_ATTRIB_NONE, NULL);
blitter_restore_CSOs(ctx);
}
-void util_blitter_fill(struct blitter_context *blitter,
- struct pipe_surface *dst,
- unsigned dstx, unsigned dsty,
- unsigned width, unsigned height,
- unsigned value)
+/* draw a rectangle across a region using a custom dsa stage - for r600g */
+void util_blitter_custom_depth_stencil(struct blitter_context *blitter,
+ struct pipe_surface *zsurf,
+ struct pipe_surface *cbsurf,
+ void *dsa_stage, float depth)
{
struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
- struct pipe_context *pipe = ctx->pipe;
- struct pipe_screen *screen = pipe->screen;
+ struct pipe_context *pipe = ctx->base.pipe;
struct pipe_framebuffer_state fb_state;
- float rgba[4];
- ubyte ub_rgba[4] = {0};
- union util_color color;
- int i;
-
- assert(dst->texture);
- if (!dst->texture)
- return;
- /* check if we can render to the surface */
- if (util_format_is_depth_or_stencil(dst->format) || /* unlikely, but you never know */
- !screen->is_format_supported(screen, dst->format, dst->texture->target,
- PIPE_BIND_RENDER_TARGET, 0)) {
- util_surface_fill(pipe, dst, dstx, dsty, width, height, value);
+ assert(zsurf->texture);
+ if (!zsurf->texture)
return;
- }
-
- /* unpack the color */
- color.ui = value;
- util_unpack_color_ub(dst->format, &color,
- ub_rgba, ub_rgba+1, ub_rgba+2, ub_rgba+3);
- for (i = 0; i < 4; i++)
- rgba[i] = ubyte_to_float(ub_rgba[i]);
/* check the saved state */
blitter_check_saved_CSOs(ctx);
@@ -853,22 +984,38 @@ void util_blitter_fill(struct blitter_context *blitter,
/* bind CSOs */
pipe->bind_blend_state(pipe, ctx->blend_write_color);
- pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil);
+ pipe->bind_depth_stencil_alpha_state(pipe, dsa_stage);
+
pipe->bind_rasterizer_state(pipe, ctx->rs_state);
- pipe->bind_fs_state(pipe, blitter_get_fs_col(ctx, 1));
+ pipe->bind_fs_state(pipe, blitter_get_fs_col(ctx, 0));
pipe->bind_vs_state(pipe, ctx->vs_col);
pipe->bind_vertex_elements_state(pipe, ctx->velem_state);
/* set a framebuffer state */
- fb_state.width = dst->width;
- fb_state.height = dst->height;
+ fb_state.width = zsurf->width;
+ fb_state.height = zsurf->height;
fb_state.nr_cbufs = 1;
- fb_state.cbufs[0] = dst;
- fb_state.zsbuf = 0;
+ if (cbsurf) {
+ fb_state.cbufs[0] = cbsurf;
+ fb_state.nr_cbufs = 1;
+ } else {
+ fb_state.cbufs[0] = NULL;
+ fb_state.nr_cbufs = 0;
+ }
+ fb_state.zsbuf = zsurf;
pipe->set_framebuffer_state(pipe, &fb_state);
- blitter_set_clear_color(ctx, rgba);
- blitter_set_rectangle(ctx, 0, 0, width, height, dst->width, dst->height, 0);
- blitter_draw_quad(ctx);
+ blitter_set_dst_dimensions(ctx, zsurf->width, zsurf->height);
+ blitter->draw_rectangle(blitter, 0, 0, zsurf->width, zsurf->height, depth,
+ UTIL_BLITTER_ATTRIB_NONE, NULL);
blitter_restore_CSOs(ctx);
}
+
+/* flush a region of a depth stencil surface for r300g */
+void util_blitter_flush_depth_stencil(struct blitter_context *blitter,
+ struct pipe_surface *dstsurf)
+{
+ struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
+ util_blitter_custom_depth_stencil(blitter, dstsurf, NULL,
+ ctx->dsa_flush_depth_stencil, 0.0f);
+}
diff --git a/src/gallium/auxiliary/util/u_blitter.h b/src/gallium/auxiliary/util/u_blitter.h
index f6e3ce4874e..f9f96f25c77 100644
--- a/src/gallium/auxiliary/util/u_blitter.h
+++ b/src/gallium/auxiliary/util/u_blitter.h
@@ -27,6 +27,8 @@
#ifndef U_BLITTER_H
#define U_BLITTER_H
+#include "util/u_framebuffer.h"
+#include "util/u_inlines.h"
#include "util/u_memory.h"
#include "pipe/p_state.h"
@@ -38,9 +40,48 @@ extern "C" {
struct pipe_context;
+enum blitter_attrib_type {
+ UTIL_BLITTER_ATTRIB_NONE,
+ UTIL_BLITTER_ATTRIB_COLOR,
+ UTIL_BLITTER_ATTRIB_TEXCOORD
+};
+
struct blitter_context
{
+ /**
+ * Draw a rectangle.
+ *
+ * \param x1 An X coordinate of the top-left corner.
+ * \param y1 A Y coordinate of the top-left corner.
+ * \param x2 An X coordinate of the bottom-right corner.
+ * \param y2 A Y coordinate of the bottom-right corner.
+ * \param depth A depth which the rectangle is rendered at.
+ *
+ * \param type Semantics of the attributes "attrib".
+ * If type is UTIL_BLITTER_ATTRIB_NONE, ignore them.
+ * If type is UTIL_BLITTER_ATTRIB_COLOR, the attributes
+ * make up a constant RGBA color, and should go to the COLOR0
+ * varying slot of a fragment shader.
+ * If type is UTIL_BLITTER_ATTRIB_TEXCOORD, {a1, a2} and
+ * {a3, a4} specify top-left and bottom-right texture
+ * coordinates of the rectangle, respectively, and should go
+ * to the GENERIC0 varying slot of a fragment shader.
+ *
+ * \param attrib See type.
+ *
+ * \note A driver may optionally override this callback to implement
+ * a specialized hardware path for drawing a rectangle, e.g. using
+ * a rectangular point sprite.
+ */
+ void (*draw_rectangle)(struct blitter_context *blitter,
+ unsigned x1, unsigned y1, unsigned x2, unsigned y2,
+ float depth,
+ enum blitter_attrib_type type,
+ const float attrib[4]);
+
/* Private members, really. */
+ struct pipe_context *pipe; /**< pipe context */
+
void *saved_blend_state; /**< blend state */
void *saved_dsa_state; /**< depth stencil alpha state */
void *saved_velem_state; /**< vertex elements state */
@@ -72,6 +113,15 @@ struct blitter_context *util_blitter_create(struct pipe_context *pipe);
*/
void util_blitter_destroy(struct blitter_context *blitter);
+/**
+ * Return the pipe context associated with a blitter context.
+ */
+static INLINE
+struct pipe_context *util_blitter_get_pipe(struct blitter_context *blitter)
+{
+ return blitter->pipe;
+}
+
/*
* These CSOs must be saved before any of the following functions is called:
* - blend state
@@ -112,52 +162,56 @@ void util_blitter_clear(struct blitter_context *blitter,
* - fragment sampler states
* - fragment sampler textures
*/
-void util_blitter_copy(struct blitter_context *blitter,
- struct pipe_surface *dst,
- unsigned dstx, unsigned dsty,
- struct pipe_surface *src,
- unsigned srcx, unsigned srcy,
- unsigned width, unsigned height,
- boolean ignore_stencil);
+void util_blitter_copy_region(struct blitter_context *blitter,
+ struct pipe_resource *dst,
+ struct pipe_subresource subdst,
+ unsigned dstx, unsigned dsty, unsigned dstz,
+ struct pipe_resource *src,
+ struct pipe_subresource subsrc,
+ unsigned srcx, unsigned srcy, unsigned srcz,
+ unsigned width, unsigned height,
+ boolean ignore_stencil);
/**
- * Fill a region of a surface with a constant value.
- *
- * If the surface cannot be rendered to or it's a depth-stencil format,
- * a software fallback path is taken.
+ * Clear a region of a (color) surface to a constant value.
*
* These states must be saved in the blitter in addition to the state objects
* already required to be saved:
* - framebuffer state
*/
-void util_blitter_fill(struct blitter_context *blitter,
- struct pipe_surface *dst,
- unsigned dstx, unsigned dsty,
- unsigned width, unsigned height,
- unsigned value);
+void util_blitter_clear_render_target(struct blitter_context *blitter,
+ struct pipe_surface *dst,
+ const float *rgba,
+ unsigned dstx, unsigned dsty,
+ unsigned width, unsigned height);
/**
- * Copy all pixels from one surface to another.
+ * Clear a region of a depth-stencil surface, both stencil and depth
+ * or only one of them if this is a combined depth-stencil surface.
*
- * The rules are the same as in util_blitter_copy with the addition that
- * surfaces must have the same size.
+ * These states must be saved in the blitter in addition to the state objects
+ * already required to be saved:
+ * - framebuffer state
*/
-static INLINE
-void util_blitter_copy_surface(struct blitter_context *blitter,
- struct pipe_surface *dst,
- struct pipe_surface *src,
- boolean ignore_stencil)
-{
- assert(dst->width == src->width && dst->height == src->height);
-
- util_blitter_copy(blitter, dst, 0, 0, src, 0, 0, src->width, src->height,
- ignore_stencil);
-}
-
+void util_blitter_clear_depth_stencil(struct blitter_context *blitter,
+ struct pipe_surface *dst,
+ unsigned clear_flags,
+ double depth,
+ unsigned stencil,
+ unsigned dstx, unsigned dsty,
+ unsigned width, unsigned height);
+
+void util_blitter_flush_depth_stencil(struct blitter_context *blitter,
+ struct pipe_surface *dstsurf);
+
+void util_blitter_custom_depth_stencil(struct blitter_context *blitter,
+ struct pipe_surface *zsurf,
+ struct pipe_surface *cbsurf,
+ void *dsa_stage, float depth);
/* The functions below should be used to save currently bound constant state
* objects inside a driver. The objects are automatically restored at the end
- * of the util_blitter_{clear, fill, copy, copy_surface} functions and then
+ * of the util_blitter_{clear, copy_region, fill_region} functions and then
* forgotten.
*
* CSOs not listed here are not affected by util_blitter. */
@@ -213,9 +267,10 @@ void util_blitter_save_vertex_shader(struct blitter_context *blitter,
static INLINE
void util_blitter_save_framebuffer(struct blitter_context *blitter,
- struct pipe_framebuffer_state *state)
+ const struct pipe_framebuffer_state *state)
{
- blitter->saved_fb_state = *state;
+ blitter->saved_fb_state.nr_cbufs = 0; /* It's ~0 now, meaning it's unsaved. */
+ util_copy_framebuffer_state(&blitter->saved_fb_state, state);
}
static INLINE
@@ -250,12 +305,13 @@ util_blitter_save_fragment_sampler_views(struct blitter_context *blitter,
int num_views,
struct pipe_sampler_view **views)
{
+ unsigned i;
assert(num_views <= Elements(blitter->saved_sampler_views));
blitter->saved_num_sampler_views = num_views;
- memcpy(blitter->saved_sampler_views,
- views,
- num_views * sizeof(struct pipe_sampler_view *));
+ for (i = 0; i < num_views; i++)
+ pipe_sampler_view_reference(&blitter->saved_sampler_views[i],
+ views[i]);
}
static INLINE void
@@ -263,9 +319,18 @@ util_blitter_save_vertex_buffers(struct blitter_context *blitter,
int num_vertex_buffers,
struct pipe_vertex_buffer *vertex_buffers)
{
+ unsigned i;
assert(num_vertex_buffers <= Elements(blitter->saved_vertex_buffers));
blitter->saved_num_vertex_buffers = num_vertex_buffers;
+
+ for (i = 0; i < num_vertex_buffers; i++) {
+ if (vertex_buffers[i].buffer) {
+ pipe_resource_reference(&blitter->saved_vertex_buffers[i].buffer,
+ vertex_buffers[i].buffer);
+ }
+ }
+
memcpy(blitter->saved_vertex_buffers,
vertex_buffers,
num_vertex_buffers * sizeof(struct pipe_vertex_buffer));
diff --git a/src/gallium/auxiliary/util/u_box.h b/src/gallium/auxiliary/util/u_box.h
index 919967b55a7..e9c71743fc8 100644
--- a/src/gallium/auxiliary/util/u_box.h
+++ b/src/gallium/auxiliary/util/u_box.h
@@ -60,6 +60,25 @@ void u_box_2d_zslice( unsigned x,
box->depth = 1;
}
+
+static INLINE
+void u_box_3d( unsigned x,
+ unsigned y,
+ unsigned z,
+ unsigned w,
+ unsigned h,
+ unsigned d,
+ struct pipe_box *box )
+{
+ box->x = x;
+ box->y = y;
+ box->z = z;
+ box->width = w;
+ box->height = h;
+ box->depth = d;
+}
+
+
static INLINE
struct pipe_subresource u_subresource( unsigned face,
unsigned level )
diff --git a/src/gallium/auxiliary/util/u_caps.c b/src/gallium/auxiliary/util/u_caps.c
new file mode 100644
index 00000000000..e209a98b706
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_caps.c
@@ -0,0 +1,271 @@
+/**************************************************************************
+ *
+ * Copyright 2010 Vmware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "pipe/p_screen.h"
+#include "util/u_format.h"
+#include "util/u_debug.h"
+#include "u_caps.h"
+
+/**
+ * Iterates over a list of caps checks as defined in u_caps.h. Should
+ * all checks pass returns TRUE and out is set to the last element of
+ * the list (TERMINATE). Should any check fail returns FALSE and set
+ * out to the index of the start of the first failing check.
+ */
+boolean
+util_check_caps_out(struct pipe_screen *screen, const unsigned *list, int *out)
+{
+ int i, tmpi;
+ float tmpf;
+
+ for (i = 0; list[i];) {
+ switch(list[i++]) {
+ case UTIL_CAPS_CHECK_CAP:
+ if (!screen->get_param(screen, list[i++])) {
+ *out = i - 2;
+ return FALSE;
+ }
+ break;
+ case UTIL_CAPS_CHECK_INT:
+ tmpi = screen->get_param(screen, list[i++]);
+ if (tmpi < (int)list[i++]) {
+ *out = i - 3;
+ return FALSE;
+ }
+ break;
+ case UTIL_CAPS_CHECK_FLOAT:
+ tmpf = screen->get_paramf(screen, list[i++]);
+ if (tmpf < (float)list[i++]) {
+ *out = i - 3;
+ return FALSE;
+ }
+ break;
+ case UTIL_CAPS_CHECK_FORMAT:
+ if (!screen->is_format_supported(screen,
+ list[i++],
+ PIPE_TEXTURE_2D,
+ 0,
+ PIPE_BIND_SAMPLER_VIEW,
+ 0)) {
+ *out = i - 2;
+ return FALSE;
+ }
+ break;
+ case UTIL_CAPS_CHECK_SHADER:
+ tmpi = screen->get_shader_param(screen, list[i] >> 24, list[i] & ((1 << 24) - 1));
+ ++i;
+ if (tmpi < (int)list[i++]) {
+ *out = i - 3;
+ return FALSE;
+ }
+ break;
+ case UTIL_CAPS_CHECK_UNIMPLEMENTED:
+ *out = i - 1;
+ return FALSE;
+ default:
+ assert(!"Unsupported check");
+ return FALSE;
+ }
+ }
+
+ *out = i;
+ return TRUE;
+}
+
+/**
+ * Iterates over a list of caps checks as defined in u_caps.h.
+ * Returns TRUE if all caps checks pass returns FALSE otherwise.
+ */
+boolean
+util_check_caps(struct pipe_screen *screen, const unsigned *list)
+{
+ int out;
+ return util_check_caps_out(screen, list, &out);
+}
+
+
+/*
+ * Below follows some demo lists.
+ *
+ * None of these lists are exhausting lists of what is
+ * actually needed to support said API and more here for
+ * as example on how to uses the above functions. Especially
+ * for DX10 and DX11 where Gallium is missing features.
+ */
+
+/* DX 9_1 */
+static unsigned caps_dx_9_1[] = {
+ UTIL_CHECK_INT(MAX_RENDER_TARGETS, 1),
+ UTIL_CHECK_INT(MAX_TEXTURE_2D_LEVELS, 12), /* 2048 */
+ UTIL_CHECK_INT(MAX_TEXTURE_3D_LEVELS, 9), /* 256 */
+ UTIL_CHECK_INT(MAX_TEXTURE_CUBE_LEVELS, 10), /* 512 */
+ UTIL_CHECK_FLOAT(MAX_TEXTURE_ANISOTROPY, 2),
+ UTIL_CHECK_TERMINATE
+};
+
+/* DX 9_2 */
+static unsigned caps_dx_9_2[] = {
+ UTIL_CHECK_CAP(OCCLUSION_QUERY),
+ UTIL_CHECK_CAP(BLEND_EQUATION_SEPARATE),
+ UTIL_CHECK_INT(MAX_RENDER_TARGETS, 1),
+ UTIL_CHECK_INT(MAX_TEXTURE_2D_LEVELS, 12), /* 2048 */
+ UTIL_CHECK_INT(MAX_TEXTURE_3D_LEVELS, 9), /* 256 */
+ UTIL_CHECK_INT(MAX_TEXTURE_CUBE_LEVELS, 10), /* 512 */
+ UTIL_CHECK_FLOAT(MAX_TEXTURE_ANISOTROPY, 16),
+ UTIL_CHECK_TERMINATE
+};
+
+/* DX 9_3 */
+static unsigned caps_dx_9_3[] = {
+ UTIL_CHECK_CAP(SM3),
+ //UTIL_CHECK_CAP(INSTANCING),
+ UTIL_CHECK_CAP(OCCLUSION_QUERY),
+ UTIL_CHECK_INT(MAX_RENDER_TARGETS, 4),
+ UTIL_CHECK_INT(MAX_TEXTURE_2D_LEVELS, 13), /* 4096 */
+ UTIL_CHECK_INT(MAX_TEXTURE_3D_LEVELS, 9), /* 256 */
+ UTIL_CHECK_INT(MAX_TEXTURE_CUBE_LEVELS, 10), /* 512 */
+ UTIL_CHECK_FLOAT(MAX_TEXTURE_ANISOTROPY, 16),
+ UTIL_CHECK_TERMINATE
+};
+
+/* DX 10 */
+static unsigned caps_dx_10[] = {
+ UTIL_CHECK_CAP(SM3),
+ //UTIL_CHECK_CAP(INSTANCING),
+ UTIL_CHECK_CAP(OCCLUSION_QUERY),
+ UTIL_CHECK_INT(MAX_RENDER_TARGETS, 8),
+ UTIL_CHECK_INT(MAX_TEXTURE_2D_LEVELS, 14), /* 8192 */
+ UTIL_CHECK_INT(MAX_TEXTURE_3D_LEVELS, 12), /* 2048 */
+ UTIL_CHECK_INT(MAX_TEXTURE_CUBE_LEVELS, 14), /* 8192 */
+ UTIL_CHECK_FLOAT(MAX_TEXTURE_ANISOTROPY, 16),
+ UTIL_CHECK_UNIMPLEMENTED, /* XXX Unimplemented features in Gallium */
+ UTIL_CHECK_TERMINATE
+};
+
+/* DX11 */
+static unsigned caps_dx_11[] = {
+ UTIL_CHECK_CAP(SM3),
+ //UTIL_CHECK_CAP(INSTANCING),
+ UTIL_CHECK_CAP(OCCLUSION_QUERY),
+ UTIL_CHECK_INT(MAX_RENDER_TARGETS, 8),
+ UTIL_CHECK_INT(MAX_TEXTURE_2D_LEVELS, 14), /* 16384 */
+ UTIL_CHECK_INT(MAX_TEXTURE_3D_LEVELS, 12), /* 2048 */
+ UTIL_CHECK_INT(MAX_TEXTURE_CUBE_LEVELS, 14), /* 16384 */
+ UTIL_CHECK_FLOAT(MAX_TEXTURE_ANISOTROPY, 16),
+ UTIL_CHECK_FORMAT(B8G8R8A8_UNORM),
+ UTIL_CHECK_UNIMPLEMENTED, /* XXX Unimplemented features in Gallium */
+ UTIL_CHECK_TERMINATE
+};
+
+/* OpenGL 2.1 */
+static unsigned caps_opengl_2_1[] = {
+ UTIL_CHECK_CAP(GLSL),
+ UTIL_CHECK_CAP(OCCLUSION_QUERY),
+ UTIL_CHECK_CAP(TWO_SIDED_STENCIL),
+ UTIL_CHECK_CAP(BLEND_EQUATION_SEPARATE),
+ UTIL_CHECK_INT(MAX_RENDER_TARGETS, 2),
+ UTIL_CHECK_TERMINATE
+};
+
+/* OpenGL 3.0 */
+/* UTIL_CHECK_INT(MAX_RENDER_TARGETS, 8), */
+
+/* Shader Model 3 */
+static unsigned caps_sm3[] = {
+ UTIL_CHECK_SHADER(FRAGMENT, MAX_INSTRUCTIONS, 512),
+ UTIL_CHECK_SHADER(FRAGMENT, MAX_INPUTS, 10),
+ UTIL_CHECK_SHADER(FRAGMENT, MAX_TEMPS, 32),
+ UTIL_CHECK_SHADER(FRAGMENT, MAX_ADDRS, 1),
+ UTIL_CHECK_SHADER(FRAGMENT, MAX_CONSTS, 224),
+
+ UTIL_CHECK_SHADER(VERTEX, MAX_INSTRUCTIONS, 512),
+ UTIL_CHECK_SHADER(VERTEX, MAX_INPUTS, 16),
+ UTIL_CHECK_SHADER(VERTEX, MAX_TEMPS, 32),
+ UTIL_CHECK_SHADER(VERTEX, MAX_ADDRS, 2),
+ UTIL_CHECK_SHADER(VERTEX, MAX_CONSTS, 256),
+
+ UTIL_CHECK_TERMINATE
+};
+
+/**
+ * Demo function which checks against theoretical caps needed for different APIs.
+ */
+void util_caps_demo_print(struct pipe_screen *screen)
+{
+ struct {
+ char* name;
+ unsigned *list;
+ } list[] = {
+ {"DX 9.1", caps_dx_9_1},
+ {"DX 9.2", caps_dx_9_2},
+ {"DX 9.3", caps_dx_9_3},
+ {"DX 10", caps_dx_10},
+ {"DX 11", caps_dx_11},
+ {"OpenGL 2.1", caps_opengl_2_1},
+/* {"OpenGL 3.0", caps_opengl_3_0},*/
+ {"SM3", caps_sm3},
+ {NULL, NULL}
+ };
+ int i, out = 0;
+
+ for (i = 0; list[i].name; i++) {
+ if (util_check_caps_out(screen, list[i].list, &out)) {
+ debug_printf("%s: %s yes\n", __FUNCTION__, list[i].name);
+ continue;
+ }
+ switch (list[i].list[out]) {
+ case UTIL_CAPS_CHECK_CAP:
+ debug_printf("%s: %s no (cap %u not supported)\n", __FUNCTION__,
+ list[i].name,
+ list[i].list[out + 1]);
+ break;
+ case UTIL_CAPS_CHECK_INT:
+ debug_printf("%s: %s no (cap %u less then %u)\n", __FUNCTION__,
+ list[i].name,
+ list[i].list[out + 1],
+ list[i].list[out + 2]);
+ break;
+ case UTIL_CAPS_CHECK_FLOAT:
+ debug_printf("%s: %s no (cap %u less then %f)\n", __FUNCTION__,
+ list[i].name,
+ list[i].list[out + 1],
+ (double)(int)list[i].list[out + 2]);
+ break;
+ case UTIL_CAPS_CHECK_FORMAT:
+ debug_printf("%s: %s no (format %s not supported)\n", __FUNCTION__,
+ list[i].name,
+ util_format_name(list[i].list[out + 1]) + 12);
+ break;
+ case UTIL_CAPS_CHECK_UNIMPLEMENTED:
+ debug_printf("%s: %s no (not implemented in gallium or state tracker)\n",
+ __FUNCTION__, list[i].name);
+ break;
+ default:
+ assert(!"Unsupported check");
+ }
+ }
+}
diff --git a/src/gallium/auxiliary/util/u_caps.h b/src/gallium/auxiliary/util/u_caps.h
new file mode 100644
index 00000000000..7bd23800414
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_caps.h
@@ -0,0 +1,71 @@
+/**************************************************************************
+ *
+ * Copyright 2010 Vmware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef U_CAPS_H
+#define U_CAPS_H
+
+#include "pipe/p_compiler.h"
+
+struct pipe_screen;
+
+enum u_caps_check_enum {
+ UTIL_CAPS_CHECK_TERMINATE = 0,
+ UTIL_CAPS_CHECK_CAP,
+ UTIL_CAPS_CHECK_INT,
+ UTIL_CAPS_CHECK_FLOAT,
+ UTIL_CAPS_CHECK_FORMAT,
+ UTIL_CAPS_CHECK_SHADER,
+ UTIL_CAPS_CHECK_UNIMPLEMENTED,
+};
+
+#define UTIL_CHECK_CAP(cap) \
+ UTIL_CAPS_CHECK_CAP, PIPE_CAP_##cap
+
+#define UTIL_CHECK_INT(cap, higher) \
+ UTIL_CAPS_CHECK_INT, PIPE_CAP_##cap, (unsigned)(higher)
+
+/* Floats currently lose precision */
+#define UTIL_CHECK_FLOAT(cap, higher) \
+ UTIL_CAPS_CHECK_FLOAT, PIPE_CAP_##cap, (unsigned)(int)(higher)
+
+#define UTIL_CHECK_FORMAT(format) \
+ UTIL_CAPS_CHECK_FORMAT, PIPE_FORMAT_##format
+
+#define UTIL_CHECK_SHADER(shader, cap, higher) \
+ UTIL_CAPS_CHECK_SHADER, (PIPE_SHADER_##shader << 24) | PIPE_SHADER_CAP_##cap, (unsigned)(higher)
+
+#define UTIL_CHECK_UNIMPLEMENTED \
+ UTIL_CAPS_CHECK_UNIMPLEMENTED
+
+#define UTIL_CHECK_TERMINATE \
+ UTIL_CAPS_CHECK_TERMINATE
+
+boolean util_check_caps(struct pipe_screen *screen, const unsigned *list);
+boolean util_check_caps_out(struct pipe_screen *screen, const unsigned *list, int *out);
+void util_caps_demo_print(struct pipe_screen *screen);
+
+#endif
diff --git a/src/gallium/auxiliary/util/u_clear.h b/src/gallium/auxiliary/util/u_clear.h
index 2c32db61756..ad69df3f898 100644
--- a/src/gallium/auxiliary/util/u_clear.h
+++ b/src/gallium/auxiliary/util/u_clear.h
@@ -31,8 +31,6 @@
#include "pipe/p_context.h"
#include "pipe/p_state.h"
-#include "util/u_pack_color.h"
-#include "util/u_rect.h"
/**
@@ -45,26 +43,17 @@ util_clear(struct pipe_context *pipe,
const float *rgba, double depth, unsigned stencil)
{
if (buffers & PIPE_CLEAR_COLOR) {
- struct pipe_surface *ps = framebuffer->cbufs[0];
- union util_color uc;
-
- util_pack_color(rgba, ps->format, &uc);
- if (pipe->surface_fill) {
- pipe->surface_fill(pipe, ps, 0, 0, ps->width, ps->height, uc.ui);
- } else {
- util_surface_fill(pipe, ps, 0, 0, ps->width, ps->height, uc.ui);
+ unsigned i;
+ for (i = 0; i < framebuffer->nr_cbufs; i++) {
+ struct pipe_surface *ps = framebuffer->cbufs[i];
+ pipe->clear_render_target(pipe, ps, rgba, 0, 0, ps->width, ps->height);
}
}
if (buffers & PIPE_CLEAR_DEPTHSTENCIL) {
struct pipe_surface *ps = framebuffer->zsbuf;
-
- if (pipe->surface_fill) {
- pipe->surface_fill(pipe, ps, 0, 0, ps->width, ps->height,
- util_pack_z_stencil(ps->format, depth, stencil));
- } else {
- util_surface_fill(pipe, ps, 0, 0, ps->width, ps->height,
- util_pack_z_stencil(ps->format, depth, stencil));
- }
+ pipe->clear_depth_stencil(pipe, ps, buffers & PIPE_CLEAR_DEPTHSTENCIL,
+ depth, stencil,
+ 0, 0, ps->width, ps->height);
}
}
diff --git a/src/gallium/auxiliary/util/u_cpu_detect.c b/src/gallium/auxiliary/util/u_cpu_detect.c
index a08241971ca..32519b148b6 100644
--- a/src/gallium/auxiliary/util/u_cpu_detect.c
+++ b/src/gallium/auxiliary/util/u_cpu_detect.c
@@ -38,7 +38,7 @@
#include "u_cpu_detect.h"
#if defined(PIPE_ARCH_PPC)
-#if defined(PIPE_OS_DARWIN)
+#if defined(PIPE_OS_APPLE)
#include <sys/sysctl.h>
#else
#include <signal.h>
@@ -73,66 +73,19 @@
#endif
-struct util_cpu_caps util_cpu_caps;
-
-static int has_cpuid(void);
-
-#if defined(PIPE_ARCH_X86)
-
-/* The sigill handlers */
-#if defined(PIPE_OS_LINUX) /*&& defined(_POSIX_SOURCE) && defined(X86_FXSR_MAGIC)*/
-static void
-sigill_handler_sse(int signal, struct sigcontext sc)
-{
- /* Both the "xorps %%xmm0,%%xmm0" and "divps %xmm0,%%xmm1"
- * instructions are 3 bytes long. We must increment the instruction
- * pointer manually to avoid repeated execution of the offending
- * instruction.
- *
- * If the SIGILL is caused by a divide-by-zero when unmasked
- * exceptions aren't supported, the SIMD FPU status and control
- * word will be restored at the end of the test, so we don't need
- * to worry about doing it here. Besides, we may not be able to...
- */
- sc.eip += 3;
-
- util_cpu_caps.has_sse=0;
-}
+#ifdef DEBUG
+DEBUG_GET_ONCE_BOOL_OPTION(dump_cpu, "GALLIUM_DUMP_CPU", FALSE)
+#endif
-static void
-sigfpe_handler_sse(int signal, struct sigcontext sc)
-{
- if (sc.fpstate->magic != 0xffff) {
- /* Our signal context has the extended FPU state, so reset the
- * divide-by-zero exception mask and clear the divide-by-zero
- * exception bit.
- */
- sc.fpstate->mxcsr |= 0x00000200;
- sc.fpstate->mxcsr &= 0xfffffffb;
- } else {
- /* If we ever get here, we're completely hosed.
- */
- }
-}
-#endif /* PIPE_OS_LINUX && _POSIX_SOURCE && X86_FXSR_MAGIC */
-#if defined(PIPE_OS_WINDOWS)
-static LONG CALLBACK
-win32_sig_handler_sse(EXCEPTION_POINTERS* ep)
-{
- if(ep->ExceptionRecord->ExceptionCode==EXCEPTION_ILLEGAL_INSTRUCTION){
- ep->ContextRecord->Eip +=3;
- util_cpu_caps.has_sse=0;
- return EXCEPTION_CONTINUE_EXECUTION;
- }
- return EXCEPTION_CONTINUE_SEARCH;
-}
-#endif /* PIPE_OS_WINDOWS */
+struct util_cpu_caps util_cpu_caps;
-#endif /* PIPE_ARCH_X86 */
+#if defined(PIPE_ARCH_X86) || defined(PIPE_ARCH_X86_64)
+static int has_cpuid(void);
+#endif
-#if defined(PIPE_ARCH_PPC) && !defined(PIPE_OS_DARWIN)
+#if defined(PIPE_ARCH_PPC) && !defined(PIPE_OS_APPLE)
static jmp_buf __lv_powerpc_jmpbuf;
static volatile sig_atomic_t __lv_powerpc_canjump = 0;
@@ -153,7 +106,7 @@ sigill_handler(int sig)
static void
check_os_altivec_support(void)
{
-#if defined(PIPE_OS_DARWIN)
+#if defined(PIPE_OS_APPLE)
int sels[2] = {CTL_HW, HW_VECTORUNIT};
int has_vu = 0;
int len = sizeof (has_vu);
@@ -166,8 +119,8 @@ check_os_altivec_support(void)
util_cpu_caps.has_altivec = 1;
}
}
-#else /* !PIPE_OS_DARWIN */
- /* no Darwin, do it the brute-force way */
+#else /* !PIPE_OS_APPLE */
+ /* not on Apple/Darwin, do it the brute-force way */
/* this is borrowed from the libmpeg2 library */
signal(SIGILL, sigill_handler);
if (setjmp(__lv_powerpc_jmpbuf)) {
@@ -184,127 +137,12 @@ check_os_altivec_support(void)
signal(SIGILL, SIG_DFL);
util_cpu_caps.has_altivec = 1;
}
-#endif /* PIPE_OS_DARWIN */
+#endif /* !PIPE_OS_APPLE */
}
#endif /* PIPE_ARCH_PPC */
-/* If we're running on a processor that can do SSE, let's see if we
- * are allowed to or not. This will catch 2.4.0 or later kernels that
- * haven't been configured for a Pentium III but are running on one,
- * and RedHat patched 2.2 kernels that have broken exception handling
- * support for user space apps that do SSE.
- */
-#if defined(PIPE_ARCH_X86) || defined (PIPE_ARCH_X86_64)
-static void
-check_os_katmai_support(void)
-{
-#if defined(PIPE_ARCH_X86)
-#if defined(PIPE_OS_FREEBSD)
- int has_sse=0, ret;
- int len = sizeof (has_sse);
-
- ret = sysctlbyname("hw.instruction_sse", &has_sse, &len, NULL, 0);
- if (ret || !has_sse)
- util_cpu_caps.has_sse=0;
-
-#elif defined(PIPE_OS_NETBSD) || defined(PIPE_OS_OPENBSD)
- int has_sse, has_sse2, ret, mib[2];
- int varlen;
-
- mib[0] = CTL_MACHDEP;
- mib[1] = CPU_SSE;
- varlen = sizeof (has_sse);
-
- ret = sysctl(mib, 2, &has_sse, &varlen, NULL, 0);
- if (ret < 0 || !has_sse) {
- util_cpu_caps.has_sse = 0;
- } else {
- util_cpu_caps.has_sse = 1;
- }
-
- mib[1] = CPU_SSE2;
- varlen = sizeof (has_sse2);
- ret = sysctl(mib, 2, &has_sse2, &varlen, NULL, 0);
- if (ret < 0 || !has_sse2) {
- util_cpu_caps.has_sse2 = 0;
- } else {
- util_cpu_caps.has_sse2 = 1;
- }
- util_cpu_caps.has_sse = 0; /* FIXME ?!?!? */
-
-#elif defined(PIPE_OS_WINDOWS)
- LPTOP_LEVEL_EXCEPTION_FILTER exc_fil;
- if (util_cpu_caps.has_sse) {
- exc_fil = SetUnhandledExceptionFilter(win32_sig_handler_sse);
-#if defined(PIPE_CC_GCC)
- __asm __volatile ("xorps %xmm0, %xmm0");
-#elif defined(PIPE_CC_MSVC)
- __asm {
- xorps xmm0, xmm0 /* executing SSE instruction */
- }
-#else
-#error Unsupported compiler
-#endif
- SetUnhandledExceptionFilter(exc_fil);
- }
-#elif defined(PIPE_OS_LINUX)
- struct sigaction saved_sigill;
- struct sigaction saved_sigfpe;
-
- /* Save the original signal handlers.
- */
- sigaction(SIGILL, NULL, &saved_sigill);
- sigaction(SIGFPE, NULL, &saved_sigfpe);
-
- signal(SIGILL, (void (*)(int))sigill_handler_sse);
- signal(SIGFPE, (void (*)(int))sigfpe_handler_sse);
-
- /* Emulate test for OSFXSR in CR4. The OS will set this bit if it
- * supports the extended FPU save and restore required for SSE. If
- * we execute an SSE instruction on a PIII and get a SIGILL, the OS
- * doesn't support Streaming SIMD Exceptions, even if the processor
- * does.
- */
- if (util_cpu_caps.has_sse) {
- __asm __volatile ("xorps %xmm1, %xmm0");
- }
-
- /* Emulate test for OSXMMEXCPT in CR4. The OS will set this bit if
- * it supports unmasked SIMD FPU exceptions. If we unmask the
- * exceptions, do a SIMD divide-by-zero and get a SIGILL, the OS
- * doesn't support unmasked SIMD FPU exceptions. If we get a SIGFPE
- * as expected, we're okay but we need to clean up after it.
- *
- * Are we being too stringent in our requirement that the OS support
- * unmasked exceptions? Certain RedHat 2.2 kernels enable SSE by
- * setting CR4.OSFXSR but don't support unmasked exceptions. Win98
- * doesn't even support them. We at least know the user-space SSE
- * support is good in kernels that do support unmasked exceptions,
- * and therefore to be safe I'm going to leave this test in here.
- */
- if (util_cpu_caps.has_sse) {
- /* test_os_katmai_exception_support(); */
- }
-
- /* Restore the original signal handlers.
- */
- sigaction(SIGILL, &saved_sigill, NULL);
- sigaction(SIGFPE, &saved_sigfpe, NULL);
-
-#else
- /* We can't use POSIX signal handling to test the availability of
- * SSE, so we disable it by default.
- */
- util_cpu_caps.has_sse = 0;
-#endif /* __linux__ */
-#endif
-
-#if defined(PIPE_ARCH_X86_64)
- util_cpu_caps.has_sse = 1;
-#endif
-}
-
+#if defined(PIPE_ARCH_X86) || defined (PIPE_ARCH_X86_64)
static int has_cpuid(void)
{
#if defined(PIPE_ARCH_X86)
@@ -385,23 +223,6 @@ util_cpu_detect(void)
memset(&util_cpu_caps, 0, sizeof util_cpu_caps);
- /* Check for arch type */
-#if defined(PIPE_ARCH_MIPS)
- util_cpu_caps.arch = UTIL_CPU_ARCH_MIPS;
-#elif defined(PIPE_ARCH_ALPHA)
- util_cpu_caps.arch = UTIL_CPU_ARCH_ALPHA;
-#elif defined(PIPE_ARCH_SPARC)
- util_cpu_caps.arch = UTIL_CPU_ARCH_SPARC;
-#elif defined(PIPE_ARCH_X86) || defined(PIPE_ARCH_X86_64)
- util_cpu_caps.arch = UTIL_CPU_ARCH_X86;
- util_cpu_caps.little_endian = 1;
-#elif defined(PIPE_ARCH_PPC)
- util_cpu_caps.arch = UTIL_CPU_ARCH_POWERPC;
- util_cpu_caps.little_endian = 0;
-#else
- util_cpu_caps.arch = UTIL_CPU_ARCH_UNKNOWN;
-#endif
-
/* Count the number of CPUs in system */
#if defined(PIPE_OS_WINDOWS)
{
@@ -480,9 +301,6 @@ util_cpu_detect(void)
util_cpu_caps.cacheline = regs2[2] & 0xFF;
}
- if (util_cpu_caps.has_sse)
- check_os_katmai_support();
-
if (!util_cpu_caps.has_sse) {
util_cpu_caps.has_sse2 = 0;
util_cpu_caps.has_sse3 = 0;
@@ -497,23 +315,24 @@ util_cpu_detect(void)
#endif /* PIPE_ARCH_PPC */
#ifdef DEBUG
- debug_printf("util_cpu_caps.arch = %i\n", util_cpu_caps.arch);
- debug_printf("util_cpu_caps.nr_cpus = %u\n", util_cpu_caps.nr_cpus);
-
- debug_printf("util_cpu_caps.x86_cpu_type = %u\n", util_cpu_caps.x86_cpu_type);
- debug_printf("util_cpu_caps.cacheline = %u\n", util_cpu_caps.cacheline);
-
- debug_printf("util_cpu_caps.has_tsc = %u\n", util_cpu_caps.has_tsc);
- debug_printf("util_cpu_caps.has_mmx = %u\n", util_cpu_caps.has_mmx);
- debug_printf("util_cpu_caps.has_mmx2 = %u\n", util_cpu_caps.has_mmx2);
- debug_printf("util_cpu_caps.has_sse = %u\n", util_cpu_caps.has_sse);
- debug_printf("util_cpu_caps.has_sse2 = %u\n", util_cpu_caps.has_sse2);
- debug_printf("util_cpu_caps.has_sse3 = %u\n", util_cpu_caps.has_sse3);
- debug_printf("util_cpu_caps.has_ssse3 = %u\n", util_cpu_caps.has_ssse3);
- debug_printf("util_cpu_caps.has_sse4_1 = %u\n", util_cpu_caps.has_sse4_1);
- debug_printf("util_cpu_caps.has_3dnow = %u\n", util_cpu_caps.has_3dnow);
- debug_printf("util_cpu_caps.has_3dnow_ext = %u\n", util_cpu_caps.has_3dnow_ext);
- debug_printf("util_cpu_caps.has_altivec = %u\n", util_cpu_caps.has_altivec);
+ if (debug_get_option_dump_cpu()) {
+ debug_printf("util_cpu_caps.nr_cpus = %u\n", util_cpu_caps.nr_cpus);
+
+ debug_printf("util_cpu_caps.x86_cpu_type = %u\n", util_cpu_caps.x86_cpu_type);
+ debug_printf("util_cpu_caps.cacheline = %u\n", util_cpu_caps.cacheline);
+
+ debug_printf("util_cpu_caps.has_tsc = %u\n", util_cpu_caps.has_tsc);
+ debug_printf("util_cpu_caps.has_mmx = %u\n", util_cpu_caps.has_mmx);
+ debug_printf("util_cpu_caps.has_mmx2 = %u\n", util_cpu_caps.has_mmx2);
+ debug_printf("util_cpu_caps.has_sse = %u\n", util_cpu_caps.has_sse);
+ debug_printf("util_cpu_caps.has_sse2 = %u\n", util_cpu_caps.has_sse2);
+ debug_printf("util_cpu_caps.has_sse3 = %u\n", util_cpu_caps.has_sse3);
+ debug_printf("util_cpu_caps.has_ssse3 = %u\n", util_cpu_caps.has_ssse3);
+ debug_printf("util_cpu_caps.has_sse4_1 = %u\n", util_cpu_caps.has_sse4_1);
+ debug_printf("util_cpu_caps.has_3dnow = %u\n", util_cpu_caps.has_3dnow);
+ debug_printf("util_cpu_caps.has_3dnow_ext = %u\n", util_cpu_caps.has_3dnow_ext);
+ debug_printf("util_cpu_caps.has_altivec = %u\n", util_cpu_caps.has_altivec);
+ }
#endif
util_cpu_detect_initialized = TRUE;
diff --git a/src/gallium/auxiliary/util/u_cpu_detect.h b/src/gallium/auxiliary/util/u_cpu_detect.h
index 4b3dc39c342..f3bef0993c7 100644
--- a/src/gallium/auxiliary/util/u_cpu_detect.h
+++ b/src/gallium/auxiliary/util/u_cpu_detect.h
@@ -36,26 +36,15 @@
#define _UTIL_CPU_DETECT_H
#include "pipe/p_compiler.h"
-
-enum util_cpu_arch {
- UTIL_CPU_ARCH_UNKNOWN = 0,
- UTIL_CPU_ARCH_MIPS,
- UTIL_CPU_ARCH_ALPHA,
- UTIL_CPU_ARCH_SPARC,
- UTIL_CPU_ARCH_X86,
- UTIL_CPU_ARCH_POWERPC
-};
+#include "pipe/p_config.h"
struct util_cpu_caps {
- enum util_cpu_arch arch;
unsigned nr_cpus;
/* Feature flags */
int x86_cpu_type;
unsigned cacheline;
- unsigned little_endian:1;
-
unsigned has_tsc:1;
unsigned has_mmx:1;
unsigned has_mmx2:1;
diff --git a/src/gallium/auxiliary/util/u_debug.c b/src/gallium/auxiliary/util/u_debug.c
index 0de38e791d6..504e6d2a18f 100644
--- a/src/gallium/auxiliary/util/u_debug.c
+++ b/src/gallium/auxiliary/util/u_debug.c
@@ -42,6 +42,7 @@
#include "util/u_tile.h"
#include "util/u_prim.h"
+#include <limits.h> /* CHAR_BIT */
void _debug_vprintf(const char *format, va_list ap)
{
@@ -87,7 +88,7 @@ debug_get_option_should_print(void)
* but its cool since we set first to false
*/
first = FALSE;
- value = debug_get_bool_option("GALLIUM_PRINT_OPTIONS", TRUE);
+ value = debug_get_bool_option("GALLIUM_PRINT_OPTIONS", FALSE);
/* XXX should we print this option? Currently it wont */
return value;
}
@@ -123,8 +124,12 @@ debug_get_bool_option(const char *name, boolean dfault)
result = FALSE;
else if(!util_strcmp(str, "f"))
result = FALSE;
+ else if(!util_strcmp(str, "F"))
+ result = FALSE;
else if(!util_strcmp(str, "false"))
result = FALSE;
+ else if(!util_strcmp(str, "FALSE"))
+ result = FALSE;
else
result = TRUE;
@@ -177,16 +182,21 @@ debug_get_flags_option(const char *name,
{
unsigned long result;
const char *str;
+ const struct debug_named_value *orig = flags;
+ int namealign = 0;
str = os_get_option(name);
if(!str)
result = dfault;
else if (!util_strcmp(str, "help")) {
result = dfault;
- while (flags->name) {
- debug_printf("%s: help for %s: %s [0x%lx]\n", __FUNCTION__, name, flags->name, flags->value);
- flags++;
- }
+ _debug_printf("%s: help for %s:\n", __FUNCTION__, name);
+ for (; flags->name; ++flags)
+ namealign = MAX2(namealign, strlen(flags->name));
+ for (flags = orig; flags->name; ++flags)
+ _debug_printf("| %*s [0x%0*lx]%s%s\n", namealign, flags->name,
+ (int)sizeof(unsigned long)*CHAR_BIT/4, flags->value,
+ flags->desc ? " " : "", flags->desc ? flags->desc : "");
}
else {
result = 0;
diff --git a/src/gallium/auxiliary/util/u_debug.h b/src/gallium/auxiliary/util/u_debug.h
index e8ff2773e69..1c9624ea3ed 100644
--- a/src/gallium/auxiliary/util/u_debug.h
+++ b/src/gallium/auxiliary/util/u_debug.h
@@ -230,6 +230,7 @@ struct debug_named_value
{
const char *name;
unsigned long value;
+ const char *desc;
};
@@ -252,8 +253,9 @@ struct debug_named_value
* ...
* @endcode
*/
-#define DEBUG_NAMED_VALUE(__symbol) {#__symbol, (unsigned long)__symbol}
-#define DEBUG_NAMED_VALUE_END {NULL, 0}
+#define DEBUG_NAMED_VALUE(__symbol) DEBUG_NAMED_VALUE_WITH_DESCRIPTION(__symbol, NULL)
+#define DEBUG_NAMED_VALUE_WITH_DESCRIPTION(__symbol, __desc) {#__symbol, (unsigned long)__symbol, __desc}
+#define DEBUG_NAMED_VALUE_END {NULL, 0, NULL}
/**
diff --git a/src/gallium/auxiliary/util/u_debug_describe.c b/src/gallium/auxiliary/util/u_debug_describe.c
new file mode 100644
index 00000000000..1c90ff31069
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_debug_describe.c
@@ -0,0 +1,81 @@
+/**************************************************************************
+ *
+ * Copyright 2010 Luca Barbieri
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include <pipe/p_state.h>
+#include <util/u_format.h>
+#include <util/u_debug_describe.h>
+#include <util/u_string.h>
+
+void
+debug_describe_reference(char* buf, const struct pipe_reference*ptr)
+{
+ strcpy(buf, "pipe_object");
+}
+
+void
+debug_describe_resource(char* buf, const struct pipe_resource *ptr)
+{
+ switch(ptr->target)
+ {
+ case PIPE_BUFFER:
+ util_sprintf(buf, "pipe_buffer<%u>", (unsigned)util_format_get_stride(ptr->format, ptr->width0));
+ break;
+ case PIPE_TEXTURE_1D:
+ util_sprintf(buf, "pipe_texture1d<%u,%s,%u>", ptr->width0, util_format_short_name(ptr->format), ptr->last_level);
+ break;
+ case PIPE_TEXTURE_2D:
+ util_sprintf(buf, "pipe_texture2d<%u,%u,%s,%u>", ptr->width0, ptr->height0, util_format_short_name(ptr->format), ptr->last_level);
+ break;
+ case PIPE_TEXTURE_RECT:
+ util_sprintf(buf, "pipe_texture_rect<%u,%u,%s>", ptr->width0, ptr->height0, util_format_short_name(ptr->format));
+ break;
+ case PIPE_TEXTURE_CUBE:
+ util_sprintf(buf, "pipe_texture_cube<%u,%u,%s,%u>", ptr->width0, ptr->height0, util_format_short_name(ptr->format), ptr->last_level);
+ break;
+ case PIPE_TEXTURE_3D:
+ util_sprintf(buf, "pipe_texture3d<%u,%u,%u,%s,%u>", ptr->width0, ptr->height0, ptr->depth0, util_format_short_name(ptr->format), ptr->last_level);
+ break;
+ default:
+ util_sprintf(buf, "pipe_martian_resource<%u>", ptr->target);
+ break;
+ }
+}
+
+void
+debug_describe_surface(char* buf, const struct pipe_surface *ptr)
+{
+ char res[128];
+ debug_describe_resource(res, ptr->texture);
+ util_sprintf(buf, "pipe_surface<%s,%u,%u,%u>", res, ptr->face, ptr->level, ptr->zslice);
+}
+
+void
+debug_describe_sampler_view(char* buf, const struct pipe_sampler_view *ptr)
+{
+ char res[128];
+ debug_describe_resource(res, ptr->texture);
+ util_sprintf(buf, "pipe_sampler_view<%s,%s>", res, util_format_short_name(ptr->format));
+}
diff --git a/src/gallium/auxiliary/util/u_debug_describe.h b/src/gallium/auxiliary/util/u_debug_describe.h
new file mode 100644
index 00000000000..26d1f803bf0
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_debug_describe.h
@@ -0,0 +1,49 @@
+/**************************************************************************
+ *
+ * Copyright 2010 Luca Barbieri
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef U_DEBUG_DESCRIBE_H_
+#define U_DEBUG_DESCRIBE_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct pipe_reference;
+struct pipe_resource;
+struct pipe_surface;
+struct pipe_sampler_view;
+
+/* a 256-byte buffer is necessary and sufficient */
+void debug_describe_reference(char* buf, const struct pipe_reference*ptr);
+void debug_describe_resource(char* buf, const struct pipe_resource *ptr);
+void debug_describe_surface(char* buf, const struct pipe_surface *ptr);
+void debug_describe_sampler_view(char* buf, const struct pipe_sampler_view *ptr);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* U_DEBUG_DESCRIBE_H_ */
diff --git a/src/gallium/auxiliary/util/u_debug_refcnt.c b/src/gallium/auxiliary/util/u_debug_refcnt.c
new file mode 100644
index 00000000000..40a26c9c697
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_debug_refcnt.c
@@ -0,0 +1,181 @@
+/**************************************************************************
+ *
+ * Copyright 2010 Luca Barbieri
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#if defined(DEBUG) && (!defined(PIPE_OS_WINDOWS) || defined(PIPE_SUBSYSTEM_WINDOWS_USER))
+
+/* see http://www.mozilla.org/performance/refcnt-balancer.html for what do with the output
+ * on Linux, use tools/addr2line.sh to postprocess it before anything else
+ **/
+#include <util/u_debug.h>
+#include <util/u_debug_refcnt.h>
+#include <util/u_debug_stack.h>
+#include <util/u_debug_symbol.h>
+#include <util/u_string.h>
+#include <util/u_hash_table.h>
+#include <os/os_thread.h>
+#include <os/os_stream.h>
+
+int debug_refcnt_state;
+
+struct os_stream* stream;
+
+/* TODO: maybe move this serial machinery to a stand-alone module and expose it? */
+static pipe_mutex serials_mutex;
+static struct util_hash_table* serials_hash;
+static unsigned serials_last;
+
+static unsigned hash_ptr(void* p)
+{
+ return (unsigned)(uintptr_t)p;
+}
+
+static int compare_ptr(void* a, void* b)
+{
+ if(a == b)
+ return 0;
+ else if(a < b)
+ return -1;
+ else
+ return 1;
+}
+
+static boolean debug_serial(void* p, unsigned* pserial)
+{
+ unsigned serial;
+ boolean found = TRUE;
+ pipe_mutex_lock(serials_mutex);
+ if(!serials_hash)
+ serials_hash = util_hash_table_create(hash_ptr, compare_ptr);
+ serial = (unsigned)(uintptr_t)util_hash_table_get(serials_hash, p);
+ if(!serial)
+ {
+ /* time to stop logging... (you'll have a 100 GB logfile at least at this point)
+ * TODO: avoid this
+ */
+ serial = ++serials_last;
+ if(!serial)
+ {
+ debug_error("More than 2^32 objects detected, aborting.\n");
+ os_abort();
+ }
+
+ util_hash_table_set(serials_hash, p, (void*)(uintptr_t)serial);
+ found = FALSE;
+ }
+ pipe_mutex_unlock(serials_mutex);
+ *pserial = serial;
+ return found;
+}
+
+static void debug_serial_delete(void* p)
+{
+ pipe_mutex_lock(serials_mutex);
+ util_hash_table_remove(serials_hash, p);
+ pipe_mutex_unlock(serials_mutex);
+}
+
+#define STACK_LEN 64
+
+static void dump_stack(const char* symbols[STACK_LEN])
+{
+ unsigned i;
+ for(i = 0; i < STACK_LEN; ++i)
+ {
+ if(symbols[i])
+ os_stream_printf(stream, "%s\n", symbols[i]);
+ }
+ os_stream_write(stream, "\n", 1);
+}
+
+void debug_reference_slowpath(const struct pipe_reference* p, debug_reference_descriptor get_desc, int change)
+{
+ if(debug_refcnt_state < 0)
+ return;
+
+ if(!debug_refcnt_state)
+ {
+ const char* filename = debug_get_option("GALLIUM_REFCNT_LOG", NULL);
+ if(filename && filename[0])
+ stream = os_file_stream_create(filename);
+
+ if(stream)
+ debug_refcnt_state = 1;
+ else
+ debug_refcnt_state = -1;
+ }
+
+ if(debug_refcnt_state > 0)
+ {
+ struct debug_stack_frame frames[STACK_LEN];
+ const char* symbols[STACK_LEN];
+ char buf[1024];
+
+ unsigned i;
+ unsigned refcnt = p->count;
+ unsigned serial;
+ boolean existing = debug_serial((void*)p, &serial);
+
+ debug_backtrace_capture(frames, 1, STACK_LEN);
+ for(i = 0; i < STACK_LEN; ++i)
+ {
+ if(frames[i].function)
+ symbols[i] = debug_symbol_name_cached(frames[i].function);
+ else
+ symbols[i] = 0;
+ }
+
+ get_desc(buf, p);
+
+ if(!existing)
+ {
+ os_stream_printf(stream, "<%s> %p %u Create\n", buf, p, serial);
+ dump_stack(symbols);
+
+ /* this is there to provide a gradual change even if we don't see the initialization */
+ for(i = 1; i <= refcnt - change; ++i)
+ {
+ os_stream_printf(stream, "<%s> %p %u AddRef %u\n", buf, p, serial, i);
+ dump_stack(symbols);
+ }
+ }
+
+ if(change)
+ {
+ os_stream_printf(stream, "<%s> %p %u %s %u\n", buf, p, serial, change > 0 ? "AddRef" : "Release", refcnt);
+ dump_stack(symbols);
+ }
+
+ if(!refcnt)
+ {
+ debug_serial_delete((void*)p);
+ os_stream_printf(stream, "<%s> %p %u Destroy\n", buf, p, serial);
+ dump_stack(symbols);
+ }
+
+ os_stream_flush(stream);
+ }
+}
+#endif
diff --git a/src/gallium/auxiliary/util/u_debug_refcnt.h b/src/gallium/auxiliary/util/u_debug_refcnt.h
new file mode 100644
index 00000000000..bea2d1c478a
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_debug_refcnt.h
@@ -0,0 +1,63 @@
+/**************************************************************************
+ *
+ * Copyright 2010 Luca Barbieri
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef U_DEBUG_REFCNT_H_
+#define U_DEBUG_REFCNT_H_
+
+#include <pipe/p_config.h>
+#include <pipe/p_state.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef void (*debug_reference_descriptor)(char*, const struct pipe_reference*);
+
+#if defined(DEBUG) && (!defined(PIPE_OS_WINDOWS) || defined(PIPE_SUBSYSTEM_WINDOWS_USER))
+
+extern int debug_refcnt_state;
+
+void debug_reference_slowpath(const struct pipe_reference* p, debug_reference_descriptor get_desc, int change);
+
+static INLINE void debug_reference(const struct pipe_reference* p, debug_reference_descriptor get_desc, int change)
+{
+ if (debug_refcnt_state >= 0)
+ debug_reference_slowpath(p, get_desc, change);
+}
+
+#else
+
+static INLINE void debug_reference(const struct pipe_reference* p, debug_reference_descriptor get_desc, int change)
+{
+}
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* U_DEBUG_REFCNT_H_ */
diff --git a/src/gallium/auxiliary/util/u_debug_symbol.c b/src/gallium/auxiliary/util/u_debug_symbol.c
index 417d0cf04c9..332952af88b 100644
--- a/src/gallium/auxiliary/util/u_debug_symbol.c
+++ b/src/gallium/auxiliary/util/u_debug_symbol.c
@@ -33,9 +33,12 @@
*/
#include "pipe/p_compiler.h"
+#include "os/os_thread.h"
+#include "u_string.h"
#include "u_debug.h"
#include "u_debug_symbol.h"
+#include "u_hash_table.h"
#if defined(PIPE_SUBSYSTEM_WINDOWS_USER) && defined(PIPE_ARCH_X86)
@@ -67,21 +70,6 @@ BOOL WINAPI j_SymInitialize(HANDLE hProcess, PSTR UserSearchPath, BOOL fInvadePr
return FALSE;
}
-typedef BOOL (WINAPI *PFNSYMCLEANUP)(HANDLE);
-static PFNSYMCLEANUP pfnSymCleanup = NULL;
-
-static
-BOOL WINAPI j_SymCleanup(HANDLE hProcess)
-{
- if(
- (hModule_Imagehlp || (hModule_Imagehlp = LoadLibraryA("IMAGEHLP.DLL"))) &&
- (pfnSymCleanup || (pfnSymCleanup = (PFNSYMCLEANUP) GetProcAddress(hModule_Imagehlp, "SymCleanup")))
- )
- return pfnSymCleanup(hProcess);
- else
- return FALSE;
-}
-
typedef DWORD (WINAPI *PFNSYMSETOPTIONS)(DWORD);
static PFNSYMSETOPTIONS pfnSymSetOptions = NULL;
@@ -97,36 +85,6 @@ DWORD WINAPI j_SymSetOptions(DWORD SymOptions)
return FALSE;
}
-typedef BOOL (WINAPI *PFNSYMUNDNAME)(PIMAGEHLP_SYMBOL, PSTR, DWORD);
-static PFNSYMUNDNAME pfnSymUnDName = NULL;
-
-static
-BOOL WINAPI j_SymUnDName(PIMAGEHLP_SYMBOL Symbol, PSTR UnDecName, DWORD UnDecNameLength)
-{
- if(
- (hModule_Imagehlp || (hModule_Imagehlp = LoadLibraryA("IMAGEHLP.DLL"))) &&
- (pfnSymUnDName || (pfnSymUnDName = (PFNSYMUNDNAME) GetProcAddress(hModule_Imagehlp, "SymUnDName")))
- )
- return pfnSymUnDName(Symbol, UnDecName, UnDecNameLength);
- else
- return FALSE;
-}
-
-typedef PFUNCTION_TABLE_ACCESS_ROUTINE PFNSYMFUNCTIONTABLEACCESS;
-static PFNSYMFUNCTIONTABLEACCESS pfnSymFunctionTableAccess = NULL;
-
-static
-PVOID WINAPI j_SymFunctionTableAccess(HANDLE hProcess, DWORD AddrBase)
-{
- if(
- (hModule_Imagehlp || (hModule_Imagehlp = LoadLibraryA("IMAGEHLP.DLL"))) &&
- (pfnSymFunctionTableAccess || (pfnSymFunctionTableAccess = (PFNSYMFUNCTIONTABLEACCESS) GetProcAddress(hModule_Imagehlp, "SymFunctionTableAccess")))
- )
- return pfnSymFunctionTableAccess(hProcess, AddrBase);
- else
- return NULL;
-}
-
typedef PGET_MODULE_BASE_ROUTINE PFNSYMGETMODULEBASE;
static PFNSYMGETMODULEBASE pfnSymGetModuleBase = NULL;
@@ -142,41 +100,6 @@ DWORD WINAPI j_SymGetModuleBase(HANDLE hProcess, DWORD dwAddr)
return 0;
}
-typedef BOOL (WINAPI *PFNSTACKWALK)(DWORD, HANDLE, HANDLE, LPSTACKFRAME, LPVOID, PREAD_PROCESS_MEMORY_ROUTINE, PFUNCTION_TABLE_ACCESS_ROUTINE, PGET_MODULE_BASE_ROUTINE, PTRANSLATE_ADDRESS_ROUTINE);
-static PFNSTACKWALK pfnStackWalk = NULL;
-
-static
-BOOL WINAPI j_StackWalk(
- DWORD MachineType,
- HANDLE hProcess,
- HANDLE hThread,
- LPSTACKFRAME StackFrame,
- PVOID ContextRecord,
- PREAD_PROCESS_MEMORY_ROUTINE ReadMemoryRoutine,
- PFUNCTION_TABLE_ACCESS_ROUTINE FunctionTableAccessRoutine,
- PGET_MODULE_BASE_ROUTINE GetModuleBaseRoutine,
- PTRANSLATE_ADDRESS_ROUTINE TranslateAddress
-)
-{
- if(
- (hModule_Imagehlp || (hModule_Imagehlp = LoadLibraryA("IMAGEHLP.DLL"))) &&
- (pfnStackWalk || (pfnStackWalk = (PFNSTACKWALK) GetProcAddress(hModule_Imagehlp, "StackWalk")))
- )
- return pfnStackWalk(
- MachineType,
- hProcess,
- hThread,
- StackFrame,
- ContextRecord,
- ReadMemoryRoutine,
- FunctionTableAccessRoutine,
- GetModuleBaseRoutine,
- TranslateAddress
- );
- else
- return FALSE;
-}
-
typedef BOOL (WINAPI *PFNSYMGETSYMFROMADDR)(HANDLE, DWORD, LPDWORD, PIMAGEHLP_SYMBOL);
static PFNSYMGETSYMFROMADDR pfnSymGetSymFromAddr = NULL;
@@ -192,24 +115,9 @@ BOOL WINAPI j_SymGetSymFromAddr(HANDLE hProcess, DWORD Address, PDWORD Displacem
return FALSE;
}
-typedef BOOL (WINAPI *PFNSYMGETLINEFROMADDR)(HANDLE, DWORD, LPDWORD, PIMAGEHLP_LINE);
-static PFNSYMGETLINEFROMADDR pfnSymGetLineFromAddr = NULL;
-static
-BOOL WINAPI j_SymGetLineFromAddr(HANDLE hProcess, DWORD dwAddr, PDWORD pdwDisplacement, PIMAGEHLP_LINE Line)
-{
- if(
- (hModule_Imagehlp || (hModule_Imagehlp = LoadLibraryA("IMAGEHLP.DLL"))) &&
- (pfnSymGetLineFromAddr || (pfnSymGetLineFromAddr = (PFNSYMGETLINEFROMADDR) GetProcAddress(hModule_Imagehlp, "SymGetLineFromAddr")))
- )
- return pfnSymGetLineFromAddr(hProcess, dwAddr, pdwDisplacement, Line);
- else
- return FALSE;
-}
-
-
-static INLINE boolean
-debug_symbol_print_imagehlp(const void *addr)
+static INLINE void
+debug_symbol_name_imagehlp(const void *addr, char* buf, unsigned size)
{
HANDLE hProcess;
BYTE symbolBuffer[1024];
@@ -226,25 +134,95 @@ debug_symbol_print_imagehlp(const void *addr)
if(j_SymInitialize(hProcess, NULL, TRUE))
bSymInitialized = TRUE;
}
-
+
if(!j_SymGetSymFromAddr(hProcess, (DWORD)addr, &dwDisplacement, pSymbol))
- return FALSE;
+ buf[0] = 0;
+ else
+ {
+ strncpy(buf, pSymbol->Name, size);
+ buf[size - 1] = 0;
+ }
+}
+#endif
- debug_printf("\t%s\n", pSymbol->Name);
+#ifdef __GLIBC__
+#include <execinfo.h>
- return TRUE;
-
+/* This can only provide dynamic symbols, or binary offsets into a file.
+ *
+ * To fix this, post-process the output with tools/addr2line.sh
+ */
+static INLINE void
+debug_symbol_name_glibc(const void *addr, char* buf, unsigned size)
+{
+ char** syms = backtrace_symbols((void**)&addr, 1);
+ strncpy(buf, syms[0], size);
+ buf[size - 1] = 0;
+ free(syms);
}
#endif
-
void
-debug_symbol_print(const void *addr)
+debug_symbol_name(const void *addr, char* buf, unsigned size)
{
#if defined(PIPE_SUBSYSTEM_WINDOWS_USER) && defined(PIPE_ARCH_X86)
- if(debug_symbol_print_imagehlp(addr))
+ debug_symbol_name_imagehlp(addr, buf, size);
+ if(buf[0])
return;
#endif
-
- debug_printf("\t%p\n", addr);
+
+#ifdef __GLIBC__
+ debug_symbol_name_glibc(addr, buf, size);
+ if(buf[0])
+ return;
+#endif
+
+ util_snprintf(buf, size, "%p", addr);
+ buf[size - 1] = 0;
+}
+
+void
+debug_symbol_print(const void *addr)
+{
+ char buf[1024];
+ debug_symbol_name(addr, buf, sizeof(buf));
+ debug_printf("\t%s\n", buf);
+}
+
+struct util_hash_table* symbols_hash;
+pipe_mutex symbols_mutex;
+
+static unsigned hash_ptr(void* p)
+{
+ return (unsigned)(uintptr_t)p;
+}
+
+static int compare_ptr(void* a, void* b)
+{
+ if(a == b)
+ return 0;
+ else if(a < b)
+ return -1;
+ else
+ return 1;
+}
+
+const char*
+debug_symbol_name_cached(const void *addr)
+{
+ const char* name;
+ pipe_mutex_lock(symbols_mutex);
+ if(!symbols_hash)
+ symbols_hash = util_hash_table_create(hash_ptr, compare_ptr);
+ name = util_hash_table_get(symbols_hash, (void*)addr);
+ if(!name)
+ {
+ char buf[1024];
+ debug_symbol_name(addr, buf, sizeof(buf));
+ name = strdup(buf);
+
+ util_hash_table_set(symbols_hash, (void*)addr, (void*)name);
+ }
+ pipe_mutex_unlock(symbols_mutex);
+ return name;
}
diff --git a/src/gallium/auxiliary/util/u_debug_symbol.h b/src/gallium/auxiliary/util/u_debug_symbol.h
index 021586987b6..b247706c2a0 100644
--- a/src/gallium/auxiliary/util/u_debug_symbol.h
+++ b/src/gallium/auxiliary/util/u_debug_symbol.h
@@ -43,8 +43,13 @@ extern "C" {
void
-debug_symbol_print(const void *addr);
+debug_symbol_name(const void *addr, char* buf, unsigned size);
+
+const char*
+debug_symbol_name_cached(const void *addr);
+void
+debug_symbol_print(const void *addr);
#ifdef __cplusplus
}
diff --git a/src/gallium/auxiliary/util/u_dirty_flags.h b/src/gallium/auxiliary/util/u_dirty_flags.h
new file mode 100644
index 00000000000..7e1be45ad5a
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_dirty_flags.h
@@ -0,0 +1,28 @@
+#ifndef U_DIRTY_FLAGS_H
+#define U_DIRTY_FLAGS_H
+
+/* Here's a convenient list of dirty flags to use in a driver. Either
+ * include it directly or use it as a starting point for your own
+ * list.
+ */
+#define U_NEW_VIEWPORT 0x1
+#define U_NEW_RASTERIZER 0x2
+#define U_NEW_FS 0x4
+#define U_NEW_FS_CONSTANTS 0x8
+#define U_NEW_FS_SAMPLER_VIEW 0x10
+#define U_NEW_FS_SAMPLER_STATES 0x20
+#define U_NEW_VS 0x40
+#define U_NEW_VS_CONSTANTS 0x80
+#define U_NEW_VS_SAMPLER_VIEW 0x100
+#define U_NEW_VS_SAMPLER_STATES 0x200
+#define U_NEW_BLEND 0x400
+#define U_NEW_CLIP 0x800
+#define U_NEW_SCISSOR 0x1000
+#define U_NEW_POLYGON_STIPPLE 0x2000
+#define U_NEW_FRAMEBUFFER 0x4000
+#define U_NEW_VERTEX_ELEMENTS 0x8000
+#define U_NEW_VERTEX_BUFFER 0x10000
+#define U_NEW_QUERY 0x20000
+#define U_NEW_DEPTH_STENCIL 0x40000
+
+#endif
diff --git a/src/gallium/auxiliary/util/u_dirty_surfaces.h b/src/gallium/auxiliary/util/u_dirty_surfaces.h
index 99f260bf967..fd1bbe5ffdf 100644
--- a/src/gallium/auxiliary/util/u_dirty_surfaces.h
+++ b/src/gallium/auxiliary/util/u_dirty_surfaces.h
@@ -1,9 +1,39 @@
+/**************************************************************************
+ *
+ * Copyright 2010 Luca Barbieri
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
#ifndef U_DIRTY_SURFACES_H_
#define U_DIRTY_SURFACES_H_
+#include "pipe/p_state.h"
+
#include "util/u_double_list.h"
#include "util/u_math.h"
+struct pipe_context;
+
typedef void (*util_dirty_surface_flush_t) (struct pipe_context *, struct pipe_surface *);
struct util_dirty_surfaces
diff --git a/src/gallium/auxiliary/util/u_dl.h b/src/gallium/auxiliary/util/u_dl.h
index 2853b447c61..80a00ed6796 100644
--- a/src/gallium/auxiliary/util/u_dl.h
+++ b/src/gallium/auxiliary/util/u_dl.h
@@ -35,10 +35,13 @@
#if defined(PIPE_OS_WINDOWS)
# define UTIL_DL_EXT ".dll"
+# define UTIL_DL_PREFIX ""
#elif defined(PIPE_OS_APPLE)
# define UTIL_DL_EXT ".dylib"
+# define UTIL_DL_PREFIX "lib"
#else
# define UTIL_DL_EXT ".so"
+# define UTIL_DL_PREFIX "lib"
#endif
diff --git a/src/gallium/auxiliary/util/u_double_list.h b/src/gallium/auxiliary/util/u_double_list.h
index 53bb1342ddc..42adb1f0699 100644
--- a/src/gallium/auxiliary/util/u_double_list.h
+++ b/src/gallium/auxiliary/util/u_double_list.h
@@ -98,5 +98,20 @@ struct list_head
#define LIST_IS_EMPTY(__list) \
((__list)->next == (__list))
-
+#ifndef container_of
+#define container_of(ptr, sample, member) \
+ (void *)((char *)(ptr) \
+ - ((char *)&(sample)->member - (char *)(sample)))
+#endif
+
+#define LIST_FOR_EACH_ENTRY(pos, head, member) \
+ for (pos = container_of((head)->next, pos, member); \
+ &pos->member != (head); \
+ pos = container_of(pos->member.next, pos, member))
+
+#define LIST_FOR_EACH_ENTRY_SAFE(pos, storage, head, member) \
+ for (pos = container_of((head)->next, pos, member), \
+ storage = container_of(pos->member.next, pos, member); \
+ &pos->member != (head); \
+ pos = storage, storage = container_of(storage->member.next, storage, member))
#endif /*_U_DOUBLE_LIST_H_*/
diff --git a/src/gallium/auxiliary/util/u_draw.h b/src/gallium/auxiliary/util/u_draw.h
new file mode 100644
index 00000000000..f06d09ef91d
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_draw.h
@@ -0,0 +1,139 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef U_DRAW_H
+#define U_DRAW_H
+
+
+#include "pipe/p_compiler.h"
+#include "pipe/p_context.h"
+#include "pipe/p_state.h"
+
+
+static INLINE void
+util_draw_init_info(struct pipe_draw_info *info)
+{
+ memset(info, 0, sizeof(*info));
+ info->instance_count = 1;
+ info->max_index = 0xffffffff;
+}
+
+
+static INLINE void
+util_draw_arrays(struct pipe_context *pipe, uint mode, uint start, uint count)
+{
+ struct pipe_draw_info info;
+
+ util_draw_init_info(&info);
+ info.mode = mode;
+ info.start = start;
+ info.count = count;
+ info.min_index = start;
+ info.max_index = start + count - 1;
+
+ pipe->draw_vbo(pipe, &info);
+}
+
+static INLINE void
+util_draw_elements(struct pipe_context *pipe, int index_bias,
+ uint mode, uint start, uint count)
+{
+ struct pipe_draw_info info;
+
+ util_draw_init_info(&info);
+ info.indexed = TRUE;
+ info.mode = mode;
+ info.start = start;
+ info.count = count;
+ info.index_bias = index_bias;
+
+ pipe->draw_vbo(pipe, &info);
+}
+
+static INLINE void
+util_draw_arrays_instanced(struct pipe_context *pipe,
+ uint mode, uint start, uint count,
+ uint start_instance,
+ uint instance_count)
+{
+ struct pipe_draw_info info;
+
+ util_draw_init_info(&info);
+ info.mode = mode;
+ info.start = start;
+ info.count = count;
+ info.start_instance = start_instance;
+ info.instance_count = instance_count;
+ info.min_index = start;
+ info.max_index = start + count - 1;
+
+ pipe->draw_vbo(pipe, &info);
+}
+
+static INLINE void
+util_draw_elements_instanced(struct pipe_context *pipe,
+ int index_bias,
+ uint mode, uint start, uint count,
+ uint start_instance,
+ uint instance_count)
+{
+ struct pipe_draw_info info;
+
+ util_draw_init_info(&info);
+ info.indexed = TRUE;
+ info.mode = mode;
+ info.start = start;
+ info.count = count;
+ info.index_bias = index_bias;
+ info.start_instance = start_instance;
+ info.instance_count = instance_count;
+
+ pipe->draw_vbo(pipe, &info);
+}
+
+static INLINE void
+util_draw_range_elements(struct pipe_context *pipe,
+ int index_bias,
+ uint min_index,
+ uint max_index,
+ uint mode, uint start, uint count)
+{
+ struct pipe_draw_info info;
+
+ util_draw_init_info(&info);
+ info.indexed = TRUE;
+ info.mode = mode;
+ info.start = start;
+ info.count = count;
+ info.index_bias = index_bias;
+ info.min_index = min_index;
+ info.max_index = max_index;
+
+ pipe->draw_vbo(pipe, &info);
+}
+
+#endif
diff --git a/src/gallium/auxiliary/util/u_draw_quad.c b/src/gallium/auxiliary/util/u_draw_quad.c
index b37b48b5aef..0b6dc5880f3 100644
--- a/src/gallium/auxiliary/util/u_draw_quad.c
+++ b/src/gallium/auxiliary/util/u_draw_quad.c
@@ -60,7 +60,7 @@ util_draw_vertex_buffer(struct pipe_context *pipe,
/* note: vertex elements already set by caller */
/* draw */
- pipe->draw_arrays(pipe, prim_type, 0, num_verts);
+ util_draw_arrays(pipe, prim_type, 0, num_verts);
}
diff --git a/src/gallium/auxiliary/util/u_draw_quad.h b/src/gallium/auxiliary/util/u_draw_quad.h
index 42eb1844289..52994fe05c3 100644
--- a/src/gallium/auxiliary/util/u_draw_quad.h
+++ b/src/gallium/auxiliary/util/u_draw_quad.h
@@ -29,12 +29,18 @@
#define U_DRAWQUAD_H
+#include "pipe/p_compiler.h"
+#include "pipe/p_context.h"
+
+
#ifdef __cplusplus
extern "C" {
#endif
struct pipe_resource;
+#include "util/u_draw.h"
+
extern void
util_draw_vertex_buffer(struct pipe_context *pipe,
struct pipe_resource *vbuf, uint offset,
diff --git a/src/gallium/auxiliary/util/u_dump.h b/src/gallium/auxiliary/util/u_dump.h
index bdc73ac47d2..49536c0d593 100644
--- a/src/gallium/auxiliary/util/u_dump.h
+++ b/src/gallium/auxiliary/util/u_dump.h
@@ -71,9 +71,15 @@ const char *
util_dump_blend_func(unsigned value, boolean shortened);
const char *
+util_dump_logicop(unsigned value, boolean shortened);
+
+const char *
util_dump_func(unsigned value, boolean shortened);
const char *
+util_dump_stencil_op(unsigned value, boolean shortened);
+
+const char *
util_dump_tex_target(unsigned value, boolean shortened);
const char *
diff --git a/src/gallium/auxiliary/util/u_dump_defines.c b/src/gallium/auxiliary/util/u_dump_defines.c
index 96a22563473..692d4447c66 100644
--- a/src/gallium/auxiliary/util/u_dump_defines.c
+++ b/src/gallium/auxiliary/util/u_dump_defines.c
@@ -160,6 +160,49 @@ DEFINE_UTIL_DUMP_CONTINUOUS(blend_func)
static const char *
+util_dump_logicop_names[] = {
+ "PIPE_LOGICOP_CLEAR",
+ "PIPE_LOGICOP_NOR",
+ "PIPE_LOGICOP_AND_INVERTED",
+ "PIPE_LOGICOP_COPY_INVERTED",
+ "PIPE_LOGICOP_AND_REVERSE",
+ "PIPE_LOGICOP_INVERT",
+ "PIPE_LOGICOP_XOR",
+ "PIPE_LOGICOP_NAND",
+ "PIPE_LOGICOP_AND",
+ "PIPE_LOGICOP_EQUIV",
+ "PIPE_LOGICOP_NOOP",
+ "PIPE_LOGICOP_OR_INVERTED",
+ "PIPE_LOGICOP_COPY",
+ "PIPE_LOGICOP_OR_REVERSE",
+ "PIPE_LOGICOP_OR",
+ "PIPE_LOGICOP_SET"
+};
+
+static const char *
+util_dump_logicop_short_names[] = {
+ "clear",
+ "nor",
+ "and_inverted",
+ "copy_inverted",
+ "and_reverse",
+ "invert",
+ "xor",
+ "nand",
+ "and",
+ "equiv",
+ "noop",
+ "or_inverted",
+ "copy",
+ "or_reverse",
+ "or",
+ "set"
+};
+
+DEFINE_UTIL_DUMP_CONTINUOUS(logicop)
+
+
+static const char *
util_dump_func_names[] = {
"PIPE_FUNC_NEVER",
"PIPE_FUNC_LESS",
@@ -187,7 +230,35 @@ DEFINE_UTIL_DUMP_CONTINUOUS(func)
static const char *
+util_dump_stencil_op_names[] = {
+ "PIPE_STENCIL_OP_KEEP",
+ "PIPE_STENCIL_OP_ZERO",
+ "PIPE_STENCIL_OP_REPLACE",
+ "PIPE_STENCIL_OP_INCR",
+ "PIPE_STENCIL_OP_DECR",
+ "PIPE_STENCIL_OP_INCR_WRAP",
+ "PIPE_STENCIL_OP_DECR_WRAP",
+ "PIPE_STENCIL_OP_INVERT"
+};
+
+static const char *
+util_dump_stencil_op_short_names[] = {
+ "keep",
+ "zero",
+ "replace",
+ "incr",
+ "decr",
+ "incr_wrap",
+ "decr_wrap",
+ "invert"
+};
+
+DEFINE_UTIL_DUMP_CONTINUOUS(stencil_op)
+
+
+static const char *
util_dump_tex_target_names[] = {
+ "PIPE_BUFFER",
"PIPE_TEXTURE_1D",
"PIPE_TEXTURE_2D",
"PIPE_TEXTURE_3D",
@@ -196,6 +267,7 @@ util_dump_tex_target_names[] = {
static const char *
util_dump_tex_target_short_names[] = {
+ "buffer",
"1d",
"2d",
"3d",
diff --git a/src/gallium/auxiliary/util/u_dump_state.c b/src/gallium/auxiliary/util/u_dump_state.c
index 2ce643e90cd..cda5b8ba512 100644
--- a/src/gallium/auxiliary/util/u_dump_state.c
+++ b/src/gallium/auxiliary/util/u_dump_state.c
@@ -300,12 +300,13 @@ util_dump_rasterizer_state(struct os_stream *stream, const struct pipe_rasterize
util_dump_member(stream, bool, state, flatshade);
util_dump_member(stream, bool, state, light_twoside);
- util_dump_member(stream, uint, state, front_winding);
- util_dump_member(stream, uint, state, cull_mode);
- util_dump_member(stream, uint, state, fill_cw);
- util_dump_member(stream, uint, state, fill_ccw);
- util_dump_member(stream, bool, state, offset_cw);
- util_dump_member(stream, bool, state, offset_ccw);
+ util_dump_member(stream, uint, state, front_ccw);
+ util_dump_member(stream, uint, state, cull_face);
+ util_dump_member(stream, uint, state, fill_front);
+ util_dump_member(stream, uint, state, fill_back);
+ util_dump_member(stream, bool, state, offset_point);
+ util_dump_member(stream, bool, state, offset_line);
+ util_dump_member(stream, bool, state, offset_tri);
util_dump_member(stream, bool, state, scissor);
util_dump_member(stream, bool, state, poly_smooth);
util_dump_member(stream, bool, state, poly_stipple_enable);
diff --git a/src/gallium/auxiliary/util/u_dynarray.h b/src/gallium/auxiliary/util/u_dynarray.h
index 9d1c1713a7c..980cadf22d1 100644
--- a/src/gallium/auxiliary/util/u_dynarray.h
+++ b/src/gallium/auxiliary/util/u_dynarray.h
@@ -106,6 +106,9 @@ util_dynarray_trim(struct util_dynarray *buf)
#define util_dynarray_pop_ptr(buf, type) (type*)((char*)(buf)->data + ((buf)->size -= sizeof(type)))
#define util_dynarray_pop(buf, type) *util_dynarray_pop_ptr(buf, type)
#define util_dynarray_contains(buf, type) ((buf)->size >= sizeof(type))
+#define util_dynarray_element(buf, type, idx) ((type*)(buf)->data + (idx))
+#define util_dynarray_begin(buf) ((buf)->data)
+#define util_dynarray_end(buf) ((void*)util_dynarray_element((buf), char, (buf)->size))
#endif /* U_DYNARRAY_H */
diff --git a/src/gallium/auxiliary/util/u_format.c b/src/gallium/auxiliary/util/u_format.c
index c50c807eb89..4896faa12bf 100644
--- a/src/gallium/auxiliary/util/u_format.c
+++ b/src/gallium/auxiliary/util/u_format.c
@@ -120,11 +120,67 @@ util_format_write_4ub(enum pipe_format format, const uint8_t *src, unsigned src_
}
-static INLINE boolean
+boolean
+util_is_format_compatible(const struct util_format_description *src_desc,
+ const struct util_format_description *dst_desc)
+{
+ unsigned chan;
+
+ if (src_desc->format == dst_desc->format) {
+ return TRUE;
+ }
+
+ if (src_desc->layout != UTIL_FORMAT_LAYOUT_PLAIN ||
+ dst_desc->layout != UTIL_FORMAT_LAYOUT_PLAIN) {
+ return FALSE;
+ }
+
+ if (src_desc->block.bits != dst_desc->block.bits ||
+ src_desc->nr_channels != dst_desc->nr_channels ||
+ src_desc->colorspace != dst_desc->colorspace) {
+ return FALSE;
+ }
+
+ for (chan = 0; chan < 4; ++chan) {
+ if (src_desc->channel[chan].size !=
+ dst_desc->channel[chan].size) {
+ return FALSE;
+ }
+ }
+
+ for (chan = 0; chan < 4; ++chan) {
+ enum util_format_swizzle swizzle = dst_desc->swizzle[chan];
+
+ if (swizzle < 4) {
+ if (src_desc->swizzle[chan] != swizzle) {
+ return FALSE;
+ }
+ if ((src_desc->channel[swizzle].type !=
+ dst_desc->channel[swizzle].type) ||
+ (src_desc->channel[swizzle].normalized !=
+ dst_desc->channel[swizzle].normalized)) {
+ return FALSE;
+ }
+ }
+ }
+
+ return TRUE;
+}
+
+
+boolean
util_format_fits_8unorm(const struct util_format_description *format_desc)
{
unsigned chan;
+ /*
+ * After linearized sRGB values require more than 8bits.
+ */
+
+ if (format_desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) {
+ return FALSE;
+ }
+
switch (format_desc->layout) {
case UTIL_FORMAT_LAYOUT_S3TC:
@@ -189,11 +245,14 @@ util_format_translate(enum pipe_format dst_format,
const struct util_format_description *src_format_desc;
uint8_t *dst_row;
const uint8_t *src_row;
- unsigned y_step;
+ unsigned x_step, y_step;
unsigned dst_step;
unsigned src_step;
- if (dst_format == src_format) {
+ dst_format_desc = util_format_description(dst_format);
+ src_format_desc = util_format_description(src_format);
+
+ if (util_is_format_compatible(src_format_desc, dst_format_desc)) {
/*
* Trivial case.
*/
@@ -204,9 +263,6 @@ util_format_translate(enum pipe_format dst_format,
return;
}
- dst_format_desc = util_format_description(dst_format);
- src_format_desc = util_format_description(src_format);
-
assert(dst_x % dst_format_desc->block.width == 0);
assert(dst_y % dst_format_desc->block.height == 0);
assert(src_x % src_format_desc->block.width == 0);
@@ -221,6 +277,7 @@ util_format_translate(enum pipe_format dst_format,
*/
y_step = MAX2(dst_format_desc->block.height, src_format_desc->block.height);
+ x_step = MAX2(dst_format_desc->block.width, src_format_desc->block.width);
assert(y_step % dst_format_desc->block.height == 0);
assert(y_step % src_format_desc->block.height == 0);
@@ -237,7 +294,7 @@ util_format_translate(enum pipe_format dst_format,
unsigned tmp_stride;
uint8_t *tmp_row;
- tmp_stride = width * 4 * sizeof *tmp_row;
+ tmp_stride = MAX2(width, x_step) * 4 * sizeof *tmp_row;
tmp_row = MALLOC(y_step * tmp_stride);
if (!tmp_row)
return;
@@ -262,7 +319,7 @@ util_format_translate(enum pipe_format dst_format,
unsigned tmp_stride;
float *tmp_row;
- tmp_stride = width * 4 * sizeof *tmp_row;
+ tmp_stride = MAX2(width, x_step) * 4 * sizeof *tmp_row;
tmp_row = MALLOC(y_step * tmp_stride);
if (!tmp_row)
return;
diff --git a/src/gallium/auxiliary/util/u_format.h b/src/gallium/auxiliary/util/u_format.h
index 605b13bd114..03b73c0e98f 100644
--- a/src/gallium/auxiliary/util/u_format.h
+++ b/src/gallium/auxiliary/util/u_format.h
@@ -213,6 +213,16 @@ struct util_format_description
unsigned width, unsigned height);
/**
+ * Fetch a single pixel (i, j) from a block.
+ *
+ * XXX: Only defined for a very few select formats.
+ */
+ void
+ (*fetch_rgba_8unorm)(uint8_t *dst,
+ const uint8_t *src,
+ unsigned i, unsigned j);
+
+ /**
* Unpack pixel blocks to R32G32B32A32_FLOAT.
* Note: strides are in bytes.
*
@@ -332,12 +342,60 @@ util_format_name(enum pipe_format format)
assert(desc);
if (!desc) {
- return "???";
+ return "PIPE_FORMAT_???";
}
return desc->name;
}
+static INLINE const char *
+util_format_short_name(enum pipe_format format)
+{
+ const struct util_format_description *desc = util_format_description(format);
+
+ assert(desc);
+ if (!desc) {
+ return "???";
+ }
+
+ return desc->short_name;
+}
+
+/**
+ * Whether this format is plain, see UTIL_FORMAT_LAYOUT_PLAIN for more info.
+ */
+static INLINE boolean
+util_format_is_plain(enum pipe_format format)
+{
+ const struct util_format_description *desc = util_format_description(format);
+
+ if (!format) {
+ return FALSE;
+ }
+
+ return desc->layout == UTIL_FORMAT_LAYOUT_PLAIN ? TRUE : FALSE;
+}
+
+static INLINE boolean
+util_format_is_compressed(enum pipe_format format)
+{
+ const struct util_format_description *desc = util_format_description(format);
+
+ assert(desc);
+ if (!desc) {
+ return FALSE;
+ }
+
+ switch (desc->layout) {
+ case UTIL_FORMAT_LAYOUT_S3TC:
+ case UTIL_FORMAT_LAYOUT_RGTC:
+ /* XXX add other formats in the future */
+ return TRUE;
+ default:
+ return FALSE;
+ }
+}
+
static INLINE boolean
util_format_is_s3tc(enum pipe_format format)
{
@@ -382,6 +440,48 @@ util_format_is_depth_and_stencil(enum pipe_format format)
desc->swizzle[1] != UTIL_FORMAT_SWIZZLE_NONE) ? TRUE : FALSE;
}
+
+/**
+ * Give the RGBA colormask of the channels that can be represented in this
+ * format.
+ *
+ * That is, the channels whose values are preserved.
+ */
+static INLINE unsigned
+util_format_colormask(const struct util_format_description *desc)
+{
+ unsigned colormask;
+ unsigned chan;
+
+ switch (desc->colorspace) {
+ case UTIL_FORMAT_COLORSPACE_RGB:
+ case UTIL_FORMAT_COLORSPACE_SRGB:
+ case UTIL_FORMAT_COLORSPACE_YUV:
+ colormask = 0;
+ for (chan = 0; chan < 4; ++chan) {
+ if (desc->swizzle[chan] < 4) {
+ colormask |= (1 << chan);
+ }
+ }
+ return colormask;
+ case UTIL_FORMAT_COLORSPACE_ZS:
+ return 0;
+ default:
+ assert(0);
+ return 0;
+ }
+}
+
+
+/**
+ * Whether the src format can be blitted to destation format with a simple
+ * memcpy.
+ */
+boolean
+util_is_format_compatible(const struct util_format_description *src_desc,
+ const struct util_format_description *dst_desc);
+
+
/**
* Whether this format is a rgab8 variant.
*
@@ -573,6 +673,44 @@ util_format_has_alpha(enum pipe_format format)
}
/**
+ * Return the matching SRGB format, or PIPE_FORMAT_NONE if none.
+ */
+static INLINE enum pipe_format
+util_format_srgb(enum pipe_format format)
+{
+ switch (format) {
+ case PIPE_FORMAT_L8_UNORM:
+ return PIPE_FORMAT_L8_SRGB;
+ case PIPE_FORMAT_L8A8_UNORM:
+ return PIPE_FORMAT_L8A8_SRGB;
+ case PIPE_FORMAT_R8G8B8_UNORM:
+ return PIPE_FORMAT_R8G8B8_SRGB;
+ case PIPE_FORMAT_A8B8G8R8_UNORM:
+ return PIPE_FORMAT_A8B8G8R8_SRGB;
+ case PIPE_FORMAT_X8B8G8R8_UNORM:
+ return PIPE_FORMAT_X8B8G8R8_SRGB;
+ case PIPE_FORMAT_B8G8R8A8_UNORM:
+ return PIPE_FORMAT_B8G8R8A8_SRGB;
+ case PIPE_FORMAT_B8G8R8X8_UNORM:
+ return PIPE_FORMAT_B8G8R8X8_SRGB;
+ case PIPE_FORMAT_A8R8G8B8_UNORM:
+ return PIPE_FORMAT_A8R8G8B8_SRGB;
+ case PIPE_FORMAT_X8R8G8B8_UNORM:
+ return PIPE_FORMAT_X8R8G8B8_SRGB;
+ case PIPE_FORMAT_DXT1_RGB:
+ return PIPE_FORMAT_DXT1_SRGB;
+ case PIPE_FORMAT_DXT1_RGBA:
+ return PIPE_FORMAT_DXT1_SRGBA;
+ case PIPE_FORMAT_DXT3_RGBA:
+ return PIPE_FORMAT_DXT3_SRGBA;
+ case PIPE_FORMAT_DXT5_RGBA:
+ return PIPE_FORMAT_DXT5_SRGBA;
+ default:
+ return PIPE_FORMAT_NONE;
+ }
+}
+
+/**
* Return the number of components stored.
* Formats with block size != 1x1 will always have 1 component (the block).
*/
@@ -615,6 +753,9 @@ util_format_write_4ub(enum pipe_format format,
* Generic format conversion;
*/
+boolean
+util_format_fits_8unorm(const struct util_format_description *format_desc);
+
void
util_format_translate(enum pipe_format dst_format,
void *dst, unsigned dst_stride,
diff --git a/src/gallium/auxiliary/util/u_format_other.c b/src/gallium/auxiliary/util/u_format_other.c
index 723fa8c3bf9..fa42ec37138 100644
--- a/src/gallium/auxiliary/util/u_format_other.c
+++ b/src/gallium/auxiliary/util/u_format_other.c
@@ -121,6 +121,15 @@ util_format_r1_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
* A.k.a. D3DFMT_CxV8U8
*/
+static uint8_t
+r8g8bx_derive(int16_t r, int16_t g)
+{
+ /* Derive blue from red and green components.
+ * Apparently, we must always use integers to perform calculations,
+ * otherwise the results won't match D3D's CxV8U8 definition.
+ */
+ return (uint8_t)sqrtf(0x7f * 0x7f - r * r - g * g) * 0xff / 0x7f;
+}
void
util_format_r8g8bx_snorm_unpack_rgba_float(float *dst_row, unsigned dst_stride,
@@ -145,7 +154,7 @@ util_format_r8g8bx_snorm_unpack_rgba_float(float *dst_row, unsigned dst_stride,
dst[0] = (float)(r * (1.0f/0x7f)); /* r */
dst[1] = (float)(g * (1.0f/0x7f)); /* g */
- dst[2] = sqrtf(1.0f - dst[0] * dst[0] - dst[1] * dst[1]); /* b */
+ dst[2] = r8g8bx_derive(r, g) * (1.0f/0xff); /* b */
dst[3] = 1.0f; /* a */
dst += 4;
}
@@ -177,7 +186,7 @@ util_format_r8g8bx_snorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_strid
dst[0] = (uint8_t)(((uint16_t)MAX2(r, 0)) * 0xff / 0x7f); /* r */
dst[1] = (uint8_t)(((uint16_t)MAX2(g, 0)) * 0xff / 0x7f); /* g */
- dst[2] = (uint8_t)sqrtf(0x7f*0x7f - r * r - g * g) * 0xff / 0x7f; /* b */
+ dst[2] = r8g8bx_derive(r, g); /* b */
dst[3] = 255; /* a */
dst += 4;
}
@@ -262,6 +271,6 @@ util_format_r8g8bx_snorm_fetch_rgba_float(float *dst, const uint8_t *src,
dst[0] = r * (1.0f/0x7f); /* r */
dst[1] = g * (1.0f/0x7f); /* g */
- dst[2] = sqrtf(1.0f - dst[0] * dst[0] - dst[1] * dst[1]); /* b */
+ dst[2] = r8g8bx_derive(r, g) * (1.0f/0xff); /* b */
dst[3] = 1.0f; /* a */
}
diff --git a/src/gallium/auxiliary/util/u_format_pack.py b/src/gallium/auxiliary/util/u_format_pack.py
index 0c1bbc84c17..6d0016c0ad8 100644
--- a/src/gallium/auxiliary/util/u_format_pack.py
+++ b/src/gallium/auxiliary/util/u_format_pack.py
@@ -37,9 +37,6 @@
'''
-import sys
-import math
-
from u_format_parse import *
diff --git a/src/gallium/auxiliary/util/u_format_parse.py b/src/gallium/auxiliary/util/u_format_parse.py
index 7076c676aaf..ddb9f2443d9 100755
--- a/src/gallium/auxiliary/util/u_format_parse.py
+++ b/src/gallium/auxiliary/util/u_format_parse.py
@@ -43,7 +43,7 @@ ZS = 'zs'
def is_pot(x):
- return (x & (x - 1)) == 0;
+ return (x & (x - 1)) == 0
VERY_LARGE = 99999999999999999999999
diff --git a/src/gallium/auxiliary/util/u_format_s3tc.c b/src/gallium/auxiliary/util/u_format_s3tc.c
index 5b279b8fe26..bb989c29d81 100644
--- a/src/gallium/auxiliary/util/u_format_s3tc.c
+++ b/src/gallium/auxiliary/util/u_format_s3tc.c
@@ -120,7 +120,7 @@ util_format_s3tc_init(void)
library = util_dl_open(DXTN_LIBNAME);
if (!library) {
debug_printf("couldn't open " DXTN_LIBNAME ", software DXTn "
- "compression/decompression unavailable");
+ "compression/decompression unavailable\n");
return;
}
@@ -142,7 +142,7 @@ util_format_s3tc_init(void)
!util_format_dxtn_pack) {
debug_printf("couldn't reference all symbols in " DXTN_LIBNAME
", software DXTn compression/decompression "
- "unavailable");
+ "unavailable\n");
util_dl_close(library);
return;
}
diff --git a/src/gallium/auxiliary/util/u_format_srgb.py b/src/gallium/auxiliary/util/u_format_srgb.py
index a4c76dc00b3..3e8000f3687 100644
--- a/src/gallium/auxiliary/util/u_format_srgb.py
+++ b/src/gallium/auxiliary/util/u_format_srgb.py
@@ -39,7 +39,6 @@
'''
-import sys
import math
diff --git a/src/gallium/auxiliary/util/u_format_table.py b/src/gallium/auxiliary/util/u_format_table.py
index ae9a5981973..f0b407b8b8e 100755
--- a/src/gallium/auxiliary/util/u_format_table.py
+++ b/src/gallium/auxiliary/util/u_format_table.py
@@ -132,12 +132,17 @@ def write_format_table(formats):
if format.colorspace != ZS:
print " &util_format_%s_unpack_rgba_8unorm," % format.short_name()
print " &util_format_%s_pack_rgba_8unorm," % format.short_name()
+ if format.layout == 's3tc':
+ print " &util_format_%s_fetch_rgba_8unorm," % format.short_name()
+ else:
+ print " NULL, /* fetch_rgba_8unorm */"
print " &util_format_%s_unpack_rgba_float," % format.short_name()
print " &util_format_%s_pack_rgba_float," % format.short_name()
print " &util_format_%s_fetch_rgba_float," % format.short_name()
else:
print " NULL, /* unpack_rgba_8unorm */"
print " NULL, /* pack_rgba_8unorm */"
+ print " NULL, /* fetch_rgba_8unorm */"
print " NULL, /* unpack_rgba_float */"
print " NULL, /* pack_rgba_float */"
print " NULL, /* fetch_rgba_float */"
diff --git a/src/gallium/auxiliary/util/u_framebuffer.c b/src/gallium/auxiliary/util/u_framebuffer.c
new file mode 100644
index 00000000000..7803ec6a8b5
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_framebuffer.c
@@ -0,0 +1,148 @@
+/**************************************************************************
+ *
+ * Copyright 2009-2010 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * @file
+ * Framebuffer utility functions.
+ *
+ * @author Brian Paul
+ */
+
+
+#include "pipe/p_screen.h"
+#include "pipe/p_state.h"
+#include "pipe/p_defines.h"
+#include "util/u_inlines.h"
+
+#include "util/u_memory.h"
+#include "util/u_framebuffer.h"
+
+
+/**
+ * Compare pipe_framebuffer_state objects.
+ * \return TRUE if same, FALSE if different
+ */
+boolean
+util_framebuffer_state_equal(const struct pipe_framebuffer_state *dst,
+ const struct pipe_framebuffer_state *src)
+{
+ unsigned i;
+
+ if (dst->width != src->width ||
+ dst->height != src->height)
+ return FALSE;
+
+ for (i = 0; i < Elements(src->cbufs); i++) {
+ if (dst->cbufs[i] != src->cbufs[i]) {
+ return FALSE;
+ }
+ }
+
+ if (dst->nr_cbufs != src->nr_cbufs) {
+ return FALSE;
+ }
+
+ if (dst->zsbuf != src->zsbuf) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+/**
+ * Copy framebuffer state from src to dst, updating refcounts.
+ */
+void
+util_copy_framebuffer_state(struct pipe_framebuffer_state *dst,
+ const struct pipe_framebuffer_state *src)
+{
+ unsigned i;
+
+ dst->width = src->width;
+ dst->height = src->height;
+
+ for (i = 0; i < src->nr_cbufs; i++)
+ pipe_surface_reference(&dst->cbufs[i], src->cbufs[i]);
+
+ for (i = src->nr_cbufs; i < dst->nr_cbufs; i++)
+ pipe_surface_reference(&dst->cbufs[i], NULL);
+
+ dst->nr_cbufs = src->nr_cbufs;
+
+ pipe_surface_reference(&dst->zsbuf, src->zsbuf);
+}
+
+
+void
+util_unreference_framebuffer_state(struct pipe_framebuffer_state *fb)
+{
+ unsigned i;
+
+ for (i = 0; i < fb->nr_cbufs; i++) {
+ pipe_surface_reference(&fb->cbufs[i], NULL);
+ }
+
+ pipe_surface_reference(&fb->zsbuf, NULL);
+
+ fb->width = fb->height = 0;
+ fb->nr_cbufs = 0;
+}
+
+
+/* Where multiple sizes are allowed for framebuffer surfaces, find the
+ * minimum width and height of all bound surfaces.
+ */
+boolean
+util_framebuffer_min_size(const struct pipe_framebuffer_state *fb,
+ unsigned *width,
+ unsigned *height)
+{
+ unsigned w = ~0;
+ unsigned h = ~0;
+ unsigned i;
+
+ for (i = 0; i < fb->nr_cbufs; i++) {
+ w = MIN2(w, fb->cbufs[i]->width);
+ h = MIN2(h, fb->cbufs[i]->height);
+ }
+
+ if (fb->zsbuf) {
+ w = MIN2(w, fb->zsbuf->width);
+ h = MIN2(h, fb->zsbuf->height);
+ }
+
+ if (w == ~0) {
+ *width = 0;
+ *height = 0;
+ return FALSE;
+ }
+ else {
+ *width = w;
+ *height = h;
+ return TRUE;
+ }
+}
diff --git a/src/gallium/auxiliary/util/u_framebuffer.h b/src/gallium/auxiliary/util/u_framebuffer.h
new file mode 100644
index 00000000000..e7dc1e9e41d
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_framebuffer.h
@@ -0,0 +1,54 @@
+/**************************************************************************
+ *
+ * Copyright 2009-2010 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#ifndef U_FRAMEBUFFER_H
+#define U_FRAMEBUFFER_H
+
+
+#include "pipe/p_compiler.h"
+#include "pipe/p_state.h"
+
+
+extern boolean
+util_framebuffer_state_equal(const struct pipe_framebuffer_state *dst,
+ const struct pipe_framebuffer_state *src);
+
+extern void
+util_copy_framebuffer_state(struct pipe_framebuffer_state *dst,
+ const struct pipe_framebuffer_state *src);
+
+
+extern void
+util_unreference_framebuffer_state(struct pipe_framebuffer_state *fb);
+
+
+extern boolean
+util_framebuffer_min_size(const struct pipe_framebuffer_state *fb,
+ unsigned *width,
+ unsigned *height);
+
+#endif /* U_FRAMEBUFFER_H */
diff --git a/src/gallium/auxiliary/util/u_gen_mipmap.c b/src/gallium/auxiliary/util/u_gen_mipmap.c
index eee6030ddcc..6a931a95819 100644
--- a/src/gallium/auxiliary/util/u_gen_mipmap.c
+++ b/src/gallium/auxiliary/util/u_gen_mipmap.c
@@ -1255,6 +1255,7 @@ fallback_gen_mipmap(struct gen_mipmap_state *ctx,
make_1d_mipmap(ctx, pt, face, baseLevel, lastLevel);
break;
case PIPE_TEXTURE_2D:
+ case PIPE_TEXTURE_RECT:
case PIPE_TEXTURE_CUBE:
make_2d_mipmap(ctx, pt, face, baseLevel, lastLevel);
break;
@@ -1295,8 +1296,7 @@ util_create_gen_mipmap(struct pipe_context *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.cull_face = PIPE_FACE_NONE;
ctx->rasterizer.gl_rasterization_rules = 1;
/* sampler state */
@@ -1328,8 +1328,10 @@ util_create_gen_mipmap(struct pipe_context *pipe,
}
/* fragment shader */
- ctx->fs2d = util_make_fragment_tex_shader(pipe, TGSI_TEXTURE_2D);
- ctx->fsCube = util_make_fragment_tex_shader(pipe, TGSI_TEXTURE_CUBE);
+ ctx->fs2d = util_make_fragment_tex_shader(pipe, TGSI_TEXTURE_2D,
+ TGSI_INTERPOLATE_LINEAR);
+ ctx->fsCube = util_make_fragment_tex_shader(pipe, TGSI_TEXTURE_CUBE,
+ TGSI_INTERPOLATE_LINEAR);
/* vertex data that doesn't change */
for (i = 0; i < 4; i++) {
@@ -1494,7 +1496,7 @@ util_gen_mipmap(struct gen_mipmap_state *ctx,
/* check if we can render in the texture's format */
if (!screen->is_format_supported(screen, psv->format, PIPE_TEXTURE_2D,
- PIPE_BIND_RENDER_TARGET, 0)) {
+ pt->nr_samples, PIPE_BIND_RENDER_TARGET, 0)) {
fallback_gen_mipmap(ctx, pt, face, baseLevel, lastLevel);
return;
}
diff --git a/src/gallium/auxiliary/util/u_half.py b/src/gallium/auxiliary/util/u_half.py
index 8007482e971..915cf3b9273 100644
--- a/src/gallium/auxiliary/util/u_half.py
+++ b/src/gallium/auxiliary/util/u_half.py
@@ -83,11 +83,11 @@ for i in xrange(1, 1024):
# normalize number
while (m & 0x00800000) == 0:
- e -= 0x00800000;
- m <<= 1;
+ e -= 0x00800000
+ m <<= 1
- m &= ~0x00800000;
- e += 0x38800000;
+ m &= ~0x00800000
+ e += 0x38800000
value(m | e)
# normals
diff --git a/src/gallium/auxiliary/util/u_index_modify.c b/src/gallium/auxiliary/util/u_index_modify.c
new file mode 100644
index 00000000000..65b079ed537
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_index_modify.c
@@ -0,0 +1,127 @@
+/*
+ * Copyright 2010 Marek Olšák <[email protected]>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "pipe/p_context.h"
+#include "util/u_index_modify.h"
+#include "util/u_inlines.h"
+
+void util_shorten_ubyte_elts(struct pipe_context *context,
+ struct pipe_resource **elts,
+ int index_bias,
+ unsigned start,
+ unsigned count)
+{
+ struct pipe_screen* screen = context->screen;
+ struct pipe_resource* new_elts;
+ unsigned char *in_map;
+ unsigned short *out_map;
+ struct pipe_transfer *src_transfer, *dst_transfer;
+ unsigned i;
+
+ new_elts = pipe_buffer_create(screen,
+ PIPE_BIND_INDEX_BUFFER,
+ 2 * count);
+
+ in_map = pipe_buffer_map(context, *elts, PIPE_TRANSFER_READ, &src_transfer);
+ out_map = pipe_buffer_map(context, new_elts, PIPE_TRANSFER_WRITE, &dst_transfer);
+
+ in_map += start;
+
+ for (i = 0; i < count; i++) {
+ *out_map = (unsigned short)(*in_map + index_bias);
+ in_map++;
+ out_map++;
+ }
+
+ pipe_buffer_unmap(context, *elts, src_transfer);
+ pipe_buffer_unmap(context, new_elts, dst_transfer);
+
+ *elts = new_elts;
+}
+
+void util_rebuild_ushort_elts(struct pipe_context *context,
+ struct pipe_resource **elts,
+ int index_bias,
+ unsigned start, unsigned count)
+{
+ struct pipe_transfer *in_transfer = NULL;
+ struct pipe_transfer *out_transfer = NULL;
+ struct pipe_resource *new_elts;
+ unsigned short *in_map;
+ unsigned short *out_map;
+ unsigned i;
+
+ new_elts = pipe_buffer_create(context->screen,
+ PIPE_BIND_INDEX_BUFFER,
+ 2 * count);
+
+ in_map = pipe_buffer_map(context, *elts,
+ PIPE_TRANSFER_READ, &in_transfer);
+ out_map = pipe_buffer_map(context, new_elts,
+ PIPE_TRANSFER_WRITE, &out_transfer);
+
+ in_map += start;
+ for (i = 0; i < count; i++) {
+ *out_map = (unsigned short)(*in_map + index_bias);
+ in_map++;
+ out_map++;
+ }
+
+ pipe_buffer_unmap(context, *elts, in_transfer);
+ pipe_buffer_unmap(context, new_elts, out_transfer);
+
+ *elts = new_elts;
+}
+
+void util_rebuild_uint_elts(struct pipe_context *context,
+ struct pipe_resource **elts,
+ int index_bias,
+ unsigned start, unsigned count)
+{
+ struct pipe_transfer *in_transfer = NULL;
+ struct pipe_transfer *out_transfer = NULL;
+ struct pipe_resource *new_elts;
+ unsigned int *in_map;
+ unsigned int *out_map;
+ unsigned i;
+
+ new_elts = pipe_buffer_create(context->screen,
+ PIPE_BIND_INDEX_BUFFER,
+ 2 * count);
+
+ in_map = pipe_buffer_map(context, *elts,
+ PIPE_TRANSFER_READ, &in_transfer);
+ out_map = pipe_buffer_map(context, new_elts,
+ PIPE_TRANSFER_WRITE, &out_transfer);
+
+ in_map += start;
+ for (i = 0; i < count; i++) {
+ *out_map = (unsigned int)(*in_map + index_bias);
+ in_map++;
+ out_map++;
+ }
+
+ pipe_buffer_unmap(context, *elts, in_transfer);
+ pipe_buffer_unmap(context, new_elts, out_transfer);
+
+ *elts = new_elts;
+}
diff --git a/src/gallium/auxiliary/util/u_index_modify.h b/src/gallium/auxiliary/util/u_index_modify.h
new file mode 100644
index 00000000000..01a6cae94fc
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_index_modify.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2010 Marek Olšák <[email protected]>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef UTIL_INDEX_MODIFY_H
+#define UTIL_INDEX_MODIFY_H
+
+void util_shorten_ubyte_elts(struct pipe_context *context,
+ struct pipe_resource **elts,
+ int index_bias,
+ unsigned start,
+ unsigned count);
+
+void util_rebuild_ushort_elts(struct pipe_context *context,
+ struct pipe_resource **elts,
+ int index_bias,
+ unsigned start, unsigned count);
+
+void util_rebuild_uint_elts(struct pipe_context *context,
+ struct pipe_resource **elts,
+ int index_bias,
+ unsigned start, unsigned count);
+#endif
diff --git a/src/gallium/auxiliary/util/u_inlines.h b/src/gallium/auxiliary/util/u_inlines.h
index a48689ee8be..6ed39561fbe 100644
--- a/src/gallium/auxiliary/util/u_inlines.h
+++ b/src/gallium/auxiliary/util/u_inlines.h
@@ -33,6 +33,8 @@
#include "pipe/p_state.h"
#include "pipe/p_screen.h"
#include "util/u_debug.h"
+#include "util/u_debug_describe.h"
+#include "util/u_debug_refcnt.h"
#include "util/u_atomic.h"
#include "util/u_box.h"
#include "util/u_math.h"
@@ -67,7 +69,9 @@ pipe_is_referenced(struct pipe_reference *reference)
* \return TRUE if the object's refcount hits zero and should be destroyed.
*/
static INLINE boolean
-pipe_reference(struct pipe_reference *ptr, struct pipe_reference *reference)
+pipe_reference_described(struct pipe_reference *ptr,
+ struct pipe_reference *reference,
+ debug_reference_descriptor get_desc)
{
boolean destroy = FALSE;
@@ -76,6 +80,7 @@ pipe_reference(struct pipe_reference *ptr, struct pipe_reference *reference)
if (reference) {
assert(pipe_is_referenced(reference));
p_atomic_inc(&reference->count);
+ debug_reference(reference, get_desc, 1);
}
if (ptr) {
@@ -83,41 +88,49 @@ pipe_reference(struct pipe_reference *ptr, struct pipe_reference *reference)
if (p_atomic_dec_zero(&ptr->count)) {
destroy = TRUE;
}
+ debug_reference(ptr, get_desc, -1);
}
}
return destroy;
}
+static INLINE boolean
+pipe_reference(struct pipe_reference *ptr, struct pipe_reference *reference)
+{
+ return pipe_reference_described(ptr, reference,
+ (debug_reference_descriptor)debug_describe_reference);
+}
static INLINE void
pipe_surface_reference(struct pipe_surface **ptr, struct pipe_surface *surf)
{
struct pipe_surface *old_surf = *ptr;
- if (pipe_reference(&(*ptr)->reference, &surf->reference))
+ if (pipe_reference_described(&(*ptr)->reference, &surf->reference,
+ (debug_reference_descriptor)debug_describe_surface))
old_surf->texture->screen->tex_surface_destroy(old_surf);
*ptr = surf;
}
-
static INLINE void
pipe_resource_reference(struct pipe_resource **ptr, struct pipe_resource *tex)
{
struct pipe_resource *old_tex = *ptr;
- if (pipe_reference(&(*ptr)->reference, &tex->reference))
+ if (pipe_reference_described(&(*ptr)->reference, &tex->reference,
+ (debug_reference_descriptor)debug_describe_resource))
old_tex->screen->resource_destroy(old_tex->screen, old_tex);
*ptr = tex;
}
-
static INLINE void
pipe_sampler_view_reference(struct pipe_sampler_view **ptr, struct pipe_sampler_view *view)
{
struct pipe_sampler_view *old_view = *ptr;
- if (pipe_reference(&(*ptr)->reference, &view->reference))
+ if (pipe_reference_described(&(*ptr)->reference, &view->reference,
+ (debug_reference_descriptor)debug_describe_sampler_view))
old_view->context->sampler_view_destroy(old_view->context, old_view);
*ptr = view;
}
@@ -369,6 +382,23 @@ pipe_transfer_destroy( struct pipe_context *context,
}
+static INLINE boolean util_get_offset(
+ const struct pipe_rasterizer_state *templ,
+ unsigned fill_mode)
+{
+ switch(fill_mode) {
+ case PIPE_POLYGON_MODE_POINT:
+ return templ->offset_point;
+ case PIPE_POLYGON_MODE_LINE:
+ return templ->offset_line;
+ case PIPE_POLYGON_MODE_FILL:
+ return templ->offset_tri;
+ default:
+ assert(0);
+ return FALSE;
+ }
+}
+
#ifdef __cplusplus
}
#endif
diff --git a/src/gallium/auxiliary/util/u_linear.h b/src/gallium/auxiliary/util/u_linear.h
index 42c40b2aa75..81ffc9fb27d 100644
--- a/src/gallium/auxiliary/util/u_linear.h
+++ b/src/gallium/auxiliary/util/u_linear.h
@@ -33,6 +33,7 @@
#ifndef U_LINEAR_H
#define U_LINEAR_H
+#include "pipe/p_compiler.h"
#include "pipe/p_format.h"
struct u_linear_format_block
diff --git a/src/gallium/auxiliary/util/u_linkage.c b/src/gallium/auxiliary/util/u_linkage.c
new file mode 100644
index 00000000000..2f6f41ba843
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_linkage.c
@@ -0,0 +1,149 @@
+/**************************************************************************
+ *
+ * Copyright 2010 Luca Barbieri
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "util/u_debug.h"
+#include "pipe/p_shader_tokens.h"
+#include "tgsi/tgsi_parse.h"
+#include "tgsi/tgsi_scan.h"
+#include "util/u_linkage.h"
+
+/* we must only record the registers that are actually used, not just declared */
+static INLINE boolean
+util_semantic_set_test_and_set(struct util_semantic_set *set, unsigned value)
+{
+ unsigned mask = 1 << (value % (sizeof(long) * 8));
+ unsigned long *p = &set->masks[value / (sizeof(long) * 8)];
+ unsigned long v = *p & mask;
+ *p |= mask;
+ return !!v;
+}
+
+unsigned
+util_semantic_set_from_program_file(struct util_semantic_set *set, const struct tgsi_token *tokens, enum tgsi_file_type file)
+{
+ struct tgsi_shader_info info;
+ struct tgsi_parse_context parse;
+ unsigned count = 0;
+ ubyte *semantic_name;
+ ubyte *semantic_index;
+
+ tgsi_scan_shader(tokens, &info);
+
+ if(file == TGSI_FILE_INPUT)
+ {
+ semantic_name = info.input_semantic_name;
+ semantic_index = info.input_semantic_index;
+ }
+ else if(file == TGSI_FILE_OUTPUT)
+ {
+ semantic_name = info.output_semantic_name;
+ semantic_index = info.output_semantic_index;
+ }
+ else
+ {
+ assert(0);
+ semantic_name = NULL;
+ semantic_index = NULL;
+ }
+
+ tgsi_parse_init(&parse, tokens);
+
+ memset(set->masks, 0, sizeof(set->masks));
+ while(!tgsi_parse_end_of_tokens(&parse))
+ {
+ tgsi_parse_token(&parse);
+
+ if(parse.FullToken.Token.Type == TGSI_TOKEN_TYPE_INSTRUCTION)
+ {
+ const struct tgsi_full_instruction *finst = &parse.FullToken.FullInstruction;
+ unsigned i;
+ for(i = 0; i < finst->Instruction.NumDstRegs; ++i)
+ {
+ if(finst->Dst[i].Register.File == file)
+ {
+ unsigned idx = finst->Dst[i].Register.Index;
+ if(semantic_name[idx] == TGSI_SEMANTIC_GENERIC)
+ {
+ if(!util_semantic_set_test_and_set(set, semantic_index[idx]))
+ ++count;
+ }
+ }
+ }
+
+ for(i = 0; i < finst->Instruction.NumSrcRegs; ++i)
+ {
+ if(finst->Src[i].Register.File == file)
+ {
+ unsigned idx = finst->Src[i].Register.Index;
+ if(semantic_name[idx] == TGSI_SEMANTIC_GENERIC)
+ {
+ if(!util_semantic_set_test_and_set(set, semantic_index[idx]))
+ ++count;
+ }
+ }
+ }
+ }
+ }
+ tgsi_parse_free(&parse);
+
+ return count;
+}
+
+#define UTIL_SEMANTIC_SET_FOR_EACH(i, set) for(i = 0; i < 256; ++i) if(set->masks[i / (sizeof(long) * 8)] & (1 << (i % (sizeof(long) * 8))))
+
+void
+util_semantic_layout_from_set(unsigned char *layout, const struct util_semantic_set *set, unsigned efficient_slots, unsigned num_slots)
+{
+ int first = -1;
+ int last = -1;
+ unsigned i;
+
+ memset(layout, 0xff, num_slots);
+
+ UTIL_SEMANTIC_SET_FOR_EACH(i, set)
+ {
+ if(first < 0)
+ first = i;
+ last = i;
+ }
+
+ if(last < efficient_slots)
+ {
+ UTIL_SEMANTIC_SET_FOR_EACH(i, set)
+ layout[i] = i;
+ }
+ else if((last - first) < efficient_slots)
+ {
+ UTIL_SEMANTIC_SET_FOR_EACH(i, set)
+ layout[i - first] = i;
+ }
+ else
+ {
+ unsigned idx = 0;
+ UTIL_SEMANTIC_SET_FOR_EACH(i, set)
+ layout[idx++] = i;
+ }
+}
diff --git a/src/gallium/auxiliary/util/u_linkage.h b/src/gallium/auxiliary/util/u_linkage.h
new file mode 100644
index 00000000000..4720e0ee603
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_linkage.h
@@ -0,0 +1,66 @@
+/**************************************************************************
+ *
+ * Copyright 2010 Luca Barbieri
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef U_LINKAGE_H_
+#define U_LINKAGE_H_
+
+#include "pipe/p_compiler.h"
+#include "pipe/p_shader_tokens.h"
+
+struct util_semantic_set
+{
+ unsigned long masks[256 / 8 / sizeof(unsigned long)];
+};
+
+static INLINE bool
+util_semantic_set_contains(struct util_semantic_set *set, unsigned char value)
+{
+ return !!(set->masks[value / (sizeof(long) * 8)] & (1 << (value / (sizeof(long) * 8))));
+}
+
+unsigned util_semantic_set_from_program_file(struct util_semantic_set *set, const struct tgsi_token *tokens, enum tgsi_file_type file);
+
+/* efficient_slots is the number of slots such that hardware performance is
+ * the same for using that amount, with holes, or less slots but with less
+ * holes.
+ *
+ * num_slots is the size of the layout array and hardware limit instead.
+ *
+ * efficient_slots == 0 or efficient_solts == num_slots are typical settings.
+ */
+void util_semantic_layout_from_set(unsigned char *layout, const struct util_semantic_set *set, unsigned efficient_slots, unsigned num_slots);
+
+static INLINE void
+util_semantic_table_from_layout(unsigned char *table, unsigned char *layout, unsigned char first_slot_value, unsigned char num_slots)
+{
+ int i;
+ memset(table, 0xff, sizeof(table));
+
+ for(i = 0; i < num_slots; ++i)
+ table[layout[i]] = first_slot_value + i;
+}
+
+#endif /* U_LINKAGE_H_ */
diff --git a/src/gallium/auxiliary/util/u_math.h b/src/gallium/auxiliary/util/u_math.h
index d1ec13def30..69a76814945 100644
--- a/src/gallium/auxiliary/util/u_math.h
+++ b/src/gallium/auxiliary/util/u_math.h
@@ -168,6 +168,9 @@ static INLINE float logf( float f )
#undef logf
#define logf(x) ((float)log((double)(x)))
#endif /* logf */
+
+#define isfinite(x) _finite((double)(x))
+#define isnan(x) _isnan((double)(x))
#endif
static INLINE double log2( double x )
@@ -335,26 +338,25 @@ util_iround(float f)
}
-
/**
- * Test if x is NaN or +/- infinity.
+ * Approximate floating point comparison
*/
static INLINE boolean
-util_is_inf_or_nan(float x)
+util_is_approx(float a, float b, float tol)
{
- union fi tmp;
- tmp.f = x;
- return !(int)((unsigned int)((tmp.i & 0x7fffffff)-0x7f800000) >> 31);
+ return fabs(b - a) <= tol;
}
/**
- * Test whether x is a power of two.
+ * Test if x is NaN or +/- infinity.
*/
static INLINE boolean
-util_is_pot(unsigned x)
+util_is_inf_or_nan(float x)
{
- return (x & (x - 1)) == 0;
+ union fi tmp;
+ tmp.f = x;
+ return !(int)((unsigned int)((tmp.i & 0x7fffffff)-0x7f800000) >> 31);
}
@@ -554,13 +556,30 @@ util_bswap16(uint16_t n)
#define MIN3( A, B, C ) MIN2( MIN2( A, B ), C )
#define MAX3( A, B, C ) MAX2( MAX2( A, B ), C )
+#define MIN4( A, B, C, D ) MIN2( MIN2( A, B ), MIN2(C, D) )
+#define MAX4( A, B, C, D ) MAX2( MAX2( A, B ), MAX2(C, D) )
+
+/**
+ * Align a value, only works pot alignemnts.
+ */
static INLINE int
align(int value, int alignment)
{
return (value + alignment - 1) & ~(alignment - 1);
}
+/**
+ * Works like align but on npot alignments.
+ */
+static INLINE size_t
+util_align_npot(size_t value, size_t alignment)
+{
+ if (value % alignment)
+ return value + (alignment - (value % alignment));
+ return value;
+}
+
static INLINE unsigned
u_minify(unsigned value, unsigned levels)
{
diff --git a/src/gallium/auxiliary/util/u_mempool.c b/src/gallium/auxiliary/util/u_mempool.c
new file mode 100644
index 00000000000..1f336b39a1a
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_mempool.c
@@ -0,0 +1,169 @@
+/*
+ * Copyright 2010 Marek Olšák <[email protected]>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "util/u_mempool.h"
+
+#include "util/u_math.h"
+#include "util/u_memory.h"
+#include "util/u_simple_list.h"
+
+#include <stdio.h>
+
+#define UTIL_MEMPOOL_MAGIC 0xcafe4321
+
+/* The block is either allocated memory or free space. */
+struct util_mempool_block {
+ /* The header. */
+ /* The first next free block. */
+ struct util_mempool_block *next_free;
+
+ intptr_t magic;
+
+ /* Memory after the last member is dedicated to the block itself.
+ * The allocated size is always larger than this structure. */
+};
+
+static struct util_mempool_block *
+util_mempool_get_block(struct util_mempool *pool,
+ struct util_mempool_page *page, unsigned index)
+{
+ return (struct util_mempool_block*)
+ ((uint8_t*)page + sizeof(struct util_mempool_page) +
+ (pool->block_size * index));
+}
+
+static void util_mempool_add_new_page(struct util_mempool *pool)
+{
+ struct util_mempool_page *page;
+ struct util_mempool_block *block;
+ int i;
+
+ page = MALLOC(pool->page_size);
+ insert_at_tail(&pool->list, page);
+
+ /* Mark all blocks as free. */
+ for (i = 0; i < pool->num_blocks-1; i++) {
+ block = util_mempool_get_block(pool, page, i);
+ block->next_free = util_mempool_get_block(pool, page, i+1);
+ block->magic = UTIL_MEMPOOL_MAGIC;
+ }
+
+ block = util_mempool_get_block(pool, page, pool->num_blocks-1);
+ block->next_free = pool->first_free;
+ block->magic = UTIL_MEMPOOL_MAGIC;
+ pool->first_free = util_mempool_get_block(pool, page, 0);
+ pool->num_pages++;
+
+#if 0
+ fprintf(stderr, "New page! Num of pages: %i\n", pool->num_pages);
+#endif
+}
+
+static void *util_mempool_malloc_st(struct util_mempool *pool)
+{
+ struct util_mempool_block *block;
+
+ if (!pool->first_free)
+ util_mempool_add_new_page(pool);
+
+ block = pool->first_free;
+ assert(block->magic == UTIL_MEMPOOL_MAGIC);
+ pool->first_free = block->next_free;
+
+ return (uint8_t*)block + sizeof(struct util_mempool_block);
+}
+
+static void util_mempool_free_st(struct util_mempool *pool, void *ptr)
+{
+ struct util_mempool_block *block =
+ (struct util_mempool_block*)
+ ((uint8_t*)ptr - sizeof(struct util_mempool_block));
+
+ assert(block->magic == UTIL_MEMPOOL_MAGIC);
+ block->next_free = pool->first_free;
+ pool->first_free = block;
+}
+
+static void *util_mempool_malloc_mt(struct util_mempool *pool)
+{
+ void *mem;
+
+ pipe_mutex_lock(pool->mutex);
+ mem = util_mempool_malloc_st(pool);
+ pipe_mutex_unlock(pool->mutex);
+ return mem;
+}
+
+static void util_mempool_free_mt(struct util_mempool *pool, void *ptr)
+{
+ pipe_mutex_lock(pool->mutex);
+ util_mempool_free_st(pool, ptr);
+ pipe_mutex_unlock(pool->mutex);
+}
+
+void util_mempool_set_thread_safety(struct util_mempool *pool,
+ enum util_mempool_threading threading)
+{
+ pool->threading = threading;
+
+ if (threading) {
+ pool->malloc = util_mempool_malloc_mt;
+ pool->free = util_mempool_free_mt;
+ } else {
+ pool->malloc = util_mempool_malloc_st;
+ pool->free = util_mempool_free_st;
+ }
+}
+
+void util_mempool_create(struct util_mempool *pool,
+ unsigned item_size,
+ unsigned num_blocks,
+ enum util_mempool_threading threading)
+{
+ item_size = align(item_size, sizeof(intptr_t));
+
+ pool->num_pages = 0;
+ pool->num_blocks = num_blocks;
+ pool->block_size = sizeof(struct util_mempool_block) + item_size;
+ pool->block_size = align(pool->block_size, sizeof(intptr_t));
+ pool->page_size = sizeof(struct util_mempool_page) +
+ num_blocks * pool->block_size;
+ pool->first_free = NULL;
+
+ make_empty_list(&pool->list);
+
+ pipe_mutex_init(pool->mutex);
+
+ util_mempool_set_thread_safety(pool, threading);
+}
+
+void util_mempool_destroy(struct util_mempool *pool)
+{
+ struct util_mempool_page *page, *temp;
+
+ foreach_s(page, temp, &pool->list) {
+ remove_from_list(page);
+ FREE(page);
+ }
+
+ pipe_mutex_destroy(pool->mutex);
+}
diff --git a/src/gallium/auxiliary/util/u_mempool.h b/src/gallium/auxiliary/util/u_mempool.h
new file mode 100644
index 00000000000..a5b5d6a9b7c
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_mempool.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2010 Marek Olšák <[email protected]>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+/**
+ * @file
+ * Simple memory pool for equally sized memory allocations.
+ * util_mempool_malloc and util_mempool_free are in O(1).
+ *
+ * Good for allocations which have very low lifetime and are allocated
+ * and freed very often. Use a profiler first!
+ *
+ * Candidates: get_transfer, user_buffer_create
+ *
+ * @author Marek Olšák
+ */
+
+#ifndef U_MEMPOOL_H
+#define U_MEMPOOL_H
+
+#include "os/os_thread.h"
+
+enum util_mempool_threading {
+ UTIL_MEMPOOL_SINGLETHREADED = FALSE,
+ UTIL_MEMPOOL_MULTITHREADED = TRUE
+};
+
+/* The page is an array of blocks (allocations). */
+struct util_mempool_page {
+ /* The header (linked-list pointers). */
+ struct util_mempool_page *prev, *next;
+
+ /* Memory after the last member is dedicated to the page itself.
+ * The allocated size is always larger than this structure. */
+};
+
+struct util_mempool {
+ /* Public members. */
+ void *(*malloc)(struct util_mempool *pool);
+ void (*free)(struct util_mempool *pool, void *ptr);
+
+ /* Private members. */
+ struct util_mempool_block *first_free;
+
+ struct util_mempool_page list;
+
+ unsigned block_size;
+ unsigned page_size;
+ unsigned num_blocks;
+ unsigned num_pages;
+ enum util_mempool_threading threading;
+
+ pipe_mutex mutex;
+};
+
+void util_mempool_create(struct util_mempool *pool,
+ unsigned item_size,
+ unsigned num_blocks,
+ enum util_mempool_threading threading);
+
+void util_mempool_destroy(struct util_mempool *pool);
+
+void util_mempool_set_thread_safety(struct util_mempool *pool,
+ enum util_mempool_threading threading);
+
+#define util_mempool_malloc(pool) (pool)->malloc(pool)
+#define util_mempool_free(pool, ptr) (pool)->free(pool, ptr)
+
+#endif
diff --git a/src/gallium/auxiliary/util/u_network.c b/src/gallium/auxiliary/util/u_network.c
index 87ee0e47685..77f2c5fc7de 100644
--- a/src/gallium/auxiliary/util/u_network.c
+++ b/src/gallium/auxiliary/util/u_network.c
@@ -6,7 +6,7 @@
#if defined(PIPE_SUBSYSTEM_WINDOWS_USER)
# include <winsock2.h>
# include <windows.h>
-#elif defined(PIPE_OS_LINUX) || defined(PIPE_OS_HAIKU) || defined(PIPE_OS_APPLE)
+#elif defined(PIPE_OS_LINUX) || defined(PIPE_OS_HAIKU) || defined(PIPE_OS_APPLE) || defined(PIPE_OS_CYGWIN)
# include <sys/socket.h>
# include <netinet/in.h>
# include <unistd.h>
diff --git a/src/gallium/auxiliary/util/u_pack_color.h b/src/gallium/auxiliary/util/u_pack_color.h
index 3ebef9fb749..5378f2d782f 100644
--- a/src/gallium/auxiliary/util/u_pack_color.h
+++ b/src/gallium/auxiliary/util/u_pack_color.h
@@ -42,12 +42,18 @@
#include "util/u_math.h"
-
+/**
+ * Helper union for packing pixel values.
+ * Will often contain values in formats which are too complex to be described
+ * in simple terms, hence might just effectively contain a number of bytes.
+ * Must be big enough to hold data for all formats (currently 256 bits).
+ */
union util_color {
ubyte ub;
ushort us;
uint ui;
float f[4];
+ double d[4];
};
/**
@@ -388,7 +394,7 @@ util_pack_color(const float rgba[4], enum pipe_format format, union util_color *
return;
case PIPE_FORMAT_B4G4R4A4_UNORM:
{
- uc->ub = ((a & 0xf0) << 8) | ((r & 0xf0) << 4) | ((g & 0xf0) << 0) | (b >> 4);
+ uc->us = ((a & 0xf0) << 8) | ((r & 0xf0) << 4) | ((g & 0xf0) << 0) | (b >> 4);
}
return;
case PIPE_FORMAT_A8_UNORM:
@@ -425,13 +431,65 @@ util_pack_color(const float rgba[4], enum pipe_format format, union util_color *
}
}
+/* Integer versions of util_pack_z and util_pack_z_stencil - useful for
+ * constructing clear masks.
+ */
+static INLINE uint32_t
+util_pack_mask_z(enum pipe_format format, uint32_t z)
+{
+ switch (format) {
+ case PIPE_FORMAT_Z16_UNORM:
+ return z & 0xffff;
+ case PIPE_FORMAT_Z32_UNORM:
+ case PIPE_FORMAT_Z32_FLOAT:
+ return z;
+ case PIPE_FORMAT_Z24_UNORM_S8_USCALED:
+ case PIPE_FORMAT_Z24X8_UNORM:
+ return z & 0xffffff;
+ case PIPE_FORMAT_S8_USCALED_Z24_UNORM:
+ case PIPE_FORMAT_X8Z24_UNORM:
+ return (z & 0xffffff) << 8;
+ case PIPE_FORMAT_S8_USCALED:
+ return 0;
+ default:
+ debug_print_format("gallium: unhandled format in util_pack_mask_z()", format);
+ assert(0);
+ return 0;
+ }
+}
+
+static INLINE uint32_t
+util_pack_mask_z_stencil(enum pipe_format format, uint32_t z, uint8_t s)
+{
+ uint32_t packed = util_pack_mask_z(format, z);
+
+ switch (format) {
+ case PIPE_FORMAT_Z24_UNORM_S8_USCALED:
+ packed |= (uint32_t)s << 24;
+ break;
+ case PIPE_FORMAT_S8_USCALED_Z24_UNORM:
+ packed |= s;
+ break;
+ case PIPE_FORMAT_S8_USCALED:
+ packed |= s;
+ break;
+ default:
+ break;
+ }
+
+ return packed;
+}
+
+
/**
* Note: it's assumed that z is in [0,1]
*/
-static INLINE uint
+static INLINE uint32_t
util_pack_z(enum pipe_format format, double z)
{
+ union fi fui;
+
if (z == 0.0)
return 0;
@@ -439,24 +497,25 @@ util_pack_z(enum pipe_format format, double z)
case PIPE_FORMAT_Z16_UNORM:
if (z == 1.0)
return 0xffff;
- return (uint) (z * 0xffff);
+ return (uint32_t) (z * 0xffff);
case PIPE_FORMAT_Z32_UNORM:
/* special-case to avoid overflow */
if (z == 1.0)
return 0xffffffff;
- return (uint) (z * 0xffffffff);
+ return (uint32_t) (z * 0xffffffff);
case PIPE_FORMAT_Z32_FLOAT:
- return (uint)z;
+ fui.f = (float)z;
+ return fui.ui;
case PIPE_FORMAT_Z24_UNORM_S8_USCALED:
case PIPE_FORMAT_Z24X8_UNORM:
if (z == 1.0)
return 0xffffff;
- return (uint) (z * 0xffffff);
+ return (uint32_t) (z * 0xffffff);
case PIPE_FORMAT_S8_USCALED_Z24_UNORM:
case PIPE_FORMAT_X8Z24_UNORM:
if (z == 1.0)
return 0xffffff00;
- return ((uint) (z * 0xffffff)) << 8;
+ return ((uint32_t) (z * 0xffffff)) << 8;
case PIPE_FORMAT_S8_USCALED:
/* this case can get it via util_pack_z_stencil() */
return 0;
@@ -472,14 +531,14 @@ util_pack_z(enum pipe_format format, double z)
* Pack Z and/or stencil values into a 32-bit value described by format.
* Note: it's assumed that z is in [0,1] and s in [0,255]
*/
-static INLINE uint
-util_pack_z_stencil(enum pipe_format format, double z, uint s)
+static INLINE uint32_t
+util_pack_z_stencil(enum pipe_format format, double z, uint8_t s)
{
- unsigned packed = util_pack_z(format, z);
+ uint32_t packed = util_pack_z(format, z);
switch (format) {
case PIPE_FORMAT_Z24_UNORM_S8_USCALED:
- packed |= s << 24;
+ packed |= (uint32_t)s << 24;
break;
case PIPE_FORMAT_S8_USCALED_Z24_UNORM:
packed |= s;
diff --git a/src/gallium/auxiliary/util/u_pointer.h b/src/gallium/auxiliary/util/u_pointer.h
index e1af9f11cb9..cce0c7430e7 100644
--- a/src/gallium/auxiliary/util/u_pointer.h
+++ b/src/gallium/auxiliary/util/u_pointer.h
@@ -98,6 +98,29 @@ align16( void *unaligned )
return align_pointer( unaligned, 16 );
}
+typedef void (*func_pointer)(void);
+
+static INLINE func_pointer
+pointer_to_func( void *p )
+{
+ union {
+ void *p;
+ func_pointer f;
+ } pf;
+ pf.p = p;
+ return pf.f;
+}
+
+static INLINE void *
+func_to_pointer( func_pointer f )
+{
+ union {
+ void *p;
+ func_pointer f;
+ } pf;
+ pf.f = f;
+ return pf.p;
+}
#ifdef __cplusplus
diff --git a/src/gallium/auxiliary/util/u_prim.h b/src/gallium/auxiliary/util/u_prim.h
index 64390e13851..3c851f73401 100644
--- a/src/gallium/auxiliary/util/u_prim.h
+++ b/src/gallium/auxiliary/util/u_prim.h
@@ -108,6 +108,20 @@ static INLINE boolean u_trim_pipe_prim( unsigned pipe_prim, unsigned *nr )
ok = (*nr >= 4);
*nr -= (*nr % 2);
break;
+ case PIPE_PRIM_LINES_ADJACENCY:
+ ok = (*nr >= 4);
+ *nr -= (*nr % 4);
+ break;
+ case PIPE_PRIM_LINE_STRIP_ADJACENCY:
+ ok = (*nr >= 4);
+ break;
+ case PIPE_PRIM_TRIANGLES_ADJACENCY:
+ ok = (*nr >= 6);
+ *nr -= (*nr % 5);
+ break;
+ case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY:
+ ok = (*nr >= 4);
+ break;
default:
ok = 0;
break;
@@ -169,6 +183,52 @@ u_vertices_per_prim(int primitive)
}
}
+/**
+ * Returns the number of decomposed primitives for the given
+ * vertex count.
+ * Geometry shader is invoked once for each triangle in
+ * triangle strip, triangle fans and triangles and once
+ * for each line in line strip, line loop, lines.
+ */
+static INLINE unsigned
+u_gs_prims_for_vertices(int primitive, int vertices)
+{
+ switch(primitive) {
+ case PIPE_PRIM_POINTS:
+ return vertices;
+ case PIPE_PRIM_LINES:
+ return vertices / 2;
+ case PIPE_PRIM_LINE_LOOP:
+ return vertices;
+ case PIPE_PRIM_LINE_STRIP:
+ return vertices - 1;
+ case PIPE_PRIM_TRIANGLES:
+ return vertices / 3;
+ case PIPE_PRIM_TRIANGLE_STRIP:
+ return vertices - 2;
+ case PIPE_PRIM_TRIANGLE_FAN:
+ return vertices - 2;
+ case PIPE_PRIM_LINES_ADJACENCY:
+ return vertices / 2;
+ case PIPE_PRIM_LINE_STRIP_ADJACENCY:
+ return vertices - 1;
+ case PIPE_PRIM_TRIANGLES_ADJACENCY:
+ return vertices / 3;
+ case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY:
+ return vertices - 2;
+
+ /* following primitives should never be used
+ * with geometry shaders abd their size is
+ * undefined */
+ case PIPE_PRIM_POLYGON:
+ case PIPE_PRIM_QUADS:
+ case PIPE_PRIM_QUAD_STRIP:
+ default:
+ debug_printf("Unrecognized geometry shader primitive");
+ return 3;
+ }
+}
+
const char *u_prim_name( unsigned pipe_prim );
#endif
diff --git a/src/gallium/auxiliary/util/u_rect.c b/src/gallium/auxiliary/util/u_rect.c
index 098cdfd58b1..56fcfac0693 100644
--- a/src/gallium/auxiliary/util/u_rect.c
+++ b/src/gallium/auxiliary/util/u_rect.c
@@ -30,13 +30,9 @@
*/
-#include "pipe/p_defines.h"
-#include "pipe/p_format.h"
-#include "pipe/p_context.h"
-#include "pipe/p_screen.h"
#include "util/u_format.h"
-#include "util/u_inlines.h"
#include "util/u_rect.h"
+#include "util/u_pack_color.h"
/**
@@ -99,7 +95,7 @@ util_fill_rect(ubyte * dst,
unsigned dst_y,
unsigned width,
unsigned height,
- uint32_t value)
+ union util_color *uc)
{
unsigned i, j;
unsigned width_size;
@@ -115,193 +111,54 @@ util_fill_rect(ubyte * dst,
dst_y /= blockheight;
width = (width + blockwidth - 1)/blockwidth;
height = (height + blockheight - 1)/blockheight;
-
+
dst += dst_x * blocksize;
dst += dst_y * dst_stride;
width_size = width * blocksize;
-
+
switch (blocksize) {
case 1:
if(dst_stride == width_size)
- memset(dst, (ubyte) value, height * width_size);
+ memset(dst, uc->ub, height * width_size);
else {
- for (i = 0; i < height; i++) {
- memset(dst, (ubyte) value, width_size);
- dst += dst_stride;
- }
+ for (i = 0; i < height; i++) {
+ memset(dst, uc->ub, width_size);
+ dst += dst_stride;
+ }
}
break;
case 2:
for (i = 0; i < height; i++) {
- uint16_t *row = (uint16_t *)dst;
- for (j = 0; j < width; j++)
- *row++ = (uint16_t) value;
- dst += dst_stride;
+ uint16_t *row = (uint16_t *)dst;
+ for (j = 0; j < width; j++)
+ *row++ = uc->us;
+ dst += dst_stride;
}
break;
case 4:
for (i = 0; i < height; i++) {
- uint32_t *row = (uint32_t *)dst;
- for (j = 0; j < width; j++)
- *row++ = value;
- dst += dst_stride;
+ uint32_t *row = (uint32_t *)dst;
+ for (j = 0; j < width; j++)
+ *row++ = uc->ui;
+ dst += dst_stride;
}
break;
- default:
- assert(0);
- break;
- }
-}
-
-
-
-/**
- * Fallback function for pipe->surface_copy().
- * Note: (X,Y)=(0,0) is always the upper-left corner.
- * if do_flip, flip the image vertically on its way from src rect to dst rect.
- * XXX should probably put this in new u_surface.c file...
- */
-void
-util_surface_copy(struct pipe_context *pipe,
- boolean do_flip,
- struct pipe_surface *dst,
- unsigned dst_x, unsigned dst_y,
- struct pipe_surface *src,
- unsigned src_x, unsigned src_y,
- unsigned w, unsigned h)
-{
- struct pipe_transfer *src_trans, *dst_trans;
- void *dst_map;
- const void *src_map;
- enum pipe_format src_format, dst_format;
-
- assert(src->texture && dst->texture);
- if (!src->texture || !dst->texture)
- return;
-
- src_format = src->texture->format;
- dst_format = dst->texture->format;
-
- src_trans = pipe_get_transfer(pipe,
- src->texture,
- src->face,
- src->level,
- src->zslice,
- PIPE_TRANSFER_READ,
- src_x, src_y, w, h);
-
- dst_trans = pipe_get_transfer(pipe,
- dst->texture,
- dst->face,
- dst->level,
- dst->zslice,
- PIPE_TRANSFER_WRITE,
- dst_x, dst_y, w, h);
-
- assert(util_format_get_blocksize(dst_format) == util_format_get_blocksize(src_format));
- assert(util_format_get_blockwidth(dst_format) == util_format_get_blockwidth(src_format));
- assert(util_format_get_blockheight(dst_format) == util_format_get_blockheight(src_format));
-
- src_map = pipe->transfer_map(pipe, src_trans);
- dst_map = pipe->transfer_map(pipe, dst_trans);
-
- assert(src_map);
- assert(dst_map);
-
- if (src_map && dst_map) {
- /* If do_flip, invert src_y position and pass negative src stride */
- util_copy_rect(dst_map,
- dst_format,
- dst_trans->stride,
- 0, 0,
- w, h,
- src_map,
- do_flip ? -(int) src_trans->stride : src_trans->stride,
- 0,
- do_flip ? h - 1 : 0);
- }
-
- pipe->transfer_unmap(pipe, src_trans);
- pipe->transfer_unmap(pipe, dst_trans);
-
- pipe->transfer_destroy(pipe, src_trans);
- pipe->transfer_destroy(pipe, dst_trans);
-}
-
-
-
-#define UBYTE_TO_USHORT(B) ((B) | ((B) << 8))
-
-
-/**
- * Fallback for pipe->surface_fill() function.
- * XXX should probably put this in new u_surface.c file...
- */
-void
-util_surface_fill(struct pipe_context *pipe,
- struct pipe_surface *dst,
- unsigned dstx, unsigned dsty,
- unsigned width, unsigned height, unsigned value)
-{
- struct pipe_transfer *dst_trans;
- void *dst_map;
-
- assert(dst->texture);
- if (!dst->texture)
- return;
- dst_trans = pipe_get_transfer(pipe,
- dst->texture,
- dst->face,
- dst->level,
- dst->zslice,
- PIPE_TRANSFER_WRITE,
- dstx, dsty, width, height);
-
- dst_map = pipe->transfer_map(pipe, dst_trans);
-
- assert(dst_map);
-
- if (dst_map) {
- assert(dst_trans->stride > 0);
-
- switch (util_format_get_blocksize(dst->texture->format)) {
- case 1:
- case 2:
- case 4:
- util_fill_rect(dst_map, dst->texture->format,
- dst_trans->stride,
- 0, 0, width, height, value);
- break;
- case 8:
- {
- /* expand the 4-byte clear value to an 8-byte value */
- ushort *row = (ushort *) dst_map;
- ushort val0 = UBYTE_TO_USHORT((value >> 0) & 0xff);
- ushort val1 = UBYTE_TO_USHORT((value >> 8) & 0xff);
- ushort val2 = UBYTE_TO_USHORT((value >> 16) & 0xff);
- ushort val3 = UBYTE_TO_USHORT((value >> 24) & 0xff);
- unsigned i, j;
- val0 = (val0 << 8) | val0;
- val1 = (val1 << 8) | val1;
- val2 = (val2 << 8) | val2;
- val3 = (val3 << 8) | val3;
- for (i = 0; i < height; i++) {
- for (j = 0; j < width; j++) {
- row[j*4+0] = val0;
- row[j*4+1] = val1;
- row[j*4+2] = val2;
- row[j*4+3] = val3;
- }
- row += dst_trans->stride/2;
- }
+ case 8:
+ case 12:
+ case 16:
+ case 24:
+ case 32:
+ for (i = 0; i < height; i++) {
+ ubyte *row = dst;
+ for (j = 0; j < width; j++) {
+ memcpy(row, uc, blocksize);
+ row += blocksize;
+ }
+ dst += dst_stride;
}
break;
- default:
- assert(0);
- break;
- }
+ default:
+ assert(0);
+ break;
}
-
- pipe->transfer_unmap(pipe, dst_trans);
- pipe->transfer_destroy(pipe, dst_trans);
}
diff --git a/src/gallium/auxiliary/util/u_rect.h b/src/gallium/auxiliary/util/u_rect.h
index b44d821904b..4cb90d3c316 100644
--- a/src/gallium/auxiliary/util/u_rect.h
+++ b/src/gallium/auxiliary/util/u_rect.h
@@ -26,20 +26,67 @@
**************************************************************************/
-/**
- * Pipe copy/fill rect helpers.
+#ifndef U_RECT_H
+#define U_RECT_H
+
+#include "pipe/p_compiler.h"
+
+struct u_rect {
+ int x0, x1;
+ int y0, y1;
+};
+
+/* Do two rectangles intersect?
*/
+static INLINE boolean
+u_rect_test_intersection(const struct u_rect *a,
+ const struct u_rect *b)
+{
+ return (!(a->x1 < b->x0 ||
+ b->x1 < a->x0 ||
+ a->y1 < b->y0 ||
+ b->y1 < a->y0));
+}
+/* Find the intersection of two rectangles known to intersect.
+ */
+static INLINE void
+u_rect_find_intersection(const struct u_rect *a,
+ struct u_rect *b)
+{
+ /* Caller should verify intersection exists before calling.
+ */
+ if (b->x0 < a->x0) b->x0 = a->x0;
+ if (b->x1 > a->x1) b->x1 = a->x1;
+ if (b->y0 < a->y0) b->y0 = a->y0;
+ if (b->y1 > a->y1) b->y1 = a->y1;
+}
-#ifndef U_RECT_H
-#define U_RECT_H
+static INLINE void
+u_rect_possible_intersection(const struct u_rect *a,
+ struct u_rect *b)
+{
+ if (u_rect_test_intersection(a,b)) {
+ u_rect_find_intersection(a,b);
+ }
+ else {
+ b->x0 = b->x1 = b->y0 = b->y1 = 0;
+ }
+}
#include "pipe/p_format.h"
+#include "util/u_pack_color.h"
+
-struct pipe_context;
-struct pipe_surface;
+/**********************************************************************
+ * Pipe copy/fill rect helpers.
+ */
+
+/* These really should move to a different file:
+ */
+#include "pipe/p_format.h"
extern void
util_copy_rect(ubyte * dst, enum pipe_format format,
@@ -50,23 +97,7 @@ util_copy_rect(ubyte * dst, enum pipe_format format,
extern void
util_fill_rect(ubyte * dst, enum pipe_format format,
unsigned dst_stride, unsigned dst_x, unsigned dst_y,
- unsigned width, unsigned height, uint32_t value);
-
-
-extern void
-util_surface_copy(struct pipe_context *pipe,
- boolean do_flip,
- struct pipe_surface *dst,
- unsigned dst_x, unsigned dst_y,
- struct pipe_surface *src,
- unsigned src_x, unsigned src_y,
- unsigned w, unsigned h);
-
-extern void
-util_surface_fill(struct pipe_context *pipe,
- struct pipe_surface *dst,
- unsigned dstx, unsigned dsty,
- unsigned width, unsigned height, unsigned value);
+ unsigned width, unsigned height, union util_color *uc);
#endif /* U_RECT_H */
diff --git a/src/gallium/auxiliary/util/u_simple_list.h b/src/gallium/auxiliary/util/u_simple_list.h
index f5f43b0faa2..fe59771371b 100644
--- a/src/gallium/auxiliary/util/u_simple_list.h
+++ b/src/gallium/auxiliary/util/u_simple_list.h
@@ -46,6 +46,8 @@
do { \
(elem)->next->prev = (elem)->prev; \
(elem)->prev->next = (elem)->next; \
+ (elem)->next = elem; \
+ (elem)->prev = elem; \
} while (0)
/**
diff --git a/src/gallium/auxiliary/util/u_simple_shaders.c b/src/gallium/auxiliary/util/u_simple_shaders.c
index 019dda767d0..58ef68377fc 100644
--- a/src/gallium/auxiliary/util/u_simple_shaders.c
+++ b/src/gallium/auxiliary/util/u_simple_shaders.c
@@ -37,6 +37,7 @@
#include "pipe/p_context.h"
#include "pipe/p_shader_tokens.h"
+#include "pipe/p_state.h"
#include "util/u_simple_shaders.h"
#include "util/u_debug.h"
#include "tgsi/tgsi_ureg.h"
@@ -87,10 +88,15 @@ util_make_vertex_passthrough_shader(struct pipe_context *pipe,
* MOV OUT[0], IMM[0] // (if writemask != 0xf)
* TEX OUT[0].writemask, IN[0], SAMP[0], 2D;
* END;
+ *
+ * \param tex_target one of PIPE_TEXTURE_x
+ * \parma interp_mode either TGSI_INTERPOLATE_LINEAR or PERSPECTIVE
+ * \param writemask mask of TGSI_WRITEMASK_x
*/
void *
util_make_fragment_tex_shader_writemask(struct pipe_context *pipe,
unsigned tex_target,
+ unsigned interp_mode,
unsigned writemask )
{
struct ureg_program *ureg;
@@ -98,6 +104,9 @@ util_make_fragment_tex_shader_writemask(struct pipe_context *pipe,
struct ureg_src tex;
struct ureg_dst out;
+ assert(interp_mode == TGSI_INTERPOLATE_LINEAR ||
+ interp_mode == TGSI_INTERPOLATE_PERSPECTIVE);
+
ureg = ureg_create( TGSI_PROCESSOR_FRAGMENT );
if (ureg == NULL)
return NULL;
@@ -106,7 +115,7 @@ util_make_fragment_tex_shader_writemask(struct pipe_context *pipe,
tex = ureg_DECL_fs_input( ureg,
TGSI_SEMANTIC_GENERIC, 0,
- TGSI_INTERPOLATE_PERSPECTIVE );
+ interp_mode );
out = ureg_DECL_output( ureg,
TGSI_SEMANTIC_COLOR,
@@ -133,10 +142,12 @@ util_make_fragment_tex_shader_writemask(struct pipe_context *pipe,
* \param tex_target one of PIPE_TEXTURE_x
*/
void *
-util_make_fragment_tex_shader(struct pipe_context *pipe, unsigned tex_target )
+util_make_fragment_tex_shader(struct pipe_context *pipe, unsigned tex_target,
+ unsigned interp_mode)
{
return util_make_fragment_tex_shader_writemask( pipe,
tex_target,
+ interp_mode,
TGSI_WRITEMASK_XYZW );
}
@@ -147,7 +158,8 @@ util_make_fragment_tex_shader(struct pipe_context *pipe, unsigned tex_target )
*/
void *
util_make_fragment_tex_shader_writedepth(struct pipe_context *pipe,
- unsigned tex_target)
+ unsigned tex_target,
+ unsigned interp_mode)
{
struct ureg_program *ureg;
struct ureg_src sampler;
@@ -163,7 +175,7 @@ util_make_fragment_tex_shader_writedepth(struct pipe_context *pipe,
tex = ureg_DECL_fs_input( ureg,
TGSI_SEMANTIC_GENERIC, 0,
- TGSI_INTERPOLATE_PERSPECTIVE );
+ interp_mode );
out = ureg_DECL_output( ureg,
TGSI_SEMANTIC_COLOR,
diff --git a/src/gallium/auxiliary/util/u_simple_shaders.h b/src/gallium/auxiliary/util/u_simple_shaders.h
index 6e760942e25..4aa34bc4757 100644
--- a/src/gallium/auxiliary/util/u_simple_shaders.h
+++ b/src/gallium/auxiliary/util/u_simple_shaders.h
@@ -52,15 +52,18 @@ util_make_vertex_passthrough_shader(struct pipe_context *pipe,
extern void *
util_make_fragment_tex_shader_writemask(struct pipe_context *pipe,
unsigned tex_target,
+ unsigned interp_mode,
unsigned writemask);
extern void *
-util_make_fragment_tex_shader(struct pipe_context *pipe, unsigned tex_target);
+util_make_fragment_tex_shader(struct pipe_context *pipe, unsigned tex_target,
+ unsigned interp_mode);
extern void *
util_make_fragment_tex_shader_writedepth(struct pipe_context *pipe,
- unsigned tex_target);
+ unsigned tex_target,
+ unsigned interp_mode);
extern void *
diff --git a/src/gallium/auxiliary/util/u_split_prim.h b/src/gallium/auxiliary/util/u_split_prim.h
new file mode 100644
index 00000000000..7f80fc12700
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_split_prim.h
@@ -0,0 +1,114 @@
+/* Originally written by Ben Skeggs for the nv50 driver*/
+
+#ifndef U_SPLIT_PRIM_H
+#define U_SPLIT_PRIM_H
+
+#include "pipe/p_defines.h"
+#include "pipe/p_compiler.h"
+
+#include "util/u_debug.h"
+
+struct util_split_prim {
+ void *priv;
+ void (*emit)(void *priv, unsigned start, unsigned count);
+ void (*edge)(void *priv, boolean enabled);
+
+ unsigned mode;
+ unsigned start;
+ unsigned p_start;
+ unsigned p_end;
+
+ uint repeat_first:1;
+ uint close_first:1;
+ uint edgeflag_off:1;
+};
+
+static INLINE void
+util_split_prim_init(struct util_split_prim *s,
+ unsigned mode, unsigned start, unsigned count)
+{
+ if (mode == PIPE_PRIM_LINE_LOOP) {
+ s->mode = PIPE_PRIM_LINE_STRIP;
+ s->close_first = 1;
+ } else {
+ s->mode = mode;
+ s->close_first = 0;
+ }
+ s->start = start;
+ s->p_start = start;
+ s->p_end = start + count;
+ s->edgeflag_off = 0;
+ s->repeat_first = 0;
+}
+
+static INLINE boolean
+util_split_prim_next(struct util_split_prim *s, unsigned max_verts)
+{
+ int repeat = 0;
+
+ if (s->repeat_first) {
+ s->emit(s->priv, s->start, 1);
+ max_verts--;
+ if (s->edgeflag_off) {
+ s->edge(s->priv, TRUE);
+ s->edgeflag_off = FALSE;
+ }
+ }
+
+ if ((s->p_end - s->p_start) + s->close_first <= max_verts) {
+ s->emit(s->priv, s->p_start, s->p_end - s->p_start);
+ if (s->close_first)
+ s->emit(s->priv, s->start, 1);
+ return TRUE;
+ }
+
+ switch (s->mode) {
+ case PIPE_PRIM_LINES:
+ max_verts &= ~1;
+ break;
+ case PIPE_PRIM_LINE_STRIP:
+ repeat = 1;
+ break;
+ case PIPE_PRIM_POLYGON:
+ max_verts--;
+ s->emit(s->priv, s->p_start, max_verts);
+ s->edge(s->priv, FALSE);
+ s->emit(s->priv, s->p_start + max_verts, 1);
+ s->p_start += max_verts;
+ s->repeat_first = TRUE;
+ s->edgeflag_off = TRUE;
+ return FALSE;
+ case PIPE_PRIM_TRIANGLES:
+ max_verts = max_verts - (max_verts % 3);
+ break;
+ case PIPE_PRIM_TRIANGLE_STRIP:
+ /* to ensure winding stays correct, always split
+ * on an even number of generated triangles
+ */
+ max_verts = max_verts & ~1;
+ repeat = 2;
+ break;
+ case PIPE_PRIM_TRIANGLE_FAN:
+ s->repeat_first = TRUE;
+ repeat = 1;
+ break;
+ case PIPE_PRIM_QUADS:
+ max_verts &= ~3;
+ break;
+ case PIPE_PRIM_QUAD_STRIP:
+ max_verts &= ~1;
+ repeat = 2;
+ break;
+ case PIPE_PRIM_POINTS:
+ break;
+ default:
+ /* TODO: implement adjacency primitives */
+ assert(0);
+ }
+
+ s->emit (s->priv, s->p_start, max_verts);
+ s->p_start += (max_verts - repeat);
+ return FALSE;
+}
+
+#endif /* U_SPLIT_PRIM_H */
diff --git a/src/gallium/auxiliary/util/u_sse.h b/src/gallium/auxiliary/util/u_sse.h
index e2a8491e62c..03198c91da4 100644
--- a/src/gallium/auxiliary/util/u_sse.h
+++ b/src/gallium/auxiliary/util/u_sse.h
@@ -41,7 +41,6 @@
#if defined(PIPE_ARCH_SSE)
-#include <xmmintrin.h>
#include <emmintrin.h>
@@ -72,6 +71,33 @@ _mm_castps_si128(__m128 a)
#endif /* defined(_MSC_VER) && _MSC_VER < 1500 */
+
+#if defined(PIPE_ARCH_SSSE3)
+
+#include <tmmintrin.h>
+
+#else /* !PIPE_ARCH_SSSE3 */
+
+/**
+ * Describe _mm_shuffle_epi8() with gcc extended inline assembly, for cases
+ * where -mssse3 is not supported/enabled.
+ *
+ * MSVC will never get in here as its intrinsics support do not rely on
+ * compiler command line options.
+ */
+static __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_shuffle_epi8(__m128i a, __m128i mask)
+{
+ __m128i result;
+ __asm__("pshufb %1, %0"
+ : "=x" (result)
+ : "xm" (mask), "0" (a));
+ return result;
+}
+
+#endif /* !PIPE_ARCH_SSSE3 */
+
+
#endif /* PIPE_ARCH_X86 || PIPE_ARCH_X86_64 */
#endif /* U_SSE_H_ */
diff --git a/src/gallium/auxiliary/util/u_staging.c b/src/gallium/auxiliary/util/u_staging.c
new file mode 100644
index 00000000000..c5d68f8df86
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_staging.c
@@ -0,0 +1,117 @@
+/**************************************************************************
+ *
+ * Copyright 2010 Luca Barbieri
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "util/u_staging.h"
+#include "pipe/p_context.h"
+#include "util/u_memory.h"
+#include "util/u_inlines.h"
+
+static void
+util_staging_resource_template(struct pipe_resource *pt, unsigned width, unsigned height, unsigned depth, struct pipe_resource *template)
+{
+ memset(template, 0, sizeof(struct pipe_resource));
+ if(pt->target != PIPE_BUFFER && depth <= 1)
+ template->target = PIPE_TEXTURE_RECT;
+ else
+ template->target = pt->target;
+ template->format = pt->format;
+ template->width0 = width;
+ template->height0 = height;
+ template->depth0 = depth;
+ template->last_level = 0;
+ template->nr_samples = pt->nr_samples;
+ template->bind = 0;
+ template->usage = PIPE_USAGE_STAGING;
+ template->flags = 0;
+}
+
+struct util_staging_transfer *
+util_staging_transfer_init(struct pipe_context *pipe,
+ struct pipe_resource *pt,
+ struct pipe_subresource sr,
+ unsigned usage,
+ const struct pipe_box *box,
+ bool direct, struct util_staging_transfer *tx)
+{
+ struct pipe_screen *pscreen = pipe->screen;
+
+ struct pipe_resource staging_resource_template;
+
+ pipe_resource_reference(&tx->base.resource, pt);
+ tx->base.sr = sr;
+ tx->base.usage = usage;
+ tx->base.box = *box;
+
+ if (direct)
+ {
+ tx->staging_resource = pt;
+ return tx;
+ }
+
+ util_staging_resource_template(pt, box->width, box->height, box->depth, &staging_resource_template);
+ tx->staging_resource = pscreen->resource_create(pscreen, &staging_resource_template);
+ if (!tx->staging_resource)
+ {
+ pipe_resource_reference(&tx->base.resource, NULL);
+ FREE(tx);
+ return NULL;
+ }
+
+ if (usage & PIPE_TRANSFER_READ)
+ {
+ struct pipe_subresource dstsr;
+ unsigned zi;
+ dstsr.face = 0;
+ dstsr.level = 0;
+ for(zi = 0; zi < box->depth; ++zi)
+ pipe->resource_copy_region(pipe, tx->staging_resource, dstsr, 0, 0, 0, tx->base.resource, sr, box->x, box->y, box->z + zi, box->width, box->height);
+ }
+
+ return tx;
+}
+
+void
+util_staging_transfer_destroy(struct pipe_context *pipe, struct pipe_transfer *ptx)
+{
+ struct util_staging_transfer *tx = (struct util_staging_transfer *)ptx;
+
+ if (tx->staging_resource != tx->base.resource)
+ {
+ if(tx->base.usage & PIPE_TRANSFER_WRITE) {
+ struct pipe_subresource srcsr;
+ unsigned zi;
+ srcsr.face = 0;
+ srcsr.level = 0;
+ for(zi = 0; zi < tx->base.box.depth; ++zi)
+ pipe->resource_copy_region(pipe, tx->base.resource, tx->base.sr, tx->base.box.x, tx->base.box.y, tx->base.box.z + zi, tx->staging_resource, srcsr, 0, 0, 0, tx->base.box.width, tx->base.box.height);
+ }
+
+ pipe_resource_reference(&tx->staging_resource, NULL);
+ }
+
+ pipe_resource_reference(&ptx->resource, NULL);
+ FREE(ptx);
+}
diff --git a/src/gallium/auxiliary/util/u_staging.h b/src/gallium/auxiliary/util/u_staging.h
new file mode 100644
index 00000000000..1aab78cc881
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_staging.h
@@ -0,0 +1,63 @@
+/**************************************************************************
+ *
+ * Copyright 2010 Luca Barbieri
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/* Direct3D 10/11 has no concept of transfers. Applications instead
+ * create resources with a STAGING or DYNAMIC usage, copy between them
+ * and the real resource and use Map to map the STAGING/DYNAMIC resource.
+ *
+ * This util module allows to implement Gallium drivers as a Direct3D
+ * driver would be implemented: transfers allocate a resource with
+ * PIPE_USAGE_STAGING, and copy the data between it and the real resource
+ * with resource_copy_region.
+ */
+
+#ifndef U_STAGING_H
+#define U_STAGING_H
+
+#include "pipe/p_state.h"
+
+struct util_staging_transfer {
+ struct pipe_transfer base;
+
+ /* if direct, same as base.resource, otherwise the temporary staging resource */
+ struct pipe_resource *staging_resource;
+};
+
+/* user must be stride, slice_stride and offset */
+/* pt->usage == PIPE_USAGE_DYNAMIC || pt->usage == PIPE_USAGE_STAGING should be a good value to pass for direct */
+/* staging resource is currently created with PIPE_USAGE_STAGING */
+struct util_staging_transfer *
+util_staging_transfer_init(struct pipe_context *pipe,
+ struct pipe_resource *pt,
+ struct pipe_subresource sr,
+ unsigned usage,
+ const struct pipe_box *box,
+ bool direct, struct util_staging_transfer *tx);
+
+void
+util_staging_transfer_destroy(struct pipe_context *pipe, struct pipe_transfer *ptx);
+
+#endif
diff --git a/src/gallium/auxiliary/util/u_surface.c b/src/gallium/auxiliary/util/u_surface.c
index 42440d0d673..f78b6838a72 100644
--- a/src/gallium/auxiliary/util/u_surface.c
+++ b/src/gallium/auxiliary/util/u_surface.c
@@ -32,13 +32,15 @@
*/
+#include "pipe/p_defines.h"
#include "pipe/p_screen.h"
#include "pipe/p_state.h"
-#include "pipe/p_defines.h"
-#include "util/u_inlines.h"
-#include "util/u_memory.h"
+#include "util/u_format.h"
+#include "util/u_inlines.h"
+#include "util/u_rect.h"
#include "util/u_surface.h"
+#include "util/u_pack_color.h"
/**
@@ -68,7 +70,7 @@ util_create_rgba_surface(struct pipe_screen *screen,
/* Choose surface format */
for (i = 0; rgbaFormats[i]; i++) {
if (screen->is_format_supported(screen, rgbaFormats[i],
- target, bind, 0)) {
+ target, 0, bind, 0)) {
format = rgbaFormats[i];
break;
}
@@ -118,70 +120,231 @@ util_destroy_rgba_surface(struct pipe_resource *texture,
/**
- * Compare pipe_framebuffer_state objects.
- * \return TRUE if same, FALSE if different
+ * Fallback function for pipe->resource_copy_region().
+ * Note: (X,Y)=(0,0) is always the upper-left corner.
*/
-boolean
-util_framebuffer_state_equal(const struct pipe_framebuffer_state *dst,
- const struct pipe_framebuffer_state *src)
+void
+util_resource_copy_region(struct pipe_context *pipe,
+ struct pipe_resource *dst,
+ struct pipe_subresource subdst,
+ unsigned dst_x, unsigned dst_y, unsigned dst_z,
+ struct pipe_resource *src,
+ struct pipe_subresource subsrc,
+ unsigned src_x, unsigned src_y, unsigned src_z,
+ unsigned w, unsigned h)
{
- unsigned i;
+ struct pipe_transfer *src_trans, *dst_trans;
+ void *dst_map;
+ const void *src_map;
+ enum pipe_format src_format, dst_format;
+
+ assert(src && dst);
+ if (!src || !dst)
+ return;
+
+ src_format = src->format;
+ dst_format = dst->format;
+
+ src_trans = pipe_get_transfer(pipe,
+ src,
+ subsrc.face,
+ subsrc.level,
+ src_z,
+ PIPE_TRANSFER_READ,
+ src_x, src_y, w, h);
+
+ dst_trans = pipe_get_transfer(pipe,
+ dst,
+ subdst.face,
+ subdst.level,
+ src_z,
+ PIPE_TRANSFER_WRITE,
+ dst_x, dst_y, w, h);
+
+ assert(util_format_get_blocksize(dst_format) == util_format_get_blocksize(src_format));
+ assert(util_format_get_blockwidth(dst_format) == util_format_get_blockwidth(src_format));
+ assert(util_format_get_blockheight(dst_format) == util_format_get_blockheight(src_format));
+
+ src_map = pipe->transfer_map(pipe, src_trans);
+ dst_map = pipe->transfer_map(pipe, dst_trans);
+
+ assert(src_map);
+ assert(dst_map);
+
+ if (src_map && dst_map) {
+ util_copy_rect(dst_map,
+ dst_format,
+ dst_trans->stride,
+ 0, 0,
+ w, h,
+ src_map,
+ src_trans->stride,
+ 0,
+ 0);
+ }
- if (dst->width != src->width ||
- dst->height != src->height)
- return FALSE;
+ pipe->transfer_unmap(pipe, src_trans);
+ pipe->transfer_unmap(pipe, dst_trans);
- for (i = 0; i < Elements(src->cbufs); i++) {
- if (dst->cbufs[i] != src->cbufs[i]) {
- return FALSE;
- }
- }
+ pipe->transfer_destroy(pipe, src_trans);
+ pipe->transfer_destroy(pipe, dst_trans);
+}
- if (dst->nr_cbufs != src->nr_cbufs) {
- return FALSE;
- }
- if (dst->zsbuf != src->zsbuf) {
- return FALSE;
- }
- return TRUE;
-}
+#define UBYTE_TO_USHORT(B) ((B) | ((B) << 8))
/**
- * Copy framebuffer state from src to dst, updating refcounts.
+ * Fallback for pipe->clear_render_target() function.
+ * XXX this looks too hackish to be really useful.
+ * cpp > 4 looks like a gross hack at best...
+ * Plus can't use these transfer fallbacks when clearing
+ * multisampled surfaces for instance.
*/
void
-util_copy_framebuffer_state(struct pipe_framebuffer_state *dst,
- const struct pipe_framebuffer_state *src)
+util_clear_render_target(struct pipe_context *pipe,
+ struct pipe_surface *dst,
+ const float *rgba,
+ unsigned dstx, unsigned dsty,
+ unsigned width, unsigned height)
{
- unsigned i;
+ struct pipe_transfer *dst_trans;
+ void *dst_map;
+ union util_color uc;
- dst->width = src->width;
- dst->height = src->height;
+ assert(dst->texture);
+ if (!dst->texture)
+ return;
- for (i = 0; i < Elements(src->cbufs); i++) {
- pipe_surface_reference(&dst->cbufs[i], src->cbufs[i]);
- }
+ dst_trans = pipe_get_transfer(pipe,
+ dst->texture,
+ dst->face,
+ dst->level,
+ dst->zslice,
+ PIPE_TRANSFER_WRITE,
+ dstx, dsty, width, height);
- dst->nr_cbufs = src->nr_cbufs;
+ dst_map = pipe->transfer_map(pipe, dst_trans);
- pipe_surface_reference(&dst->zsbuf, src->zsbuf);
-}
+ assert(dst_map);
+
+ if (dst_map) {
+ assert(dst_trans->stride > 0);
+ util_pack_color(rgba, dst->texture->format, &uc);
+ util_fill_rect(dst_map, dst->texture->format,
+ dst_trans->stride,
+ 0, 0, width, height, &uc);
+ }
+
+ pipe->transfer_unmap(pipe, dst_trans);
+ pipe->transfer_destroy(pipe, dst_trans);
+}
+/**
+ * Fallback for pipe->clear_stencil() function.
+ * sw fallback doesn't look terribly useful here.
+ * Plus can't use these transfer fallbacks when clearing
+ * multisampled surfaces for instance.
+ */
void
-util_unreference_framebuffer_state(struct pipe_framebuffer_state *fb)
+util_clear_depth_stencil(struct pipe_context *pipe,
+ struct pipe_surface *dst,
+ unsigned clear_flags,
+ double depth,
+ unsigned stencil,
+ unsigned dstx, unsigned dsty,
+ unsigned width, unsigned height)
{
- unsigned i;
-
- for (i = 0; i < fb->nr_cbufs; i++) {
- pipe_surface_reference(&fb->cbufs[i], NULL);
+ struct pipe_transfer *dst_trans;
+ ubyte *dst_map;
+ boolean need_rmw = FALSE;
+
+ if ((clear_flags & PIPE_CLEAR_DEPTHSTENCIL) &&
+ ((clear_flags & PIPE_CLEAR_DEPTHSTENCIL) != PIPE_CLEAR_DEPTHSTENCIL) &&
+ util_format_is_depth_and_stencil(dst->format))
+ need_rmw = TRUE;
+
+ assert(dst->texture);
+ if (!dst->texture)
+ return;
+ dst_trans = pipe_get_transfer(pipe,
+ dst->texture,
+ dst->face,
+ dst->level,
+ dst->zslice,
+ (need_rmw ? PIPE_TRANSFER_READ_WRITE :
+ PIPE_TRANSFER_WRITE),
+ dstx, dsty, width, height);
+
+ dst_map = pipe->transfer_map(pipe, dst_trans);
+
+ assert(dst_map);
+
+ if (dst_map) {
+ unsigned dst_stride = dst_trans->stride;
+ unsigned zstencil = util_pack_z_stencil(dst->texture->format, depth, stencil);
+ unsigned i, j;
+ assert(dst_trans->stride > 0);
+
+ switch (util_format_get_blocksize(dst->format)) {
+ case 1:
+ assert(dst->format == PIPE_FORMAT_S8_USCALED);
+ if(dst_stride == width)
+ memset(dst_map, (ubyte) zstencil, height * width);
+ else {
+ for (i = 0; i < height; i++) {
+ memset(dst_map, (ubyte) zstencil, width);
+ dst_map += dst_stride;
+ }
+ }
+ break;
+ case 2:
+ assert(dst->format == PIPE_FORMAT_Z16_UNORM);
+ for (i = 0; i < height; i++) {
+ uint16_t *row = (uint16_t *)dst_map;
+ for (j = 0; j < width; j++)
+ *row++ = (uint16_t) zstencil;
+ dst_map += dst_stride;
+ }
+ break;
+ case 4:
+ if (!need_rmw) {
+ for (i = 0; i < height; i++) {
+ uint32_t *row = (uint32_t *)dst_map;
+ for (j = 0; j < width; j++)
+ *row++ = zstencil;
+ dst_map += dst_stride;
+ }
+ }
+ else {
+ uint32_t dst_mask;
+ if (dst->format == PIPE_FORMAT_Z24_UNORM_S8_USCALED)
+ dst_mask = 0xffffff00;
+ else {
+ assert(dst->format == PIPE_FORMAT_S8_USCALED_Z24_UNORM);
+ dst_mask = 0xffffff;
+ }
+ if (clear_flags & PIPE_CLEAR_DEPTH)
+ dst_mask = ~dst_mask;
+ for (i = 0; i < height; i++) {
+ uint32_t *row = (uint32_t *)dst_map;
+ for (j = 0; j < width; j++) {
+ uint32_t tmp = *row & dst_mask;
+ *row++ = tmp | (zstencil & ~dst_mask);
+ }
+ dst_map += dst_stride;
+ }
+ }
+ break;
+ case 8:
+ default:
+ assert(0);
+ break;
+ }
}
- pipe_surface_reference(&fb->zsbuf, NULL);
-
- fb->width = fb->height = 0;
- fb->nr_cbufs = 0;
+ pipe->transfer_unmap(pipe, dst_trans);
+ pipe->transfer_destroy(pipe, dst_trans);
}
diff --git a/src/gallium/auxiliary/util/u_surface.h b/src/gallium/auxiliary/util/u_surface.h
index 119fcd4ce8e..6cd12af3a8b 100644
--- a/src/gallium/auxiliary/util/u_surface.h
+++ b/src/gallium/auxiliary/util/u_surface.h
@@ -33,23 +33,6 @@
#include "pipe/p_state.h"
-/**
- * Are s1 and s2 the same surface?
- * Surfaces are basically views into textures so check if the two surfaces
- * name the same part of the same texture.
- */
-static INLINE boolean
-util_same_surface(const struct pipe_surface *s1, const struct pipe_surface *s2)
-{
- return (s1->texture == s2->texture &&
- s1->face == s2->face &&
- s1->level == s2->level &&
- s1->zslice == s2->zslice);
-}
-
-
-
-
extern boolean
util_create_rgba_surface(struct pipe_screen *screen,
uint width, uint height, uint bind,
@@ -62,17 +45,32 @@ util_destroy_rgba_surface(struct pipe_resource *texture,
struct pipe_surface *surface);
-extern boolean
-util_framebuffer_state_equal(const struct pipe_framebuffer_state *dst,
- const struct pipe_framebuffer_state *src);
extern void
-util_copy_framebuffer_state(struct pipe_framebuffer_state *dst,
- const struct pipe_framebuffer_state *src);
+util_resource_copy_region(struct pipe_context *pipe,
+ struct pipe_resource *dst,
+ struct pipe_subresource subdst,
+ unsigned dst_x, unsigned dst_y, unsigned dst_z,
+ struct pipe_resource *src,
+ struct pipe_subresource subsrc,
+ unsigned src_x, unsigned src_y, unsigned src_z,
+ unsigned w, unsigned h);
+extern void
+util_clear_render_target(struct pipe_context *pipe,
+ struct pipe_surface *dst,
+ const float *rgba,
+ unsigned dstx, unsigned dsty,
+ unsigned width, unsigned height);
extern void
-util_unreference_framebuffer_state(struct pipe_framebuffer_state *fb);
+util_clear_depth_stencil(struct pipe_context *pipe,
+ struct pipe_surface *dst,
+ unsigned clear_flags,
+ double depth,
+ unsigned stencil,
+ unsigned dstx, unsigned dsty,
+ unsigned width, unsigned height);
#endif /* U_SURFACE_H */
diff --git a/src/gallium/auxiliary/util/u_surfaces.c b/src/gallium/auxiliary/util/u_surfaces.c
index 668da8c5c27..404e1219952 100644
--- a/src/gallium/auxiliary/util/u_surfaces.c
+++ b/src/gallium/auxiliary/util/u_surfaces.c
@@ -1,42 +1,50 @@
+/**************************************************************************
+ *
+ * Copyright 2010 Luca Barbieri
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
#include "u_surfaces.h"
#include "util/u_hash_table.h"
#include "util/u_inlines.h"
#include "util/u_memory.h"
-/* TODO: ouch, util_hash_table should do these by default when passed a null function pointer
- * this indirect function call is quite bad
- */
-static unsigned
-hash(void *key)
-{
- return (unsigned)(uintptr_t)key;
-}
-
-static int
-compare(void *key1, void *key2)
-{
- return (unsigned)(uintptr_t)key1 - (unsigned)(uintptr_t)key2;
-}
-
struct pipe_surface *
util_surfaces_do_get(struct util_surfaces *us, unsigned surface_struct_size, struct pipe_screen *pscreen, struct pipe_resource *pt, unsigned face, unsigned level, unsigned zslice, unsigned flags)
{
struct pipe_surface *ps;
- void *key = NULL;
if(pt->target == PIPE_TEXTURE_3D || pt->target == PIPE_TEXTURE_CUBE)
- { /* or 2D array */
- if(!us->u.table)
- us->u.table = util_hash_table_create(hash, compare);
- key = (void *)(((zslice + face) << 8) | level);
- /* TODO: ouch, should have a get-reference function...
- * also, shouldn't allocate a two-pointer structure for each item... */
- ps = util_hash_table_get(us->u.table, key);
+ { /* or 2D array */
+ if(!us->u.hash)
+ us->u.hash = cso_hash_create();
+
+ ps = cso_hash_iter_data(cso_hash_find(us->u.hash, ((zslice + face) << 8) | level));
}
else
{
if(!us->u.array)
- us->u.array = CALLOC(pt->last_level + 1, sizeof(struct pipe_surface *));
+ us->u.array = CALLOC(pt->last_level + 1, sizeof(struct pipe_surface *));
ps = us->u.array[level];
}
@@ -54,7 +62,7 @@ util_surfaces_do_get(struct util_surfaces *us, unsigned surface_struct_size, str
ps->offset = ~0;
if(pt->target == PIPE_TEXTURE_3D || pt->target == PIPE_TEXTURE_CUBE)
- util_hash_table_set(us->u.table, key, ps);
+ cso_hash_insert(us->u.hash, ((zslice + face) << 8) | level, ps);
else
us->u.array[level] = ps;
@@ -66,47 +74,44 @@ util_surfaces_do_detach(struct util_surfaces *us, struct pipe_surface *ps)
{
struct pipe_resource *pt = ps->texture;
if(pt->target == PIPE_TEXTURE_3D || pt->target == PIPE_TEXTURE_CUBE)
- { /* or 2D array */
- void* key = (void*)(uintptr_t)(((ps->zslice + ps->face) << 8) | ps->level);
- util_hash_table_remove(us->u.table, key);
+ { /* or 2D array */
+ cso_hash_erase(us->u.hash, cso_hash_find(us->u.hash, ((ps->zslice + ps->face) << 8) | ps->level));
}
else
us->u.array[ps->level] = 0;
}
-static enum pipe_error
-util_surfaces_destroy_callback(void *key, void *value, void *data)
-{
- void (*destroy_surface) (struct pipe_surface * ps) = data;
- destroy_surface((struct pipe_surface *)value);
- return PIPE_OK;
-}
-
void
util_surfaces_destroy(struct util_surfaces *us, struct pipe_resource *pt, void (*destroy_surface) (struct pipe_surface *))
{
if(pt->target == PIPE_TEXTURE_3D || pt->target == PIPE_TEXTURE_CUBE)
- { /* or 2D array */
- if(us->u.table)
+ { /* or 2D array */
+ if(us->u.hash)
{
- util_hash_table_foreach(us->u.table, util_surfaces_destroy_callback, destroy_surface);
- util_hash_table_destroy(us->u.table);
- us->u.table = NULL;
+ struct cso_hash_iter iter;
+ iter = cso_hash_first_node(us->u.hash);
+ while (!cso_hash_iter_is_null(iter)) {
+ destroy_surface(cso_hash_iter_data(iter));
+ iter = cso_hash_iter_next(iter);
+ }
+
+ cso_hash_delete(us->u.hash);
+ us->u.hash = NULL;
}
}
else
{
if(us->u.array)
{
- unsigned i;
- for(i = 0; i < pt->last_level; ++i)
- {
- struct pipe_surface *ps = us->u.array[i];
- if(ps)
- destroy_surface(ps);
- }
- FREE(us->u.array);
- us->u.array = NULL;
+ unsigned i;
+ for(i = 0; i <= pt->last_level; ++i)
+ {
+ struct pipe_surface *ps = us->u.array[i];
+ if(ps)
+ destroy_surface(ps);
+ }
+ FREE(us->u.array);
+ us->u.array = NULL;
}
}
}
diff --git a/src/gallium/auxiliary/util/u_surfaces.h b/src/gallium/auxiliary/util/u_surfaces.h
index 0195bf5afba..17d8a5d3a5b 100644
--- a/src/gallium/auxiliary/util/u_surfaces.h
+++ b/src/gallium/auxiliary/util/u_surfaces.h
@@ -1,18 +1,44 @@
+/**************************************************************************
+ *
+ * Copyright 2010 Luca Barbieri
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
#ifndef U_SURFACES_H_
#define U_SURFACES_H_
#include "pipe/p_compiler.h"
#include "pipe/p_state.h"
#include "util/u_atomic.h"
-
-struct util_hash_table;
+#include "cso_cache/cso_hash.h"
struct util_surfaces
{
union
{
- struct util_hash_table *table;
+ struct cso_hash *hash;
struct pipe_surface **array;
+ void* pv;
} u;
};
@@ -22,7 +48,7 @@ struct pipe_surface *util_surfaces_do_get(struct util_surfaces *us, unsigned sur
static INLINE struct pipe_surface *
util_surfaces_get(struct util_surfaces *us, unsigned surface_struct_size, struct pipe_screen *pscreen, struct pipe_resource *pt, unsigned face, unsigned level, unsigned zslice, unsigned flags)
{
- if(likely(pt->target == PIPE_TEXTURE_2D && us->u.array))
+ if(likely((pt->target == PIPE_TEXTURE_2D || pt->target == PIPE_TEXTURE_RECT) && us->u.array))
{
struct pipe_surface *ps = us->u.array[level];
if(ps)
@@ -35,12 +61,24 @@ util_surfaces_get(struct util_surfaces *us, unsigned surface_struct_size, struct
return util_surfaces_do_get(us, surface_struct_size, pscreen, pt, face, level, zslice, flags);
}
+static INLINE struct pipe_surface *
+util_surfaces_peek(struct util_surfaces *us, struct pipe_resource *pt, unsigned face, unsigned level, unsigned zslice)
+{
+ if(!us->u.pv)
+ return 0;
+
+ if(unlikely(pt->target == PIPE_TEXTURE_3D || pt->target == PIPE_TEXTURE_CUBE))
+ return cso_hash_iter_data(cso_hash_find(us->u.hash, ((zslice + face) << 8) | level));
+ else
+ return us->u.array[level];
+}
+
void util_surfaces_do_detach(struct util_surfaces *us, struct pipe_surface *ps);
static INLINE void
util_surfaces_detach(struct util_surfaces *us, struct pipe_surface *ps)
{
- if(likely(ps->texture->target == PIPE_TEXTURE_2D))
+ if(likely(ps->texture->target == PIPE_TEXTURE_2D || ps->texture->target == PIPE_TEXTURE_RECT))
{
us->u.array[ps->level] = 0;
return;
diff --git a/src/gallium/auxiliary/util/u_tile.h b/src/gallium/auxiliary/util/u_tile.h
index 986eee07435..558351d0ce5 100644
--- a/src/gallium/auxiliary/util/u_tile.h
+++ b/src/gallium/auxiliary/util/u_tile.h
@@ -29,7 +29,10 @@
#define P_TILE_H
#include "pipe/p_compiler.h"
+#include "pipe/p_format.h"
+#include "pipe/p_state.h"
+struct pipe_context;
struct pipe_transfer;
/**
diff --git a/src/gallium/auxiliary/util/u_transfer.c b/src/gallium/auxiliary/util/u_transfer.c
index bedace3b1dc..69f6fab9504 100644
--- a/src/gallium/auxiliary/util/u_transfer.c
+++ b/src/gallium/auxiliary/util/u_transfer.c
@@ -35,12 +35,12 @@ void u_default_transfer_inline_write( struct pipe_context *pipe,
util_copy_rect(map,
resource->format,
- transfer->stride, /* bytes? */
+ transfer->stride, /* bytes */
0, 0,
box->width,
box->height,
data,
- box->width, /* bytes? texels? */
+ stride, /* bytes */
0, 0);
out:
diff --git a/src/gallium/auxiliary/util/u_transfer.h b/src/gallium/auxiliary/util/u_transfer.h
index eb07945d15f..e3a38730f21 100644
--- a/src/gallium/auxiliary/util/u_transfer.h
+++ b/src/gallium/auxiliary/util/u_transfer.h
@@ -8,6 +8,7 @@
#include "pipe/p_state.h"
struct pipe_context;
+struct winsys_handle;
boolean u_default_resource_get_handle(struct pipe_screen *screen,
struct pipe_resource *resource,
diff --git a/src/gallium/auxiliary/util/u_upload_mgr.c b/src/gallium/auxiliary/util/u_upload_mgr.c
index 75d44432d9e..af229e61a00 100644
--- a/src/gallium/auxiliary/util/u_upload_mgr.c
+++ b/src/gallium/auxiliary/util/u_upload_mgr.c
@@ -59,6 +59,8 @@ struct u_upload_mgr *u_upload_create( struct pipe_context *pipe,
unsigned usage )
{
struct u_upload_mgr *upload = CALLOC_STRUCT( u_upload_mgr );
+ if (!upload)
+ return NULL;
upload->pipe = pipe;
upload->default_size = default_size;
diff --git a/src/gallium/auxiliary/util/u_upload_mgr.h b/src/gallium/auxiliary/util/u_upload_mgr.h
index a124924fc80..de016df02e0 100644
--- a/src/gallium/auxiliary/util/u_upload_mgr.h
+++ b/src/gallium/auxiliary/util/u_upload_mgr.h
@@ -32,11 +32,8 @@
#ifndef U_UPLOAD_MGR_H
#define U_UPLOAD_MGR_H
-#include "pipe/p_defines.h"
-
-struct pipe_screen;
+struct pipe_context;
struct pipe_resource;
-struct u_upload_mgr;
struct u_upload_mgr *u_upload_create( struct pipe_context *pipe,