summaryrefslogtreecommitdiff
path: root/src/gallium/auxiliary
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/auxiliary')
-rw-r--r--src/gallium/auxiliary/cso_cache/cso_context.c36
-rw-r--r--src/gallium/auxiliary/cso_cache/cso_context.h13
-rw-r--r--src/gallium/auxiliary/draw/draw_passthrough.c349
-rw-r--r--src/gallium/auxiliary/draw/draw_prim.c3
-rw-r--r--src/gallium/auxiliary/draw/draw_vbuf.h6
-rw-r--r--src/gallium/auxiliary/rtasm/rtasm_ppc_spe.c16
-rw-r--r--src/gallium/auxiliary/util/Makefile4
-rw-r--r--src/gallium/auxiliary/util/SConscript4
-rw-r--r--src/gallium/auxiliary/util/u_blit.c276
-rw-r--r--src/gallium/auxiliary/util/u_blit.h60
-rw-r--r--src/gallium/auxiliary/util/u_draw_quad.c112
-rw-r--r--src/gallium/auxiliary/util/u_draw_quad.h37
-rw-r--r--src/gallium/auxiliary/util/u_gen_mipmap.c877
-rw-r--r--src/gallium/auxiliary/util/u_gen_mipmap.h52
-rw-r--r--src/gallium/auxiliary/util/u_handle_table.c30
-rw-r--r--src/gallium/auxiliary/util/u_handle_table.h9
-rw-r--r--src/gallium/auxiliary/util/u_hash_table.c23
-rw-r--r--src/gallium/auxiliary/util/u_hash_table.h5
-rw-r--r--src/gallium/auxiliary/util/u_pack_color.h133
-rw-r--r--src/gallium/auxiliary/util/u_simple_shaders.c263
-rw-r--r--src/gallium/auxiliary/util/u_simple_shaders.h52
21 files changed, 2250 insertions, 110 deletions
diff --git a/src/gallium/auxiliary/cso_cache/cso_context.c b/src/gallium/auxiliary/cso_cache/cso_context.c
index fd86bfaca9..294ac82281 100644
--- a/src/gallium/auxiliary/cso_cache/cso_context.c
+++ b/src/gallium/auxiliary/cso_cache/cso_context.c
@@ -149,6 +149,12 @@ void cso_set_blend(struct cso_context *ctx,
}
}
+void cso_unset_blend(struct cso_context *ctx)
+{
+ ctx->blend = NULL;
+}
+
+
void cso_single_sampler(struct cso_context *ctx,
unsigned idx,
const struct pipe_sampler_state *templ)
@@ -220,6 +226,15 @@ void cso_set_samplers( struct cso_context *ctx,
cso_single_sampler_done( ctx );
}
+void cso_unset_samplers( struct cso_context *ctx )
+{
+ uint i;
+ for (i = 0; i < ctx->nr_samplers; i++)
+ ctx->samplers[i] = NULL;
+}
+
+
+
void cso_set_depth_stencil_alpha(struct cso_context *ctx,
const struct pipe_depth_stencil_alpha_state *templ)
{
@@ -252,6 +267,11 @@ void cso_set_depth_stencil_alpha(struct cso_context *ctx,
}
}
+void cso_unset_depth_stencil_alpha(struct cso_context *ctx)
+{
+ ctx->depth_stencil = NULL;
+}
+
void cso_set_rasterizer(struct cso_context *ctx,
@@ -285,7 +305,10 @@ void cso_set_rasterizer(struct cso_context *ctx,
}
}
-
+void cso_unset_rasterizer(struct cso_context *ctx)
+{
+ ctx->rasterizer = NULL;
+}
@@ -320,6 +343,12 @@ void cso_set_fragment_shader(struct cso_context *ctx,
}
}
+void cso_unset_fragment_shader(struct cso_context *ctx)
+{
+ ctx->fragment_shader = NULL;
+}
+
+
void cso_set_vertex_shader(struct cso_context *ctx,
const struct pipe_shader_state *templ)
{
@@ -350,3 +379,8 @@ void cso_set_vertex_shader(struct cso_context *ctx,
ctx->pipe->bind_vs_state(ctx->pipe, handle);
}
}
+
+void cso_unset_vertex_shader(struct cso_context *ctx)
+{
+ ctx->vertex_shader = NULL;
+}
diff --git a/src/gallium/auxiliary/cso_cache/cso_context.h b/src/gallium/auxiliary/cso_cache/cso_context.h
index 1f2a630804..6aa619abf5 100644
--- a/src/gallium/auxiliary/cso_cache/cso_context.h
+++ b/src/gallium/auxiliary/cso_cache/cso_context.h
@@ -44,16 +44,25 @@ struct cso_context *cso_create_context( struct pipe_context *pipe );
void cso_set_blend( struct cso_context *cso,
const struct pipe_blend_state *blend );
+void cso_unset_blend(struct cso_context *cso);
+
void cso_set_depth_stencil_alpha( struct cso_context *cso,
const struct pipe_depth_stencil_alpha_state *dsa );
+void cso_unset_depth_stencil_alpha( struct cso_context *cso );
+
void cso_set_rasterizer( struct cso_context *cso,
const struct pipe_rasterizer_state *rasterizer );
+void cso_unset_rasterizer( struct cso_context *cso );
+
void cso_set_samplers( struct cso_context *cso,
unsigned count,
const struct pipe_sampler_state **states );
+void cso_unset_samplers( struct cso_context *cso );
+
+
/* Alternate interface to support state trackers that like to modify
* samplers one at a time:
*/
@@ -72,9 +81,13 @@ void cso_single_sampler_done( struct cso_context *cso );
void cso_set_fragment_shader( struct cso_context *cso,
const struct pipe_shader_state *shader );
+void cso_unset_fragment_shader( struct cso_context *cso );
+
void cso_set_vertex_shader( struct cso_context *cso,
const struct pipe_shader_state *shader );
+void cso_unset_vertex_shader( struct cso_context *cso );
+
void cso_destroy_context( struct cso_context *cso );
diff --git a/src/gallium/auxiliary/draw/draw_passthrough.c b/src/gallium/auxiliary/draw/draw_passthrough.c
index d16f056191..fdec6a591b 100644
--- a/src/gallium/auxiliary/draw/draw_passthrough.c
+++ b/src/gallium/auxiliary/draw/draw_passthrough.c
@@ -85,14 +85,52 @@ fetch_store_general( struct draw_context *draw,
const unsigned *pitch = draw->vertex_fetch.pitch;
const ubyte **src = draw->vertex_fetch.src_ptr;
- for (i = start; i < count; i++) {
+ for (i = start; i < start + count; i++) {
for (j = 0; j < nr_attrs; j++) {
+ /* vinfo->src_index is the output of the vertex shader
+ * matching this hw-vertex component.
+ *
+ * In passthrough, we require a 1:1 mapping between vertex
+ * shader outputs and inputs, which in turn correspond to
+ * vertex elements in the state. So, this is the vertex
+ * element we're interested in...
+ */
const uint jj = vinfo->src_index[j];
const enum pipe_format srcFormat = draw->vertex_element[jj].src_format;
const ubyte *from = src[jj] + i * pitch[jj];
float attrib[4];
+ /* Except... When we're not. Two cases EMIT_HEADER &
+ * EMIT_1F_PSIZE don't consume an input. Should have some
+ * method for indicating this, or change the logic here
+ * somewhat so it doesn't matter.
+ *
+ * Just hack this up now, do something better about it later.
+ */
+ if (vinfo->emit[j] == EMIT_HEADER) {
+ memset(out, 0, sizeof(struct vertex_header));
+ out += sizeof(struct vertex_header) / 4;
+ continue;
+ }
+ else if (vinfo->emit[j] == EMIT_1F_PSIZE) {
+ out[0] = 1.0; /* xxx */
+ out += 1;
+ continue;
+ }
+
+
+ /* The normal fetch/emit code:
+ */
switch (srcFormat) {
+ case PIPE_FORMAT_B8G8R8A8_UNORM:
+ {
+ ubyte *ub = (ubyte *) from;
+ attrib[0] = UBYTE_TO_FLOAT(ub[0]);
+ attrib[1] = UBYTE_TO_FLOAT(ub[1]);
+ attrib[2] = UBYTE_TO_FLOAT(ub[2]);
+ attrib[3] = UBYTE_TO_FLOAT(ub[3]);
+ }
+ break;
case PIPE_FORMAT_R32G32B32A32_FLOAT:
{
float *f = (float *) from;
@@ -130,14 +168,21 @@ fetch_store_general( struct draw_context *draw,
}
break;
default:
- abort();
+ assert(0);
}
- /* XXX this will probably only work for softpipe */
+ debug_printf("attrib %d: %f %f %f %f\n", j,
+ attrib[0], attrib[1], attrib[2], attrib[3]);
+
switch (vinfo->emit[j]) {
- case EMIT_HEADER:
- memset(out, 0, sizeof(struct vertex_header));
- out += sizeof(struct vertex_header) / 4;
+ case EMIT_1F:
+ out[0] = attrib[0];
+ out += 1;
+ break;
+ case EMIT_2F:
+ out[0] = attrib[0];
+ out[1] = attrib[1];
+ out += 2;
break;
case EMIT_4F:
out[0] = attrib[0];
@@ -147,64 +192,15 @@ fetch_store_general( struct draw_context *draw,
out += 4;
break;
default:
- abort();
+ assert(0);
}
-
}
+ debug_printf("\n");
}
}
-/* Example of a fetch/emit passthrough shader which could be
- * generated when bypass_clipping is enabled on a passthrough vertex
- * shader.
- */
-static void fetch_xyz_rgb_st( struct draw_context *draw,
- float *out,
- unsigned start,
- unsigned count )
-{
- const unsigned *pitch = draw->vertex_fetch.pitch;
- const ubyte **src = draw->vertex_fetch.src_ptr;
- unsigned i;
-
- const ubyte *xyzw = src[0] + start * pitch[0];
- const ubyte *rgba = src[1] + start * pitch[1];
- const ubyte *st = src[2] + start * pitch[2];
-
- /* loop over vertex attributes (vertex shader inputs)
- */
- for (i = 0; i < count; i++) {
- {
- const float *in = (const float *)xyzw; xyzw += pitch[0];
- /* decode input, encode output. Assume both are float[4] */
- out[0] = in[0];
- out[1] = in[1];
- out[2] = in[2];
- out[3] = in[3];
- }
-
- {
- const float *in = (const float *)rgba; rgba += pitch[1];
- /* decode input, encode output. Assume both are float[4] */
- out[4] = in[0];
- out[5] = in[1];
- out[6] = in[2];
- out[7] = in[3];
- }
-
- {
- const float *in = (const float *)st; st += pitch[2];
- /* decode input, encode output. Assume both are float[2] */
- out[8] = in[0];
- out[9] = in[1];
- }
-
- out += 10;
- }
-}
-
static boolean update_shader( struct draw_context *draw )
{
const struct vertex_info *vinfo = draw->render->get_vertex_info(draw->render);
@@ -229,70 +225,166 @@ static boolean update_shader( struct draw_context *draw )
draw->pt.hw_vertex_size = vinfo->size * 4;
- /* Just trying to figure out how this would work:
- */
- if (draw->rasterizer->bypass_vs ||
- (nr_attrs == 3 && 0 /* some other tests */))
- {
-#if 0
- draw->vertex_fetch.pt_fetch = fetch_xyz_rgb_st;
-#else
- draw->vertex_fetch.pt_fetch = fetch_store_general;
-#endif
- /*assert(vinfo->size == 10);*/
+ draw->vertex_fetch.pt_fetch = fetch_store_general;
+ return TRUE;
+}
+
+
+
+
+static boolean split_prim_inplace(unsigned prim, unsigned *first, unsigned *incr)
+{
+ switch (prim) {
+ case PIPE_PRIM_POINTS:
+ *first = 1;
+ *incr = 1;
+ return TRUE;
+ case PIPE_PRIM_LINES:
+ *first = 2;
+ *incr = 2;
return TRUE;
+ case PIPE_PRIM_LINE_STRIP:
+ *first = 2;
+ *incr = 1;
+ return TRUE;
+ case PIPE_PRIM_TRIANGLES:
+ *first = 3;
+ *incr = 3;
+ return TRUE;
+ case PIPE_PRIM_TRIANGLE_STRIP:
+ *first = 3;
+ *incr = 1;
+ return TRUE;
+ case PIPE_PRIM_QUADS:
+ *first = 4;
+ *incr = 4;
+ return TRUE;
+ case PIPE_PRIM_QUAD_STRIP:
+ *first = 4;
+ *incr = 2;
+ return TRUE;
+ default:
+ *first = 0;
+ *incr = 1; /* set to one so that count % incr works */
+ return FALSE;
}
-
- return FALSE;
}
static boolean set_prim( struct draw_context *draw,
- unsigned prim )
+ unsigned prim,
+ unsigned count )
{
assert(!draw->user.elts);
- draw->pt.prim = prim;
-
switch (prim) {
case PIPE_PRIM_LINE_LOOP:
+ if (count > 1024)
+ return FALSE;
+ return draw->render->set_primitive( draw->render, PIPE_PRIM_LINE_STRIP );
+
+ case PIPE_PRIM_TRIANGLE_FAN:
+ case PIPE_PRIM_POLYGON:
+ if (count > 1024)
+ return FALSE;
+ return draw->render->set_primitive( draw->render, prim );
+
case PIPE_PRIM_QUADS:
case PIPE_PRIM_QUAD_STRIP:
- return FALSE;
+ return draw->render->set_primitive( draw->render, PIPE_PRIM_TRIANGLES );
+
default:
- draw->render->set_primitive( draw->render, prim );
- return TRUE;
+ return draw->render->set_primitive( draw->render, prim );
+ break;
}
+
+ return TRUE;
}
-boolean
-draw_passthrough_arrays(struct draw_context *draw,
- unsigned prim,
- unsigned start,
- unsigned count)
+
+#define INDEX(i) (start + (i))
+static void pt_draw_arrays( struct draw_context *draw,
+ unsigned start,
+ unsigned length )
{
- float *hw_verts;
+ ushort *tmp = NULL;
+ unsigned i, j;
- if (draw_need_pipeline(draw))
- return FALSE;
+ switch (draw->pt.prim) {
+ case PIPE_PRIM_LINE_LOOP:
+ tmp = MALLOC( sizeof(ushort) * (length + 1) );
- if (!set_prim(draw, prim))
- return FALSE;
+ for (i = 0; i < length; i++)
+ tmp[i] = INDEX(i);
+ tmp[length] = 0;
- if (!update_shader(draw))
- return FALSE;
+ draw->render->draw( draw->render,
+ tmp,
+ length+1 );
+ break;
- hw_verts = draw->render->allocate_vertices( draw->render,
- draw->pt.hw_vertex_size,
- count );
+
+ case PIPE_PRIM_QUAD_STRIP:
+ tmp = MALLOC( sizeof(ushort) * (length / 2 * 6) );
+
+ for (j = i = 0; i + 3 < length; i += 2, j += 6) {
+ tmp[j+0] = INDEX(i+0);
+ tmp[j+1] = INDEX(i+1);
+ tmp[j+2] = INDEX(i+3);
+
+ tmp[j+3] = INDEX(i+2);
+ tmp[j+4] = INDEX(i+0);
+ tmp[j+5] = INDEX(i+3);
+ }
+
+ if (j)
+ draw->render->draw( draw->render, tmp, j );
+ break;
+
+ case PIPE_PRIM_QUADS:
+ tmp = MALLOC( sizeof(int) * (length / 4 * 6) );
+
+ for (j = i = 0; i + 3 < length; i += 4, j += 6) {
+ tmp[j+0] = INDEX(i+0);
+ tmp[j+1] = INDEX(i+1);
+ tmp[j+2] = INDEX(i+3);
+
+ tmp[j+3] = INDEX(i+1);
+ tmp[j+4] = INDEX(i+2);
+ tmp[j+5] = INDEX(i+3);
+ }
+
+ if (j)
+ draw->render->draw( draw->render, tmp, j );
+ break;
+
+ default:
+ draw->render->draw_arrays( draw->render,
+ start,
+ length );
+ break;
+ }
+
+ if (tmp)
+ FREE(tmp);
+}
+
+
+
+static boolean do_draw( struct draw_context *draw,
+ unsigned start, unsigned count )
+{
+ float *hw_verts =
+ draw->render->allocate_vertices( draw->render,
+ (ushort)draw->pt.hw_vertex_size,
+ (ushort)count );
if (!hw_verts)
return FALSE;
- /* Single routine to fetch vertices, run shader and emit HW verts.
- * Clipping and viewport transformation are done on hardware.
+ /* Single routine to fetch vertices and emit HW verts.
*/
draw->vertex_fetch.pt_fetch( draw,
hw_verts,
@@ -301,9 +393,9 @@ draw_passthrough_arrays(struct draw_context *draw,
/* Draw arrays path to avoid re-emitting index list again and
* again.
*/
- draw->render->draw_arrays( draw->render,
- start,
- count );
+ pt_draw_arrays( draw,
+ 0,
+ count );
draw->render->release_vertices( draw->render,
@@ -314,3 +406,68 @@ draw_passthrough_arrays(struct draw_context *draw,
return TRUE;
}
+
+boolean
+draw_passthrough_arrays(struct draw_context *draw,
+ unsigned prim,
+ unsigned start,
+ unsigned count)
+{
+ unsigned i = 0;
+ unsigned first, incr;
+
+ //debug_printf("%s prim %d start %d count %d\n", __FUNCTION__, prim, start, count);
+
+ split_prim_inplace(prim, &first, &incr);
+
+ count -= (count - first) % incr;
+
+ debug_printf("%s %d %d %d\n", __FUNCTION__, prim, start, count);
+
+ if (draw_need_pipeline(draw))
+ return FALSE;
+
+ debug_printf("%s AAA\n", __FUNCTION__);
+
+ if (!set_prim(draw, prim, count))
+ return FALSE;
+
+ /* XXX: need a single value that reflects the most recent call to
+ * driver->set_primitive:
+ */
+ draw->pt.prim = prim;
+
+ debug_printf("%s BBB\n", __FUNCTION__);
+
+ if (!update_shader(draw))
+ return FALSE;
+
+ debug_printf("%s CCC\n", __FUNCTION__);
+
+ /* Chop this up into bite-sized pieces that a driver should be able
+ * to devour -- problem is we don't have a quick way to query the
+ * driver on the maximum size for this chunk in the current state.
+ */
+ while (i + first <= count) {
+ int nr = MIN2( count - i, 1024 );
+
+ /* snap to prim boundary
+ */
+ nr -= (nr - first) % incr;
+
+ if (!do_draw( draw, start + i, nr )) {
+ assert(0);
+ return FALSE;
+ }
+
+ /* increment allowing for repeated vertices
+ */
+ i += nr - (first - incr);
+ }
+
+
+ debug_printf("%s DONE\n", __FUNCTION__);
+ return TRUE;
+}
+
+
diff --git a/src/gallium/auxiliary/draw/draw_prim.c b/src/gallium/auxiliary/draw/draw_prim.c
index 888fa536ea..cb0277fb6c 100644
--- a/src/gallium/auxiliary/draw/draw_prim.c
+++ b/src/gallium/auxiliary/draw/draw_prim.c
@@ -169,11 +169,12 @@ void draw_do_flush( struct draw_context *draw, unsigned flags )
flushing = TRUE;
if (flags >= DRAW_FLUSH_SHADER_QUEUE) {
- if (draw->vs.queue_nr)
+ if (draw->vs.queue_nr) {
if (draw->rasterizer->bypass_vs)
fetch_and_store(draw);
else
(*draw->shader_queue_flush)(draw);
+ }
if (flags >= DRAW_FLUSH_PRIM_QUEUE) {
if (draw->pq.queue_nr)
diff --git a/src/gallium/auxiliary/draw/draw_vbuf.h b/src/gallium/auxiliary/draw/draw_vbuf.h
index 5e7de905c1..e90f37872a 100644
--- a/src/gallium/auxiliary/draw/draw_vbuf.h
+++ b/src/gallium/auxiliary/draw/draw_vbuf.h
@@ -74,9 +74,11 @@ struct vbuf_render {
/**
* Notify the renderer of the current primitive when it changes.
- * Prim is restricted to TRIANGLES, LINES and POINTS.
+ * Must succeed for TRIANGLES, LINES and POINTS. Other prims at
+ * the discretion of the driver, for the benefit of the passthrough
+ * path.
*/
- void (*set_primitive)( struct vbuf_render *, unsigned prim );
+ boolean (*set_primitive)( struct vbuf_render *, unsigned prim );
/**
* DrawElements, note indices are ushort:
diff --git a/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.c b/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.c
index a996218ce7..24be65bff9 100644
--- a/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.c
+++ b/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.c
@@ -316,7 +316,9 @@ void spe_init_func(struct spe_function *p, unsigned code_size)
void spe_release_func(struct spe_function *p)
{
- align_free(p->store);
+ if (p->store != NULL) {
+ align_free(p->store);
+ }
p->store = NULL;
p->csr = NULL;
}
@@ -326,8 +328,8 @@ int spe_allocate_available_register(struct spe_function *p)
{
unsigned i;
for (i = 0; i < 128; i++) {
- const uint64_t mask = (1ULL << (i % 128));
- const unsigned idx = i / 128;
+ const uint64_t mask = (1ULL << (i % 64));
+ const unsigned idx = i / 64;
if ((p->regs[idx] & mask) != 0) {
p->regs[idx] &= ~mask;
@@ -341,8 +343,8 @@ int spe_allocate_available_register(struct spe_function *p)
int spe_allocate_register(struct spe_function *p, int reg)
{
- const unsigned idx = reg / 128;
- const unsigned bit = reg % 128;
+ const unsigned idx = reg / 64;
+ const unsigned bit = reg % 64;
assert((p->regs[idx] & (1ULL << bit)) != 0);
@@ -353,8 +355,8 @@ int spe_allocate_register(struct spe_function *p, int reg)
void spe_release_register(struct spe_function *p, int reg)
{
- const unsigned idx = reg / 128;
- const unsigned bit = reg % 128;
+ const unsigned idx = reg / 64;
+ const unsigned bit = reg % 64;
assert((p->regs[idx] & (1ULL << bit)) == 0);
diff --git a/src/gallium/auxiliary/util/Makefile b/src/gallium/auxiliary/util/Makefile
index 2016c6fb1f..9b6c2708b6 100644
--- a/src/gallium/auxiliary/util/Makefile
+++ b/src/gallium/auxiliary/util/Makefile
@@ -7,9 +7,13 @@ C_SOURCES = \
p_debug.c \
p_tile.c \
p_util.c \
+ u_blit.c \
+ u_draw_quad.c \
+ u_gen_mipmap.c \
u_handle_table.c \
u_hash_table.c \
u_mm.c \
+ u_simple_shaders.c \
u_snprintf.c
include ../../Makefile.template
diff --git a/src/gallium/auxiliary/util/SConscript b/src/gallium/auxiliary/util/SConscript
index 154a3eca8c..b44f2d5e39 100644
--- a/src/gallium/auxiliary/util/SConscript
+++ b/src/gallium/auxiliary/util/SConscript
@@ -6,9 +6,13 @@ util = env.ConvenienceLibrary(
'p_debug.c',
'p_tile.c',
'p_util.c',
+ 'u_blit.c',
+ 'u_draw_quad.c',
+ 'u_gen_mipmap.c',
'u_handle_table.c',
'u_hash_table.c',
'u_mm.c',
+ 'u_simple_shaders.c',
'u_snprintf.c',
])
diff --git a/src/gallium/auxiliary/util/u_blit.c b/src/gallium/auxiliary/util/u_blit.c
new file mode 100644
index 0000000000..4b4ab8185f
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_blit.c
@@ -0,0 +1,276 @@
+/**************************************************************************
+ *
+ * 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.
+ *
+ **************************************************************************/
+
+/**
+ * @file
+ * Copy/blit pixel rect between surfaces
+ *
+ * @author Brian Paul
+ */
+
+
+#include "pipe/p_context.h"
+#include "pipe/p_debug.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_inlines.h"
+#include "pipe/p_util.h"
+#include "pipe/p_winsys.h"
+#include "pipe/p_shader_tokens.h"
+
+#include "util/u_draw_quad.h"
+#include "util/u_blit.h"
+#include "util/u_simple_shaders.h"
+
+
+struct blit_state
+{
+ struct pipe_context *pipe;
+
+ void *blend;
+ void *depthstencil;
+ void *rasterizer;
+ void *samplers[2]; /* one for linear, one for nearest sampling */
+
+ /*struct pipe_viewport_state viewport;*/
+ struct pipe_sampler_state *vs;
+ struct pipe_sampler_state *fs;
+};
+
+
+/**
+ * Create state object for blit.
+ * Intended to be created once and re-used for many blit() calls.
+ */
+struct blit_state *
+util_create_blit(struct pipe_context *pipe)
+{
+ struct pipe_blend_state blend;
+ struct pipe_depth_stencil_alpha_state depthstencil;
+ struct pipe_rasterizer_state rasterizer;
+ struct blit_state *ctx;
+ struct pipe_sampler_state sampler;
+
+ ctx = CALLOC_STRUCT(blit_state);
+ if (!ctx)
+ return NULL;
+
+ ctx->pipe = pipe;
+
+ /* we don't use blending, but need to set valid values */
+ memset(&blend, 0, sizeof(blend));
+ blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE;
+ blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE;
+ blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
+ blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
+ blend.colormask = PIPE_MASK_RGBA;
+ ctx->blend = pipe->create_blend_state(pipe, &blend);
+
+ /* depth/stencil/alpha */
+ memset(&depthstencil, 0, sizeof(depthstencil));
+ ctx->depthstencil = pipe->create_depth_stencil_alpha_state(pipe, &depthstencil);
+
+ /* rasterizer */
+ memset(&rasterizer, 0, sizeof(rasterizer));
+ rasterizer.front_winding = PIPE_WINDING_CW;
+ rasterizer.cull_mode = PIPE_WINDING_NONE;
+ rasterizer.bypass_clipping = 1; /* bypasses viewport too */
+ /*rasterizer.bypass_vs = 1;*/
+ ctx->rasterizer = pipe->create_rasterizer_state(pipe, &rasterizer);
+
+ /* samplers */
+ memset(&sampler, 0, sizeof(sampler));
+ sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
+ sampler.min_img_filter = PIPE_TEX_MIPFILTER_NEAREST;
+ sampler.mag_img_filter = PIPE_TEX_MIPFILTER_NEAREST;
+ sampler.normalized_coords = 1;
+ ctx->samplers[0] = pipe->create_sampler_state(pipe, &sampler);
+
+ sampler.min_img_filter = PIPE_TEX_MIPFILTER_LINEAR;
+ sampler.mag_img_filter = PIPE_TEX_MIPFILTER_LINEAR;
+ ctx->samplers[1] = pipe->create_sampler_state(pipe, &sampler);
+
+
+#if 0
+ /* viewport */
+ ctx->viewport.scale[0] = 1.0;
+ ctx->viewport.scale[1] = 1.0;
+ ctx->viewport.scale[2] = 1.0;
+ ctx->viewport.scale[3] = 1.0;
+ ctx->viewport.translate[0] = 0.0;
+ ctx->viewport.translate[1] = 0.0;
+ ctx->viewport.translate[2] = 0.0;
+ ctx->viewport.translate[3] = 0.0;
+#endif
+
+ /* vertex shader */
+ {
+ const uint semantic_names[] = { TGSI_SEMANTIC_POSITION,
+ TGSI_SEMANTIC_GENERIC };
+ const uint semantic_indexes[] = { 0, 0 };
+ ctx->vs = util_make_vertex_passthrough_shader(pipe, 2, semantic_names,
+ semantic_indexes);
+ }
+
+ /* fragment shader */
+ ctx->fs = util_make_fragment_tex_shader(pipe);
+
+ return ctx;
+}
+
+
+/**
+ * Destroy a blit context
+ */
+void
+util_destroy_blit(struct blit_state *ctx)
+{
+ struct pipe_context *pipe = ctx->pipe;
+
+ pipe->delete_blend_state(pipe, ctx->blend);
+ pipe->delete_depth_stencil_alpha_state(pipe, ctx->depthstencil);
+ pipe->delete_rasterizer_state(pipe, ctx->rasterizer);
+ pipe->delete_sampler_state(pipe, ctx->samplers[0]);
+ pipe->delete_sampler_state(pipe, ctx->samplers[1]);
+
+ pipe->delete_vs_state(pipe, ctx->vs);
+ pipe->delete_fs_state(pipe, ctx->fs);
+
+ FREE(ctx);
+}
+
+
+/**
+ * Copy pixel block from src surface to dst surface.
+ * Overlapping regions are acceptable.
+ * XXX need some control over blitting Z and/or stencil.
+ */
+void
+util_blit_pixels(struct blit_state *ctx,
+ struct pipe_surface *src,
+ int srcX0, int srcY0,
+ int srcX1, int srcY1,
+ struct pipe_surface *dst,
+ int dstX0, int dstY0,
+ int dstX1, int dstY1,
+ float z, uint filter)
+{
+ struct pipe_context *pipe = ctx->pipe;
+ struct pipe_screen *screen = pipe->screen;
+ struct pipe_texture texTemp, *tex;
+ struct pipe_surface *texSurf;
+ struct pipe_framebuffer_state fb;
+ const int srcW = abs(srcX1 - srcX0);
+ const int srcH = abs(srcY1 - srcY0);
+ const int srcLeft = MIN2(srcX0, srcX1);
+ const int srcTop = MIN2(srcY0, srcY1);
+
+ assert(filter == PIPE_TEX_MIPFILTER_NEAREST ||
+ filter == PIPE_TEX_MIPFILTER_LINEAR);
+
+ if (srcLeft != srcX0) {
+ /* left-right flip */
+ int tmp = dstX0;
+ dstX0 = dstX1;
+ dstX1 = tmp;
+ }
+
+ if (srcTop != srcY0) {
+ /* up-down flip */
+ int tmp = dstY0;
+ dstY0 = dstY1;
+ dstY1 = tmp;
+ }
+
+ /*
+ * XXX for now we're always creating a temporary texture.
+ * Strictly speaking that's not always needed.
+ */
+
+ /* create temp texture */
+ memset(&texTemp, 0, sizeof(texTemp));
+ texTemp.target = PIPE_TEXTURE_2D;
+ texTemp.format = src->format;
+ texTemp.last_level = 0;
+ texTemp.width[0] = srcW;
+ texTemp.height[0] = srcH;
+ texTemp.depth[0] = 1;
+ texTemp.compressed = 0;
+ texTemp.cpp = pf_get_bits(src->format) / 8;
+
+ tex = screen->texture_create(screen, &texTemp);
+ if (!tex)
+ return;
+
+ texSurf = screen->get_tex_surface(screen, tex, 0, 0, 0);
+
+ /* load temp texture */
+ pipe->surface_copy(pipe, FALSE,
+ texSurf, 0, 0, /* dest */
+ src, srcLeft, srcTop, /* src */
+ srcW, srcH); /* size */
+
+ /* drawing dest */
+ memset(&fb, 0, sizeof(fb));
+ fb.num_cbufs = 1;
+ fb.cbufs[0] = dst;
+ pipe->set_framebuffer_state(pipe, &fb);
+
+ /* sampler */
+ if (filter == PIPE_TEX_MIPFILTER_NEAREST)
+ pipe->bind_sampler_states(pipe, 1, &ctx->samplers[0]);
+ else
+ pipe->bind_sampler_states(pipe, 1, &ctx->samplers[1]);
+
+ /* texture */
+ pipe->set_sampler_textures(pipe, 1, &tex);
+
+ /* shaders */
+ pipe->bind_fs_state(pipe, ctx->fs);
+ pipe->bind_vs_state(pipe, ctx->vs);
+
+ /* misc state */
+ pipe->bind_blend_state(pipe, ctx->blend);
+ pipe->bind_depth_stencil_alpha_state(pipe, ctx->depthstencil);
+ pipe->bind_rasterizer_state(pipe, ctx->rasterizer);
+
+ /* draw quad */
+ util_draw_texquad(pipe, dstX0, dstY0, dstX1, dstY1, z);
+
+ /* unbind */
+ pipe->set_sampler_textures(pipe, 0, NULL);
+ pipe->bind_sampler_states(pipe, 0, NULL);
+
+ /* free stuff */
+ pipe_surface_reference(&texSurf, NULL);
+ screen->texture_release(screen, &tex);
+
+ /* Note: caller must restore pipe/gallium state at this time */
+}
+
diff --git a/src/gallium/auxiliary/util/u_blit.h b/src/gallium/auxiliary/util/u_blit.h
new file mode 100644
index 0000000000..a349be99ad
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_blit.h
@@ -0,0 +1,60 @@
+/**************************************************************************
+ *
+ * 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_BLIT_H
+#define U_BLIT_H
+
+
+struct pipe_context;
+struct pipe_surface;
+
+
+struct blit_state;
+
+
+extern struct blit_state *
+util_create_blit(struct pipe_context *pipe);
+
+
+extern void
+util_destroy_blit(struct blit_state *ctx);
+
+
+
+extern void
+util_blit_pixels(struct blit_state *ctx,
+ struct pipe_surface *src,
+ int srcX0, int srcY0,
+ int srcX1, int srcY1,
+ struct pipe_surface *dst,
+ int dstX0, int dstY0,
+ int dstX1, int dstY1,
+ float z, uint filter);
+
+
+#endif
diff --git a/src/gallium/auxiliary/util/u_draw_quad.c b/src/gallium/auxiliary/util/u_draw_quad.c
new file mode 100644
index 0000000000..79a69de633
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_draw_quad.c
@@ -0,0 +1,112 @@
+/**************************************************************************
+ *
+ * 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.
+ *
+ **************************************************************************/
+
+
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_inlines.h"
+#include "pipe/p_winsys.h"
+#include "util/u_draw_quad.h"
+
+
+/**
+ * Draw screen-aligned textured quad.
+ */
+void
+util_draw_texquad(struct pipe_context *pipe,
+ float x0, float y0, float x1, float y1, float z)
+{
+ struct pipe_buffer *vbuf;
+ struct pipe_vertex_buffer vbuffer;
+ struct pipe_vertex_element velement;
+ uint numAttribs = 2, vertexBytes, i, j;
+ float *v;
+
+ vertexBytes = 4 * (4 * numAttribs * sizeof(float));
+
+ /* XXX create one-time */
+ vbuf = pipe->winsys->buffer_create(pipe->winsys, 32,
+ PIPE_BUFFER_USAGE_VERTEX, vertexBytes);
+ assert(vbuf);
+
+ v = (float *) pipe->winsys->buffer_map(pipe->winsys, vbuf,
+ PIPE_BUFFER_USAGE_CPU_WRITE);
+
+ /*
+ * Load vertex buffer
+ */
+ for (i = j = 0; i < 4; i++) {
+ v[j + 2] = z; /* z */
+ v[j + 3] = 1.0; /* w */
+ v[j + 6] = 0.0; /* r */
+ v[j + 7] = 1.0; /* q */
+ j += 8;
+ }
+
+ v[0] = x0;
+ v[1] = y0;
+ v[4] = 0.0; /*s*/
+ v[5] = 0.0; /*t*/
+
+ v[8] = x1;
+ v[9] = y0;
+ v[12] = 1.0;
+ v[13] = 0.0;
+
+ v[16] = x1;
+ v[17] = y1;
+ v[20] = 1.0;
+ v[21] = 1.0;
+
+ v[24] = x0;
+ v[25] = y1;
+ v[28] = 0.0;
+ v[29] = 1.0;
+
+ pipe->winsys->buffer_unmap(pipe->winsys, vbuf);
+
+ /* tell pipe about the vertex buffer */
+ vbuffer.buffer = vbuf;
+ vbuffer.pitch = numAttribs * 4 * sizeof(float); /* vertex size */
+ vbuffer.buffer_offset = 0;
+ pipe->set_vertex_buffer(pipe, 0, &vbuffer);
+
+ /* tell pipe about the vertex attributes */
+ for (i = 0; i < numAttribs; i++) {
+ velement.src_offset = i * 4 * sizeof(float);
+ velement.vertex_buffer_index = 0;
+ velement.src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
+ velement.nr_components = 4;
+ pipe->set_vertex_element(pipe, i, &velement);
+ }
+
+ /* draw */
+ pipe->draw_arrays(pipe, PIPE_PRIM_TRIANGLE_FAN, 0, 4);
+
+ /* XXX: do one-time */
+ pipe_buffer_reference(pipe->winsys, &vbuf, NULL);
+}
diff --git a/src/gallium/auxiliary/util/u_draw_quad.h b/src/gallium/auxiliary/util/u_draw_quad.h
new file mode 100644
index 0000000000..a97f55d2ef
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_draw_quad.h
@@ -0,0 +1,37 @@
+/**************************************************************************
+ *
+ * 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_DRAWQUAD_H
+#define U_DRAWQUAD_H
+
+
+extern void
+util_draw_texquad(struct pipe_context *pipe,
+ float x0, float y0, float x1, float y1, float z);
+
+
+#endif
diff --git a/src/gallium/auxiliary/util/u_gen_mipmap.c b/src/gallium/auxiliary/util/u_gen_mipmap.c
new file mode 100644
index 0000000000..e18f8ab72a
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_gen_mipmap.c
@@ -0,0 +1,877 @@
+/**************************************************************************
+ *
+ * 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.
+ *
+ **************************************************************************/
+
+/**
+ * @file
+ * Mipmap generation utility
+ *
+ * @author Brian Paul
+ */
+
+
+#include "pipe/p_context.h"
+#include "pipe/p_debug.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_inlines.h"
+#include "pipe/p_util.h"
+#include "pipe/p_winsys.h"
+#include "pipe/p_shader_tokens.h"
+
+#include "util/u_draw_quad.h"
+#include "util/u_gen_mipmap.h"
+#include "util/u_simple_shaders.h"
+
+#include "tgsi/util/tgsi_build.h"
+#include "tgsi/util/tgsi_dump.h"
+#include "tgsi/util/tgsi_parse.h"
+
+
+struct gen_mipmap_state
+{
+ struct pipe_context *pipe;
+
+ void *blend;
+ void *depthstencil;
+ void *rasterizer;
+ /*struct pipe_viewport_state viewport;*/
+ struct pipe_sampler_state *vs;
+ struct pipe_sampler_state *fs;
+};
+
+
+
+enum dtype
+{
+ UBYTE,
+ UBYTE_3_3_2,
+ USHORT,
+ USHORT_4_4_4_4,
+ USHORT_5_6_5,
+ USHORT_1_5_5_5_REV,
+ UINT,
+ FLOAT,
+ HALF_FLOAT
+};
+
+
+typedef ushort half_float;
+
+
+#if 0
+extern half_float
+float_to_half(float f);
+
+extern float
+half_to_float(half_float h);
+#endif
+
+
+/**
+ * Average together two rows of a source image to produce a single new
+ * row in the dest image. It's legal for the two source rows to point
+ * to the same data. The source width must be equal to either the
+ * dest width or two times the dest width.
+ * \param datatype GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT, GL_FLOAT, etc.
+ * \param comps number of components per pixel (1..4)
+ */
+static void
+do_row(enum dtype datatype, uint comps, int srcWidth,
+ const void *srcRowA, const void *srcRowB,
+ int dstWidth, void *dstRow)
+{
+ const uint k0 = (srcWidth == dstWidth) ? 0 : 1;
+ const uint colStride = (srcWidth == dstWidth) ? 1 : 2;
+
+ assert(comps >= 1);
+ assert(comps <= 4);
+
+ /* This assertion is no longer valid with non-power-of-2 textures
+ assert(srcWidth == dstWidth || srcWidth == 2 * dstWidth);
+ */
+
+ if (datatype == UBYTE && comps == 4) {
+ uint i, j, k;
+ const ubyte(*rowA)[4] = (const ubyte(*)[4]) srcRowA;
+ const ubyte(*rowB)[4] = (const ubyte(*)[4]) srcRowB;
+ ubyte(*dst)[4] = (ubyte(*)[4]) dstRow;
+ for (i = j = 0, k = k0; i < (uint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4;
+ dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4;
+ dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4;
+ dst[i][3] = (rowA[j][3] + rowA[k][3] + rowB[j][3] + rowB[k][3]) / 4;
+ }
+ }
+ else if (datatype == UBYTE && comps == 3) {
+ uint i, j, k;
+ const ubyte(*rowA)[3] = (const ubyte(*)[3]) srcRowA;
+ const ubyte(*rowB)[3] = (const ubyte(*)[3]) srcRowB;
+ ubyte(*dst)[3] = (ubyte(*)[3]) dstRow;
+ for (i = j = 0, k = k0; i < (uint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4;
+ dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4;
+ dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4;
+ }
+ }
+ else if (datatype == UBYTE && comps == 2) {
+ uint i, j, k;
+ const ubyte(*rowA)[2] = (const ubyte(*)[2]) srcRowA;
+ const ubyte(*rowB)[2] = (const ubyte(*)[2]) srcRowB;
+ ubyte(*dst)[2] = (ubyte(*)[2]) dstRow;
+ for (i = j = 0, k = k0; i < (uint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) >> 2;
+ dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) >> 2;
+ }
+ }
+ else if (datatype == UBYTE && comps == 1) {
+ uint i, j, k;
+ const ubyte *rowA = (const ubyte *) srcRowA;
+ const ubyte *rowB = (const ubyte *) srcRowB;
+ ubyte *dst = (ubyte *) dstRow;
+ for (i = j = 0, k = k0; i < (uint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) >> 2;
+ }
+ }
+
+ else if (datatype == USHORT && comps == 4) {
+ uint i, j, k;
+ const ushort(*rowA)[4] = (const ushort(*)[4]) srcRowA;
+ const ushort(*rowB)[4] = (const ushort(*)[4]) srcRowB;
+ ushort(*dst)[4] = (ushort(*)[4]) dstRow;
+ for (i = j = 0, k = k0; i < (uint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4;
+ dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4;
+ dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4;
+ dst[i][3] = (rowA[j][3] + rowA[k][3] + rowB[j][3] + rowB[k][3]) / 4;
+ }
+ }
+ else if (datatype == USHORT && comps == 3) {
+ uint i, j, k;
+ const ushort(*rowA)[3] = (const ushort(*)[3]) srcRowA;
+ const ushort(*rowB)[3] = (const ushort(*)[3]) srcRowB;
+ ushort(*dst)[3] = (ushort(*)[3]) dstRow;
+ for (i = j = 0, k = k0; i < (uint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4;
+ dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4;
+ dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4;
+ }
+ }
+ else if (datatype == USHORT && comps == 2) {
+ uint i, j, k;
+ const ushort(*rowA)[2] = (const ushort(*)[2]) srcRowA;
+ const ushort(*rowB)[2] = (const ushort(*)[2]) srcRowB;
+ ushort(*dst)[2] = (ushort(*)[2]) dstRow;
+ for (i = j = 0, k = k0; i < (uint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4;
+ dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4;
+ }
+ }
+ else if (datatype == USHORT && comps == 1) {
+ uint i, j, k;
+ const ushort *rowA = (const ushort *) srcRowA;
+ const ushort *rowB = (const ushort *) srcRowB;
+ ushort *dst = (ushort *) dstRow;
+ for (i = j = 0, k = k0; i < (uint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) / 4;
+ }
+ }
+
+ else if (datatype == FLOAT && comps == 4) {
+ uint i, j, k;
+ const float(*rowA)[4] = (const float(*)[4]) srcRowA;
+ const float(*rowB)[4] = (const float(*)[4]) srcRowB;
+ float(*dst)[4] = (float(*)[4]) dstRow;
+ for (i = j = 0, k = k0; i < (uint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ dst[i][0] = (rowA[j][0] + rowA[k][0] +
+ rowB[j][0] + rowB[k][0]) * 0.25F;
+ dst[i][1] = (rowA[j][1] + rowA[k][1] +
+ rowB[j][1] + rowB[k][1]) * 0.25F;
+ dst[i][2] = (rowA[j][2] + rowA[k][2] +
+ rowB[j][2] + rowB[k][2]) * 0.25F;
+ dst[i][3] = (rowA[j][3] + rowA[k][3] +
+ rowB[j][3] + rowB[k][3]) * 0.25F;
+ }
+ }
+ else if (datatype == FLOAT && comps == 3) {
+ uint i, j, k;
+ const float(*rowA)[3] = (const float(*)[3]) srcRowA;
+ const float(*rowB)[3] = (const float(*)[3]) srcRowB;
+ float(*dst)[3] = (float(*)[3]) dstRow;
+ for (i = j = 0, k = k0; i < (uint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ dst[i][0] = (rowA[j][0] + rowA[k][0] +
+ rowB[j][0] + rowB[k][0]) * 0.25F;
+ dst[i][1] = (rowA[j][1] + rowA[k][1] +
+ rowB[j][1] + rowB[k][1]) * 0.25F;
+ dst[i][2] = (rowA[j][2] + rowA[k][2] +
+ rowB[j][2] + rowB[k][2]) * 0.25F;
+ }
+ }
+ else if (datatype == FLOAT && comps == 2) {
+ uint i, j, k;
+ const float(*rowA)[2] = (const float(*)[2]) srcRowA;
+ const float(*rowB)[2] = (const float(*)[2]) srcRowB;
+ float(*dst)[2] = (float(*)[2]) dstRow;
+ for (i = j = 0, k = k0; i < (uint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ dst[i][0] = (rowA[j][0] + rowA[k][0] +
+ rowB[j][0] + rowB[k][0]) * 0.25F;
+ dst[i][1] = (rowA[j][1] + rowA[k][1] +
+ rowB[j][1] + rowB[k][1]) * 0.25F;
+ }
+ }
+ else if (datatype == FLOAT && comps == 1) {
+ uint i, j, k;
+ const float *rowA = (const float *) srcRowA;
+ const float *rowB = (const float *) srcRowB;
+ float *dst = (float *) dstRow;
+ for (i = j = 0, k = k0; i < (uint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) * 0.25F;
+ }
+ }
+
+#if 0
+ else if (datatype == HALF_FLOAT && comps == 4) {
+ uint i, j, k, comp;
+ const half_float(*rowA)[4] = (const half_float(*)[4]) srcRowA;
+ const half_float(*rowB)[4] = (const half_float(*)[4]) srcRowB;
+ half_float(*dst)[4] = (half_float(*)[4]) dstRow;
+ for (i = j = 0, k = k0; i < (uint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ for (comp = 0; comp < 4; comp++) {
+ float aj, ak, bj, bk;
+ aj = half_to_float(rowA[j][comp]);
+ ak = half_to_float(rowA[k][comp]);
+ bj = half_to_float(rowB[j][comp]);
+ bk = half_to_float(rowB[k][comp]);
+ dst[i][comp] = float_to_half((aj + ak + bj + bk) * 0.25F);
+ }
+ }
+ }
+ else if (datatype == HALF_FLOAT && comps == 3) {
+ uint i, j, k, comp;
+ const half_float(*rowA)[3] = (const half_float(*)[3]) srcRowA;
+ const half_float(*rowB)[3] = (const half_float(*)[3]) srcRowB;
+ half_float(*dst)[3] = (half_float(*)[3]) dstRow;
+ for (i = j = 0, k = k0; i < (uint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ for (comp = 0; comp < 3; comp++) {
+ float aj, ak, bj, bk;
+ aj = half_to_float(rowA[j][comp]);
+ ak = half_to_float(rowA[k][comp]);
+ bj = half_to_float(rowB[j][comp]);
+ bk = half_to_float(rowB[k][comp]);
+ dst[i][comp] = float_to_half((aj + ak + bj + bk) * 0.25F);
+ }
+ }
+ }
+ else if (datatype == HALF_FLOAT && comps == 2) {
+ uint i, j, k, comp;
+ const half_float(*rowA)[2] = (const half_float(*)[2]) srcRowA;
+ const half_float(*rowB)[2] = (const half_float(*)[2]) srcRowB;
+ half_float(*dst)[2] = (half_float(*)[2]) dstRow;
+ for (i = j = 0, k = k0; i < (uint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ for (comp = 0; comp < 2; comp++) {
+ float aj, ak, bj, bk;
+ aj = half_to_float(rowA[j][comp]);
+ ak = half_to_float(rowA[k][comp]);
+ bj = half_to_float(rowB[j][comp]);
+ bk = half_to_float(rowB[k][comp]);
+ dst[i][comp] = float_to_half((aj + ak + bj + bk) * 0.25F);
+ }
+ }
+ }
+ else if (datatype == HALF_FLOAT && comps == 1) {
+ uint i, j, k;
+ const half_float *rowA = (const half_float *) srcRowA;
+ const half_float *rowB = (const half_float *) srcRowB;
+ half_float *dst = (half_float *) dstRow;
+ for (i = j = 0, k = k0; i < (uint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ float aj, ak, bj, bk;
+ aj = half_to_float(rowA[j]);
+ ak = half_to_float(rowA[k]);
+ bj = half_to_float(rowB[j]);
+ bk = half_to_float(rowB[k]);
+ dst[i] = float_to_half((aj + ak + bj + bk) * 0.25F);
+ }
+ }
+#endif
+
+ else if (datatype == UINT && comps == 1) {
+ uint i, j, k;
+ const uint *rowA = (const uint *) srcRowA;
+ const uint *rowB = (const uint *) srcRowB;
+ uint *dst = (uint *) dstRow;
+ for (i = j = 0, k = k0; i < (uint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ dst[i] = rowA[j] / 4 + rowA[k] / 4 + rowB[j] / 4 + rowB[k] / 4;
+ }
+ }
+
+ else if (datatype == USHORT_5_6_5 && comps == 3) {
+ uint i, j, k;
+ const ushort *rowA = (const ushort *) srcRowA;
+ const ushort *rowB = (const ushort *) srcRowB;
+ ushort *dst = (ushort *) dstRow;
+ for (i = j = 0, k = k0; i < (uint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ const int rowAr0 = rowA[j] & 0x1f;
+ const int rowAr1 = rowA[k] & 0x1f;
+ const int rowBr0 = rowB[j] & 0x1f;
+ const int rowBr1 = rowB[k] & 0x1f;
+ const int rowAg0 = (rowA[j] >> 5) & 0x3f;
+ const int rowAg1 = (rowA[k] >> 5) & 0x3f;
+ const int rowBg0 = (rowB[j] >> 5) & 0x3f;
+ const int rowBg1 = (rowB[k] >> 5) & 0x3f;
+ const int rowAb0 = (rowA[j] >> 11) & 0x1f;
+ const int rowAb1 = (rowA[k] >> 11) & 0x1f;
+ const int rowBb0 = (rowB[j] >> 11) & 0x1f;
+ const int rowBb1 = (rowB[k] >> 11) & 0x1f;
+ const int red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2;
+ const int green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2;
+ const int blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2;
+ dst[i] = (blue << 11) | (green << 5) | red;
+ }
+ }
+ else if (datatype == USHORT_4_4_4_4 && comps == 4) {
+ uint i, j, k;
+ const ushort *rowA = (const ushort *) srcRowA;
+ const ushort *rowB = (const ushort *) srcRowB;
+ ushort *dst = (ushort *) dstRow;
+ for (i = j = 0, k = k0; i < (uint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ const int rowAr0 = rowA[j] & 0xf;
+ const int rowAr1 = rowA[k] & 0xf;
+ const int rowBr0 = rowB[j] & 0xf;
+ const int rowBr1 = rowB[k] & 0xf;
+ const int rowAg0 = (rowA[j] >> 4) & 0xf;
+ const int rowAg1 = (rowA[k] >> 4) & 0xf;
+ const int rowBg0 = (rowB[j] >> 4) & 0xf;
+ const int rowBg1 = (rowB[k] >> 4) & 0xf;
+ const int rowAb0 = (rowA[j] >> 8) & 0xf;
+ const int rowAb1 = (rowA[k] >> 8) & 0xf;
+ const int rowBb0 = (rowB[j] >> 8) & 0xf;
+ const int rowBb1 = (rowB[k] >> 8) & 0xf;
+ const int rowAa0 = (rowA[j] >> 12) & 0xf;
+ const int rowAa1 = (rowA[k] >> 12) & 0xf;
+ const int rowBa0 = (rowB[j] >> 12) & 0xf;
+ const int rowBa1 = (rowB[k] >> 12) & 0xf;
+ const int red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2;
+ const int green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2;
+ const int blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2;
+ const int alpha = (rowAa0 + rowAa1 + rowBa0 + rowBa1) >> 2;
+ dst[i] = (alpha << 12) | (blue << 8) | (green << 4) | red;
+ }
+ }
+ else if (datatype == USHORT_1_5_5_5_REV && comps == 4) {
+ uint i, j, k;
+ const ushort *rowA = (const ushort *) srcRowA;
+ const ushort *rowB = (const ushort *) srcRowB;
+ ushort *dst = (ushort *) dstRow;
+ for (i = j = 0, k = k0; i < (uint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ const int rowAr0 = rowA[j] & 0x1f;
+ const int rowAr1 = rowA[k] & 0x1f;
+ const int rowBr0 = rowB[j] & 0x1f;
+ const int rowBr1 = rowB[k] & 0xf;
+ const int rowAg0 = (rowA[j] >> 5) & 0x1f;
+ const int rowAg1 = (rowA[k] >> 5) & 0x1f;
+ const int rowBg0 = (rowB[j] >> 5) & 0x1f;
+ const int rowBg1 = (rowB[k] >> 5) & 0x1f;
+ const int rowAb0 = (rowA[j] >> 10) & 0x1f;
+ const int rowAb1 = (rowA[k] >> 10) & 0x1f;
+ const int rowBb0 = (rowB[j] >> 10) & 0x1f;
+ const int rowBb1 = (rowB[k] >> 10) & 0x1f;
+ const int rowAa0 = (rowA[j] >> 15) & 0x1;
+ const int rowAa1 = (rowA[k] >> 15) & 0x1;
+ const int rowBa0 = (rowB[j] >> 15) & 0x1;
+ const int rowBa1 = (rowB[k] >> 15) & 0x1;
+ const int red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2;
+ const int green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2;
+ const int blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2;
+ const int alpha = (rowAa0 + rowAa1 + rowBa0 + rowBa1) >> 2;
+ dst[i] = (alpha << 15) | (blue << 10) | (green << 5) | red;
+ }
+ }
+ else if (datatype == UBYTE_3_3_2 && comps == 3) {
+ uint i, j, k;
+ const ubyte *rowA = (const ubyte *) srcRowA;
+ const ubyte *rowB = (const ubyte *) srcRowB;
+ ubyte *dst = (ubyte *) dstRow;
+ for (i = j = 0, k = k0; i < (uint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ const int rowAr0 = rowA[j] & 0x3;
+ const int rowAr1 = rowA[k] & 0x3;
+ const int rowBr0 = rowB[j] & 0x3;
+ const int rowBr1 = rowB[k] & 0x3;
+ const int rowAg0 = (rowA[j] >> 2) & 0x7;
+ const int rowAg1 = (rowA[k] >> 2) & 0x7;
+ const int rowBg0 = (rowB[j] >> 2) & 0x7;
+ const int rowBg1 = (rowB[k] >> 2) & 0x7;
+ const int rowAb0 = (rowA[j] >> 5) & 0x7;
+ const int rowAb1 = (rowA[k] >> 5) & 0x7;
+ const int rowBb0 = (rowB[j] >> 5) & 0x7;
+ const int rowBb1 = (rowB[k] >> 5) & 0x7;
+ const int red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2;
+ const int green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2;
+ const int blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2;
+ dst[i] = (blue << 5) | (green << 2) | red;
+ }
+ }
+ else {
+ debug_printf("bad format in do_row()");
+ }
+}
+
+
+static void
+format_to_type_comps(enum pipe_format pformat,
+ enum dtype *datatype, uint *comps)
+{
+ switch (pformat) {
+ case PIPE_FORMAT_A8R8G8B8_UNORM:
+ case PIPE_FORMAT_B8G8R8A8_UNORM:
+ *datatype = UBYTE;
+ *comps = 4;
+ return;
+ case PIPE_FORMAT_A1R5G5B5_UNORM:
+ *datatype = USHORT_1_5_5_5_REV;
+ *comps = 4;
+ return;
+ case PIPE_FORMAT_A4R4G4B4_UNORM:
+ *datatype = USHORT_4_4_4_4;
+ *comps = 4;
+ return;
+ case PIPE_FORMAT_R5G6B5_UNORM:
+ *datatype = USHORT_5_6_5;
+ *comps = 3;
+ return;
+ case PIPE_FORMAT_U_L8:
+ case PIPE_FORMAT_U_A8:
+ case PIPE_FORMAT_U_I8:
+ *datatype = UBYTE;
+ *comps = 1;
+ return;
+ case PIPE_FORMAT_U_A8_L8:
+ *datatype = UBYTE;
+ *comps = 2;
+ return;
+ default:
+ assert(0);
+ }
+}
+
+
+static void
+reduce_1d(enum pipe_format pformat,
+ int srcWidth, const ubyte *srcPtr,
+ int dstWidth, ubyte *dstPtr)
+{
+ enum dtype datatype;
+ uint comps;
+
+ format_to_type_comps(pformat, &datatype, &comps);
+
+ /* we just duplicate the input row, kind of hack, saves code */
+ do_row(datatype, comps,
+ srcWidth, srcPtr, srcPtr,
+ dstWidth, dstPtr);
+}
+
+
+/**
+ * Strides are in bytes. If zero, it'll be computed as width * bpp.
+ */
+static void
+reduce_2d(enum pipe_format pformat,
+ int srcWidth, int srcHeight,
+ int srcRowStride, const ubyte *srcPtr,
+ int dstWidth, int dstHeight,
+ int dstRowStride, ubyte *dstPtr)
+{
+ enum dtype datatype;
+ uint comps;
+ const int bpt = pf_get_size(pformat);
+ const ubyte *srcA, *srcB;
+ ubyte *dst;
+ int row;
+
+ format_to_type_comps(pformat, &datatype, &comps);
+
+ if (!srcRowStride)
+ srcRowStride = bpt * srcWidth;
+
+ if (!dstRowStride)
+ dstRowStride = bpt * dstWidth;
+
+ /* Compute src and dst pointers */
+ srcA = srcPtr;
+ if (srcHeight > 1)
+ srcB = srcA + srcRowStride;
+ else
+ srcB = srcA;
+ dst = dstPtr;
+
+ for (row = 0; row < dstHeight; row++) {
+ do_row(datatype, comps,
+ srcWidth, srcA, srcB,
+ dstWidth, dst);
+ srcA += 2 * srcRowStride;
+ srcB += 2 * srcRowStride;
+ dst += dstRowStride;
+ }
+}
+
+
+static void
+make_1d_mipmap(struct gen_mipmap_state *ctx,
+ struct pipe_texture *pt,
+ uint face, uint baseLevel, uint lastLevel)
+{
+ struct pipe_context *pipe = ctx->pipe;
+ struct pipe_screen *screen = pipe->screen;
+ struct pipe_winsys *winsys = pipe->winsys;
+ const uint zslice = 0;
+ uint dstLevel;
+
+ for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) {
+ const uint srcLevel = dstLevel - 1;
+ struct pipe_surface *srcSurf, *dstSurf;
+ void *srcMap, *dstMap;
+
+ srcSurf = screen->get_tex_surface(screen, pt, face, srcLevel, zslice);
+ dstSurf = screen->get_tex_surface(screen, pt, face, dstLevel, zslice);
+
+ srcMap = ((ubyte *) winsys->buffer_map(winsys, srcSurf->buffer,
+ PIPE_BUFFER_USAGE_CPU_READ)
+ + srcSurf->offset);
+ dstMap = ((ubyte *) winsys->buffer_map(winsys, dstSurf->buffer,
+ PIPE_BUFFER_USAGE_CPU_WRITE)
+ + dstSurf->offset);
+
+ reduce_1d(pt->format,
+ srcSurf->width, srcMap,
+ dstSurf->width, dstMap);
+
+ winsys->buffer_unmap(winsys, srcSurf->buffer);
+ winsys->buffer_unmap(winsys, dstSurf->buffer);
+
+ pipe_surface_reference(&srcSurf, NULL);
+ pipe_surface_reference(&dstSurf, NULL);
+ }
+}
+
+
+static void
+make_2d_mipmap(struct gen_mipmap_state *ctx,
+ struct pipe_texture *pt,
+ uint face, uint baseLevel, uint lastLevel)
+{
+ struct pipe_context *pipe = ctx->pipe;
+ struct pipe_screen *screen = pipe->screen;
+ struct pipe_winsys *winsys = pipe->winsys;
+ const uint zslice = 0;
+ uint dstLevel;
+ const int bpt = pf_get_size(pt->format);
+
+ for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) {
+ const uint srcLevel = dstLevel - 1;
+ struct pipe_surface *srcSurf, *dstSurf;
+ ubyte *srcMap, *dstMap;
+
+ srcSurf = screen->get_tex_surface(screen, pt, face, srcLevel, zslice);
+ dstSurf = screen->get_tex_surface(screen, pt, face, dstLevel, zslice);
+
+ srcMap = ((ubyte *) winsys->buffer_map(winsys, srcSurf->buffer,
+ PIPE_BUFFER_USAGE_CPU_READ)
+ + srcSurf->offset);
+ dstMap = ((ubyte *) winsys->buffer_map(winsys, dstSurf->buffer,
+ PIPE_BUFFER_USAGE_CPU_WRITE)
+ + dstSurf->offset);
+
+ reduce_2d(pt->format,
+ srcSurf->width, srcSurf->height,
+ srcSurf->pitch * bpt, srcMap,
+ dstSurf->width, dstSurf->height,
+ dstSurf->pitch * bpt, dstMap);
+
+ winsys->buffer_unmap(winsys, srcSurf->buffer);
+ winsys->buffer_unmap(winsys, dstSurf->buffer);
+
+ pipe_surface_reference(&srcSurf, NULL);
+ pipe_surface_reference(&dstSurf, NULL);
+ }
+}
+
+
+static void
+make_3d_mipmap(struct gen_mipmap_state *ctx,
+ struct pipe_texture *pt,
+ uint face, uint baseLevel, uint lastLevel)
+{
+}
+
+
+static void
+fallback_gen_mipmap(struct gen_mipmap_state *ctx,
+ struct pipe_texture *pt,
+ uint face, uint baseLevel, uint lastLevel)
+{
+ switch (pt->target) {
+ case PIPE_TEXTURE_1D:
+ make_1d_mipmap(ctx, pt, face, baseLevel, lastLevel);
+ break;
+ case PIPE_TEXTURE_2D:
+ case PIPE_TEXTURE_CUBE:
+ make_2d_mipmap(ctx, pt, face, baseLevel, lastLevel);
+ break;
+ case PIPE_TEXTURE_3D:
+ make_3d_mipmap(ctx, pt, face, baseLevel, lastLevel);
+ break;
+ default:
+ assert(0);
+ }
+}
+
+
+/**
+ * Create a mipmap generation context.
+ * The idea is to create one of these and re-use it each time we need to
+ * generate a mipmap.
+ */
+struct gen_mipmap_state *
+util_create_gen_mipmap(struct pipe_context *pipe)
+{
+ struct pipe_blend_state blend;
+ struct pipe_depth_stencil_alpha_state depthstencil;
+ struct pipe_rasterizer_state rasterizer;
+ struct gen_mipmap_state *ctx;
+
+ ctx = CALLOC_STRUCT(gen_mipmap_state);
+ if (!ctx)
+ return NULL;
+
+ ctx->pipe = pipe;
+
+ /* we don't use blending, but need to set valid values */
+ memset(&blend, 0, sizeof(blend));
+ blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE;
+ blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE;
+ blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
+ blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
+ blend.colormask = PIPE_MASK_RGBA;
+ ctx->blend = pipe->create_blend_state(pipe, &blend);
+
+ /* depth/stencil/alpha */
+ memset(&depthstencil, 0, sizeof(depthstencil));
+ ctx->depthstencil = pipe->create_depth_stencil_alpha_state(pipe, &depthstencil);
+
+ /* rasterizer */
+ memset(&rasterizer, 0, sizeof(rasterizer));
+ rasterizer.front_winding = PIPE_WINDING_CW;
+ rasterizer.cull_mode = PIPE_WINDING_NONE;
+ rasterizer.bypass_clipping = 1; /* bypasses viewport too */
+ //rasterizer.bypass_vs = 1;
+ ctx->rasterizer = pipe->create_rasterizer_state(pipe, &rasterizer);
+
+#if 0
+ /* viewport */
+ ctx->viewport.scale[0] = 1.0;
+ ctx->viewport.scale[1] = 1.0;
+ ctx->viewport.scale[2] = 1.0;
+ ctx->viewport.scale[3] = 1.0;
+ ctx->viewport.translate[0] = 0.0;
+ ctx->viewport.translate[1] = 0.0;
+ ctx->viewport.translate[2] = 0.0;
+ ctx->viewport.translate[3] = 0.0;
+#endif
+
+ /* vertex shader */
+ {
+ const uint semantic_names[] = { TGSI_SEMANTIC_POSITION,
+ TGSI_SEMANTIC_GENERIC };
+ const uint semantic_indexes[] = { 0, 0 };
+ ctx->vs = util_make_vertex_passthrough_shader(pipe, 2, semantic_names,
+ semantic_indexes);
+ }
+
+ /* fragment shader */
+ ctx->fs = util_make_fragment_tex_shader(pipe);
+
+ return ctx;
+}
+
+
+/**
+ * Destroy a mipmap generation context
+ */
+void
+util_destroy_gen_mipmap(struct gen_mipmap_state *ctx)
+{
+ struct pipe_context *pipe = ctx->pipe;
+
+ pipe->delete_blend_state(pipe, ctx->blend);
+ pipe->delete_depth_stencil_alpha_state(pipe, ctx->depthstencil);
+ pipe->delete_rasterizer_state(pipe, ctx->rasterizer);
+ pipe->delete_vs_state(pipe, ctx->vs);
+ pipe->delete_fs_state(pipe, ctx->fs);
+
+ FREE(ctx);
+}
+
+
+#if 0
+static void
+simple_viewport(struct pipe_context *pipe, uint width, uint height)
+{
+ struct pipe_viewport_state vp;
+
+ vp.scale[0] = 0.5 * width;
+ vp.scale[1] = -0.5 * height;
+ vp.scale[2] = 1.0;
+ vp.scale[3] = 1.0;
+ vp.translate[0] = 0.5 * width;
+ vp.translate[1] = 0.5 * height;
+ vp.translate[2] = 0.0;
+ vp.translate[3] = 0.0;
+
+ pipe->set_viewport_state(pipe, &vp);
+}
+#endif
+
+
+/**
+ * Generate mipmap images. It's assumed all needed texture memory is
+ * already allocated.
+ *
+ * \param pt the texture to generate mipmap levels for
+ * \param face which cube face to generate mipmaps for (0 for non-cube maps)
+ * \param baseLevel the first mipmap level to use as a src
+ * \param lastLevel the last mipmap level to generate
+ */
+void
+util_gen_mipmap(struct gen_mipmap_state *ctx,
+ struct pipe_texture *pt,
+ uint face, uint baseLevel, uint lastLevel)
+{
+ struct pipe_context *pipe = ctx->pipe;
+ struct pipe_screen *screen = pipe->screen;
+ struct pipe_framebuffer_state fb;
+ struct pipe_sampler_state sampler;
+ void *sampler_cso;
+ uint dstLevel;
+ uint zslice = 0;
+
+ /* check if we can render in the texture's format */
+ if (!screen->is_format_supported(screen, pt->format, PIPE_SURFACE)) {
+ fallback_gen_mipmap(ctx, pt, face, baseLevel, lastLevel);
+ return;
+ }
+
+ /* init framebuffer state */
+ memset(&fb, 0, sizeof(fb));
+ fb.num_cbufs = 1;
+
+ /* sampler state */
+ memset(&sampler, 0, sizeof(sampler));
+ sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NEAREST;
+ sampler.min_img_filter = PIPE_TEX_FILTER_LINEAR;
+ sampler.mag_img_filter = PIPE_TEX_FILTER_LINEAR;
+ sampler.normalized_coords = 1;
+
+ /* bind our state */
+ pipe->bind_blend_state(pipe, ctx->blend);
+ pipe->bind_depth_stencil_alpha_state(pipe, ctx->depthstencil);
+ pipe->bind_rasterizer_state(pipe, ctx->rasterizer);
+ pipe->bind_vs_state(pipe, ctx->vs);
+ pipe->bind_fs_state(pipe, ctx->fs);
+#if 0
+ pipe->set_viewport_state(pipe, &ctx->viewport);
+#endif
+
+ /*
+ * XXX for small mipmap levels, it may be faster to use the software
+ * fallback path...
+ */
+ for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) {
+ const uint srcLevel = dstLevel - 1;
+
+ /*
+ * Setup framebuffer / dest surface
+ */
+ fb.cbufs[0] = screen->get_tex_surface(screen, pt, face, dstLevel, zslice);
+ pipe->set_framebuffer_state(pipe, &fb);
+
+ /*
+ * Setup sampler state
+ * Note: we should only have to set the min/max LOD clamps to ensure
+ * we grab texels from the right mipmap level. But some hardware
+ * has trouble with min clamping so we also set the lod_bias to
+ * try to work around that.
+ */
+ sampler.min_lod = sampler.max_lod = (float) srcLevel;
+ sampler.lod_bias = (float) srcLevel;
+ sampler_cso = pipe->create_sampler_state(pipe, &sampler);
+ pipe->bind_sampler_states(pipe, 1, &sampler_cso);
+
+#if 0
+ simple_viewport(pipe, pt->width[dstLevel], pt->height[dstLevel]);
+#endif
+
+ pipe->set_sampler_textures(pipe, 1, &pt);
+
+ /* quad coords in window coords (bypassing clipping, viewport mapping) */
+ util_draw_texquad(pipe,
+ 0.0F, 0.0F, /* x0, y0 */
+ (float) pt->width[dstLevel], /* x1 */
+ (float) pt->height[dstLevel], /* y1 */
+ 0.0F); /* z */
+
+
+ pipe->flush(pipe, PIPE_FLUSH_WAIT);
+
+ /*pipe->texture_update(pipe, pt); not really needed */
+
+ pipe->delete_sampler_state(pipe, sampler_cso);
+ }
+
+ /* Note: caller must restore pipe/gallium state at this time */
+}
diff --git a/src/gallium/auxiliary/util/u_gen_mipmap.h b/src/gallium/auxiliary/util/u_gen_mipmap.h
new file mode 100644
index 0000000000..80496140a2
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_gen_mipmap.h
@@ -0,0 +1,52 @@
+/**************************************************************************
+ *
+ * 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_GENMIPMAP_H
+#define U_GENMIPMAP_H
+
+#include "pipe/p_state.h"
+
+
+struct gen_mipmap_state;
+
+
+extern struct gen_mipmap_state *
+util_create_gen_mipmap(struct pipe_context *pipe);
+
+
+extern void
+util_destroy_gen_mipmap(struct gen_mipmap_state *ctx);
+
+
+
+extern void
+util_gen_mipmap(struct gen_mipmap_state *ctx,
+ struct pipe_texture *pt,
+ uint face, uint baseLevel, uint lastLevel);
+
+
+#endif
diff --git a/src/gallium/auxiliary/util/u_handle_table.c b/src/gallium/auxiliary/util/u_handle_table.c
index d25872972a..0bfb9e1b4a 100644
--- a/src/gallium/auxiliary/util/u_handle_table.c
+++ b/src/gallium/auxiliary/util/u_handle_table.c
@@ -226,9 +226,13 @@ handle_table_remove(struct handle_table *ht,
index = handle - 1;
object = ht->objects[index];
- assert(object);
+ if(!object) {
+ /* XXX: this warning may be noisy for legitimate use -- remove later */
+ debug_warning("removing empty handle");
+ return;
+ }
- if(object && ht->destroy)
+ if(ht->destroy)
ht->destroy(object);
ht->objects[index] = NULL;
@@ -237,6 +241,28 @@ handle_table_remove(struct handle_table *ht,
}
+unsigned
+handle_table_get_next_handle(struct handle_table *ht,
+ unsigned handle)
+{
+ unsigned index;
+
+ for(index = handle; index < ht->size; ++index) {
+ if(!ht->objects[index])
+ return index + 1;
+ }
+
+ return 0;
+}
+
+
+unsigned
+handle_table_get_first_handle(struct handle_table *ht)
+{
+ return handle_table_get_next_handle(ht, 0);
+}
+
+
void
handle_table_destroy(struct handle_table *ht)
{
diff --git a/src/gallium/auxiliary/util/u_handle_table.h b/src/gallium/auxiliary/util/u_handle_table.h
index a2f1f604ad..d080135c9f 100644
--- a/src/gallium/auxiliary/util/u_handle_table.h
+++ b/src/gallium/auxiliary/util/u_handle_table.h
@@ -100,6 +100,15 @@ void
handle_table_destroy(struct handle_table *ht);
+unsigned
+handle_table_get_first_handle(struct handle_table *ht);
+
+
+unsigned
+handle_table_get_next_handle(struct handle_table *ht,
+ unsigned handle);
+
+
#ifdef __cplusplus
}
#endif
diff --git a/src/gallium/auxiliary/util/u_hash_table.c b/src/gallium/auxiliary/util/u_hash_table.c
index ac2cb1b540..f3f16a8d94 100644
--- a/src/gallium/auxiliary/util/u_hash_table.c
+++ b/src/gallium/auxiliary/util/u_hash_table.c
@@ -187,6 +187,28 @@ hash_table_remove(struct hash_table *ht,
}
+enum pipe_error
+hash_table_foreach(struct hash_table *ht,
+ enum pipe_error (*callback)(void *key, void *value, void *data),
+ void *data)
+{
+ struct cso_hash_iter iter;
+ struct hash_table_item *item;
+ enum pipe_error result;
+
+ iter = cso_hash_first_node(ht->cso);
+ while (!cso_hash_iter_is_null(iter)) {
+ item = (struct hash_table_item *)cso_hash_iter_data(iter);
+ result = callback(item->key, item->value, data);
+ if(result != PIPE_OK)
+ return result;
+ iter = cso_hash_iter_next(iter);
+ }
+
+ return PIPE_OK;
+}
+
+
void
hash_table_destroy(struct hash_table *ht)
{
@@ -196,4 +218,3 @@ hash_table_destroy(struct hash_table *ht)
FREE(ht);
}
-
diff --git a/src/gallium/auxiliary/util/u_hash_table.h b/src/gallium/auxiliary/util/u_hash_table.h
index d941f2c6b1..1583bd7548 100644
--- a/src/gallium/auxiliary/util/u_hash_table.h
+++ b/src/gallium/auxiliary/util/u_hash_table.h
@@ -75,6 +75,11 @@ hash_table_remove(struct hash_table *ht,
void *key);
+enum pipe_error
+hash_table_foreach(struct hash_table *ht,
+ enum pipe_error (*callback)(void *key, void *value, void *data),
+ void *data);
+
void
hash_table_destroy(struct hash_table *ht);
diff --git a/src/gallium/auxiliary/util/u_pack_color.h b/src/gallium/auxiliary/util/u_pack_color.h
new file mode 100644
index 0000000000..cd13823985
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_pack_color.h
@@ -0,0 +1,133 @@
+/**************************************************************************
+ *
+ * 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.
+ *
+ **************************************************************************/
+
+/**
+ * @file
+ * Functions to produce packed colors/Z from floats.
+ */
+
+
+#ifndef U_PACK_COLOR_H
+#define U_PACK_COLOR_H
+
+
+#include "pipe/p_compiler.h"
+#include "pipe/p_format.h"
+
+
+/**
+ * Note rgba outside [0,1] will be clamped for int pixel formats.
+ */
+static INLINE void
+util_pack_color(const float rgba[4], enum pipe_format format, void *dest)
+{
+ ubyte r, g, b, a;
+
+ if (pf_size_x(format) <= 8) {
+ /* format uses 8-bit components or less */
+ UNCLAMPED_FLOAT_TO_UBYTE(r, rgba[0]);
+ UNCLAMPED_FLOAT_TO_UBYTE(g, rgba[1]);
+ UNCLAMPED_FLOAT_TO_UBYTE(b, rgba[2]);
+ UNCLAMPED_FLOAT_TO_UBYTE(a, rgba[3]);
+ }
+
+ switch (format) {
+ case PIPE_FORMAT_R8G8B8A8_UNORM:
+ {
+ uint *d = (uint *) dest;
+ *d = (r << 24) | (g << 16) | (b << 8) | a;
+ }
+ return;
+ case PIPE_FORMAT_A8R8G8B8_UNORM:
+ {
+ uint *d = (uint *) dest;
+ *d = (a << 24) | (r << 16) | (g << 8) | b;
+ }
+ return;
+ case PIPE_FORMAT_B8G8R8A8_UNORM:
+ {
+ uint *d = (uint *) dest;
+ *d = (b << 24) | (g << 16) | (r << 8) | a;
+ }
+ return;
+ case PIPE_FORMAT_R5G6B5_UNORM:
+ {
+ ushort *d = (ushort *) dest;
+ *d = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | (b >> 3);
+ }
+ return;
+ case PIPE_FORMAT_R32G32B32A32_FLOAT:
+ {
+ float *d = (float *) dest;
+ d[0] = rgba[0];
+ d[1] = rgba[1];
+ d[2] = rgba[2];
+ d[3] = rgba[3];
+ }
+ return;
+ case PIPE_FORMAT_R32G32B32_FLOAT:
+ {
+ float *d = (float *) dest;
+ d[0] = rgba[0];
+ d[1] = rgba[1];
+ d[2] = rgba[2];
+ }
+ return;
+ /* XXX lots more cases to add */
+ default:
+ debug_printf("gallium: unhandled format in util_pack_color()");
+ }
+}
+
+
+/**
+ * Note: it's assumed that z is in [0,1]
+ */
+static INLINE uint
+util_pack_z(enum pipe_format format, double z)
+{
+ switch (format) {
+ case PIPE_FORMAT_Z16_UNORM:
+ return (uint) (z * 0xffff);
+ case PIPE_FORMAT_Z32_UNORM:
+ /* special-case to avoid overflow */
+ if (z == 1.0)
+ return 0xffffffff;
+ else
+ return (uint) (z * 0xffffffff);
+ case PIPE_FORMAT_S8Z24_UNORM:
+ return (uint) (z * 0xffffff);
+ case PIPE_FORMAT_Z24S8_UNORM:
+ return ((uint) (z * 0xffffff)) << 8;
+ default:
+ debug_printf("gallium: unhandled fomrat in util_pack_z()");
+ return 0;
+ }
+}
+
+
+#endif /* U_PACK_COLOR_H */
diff --git a/src/gallium/auxiliary/util/u_simple_shaders.c b/src/gallium/auxiliary/util/u_simple_shaders.c
new file mode 100644
index 0000000000..88e2ab05bd
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_simple_shaders.c
@@ -0,0 +1,263 @@
+/**************************************************************************
+ *
+ * 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.
+ *
+ **************************************************************************/
+
+/**
+ * @file
+ * Simple vertex/fragment shader generators.
+ *
+ * @author Brian Paul
+ */
+
+
+#include "pipe/p_context.h"
+#include "pipe/p_debug.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_inlines.h"
+#include "pipe/p_util.h"
+#include "pipe/p_winsys.h"
+#include "pipe/p_shader_tokens.h"
+
+#include "util/u_simple_shaders.h"
+
+#include "tgsi/util/tgsi_build.h"
+#include "tgsi/util/tgsi_dump.h"
+#include "tgsi/util/tgsi_parse.h"
+
+
+
+/**
+ * Make simple vertex pass-through shader.
+ */
+void *
+util_make_vertex_passthrough_shader(struct pipe_context *pipe,
+ uint num_attribs,
+ const uint *semantic_names,
+ const uint *semantic_indexes)
+{
+ uint maxTokens = 100;
+ struct tgsi_token *tokens;
+ struct tgsi_header *header;
+ struct tgsi_processor *processor;
+ struct tgsi_full_declaration decl;
+ struct tgsi_full_instruction inst;
+ const uint procType = TGSI_PROCESSOR_VERTEX;
+ uint ti, i;
+ struct pipe_shader_state shader;
+
+ tokens = (struct tgsi_token *) malloc(maxTokens * sizeof(tokens[0]));
+
+ /* shader header
+ */
+ *(struct tgsi_version *) &tokens[0] = tgsi_build_version();
+
+ header = (struct tgsi_header *) &tokens[1];
+ *header = tgsi_build_header();
+
+ processor = (struct tgsi_processor *) &tokens[2];
+ *processor = tgsi_build_processor( procType, header );
+
+ ti = 3;
+
+ /* declare inputs */
+ for (i = 0; i < num_attribs; i++) {
+
+ decl = tgsi_default_full_declaration();
+ decl.Declaration.File = TGSI_FILE_INPUT;
+ /*
+ decl.Declaration.Semantic = 1;
+ decl.Semantic.SemanticName = TGSI_SEMANTIC_POSITION;
+ decl.Semantic.SemanticIndex = 0;
+ */
+ decl.u.DeclarationRange.First =
+ decl.u.DeclarationRange.Last = 0;
+ ti += tgsi_build_full_declaration(&decl,
+ &tokens[ti],
+ header,
+ maxTokens - ti);
+ }
+
+ /* declare outputs */
+ for (i = 0; i < num_attribs; i++) {
+
+ decl = tgsi_default_full_declaration();
+ decl.Declaration.File = TGSI_FILE_OUTPUT;
+ decl.Declaration.Semantic = 1;
+ decl.Semantic.SemanticName = semantic_names[i];
+ decl.Semantic.SemanticIndex = semantic_indexes[i];
+ decl.u.DeclarationRange.First =
+ decl.u.DeclarationRange.Last = 0;
+ ti += tgsi_build_full_declaration(&decl,
+ &tokens[ti],
+ header,
+ maxTokens - ti);
+
+ }
+
+ /* emit MOV instructions */
+ for (i = 0; i < num_attribs; i++) {
+ /* MOVE out[i], in[i]; */
+ inst = tgsi_default_full_instruction();
+ inst.Instruction.Opcode = TGSI_OPCODE_MOV;
+ inst.Instruction.NumDstRegs = 1;
+ inst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_OUTPUT;
+ inst.FullDstRegisters[0].DstRegister.Index = i;
+ inst.Instruction.NumSrcRegs = 1;
+ inst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_INPUT;
+ inst.FullSrcRegisters[0].SrcRegister.Index = i;
+ ti += tgsi_build_full_instruction(&inst,
+ &tokens[ti],
+ header,
+ maxTokens - ti );
+ }
+
+ /* END instruction */
+ inst = tgsi_default_full_instruction();
+ inst.Instruction.Opcode = TGSI_OPCODE_END;
+ inst.Instruction.NumDstRegs = 0;
+ inst.Instruction.NumSrcRegs = 0;
+ ti += tgsi_build_full_instruction(&inst,
+ &tokens[ti],
+ header,
+ maxTokens - ti );
+
+#if 0 /*debug*/
+ tgsi_dump(tokens, 0);
+#endif
+
+ shader.tokens = tokens;
+ return pipe->create_vs_state(pipe, &shader);
+}
+
+
+
+
+/**
+ * Make simple fragment texture shader:
+ * TEX OUT[0], IN[0], SAMP[0], 2D;
+ * END;
+ */
+void *
+util_make_fragment_tex_shader(struct pipe_context *pipe)
+{
+ uint maxTokens = 100;
+ struct tgsi_token *tokens;
+ struct tgsi_header *header;
+ struct tgsi_processor *processor;
+ struct tgsi_full_declaration decl;
+ struct tgsi_full_instruction inst;
+ const uint procType = TGSI_PROCESSOR_FRAGMENT;
+ uint ti;
+ struct pipe_shader_state shader;
+
+ tokens = (struct tgsi_token *) malloc(maxTokens * sizeof(tokens[0]));
+
+ /* shader header
+ */
+ *(struct tgsi_version *) &tokens[0] = tgsi_build_version();
+
+ header = (struct tgsi_header *) &tokens[1];
+ *header = tgsi_build_header();
+
+ processor = (struct tgsi_processor *) &tokens[2];
+ *processor = tgsi_build_processor( procType, header );
+
+ ti = 3;
+
+ /* declare TEX[0] input */
+ decl = tgsi_default_full_declaration();
+ decl.Declaration.File = TGSI_FILE_INPUT;
+ decl.Declaration.Semantic = 1;
+ decl.Semantic.SemanticName = TGSI_SEMANTIC_GENERIC;
+ decl.Semantic.SemanticIndex = 0;
+ /* XXX this could be linear... */
+ decl.Declaration.Interpolate = 1;
+ decl.Interpolation.Interpolate = TGSI_INTERPOLATE_PERSPECTIVE;
+ decl.u.DeclarationRange.First =
+ decl.u.DeclarationRange.Last = 0;
+ ti += tgsi_build_full_declaration(&decl,
+ &tokens[ti],
+ header,
+ maxTokens - ti);
+
+ /* declare color[0] output */
+ decl = tgsi_default_full_declaration();
+ decl.Declaration.File = TGSI_FILE_OUTPUT;
+ decl.Declaration.Semantic = 1;
+ decl.Semantic.SemanticName = TGSI_SEMANTIC_COLOR;
+ decl.Semantic.SemanticIndex = 0;
+ decl.u.DeclarationRange.First =
+ decl.u.DeclarationRange.Last = 0;
+ ti += tgsi_build_full_declaration(&decl,
+ &tokens[ti],
+ header,
+ maxTokens - ti);
+
+ /* declare sampler */
+ decl = tgsi_default_full_declaration();
+ decl.Declaration.File = TGSI_FILE_SAMPLER;
+ decl.u.DeclarationRange.First =
+ decl.u.DeclarationRange.Last = 0;
+ ti += tgsi_build_full_declaration(&decl,
+ &tokens[ti],
+ header,
+ maxTokens - ti);
+
+ /* TEX instruction */
+ inst = tgsi_default_full_instruction();
+ inst.Instruction.Opcode = TGSI_OPCODE_TEX;
+ inst.Instruction.NumDstRegs = 1;
+ inst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_OUTPUT;
+ inst.FullDstRegisters[0].DstRegister.Index = 0;
+ inst.Instruction.NumSrcRegs = 2;
+ inst.InstructionExtTexture.Texture = TGSI_TEXTURE_2D;
+ inst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_INPUT;
+ inst.FullSrcRegisters[0].SrcRegister.Index = 0;
+ inst.FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_SAMPLER;
+ inst.FullSrcRegisters[1].SrcRegister.Index = 0;
+ ti += tgsi_build_full_instruction(&inst,
+ &tokens[ti],
+ header,
+ maxTokens - ti );
+
+ /* END instruction */
+ inst = tgsi_default_full_instruction();
+ inst.Instruction.Opcode = TGSI_OPCODE_END;
+ inst.Instruction.NumDstRegs = 0;
+ inst.Instruction.NumSrcRegs = 0;
+ ti += tgsi_build_full_instruction(&inst,
+ &tokens[ti],
+ header,
+ maxTokens - ti );
+
+#if 0 /*debug*/
+ tgsi_dump(tokens, 0);
+#endif
+
+ shader.tokens = tokens;
+ return pipe->create_fs_state(pipe, &shader);
+}
+
diff --git a/src/gallium/auxiliary/util/u_simple_shaders.h b/src/gallium/auxiliary/util/u_simple_shaders.h
new file mode 100644
index 0000000000..3ef4f28801
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_simple_shaders.h
@@ -0,0 +1,52 @@
+/**************************************************************************
+ *
+ * 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_SIMPLE_SHADERS_H
+#define U_SIMPLE_SHADERS_H
+
+
+#include "pipe/p_compiler.h"
+
+
+struct pipe_context;
+
+
+extern void *
+util_make_vertex_passthrough_shader(struct pipe_context *pipe,
+ uint num_attribs,
+ const uint *semantic_names,
+ const uint *semantic_indexes);
+
+
+extern void *
+util_make_fragment_tex_shader(struct pipe_context *pipe);
+
+
+#endif
+
+