gallium: remove use of origin_lower_left
authorBrian Paul <brianp@vmware.com>
Sat, 21 Mar 2009 02:25:34 +0000 (20:25 -0600)
committerBrian Paul <brianp@vmware.com>
Sat, 21 Mar 2009 02:29:07 +0000 (20:29 -0600)
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.

src/gallium/drivers/softpipe/sp_quad_stipple.c
src/gallium/drivers/softpipe/sp_setup.c
src/mesa/state_tracker/st_atom_rasterizer.c
src/mesa/state_tracker/st_atom_stipple.c
src/mesa/state_tracker/st_context.h
src/mesa/state_tracker/st_mesa_to_tgsi.c

index 05e862f0977bf41d4aeeda47f39a04ddad3a71cd..07162db7b6e0864dc1b374bf19d3ca2057a6b017 100644 (file)
@@ -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)
index 0925653b5d54234e496e2d799e80f0e7228233d2..96cb09b9051e674235239b7fc6fb0589010b5129 100644 (file)
@@ -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];
index ea76487bcfc885f0a7dbfa9e05d931ba6177d5b5..5bdcaa4a0147544a9244803f32a08825d6dd6c1f 100644 (file)
@@ -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
index f395930ab40343bc2e89f9686bf194300a69ad96..31e124b32935a4d20bd6f02fd7b27e4afe6eb9e6 100644 (file)
 #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 */
index d7518ab689765461306d1f85ab02fb9cff27f77a..ae8c2978bf83742ad6d2cc57ae02e22f3ac0b2c4 100644 (file)
@@ -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 {
index cbf3f334c08c4bc74c3a942f94289dc4eca505a3..ffa607dd87c858b3e748906535c195a4206b35c5 100644 (file)
@@ -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,