summaryrefslogtreecommitdiff
path: root/src/gallium/auxiliary/util
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/auxiliary/util')
-rw-r--r--src/gallium/auxiliary/util/u_blitter.c341
-rw-r--r--src/gallium/auxiliary/util/u_blitter.h93
-rw-r--r--src/gallium/auxiliary/util/u_caps.c17
-rw-r--r--src/gallium/auxiliary/util/u_cpu_detect.c12
-rw-r--r--src/gallium/auxiliary/util/u_debug.c4
-rw-r--r--src/gallium/auxiliary/util/u_double_list.h17
-rw-r--r--src/gallium/auxiliary/util/u_format.c2
-rw-r--r--src/gallium/auxiliary/util/u_format.h13
-rwxr-xr-xsrc/gallium/auxiliary/util/u_format_table.py5
-rw-r--r--src/gallium/auxiliary/util/u_math.h14
-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
13 files changed, 621 insertions, 155 deletions
diff --git a/src/gallium/auxiliary/util/u_blitter.c b/src/gallium/auxiliary/util/u_blitter.c
index dfe2101c2e..0d94aaae95 100644
--- a/src/gallium/auxiliary/util/u_blitter.c
+++ b/src/gallium/auxiliary/util/u_blitter.c
@@ -52,9 +52,8 @@
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} */
@@ -97,15 +96,25 @@ struct blitter_context_priv
/* 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 +129,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));
@@ -219,17 +229,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);
@@ -260,10 +270,6 @@ void util_blitter_destroy(struct blitter_context *blitter)
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);
}
@@ -271,112 +277,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_assign_framebuffer_state(&ctx->base.saved_fb_state, NULL);
+ 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->base.saved_num_vertex_buffers,
+ ctx->base.saved_vertex_buffers);
- for (i = 0; i < ctx->blitter.saved_num_vertex_buffers; i++) {
- if (ctx->blitter.saved_vertex_buffers[i].buffer) {
- pipe_resource_reference(&ctx->blitter.saved_vertex_buffers[i].buffer,
+ 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->blitter.saved_num_vertex_buffers = ~0;
+ 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,
@@ -401,29 +412,45 @@ static void blitter_set_clear_color(struct blitter_context_priv *ctx,
}
}
+static void get_normalized_texcoords(struct pipe_resource *src,
+ struct pipe_subresource subsrc,
+ unsigned x1, unsigned y1,
+ unsigned x2, unsigned y2,
+ float out[4])
+{
+ 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);
+}
+
+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*/
+}
+
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)
{
- int i;
- float s1 = x1 / (float)u_minify(src->width0, subsrc.level);
- float t1 = y1 / (float)u_minify(src->height0, subsrc.level);
- float s2 = x2 / (float)u_minify(src->width0, subsrc.level);
- float t2 = y2 / (float)u_minify(src->height0, subsrc.level);
-
- ctx->vertices[0][1][0] = s1; /*t0.s*/
- ctx->vertices[0][1][1] = t1; /*t0.t*/
-
- ctx->vertices[1][1][0] = s2; /*t1.s*/
- ctx->vertices[1][1][1] = t1; /*t1.t*/
-
- ctx->vertices[2][1][0] = s2; /*t2.s*/
- ctx->vertices[2][1][1] = t2; /*t2.t*/
+ unsigned i;
+ float coord[4];
- ctx->vertices[3][1][0] = s1; /*t3.s*/
- ctx->vertices[3][1][1] = t2; /*t3.t*/
+ get_normalized_texcoords(src, subsrc, x1, y1, x2, y2, 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*/
@@ -454,20 +481,11 @@ static void blitter_set_texcoords_cube(struct blitter_context_priv *ctx,
unsigned x2, unsigned y2)
{
int i;
- float s1 = x1 / (float)u_minify(src->width0, subsrc.level);
- float t1 = y1 / (float)u_minify(src->height0, subsrc.level);
- float s2 = x2 / (float)u_minify(src->width0, subsrc.level);
- float t2 = y2 / (float)u_minify(src->height0, subsrc.level);
+ 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_normalized_texcoords(src, subsrc, x1, y1, x2, y2, coord);
+ set_texcoords_in_vertices(coord, &st[0][0], 2);
util_map_texcoords2d_onto_cubemap(subsrc.face,
/* pointer, stride in floats */
@@ -478,9 +496,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,
@@ -495,7 +520,7 @@ static INLINE
void **blitter_get_sampler_state(struct blitter_context_priv *ctx,
int miplevel)
{
- 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);
@@ -518,7 +543,7 @@ void **blitter_get_sampler_state(struct blitter_context_priv *ctx,
static INLINE
void *blitter_get_fs_col(struct blitter_context_priv *ctx, unsigned num_cbufs)
{
- struct pipe_context *pipe = ctx->pipe;
+ struct pipe_context *pipe = ctx->base.pipe;
assert(num_cbufs <= PIPE_MAX_COLOR_BUFS);
@@ -531,7 +556,7 @@ void *blitter_get_fs_col(struct blitter_context_priv *ctx, unsigned num_cbufs)
/** Convert PIPE_TEXTURE_x to TGSI_TEXTURE_x */
static unsigned
-pipe_tex_to_tgsi_tex(unsigned pipe_tex_target)
+pipe_tex_to_tgsi_tex(enum pipe_texture_target pipe_tex_target)
{
switch (pipe_tex_target) {
case PIPE_TEXTURE_1D:
@@ -553,7 +578,7 @@ 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);
@@ -572,7 +597,7 @@ 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);
@@ -588,6 +613,31 @@ void *blitter_get_fs_texfetch_depth(struct blitter_context_priv *ctx,
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,
@@ -596,7 +646,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);
@@ -630,9 +680,9 @@ 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);
}
@@ -654,7 +704,7 @@ void util_blitter_copy_region(struct blitter_context *blitter,
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;
@@ -736,11 +786,6 @@ void util_blitter_copy_region(struct blitter_context *blitter,
u_sampler_view_default_template(&viewTempl, src, src->format);
view = pipe->create_sampler_view(pipe, src, &viewTempl);
- if (ctx->sampler_view) {
- pipe_sampler_view_reference(&ctx->sampler_view, NULL);
- }
- ctx->sampler_view = view;
-
/* Set rasterizer state, shaders, and textures. */
pipe->bind_rasterizer_state(pipe, ctx->rs_state);
pipe->bind_vs_state(pipe, ctx->vs_tex);
@@ -750,32 +795,49 @@ void util_blitter_copy_region(struct blitter_context *blitter,
pipe->set_fragment_sampler_views(pipe, 1, &view);
pipe->set_framebuffer_state(pipe, &fb_state);
- /* Set texture coordinates. */
+ 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, subsrc,
- srcx, srcy, srcx+width, srcy+height);
+ {
+ /* Set texture coordinates. */
+ float coord[4];
+ get_normalized_texcoords(src, subsrc, srcx, srcy,
+ srcx+width, srcy+height, 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, subsrc, srcz,
- srcx, srcy, srcx+width, srcy+height);
- break;
case PIPE_TEXTURE_CUBE:
- blitter_set_texcoords_cube(ctx, src, subsrc,
- 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,
- dstsurf->width, dstsurf->height, 0);
- blitter_draw_quad(ctx);
blitter_restore_CSOs(ctx);
pipe_surface_reference(&dstsurf, NULL);
+ pipe_sampler_view_reference(&view, NULL);
}
/* Clear a region of a color surface to a constant value. */
@@ -786,7 +848,7 @@ void util_blitter_clear_render_target(struct blitter_context *blitter,
unsigned width, unsigned height)
{
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_framebuffer_state fb_state;
assert(dstsurf->texture);
@@ -813,9 +875,9 @@ void util_blitter_clear_render_target(struct blitter_context *blitter,
fb_state.zsbuf = 0;
pipe->set_framebuffer_state(pipe, &fb_state);
- blitter_set_clear_color(ctx, rgba);
- blitter_set_rectangle(ctx, 0, 0, width, height, dstsurf->width, dstsurf->height, 0);
- blitter_draw_quad(ctx);
+ 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);
}
@@ -829,7 +891,7 @@ void util_blitter_clear_depth_stencil(struct blitter_context *blitter,
unsigned width, unsigned height)
{
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_framebuffer_state fb_state;
struct pipe_stencil_ref sr = { { 0 } };
@@ -873,7 +935,8 @@ void util_blitter_clear_depth_stencil(struct blitter_context *blitter,
fb_state.zsbuf = dstsurf;
pipe->set_framebuffer_state(pipe, &fb_state);
- blitter_set_rectangle(ctx, 0, 0, width, height, dstsurf->width, dstsurf->height, depth);
- blitter_draw_quad(ctx);
+ 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);
}
diff --git a/src/gallium/auxiliary/util/u_blitter.h b/src/gallium/auxiliary/util/u_blitter.h
index 22849280ab..ba3f92eca8 100644
--- a/src/gallium/auxiliary/util/u_blitter.h
+++ b/src/gallium/auxiliary/util/u_blitter.h
@@ -39,9 +39,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 */
@@ -73,6 +112,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
@@ -208,11 +256,45 @@ void util_blitter_save_vertex_shader(struct blitter_context *blitter,
blitter->saved_vs = vs;
}
+/* XXX This should probably be moved elsewhere. */
+static INLINE
+void util_assign_framebuffer_state(struct pipe_framebuffer_state *dst,
+ const struct pipe_framebuffer_state *src)
+{
+ unsigned i;
+
+ if (src) {
+ /* Reference all surfaces. */
+ for (i = 0; i < src->nr_cbufs; i++) {
+ pipe_surface_reference(&dst->cbufs[i], src->cbufs[i]);
+ }
+ for (; i < dst->nr_cbufs; i++) {
+ pipe_surface_reference(&dst->cbufs[i], NULL);
+ }
+
+ pipe_surface_reference(&dst->zsbuf, src->zsbuf);
+
+ dst->nr_cbufs = src->nr_cbufs;
+ dst->width = src->width;
+ dst->height = src->height;
+ } else {
+ /* Set all surfaces to NULL. */
+ for (i = 0; i < dst->nr_cbufs; i++) {
+ pipe_surface_reference(&dst->cbufs[i], NULL);
+ }
+
+ pipe_surface_reference(&dst->zsbuf, NULL);
+
+ dst->nr_cbufs = 0;
+ }
+}
+
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_assign_framebuffer_state(&blitter->saved_fb_state, state);
}
static INLINE
@@ -247,12 +329,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
diff --git a/src/gallium/auxiliary/util/u_caps.c b/src/gallium/auxiliary/util/u_caps.c
index 294ee37033..94d5bd3027 100644
--- a/src/gallium/auxiliary/util/u_caps.c
+++ b/src/gallium/auxiliary/util/u_caps.c
@@ -186,6 +186,22 @@ static unsigned caps_opengl_2_1[] = {
/* OpenGL 3.0 */
/* UTIL_CHECK_INT(MAX_RENDER_TARGETS, 8), */
+/* Shader Model 3 */
+static unsigned caps_sm3[] = {
+ UTIL_CHECK_INT(MAX_FS_INSTRUCTIONS, 512),
+ UTIL_CHECK_INT(MAX_FS_INPUTS, 10),
+ UTIL_CHECK_INT(MAX_FS_TEMPS, 32),
+ UTIL_CHECK_INT(MAX_FS_ADDRS, 1),
+ UTIL_CHECK_INT(MAX_FS_CONSTS, 224),
+
+ UTIL_CHECK_INT(MAX_VS_INSTRUCTIONS, 512),
+ UTIL_CHECK_INT(MAX_VS_INPUTS, 16),
+ UTIL_CHECK_INT(MAX_VS_TEMPS, 32),
+ UTIL_CHECK_INT(MAX_VS_ADDRS, 2),
+ UTIL_CHECK_INT(MAX_VS_CONSTS, 256),
+
+ UTIL_CHECK_TERMINATE
+};
/**
* Demo function which checks against theoretical caps needed for different APIs.
@@ -203,6 +219,7 @@ void util_caps_demo_print(struct pipe_screen *screen)
{"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;
diff --git a/src/gallium/auxiliary/util/u_cpu_detect.c b/src/gallium/auxiliary/util/u_cpu_detect.c
index a08241971c..23d33af4e4 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>
@@ -132,7 +132,7 @@ win32_sig_handler_sse(EXCEPTION_POINTERS* ep)
#endif /* PIPE_ARCH_X86 */
-#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 +153,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 +166,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,7 +184,7 @@ 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 */
diff --git a/src/gallium/auxiliary/util/u_debug.c b/src/gallium/auxiliary/util/u_debug.c
index 5e373ff24c..ad162558bc 100644
--- a/src/gallium/auxiliary/util/u_debug.c
+++ b/src/gallium/auxiliary/util/u_debug.c
@@ -190,11 +190,11 @@ debug_get_flags_option(const char *name,
result = dfault;
else if (!util_strcmp(str, "help")) {
result = dfault;
- debug_printf("%s: help for %s:\n", __FUNCTION__, name);
+ _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,
+ _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 : "");
}
diff --git a/src/gallium/auxiliary/util/u_double_list.h b/src/gallium/auxiliary/util/u_double_list.h
index 53bb1342dd..42adb1f069 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_format.c b/src/gallium/auxiliary/util/u_format.c
index 3168a1fab4..43d09f1960 100644
--- a/src/gallium/auxiliary/util/u_format.c
+++ b/src/gallium/auxiliary/util/u_format.c
@@ -120,7 +120,7 @@ util_format_write_4ub(enum pipe_format format, const uint8_t *src, unsigned src_
}
-static INLINE boolean
+boolean
util_format_fits_8unorm(const struct util_format_description *format_desc)
{
unsigned chan;
diff --git a/src/gallium/auxiliary/util/u_format.h b/src/gallium/auxiliary/util/u_format.h
index fd95bea1a7..38254b1096 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.
*
@@ -663,6 +673,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_table.py b/src/gallium/auxiliary/util/u_format_table.py
index ae9a598197..f0b407b8b8 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_math.h b/src/gallium/auxiliary/util/u_math.h
index 6370e77986..fe19466436 100644
--- a/src/gallium/auxiliary/util/u_math.h
+++ b/src/gallium/auxiliary/util/u_math.h
@@ -567,12 +567,26 @@ util_bswap16(uint16_t n)
#define MAX3( A, B, C ) MAX2( MAX2( A, B ), C )
+/**
+ * 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 0000000000..1f336b39a1
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_mempool.c
@@ -0,0 +1,169 @@
+/*
+ * Copyright 2010 Marek Olšák <maraeo@gmail.com>
+ *
+ * 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 0000000000..a5b5d6a9b7
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_mempool.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2010 Marek Olšák <maraeo@gmail.com>
+ *
+ * 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 87ee0e4768..77f2c5fc7d 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>