Beispiel #1
0
/*
 * When the pixel buffer is full, or needs to be flushed, call this
 * function.  All the pixels in the pixel buffer will be subjected
 * to texturing, scissoring, stippling, alpha testing, stenciling,
 * depth testing, blending, and finally written to the frame buffer.
 */
void gl_flush_pb( GLcontext *ctx )
{
   struct pixel_buffer* PB = ctx->PB;

   DEFARRAY(GLubyte,mask,PB_SIZE+4);   /* add 4 for manually unrolled loop, below */
   DEFARRAY(GLubyte, rsave, PB_SIZE);
   DEFARRAY(GLubyte, gsave, PB_SIZE);
   DEFARRAY(GLubyte, bsave, PB_SIZE);
   DEFARRAY(GLubyte, asave, PB_SIZE);

   if (PB->count==0)  goto CleanUp;

   /* initialize mask array and clip pixels simultaneously */
   {
      GLint xmin = ctx->Buffer->Xmin;
      GLint xmax = ctx->Buffer->Xmax;
      GLint ymin = ctx->Buffer->Ymin;
      GLint ymax = ctx->Buffer->Ymax;
      GLint *x = PB->x;
      GLint *y = PB->y;
      GLuint i = 0;
      /* manually unrolled loop, OK to go past PB->count */
      do {
         mask[i] = (x[i]>=xmin) & (x[i]<=xmax) & (y[i]>=ymin) & (y[i]<=ymax);
         i++;
         mask[i] = (x[i]>=xmin) & (x[i]<=xmax) & (y[i]>=ymin) & (y[i]<=ymax);
         i++;
         mask[i] = (x[i]>=xmin) & (x[i]<=xmax) & (y[i]>=ymin) & (y[i]<=ymax);
         i++;
         mask[i] = (x[i]>=xmin) & (x[i]<=xmax) & (y[i]>=ymin) & (y[i]<=ymax);
         i++;
      } while (i<PB->count);
   }

   if (ctx->Visual->RGBAflag) {
      /* RGBA COLOR PIXELS */
      if (PB->mono && ctx->MutablePixels) {
	 /* Copy flat color to all pixels */
         MEMSET( PB->r, PB->color[0], PB->count );
         MEMSET( PB->g, PB->color[1], PB->count );
         MEMSET( PB->b, PB->color[2], PB->count );
         MEMSET( PB->a, PB->color[3], PB->count );
      }

      /* If each pixel can be of a different color... */
      if (ctx->MutablePixels || !PB->mono) {

	 if (ctx->Texture.Enabled & TEXTURE_3D) {
            /* TODO: need texture lambda valus */
	    gl_texture_pixels_3d( ctx, PB->count, PB->s, PB->t, PB->u, NULL,
                                  PB->r, PB->g, PB->b, PB->a);
	 }
	 else if (ctx->Texture.Enabled & TEXTURE_2D) {
            /* TODO: need texture lambda valus */
	    gl_texture_pixels_2d( ctx, PB->count, PB->s, PB->t, NULL,
                                  PB->r, PB->g, PB->b, PB->a);
	 }
	 else if (ctx->Texture.Enabled & TEXTURE_1D) {
           /* TODO: need texture lambda values */
	    gl_texture_pixels_1d( ctx, PB->count, PB->s, NULL,
                                  PB->r, PB->g, PB->b, PB->a );
	 }

	 if (ctx->Fog.Enabled
             && (ctx->Hint.Fog==GL_NICEST || PB->primitive==GL_BITMAP)) {
	    gl_fog_color_pixels( ctx, PB->count, PB->z,
				 PB->r, PB->g, PB->b, PB->a );
	 }

         /* Scissoring already done above */

	 if (ctx->Color.AlphaEnabled) {
	    if (gl_alpha_test( ctx, PB->count, PB->a, mask )==0) {
	       goto CleanUp;
	    }
	 }

	 if (ctx->Stencil.Enabled) {
	    /* first stencil test */
	    if (gl_stencil_pixels( ctx, PB->count, PB->x, PB->y, mask )==0) {
	       goto CleanUp;
	    }
	    /* depth buffering w/ stencil */
	    gl_depth_stencil_pixels( ctx, PB->count, PB->x, PB->y, PB->z, mask );
	 }
	 else if (ctx->Depth.Test) {
	    /* regular depth testing */
	    (*ctx->Driver.DepthTestPixels)( ctx, PB->count, PB->x, PB->y, PB->z, mask );
	 }

         if (ctx->RasterMask & NO_DRAW_BIT) {
            goto CleanUp;
         }

         if (ctx->RasterMask & FRONT_AND_BACK_BIT) {
            /* make a copy of the colors */
            MEMCPY( rsave, PB->r, PB->count * sizeof(GLubyte) );
            MEMCPY( gsave, PB->r, PB->count * sizeof(GLubyte) );
            MEMCPY( bsave, PB->r, PB->count * sizeof(GLubyte) );
            MEMCPY( asave, PB->r, PB->count * sizeof(GLubyte) );
         }

         if (ctx->Color.SWLogicOpEnabled) {
            gl_logicop_rgba_pixels( ctx, PB->count, PB->x, PB->y,
                                    PB->r, PB->g, PB->b, PB->a, mask);
         }
         else if (ctx->Color.BlendEnabled) {
            gl_blend_pixels( ctx, PB->count, PB->x, PB->y,
                             PB->r, PB->g, PB->b, PB->a, mask);
         }

         if (ctx->Color.SWmasking) {
            gl_mask_color_pixels( ctx, PB->count, PB->x, PB->y,
                                  PB->r, PB->g, PB->b, PB->a, mask );
         }

         /* write pixels */
         (*ctx->Driver.WriteColorPixels)( ctx, PB->count, PB->x, PB->y,
                                          PB->r, PB->g, PB->b, PB->a, mask );
         if (ctx->RasterMask & ALPHABUF_BIT) {
            gl_write_alpha_pixels( ctx, PB->count, PB->x, PB->y, PB->a, mask );
         }

         if (ctx->RasterMask & FRONT_AND_BACK_BIT) {
            /*** Also draw to back buffer ***/
            (*ctx->Driver.SetBuffer)( ctx, GL_BACK );
            if (ctx->Color.SWLogicOpEnabled) {
               gl_logicop_rgba_pixels( ctx, PB->count, PB->x, PB->y,
                                       PB->r, PB->g, PB->b, PB->a, mask);
            }
            else if (ctx->Color.BlendEnabled) {
               gl_blend_pixels( ctx, PB->count, PB->x, PB->y,
                                rsave, gsave, bsave, asave, mask );
            }
            if (ctx->Color.SWmasking) {
               gl_mask_color_pixels( ctx, PB->count, PB->x, PB->y,
                                     rsave, gsave, bsave, asave, mask);
            }
            (*ctx->Driver.WriteColorPixels)( ctx, PB->count, PB->x, PB->y,
                                             rsave, gsave, bsave, asave, mask);
            if (ctx->RasterMask & ALPHABUF_BIT) {
               ctx->Buffer->Alpha = ctx->Buffer->BackAlpha;
               gl_write_alpha_pixels( ctx, PB->count, PB->x, PB->y,
                                      asave, mask );
               ctx->Buffer->Alpha = ctx->Buffer->FrontAlpha;
            }
            (*ctx->Driver.SetBuffer)( ctx, GL_FRONT );
            /*** ALL DONE ***/
         }
      }
      else {
	 /* Same color for all pixels */

         /* Scissoring already done above */

	 if (ctx->Color.AlphaEnabled) {
	    if (gl_alpha_test( ctx, PB->count, PB->a, mask )==0) {
	       goto CleanUp;
	    }
	 }

	 if (ctx->Stencil.Enabled) {
	    /* first stencil test */
	    if (gl_stencil_pixels( ctx, PB->count, PB->x, PB->y, mask )==0) {
	       goto CleanUp;
	    }
	    /* depth buffering w/ stencil */
	    gl_depth_stencil_pixels( ctx, PB->count, PB->x, PB->y, PB->z, mask );
	 }
	 else if (ctx->Depth.Test) {
	    /* regular depth testing */
	    (*ctx->Driver.DepthTestPixels)( ctx, PB->count, PB->x, PB->y, PB->z, mask );
	 }

         if (ctx->RasterMask & NO_DRAW_BIT) {
            goto CleanUp;
         }

         /* write pixels */
         {
            GLubyte red, green, blue, alpha;
            red   = PB->color[0];
            green = PB->color[1];
            blue  = PB->color[2];
            alpha = PB->color[3];
	    (*ctx->Driver.Color)( ctx, red, green, blue, alpha );
         }
         (*ctx->Driver.WriteMonocolorPixels)( ctx, PB->count, PB->x, PB->y, mask );
         if (ctx->RasterMask & ALPHABUF_BIT) {
            gl_write_mono_alpha_pixels( ctx, PB->count, PB->x, PB->y,
                                        PB->color[3], mask );
         }

         if (ctx->RasterMask & FRONT_AND_BACK_BIT) {
            /*** Also render to back buffer ***/
            (*ctx->Driver.SetBuffer)( ctx, GL_BACK );
            (*ctx->Driver.WriteMonocolorPixels)( ctx, PB->count, PB->x, PB->y, mask );
            if (ctx->RasterMask & ALPHABUF_BIT) {
               ctx->Buffer->Alpha = ctx->Buffer->BackAlpha;
               gl_write_mono_alpha_pixels( ctx, PB->count, PB->x, PB->y,
                                           PB->color[3], mask );
               ctx->Buffer->Alpha = ctx->Buffer->FrontAlpha;
            }
            (*ctx->Driver.SetBuffer)( ctx, GL_FRONT );
	 }
         /*** ALL DONE ***/
      }
   }
   else {
      /* COLOR INDEX PIXELS */

      /* If we may be writting pixels with different indexes... */
      if (PB->mono && ctx->MutablePixels) {
	 /* copy index to all pixels */
         GLuint n = PB->count, indx = PB->index;
         GLuint *pbindex = PB->i;
         do {
	    *pbindex++ = indx;
            n--;
	 } while (n);
      }

      if (ctx->MutablePixels || !PB->mono) {
	 /* Pixel color index may be modified */
         GLuint isave[PB_SIZE];

	 if (ctx->Fog.Enabled
             && (ctx->Hint.Fog==GL_NICEST || PB->primitive==GL_BITMAP)) {
	    gl_fog_index_pixels( ctx, PB->count, PB->z, PB->i );
	 }

         /* Scissoring already done above */

	 if (ctx->Stencil.Enabled) {
	    /* first stencil test */
	    if (gl_stencil_pixels( ctx, PB->count, PB->x, PB->y, mask )==0) {
	       goto CleanUp;
	    }
	    /* depth buffering w/ stencil */
	    gl_depth_stencil_pixels( ctx, PB->count, PB->x, PB->y, PB->z, mask );
	 }
	 else if (ctx->Depth.Test) {
	    /* regular depth testing */
	    (*ctx->Driver.DepthTestPixels)( ctx, PB->count, PB->x, PB->y, PB->z, mask );
	 }

         if (ctx->RasterMask & NO_DRAW_BIT) {
            goto CleanUp;
         }

         if (ctx->RasterMask & FRONT_AND_BACK_BIT) {
            /* make a copy of the indexes */
            MEMCPY( isave, PB->i, PB->count * sizeof(GLuint) );
         }

         if (ctx->Color.SWLogicOpEnabled) {
            gl_logicop_ci_pixels( ctx, PB->count, PB->x, PB->y, PB->i, mask );
         }

         if (ctx->Color.SWmasking) {
            gl_mask_index_pixels( ctx, PB->count, PB->x, PB->y, PB->i, mask );
         }

         /* write pixels */
         (*ctx->Driver.WriteIndexPixels)( ctx, PB->count, PB->x, PB->y,
                                          PB->i, mask );

         if (ctx->RasterMask & FRONT_AND_BACK_BIT) {
            /*** Also write to back buffer ***/
            (*ctx->Driver.SetBuffer)( ctx, GL_BACK );
            MEMCPY( PB->i, isave, PB->count * sizeof(GLuint) );
            if (ctx->Color.SWLogicOpEnabled) {
               gl_logicop_ci_pixels( ctx, PB->count, PB->x, PB->y, PB->i, mask );
            }
            if (ctx->Color.SWmasking) {
               gl_mask_index_pixels( ctx, PB->count, PB->x, PB->y,
                                     PB->i, mask );
            }
            (*ctx->Driver.WriteIndexPixels)( ctx, PB->count, PB->x, PB->y,
                                             PB->i, mask );
            (*ctx->Driver.SetBuffer)( ctx, GL_FRONT );
         }

         /*** ALL DONE ***/
      }
      else {
	 /* Same color index for all pixels */

         /* Scissoring already done above */

	 if (ctx->Stencil.Enabled) {
	    /* first stencil test */
	    if (gl_stencil_pixels( ctx, PB->count, PB->x, PB->y, mask )==0) {
	       goto CleanUp;
	    }
	    /* depth buffering w/ stencil */
	    gl_depth_stencil_pixels( ctx, PB->count, PB->x, PB->y, PB->z, mask );
	 }
	 else if (ctx->Depth.Test) {
	    /* regular depth testing */
	    (*ctx->Driver.DepthTestPixels)( ctx, PB->count, PB->x, PB->y, PB->z, mask );
	 }
         
         if (ctx->RasterMask & NO_DRAW_BIT) {
            goto CleanUp;
         }

         /* write pixels */
         (*ctx->Driver.Index)( ctx, PB->index );
         (*ctx->Driver.WriteMonoindexPixels)( ctx, PB->count, PB->x, PB->y, mask );

         if (ctx->RasterMask & FRONT_AND_BACK_BIT) {
            /*** Also write to back buffer ***/
            (*ctx->Driver.SetBuffer)( ctx, GL_BACK );
            (*ctx->Driver.WriteMonoindexPixels)( ctx, PB->count, PB->x, PB->y, mask );
            (*ctx->Driver.SetBuffer)( ctx, GL_FRONT );
         }
         /*** ALL DONE ***/
      }
   }

CleanUp:
   PB->count = 0;
   UNDEFARRAY(mask);
   UNDEFARRAY(rsave);
   UNDEFARRAY(gsave);
   UNDEFARRAY(bsave);
   UNDEFARRAY(asave);
}
Beispiel #2
0
/*
 * Textured RGBA line:  any width, smooth or flat, stippled, any raster ops
 * with texturing.
 */
static void textured_rgba_line( GLcontext *ctx,
                                GLuint v1, GLuint v2, GLuint pv )
{
   struct vertex_buffer *VB = ctx->VB;
   struct pixel_buffer *PB = ctx->PB;
   GLint x1, y1, x2, y2;
   GLint x[MAXPOINTS], y[MAXPOINTS];
   GLdepth z[MAXPOINTS];
   GLubyte mask[MAXPOINTS];
   /* Allocate arrays dynamically on Mac */
   DEFARRAY(GLubyte,red,MAXPOINTS);
   DEFARRAY(GLubyte,green,MAXPOINTS);
   DEFARRAY(GLubyte,blue,MAXPOINTS);
   DEFARRAY(GLubyte,alpha,MAXPOINTS);
   DEFARRAY(GLfloat,s,MAXPOINTS);
   DEFARRAY(GLfloat,t,MAXPOINTS);
   DEFARRAY(GLfloat,u,MAXPOINTS);
#if 0
   DEFARRAY(GLfloat,v,MAXPOINTS);
#endif
   GLint i, n;
   GLint dx, dy;

   x1 = (GLint) VB->Win[v1][0];
   y1 = (GLint) VB->Win[v1][1];
   x2 = (GLint) VB->Win[v2][0];
   y2 = (GLint) VB->Win[v2][1];

   /* compute the line */
   if (ctx->Line.StippleFlag) {
      n = gl_stippled_bresenham( ctx, x1, y1, x2, y2, x, y, mask );
   }
   else {
      n = gl_bresenham( ctx, x1, y1, x2, y2, x, y );
      for (i=0;i<n;i++) {
	 mask[i] = 1;
      }
   }

   if (ctx->Depth.Test) {
      GLint z1 = (GLint) (VB->Win[v1][2] + ctx->LineZoffset);
      GLint z2 = (GLint) (VB->Win[v2][2] + ctx->LineZoffset);
      GL_INTERPOLATE_Z( n, z1, z2, z );
   }

   if (ctx->Light.ShadeModel==GL_FLAT) {
      GLint r, g, b, a;
      r = VB->Color[pv][0];  /* colors are ints, not in fixed point */
      g = VB->Color[pv][1];
      b = VB->Color[pv][2];
      a = VB->Color[pv][3];
      for (i=0;i<n;i++) {
	 red[i]   = r;
	 green[i] = g;
	 blue[i]  = b;
	 alpha[i] = a;
      }
   }
   else {
      /* interpolate color, VB->Colors are in fixed point */
      gl_interpolate_rgba( n,
                           VB->Color[v1][0], VB->Color[v2][0], red,
                           VB->Color[v1][1], VB->Color[v2][1], green,
                           VB->Color[v1][2], VB->Color[v2][2], blue,
                           VB->Color[v1][3], VB->Color[v2][3], alpha );
   }

   /* interpolate texture coordinates */
   {
      GLfloat w1 = 1.0F / VB->Clip[v1][3];
      GLfloat w2 = 1.0F / VB->Clip[v2][3];
      GLfloat s1 = VB->TexCoord[v1][0] * w1;
      GLfloat s2 = VB->TexCoord[v2][0] * w2;
      GLfloat t1 = VB->TexCoord[v1][1] * w1;
      GLfloat t2 = VB->TexCoord[v2][1] * w2;
      GLfloat u1 = VB->TexCoord[v1][2] * w1;
      GLfloat u2 = VB->TexCoord[v2][2] * w2;
      /* don't interpolate r since we don't do 3-D textures, yet */
      GLfloat q1 = VB->TexCoord[v1][3] * w1;
      GLfloat q2 = VB->TexCoord[v2][3] * w2;
      GLfloat inv_n = 1.0F / (GLfloat) n;
      GLfloat ds = (s2-s1) * inv_n;
      GLfloat dt = (t2-t1) * inv_n;
      GLfloat du = (u2-u1) * inv_n;
      GLfloat dq = (q2-q1) * inv_n;
      for (i=0;i<n;i++) {
         s[i] = s1 / q1;
         t[i] = t1 / q1;
         u[i] = u1 / q1;
         s1 += ds;
         t1 += dt;
         u1 += du;
         q1 += dq;
      }
   }

   /* compute delta x and delta y */
   if (x1>x2) {
      dx = x1 - x2;
   }
   else {
      dx = x2 - x1;
   }
   if (y1>y2) {
      dy = y1 - y2;
   }
   else {
      dy = y2 - y1;
   }

   /* render */
   if (ctx->Line.Width==2.0F) {
      /* special case, easy to optimize */
      if (dx>dy) {
	 /* X-major: duplicate pixels in Y direction */
	 for (i=0;i<n;i++) {
	    if (mask[i]) {
	       PB_WRITE_TEX_PIXEL( PB, x[i], y[i]-1, z[i],
			  red[i], green[i], blue[i], alpha[i], s[i], t[i], u[i] );
	       PB_WRITE_TEX_PIXEL( PB, x[i], y[i], z[i],
			  red[i], green[i], blue[i], alpha[i], s[i], t[i], u[i] );
	    }
	 }
      }
      else {
	 /* Y-major: duplicate pixels in X direction */
	 for (i=0;i<n;i++) {
	    if (mask[i]) {
	       PB_WRITE_TEX_PIXEL( PB, x[i]-1, y[i], z[i],
			  red[i], green[i], blue[i], alpha[i], s[i], t[i], u[i] );
	       PB_WRITE_TEX_PIXEL( PB, x[i], y[i], z[i],
			  red[i], green[i], blue[i], alpha[i], s[i], t[i], u[i] );
	    }
	 }
      }
      PB_CHECK_FLUSH( ctx, PB );
   }
   else {
      GLint width, w0, w1;
      width = (GLint) CLAMP( ctx->Line.Width, MIN_LINE_WIDTH, MAX_LINE_WIDTH );
      w0 = -width / 2;
      w1 = w0 + width - 1;

      if (dx>dy) {
	 /* X-major: duplicate pixels in Y direction */
	 for (i=0;i<n;i++) {
	    if (mask[i]) {
	       GLint yy;
	       GLint y0 = y[i] + w0;
	       GLint y1 = y[i] + w1;
	       for (yy=y0;yy<=y1;yy++) {
		  PB_WRITE_TEX_PIXEL( PB, x[i], yy, z[i],
			     red[i], green[i], blue[i], alpha[i], s[i], t[i], u[i] );
	       }
	       PB_CHECK_FLUSH( ctx, PB );
	    }
	 }
      }
      else {
	 /* Y-major: duplicate pixels in X direction */
	 for (i=0;i<n;i++) {
	    if (mask[i]) {
	       GLint xx;
	       GLint x0 = x[i] + w0;
	       GLint x1 = x[i] + w1;
	       for (xx=x0;xx<=x1;xx++) {
		  PB_WRITE_TEX_PIXEL( PB, xx, y[i], z[i],
			     red[i], green[i], blue[i], alpha[i], s[i], t[i], u[i] );
	       }
	       PB_CHECK_FLUSH( ctx, PB );
	    }
	 }
      }
   }

   /* Deallocate dynamic arrays on Mac */
   UNDEFARRAY(red);
   UNDEFARRAY(green);
   UNDEFARRAY(blue);
   UNDEFARRAY(alpha);
   UNDEFARRAY(s);
   UNDEFARRAY(t);
   UNDEFARRAY(u);
#if 0
   UNDEFARRAY(v); 
#endif
}