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

  1. /* $Id: accum.c,v 1.5 1997/07/24 01:24:28 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: accum.c,v $
  26.  * Revision 1.5  1997/07/24 01:24:28  brianp
  27.  * changed precompiled header symbol from PCH to PC_HEADER
  28.  *
  29.  * Revision 1.4  1997/05/28 03:23:09  brianp
  30.  * added precompiled header (PCH) support
  31.  *
  32.  * Revision 1.3  1997/04/30 01:54:48  brianp
  33.  * call gl_warning() if calling gl_Accum w/out accum buffer
  34.  *
  35.  * Revision 1.2  1996/09/15 14:19:44  brianp
  36.  * now use GLframebuffer and GLvisual
  37.  * added gl_alloc_accum_buffer()
  38.  *
  39.  * Revision 1.1  1996/09/13 01:38:16  brianp
  40.  * Initial revision
  41.  *
  42.  */
  43.  
  44.  
  45. #ifdef PC_HEADER
  46. #include "all.h"
  47. #else
  48. #include <limits.h>
  49. #include <stdlib.h>
  50. #include <stdio.h>
  51. #include <string.h>
  52. #include "accum.h"
  53. #include "context.h"
  54. #include "dlist.h"
  55. #include "macros.h"
  56. #include "types.h"
  57. #endif
  58.  
  59.  
  60. void gl_alloc_accum_buffer( GLcontext *ctx )
  61. {
  62.    GLint n;
  63.  
  64.    if (ctx->Buffer->Accum) {
  65.       free( ctx->Buffer->Accum );
  66.       ctx->Buffer->Accum = NULL;
  67.    }
  68.  
  69.    /* allocate accumulation buffer if not already present */
  70.    n = ctx->Buffer->Width * ctx->Buffer->Height * 4 * sizeof(GLaccum);
  71.    ctx->Buffer->Accum = (GLaccum *) malloc( n );
  72.    if (!ctx->Buffer->Accum) {
  73.       /* unable to setup accumulation buffer */
  74.       gl_error( ctx, GL_OUT_OF_MEMORY, "glAccum" );
  75.    }
  76. }
  77.  
  78.  
  79.  
  80. void gl_ClearAccum( GLcontext *ctx,
  81.             GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha )
  82. {
  83.    if (INSIDE_BEGIN_END(ctx)) {
  84.       gl_error( ctx, GL_INVALID_OPERATION, "glAccum" );
  85.       return;
  86.    }
  87.    ctx->Accum.ClearColor[0] = CLAMP( red, -1.0, 1.0 );
  88.    ctx->Accum.ClearColor[1] = CLAMP( green, -1.0, 1.0 );
  89.    ctx->Accum.ClearColor[2] = CLAMP( blue, -1.0, 1.0 );
  90.    ctx->Accum.ClearColor[3] = CLAMP( alpha, -1.0, 1.0 );
  91. }
  92.  
  93.  
  94.  
  95.  
  96. void gl_Accum( GLcontext *ctx, GLenum op, GLfloat value )
  97. {
  98.    GLuint xpos, ypos, width, height;
  99.    GLfloat acc_scale;
  100.  
  101.    if (INSIDE_BEGIN_END(ctx)) {
  102.       gl_error( ctx, GL_INVALID_OPERATION, "glAccum" );
  103.       return;
  104.    }
  105.  
  106.    if (ctx->Visual->AccumBits==0 || !ctx->Buffer->Accum) {
  107.       /* No accumulation buffer! */
  108.       gl_warning(ctx, "Calling glAccum() without an accumulation buffer");
  109.       return;
  110.    }
  111.  
  112.    if (sizeof(GLaccum)==1) {
  113.       acc_scale = 127.0;
  114.    }
  115.    else if (sizeof(GLaccum)==2) {
  116.       acc_scale = 32767.0;
  117.    }
  118.    else {
  119.       /* sizeof(GLaccum) > 2 (Cray) */
  120.       acc_scale = (float) SHRT_MAX;
  121.    }
  122.  
  123.    /* Determine region to operate upon. */
  124.    if (ctx->Scissor.Enabled) {
  125.       xpos = ctx->Scissor.X;
  126.       ypos = ctx->Scissor.Y;
  127.       width = ctx->Scissor.Width;
  128.       height = ctx->Scissor.Height;
  129.    }
  130.    else {
  131.       /* whole window */
  132.       xpos = 0;
  133.       ypos = 0;
  134.       width = ctx->Buffer->Width;
  135.       height = ctx->Buffer->Height;
  136.    }
  137.  
  138.    switch (op) {
  139.       case GL_ADD:
  140.      {
  141.         GLaccum ival, *acc;
  142.         GLuint i, j;
  143.  
  144.         ival = (GLaccum) (value * acc_scale);
  145.         for (j=0;j<height;j++) {
  146.            acc = ctx->Buffer->Accum
  147.              + (ypos * ctx->Buffer->Width + xpos) * 4;
  148.            for (i=0;i<width;i++) {
  149.           *acc += ival;   acc++;   /* red */
  150.           *acc += ival;   acc++;   /* green */
  151.           *acc += ival;   acc++;   /* blue */
  152.           *acc += ival;   acc++;   /* alpha */
  153.            }
  154.            ypos++;
  155.         }
  156.      }
  157.      break;
  158.       case GL_MULT:
  159.      {
  160.         GLaccum *acc;
  161.         GLuint i, j;
  162.  
  163.         for (j=0;j<height;j++) {
  164.            acc = ctx->Buffer->Accum
  165.              + (ypos * ctx->Buffer->Width + xpos) * 4;
  166.            for (i=0;i<width;i++) {
  167.           *acc = (GLaccum) ( (GLfloat) *acc * value );    acc++; /*r*/
  168.           *acc = (GLaccum) ( (GLfloat) *acc * value );    acc++; /*g*/
  169.           *acc = (GLaccum) ( (GLfloat) *acc * value );    acc++; /*g*/
  170.           *acc = (GLaccum) ( (GLfloat) *acc * value );    acc++; /*a*/
  171.            }
  172.            ypos++;
  173.         }
  174.      }
  175.      break;
  176.       case GL_ACCUM:
  177.      {
  178.         GLaccum *acc;
  179.         GLubyte red[MAX_WIDTH], green[MAX_WIDTH];
  180.         GLubyte blue[MAX_WIDTH], alpha[MAX_WIDTH];
  181.         GLfloat rscale, gscale, bscale, ascale;
  182.         GLuint i, j;
  183.         (void) (*ctx->Driver.SetBuffer)( ctx, ctx->Pixel.ReadBuffer );
  184.  
  185.         /* Accumulate */
  186.         rscale = value * acc_scale * ctx->Visual->InvRedScale;
  187.         gscale = value * acc_scale * ctx->Visual->InvGreenScale;
  188.         bscale = value * acc_scale * ctx->Visual->InvBlueScale;
  189.         ascale = value * acc_scale * ctx->Visual->InvAlphaScale;
  190.         for (j=0;j<height;j++) {
  191.            (*ctx->Driver.ReadColorSpan)( ctx, width, xpos, ypos,
  192.                          red, green, blue, alpha);
  193.            acc = ctx->Buffer->Accum
  194.              + (ypos * ctx->Buffer->Width + xpos) * 4;
  195.            for (i=0;i<width;i++) {
  196.           *acc += (GLaccum) ( (GLfloat) red[i]   * rscale );  acc++;
  197.           *acc += (GLaccum) ( (GLfloat) green[i] * gscale );  acc++;
  198.           *acc += (GLaccum) ( (GLfloat) blue[i]  * bscale );  acc++;
  199.           *acc += (GLaccum) ( (GLfloat) alpha[i] * ascale );  acc++;
  200.            }
  201.            ypos++;
  202.         }
  203.  
  204.         (void) (*ctx->Driver.SetBuffer)( ctx, ctx->Color.DrawBuffer );
  205.      }
  206.      break;
  207.       case GL_LOAD:
  208.      {
  209.         GLaccum *acc;
  210.         GLubyte red[MAX_WIDTH], green[MAX_WIDTH];
  211.         GLubyte blue[MAX_WIDTH], alpha[MAX_WIDTH];
  212.         GLfloat rscale, gscale, bscale, ascale;
  213.         GLuint i, j;
  214.  
  215.         (void) (*ctx->Driver.SetBuffer)( ctx, ctx->Pixel.ReadBuffer );
  216.  
  217.         /* Load accumulation buffer */
  218.         rscale = value * acc_scale * ctx->Visual->InvRedScale;
  219.         gscale = value * acc_scale * ctx->Visual->InvGreenScale;
  220.         bscale = value * acc_scale * ctx->Visual->InvBlueScale;
  221.         ascale = value * acc_scale * ctx->Visual->InvAlphaScale;
  222.         for (j=0;j<height;j++) {
  223.            (*ctx->Driver.ReadColorSpan)( ctx, width, xpos, ypos,
  224.                          red, green, blue, alpha);
  225.            acc = ctx->Buffer->Accum
  226.              + (ypos * ctx->Buffer->Width + xpos) * 4;
  227.            for (i=0;i<width;i++) {
  228.           *acc++ = (GLaccum) ( (GLfloat) red[i]   * rscale );
  229.           *acc++ = (GLaccum) ( (GLfloat) green[i] * gscale );
  230.           *acc++ = (GLaccum) ( (GLfloat) blue[i]  * bscale );
  231.           *acc++ = (GLaccum) ( (GLfloat) alpha[i] * ascale );
  232.            }
  233.            ypos++;
  234.         }
  235.  
  236.         (void) (*ctx->Driver.SetBuffer)( ctx, ctx->Color.DrawBuffer );
  237.      }
  238.      break;
  239.       case GL_RETURN:
  240.      {
  241.         GLubyte red[MAX_WIDTH], green[MAX_WIDTH];
  242.         GLubyte blue[MAX_WIDTH], alpha[MAX_WIDTH];
  243.         GLaccum *acc;
  244.         GLfloat rscale, gscale, bscale, ascale;
  245.         GLint rmax, gmax, bmax, amax;
  246.         GLuint i, j;
  247.  
  248.         rscale = value / acc_scale * ctx->Visual->RedScale;
  249.         gscale = value / acc_scale * ctx->Visual->GreenScale;
  250.         bscale = value / acc_scale * ctx->Visual->BlueScale;
  251.         ascale = value / acc_scale * ctx->Visual->AlphaScale;
  252.         rmax = (GLint) ctx->Visual->RedScale;
  253.         gmax = (GLint) ctx->Visual->GreenScale;
  254.         bmax = (GLint) ctx->Visual->BlueScale;
  255.         amax = (GLint) ctx->Visual->AlphaScale;
  256.  
  257.         for (j=0;j<height;j++) {
  258.            acc = ctx->Buffer->Accum
  259.              + (ypos * ctx->Buffer->Width + xpos) * 4;
  260.            for (i=0;i<width;i++) {
  261.           GLint r, g, b, a;
  262.           r = (GLint) ( (GLfloat) (*acc++) * rscale + 0.5F );
  263.           g = (GLint) ( (GLfloat) (*acc++) * gscale + 0.5F );
  264.           b = (GLint) ( (GLfloat) (*acc++) * bscale + 0.5F );
  265.           a = (GLint) ( (GLfloat) (*acc++) * ascale + 0.5F );
  266.           red[i]   = CLAMP( r, 0, rmax );
  267.           green[i] = CLAMP( g, 0, gmax );
  268.           blue[i]  = CLAMP( b, 0, bmax );
  269.           alpha[i] = CLAMP( a, 0, amax );
  270.            }
  271.            (*ctx->Driver.WriteColorSpan)( ctx, width, xpos, ypos,
  272.                           red, green, blue, alpha, NULL );
  273.            ypos++;
  274.         }
  275.      }
  276.      break;
  277.       default:
  278.      gl_error( ctx, GL_INVALID_ENUM, "glAccum" );
  279.    }
  280. }
  281.  
  282.  
  283.  
  284.  
  285. /*
  286.  * Clear the accumulation Buffer->
  287.  */
  288. void gl_clear_accum_buffer( GLcontext *ctx )
  289. {
  290.    GLuint buffersize;
  291.    GLfloat acc_scale;
  292.  
  293.    if (ctx->Visual->AccumBits==0) {
  294.       /* No accumulation buffer! */
  295.       return;
  296.    }
  297.  
  298.    if (sizeof(GLaccum)==1) {
  299.       acc_scale = 127.0;
  300.    }
  301.    else if (sizeof(GLaccum)==2) {
  302.       acc_scale = 32767.0;
  303.    }
  304.    else {
  305.       /* sizeof(GLaccum) > 2 (Cray) */
  306.       acc_scale = (float) SHRT_MAX;
  307.    }
  308.  
  309.    /* number of pixels */
  310.    buffersize = ctx->Buffer->Width * ctx->Buffer->Height;
  311.  
  312.    if (!ctx->Buffer->Accum) {
  313.       /* try to alloc accumulation buffer */
  314.       ctx->Buffer->Accum = (GLaccum *)
  315.                malloc( buffersize * 4 * sizeof(GLaccum) );
  316.    }
  317.  
  318.    if (ctx->Buffer->Accum) {
  319.       if (ctx->Scissor.Enabled) {
  320.      /* Limit clear to scissor box */
  321.      GLaccum r, g, b, a;
  322.      GLint i, j;
  323.      GLint width, height;
  324.      GLaccum *row;
  325.      r = (GLaccum) (ctx->Accum.ClearColor[0] * acc_scale);
  326.      g = (GLaccum) (ctx->Accum.ClearColor[1] * acc_scale);
  327.      b = (GLaccum) (ctx->Accum.ClearColor[2] * acc_scale);
  328.      a = (GLaccum) (ctx->Accum.ClearColor[3] * acc_scale);
  329.      /* size of region to clear */
  330.      width = 4 * (ctx->Buffer->Xmax - ctx->Buffer->Xmin + 1);
  331.      height = ctx->Buffer->Ymax - ctx->Buffer->Ymin + 1;
  332.      /* ptr to first element to clear */
  333.      row = ctx->Buffer->Accum
  334.            + 4 * (ctx->Buffer->Ymin * ctx->Buffer->Width
  335.               + ctx->Buffer->Xmin);
  336.      for (j=0;j<height;j++) {
  337.         for (i=0;i<width;i+=4) {
  338.            row[i+0] = r;
  339.            row[i+1] = g;
  340.            row[i+2] = b;
  341.            row[i+3] = a;
  342.         }
  343.         row += 4 * ctx->Buffer->Width;
  344.      }
  345.       }
  346.       else {
  347.      /* clear whole buffer */
  348.      if (ctx->Accum.ClearColor[0]==0.0 &&
  349.          ctx->Accum.ClearColor[1]==0.0 &&
  350.          ctx->Accum.ClearColor[2]==0.0 &&
  351.          ctx->Accum.ClearColor[3]==0.0) {
  352.         /* Black */
  353.         MEMSET( ctx->Buffer->Accum, 0, buffersize * 4 * sizeof(GLaccum) );
  354.      }
  355.      else {
  356.         /* Not black */
  357.         GLaccum *acc, r, g, b, a;
  358.         GLuint i;
  359.  
  360.         acc = ctx->Buffer->Accum;
  361.         r = (GLaccum) (ctx->Accum.ClearColor[0] * acc_scale);
  362.         g = (GLaccum) (ctx->Accum.ClearColor[1] * acc_scale);
  363.         b = (GLaccum) (ctx->Accum.ClearColor[2] * acc_scale);
  364.         a = (GLaccum) (ctx->Accum.ClearColor[3] * acc_scale);
  365.         for (i=0;i<buffersize;i++) {
  366.            *acc++ = r;
  367.            *acc++ = g;
  368.            *acc++ = b;
  369.            *acc++ = a;
  370.         }
  371.      }
  372.       }
  373.    }
  374. }
  375.