Exemple #1
0
void
_swrast_feedback_line(GLcontext *ctx, const SWvertex *v0,
                      const SWvertex *v1)
{
   GLenum token = GL_LINE_TOKEN;
   SWcontext *swrast = SWRAST_CONTEXT(ctx);

   if (swrast->StippleCounter == 0)
      token = GL_LINE_RESET_TOKEN;

   _mesa_feedback_token(ctx, (GLfloat) (GLint) token);

   if (ctx->Light.ShadeModel == GL_SMOOTH) {
      feedback_vertex(ctx, v0, v0);
      feedback_vertex(ctx, v1, v1);
   }
   else {
      feedback_vertex(ctx, v0, v1);
      feedback_vertex(ctx, v1, v1);
   }

   swrast->StippleCounter++;
}
Exemple #2
0
/**
 * Do software-based glCopyPixels.
 * By time we get here, all parameters will have been error-checked.
 */
void
_swrast_CopyPixels( GLcontext *ctx,
		    GLint srcx, GLint srcy, GLsizei width, GLsizei height,
		    GLint destx, GLint desty, GLenum type )
{
   SWcontext *swrast = SWRAST_CONTEXT(ctx);
   RENDER_START(swrast,ctx);
      
   if (swrast->NewState)
      _swrast_validate_derived( ctx );

   if (!fast_copy_pixels(ctx, srcx, srcy, width, height, destx, desty, type)) {
      switch (type) {
      case GL_COLOR:
         if (ctx->Visual.rgbMode) {
            copy_rgba_pixels( ctx, srcx, srcy, width, height, destx, desty );
         }
         else {
            copy_ci_pixels( ctx, srcx, srcy, width, height, destx, desty );
         }
         break;
      case GL_DEPTH:
         copy_depth_pixels( ctx, srcx, srcy, width, height, destx, desty );
         break;
      case GL_STENCIL:
         copy_stencil_pixels( ctx, srcx, srcy, width, height, destx, desty );
         break;
      case GL_DEPTH_STENCIL_EXT:
         copy_depth_stencil_pixels(ctx, srcx, srcy, width, height, destx, desty);
         break;
      default:
         _mesa_problem(ctx, "unexpected type in _swrast_CopyPixels");
      }
   }

   RENDER_FINISH(swrast,ctx);
}
Exemple #3
0
/*
 * Clear the front/back/left/right color buffers.
 * This function is usually only called if we need to clear the
 * buffers with masking.
 */
static void
clear_color_buffers(GLcontext *ctx)
{
   SWcontext *swrast = SWRAST_CONTEXT(ctx);
   const GLuint colorMask = *((GLuint *) &ctx->Color.ColorMask);
   GLuint bufferBit;

   /* loop over four possible dest color buffers */
   for (bufferBit = 1; bufferBit <= 8; bufferBit = bufferBit << 1) {
      if (bufferBit & ctx->Color._DrawDestMask) {
         (*swrast->Driver.SetBuffer)(ctx, ctx->DrawBuffer, bufferBit);

         if (colorMask != 0xffffffff) {
            clear_color_buffer_with_masking(ctx);
         }
         else {
            clear_color_buffer(ctx);
         }
      }
   }

   /* restore default read/draw buffer */
   _swrast_use_draw_buffer(ctx);
}
Exemple #4
0
/**
 * Determine if we can defer texturing/shading until after Z/stencil
 * testing.  This potentially allows us to skip texturing/shading for
 * lots of fragments.
 */
static void
_swrast_update_deferred_texture(GLcontext *ctx)
{
   SWcontext *swrast = SWRAST_CONTEXT(ctx);
   if (ctx->Color.AlphaEnabled) {
      /* alpha test depends on post-texture/shader colors */
      swrast->_DeferredTexture = GL_FALSE;
   }
   else {
      const struct gl_fragment_program *fprog
         = ctx->FragmentProgram._Current;
      if (fprog && (fprog->Base.OutputsWritten & (1 << FRAG_RESULT_DEPR))) {
         /* Z comes from fragment program/shader */
         swrast->_DeferredTexture = GL_FALSE;
      }
      else if (ctx->Query.CurrentOcclusionObject) {
         /* occlusion query depends on shader discard/kill results */
         swrast->_DeferredTexture = GL_FALSE;
      }
      else {
         swrast->_DeferredTexture = GL_TRUE;
      }
   }
}
Exemple #5
0
void ffbDDInitRenderFuncs( GLcontext *ctx )
{
 	TNLcontext *tnl = TNL_CONTEXT(ctx);
	SWcontext *swrast = SWRAST_CONTEXT(ctx);
	static int firsttime = 1;

	if (firsttime) {
		init_rast_tab();
		init_tri_tab();
		init_render_tab();
		firsttime = 0;
	}

	tnl->Driver.RunPipeline = ffbRunPipeline;
	tnl->Driver.Render.Start = ffbRenderStart;
	tnl->Driver.Render.Finish = ffbRenderFinish; 
	tnl->Driver.Render.PrimitiveNotify = ffbRenderPrimitive;
	tnl->Driver.Render.ResetLineStipple = _swrast_ResetLineStipple;
	tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts;
	tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts;

	swrast->Driver.SpanRenderStart = ffbSWRenderStart;
	swrast->Driver.SpanRenderFinish = ffbSWRenderFinish;
}
Exemple #6
0
/**
 * Update the swrast->_TextureCombinePrimary flag.
 */
static void
_swrast_update_texture_env( struct gl_context *ctx )
{
   SWcontext *swrast = SWRAST_CONTEXT(ctx);
   GLuint i;

   swrast->_TextureCombinePrimary = GL_FALSE;

   for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
      const struct gl_tex_env_combine_state *combine =
         ctx->Texture.Unit[i]._CurrentCombine;
      GLuint term;
      for (term = 0; term < combine->_NumArgsRGB; term++) {
         if (combine->SourceRGB[term] == GL_PRIMARY_COLOR) {
            swrast->_TextureCombinePrimary = GL_TRUE;
            return;
         }
         if (combine->SourceA[term] == GL_PRIMARY_COLOR) {
            swrast->_TextureCombinePrimary = GL_TRUE;
            return;
         }
      }
   }
}
Exemple #7
0
/**
 * Called via the device driver's ctx->Driver.Clear() function if the
 * device driver can't clear one or more of the buffers itself.
 * \param buffers  bitfield of BUFFER_BIT_* values indicating which
 *                 renderbuffers are to be cleared.
 * \param all  if GL_TRUE, clear whole buffer, else clear specified region.
 */
void
_swrast_Clear(struct gl_context *ctx, GLbitfield buffers)
{
#ifdef DEBUG_FOO
   {
      const GLbitfield legalBits =
         BUFFER_BIT_FRONT_LEFT |
	 BUFFER_BIT_FRONT_RIGHT |
	 BUFFER_BIT_BACK_LEFT |
	 BUFFER_BIT_BACK_RIGHT |
	 BUFFER_BIT_DEPTH |
	 BUFFER_BIT_STENCIL |
	 BUFFER_BIT_ACCUM |
         BUFFER_BIT_AUX0;
      assert((buffers & (~legalBits)) == 0);
   }
#endif

   if (SWRAST_CONTEXT(ctx)->NewState)
      _swrast_validate_derived(ctx);

   if (buffers & BUFFER_BITS_COLOR) {
      clear_color_buffers(ctx);
   }

   if (buffers & BUFFER_BIT_ACCUM) {
      _mesa_clear_accum_buffer(ctx);
   }

   if (buffers & BUFFER_BIT_DEPTH) {
      _swrast_clear_depth_buffer(ctx);
   }
   if (buffers & BUFFER_BIT_STENCIL) {
      _swrast_clear_stencil_buffer(ctx);
   }
}
Exemple #8
0
/*
 * New in Mesa 3.5
 *
 * Create context and specify size of ancillary buffers.
 */
GLAPI OSMesaContext GLAPIENTRY
OSMesaCreateContextExt( GLenum format, GLint depthBits, GLint stencilBits,
                        GLint accumBits, OSMesaContext sharelist )
{
   OSMesaContext osmesa;
   struct dd_function_table functions;
   GLint rind, gind, bind, aind;
   GLint indexBits = 0, redBits = 0, greenBits = 0, blueBits = 0, alphaBits =0;
   GLboolean rgbmode;

   rind = gind = bind = aind = 0;
   if (format==OSMESA_COLOR_INDEX) {
      indexBits = 8;
      rgbmode = GL_FALSE;
   }
   else if (format==OSMESA_RGBA) {
      indexBits = 0;
      redBits = CHAN_BITS;
      greenBits = CHAN_BITS;
      blueBits = CHAN_BITS;
      alphaBits = CHAN_BITS;
      rind = 0;
      gind = 1;
      bind = 2;
      aind = 3;
      rgbmode = GL_TRUE;
   }
   else if (format==OSMESA_BGRA) {
      indexBits = 0;
      redBits = CHAN_BITS;
      greenBits = CHAN_BITS;
      blueBits = CHAN_BITS;
      alphaBits = CHAN_BITS;
      bind = 0;
      gind = 1;
      rind = 2;
      aind = 3;
      rgbmode = GL_TRUE;
   }
   else if (format==OSMESA_ARGB) {
      indexBits = 0;
      redBits = CHAN_BITS;
      greenBits = CHAN_BITS;
      blueBits = CHAN_BITS;
      alphaBits = CHAN_BITS;
      aind = 0;
      rind = 1;
      gind = 2;
      bind = 3;
      rgbmode = GL_TRUE;
   }
   else if (format==OSMESA_RGB) {
      indexBits = 0;
      redBits = CHAN_BITS;
      greenBits = CHAN_BITS;
      blueBits = CHAN_BITS;
      alphaBits = 0;
      rind = 0;
      gind = 1;
      bind = 2;
      rgbmode = GL_TRUE;
   }
   else if (format==OSMESA_BGR) {
      indexBits = 0;
      redBits = CHAN_BITS;
      greenBits = CHAN_BITS;
      blueBits = CHAN_BITS;
      alphaBits = 0;
      rind = 2;
      gind = 1;
      bind = 0;
      rgbmode = GL_TRUE;
   }
#if CHAN_TYPE == GL_UNSIGNED_BYTE
   else if (format==OSMESA_RGB_565) {
      indexBits = 0;
      redBits = 5;
      greenBits = 6;
      blueBits = 5;
      alphaBits = 0;
      rind = 0; /* not used */
      gind = 0;
      bind = 0;
      rgbmode = GL_TRUE;
   }
#endif
   else {
      return NULL;
   }

   osmesa = (OSMesaContext) CALLOC_STRUCT(osmesa_context);
   if (osmesa) {
      osmesa->gl_visual = _mesa_create_visual( rgbmode,
                                               GL_FALSE,    /* double buffer */
                                               GL_FALSE,    /* stereo */
                                               redBits,
                                               greenBits,
                                               blueBits,
                                               alphaBits,
                                               indexBits,
                                               depthBits,
                                               stencilBits,
                                               accumBits,
                                               accumBits,
                                               accumBits,
                                               alphaBits ? accumBits : 0,
                                               1            /* num samples */
                                               );
      if (!osmesa->gl_visual) {
         FREE(osmesa);
         return NULL;
      }

      /* Initialize device driver function table */
      _mesa_init_driver_functions(&functions);
      /* override with our functions */
      functions.GetString = get_string;
      functions.UpdateState = osmesa_update_state;
      functions.GetBufferSize = get_buffer_size;

      if (!_mesa_initialize_context(&osmesa->mesa,
                                    osmesa->gl_visual,
                                    sharelist ? &sharelist->mesa
                                              : (GLcontext *) NULL,
                                    &functions, (void *) osmesa)) {
         _mesa_destroy_visual( osmesa->gl_visual );
         FREE(osmesa);
         return NULL;
      }

      _mesa_enable_sw_extensions(&(osmesa->mesa));
      _mesa_enable_1_3_extensions(&(osmesa->mesa));
      _mesa_enable_1_4_extensions(&(osmesa->mesa));
      _mesa_enable_1_5_extensions(&(osmesa->mesa));

      osmesa->gl_buffer = _mesa_create_framebuffer(osmesa->gl_visual);
      if (!osmesa->gl_buffer) {
         _mesa_destroy_visual( osmesa->gl_visual );
         _mesa_free_context_data( &osmesa->mesa );
         FREE(osmesa);
         return NULL;
      }

      /* create front color buffer in user-provided memory (no back buffer) */
      _mesa_add_renderbuffer(osmesa->gl_buffer, BUFFER_FRONT_LEFT,
                             new_osmesa_renderbuffer(format));
      _mesa_add_soft_renderbuffers(osmesa->gl_buffer,
                                   GL_FALSE, /* color */
                                   osmesa->gl_visual->haveDepthBuffer,
                                   osmesa->gl_visual->haveStencilBuffer,
                                   osmesa->gl_visual->haveAccumBuffer,
                                   GL_FALSE, /* alpha */
                                   GL_FALSE /* aux */ );

      osmesa->format = format;
      osmesa->buffer = NULL;
      osmesa->width = 0;
      osmesa->height = 0;
      osmesa->userRowLength = 0;
      osmesa->rowlength = 0;
      osmesa->yup = GL_TRUE;
      osmesa->rInd = rind;
      osmesa->gInd = gind;
      osmesa->bInd = bind;
      osmesa->aInd = aind;

      /* Initialize the software rasterizer and helper modules. */
      {
	 GLcontext *ctx = &osmesa->mesa;
         SWcontext *swrast;
         TNLcontext *tnl;

	 if (!_swrast_CreateContext( ctx ) ||
             !_ac_CreateContext( ctx ) ||
             !_tnl_CreateContext( ctx ) ||
             !_swsetup_CreateContext( ctx )) {
            _mesa_destroy_visual(osmesa->gl_visual);
            _mesa_free_context_data(ctx);
            _mesa_free(osmesa);
            return NULL;
         }
	
	 _swsetup_Wakeup( ctx );

         /* use default TCL pipeline */
         tnl = TNL_CONTEXT(ctx);
         tnl->Driver.RunPipeline = _tnl_run_pipeline;

         /* Extend the software rasterizer with our optimized line and triangle
          * drawing functions.
          */
         swrast = SWRAST_CONTEXT( ctx );
         swrast->choose_line = osmesa_choose_line;
         swrast->choose_triangle = osmesa_choose_triangle;
      }
   }
   return osmesa;
}
Exemple #9
0
/**
 * Apply texture mapping to a span of fragments.
 */
void
_swrast_texture_span( struct gl_context *ctx, SWspan *span )
{
   SWcontext *swrast = SWRAST_CONTEXT(ctx);
   float4_array primary_rgba;
   GLuint unit;

   if (!swrast->TexelBuffer) {
#ifdef _OPENMP
      const GLint maxThreads = omp_get_max_threads();
#else
      const GLint maxThreads = 1;
#endif

      /* TexelBuffer is also global and normally shared by all SWspan
       * instances; when running with multiple threads, create one per
       * thread.
       */
      swrast->TexelBuffer =
	 malloc(ctx->Const.FragmentProgram.MaxTextureImageUnits * maxThreads *
			    SWRAST_MAX_WIDTH * 4 * sizeof(GLfloat));
      if (!swrast->TexelBuffer) {
	 _mesa_error(ctx, GL_OUT_OF_MEMORY, "texture_combine");
	 return;
      }
   }

   primary_rgba = malloc(span->end * 4 * sizeof(GLfloat));

   if (!primary_rgba) {
      _mesa_error(ctx, GL_OUT_OF_MEMORY, "texture_span");
      return;
   }

   ASSERT(span->end <= SWRAST_MAX_WIDTH);

   /*
    * Save copy of the incoming fragment colors (the GL_PRIMARY_COLOR)
    */
   if (swrast->_TextureCombinePrimary) {
      GLuint i;
      for (i = 0; i < span->end; i++) {
         primary_rgba[i][RCOMP] = CHAN_TO_FLOAT(span->array->rgba[i][RCOMP]);
         primary_rgba[i][GCOMP] = CHAN_TO_FLOAT(span->array->rgba[i][GCOMP]);
         primary_rgba[i][BCOMP] = CHAN_TO_FLOAT(span->array->rgba[i][BCOMP]);
         primary_rgba[i][ACOMP] = CHAN_TO_FLOAT(span->array->rgba[i][ACOMP]);
      }
   }

   /* First must sample all bump maps */
   for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
      const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];

      if (texUnit->_ReallyEnabled &&
         texUnit->_CurrentCombine->ModeRGB == GL_BUMP_ENVMAP_ATI) {
         const GLfloat (*texcoords)[4] = (const GLfloat (*)[4])
            span->array->attribs[VARYING_SLOT_TEX0 + unit];
         float4_array targetcoords =
            span->array->attribs[VARYING_SLOT_TEX0 +
               ctx->Texture.Unit[unit].BumpTarget - GL_TEXTURE0];

         const struct gl_sampler_object *samp = _mesa_get_samplerobj(ctx, unit);
         GLfloat *lambda = span->array->lambda[unit];
         float4_array texels = get_texel_array(swrast, unit);
         GLuint i;
         GLfloat rotMatrix00 = ctx->Texture.Unit[unit].RotMatrix[0];
         GLfloat rotMatrix01 = ctx->Texture.Unit[unit].RotMatrix[1];
         GLfloat rotMatrix10 = ctx->Texture.Unit[unit].RotMatrix[2];
         GLfloat rotMatrix11 = ctx->Texture.Unit[unit].RotMatrix[3];

         /* adjust texture lod (lambda) */
         if (span->arrayMask & SPAN_LAMBDA) {
            if (texUnit->LodBias + samp->LodBias != 0.0F) {
               /* apply LOD bias, but don't clamp yet */
               const GLfloat bias = CLAMP(texUnit->LodBias + samp->LodBias,
                                          -ctx->Const.MaxTextureLodBias,
                                          ctx->Const.MaxTextureLodBias);
               GLuint i;
               for (i = 0; i < span->end; i++) {
                  lambda[i] += bias;
               }
            }

            if (samp->MinLod != -1000.0 ||
                samp->MaxLod != 1000.0) {
               /* apply LOD clamping to lambda */
               const GLfloat min = samp->MinLod;
               const GLfloat max = samp->MaxLod;
               GLuint i;
               for (i = 0; i < span->end; i++) {
                  GLfloat l = lambda[i];
                  lambda[i] = CLAMP(l, min, max);
               }
            }
         }

         /* Sample the texture (span->end = number of fragments) */
         swrast->TextureSample[unit]( ctx, samp,
                                      ctx->Texture.Unit[unit]._Current,
                                      span->end, texcoords, lambda, texels );

         /* manipulate the span values of the bump target
            not sure this can work correctly even ignoring
            the problem that channel is unsigned */
         for (i = 0; i < span->end; i++) {
            targetcoords[i][0] += (texels[i][0] * rotMatrix00 + texels[i][1] *
                                  rotMatrix01) / targetcoords[i][3];
            targetcoords[i][1] += (texels[i][0] * rotMatrix10 + texels[i][1] *
                                  rotMatrix11) / targetcoords[i][3];
         }
      }
   }

   /*
    * Must do all texture sampling before combining in order to
    * accomodate GL_ARB_texture_env_crossbar.
    */
   for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
      const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
      if (texUnit->_ReallyEnabled &&
          texUnit->_CurrentCombine->ModeRGB != GL_BUMP_ENVMAP_ATI) {
         const GLfloat (*texcoords)[4] = (const GLfloat (*)[4])
            span->array->attribs[VARYING_SLOT_TEX0 + unit];
         const struct gl_texture_object *curObj = texUnit->_Current;
         const struct gl_sampler_object *samp = _mesa_get_samplerobj(ctx, unit);
         GLfloat *lambda = span->array->lambda[unit];
         float4_array texels = get_texel_array(swrast, unit);

         /* adjust texture lod (lambda) */
         if (span->arrayMask & SPAN_LAMBDA) {
            if (texUnit->LodBias + samp->LodBias != 0.0F) {
               /* apply LOD bias, but don't clamp yet */
               const GLfloat bias = CLAMP(texUnit->LodBias + samp->LodBias,
                                          -ctx->Const.MaxTextureLodBias,
                                          ctx->Const.MaxTextureLodBias);
               GLuint i;
               for (i = 0; i < span->end; i++) {
                  lambda[i] += bias;
               }
            }

            if (samp->MinLod != -1000.0 ||
                samp->MaxLod != 1000.0) {
               /* apply LOD clamping to lambda */
               const GLfloat min = samp->MinLod;
               const GLfloat max = samp->MaxLod;
               GLuint i;
               for (i = 0; i < span->end; i++) {
                  GLfloat l = lambda[i];
                  lambda[i] = CLAMP(l, min, max);
               }
            }
         }
         else if (samp->MaxAnisotropy > 1.0 &&
                  samp->MinFilter == GL_LINEAR_MIPMAP_LINEAR) {
            /* sample_lambda_2d_aniso is beeing used as texture_sample_func,
             * it requires the current SWspan *span as an additional parameter.
             * In order to keep the same function signature, the unused lambda
             * parameter will be modified to actually contain the SWspan pointer.
             * This is a Hack. To make it right, the texture_sample_func
             * signature and all implementing functions need to be modified.
             */
            /* "hide" SWspan struct; cast to (GLfloat *) to suppress warning */
            lambda = (GLfloat *)span;
         }

         /* Sample the texture (span->end = number of fragments) */
         swrast->TextureSample[unit]( ctx, samp,
                                      ctx->Texture.Unit[unit]._Current,
                                      span->end, texcoords, lambda, texels );

         /* GL_EXT_texture_swizzle */
         if (curObj->_Swizzle != SWIZZLE_NOOP) {
            swizzle_texels(curObj->_Swizzle, span->end, texels);
         }
      }
   }

   /*
    * OK, now apply the texture (aka texture combine/blend).
    * We modify the span->color.rgba values.
    */
   for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
      if (ctx->Texture.Unit[unit]._ReallyEnabled)
         texture_combine(ctx, unit, primary_rgba, swrast->TexelBuffer, span);
   }

   free(primary_rgba);
}
static void
accum_load(GLcontext *ctx, GLfloat value,
           GLint xpos, GLint ypos, GLint width, GLint height )
{
   SWcontext *swrast = SWRAST_CONTEXT(ctx);
   struct gl_renderbuffer *rb
      = ctx->DrawBuffer->Attachment[BUFFER_ACCUM].Renderbuffer;
   const GLboolean directAccess = (rb->GetPointer(ctx, rb, 0, 0) != NULL);

   assert(rb);

   if (!ctx->ReadBuffer->_ColorReadBuffer) {
      /* no read buffer - OK */
      return;
   }

   /* This is a change to go into optimized accum buffer mode */
   if (value > 0.0 && value <= 1.0) {
#if USE_OPTIMIZED_ACCUM
      swrast->_IntegerAccumMode = GL_TRUE;
#else
      swrast->_IntegerAccumMode = GL_FALSE;
#endif
      swrast->_IntegerAccumScaler = value;
   }
   else {
      swrast->_IntegerAccumMode = GL_FALSE;
      swrast->_IntegerAccumScaler = 0.0;
   }

   if (rb->DataType == GL_SHORT || rb->DataType == GL_UNSIGNED_SHORT) {
      const GLfloat scale = value * ACCUM_SCALE16 / CHAN_MAXF;
      GLshort accumRow[4 * MAX_WIDTH];
      GLchan rgba[MAX_WIDTH][4];
      GLint i;

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

         /* read colors from color buffer */
         _swrast_read_rgba_span(ctx, ctx->ReadBuffer->_ColorReadBuffer, width,
                                xpos, ypos + i, CHAN_TYPE, rgba);

         /* do load */
         if (swrast->_IntegerAccumMode) {
            /* just copy values in */
            GLint j;
            assert(swrast->_IntegerAccumScaler > 0.0);
            assert(swrast->_IntegerAccumScaler <= 1.0);
            for (j = 0; j < width; j++) {
               acc[j * 4 + 0] = rgba[j][RCOMP];
               acc[j * 4 + 1] = rgba[j][GCOMP];
               acc[j * 4 + 2] = rgba[j][BCOMP];
               acc[j * 4 + 3] = rgba[j][ACOMP];
            }
         }
         else {
            /* scaled integer (or float) accum buffer */
            GLint j;
            for (j = 0; j < width; j++) {
               acc[j * 4 + 0] = (GLshort) ((GLfloat) rgba[j][RCOMP] * scale);
               acc[j * 4 + 1] = (GLshort) ((GLfloat) rgba[j][GCOMP] * scale);
               acc[j * 4 + 2] = (GLshort) ((GLfloat) rgba[j][BCOMP] * scale);
               acc[j * 4 + 3] = (GLshort) ((GLfloat) rgba[j][ACOMP] * scale);
            }
         }

         if (!directAccess) {
            rb->PutRow(ctx, rb, width, xpos, ypos + i, accumRow, NULL);
         }
      }
   }
}
Exemple #11
0
/**
 * Helper function called from _swrast_write_zoomed_rgba/rgb/
 * index/depth_span().
 */
static void
zoom_span( struct gl_context *ctx, GLint imgX, GLint imgY, const SWspan *span,
           const GLvoid *src, GLenum format )
{
   SWcontext *swrast = SWRAST_CONTEXT(ctx);
   SWspan zoomed;
   GLint x0, x1, y0, y1;
   GLint zoomedWidth;

   if (!compute_zoomed_bounds(ctx, imgX, imgY, span->x, span->y, span->end,
                              &x0, &x1, &y0, &y1)) {
      return;  /* totally clipped */
   }

   if (!swrast->ZoomedArrays) {
      /* allocate on demand */
      swrast->ZoomedArrays = (SWspanarrays *) CALLOC(sizeof(SWspanarrays));
      if (!swrast->ZoomedArrays)
         return;
   }

   zoomedWidth = x1 - x0;
   ASSERT(zoomedWidth > 0);
   ASSERT(zoomedWidth <= MAX_WIDTH);

   /* no pixel arrays! must be horizontal spans. */
   ASSERT((span->arrayMask & SPAN_XY) == 0);
   ASSERT(span->primitive == GL_BITMAP);

   INIT_SPAN(zoomed, GL_BITMAP);
   zoomed.x = x0;
   zoomed.end = zoomedWidth;
   zoomed.array = swrast->ZoomedArrays;
   zoomed.array->ChanType = span->array->ChanType;
   if (zoomed.array->ChanType == GL_UNSIGNED_BYTE)
      zoomed.array->rgba = (GLchan (*)[4]) zoomed.array->rgba8;
   else if (zoomed.array->ChanType == GL_UNSIGNED_SHORT)
      zoomed.array->rgba = (GLchan (*)[4]) zoomed.array->rgba16;
   else
      zoomed.array->rgba = (GLchan (*)[4]) zoomed.array->attribs[FRAG_ATTRIB_COL];

   COPY_4V(zoomed.attrStart[FRAG_ATTRIB_WPOS], span->attrStart[FRAG_ATTRIB_WPOS]);
   COPY_4V(zoomed.attrStepX[FRAG_ATTRIB_WPOS], span->attrStepX[FRAG_ATTRIB_WPOS]);
   COPY_4V(zoomed.attrStepY[FRAG_ATTRIB_WPOS], span->attrStepY[FRAG_ATTRIB_WPOS]);

   zoomed.attrStart[FRAG_ATTRIB_FOGC][0] = span->attrStart[FRAG_ATTRIB_FOGC][0];
   zoomed.attrStepX[FRAG_ATTRIB_FOGC][0] = span->attrStepX[FRAG_ATTRIB_FOGC][0];
   zoomed.attrStepY[FRAG_ATTRIB_FOGC][0] = span->attrStepY[FRAG_ATTRIB_FOGC][0];

   if (format == GL_RGBA || format == GL_RGB) {
      /* copy Z info */
      zoomed.z = span->z;
      zoomed.zStep = span->zStep;
      /* we'll generate an array of colorss */
      zoomed.interpMask = span->interpMask & ~SPAN_RGBA;
      zoomed.arrayMask |= SPAN_RGBA;
      zoomed.arrayAttribs |= FRAG_BIT_COL;  /* we'll produce these values */
      ASSERT(span->arrayMask & SPAN_RGBA);
   }
   else if (format == GL_DEPTH_COMPONENT) {
      /* Copy color info */
      zoomed.red = span->red;
      zoomed.green = span->green;
      zoomed.blue = span->blue;
      zoomed.alpha = span->alpha;
      zoomed.redStep = span->redStep;
      zoomed.greenStep = span->greenStep;
      zoomed.blueStep = span->blueStep;
      zoomed.alphaStep = span->alphaStep;
      /* we'll generate an array of depth values */
      zoomed.interpMask = span->interpMask & ~SPAN_Z;
      zoomed.arrayMask |= SPAN_Z;
      ASSERT(span->arrayMask & SPAN_Z);
   }
   else {
      _mesa_problem(ctx, "Bad format in zoom_span");
      return;
   }

   /* zoom the span horizontally */
   if (format == GL_RGBA) {
      if (zoomed.array->ChanType == GL_UNSIGNED_BYTE) {
         const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) src;
         GLint i;
         for (i = 0; i < zoomedWidth; i++) {
            GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - span->x;
            ASSERT(j >= 0);
            ASSERT(j < (GLint) span->end);
            COPY_4UBV(zoomed.array->rgba8[i], rgba[j]);
         }
      }
      else if (zoomed.array->ChanType == GL_UNSIGNED_SHORT) {
         const GLushort (*rgba)[4] = (const GLushort (*)[4]) src;
         GLint i;
         for (i = 0; i < zoomedWidth; i++) {
            GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - span->x;
            ASSERT(j >= 0);
            ASSERT(j < (GLint) span->end);
            COPY_4V(zoomed.array->rgba16[i], rgba[j]);
         }
      }
      else {
         const GLfloat (*rgba)[4] = (const GLfloat (*)[4]) src;
         GLint i;
         for (i = 0; i < zoomedWidth; i++) {
            GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - span->x;
            ASSERT(j >= 0);
            ASSERT(j < span->end);
            COPY_4V(zoomed.array->attribs[FRAG_ATTRIB_COL][i], rgba[j]);
         }
      }
   }
   else if (format == GL_RGB) {
      if (zoomed.array->ChanType == GL_UNSIGNED_BYTE) {
         const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) src;
         GLint i;
         for (i = 0; i < zoomedWidth; i++) {
            GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - span->x;
            ASSERT(j >= 0);
            ASSERT(j < (GLint) span->end);
            zoomed.array->rgba8[i][0] = rgb[j][0];
            zoomed.array->rgba8[i][1] = rgb[j][1];
            zoomed.array->rgba8[i][2] = rgb[j][2];
            zoomed.array->rgba8[i][3] = 0xff;
         }
      }
      else if (zoomed.array->ChanType == GL_UNSIGNED_SHORT) {
         const GLushort (*rgb)[3] = (const GLushort (*)[3]) src;
         GLint i;
         for (i = 0; i < zoomedWidth; i++) {
            GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - span->x;
            ASSERT(j >= 0);
            ASSERT(j < (GLint) span->end);
            zoomed.array->rgba16[i][0] = rgb[j][0];
            zoomed.array->rgba16[i][1] = rgb[j][1];
            zoomed.array->rgba16[i][2] = rgb[j][2];
            zoomed.array->rgba16[i][3] = 0xffff;
         }
      }
      else {
         const GLfloat (*rgb)[3] = (const GLfloat (*)[3]) src;
         GLint i;
         for (i = 0; i < zoomedWidth; i++) {
            GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - span->x;
            ASSERT(j >= 0);
            ASSERT(j < span->end);
            zoomed.array->attribs[FRAG_ATTRIB_COL][i][0] = rgb[j][0];
            zoomed.array->attribs[FRAG_ATTRIB_COL][i][1] = rgb[j][1];
            zoomed.array->attribs[FRAG_ATTRIB_COL][i][2] = rgb[j][2];
            zoomed.array->attribs[FRAG_ATTRIB_COL][i][3] = 1.0F;
         }
      }
   }
   else if (format == GL_DEPTH_COMPONENT) {
      const GLuint *zValues = (const GLuint *) src;
      GLint i;
      for (i = 0; i < zoomedWidth; i++) {
         GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - span->x;
         ASSERT(j >= 0);
         ASSERT(j < (GLint) span->end);
         zoomed.array->z[i] = zValues[j];
      }
      /* Now, fall into the RGB path below */
      format = GL_RGBA;
   }

   /* write the span in rows [r0, r1) */
   if (format == GL_RGBA || format == GL_RGB) {
      /* Writing the span may modify the colors, so make a backup now if we're
       * going to call _swrast_write_zoomed_span() more than once.
       * Also, clipping may change the span end value, so store it as well.
       */
      const GLint end = zoomed.end; /* save */
      void *rgbaSave;
      const GLint pixelSize =
         (zoomed.array->ChanType == GL_UNSIGNED_BYTE) ? 4 * sizeof(GLubyte) :
         ((zoomed.array->ChanType == GL_UNSIGNED_SHORT) ? 4 * sizeof(GLushort)
          : 4 * sizeof(GLfloat));

      rgbaSave = malloc(zoomed.end * pixelSize);
      if (!rgbaSave) {
         return;
      }

      if (y1 - y0 > 1) {
         memcpy(rgbaSave, zoomed.array->rgba, zoomed.end * pixelSize);
      }
      for (zoomed.y = y0; zoomed.y < y1; zoomed.y++) {
         _swrast_write_rgba_span(ctx, &zoomed);
         zoomed.end = end;  /* restore */
         if (y1 - y0 > 1) {
            /* restore the colors */
            memcpy(zoomed.array->rgba, rgbaSave, zoomed.end * pixelSize);
         }
      }

      free(rgbaSave);
   }
}
/**
 * Recompute the value of swrast->_RasterMask, etc. according to
 * the current context.  The _RasterMask field can be easily tested by
 * drivers to determine certain basic GL state (does the primitive need
 * stenciling, logic-op, fog, etc?).
 */
static void
_swrast_update_rasterflags( GLcontext *ctx )
{
   GLuint rasterMask = 0;

   if (ctx->Color.AlphaEnabled)           rasterMask |= ALPHATEST_BIT;
   if (ctx->Color.BlendEnabled)           rasterMask |= BLEND_BIT;
   if (ctx->Depth.Test)                   rasterMask |= DEPTH_BIT;
   if (ctx->Fog.Enabled)                  rasterMask |= FOG_BIT;
   if (ctx->Scissor.Enabled)              rasterMask |= CLIP_BIT;
   if (ctx->Stencil.Enabled)              rasterMask |= STENCIL_BIT;
   if (ctx->Visual.rgbMode) {
      const GLuint colorMask = *((GLuint *) &ctx->Color.ColorMask);
      if (colorMask != 0xffffffff)        rasterMask |= MASKING_BIT;
      if (ctx->Color._LogicOpEnabled)     rasterMask |= LOGIC_OP_BIT;
      if (ctx->Texture._EnabledUnits)     rasterMask |= TEXTURE_BIT;
   }
   else {
      if (ctx->Color.IndexMask != 0xffffffff) rasterMask |= MASKING_BIT;
      if (ctx->Color.IndexLogicOpEnabled)     rasterMask |= LOGIC_OP_BIT;
   }

   if (ctx->DrawBuffer->UseSoftwareAlphaBuffers
       && ctx->Color.ColorMask[ACOMP]
       && ctx->Color.DrawBuffer != GL_NONE)
      rasterMask |= ALPHABUF_BIT;

   if (   ctx->Viewport.X < 0
       || ctx->Viewport.X + ctx->Viewport.Width > (GLint) ctx->DrawBuffer->Width
       || ctx->Viewport.Y < 0
       || ctx->Viewport.Y + ctx->Viewport.Height > (GLint) ctx->DrawBuffer->Height) {
      rasterMask |= CLIP_BIT;
   }

   if (ctx->Depth.OcclusionTest || ctx->Occlusion.Active)
      rasterMask |= OCCLUSION_BIT;


   /* If we're not drawing to exactly one color buffer set the
    * MULTI_DRAW_BIT flag.  Also set it if we're drawing to no
    * buffers or the RGBA or CI mask disables all writes.
    */
   if (_mesa_bitcount(ctx->Color._DrawDestMask[0]) != 1) {
      /* more than one color buffer designated for writing (or zero buffers) */
      rasterMask |= MULTI_DRAW_BIT;
   }
   else if (ctx->Visual.rgbMode && *((GLuint *) ctx->Color.ColorMask) == 0) {
      rasterMask |= MULTI_DRAW_BIT; /* all RGBA channels disabled */
   }
   else if (!ctx->Visual.rgbMode && ctx->Color.IndexMask==0) {
      rasterMask |= MULTI_DRAW_BIT; /* all color index bits disabled */
   }

   if (ctx->FragmentProgram._Enabled) {
      rasterMask |= FRAGPROG_BIT;
   }

   if (ctx->ATIFragmentShader._Enabled) {
      rasterMask |= ATIFRAGSHADER_BIT;
   }

   SWRAST_CONTEXT(ctx)->_RasterMask = rasterMask;
}
Exemple #13
0
void
_swrast_SetFacing(struct gl_context *ctx, GLuint facing)
{
   SWRAST_CONTEXT(ctx)->PointLineFacing = facing;
}
Exemple #14
0
/**
 * Apply stencil test to an array of pixels before depth buffering.
 *
 * \note Used for software stencil buffer only.
 * Input:  n - number of pixels in the span
 *         x, y - array of [n] pixels to stencil
 *         mask - array [n] of flag:  0=skip the pixel, 1=stencil the pixel
 * Output:  mask - pixels which fail the stencil test will have their
 *                 mask flag set to 0.
 * \return  GL_FALSE = all pixels failed, GL_TRUE = zero or more pixels passed.
 */
static GLboolean
stencil_test_pixels( GLcontext *ctx, GLuint face, GLuint n,
                     const GLint x[], const GLint y[], GLubyte mask[] )
{
   GLubyte fail[MAX_WIDTH];
   GLstencil r, s;
   GLuint i;
   GLboolean allfail = GL_FALSE;
   const GLuint valueMask = ctx->Stencil.ValueMask[face];

  /* software stencil buffer only! */
   ASSERT(ctx->DrawBuffer->UseSoftwareStencilBuffer);
   ASSERT(!SWRAST_CONTEXT(ctx)->Driver.ReadStencilSpan);
   ASSERT(!SWRAST_CONTEXT(ctx)->Driver.WriteStencilSpan);

   /*
    * Perform stencil test.  The results of this operation are stored
    * in the fail[] array:
    *   IF fail[i] is non-zero THEN
    *       the stencil fail operator is to be applied
    *   ELSE
    *       the stencil fail operator is not to be applied
    *   ENDIF
    */

   switch (ctx->Stencil.Function[face]) {
      case GL_NEVER:
         /* always fail */
         for (i=0;i<n;i++) {
	    if (mask[i]) {
	       mask[i] = 0;
	       fail[i] = 1;
	    }
	    else {
	       fail[i] = 0;
	    }
	 }
	 allfail = GL_TRUE;
	 break;
      case GL_LESS:
	 r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
	 for (i=0;i<n;i++) {
	    if (mask[i]) {
               GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
	       s = (GLstencil) (*sptr & valueMask);
	       if (r < s) {
		  /* passed */
		  fail[i] = 0;
	       }
	       else {
		  fail[i] = 1;
		  mask[i] = 0;
	       }
	    }
	    else {
	       fail[i] = 0;
	    }
	 }
	 break;
      case GL_LEQUAL:
	 r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
	 for (i=0;i<n;i++) {
	    if (mask[i]) {
               GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
	       s = (GLstencil) (*sptr & valueMask);
	       if (r <= s) {
		  /* pass */
		  fail[i] = 0;
	       }
	       else {
		  fail[i] = 1;
		  mask[i] = 0;
	       }
	    }
	    else {
	       fail[i] = 0;
	    }
	 }
	 break;
      case GL_GREATER:
	 r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
	 for (i=0;i<n;i++) {
	    if (mask[i]) {
               GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
	       s = (GLstencil) (*sptr & valueMask);
	       if (r > s) {
		  /* passed */
		  fail[i] = 0;
	       }
	       else {
		  fail[i] = 1;
		  mask[i] = 0;
	       }
	    }
	    else {
	       fail[i] = 0;
	    }
	 }
	 break;
      case GL_GEQUAL:
	 r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
	 for (i=0;i<n;i++) {
	    if (mask[i]) {
               GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
	       s = (GLstencil) (*sptr & valueMask);
	       if (r >= s) {
		  /* passed */
		  fail[i] = 0;
	       }
	       else {
		  fail[i] = 1;
		  mask[i] = 0;
	       }
	    }
	    else {
	       fail[i] = 0;
	    }
	 }
	 break;
      case GL_EQUAL:
	 r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
	 for (i=0;i<n;i++) {
	    if (mask[i]) {
               GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
	       s = (GLstencil) (*sptr & valueMask);
	       if (r == s) {
		  /* passed */
		  fail[i] = 0;
	       }
	       else {
		  fail[i] = 1;
		  mask[i] = 0;
	       }
	    }
	    else {
	       fail[i] = 0;
	    }
	 }
	 break;
      case GL_NOTEQUAL:
	 r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
	 for (i=0;i<n;i++) {
	    if (mask[i]) {
               GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
	       s = (GLstencil) (*sptr & valueMask);
	       if (r != s) {
		  /* passed */
		  fail[i] = 0;
	       }
	       else {
		  fail[i] = 1;
		  mask[i] = 0;
	       }
	    }
	    else {
	       fail[i] = 0;
	    }
	 }
	 break;
      case GL_ALWAYS:
	 /* always pass */
	 for (i=0;i<n;i++) {
	    fail[i] = 0;
	 }
	 break;
      default:
         _mesa_problem(ctx, "Bad stencil func in gl_stencil_pixels");
         return 0;
   }

   if (ctx->Stencil.FailFunc[face] != GL_KEEP) {
      apply_stencil_op_to_pixels( ctx, n, x, y, ctx->Stencil.FailFunc[face],
                                  face, fail );
   }

   return !allfail;
}
Exemple #15
0
/**
 * Apply the given stencil operator for each pixel in the array whose
 * mask flag is set.
 * \note  This is for software stencil buffers only.
 * Input:  n - number of pixels in the span
 *         x, y - array of [n] pixels
 *         operator - the stencil buffer operator
 *         mask - array [n] of flag:  1=apply operator, 0=don't apply operator
 */
static void
apply_stencil_op_to_pixels( const GLcontext *ctx,
                            GLuint n, const GLint x[], const GLint y[],
                            GLenum oper, GLuint face, const GLubyte mask[] )
{
   const GLstencil ref = ctx->Stencil.Ref[face];
   const GLstencil wrtmask = ctx->Stencil.WriteMask[face];
   const GLstencil invmask = (GLstencil) (~wrtmask);
   GLuint i;

   ASSERT(!SWRAST_CONTEXT(ctx)->Driver.WriteStencilSpan);  /* software stencil buffer only! */

   switch (oper) {
      case GL_KEEP:
         /* do nothing */
         break;
      case GL_ZERO:
	 if (invmask==0) {
	    for (i=0;i<n;i++) {
	       if (mask[i]) {
                  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
                  *sptr = 0;
	       }
	    }
	 }
	 else {
	    for (i=0;i<n;i++) {
	       if (mask[i]) {
                  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
		  *sptr = (GLstencil) (invmask & *sptr);
	       }
	    }
	 }
	 break;
      case GL_REPLACE:
	 if (invmask==0) {
	    for (i=0;i<n;i++) {
	       if (mask[i]) {
                  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
                  *sptr = ref;
	       }
	    }
	 }
	 else {
	    for (i=0;i<n;i++) {
	       if (mask[i]) {
                  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
		  *sptr = (GLstencil) ((invmask & *sptr ) | (wrtmask & ref));
	       }
	    }
	 }
	 break;
      case GL_INCR:
	 if (invmask==0) {
	    for (i=0;i<n;i++) {
	       if (mask[i]) {
                  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
		  if (*sptr < STENCIL_MAX) {
		     *sptr = (GLstencil) (*sptr + 1);
		  }
	       }
	    }
	 }
	 else {
	    for (i=0;i<n;i++) {
	       if (mask[i]) {
                  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
		  if (*sptr < STENCIL_MAX) {
		     *sptr = (GLstencil) ((invmask & *sptr) | (wrtmask & (*sptr+1)));
		  }
	       }
	    }
	 }
	 break;
      case GL_DECR:
	 if (invmask==0) {
	    for (i=0;i<n;i++) {
	       if (mask[i]) {
                  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
		  if (*sptr>0) {
		     *sptr = (GLstencil) (*sptr - 1);
		  }
	       }
	    }
	 }
	 else {
	    for (i=0;i<n;i++) {
	       if (mask[i]) {
                  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
		  if (*sptr>0) {
		     *sptr = (GLstencil) ((invmask & *sptr) | (wrtmask & (*sptr-1)));
		  }
	       }
	    }
	 }
	 break;
      case GL_INCR_WRAP_EXT:
	 if (invmask==0) {
	    for (i=0;i<n;i++) {
	       if (mask[i]) {
                  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
                  *sptr = (GLstencil) (*sptr + 1);
	       }
	    }
	 }
	 else {
	    for (i=0;i<n;i++) {
	       if (mask[i]) {
                  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
                  *sptr = (GLstencil) ((invmask & *sptr) | (wrtmask & (*sptr+1)));
	       }
	    }
	 }
	 break;
      case GL_DECR_WRAP_EXT:
	 if (invmask==0) {
	    for (i=0;i<n;i++) {
	       if (mask[i]) {
                  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
                  *sptr = (GLstencil) (*sptr - 1);
	       }
	    }
	 }
	 else {
	    for (i=0;i<n;i++) {
	       if (mask[i]) {
                  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
                  *sptr = (GLstencil) ((invmask & *sptr) | (wrtmask & (*sptr-1)));
	       }
	    }
	 }
	 break;
      case GL_INVERT:
	 if (invmask==0) {
	    for (i=0;i<n;i++) {
	       if (mask[i]) {
                  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
                  *sptr = (GLstencil) (~*sptr);
	       }
	    }
	 }
	 else {
	    for (i=0;i<n;i++) {
	       if (mask[i]) {
                  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
                  *sptr = (GLstencil) ((invmask & *sptr) | (wrtmask & ~*sptr));
	       }
	    }
	 }
	 break;
      default:
         _mesa_problem(ctx, "Bad stencilop in apply_stencil_op_to_pixels");
   }
}
Exemple #16
0
/**
 * Apply stencil and depth testing to the span of pixels.
 * Both software and hardware stencil buffers are acceptable.
 * Input:  n - number of pixels in the span
 *         x, y - location of leftmost pixel in span
 *         z - array [n] of z values
 *         mask - array [n] of flags  (1=test this pixel, 0=skip the pixel)
 * Output:  mask - array [n] of flags (1=stencil and depth test passed)
 * Return: GL_FALSE - all fragments failed the testing
 *         GL_TRUE - one or more fragments passed the testing
 *
 */
static GLboolean
stencil_and_ztest_span(GLcontext *ctx, struct sw_span *span, GLuint face)
{
   SWcontext *swrast = SWRAST_CONTEXT(ctx);
   GLstencil stencilRow[MAX_WIDTH];
   GLstencil *stencil;
   const GLuint n = span->end;
   const GLint x = span->x;
   const GLint y = span->y;
   GLubyte *mask = span->array->mask;

   ASSERT((span->arrayMask & SPAN_XY) == 0);
   ASSERT(ctx->Stencil.Enabled);
   ASSERT(n <= MAX_WIDTH);
#ifdef DEBUG
   if (ctx->Depth.Test) {
      ASSERT(span->arrayMask & SPAN_Z);
   }
#endif
   
   /* Get initial stencil values */
   if (swrast->Driver.WriteStencilSpan) {
      /* Get stencil values from the hardware stencil buffer */
      ASSERT(swrast->Driver.ReadStencilSpan);
      (*swrast->Driver.ReadStencilSpan)(ctx, n, x, y, stencilRow);
      stencil = stencilRow;
   }
   else {
      /* Get pointer into software stencil buffer */
      stencil = STENCIL_ADDRESS(x, y);
   }
   
   /*
    * Apply the stencil test to the fragments.
    * failMask[i] is 1 if the stencil test failed.
    */
   if (do_stencil_test( ctx, face, n, stencil, mask ) == GL_FALSE) {
      /* all fragments failed the stencil test, we're done. */
      span->writeAll = GL_FALSE;
      return GL_FALSE;
   }

   /*
    * Some fragments passed the stencil test, apply depth test to them
    * and apply Zpass and Zfail stencil ops.
    */
   if (ctx->Depth.Test == GL_FALSE) {
      /*
       * No depth buffer, just apply zpass stencil function to active pixels.
       */
      apply_stencil_op( ctx, ctx->Stencil.ZPassFunc[face], face, n, stencil, mask );
   }
   else {
      /*
       * Perform depth buffering, then apply zpass or zfail stencil function.
       */
      GLubyte passmask[MAX_WIDTH], failmask[MAX_WIDTH], oldmask[MAX_WIDTH];
      GLuint i;

      /* save the current mask bits */
      MEMCPY(oldmask, mask, n * sizeof(GLubyte));

      /* apply the depth test */
      _swrast_depth_test_span(ctx, span);

      /* Set the stencil pass/fail flags according to result of depth testing.
       * if oldmask[i] == 0 then
       *    Don't touch the stencil value
       * else if oldmask[i] and newmask[i] then
       *    Depth test passed
       * else
       *    assert(oldmask[i] && !newmask[i])
       *    Depth test failed
       * endif
       */
      for (i=0;i<n;i++) {
         ASSERT(mask[i] == 0 || mask[i] == 1);
         passmask[i] = oldmask[i] & mask[i];
         failmask[i] = oldmask[i] & (mask[i] ^ 1);
      }

      /* apply the pass and fail operations */
      if (ctx->Stencil.ZFailFunc[face] != GL_KEEP) {
         apply_stencil_op( ctx, ctx->Stencil.ZFailFunc[face], face,
                           n, stencil, failmask );
      }
      if (ctx->Stencil.ZPassFunc[face] != GL_KEEP) {
         apply_stencil_op( ctx, ctx->Stencil.ZPassFunc[face], face,
                           n, stencil, passmask );
      }
   }

   /*
    * Write updated stencil values back into hardware stencil buffer.
    */
   if (swrast->Driver.WriteStencilSpan) {
      ASSERT(stencil == stencilRow);
      (swrast->Driver.WriteStencilSpan)(ctx, n, x, y, stencil, mask );
   }
   
   span->writeAll = GL_FALSE;
   
   return GL_TRUE;  /* one or more fragments passed both tests */
}
Exemple #17
0
/**
 * Recompute the value of swrast->_RasterMask, etc. according to
 * the current context.  The _RasterMask field can be easily tested by
 * drivers to determine certain basic GL state (does the primitive need
 * stenciling, logic-op, fog, etc?).
 */
static void
_swrast_update_rasterflags( struct gl_context *ctx )
{
   SWcontext *swrast = SWRAST_CONTEXT(ctx);
   GLbitfield rasterMask = 0;
   GLuint i;

   if (ctx->Color.AlphaEnabled)           rasterMask |= ALPHATEST_BIT;
   if (ctx->Color.BlendEnabled)           rasterMask |= BLEND_BIT;
   if (ctx->Depth.Test)                   rasterMask |= DEPTH_BIT;
   if (swrast->_FogEnabled)               rasterMask |= FOG_BIT;
   if (ctx->Scissor.EnableFlags)          rasterMask |= CLIP_BIT;
   if (ctx->Stencil._Enabled)             rasterMask |= STENCIL_BIT;
   for (i = 0; i < ctx->Const.MaxDrawBuffers; i++) {
      if (!ctx->Color.ColorMask[i][0] ||
          !ctx->Color.ColorMask[i][1] ||
          !ctx->Color.ColorMask[i][2] ||
          !ctx->Color.ColorMask[i][3]) {
         rasterMask |= MASKING_BIT;
         break;
      }
   }
   if (ctx->Color.ColorLogicOpEnabled) rasterMask |= LOGIC_OP_BIT;
   if (ctx->Texture._MaxEnabledTexImageUnit >= 0) rasterMask |= TEXTURE_BIT;
   if (   ctx->ViewportArray[0].X < 0
       || ctx->ViewportArray[0].X + ctx->ViewportArray[0].Width > (GLfloat) ctx->DrawBuffer->Width
       || ctx->ViewportArray[0].Y < 0
       || ctx->ViewportArray[0].Y + ctx->ViewportArray[0].Height > (GLfloat) ctx->DrawBuffer->Height) {
      rasterMask |= CLIP_BIT;
   }

   if (ctx->Query.CurrentOcclusionObject)
      rasterMask |= OCCLUSION_BIT;


   /* If we're not drawing to exactly one color buffer set the
    * MULTI_DRAW_BIT flag.  Also set it if we're drawing to no
    * buffers or the RGBA or CI mask disables all writes.
    */
   if (ctx->DrawBuffer->_NumColorDrawBuffers != 1) {
      /* more than one color buffer designated for writing (or zero buffers) */
      rasterMask |= MULTI_DRAW_BIT;
   }

   for (i = 0; i < ctx->Const.MaxDrawBuffers; i++) {
      if (ctx->Color.ColorMask[i][0] +
          ctx->Color.ColorMask[i][1] +
          ctx->Color.ColorMask[i][2] +
          ctx->Color.ColorMask[i][3] == 0) {
         rasterMask |= MULTI_DRAW_BIT; /* all RGBA channels disabled */
         break;
      }
   }


   if (_swrast_use_fragment_program(ctx)) {
      rasterMask |= FRAGPROG_BIT;
   }

   if (ctx->ATIFragmentShader._Enabled) {
      rasterMask |= ATIFRAGSHADER_BIT;
   }

#if CHAN_TYPE == GL_FLOAT
   if (ctx->Color.ClampFragmentColor == GL_TRUE) {
      rasterMask |= CLAMPING_BIT;
   }
#endif

   SWRAST_CONTEXT(ctx)->_RasterMask = rasterMask;
}
Exemple #18
0
/**
 * Apply stencil and depth testing to an array of pixels.
 * This is used both for software and hardware stencil buffers.
 *
 * The comments in this function are a bit sparse but the code is
 * almost identical to stencil_and_ztest_span(), which is well
 * commented.
 *
 * Input:  n - number of pixels in the array
 *         x, y - array of [n] pixel positions
 *         z - array [n] of z values
 *         mask - array [n] of flags  (1=test this pixel, 0=skip the pixel)
 * Output: mask - array [n] of flags (1=stencil and depth test passed)
 * Return: GL_FALSE - all fragments failed the testing
 *         GL_TRUE - one or more fragments passed the testing
 */
static GLboolean
stencil_and_ztest_pixels( GLcontext *ctx, struct sw_span *span, GLuint face )
{
   const GLuint n = span->end;
   const GLint *x = span->array->x;
   const GLint *y = span->array->y;
   GLubyte *mask = span->array->mask;
   SWcontext *swrast = SWRAST_CONTEXT(ctx);

   ASSERT(span->arrayMask & SPAN_XY);
   ASSERT(ctx->Stencil.Enabled);
   ASSERT(n <= MAX_WIDTH);

   if (swrast->Driver.WriteStencilPixels) {
      /*** Hardware stencil buffer ***/
      GLstencil stencil[MAX_WIDTH];
      GLubyte origMask[MAX_WIDTH];

      ASSERT(!ctx->DrawBuffer->UseSoftwareStencilBuffer);
      ASSERT(swrast->Driver.ReadStencilPixels);
      (*swrast->Driver.ReadStencilPixels)(ctx, n, x, y, stencil);

      MEMCPY(origMask, mask, n * sizeof(GLubyte));

      (void) do_stencil_test(ctx, face, n, stencil, mask);

      if (ctx->Depth.Test == GL_FALSE) {
         apply_stencil_op(ctx, ctx->Stencil.ZPassFunc[face], face,
                          n, stencil, mask);
      }
      else {
         _swrast_depth_test_span(ctx, span);

         if (ctx->Stencil.ZFailFunc[face] != GL_KEEP) {
            GLubyte failmask[MAX_WIDTH];
            GLuint i;
            for (i = 0; i < n; i++) {
               ASSERT(mask[i] == 0 || mask[i] == 1);
               failmask[i] = origMask[i] & (mask[i] ^ 1);
            }
            apply_stencil_op(ctx, ctx->Stencil.ZFailFunc[face], face,
                             n, stencil, failmask);
         }
         if (ctx->Stencil.ZPassFunc[face] != GL_KEEP) {
            GLubyte passmask[MAX_WIDTH];
            GLuint i;
            for (i = 0; i < n; i++) {
               ASSERT(mask[i] == 0 || mask[i] == 1);
               passmask[i] = origMask[i] & mask[i];
            }
            apply_stencil_op(ctx, ctx->Stencil.ZPassFunc[face], face,
                             n, stencil, passmask);
         }
      }

      /* Write updated stencil values into hardware stencil buffer */
      (swrast->Driver.WriteStencilPixels)(ctx, n, x, y, stencil, origMask);

      return GL_TRUE;
   }
   else {
      /*** Software stencil buffer ***/

      ASSERT(ctx->DrawBuffer->UseSoftwareStencilBuffer);

      if (stencil_test_pixels(ctx, face, n, x, y, mask) == GL_FALSE) {
         /* all fragments failed the stencil test, we're done. */
         return GL_FALSE;
      }

      if (ctx->Depth.Test==GL_FALSE) {
         apply_stencil_op_to_pixels(ctx, n, x, y,
                                    ctx->Stencil.ZPassFunc[face], face, mask);
      }
      else {
         GLubyte passmask[MAX_WIDTH], failmask[MAX_WIDTH], oldmask[MAX_WIDTH];
         GLuint i;

         MEMCPY(oldmask, mask, n * sizeof(GLubyte));

         _swrast_depth_test_span(ctx, span);

         for (i=0;i<n;i++) {
            ASSERT(mask[i] == 0 || mask[i] == 1);
            passmask[i] = oldmask[i] & mask[i];
            failmask[i] = oldmask[i] & (mask[i] ^ 1);
         }

         if (ctx->Stencil.ZFailFunc[face] != GL_KEEP) {
            apply_stencil_op_to_pixels(ctx, n, x, y,
                                       ctx->Stencil.ZFailFunc[face],
                                       face, failmask);
         }
         if (ctx->Stencil.ZPassFunc[face] != GL_KEEP) {
            apply_stencil_op_to_pixels(ctx, n, x, y,
                                       ctx->Stencil.ZPassFunc[face],
                                       face, passmask);
         }
      }

      return GL_TRUE;  /* one or more fragments passed both tests */
   }
}
Exemple #19
0
/*
 * Render a bitmap.
 */
void
_swrast_Bitmap( GLcontext *ctx, GLint px, GLint py,
		GLsizei width, GLsizei height,
		const struct gl_pixelstore_attrib *unpack,
		const GLubyte *bitmap )
{
   SWcontext *swrast = SWRAST_CONTEXT(ctx);
   GLint row, col;
   GLuint count = 0;
   struct sw_span span;

   ASSERT(ctx->RenderMode == GL_RENDER);
   ASSERT(bitmap);

   RENDER_START(swrast,ctx);

   if (SWRAST_CONTEXT(ctx)->NewState)
      _swrast_validate_derived( ctx );

   INIT_SPAN(span, GL_BITMAP, width, 0, SPAN_XY);

   if (ctx->Visual.rgbMode) {
      span.interpMask |= SPAN_RGBA;
      span.red   = FloatToFixed(ctx->Current.RasterColor[0] * CHAN_MAXF);
      span.green = FloatToFixed(ctx->Current.RasterColor[1] * CHAN_MAXF);
      span.blue  = FloatToFixed(ctx->Current.RasterColor[2] * CHAN_MAXF);
      span.alpha = FloatToFixed(ctx->Current.RasterColor[3] * CHAN_MAXF);
      span.redStep = span.greenStep = span.blueStep = span.alphaStep = 0;
   }
   else {
      span.interpMask |= SPAN_INDEX;
      span.index = ChanToFixed(ctx->Current.RasterIndex);
      span.indexStep = 0;
   }

   if (ctx->Depth.Test)
      _mesa_span_default_z(ctx, &span);
   if (ctx->Fog.Enabled)
      _mesa_span_default_fog(ctx, &span);
   if (ctx->Texture._EnabledUnits)
      _mesa_span_default_texcoords(ctx, &span);

   for (row = 0; row < height; row++, span.y++) {
      const GLubyte *src = (const GLubyte *) _mesa_image_address( unpack,
                 bitmap, width, height, GL_COLOR_INDEX, GL_BITMAP, 0, row, 0 );

      if (unpack->LsbFirst) {
         /* Lsb first */
         GLubyte mask = 1U << (unpack->SkipPixels & 0x7);
         for (col = 0; col < width; col++) {
            if (*src & mask) {
               span.array->x[count] = px + col;
               span.array->y[count] = py + row;
               count++;
            }
            if (mask == 128U) {
               src++;
               mask = 1U;
            }
            else {
               mask = mask << 1;
            }
         }

         /* get ready for next row */
         if (mask != 1)
            src++;
      }
      else {
         /* Msb first */
         GLubyte mask = 128U >> (unpack->SkipPixels & 0x7);
         for (col = 0; col < width; col++) {
            if (*src & mask) {
               span.array->x[count] = px + col;
               span.array->y[count] = py + row;
               count++;
            }
            if (mask == 1U) {
               src++;
               mask = 128U;
            }
            else {
               mask = mask >> 1;
            }
         }

         /* get ready for next row */
         if (mask != 128)
            src++;
      }

      if (count + width >= MAX_WIDTH || row + 1 == height) {
         /* flush the span */
         span.end = count;
         if (ctx->Visual.rgbMode)
            _mesa_write_rgba_span(ctx, &span);
         else
            _mesa_write_index_span(ctx, &span);
         span.end = 0;
         count = 0;
      }
   }

   RENDER_FINISH(swrast,ctx);
}
Exemple #20
0
/*
 * XXX this is another way to implement Bitmap.  Use horizontal runs of
 * fragments, initializing the mask array to indicate which fragments to
 * draw or skip.
 */
void
_swrast_Bitmap( struct gl_context *ctx, GLint px, GLint py,
		GLsizei width, GLsizei height,
		const struct gl_pixelstore_attrib *unpack,
		const GLubyte *bitmap )
{
   SWcontext *swrast = SWRAST_CONTEXT(ctx);
   GLint row, col;
   SWspan span;

   ASSERT(ctx->RenderMode == GL_RENDER);
   ASSERT(bitmap);

   swrast_render_start(ctx);

   if (SWRAST_CONTEXT(ctx)->NewState)
      _swrast_validate_derived( ctx );

   INIT_SPAN(span, GL_BITMAP);
   span.end = width;
   span.arrayMask = SPAN_MASK;
   _swrast_span_default_attribs(ctx, &span);

   /*span.arrayMask |= SPAN_MASK;*/  /* we'll init span.mask[] */
   span.x = px;
   span.y = py;
   /*span.end = width;*/

   for (row=0; row<height; row++, span.y++) {
      const GLubyte *src = (const GLubyte *) _mesa_image_address2d(unpack,
                 bitmap, width, height, GL_COLOR_INDEX, GL_BITMAP, row, 0);

      if (unpack->LsbFirst) {
         /* Lsb first */
         GLubyte mask = 1U << (unpack->SkipPixels & 0x7);
         for (col=0; col<width; col++) {
            span.array->mask[col] = (*src & mask) ? GL_TRUE : GL_FALSE;
            if (mask == 128U) {
               src++;
               mask = 1U;
            }
            else {
               mask = mask << 1;
            }
         }

         _swrast_write_rgba_span(ctx, &span);

         /* get ready for next row */
         if (mask != 1)
            src++;
      }
      else {
         /* Msb first */
         GLubyte mask = 128U >> (unpack->SkipPixels & 0x7);
         for (col=0; col<width; col++) {
            span.array->mask[col] = (*src & mask) ? GL_TRUE : GL_FALSE;
            if (mask == 1U) {
               src++;
               mask = 128U;
            }
            else {
               mask = mask >> 1;
            }
         }

         _swrast_write_rgba_span(ctx, &span);

         /* get ready for next row */
         if (mask != 128)
            src++;
      }
   }

   swrast_render_finish(ctx);
}
struct swrast_device_driver *
_swrast_GetDeviceDriverReference( GLcontext *ctx )
{
   SWcontext *swrast = SWRAST_CONTEXT(ctx);
   return &swrast->Driver;
}
Exemple #22
0
/**
 * Render a bitmap.
 * Called via ctx->Driver.Bitmap()
 * All parameter error checking will have been done before this is called.
 */
void
_swrast_Bitmap( struct gl_context *ctx, GLint px, GLint py,
		GLsizei width, GLsizei height,
		const struct gl_pixelstore_attrib *unpack,
		const GLubyte *bitmap )
{
   GLint row, col;
   GLuint count = 0;
   SWspan span;

   ASSERT(ctx->RenderMode == GL_RENDER);

   if (!_mesa_check_conditional_render(ctx))
      return; /* don't draw */

   bitmap = (const GLubyte *) _mesa_map_pbo_source(ctx, unpack, bitmap);
   if (!bitmap)
      return;

   swrast_render_start(ctx);

   if (SWRAST_CONTEXT(ctx)->NewState)
      _swrast_validate_derived( ctx );

   INIT_SPAN(span, GL_BITMAP);
   span.end = width;
   span.arrayMask = SPAN_XY;
   _swrast_span_default_attribs(ctx, &span);

   for (row = 0; row < height; row++) {
      const GLubyte *src = (const GLubyte *) _mesa_image_address2d(unpack,
                 bitmap, width, height, GL_COLOR_INDEX, GL_BITMAP, row, 0);

      if (unpack->LsbFirst) {
         /* Lsb first */
         GLubyte mask = 1U << (unpack->SkipPixels & 0x7);
         for (col = 0; col < width; col++) {
            if (*src & mask) {
               span.array->x[count] = px + col;
               span.array->y[count] = py + row;
               count++;
            }
            if (mask == 128U) {
               src++;
               mask = 1U;
            }
            else {
               mask = mask << 1;
            }
         }

         /* get ready for next row */
         if (mask != 1)
            src++;
      }
      else {
         /* Msb first */
         GLubyte mask = 128U >> (unpack->SkipPixels & 0x7);
         for (col = 0; col < width; col++) {
            if (*src & mask) {
               span.array->x[count] = px + col;
               span.array->y[count] = py + row;
               count++;
            }
            if (mask == 1U) {
               src++;
               mask = 128U;
            }
            else {
               mask = mask >> 1;
            }
         }

         /* get ready for next row */
         if (mask != 128)
            src++;
      }

      if (count + width >= SWRAST_MAX_WIDTH || row + 1 == height) {
         /* flush the span */
         span.end = count;
         _swrast_write_rgba_span(ctx, &span);
         span.end = 0;
         count = 0;
      }
   }

   swrast_render_finish(ctx);

   _mesa_unmap_pbo_source(ctx, unpack);
}
static void
accum_accum(GLcontext *ctx, GLfloat value,
            GLint xpos, GLint ypos, GLint width, GLint height )
{
   SWcontext *swrast = SWRAST_CONTEXT(ctx);
   struct gl_renderbuffer *rb
      = ctx->DrawBuffer->Attachment[BUFFER_ACCUM].Renderbuffer;
   const GLboolean directAccess = (rb->GetPointer(ctx, rb, 0, 0) != NULL);

   assert(rb);

   if (!ctx->ReadBuffer->_ColorReadBuffer) {
      /* no read buffer - OK */
      return;
   }

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

   if (rb->DataType == GL_SHORT || rb->DataType == GL_UNSIGNED_SHORT) {
      const GLfloat scale = value * ACCUM_SCALE16 / CHAN_MAXF;
      GLshort accumRow[4 * MAX_WIDTH];
      GLchan rgba[MAX_WIDTH][4];
      GLint i;

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

         /* read colors from color buffer */
         _swrast_read_rgba_span(ctx, ctx->ReadBuffer->_ColorReadBuffer, width,
                                xpos, ypos + i, CHAN_TYPE, rgba);

         /* do accumulation */
         if (swrast->_IntegerAccumMode) {
            /* simply add integer color values into accum buffer */
            GLint j;
            for (j = 0; j < width; j++) {
               acc[j * 4 + 0] += rgba[j][RCOMP];
               acc[j * 4 + 1] += rgba[j][GCOMP];
               acc[j * 4 + 2] += rgba[j][BCOMP];
               acc[j * 4 + 3] += rgba[j][ACOMP];
            }
         }
         else {
            /* scaled integer (or float) accum buffer */
            GLint j;
            for (j = 0; j < width; j++) {
               acc[j * 4 + 0] += (GLshort) ((GLfloat) rgba[j][RCOMP] * scale);
               acc[j * 4 + 1] += (GLshort) ((GLfloat) rgba[j][GCOMP] * scale);
               acc[j * 4 + 2] += (GLshort) ((GLfloat) rgba[j][BCOMP] * scale);
               acc[j * 4 + 3] += (GLshort) ((GLfloat) rgba[j][ACOMP] * scale);
            }
         }

         if (!directAccess) {
            rb->PutRow(ctx, rb, width, xpos, ypos + i, accumRow, NULL);
         }
      }
   }
   else {
      /* other types someday */
   }
}
Exemple #24
0
/**
 * Set default fragment attributes for the span using the
 * current raster values.  Used prior to glDraw/CopyPixels
 * and glBitmap.
 */
void
_swrast_span_default_attribs(struct gl_context *ctx, SWspan *span)
{
   GLchan r, g, b, a;
   /* Z*/
   {
      const GLfloat depthMax = ctx->DrawBuffer->_DepthMaxF;
      if (ctx->DrawBuffer->Visual.depthBits <= 16)
         span->z = FloatToFixed(ctx->Current.RasterPos[2] * depthMax + 0.5F);
      else {
         GLfloat tmpf = ctx->Current.RasterPos[2] * depthMax; 
         tmpf = MIN2(tmpf, depthMax);
         span->z = (GLint)tmpf;
      }
      span->zStep = 0;
      span->interpMask |= SPAN_Z;
   }

   /* W (for perspective correction) */
   span->attrStart[FRAG_ATTRIB_WPOS][3] = 1.0;
   span->attrStepX[FRAG_ATTRIB_WPOS][3] = 0.0;
   span->attrStepY[FRAG_ATTRIB_WPOS][3] = 0.0;

   /* primary color, or color index */
   UNCLAMPED_FLOAT_TO_CHAN(r, ctx->Current.RasterColor[0]);
   UNCLAMPED_FLOAT_TO_CHAN(g, ctx->Current.RasterColor[1]);
   UNCLAMPED_FLOAT_TO_CHAN(b, ctx->Current.RasterColor[2]);
   UNCLAMPED_FLOAT_TO_CHAN(a, ctx->Current.RasterColor[3]);
#if CHAN_TYPE == GL_FLOAT
   span->red = r;
   span->green = g;
   span->blue = b;
   span->alpha = a;
#else
   span->red   = IntToFixed(r);
   span->green = IntToFixed(g);
   span->blue  = IntToFixed(b);
   span->alpha = IntToFixed(a);
#endif
   span->redStep = 0;
   span->greenStep = 0;
   span->blueStep = 0;
   span->alphaStep = 0;
   span->interpMask |= SPAN_RGBA;

   COPY_4V(span->attrStart[FRAG_ATTRIB_COL], ctx->Current.RasterColor);
   ASSIGN_4V(span->attrStepX[FRAG_ATTRIB_COL], 0.0, 0.0, 0.0, 0.0);
   ASSIGN_4V(span->attrStepY[FRAG_ATTRIB_COL], 0.0, 0.0, 0.0, 0.0);

   /* fog */
   {
      const SWcontext *swrast = SWRAST_CONTEXT(ctx);
      GLfloat fogVal; /* a coord or a blend factor */
      if (swrast->_PreferPixelFog) {
         /* fog blend factors will be computed from fog coordinates per pixel */
         fogVal = ctx->Current.RasterDistance;
      }
      else {
         /* fog blend factor should be computed from fogcoord now */
         fogVal = _swrast_z_to_fogfactor(ctx, ctx->Current.RasterDistance);
      }
      span->attrStart[FRAG_ATTRIB_FOGC][0] = fogVal;
      span->attrStepX[FRAG_ATTRIB_FOGC][0] = 0.0;
      span->attrStepY[FRAG_ATTRIB_FOGC][0] = 0.0;
   }

   /* texcoords */
   {
      const GLuint attr = FRAG_ATTRIB_TEX;
      const GLfloat *tc = ctx->Current.RasterTexCoords;
      if (tc[3] > 0.0F) {
         /* use (s/q, t/q, r/q, 1) */
         span->attrStart[attr][0] = tc[0] / tc[3];
         span->attrStart[attr][1] = tc[1] / tc[3];
         span->attrStart[attr][2] = tc[2] / tc[3];
         span->attrStart[attr][3] = 1.0;
      }
      else {
         ASSIGN_4V(span->attrStart[attr], 0.0F, 0.0F, 0.0F, 1.0F);
      }
      ASSIGN_4V(span->attrStepX[attr], 0.0F, 0.0F, 0.0F, 0.0F);
      ASSIGN_4V(span->attrStepY[attr], 0.0F, 0.0F, 0.0F, 0.0F);
   }
}
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 */
   }
}
Exemple #26
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;
}
Exemple #27
0
/**
 * Do texture application for:
 *  GL_EXT_texture_env_combine
 *  GL_ARB_texture_env_combine
 *  GL_EXT_texture_env_dot3
 *  GL_ARB_texture_env_dot3
 *  GL_ATI_texture_env_combine3
 *  GL_NV_texture_env_combine4
 *  conventional GL texture env modes
 *
 * \param ctx          rendering context
 * \param unit         the texture combiner unit
 * \param primary_rgba incoming fragment color array
 * \param texelBuffer  pointer to texel colors for all texture units
 * 
 * \param span         two fields are used in this function:
 *                       span->end: number of fragments to process
 *                       span->array->rgba: incoming/result fragment colors
 */
static void
texture_combine( struct gl_context *ctx, GLuint unit,
                 const float4_array primary_rgba,
                 const GLfloat *texelBuffer,
                 SWspan *span )
{
   SWcontext *swrast = SWRAST_CONTEXT(ctx);
   const struct gl_texture_unit *textureUnit = &(ctx->Texture.Unit[unit]);
   const struct gl_tex_env_combine_state *combine = textureUnit->_CurrentCombine;
   float4_array argRGB[MAX_COMBINER_TERMS];
   float4_array argA[MAX_COMBINER_TERMS];
   const GLfloat scaleRGB = (GLfloat) (1 << combine->ScaleShiftRGB);
   const GLfloat scaleA = (GLfloat) (1 << combine->ScaleShiftA);
   const GLuint numArgsRGB = combine->_NumArgsRGB;
   const GLuint numArgsA = combine->_NumArgsA;
   float4_array ccolor[4], rgba;
   GLuint i, term;
   GLuint n = span->end;
   GLchan (*rgbaChan)[4] = span->array->rgba;

   /* alloc temp pixel buffers */
   rgba = malloc(4 * n * sizeof(GLfloat));
   if (!rgba) {
      _mesa_error(ctx, GL_OUT_OF_MEMORY, "texture_combine");
      return;
   }

   for (i = 0; i < numArgsRGB || i < numArgsA; i++) {
      ccolor[i] = malloc(4 * n * sizeof(GLfloat));
      if (!ccolor[i]) {
         while (i) {
            free(ccolor[i]);
            i--;
         }
         _mesa_error(ctx, GL_OUT_OF_MEMORY, "texture_combine");
         free(rgba);
         return;
      }
   }

   for (i = 0; i < n; i++) {
      rgba[i][RCOMP] = CHAN_TO_FLOAT(rgbaChan[i][RCOMP]);
      rgba[i][GCOMP] = CHAN_TO_FLOAT(rgbaChan[i][GCOMP]);
      rgba[i][BCOMP] = CHAN_TO_FLOAT(rgbaChan[i][BCOMP]);
      rgba[i][ACOMP] = CHAN_TO_FLOAT(rgbaChan[i][ACOMP]);
   }

   /*
   printf("modeRGB 0x%x  modeA 0x%x  srcRGB1 0x%x  srcA1 0x%x  srcRGB2 0x%x  srcA2 0x%x\n",
          combine->ModeRGB,
          combine->ModeA,
          combine->SourceRGB[0],
          combine->SourceA[0],
          combine->SourceRGB[1],
          combine->SourceA[1]);
   */

   /*
    * Do operand setup for up to 4 operands.  Loop over the terms.
    */
   for (term = 0; term < numArgsRGB; term++) {
      const GLenum srcRGB = combine->SourceRGB[term];
      const GLenum operandRGB = combine->OperandRGB[term];

      switch (srcRGB) {
         case GL_TEXTURE:
            argRGB[term] = get_texel_array(swrast, unit);
            break;
         case GL_PRIMARY_COLOR:
            argRGB[term] = primary_rgba;
            break;
         case GL_PREVIOUS:
            argRGB[term] = rgba;
            break;
         case GL_CONSTANT:
            {
               float4_array c = ccolor[term];
               GLfloat red   = textureUnit->EnvColor[0];
               GLfloat green = textureUnit->EnvColor[1];
               GLfloat blue  = textureUnit->EnvColor[2];
               GLfloat alpha = textureUnit->EnvColor[3];
               for (i = 0; i < n; i++) {
                  ASSIGN_4V(c[i], red, green, blue, alpha);
               }
               argRGB[term] = ccolor[term];
            }
            break;
	 /* GL_ATI_texture_env_combine3 allows GL_ZERO & GL_ONE as sources.
	  */
	 case GL_ZERO:
            {
               float4_array c = ccolor[term];
               for (i = 0; i < n; i++) {
                  ASSIGN_4V(c[i], 0.0F, 0.0F, 0.0F, 0.0F);
               }
               argRGB[term] = ccolor[term];
            }
            break;
	 case GL_ONE:
            {
               float4_array c = ccolor[term];
               for (i = 0; i < n; i++) {
                  ASSIGN_4V(c[i], 1.0F, 1.0F, 1.0F, 1.0F);
               }
               argRGB[term] = ccolor[term];
            }
            break;
         default:
            /* ARB_texture_env_crossbar source */
            {
               const GLuint srcUnit = srcRGB - GL_TEXTURE0;
               ASSERT(srcUnit < ctx->Const.MaxTextureUnits);
               if (!ctx->Texture.Unit[srcUnit]._ReallyEnabled)
                  goto end;
               argRGB[term] = get_texel_array(swrast, srcUnit);
            }
      }

      if (operandRGB != GL_SRC_COLOR) {
         float4_array src = argRGB[term];
         float4_array dst = ccolor[term];

         /* point to new arg[term] storage */
         argRGB[term] = ccolor[term];

         switch (operandRGB) {
         case GL_ONE_MINUS_SRC_COLOR:
            for (i = 0; i < n; i++) {
               dst[i][RCOMP] = 1.0F - src[i][RCOMP];
               dst[i][GCOMP] = 1.0F - src[i][GCOMP];
               dst[i][BCOMP] = 1.0F - src[i][BCOMP];
            }
            break;
         case GL_SRC_ALPHA:
            for (i = 0; i < n; i++) {
               dst[i][RCOMP] =
               dst[i][GCOMP] =
               dst[i][BCOMP] = src[i][ACOMP];
            }
            break;
         case GL_ONE_MINUS_SRC_ALPHA:
            for (i = 0; i < n; i++) {
               dst[i][RCOMP] =
               dst[i][GCOMP] =
               dst[i][BCOMP] = 1.0F - src[i][ACOMP];
            }
            break;
         default:
            _mesa_problem(ctx, "Bad operandRGB");
         }
      }
   }

   /*
    * Set up the argA[term] pointers
    */
   for (term = 0; term < numArgsA; term++) {
      const GLenum srcA = combine->SourceA[term];
      const GLenum operandA = combine->OperandA[term];

      switch (srcA) {
         case GL_TEXTURE:
            argA[term] = get_texel_array(swrast, unit);
            break;
         case GL_PRIMARY_COLOR:
            argA[term] = primary_rgba;
            break;
         case GL_PREVIOUS:
            argA[term] = rgba;
            break;
         case GL_CONSTANT:
            {
               float4_array c = ccolor[term];
               GLfloat alpha = textureUnit->EnvColor[3];
               for (i = 0; i < n; i++)
                  c[i][ACOMP] = alpha;
               argA[term] = ccolor[term];
            }
            break;
	 /* GL_ATI_texture_env_combine3 allows GL_ZERO & GL_ONE as sources.
	  */
	 case GL_ZERO:
            {
               float4_array c = ccolor[term];
               for (i = 0; i < n; i++)
                  c[i][ACOMP] = 0.0F;
               argA[term] = ccolor[term];
            }
            break;
	 case GL_ONE:
            {
               float4_array c = ccolor[term];
               for (i = 0; i < n; i++)
                  c[i][ACOMP] = 1.0F;
               argA[term] = ccolor[term];
            }
            break;
         default:
            /* ARB_texture_env_crossbar source */
            {
               const GLuint srcUnit = srcA - GL_TEXTURE0;
               ASSERT(srcUnit < ctx->Const.MaxTextureUnits);
               if (!ctx->Texture.Unit[srcUnit]._ReallyEnabled)
                  goto end;
               argA[term] = get_texel_array(swrast, srcUnit);
            }
      }

      if (operandA == GL_ONE_MINUS_SRC_ALPHA) {
         float4_array src = argA[term];
         float4_array dst = ccolor[term];
         argA[term] = ccolor[term];
         for (i = 0; i < n; i++) {
            dst[i][ACOMP] = 1.0F - src[i][ACOMP];
         }
      }
   }

   /* RGB channel combine */
   {
      float4_array arg0 = argRGB[0];
      float4_array arg1 = argRGB[1];
      float4_array arg2 = argRGB[2];
      float4_array arg3 = argRGB[3];

      switch (combine->ModeRGB) {
      case GL_REPLACE:
         for (i = 0; i < n; i++) {
            rgba[i][RCOMP] = arg0[i][RCOMP] * scaleRGB;
            rgba[i][GCOMP] = arg0[i][GCOMP] * scaleRGB;
            rgba[i][BCOMP] = arg0[i][BCOMP] * scaleRGB;
         }
         break;
      case GL_MODULATE:
         for (i = 0; i < n; i++) {
            rgba[i][RCOMP] = arg0[i][RCOMP] * arg1[i][RCOMP] * scaleRGB;
            rgba[i][GCOMP] = arg0[i][GCOMP] * arg1[i][GCOMP] * scaleRGB;
            rgba[i][BCOMP] = arg0[i][BCOMP] * arg1[i][BCOMP] * scaleRGB;
         }
         break;
      case GL_ADD:
         if (textureUnit->EnvMode == GL_COMBINE4_NV) {
            /* (a * b) + (c * d) */
            for (i = 0; i < n; i++) {
               rgba[i][RCOMP] = (arg0[i][RCOMP] * arg1[i][RCOMP] +
                                 arg2[i][RCOMP] * arg3[i][RCOMP]) * scaleRGB;
               rgba[i][GCOMP] = (arg0[i][GCOMP] * arg1[i][GCOMP] +
                                 arg2[i][GCOMP] * arg3[i][GCOMP]) * scaleRGB;
               rgba[i][BCOMP] = (arg0[i][BCOMP] * arg1[i][BCOMP] +
                                 arg2[i][BCOMP] * arg3[i][BCOMP]) * scaleRGB;
            }
         }
         else {
            /* 2-term addition */
            for (i = 0; i < n; i++) {
               rgba[i][RCOMP] = (arg0[i][RCOMP] + arg1[i][RCOMP]) * scaleRGB;
               rgba[i][GCOMP] = (arg0[i][GCOMP] + arg1[i][GCOMP]) * scaleRGB;
               rgba[i][BCOMP] = (arg0[i][BCOMP] + arg1[i][BCOMP]) * scaleRGB;
            }
         }
         break;
      case GL_ADD_SIGNED:
         if (textureUnit->EnvMode == GL_COMBINE4_NV) {
            /* (a * b) + (c * d) - 0.5 */
            for (i = 0; i < n; i++) {
               rgba[i][RCOMP] = (arg0[i][RCOMP] * arg1[i][RCOMP] +
                                 arg2[i][RCOMP] * arg3[i][RCOMP] - 0.5F) * scaleRGB;
               rgba[i][GCOMP] = (arg0[i][GCOMP] * arg1[i][GCOMP] +
                                 arg2[i][GCOMP] * arg3[i][GCOMP] - 0.5F) * scaleRGB;
               rgba[i][BCOMP] = (arg0[i][BCOMP] * arg1[i][BCOMP] +
                                 arg2[i][BCOMP] * arg3[i][BCOMP] - 0.5F) * scaleRGB;
            }
         }
         else {
            for (i = 0; i < n; i++) {
               rgba[i][RCOMP] = (arg0[i][RCOMP] + arg1[i][RCOMP] - 0.5F) * scaleRGB;
               rgba[i][GCOMP] = (arg0[i][GCOMP] + arg1[i][GCOMP] - 0.5F) * scaleRGB;
               rgba[i][BCOMP] = (arg0[i][BCOMP] + arg1[i][BCOMP] - 0.5F) * scaleRGB;
            }
         }
         break;
      case GL_INTERPOLATE:
         for (i = 0; i < n; i++) {
            rgba[i][RCOMP] = (arg0[i][RCOMP] * arg2[i][RCOMP] +
                          arg1[i][RCOMP] * (1.0F - arg2[i][RCOMP])) * scaleRGB;
            rgba[i][GCOMP] = (arg0[i][GCOMP] * arg2[i][GCOMP] +
                          arg1[i][GCOMP] * (1.0F - arg2[i][GCOMP])) * scaleRGB;
            rgba[i][BCOMP] = (arg0[i][BCOMP] * arg2[i][BCOMP] +
                          arg1[i][BCOMP] * (1.0F - arg2[i][BCOMP])) * scaleRGB;
         }
         break;
      case GL_SUBTRACT:
         for (i = 0; i < n; i++) {
            rgba[i][RCOMP] = (arg0[i][RCOMP] - arg1[i][RCOMP]) * scaleRGB;
            rgba[i][GCOMP] = (arg0[i][GCOMP] - arg1[i][GCOMP]) * scaleRGB;
            rgba[i][BCOMP] = (arg0[i][BCOMP] - arg1[i][BCOMP]) * scaleRGB;
         }
         break;
      case GL_DOT3_RGB_EXT:
      case GL_DOT3_RGBA_EXT:
         /* Do not scale the result by 1 2 or 4 */
         for (i = 0; i < n; i++) {
            GLfloat dot = ((arg0[i][RCOMP] - 0.5F) * (arg1[i][RCOMP] - 0.5F) +
                           (arg0[i][GCOMP] - 0.5F) * (arg1[i][GCOMP] - 0.5F) +
                           (arg0[i][BCOMP] - 0.5F) * (arg1[i][BCOMP] - 0.5F))
               * 4.0F;
            dot = CLAMP(dot, 0.0F, 1.0F);
            rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = dot;
         }
         break;
      case GL_DOT3_RGB:
      case GL_DOT3_RGBA:
         /* DO scale the result by 1 2 or 4 */
         for (i = 0; i < n; i++) {
            GLfloat dot = ((arg0[i][RCOMP] - 0.5F) * (arg1[i][RCOMP] - 0.5F) +
                           (arg0[i][GCOMP] - 0.5F) * (arg1[i][GCOMP] - 0.5F) +
                           (arg0[i][BCOMP] - 0.5F) * (arg1[i][BCOMP] - 0.5F))
               * 4.0F * scaleRGB;
            dot = CLAMP(dot, 0.0F, 1.0F);
            rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = dot;
         }
         break;
      case GL_MODULATE_ADD_ATI:
         for (i = 0; i < n; i++) {
            rgba[i][RCOMP] = ((arg0[i][RCOMP] * arg2[i][RCOMP]) +
                              arg1[i][RCOMP]) * scaleRGB;
            rgba[i][GCOMP] = ((arg0[i][GCOMP] * arg2[i][GCOMP]) +
                              arg1[i][GCOMP]) * scaleRGB;
            rgba[i][BCOMP] = ((arg0[i][BCOMP] * arg2[i][BCOMP]) +
                              arg1[i][BCOMP]) * scaleRGB;
	 }
         break;
      case GL_MODULATE_SIGNED_ADD_ATI:
         for (i = 0; i < n; i++) {
            rgba[i][RCOMP] = ((arg0[i][RCOMP] * arg2[i][RCOMP]) +
                              arg1[i][RCOMP] - 0.5F) * scaleRGB;
            rgba[i][GCOMP] = ((arg0[i][GCOMP] * arg2[i][GCOMP]) +
                              arg1[i][GCOMP] - 0.5F) * scaleRGB;
            rgba[i][BCOMP] = ((arg0[i][BCOMP] * arg2[i][BCOMP]) +
                              arg1[i][BCOMP] - 0.5F) * scaleRGB;
	 }
         break;
      case GL_MODULATE_SUBTRACT_ATI:
         for (i = 0; i < n; i++) {
            rgba[i][RCOMP] = ((arg0[i][RCOMP] * arg2[i][RCOMP]) -
                              arg1[i][RCOMP]) * scaleRGB;
            rgba[i][GCOMP] = ((arg0[i][GCOMP] * arg2[i][GCOMP]) -
                              arg1[i][GCOMP]) * scaleRGB;
            rgba[i][BCOMP] = ((arg0[i][BCOMP] * arg2[i][BCOMP]) -
                              arg1[i][BCOMP]) * scaleRGB;
	 }
         break;
      case GL_BUMP_ENVMAP_ATI:
         /* this produces a fixed rgba color, and the coord calc is done elsewhere */
         for (i = 0; i < n; i++) {
            /* rgba result is 0,0,0,1 */
            rgba[i][RCOMP] = 0.0;
            rgba[i][GCOMP] = 0.0;
            rgba[i][BCOMP] = 0.0;
            rgba[i][ACOMP] = 1.0;
	 }
         goto end; /* no alpha processing */
      default:
         _mesa_problem(ctx, "invalid combine mode");
      }
   }

   /* Alpha channel combine */
   {
      float4_array arg0 = argA[0];
      float4_array arg1 = argA[1];
      float4_array arg2 = argA[2];
      float4_array arg3 = argA[3];

      switch (combine->ModeA) {
      case GL_REPLACE:
         for (i = 0; i < n; i++) {
            rgba[i][ACOMP] = arg0[i][ACOMP] * scaleA;
         }
         break;
      case GL_MODULATE:
         for (i = 0; i < n; i++) {
            rgba[i][ACOMP] = arg0[i][ACOMP] * arg1[i][ACOMP] * scaleA;
         }
         break;
      case GL_ADD:
         if (textureUnit->EnvMode == GL_COMBINE4_NV) {
            /* (a * b) + (c * d) */
            for (i = 0; i < n; i++) {
               rgba[i][ACOMP] = (arg0[i][ACOMP] * arg1[i][ACOMP] +
                                 arg2[i][ACOMP] * arg3[i][ACOMP]) * scaleA;
            }
         }
         else {
            /* two-term add */
            for (i = 0; i < n; i++) {
               rgba[i][ACOMP] = (arg0[i][ACOMP] + arg1[i][ACOMP]) * scaleA;
            }
         }
         break;
      case GL_ADD_SIGNED:
         if (textureUnit->EnvMode == GL_COMBINE4_NV) {
            /* (a * b) + (c * d) - 0.5 */
            for (i = 0; i < n; i++) {
               rgba[i][ACOMP] = (arg0[i][ACOMP] * arg1[i][ACOMP] +
                                 arg2[i][ACOMP] * arg3[i][ACOMP] -
                                 0.5F) * scaleA;
            }
         }
         else {
            /* a + b - 0.5 */
            for (i = 0; i < n; i++) {
               rgba[i][ACOMP] = (arg0[i][ACOMP] + arg1[i][ACOMP] - 0.5F) * scaleA;
            }
         }
         break;
      case GL_INTERPOLATE:
         for (i = 0; i < n; i++) {
            rgba[i][ACOMP] = (arg0[i][ACOMP] * arg2[i][ACOMP] +
                              arg1[i][ACOMP] * (1.0F - arg2[i][ACOMP]))
               * scaleA;
         }
         break;
      case GL_SUBTRACT:
         for (i = 0; i < n; i++) {
            rgba[i][ACOMP] = (arg0[i][ACOMP] - arg1[i][ACOMP]) * scaleA;
         }
         break;
      case GL_MODULATE_ADD_ATI:
         for (i = 0; i < n; i++) {
            rgba[i][ACOMP] = ((arg0[i][ACOMP] * arg2[i][ACOMP])
                              + arg1[i][ACOMP]) * scaleA;
         }
         break;
      case GL_MODULATE_SIGNED_ADD_ATI:
         for (i = 0; i < n; i++) {
            rgba[i][ACOMP] = ((arg0[i][ACOMP] * arg2[i][ACOMP]) +
                              arg1[i][ACOMP] - 0.5F) * scaleA;
         }
         break;
      case GL_MODULATE_SUBTRACT_ATI:
         for (i = 0; i < n; i++) {
            rgba[i][ACOMP] = ((arg0[i][ACOMP] * arg2[i][ACOMP])
                              - arg1[i][ACOMP]) * scaleA;
         }
         break;
      default:
         _mesa_problem(ctx, "invalid combine mode");
      }
   }

   /* Fix the alpha component for GL_DOT3_RGBA_EXT/ARB combining.
    * This is kind of a kludge.  It would have been better if the spec
    * were written such that the GL_COMBINE_ALPHA value could be set to
    * GL_DOT3.
    */
   if (combine->ModeRGB == GL_DOT3_RGBA_EXT ||
       combine->ModeRGB == GL_DOT3_RGBA) {
      for (i = 0; i < n; i++) {
	 rgba[i][ACOMP] = rgba[i][RCOMP];
      }
   }

   for (i = 0; i < n; i++) {
      UNCLAMPED_FLOAT_TO_CHAN(rgbaChan[i][RCOMP], rgba[i][RCOMP]);
      UNCLAMPED_FLOAT_TO_CHAN(rgbaChan[i][GCOMP], rgba[i][GCOMP]);
      UNCLAMPED_FLOAT_TO_CHAN(rgbaChan[i][BCOMP], rgba[i][BCOMP]);
      UNCLAMPED_FLOAT_TO_CHAN(rgbaChan[i][ACOMP], rgba[i][ACOMP]);
   }
   /* The span->array->rgba values are of CHAN type so set
    * span->array->ChanType field accordingly.
    */
   span->array->ChanType = CHAN_TYPE;

end:
   for (i = 0; i < numArgsRGB || i < numArgsA; i++) {
      free(ccolor[i]);
   }
   free(rgba);
}
Exemple #28
0
/**
 * Return pointer to line drawing function, or NULL if we should use a
 * swrast fallback.
 */
static swrast_tri_func
get_triangle_func(struct gl_context *ctx)
{
#if CHAN_BITS == 8
   SWcontext *swrast = SWRAST_CONTEXT(ctx);
   XMesaContext xmesa = XMESA_CONTEXT(ctx);
   const struct xmesa_renderbuffer *xrb;

#ifdef DEBUG
   triFuncName = NULL;
#endif

   /* trivial fallback tests */
   if ((ctx->DrawBuffer->_ColorDrawBufferIndexes[0] != BUFFER_BIT_FRONT_LEFT) &&
       (ctx->DrawBuffer->_ColorDrawBufferIndexes[0] != BUFFER_BIT_BACK_LEFT))
      return (swrast_tri_func) NULL;
   if (ctx->RenderMode != GL_RENDER)
      return (swrast_tri_func) NULL;
   if (ctx->Polygon.SmoothFlag)
      return (swrast_tri_func) NULL;
   if (ctx->Texture._EnabledUnits)
      return (swrast_tri_func) NULL;
   if (swrast->_RasterMask & MULTI_DRAW_BIT)
      return (swrast_tri_func) NULL;
   if (ctx->Polygon.CullFlag && 
       ctx->Polygon.CullFaceMode == GL_FRONT_AND_BACK)
      return (swrast_tri_func) NULL;

   xrb = xmesa_renderbuffer(ctx->DrawBuffer->_ColorDrawBuffers[0]);

   if (xrb->ximage) {
      if (   ctx->Light.ShadeModel==GL_SMOOTH
          && swrast->_RasterMask==DEPTH_BIT
          && ctx->Depth.Func==GL_LESS
          && ctx->Depth.Mask==GL_TRUE
          && ctx->Visual.depthBits == DEFAULT_SOFTWARE_DEPTH_BITS
          && ctx->Polygon.StippleFlag==GL_FALSE) {
         switch (xmesa->pixelformat) {
            case PF_Truecolor:
	       USE(smooth_TRUECOLOR_z_triangle);
            case PF_8A8B8G8R:
               USE(smooth_8A8B8G8R_z_triangle);
            case PF_8A8R8G8B:
               USE(smooth_8A8R8G8B_z_triangle);
            case PF_8R8G8B:
               USE(smooth_8R8G8B_z_triangle);
            case PF_8R8G8B24:
               USE(smooth_8R8G8B24_z_triangle);
            case PF_Dither_True:
               USE(smooth_TRUEDITHER_z_triangle);
            case PF_5R6G5B:
               USE(smooth_5R6G5B_z_triangle);
            case PF_Dither_5R6G5B:
               USE(smooth_DITHER_5R6G5B_z_triangle);
            default:
               return (swrast_tri_func) NULL;
         }
      }
      if (   ctx->Light.ShadeModel==GL_FLAT
          && swrast->_RasterMask==DEPTH_BIT
          && ctx->Depth.Func==GL_LESS
          && ctx->Depth.Mask==GL_TRUE
          && ctx->Visual.depthBits == DEFAULT_SOFTWARE_DEPTH_BITS
          && ctx->Polygon.StippleFlag==GL_FALSE) {
         switch (xmesa->pixelformat) {
            case PF_Truecolor:
	       USE(flat_TRUECOLOR_z_triangle);
            case PF_8A8B8G8R:
               USE(flat_8A8B8G8R_z_triangle);
            case PF_8A8R8G8B:
               USE(flat_8A8R8G8B_z_triangle);
            case PF_8R8G8B:
               USE(flat_8R8G8B_z_triangle);
            case PF_8R8G8B24:
               USE(flat_8R8G8B24_z_triangle);
            case PF_Dither_True:
               USE(flat_TRUEDITHER_z_triangle);
            case PF_5R6G5B:
               USE(flat_5R6G5B_z_triangle);
            case PF_Dither_5R6G5B:
               USE(flat_DITHER_5R6G5B_z_triangle);
            default:
               return (swrast_tri_func) NULL;
         }
      }
      if (   swrast->_RasterMask==0   /* no depth test */
          && ctx->Light.ShadeModel==GL_SMOOTH
          && ctx->Polygon.StippleFlag==GL_FALSE) {
         switch (xmesa->pixelformat) {
            case PF_Truecolor:
	       USE(smooth_TRUECOLOR_triangle);
            case PF_8A8B8G8R:
               USE(smooth_8A8B8G8R_triangle);
            case PF_8A8R8G8B:
               USE(smooth_8A8R8G8B_triangle);
            case PF_8R8G8B:
               USE(smooth_8R8G8B_triangle);
            case PF_8R8G8B24:
               USE(smooth_8R8G8B24_triangle);
            case PF_Dither_True:
               USE(smooth_TRUEDITHER_triangle);
            case PF_5R6G5B:
               USE(smooth_5R6G5B_triangle);
            case PF_Dither_5R6G5B:
               USE(smooth_DITHER_5R6G5B_triangle);
            default:
               return (swrast_tri_func) NULL;
         }
      }

      if (   swrast->_RasterMask==0   /* no depth test */
          && ctx->Light.ShadeModel==GL_FLAT
          && ctx->Polygon.StippleFlag==GL_FALSE) {
         switch (xmesa->pixelformat) {
            case PF_Truecolor:
	       USE(flat_TRUECOLOR_triangle);
            case PF_Dither_True:
	       USE(flat_TRUEDITHER_triangle);
            case PF_8A8B8G8R:
               USE(flat_8A8B8G8R_triangle);
            case PF_8A8R8G8B:
               USE(flat_8A8R8G8B_triangle);
            case PF_8R8G8B:
               USE(flat_8R8G8B_triangle);
            case PF_8R8G8B24:
               USE(flat_8R8G8B24_triangle);
            case PF_5R6G5B:
               USE(flat_5R6G5B_triangle);
            case PF_Dither_5R6G5B:
               USE(flat_DITHER_5R6G5B_triangle);
            default:
               return (swrast_tri_func) NULL;
         }
      }
   }
#endif /* CHAN_BITS == 8 */

   return (swrast_tri_func) NULL;
}
Exemple #29
0
/**
 * New in Mesa 3.5
 *
 * Create context and specify size of ancillary buffers.
 */
GLAPI OSMesaContext GLAPIENTRY
OSMesaCreateContextExt( GLenum format, GLint depthBits, GLint stencilBits,
                        GLint accumBits, OSMesaContext sharelist )
{
   OSMesaContext osmesa;
   struct dd_function_table functions;
   GLint rind, gind, bind, aind;
   GLint redBits = 0, greenBits = 0, blueBits = 0, alphaBits =0;

   rind = gind = bind = aind = 0;
   if (format==OSMESA_RGBA) {
      redBits = CHAN_BITS;
      greenBits = CHAN_BITS;
      blueBits = CHAN_BITS;
      alphaBits = CHAN_BITS;
      rind = 0;
      gind = 1;
      bind = 2;
      aind = 3;
   }
   else if (format==OSMESA_BGRA) {
      redBits = CHAN_BITS;
      greenBits = CHAN_BITS;
      blueBits = CHAN_BITS;
      alphaBits = CHAN_BITS;
      bind = 0;
      gind = 1;
      rind = 2;
      aind = 3;
   }
   else if (format==OSMESA_ARGB) {
      redBits = CHAN_BITS;
      greenBits = CHAN_BITS;
      blueBits = CHAN_BITS;
      alphaBits = CHAN_BITS;
      aind = 0;
      rind = 1;
      gind = 2;
      bind = 3;
   }
   else if (format==OSMESA_RGB) {
      redBits = CHAN_BITS;
      greenBits = CHAN_BITS;
      blueBits = CHAN_BITS;
      alphaBits = 0;
      rind = 0;
      gind = 1;
      bind = 2;
   }
   else if (format==OSMESA_BGR) {
      redBits = CHAN_BITS;
      greenBits = CHAN_BITS;
      blueBits = CHAN_BITS;
      alphaBits = 0;
      rind = 2;
      gind = 1;
      bind = 0;
   }
#if CHAN_TYPE == GL_UNSIGNED_BYTE
   else if (format==OSMESA_RGB_565) {
      redBits = 5;
      greenBits = 6;
      blueBits = 5;
      alphaBits = 0;
      rind = 0; /* not used */
      gind = 0;
      bind = 0;
   }
#endif
   else {
      return NULL;
   }

   osmesa = (OSMesaContext) CALLOC_STRUCT(osmesa_context);
   if (osmesa) {
      osmesa->gl_visual = _mesa_create_visual( GL_FALSE,    /* double buffer */
                                               GL_FALSE,    /* stereo */
                                               redBits,
                                               greenBits,
                                               blueBits,
                                               alphaBits,
                                               depthBits,
                                               stencilBits,
                                               accumBits,
                                               accumBits,
                                               accumBits,
                                               alphaBits ? accumBits : 0,
                                               1            /* num samples */
                                               );
      if (!osmesa->gl_visual) {
         free(osmesa);
         return NULL;
      }

      /* Initialize device driver function table */
      _mesa_init_driver_functions(&functions);
      /* override with our functions */
      functions.GetString = get_string;
      functions.UpdateState = osmesa_update_state;
      functions.GetBufferSize = NULL;

      if (!_mesa_initialize_context(&osmesa->mesa,
                                    API_OPENGL_COMPAT,
                                    osmesa->gl_visual,
                                    sharelist ? &sharelist->mesa
                                              : (struct gl_context *) NULL,
                                    &functions)) {
         _mesa_destroy_visual( osmesa->gl_visual );
         free(osmesa);
         return NULL;
      }

      _mesa_enable_sw_extensions(&(osmesa->mesa));
      _mesa_enable_1_3_extensions(&(osmesa->mesa));
      _mesa_enable_1_4_extensions(&(osmesa->mesa));
      _mesa_enable_1_5_extensions(&(osmesa->mesa));
      _mesa_enable_2_0_extensions(&(osmesa->mesa));
      _mesa_enable_2_1_extensions(&(osmesa->mesa));

      osmesa->gl_buffer = _mesa_create_framebuffer(osmesa->gl_visual);
      if (!osmesa->gl_buffer) {
         _mesa_destroy_visual( osmesa->gl_visual );
         _mesa_free_context_data( &osmesa->mesa );
         free(osmesa);
         return NULL;
      }

      /* Create depth/stencil/accum buffers.  We'll create the color
       * buffer later in OSMesaMakeCurrent().
       */
      _swrast_add_soft_renderbuffers(osmesa->gl_buffer,
                                     GL_FALSE, /* color */
                                     osmesa->gl_visual->haveDepthBuffer,
                                     osmesa->gl_visual->haveStencilBuffer,
                                     osmesa->gl_visual->haveAccumBuffer,
                                     GL_FALSE, /* alpha */
                                     GL_FALSE /* aux */ );

      osmesa->format = format;
      osmesa->userRowLength = 0;
      osmesa->yup = GL_TRUE;
      osmesa->rInd = rind;
      osmesa->gInd = gind;
      osmesa->bInd = bind;
      osmesa->aInd = aind;

      _mesa_meta_init(&osmesa->mesa);

      /* Initialize the software rasterizer and helper modules. */
      {
	 struct gl_context *ctx = &osmesa->mesa;
         SWcontext *swrast;
         TNLcontext *tnl;

	 if (!_swrast_CreateContext( ctx ) ||
             !_vbo_CreateContext( ctx ) ||
             !_tnl_CreateContext( ctx ) ||
             !_swsetup_CreateContext( ctx )) {
            _mesa_destroy_visual(osmesa->gl_visual);
            _mesa_free_context_data(ctx);
            free(osmesa);
            return NULL;
         }
	
	 _swsetup_Wakeup( ctx );

         /* use default TCL pipeline */
         tnl = TNL_CONTEXT(ctx);
         tnl->Driver.RunPipeline = _tnl_run_pipeline;

         ctx->Driver.MapRenderbuffer = osmesa_MapRenderbuffer;
         ctx->Driver.UnmapRenderbuffer = osmesa_UnmapRenderbuffer;

         /* Extend the software rasterizer with our optimized line and triangle
          * drawing functions.
          */
         swrast = SWRAST_CONTEXT( ctx );
         swrast->choose_line = osmesa_choose_line;
         swrast->choose_triangle = osmesa_choose_triangle;
      }
   }
   return osmesa;
}
Exemple #30
0
/**
 * Try to do a fast and simple RGB(a) glDrawPixels.
 * Return:  GL_TRUE if success, GL_FALSE if slow path must be used instead
 */
static GLboolean
fast_draw_rgba_pixels(struct gl_context *ctx, GLint x, GLint y,
                      GLsizei width, GLsizei height,
                      GLenum format, GLenum type,
                      const struct gl_pixelstore_attrib *userUnpack,
                      const GLvoid *pixels)
{
   struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[0];
   SWcontext *swrast = SWRAST_CONTEXT(ctx);
   struct gl_pixelstore_attrib unpack;

   if (!rb)
      return GL_TRUE; /* no-op */

   if (ctx->DrawBuffer->_NumColorDrawBuffers > 1 ||
       (swrast->_RasterMask & ~CLIP_BIT) ||
       ctx->Texture._EnabledCoordUnits ||
       userUnpack->SwapBytes ||
       ctx->Pixel.ZoomX != 1.0f ||
       fabsf(ctx->Pixel.ZoomY) != 1.0f ||
       ctx->_ImageTransferState) {
      /* can't handle any of those conditions */
      return GL_FALSE;
   }

   unpack = *userUnpack;

   /* clipping */
   if (!_mesa_clip_drawpixels(ctx, &x, &y, &width, &height, &unpack)) {
      /* image was completely clipped: no-op, all done */
      return GL_TRUE;
   }

   if (format == GL_RGB &&
       type == GL_UNSIGNED_BYTE &&
       (rb->Format == MESA_FORMAT_XRGB8888 ||
        rb->Format == MESA_FORMAT_ARGB8888)) {
      fast_draw_rgb_ubyte_pixels(ctx, rb, x, y, width, height,
                                 &unpack, pixels);
      return GL_TRUE;
   }

   if (format == GL_RGBA &&
       type == GL_UNSIGNED_BYTE &&
       (rb->Format == MESA_FORMAT_XRGB8888 ||
        rb->Format == MESA_FORMAT_ARGB8888)) {
      fast_draw_rgba_ubyte_pixels(ctx, rb, x, y, width, height,
                                  &unpack, pixels);
      return GL_TRUE;
   }

   if (_mesa_format_matches_format_and_type(rb->Format, format, type,
                                            ctx->Unpack.SwapBytes)) {
      fast_draw_generic_pixels(ctx, rb, x, y, width, height,
                               format, type, &unpack, pixels);
      return GL_TRUE;
   }

   /* can't handle this pixel format and/or data type */
   return GL_FALSE;
}