* Keith Whitwell <keith@tungstengraphics.com>
*/
+#include "pipe/p_state.h"
#include "brw_batchbuffer.h"
-
#include "brw_defines.h"
#include "brw_context.h"
+#include "brw_pipe_rast.h"
#include "brw_eu.h"
-#include "brw_util.h"
#include "brw_sf.h"
#include "brw_state.h"
-static void compile_sf_prog( struct brw_context *brw,
- struct brw_sf_prog_key *key )
+static enum pipe_error compile_sf_prog( struct brw_context *brw,
+ struct brw_sf_prog_key *key,
+ struct brw_winsys_buffer **bo_out )
{
+ enum pipe_error ret;
struct brw_sf_compile c;
const GLuint *program;
GLuint program_size;
- GLuint i, idx;
memset(&c, 0, sizeof(c));
brw_init_compile(brw, &c.func);
c.key = *key;
- c.nr_attrs = util_count_bits(c.key.attrs);
+ c.nr_attrs = c.key.nr_attrs;
c.nr_attr_regs = (c.nr_attrs+1)/2;
c.nr_setup_attrs = c.key.nr_attrs;
c.nr_setup_regs = (c.nr_setup_attrs+1)/2;
c.prog_data.urb_read_length = c.nr_attr_regs;
c.prog_data.urb_entry_size = c.nr_setup_regs * 2;
- /* Construct map from attribute number to position in the vertex.
+ /* Special case when there are no attributes to setup.
+ *
+ * XXX: should be able to set nr_setup_attrs to nr_attrs-1 -- but
+ * breaks vp-tris.c
*/
- for (i = idx = 0; i < VERT_RESULT_MAX; i++)
- if (c.key.attrs & (1<<i)) {
- c.attr_to_idx[i] = idx;
- c.idx_to_attr[idx] = i;
- if (i >= VERT_RESULT_TEX0 && i <= VERT_RESULT_TEX7) {
- c.point_attrs[i].CoordReplace =
- ctx->Point.CoordReplace[i - VERT_RESULT_TEX0];
- }
- else {
- c.point_attrs[i].CoordReplace = GL_FALSE;
- }
- idx++;
+ if (c.nr_attrs - 1 == 0) {
+ c.nr_verts = 0;
+ brw_emit_null_setup( &c );
+ }
+ else {
+ /* Which primitive? Or all three?
+ */
+ switch (key->primitive) {
+ case SF_TRIANGLES:
+ c.nr_verts = 3;
+ brw_emit_tri_setup( &c, GL_TRUE );
+ break;
+ case SF_LINES:
+ c.nr_verts = 2;
+ brw_emit_line_setup( &c, GL_TRUE );
+ break;
+ case SF_POINTS:
+ c.nr_verts = 1;
+ if (key->do_point_sprite)
+ brw_emit_point_sprite_setup( &c, GL_TRUE );
+ else
+ brw_emit_point_setup( &c, GL_TRUE );
+ break;
+ case SF_UNFILLED_TRIS:
+ c.nr_verts = 3;
+ brw_emit_anyprim_setup( &c );
+ break;
+ default:
+ assert(0);
+ return PIPE_ERROR_BAD_INPUT;
}
-
- /* Which primitive? Or all three?
- */
- switch (key->primitive) {
- case SF_TRIANGLES:
- c.nr_verts = 3;
- brw_emit_tri_setup( &c, GL_TRUE );
- break;
- case SF_LINES:
- c.nr_verts = 2;
- brw_emit_line_setup( &c, GL_TRUE );
- break;
- case SF_POINTS:
- c.nr_verts = 1;
- if (key->do_point_sprite)
- brw_emit_point_sprite_setup( &c, GL_TRUE );
- else
- brw_emit_point_setup( &c, GL_TRUE );
- break;
- case SF_UNFILLED_TRIS:
- c.nr_verts = 3;
- brw_emit_anyprim_setup( &c );
- break;
- default:
- assert(0);
- return;
}
/* get the program
*/
- program = brw_get_program(&c.func, &program_size);
+ ret = brw_get_program(&c.func, &program, &program_size);
+ if (ret)
+ return ret;
/* Upload
*/
- brw->sws->bo_unreference(brw->sf.prog_bo);
- brw->sf.prog_bo = brw_upload_cache( &brw->cache, BRW_SF_PROG,
- &c.key, sizeof(c.key),
- NULL, 0,
- program, program_size,
- &c.prog_data,
- &brw->sf.prog_data );
+ ret = brw_upload_cache( &brw->cache, BRW_SF_PROG,
+ &c.key, sizeof(c.key),
+ NULL, 0,
+ program, program_size,
+ &c.prog_data,
+ &brw->sf.prog_data,
+ bo_out);
+ if (ret)
+ return ret;
+
+ return PIPE_OK;
}
/* Calculate interpolants for triangle and line rasterization.
*/
-static void upload_sf_prog(struct brw_context *brw)
+static enum pipe_error upload_sf_prog(struct brw_context *brw)
{
+ const struct brw_fs_signature *sig = &brw->curr.fragment_shader->signature;
+ const struct pipe_rasterizer_state *rast = &brw->curr.rast->templ;
struct brw_sf_prog_key key;
+ enum pipe_error ret;
+ unsigned i;
memset(&key, 0, sizeof(key));
/* Populate the key, noting state dependencies:
*/
- /* CACHE_NEW_VS_PROG */
- key.attrs = brw->vs.prog_data->nr_outputs_written;
+
+ /* XXX: Add one to account for the position input.
+ */
+ /* PIPE_NEW_FRAGMENT_SIGNATURE */
+ key.nr_attrs = sig->nr_inputs + 1;
+
+
+ /* XXX: why is position required to be linear? why do we care
+ * about it at all?
+ */
+ key.linear_attrs = 1; /* position -- but why? */
+
+ for (i = 0; i < sig->nr_inputs; i++) {
+ switch (sig->input[i].interp) {
+ case TGSI_INTERPOLATE_CONSTANT:
+ break;
+ case TGSI_INTERPOLATE_LINEAR:
+ key.linear_attrs |= 1 << (i+1);
+ break;
+ case TGSI_INTERPOLATE_PERSPECTIVE:
+ key.persp_attrs |= 1 << (i+1);
+ break;
+ }
+ }
/* BRW_NEW_REDUCED_PRIMITIVE */
switch (brw->reduced_primitive) {
- case GL_TRIANGLES:
- /* NOTE: We just use the edgeflag attribute as an indicator that
- * unfilled triangles are active. We don't actually do the
- * edgeflag testing here, it is already done in the clip
- * program.
+ case PIPE_PRIM_TRIANGLES:
+ /* PIPE_NEW_RAST
*/
- if (key.attrs & (1<<VERT_RESULT_EDGE))
+ if (rast->fill_front != PIPE_POLYGON_MODE_FILL ||
+ rast->fill_back != PIPE_POLYGON_MODE_FILL)
key.primitive = SF_UNFILLED_TRIS;
else
key.primitive = SF_TRIANGLES;
break;
- case GL_LINES:
+ case PIPE_PRIM_LINES:
key.primitive = SF_LINES;
break;
- case GL_POINTS:
+ case PIPE_PRIM_POINTS:
key.primitive = SF_POINTS;
break;
}
- key.do_point_sprite = ctx->Point.PointSprite;
- key.SpriteOrigin = ctx->Point.SpriteOrigin;
- /* _NEW_LIGHT */
- key.do_flat_shading = (ctx->Light.ShadeModel == GL_FLAT);
- key.do_twoside_color = (ctx->Light.Enabled && ctx->Light.Model.TwoSide);
-
- /* _NEW_HINT */
- key.linear_color = 0;
+ key.do_point_sprite = rast->sprite_coord_enable ? 1 : 0;
+ key.sprite_origin_lower_left = (rast->sprite_coord_mode == PIPE_SPRITE_COORD_LOWER_LEFT);
+ key.point_coord_replace_attrs = rast->sprite_coord_enable;
+ key.do_flat_shading = rast->flatshade;
+ key.do_twoside_color = rast->light_twoside;
- /* _NEW_POLYGON */
if (key.do_twoside_color) {
- /* If we're rendering to a FBO, we have to invert the polygon
- * face orientation, just as we invert the viewport in
- * sf_unit_create_from_key(). ctx->DrawBuffer->Name will be
- * nonzero if we're rendering to such an FBO.
- */
- key.frontface_ccw = (ctx->Polygon.FrontFace == GL_CCW) ^ (ctx->DrawBuffer->Name != 0);
+ key.frontface_ccw = rast->front_ccw;
}
- brw->sws->bo_unreference(brw->sf.prog_bo);
- brw->sf.prog_bo = brw_search_cache(&brw->cache, BRW_SF_PROG,
- &key, sizeof(key),
- NULL, 0,
- &brw->sf.prog_data);
- if (brw->sf.prog_bo == NULL)
- compile_sf_prog( brw, &key );
+ if (brw_search_cache(&brw->cache, BRW_SF_PROG,
+ &key, sizeof(key),
+ NULL, 0,
+ &brw->sf.prog_data,
+ &brw->sf.prog_bo))
+ return PIPE_OK;
+
+ ret = compile_sf_prog( brw, &key, &brw->sf.prog_bo );
+ if (ret)
+ return ret;
+
+ return PIPE_OK;
}
const struct brw_tracked_state brw_sf_prog = {
.dirty = {
- .mesa = (_NEW_HINT | _NEW_LIGHT | _NEW_POLYGON | _NEW_POINT),
+ .mesa = (PIPE_NEW_RAST | PIPE_NEW_FRAGMENT_SIGNATURE),
.brw = (BRW_NEW_REDUCED_PRIMITIVE),
- .cache = CACHE_NEW_VS_PROG
+ .cache = 0
},
.prepare = upload_sf_prog
};