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:
@@ -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)
|
||||||
|
@@ -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];
|
||||||
|
@@ -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
|
||||||
|
@@ -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 */
|
||||||
|
@@ -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 {
|
||||||
|
@@ -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,
|
||||||
|
Reference in New Issue
Block a user