blob: 2117e91a9e453bd99b0a100a5e625f753b64d55d [file] [log] [blame]
#include "util/u_memory.h"
#include "pipe/p_defines.h"
#include "brw_context.h"
#include "brw_defines.h"
#include "brw_pipe_rast.h"
#include "brw_wm.h"
static unsigned translate_fill( unsigned fill )
{
switch (fill) {
case PIPE_POLYGON_MODE_FILL:
return CLIP_FILL;
case PIPE_POLYGON_MODE_LINE:
return CLIP_LINE;
case PIPE_POLYGON_MODE_POINT:
return CLIP_POINT;
default:
assert(0);
return CLIP_FILL;
}
}
/* Calculates the key for triangle-mode clipping. Non-triangle
* clipping keys use much less information and are computed on the
* fly.
*/
static void
calculate_clip_key_rast( const struct brw_context *brw,
const struct pipe_rasterizer_state *templ,
const struct brw_rasterizer_state *rast,
struct brw_clip_prog_key *key)
{
memset(key, 0, sizeof *key);
if (brw->chipset.is_igdng)
key->clip_mode = BRW_CLIPMODE_KERNEL_CLIP;
else
key->clip_mode = BRW_CLIPMODE_NORMAL;
key->do_flat_shading = templ->flatshade;
if (templ->cull_mode == PIPE_WINDING_BOTH) {
key->clip_mode = BRW_CLIPMODE_REJECT_ALL;
return;
}
key->fill_ccw = CLIP_CULL;
key->fill_cw = CLIP_CULL;
if (!(templ->cull_mode & PIPE_WINDING_CCW)) {
key->fill_ccw = translate_fill(templ->fill_ccw);
}
if (!(templ->cull_mode & PIPE_WINDING_CW)) {
key->fill_cw = translate_fill(templ->fill_cw);
}
if (key->fill_cw == CLIP_LINE ||
key->fill_ccw == CLIP_LINE ||
key->fill_cw == CLIP_POINT ||
key->fill_ccw == CLIP_POINT) {
key->do_unfilled = 1;
key->clip_mode = BRW_CLIPMODE_CLIP_NON_REJECTED;
}
key->offset_ccw = templ->offset_ccw;
key->offset_cw = templ->offset_cw;
if (templ->light_twoside && key->fill_cw != CLIP_CULL)
key->copy_bfc_cw = 1;
if (templ->light_twoside && key->fill_ccw != CLIP_CULL)
key->copy_bfc_ccw = 1;
}
static void
calculate_line_stipple_rast( const struct pipe_rasterizer_state *templ,
struct brw_line_stipple *bls )
{
GLfloat tmp = 1.0f / (templ->line_stipple_factor + 1);
GLint tmpi = tmp * (1<<13);
bls->header.opcode = CMD_LINE_STIPPLE_PATTERN;
bls->header.length = sizeof(*bls)/4 - 2;
bls->bits0.pattern = templ->line_stipple_pattern;
bls->bits1.repeat_count = templ->line_stipple_factor + 1;
bls->bits1.inverse_repeat_count = tmpi;
}
static void *brw_create_rasterizer_state( struct pipe_context *pipe,
const struct pipe_rasterizer_state *templ )
{
struct brw_context *brw = brw_context(pipe);
struct brw_rasterizer_state *rast;
rast = CALLOC_STRUCT(brw_rasterizer_state);
if (rast == NULL)
return NULL;
rast->templ = *templ;
calculate_clip_key_rast( brw, templ, rast, &rast->clip_key );
if (templ->line_stipple_enable)
calculate_line_stipple_rast( templ, &rast->bls );
/* Caclculate lookup value for WM IZ table.
*/
if (templ->line_smooth) {
if (templ->fill_cw == PIPE_POLYGON_MODE_LINE &&
templ->fill_ccw == PIPE_POLYGON_MODE_LINE) {
rast->unfilled_aa_line = AA_ALWAYS;
}
else if (templ->fill_cw == PIPE_POLYGON_MODE_LINE ||
templ->fill_ccw == PIPE_POLYGON_MODE_LINE) {
rast->unfilled_aa_line = AA_SOMETIMES;
}
else {
rast->unfilled_aa_line = AA_NEVER;
}
}
else {
rast->unfilled_aa_line = AA_NEVER;
}
return (void *)rast;
}
static void brw_bind_rasterizer_state(struct pipe_context *pipe,
void *cso)
{
struct brw_context *brw = brw_context(pipe);
brw->curr.rast = (const struct brw_rasterizer_state *)cso;
brw->state.dirty.mesa |= PIPE_NEW_RAST;
}
static void brw_delete_rasterizer_state(struct pipe_context *pipe,
void *cso)
{
struct brw_context *brw = brw_context(pipe);
assert((const void *)cso != (const void *)brw->curr.rast);
FREE(cso);
}
void brw_pipe_rast_init( struct brw_context *brw )
{
brw->base.create_rasterizer_state = brw_create_rasterizer_state;
brw->base.bind_rasterizer_state = brw_bind_rasterizer_state;
brw->base.delete_rasterizer_state = brw_delete_rasterizer_state;
}
void brw_pipe_rast_cleanup( struct brw_context *brw )
{
}