Beispiel #1
0
/**
 * Clear the color buffer when glColorMask is in effect.
 */
static void
clear_rgba_buffer_with_masking(GLcontext *ctx, struct gl_renderbuffer *rb)
{
   const GLint x = ctx->DrawBuffer->_Xmin;
   const GLint y = ctx->DrawBuffer->_Ymin;
   const GLint height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
   const GLint width  = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
   SWspan span;
   GLint i;

   ASSERT(ctx->Visual.rgbMode);
   ASSERT(rb->PutRow);

   /* Initialize color span with clear color */
   /* XXX optimize for clearcolor == black/zero (bzero) */
   INIT_SPAN(span, GL_BITMAP, width, 0, SPAN_RGBA);
   span.array->ChanType = rb->DataType;
   if (span.array->ChanType == GL_UNSIGNED_BYTE) {
      GLubyte clearColor[4];
      UNCLAMPED_FLOAT_TO_UBYTE(clearColor[RCOMP], ctx->Color.ClearColor[0]);
      UNCLAMPED_FLOAT_TO_UBYTE(clearColor[GCOMP], ctx->Color.ClearColor[1]);
      UNCLAMPED_FLOAT_TO_UBYTE(clearColor[BCOMP], ctx->Color.ClearColor[2]);
      UNCLAMPED_FLOAT_TO_UBYTE(clearColor[ACOMP], ctx->Color.ClearColor[3]);
      for (i = 0; i < width; i++) {
         COPY_4UBV(span.array->rgba[i], clearColor);
      }
   }
   else if (span.array->ChanType == GL_UNSIGNED_SHORT) {
      GLushort clearColor[4];
      UNCLAMPED_FLOAT_TO_USHORT(clearColor[RCOMP], ctx->Color.ClearColor[0]);
      UNCLAMPED_FLOAT_TO_USHORT(clearColor[GCOMP], ctx->Color.ClearColor[1]);
      UNCLAMPED_FLOAT_TO_USHORT(clearColor[BCOMP], ctx->Color.ClearColor[2]);
      UNCLAMPED_FLOAT_TO_USHORT(clearColor[ACOMP], ctx->Color.ClearColor[3]);
      for (i = 0; i < width; i++) {
         COPY_4V(span.array->rgba[i], clearColor);
      }
   }
   else {
      ASSERT(span.array->ChanType == GL_FLOAT);
      for (i = 0; i < width; i++) {
         CLAMPED_FLOAT_TO_CHAN(span.array->rgba[i][0], ctx->Color.ClearColor[0]);
         CLAMPED_FLOAT_TO_CHAN(span.array->rgba[i][1], ctx->Color.ClearColor[1]);
         CLAMPED_FLOAT_TO_CHAN(span.array->rgba[i][2], ctx->Color.ClearColor[2]);
         CLAMPED_FLOAT_TO_CHAN(span.array->rgba[i][3], ctx->Color.ClearColor[3]);
      }
   }

   /* Note that masking will change the color values, but only the
    * channels for which the write mask is GL_FALSE.  The channels
    * which which are write-enabled won't get modified.
    */
   for (i = 0; i < height; i++) {
      span.x = x;
      span.y = y + i;
      _swrast_mask_rgba_span(ctx, rb, &span);
      /* write masked row */
      rb->PutRow(ctx, rb, width, x, y + i, span.array->rgba, NULL);
   }
}
static void
accum_return(GLcontext *ctx, GLfloat value,
             GLint xpos, GLint ypos, GLint width, GLint height )
{
   SWcontext *swrast = SWRAST_CONTEXT(ctx);
   struct gl_framebuffer *fb = ctx->DrawBuffer;
   struct gl_renderbuffer *accumRb = fb->Attachment[BUFFER_ACCUM].Renderbuffer;
   const GLboolean directAccess
      = (accumRb->GetPointer(ctx, accumRb, 0, 0) != NULL);
   const GLboolean masking = (!ctx->Color.ColorMask[RCOMP] ||
                              !ctx->Color.ColorMask[GCOMP] ||
                              !ctx->Color.ColorMask[BCOMP] ||
                              !ctx->Color.ColorMask[ACOMP]);

   static GLchan multTable[32768];
   static GLfloat prevMult = 0.0;
   const GLfloat mult = swrast->_IntegerAccumScaler;
   const GLint max = MIN2((GLint) (256 / mult), 32767);

   /* May have to leave optimized accum buffer mode */
   if (swrast->_IntegerAccumMode && value != 1.0)
      rescale_accum(ctx);

   if (swrast->_IntegerAccumMode && swrast->_IntegerAccumScaler > 0) {
      /* build lookup table to avoid many floating point multiplies */
      GLint j;
      assert(swrast->_IntegerAccumScaler <= 1.0);
      if (mult != prevMult) {
         for (j = 0; j < max; j++)
            multTable[j] = IROUND((GLfloat) j * mult);
         prevMult = mult;
      }
   }

   if (accumRb->DataType == GL_SHORT ||
       accumRb->DataType == GL_UNSIGNED_SHORT) {
      const GLfloat scale = value * CHAN_MAXF / ACCUM_SCALE16;
      GLuint buffer;
      GLint i;

      /* XXX maybe transpose the 'i' and 'buffer' loops??? */
      for (i = 0; i < height; i++) {
         GLshort accumRow[4 * MAX_WIDTH];
         GLshort *acc;
         SWspan span;

         /* init color span */
         INIT_SPAN(span, GL_BITMAP);
         span.end = width;
         span.arrayMask = SPAN_RGBA;
         span.x = xpos;
         span.y = ypos + i;

         if (directAccess) {
            acc = (GLshort *) accumRb->GetPointer(ctx, accumRb, xpos, ypos +i);
         }
         else {
            accumRb->GetRow(ctx, accumRb, width, xpos, ypos + i, accumRow);
            acc = accumRow;
         }

         /* get the colors to return */
         if (swrast->_IntegerAccumMode) {
            GLint j;
            for (j = 0; j < width; j++) {
               ASSERT(acc[j * 4 + 0] < max);
               ASSERT(acc[j * 4 + 1] < max);
               ASSERT(acc[j * 4 + 2] < max);
               ASSERT(acc[j * 4 + 3] < max);
               span.array->rgba[j][RCOMP] = multTable[acc[j * 4 + 0]];
               span.array->rgba[j][GCOMP] = multTable[acc[j * 4 + 1]];
               span.array->rgba[j][BCOMP] = multTable[acc[j * 4 + 2]];
               span.array->rgba[j][ACOMP] = multTable[acc[j * 4 + 3]];
            }
         }
         else {
            /* scaled integer (or float) accum buffer */
            GLint j;
            for (j = 0; j < width; j++) {
#if CHAN_BITS==32
               GLchan r = acc[j * 4 + 0] * scale;
               GLchan g = acc[j * 4 + 1] * scale;
               GLchan b = acc[j * 4 + 2] * scale;
               GLchan a = acc[j * 4 + 3] * scale;
#else
               GLint r = IROUND( (GLfloat) (acc[j * 4 + 0]) * scale );
               GLint g = IROUND( (GLfloat) (acc[j * 4 + 1]) * scale );
               GLint b = IROUND( (GLfloat) (acc[j * 4 + 2]) * scale );
               GLint a = IROUND( (GLfloat) (acc[j * 4 + 3]) * scale );
#endif
               span.array->rgba[j][RCOMP] = CLAMP( r, 0, CHAN_MAX );
               span.array->rgba[j][GCOMP] = CLAMP( g, 0, CHAN_MAX );
               span.array->rgba[j][BCOMP] = CLAMP( b, 0, CHAN_MAX );
               span.array->rgba[j][ACOMP] = CLAMP( a, 0, CHAN_MAX );
            }
         }

         /* store colors */
         for (buffer = 0; buffer < fb->_NumColorDrawBuffers; buffer++) {
            struct gl_renderbuffer *rb = fb->_ColorDrawBuffers[buffer];
            if (masking) {
               _swrast_mask_rgba_span(ctx, rb, &span);
            }
            rb->PutRow(ctx, rb, width, xpos, ypos + i, span.array->rgba, NULL);
         }
      }
   }
   else {
      /* other types someday */
   }
}
Beispiel #3
0
/**
 * Apply all the per-fragment operations to a span.
 * This now includes texturing (_swrast_write_texture_span() is history).
 * This function may modify any of the array values in the span.
 * span->interpMask and span->arrayMask may be changed but will be restored
 * to their original values before returning.
 */
void
_swrast_write_rgba_span( struct gl_context *ctx, SWspan *span)
{
   const SWcontext *swrast = SWRAST_CONTEXT(ctx);
   const GLuint colorMask = *((GLuint *)ctx->Color.ColorMask);
   const GLbitfield origInterpMask = span->interpMask;
   const GLbitfield origArrayMask = span->arrayMask;
   const GLbitfield64 origArrayAttribs = span->arrayAttribs;
   const GLenum origChanType = span->array->ChanType;
   void * const origRgba = span->array->rgba;
   const GLboolean texture = ctx->Texture._EnabledCoord;
   struct gl_framebuffer *fb = ctx->DrawBuffer;

   /*
   printf("%s()  interp 0x%x  array 0x%x\n", __FUNCTION__,
          span->interpMask, span->arrayMask);
   */

   ASSERT(span->primitive == GL_POINT ||
          span->primitive == GL_LINE ||
	  span->primitive == GL_POLYGON ||
          span->primitive == GL_BITMAP);

   /* Fragment write masks */
   if (span->arrayMask & SPAN_MASK) {
      /* mask was initialized by caller, probably glBitmap */
      span->writeAll = GL_FALSE;
   }
   else {
      memset(span->array->mask, 1, span->end);
      span->writeAll = GL_TRUE;
   }

   /* Clip to window/scissor box */
   if (!clip_span(ctx, span)) {
      return;
   }

   ASSERT(span->end <= MAX_WIDTH);

   /* Depth bounds test */
   if (ctx->Depth.BoundsTest && fb->Visual.depthBits > 0) {
      if (!_swrast_depth_bounds_test(ctx, span)) {
         return;
      }
   }

#ifdef DEBUG
   /* Make sure all fragments are within window bounds */
   if (span->arrayMask & SPAN_XY) {
      /* array of pixel locations */
      GLuint i;
      for (i = 0; i < span->end; i++) {
         if (span->array->mask[i]) {
            assert(span->array->x[i] >= fb->_Xmin);
            assert(span->array->x[i] < fb->_Xmax);
            assert(span->array->y[i] >= fb->_Ymin);
            assert(span->array->y[i] < fb->_Ymax);
         }
      }
   }
#endif

   /* Polygon Stippling */
   if (ctx->Polygon.StippleFlag && span->primitive == GL_POLYGON) {
      stipple_polygon_span(ctx, span);
   }

   /* This is the normal place to compute the fragment color/Z
    * from texturing or shading.
    */
   if (texture && !swrast->_DeferredTexture) {
      shade_texture_span(ctx, span);
   }

   /* Do the alpha test */
   if (ctx->Color.AlphaEnabled) {
      if (!_swrast_alpha_test(ctx, span)) {
         /* all fragments failed test */
         goto end;
      }
   }

   /* Stencil and Z testing */
   if (ctx->Stencil._Enabled || ctx->Depth.Test) {
      if (!(span->arrayMask & SPAN_Z))
         _swrast_span_interpolate_z(ctx, span);

      if (ctx->Stencil._Enabled) {
         /* Combined Z/stencil tests */
         if (!_swrast_stencil_and_ztest_span(ctx, span)) {
            /* all fragments failed test */
            goto end;
         }
      }
      else if (fb->Visual.depthBits > 0) {
         /* Just regular depth testing */
         ASSERT(ctx->Depth.Test);
         ASSERT(span->arrayMask & SPAN_Z);
         if (!_swrast_depth_test_span(ctx, span)) {
            /* all fragments failed test */
            goto end;
         }
      }
   }

   /* We had to wait until now to check for glColorMask(0,0,0,0) because of
    * the occlusion test.
    */
   if (colorMask == 0) {
      /* no colors to write */
      goto end;
   }

   /* If we were able to defer fragment color computation to now, there's
    * a good chance that many fragments will have already been killed by
    * Z/stencil testing.
    */
   if (texture && swrast->_DeferredTexture) {
      shade_texture_span(ctx, span);
   }

#if CHAN_BITS == 32
   if ((span->arrayAttribs & FRAG_BIT_COL0) == 0) {
      interpolate_active_attribs(ctx, span, FRAG_BIT_COL0);
   }
#else
   if ((span->arrayMask & SPAN_RGBA) == 0) {
      interpolate_int_colors(ctx, span);
   }
#endif

   ASSERT(span->arrayMask & SPAN_RGBA);

   /* Fog */
   if (swrast->_FogEnabled) {
      _swrast_fog_rgba_span(ctx, span);
   }

   /* Antialias coverage application */
   if (span->arrayMask & SPAN_COVERAGE) {
      apply_aa_coverage(span);
   }

   /*
    * Write to renderbuffers.
    * Depending on glDrawBuffer() state and the which color outputs are
    * written by the fragment shader, we may either replicate one color to
    * all renderbuffers or write a different color to each renderbuffer.
    * multiFragOutputs=TRUE for the later case.
    */
   {
      struct gl_renderbuffer *rb = fb->_ColorDrawBuffer;

      /* color[fragOutput] will be written to buffer */

      if (rb) {
         struct swrast_renderbuffer *srb = swrast_renderbuffer(rb);
         GLenum colorType = srb->ColorType;

         assert(colorType == GL_UNSIGNED_BYTE ||
                colorType == GL_FLOAT);

         /* set span->array->rgba to colors for renderbuffer's datatype */
         if (span->array->ChanType != colorType) {
            convert_color_type(span, colorType, 0);
         }
         else {
            if (span->array->ChanType == GL_UNSIGNED_BYTE) {
               span->array->rgba = span->array->rgba8;
            }
            else {
               span->array->rgba = (void *)span->array->attribs[FRAG_ATTRIB_COL];
            }
         }


         ASSERT(rb->_BaseFormat == GL_RGBA ||
                rb->_BaseFormat == GL_RGB ||
                rb->_BaseFormat == GL_RED ||
                rb->_BaseFormat == GL_RG ||
                rb->_BaseFormat == GL_ALPHA);

         if (ctx->Color.ColorLogicOpEnabled) {
            _swrast_logicop_rgba_span(ctx, rb, span);
         }
         else if (ctx->Color.BlendEnabled) {
            _swrast_blend_span(ctx, rb, span);
         }

         if (colorMask != 0xffffffff) {
            _swrast_mask_rgba_span(ctx, rb, span);
         }

         if (span->arrayMask & SPAN_XY) {
            /* array of pixel coords */
            put_values(ctx, rb,
                       span->array->ChanType, span->end,
                       span->array->x, span->array->y,
                       span->array->rgba, span->array->mask);
         }
         else {
            /* horizontal run of pixels */
            _swrast_put_row(ctx, rb,
                            span->array->ChanType,
                            span->end, span->x, span->y,
                            span->array->rgba,
                            span->writeAll ? NULL: span->array->mask);
         }

      } /* if rb */
   }

end:
   /* restore these values before returning */
   span->interpMask = origInterpMask;
   span->arrayMask = origArrayMask;
   span->arrayAttribs = origArrayAttribs;
   span->array->ChanType = origChanType;
   span->array->rgba = origRgba;
}