#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;
c.prog_data.urb_read_length = c.nr_attr_regs;
c.prog_data.urb_entry_size = c.nr_setup_regs * 2;
-
- /* Which primitive? Or all three?
+ /* 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
*/
- 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;
+ 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;
+ }
}
/* 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 int 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.nr_attrs = brw->curr.vertex_shader->info.file_max[TGSI_FILE_OUTPUT] + 1;
+ /* XXX: Add one to account for the position input.
+ */
+ /* PIPE_NEW_FRAGMENT_SIGNATURE */
+ key.nr_attrs = sig->nr_inputs + 1;
- /* XXX: this is probably where the mapping between vertex shader
- * outputs and fragment shader inputs should be handled. Assume
- * for now 1:1 correspondance.
- *
- * XXX: scan frag shader inputs to work out linear vs. perspective
- * interpolation below.
- *
- * XXX: as long as we're hard-wiring, is eg. position required to
- * be linear?
+
+ /* XXX: why is position required to be linear? why do we care
+ * about it at all?
*/
- key.linear_attrs = 0;
- key.persp_attrs = (1 << key.nr_attrs) - 1;
+ 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 PIPE_PRIM_TRIANGLES:
/* PIPE_NEW_RAST
*/
- if (brw->curr.rast->templ.fill_cw != PIPE_POLYGON_MODE_FILL ||
- brw->curr.rast->templ.fill_ccw != PIPE_POLYGON_MODE_FILL)
+ 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;
}
- key.do_point_sprite = brw->curr.rast->templ.point_sprite;
- key.sprite_origin_lower_left = 0; /* XXX: ctx->Point.SpriteOrigin - fix rast state */
- key.do_flat_shading = brw->curr.rast->templ.flatshade;
- key.do_twoside_color = brw->curr.rast->templ.light_twoside;
+ 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;
if (key.do_twoside_color) {
- key.frontface_ccw = (brw->curr.rast->templ.front_winding ==
- PIPE_WINDING_CCW);
+ 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 0;
+ return PIPE_OK;
}
const struct brw_tracked_state brw_sf_prog = {
.dirty = {
- .mesa = (PIPE_NEW_RAST | PIPE_NEW_VERTEX_SHADER),
+ .mesa = (PIPE_NEW_RAST | PIPE_NEW_FRAGMENT_SIGNATURE),
.brw = (BRW_NEW_REDUCED_PRIMITIVE),
.cache = 0
},