gallium: remove use of origin_lower_left

This was used to indicate OpenGL's lower-left origin for fragment window
coordinates for polygon stipple and gl_FragCoord.

Now:
  - fragment coordinate origin is always upper-left corner
  - GL polygon stipple is inverted and shifted before given to gallium
  - GL fragment programs that use INPUT[WPOS] are modified to use an
    inverted window coord which is placed in a temp register.

Note: the origin_lower_left field still exists in pipe_rasterizer_state.
Remove it when all the drivers, etc. no longer reference it.
This commit is contained in:
Brian Paul
2009-03-20 20:25:34 -06:00
parent 1f45ae0813
commit 401cbd0d23
6 changed files with 207 additions and 53 deletions

View File

@@ -22,21 +22,11 @@ stipple_quad(struct quad_stage *qs, struct quad_header *quad)
if (quad->input.prim == QUAD_PRIM_TRI) { if (quad->input.prim == QUAD_PRIM_TRI) {
struct softpipe_context *softpipe = qs->softpipe; struct softpipe_context *softpipe = qs->softpipe;
/* need to invert Y to index into OpenGL's stipple pattern */ /* need to invert Y to index into OpenGL's stipple pattern */
int y0, y1;
uint stipple0, stipple1;
const int col0 = quad->input.x0 % 32; const int col0 = quad->input.x0 % 32;
const int y0 = quad->input.y0;
if (softpipe->rasterizer->origin_lower_left) { const int y1 = y0 + 1;
y0 = softpipe->framebuffer.height - 1 - quad->input.y0; const uint stipple0 = softpipe->poly_stipple.stipple[y0 % 32];
y1 = y0 - 1; const uint stipple1 = softpipe->poly_stipple.stipple[y1 % 32];
}
else {
y0 = quad->input.y0;
y1 = y0 + 1;
}
stipple0 = softpipe->poly_stipple.stipple[y0 % 32];
stipple1 = softpipe->poly_stipple.stipple[y1 % 32];
/* turn off quad mask bits that fail the stipple test */ /* turn off quad mask bits that fail the stipple test */
if ((stipple0 & (bit31 >> col0)) == 0) if ((stipple0 & (bit31 >> col0)) == 0)

View File

@@ -732,18 +732,9 @@ setup_fragcoord_coeff(struct setup_context *setup, uint slot)
setup->coef[slot].dadx[0] = 1.0; setup->coef[slot].dadx[0] = 1.0;
setup->coef[slot].dady[0] = 0.0; setup->coef[slot].dady[0] = 0.0;
/*Y*/ /*Y*/
if (setup->softpipe->rasterizer->origin_lower_left) { setup->coef[slot].a0[1] = 0.0;
/* y=0=bottom */
const int winHeight = setup->softpipe->framebuffer.height;
setup->coef[slot].a0[1] = (float) (winHeight - 1);
setup->coef[slot].dady[1] = -1.0;
}
else {
/* y=0=top */
setup->coef[slot].a0[1] = 0.0;
setup->coef[slot].dady[1] = 1.0;
}
setup->coef[slot].dadx[1] = 0.0; setup->coef[slot].dadx[1] = 0.0;
setup->coef[slot].dady[1] = 1.0;
/*Z*/ /*Z*/
setup->coef[slot].a0[2] = setup->posCoef.a0[2]; setup->coef[slot].a0[2] = setup->posCoef.a0[2];
setup->coef[slot].dadx[2] = setup->posCoef.dadx[2]; setup->coef[slot].dadx[2] = setup->posCoef.dadx[2];

View File

@@ -79,6 +79,7 @@ static void update_raster_state( struct st_context *st )
memset(raster, 0, sizeof(*raster)); memset(raster, 0, sizeof(*raster));
/* XXX obsolete field, remove someday */
raster->origin_lower_left = 1; /* Always true for OpenGL */ raster->origin_lower_left = 1; /* Always true for OpenGL */
/* _NEW_POLYGON, _NEW_BUFFERS /* _NEW_POLYGON, _NEW_BUFFERS

View File

@@ -39,24 +39,52 @@
#include "pipe/p_defines.h" #include "pipe/p_defines.h"
static void /**
update_stipple( struct st_context *st ) * OpenGL's polygon stipple is indexed with window coordinates in which
* the origin (0,0) is the lower-left corner of the window.
* With Gallium, the origin is the upper-left corner of the window.
* To convert GL's polygon stipple to what gallium expects we need to
* invert the pattern vertically and rotate the stipple rows according
* to the window height.
*/
static void
invert_stipple(GLuint dest[32], const GLuint src[32], GLuint winHeight)
{ {
const GLuint sz = sizeof(st->state.poly_stipple.stipple); GLuint i;
assert(sz == sizeof(st->ctx->PolygonStipple));
if (memcmp(&st->state.poly_stipple.stipple, st->ctx->PolygonStipple, sz)) { for (i = 0; i < 32; i++) {
/* state has changed */ dest[i] = src[(winHeight - 1 - i) & 0x1f];
memcpy(st->state.poly_stipple.stipple, st->ctx->PolygonStipple, sz);
st->pipe->set_polygon_stipple(st->pipe, &st->state.poly_stipple);
} }
} }
static void
update_stipple( struct st_context *st )
{
const GLuint sz = sizeof(st->state.poly_stipple);
assert(sz == sizeof(st->ctx->PolygonStipple));
if (memcmp(st->state.poly_stipple, st->ctx->PolygonStipple, sz)) {
/* state has changed */
struct pipe_poly_stipple newStipple;
memcpy(st->state.poly_stipple, st->ctx->PolygonStipple, sz);
invert_stipple(newStipple.stipple, st->ctx->PolygonStipple,
st->ctx->DrawBuffer->Height);
st->pipe->set_polygon_stipple(st->pipe, &newStipple);
}
}
/** Update the stipple when the pattern or window height changes */
const struct st_tracked_state st_update_polygon_stipple = { const struct st_tracked_state st_update_polygon_stipple = {
"st_update_polygon_stipple", /* name */ "st_update_polygon_stipple", /* name */
{ /* dirty */ { /* dirty */
(_NEW_POLYGONSTIPPLE), /* mesa */ (_NEW_POLYGONSTIPPLE |
_NEW_BUFFERS), /* mesa */
0, /* st */ 0, /* st */
}, },
update_stipple /* update */ update_stipple /* update */

View File

@@ -93,12 +93,13 @@ struct st_context
struct pipe_constant_buffer constants[2]; struct pipe_constant_buffer constants[2];
struct pipe_framebuffer_state framebuffer; struct pipe_framebuffer_state framebuffer;
struct pipe_texture *sampler_texture[PIPE_MAX_SAMPLERS]; struct pipe_texture *sampler_texture[PIPE_MAX_SAMPLERS];
struct pipe_poly_stipple poly_stipple;
struct pipe_scissor_state scissor; struct pipe_scissor_state scissor;
struct pipe_viewport_state viewport; struct pipe_viewport_state viewport;
GLuint num_samplers; GLuint num_samplers;
GLuint num_textures; GLuint num_textures;
GLuint poly_stipple[32]; /**< In OpenGL's bottom-to-top order */
} state; } state;
struct { struct {

View File

@@ -219,8 +219,9 @@ compile_instruction(
const GLuint immediateMapping[], const GLuint immediateMapping[],
GLboolean indirectAccess, GLboolean indirectAccess,
GLuint preamble_size, GLuint preamble_size,
GLuint processor, GLuint procType,
GLboolean *insideSubroutine) GLboolean *insideSubroutine,
GLint wposTemp)
{ {
GLuint i; GLuint i;
struct tgsi_full_dst_register *fulldst; struct tgsi_full_dst_register *fulldst;
@@ -247,19 +248,29 @@ compile_instruction(
GLuint j; GLuint j;
fullsrc = &fullinst->FullSrcRegisters[i]; fullsrc = &fullinst->FullSrcRegisters[i];
fullsrc->SrcRegister.File = map_register_file(
inst->SrcReg[i].File,
inst->SrcReg[i].Index,
immediateMapping,
indirectAccess );
fullsrc->SrcRegister.Index = map_register_file_index(
fullsrc->SrcRegister.File,
inst->SrcReg[i].Index,
inputMapping,
outputMapping,
immediateMapping,
indirectAccess );
if (procType == TGSI_PROCESSOR_FRAGMENT &&
inst->SrcReg[i].File == PROGRAM_INPUT &&
inst->SrcReg[i].Index == FRAG_ATTRIB_WPOS) {
/* special case of INPUT[WPOS] */
fullsrc->SrcRegister.File = TGSI_FILE_TEMPORARY;
fullsrc->SrcRegister.Index = wposTemp;
}
else {
/* any other src register */
fullsrc->SrcRegister.File = map_register_file(
inst->SrcReg[i].File,
inst->SrcReg[i].Index,
immediateMapping,
indirectAccess );
fullsrc->SrcRegister.Index = map_register_file_index(
fullsrc->SrcRegister.File,
inst->SrcReg[i].Index,
inputMapping,
outputMapping,
immediateMapping,
indirectAccess );
}
/* swizzle (ext swizzle also depends on negation) */ /* swizzle (ext swizzle also depends on negation) */
{ {
@@ -733,6 +744,111 @@ find_temporaries(const struct gl_program *program,
} }
/**
* Find an unused temporary in the tempsUsed array.
*/
static int
find_free_temporary(GLboolean tempsUsed[MAX_PROGRAM_TEMPS])
{
int i;
for (i = 0; i < MAX_PROGRAM_TEMPS; i++) {
if (!tempsUsed[i]) {
tempsUsed[i] = GL_TRUE;
return i;
}
}
return -1;
}
/** helper for building simple TGSI instruction, one src register */
static void
build_tgsi_instruction1(struct tgsi_full_instruction *inst,
int opcode,
int dstFile, int dstIndex, int writemask,
int srcFile1, int srcIndex1)
{
*inst = tgsi_default_full_instruction();
inst->Instruction.Opcode = opcode;
inst->Instruction.NumDstRegs = 1;
inst->FullDstRegisters[0].DstRegister.File = dstFile;
inst->FullDstRegisters[0].DstRegister.Index = dstIndex;
inst->FullDstRegisters[0].DstRegister.WriteMask = writemask;
inst->Instruction.NumSrcRegs = 1;
inst->FullSrcRegisters[0].SrcRegister.File = srcFile1;
inst->FullSrcRegisters[0].SrcRegister.Index = srcIndex1;
}
/** helper for building simple TGSI instruction, two src registers */
static void
build_tgsi_instruction2(struct tgsi_full_instruction *inst,
int opcode,
int dstFile, int dstIndex, int writemask,
int srcFile1, int srcIndex1,
int srcFile2, int srcIndex2)
{
*inst = tgsi_default_full_instruction();
inst->Instruction.Opcode = opcode;
inst->Instruction.NumDstRegs = 1;
inst->FullDstRegisters[0].DstRegister.File = dstFile;
inst->FullDstRegisters[0].DstRegister.Index = dstIndex;
inst->FullDstRegisters[0].DstRegister.WriteMask = writemask;
inst->Instruction.NumSrcRegs = 2;
inst->FullSrcRegisters[0].SrcRegister.File = srcFile1;
inst->FullSrcRegisters[0].SrcRegister.Index = srcIndex1;
inst->FullSrcRegisters[1].SrcRegister.File = srcFile2;
inst->FullSrcRegisters[1].SrcRegister.Index = srcIndex2;
}
/**
* Emit the TGSI instructions for inverting the WPOS y coordinate.
*/
static int
emit_inverted_wpos(struct tgsi_token *tokens,
int wpos_temp,
int winsize_const,
int wpos_input,
struct tgsi_header *header, int maxTokens)
{
struct tgsi_full_instruction fullinst;
int ti = 0;
/* MOV wpos_temp.xzw, input[wpos]; */
build_tgsi_instruction1(&fullinst,
TGSI_OPCODE_MOV,
TGSI_FILE_TEMPORARY, wpos_temp, WRITEMASK_XZW,
TGSI_FILE_INPUT, 0);
ti += tgsi_build_full_instruction(&fullinst,
&tokens[ti],
header,
maxTokens - ti);
/* SUB wpos_temp.y, const[winsize_const] - input[wpos_input]; */
build_tgsi_instruction2(&fullinst,
TGSI_OPCODE_SUB,
TGSI_FILE_TEMPORARY, wpos_temp, WRITEMASK_Y,
TGSI_FILE_CONSTANT, winsize_const,
TGSI_FILE_INPUT, wpos_input);
ti += tgsi_build_full_instruction(&fullinst,
&tokens[ti],
header,
maxTokens - ti);
return ti;
}
/** /**
@@ -778,16 +894,34 @@ st_translate_mesa_program(
GLuint ti; /* token index */ GLuint ti; /* token index */
struct tgsi_header *header; struct tgsi_header *header;
struct tgsi_processor *processor; struct tgsi_processor *processor;
struct tgsi_full_instruction fullinst;
GLuint preamble_size = 0; GLuint preamble_size = 0;
GLuint immediates[1000]; GLuint immediates[1000];
GLuint numImmediates = 0; GLuint numImmediates = 0;
GLboolean insideSubroutine = GL_FALSE; GLboolean insideSubroutine = GL_FALSE;
GLboolean indirectAccess = GL_FALSE; GLboolean indirectAccess = GL_FALSE;
GLboolean tempsUsed[MAX_PROGRAM_TEMPS + 1];
GLint wposTemp = -1, winHeightConst = -1;
assert(procType == TGSI_PROCESSOR_FRAGMENT || assert(procType == TGSI_PROCESSOR_FRAGMENT ||
procType == TGSI_PROCESSOR_VERTEX); procType == TGSI_PROCESSOR_VERTEX);
find_temporaries(program, tempsUsed);
if (procType == TGSI_PROCESSOR_FRAGMENT) {
if (program->InputsRead & FRAG_BIT_WPOS) {
/* Fragment program uses fragment position input.
* Need to replace instances of INPUT[WPOS] with temp T
* where T = INPUT[WPOS] by y is inverted.
*/
static const gl_state_index winSizeState[STATE_LENGTH]
= { STATE_INTERNAL, STATE_FB_SIZE, 0, 0, 0 };
winHeightConst = _mesa_add_state_reference(program->Parameters,
winSizeState);
wposTemp = find_free_temporary(tempsUsed);
}
}
*(struct tgsi_version *) &tokens[0] = tgsi_build_version(); *(struct tgsi_version *) &tokens[0] = tgsi_build_version();
header = (struct tgsi_header *) &tokens[1]; header = (struct tgsi_header *) &tokens[1];
@@ -884,11 +1018,9 @@ st_translate_mesa_program(
/* temporary decls */ /* temporary decls */
{ {
GLboolean tempsUsed[MAX_PROGRAM_TEMPS + 1];
GLboolean inside_range = GL_FALSE; GLboolean inside_range = GL_FALSE;
GLuint start_range = 0; GLuint start_range = 0;
find_temporaries(program, tempsUsed);
tempsUsed[MAX_PROGRAM_TEMPS] = GL_FALSE; tempsUsed[MAX_PROGRAM_TEMPS] = GL_FALSE;
for (i = 0; i < MAX_PROGRAM_TEMPS + 1; i++) { for (i = 0; i < MAX_PROGRAM_TEMPS + 1; i++) {
if (tempsUsed[i] && !inside_range) { if (tempsUsed[i] && !inside_range) {
@@ -1018,7 +1150,17 @@ st_translate_mesa_program(
} }
} }
/* invert WPOS fragment input */
if (wposTemp >= 0) {
ti += emit_inverted_wpos(&tokens[ti], wposTemp, winHeightConst,
inputMapping[FRAG_ATTRIB_WPOS],
header, maxTokens - ti);
preamble_size = 2; /* two instructions added */
}
for (i = 0; i < program->NumInstructions; i++) { for (i = 0; i < program->NumInstructions; i++) {
struct tgsi_full_instruction fullinst;
compile_instruction( compile_instruction(
&program->Instructions[i], &program->Instructions[i],
&fullinst, &fullinst,
@@ -1028,7 +1170,8 @@ st_translate_mesa_program(
indirectAccess, indirectAccess,
preamble_size, preamble_size,
procType, procType,
&insideSubroutine ); &insideSubroutine,
wposTemp);
ti += tgsi_build_full_instruction( ti += tgsi_build_full_instruction(
&fullinst, &fullinst,