Example #1
0
void emit_math1(struct brw_wm_compile *c,
		GLuint function,
		const struct brw_reg *dst,
		GLuint mask,
		const struct brw_reg *arg0)
{
   struct brw_compile *p = &c->func;
   struct intel_context *intel = &p->brw->intel;
   int dst_chan = _mesa_ffs(mask & WRITEMASK_XYZW) - 1;
   GLuint saturate = ((mask & SATURATE) ?
		      BRW_MATH_SATURATE_SATURATE :
		      BRW_MATH_SATURATE_NONE);
   struct brw_reg src;

   if (!(mask & WRITEMASK_XYZW))
      return; /* Do not emit dead code */

   assert(is_power_of_two(mask & WRITEMASK_XYZW));

   if (intel->gen >= 6 && ((arg0[0].hstride == BRW_HORIZONTAL_STRIDE_0 ||
			    arg0[0].file != BRW_GENERAL_REGISTER_FILE) ||
			   arg0[0].negate || arg0[0].abs)) {
      /* Gen6 math requires that source and dst horizontal stride be 1,
       * and that the argument be in the GRF.
       *
       * The hardware ignores source modifiers (negate and abs) on math
       * instructions, so we also move to a temp to set those up.
       */
      src = dst[dst_chan];
      brw_MOV(p, src, arg0[0]);
   } else {
      src = arg0[0];
   }

   /* Send two messages to perform all 16 operations:
    */
   brw_push_insn_state(p);
   brw_set_compression_control(p, BRW_COMPRESSION_NONE);
   brw_math(p,
	    dst[dst_chan],
	    function,
	    saturate,
	    2,
	    src,
	    BRW_MATH_DATA_VECTOR,
	    BRW_MATH_PRECISION_FULL);

   if (c->dispatch_width == 16) {
      brw_set_compression_control(p, BRW_COMPRESSION_2NDHALF);
      brw_math(p,
	       offset(dst[dst_chan],1),
	       function,
	       saturate,
	       3,
	       sechalf(src),
	       BRW_MATH_DATA_VECTOR,
	       BRW_MATH_PRECISION_FULL);
   }
   brw_pop_insn_state(p);
}
Example #2
0
/* Many Mesa opcodes produce the same value across all the result channels.
 * We'd rather not have to support that splatting in the opcode implementations,
 * and brw_wm_pass*.c wants to optimize them out by shuffling references around
 * anyway.  We can easily get both by emitting the opcode to one channel, and
 * then MOVing it to the others, which brw_wm_pass*.c already understands.
 */
static struct prog_instruction *emit_scalar_insn(struct brw_wm_compile *c,
						 const struct prog_instruction *inst0)
{
   struct prog_instruction *inst;
   unsigned int dst_chan;
   unsigned int other_channel_mask;

   if (inst0->DstReg.WriteMask == 0)
      return NULL;

   dst_chan = _mesa_ffs(inst0->DstReg.WriteMask) - 1;
   inst = get_fp_inst(c);
   *inst = *inst0;
   inst->DstReg.WriteMask = 1 << dst_chan;

   other_channel_mask = inst0->DstReg.WriteMask & ~(1 << dst_chan);
   if (other_channel_mask != 0) {
      inst = emit_op(c,
		     OPCODE_MOV,
		     dst_mask(inst0->DstReg, other_channel_mask),
		     0,
		     src_swizzle1(src_reg_from_dst(inst0->DstReg), dst_chan),
		     src_undef(),
		     src_undef());
   }
   return inst;
}
Example #3
0
/**
 * Print a fragment program's InputsRead field in human-readable format.
 * For debugging.
 */
void
_mesa_print_fp_inputs(GLbitfield inputs)
{
   printf("FP Inputs 0x%x: \n", inputs);
   while (inputs) {
      GLint attr = _mesa_ffs(inputs) - 1;
      const char *name = arb_input_attrib_string(attr,
                                                 GL_FRAGMENT_PROGRAM_ARB);
      printf("  %d: %s\n", attr, name);
      inputs &= ~(1 << attr);
   }
}
Example #4
0
static struct prog_dst_register get_temp( struct brw_wm_compile *c )
{
   int bit = _mesa_ffs( ~c->fp_temp );

   if (!bit) {
      printf("%s: out of temporaries\n", __FILE__);
      exit(1);
   }

   c->fp_temp |= 1<<(bit-1);
   return dst_reg(PROGRAM_TEMPORARY, FIRST_INTERNAL_TEMP+(bit-1));
}
Example #5
0
static struct ureg get_temp( struct tnl_program *p )
{
   int bit = _mesa_ffs( ~p->temp_in_use );
   if (!bit) {
      _mesa_problem(NULL, "%s: out of temporaries\n", __FILE__);
      _mesa_exit(1);
   }

   if ((GLuint) bit > p->program->Base.NumTemporaries)
      p->program->Base.NumTemporaries = bit;

   p->temp_in_use |= 1<<(bit-1);
   return make_ureg(PROGRAM_TEMPORARY, bit-1);
}
Example #6
0
void emit_dp2(struct brw_compile *p,
	      const struct brw_reg *dst,
	      GLuint mask,
	      const struct brw_reg *arg0,
	      const struct brw_reg *arg1)
{
   int dst_chan = _mesa_ffs(mask & WRITEMASK_XYZW) - 1;

   if (!(mask & WRITEMASK_XYZW))
      return; /* Do not emit dead code */

   assert(is_power_of_two(mask & WRITEMASK_XYZW));

   brw_MUL(p, brw_null_reg(), arg0[0], arg1[0]);

   brw_set_saturate(p, (mask & SATURATE) ? 1 : 0);
   brw_MAC(p, dst[dst_chan], arg0[1], arg1[1]);
   brw_set_saturate(p, 0);
}
Example #7
0
void emit_math2(struct brw_wm_compile *c,
		GLuint function,
		const struct brw_reg *dst,
		GLuint mask,
		const struct brw_reg *arg0,
		const struct brw_reg *arg1)
{
   struct brw_compile *p = &c->func;
   struct intel_context *intel = &p->brw->intel;
   int dst_chan = _mesa_ffs(mask & WRITEMASK_XYZW) - 1;

   if (!(mask & WRITEMASK_XYZW))
      return; /* Do not emit dead code */

   assert(is_power_of_two(mask & WRITEMASK_XYZW));

   brw_push_insn_state(p);

   /* math can only operate on up to a vec8 at a time, so in
    * dispatch_width==16 we have to do the second half manually.
    */
   if (intel->gen >= 6) {
      struct brw_reg src0 = arg0[0];
      struct brw_reg src1 = arg1[0];
      struct brw_reg temp_dst = dst[dst_chan];

      if (arg0[0].hstride == BRW_HORIZONTAL_STRIDE_0) {
	 brw_MOV(p, temp_dst, src0);
	 src0 = temp_dst;
      }

      if (arg1[0].hstride == BRW_HORIZONTAL_STRIDE_0) {
	 /* This is a heinous hack to get a temporary register for use
	  * in case both arg0 and arg1 are constants.  Why you're
	  * doing exponentiation on constant values in the shader, we
	  * don't know.
	  *
	  * max_wm_grf is almost surely less than the maximum GRF, and
	  * gen6 doesn't care about the number of GRFs used in a
	  * shader like pre-gen6 did.
	  */
	 struct brw_reg temp = brw_vec8_grf(c->max_wm_grf, 0);
	 brw_MOV(p, temp, src1);
	 src1 = temp;
      }

      brw_set_saturate(p, (mask & SATURATE) ? 1 : 0);
      brw_set_compression_control(p, BRW_COMPRESSION_NONE);
      brw_math2(p,
		temp_dst,
		function,
		src0,
		src1);
      if (c->dispatch_width == 16) {
	 brw_set_compression_control(p, BRW_COMPRESSION_2NDHALF);
	 brw_math2(p,
		   sechalf(temp_dst),
		   function,
		   sechalf(src0),
		   sechalf(src1));
      }
   } else {
      GLuint saturate = ((mask & SATURATE) ?
			 BRW_MATH_SATURATE_SATURATE :
			 BRW_MATH_SATURATE_NONE);

      brw_set_compression_control(p, BRW_COMPRESSION_NONE);
      brw_MOV(p, brw_message_reg(3), arg1[0]);
      if (c->dispatch_width == 16) {
	 brw_set_compression_control(p, BRW_COMPRESSION_2NDHALF);
	 brw_MOV(p, brw_message_reg(5), sechalf(arg1[0]));
      }

      brw_set_compression_control(p, BRW_COMPRESSION_NONE);
      brw_math(p,
	       dst[dst_chan],
	       function,
	       saturate,
	       2,
	       arg0[0],
	       BRW_MATH_DATA_VECTOR,
	       BRW_MATH_PRECISION_FULL);

      /* Send two messages to perform all 16 operations:
       */
      if (c->dispatch_width == 16) {
	 brw_set_compression_control(p, BRW_COMPRESSION_2NDHALF);
	 brw_math(p,
		  offset(dst[dst_chan],1),
		  function,
		  saturate,
		  4,
		  sechalf(arg0[0]),
		  BRW_MATH_DATA_VECTOR,
		  BRW_MATH_PRECISION_FULL);
      }
   }
   brw_pop_insn_state(p);
}
Example #8
0
/**
 * Find a translated vertex program that corresponds to stvp and
 * has outputs matched to stfp's inputs.
 * This performs vertex and fragment translation (to TGSI) when needed.
 */
static struct translated_vertex_program *
find_translated_vp(struct st_context *st,
                   struct st_vertex_program *stvp,
                   struct st_fragment_program *stfp)
{
   static const GLuint UNUSED = ~0;
   struct translated_vertex_program *xvp;
   const GLbitfield fragInputsRead = stfp->Base.Base.InputsRead;

   /*
    * Translate fragment program if needed.
    */
   if (!stfp->state.tokens) {
      GLuint inAttr, numIn = 0;

      for (inAttr = 0; inAttr < FRAG_ATTRIB_MAX; inAttr++) {
         if (fragInputsRead & (1 << inAttr)) {
            stfp->input_to_slot[inAttr] = numIn;
            numIn++;
         }
         else {
            stfp->input_to_slot[inAttr] = UNUSED;
         }
      }

      stfp->num_input_slots = numIn;

      assert(stfp->Base.Base.NumInstructions > 1);

      st_translate_fragment_program(st, stfp, stfp->input_to_slot);
   }


   /* See if we've got a translated vertex program whose outputs match
    * the fragment program's inputs.
    * XXX This could be a hash lookup, using InputsRead as the key.
    */
   for (xvp = stfp->vertex_programs; xvp; xvp = xvp->next) {
      if (xvp->master == stvp && xvp->frag_inputs == fragInputsRead) {
         break;
      }
   }

   /* No?  Allocate translated vp object now */
   if (!xvp) {
      xvp = ST_CALLOC_STRUCT(translated_vertex_program);
      xvp->frag_inputs = fragInputsRead;
      xvp->master = stvp;

      xvp->next = stfp->vertex_programs;
      stfp->vertex_programs = xvp;
   }

   /* See if we need to translate vertex program to TGSI form */
   if (xvp->serialNo != stvp->serialNo) {
      GLuint outAttr;
      const GLbitfield outputsWritten = stvp->Base.Base.OutputsWritten;
      GLuint numVpOuts = 0;
      GLboolean emitPntSize = GL_FALSE, emitBFC0 = GL_FALSE, emitBFC1 = GL_FALSE;
      GLbitfield usedGenerics = 0x0;
      GLbitfield usedOutputSlots = 0x0;

      /* Compute mapping of vertex program outputs to slots, which depends
       * on the fragment program's input->slot mapping.
       */
      for (outAttr = 0; outAttr < VERT_RESULT_MAX; outAttr++) {
         /* set defaults: */
         xvp->output_to_slot[outAttr] = UNUSED;
         xvp->output_to_semantic_name[outAttr] = TGSI_SEMANTIC_COUNT;
         xvp->output_to_semantic_index[outAttr] = 99;

         if (outAttr == VERT_RESULT_HPOS) {
            /* always put xformed position into slot zero */
            GLuint slot = 0;
            xvp->output_to_slot[VERT_RESULT_HPOS] = slot;
            xvp->output_to_semantic_name[outAttr] = TGSI_SEMANTIC_POSITION;
            xvp->output_to_semantic_index[outAttr] = 0;
            numVpOuts++;
            usedOutputSlots |= (1 << slot);
         }
         else if (outputsWritten & (1 << outAttr)) {
            /* see if the frag prog wants this vert output */
            GLint fpInAttrib = vp_out_to_fp_in(outAttr);
            if (fpInAttrib >= 0) {
               GLuint fpInSlot = stfp->input_to_slot[fpInAttrib];
               if (fpInSlot != ~0) {
                  /* match this vp output to the fp input */
                  GLuint vpOutSlot = stfp->input_map[fpInSlot];
                  xvp->output_to_slot[outAttr] = vpOutSlot;
                  xvp->output_to_semantic_name[outAttr] = stfp->input_semantic_name[fpInSlot];
                  xvp->output_to_semantic_index[outAttr] = stfp->input_semantic_index[fpInSlot];
                  numVpOuts++;
                  usedOutputSlots |= (1 << vpOutSlot);
               }
               else {
#if 0 /*debug*/
                  printf("VP output %d not used by FP\n", outAttr);
#endif
               }
            }
            else if (outAttr == VERT_RESULT_PSIZ)
               emitPntSize = GL_TRUE;
            else if (outAttr == VERT_RESULT_BFC0)
               emitBFC0 = GL_TRUE;
            else if (outAttr == VERT_RESULT_BFC1)
               emitBFC1 = GL_TRUE;
         }
#if 0 /*debug*/
         printf("assign vp output_to_slot[%d] = %d\n", outAttr, 
                xvp->output_to_slot[outAttr]);
#endif
      }

      /* must do these last */
      if (emitPntSize) {
         GLuint slot = numVpOuts++;
         xvp->output_to_slot[VERT_RESULT_PSIZ] = slot;
         xvp->output_to_semantic_name[VERT_RESULT_PSIZ] = TGSI_SEMANTIC_PSIZE;
         xvp->output_to_semantic_index[VERT_RESULT_PSIZ] = 0;
         usedOutputSlots |= (1 << slot);
      }
      if (emitBFC0) {
         GLuint slot = numVpOuts++;
         xvp->output_to_slot[VERT_RESULT_BFC0] = slot;
         xvp->output_to_semantic_name[VERT_RESULT_BFC0] = TGSI_SEMANTIC_COLOR;
         xvp->output_to_semantic_index[VERT_RESULT_BFC0] = 0;
         usedOutputSlots |= (1 << slot);
      }
      if (emitBFC1) {
         GLuint slot = numVpOuts++;
         xvp->output_to_slot[VERT_RESULT_BFC1] = slot;
         xvp->output_to_semantic_name[VERT_RESULT_BFC1] = TGSI_SEMANTIC_COLOR;
         xvp->output_to_semantic_index[VERT_RESULT_BFC1] = 1;
         usedOutputSlots |= (1 << slot);
      }

      /* build usedGenerics mask */
      usedGenerics = 0x0;
      for (outAttr = 0; outAttr < VERT_RESULT_MAX; outAttr++) {
         if (xvp->output_to_semantic_name[outAttr] == TGSI_SEMANTIC_GENERIC) {
            usedGenerics |= (1 << xvp->output_to_semantic_index[outAttr]);
         }
      }

      /* For each vertex program output that doesn't match up to a fragment
       * program input, map the vertex program output to a free slot and
       * free generic attribute.
       */
      for (outAttr = 0; outAttr < VERT_RESULT_MAX; outAttr++) {
         if (outputsWritten & (1 << outAttr)) {
            if (xvp->output_to_slot[outAttr] == UNUSED) {
               GLint freeGeneric = _mesa_ffs(~usedGenerics) - 1;
               GLint freeSlot = _mesa_ffs(~usedOutputSlots) - 1;
               usedGenerics |= (1 << freeGeneric);
               usedOutputSlots |= (1 << freeSlot);
               xvp->output_to_slot[outAttr] = freeSlot;
               xvp->output_to_semantic_name[outAttr] = TGSI_SEMANTIC_GENERIC;
               xvp->output_to_semantic_index[outAttr] = freeGeneric;
            }
         }

#if 0 /*debug*/
         printf("vp output_to_slot[%d] = %d\n", outAttr, 
                xvp->output_to_slot[outAttr]);
#endif
      }

      assert(stvp->Base.Base.NumInstructions > 1);

      st_translate_vertex_program(st, stvp, xvp->output_to_slot,
                                  xvp->output_to_semantic_name,
                                  xvp->output_to_semantic_index);

      xvp->vp = stvp;

      /* translated VP is up to date now */
      xvp->serialNo = stvp->serialNo;
   }

   return xvp;
}
Example #9
0
/**
 * Called by ctx->Driver.Clear.
 */
static void
intelClear(struct gl_context *ctx, GLbitfield mask)
{
   struct intel_context *intel = intel_context(ctx);
   const GLuint colorMask = *((GLuint *) & ctx->Color.ColorMask[0]);
   GLbitfield tri_mask = 0;
   GLbitfield blit_mask = 0;
   GLbitfield swrast_mask = 0;
   struct gl_framebuffer *fb = ctx->DrawBuffer;
   struct intel_renderbuffer *irb;
   int i;

   if (!_mesa_check_conditional_render(ctx))
      return;

   if (mask & (BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_FRONT_RIGHT)) {
      intel->front_buffer_dirty = GL_TRUE;
   }

   if (0)
      fprintf(stderr, "%s\n", __FUNCTION__);

   /* Get SW clears out of the way: Anything without an intel_renderbuffer */
   for (i = 0; i < BUFFER_COUNT; i++) {
      if (!(mask & (1 << i)))
	 continue;

      irb = intel_get_renderbuffer(fb, i);
      if (unlikely(!irb)) {
	 swrast_mask |= (1 << i);
	 mask &= ~(1 << i);
      }
   }
   if (unlikely(swrast_mask)) {
      debug_mask("swrast", swrast_mask);
      _swrast_Clear(ctx, swrast_mask);
   }

   /* HW color buffers (front, back, aux, generic FBO, etc) */
   if (intel->gen < 6 && colorMask == ~0) {
      /* clear all R,G,B,A */
      blit_mask |= (mask & BUFFER_BITS_COLOR);
   }
   else {
      /* glColorMask in effect */
      tri_mask |= (mask & BUFFER_BITS_COLOR);
   }

   /* Make sure we have up to date buffers before we start looking at
    * the tiling bits to determine how to clear. */
   intel_prepare_render(intel);

   /* HW stencil */
   if (mask & BUFFER_BIT_STENCIL) {
      const struct intel_region *stencilRegion
         = intel_get_rb_region(fb, BUFFER_STENCIL);
      if (stencilRegion) {
         /* have hw stencil */
         if (stencilRegion->tiling == I915_TILING_Y ||
	     (ctx->Stencil.WriteMask[0] & 0xff) != 0xff) {
	    /* We have to use the 3D engine if we're clearing a partial mask
	     * of the stencil buffer, or if we're on a 965 which has a tiled
	     * depth/stencil buffer in a layout we can't blit to.
	     */
            tri_mask |= BUFFER_BIT_STENCIL;
         }
	 else if (intel->has_separate_stencil &&
	       stencilRegion->tiling == I915_TILING_NONE) {
	    /* The stencil buffer is actually W tiled, which the hardware
	     * cannot blit to. */
	    tri_mask |= BUFFER_BIT_STENCIL;
	 }
         else {
            /* clearing all stencil bits, use blitting */
            blit_mask |= BUFFER_BIT_STENCIL;
         }
      }
   }

   /* HW depth */
   if (mask & BUFFER_BIT_DEPTH) {
      const struct intel_region *irb = intel_get_rb_region(fb, BUFFER_DEPTH);

      /* clear depth with whatever method is used for stencil (see above) */
      if (irb->tiling == I915_TILING_Y || tri_mask & BUFFER_BIT_STENCIL)
         tri_mask |= BUFFER_BIT_DEPTH;
      else
         blit_mask |= BUFFER_BIT_DEPTH;
   }

   /* If we're doing a tri pass for depth/stencil, include a likely color
    * buffer with it.
    */
   if (mask & (BUFFER_BIT_DEPTH | BUFFER_BIT_STENCIL)) {
      int color_bit = _mesa_ffs(mask & BUFFER_BITS_COLOR);
      if (color_bit != 0) {
	 tri_mask |= blit_mask & (1 << (color_bit - 1));
	 blit_mask &= ~(1 << (color_bit - 1));
      }
   }

   /* Anything left, just use tris */
   tri_mask |= mask & ~blit_mask;

   if (blit_mask) {
      debug_mask("blit", blit_mask);
      tri_mask |= intelClearWithBlit(ctx, blit_mask);
   }

   if (tri_mask) {
      debug_mask("tri", tri_mask);
      if (ctx->Extensions.ARB_fragment_shader)
	 _mesa_meta_glsl_Clear(&intel->ctx, tri_mask);
      else
	 _mesa_meta_Clear(&intel->ctx, tri_mask);
   }
}
Example #10
0
/**
 * Helper function to set the GL_DRAW_BUFFER state in the context and
 * current FBO.  Called via glDrawBuffer(), glDrawBuffersARB()
 *
 * All error checking will have been done prior to calling this function
 * so nothing should go wrong at this point.
 *
 * \param ctx  current context
 * \param n    number of color outputs to set
 * \param buffers  array[n] of colorbuffer names, like GL_LEFT.
 * \param destMask  array[n] of BUFFER_BIT_* bitmasks which correspond to the
 *                  colorbuffer names.  (i.e. GL_FRONT_AND_BACK =>
 *                  BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT).
 */
void
_mesa_drawbuffers(GLcontext *ctx, GLuint n, const GLenum *buffers,
                  const GLbitfield *destMask)
{
   struct gl_framebuffer *fb = ctx->DrawBuffer;
   GLbitfield mask[MAX_DRAW_BUFFERS];
   GLboolean newState = GL_FALSE;

   if (!destMask) {
      /* compute destMask values now */
      const GLbitfield supportedMask = supported_buffer_bitmask(ctx, fb);
      GLuint output;
      for (output = 0; output < n; output++) {
         mask[output] = draw_buffer_enum_to_bitmask(buffers[output]);
         ASSERT(mask[output] != BAD_MASK);
         mask[output] &= supportedMask;
      }
      destMask = mask;
   }

   /*
    * If n==1, destMask[0] may have up to four bits set.
    * Otherwise, destMask[x] can only have one bit set.
    */
   if (n == 1) {
      GLuint count = 0, destMask0 = destMask[0];
      while (destMask0) {
         GLint bufIndex = _mesa_ffs(destMask0) - 1;
         if (fb->_ColorDrawBufferIndexes[count] != bufIndex) {
            fb->_ColorDrawBufferIndexes[count] = bufIndex;
            newState = GL_TRUE;
         }
         count++;
         destMask0 &= ~(1 << bufIndex);
      }
      fb->ColorDrawBuffer[0] = buffers[0];
      if (fb->_NumColorDrawBuffers != count) {
         fb->_NumColorDrawBuffers = count;
         newState = GL_TRUE;
      }
   }
   else {
      GLuint buf, count = 0;
      for (buf = 0; buf < n; buf++ ) {
         if (destMask[buf]) {
            GLint bufIndex = _mesa_ffs(destMask[buf]) - 1;
            /* only one bit should be set in the destMask[buf] field */
            ASSERT(_mesa_bitcount(destMask[buf]) == 1);
            if (fb->_ColorDrawBufferIndexes[buf] != bufIndex) {
               fb->_ColorDrawBufferIndexes[buf] = bufIndex;
               newState = GL_TRUE;
            }
            fb->ColorDrawBuffer[buf] = buffers[buf];
            count = buf + 1;
         }
         else {
            if (fb->_ColorDrawBufferIndexes[buf] != -1) {
               fb->_ColorDrawBufferIndexes[buf] = -1;
               newState = GL_TRUE;
            }
         }
      }
      /* set remaining outputs to -1 (GL_NONE) */
      while (buf < ctx->Const.MaxDrawBuffers) {
         if (fb->_ColorDrawBufferIndexes[buf] != -1) {
            fb->_ColorDrawBufferIndexes[buf] = -1;
            newState = GL_TRUE;
         }
         fb->ColorDrawBuffer[buf] = GL_NONE;
         buf++;
      }
      fb->_NumColorDrawBuffers = count;
   }

   if (fb->Name == 0) {
      /* also set context drawbuffer state */
      GLuint buf;
      for (buf = 0; buf < ctx->Const.MaxDrawBuffers; buf++) {
         if (ctx->Color.DrawBuffer[buf] != fb->ColorDrawBuffer[buf]) {
            ctx->Color.DrawBuffer[buf] = fb->ColorDrawBuffer[buf];
            newState = GL_TRUE;
         }
      }
   }

   if (newState)
      FLUSH_VERTICES(ctx, _NEW_BUFFERS);
}
Example #11
0
/**
 * Called by ctx->Driver.Clear.
 */
static void
intelClear(GLcontext *ctx, GLbitfield mask)
{
   struct intel_context *intel = intel_context(ctx);
   const GLuint colorMask = *((GLuint *) & ctx->Color.ColorMask);
   GLbitfield tri_mask = 0;
   GLbitfield blit_mask = 0;
   GLbitfield swrast_mask = 0;
   struct gl_framebuffer *fb = ctx->DrawBuffer;
   GLuint i;

   if (0)
      fprintf(stderr, "%s\n", __FUNCTION__);

   /* HW color buffers (front, back, aux, generic FBO, etc) */
   if (colorMask == ~0) {
      /* clear all R,G,B,A */
      /* XXX FBO: need to check if colorbuffers are software RBOs! */
      blit_mask |= (mask & BUFFER_BITS_COLOR);
   }
   else {
      /* glColorMask in effect */
      tri_mask |= (mask & (BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT));
   }

   /* HW stencil */
   if (mask & BUFFER_BIT_STENCIL) {
      const struct intel_region *stencilRegion
         = intel_get_rb_region(fb, BUFFER_STENCIL);
      if (stencilRegion) {
         /* have hw stencil */
         if (IS_965(intel->intelScreen->deviceID) ||
	     (ctx->Stencil.WriteMask[0] & 0xff) != 0xff) {
	    /* We have to use the 3D engine if we're clearing a partial mask
	     * of the stencil buffer, or if we're on a 965 which has a tiled
	     * depth/stencil buffer in a layout we can't blit to.
	     */
            tri_mask |= BUFFER_BIT_STENCIL;
         }
         else {
            /* clearing all stencil bits, use blitting */
            blit_mask |= BUFFER_BIT_STENCIL;
         }
      }
   }

   /* HW depth */
   if (mask & BUFFER_BIT_DEPTH) {
      /* clear depth with whatever method is used for stencil (see above) */
      if (IS_965(intel->intelScreen->deviceID) ||
	  tri_mask & BUFFER_BIT_STENCIL)
         tri_mask |= BUFFER_BIT_DEPTH;
      else
         blit_mask |= BUFFER_BIT_DEPTH;
   }

   /* If we're doing a tri pass for depth/stencil, include a likely color
    * buffer with it.
    */
   if (mask & (BUFFER_BIT_DEPTH | BUFFER_BIT_STENCIL)) {
      int color_bit = _mesa_ffs(mask & TRI_CLEAR_COLOR_BITS);
      if (color_bit != 0) {
	 tri_mask |= blit_mask & (1 << (color_bit - 1));
	 blit_mask &= ~(1 << (color_bit - 1));
      }
   }

   /* SW fallback clearing */
   swrast_mask = mask & ~tri_mask & ~blit_mask;

   for (i = 0; i < BUFFER_COUNT; i++) {
      GLuint bufBit = 1 << i;
      if ((blit_mask | tri_mask) & bufBit) {
         if (!fb->Attachment[i].Renderbuffer->ClassID) {
            blit_mask &= ~bufBit;
            tri_mask &= ~bufBit;
            swrast_mask |= bufBit;
         }
      }
   }

   if (blit_mask) {
      if (INTEL_DEBUG & DEBUG_BLIT) {
	 DBG("blit clear:");
	 for (i = 0; i < BUFFER_COUNT; i++) {
	    if (blit_mask & (1 << i))
	       DBG(" %s", buffer_names[i]);
	 }
	 DBG("\n");
      }
      intelClearWithBlit(ctx, blit_mask);
   }

   if (tri_mask) {
      if (INTEL_DEBUG & DEBUG_BLIT) {
	 DBG("tri clear:");
	 for (i = 0; i < BUFFER_COUNT; i++) {
	    if (tri_mask & (1 << i))
	       DBG(" %s", buffer_names[i]);
	 }
	 DBG("\n");
      }
      intel_clear_tris(ctx, tri_mask);
   }

   if (swrast_mask) {
      if (INTEL_DEBUG & DEBUG_BLIT) {
	 DBG("swrast clear:");
	 for (i = 0; i < BUFFER_COUNT; i++) {
	    if (swrast_mask & (1 << i))
	       DBG(" %s", buffer_names[i]);
	 }
	 DBG("\n");
      }
      _swrast_Clear(ctx, swrast_mask);
   }
}
Example #12
0
/**
 * Perform glClear where mask contains only color, depth, and/or stencil.
 *
 * The implementation is based on calling into Mesa to set GL state and
 * performing normal triangle rendering.  The intent of this path is to
 * have as generic a path as possible, so that any driver could make use of
 * it.
 */
void
intel_clear_tris(GLcontext *ctx, GLbitfield mask)
{
   struct intel_context *intel = intel_context(ctx);
   GLfloat dst_z;
   struct gl_framebuffer *fb = ctx->DrawBuffer;
   int i;
   GLboolean saved_fp_enable = GL_FALSE, saved_vp_enable = GL_FALSE;
   GLuint saved_shader_program = 0;
   unsigned int saved_active_texture;
   struct gl_array_object *arraySave = NULL;

   if (!intel->clear.arrayObj)
      init_clear(ctx);

   assert((mask & ~(TRI_CLEAR_COLOR_BITS | BUFFER_BIT_DEPTH |
		    BUFFER_BIT_STENCIL)) == 0);

   _mesa_PushAttrib(GL_COLOR_BUFFER_BIT |
		    GL_CURRENT_BIT |
		    GL_DEPTH_BUFFER_BIT |
		    GL_ENABLE_BIT |
		    GL_POLYGON_BIT |
		    GL_STENCIL_BUFFER_BIT |
		    GL_TRANSFORM_BIT |
		    GL_CURRENT_BIT);
   saved_active_texture = ctx->Texture.CurrentUnit;

   /* Disable existing GL state we don't want to apply to a clear. */
   _mesa_Disable(GL_ALPHA_TEST);
   _mesa_Disable(GL_BLEND);
   _mesa_Disable(GL_CULL_FACE);
   _mesa_Disable(GL_FOG);
   _mesa_Disable(GL_POLYGON_SMOOTH);
   _mesa_Disable(GL_POLYGON_STIPPLE);
   _mesa_Disable(GL_POLYGON_OFFSET_FILL);
   _mesa_Disable(GL_LIGHTING);
   _mesa_Disable(GL_CLIP_PLANE0);
   _mesa_Disable(GL_CLIP_PLANE1);
   _mesa_Disable(GL_CLIP_PLANE2);
   _mesa_Disable(GL_CLIP_PLANE3);
   _mesa_Disable(GL_CLIP_PLANE4);
   _mesa_Disable(GL_CLIP_PLANE5);
   _mesa_PolygonMode(GL_FRONT_AND_BACK, GL_FILL);
   if (ctx->Extensions.ARB_fragment_program && ctx->FragmentProgram.Enabled) {
      saved_fp_enable = GL_TRUE;
      _mesa_Disable(GL_FRAGMENT_PROGRAM_ARB);
   }
   if (ctx->Extensions.ARB_vertex_program && ctx->VertexProgram.Enabled) {
      saved_vp_enable = GL_TRUE;
      _mesa_Disable(GL_VERTEX_PROGRAM_ARB);
   }
   if (ctx->Extensions.ARB_shader_objects && ctx->Shader.CurrentProgram) {
      saved_shader_program = ctx->Shader.CurrentProgram->Name;
      _mesa_UseProgramObjectARB(0);
   }

   if (ctx->Texture._EnabledUnits != 0) {
      int i;

      for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
	 _mesa_ActiveTextureARB(GL_TEXTURE0 + i);
	 _mesa_Disable(GL_TEXTURE_1D);
	 _mesa_Disable(GL_TEXTURE_2D);
	 _mesa_Disable(GL_TEXTURE_3D);
	 if (ctx->Extensions.ARB_texture_cube_map)
	    _mesa_Disable(GL_TEXTURE_CUBE_MAP_ARB);
	 if (ctx->Extensions.NV_texture_rectangle)
	    _mesa_Disable(GL_TEXTURE_RECTANGLE_NV);
	 if (ctx->Extensions.MESA_texture_array) {
	    _mesa_Disable(GL_TEXTURE_1D_ARRAY_EXT);
	    _mesa_Disable(GL_TEXTURE_2D_ARRAY_EXT);
	 }
      }
   }

   /* save current array object, bind our private one */
   _mesa_reference_array_object(ctx, &arraySave, ctx->Array.ArrayObj);
   _mesa_reference_array_object(ctx, &ctx->Array.ArrayObj, intel->clear.arrayObj);

   intel_meta_set_passthrough_transform(intel);

   for (i = 0; i < 4; i++) {
      COPY_4FV(intel->clear.color[i], ctx->Color.ClearColor);
   }

   /* convert clear Z from [0,1] to NDC coord in [-1,1] */
   dst_z = -1.0 + 2.0 * ctx->Depth.Clear;

   /* Prepare the vertices, which are the same regardless of which buffer we're
    * drawing to.
    */
   intel->clear.vertices[0][0] = fb->_Xmin;
   intel->clear.vertices[0][1] = fb->_Ymin;
   intel->clear.vertices[0][2] = dst_z;
   intel->clear.vertices[1][0] = fb->_Xmax;
   intel->clear.vertices[1][1] = fb->_Ymin;
   intel->clear.vertices[1][2] = dst_z;
   intel->clear.vertices[2][0] = fb->_Xmax;
   intel->clear.vertices[2][1] = fb->_Ymax;
   intel->clear.vertices[2][2] = dst_z;
   intel->clear.vertices[3][0] = fb->_Xmin;
   intel->clear.vertices[3][1] = fb->_Ymax;
   intel->clear.vertices[3][2] = dst_z;

   while (mask != 0) {
      GLuint this_mask = 0;
      GLuint color_bit;

      color_bit = _mesa_ffs(mask & TRI_CLEAR_COLOR_BITS);
      if (color_bit != 0)
	 this_mask |= (1 << (color_bit - 1));

      /* Clear depth/stencil in the same pass as color. */
      this_mask |= (mask & (BUFFER_BIT_DEPTH | BUFFER_BIT_STENCIL));

      /* Select the current color buffer and use the color write mask if
       * we have one, otherwise don't write any color channels.
       */
      if (this_mask & BUFFER_BIT_FRONT_LEFT)
	 _mesa_DrawBuffer(GL_FRONT_LEFT);
      else if (this_mask & BUFFER_BIT_BACK_LEFT)
	 _mesa_DrawBuffer(GL_BACK_LEFT);
      else if (color_bit != 0)
	 _mesa_DrawBuffer(GL_COLOR_ATTACHMENT0 +
			  (color_bit - BUFFER_COLOR0 - 1));
      else
	 _mesa_ColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);

      /* Control writing of the depth clear value to depth. */
      if (this_mask & BUFFER_BIT_DEPTH) {
	 _mesa_DepthFunc(GL_ALWAYS);
	 _mesa_Enable(GL_DEPTH_TEST);
      } else {
	 _mesa_Disable(GL_DEPTH_TEST);
	 _mesa_DepthMask(GL_FALSE);
      }

      /* Control writing of the stencil clear value to stencil. */
      if (this_mask & BUFFER_BIT_STENCIL) {
	 _mesa_Enable(GL_STENCIL_TEST);
	 _mesa_StencilOpSeparate(GL_FRONT_AND_BACK,
				 GL_REPLACE, GL_REPLACE, GL_REPLACE);
	 _mesa_StencilFuncSeparate(GL_FRONT_AND_BACK, GL_ALWAYS,
				   ctx->Stencil.Clear,
				   ctx->Stencil.WriteMask[0]);
      } else {
	 _mesa_Disable(GL_STENCIL_TEST);
      }

      _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);

      mask &= ~this_mask;
   }

   intel_meta_restore_transform(intel);

   _mesa_ActiveTextureARB(GL_TEXTURE0 + saved_active_texture);
   if (saved_fp_enable)
      _mesa_Enable(GL_FRAGMENT_PROGRAM_ARB);
   if (saved_vp_enable)
      _mesa_Enable(GL_VERTEX_PROGRAM_ARB);

   if (saved_shader_program)
      _mesa_UseProgramObjectARB(saved_shader_program);

   _mesa_PopAttrib();

   /* restore current array object */
   _mesa_reference_array_object(ctx, &ctx->Array.ArrayObj, arraySave);
   _mesa_reference_array_object(ctx, &arraySave, NULL);
}
Example #13
0
/**
 * Translate TEXTURE_x_BIT to TEXTURE_x_INDEX.
 */
static GLuint translate_tex_src_bit( GLbitfield bit )
{
    ASSERT(bit);
    return _mesa_ffs(bit) - 1;
}
Example #14
0
/**
 * Use blitting to clear the renderbuffers named by 'flags'.
 * Note: we can't use the ctx->DrawBuffer->_ColorDrawBufferIndexes field
 * since that might include software renderbuffers or renderbuffers
 * which we're clearing with triangles.
 * \param mask  bitmask of BUFFER_BIT_* values indicating buffers to clear
 */
GLbitfield
intelClearWithBlit(struct gl_context *ctx, GLbitfield mask)
{
    struct intel_context *intel = intel_context(ctx);
    struct gl_framebuffer *fb = ctx->DrawBuffer;
    GLuint clear_depth_value, clear_depth_mask;
    GLboolean all;
    GLint cx, cy, cw, ch;
    GLbitfield fail_mask = 0;
    BATCH_LOCALS;

    /*
     * Compute values for clearing the buffers.
     */
    clear_depth_value = 0;
    clear_depth_mask = 0;
    if (mask & BUFFER_BIT_DEPTH) {
        clear_depth_value = (GLuint) (fb->_DepthMax * ctx->Depth.Clear);
        clear_depth_mask = XY_BLT_WRITE_RGB;
    }
    if (mask & BUFFER_BIT_STENCIL) {
        clear_depth_value |= (ctx->Stencil.Clear & 0xff) << 24;
        clear_depth_mask |= XY_BLT_WRITE_ALPHA;
    }

    cx = fb->_Xmin;
    if (fb->Name == 0)
        cy = ctx->DrawBuffer->Height - fb->_Ymax;
    else
        cy = fb->_Ymin;
    cw = fb->_Xmax - fb->_Xmin;
    ch = fb->_Ymax - fb->_Ymin;

    if (cw == 0 || ch == 0)
        return 0;

    all = (cw == fb->Width && ch == fb->Height);

    /* Loop over all renderbuffers */
    mask &= (1 << BUFFER_COUNT) - 1;
    while (mask) {
        GLuint buf = _mesa_ffs(mask) - 1;
        GLboolean is_depth_stencil = buf == BUFFER_DEPTH || buf == BUFFER_STENCIL;
        struct intel_renderbuffer *irb;
        drm_intel_bo *write_buffer;
        int x1, y1, x2, y2;
        uint32_t clear_val;
        uint32_t BR13, CMD;
        int pitch, cpp;
        drm_intel_bo *aper_array[2];

        mask &= ~(1 << buf);

        irb = intel_get_renderbuffer(fb, buf);
        if (irb == NULL || irb->region == NULL || irb->region->buffer == NULL) {
            fail_mask |= 1 << buf;
            continue;
        }

        /* OK, clear this renderbuffer */
        write_buffer = intel_region_buffer(intel, irb->region,
                                           all ? INTEL_WRITE_FULL :
                                           INTEL_WRITE_PART);
        x1 = cx + irb->draw_x;
        y1 = cy + irb->draw_y;
        x2 = cx + cw + irb->draw_x;
        y2 = cy + ch + irb->draw_y;

        pitch = irb->region->pitch;
        cpp = irb->region->cpp;

        DBG("%s dst:buf(%p)/%d %d,%d sz:%dx%d\n",
            __FUNCTION__,
            irb->region->buffer, (pitch * cpp),
            x1, y1, x2 - x1, y2 - y1);

        BR13 = 0xf0 << 16;
        CMD = XY_COLOR_BLT_CMD;

        /* Setup the blit command */
        if (cpp == 4) {
            if (is_depth_stencil) {
                CMD |= clear_depth_mask;
            } else {
                /* clearing RGBA */
                CMD |= XY_BLT_WRITE_ALPHA | XY_BLT_WRITE_RGB;
            }
        }

        assert(irb->region->tiling != I915_TILING_Y);

#ifndef I915
        if (irb->region->tiling != I915_TILING_NONE) {
            CMD |= XY_DST_TILED;
            pitch /= 4;
        }
#endif
        BR13 |= (pitch * cpp);

        if (is_depth_stencil) {
            clear_val = clear_depth_value;
        } else {
            uint8_t clear[4];
            GLclampf *color = ctx->Color.ClearColor;

            CLAMPED_FLOAT_TO_UBYTE(clear[0], color[0]);
            CLAMPED_FLOAT_TO_UBYTE(clear[1], color[1]);
            CLAMPED_FLOAT_TO_UBYTE(clear[2], color[2]);
            CLAMPED_FLOAT_TO_UBYTE(clear[3], color[3]);

            switch (irb->Base.Format) {
            case MESA_FORMAT_ARGB8888:
            case MESA_FORMAT_XRGB8888:
                clear_val = PACK_COLOR_8888(clear[3], clear[0],
                                            clear[1], clear[2]);
                break;
            case MESA_FORMAT_RGB565:
                clear_val = PACK_COLOR_565(clear[0], clear[1], clear[2]);
                break;
            case MESA_FORMAT_ARGB4444:
                clear_val = PACK_COLOR_4444(clear[3], clear[0],
                                            clear[1], clear[2]);
                break;
            case MESA_FORMAT_ARGB1555:
                clear_val = PACK_COLOR_1555(clear[3], clear[0],
                                            clear[1], clear[2]);
                break;
            case MESA_FORMAT_A8:
                clear_val = PACK_COLOR_8888(clear[3], clear[3],
                                            clear[3], clear[3]);
                break;
            default:
                fail_mask |= 1 << buf;
                continue;
            }
        }

        BR13 |= br13_for_cpp(cpp);

        assert(x1 < x2);
        assert(y1 < y2);

        /* do space check before going any further */
        aper_array[0] = intel->batch.bo;
        aper_array[1] = write_buffer;

        if (drm_intel_bufmgr_check_aperture_space(aper_array,
                ARRAY_SIZE(aper_array)) != 0) {
            intel_batchbuffer_flush(intel);
        }

        BEGIN_BATCH_BLT(6);
        OUT_BATCH(CMD);
        OUT_BATCH(BR13);
        OUT_BATCH((y1 << 16) | x1);
        OUT_BATCH((y2 << 16) | x2);
        OUT_RELOC_FENCED(write_buffer,
                         I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER,
                         0);
        OUT_BATCH(clear_val);
        ADVANCE_BATCH();

        if (intel->always_flush_cache)
            intel_batchbuffer_emit_mi_flush(intel);

        if (buf == BUFFER_DEPTH || buf == BUFFER_STENCIL)
            mask &= ~(BUFFER_BIT_DEPTH | BUFFER_BIT_STENCIL);
    }

    return fail_mask;
}