summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/gallium/drivers/softpipe/sp_quad_stipple.c18
-rw-r--r--src/gallium/drivers/softpipe/sp_setup.c13
-rw-r--r--src/mesa/state_tracker/st_atom_rasterizer.c1
-rw-r--r--src/mesa/state_tracker/st_atom_stipple.c38
-rw-r--r--src/mesa/state_tracker/st_context.h3
-rw-r--r--src/mesa/state_tracker/st_mesa_to_tgsi.c179
6 files changed, 203 insertions, 49 deletions
diff --git a/src/gallium/drivers/softpipe/sp_quad_stipple.c b/src/gallium/drivers/softpipe/sp_quad_stipple.c
index 05e862f0977..07162db7b6e 100644
--- a/src/gallium/drivers/softpipe/sp_quad_stipple.c
+++ b/src/gallium/drivers/softpipe/sp_quad_stipple.c
@@ -22,21 +22,11 @@ stipple_quad(struct quad_stage *qs, struct quad_header *quad)
if (quad->input.prim == QUAD_PRIM_TRI) {
struct softpipe_context *softpipe = qs->softpipe;
/* need to invert Y to index into OpenGL's stipple pattern */
- int y0, y1;
- uint stipple0, stipple1;
const int col0 = quad->input.x0 % 32;
-
- if (softpipe->rasterizer->origin_lower_left) {
- y0 = softpipe->framebuffer.height - 1 - quad->input.y0;
- y1 = y0 - 1;
- }
- else {
- y0 = quad->input.y0;
- y1 = y0 + 1;
- }
-
- stipple0 = softpipe->poly_stipple.stipple[y0 % 32];
- stipple1 = softpipe->poly_stipple.stipple[y1 % 32];
+ const int y0 = quad->input.y0;
+ const int y1 = y0 + 1;
+ const uint stipple0 = softpipe->poly_stipple.stipple[y0 % 32];
+ const uint stipple1 = softpipe->poly_stipple.stipple[y1 % 32];
/* turn off quad mask bits that fail the stipple test */
if ((stipple0 & (bit31 >> col0)) == 0)
diff --git a/src/gallium/drivers/softpipe/sp_setup.c b/src/gallium/drivers/softpipe/sp_setup.c
index 0925653b5d5..96cb09b9051 100644
--- a/src/gallium/drivers/softpipe/sp_setup.c
+++ b/src/gallium/drivers/softpipe/sp_setup.c
@@ -732,18 +732,9 @@ setup_fragcoord_coeff(struct setup_context *setup, uint slot)
setup->coef[slot].dadx[0] = 1.0;
setup->coef[slot].dady[0] = 0.0;
/*Y*/
- if (setup->softpipe->rasterizer->origin_lower_left) {
- /* 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].a0[1] = 0.0;
setup->coef[slot].dadx[1] = 0.0;
+ setup->coef[slot].dady[1] = 1.0;
/*Z*/
setup->coef[slot].a0[2] = setup->posCoef.a0[2];
setup->coef[slot].dadx[2] = setup->posCoef.dadx[2];
diff --git a/src/mesa/state_tracker/st_atom_rasterizer.c b/src/mesa/state_tracker/st_atom_rasterizer.c
index ea76487bcfc..5bdcaa4a014 100644
--- a/src/mesa/state_tracker/st_atom_rasterizer.c
+++ b/src/mesa/state_tracker/st_atom_rasterizer.c
@@ -79,6 +79,7 @@ static void update_raster_state( struct st_context *st )
memset(raster, 0, sizeof(*raster));
+ /* XXX obsolete field, remove someday */
raster->origin_lower_left = 1; /* Always true for OpenGL */
/* _NEW_POLYGON, _NEW_BUFFERS
diff --git a/src/mesa/state_tracker/st_atom_stipple.c b/src/mesa/state_tracker/st_atom_stipple.c
index f395930ab40..31e124b3293 100644
--- a/src/mesa/state_tracker/st_atom_stipple.c
+++ b/src/mesa/state_tracker/st_atom_stipple.c
@@ -39,24 +39,52 @@
#include "pipe/p_defines.h"
+/**
+ * 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)
+{
+ GLuint i;
+
+ for (i = 0; i < 32; i++) {
+ dest[i] = src[(winHeight - 1 - i) & 0x1f];
+ }
+}
+
+
+
static void
update_stipple( struct st_context *st )
{
- const GLuint sz = sizeof(st->state.poly_stipple.stipple);
+ const GLuint sz = sizeof(st->state.poly_stipple);
assert(sz == sizeof(st->ctx->PolygonStipple));
- if (memcmp(&st->state.poly_stipple.stipple, st->ctx->PolygonStipple, sz)) {
+ if (memcmp(st->state.poly_stipple, st->ctx->PolygonStipple, sz)) {
/* state has changed */
- memcpy(st->state.poly_stipple.stipple, st->ctx->PolygonStipple, sz);
- st->pipe->set_polygon_stipple(st->pipe, &st->state.poly_stipple);
+ 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 = {
"st_update_polygon_stipple", /* name */
{ /* dirty */
- (_NEW_POLYGONSTIPPLE), /* mesa */
+ (_NEW_POLYGONSTIPPLE |
+ _NEW_BUFFERS), /* mesa */
0, /* st */
},
update_stipple /* update */
diff --git a/src/mesa/state_tracker/st_context.h b/src/mesa/state_tracker/st_context.h
index d7518ab6897..ae8c2978bf8 100644
--- a/src/mesa/state_tracker/st_context.h
+++ b/src/mesa/state_tracker/st_context.h
@@ -93,12 +93,13 @@ struct st_context
struct pipe_constant_buffer constants[2];
struct pipe_framebuffer_state framebuffer;
struct pipe_texture *sampler_texture[PIPE_MAX_SAMPLERS];
- struct pipe_poly_stipple poly_stipple;
struct pipe_scissor_state scissor;
struct pipe_viewport_state viewport;
GLuint num_samplers;
GLuint num_textures;
+
+ GLuint poly_stipple[32]; /**< In OpenGL's bottom-to-top order */
} state;
struct {
diff --git a/src/mesa/state_tracker/st_mesa_to_tgsi.c b/src/mesa/state_tracker/st_mesa_to_tgsi.c
index cbf3f334c08..ffa607dd87c 100644
--- a/src/mesa/state_tracker/st_mesa_to_tgsi.c
+++ b/src/mesa/state_tracker/st_mesa_to_tgsi.c
@@ -219,8 +219,9 @@ compile_instruction(
const GLuint immediateMapping[],
GLboolean indirectAccess,
GLuint preamble_size,
- GLuint processor,
- GLboolean *insideSubroutine)
+ GLuint procType,
+ GLboolean *insideSubroutine,
+ GLint wposTemp)
{
GLuint i;
struct tgsi_full_dst_register *fulldst;
@@ -247,19 +248,29 @@ compile_instruction(
GLuint j;
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) */
{
@@ -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 */
struct tgsi_header *header;
struct tgsi_processor *processor;
- struct tgsi_full_instruction fullinst;
GLuint preamble_size = 0;
GLuint immediates[1000];
GLuint numImmediates = 0;
GLboolean insideSubroutine = GL_FALSE;
GLboolean indirectAccess = GL_FALSE;
+ GLboolean tempsUsed[MAX_PROGRAM_TEMPS + 1];
+ GLint wposTemp = -1, winHeightConst = -1;
assert(procType == TGSI_PROCESSOR_FRAGMENT ||
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();
header = (struct tgsi_header *) &tokens[1];
@@ -884,11 +1018,9 @@ st_translate_mesa_program(
/* temporary decls */
{
- GLboolean tempsUsed[MAX_PROGRAM_TEMPS + 1];
GLboolean inside_range = GL_FALSE;
GLuint start_range = 0;
- find_temporaries(program, tempsUsed);
tempsUsed[MAX_PROGRAM_TEMPS] = GL_FALSE;
for (i = 0; i < MAX_PROGRAM_TEMPS + 1; i++) {
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++) {
+ struct tgsi_full_instruction fullinst;
+
compile_instruction(
&program->Instructions[i],
&fullinst,
@@ -1028,7 +1170,8 @@ st_translate_mesa_program(
indirectAccess,
preamble_size,
procType,
- &insideSubroutine );
+ &insideSubroutine,
+ wposTemp);
ti += tgsi_build_full_instruction(
&fullinst,