home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 6 / AACD06.ISO / AACD / System / Mesa-3.1 / src / pb.c < prev    next >
C/C++ Source or Header  |  2000-01-07  |  16KB  |  502 lines

  1. /* $Id: pb.c,v 1.3.2.1 1999/11/25 16:51:25 keithw Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  3.1
  6.  * 
  7.  * Copyright (C) 1999  Brian Paul   All Rights Reserved.
  8.  * 
  9.  * Permission is hereby granted, free of charge, to any person obtaining a
  10.  * copy of this software and associated documentation files (the "Software"),
  11.  * to deal in the Software without restriction, including without limitation
  12.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  13.  * and/or sell copies of the Software, and to permit persons to whom the
  14.  * Software is furnished to do so, subject to the following conditions:
  15.  * 
  16.  * The above copyright notice and this permission notice shall be included
  17.  * in all copies or substantial portions of the Software.
  18.  * 
  19.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  20.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  22.  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
  23.  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  24.  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  25.  */
  26.  
  27.  
  28.  
  29.  
  30.  
  31. /*
  32.  * Pixel buffer:
  33.  *
  34.  * As fragments are produced (by point, line, and bitmap drawing) they
  35.  * are accumlated in a buffer.  When the buffer is full or has to be
  36.  * flushed (glEnd), we apply all enabled rasterization functions to the
  37.  * pixels and write the results to the display buffer.  The goal is to
  38.  * maximize the number of pixels processed inside loops and to minimize
  39.  * the number of function calls.
  40.  */
  41. /* $XFree86: xc/lib/GL/mesa/src/pb.c,v 1.3 1999/04/04 00:20:28 dawes Exp $ */
  42.  
  43.  
  44. #ifdef PC_HEADER
  45. #include "all.h"
  46. #else
  47. #ifndef XFree86Server
  48. #include <stdlib.h>
  49. #include <string.h>
  50. #else
  51. #include "GL/xf86glx.h"
  52. #endif
  53. #include "alpha.h"
  54. #include "alphabuf.h"
  55. #include "blend.h"
  56. #include "depth.h"
  57. #include "fog.h"
  58. #include "logic.h"
  59. #include "macros.h"
  60. #include "masking.h"
  61. #include "pb.h"
  62. #include "scissor.h"
  63. #include "stencil.h"
  64. #include "texture.h"
  65. #include "types.h"
  66. #endif
  67.  
  68.  
  69.  
  70. /*
  71.  * Allocate and initialize a new pixel buffer structure.
  72.  */
  73. struct pixel_buffer *gl_alloc_pb(void)
  74. {
  75.    struct pixel_buffer *pb;
  76.    pb = (struct pixel_buffer *) calloc(sizeof(struct pixel_buffer), 1);
  77.    if (pb) {
  78.       int i, j;
  79.       /* set non-zero fields */
  80.       pb->primitive = GL_BITMAP;
  81.       /* Set all lambda values to 0.0 since we don't do mipmapping for
  82.        * points or lines and want to use the level 0 texture image.
  83.        */
  84.  
  85.       for (j=0;j<MAX_TEXTURE_UNITS;j++) {
  86.          for (i=0; i<PB_SIZE; i++) {
  87.             pb->lambda[j][i] = 0.0;
  88.          }
  89.       }
  90.    }
  91.    return pb;
  92. }
  93.  
  94.  
  95.  
  96. /*
  97.  * Draw to more than one color buffer (or none).
  98.  */
  99. static void multi_write_index_pixels( GLcontext *ctx, GLuint n,
  100.                                       const GLint x[], const GLint y[],
  101.                                       const GLuint indexes[],
  102.                                       const GLubyte mask[] )
  103. {
  104.    GLuint bufferBit;
  105.  
  106.    if (ctx->Color.DrawBuffer == GL_NONE)
  107.       return;
  108.  
  109.    /* loop over four possible dest color buffers */
  110.    for (bufferBit = 1; bufferBit <= 8; bufferBit = bufferBit << 1) {
  111.       if (bufferBit & ctx->Color.DrawDestMask) {
  112.          GLuint indexTmp[MAX_WIDTH];
  113.          ASSERT(n < MAX_WIDTH);
  114.  
  115.          if (bufferBit == FRONT_LEFT_BIT)
  116.             (*ctx->Driver.SetBuffer)( ctx, GL_FRONT_LEFT);
  117.          else if (bufferBit == FRONT_RIGHT_BIT)
  118.             (*ctx->Driver.SetBuffer)( ctx, GL_FRONT_RIGHT);
  119.          else if (bufferBit == BACK_LEFT_BIT)
  120.             (*ctx->Driver.SetBuffer)( ctx, GL_BACK_LEFT);
  121.          else
  122.             (*ctx->Driver.SetBuffer)( ctx, GL_BACK_RIGHT);
  123.  
  124.          /* make copy of incoming indexes */
  125.          MEMCPY( indexTmp, indexes, n * sizeof(GLuint) );
  126.          if (ctx->Color.SWLogicOpEnabled) {
  127.             gl_logicop_ci_pixels( ctx, n, x, y, indexTmp, mask );
  128.          }
  129.          if (ctx->Color.SWmasking) {
  130.             gl_mask_index_pixels( ctx, n, x, y, indexTmp, mask );
  131.          }
  132.          (*ctx->Driver.WriteCI32Pixels)( ctx, n, x, y, indexTmp, mask );
  133.       }
  134.    }
  135.  
  136.    /* restore default dest buffer */
  137.    (void) (*ctx->Driver.SetBuffer)( ctx, ctx->Color.DriverDrawBuffer);
  138. }
  139.  
  140.  
  141.  
  142. /*
  143.  * Draw to more than one RGBA color buffer (or none).
  144.  */
  145. static void multi_write_rgba_pixels( GLcontext *ctx, GLuint n,
  146.                                      const GLint x[], const GLint y[],
  147.                                      CONST GLubyte rgba[][4],
  148.                                      const GLubyte mask[] )
  149. {
  150.    GLuint bufferBit;
  151.  
  152.    if (ctx->Color.DrawBuffer == GL_NONE)
  153.       return;
  154.  
  155.    /* loop over four possible dest color buffers */
  156.    for (bufferBit = 1; bufferBit <= 8; bufferBit = bufferBit << 1) {
  157.       if (bufferBit & ctx->Color.DrawDestMask) {
  158.          GLubyte rgbaTmp[MAX_WIDTH][4];
  159.          ASSERT(n < MAX_WIDTH);
  160.  
  161.          if (bufferBit == FRONT_LEFT_BIT) {
  162.             (*ctx->Driver.SetBuffer)( ctx, GL_FRONT_LEFT);
  163.             ctx->Buffer->Alpha = ctx->Buffer->FrontLeftAlpha;
  164.          }
  165.          else if (bufferBit == FRONT_RIGHT_BIT) {
  166.             (*ctx->Driver.SetBuffer)( ctx, GL_FRONT_RIGHT);
  167.             ctx->Buffer->Alpha = ctx->Buffer->FrontRightAlpha;
  168.          }
  169.          else if (bufferBit == BACK_LEFT_BIT) {
  170.             (*ctx->Driver.SetBuffer)( ctx, GL_BACK_LEFT);
  171.             ctx->Buffer->Alpha = ctx->Buffer->BackLeftAlpha;
  172.          }
  173.          else {
  174.             (*ctx->Driver.SetBuffer)( ctx, GL_BACK_RIGHT);
  175.             ctx->Buffer->Alpha = ctx->Buffer->BackRightAlpha;
  176.          }
  177.  
  178.          /* make copy of incoming colors */
  179.          MEMCPY( rgbaTmp, rgba, 4 * n * sizeof(GLubyte) );
  180.  
  181.          if (ctx->Color.SWLogicOpEnabled) {
  182.             gl_logicop_rgba_pixels( ctx, n, x, y, rgbaTmp, mask );
  183.          }
  184.          else if (ctx->Color.BlendEnabled) {
  185.             gl_blend_pixels( ctx, n, x, y, rgbaTmp, mask );
  186.          }
  187.          if (ctx->Color.SWmasking) {
  188.             gl_mask_rgba_pixels( ctx, n, x, y, rgbaTmp, mask );
  189.          }
  190.  
  191.          (*ctx->Driver.WriteRGBAPixels)( ctx, n, x, y, 
  192.                      (const GLubyte (*)[4])rgbaTmp, mask );
  193.          if (ctx->RasterMask & ALPHABUF_BIT) {
  194.             gl_write_alpha_pixels( ctx, n, x, y, 
  195.                    (const GLubyte (*)[4])rgbaTmp, mask );
  196.          }
  197.       }
  198.    }
  199.  
  200.    /* restore default dest buffer */
  201.    (void) (*ctx->Driver.SetBuffer)( ctx, ctx->Color.DriverDrawBuffer);
  202. }
  203.  
  204.  
  205.  
  206. /*
  207.  * Add specular color to primary color.  This is used only when
  208.  * GL_LIGHT_MODEL_COLOR_CONTROL = GL_SEPARATE_SPECULAR_COLOR.
  209.  */
  210. static void add_colors( GLuint n, GLubyte rgba[][4], CONST GLubyte spec[][3] )
  211. {
  212.    GLuint i;
  213.    for (i=0; i<n; i++) {
  214.       GLint r = rgba[i][RCOMP] + spec[i][RCOMP];
  215.       GLint g = rgba[i][GCOMP] + spec[i][GCOMP];
  216.       GLint b = rgba[i][BCOMP] + spec[i][BCOMP];
  217.       rgba[i][RCOMP] = MIN2(r, 255);
  218.       rgba[i][GCOMP] = MIN2(g, 255);
  219.       rgba[i][BCOMP] = MIN2(b, 255);
  220.    }
  221. }
  222.  
  223.  
  224.  
  225. /*
  226.  * When the pixel buffer is full, or needs to be flushed, call this
  227.  * function.  All the pixels in the pixel buffer will be subjected
  228.  * to texturing, scissoring, stippling, alpha testing, stenciling,
  229.  * depth testing, blending, and finally written to the frame buffer.
  230.  */
  231. void gl_flush_pb( GLcontext *ctx )
  232. {
  233.    struct pixel_buffer* PB = ctx->PB;
  234.    GLubyte mask[PB_SIZE];
  235.  
  236.    if (PB->count==0)
  237.       goto CleanUp;
  238.  
  239.    /* initialize mask array and clip pixels simultaneously */
  240.    {
  241.       GLint xmin = ctx->Buffer->Xmin;
  242.       GLint xmax = ctx->Buffer->Xmax;
  243.       GLint ymin = ctx->Buffer->Ymin;
  244.       GLint ymax = ctx->Buffer->Ymax;
  245.       GLint *x = PB->x;
  246.       GLint *y = PB->y;
  247.       GLuint i, n = PB->count;
  248.       for (i=0;i<n;i++) {
  249.          mask[i] = (x[i]>=xmin) & (x[i]<=xmax) & (y[i]>=ymin) & (y[i]<=ymax);
  250.       }
  251.    }
  252.  
  253.    if (ctx->Visual->RGBAflag) {
  254.       /*
  255.        * RGBA COLOR PIXELS
  256.        */
  257.       if (PB->mono && ctx->MutablePixels) {
  258.      /* Copy mono color to all pixels */
  259.          GLuint i;
  260.          for (i=0; i<PB->count; i++) {
  261.             PB->rgba[i][RCOMP] = PB->color[RCOMP];
  262.             PB->rgba[i][GCOMP] = PB->color[GCOMP];
  263.             PB->rgba[i][BCOMP] = PB->color[BCOMP];
  264.             PB->rgba[i][ACOMP] = PB->color[ACOMP];
  265.          }
  266.       }
  267.  
  268.       /* If each pixel can be of a different color... */
  269.       if (ctx->MutablePixels || !PB->mono) {
  270.  
  271.      if (ctx->Texture.ReallyEnabled) {
  272.             int texUnit;
  273.             for (texUnit=0;texUnit<MAX_TEXTURE_UNITS;texUnit++) {
  274.             gl_texture_pixels( ctx, texUnit,
  275.                                    PB->count, PB->s[texUnit], PB->t[texUnit],
  276.                                    PB->u[texUnit], PB->lambda[texUnit],
  277.                                    PB->rgba);
  278.             }
  279.      }
  280.  
  281.          if (ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR
  282.              && ctx->Light.Enabled) {
  283.             /* add specular color to primary color */
  284.             add_colors( PB->count, PB->rgba, (const GLubyte (*)[3]) PB->spec );
  285.          }
  286.  
  287.      if (ctx->Fog.Enabled
  288.              && (ctx->FogMode == FOG_FRAGMENT || PB->primitive==GL_BITMAP)) {
  289.         gl_fog_rgba_pixels( ctx, PB->count, PB->z, PB->rgba );
  290.      }
  291.  
  292.          /* Scissoring already done above */
  293.  
  294.      if (ctx->Color.AlphaEnabled) {
  295.         if (gl_alpha_test( ctx, PB->count, 
  296.                    (const GLubyte (*)[4])PB->rgba, mask )==0) {
  297.            goto CleanUp;
  298.         }
  299.      }
  300.  
  301.      if (ctx->Stencil.Enabled) {
  302.         /* first stencil test */
  303.         if (gl_stencil_pixels( ctx, PB->count, PB->x, PB->y, mask )==0) {
  304.            goto CleanUp;
  305.         }
  306.         /* depth buffering w/ stencil */
  307.         gl_depth_stencil_pixels( ctx, PB->count, PB->x, PB->y, PB->z, mask );
  308.      }
  309.      else if (ctx->Depth.Test) {
  310.         /* regular depth testing */
  311.         (*ctx->Driver.DepthTestPixels)( ctx, PB->count, PB->x, PB->y,
  312.                                             PB->z, mask );
  313.      }
  314.  
  315.          
  316.          if (ctx->RasterMask & MULTI_DRAW_BIT) {
  317.             multi_write_rgba_pixels( ctx, PB->count, PB->x, PB->y,
  318.                                      (const GLubyte (*)[4])PB->rgba, mask );
  319.          }
  320.          else {
  321.             /* normal case: write to exactly one buffer */
  322.  
  323.             if (ctx->Color.SWLogicOpEnabled) {
  324.                gl_logicop_rgba_pixels( ctx, PB->count, PB->x, PB->y,
  325.                                        PB->rgba, mask);
  326.             }
  327.             else if (ctx->Color.BlendEnabled) {
  328.                gl_blend_pixels( ctx, PB->count, PB->x, PB->y, PB->rgba, mask);
  329.             }
  330.             if (ctx->Color.SWmasking) {
  331.                gl_mask_rgba_pixels(ctx, PB->count, PB->x, PB->y, PB->rgba, mask);
  332.             }
  333.  
  334.             (*ctx->Driver.WriteRGBAPixels)( ctx, PB->count, PB->x, PB->y,
  335.                                             (const GLubyte (*)[4]) PB->rgba,
  336.                         mask );
  337.             if (ctx->RasterMask & ALPHABUF_BIT) {
  338.                gl_write_alpha_pixels( ctx, PB->count, PB->x, PB->y, 
  339.                       (const GLubyte (*)[4]) PB->rgba, mask );
  340.             }
  341.          }
  342.       }
  343.       else {
  344.      /* Same color for all pixels */
  345.  
  346.          /* Scissoring already done above */
  347.  
  348.      if (ctx->Color.AlphaEnabled) {
  349.         if (gl_alpha_test( ctx, PB->count, 
  350.                    (const GLubyte (*)[4]) PB->rgba, mask )==0) {
  351.            goto CleanUp;
  352.         }
  353.      }
  354.  
  355.      if (ctx->Stencil.Enabled) {
  356.         /* first stencil test */
  357.         if (gl_stencil_pixels( ctx, PB->count, PB->x, PB->y, mask )==0) {
  358.            goto CleanUp;
  359.         }
  360.         /* depth buffering w/ stencil */
  361.         gl_depth_stencil_pixels( ctx, PB->count, PB->x, PB->y, PB->z, mask );
  362.      }
  363.      else if (ctx->Depth.Test) {
  364.         /* regular depth testing */
  365.         (*ctx->Driver.DepthTestPixels)( ctx, PB->count, PB->x, PB->y, PB->z, mask );
  366.      }
  367.  
  368.          if (ctx->Color.DrawBuffer == GL_NONE) {
  369.             goto CleanUp;
  370.          }
  371.  
  372.          if (ctx->RasterMask & MULTI_DRAW_BIT) {
  373.             /* Copy mono color to all pixels */
  374.             GLuint i;
  375.             for (i=0; i<PB->count; i++) {
  376.                PB->rgba[i][RCOMP] = PB->color[RCOMP];
  377.                PB->rgba[i][GCOMP] = PB->color[GCOMP];
  378.                PB->rgba[i][BCOMP] = PB->color[BCOMP];
  379.                PB->rgba[i][ACOMP] = PB->color[ACOMP];
  380.             }
  381.             multi_write_rgba_pixels( ctx, PB->count, PB->x, PB->y,
  382.                                      (const GLubyte (*)[4]) PB->rgba, mask );
  383.          }
  384.          else {
  385.             /* normal case: write to exactly one buffer */
  386.  
  387.             GLubyte red, green, blue, alpha;
  388.             red   = PB->color[RCOMP];
  389.             green = PB->color[GCOMP];
  390.             blue  = PB->color[BCOMP];
  391.             alpha = PB->color[ACOMP];
  392.         (*ctx->Driver.Color)( ctx, red, green, blue, alpha );
  393.  
  394.             (*ctx->Driver.WriteMonoRGBAPixels)( ctx, PB->count, PB->x, PB->y, mask );
  395.             if (ctx->RasterMask & ALPHABUF_BIT) {
  396.                gl_write_mono_alpha_pixels( ctx, PB->count, PB->x, PB->y,
  397.                                            PB->color[ACOMP], mask );
  398.             }
  399.          }
  400.          /*** ALL DONE ***/
  401.       }
  402.    }
  403.    else {
  404.       /*
  405.        * COLOR INDEX PIXELS
  406.        */
  407.  
  408.       /* If we may be writting pixels with different indexes... */
  409.       if (PB->mono && ctx->MutablePixels) {
  410.      /* copy index to all pixels */
  411.          GLuint n = PB->count, indx = PB->index;
  412.          GLuint *pbindex = PB->i;
  413.          do {
  414.         *pbindex++ = indx;
  415.             n--;
  416.      } while (n);
  417.       }
  418.  
  419.       if (ctx->MutablePixels || !PB->mono) {
  420.  
  421.      if (ctx->Fog.Enabled
  422.              && (ctx->FogMode==FOG_FRAGMENT || PB->primitive==GL_BITMAP)) {
  423.         gl_fog_ci_pixels( ctx, PB->count, PB->z, PB->i );
  424.      }
  425.  
  426.          /* Scissoring already done above */
  427.  
  428.      if (ctx->Stencil.Enabled) {
  429.         /* first stencil test */
  430.         if (gl_stencil_pixels( ctx, PB->count, PB->x, PB->y, mask )==0) {
  431.            goto CleanUp;
  432.         }
  433.         /* depth buffering w/ stencil */
  434.         gl_depth_stencil_pixels( ctx, PB->count, PB->x, PB->y, PB->z, mask );
  435.      }
  436.      else if (ctx->Depth.Test) {
  437.         /* regular depth testing */
  438.         (*ctx->Driver.DepthTestPixels)( ctx, PB->count, PB->x, PB->y, PB->z, mask );
  439.      }
  440.  
  441.          if (ctx->RasterMask & MULTI_DRAW_BIT) {
  442.             multi_write_index_pixels( ctx, PB->count, PB->x, PB->y, PB->i, mask );
  443.          }
  444.          else {
  445.             /* normal case: write to exactly one buffer */
  446.  
  447.             if (ctx->Color.SWLogicOpEnabled) {
  448.                gl_logicop_ci_pixels( ctx, PB->count, PB->x, PB->y, PB->i, mask );
  449.             }
  450.             if (ctx->Color.SWmasking) {
  451.                gl_mask_index_pixels( ctx, PB->count, PB->x, PB->y, PB->i, mask );
  452.             }
  453.  
  454.             (*ctx->Driver.WriteCI32Pixels)( ctx, PB->count, PB->x, PB->y,
  455.                                             PB->i, mask );
  456.          }
  457.  
  458.          /*** ALL DONE ***/
  459.       }
  460.       else {
  461.      /* Same color index for all pixels */
  462.  
  463.          /* Scissoring already done above */
  464.  
  465.      if (ctx->Stencil.Enabled) {
  466.         /* first stencil test */
  467.         if (gl_stencil_pixels( ctx, PB->count, PB->x, PB->y, mask )==0) {
  468.            goto CleanUp;
  469.         }
  470.         /* depth buffering w/ stencil */
  471.         gl_depth_stencil_pixels( ctx, PB->count, PB->x, PB->y, PB->z, mask );
  472.      }
  473.      else if (ctx->Depth.Test) {
  474.         /* regular depth testing */
  475.         (*ctx->Driver.DepthTestPixels)( ctx, PB->count, PB->x, PB->y, PB->z, mask );
  476.      }
  477.          
  478.          if (ctx->RasterMask & MULTI_DRAW_BIT) {
  479.             GLuint n = PB->count, indx = PB->index;
  480.             GLuint *pbindex = PB->i;
  481.             do {
  482.                *pbindex++ = indx;
  483.                n--;
  484.             } while (n);
  485.  
  486.             multi_write_index_pixels( ctx, PB->count, PB->x, PB->y, PB->i, mask );
  487.          }
  488.          else {
  489.             /* normal case: write to exactly one buffer */
  490.  
  491.             (*ctx->Driver.Index)( ctx, PB->index );
  492.             (*ctx->Driver.WriteMonoCIPixels)( ctx, PB->count, PB->x, PB->y, mask );
  493.          }
  494.       }
  495.    }
  496.  
  497. CleanUp:
  498.    PB->count = 0;
  499. }
  500.  
  501.  
  502.