home *** CD-ROM | disk | FTP | other *** search
/ Amiga MA Magazine 1998 #6 / amigamamagazinepolishissue1998.iso / coders / mesa-1.2.8 / src / accum.c next >
C/C++ Source or Header  |  1996-05-27  |  11KB  |  387 lines

  1. /* $Id: accum.c,v 1.17 1996/05/21 14:58:49 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  1.2
  6.  * Copyright (C) 1995-1996  Brian Paul  (brianp@ssec.wisc.edu)
  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: accum.c,v $
  26.  * Revision 1.17  1996/05/21  14:58:49  brianp
  27.  * added rounding to glAccum( GL_RETURN, r ) per Alex De Bruyn
  28.  *
  29.  * Revision 1.16  1995/12/20  20:30:19  brianp
  30.  * allow larger than 2-byte accumulation buffer components, per James Johnson
  31.  *
  32.  * Revision 1.15  1995/12/18  17:24:43  brianp
  33.  * replaced ACC_TYPE with GLaccum
  34.  *
  35.  * Revision 1.14  1995/10/13  22:42:57  brianp
  36.  * use new DD.set_buffer function
  37.  *
  38.  * Revision 1.13  1995/09/18  14:20:50  brianp
  39.  * call DD.write_span_color with NULL mask, temporary hack
  40.  *
  41.  * Revision 1.12  1995/08/31  21:26:18  brianp
  42.  * use DD.read_color_span instead of dd_read_color_span
  43.  *
  44.  * Revision 1.11  1995/07/24  20:34:16  brianp
  45.  * replaced memset() with MEMSET() and memcpy() with MEMCPY()
  46.  *
  47.  * Revision 1.10  1995/06/12  15:35:00  brianp
  48.  * changed color arrays to GLubyte
  49.  *
  50.  * Revision 1.9  1995/05/22  21:02:41  brianp
  51.  * Release 1.2
  52.  *
  53.  * Revision 1.8  1995/05/12  19:22:23  brianp
  54.  * added #include "macros.h"
  55.  *
  56.  * Revision 1.7  1995/05/12  19:20:19  brianp
  57.  * replaced CC.Mode!=0 with INSIDE_BEGIN_END
  58.  *
  59.  * Revision 1.6  1995/04/11  14:03:27  brianp
  60.  * changed (*CC.write...) to (*DD.write...)
  61.  *
  62.  * Revision 1.5  1995/03/30  21:06:50  brianp
  63.  * updated to use pointers to CC.write_* functions
  64.  *
  65.  * Revision 1.4  1995/03/24  15:28:22  brianp
  66.  * replaced ACCUM_BITS with ACC_TYPE
  67.  *
  68.  * Revision 1.3  1995/03/13  20:54:27  brianp
  69.  * added read buffer logic
  70.  *
  71.  * Revision 1.2  1995/03/04  19:29:44  brianp
  72.  * 1.1 beta revision
  73.  *
  74.  * Revision 1.1  1995/02/24  14:14:02  brianp
  75.  * Initial revision
  76.  *
  77.  */
  78.  
  79.  
  80. #include <limits.h>
  81. #include <stdlib.h>
  82. #include <string.h>
  83. #include "context.h"
  84. #include "dd.h"
  85. #include "list.h"
  86. #include "macros.h"
  87.  
  88.  
  89.  
  90.  
  91. void glClearAccum( GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha )
  92. {
  93.    if (CC.CompileFlag) {
  94.       gl_save_clearaccum( red, green, blue, alpha );
  95.    }
  96.    if (CC.ExecuteFlag) {
  97.       if (INSIDE_BEGIN_END) {
  98.      gl_error( GL_INVALID_OPERATION, "glAccum" );
  99.      return;
  100.       }
  101.       CC.Accum.ClearColor[0] = CLAMP( red, -1.0, 1.0 );
  102.       CC.Accum.ClearColor[1] = CLAMP( green, -1.0, 1.0 );
  103.       CC.Accum.ClearColor[2] = CLAMP( blue, -1.0, 1.0 );
  104.       CC.Accum.ClearColor[3] = CLAMP( alpha, -1.0, 1.0 );
  105.    }
  106. }
  107.  
  108.  
  109.  
  110.  
  111. void gl_accum( GLenum op, GLfloat value )
  112. {
  113.    GLuint xpos, ypos, width, height;
  114.    GLfloat acc_scale;
  115.  
  116.    if (sizeof(GLaccum)==1) {
  117.       acc_scale = 127.0;
  118.    }
  119.    else if (sizeof(GLaccum)==2) {
  120.       acc_scale = 32767.0;
  121.    }
  122.    else {
  123.       /* sizeof(GLaccum) > 2 (Cray) */
  124.       acc_scale = (float) SHRT_MAX;
  125.    }
  126.  
  127.    if (INSIDE_BEGIN_END) {
  128.       gl_error( GL_INVALID_OPERATION, "glAccum" );
  129.       return;
  130.    }
  131.  
  132.    if (!CC.AccumBuffer) {
  133.       /* allocate accumulation buffer if not already present */
  134.       CC.AccumBuffer = (GLaccum *)
  135.         malloc( CC.BufferWidth * CC.BufferHeight * 4 * sizeof(GLaccum) );
  136.       if (!CC.AccumBuffer) {
  137.      /* unable to setup accumulation buffer */
  138.      gl_error( GL_OUT_OF_MEMORY, "glAccum" );
  139.      return;
  140.       }
  141.    }
  142.  
  143.    /* Determine region to operate upon. */
  144.    if (CC.Scissor.Enabled) {
  145.       xpos = CC.Scissor.X;
  146.       ypos = CC.Scissor.Y;
  147.       width = CC.Scissor.Width;
  148.       height = CC.Scissor.Height;
  149.    }
  150.    else {
  151.       /* whole window */
  152.       xpos = 0;
  153.       ypos = 0;
  154.       width = CC.BufferWidth;
  155.       height = CC.BufferHeight;
  156.    }
  157.  
  158.    switch (op) {
  159.       case GL_ADD:
  160.          {
  161.         GLaccum ival, *acc;
  162.         GLuint i, j;
  163.  
  164.         ival = (GLaccum) (value * acc_scale);
  165.         for (j=0;j<height;j++) {
  166.            acc = CC.AccumBuffer + ( ypos * CC.BufferWidth + xpos ) * 4;
  167.            for (i=0;i<width;i++) {
  168.           *acc += ival;      acc++;   /* red */
  169.           *acc += ival;      acc++;   /* green */
  170.           *acc += ival;      acc++;   /* blue */
  171.           *acc += ival;      acc++;   /* alpha */
  172.            }
  173.            ypos++;
  174.         }
  175.      }
  176.      break;
  177.       case GL_MULT:
  178.      {
  179.         GLaccum *acc;
  180.         GLuint i, j;
  181.  
  182.         for (j=0;j<height;j++) {
  183.            acc = CC.AccumBuffer + ( ypos * CC.BufferWidth + xpos ) * 4;
  184.            for (i=0;i<width;i++) {
  185.           *acc = (GLaccum) ( (GLfloat) *acc * value );      acc++; /*r*/
  186.           *acc = (GLaccum) ( (GLfloat) *acc * value );      acc++; /*g*/
  187.           *acc = (GLaccum) ( (GLfloat) *acc * value );      acc++; /*g*/
  188.           *acc = (GLaccum) ( (GLfloat) *acc * value );      acc++; /*a*/
  189.            }
  190.            ypos++;
  191.         }
  192.      }
  193.      break;
  194.       case GL_ACCUM:
  195.      {
  196.         GLaccum *acc;
  197.         GLubyte red[MAX_WIDTH], green[MAX_WIDTH];
  198.         GLubyte blue[MAX_WIDTH], alpha[MAX_WIDTH];
  199.         GLfloat rscale, gscale, bscale, ascale;
  200.         GLuint i, j;
  201.  
  202.         (void) (*DD.set_buffer)( CC.Pixel.ReadBuffer );
  203.  
  204.         /* Accumulate */
  205.         rscale = value * acc_scale / CC.RedScale;
  206.         gscale = value * acc_scale / CC.GreenScale;
  207.         bscale = value * acc_scale / CC.BlueScale;
  208.         ascale = value * acc_scale / CC.AlphaScale;
  209.         for (j=0;j<height;j++) {
  210.            (*DD.read_color_span)( width, xpos, ypos,
  211.                                       red, green, blue, alpha);
  212.            acc = CC.AccumBuffer + ( ypos * CC.BufferWidth + xpos ) * 4;
  213.            for (i=0;i<width;i++) {
  214.           *acc += (GLaccum) ( (GLfloat) red[i]   * rscale );  acc++;
  215.           *acc += (GLaccum) ( (GLfloat) green[i] * gscale );  acc++;
  216.           *acc += (GLaccum) ( (GLfloat) blue[i]  * bscale );  acc++;
  217.           *acc += (GLaccum) ( (GLfloat) alpha[i] * ascale );  acc++;
  218.            }
  219.            ypos++;
  220.         }
  221.  
  222.         (void) (*DD.set_buffer)( CC.Color.DrawBuffer );
  223.      }
  224.      break;
  225.       case GL_LOAD:
  226.      {
  227.         GLaccum *acc;
  228.         GLubyte red[MAX_WIDTH], green[MAX_WIDTH];
  229.         GLubyte blue[MAX_WIDTH], alpha[MAX_WIDTH];
  230.         GLfloat rscale, gscale, bscale, ascale;
  231.         GLuint i, j;
  232.  
  233.         (void) (*DD.set_buffer)( CC.Pixel.ReadBuffer );
  234.  
  235.         /* Load accumulation buffer */
  236.         rscale = value * acc_scale / CC.RedScale;
  237.         gscale = value * acc_scale / CC.GreenScale;
  238.         bscale = value * acc_scale / CC.BlueScale;
  239.         ascale = value * acc_scale / CC.AlphaScale;
  240.         for (j=0;j<height;j++) {
  241.            (*DD.read_color_span)( width, xpos, ypos,
  242.                                       red, green, blue, alpha);
  243.            acc = CC.AccumBuffer + ( ypos * CC.BufferWidth + xpos ) * 4;
  244.            for (i=0;i<width;i++) {
  245.           *acc++ = (GLaccum) ( (GLfloat) red[i]   * rscale );
  246.           *acc++ = (GLaccum) ( (GLfloat) green[i] * gscale );
  247.           *acc++ = (GLaccum) ( (GLfloat) blue[i]  * bscale );
  248.           *acc++ = (GLaccum) ( (GLfloat) alpha[i] * ascale );
  249.            }
  250.            ypos++;
  251.         }
  252.  
  253.         (void) (*DD.set_buffer)( CC.Color.DrawBuffer );
  254.      }
  255.      break;
  256.       case GL_RETURN:
  257.      {
  258.         GLubyte red[MAX_WIDTH], green[MAX_WIDTH];
  259.         GLubyte blue[MAX_WIDTH], alpha[MAX_WIDTH];
  260.         GLaccum *acc;
  261.         GLfloat rscale, gscale, bscale, ascale;
  262.         GLint rmax, gmax, bmax, amax;
  263.         GLuint i, j;
  264.  
  265.         rscale = value / acc_scale * CC.RedScale;
  266.         gscale = value / acc_scale * CC.GreenScale;
  267.         bscale = value / acc_scale * CC.BlueScale;
  268.         ascale = value / acc_scale * CC.AlphaScale;
  269.         rmax = (GLint) CC.RedScale;
  270.         gmax = (GLint) CC.GreenScale;
  271.         bmax = (GLint) CC.BlueScale;
  272.         amax = (GLint) CC.AlphaScale;
  273.         for (j=0;j<height;j++) {
  274.            acc = CC.AccumBuffer + ( ypos * CC.BufferWidth + xpos ) * 4;
  275.            for (i=0;i<width;i++) {
  276.           GLint r, g, b, a;
  277.           r = (GLint) ( (GLfloat) (*acc++) * rscale + 0.5F );
  278.           g = (GLint) ( (GLfloat) (*acc++) * gscale + 0.5F );
  279.           b = (GLint) ( (GLfloat) (*acc++) * bscale + 0.5F );
  280.           a = (GLint) ( (GLfloat) (*acc++) * ascale + 0.5F );
  281.           red[i]   = CLAMP( r, 0, rmax );
  282.           green[i] = CLAMP( g, 0, gmax );
  283.           blue[i]  = CLAMP( b, 0, bmax );
  284.           alpha[i] = CLAMP( a, 0, amax );
  285.            }
  286.            (*DD.write_color_span)( width, xpos, ypos,
  287.                        red, green, blue, alpha, NULL );
  288.            ypos++;
  289.         }
  290.      }
  291.      break;
  292.       default:
  293.          gl_error( GL_INVALID_ENUM, "glAccum" );
  294.    }
  295. }
  296.  
  297.  
  298.  
  299.  
  300. void glAccum( GLenum op, GLfloat value )
  301. {
  302.    if (CC.ExecuteFlag) {
  303.       gl_accum( op, value );
  304.    }
  305.    if (CC.CompileFlag) {
  306.       gl_save_accum( op, value );
  307.    }
  308. }
  309.  
  310.  
  311.  
  312. /*
  313.  * Clear the accumulation buffer.
  314.  */
  315. void gl_clear_accum_buffer( void )
  316. {
  317.    GLuint buffersize;
  318.    GLfloat acc_scale;
  319.  
  320.    if (sizeof(GLaccum)==1) {
  321.       acc_scale = 127.0;
  322.    }
  323.    else if (sizeof(GLaccum)==2) {
  324.       acc_scale = 32767.0;
  325.    }
  326.    else {
  327.       /* sizeof(GLaccum) > 2 (Cray) */
  328.       acc_scale = (float) SHRT_MAX;
  329.    }
  330.  
  331.    buffersize = CC.BufferWidth * CC.BufferHeight;  /* number of pixels */
  332.  
  333.    if (!CC.AccumBuffer) {
  334.       /* try to alloc accumulation buffer */
  335.       CC.AccumBuffer = (GLaccum *)
  336.                        malloc( buffersize * 4 * sizeof(GLaccum) );
  337.    }
  338.  
  339.    if (CC.AccumBuffer) {
  340.       if (CC.Scissor.Enabled) {
  341.      /* Limit clear to scissor box */
  342.      GLaccum r, g, b, a;
  343.      GLint x, y, i;
  344.      r = (GLaccum) (CC.Accum.ClearColor[0] * acc_scale);
  345.      g = (GLaccum) (CC.Accum.ClearColor[1] * acc_scale);
  346.      b = (GLaccum) (CC.Accum.ClearColor[2] * acc_scale);
  347.      a = (GLaccum) (CC.Accum.ClearColor[3] * acc_scale);
  348.      for (y=CC.Scissor.Ymin; y<=CC.Scissor.Ymax; y++) {
  349.         for (x=CC.Scissor.Xmin; x<=CC.Scissor.Xmax; x++) {
  350.            i = 4 * (y * CC.BufferWidth + x);
  351.            CC.AccumBuffer[i+0] = r;
  352.            CC.AccumBuffer[i+1] = g;
  353.            CC.AccumBuffer[i+2] = b;
  354.            CC.AccumBuffer[i+3] = a;
  355.         }
  356.      }
  357.       }
  358.       else {
  359.      /* clear whole buffer */
  360.      if (CC.Accum.ClearColor[0]==0.0 &&
  361.          CC.Accum.ClearColor[1]==0.0 &&
  362.          CC.Accum.ClearColor[2]==0.0 &&
  363.          CC.Accum.ClearColor[3]==0.0) {
  364.         /* Black */
  365.         MEMSET( CC.AccumBuffer, 0, buffersize * 4 * sizeof(GLaccum) );
  366.      }
  367.      else {
  368.         /* Not black */
  369.         GLaccum *acc, r, g, b, a;
  370.         GLuint i;
  371.  
  372.         acc = CC.AccumBuffer;
  373.         r = (GLaccum) (CC.Accum.ClearColor[0] * acc_scale);
  374.         g = (GLaccum) (CC.Accum.ClearColor[1] * acc_scale);
  375.         b = (GLaccum) (CC.Accum.ClearColor[2] * acc_scale);
  376.         a = (GLaccum) (CC.Accum.ClearColor[3] * acc_scale);
  377.         for (i=0;i<buffersize;i++) {
  378.            *acc++ = r;
  379.            *acc++ = g;
  380.            *acc++ = b;
  381.            *acc++ = a;
  382.         }
  383.      }
  384.       }
  385.    }
  386. }
  387.