#include "sp_setup.h"
#include "sp_state.h"
#include "draw/draw_context.h"
-#include "draw/draw_private.h"
#include "draw/draw_vertex.h"
#include "pipe/p_shader_tokens.h"
#include "util/u_math.h"
#define DEBUG_VERTS 0
#define DEBUG_FRAGS 0
+
/**
* Triangle edge info
*/
};
+/**
+ * Max number of quads (2x2 pixel blocks) to process per batch.
+ * This can't be arbitrarily increased since we depend on some 32-bit
+ * bitmasks (two bits per quad).
+ */
#define MAX_QUADS 16
/**
- * Triangle setup info (derived from draw_stage).
+ * Triangle setup info.
* Also used for line drawing (taking some liberties).
*/
struct setup_context {
uint numFragsWritten; /**< per primitive */
#endif
- unsigned winding; /* which winding to cull */
+ unsigned cull_face; /* which faces cull */
unsigned nr_vertex_attrs;
};
-/**
- * Do triangle cull test using tri determinant (sign indicates orientation)
- * \return true if triangle is to be culled.
- */
-static INLINE boolean
-cull_tri(const struct setup_context *setup, float det)
-{
- if (det != 0) {
- /* if (det < 0 then Z points toward camera and triangle is
- * counter-clockwise winding.
- */
- unsigned winding = (det < 0) ? PIPE_WINDING_CCW : PIPE_WINDING_CW;
-
- if ((winding & setup->winding) == 0)
- return FALSE;
- }
-
- /* Culled:
- */
- return TRUE;
-}
* Clip setup->quad against the scissor/surface bounds.
*/
static INLINE void
-quad_clip( struct setup_context *setup, struct quad_header *quad )
+quad_clip(struct setup_context *setup, struct quad_header *quad)
{
const struct pipe_scissor_state *cliprect = &setup->softpipe->cliprect;
const int minx = (int) cliprect->minx;
* Emit a quad (pass to next stage) with clipping.
*/
static INLINE void
-clip_emit_quad( struct setup_context *setup, struct quad_header *quad )
+clip_emit_quad(struct setup_context *setup, struct quad_header *quad)
{
quad_clip( setup, quad );
* Given an X or Y coordinate, return the block/quad coordinate that it
* belongs to.
*/
-static INLINE int block( int x )
+static INLINE int
+block(int x)
{
return x & ~(2-1);
}
-static INLINE int block_x( int x )
+
+static INLINE int
+block_x(int x)
{
return x & ~(16-1);
}
/**
* Render a horizontal span of quads
*/
-static void flush_spans( struct setup_context *setup )
+static void
+flush_spans(struct setup_context *setup)
{
- const int step = 16;
+ const int step = MAX_QUADS;
const int xleft0 = setup->span.left[0];
const int xleft1 = setup->span.left[1];
const int xright0 = setup->span.right[0];
const int xright1 = setup->span.right[1];
struct quad_stage *pipe = setup->softpipe->quad.first;
-
- int minleft = block_x(MIN2(xleft0, xleft1));
- int maxright = MAX2(xright0, xright1);
+ const int minleft = block_x(MIN2(xleft0, xleft1));
+ const int maxright = MAX2(xright0, xright1);
int x;
+ /* process quads in horizontal chunks of 16 */
for (x = minleft; x < maxright; x += step) {
unsigned skip_left0 = CLAMP(xleft0 - x, 0, step);
unsigned skip_left1 = CLAMP(xleft1 - x, 0, step);
#if DEBUG_VERTS
-static void print_vertex(const struct setup_context *setup,
- const float (*v)[4])
+static void
+print_vertex(const struct setup_context *setup,
+ const float (*v)[4])
{
int i;
debug_printf(" Vertex: (%p)\n", (void *) v);
}
#endif
+
/**
* Sort the vertices from top to bottom order, setting up the triangle
* edge fields (ebot, emaj, etop).
* \return FALSE if coords are inf/nan (cull the tri), TRUE otherwise
*/
-static boolean setup_sort_vertices( struct setup_context *setup,
- float det,
- const float (*v0)[4],
- const float (*v1)[4],
- const float (*v2)[4] )
+static boolean
+setup_sort_vertices(struct setup_context *setup,
+ float det,
+ const float (*v0)[4],
+ const float (*v1)[4],
+ const float (*v2)[4])
{
- setup->vprovoke = v2;
+ if (setup->softpipe->rasterizer->flatshade_first)
+ setup->vprovoke = v0;
+ else
+ setup->vprovoke = v2;
/* determine bottom to top order of vertices */
{
/* 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
+ * 0 = front-facing, 1 = back-facing
*/
setup->facing =
- ((det > 0.0) ^
- (setup->softpipe->rasterizer->front_winding == PIPE_WINDING_CW));
+ ((det < 0.0) ^
+ (setup->softpipe->rasterizer->front_ccw));
+
+ {
+ unsigned face = setup->facing == 0 ? PIPE_FACE_FRONT : PIPE_FACE_BACK;
+
+ if (face & setup->cull_face)
+ return FALSE;
+ }
+
/* Prepare pixel offset for rasterisation:
* - pixel center (0.5, 0.5) for GL, or
}
+/* Apply cylindrical wrapping to v0, v1, v2 coordinates, if enabled.
+ * Input coordinates must be in [0, 1] range, otherwise results are undefined.
+ * Some combinations of coordinates produce invalid results,
+ * but this behaviour is acceptable.
+ */
+static void
+tri_apply_cylindrical_wrap(float v0,
+ float v1,
+ float v2,
+ uint cylindrical_wrap,
+ float output[3])
+{
+ if (cylindrical_wrap) {
+ float delta;
+
+ delta = v1 - v0;
+ if (delta > 0.5f) {
+ v0 += 1.0f;
+ }
+ else if (delta < -0.5f) {
+ v1 += 1.0f;
+ }
+
+ delta = v2 - v1;
+ if (delta > 0.5f) {
+ v1 += 1.0f;
+ }
+ else if (delta < -0.5f) {
+ v2 += 1.0f;
+ }
+
+ delta = v0 - v2;
+ if (delta > 0.5f) {
+ v2 += 1.0f;
+ }
+ else if (delta < -0.5f) {
+ v0 += 1.0f;
+ }
+ }
+
+ output[0] = v0;
+ output[1] = v1;
+ output[2] = v2;
+}
+
+
/**
* Compute a0 for a constant-valued coefficient (GL_FLAT shading).
* The value value comes from vertex[slot][i].
* \param slot which attribute slot
* \param i which component of the slot (0..3)
*/
-static void const_coeff( struct setup_context *setup,
- struct tgsi_interp_coef *coef,
- uint vertSlot, uint i)
+static void
+const_coeff(struct setup_context *setup,
+ struct tgsi_interp_coef *coef,
+ uint vertSlot, uint i)
{
assert(i <= 3);
/**
* Compute a0, dadx and dady for a linearly interpolated coefficient,
* for a triangle.
+ * v[0], v[1] and v[2] are vmin, vmid and vmax, respectively.
*/
-static void tri_linear_coeff( struct setup_context *setup,
- struct tgsi_interp_coef *coef,
- uint vertSlot, uint i)
+static void
+tri_linear_coeff(struct setup_context *setup,
+ struct tgsi_interp_coef *coef,
+ uint i,
+ const float v[3])
{
- float botda = setup->vmid[vertSlot][i] - setup->vmin[vertSlot][i];
- float majda = setup->vmax[vertSlot][i] - setup->vmin[vertSlot][i];
+ float botda = v[1] - v[0];
+ float majda = v[2] - v[0];
float a = setup->ebot.dy * majda - botda * setup->emaj.dy;
float b = setup->emaj.dx * botda - majda * setup->ebot.dx;
float dadx = a * setup->oneoverarea;
* to define a0 as the sample at a pixel center somewhere near vmin
* instead - i'll switch to this later.
*/
- coef->a0[i] = (setup->vmin[vertSlot][i] -
+ coef->a0[i] = (v[0] -
(dadx * (setup->vmin[0][0] - setup->pixel_offset) +
dady * (setup->vmin[0][1] - setup->pixel_offset)));
* the plane coefficients (a0, dadx, dady).
* Later, when we compute the value at a particular fragment position we'll
* divide the interpolated value by the interpolated W at that fragment.
+ * v[0], v[1] and v[2] are vmin, vmid and vmax, respectively.
*/
-static void tri_persp_coeff( struct setup_context *setup,
- struct tgsi_interp_coef *coef,
- uint vertSlot, uint i)
+static void
+tri_persp_coeff(struct setup_context *setup,
+ struct tgsi_interp_coef *coef,
+ uint i,
+ const float v[3])
{
/* premultiply by 1/w (v[0][3] is always W):
*/
- float mina = setup->vmin[vertSlot][i] * setup->vmin[0][3];
- float mida = setup->vmid[vertSlot][i] * setup->vmid[0][3];
- float maxa = setup->vmax[vertSlot][i] * setup->vmax[0][3];
+ float mina = v[0] * setup->vmin[0][3];
+ float mida = v[1] * setup->vmid[0][3];
+ float maxa = v[2] * setup->vmax[0][3];
float botda = mida - mina;
float majda = maxa - mina;
float a = setup->ebot.dy * majda - botda * setup->emaj.dy;
/**
* Special coefficient setup for gl_FragCoord.
- * X and Y are trivial, though Y has to be inverted for OpenGL.
+ * X and Y are trivial, though Y may have to be inverted for OpenGL.
* Z and W are copied from posCoef which should have already been computed.
* We could do a bit less work if we'd examine gl_FragCoord's swizzle mask.
*/
static void
setup_fragcoord_coeff(struct setup_context *setup, uint slot)
{
+ struct sp_fragment_shader* spfs = setup->softpipe->fs;
/*X*/
- setup->coef[slot].a0[0] = 0;
+ setup->coef[slot].a0[0] = spfs->pixel_center_integer ? 0.0 : 0.5;
setup->coef[slot].dadx[0] = 1.0;
setup->coef[slot].dady[0] = 0.0;
/*Y*/
- setup->coef[slot].a0[1] = 0.0;
+ setup->coef[slot].a0[1] =
+ (spfs->origin_lower_left ? setup->softpipe->framebuffer.height : 0)
+ + (spfs->pixel_center_integer ? 0.0 : 0.5);
setup->coef[slot].dadx[1] = 0.0;
- setup->coef[slot].dady[1] = 1.0;
+ setup->coef[slot].dady[1] = spfs->origin_lower_left ? -1.0 : 1.0;
/*Z*/
setup->coef[slot].a0[2] = setup->posCoef.a0[2];
setup->coef[slot].dadx[2] = setup->posCoef.dadx[2];
* 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_context *setup )
+static void
+setup_tri_coefficients(struct setup_context *setup)
{
struct softpipe_context *softpipe = setup->softpipe;
const struct sp_fragment_shader *spfs = softpipe->fs;
const struct vertex_info *vinfo = softpipe_get_vertex_info(softpipe);
uint fragSlot;
+ float v[3];
/* z and w are done by linear interpolation:
*/
- tri_linear_coeff(setup, &setup->posCoef, 0, 2);
- tri_linear_coeff(setup, &setup->posCoef, 0, 3);
+ v[0] = setup->vmin[0][2];
+ v[1] = setup->vmid[0][2];
+ v[2] = setup->vmax[0][2];
+ tri_linear_coeff(setup, &setup->posCoef, 2, v);
+
+ v[0] = setup->vmin[0][3];
+ v[1] = setup->vmid[0][3];
+ v[2] = setup->vmax[0][3];
+ tri_linear_coeff(setup, &setup->posCoef, 3, v);
/* setup interpolation for all the remaining attributes:
*/
const_coeff(setup, &setup->coef[fragSlot], vertSlot, j);
break;
case INTERP_LINEAR:
- for (j = 0; j < NUM_CHANNELS; j++)
- tri_linear_coeff(setup, &setup->coef[fragSlot], vertSlot, j);
+ for (j = 0; j < NUM_CHANNELS; j++) {
+ tri_apply_cylindrical_wrap(setup->vmin[vertSlot][j],
+ setup->vmid[vertSlot][j],
+ setup->vmax[vertSlot][j],
+ spfs->info.input_cylindrical_wrap[fragSlot] & (1 << j),
+ v);
+ tri_linear_coeff(setup, &setup->coef[fragSlot], j, v);
+ }
break;
case INTERP_PERSPECTIVE:
- for (j = 0; j < NUM_CHANNELS; j++)
- tri_persp_coeff(setup, &setup->coef[fragSlot], vertSlot, j);
+ for (j = 0; j < NUM_CHANNELS; j++) {
+ tri_apply_cylindrical_wrap(setup->vmin[vertSlot][j],
+ setup->vmid[vertSlot][j],
+ setup->vmax[vertSlot][j],
+ spfs->info.input_cylindrical_wrap[fragSlot] & (1 << j),
+ v);
+ tri_persp_coeff(setup, &setup->coef[fragSlot], j, v);
+ }
break;
case INTERP_POS:
setup_fragcoord_coeff(setup, fragSlot);
}
if (spfs->info.input_semantic_name[fragSlot] == TGSI_SEMANTIC_FACE) {
- setup->coef[fragSlot].a0[0] = 1.0f - setup->facing;
+ /* convert 0 to 1.0 and 1 to -1.0 */
+ setup->coef[fragSlot].a0[0] = setup->facing * -2.0f + 1.0f;
setup->coef[fragSlot].dadx[0] = 0.0;
setup->coef[fragSlot].dady[0] = 0.0;
}
}
-
-static void setup_tri_edges( struct setup_context *setup )
+static void
+setup_tri_edges(struct setup_context *setup)
{
float vmin_x = setup->vmin[0][0] + setup->pixel_offset;
float vmid_x = setup->vmid[0][0] + setup->pixel_offset;
setup->emaj.sy = ceilf(vmin_y);
setup->emaj.lines = (int) ceilf(vmax_y - setup->emaj.sy);
- setup->emaj.dxdy = setup->emaj.dx / setup->emaj.dy;
+ setup->emaj.dxdy = setup->emaj.dy ? setup->emaj.dx / setup->emaj.dy : .0f;
setup->emaj.sx = vmin_x + (setup->emaj.sy - vmin_y) * setup->emaj.dxdy;
setup->etop.sy = ceilf(vmid_y);
setup->etop.lines = (int) ceilf(vmax_y - setup->etop.sy);
- setup->etop.dxdy = setup->etop.dx / setup->etop.dy;
+ setup->etop.dxdy = setup->etop.dy ? setup->etop.dx / setup->etop.dy : .0f;
setup->etop.sx = vmid_x + (setup->etop.sy - vmid_y) * setup->etop.dxdy;
setup->ebot.sy = ceilf(vmin_y);
setup->ebot.lines = (int) ceilf(vmid_y - setup->ebot.sy);
- setup->ebot.dxdy = setup->ebot.dx / setup->ebot.dy;
+ setup->ebot.dxdy = setup->ebot.dy ? setup->ebot.dx / setup->ebot.dy : .0f;
setup->ebot.sx = vmin_x + (setup->ebot.sy - vmin_y) * setup->ebot.dxdy;
}
* Render the upper or lower half of a triangle.
* Scissoring/cliprect is applied here too.
*/
-static void subtriangle( struct setup_context *setup,
- struct edge *eleft,
- struct edge *eright,
- unsigned lines )
+static void
+subtriangle(struct setup_context *setup,
+ struct edge *eleft,
+ struct edge *eright,
+ int lines)
{
const struct pipe_scissor_state *cliprect = &setup->softpipe->cliprect;
const int minx = (int) cliprect->minx;
int sy = (int)eleft->sy;
assert((int)eleft->sy == (int) eright->sy);
+ assert(lines >= 0);
/* clip top/bottom */
start_y = sy;
* calculate it here.
*/
static float
-calc_det( const float (*v0)[4],
- const float (*v1)[4],
- const float (*v2)[4] )
+calc_det(const float (*v0)[4],
+ const float (*v1)[4],
+ const float (*v2)[4])
{
/* edge vectors e = v0 - v2, f = v1 - v2 */
const float ex = v0[0][0] - v2[0][0];
/**
* Do setup for triangle rasterization, then render the triangle.
*/
-void sp_setup_tri( struct setup_context *setup,
- const float (*v0)[4],
- const float (*v1)[4],
- const float (*v2)[4] )
+void
+sp_setup_tri(struct setup_context *setup,
+ const float (*v0)[4],
+ const float (*v1)[4],
+ const float (*v2)[4])
{
float det;
setup->numFragsWritten = 0;
#endif
- if (cull_tri( setup, det ))
- return;
-
if (!setup_sort_vertices( setup, det, v0, v1, v2 ))
return;
+
setup_tri_coefficients( setup );
setup_tri_edges( setup );
}
+/* Apply cylindrical wrapping to v0, v1 coordinates, if enabled.
+ * Input coordinates must be in [0, 1] range, otherwise results are undefined.
+ */
+static void
+line_apply_cylindrical_wrap(float v0,
+ float v1,
+ uint cylindrical_wrap,
+ float output[2])
+{
+ if (cylindrical_wrap) {
+ float delta;
+
+ delta = v1 - v0;
+ if (delta > 0.5f) {
+ v0 += 1.0f;
+ }
+ else if (delta < -0.5f) {
+ v1 += 1.0f;
+ }
+ }
+
+ output[0] = v0;
+ output[1] = v1;
+}
+
/**
* Compute a0, dadx and dady for a linearly interpolated coefficient,
* for a line.
+ * v[0] and v[1] are vmin and vmax, respectively.
*/
static void
line_linear_coeff(const struct setup_context *setup,
struct tgsi_interp_coef *coef,
- uint vertSlot, uint i)
+ uint i,
+ const float v[2])
{
- const float da = setup->vmax[vertSlot][i] - setup->vmin[vertSlot][i];
+ const float da = v[1] - v[0];
const float dadx = da * setup->emaj.dx * setup->oneoverarea;
const float dady = da * setup->emaj.dy * setup->oneoverarea;
coef->dadx[i] = dadx;
coef->dady[i] = dady;
- coef->a0[i] = (setup->vmin[vertSlot][i] -
+ coef->a0[i] = (v[0] -
(dadx * (setup->vmin[0][0] - setup->pixel_offset) +
dady * (setup->vmin[0][1] - setup->pixel_offset)));
}
/**
* Compute a0, dadx and dady for a perspective-corrected interpolant,
* for a line.
+ * v[0] and v[1] are vmin and vmax, respectively.
*/
static void
line_persp_coeff(const struct setup_context *setup,
struct tgsi_interp_coef *coef,
- uint vertSlot, uint i)
+ uint i,
+ const float v[2])
{
- /* XXX double-check/verify this arithmetic */
- const float a0 = setup->vmin[vertSlot][i] * setup->vmin[0][3];
- const float a1 = setup->vmax[vertSlot][i] * setup->vmax[0][3];
+ const float a0 = v[0] * setup->vmin[0][3];
+ const float a1 = v[1] * setup->vmax[0][3];
const float da = a1 - a0;
const float dadx = da * setup->emaj.dx * setup->oneoverarea;
const float dady = da * setup->emaj.dy * setup->oneoverarea;
coef->dadx[i] = dadx;
coef->dady[i] = dady;
- coef->a0[i] = (setup->vmin[vertSlot][i] -
+ coef->a0[i] = (a0 -
(dadx * (setup->vmin[0][0] - setup->pixel_offset) +
dady * (setup->vmin[0][1] - setup->pixel_offset)));
}
* Compute the setup->coef[] array dadx, dady, a0 values.
* Must be called after setup->vmin,vmax are initialized.
*/
-static INLINE boolean
+static boolean
setup_line_coefficients(struct setup_context *setup,
const float (*v0)[4],
const float (*v1)[4])
const struct vertex_info *vinfo = softpipe_get_vertex_info(softpipe);
uint fragSlot;
float area;
+ float v[2];
/* use setup->vmin, vmax to point to vertices */
if (softpipe->rasterizer->flatshade_first)
/* z and w are done by linear interpolation:
*/
- line_linear_coeff(setup, &setup->posCoef, 0, 2);
- line_linear_coeff(setup, &setup->posCoef, 0, 3);
+ v[0] = setup->vmin[0][2];
+ v[1] = setup->vmax[0][2];
+ line_linear_coeff(setup, &setup->posCoef, 2, v);
+
+ v[0] = setup->vmin[0][3];
+ v[1] = setup->vmax[0][3];
+ line_linear_coeff(setup, &setup->posCoef, 3, v);
/* setup interpolation for all the remaining attributes:
*/
const_coeff(setup, &setup->coef[fragSlot], vertSlot, j);
break;
case INTERP_LINEAR:
- for (j = 0; j < NUM_CHANNELS; j++)
- line_linear_coeff(setup, &setup->coef[fragSlot], vertSlot, j);
+ for (j = 0; j < NUM_CHANNELS; j++) {
+ line_apply_cylindrical_wrap(setup->vmin[vertSlot][j],
+ setup->vmax[vertSlot][j],
+ spfs->info.input_cylindrical_wrap[fragSlot] & (1 << j),
+ v);
+ line_linear_coeff(setup, &setup->coef[fragSlot], j, v);
+ }
break;
case INTERP_PERSPECTIVE:
- for (j = 0; j < NUM_CHANNELS; j++)
- line_persp_coeff(setup, &setup->coef[fragSlot], vertSlot, j);
+ for (j = 0; j < NUM_CHANNELS; j++) {
+ line_apply_cylindrical_wrap(setup->vmin[vertSlot][j],
+ setup->vmax[vertSlot][j],
+ spfs->info.input_cylindrical_wrap[fragSlot] & (1 << j),
+ v);
+ line_persp_coeff(setup, &setup->coef[fragSlot], j, v);
+ }
break;
case INTERP_POS:
setup_fragcoord_coeff(setup, fragSlot);
}
if (spfs->info.input_semantic_name[fragSlot] == TGSI_SEMANTIC_FACE) {
- setup->coef[fragSlot].a0[0] = 1.0f - setup->facing;
+ /* convert 0 to 1.0 and 1 to -1.0 */
+ setup->coef[fragSlot].a0[0] = setup->facing * -2.0f + 1.0f;
setup->coef[fragSlot].dadx[0] = 0.0;
setup->coef[fragSlot].dady[0] = 0.0;
}
*/
void
sp_setup_line(struct setup_context *setup,
- const float (*v0)[4],
- const float (*v1)[4])
+ const float (*v0)[4],
+ const float (*v1)[4])
{
int x0 = (int) v0[0][0];
int x1 = (int) v1[0][0];
* XXX could optimize a lot for 1-pixel points.
*/
void
-sp_setup_point( struct setup_context *setup,
- const float (*v0)[4] )
+sp_setup_point(struct setup_context *setup,
+ const float (*v0)[4])
{
struct softpipe_context *softpipe = setup->softpipe;
const struct sp_fragment_shader *spfs = softpipe->fs;
}
if (spfs->info.input_semantic_name[fragSlot] == TGSI_SEMANTIC_FACE) {
- setup->coef[fragSlot].a0[0] = 1.0f - setup->facing;
+ /* convert 0 to 1.0 and 1 to -1.0 */
+ setup->coef[fragSlot].a0[0] = setup->facing * -2.0f + 1.0f;
setup->coef[fragSlot].dadx[0] = 0.0;
setup->coef[fragSlot].dady[0] = 0.0;
}
}
}
-void sp_setup_prepare( struct setup_context *setup )
+
+/**
+ * Called by vbuf code just before we start buffering primitives.
+ */
+void
+sp_setup_prepare(struct setup_context *setup)
{
struct softpipe_context *sp = setup->softpipe;
sp->quad.first->begin( sp->quad.first );
if (sp->reduced_api_prim == PIPE_PRIM_TRIANGLES &&
- sp->rasterizer->fill_cw == PIPE_POLYGON_MODE_FILL &&
- sp->rasterizer->fill_ccw == PIPE_POLYGON_MODE_FILL) {
+ sp->rasterizer->fill_front == PIPE_POLYGON_MODE_FILL &&
+ sp->rasterizer->fill_back == PIPE_POLYGON_MODE_FILL) {
/* we'll do culling */
- setup->winding = sp->rasterizer->cull_mode;
+ setup->cull_face = sp->rasterizer->cull_face;
}
else {
/* 'draw' will do culling */
- setup->winding = PIPE_WINDING_NONE;
+ setup->cull_face = PIPE_FACE_NONE;
}
}
-
-void sp_setup_destroy_context( struct setup_context *setup )
+void
+sp_setup_destroy_context(struct setup_context *setup)
{
FREE( setup );
}
/**
* Create a new primitive setup/render stage.
*/
-struct setup_context *sp_setup_create_context( struct softpipe_context *softpipe )
+struct setup_context *
+sp_setup_create_context(struct softpipe_context *softpipe)
{
struct setup_context *setup = CALLOC_STRUCT(setup_context);
unsigned i;
return setup;
}
-