summaryrefslogtreecommitdiff
path: root/src/mesa/pipe/softpipe
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa/pipe/softpipe')
-rw-r--r--src/mesa/pipe/softpipe/Makefile3
-rw-r--r--src/mesa/pipe/softpipe/sp_clear.c71
-rw-r--r--src/mesa/pipe/softpipe/sp_clear.h43
-rw-r--r--src/mesa/pipe/softpipe/sp_context.c126
-rw-r--r--src/mesa/pipe/softpipe/sp_context.h153
-rw-r--r--src/mesa/pipe/softpipe/sp_headers.h95
-rw-r--r--src/mesa/pipe/softpipe/sp_prim_setup.c1005
-rw-r--r--src/mesa/pipe/softpipe/sp_prim_setup.h122
-rw-r--r--src/mesa/pipe/softpipe/sp_quad.c71
-rw-r--r--src/mesa/pipe/softpipe/sp_quad.h65
-rw-r--r--src/mesa/pipe/softpipe/sp_quad_alpha_test.c94
-rw-r--r--src/mesa/pipe/softpipe/sp_quad_blend.c395
-rw-r--r--src/mesa/pipe/softpipe/sp_quad_bufloop.c62
-rw-r--r--src/mesa/pipe/softpipe/sp_quad_colormask.c84
-rw-r--r--src/mesa/pipe/softpipe/sp_quad_coverage.c74
-rw-r--r--src/mesa/pipe/softpipe/sp_quad_depth_test.c167
-rw-r--r--src/mesa/pipe/softpipe/sp_quad_fs.c218
-rw-r--r--src/mesa/pipe/softpipe/sp_quad_occlusion.c67
-rw-r--r--src/mesa/pipe/softpipe/sp_quad_output.c95
-rw-r--r--src/mesa/pipe/softpipe/sp_quad_stencil.c288
-rw-r--r--src/mesa/pipe/softpipe/sp_quad_stipple.c48
-rw-r--r--src/mesa/pipe/softpipe/sp_state.h87
-rw-r--r--src/mesa/pipe/softpipe/sp_state_blend.c93
-rw-r--r--src/mesa/pipe/softpipe/sp_state_clip.c85
-rw-r--r--src/mesa/pipe/softpipe/sp_state_derived.c153
-rw-r--r--src/mesa/pipe/softpipe/sp_state_fs.c50
-rw-r--r--src/mesa/pipe/softpipe/sp_state_sampler.c64
-rw-r--r--src/mesa/pipe/softpipe/sp_state_setup.c47
-rw-r--r--src/mesa/pipe/softpipe/sp_state_surface.c61
-rw-r--r--src/mesa/pipe/softpipe/sp_surface.c153
-rw-r--r--src/mesa/pipe/softpipe/sp_surface.h101
31 files changed, 4240 insertions, 0 deletions
diff --git a/src/mesa/pipe/softpipe/Makefile b/src/mesa/pipe/softpipe/Makefile
new file mode 100644
index 0000000000..12a8bd0409
--- /dev/null
+++ b/src/mesa/pipe/softpipe/Makefile
@@ -0,0 +1,3 @@
+default:
+ cd ../.. ; make
+
diff --git a/src/mesa/pipe/softpipe/sp_clear.c b/src/mesa/pipe/softpipe/sp_clear.c
new file mode 100644
index 0000000000..e83bc053ef
--- /dev/null
+++ b/src/mesa/pipe/softpipe/sp_clear.c
@@ -0,0 +1,71 @@
+/**************************************************************************
+ *
+ * Copyright 2007 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.
+ *
+ **************************************************************************/
+
+/* Author:
+ * Brian Paul
+ */
+
+
+#include "sp_clear.h"
+#include "sp_context.h"
+#include "sp_surface.h"
+#include "colormac.h"
+
+
+void
+softpipe_clear(struct pipe_context *pipe, GLboolean color, GLboolean depth,
+ GLboolean stencil, GLboolean accum)
+{
+ const struct softpipe_context *softpipe = softpipe_context(pipe);
+ const GLint x = softpipe->scissor.minx;
+ const GLint y = softpipe->scissor.miny;
+ const GLint w = softpipe->scissor.maxx - x;
+ const GLint h = softpipe->scissor.maxy - y;
+
+ if (color) {
+ GLuint i;
+ GLubyte clr[4];
+
+ UNCLAMPED_FLOAT_TO_UBYTE(clr[0], softpipe->clear_color.color[0]);
+ UNCLAMPED_FLOAT_TO_UBYTE(clr[1], softpipe->clear_color.color[1]);
+ UNCLAMPED_FLOAT_TO_UBYTE(clr[2], softpipe->clear_color.color[2]);
+ UNCLAMPED_FLOAT_TO_UBYTE(clr[3], softpipe->clear_color.color[3]);
+
+ for (i = 0; i < softpipe->framebuffer.num_cbufs; i++) {
+ struct pipe_surface *ps = softpipe->framebuffer.cbufs[i];
+ struct softpipe_surface *sps = softpipe_surface(ps);
+ GLint j;
+ for (j = 0; j < h; j++) {
+ sps->write_mono_row_ub(sps, w, x, y + j, clr);
+ }
+ }
+ }
+
+ if (depth) {
+ }
+
+}
diff --git a/src/mesa/pipe/softpipe/sp_clear.h b/src/mesa/pipe/softpipe/sp_clear.h
new file mode 100644
index 0000000000..f9db99dd32
--- /dev/null
+++ b/src/mesa/pipe/softpipe/sp_clear.h
@@ -0,0 +1,43 @@
+/**************************************************************************
+ *
+ * Copyright 2007 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.
+ *
+ **************************************************************************/
+
+/* Author:
+ * Brian Paul
+ */
+
+#ifndef SP_CLEAR_H
+#define SP_CLEAR_H
+
+#include "pipe/p_state.h"
+struct pipe_context;
+
+extern void
+softpipe_clear(struct pipe_context *pipe, GLboolean color, GLboolean depth,
+ GLboolean stencil, GLboolean accum);
+
+
+#endif /* SP_CLEAR_H */
diff --git a/src/mesa/pipe/softpipe/sp_context.c b/src/mesa/pipe/softpipe/sp_context.c
new file mode 100644
index 0000000000..3bb04a6835
--- /dev/null
+++ b/src/mesa/pipe/softpipe/sp_context.c
@@ -0,0 +1,126 @@
+/**************************************************************************
+ *
+ * Copyright 2007 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.
+ *
+ **************************************************************************/
+
+/* Author:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "main/imports.h"
+#include "main/macros.h"
+#include "pipe/draw/draw_context.h"
+#include "sp_context.h"
+#include "sp_clear.h"
+#include "sp_state.h"
+#include "sp_prim_setup.h"
+
+
+static void softpipe_destroy( struct pipe_context *pipe )
+{
+ struct softpipe_context *softpipe = softpipe_context( pipe );
+
+ draw_destroy( softpipe->draw );
+
+ free( softpipe );
+}
+
+
+static void softpipe_draw_vb( struct pipe_context *pipe,
+ struct vertex_buffer *VB )
+{
+ struct softpipe_context *softpipe = softpipe_context( pipe );
+
+ if (softpipe->dirty)
+ softpipe_update_derived( softpipe );
+
+ draw_vb( softpipe->draw, VB );
+}
+
+
+static void softpipe_reset_occlusion_counter(struct pipe_context *pipe)
+{
+ struct softpipe_context *softpipe = softpipe_context( pipe );
+ softpipe->occlusion_counter = 0;
+}
+
+/* XXX pipe param should be const */
+static GLuint softpipe_get_occlusion_counter(struct pipe_context *pipe)
+{
+ struct softpipe_context *softpipe = softpipe_context( pipe );
+ return softpipe->occlusion_counter;
+}
+
+
+struct pipe_context *softpipe_create( void )
+{
+ struct softpipe_context *softpipe = CALLOC_STRUCT(softpipe_context);
+
+ softpipe->pipe.destroy = softpipe_destroy;
+ softpipe->pipe.set_alpha_test_state = softpipe_set_alpha_test_state;
+ softpipe->pipe.set_blend_color = softpipe_set_blend_color;
+ softpipe->pipe.set_blend_state = softpipe_set_blend_state;
+ softpipe->pipe.set_clip_state = softpipe_set_clip_state;
+ softpipe->pipe.set_clear_color_state = softpipe_set_clear_color_state;
+ softpipe->pipe.set_depth_state = softpipe_set_depth_test_state;
+ softpipe->pipe.set_framebuffer_state = softpipe_set_framebuffer_state;
+ softpipe->pipe.set_fs_state = softpipe_set_fs_state;
+ softpipe->pipe.set_polygon_stipple = softpipe_set_polygon_stipple;
+ softpipe->pipe.set_sampler_state = softpipe_set_sampler_state;
+ softpipe->pipe.set_scissor_state = softpipe_set_scissor_state;
+ softpipe->pipe.set_setup_state = softpipe_set_setup_state;
+ softpipe->pipe.set_stencil_state = softpipe_set_stencil_state;
+ softpipe->pipe.set_texture_state = softpipe_set_texture_state;
+ softpipe->pipe.set_viewport_state = softpipe_set_viewport_state;
+ softpipe->pipe.draw_vb = softpipe_draw_vb;
+ softpipe->pipe.clear = softpipe_clear;
+ softpipe->pipe.reset_occlusion_counter = softpipe_reset_occlusion_counter;
+ softpipe->pipe.get_occlusion_counter = softpipe_get_occlusion_counter;
+
+ softpipe->quad.polygon_stipple = sp_quad_polygon_stipple_stage(softpipe);
+ softpipe->quad.shade = sp_quad_shade_stage(softpipe);
+ softpipe->quad.alpha_test = sp_quad_alpha_test_stage(softpipe);
+ softpipe->quad.depth_test = sp_quad_depth_test_stage(softpipe);
+ softpipe->quad.stencil_test = sp_quad_stencil_test_stage(softpipe);
+ softpipe->quad.occlusion = sp_quad_occlusion_stage(softpipe);
+ softpipe->quad.coverage = sp_quad_coverage_stage(softpipe);
+ softpipe->quad.bufloop = sp_quad_bufloop_stage(softpipe);
+ softpipe->quad.blend = sp_quad_blend_stage(softpipe);
+ softpipe->quad.colormask = sp_quad_colormask_stage(softpipe);
+ softpipe->quad.output = sp_quad_output_stage(softpipe);
+
+ /*
+ * Create drawing context and plug our rendering stage into it.
+ */
+ softpipe->draw = draw_create();
+ draw_set_setup_stage(softpipe->draw, sp_draw_render_stage(softpipe));
+
+ /*
+ * XXX we could plug GL selection/feedback into the drawing pipeline
+ * by specifying a different setup/render stage.
+ */
+
+ return &softpipe->pipe;
+}
diff --git a/src/mesa/pipe/softpipe/sp_context.h b/src/mesa/pipe/softpipe/sp_context.h
new file mode 100644
index 0000000000..ef1a06ccaf
--- /dev/null
+++ b/src/mesa/pipe/softpipe/sp_context.h
@@ -0,0 +1,153 @@
+/**************************************************************************
+ *
+ * Copyright 2007 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.
+ *
+ **************************************************************************/
+
+/* Authors: Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#ifndef SP_CONTEXT_H
+#define SP_CONTEXT_H
+
+#include "glheader.h"
+
+#include "pipe/p_state.h"
+#include "pipe/p_context.h"
+
+#include "sp_quad.h"
+
+
+struct softpipe_surface;
+struct draw_context;
+struct draw_stage;
+
+
+enum interp_mode {
+ INTERP_CONSTANT,
+ INTERP_LINEAR,
+ INTERP_PERSPECTIVE
+};
+
+
+#define SP_NEW_VIEWPORT 0x1
+#define SP_NEW_SETUP 0x2
+#define SP_NEW_FS 0x4
+#define SP_NEW_BLEND 0x8
+#define SP_NEW_CLIP 0x10
+#define SP_NEW_SCISSOR 0x20
+#define SP_NEW_STIPPLE 0x40
+#define SP_NEW_FRAMEBUFFER 0x80
+#define SP_NEW_ALPHA_TEST 0x100
+#define SP_NEW_DEPTH_TEST 0x200
+#define SP_NEW_SAMPLER 0x400
+#define SP_NEW_TEXTURE 0x800
+#define SP_NEW_STENCIL 0x1000
+
+
+struct softpipe_context {
+ struct pipe_context pipe; /**< base class */
+
+ /* The most recent drawing state as set by the driver:
+ */
+ struct pipe_alpha_test_state alpha_test;
+ struct pipe_blend_state blend;
+ struct pipe_blend_color blend_color;
+ struct pipe_clear_color_state clear_color;
+ struct pipe_clip_state clip;
+ struct pipe_depth_state depth_test;
+ struct pipe_framebuffer_state framebuffer;
+ struct pipe_fs_state fs;
+ struct pipe_poly_stipple poly_stipple;
+ struct pipe_scissor_state scissor;
+ struct pipe_sampler_state sampler[PIPE_MAX_SAMPLERS];
+ struct pipe_setup_state setup;
+ struct pipe_stencil_state stencil;
+ struct pipe_texture_object *texture[PIPE_MAX_SAMPLERS];
+ struct pipe_viewport_state viewport;
+ GLuint dirty;
+
+ /* Setup derived state. TODO: this should be passed in the program
+ * tokens as parameters to DECL instructions.
+ *
+ * For now we just set colors to CONST on flatshade, textures to
+ * perspective always and everything else to linear.
+ */
+ enum interp_mode interp[PIPE_ATTRIB_MAX];
+
+
+ /* FS + setup derived state:
+ */
+
+ /** Map fragment program attribute to quad/coef array slot */
+ GLuint fp_attr_to_slot[PIPE_ATTRIB_MAX];
+ /** Map vertex format attribute to a vertex attribute slot */
+ GLuint vf_attr_to_slot[PIPE_ATTRIB_MAX];
+ GLuint nr_attrs;
+ GLuint nr_frag_attrs; /**< number of active fragment attribs */
+ GLbitfield attr_mask; /**< bitfield of VF_ATTRIB_ indexes/bits */
+
+ GLboolean need_z; /**< produce quad/fragment Z values? */
+ GLboolean need_w; /**< produce quad/fragment W values? */
+
+ /* Stipple derived state:
+ */
+ GLubyte stipple_masks[16][16];
+
+ GLuint occlusion_counter;
+
+ /** Software quad rendering pipeline */
+ struct {
+ struct quad_stage *polygon_stipple;
+ struct quad_stage *shade;
+ struct quad_stage *alpha_test;
+ struct quad_stage *stencil_test;
+ struct quad_stage *depth_test;
+ struct quad_stage *occlusion;
+ struct quad_stage *coverage;
+ struct quad_stage *bufloop;
+ struct quad_stage *blend;
+ struct quad_stage *colormask;
+ struct quad_stage *output;
+
+ struct quad_stage *first; /**< points to one of the above stages */
+ } quad;
+
+ /** The primitive drawing context */
+ struct draw_context *draw;
+
+ struct pipe_surface *cbuf; /**< current color buffer (one of cbufs) */
+};
+
+
+
+
+static INLINE struct softpipe_context *
+softpipe_context( struct pipe_context *pipe )
+{
+ return (struct softpipe_context *)pipe;
+}
+
+
+#endif /* SP_CONTEXT_H */
diff --git a/src/mesa/pipe/softpipe/sp_headers.h b/src/mesa/pipe/softpipe/sp_headers.h
new file mode 100644
index 0000000000..68a84621f2
--- /dev/null
+++ b/src/mesa/pipe/softpipe/sp_headers.h
@@ -0,0 +1,95 @@
+/**************************************************************************
+ *
+ * Copyright 2007 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.
+ *
+ **************************************************************************/
+
+/* Authors: Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#ifndef SP_HEADERS_H
+#define SP_HEADERS_H
+
+
+#define PRIM_POINT 1
+#define PRIM_LINE 2
+#define PRIM_TRI 3
+
+
+/* The rasterizer generates 2x2 quads of fragment and feeds them to
+ * the current fp_machine (see below).
+ */
+#define QUAD_BOTTOM_LEFT 0
+#define QUAD_BOTTOM_RIGHT 1
+#define QUAD_TOP_LEFT 2
+#define QUAD_TOP_RIGHT 3
+#define QUAD_SIZE (2*2)
+
+#define MASK_BOTTOM_LEFT 0x1
+#define MASK_BOTTOM_RIGHT 0x2
+#define MASK_TOP_LEFT 0x4
+#define MASK_TOP_RIGHT 0x8
+#define MASK_ALL 0xf
+
+
+#define NUM_CHANNELS 4 /* avoid confusion between 4 pixels and 4 channels */
+
+
+struct setup_coefficient {
+ GLfloat a0[NUM_CHANNELS]; /* in an xyzw layout */
+ GLfloat dadx[NUM_CHANNELS];
+ GLfloat dady[NUM_CHANNELS];
+};
+
+
+
+/**
+ * Encodes everything we need to know about a 2x2 pixel block. Uses
+ * "Channel-Serial" or "SoA" layout.
+ */
+struct quad_header {
+ GLint x0;
+ GLint y0;
+ GLuint mask:4;
+ GLuint facing:1; /**< Front (0) or back (1) facing? */
+ GLuint prim:2; /**< PRIM_POINT, LINE, TRI */
+
+ struct {
+ GLfloat color[4][QUAD_SIZE]; /* rrrr, gggg, bbbb, aaaa */
+ GLfloat depth[QUAD_SIZE];
+ } outputs;
+
+ GLfloat coverage[QUAD_SIZE]; /** fragment coverage for antialiasing */
+
+ const struct setup_coefficient *coef;
+
+ const enum interp_mode *interp; /* XXX: this information should be
+ * encoded in fragment program DECL
+ * statements. */
+
+ GLuint nr_attrs;
+};
+
+
+#endif /* SP_HEADERS_H */
diff --git a/src/mesa/pipe/softpipe/sp_prim_setup.c b/src/mesa/pipe/softpipe/sp_prim_setup.c
new file mode 100644
index 0000000000..6420fc8809
--- /dev/null
+++ b/src/mesa/pipe/softpipe/sp_prim_setup.c
@@ -0,0 +1,1005 @@
+/**************************************************************************
+ *
+ * Copyright 2007 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.
+ *
+ **************************************************************************/
+
+/**
+ * \brief Primitive rasterization/rendering (points, lines, triangles)
+ *
+ * \author Keith Whitwell <keith@tungstengraphics.com>
+ * \author Brian Paul
+ */
+
+
+#include "imports.h"
+#include "macros.h"
+
+#include "sp_context.h"
+#include "sp_headers.h"
+#include "pipe/draw/draw_private.h"
+#include "sp_quad.h"
+#include "sp_prim_setup.h"
+
+
+
+/**
+ * Emit/render a quad.
+ * This passes the quad to the first stage of per-fragment operations.
+ */
+static INLINE void
+quad_emit(struct softpipe_context *sp, struct quad_header *quad)
+{
+ sp->quad.first->run(sp->quad.first, quad);
+}
+
+
+/**
+ * Triangle edge info
+ */
+struct edge {
+ GLfloat dx; /* X(v1) - X(v0), used only during setup */
+ GLfloat dy; /* Y(v1) - Y(v0), used only during setup */
+ GLfloat dxdy; /* dx/dy */
+ GLfloat sx; /* first sample point x coord */
+ GLfloat sy;
+ GLint lines; /* number of lines on this edge */
+};
+
+
+/**
+ * Triangle setup info (derived from draw_stage).
+ * Also used for line drawing (taking some liberties).
+ */
+struct setup_stage {
+ struct draw_stage stage; /**< This must be first (base class) */
+
+ /*XXX NEW */
+ struct softpipe_context *softpipe;
+
+ /* Vertices are just an array of floats making up each attribute in
+ * turn. Currently fixed at 4 floats, but should change in time.
+ * Codegen will help cope with this.
+ */
+ const struct vertex_header *vmax;
+ const struct vertex_header *vmid;
+ const struct vertex_header *vmin;
+ const struct vertex_header *vprovoke;
+
+ struct edge ebot;
+ struct edge etop;
+ struct edge emaj;
+
+ GLfloat oneoverarea;
+
+ struct setup_coefficient coef[FRAG_ATTRIB_MAX];
+ struct quad_header quad;
+
+ struct {
+ GLint left[2]; /**< [0] = row0, [1] = row1 */
+ GLint right[2];
+ GLint y;
+ GLuint y_flags;
+ GLuint mask; /**< mask of MASK_BOTTOM/TOP_LEFT/RIGHT bits */
+ } span;
+};
+
+
+
+/**
+ * Basically a cast wrapper.
+ */
+static inline struct setup_stage *setup_stage( struct draw_stage *stage )
+{
+ return (struct setup_stage *)stage;
+}
+
+
+/**
+ * Given an X or Y coordinate, return the block/quad coordinate that it
+ * belongs to.
+ */
+static inline GLint block( GLint x )
+{
+ return x & ~1;
+}
+
+
+
+/**
+ * Run shader on a quad/block.
+ */
+static void run_shader_block( struct setup_stage *setup,
+ GLint x, GLint y, GLuint mask )
+{
+ setup->quad.x0 = x;
+ setup->quad.y0 = y;
+ setup->quad.mask = mask;
+
+ quad_emit(setup->softpipe, &setup->quad);
+}
+
+
+/**
+ * Compute mask which indicates which pixels in the 2x2 quad are actually inside
+ * the triangle's bounds.
+ *
+ * this is pretty nasty... may need to rework flush_spans again to
+ * fix it, if possible.
+ */
+static GLuint calculate_mask( struct setup_stage *setup,
+ GLint x )
+{
+ GLuint mask = 0;
+
+ if (x >= setup->span.left[0] && x < setup->span.right[0])
+ mask |= MASK_BOTTOM_LEFT;
+
+ if (x >= setup->span.left[1] && x < setup->span.right[1])
+ mask |= MASK_TOP_LEFT;
+
+ if (x+1 >= setup->span.left[0] && x+1 < setup->span.right[0])
+ mask |= MASK_BOTTOM_RIGHT;
+
+ if (x+1 >= setup->span.left[1] && x+1 < setup->span.right[1])
+ mask |= MASK_TOP_RIGHT;
+
+ return mask;
+}
+
+
+/**
+ * Render a horizontal span of quads
+ */
+static void flush_spans( struct setup_stage *setup )
+{
+ GLint minleft, maxright;
+ GLint x;
+
+ switch (setup->span.y_flags) {
+ case 3:
+ minleft = MIN2(setup->span.left[0], setup->span.left[1]);
+ maxright = MAX2(setup->span.right[0], setup->span.right[1]);
+ break;
+
+ case 1:
+ minleft = setup->span.left[0];
+ maxright = setup->span.right[0];
+ break;
+
+ case 2:
+ minleft = setup->span.left[1];
+ maxright = setup->span.right[1];
+ break;
+
+ default:
+ return;
+ }
+
+
+ for (x = block(minleft); x <= block(maxright); )
+ {
+ run_shader_block( setup, x,
+ setup->span.y,
+ calculate_mask( setup, x ) );
+ x += 2;
+ }
+
+ setup->span.y = 0;
+ setup->span.y_flags = 0;
+ setup->span.right[0] = 0;
+ setup->span.right[1] = 0;
+}
+
+
+static GLboolean setup_sort_vertices( struct setup_stage *setup,
+ const struct prim_header *prim )
+{
+ const struct vertex_header *v0 = prim->v[0];
+ const struct vertex_header *v1 = prim->v[1];
+ const struct vertex_header *v2 = prim->v[2];
+
+ setup->vprovoke = v2;
+
+ /* determine bottom to top order of vertices */
+ {
+ GLfloat y0 = v0->data[0][1];
+ GLfloat y1 = v1->data[0][1];
+ GLfloat y2 = v2->data[0][1];
+ if (y0 <= y1) {
+ if (y1 <= y2) {
+ /* y0<=y1<=y2 */
+ setup->vmin = v0;
+ setup->vmid = v1;
+ setup->vmax = v2;
+ }
+ else if (y2 <= y0) {
+ /* y2<=y0<=y1 */
+ setup->vmin = v2;
+ setup->vmid = v0;
+ setup->vmax = v1;
+ }
+ else {
+ /* y0<=y2<=y1 */
+ setup->vmin = v0;
+ setup->vmid = v2;
+ setup->vmax = v1;
+ }
+ }
+ else {
+ if (y0 <= y2) {
+ /* y1<=y0<=y2 */
+ setup->vmin = v1;
+ setup->vmid = v0;
+ setup->vmax = v2;
+ }
+ else if (y2 <= y1) {
+ /* y2<=y1<=y0 */
+ setup->vmin = v2;
+ setup->vmid = v1;
+ setup->vmax = v0;
+ }
+ else {
+ /* y1<=y2<=y0 */
+ setup->vmin = v1;
+ setup->vmid = v2;
+ setup->vmax = v0;
+ }
+ }
+ }
+
+ setup->ebot.dx = setup->vmid->data[0][0] - setup->vmin->data[0][0];
+ setup->ebot.dy = setup->vmid->data[0][1] - setup->vmin->data[0][1];
+ setup->emaj.dx = setup->vmax->data[0][0] - setup->vmin->data[0][0];
+ setup->emaj.dy = setup->vmax->data[0][1] - setup->vmin->data[0][1];
+ setup->etop.dx = setup->vmax->data[0][0] - setup->vmid->data[0][0];
+ setup->etop.dy = setup->vmax->data[0][1] - setup->vmid->data[0][1];
+
+ /*
+ * Compute triangle's area. Use 1/area to compute partial
+ * derivatives of attributes later.
+ *
+ * The area will be the same as prim->det, but the sign may be
+ * different depending on how the vertices get sorted above.
+ *
+ * To determine whether the primitive is front or back facing we
+ * use the prim->det value because its sign is correct.
+ */
+ {
+ const GLfloat area = (setup->emaj.dx * setup->ebot.dy -
+ setup->ebot.dx * setup->emaj.dy);
+
+ setup->oneoverarea = 1.0 / area;
+ /*
+ _mesa_printf("%s one-over-area %f area %f det %f\n",
+ __FUNCTION__, setup->oneoverarea, area, prim->det );
+ */
+ }
+
+ /* We need to know if this is a front or back-facing triangle for:
+ * - the GLSL gl_FrontFacing fragment attribute (bool)
+ * - two-sided stencil test
+ */
+ setup->quad.facing = (prim->det > 0.0) ^ (setup->softpipe->setup.front_winding == PIPE_WINDING_CW);
+
+ return GL_TRUE;
+}
+
+
+/**
+ * Compute a0 for a constant-valued coefficient (GL_FLAT shading).
+ * The value value comes from vertex->data[slot][i].
+ * The result will be put into setup->coef[slot].a0[i].
+ * \param slot which attribute slot
+ * \param i which component of the slot (0..3)
+ */
+static void const_coeff( struct setup_stage *setup,
+ GLuint slot,
+ GLuint i )
+{
+ assert(slot < FRAG_ATTRIB_MAX);
+ assert(i <= 3);
+
+ setup->coef[slot].dadx[i] = 0;
+ setup->coef[slot].dady[i] = 0;
+
+ /* need provoking vertex info!
+ */
+ setup->coef[slot].a0[i] = setup->vprovoke->data[slot][i];
+}
+
+
+/**
+ * Compute a0, dadx and dady for a linearly interpolated coefficient,
+ * for a triangle.
+ */
+static void tri_linear_coeff( struct setup_stage *setup,
+ GLuint slot,
+ GLuint i)
+{
+ GLfloat botda = setup->vmid->data[slot][i] - setup->vmin->data[slot][i];
+ GLfloat majda = setup->vmax->data[slot][i] - setup->vmin->data[slot][i];
+ GLfloat a = setup->ebot.dy * majda - botda * setup->emaj.dy;
+ GLfloat b = setup->emaj.dx * botda - majda * setup->ebot.dx;
+
+ assert(slot < FRAG_ATTRIB_MAX);
+ assert(i <= 3);
+
+ setup->coef[slot].dadx[i] = a * setup->oneoverarea;
+ setup->coef[slot].dady[i] = b * setup->oneoverarea;
+
+ /* calculate a0 as the value which would be sampled for the
+ * fragment at (0,0), taking into account that we want to sample at
+ * pixel centers, in other words (0.5, 0.5).
+ *
+ * this is neat but unfortunately not a good way to do things for
+ * triangles with very large values of dadx or dady as it will
+ * result in the subtraction and re-addition from a0 of a very
+ * large number, which means we'll end up loosing a lot of the
+ * fractional bits and precision from a0. the way to fix this is
+ * to define a0 as the sample at a pixel center somewhere near vmin
+ * instead - i'll switch to this later.
+ */
+ setup->coef[slot].a0[i] = (setup->vmin->data[slot][i] -
+ (setup->coef[slot].dadx[i] * (setup->vmin->data[0][0] - 0.5) +
+ setup->coef[slot].dady[i] * (setup->vmin->data[0][1] - 0.5)));
+
+ /*
+ _mesa_printf("attr[%d].%c: %f dx:%f dy:%f\n",
+ slot, "xyzw"[i],
+ setup->coef[slot].a0[i],
+ setup->coef[slot].dadx[i],
+ setup->coef[slot].dady[i]);
+ */
+}
+
+
+/**
+ * Compute a0, dadx and dady for a perspective-corrected interpolant,
+ * for a triangle.
+ */
+static void tri_persp_coeff( struct setup_stage *setup,
+ GLuint slot,
+ GLuint i )
+{
+ /* premultiply by 1/w:
+ */
+ GLfloat mina = setup->vmin->data[slot][i] * setup->vmin->data[0][3];
+ GLfloat mida = setup->vmid->data[slot][i] * setup->vmid->data[0][3];
+ GLfloat maxa = setup->vmax->data[slot][i] * setup->vmax->data[0][3];
+
+ GLfloat botda = mida - mina;
+ GLfloat majda = maxa - mina;
+ GLfloat a = setup->ebot.dy * majda - botda * setup->emaj.dy;
+ GLfloat b = setup->emaj.dx * botda - majda * setup->ebot.dx;
+
+ assert(slot < FRAG_ATTRIB_MAX);
+ assert(i <= 3);
+
+ setup->coef[slot].dadx[i] = a * setup->oneoverarea;
+ setup->coef[slot].dady[i] = b * setup->oneoverarea;
+ setup->coef[slot].a0[i] = (mina -
+ (setup->coef[slot].dadx[i] * (setup->vmin->data[0][0] - 0.5) +
+ setup->coef[slot].dady[i] * (setup->vmin->data[0][1] - 0.5)));
+}
+
+
+
+/**
+ * Compute the setup->coef[] array dadx, dady, a0 values.
+ * Must be called after setup->vmin,vmid,vmax,vprovoke are initialized.
+ */
+static void setup_tri_coefficients( struct setup_stage *setup )
+{
+ const enum interp_mode *interp = setup->softpipe->interp;
+ GLuint slot, j;
+
+ /* z and w are done by linear interpolation:
+ */
+ tri_linear_coeff(setup, 0, 2);
+ tri_linear_coeff(setup, 0, 3);
+
+ /* setup interpolation for all the remaining attributes:
+ */
+ for (slot = 1; slot < setup->quad.nr_attrs; slot++) {
+ switch (interp[slot]) {
+ case INTERP_CONSTANT:
+ for (j = 0; j < NUM_CHANNELS; j++)
+ const_coeff(setup, slot, j);
+ break;
+
+ case INTERP_LINEAR:
+ for (j = 0; j < NUM_CHANNELS; j++)
+ tri_linear_coeff(setup, slot, j);
+ break;
+
+ case INTERP_PERSPECTIVE:
+ for (j = 0; j < NUM_CHANNELS; j++)
+ tri_persp_coeff(setup, slot, j);
+ break;
+ }
+ }
+}
+
+
+
+static void setup_tri_edges( struct setup_stage *setup )
+{
+ GLfloat vmin_x = setup->vmin->data[0][0] + 0.5;
+ GLfloat vmid_x = setup->vmid->data[0][0] + 0.5;
+
+ GLfloat vmin_y = setup->vmin->data[0][1] - 0.5;
+ GLfloat vmid_y = setup->vmid->data[0][1] - 0.5;
+ GLfloat vmax_y = setup->vmax->data[0][1] - 0.5;
+
+ setup->emaj.sy = ceilf(vmin_y);
+ setup->emaj.lines = (GLint) ceilf(vmax_y - setup->emaj.sy);
+ setup->emaj.dxdy = setup->emaj.dx / setup->emaj.dy;
+ setup->emaj.sx = vmin_x + (setup->emaj.sy - vmin_y) * setup->emaj.dxdy;
+
+ setup->etop.sy = ceilf(vmid_y);
+ setup->etop.lines = (GLint) ceilf(vmax_y - setup->etop.sy);
+ setup->etop.dxdy = setup->etop.dx / setup->etop.dy;
+ setup->etop.sx = vmid_x + (setup->etop.sy - vmid_y) * setup->etop.dxdy;
+
+ setup->ebot.sy = ceilf(vmin_y);
+ setup->ebot.lines = (GLint) ceilf(vmid_y - setup->ebot.sy);
+ setup->ebot.dxdy = setup->ebot.dx / setup->ebot.dy;
+ setup->ebot.sx = vmin_x + (setup->ebot.sy - vmin_y) * setup->ebot.dxdy;
+}
+
+
+/**
+ * Render the upper or lower half of a triangle.
+ * Scissoring is applied here too.
+ */
+static void subtriangle( struct setup_stage *setup,
+ struct edge *eleft,
+ struct edge *eright,
+ GLuint lines )
+{
+ GLint y, start_y, finish_y;
+ GLint sy = (GLint)eleft->sy;
+
+ assert((GLint)eleft->sy == (GLint) eright->sy);
+ assert((GLint)eleft->sy >= 0); /* catch bug in x64? */
+
+ /* scissor y:
+ */
+ if (setup->softpipe->setup.scissor) {
+ start_y = sy;
+ finish_y = start_y + lines;
+
+ if (start_y < setup->softpipe->scissor.miny)
+ start_y = setup->softpipe->scissor.miny;
+
+ if (finish_y > setup->softpipe->scissor.maxy)
+ finish_y = setup->softpipe->scissor.maxy;
+
+ start_y -= sy;
+ finish_y -= sy;
+ }
+ else {
+ start_y = 0;
+ finish_y = lines;
+ }
+
+ /*
+ _mesa_printf("%s %d %d\n", __FUNCTION__, start_y, finish_y);
+ */
+
+ for (y = start_y; y < finish_y; y++) {
+
+ /* avoid accumulating adds as floats don't have the precision to
+ * accurately iterate large triangle edges that way. luckily we
+ * can just multiply these days.
+ *
+ * this is all drowned out by the attribute interpolation anyway.
+ */
+ GLint left = (GLint)(eleft->sx + y * eleft->dxdy);
+ GLint right = (GLint)(eright->sx + y * eright->dxdy);
+
+ /* scissor x:
+ */
+ if (setup->softpipe->setup.scissor) {
+ if (left < setup->softpipe->scissor.minx)
+ left = setup->softpipe->scissor.minx;
+
+ if (right > setup->softpipe->scissor.maxx)
+ right = setup->softpipe->scissor.maxx;
+ }
+
+ if (left < right) {
+ GLint _y = sy+y;
+ if (block(_y) != setup->span.y) {
+ flush_spans(setup);
+ setup->span.y = block(_y);
+ }
+
+ setup->span.left[_y&1] = left;
+ setup->span.right[_y&1] = right;
+ setup->span.y_flags |= 1<<(_y&1);
+ }
+ }
+
+
+ /* save the values so that emaj can be restarted:
+ */
+ eleft->sx += lines * eleft->dxdy;
+ eright->sx += lines * eright->dxdy;
+ eleft->sy += lines;
+ eright->sy += lines;
+}
+
+
+/**
+ * Do setup for triangle rasterization, then render the triangle.
+ */
+static void setup_tri( struct draw_stage *stage,
+ struct prim_header *prim )
+{
+ struct setup_stage *setup = setup_stage( stage );
+
+ /*
+ _mesa_printf("%s\n", __FUNCTION__ );
+ */
+
+ setup_sort_vertices( setup, prim );
+ setup_tri_coefficients( setup );
+ setup_tri_edges( setup );
+
+ setup->quad.prim = PRIM_TRI;
+
+ setup->span.y = 0;
+ setup->span.y_flags = 0;
+ setup->span.right[0] = 0;
+ setup->span.right[1] = 0;
+ /* setup->span.z_mode = tri_z_mode( setup->ctx ); */
+
+ /* init_constant_attribs( setup ); */
+
+ if (setup->oneoverarea < 0.0) {
+ /* emaj on left:
+ */
+ subtriangle( setup, &setup->emaj, &setup->ebot, setup->ebot.lines );
+ subtriangle( setup, &setup->emaj, &setup->etop, setup->etop.lines );
+ }
+ else {
+ /* emaj on right:
+ */
+ subtriangle( setup, &setup->ebot, &setup->emaj, setup->ebot.lines );
+ subtriangle( setup, &setup->etop, &setup->emaj, setup->etop.lines );
+ }
+
+ flush_spans( setup );
+}
+
+
+
+/**
+ * Compute a0, dadx and dady for a linearly interpolated coefficient,
+ * for a line.
+ */
+static void
+line_linear_coeff(struct setup_stage *setup, GLuint slot, GLuint i)
+{
+ const GLfloat dz = setup->vmax->data[slot][i] - setup->vmin->data[slot][i];
+ const GLfloat dadx = dz * setup->emaj.dx * setup->oneoverarea;
+ const GLfloat dady = dz * setup->emaj.dy * setup->oneoverarea;
+ setup->coef[slot].dadx[i] = dadx;
+ setup->coef[slot].dady[i] = dady;
+ setup->coef[slot].a0[i]
+ = (setup->vmin->data[slot][i] -
+ (dadx * (setup->vmin->data[0][0] - 0.5) +
+ dady * (setup->vmin->data[0][1] - 0.5)));
+}
+
+
+/**
+ * Compute a0, dadx and dady for a perspective-corrected interpolant,
+ * for a line.
+ */
+static void
+line_persp_coeff(struct setup_stage *setup, GLuint slot, GLuint i)
+{
+ /* XXX to do */
+ line_linear_coeff(setup, slot, i); /* XXX temporary */
+}
+
+
+/**
+ * Compute the setup->coef[] array dadx, dady, a0 values.
+ * Must be called after setup->vmin,vmax are initialized.
+ */
+static INLINE void
+setup_line_coefficients(struct setup_stage *setup, struct prim_header *prim)
+{
+ const enum interp_mode *interp = setup->softpipe->interp;
+ GLuint slot, j;
+
+ /* use setup->vmin, vmax to point to vertices */
+ setup->vprovoke = prim->v[1];
+ setup->vmin = prim->v[0];
+ setup->vmax = prim->v[1];
+
+ setup->emaj.dx = setup->vmax->data[0][0] - setup->vmin->data[0][0];
+ setup->emaj.dy = setup->vmax->data[0][1] - setup->vmin->data[0][1];
+ /* NOTE: this is not really 1/area */
+ setup->oneoverarea = 1.0 / (setup->emaj.dx * setup->emaj.dx +
+ setup->emaj.dy * setup->emaj.dy);
+
+ /* z and w are done by linear interpolation:
+ */
+ line_linear_coeff(setup, 0, 2);
+ line_linear_coeff(setup, 0, 3);
+
+ /* setup interpolation for all the remaining attributes:
+ */
+ for (slot = 1; slot < setup->quad.nr_attrs; slot++) {
+ switch (interp[slot]) {
+ case INTERP_CONSTANT:
+ for (j = 0; j < NUM_CHANNELS; j++)
+ const_coeff(setup, slot, j);
+ break;
+
+ case INTERP_LINEAR:
+ for (j = 0; j < NUM_CHANNELS; j++)
+ line_linear_coeff(setup, slot, j);
+ break;
+
+ case INTERP_PERSPECTIVE:
+ for (j = 0; j < NUM_CHANNELS; j++)
+ line_persp_coeff(setup, slot, j);
+ break;
+ }
+ }
+}
+
+
+/**
+ * Plot a pixel in a line segment.
+ */
+static INLINE void
+plot(struct setup_stage *setup, GLint x, GLint y)
+{
+ const GLint iy = y & 1;
+ const GLint ix = x & 1;
+ const GLint quadX = x - ix;
+ const GLint quadY = y - iy;
+ const GLint mask = (1 << ix) << (2 * iy);
+
+ if (quadX != setup->quad.x0 ||
+ quadY != setup->quad.y0)
+ {
+ /* flush prev quad, start new quad */
+
+ if (setup->quad.x0 != -1)
+ quad_emit(setup->softpipe, &setup->quad);
+
+ setup->quad.x0 = quadX;
+ setup->quad.y0 = quadY;
+ setup->quad.mask = 0x0;
+ }
+
+ setup->quad.mask |= mask;
+}
+
+
+
+/**
+ * Do setup for line rasterization, then render the line.
+ * XXX single-pixel width, no stipple, etc
+ * XXX no scissoring yet.
+ */
+static void
+setup_line(struct draw_stage *stage, struct prim_header *prim)
+{
+ const struct vertex_header *v0 = prim->v[0];
+ const struct vertex_header *v1 = prim->v[1];
+ struct setup_stage *setup = setup_stage( stage );
+
+ GLint x0 = (GLint) v0->data[0][0];
+ GLint x1 = (GLint) v1->data[0][0];
+ GLint y0 = (GLint) v0->data[0][1];
+ GLint y1 = (GLint) v1->data[0][1];
+ GLint dx = x1 - x0;
+ GLint dy = y1 - y0;
+ GLint xstep, ystep;
+
+ if (dx == 0 && dy == 0)
+ return;
+
+ setup_line_coefficients(setup, prim);
+
+ if (dx < 0) {
+ dx = -dx; /* make positive */
+ xstep = -1;
+ }
+ else {
+ xstep = 1;
+ }
+
+ if (dy < 0) {
+ dy = -dy; /* make positive */
+ ystep = -1;
+ }
+ else {
+ ystep = 1;
+ }
+
+ assert(dx >= 0);
+ assert(dy >= 0);
+
+ setup->quad.x0 = setup->quad.y0 = -1;
+ setup->quad.mask = 0x0;
+ setup->quad.prim = PRIM_LINE;
+
+ if (dx > dy) {
+ /*** X-major line ***/
+ GLint i;
+ const GLint errorInc = dy + dy;
+ GLint error = errorInc - dx;
+ const GLint errorDec = error - dx;
+
+ for (i = 0; i < dx; i++) {
+ plot(setup, x0, y0);
+
+ x0 += xstep;
+ if (error < 0) {
+ error += errorInc;
+ }
+ else {
+ error += errorDec;
+ y0 += ystep;
+ }
+ }
+ }
+ else {
+ /*** Y-major line ***/
+ GLint i;
+ const GLint errorInc = dx + dx;
+ GLint error = errorInc - dy;
+ const GLint errorDec = error - dy;
+
+ for (i = 0; i < dy; i++) {
+ plot(setup, x0, y0);
+
+ y0 += ystep;
+
+ if (error < 0) {
+ error += errorInc;
+ }
+ else {
+ error += errorDec;
+ x0 += xstep;
+ }
+ }
+ }
+
+ /* draw final quad */
+ if (setup->quad.mask) {
+ quad_emit(setup->softpipe, &setup->quad);
+ }
+}
+
+
+/**
+ * Do setup for point rasterization, then render the point.
+ * Round or square points...
+ * XXX could optimize a lot for 1-pixel points.
+ */
+static void
+setup_point(struct draw_stage *stage, struct prim_header *prim)
+{
+ struct setup_stage *setup = setup_stage( stage );
+ /*XXX this should be a vertex attrib! */
+ GLfloat halfSize = 0.5 * setup->softpipe->setup.point_size;
+ GLboolean round = setup->softpipe->setup.point_smooth;
+ const struct vertex_header *v0 = prim->v[0];
+ const GLfloat x = v0->data[FRAG_ATTRIB_WPOS][0];
+ const GLfloat y = v0->data[FRAG_ATTRIB_WPOS][1];
+ GLuint slot, j;
+
+ /* For points, all interpolants are constant-valued.
+ * However, for point sprites, we'll need to setup texcoords appropriately.
+ * XXX: which coefficients are the texcoords???
+ * We may do point sprites as textured quads...
+ *
+ * KW: We don't know which coefficients are texcoords - ultimately
+ * the choice of what interpolation mode to use for each attribute
+ * should be determined by the fragment program, using
+ * per-attribute declaration statements that include interpolation
+ * mode as a parameter. So either the fragment program will have
+ * to be adjusted for pointsprite vs normal point behaviour, or
+ * otherwise a special interpolation mode will have to be defined
+ * which matches the required behaviour for point sprites. But -
+ * the latter is not a feature of normal hardware, and as such
+ * probably should be ruled out on that basis.
+ */
+ setup->vprovoke = prim->v[0];
+ const_coeff(setup, 0, 2);
+ const_coeff(setup, 0, 3);
+ for (slot = 1; slot < setup->quad.nr_attrs; slot++) {
+ for (j = 0; j < NUM_CHANNELS; j++)
+ const_coeff(setup, slot, j);
+ }
+
+ setup->quad.prim = PRIM_POINT;
+
+ /* XXX need to clip against scissor bounds too */
+
+ if (halfSize <= 0.5 && !round) {
+ /* special case for 1-pixel points */
+ const GLint ix = ((GLint) x) & 1;
+ const GLint iy = ((GLint) y) & 1;
+ setup->quad.x0 = x - ix;
+ setup->quad.y0 = y - iy;
+ setup->quad.mask = (1 << ix) << (2 * iy);
+ quad_emit(setup->softpipe, &setup->quad);
+ }
+ else {
+ const GLint ixmin = block((GLint) (x - halfSize));
+ const GLint ixmax = block((GLint) (x + halfSize));
+ const GLint iymin = block((GLint) (y - halfSize));
+ const GLint iymax = block((GLint) (y + halfSize));
+ GLint ix, iy;
+
+ if (round) {
+ /* rounded points */
+ const GLfloat rmin = halfSize - 0.7071F; /* 0.7071 = sqrt(2)/2 */
+ const GLfloat rmax = halfSize + 0.7071F;
+ const GLfloat rmin2 = MAX2(0.0F, rmin * rmin);
+ const GLfloat rmax2 = rmax * rmax;
+ const GLfloat cscale = 1.0F / (rmax2 - rmin2);
+
+ for (iy = iymin; iy <= iymax; iy += 2) {
+ for (ix = ixmin; ix <= ixmax; ix += 2) {
+ GLfloat dx, dy, dist2, cover;
+
+ setup->quad.mask = 0x0;
+
+ dx = (ix + 0.5) - x;
+ dy = (iy + 0.5) - y;
+ dist2 = dx * dx + dy * dy;
+ if (dist2 <= rmax2) {
+ cover = 1.0F - (dist2 - rmin2) * cscale;
+ setup->quad.coverage[QUAD_BOTTOM_LEFT] = MIN2(cover, 1.0);
+ setup->quad.mask |= MASK_BOTTOM_LEFT;
+ }
+
+ dx = (ix + 1.5) - x;
+ dy = (iy + 0.5) - y;
+ dist2 = dx * dx + dy * dy;
+ if (dist2 <= rmax2) {
+ cover = 1.0F - (dist2 - rmin2) * cscale;
+ setup->quad.coverage[QUAD_BOTTOM_RIGHT] = MIN2(cover, 1.0);
+ setup->quad.mask |= MASK_BOTTOM_RIGHT;
+ }
+
+ dx = (ix + 0.5) - x;
+ dy = (iy + 1.5) - y;
+ dist2 = dx * dx + dy * dy;
+ if (dist2 <= rmax2) {
+ cover = 1.0F - (dist2 - rmin2) * cscale;
+ setup->quad.coverage[QUAD_TOP_LEFT] = MIN2(cover, 1.0);
+ setup->quad.mask |= MASK_TOP_LEFT;
+ }
+
+ dx = (ix + 1.5) - x;
+ dy = (iy + 1.5) - y;
+ dist2 = dx * dx + dy * dy;
+ if (dist2 <= rmax2) {
+ cover = 1.0F - (dist2 - rmin2) * cscale;
+ setup->quad.coverage[QUAD_TOP_RIGHT] = MIN2(cover, 1.0);
+ setup->quad.mask |= MASK_TOP_RIGHT;
+ }
+
+ if (setup->quad.mask) {
+ setup->quad.x0 = ix;
+ setup->quad.y0 = iy;
+ quad_emit( setup->softpipe, &setup->quad );
+ }
+ }
+ }
+ }
+ else {
+ /* square points */
+ for (iy = iymin; iy <= iymax; iy += 2) {
+ for (ix = ixmin; ix <= ixmax; ix += 2) {
+ setup->quad.mask = 0xf;
+
+ if (ix + 0.5 < x - halfSize) {
+ /* fragment is past left edge of point, turn off left bits */
+ setup->quad.mask &= ~(MASK_BOTTOM_LEFT | MASK_TOP_LEFT);
+ }
+
+ if (ix + 1.5 > x + halfSize) {
+ /* past the right edge */
+ setup->quad.mask &= ~(MASK_BOTTOM_RIGHT | MASK_TOP_RIGHT);
+ }
+
+ if (iy + 0.5 < y - halfSize) {
+ /* below the bottom edge */
+ setup->quad.mask &= ~(MASK_BOTTOM_LEFT | MASK_BOTTOM_RIGHT);
+ }
+
+ if (iy + 1.5 > y + halfSize) {
+ /* above the top edge */
+ setup->quad.mask &= ~(MASK_TOP_LEFT | MASK_TOP_RIGHT);
+ }
+
+ if (setup->quad.mask) {
+ setup->quad.x0 = ix;
+ setup->quad.y0 = iy;
+ quad_emit( setup->softpipe, &setup->quad );
+ }
+ }
+ }
+ }
+ }
+}
+
+
+
+static void setup_begin( struct draw_stage *stage )
+{
+ struct setup_stage *setup = setup_stage(stage);
+
+ setup->quad.nr_attrs = setup->softpipe->nr_frag_attrs;
+
+ /*
+ * XXX this is where we might map() the renderbuffers to begin
+ * s/w rendering.
+ */
+}
+
+
+static void setup_end( struct draw_stage *stage )
+{
+ /*
+ * XXX this is where we might unmap() the renderbuffers after
+ * s/w rendering.
+ */
+}
+
+
+/**
+ * Create a new primitive setup/render stage.
+ */
+struct draw_stage *sp_draw_render_stage( struct softpipe_context *softpipe )
+{
+ struct setup_stage *setup = CALLOC_STRUCT(setup_stage);
+
+ setup->softpipe = softpipe;
+ setup->stage.draw = softpipe->draw;
+ setup->stage.begin = setup_begin;
+ setup->stage.point = setup_point;
+ setup->stage.line = setup_line;
+ setup->stage.tri = setup_tri;
+ setup->stage.end = setup_end;
+
+ setup->quad.coef = setup->coef;
+
+ return &setup->stage;
+}
diff --git a/src/mesa/pipe/softpipe/sp_prim_setup.h b/src/mesa/pipe/softpipe/sp_prim_setup.h
new file mode 100644
index 0000000000..e5abefcd49
--- /dev/null
+++ b/src/mesa/pipe/softpipe/sp_prim_setup.h
@@ -0,0 +1,122 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5
+ *
+ * Copyright (C) 1999-2005 Brian Paul 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, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL 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 SP_PRIM_SETUP_H
+#define SP_PRIM_SETUP_H
+
+
+/* Vertices are just an array of floats, with all the attributes
+ * packed. We currently assume a layout like:
+ *
+ * attr[0][0..3] - window position
+ * attr[1..n][0..3] - remaining attributes.
+ *
+ * Attributes are assumed to be 4 floats wide but are packed so that
+ * all the enabled attributes run contiguously.
+ */
+
+#include "glheader.h"
+#include "imports.h"
+#if 0
+#include "s_tri_public.h"
+#endif
+#include "s_context.h"
+
+
+extern struct draw_stage *sp_draw_render_stage( struct softpipe_context *softpipe );
+
+
+#if 0 /* UNUSED? */
+struct tri_context;
+struct fp_context;
+struct be_context;
+
+/* Note the rasterizer does not take a GLcontext argument. This is
+ * deliberate.
+ */
+struct tri_context *tri_create_context( GLcontext *ctx );
+
+void tri_destroy_context( struct tri_context *tri );
+
+void tri_set_fp_context( struct tri_context *tri,
+ struct fp_context *fp,
+ void (*fp_run)( struct fp_context *fp,
+ const struct fp_inputs *,
+ struct fp_outputs * ));
+
+
+void tri_set_be_context( struct tri_context *tri,
+ struct be_context *be,
+ void (*be_run)( struct be_context *be,
+ const struct fp_outputs * ));
+
+void tri_set_attribs( struct tri_context *tri,
+ const struct attr_info *info,
+ GLuint nr_attrib );
+
+void tri_set_backface( struct tri_context *tri,
+ GLfloat backface );
+
+void tri_set_scissor( struct tri_context *tri,
+ GLint x,
+ GLint y,
+ GLuint width,
+ GLuint height,
+ GLboolean enabled );
+
+void tri_set_stipple( struct tri_context *tri,
+ const GLuint *pattern,
+ GLboolean enabled );
+
+/* Unfilled triangles will be handled elsewhere (higher in the
+ * pipeline), as will things like stipple (lower in the pipeline).
+ */
+
+void tri_triangle( struct tri_context *tri,
+ const struct vertex *v0,
+ const struct vertex *v1,
+ const struct vertex *v2 );
+
+/* TODO: rasterize_line, rasterize_point??
+ * How will linestipple work?
+ */
+
+
+#ifdef SETUP_PRIVATE
+
+GLboolean tri_setup( struct tri_context *tri,
+ const struct vertex *v0,
+ const struct vertex *v1,
+ const struct vertex *v2 );
+
+void tri_rasterize( struct tri_context *tri );
+void tri_rasterize_spans( struct tri_context *tri );
+
+#endif
+
+
+#endif
+
+#endif /* SP_PRIM_SETUP_H */
diff --git a/src/mesa/pipe/softpipe/sp_quad.c b/src/mesa/pipe/softpipe/sp_quad.c
new file mode 100644
index 0000000000..0053b16e68
--- /dev/null
+++ b/src/mesa/pipe/softpipe/sp_quad.c
@@ -0,0 +1,71 @@
+
+
+#include "sp_context.h"
+
+
+
+void
+sp_build_quad_pipeline(struct softpipe_context *sp)
+{
+ /* build up the pipeline in reverse order... */
+
+ sp->quad.first = sp->quad.output;
+
+ if (sp->blend.colormask != 0xf) {
+ sp->quad.colormask->next = sp->quad.first;
+ sp->quad.first = sp->quad.colormask;
+ }
+
+ if (sp->blend.blend_enable) {
+ sp->quad.blend->next = sp->quad.first;
+ sp->quad.first = sp->quad.blend;
+ }
+
+ if (sp->framebuffer.num_cbufs == 1) {
+ /* the usual case: write to exactly one colorbuf */
+ sp->cbuf = sp->framebuffer.cbufs[0];
+ }
+ else {
+ /* insert bufloop stage */
+ sp->quad.bufloop->next = sp->quad.first;
+ sp->quad.first = sp->quad.bufloop;
+ }
+
+ if (sp->depth_test.occlusion_count) {
+ sp->quad.occlusion->next = sp->quad.first;
+ sp->quad.first = sp->quad.occlusion;
+ }
+
+ if (sp->setup.poly_smooth ||
+ sp->setup.line_smooth ||
+ sp->setup.point_smooth) {
+ sp->quad.coverage->next = sp->quad.first;
+ sp->quad.first = sp->quad.coverage;
+ }
+
+ if ( sp->stencil.front_enabled
+ || sp->stencil.front_enabled) {
+ sp->quad.stencil_test->next = sp->quad.first;
+ sp->quad.first = sp->quad.stencil_test;
+ }
+ else if (sp->depth_test.enabled) {
+ sp->quad.depth_test->next = sp->quad.first;
+ sp->quad.first = sp->quad.depth_test;
+ }
+
+ if (sp->alpha_test.enabled) {
+ sp->quad.alpha_test->next = sp->quad.first;
+ sp->quad.first = sp->quad.alpha_test;
+ }
+
+ /* XXX always enable shader? */
+ if (1) {
+ sp->quad.shade->next = sp->quad.first;
+ sp->quad.first = sp->quad.shade;
+ }
+
+ if (sp->setup.poly_stipple_enable) {
+ sp->quad.polygon_stipple->next = sp->quad.first;
+ sp->quad.first = sp->quad.polygon_stipple;
+ }
+}
diff --git a/src/mesa/pipe/softpipe/sp_quad.h b/src/mesa/pipe/softpipe/sp_quad.h
new file mode 100644
index 0000000000..2ee53bdecd
--- /dev/null
+++ b/src/mesa/pipe/softpipe/sp_quad.h
@@ -0,0 +1,65 @@
+/**************************************************************************
+ *
+ * Copyright 2007 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.
+ *
+ **************************************************************************/
+
+/* Authors: Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#ifndef SP_TILE_H
+#define SP_TILE_H
+
+
+struct softpipe_context;
+struct quad_header;
+
+
+struct quad_stage {
+ struct softpipe_context *softpipe;
+
+ struct quad_stage *next;
+
+ /** the stage action */
+ void (*run)(struct quad_stage *qs, struct quad_header *quad);
+};
+
+
+struct quad_stage *sp_quad_polygon_stipple_stage( struct softpipe_context *softpipe );
+struct quad_stage *sp_quad_shade_stage( struct softpipe_context *softpipe );
+struct quad_stage *sp_quad_alpha_test_stage( struct softpipe_context *softpipe );
+struct quad_stage *sp_quad_stencil_test_stage( struct softpipe_context *softpipe );
+struct quad_stage *sp_quad_depth_test_stage( struct softpipe_context *softpipe );
+struct quad_stage *sp_quad_occlusion_stage( struct softpipe_context *softpipe );
+struct quad_stage *sp_quad_coverage_stage( struct softpipe_context *softpipe );
+struct quad_stage *sp_quad_bufloop_stage( struct softpipe_context *softpipe );
+struct quad_stage *sp_quad_blend_stage( struct softpipe_context *softpipe );
+struct quad_stage *sp_quad_colormask_stage( struct softpipe_context *softpipe );
+struct quad_stage *sp_quad_output_stage( struct softpipe_context *softpipe );
+
+void sp_build_quad_pipeline(struct softpipe_context *sp);
+
+void sp_depth_test_quad(struct quad_stage *qs, struct quad_header *quad);
+
+#endif /* SP_TILE_H */
diff --git a/src/mesa/pipe/softpipe/sp_quad_alpha_test.c b/src/mesa/pipe/softpipe/sp_quad_alpha_test.c
new file mode 100644
index 0000000000..8c28a824be
--- /dev/null
+++ b/src/mesa/pipe/softpipe/sp_quad_alpha_test.c
@@ -0,0 +1,94 @@
+
+/**
+ * quad alpha test
+ */
+
+#include "glheader.h"
+#include "imports.h"
+#include "sp_context.h"
+#include "sp_headers.h"
+#include "sp_quad.h"
+#include "pipe/p_defines.h"
+
+
+static void
+alpha_test_quad(struct quad_stage *qs, struct quad_header *quad)
+{
+ struct softpipe_context *softpipe = qs->softpipe;
+ const GLfloat ref = softpipe->alpha_test.ref;
+ GLuint passMask = 0x0, j;
+
+ switch (softpipe->alpha_test.func) {
+ case PIPE_FUNC_NEVER:
+ quad->mask = 0x0;
+ break;
+ case PIPE_FUNC_LESS:
+ /*
+ * If mask were an array [4] we could do this SIMD-style:
+ * passMask = (quad->outputs.color[3] <= vec4(ref));
+ */
+ for (j = 0; j < QUAD_SIZE; j++) {
+ if (quad->outputs.color[3][j] < ref) {
+ passMask |= (1 << j);
+ }
+ }
+ break;
+ case PIPE_FUNC_EQUAL:
+ for (j = 0; j < QUAD_SIZE; j++) {
+ if (quad->outputs.color[3][j] == ref) {
+ passMask |= (1 << j);
+ }
+ }
+ break;
+ case PIPE_FUNC_LEQUAL:
+ for (j = 0; j < QUAD_SIZE; j++) {
+ if (quad->outputs.color[3][j] <= ref) {
+ passMask |= (1 << j);
+ }
+ }
+ break;
+ case PIPE_FUNC_GREATER:
+ for (j = 0; j < QUAD_SIZE; j++) {
+ if (quad->outputs.color[3][j] > ref) {
+ passMask |= (1 << j);
+ }
+ }
+ break;
+ case PIPE_FUNC_NOTEQUAL:
+ for (j = 0; j < QUAD_SIZE; j++) {
+ if (quad->outputs.color[3][j] != ref) {
+ passMask |= (1 << j);
+ }
+ }
+ break;
+ case PIPE_FUNC_GEQUAL:
+ for (j = 0; j < QUAD_SIZE; j++) {
+ if (quad->outputs.color[3][j] >= ref) {
+ passMask |= (1 << j);
+ }
+ }
+ break;
+ case PIPE_FUNC_ALWAYS:
+ passMask = MASK_ALL;
+ break;
+ default:
+ abort();
+ }
+
+ quad->mask &= passMask;
+
+ if (quad->mask)
+ qs->next->run(qs->next, quad);
+}
+
+
+struct quad_stage *
+sp_quad_alpha_test_stage( struct softpipe_context *softpipe )
+{
+ struct quad_stage *stage = CALLOC_STRUCT(quad_stage);
+
+ stage->softpipe = softpipe;
+ stage->run = alpha_test_quad;
+
+ return stage;
+}
diff --git a/src/mesa/pipe/softpipe/sp_quad_blend.c b/src/mesa/pipe/softpipe/sp_quad_blend.c
new file mode 100644
index 0000000000..3d097aea65
--- /dev/null
+++ b/src/mesa/pipe/softpipe/sp_quad_blend.c
@@ -0,0 +1,395 @@
+/**************************************************************************
+ *
+ * Copyright 2007 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.
+ *
+ **************************************************************************/
+
+/**
+ * quad blending
+ * \author Brian Paul
+ */
+
+#include "glheader.h"
+#include "imports.h"
+#include "macros.h"
+#include "pipe/p_defines.h"
+#include "sp_context.h"
+#include "sp_headers.h"
+#include "sp_surface.h"
+#include "sp_quad.h"
+
+
+#define VEC4_COPY(DST, SRC) \
+do { \
+ DST[0] = SRC[0]; \
+ DST[1] = SRC[1]; \
+ DST[2] = SRC[2]; \
+ DST[3] = SRC[3]; \
+} while(0)
+
+#define VEC4_SCALAR(DST, SRC) \
+do { \
+ DST[0] = SRC; \
+ DST[1] = SRC; \
+ DST[2] = SRC; \
+ DST[3] = SRC; \
+} while(0)
+
+#define VEC4_ADD(SUM, A, B) \
+do { \
+ SUM[0] = A[0] + B[0]; \
+ SUM[1] = A[1] + B[1]; \
+ SUM[2] = A[2] + B[2]; \
+ SUM[3] = A[3] + B[3]; \
+} while (0)
+
+#define VEC4_SUB(SUM, A, B) \
+do { \
+ SUM[0] = A[0] - B[0]; \
+ SUM[1] = A[1] - B[1]; \
+ SUM[2] = A[2] - B[2]; \
+ SUM[3] = A[3] - B[3]; \
+} while (0)
+
+#define VEC4_MUL(SUM, A, B) \
+do { \
+ SUM[0] = A[0] * B[0]; \
+ SUM[1] = A[1] * B[1]; \
+ SUM[2] = A[2] * B[2]; \
+ SUM[3] = A[3] * B[3]; \
+} while (0)
+
+#define VEC4_MIN(SUM, A, B) \
+do { \
+ SUM[0] = (A[0] < B[0]) ? A[0] : B[0]; \
+ SUM[1] = (A[1] < B[1]) ? A[1] : B[1]; \
+ SUM[2] = (A[2] < B[2]) ? A[2] : B[2]; \
+ SUM[3] = (A[3] < B[3]) ? A[3] : B[3]; \
+} while (0)
+
+#define VEC4_MAX(SUM, A, B) \
+do { \
+ SUM[0] = (A[0] > B[0]) ? A[0] : B[0]; \
+ SUM[1] = (A[1] > B[1]) ? A[1] : B[1]; \
+ SUM[2] = (A[2] > B[2]) ? A[2] : B[2]; \
+ SUM[3] = (A[3] > B[3]) ? A[3] : B[3]; \
+} while (0)
+
+
+
+static void
+blend_quad(struct quad_stage *qs, struct quad_header *quad)
+{
+ static const GLfloat zero[4] = { 0, 0, 0, 0 };
+ static const GLfloat one[4] = { 1, 1, 1, 1 };
+ struct softpipe_context *softpipe = qs->softpipe;
+ struct softpipe_surface *sps = softpipe_surface(softpipe->cbuf);
+ GLfloat source[4][QUAD_SIZE], dest[4][QUAD_SIZE];
+
+ /* get colors from framebuffer */
+ sps->read_quad_f_swz(sps, quad->x0, quad->y0, dest);
+
+ /*
+ * Compute src/first term RGB
+ */
+ switch (softpipe->blend.rgb_src_factor) {
+ case PIPE_BLENDFACTOR_ONE:
+ VEC4_COPY(source[0], quad->outputs.color[0]); /* R */
+ VEC4_COPY(source[1], quad->outputs.color[1]); /* G */
+ VEC4_COPY(source[2], quad->outputs.color[2]); /* B */
+ break;
+ case PIPE_BLENDFACTOR_SRC_COLOR:
+ VEC4_MUL(source[0], quad->outputs.color[0], quad->outputs.color[0]); /* R */
+ VEC4_MUL(source[1], quad->outputs.color[1], quad->outputs.color[1]); /* G */
+ VEC4_MUL(source[2], quad->outputs.color[2], quad->outputs.color[2]); /* B */
+ break;
+ case PIPE_BLENDFACTOR_SRC_ALPHA:
+ {
+ const GLfloat *alpha = quad->outputs.color[3];
+ VEC4_MUL(source[0], quad->outputs.color[0], alpha); /* R */
+ VEC4_MUL(source[1], quad->outputs.color[1], alpha); /* G */
+ VEC4_MUL(source[2], quad->outputs.color[2], alpha); /* B */
+ }
+ break;
+ case PIPE_BLENDFACTOR_DST_COLOR:
+ VEC4_MUL(source[0], quad->outputs.color[0], dest[0]); /* R */
+ VEC4_MUL(source[1], quad->outputs.color[1], dest[1]); /* G */
+ VEC4_MUL(source[2], quad->outputs.color[2], dest[2]); /* B */
+ break;
+ case PIPE_BLENDFACTOR_DST_ALPHA:
+ {
+ const GLfloat *alpha = dest[3];
+ VEC4_MUL(source[0], quad->outputs.color[0], alpha); /* R */
+ VEC4_MUL(source[1], quad->outputs.color[1], alpha); /* G */
+ VEC4_MUL(source[2], quad->outputs.color[2], alpha); /* B */
+ }
+ break;
+ case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
+ assert(0); /* to do */
+ break;
+ case PIPE_BLENDFACTOR_CONST_COLOR:
+ {
+ GLfloat comp[4];
+ VEC4_SCALAR(comp, softpipe->blend_color.color[0]); /* R */
+ VEC4_MUL(source[0], quad->outputs.color[0], comp); /* R */
+ VEC4_SCALAR(comp, softpipe->blend_color.color[1]); /* G */
+ VEC4_MUL(source[1], quad->outputs.color[1], comp); /* G */
+ VEC4_SCALAR(comp, softpipe->blend_color.color[2]); /* B */
+ VEC4_MUL(source[2], quad->outputs.color[2], comp); /* B */
+ }
+ break;
+ case PIPE_BLENDFACTOR_CONST_ALPHA:
+ {
+ GLfloat alpha[4];
+ VEC4_SCALAR(alpha, softpipe->blend_color.color[3]);
+ VEC4_MUL(source[0], quad->outputs.color[0], alpha); /* R */
+ VEC4_MUL(source[1], quad->outputs.color[1], alpha); /* G */
+ VEC4_MUL(source[2], quad->outputs.color[2], alpha); /* B */
+ }
+ break;
+ case PIPE_BLENDFACTOR_SRC1_COLOR:
+ assert(0); /* to do */
+ break;
+ case PIPE_BLENDFACTOR_SRC1_ALPHA:
+ assert(0); /* to do */
+ break;
+ case PIPE_BLENDFACTOR_ZERO:
+ VEC4_COPY(source[0], zero); /* R */
+ VEC4_COPY(source[1], zero); /* G */
+ VEC4_COPY(source[2], zero); /* B */
+ break;
+ case PIPE_BLENDFACTOR_INV_SRC_COLOR:
+ {
+ GLfloat inv_comp[4];
+ VEC4_SUB(inv_comp, one, quad->outputs.color[0]); /* R */
+ VEC4_MUL(source[0], quad->outputs.color[0], inv_comp); /* R */
+ VEC4_SUB(inv_comp, one, quad->outputs.color[1]); /* G */
+ VEC4_MUL(source[1], quad->outputs.color[1], inv_comp); /* G */
+ VEC4_SUB(inv_comp, one, quad->outputs.color[2]); /* B */
+ VEC4_MUL(source[2], quad->outputs.color[2], inv_comp); /* B */
+ }
+ break;
+ case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
+ {
+ GLfloat inv_alpha[4];
+ VEC4_SUB(inv_alpha, one, quad->outputs.color[3]);
+ VEC4_MUL(source[0], quad->outputs.color[0], inv_alpha); /* R */
+ VEC4_MUL(source[1], quad->outputs.color[1], inv_alpha); /* G */
+ VEC4_MUL(source[2], quad->outputs.color[2], inv_alpha); /* B */
+ }
+ break;
+ case PIPE_BLENDFACTOR_INV_DST_ALPHA:
+ {
+ GLfloat inv_alpha[4];
+ VEC4_SUB(inv_alpha, one, dest[3]);
+ VEC4_MUL(source[0], quad->outputs.color[0], inv_alpha); /* R */
+ VEC4_MUL(source[1], quad->outputs.color[1], inv_alpha); /* G */
+ VEC4_MUL(source[2], quad->outputs.color[2], inv_alpha); /* B */
+ }
+ break;
+ case PIPE_BLENDFACTOR_INV_DST_COLOR:
+ {
+ GLfloat inv_comp[4];
+ VEC4_SUB(inv_comp, one, dest[0]); /* R */
+ VEC4_MUL(source[0], quad->outputs.color[0], inv_comp); /* R */
+ VEC4_SUB(inv_comp, one, dest[1]); /* G */
+ VEC4_MUL(source[1], quad->outputs.color[1], inv_comp); /* G */
+ VEC4_SUB(inv_comp, one, dest[2]); /* B */
+ VEC4_MUL(source[2], quad->outputs.color[2], inv_comp); /* B */
+ }
+ break;
+ case PIPE_BLENDFACTOR_INV_CONST_COLOR:
+ {
+ GLfloat inv_comp[4];
+ /* R */
+ VEC4_SCALAR(inv_comp, 1.0 - softpipe->blend_color.color[0]);
+ VEC4_MUL(source[0], quad->outputs.color[0], inv_comp);
+ /* G */
+ VEC4_SCALAR(inv_comp, 1.0 - softpipe->blend_color.color[1]);
+ VEC4_MUL(source[1], quad->outputs.color[1], inv_comp);
+ /* B */
+ VEC4_SCALAR(inv_comp, 1.0 - softpipe->blend_color.color[2]);
+ VEC4_MUL(source[2], quad->outputs.color[2], inv_comp);
+ }
+ break;
+ case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
+ {
+ GLfloat alpha[4], inv_alpha[4];
+ VEC4_SCALAR(alpha, 1.0 - softpipe->blend_color.color[3]);
+ VEC4_MUL(source[0], quad->outputs.color[0], inv_alpha); /* R */
+ VEC4_MUL(source[1], quad->outputs.color[1], inv_alpha); /* G */
+ VEC4_MUL(source[2], quad->outputs.color[2], inv_alpha); /* B */
+ }
+ break;
+ case PIPE_BLENDFACTOR_INV_SRC1_COLOR:
+ assert(0); /* to do */
+ break;
+ case PIPE_BLENDFACTOR_INV_SRC1_ALPHA:
+ assert(0); /* to do */
+ break;
+ default:
+ abort();
+ }
+
+ /*
+ * Compute src/first term A
+ */
+ switch (softpipe->blend.alpha_src_factor) {
+ case PIPE_BLENDFACTOR_ONE:
+ VEC4_COPY(source[3], quad->outputs.color[3]); /* A */
+ break;
+ case PIPE_BLENDFACTOR_SRC_ALPHA:
+ {
+ const GLfloat *alpha = quad->outputs.color[3];
+ VEC4_MUL(source[3], quad->outputs.color[3], alpha); /* A */
+ }
+ break;
+ case PIPE_BLENDFACTOR_ZERO:
+ VEC4_COPY(source[3], zero); /* A */
+ break;
+ /* XXX fill in remaining terms */
+ default:
+ abort();
+ }
+
+
+ /*
+ * Compute dest/second term RGB
+ */
+ switch (softpipe->blend.rgb_dst_factor) {
+ case PIPE_BLENDFACTOR_ONE:
+ /* dest = dest * 1 NO-OP, leave dest as-is */
+ break;
+ case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
+ {
+ GLfloat one_minus_alpha[QUAD_SIZE];
+ VEC4_SUB(one_minus_alpha, one, quad->outputs.color[3]);
+ VEC4_MUL(dest[0], dest[0], one_minus_alpha); /* R */
+ VEC4_MUL(dest[1], dest[1], one_minus_alpha); /* G */
+ VEC4_MUL(dest[2], dest[2], one_minus_alpha); /* B */
+ }
+ break;
+ case PIPE_BLENDFACTOR_ZERO:
+ VEC4_COPY(dest[0], zero); /* R */
+ VEC4_COPY(dest[1], zero); /* G */
+ VEC4_COPY(dest[2], zero); /* B */
+ break;
+ /* XXX fill in remaining terms */
+ default:
+ abort();
+ }
+
+ /*
+ * Compute dest/second term A
+ */
+ switch (softpipe->blend.alpha_dst_factor) {
+ case PIPE_BLENDFACTOR_ONE:
+ /* dest = dest * 1 NO-OP, leave dest as-is */
+ break;
+ case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
+ {
+ GLfloat one_minus_alpha[QUAD_SIZE];
+ VEC4_SUB(one_minus_alpha, one, quad->outputs.color[3]);
+ VEC4_MUL(dest[3], dest[3], one_minus_alpha); /* A */
+ }
+ break;
+ case PIPE_BLENDFACTOR_ZERO:
+ VEC4_COPY(dest[3], zero); /* A */
+ break;
+ /* XXX fill in remaining terms */
+ default:
+ abort();
+ }
+
+ /*
+ * Combine RGB terms
+ */
+ switch (softpipe->blend.rgb_func) {
+ case PIPE_BLEND_ADD:
+ VEC4_ADD(quad->outputs.color[0], source[0], dest[0]); /* R */
+ VEC4_ADD(quad->outputs.color[1], source[1], dest[1]); /* G */
+ VEC4_ADD(quad->outputs.color[2], source[2], dest[2]); /* B */
+ break;
+ case PIPE_BLEND_SUBTRACT:
+ VEC4_SUB(quad->outputs.color[0], source[0], dest[0]); /* R */
+ VEC4_SUB(quad->outputs.color[1], source[1], dest[1]); /* G */
+ VEC4_SUB(quad->outputs.color[2], source[2], dest[2]); /* B */
+ break;
+ case PIPE_BLEND_REVERSE_SUBTRACT:
+ VEC4_SUB(quad->outputs.color[0], dest[0], source[0]); /* R */
+ VEC4_SUB(quad->outputs.color[1], dest[1], source[1]); /* G */
+ VEC4_SUB(quad->outputs.color[2], dest[2], source[2]); /* B */
+ break;
+ case PIPE_BLEND_MIN:
+ VEC4_MIN(quad->outputs.color[0], source[0], dest[0]); /* R */
+ VEC4_MIN(quad->outputs.color[1], source[1], dest[1]); /* G */
+ VEC4_MIN(quad->outputs.color[2], source[2], dest[2]); /* B */
+ break;
+ case PIPE_BLEND_MAX:
+ VEC4_MAX(quad->outputs.color[0], source[0], dest[0]); /* R */
+ VEC4_MAX(quad->outputs.color[1], source[1], dest[1]); /* G */
+ VEC4_MAX(quad->outputs.color[2], source[2], dest[2]); /* B */
+ break;
+ default:
+ abort();
+ }
+
+ /*
+ * Combine A terms
+ */
+ switch (softpipe->blend.alpha_func) {
+ case PIPE_BLEND_ADD:
+ VEC4_ADD(quad->outputs.color[3], source[3], dest[3]); /* A */
+ break;
+ case PIPE_BLEND_SUBTRACT:
+ VEC4_SUB(quad->outputs.color[3], source[3], dest[3]); /* A */
+ break;
+ case PIPE_BLEND_REVERSE_SUBTRACT:
+ VEC4_SUB(quad->outputs.color[3], dest[3], source[3]); /* A */
+ break;
+ case PIPE_BLEND_MIN:
+ VEC4_MIN(quad->outputs.color[3], source[3], dest[3]); /* A */
+ break;
+ case PIPE_BLEND_MAX:
+ VEC4_MAX(quad->outputs.color[3], source[3], dest[3]); /* A */
+ default:
+ abort();
+ }
+
+ /* pass blended quad to next stage */
+ qs->next->run(qs->next, quad);
+}
+
+
+
+
+struct quad_stage *sp_quad_blend_stage( struct softpipe_context *softpipe )
+{
+ struct quad_stage *stage = CALLOC_STRUCT(quad_stage);
+
+ stage->softpipe = softpipe;
+ stage->run = blend_quad;
+
+ return stage;
+}
diff --git a/src/mesa/pipe/softpipe/sp_quad_bufloop.c b/src/mesa/pipe/softpipe/sp_quad_bufloop.c
new file mode 100644
index 0000000000..be32d02a46
--- /dev/null
+++ b/src/mesa/pipe/softpipe/sp_quad_bufloop.c
@@ -0,0 +1,62 @@
+
+
+#include "main/glheader.h"
+#include "main/imports.h"
+#include "sp_context.h"
+#include "sp_headers.h"
+#include "sp_surface.h"
+#include "sp_quad.h"
+
+
+/**
+ * Loop over colorbuffers, passing quad to next stage each time.
+ */
+static void
+cbuf_loop_quad(struct quad_stage *qs, struct quad_header *quad)
+{
+ struct softpipe_context *softpipe = qs->softpipe;
+ GLfloat tmp[4][QUAD_SIZE];
+ GLuint i;
+
+ assert(sizeof(quad->outputs.color) == sizeof(tmp));
+ assert(softpipe->framebuffer.num_cbufs <= PIPE_MAX_COLOR_BUFS);
+
+ /* make copy of original colors since they can get modified
+ * by blending and masking.
+ * XXX we won't have to do this if the fragment program actually emits
+ * N separate colors and we're drawing to N color buffers (MRT).
+ * But if we emitted one color and glDrawBuffer(GL_FRONT_AND_BACK) is
+ * in effect, we need to save/restore colors like this.
+ */
+ memcpy(tmp, quad->outputs.color, sizeof(tmp));
+
+ for (i = 0; i < softpipe->framebuffer.num_cbufs; i++) {
+ /* set current cbuffer */
+ softpipe->cbuf = softpipe->framebuffer.cbufs[i];
+
+ /* pass blended quad to next stage */
+ qs->next->run(qs->next, quad);
+
+ /* restore quad's colors for next buffer */
+ memcpy(quad->outputs.color, tmp, sizeof(tmp));
+ }
+
+ softpipe->cbuf = NULL; /* prevent accidental use */
+}
+
+
+/**
+ * Create the colorbuffer loop stage.
+ * This is used to implement multiple render targets and GL_FRONT_AND_BACK
+ * rendering.
+ */
+struct quad_stage *sp_quad_bufloop_stage( struct softpipe_context *softpipe )
+{
+ struct quad_stage *stage = CALLOC_STRUCT(quad_stage);
+
+ stage->softpipe = softpipe;
+ stage->run = cbuf_loop_quad;
+
+ return stage;
+}
+
diff --git a/src/mesa/pipe/softpipe/sp_quad_colormask.c b/src/mesa/pipe/softpipe/sp_quad_colormask.c
new file mode 100644
index 0000000000..fff6efa8f6
--- /dev/null
+++ b/src/mesa/pipe/softpipe/sp_quad_colormask.c
@@ -0,0 +1,84 @@
+/**************************************************************************
+ *
+ * Copyright 2007 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.
+ *
+ **************************************************************************/
+
+/**
+ * \brief quad colormask stage
+ * \author Brian Paul
+ */
+
+#include "main/glheader.h"
+#include "main/imports.h"
+#include "main/macros.h"
+#include "pipe/p_defines.h"
+#include "sp_context.h"
+#include "sp_headers.h"
+#include "sp_surface.h"
+#include "sp_quad.h"
+
+
+
+static void
+colormask_quad(struct quad_stage *qs, struct quad_header *quad)
+{
+ struct softpipe_context *softpipe = qs->softpipe;
+ struct softpipe_surface *sps = softpipe_surface(softpipe->cbuf);
+ GLfloat dest[4][QUAD_SIZE];
+
+ sps->read_quad_f_swz(sps, quad->x0, quad->y0, dest);
+
+ /* R */
+ if (!(softpipe->blend.colormask & PIPE_MASK_R))
+ COPY_4FV(quad->outputs.color[0], dest[0]);
+
+ /* G */
+ if (!(softpipe->blend.colormask & PIPE_MASK_G))
+ COPY_4FV(quad->outputs.color[1], dest[1]);
+
+ /* B */
+ if (!(softpipe->blend.colormask & PIPE_MASK_B))
+ COPY_4FV(quad->outputs.color[2], dest[2]);
+
+ /* A */
+ if (!(softpipe->blend.colormask & PIPE_MASK_A))
+ COPY_4FV(quad->outputs.color[3], dest[3]);
+
+ /* pass quad to next stage */
+ qs->next->run(qs->next, quad);
+}
+
+
+
+
+struct quad_stage *sp_quad_colormask_stage( struct softpipe_context *softpipe )
+{
+ struct quad_stage *stage = CALLOC_STRUCT(quad_stage);
+
+ stage->softpipe = softpipe;
+ stage->run = colormask_quad;
+
+ return stage;
+}
diff --git a/src/mesa/pipe/softpipe/sp_quad_coverage.c b/src/mesa/pipe/softpipe/sp_quad_coverage.c
new file mode 100644
index 0000000000..cdd8890c7f
--- /dev/null
+++ b/src/mesa/pipe/softpipe/sp_quad_coverage.c
@@ -0,0 +1,74 @@
+/**************************************************************************
+ *
+ * Copyright 2007 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.
+ *
+ **************************************************************************/
+
+
+/**
+ * \brief Apply AA coverage to quad alpha valus
+ * \author Brian Paul
+ */
+
+
+#include "main/glheader.h"
+#include "main/macros.h"
+#include "pipe/p_defines.h"
+#include "sp_context.h"
+#include "sp_headers.h"
+#include "sp_quad.h"
+
+
+/**
+ * Multiply quad's alpha values by the fragment coverage.
+ */
+static void
+coverage_quad(struct quad_stage *qs, struct quad_header *quad)
+{
+ struct softpipe_context *softpipe = qs->softpipe;
+
+ if ((softpipe->setup.poly_smooth && quad->prim == PRIM_TRI) ||
+ (softpipe->setup.line_smooth && quad->prim == PRIM_LINE) ||
+ (softpipe->setup.point_smooth && quad->prim == PRIM_POINT)) {
+ GLuint j;
+ for (j = 0; j < QUAD_SIZE; j++) {
+ assert(quad->coverage[j] >= 0.0);
+ assert(quad->coverage[j] <= 1.0);
+ quad->outputs.color[3][j] *= quad->coverage[j];
+ }
+ }
+
+ qs->next->run(qs->next, quad);
+}
+
+
+struct quad_stage *sp_quad_coverage_stage( struct softpipe_context *softpipe )
+{
+ struct quad_stage *stage = CALLOC_STRUCT(quad_stage);
+
+ stage->softpipe = softpipe;
+ stage->run = coverage_quad;
+
+ return stage;
+}
diff --git a/src/mesa/pipe/softpipe/sp_quad_depth_test.c b/src/mesa/pipe/softpipe/sp_quad_depth_test.c
new file mode 100644
index 0000000000..d47c4c42b8
--- /dev/null
+++ b/src/mesa/pipe/softpipe/sp_quad_depth_test.c
@@ -0,0 +1,167 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5
+ *
+ * Copyright (C) 1999-2005 Brian Paul 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, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL 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.
+ */
+
+/**
+ * \brief Quad depth testing
+ */
+
+#include "main/glheader.h"
+#include "main/imports.h"
+#include "pipe/p_defines.h"
+#include "sp_context.h"
+#include "sp_headers.h"
+#include "sp_surface.h"
+#include "sp_quad.h"
+
+
+/**
+ * Do depth testing for a quad.
+ * Not static since it's used by the stencil code.
+ */
+void
+sp_depth_test_quad(struct quad_stage *qs, struct quad_header *quad)
+{
+ struct softpipe_context *softpipe = qs->softpipe;
+ struct softpipe_surface *sps = softpipe_surface(softpipe->framebuffer.zbuf);
+ GLuint bzzzz[QUAD_SIZE]; /**< Z values fetched from depth buffer */
+ GLuint qzzzz[QUAD_SIZE]; /**< Z values from the quad */
+ GLuint zmask = 0;
+ GLuint j;
+ GLfloat scale;
+
+ assert(sps); /* shouldn't get here if there's no zbuffer */
+
+ /*
+ * To increase efficiency, we should probably have multiple versions
+ * of this function that are specifically for Z16, Z32 and FP Z buffers.
+ * Try to effectively do that with codegen...
+ */
+ if (sps->surface.format == PIPE_FORMAT_U_Z16)
+ scale = 65535.0;
+ else
+ assert(0); /* XXX fix this someday */
+
+ /*
+ * Convert quad's float depth values to int depth values.
+ * If the Z buffer stores integer values, we _have_ to do the depth
+ * compares with integers (not floats). Otherwise, the float->int->float
+ * conversion of Z values (which isn't an identity function) will cause
+ * Z-fighting errors.
+ */
+ for (j = 0; j < QUAD_SIZE; j++) {
+ qzzzz[j] = (GLuint) (quad->outputs.depth[j] * scale);
+ }
+
+ /* get zquad from zbuffer */
+ sps->read_quad_z(sps, quad->x0, quad->y0, bzzzz);
+
+ switch (softpipe->depth_test.func) {
+ case PIPE_FUNC_NEVER:
+ /* zmask = 0 */
+ break;
+ case PIPE_FUNC_LESS:
+ /* Note this is pretty much a single sse or cell instruction.
+ * Like this: quad->mask &= (quad->outputs.depth < zzzz);
+ */
+ for (j = 0; j < QUAD_SIZE; j++) {
+ if (qzzzz[j] < bzzzz[j])
+ zmask |= 1 << j;
+ }
+ break;
+ case PIPE_FUNC_EQUAL:
+ for (j = 0; j < QUAD_SIZE; j++) {
+ if (qzzzz[j] == bzzzz[j])
+ zmask |= 1 << j;
+ }
+ break;
+ case PIPE_FUNC_LEQUAL:
+ for (j = 0; j < QUAD_SIZE; j++) {
+ if (qzzzz[j] <= bzzzz[j])
+ zmask |= (1 << j);
+ }
+ break;
+ case PIPE_FUNC_GREATER:
+ for (j = 0; j < QUAD_SIZE; j++) {
+ if (qzzzz[j] > bzzzz[j])
+ zmask |= (1 << j);
+ }
+ break;
+ case PIPE_FUNC_NOTEQUAL:
+ for (j = 0; j < QUAD_SIZE; j++) {
+ if (qzzzz[j] != bzzzz[j])
+ zmask |= (1 << j);
+ }
+ break;
+ case PIPE_FUNC_GEQUAL:
+ for (j = 0; j < QUAD_SIZE; j++) {
+ if (qzzzz[j] >= bzzzz[j])
+ zmask |= (1 << j);
+ }
+ break;
+ case PIPE_FUNC_ALWAYS:
+ zmask = MASK_ALL;
+ break;
+ default:
+ abort();
+ }
+
+ quad->mask &= zmask;
+
+ if (softpipe->depth_test.writemask) {
+
+ /* This is also efficient with sse / spe instructions:
+ */
+ for (j = 0; j < QUAD_SIZE; j++) {
+ if (quad->mask & (1 << j)) {
+ bzzzz[j] = qzzzz[j];
+ }
+ }
+
+ /* write updated zquad to zbuffer */
+ sps->write_quad_z(sps, quad->x0, quad->y0, bzzzz);
+ }
+}
+
+
+static void
+depth_test_quad(struct quad_stage *qs, struct quad_header *quad)
+{
+ sp_depth_test_quad(qs, quad);
+
+ if (quad->mask)
+ qs->next->run(qs->next, quad);
+}
+
+
+
+
+struct quad_stage *sp_quad_depth_test_stage( struct softpipe_context *softpipe )
+{
+ struct quad_stage *stage = CALLOC_STRUCT(quad_stage);
+
+ stage->softpipe = softpipe;
+ stage->run = depth_test_quad;
+
+ return stage;
+}
diff --git a/src/mesa/pipe/softpipe/sp_quad_fs.c b/src/mesa/pipe/softpipe/sp_quad_fs.c
new file mode 100644
index 0000000000..7b1c90cba6
--- /dev/null
+++ b/src/mesa/pipe/softpipe/sp_quad_fs.c
@@ -0,0 +1,218 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5
+ *
+ * Copyright (C) 1999-2005 Brian Paul 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, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL 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.
+ */
+
+/* Vertices are just an array of floats, with all the attributes
+ * packed. We currently assume a layout like:
+ *
+ * attr[0][0..3] - window position
+ * attr[1..n][0..3] - remaining attributes.
+ *
+ * Attributes are assumed to be 4 floats wide but are packed so that
+ * all the enabled attributes run contiguously.
+ */
+
+#include "glheader.h"
+#include "imports.h"
+#include "sp_context.h"
+#include "sp_headers.h"
+#include "sp_quad.h"
+
+struct exec_machine {
+ const struct setup_coefficient *coef; /**< will point to quad->coef */
+
+ GLfloat attr[FRAG_ATTRIB_MAX][4][QUAD_SIZE];
+};
+
+
+/**
+ * Compute quad's attributes values, as constants (GL_FLAT shading).
+ */
+static INLINE void cinterp( struct exec_machine *exec,
+ GLuint attrib,
+ GLuint i )
+{
+ GLuint j;
+
+ for (j = 0; j < QUAD_SIZE; j++) {
+ exec->attr[attrib][i][j] = exec->coef[attrib].a0[i];
+ }
+}
+
+
+/**
+ * Compute quad's attribute values by linear interpolation.
+ *
+ * Push into the fp:
+ *
+ * INPUT[attr] = MAD COEF_A0[attr], COEF_DADX[attr], INPUT_WPOS.xxxx
+ * INPUT[attr] = MAD INPUT[attr], COEF_DADY[attr], INPUT_WPOS.yyyy
+ */
+static INLINE void linterp( struct exec_machine *exec,
+ GLuint attrib,
+ GLuint i )
+{
+ GLuint j;
+
+ for (j = 0; j < QUAD_SIZE; j++) {
+ const GLfloat x = exec->attr[FRAG_ATTRIB_WPOS][0][j];
+ const GLfloat y = exec->attr[FRAG_ATTRIB_WPOS][1][j];
+ exec->attr[attrib][i][j] = (exec->coef[attrib].a0[i] +
+ exec->coef[attrib].dadx[i] * x +
+ exec->coef[attrib].dady[i] * y);
+ }
+}
+
+
+/**
+ * Compute quad's attribute values by linear interpolation with
+ * perspective correction.
+ *
+ * Push into the fp:
+ *
+ * INPUT[attr] = MAD COEF_A0[attr], COEF_DADX[attr], INPUT_WPOS.xxxx
+ * INPUT[attr] = MAD INPUT[attr], COEF_DADY[attr], INPUT_WPOS.yyyy
+ * INPUT[attr] = MUL INPUT[attr], INPUT_WPOS.wwww
+ *
+ * (Or should that be 1/w ???)
+ */
+static INLINE void pinterp( struct exec_machine *exec,
+ GLuint attrib,
+ GLuint i )
+{
+ GLuint j;
+
+ for (j = 0; j < QUAD_SIZE; j++) {
+ const GLfloat x = exec->attr[FRAG_ATTRIB_WPOS][0][j];
+ const GLfloat y = exec->attr[FRAG_ATTRIB_WPOS][1][j];
+ const GLfloat invW = exec->attr[FRAG_ATTRIB_WPOS][3][j];
+ exec->attr[attrib][i][j] = ((exec->coef[attrib].a0[i] +
+ exec->coef[attrib].dadx[i] * x +
+ exec->coef[attrib].dady[i] * y) * invW);
+ }
+}
+
+
+
+/* This should be done by the fragment shader execution unit (code
+ * generated from the decl instructions). Do it here for now.
+ */
+static void
+shade_quad( struct quad_stage *qs, struct quad_header *quad )
+{
+ struct softpipe_context *softpipe = qs->softpipe;
+ struct exec_machine exec;
+ GLfloat fx = quad->x0;
+ GLfloat fy = quad->y0;
+ GLuint i, j;
+ GLboolean need_z = softpipe->depth_test.enabled; /* XXX hack */
+
+ exec.coef = quad->coef;
+
+ /* Position:
+ */
+ exec.attr[FRAG_ATTRIB_WPOS][0][0] = fx;
+ exec.attr[FRAG_ATTRIB_WPOS][0][1] = fx + 1.0;
+ exec.attr[FRAG_ATTRIB_WPOS][0][2] = fx;
+ exec.attr[FRAG_ATTRIB_WPOS][0][3] = fx + 1.0;
+
+ exec.attr[FRAG_ATTRIB_WPOS][1][0] = fy;
+ exec.attr[FRAG_ATTRIB_WPOS][1][1] = fy;
+ exec.attr[FRAG_ATTRIB_WPOS][1][2] = fy + 1.0;
+ exec.attr[FRAG_ATTRIB_WPOS][1][3] = fy + 1.0;
+
+ /* Z and W are done by linear interpolation:
+ * XXX we'll probably have to use integers for Z
+ */
+ if (/*softpipe->*/need_z) {
+ linterp(&exec, 0, 2); /* attr[0].z */
+ }
+
+ if (softpipe->need_w) {
+ linterp(&exec, 0, 3); /* attr[0].w */
+// invert(&exec, 0, 3);
+ }
+
+ /* Interpolate all the remaining attributes. This will get pushed
+ * into the fragment program's responsibilities at some point.
+ */
+ for (i = 1; i < quad->nr_attrs; i++) {
+#if 1
+ for (j = 0; j < NUM_CHANNELS; j++)
+ linterp(&exec, i, j);
+#else
+ switch (quad->interp[i]) {
+ case INTERP_CONSTANT:
+ for (j = 0; j < NUM_CHANNELS; j++)
+ cinterp(&exec, i, j);
+ break;
+
+ case INTERP_LINEAR:
+ for (j = 0; j < NUM_CHANNELS; j++)
+ linterp(&exec, i, j);
+ break;
+
+ case INTERP_PERSPECTIVE:
+ for (j = 0; j < NUM_CHANNELS; j++)
+ pinterp(&exec, i, j);
+ break;
+ }
+#endif
+ }
+
+#if 0
+ softpipe->run_fs( tri->fp, quad, &tri->outputs );
+#else
+ {
+ GLuint attr = softpipe->fp_attr_to_slot[FRAG_ATTRIB_COL0];
+ assert(attr);
+
+ memcpy(quad->outputs.color,
+ exec.attr[attr],
+ sizeof(quad->outputs.color));
+
+ if (need_z) {
+ quad->outputs.depth[0] = exec.attr[0][2][0];
+ quad->outputs.depth[1] = exec.attr[0][2][1];
+ quad->outputs.depth[2] = exec.attr[0][2][2];
+ quad->outputs.depth[3] = exec.attr[0][2][3];
+ }
+ }
+#endif
+
+ /* shader may cull fragments */
+ if (quad->mask)
+ qs->next->run(qs->next, quad);
+}
+
+
+
+struct quad_stage *sp_quad_shade_stage( struct softpipe_context *softpipe )
+{
+ struct quad_stage *stage = CALLOC_STRUCT(quad_stage);
+
+ stage->softpipe = softpipe;
+ stage->run = shade_quad;
+
+ return stage;
+}
diff --git a/src/mesa/pipe/softpipe/sp_quad_occlusion.c b/src/mesa/pipe/softpipe/sp_quad_occlusion.c
new file mode 100644
index 0000000000..843c462d48
--- /dev/null
+++ b/src/mesa/pipe/softpipe/sp_quad_occlusion.c
@@ -0,0 +1,67 @@
+/**************************************************************************
+ *
+ * Copyright 2007 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.
+ *
+ **************************************************************************/
+
+
+/**
+ * \brief Quad occlusion counter stage
+ * \author Brian Paul
+ */
+
+
+#include "main/glheader.h"
+#include "main/imports.h"
+#include "pipe/p_defines.h"
+#include "sp_context.h"
+#include "sp_headers.h"
+#include "sp_surface.h"
+#include "sp_quad.h"
+
+
+static void
+occlusion_count_quad(struct quad_stage *qs, struct quad_header *quad)
+{
+ struct softpipe_context *softpipe = qs->softpipe;
+
+ softpipe->occlusion_counter += (quad->mask ) & 1;
+ softpipe->occlusion_counter += (quad->mask >> 1) & 1;
+ softpipe->occlusion_counter += (quad->mask >> 2) & 1;
+ softpipe->occlusion_counter += (quad->mask >> 3) & 1;
+
+ if (quad->mask)
+ qs->next->run(qs->next, quad);
+}
+
+
+struct quad_stage *sp_quad_occlusion_stage( struct softpipe_context *softpipe )
+{
+ struct quad_stage *stage = CALLOC_STRUCT(quad_stage);
+
+ stage->softpipe = softpipe;
+ stage->run = occlusion_count_quad;
+
+ return stage;
+}
diff --git a/src/mesa/pipe/softpipe/sp_quad_output.c b/src/mesa/pipe/softpipe/sp_quad_output.c
new file mode 100644
index 0000000000..12ab1eca1c
--- /dev/null
+++ b/src/mesa/pipe/softpipe/sp_quad_output.c
@@ -0,0 +1,95 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5
+ *
+ * Copyright (C) 1999-2005 Brian Paul 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, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL 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.
+ */
+
+/* Vertices are just an array of floats, with all the attributes
+ * packed. We currently assume a layout like:
+ *
+ * attr[0][0..3] - window position
+ * attr[1..n][0..3] - remaining attributes.
+ *
+ * Attributes are assumed to be 4 floats wide but are packed so that
+ * all the enabled attributes run contiguously.
+ */
+
+#include "glheader.h"
+#include "imports.h"
+#include "sp_context.h"
+#include "sp_headers.h"
+#include "sp_surface.h"
+#include "sp_quad.h"
+
+
+static void mask_copy( GLfloat (*dest)[4],
+ GLfloat (*src)[4],
+ GLuint mask )
+{
+ GLuint i, j;
+
+ for (i = 0; i < 4; i++) {
+ if (mask & (1<<i)) {
+ for (j = 0; j < 4; j++) {
+ dest[j][i] = src[j][i];
+ }
+ }
+ }
+}
+
+
+/**
+ * Write quad to framebuffer, taking mask into account.
+ *
+ * Note that surfaces support only full quad reads and writes.
+ */
+static void
+output_quad(struct quad_stage *qs, struct quad_header *quad)
+{
+ struct softpipe_context *softpipe = qs->softpipe;
+ struct softpipe_surface *sps = softpipe_surface(softpipe->cbuf);
+
+ if (quad->mask != MASK_ALL) {
+ GLfloat tmp[4][QUAD_SIZE];
+
+ /* XXX probably add a masked-write function someday */
+
+ sps->read_quad_f_swz(sps, quad->x0, quad->y0, tmp);
+
+ mask_copy( tmp, quad->outputs.color, quad->mask );
+
+ sps->write_quad_f_swz(sps, quad->x0, quad->y0, tmp);
+ }
+ else if (quad->mask) {
+ sps->write_quad_f_swz(sps, quad->x0, quad->y0, quad->outputs.color);
+ }
+}
+
+
+struct quad_stage *sp_quad_output_stage( struct softpipe_context *softpipe )
+{
+ struct quad_stage *stage = CALLOC_STRUCT(quad_stage);
+
+ stage->softpipe = softpipe;
+ stage->run = output_quad;
+
+ return stage;
+}
diff --git a/src/mesa/pipe/softpipe/sp_quad_stencil.c b/src/mesa/pipe/softpipe/sp_quad_stencil.c
new file mode 100644
index 0000000000..0b37474c1a
--- /dev/null
+++ b/src/mesa/pipe/softpipe/sp_quad_stencil.c
@@ -0,0 +1,288 @@
+
+/**
+ * \brief Quad stencil testing
+ */
+
+
+#include "main/glheader.h"
+#include "main/imports.h"
+#include "sp_context.h"
+#include "sp_headers.h"
+#include "sp_surface.h"
+#include "sp_quad.h"
+#include "pipe/p_defines.h"
+
+
+/** Only 8-bit stencil supported */
+#define STENCIL_MAX 0xff
+
+
+/**
+ * Do the basic stencil test (compare stencil buffer values against the
+ * reference value.
+ *
+ * \param stencilVals the stencil values from the stencil buffer
+ * \param func the stencil func (PIPE_FUNC_x)
+ * \param ref the stencil reference value
+ * \param valMask the stencil value mask indicating which bits of the stencil
+ * values and ref value are to be used.
+ * \return mask indicating which pixels passed the stencil test
+ */
+static GLbitfield
+do_stencil_test(const GLubyte stencilVals[QUAD_SIZE], GLuint func,
+ GLbitfield ref, GLbitfield valMask)
+{
+ GLbitfield passMask = 0x0;
+ GLuint j;
+
+ ref &= valMask;
+
+ switch (func) {
+ case PIPE_FUNC_NEVER:
+ /* passMask = 0x0 */
+ break;
+ case PIPE_FUNC_LESS:
+ for (j = 0; j < QUAD_SIZE; j++) {
+ if ((stencilVals[j] & valMask) < ref) {
+ passMask |= (1 << j);
+ }
+ }
+ break;
+ case PIPE_FUNC_EQUAL:
+ for (j = 0; j < QUAD_SIZE; j++) {
+ if ((stencilVals[j] & valMask) == ref) {
+ passMask |= (1 << j);
+ }
+ }
+ break;
+ case PIPE_FUNC_LEQUAL:
+ for (j = 0; j < QUAD_SIZE; j++) {
+ if ((stencilVals[j] & valMask) <= ref) {
+ passMask |= (1 << j);
+ }
+ }
+ break;
+ case PIPE_FUNC_GREATER:
+ for (j = 0; j < QUAD_SIZE; j++) {
+ if ((stencilVals[j] & valMask) > ref) {
+ passMask |= (1 << j);
+ }
+ }
+ break;
+ case PIPE_FUNC_NOTEQUAL:
+ for (j = 0; j < QUAD_SIZE; j++) {
+ if ((stencilVals[j] & valMask) != ref) {
+ passMask |= (1 << j);
+ }
+ }
+ break;
+ case PIPE_FUNC_GEQUAL:
+ for (j = 0; j < QUAD_SIZE; j++) {
+ if ((stencilVals[j] & valMask) >= ref) {
+ passMask |= (1 << j);
+ }
+ }
+ break;
+ case PIPE_FUNC_ALWAYS:
+ passMask = MASK_ALL;
+ break;
+ default:
+ assert(0);
+ }
+
+ return passMask;
+}
+
+
+/**
+ * Apply the stencil operator to stencil values.
+ *
+ * \param stencilVals the stencil buffer values (read and written)
+ * \param mask indicates which pixels to update
+ * \param op the stencil operator (PIPE_STENCIL_OP_x)
+ * \param ref the stencil reference value
+ * \param wrtMask writemask controlling which bits are changed in the
+ * stencil values
+ */
+static void
+apply_stencil_op(GLubyte stencilVals[QUAD_SIZE],
+ GLbitfield mask, GLuint op, GLubyte ref, GLubyte wrtMask)
+{
+ GLuint j;
+ GLubyte newstencil[QUAD_SIZE];
+
+ for (j = 0; j < QUAD_SIZE; j++) {
+ newstencil[j] = stencilVals[j];
+ }
+
+ switch (op) {
+ case PIPE_STENCIL_OP_KEEP:
+ /* no-op */
+ break;
+ case PIPE_STENCIL_OP_ZERO:
+ for (j = 0; j < QUAD_SIZE; j++) {
+ if (mask & (1 << j)) {
+ newstencil[j] = 0;
+ }
+ }
+ break;
+ case PIPE_STENCIL_OP_REPLACE:
+ for (j = 0; j < QUAD_SIZE; j++) {
+ if (mask & (1 << j)) {
+ newstencil[j] = ref;
+ }
+ }
+ break;
+ case PIPE_STENCIL_OP_INCR:
+ for (j = 0; j < QUAD_SIZE; j++) {
+ if (mask & (1 << j)) {
+ if (stencilVals[j] < STENCIL_MAX) {
+ newstencil[j] = stencilVals[j] + 1;
+ }
+ }
+ }
+ break;
+ case PIPE_STENCIL_OP_DECR:
+ for (j = 0; j < QUAD_SIZE; j++) {
+ if (mask & (1 << j)) {
+ if (stencilVals[j] > 0) {
+ newstencil[j] = stencilVals[j] - 1;
+ }
+ }
+ }
+ break;
+ case PIPE_STENCIL_OP_INCR_WRAP:
+ for (j = 0; j < QUAD_SIZE; j++) {
+ if (mask & (1 << j)) {
+ newstencil[j] = stencilVals[j] + 1;
+ }
+ }
+ break;
+ case PIPE_STENCIL_OP_DECR_WRAP:
+ for (j = 0; j < QUAD_SIZE; j++) {
+ if (mask & (1 << j)) {
+ newstencil[j] = stencilVals[j] - 1;
+ }
+ }
+ break;
+ case PIPE_STENCIL_OP_INVERT:
+ for (j = 0; j < QUAD_SIZE; j++) {
+ if (mask & (1 << j)) {
+ newstencil[j] = ~stencilVals[j];
+ }
+ }
+ break;
+ default:
+ assert(0);
+ }
+
+ /*
+ * update the stencil values
+ */
+ if (wrtMask != STENCIL_MAX) {
+ /* apply bit-wise stencil buffer writemask */
+ for (j = 0; j < QUAD_SIZE; j++) {
+ stencilVals[j] = (wrtMask & newstencil[j]) | (~wrtMask & stencilVals[j]);
+ }
+ }
+ else {
+ for (j = 0; j < QUAD_SIZE; j++) {
+ stencilVals[j] = newstencil[j];
+ }
+ }
+}
+
+
+/**
+ * Do stencil (and depth) testing. Stenciling depends on the outcome of
+ * depth testing.
+ */
+static void
+stencil_test_quad(struct quad_stage *qs, struct quad_header *quad)
+{
+ struct softpipe_context *softpipe = qs->softpipe;
+ struct softpipe_surface *s_surf = softpipe_surface(softpipe->framebuffer.sbuf);
+ GLuint func, zFailOp, zPassOp, failOp;
+ GLubyte ref, wrtMask, valMask;
+ GLubyte stencilVals[QUAD_SIZE];
+
+ /* choose front or back face function, operator, etc */
+ /* XXX we could do these initializations once per primitive */
+ if (softpipe->stencil.back_enabled && quad->facing) {
+ func = softpipe->stencil.back_func;
+ failOp = softpipe->stencil.back_fail_op;
+ zFailOp = softpipe->stencil.back_zfail_op;
+ zPassOp = softpipe->stencil.back_zpass_op;
+ ref = softpipe->stencil.ref_value[1];
+ wrtMask = softpipe->stencil.write_mask[1];
+ valMask = softpipe->stencil.value_mask[1];
+ }
+ else {
+ func = softpipe->stencil.front_func;
+ failOp = softpipe->stencil.front_fail_op;
+ zFailOp = softpipe->stencil.front_zfail_op;
+ zPassOp = softpipe->stencil.front_zpass_op;
+ ref = softpipe->stencil.ref_value[0];
+ wrtMask = softpipe->stencil.write_mask[0];
+ valMask = softpipe->stencil.value_mask[0];
+ }
+
+ assert(s_surf); /* shouldn't get here if there's no stencil buffer */
+ s_surf->read_quad_stencil(s_surf, quad->x0, quad->y0, stencilVals);
+
+ /* do the stencil test first */
+ {
+ GLbitfield passMask, failMask;
+ passMask = do_stencil_test(stencilVals, func, ref, valMask);
+ failMask = quad->mask & ~passMask;
+ quad->mask &= passMask;
+
+ if (failOp != PIPE_STENCIL_OP_KEEP) {
+ apply_stencil_op(stencilVals, failMask, failOp, ref, wrtMask);
+ }
+ }
+
+ if (quad->mask) {
+
+ /* now the pixels that passed the stencil test are depth tested */
+ if (softpipe->depth_test.enabled) {
+ const GLbitfield origMask = quad->mask;
+
+ sp_depth_test_quad(qs, quad); /* quad->mask is updated */
+
+ /* update stencil buffer values according to z pass/fail result */
+ if (zFailOp != PIPE_STENCIL_OP_KEEP) {
+ const GLbitfield failMask = origMask & ~quad->mask;
+ apply_stencil_op(stencilVals, failMask, zFailOp, ref, wrtMask);
+ }
+
+ if (zPassOp != PIPE_STENCIL_OP_KEEP) {
+ const GLbitfield passMask = origMask & quad->mask;
+ apply_stencil_op(stencilVals, passMask, zPassOp, ref, wrtMask);
+ }
+ }
+ else {
+ /* no depth test, apply Zpass operator to stencil buffer values */
+ apply_stencil_op(stencilVals, quad->mask, zPassOp, ref, wrtMask);
+ }
+
+ }
+
+ s_surf->write_quad_stencil(s_surf, quad->x0, quad->y0, stencilVals);
+
+ if (quad->mask)
+ qs->next->run(qs->next, quad);
+}
+
+
+
+
+struct quad_stage *sp_quad_stencil_test_stage( struct softpipe_context *softpipe )
+{
+ struct quad_stage *stage = CALLOC_STRUCT(quad_stage);
+
+ stage->softpipe = softpipe;
+ stage->run = stencil_test_quad;
+
+ return stage;
+}
diff --git a/src/mesa/pipe/softpipe/sp_quad_stipple.c b/src/mesa/pipe/softpipe/sp_quad_stipple.c
new file mode 100644
index 0000000000..cad1a1400c
--- /dev/null
+++ b/src/mesa/pipe/softpipe/sp_quad_stipple.c
@@ -0,0 +1,48 @@
+
+/**
+ * quad polygon stipple stage
+ */
+
+#include "glheader.h"
+#include "imports.h"
+#include "sp_context.h"
+#include "sp_headers.h"
+#include "sp_quad.h"
+#include "pipe/p_defines.h"
+
+
+/**
+ * Apply polygon stipple to quads produced by triangle rasterization
+ */
+static void
+stipple_quad(struct quad_stage *qs, struct quad_header *quad)
+{
+ if (quad->prim == PRIM_TRI) {
+ struct softpipe_context *softpipe = qs->softpipe;
+ const GLint col0 = quad->x0 % 32;
+ const GLint row0 = quad->y0 % 32;
+ const GLuint stipple0 = softpipe->poly_stipple.stipple[row0];
+ const GLuint stipple1 = softpipe->poly_stipple.stipple[row0 + 1];
+
+ /* XXX there may be a better way to lay out the stored stipple
+ * values to further simplify this computation.
+ */
+ quad->mask &= (((stipple0 >> col0) & 0x3) |
+ (((stipple1 >> col0) & 0x3) << 2));
+
+ if (quad->mask)
+ qs->next->run(qs->next, quad);
+ }
+}
+
+
+struct quad_stage *
+sp_quad_polygon_stipple_stage( struct softpipe_context *softpipe )
+{
+ struct quad_stage *stage = CALLOC_STRUCT(quad_stage);
+
+ stage->softpipe = softpipe;
+ stage->run = stipple_quad;
+
+ return stage;
+}
diff --git a/src/mesa/pipe/softpipe/sp_state.h b/src/mesa/pipe/softpipe/sp_state.h
new file mode 100644
index 0000000000..71c1a2d9ba
--- /dev/null
+++ b/src/mesa/pipe/softpipe/sp_state.h
@@ -0,0 +1,87 @@
+/**************************************************************************
+ *
+ * Copyright 2007 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.
+ *
+ **************************************************************************/
+
+/* Authors: Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#ifndef SP_STATE_H
+#define SP_STATE_H
+
+#include "glheader.h"
+#include "pipe/p_state.h"
+
+
+void softpipe_set_framebuffer_state( struct pipe_context *,
+ const struct pipe_framebuffer_state * );
+
+void softpipe_set_alpha_test_state( struct pipe_context *,
+ const struct pipe_alpha_test_state * );
+
+void softpipe_set_blend_state( struct pipe_context *,
+ const struct pipe_blend_state * );
+
+void softpipe_set_blend_color( struct pipe_context *pipe,
+ const struct pipe_blend_color *blend_color );
+
+void softpipe_set_clear_color_state( struct pipe_context *,
+ const struct pipe_clear_color_state * );
+
+void softpipe_set_clip_state( struct pipe_context *,
+ const struct pipe_clip_state * );
+
+void softpipe_set_depth_test_state( struct pipe_context *,
+ const struct pipe_depth_state * );
+
+void softpipe_set_fs_state( struct pipe_context *,
+ const struct pipe_fs_state * );
+
+void softpipe_set_polygon_stipple( struct pipe_context *,
+ const struct pipe_poly_stipple * );
+
+void softpipe_set_scissor_state( struct pipe_context *,
+ const struct pipe_scissor_state * );
+
+void softpipe_set_setup_state( struct pipe_context *,
+ const struct pipe_setup_state * );
+
+void softpipe_set_sampler_state( struct pipe_context *,
+ GLuint unit,
+ const struct pipe_sampler_state * );
+
+void softpipe_set_stencil_state( struct pipe_context *,
+ const struct pipe_stencil_state * );
+
+void softpipe_set_texture_state( struct pipe_context *,
+ GLuint unit,
+ struct pipe_texture_object * );
+
+void softpipe_set_viewport_state( struct pipe_context *,
+ const struct pipe_viewport_state * );
+
+void softpipe_update_derived( struct softpipe_context *softpipe );
+
+#endif
diff --git a/src/mesa/pipe/softpipe/sp_state_blend.c b/src/mesa/pipe/softpipe/sp_state_blend.c
new file mode 100644
index 0000000000..8bc22b0efc
--- /dev/null
+++ b/src/mesa/pipe/softpipe/sp_state_blend.c
@@ -0,0 +1,93 @@
+/**************************************************************************
+ *
+ * Copyright 2007 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.
+ *
+ **************************************************************************/
+
+/* Authors: Keith Whitwell <keith@tungstengraphics.com>
+ */
+#include "imports.h"
+
+#include "sp_context.h"
+#include "sp_state.h"
+
+
+void softpipe_set_blend_state( struct pipe_context *pipe,
+ const struct pipe_blend_state *blend )
+{
+ struct softpipe_context *softpipe = softpipe_context(pipe);
+
+ softpipe->blend = *blend;
+
+ softpipe->dirty |= SP_NEW_BLEND;
+}
+
+
+void softpipe_set_blend_color( struct pipe_context *pipe,
+ const struct pipe_blend_color *blend_color )
+{
+ struct softpipe_context *softpipe = softpipe_context(pipe);
+
+ softpipe->blend_color = *blend_color;
+
+ softpipe->dirty |= SP_NEW_BLEND;
+}
+
+
+/** XXX move someday? Or consolidate all these simple state setters
+ * into one file.
+ */
+void
+softpipe_set_depth_test_state(struct pipe_context *pipe,
+ const struct pipe_depth_state *depth)
+{
+ struct softpipe_context *softpipe = softpipe_context(pipe);
+
+ softpipe->depth_test = *depth;
+
+ softpipe->dirty |= SP_NEW_DEPTH_TEST;
+}
+
+void
+softpipe_set_alpha_test_state(struct pipe_context *pipe,
+ const struct pipe_alpha_test_state *alpha)
+{
+ struct softpipe_context *softpipe = softpipe_context(pipe);
+
+ softpipe->alpha_test = *alpha;
+
+ softpipe->dirty |= SP_NEW_ALPHA_TEST;
+}
+
+void
+softpipe_set_stencil_state(struct pipe_context *pipe,
+ const struct pipe_stencil_state *stencil)
+{
+ struct softpipe_context *softpipe = softpipe_context(pipe);
+
+ softpipe->stencil = *stencil;
+
+ softpipe->dirty |= SP_NEW_STENCIL;
+}
+
diff --git a/src/mesa/pipe/softpipe/sp_state_clip.c b/src/mesa/pipe/softpipe/sp_state_clip.c
new file mode 100644
index 0000000000..8cf4383d3f
--- /dev/null
+++ b/src/mesa/pipe/softpipe/sp_state_clip.c
@@ -0,0 +1,85 @@
+/**************************************************************************
+ *
+ * Copyright 2007 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.
+ *
+ **************************************************************************/
+
+/* Authors: Keith Whitwell <keith@tungstengraphics.com>
+ */
+#include "imports.h"
+
+#include "sp_context.h"
+#include "sp_state.h"
+#include "pipe/draw/draw_context.h"
+
+
+void softpipe_set_clip_state( struct pipe_context *pipe,
+ const struct pipe_clip_state *clip )
+{
+ struct softpipe_context *softpipe = softpipe_context(pipe);
+
+ /* pass the clip state to the draw module */
+ draw_set_clip_state(softpipe->draw, clip);
+}
+
+
+
+/* Called when driver state tracker notices changes to the viewport
+ * matrix:
+ */
+void softpipe_set_viewport_state( struct pipe_context *pipe,
+ const struct pipe_viewport_state *viewport )
+{
+ struct softpipe_context *softpipe = softpipe_context(pipe);
+
+ softpipe->viewport = *viewport; /* struct copy */
+ softpipe->dirty |= SP_NEW_VIEWPORT;
+
+ /* pass the viewport info to the draw module */
+ draw_set_viewport_state(softpipe->draw, viewport);
+
+ /* Using tnl/ and vf/ modules is temporary while getting started.
+ * Full pipe will have vertex shader, vertex fetch of its own.
+ */
+}
+
+
+void softpipe_set_scissor_state( struct pipe_context *pipe,
+ const struct pipe_scissor_state *scissor )
+{
+ struct softpipe_context *softpipe = softpipe_context(pipe);
+
+ memcpy( &softpipe->scissor, scissor, sizeof(*scissor) );
+ softpipe->dirty |= SP_NEW_SCISSOR;
+}
+
+
+void softpipe_set_polygon_stipple( struct pipe_context *pipe,
+ const struct pipe_poly_stipple *stipple )
+{
+ struct softpipe_context *softpipe = softpipe_context(pipe);
+
+ memcpy( &softpipe->poly_stipple, stipple, sizeof(*stipple) );
+ softpipe->dirty |= SP_NEW_STIPPLE;
+}
diff --git a/src/mesa/pipe/softpipe/sp_state_derived.c b/src/mesa/pipe/softpipe/sp_state_derived.c
new file mode 100644
index 0000000000..18dfb50e38
--- /dev/null
+++ b/src/mesa/pipe/softpipe/sp_state_derived.c
@@ -0,0 +1,153 @@
+/**************************************************************************
+ *
+ * Copyright 2003 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 "main/glheader.h"
+#include "main/macros.h"
+#include "main/enums.h"
+#include "shader/program.h"
+
+#include "vf/vf.h"
+#include "pipe/draw/draw_context.h"
+#include "sp_context.h"
+#include "sp_state.h"
+
+
+#define EMIT_ATTR( VF_ATTR, FRAG_ATTR, INTERP ) \
+do { \
+ slot_to_vf_attr[softpipe->nr_attrs] = VF_ATTR; \
+ softpipe->vf_attr_to_slot[VF_ATTR] = softpipe->nr_attrs; \
+ softpipe->fp_attr_to_slot[FRAG_ATTR] = softpipe->nr_attrs; \
+ softpipe->interp[softpipe->nr_attrs] = INTERP; \
+ softpipe->nr_attrs++; \
+ attr_mask |= (1 << (VF_ATTR)); \
+} while (0)
+
+
+static const GLuint frag_to_vf[FRAG_ATTRIB_MAX] =
+{
+ VF_ATTRIB_POS,
+ VF_ATTRIB_COLOR0,
+ VF_ATTRIB_COLOR1,
+ VF_ATTRIB_FOG,
+ VF_ATTRIB_TEX0,
+ VF_ATTRIB_TEX1,
+ VF_ATTRIB_TEX2,
+ VF_ATTRIB_TEX3,
+ VF_ATTRIB_TEX4,
+ VF_ATTRIB_TEX5,
+ VF_ATTRIB_TEX6,
+ VF_ATTRIB_TEX7,
+};
+
+
+/* Derived from: fs, setup states.
+ */
+static void calculate_vertex_layout( struct softpipe_context *softpipe )
+{
+ struct gl_fragment_program *fp = softpipe->fs.fp;
+ const GLuint inputsRead = fp->Base.InputsRead;
+ GLuint slot_to_vf_attr[VF_ATTRIB_MAX];
+ GLbitfield attr_mask = 0x0;
+ GLuint i;
+
+ softpipe->nr_attrs = 0;
+ memset(slot_to_vf_attr, 0, sizeof(slot_to_vf_attr));
+
+ memset(softpipe->fp_attr_to_slot, 0, sizeof(softpipe->fp_attr_to_slot));
+ memset(softpipe->vf_attr_to_slot, 0, sizeof(softpipe->vf_attr_to_slot));
+
+ /* TODO - Figure out if we need to do perspective divide, etc.
+ */
+ EMIT_ATTR(VF_ATTRIB_POS, FRAG_ATTRIB_WPOS, INTERP_LINEAR);
+
+ /* Pull in the rest of the attributes. They are all in float4
+ * format. Future optimizations could be to keep some attributes
+ * as fixed point or ubyte format.
+ */
+ for (i = 1; i < FRAG_ATTRIB_TEX0; i++) {
+ if (inputsRead & (i << i)) {
+ if (softpipe->setup.flatshade
+ && (i == FRAG_ATTRIB_COL0 || i == FRAG_ATTRIB_COL1))
+ EMIT_ATTR(frag_to_vf[i], i, INTERP_CONSTANT);
+ else
+ EMIT_ATTR(frag_to_vf[i], i, INTERP_LINEAR);
+ }
+ }
+
+ for (i = FRAG_ATTRIB_TEX0; i < FRAG_ATTRIB_MAX; i++) {
+ if (inputsRead & (i << i)) {
+ EMIT_ATTR(frag_to_vf[i], i, INTERP_PERSPECTIVE);
+ }
+ }
+
+ softpipe->nr_frag_attrs = softpipe->nr_attrs;
+
+ /* Additional attributes required for setup: Just twosided
+ * lighting. Edgeflag is dealt with specially by setting bits in
+ * the vertex header.
+ */
+ if (softpipe->setup.light_twoside) {
+ if (inputsRead & FRAG_BIT_COL0) {
+ EMIT_ATTR(VF_ATTRIB_BFC0, FRAG_ATTRIB_MAX, 0); /* XXX: mark as discarded after setup */
+ }
+
+ if (inputsRead & FRAG_BIT_COL1) {
+ EMIT_ATTR(VF_ATTRIB_BFC1, FRAG_ATTRIB_MAX, 0); /* XXX: discard after setup */
+ }
+ }
+
+ /* If the attributes have changed, tell the draw module (which in turn
+ * tells the vf module) about the new vertex layout.
+ */
+ if (attr_mask != softpipe->attr_mask) {
+ softpipe->attr_mask = attr_mask;
+
+ draw_set_vertex_attributes( softpipe->draw,
+ slot_to_vf_attr,
+ softpipe->nr_attrs );
+ }
+}
+
+
+/* Hopefully this will remain quite simple, otherwise need to pull in
+ * something like the state tracker mechanism.
+ */
+void softpipe_update_derived( struct softpipe_context *softpipe )
+{
+ if (softpipe->dirty & (SP_NEW_SETUP | SP_NEW_FS))
+ calculate_vertex_layout( softpipe );
+
+ if (softpipe->dirty & (SP_NEW_BLEND |
+ SP_NEW_DEPTH_TEST |
+ SP_NEW_ALPHA_TEST |
+ SP_NEW_STENCIL |
+ SP_NEW_SETUP |
+ SP_NEW_FS))
+ sp_build_quad_pipeline(softpipe);
+
+ softpipe->dirty = 0;
+}
diff --git a/src/mesa/pipe/softpipe/sp_state_fs.c b/src/mesa/pipe/softpipe/sp_state_fs.c
new file mode 100644
index 0000000000..c7ef1f1cfc
--- /dev/null
+++ b/src/mesa/pipe/softpipe/sp_state_fs.c
@@ -0,0 +1,50 @@
+/**************************************************************************
+ *
+ * Copyright 2003 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 "sp_context.h"
+#include "sp_state.h"
+
+
+
+void softpipe_set_fs_state( struct pipe_context *pipe,
+ const struct pipe_fs_state *fs )
+{
+ struct softpipe_context *softpipe = softpipe_context(pipe);
+
+ memcpy(&softpipe->fs, fs, sizeof(*fs));
+
+ softpipe->dirty |= SP_NEW_FS;
+}
+
+
+
+
+
+
+
+
+
diff --git a/src/mesa/pipe/softpipe/sp_state_sampler.c b/src/mesa/pipe/softpipe/sp_state_sampler.c
new file mode 100644
index 0000000000..9ef71f73cb
--- /dev/null
+++ b/src/mesa/pipe/softpipe/sp_state_sampler.c
@@ -0,0 +1,64 @@
+/**************************************************************************
+ *
+ * Copyright 2007 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.
+ *
+ **************************************************************************/
+
+/* Authors:
+ * Brian Paul
+ */
+
+#include "imports.h"
+
+#include "sp_context.h"
+#include "sp_state.h"
+
+
+
+void
+softpipe_set_sampler_state(struct pipe_context *pipe,
+ GLuint unit,
+ const struct pipe_sampler_state *sampler)
+{
+ struct softpipe_context *softpipe = softpipe_context(pipe);
+
+ assert(unit < PIPE_MAX_SAMPLERS);
+ softpipe->sampler[unit] = *sampler;
+
+ softpipe->dirty |= SP_NEW_SAMPLER;
+}
+
+
+void
+softpipe_set_texture_state(struct pipe_context *pipe,
+ GLuint unit,
+ struct pipe_texture_object *texture)
+{
+ struct softpipe_context *softpipe = softpipe_context(pipe);
+
+ assert(unit < PIPE_MAX_SAMPLERS);
+ softpipe->texture[unit] = texture; /* ptr, not struct */
+
+ softpipe->dirty |= SP_NEW_TEXTURE;
+}
diff --git a/src/mesa/pipe/softpipe/sp_state_setup.c b/src/mesa/pipe/softpipe/sp_state_setup.c
new file mode 100644
index 0000000000..4715a26f55
--- /dev/null
+++ b/src/mesa/pipe/softpipe/sp_state_setup.c
@@ -0,0 +1,47 @@
+/**************************************************************************
+ *
+ * Copyright 2003 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_defines.h"
+#include "sp_context.h"
+#include "sp_state.h"
+#include "pipe/draw/draw_context.h"
+
+
+void softpipe_set_setup_state( struct pipe_context *pipe,
+ const struct pipe_setup_state *setup )
+{
+ struct softpipe_context *softpipe = softpipe_context(pipe);
+
+ /* pass-through to draw module */
+ draw_set_setup_state(softpipe->draw, setup);
+
+ memcpy( &softpipe->setup, setup, sizeof(*setup) );
+
+ softpipe->dirty |= SP_NEW_SETUP;
+}
+
+
diff --git a/src/mesa/pipe/softpipe/sp_state_surface.c b/src/mesa/pipe/softpipe/sp_state_surface.c
new file mode 100644
index 0000000000..8ce81eb2b0
--- /dev/null
+++ b/src/mesa/pipe/softpipe/sp_state_surface.c
@@ -0,0 +1,61 @@
+/**************************************************************************
+ *
+ * Copyright 2007 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.
+ *
+ **************************************************************************/
+
+/* Authors: Keith Whitwell <keith@tungstengraphics.com>
+ */
+#include "imports.h"
+
+#include "sp_context.h"
+#include "sp_state.h"
+#include "sp_surface.h"
+
+
+/*
+ * XXX this might get moved someday
+ */
+void
+softpipe_set_framebuffer_state(struct pipe_context *pipe,
+ const struct pipe_framebuffer_state *fb)
+{
+ struct softpipe_context *softpipe = softpipe_context(pipe);
+
+ softpipe->framebuffer = *fb; /* struct copy */
+
+ softpipe->dirty |= SP_NEW_FRAMEBUFFER;
+}
+
+
+
+
+void
+softpipe_set_clear_color_state(struct pipe_context *pipe,
+ const struct pipe_clear_color_state *clear)
+{
+ struct softpipe_context *softpipe = softpipe_context(pipe);
+
+ softpipe->clear_color = *clear; /* struct copy */
+}
diff --git a/src/mesa/pipe/softpipe/sp_surface.c b/src/mesa/pipe/softpipe/sp_surface.c
new file mode 100644
index 0000000000..16bbacb12b
--- /dev/null
+++ b/src/mesa/pipe/softpipe/sp_surface.c
@@ -0,0 +1,153 @@
+/**************************************************************************
+ *
+ * Copyright 2003 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 "sp_context.h"
+#include "sp_state.h"
+#include "sp_surface.h"
+#include "sp_headers.h"
+
+static void rgba8_read_quad_f( struct softpipe_surface *gs,
+ GLint x, GLint y,
+ GLfloat (*rgba)[NUM_CHANNELS] )
+{
+ GLuint i, j, k = 0;
+
+ for (i = 0; i < 2; i++) {
+ for (j = 0; j < 2; j++, k++) {
+ GLubyte *ptr = gs->surface.ptr + (y+i) * gs->surface.stride + (x+j) * 4;
+ rgba[k][0] = ptr[0] * (1.0 / 255.0);
+ rgba[k][1] = ptr[1] * (1.0 / 255.0);
+ rgba[k][2] = ptr[2] * (1.0 / 255.0);
+ rgba[k][3] = ptr[3] * (1.0 / 255.0);
+ }
+ }
+}
+
+static void rgba8_read_quad_f_swz( struct softpipe_surface *gs,
+ GLint x, GLint y,
+ GLfloat (*rrrr)[QUAD_SIZE] )
+{
+ GLuint i, j, k = 0;
+
+ for (i = 0; i < 2; i++) {
+ for (j = 0; j < 2; j++, k++) {
+ GLubyte *ptr = gs->surface.ptr + (y+i) * gs->surface.stride + (x+j) * 4;
+ rrrr[0][k] = ptr[0] * (1.0 / 255.0);
+ rrrr[1][k] = ptr[1] * (1.0 / 255.0);
+ rrrr[2][k] = ptr[2] * (1.0 / 255.0);
+ rrrr[3][k] = ptr[3] * (1.0 / 255.0);
+ }
+ }
+}
+
+static void rgba8_write_quad_f( struct softpipe_surface *gs,
+ GLint x, GLint y,
+ GLfloat (*rgba)[NUM_CHANNELS] )
+{
+ GLuint i, j, k = 0;
+
+ for (i = 0; i < 2; i++) {
+ for (j = 0; j < 2; j++, k++) {
+ GLubyte *ptr = gs->surface.ptr + (y+i) * gs->surface.stride + (x+j) * 4;
+ ptr[0] = rgba[k][0] * 255.0;
+ ptr[1] = rgba[k][1] * 255.0;
+ ptr[2] = rgba[k][2] * 255.0;
+ ptr[3] = rgba[k][3] * 255.0;
+ }
+ }
+}
+
+static void rgba8_write_quad_f_swz( struct softpipe_surface *gs,
+ GLint x, GLint y,
+ GLfloat (*rrrr)[QUAD_SIZE] )
+{
+ GLuint i, j, k = 0;
+
+ for (i = 0; i < 2; i++) {
+ for (j = 0; j < 2; j++, k++) {
+ GLubyte *ptr = gs->surface.ptr + (y+i) * gs->surface.stride + (x+j) * 4;
+ ptr[0] = rrrr[0][k] * 255.0;
+ ptr[1] = rrrr[1][k] * 255.0;
+ ptr[2] = rrrr[2][k] * 255.0;
+ ptr[3] = rrrr[3][k] * 255.0;
+ }
+ }
+}
+
+
+
+
+static void rgba8_read_quad_ub( struct softpipe_surface *gs,
+ GLint x, GLint y,
+ GLubyte (*rgba)[NUM_CHANNELS] )
+{
+ GLuint i, j, k = 0;
+
+ for (i = 0; i < 2; i++) {
+ for (j = 0; j < 2; j++, k++) {
+ GLubyte *ptr = gs->surface.ptr + (y+i) * gs->surface.stride + (x+j) * 4;
+ rgba[k][0] = ptr[0];
+ rgba[k][1] = ptr[1];
+ rgba[k][2] = ptr[2];
+ rgba[k][3] = ptr[3];
+ }
+ }
+}
+
+
+static void rgba8_write_quad_ub( struct softpipe_surface *gs,
+ GLint x, GLint y,
+ GLubyte (*rgba)[NUM_CHANNELS] )
+{
+ GLuint i, j, k = 0;
+
+ for (i = 0; i < 2; i++) {
+ for (j = 0; j < 2; j++, k++) {
+ GLubyte *ptr = gs->surface.ptr + (y+i) * gs->surface.stride + (x+j) * 4;
+ ptr[0] = rgba[k][0];
+ ptr[1] = rgba[k][1];
+ ptr[2] = rgba[k][2];
+ ptr[3] = rgba[k][3];
+ }
+ }
+}
+
+
+
+
+struct softpipe_surface_type gs_rgba8 = {
+ G_SURFACE_RGBA_8888,
+ rgba8_read_quad_f,
+ rgba8_read_quad_f_swz,
+ rgba8_read_quad_ub,
+ rgba8_write_quad_f,
+ rgba8_write_quad_f_swz,
+ rgba8_write_quad_ub,
+};
+
+
+
diff --git a/src/mesa/pipe/softpipe/sp_surface.h b/src/mesa/pipe/softpipe/sp_surface.h
new file mode 100644
index 0000000000..3ba732cebe
--- /dev/null
+++ b/src/mesa/pipe/softpipe/sp_surface.h
@@ -0,0 +1,101 @@
+/**************************************************************************
+ *
+ * Copyright 2007 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.
+ *
+ **************************************************************************/
+
+/* Authors: Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#ifndef SP_SURFACE_H
+#define SP_SURFACE_H
+
+#include "glheader.h"
+#include "sp_headers.h"
+
+struct softpipe_surface;
+
+#define G_SURFACE_RGBA_8888 0x1
+
+
+/**
+ * Softpipe surface is derived from pipe_surface.
+ */
+struct softpipe_surface {
+ struct pipe_surface surface;
+
+ /**
+ * Functions for read/writing surface data
+ */
+ void (*read_quad_f)( struct softpipe_surface *,
+ GLint x, GLint y,
+ GLfloat (*rgba)[NUM_CHANNELS] );
+
+ void (*read_quad_f_swz)( struct softpipe_surface *,
+ GLint x, GLint y,
+ GLfloat (*rrrr)[QUAD_SIZE] );
+
+ void (*read_quad_ub)( struct softpipe_surface *,
+ GLint x, GLint y,
+ GLubyte (*rgba)[NUM_CHANNELS] );
+
+
+ void (*write_quad_f)( struct softpipe_surface *,
+ GLint x, GLint y,
+ GLfloat (*rgba)[NUM_CHANNELS] );
+
+ void (*write_quad_f_swz)( struct softpipe_surface *,
+ GLint x, GLint y,
+ GLfloat (*rrrr)[QUAD_SIZE] );
+
+
+ void (*write_quad_ub)( struct softpipe_surface *,
+ GLint x, GLint y,
+ GLubyte (*rgba)[NUM_CHANNELS] );
+
+ void (*write_mono_row_ub)( struct softpipe_surface *,
+ GLuint count, GLint x, GLint y,
+ GLubyte rgba[NUM_CHANNELS] );
+
+ void (*read_quad_z)(struct softpipe_surface *,
+ GLint x, GLint y, GLuint zzzz[QUAD_SIZE]);
+ void (*write_quad_z)(struct softpipe_surface *,
+ GLint x, GLint y, const GLuint zzzz[QUAD_SIZE]);
+
+ void (*read_quad_stencil)(struct softpipe_surface *,
+ GLint x, GLint y, GLubyte ssss[QUAD_SIZE]);
+ void (*write_quad_stencil)(struct softpipe_surface *,
+ GLint x, GLint y, const GLubyte ssss[QUAD_SIZE]);
+};
+
+
+/** Cast wrapper */
+static INLINE struct softpipe_surface *
+softpipe_surface(struct pipe_surface *ps)
+{
+ return (struct softpipe_surface *) ps;
+}
+
+
+#endif /* SP_SURFACE_H */