home *** CD-ROM | disk | FTP | other *** search
/ Magazyn Amiga 5 / MA_Cover_5.iso / ppc / mesa / src / pb.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-01-31  |  22.2 KB  |  771 lines

  1. /* $Id: pb.c,v 1.14 1997/11/13 02:16:48 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  2.4
  6.  * Copyright (C) 1995-1997  Brian Paul
  7.  *
  8.  * This library is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU Library General Public
  10.  * License as published by the Free Software Foundation; either
  11.  * version 2 of the License, or (at your option) any later version.
  12.  *
  13.  * This library is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.  * Library General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU Library General Public
  19.  * License along with this library; if not, write to the Free
  20.  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  */
  22.  
  23.  
  24. /*
  25.  * $Log: pb.c,v $
  26.  * Revision 1.14  1997/11/13 02:16:48  brianp
  27.  * added lambda array, initialized to zeros
  28.  *
  29.  * Revision 1.13  1997/07/24 01:24:11  brianp
  30.  * changed precompiled header symbol from PCH to PC_HEADER
  31.  *
  32.  * Revision 1.12  1997/05/28 03:26:02  brianp
  33.  * added precompiled header (PCH) support
  34.  *
  35.  * Revision 1.11  1997/05/09 22:40:19  brianp
  36.  * added gl_alloc_pb()
  37.  *
  38.  * Revision 1.10  1997/05/03 00:51:30  brianp
  39.  * new texturing function call: gl_texture_pixels()
  40.  *
  41.  * Revision 1.9  1997/05/01 02:10:33  brianp
  42.  * removed manually unrolled loop to stop Purify uninitialized memory read
  43.  *
  44.  * Revision 1.8  1997/04/16 23:54:11  brianp
  45.  * do per-pixel fog if texturing is enabled
  46.  *
  47.  * Revision 1.7  1997/02/09 19:53:43  brianp
  48.  * now use TEXTURE_xD enable constants
  49.  *
  50.  * Revision 1.6  1997/02/09 18:43:14  brianp
  51.  * added GL_EXT_texture3D support
  52.  *
  53.  * Revision 1.5  1997/02/03 20:30:54  brianp
  54.  * added a few DEFARRAY macros for BeOS
  55.  *
  56.  * Revision 1.4  1997/01/28 22:17:44  brianp
  57.  * new RGBA mode logic op support
  58.  *
  59.  * Revision 1.3  1996/09/25 03:21:10  brianp
  60.  * added NO_DRAW_BIT support
  61.  *
  62.  * Revision 1.2  1996/09/15 14:18:37  brianp
  63.  * now use GLframebuffer and GLvisual
  64.  *
  65.  * Revision 1.1  1996/09/13 01:38:16  brianp
  66.  * Initial revision
  67.  *
  68.  */
  69.  
  70.  
  71. /*
  72.  * Pixel buffer:
  73.  *
  74.  * As fragments are produced (by point, line, and bitmap drawing) they
  75.  * are accumlated in a buffer.  When the buffer is full or has to be
  76.  * flushed (glEnd), we apply all enabled rasterization functions to the
  77.  * pixels and write the results to the display buffer.  The goal is to
  78.  * maximize the number of pixels processed inside loops and to minimize
  79.  * the number of function calls.
  80.  */
  81.  
  82.  
  83.  
  84. #ifdef PC_HEADER
  85. #include "all.h"
  86. #else
  87. #include <stdlib.h>
  88. #include <string.h>
  89. #include "alpha.h"
  90. #include "alphabuf.h"
  91. #include "blend.h"
  92. #include "depth.h"
  93. #include "fog.h"
  94. #include "logic.h"
  95. #include "macros.h"
  96. #include "masking.h"
  97. #include "pb.h"
  98. #include "scissor.h"
  99. #include "stencil.h"
  100. #include "texture.h"
  101. #include "types.h"
  102. #endif
  103.  
  104.  
  105.  
  106. /*
  107.  * Allocate and initialize a new pixel buffer structure.
  108.  */
  109. struct pixel_buffer *gl_alloc_pb(void)
  110. {
  111.    struct pixel_buffer *pb;
  112.    pb = (struct pixel_buffer *) calloc(sizeof(struct pixel_buffer), 1);
  113.    if (pb) {
  114.       int i;
  115.       /* set non-zero fields */
  116.       pb->primitive = GL_BITMAP;
  117.       /* Set all lambda values to 0.0 since we don't do mipmapping for
  118.        * points or lines and want to use the level 0 texture image.
  119.        */
  120.       for (i=0; i<PB_SIZE; i++) {
  121.      pb->lambda[i] = 0.0;
  122.       }
  123.    }
  124.    return pb;
  125. }
  126.  
  127.  
  128. /* temporary bugfix for StormCPPC */
  129.  
  130. #if defined(__STORM__) && defined(__PPC__)
  131.    DEFARRAY(GLubyte,g_mask,PB_SIZE);
  132.    DEFARRAY(GLubyte, g_rsave, PB_SIZE);
  133.    DEFARRAY(GLubyte, g_gsave, PB_SIZE);
  134.    DEFARRAY(GLubyte, g_bsave, PB_SIZE);
  135.    DEFARRAY(GLubyte, g_asave, PB_SIZE);
  136. #endif
  137.  
  138. #if defined(__STORM__) && defined(__PPC__)
  139.  
  140.  
  141. /*
  142.  * When the pixel buffer is full, or needs to be flushed, call this
  143.  * function.  All the pixels in the pixel buffer will be subjected
  144.  * to texturing, scissoring, stippling, alpha testing, stenciling,
  145.  * depth testing, blending, and finally written to the frame buffer.
  146.  */
  147. void gl_flush_pb( GLcontext *ctx )
  148. {
  149.    struct pixel_buffer* PB = ctx->PB;
  150.  
  151.    if (PB->count==0)  goto CleanUp;
  152.  
  153.    /* initialize mask array and clip pixels simultaneously */
  154.    {
  155.       GLint xmin = ctx->Buffer->Xmin;
  156.       GLint xmax = ctx->Buffer->Xmax;
  157.       GLint ymin = ctx->Buffer->Ymin;
  158.       GLint ymax = ctx->Buffer->Ymax;
  159.       GLint *x = PB->x;
  160.       GLint *y = PB->y;
  161.       GLuint i, n = PB->count;
  162.       for (i=0;i<n;i++) {
  163.      g_mask[i] = (x[i]>=xmin) & (x[i]<=xmax) & (y[i]>=ymin) & (y[i]<=ymax);
  164.       }
  165.    }
  166.  
  167.    if (ctx->Visual->RGBAflag) {
  168.       /* RGBA COLOR PIXELS */
  169.       if (PB->mono && ctx->MutablePixels) {
  170.      /* Copy flat color to all pixels */
  171.      MEMSET( PB->r, PB->color[0], PB->count );
  172.      MEMSET( PB->g, PB->color[1], PB->count );
  173.      MEMSET( PB->b, PB->color[2], PB->count );
  174.      MEMSET( PB->a, PB->color[3], PB->count );
  175.       }
  176.  
  177.       /* If each pixel can be of a different color... */
  178.       if (ctx->MutablePixels || !PB->mono) {
  179.  
  180.      if (ctx->Texture.Enabled) {
  181.         /* TODO: need texture lambda valus */
  182.         gl_texture_pixels( ctx, PB->count, PB->s, PB->t, PB->u,
  183.                    PB->lambda, PB->r, PB->g, PB->b, PB->a);
  184.      }
  185.  
  186.      if (ctx->Fog.Enabled
  187.          && (ctx->Hint.Fog==GL_NICEST || PB->primitive==GL_BITMAP
  188.          || ctx->Texture.Enabled)) {
  189.         gl_fog_color_pixels( ctx, PB->count, PB->z,
  190.                  PB->r, PB->g, PB->b, PB->a );
  191.      }
  192.  
  193.      /* Scissoring already done above */
  194.  
  195.      if (ctx->Color.AlphaEnabled) {
  196.         if (gl_alpha_test( ctx, PB->count, PB->a, g_mask )==0) {
  197.            goto CleanUp;
  198.         }
  199.      }
  200.  
  201.      if (ctx->Stencil.Enabled) {
  202.         /* first stencil test */
  203.         if (gl_stencil_pixels( ctx, PB->count, PB->x, PB->y, g_mask )==0) {
  204.            goto CleanUp;
  205.         }
  206.         /* depth buffering w/ stencil */
  207.         gl_depth_stencil_pixels( ctx, PB->count, PB->x, PB->y, PB->z, g_mask );
  208.      }
  209.      else if (ctx->Depth.Test) {
  210.         /* regular depth testing */
  211.         (*ctx->Driver.DepthTestPixels)( ctx, PB->count, PB->x, PB->y, PB->z, g_mask );
  212.      }
  213.  
  214.      if (ctx->RasterMask & NO_DRAW_BIT) {
  215.         goto CleanUp;
  216.      }
  217.  
  218.      if (ctx->RasterMask & FRONT_AND_BACK_BIT) {
  219.         /* make a copy of the colors */
  220.         MEMCPY( g_rsave, PB->r, PB->count * sizeof(GLubyte) );
  221.         MEMCPY( g_gsave, PB->r, PB->count * sizeof(GLubyte) );
  222.         MEMCPY( g_bsave, PB->r, PB->count * sizeof(GLubyte) );
  223.         MEMCPY( g_asave, PB->r, PB->count * sizeof(GLubyte) );
  224.      }
  225.  
  226.      if (ctx->Color.SWLogicOpEnabled) {
  227.         gl_logicop_rgba_pixels( ctx, PB->count, PB->x, PB->y,
  228.                     PB->r, PB->g, PB->b, PB->a, g_mask);
  229.      }
  230.      else if (ctx->Color.BlendEnabled) {
  231.         gl_blend_pixels( ctx, PB->count, PB->x, PB->y,
  232.                  PB->r, PB->g, PB->b, PB->a, g_mask);
  233.      }
  234.  
  235.      if (ctx->Color.SWmasking) {
  236.         gl_mask_color_pixels( ctx, PB->count, PB->x, PB->y,
  237.                   PB->r, PB->g, PB->b, PB->a, g_mask );
  238.      }
  239.  
  240.      /* write pixels */
  241.      (*ctx->Driver.WriteColorPixels)( ctx, PB->count, PB->x, PB->y,
  242.                       PB->r, PB->g, PB->b, PB->a, g_mask );
  243.      if (ctx->RasterMask & ALPHABUF_BIT) {
  244.         gl_write_alpha_pixels( ctx, PB->count, PB->x, PB->y, PB->a, g_mask );
  245.      }
  246.  
  247.      if (ctx->RasterMask & FRONT_AND_BACK_BIT) {
  248.         /*** Also draw to back buffer ***/
  249.         (*ctx->Driver.SetBuffer)( ctx, GL_BACK );
  250.         if (ctx->Color.SWLogicOpEnabled) {
  251.            gl_logicop_rgba_pixels( ctx, PB->count, PB->x, PB->y,
  252.                        PB->r, PB->g, PB->b, PB->a, g_mask);
  253.         }
  254.         else if (ctx->Color.BlendEnabled) {
  255.            gl_blend_pixels( ctx, PB->count, PB->x, PB->y,
  256.                 g_rsave, g_gsave, g_bsave, g_asave, g_mask );
  257.         }
  258.         if (ctx->Color.SWmasking) {
  259.            gl_mask_color_pixels( ctx, PB->count, PB->x, PB->y,
  260.                      g_rsave, g_gsave, g_bsave, g_asave, g_mask);
  261.         }
  262.         (*ctx->Driver.WriteColorPixels)( ctx, PB->count, PB->x, PB->y,
  263.                          g_rsave, g_gsave, g_bsave, g_asave, g_mask);
  264.         if (ctx->RasterMask & ALPHABUF_BIT) {
  265.            ctx->Buffer->Alpha = ctx->Buffer->BackAlpha;
  266.            gl_write_alpha_pixels( ctx, PB->count, PB->x, PB->y,
  267.                       g_asave, g_mask );
  268.            ctx->Buffer->Alpha = ctx->Buffer->FrontAlpha;
  269.         }
  270.         (*ctx->Driver.SetBuffer)( ctx, GL_FRONT );
  271.         /*** ALL DONE ***/
  272.      }
  273.       }
  274.       else {
  275.      /* Same color for all pixels */
  276.  
  277.      /* Scissoring already done above */
  278.  
  279.      if (ctx->Color.AlphaEnabled) {
  280.         if (gl_alpha_test( ctx, PB->count, PB->a, g_mask )==0) {
  281.            goto CleanUp;
  282.         }
  283.      }
  284.  
  285.      if (ctx->Stencil.Enabled) {
  286.         /* first stencil test */
  287.         if (gl_stencil_pixels( ctx, PB->count, PB->x, PB->y, g_mask )==0) {
  288.            goto CleanUp;
  289.         }
  290.         /* depth buffering w/ stencil */
  291.         gl_depth_stencil_pixels( ctx, PB->count, PB->x, PB->y, PB->z, g_mask );
  292.      }
  293.      else if (ctx->Depth.Test) {
  294.         /* regular depth testing */
  295.         (*ctx->Driver.DepthTestPixels)( ctx, PB->count, PB->x, PB->y, PB->z, g_mask );
  296.      }
  297.  
  298.      if (ctx->RasterMask & NO_DRAW_BIT) {
  299.         goto CleanUp;
  300.      }
  301.  
  302.      /* write pixels */
  303.      {
  304.         GLubyte red, green, blue, alpha;
  305.         red   = PB->color[0];
  306.         green = PB->color[1];
  307.         blue  = PB->color[2];
  308.         alpha = PB->color[3];
  309.         (*ctx->Driver.Color)( ctx, red, green, blue, alpha );
  310.      }
  311.      (*ctx->Driver.WriteMonocolorPixels)( ctx, PB->count, PB->x, PB->y, g_mask );
  312.      if (ctx->RasterMask & ALPHABUF_BIT) {
  313.         gl_write_mono_alpha_pixels( ctx, PB->count, PB->x, PB->y,
  314.                     PB->color[3], g_mask );
  315.      }
  316.  
  317.      if (ctx->RasterMask & FRONT_AND_BACK_BIT) {
  318.         /*** Also render to back buffer ***/
  319.         (*ctx->Driver.SetBuffer)( ctx, GL_BACK );
  320.         (*ctx->Driver.WriteMonocolorPixels)( ctx, PB->count, PB->x, PB->y, g_mask );
  321.         if (ctx->RasterMask & ALPHABUF_BIT) {
  322.            ctx->Buffer->Alpha = ctx->Buffer->BackAlpha;
  323.            gl_write_mono_alpha_pixels( ctx, PB->count, PB->x, PB->y,
  324.                        PB->color[3], g_mask );
  325.            ctx->Buffer->Alpha = ctx->Buffer->FrontAlpha;
  326.         }
  327.         (*ctx->Driver.SetBuffer)( ctx, GL_FRONT );
  328.      }
  329.      /*** ALL DONE ***/
  330.       }
  331.    }
  332.    else {
  333.       /* COLOR INDEX PIXELS */
  334.  
  335.       /* If we may be writting pixels with different indexes... */
  336.       if (PB->mono && ctx->MutablePixels) {
  337.      /* copy index to all pixels */
  338.      GLuint n = PB->count, indx = PB->index;
  339.      GLuint *pbindex = PB->i;
  340.      do {
  341.         *pbindex++ = indx;
  342.         n--;
  343.      } while (n);
  344.       }
  345.  
  346.       if (ctx->MutablePixels || !PB->mono) {
  347.      /* Pixel color index may be modified */
  348.      GLuint isave[PB_SIZE];
  349.  
  350.      if (ctx->Fog.Enabled
  351.          && (ctx->Hint.Fog==GL_NICEST || PB->primitive==GL_BITMAP)) {
  352.         gl_fog_index_pixels( ctx, PB->count, PB->z, PB->i );
  353.      }
  354.  
  355.      /* Scissoring already done above */
  356.  
  357.      if (ctx->Stencil.Enabled) {
  358.         /* first stencil test */
  359.         if (gl_stencil_pixels( ctx, PB->count, PB->x, PB->y, g_mask )==0) {
  360.            goto CleanUp;
  361.         }
  362.         /* depth buffering w/ stencil */
  363.         gl_depth_stencil_pixels( ctx, PB->count, PB->x, PB->y, PB->z, g_mask );
  364.      }
  365.      else if (ctx->Depth.Test) {
  366.         /* regular depth testing */
  367.         (*ctx->Driver.DepthTestPixels)( ctx, PB->count, PB->x, PB->y, PB->z, g_mask );
  368.      }
  369.  
  370.      if (ctx->RasterMask & NO_DRAW_BIT) {
  371.         goto CleanUp;
  372.      }
  373.  
  374.      if (ctx->RasterMask & FRONT_AND_BACK_BIT) {
  375.         /* make a copy of the indexes */
  376.         MEMCPY( isave, PB->i, PB->count * sizeof(GLuint) );
  377.      }
  378.  
  379.      if (ctx->Color.SWLogicOpEnabled) {
  380.         gl_logicop_ci_pixels( ctx, PB->count, PB->x, PB->y, PB->i, g_mask );
  381.      }
  382.  
  383.      if (ctx->Color.SWmasking) {
  384.         gl_mask_index_pixels( ctx, PB->count, PB->x, PB->y, PB->i, g_mask );
  385.      }
  386.  
  387.      /* write pixels */
  388.      (*ctx->Driver.WriteIndexPixels)( ctx, PB->count, PB->x, PB->y,
  389.                       PB->i, g_mask );
  390.  
  391.      if (ctx->RasterMask & FRONT_AND_BACK_BIT) {
  392.         /*** Also write to back buffer ***/
  393.         (*ctx->Driver.SetBuffer)( ctx, GL_BACK );
  394.         MEMCPY( PB->i, isave, PB->count * sizeof(GLuint) );
  395.         if (ctx->Color.SWLogicOpEnabled) {
  396.            gl_logicop_ci_pixels( ctx, PB->count, PB->x, PB->y, PB->i, g_mask );
  397.         }
  398.         if (ctx->Color.SWmasking) {
  399.            gl_mask_index_pixels( ctx, PB->count, PB->x, PB->y,
  400.                      PB->i, g_mask );
  401.         }
  402.         (*ctx->Driver.WriteIndexPixels)( ctx, PB->count, PB->x, PB->y,
  403.                          PB->i, g_mask );
  404.         (*ctx->Driver.SetBuffer)( ctx, GL_FRONT );
  405.      }
  406.  
  407.      /*** ALL DONE ***/
  408.       }
  409.       else {
  410.      /* Same color index for all pixels */
  411.  
  412.      /* Scissoring already done above */
  413.  
  414.      if (ctx->Stencil.Enabled) {
  415.         /* first stencil test */
  416.         if (gl_stencil_pixels( ctx, PB->count, PB->x, PB->y, g_mask )==0) {
  417.            goto CleanUp;
  418.         }
  419.         /* depth buffering w/ stencil */
  420.         gl_depth_stencil_pixels( ctx, PB->count, PB->x, PB->y, PB->z, g_mask );
  421.      }
  422.      else if (ctx->Depth.Test) {
  423.         /* regular depth testing */
  424.         (*ctx->Driver.DepthTestPixels)( ctx, PB->count, PB->x, PB->y, PB->z, g_mask );
  425.      }
  426.      
  427.      if (ctx->RasterMask & NO_DRAW_BIT) {
  428.         goto CleanUp;
  429.      }
  430.  
  431.      /* write pixels */
  432.      (*ctx->Driver.Index)( ctx, PB->index );
  433.      (*ctx->Driver.WriteMonoindexPixels)( ctx, PB->count, PB->x, PB->y, g_mask );
  434.  
  435.      if (ctx->RasterMask & FRONT_AND_BACK_BIT) {
  436.         /*** Also write to back buffer ***/
  437.         (*ctx->Driver.SetBuffer)( ctx, GL_BACK );
  438.         (*ctx->Driver.WriteMonoindexPixels)( ctx, PB->count, PB->x, PB->y, g_mask );
  439.         (*ctx->Driver.SetBuffer)( ctx, GL_FRONT );
  440.      }
  441.      /*** ALL DONE ***/
  442.       }
  443.    }
  444.  
  445. CleanUp:
  446.    PB->count = 0;
  447. }
  448.  
  449. #else
  450.  
  451. /*
  452.  * When the pixel buffer is full, or needs to be flushed, call this
  453.  * function.  All the pixels in the pixel buffer will be subjected
  454.  * to texturing, scissoring, stippling, alpha testing, stenciling,
  455.  * depth testing, blending, and finally written to the frame buffer.
  456.  */
  457. void gl_flush_pb( GLcontext *ctx )
  458. {
  459.    struct pixel_buffer* PB = ctx->PB;
  460.  
  461.    DEFARRAY(GLubyte,mask,PB_SIZE);
  462.    DEFARRAY(GLubyte, rsave, PB_SIZE);
  463.    DEFARRAY(GLubyte, gsave, PB_SIZE);
  464.    DEFARRAY(GLubyte, bsave, PB_SIZE);
  465.    DEFARRAY(GLubyte, asave, PB_SIZE);
  466.  
  467.    if (PB->count==0)  goto CleanUp;
  468.  
  469.    /* initialize mask array and clip pixels simultaneously */
  470.    {
  471.       GLint xmin = ctx->Buffer->Xmin;
  472.       GLint xmax = ctx->Buffer->Xmax;
  473.       GLint ymin = ctx->Buffer->Ymin;
  474.       GLint ymax = ctx->Buffer->Ymax;
  475.       GLint *x = PB->x;
  476.       GLint *y = PB->y;
  477.       GLuint i, n = PB->count;
  478.       for (i=0;i<n;i++) {
  479.      mask[i] = (x[i]>=xmin) & (x[i]<=xmax) & (y[i]>=ymin) & (y[i]<=ymax);
  480.       }
  481.    }
  482.  
  483.    if (ctx->Visual->RGBAflag) {
  484.       /* RGBA COLOR PIXELS */
  485.       if (PB->mono && ctx->MutablePixels) {
  486.      /* Copy flat color to all pixels */
  487.      MEMSET( PB->r, PB->color[0], PB->count );
  488.      MEMSET( PB->g, PB->color[1], PB->count );
  489.      MEMSET( PB->b, PB->color[2], PB->count );
  490.      MEMSET( PB->a, PB->color[3], PB->count );
  491.       }
  492.  
  493.       /* If each pixel can be of a different color... */
  494.       if (ctx->MutablePixels || !PB->mono) {
  495.  
  496.      if (ctx->Texture.Enabled) {
  497.         /* TODO: need texture lambda valus */
  498.         gl_texture_pixels( ctx, PB->count, PB->s, PB->t, PB->u,
  499.                    PB->lambda, PB->r, PB->g, PB->b, PB->a);
  500.      }
  501.  
  502.      if (ctx->Fog.Enabled
  503.          && (ctx->Hint.Fog==GL_NICEST || PB->primitive==GL_BITMAP
  504.          || ctx->Texture.Enabled)) {
  505.         gl_fog_color_pixels( ctx, PB->count, PB->z,
  506.                  PB->r, PB->g, PB->b, PB->a );
  507.      }
  508.  
  509.      /* Scissoring already done above */
  510.  
  511.      if (ctx->Color.AlphaEnabled) {
  512.         if (gl_alpha_test( ctx, PB->count, PB->a, mask )==0) {
  513.            goto CleanUp;
  514.         }
  515.      }
  516.  
  517.      if (ctx->Stencil.Enabled) {
  518.         /* first stencil test */
  519.         if (gl_stencil_pixels( ctx, PB->count, PB->x, PB->y, mask )==0) {
  520.            goto CleanUp;
  521.         }
  522.         /* depth buffering w/ stencil */
  523.         gl_depth_stencil_pixels( ctx, PB->count, PB->x, PB->y, PB->z, mask );
  524.      }
  525.      else if (ctx->Depth.Test) {
  526.         /* regular depth testing */
  527.         (*ctx->Driver.DepthTestPixels)( ctx, PB->count, PB->x, PB->y, PB->z, mask );
  528.      }
  529.  
  530.      if (ctx->RasterMask & NO_DRAW_BIT) {
  531.         goto CleanUp;
  532.      }
  533.  
  534.      if (ctx->RasterMask & FRONT_AND_BACK_BIT) {
  535.         /* make a copy of the colors */
  536.         MEMCPY( rsave, PB->r, PB->count * sizeof(GLubyte) );
  537.         MEMCPY( gsave, PB->r, PB->count * sizeof(GLubyte) );
  538.         MEMCPY( bsave, PB->r, PB->count * sizeof(GLubyte) );
  539.         MEMCPY( asave, PB->r, PB->count * sizeof(GLubyte) );
  540.      }
  541.  
  542.      if (ctx->Color.SWLogicOpEnabled) {
  543.         gl_logicop_rgba_pixels( ctx, PB->count, PB->x, PB->y,
  544.                     PB->r, PB->g, PB->b, PB->a, mask);
  545.      }
  546.      else if (ctx->Color.BlendEnabled) {
  547.         gl_blend_pixels( ctx, PB->count, PB->x, PB->y,
  548.                  PB->r, PB->g, PB->b, PB->a, mask);
  549.      }
  550.  
  551.      if (ctx->Color.SWmasking) {
  552.         gl_mask_color_pixels( ctx, PB->count, PB->x, PB->y,
  553.                   PB->r, PB->g, PB->b, PB->a, mask );
  554.      }
  555.  
  556.      /* write pixels */
  557.      (*ctx->Driver.WriteColorPixels)( ctx, PB->count, PB->x, PB->y,
  558.                       PB->r, PB->g, PB->b, PB->a, mask );
  559.      if (ctx->RasterMask & ALPHABUF_BIT) {
  560.         gl_write_alpha_pixels( ctx, PB->count, PB->x, PB->y, PB->a, mask );
  561.      }
  562.  
  563.      if (ctx->RasterMask & FRONT_AND_BACK_BIT) {
  564.         /*** Also draw to back buffer ***/
  565.         (*ctx->Driver.SetBuffer)( ctx, GL_BACK );
  566.         if (ctx->Color.SWLogicOpEnabled) {
  567.            gl_logicop_rgba_pixels( ctx, PB->count, PB->x, PB->y,
  568.                        PB->r, PB->g, PB->b, PB->a, mask);
  569.         }
  570.         else if (ctx->Color.BlendEnabled) {
  571.            gl_blend_pixels( ctx, PB->count, PB->x, PB->y,
  572.                 rsave, gsave, bsave, asave, mask );
  573.         }
  574.         if (ctx->Color.SWmasking) {
  575.            gl_mask_color_pixels( ctx, PB->count, PB->x, PB->y,
  576.                      rsave, gsave, bsave, asave, mask);
  577.         }
  578.         (*ctx->Driver.WriteColorPixels)( ctx, PB->count, PB->x, PB->y,
  579.                          rsave, gsave, bsave, asave, mask);
  580.         if (ctx->RasterMask & ALPHABUF_BIT) {
  581.            ctx->Buffer->Alpha = ctx->Buffer->BackAlpha;
  582.            gl_write_alpha_pixels( ctx, PB->count, PB->x, PB->y,
  583.                       asave, mask );
  584.            ctx->Buffer->Alpha = ctx->Buffer->FrontAlpha;
  585.         }
  586.         (*ctx->Driver.SetBuffer)( ctx, GL_FRONT );
  587.         /*** ALL DONE ***/
  588.      }
  589.       }
  590.       else {
  591.      /* Same color for all pixels */
  592.  
  593.      /* Scissoring already done above */
  594.  
  595.      if (ctx->Color.AlphaEnabled) {
  596.         if (gl_alpha_test( ctx, PB->count, PB->a, mask )==0) {
  597.            goto CleanUp;
  598.         }
  599.      }
  600.  
  601.      if (ctx->Stencil.Enabled) {
  602.         /* first stencil test */
  603.         if (gl_stencil_pixels( ctx, PB->count, PB->x, PB->y, mask )==0) {
  604.            goto CleanUp;
  605.         }
  606.         /* depth buffering w/ stencil */
  607.         gl_depth_stencil_pixels( ctx, PB->count, PB->x, PB->y, PB->z, mask );
  608.      }
  609.      else if (ctx->Depth.Test) {
  610.         /* regular depth testing */
  611.         (*ctx->Driver.DepthTestPixels)( ctx, PB->count, PB->x, PB->y, PB->z, mask );
  612.      }
  613.  
  614.      if (ctx->RasterMask & NO_DRAW_BIT) {
  615.         goto CleanUp;
  616.      }
  617.  
  618.      /* write pixels */
  619.      {
  620.         GLubyte red, green, blue, alpha;
  621.         red   = PB->color[0];
  622.         green = PB->color[1];
  623.         blue  = PB->color[2];
  624.         alpha = PB->color[3];
  625.         (*ctx->Driver.Color)( ctx, red, green, blue, alpha );
  626.      }
  627.      (*ctx->Driver.WriteMonocolorPixels)( ctx, PB->count, PB->x, PB->y, mask );
  628.      if (ctx->RasterMask & ALPHABUF_BIT) {
  629.         gl_write_mono_alpha_pixels( ctx, PB->count, PB->x, PB->y,
  630.                     PB->color[3], mask );
  631.      }
  632.  
  633.      if (ctx->RasterMask & FRONT_AND_BACK_BIT) {
  634.         /*** Also render to back buffer ***/
  635.         (*ctx->Driver.SetBuffer)( ctx, GL_BACK );
  636.         (*ctx->Driver.WriteMonocolorPixels)( ctx, PB->count, PB->x, PB->y, mask );
  637.         if (ctx->RasterMask & ALPHABUF_BIT) {
  638.            ctx->Buffer->Alpha = ctx->Buffer->BackAlpha;
  639.            gl_write_mono_alpha_pixels( ctx, PB->count, PB->x, PB->y,
  640.                        PB->color[3], mask );
  641.            ctx->Buffer->Alpha = ctx->Buffer->FrontAlpha;
  642.         }
  643.         (*ctx->Driver.SetBuffer)( ctx, GL_FRONT );
  644.      }
  645.      /*** ALL DONE ***/
  646.       }
  647.    }
  648.    else {
  649.       /* COLOR INDEX PIXELS */
  650.  
  651.       /* If we may be writting pixels with different indexes... */
  652.       if (PB->mono && ctx->MutablePixels) {
  653.      /* copy index to all pixels */
  654.      GLuint n = PB->count, indx = PB->index;
  655.      GLuint *pbindex = PB->i;
  656.      do {
  657.         *pbindex++ = indx;
  658.         n--;
  659.      } while (n);
  660.       }
  661.  
  662.       if (ctx->MutablePixels || !PB->mono) {
  663.      /* Pixel color index may be modified */
  664.      GLuint isave[PB_SIZE];
  665.  
  666.      if (ctx->Fog.Enabled
  667.          && (ctx->Hint.Fog==GL_NICEST || PB->primitive==GL_BITMAP)) {
  668.         gl_fog_index_pixels( ctx, PB->count, PB->z, PB->i );
  669.      }
  670.  
  671.      /* Scissoring already done above */
  672.  
  673.      if (ctx->Stencil.Enabled) {
  674.         /* first stencil test */
  675.         if (gl_stencil_pixels( ctx, PB->count, PB->x, PB->y, mask )==0) {
  676.            goto CleanUp;
  677.         }
  678.         /* depth buffering w/ stencil */
  679.         gl_depth_stencil_pixels( ctx, PB->count, PB->x, PB->y, PB->z, mask );
  680.      }
  681.      else if (ctx->Depth.Test) {
  682.         /* regular depth testing */
  683.         (*ctx->Driver.DepthTestPixels)( ctx, PB->count, PB->x, PB->y, PB->z, mask );
  684.      }
  685.  
  686.      if (ctx->RasterMask & NO_DRAW_BIT) {
  687.         goto CleanUp;
  688.      }
  689.  
  690.      if (ctx->RasterMask & FRONT_AND_BACK_BIT) {
  691.         /* make a copy of the indexes */
  692.         MEMCPY( isave, PB->i, PB->count * sizeof(GLuint) );
  693.      }
  694.  
  695.      if (ctx->Color.SWLogicOpEnabled) {
  696.         gl_logicop_ci_pixels( ctx, PB->count, PB->x, PB->y, PB->i, mask );
  697.      }
  698.  
  699.      if (ctx->Color.SWmasking) {
  700.         gl_mask_index_pixels( ctx, PB->count, PB->x, PB->y, PB->i, mask );
  701.      }
  702.  
  703.      /* write pixels */
  704.      (*ctx->Driver.WriteIndexPixels)( ctx, PB->count, PB->x, PB->y,
  705.                       PB->i, mask );
  706.  
  707.      if (ctx->RasterMask & FRONT_AND_BACK_BIT) {
  708.         /*** Also write to back buffer ***/
  709.         (*ctx->Driver.SetBuffer)( ctx, GL_BACK );
  710.         MEMCPY( PB->i, isave, PB->count * sizeof(GLuint) );
  711.         if (ctx->Color.SWLogicOpEnabled) {
  712.            gl_logicop_ci_pixels( ctx, PB->count, PB->x, PB->y, PB->i, mask );
  713.         }
  714.         if (ctx->Color.SWmasking) {
  715.            gl_mask_index_pixels( ctx, PB->count, PB->x, PB->y,
  716.                      PB->i, mask );
  717.         }
  718.         (*ctx->Driver.WriteIndexPixels)( ctx, PB->count, PB->x, PB->y,
  719.                          PB->i, mask );
  720.         (*ctx->Driver.SetBuffer)( ctx, GL_FRONT );
  721.      }
  722.  
  723.      /*** ALL DONE ***/
  724.       }
  725.       else {
  726.      /* Same color index for all pixels */
  727.  
  728.      /* Scissoring already done above */
  729.  
  730.      if (ctx->Stencil.Enabled) {
  731.         /* first stencil test */
  732.         if (gl_stencil_pixels( ctx, PB->count, PB->x, PB->y, mask )==0) {
  733.            goto CleanUp;
  734.         }
  735.         /* depth buffering w/ stencil */
  736.         gl_depth_stencil_pixels( ctx, PB->count, PB->x, PB->y, PB->z, mask );
  737.      }
  738.      else if (ctx->Depth.Test) {
  739.         /* regular depth testing */
  740.         (*ctx->Driver.DepthTestPixels)( ctx, PB->count, PB->x, PB->y, PB->z, mask );
  741.      }
  742.      
  743.      if (ctx->RasterMask & NO_DRAW_BIT) {
  744.         goto CleanUp;
  745.      }
  746.  
  747.      /* write pixels */
  748.      (*ctx->Driver.Index)( ctx, PB->index );
  749.      (*ctx->Driver.WriteMonoindexPixels)( ctx, PB->count, PB->x, PB->y, mask );
  750.  
  751.      if (ctx->RasterMask & FRONT_AND_BACK_BIT) {
  752.         /*** Also write to back buffer ***/
  753.         (*ctx->Driver.SetBuffer)( ctx, GL_BACK );
  754.         (*ctx->Driver.WriteMonoindexPixels)( ctx, PB->count, PB->x, PB->y, mask );
  755.         (*ctx->Driver.SetBuffer)( ctx, GL_FRONT );
  756.      }
  757.      /*** ALL DONE ***/
  758.       }
  759.    }
  760.  
  761. CleanUp:
  762.    PB->count = 0;
  763.    UNDEFARRAY(mask);
  764.    UNDEFARRAY(rsave);
  765.    UNDEFARRAY(gsave);
  766.    UNDEFARRAY(bsave);
  767.    UNDEFARRAY(asave);
  768. }
  769.  
  770. #endif
  771.