xref: /reactos/dll/opengl/mesa/accum.c (revision 5f2bebf7)
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 <string.h>
51 #include "accum.h"
52 #include "context.h"
53 #include "dlist.h"
54 #include "macros.h"
55 #include "types.h"
56 #endif
57 
58 
gl_alloc_accum_buffer(GLcontext * ctx)59 void gl_alloc_accum_buffer( GLcontext *ctx )
60 {
61    GLint n;
62 
63    if (ctx->Buffer->Accum) {
64       free( ctx->Buffer->Accum );
65       ctx->Buffer->Accum = NULL;
66    }
67 
68    /* allocate accumulation buffer if not already present */
69    n = ctx->Buffer->Width * ctx->Buffer->Height * 4 * sizeof(GLaccum);
70    ctx->Buffer->Accum = (GLaccum *) malloc( n );
71    if (!ctx->Buffer->Accum) {
72       /* unable to setup accumulation buffer */
73       gl_error( ctx, GL_OUT_OF_MEMORY, "glAccum" );
74    }
75 }
76 
77 
78 
gl_ClearAccum(GLcontext * ctx,GLfloat red,GLfloat green,GLfloat blue,GLfloat alpha)79 void gl_ClearAccum( GLcontext *ctx,
80                     GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha )
81 {
82    if (INSIDE_BEGIN_END(ctx)) {
83       gl_error( ctx, GL_INVALID_OPERATION, "glAccum" );
84       return;
85    }
86    ctx->Accum.ClearColor[0] = CLAMP( red, -1.0, 1.0 );
87    ctx->Accum.ClearColor[1] = CLAMP( green, -1.0, 1.0 );
88    ctx->Accum.ClearColor[2] = CLAMP( blue, -1.0, 1.0 );
89    ctx->Accum.ClearColor[3] = CLAMP( alpha, -1.0, 1.0 );
90 }
91 
92 
93 
94 
gl_Accum(GLcontext * ctx,GLenum op,GLfloat value)95 void gl_Accum( GLcontext *ctx, GLenum op, GLfloat value )
96 {
97    GLuint xpos, ypos, width, height;
98    GLfloat acc_scale;
99 
100    if (INSIDE_BEGIN_END(ctx)) {
101       gl_error( ctx, GL_INVALID_OPERATION, "glAccum" );
102       return;
103    }
104 
105    if (ctx->Visual->AccumBits==0 || !ctx->Buffer->Accum) {
106       /* No accumulation buffer! */
107       gl_warning(ctx, "Calling glAccum() without an accumulation buffer");
108       return;
109    }
110 
111    if (sizeof(GLaccum)==1) {
112       acc_scale = 127.0;
113    }
114    else if (sizeof(GLaccum)==2) {
115       acc_scale = 32767.0;
116    }
117    else {
118       /* sizeof(GLaccum) > 2 (Cray) */
119       acc_scale = (float) SHRT_MAX;
120    }
121 
122    /* Determine region to operate upon. */
123    if (ctx->Scissor.Enabled) {
124       xpos = ctx->Scissor.X;
125       ypos = ctx->Scissor.Y;
126       width = ctx->Scissor.Width;
127       height = ctx->Scissor.Height;
128    }
129    else {
130       /* whole window */
131       xpos = 0;
132       ypos = 0;
133       width = ctx->Buffer->Width;
134       height = ctx->Buffer->Height;
135    }
136 
137    switch (op) {
138       case GL_ADD:
139          {
140 	    GLaccum ival, *acc;
141 	    GLuint i, j;
142 
143 	    ival = (GLaccum) (value * acc_scale);
144 	    for (j=0;j<height;j++) {
145 	       acc = ctx->Buffer->Accum
146                      + (ypos * ctx->Buffer->Width + xpos) * 4;
147 	       for (i=0;i<width;i++) {
148 		  *acc += ival;	  acc++;   /* red */
149 		  *acc += ival;	  acc++;   /* green */
150 		  *acc += ival;	  acc++;   /* blue */
151 		  *acc += ival;	  acc++;   /* alpha */
152 	       }
153 	       ypos++;
154 	    }
155 	 }
156 	 break;
157       case GL_MULT:
158 	 {
159 	    GLaccum *acc;
160 	    GLuint i, j;
161 
162 	    for (j=0;j<height;j++) {
163 	       acc = ctx->Buffer->Accum
164                      + (ypos * ctx->Buffer->Width + xpos) * 4;
165 	       for (i=0;i<width;i++) {
166 		  *acc = (GLaccum) ( (GLfloat) *acc * value );	  acc++; /*r*/
167 		  *acc = (GLaccum) ( (GLfloat) *acc * value );	  acc++; /*g*/
168 		  *acc = (GLaccum) ( (GLfloat) *acc * value );	  acc++; /*g*/
169 		  *acc = (GLaccum) ( (GLfloat) *acc * value );	  acc++; /*a*/
170 	       }
171 	       ypos++;
172 	    }
173 	 }
174 	 break;
175       case GL_ACCUM:
176 	 {
177 	    GLaccum *acc;
178 	    GLubyte red[MAX_WIDTH], green[MAX_WIDTH];
179 	    GLubyte blue[MAX_WIDTH], alpha[MAX_WIDTH];
180 	    GLfloat rscale, gscale, bscale, ascale;
181 	    GLuint i, j;
182 
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 	    for (j=0;j<height;j++) {
257 	       acc = ctx->Buffer->Accum
258                      + (ypos * ctx->Buffer->Width + xpos) * 4;
259 	       for (i=0;i<width;i++) {
260 		  GLint r, g, b, a;
261 		  r = (GLint) ( (GLfloat) (*acc++) * rscale + 0.5F );
262 		  g = (GLint) ( (GLfloat) (*acc++) * gscale + 0.5F );
263 		  b = (GLint) ( (GLfloat) (*acc++) * bscale + 0.5F );
264 		  a = (GLint) ( (GLfloat) (*acc++) * ascale + 0.5F );
265 		  red[i]   = CLAMP( r, 0, rmax );
266 		  green[i] = CLAMP( g, 0, gmax );
267 		  blue[i]  = CLAMP( b, 0, bmax );
268 		  alpha[i] = CLAMP( a, 0, amax );
269 	       }
270 	       (*ctx->Driver.WriteColorSpan)( ctx, width, xpos, ypos,
271                                               red, green, blue, alpha, NULL );
272 	       ypos++;
273 	    }
274 	 }
275 	 break;
276       default:
277          gl_error( ctx, GL_INVALID_ENUM, "glAccum" );
278    }
279 }
280 
281 
282 
283 
284 /*
285  * Clear the accumulation Buffer->
286  */
gl_clear_accum_buffer(GLcontext * ctx)287 void gl_clear_accum_buffer( GLcontext *ctx )
288 {
289    GLuint buffersize;
290    GLfloat acc_scale;
291 
292    if (ctx->Visual->AccumBits==0) {
293       /* No accumulation buffer! */
294       return;
295    }
296 
297    if (sizeof(GLaccum)==1) {
298       acc_scale = 127.0;
299    }
300    else if (sizeof(GLaccum)==2) {
301       acc_scale = 32767.0;
302    }
303    else {
304       /* sizeof(GLaccum) > 2 (Cray) */
305       acc_scale = (float) SHRT_MAX;
306    }
307 
308    /* number of pixels */
309    buffersize = ctx->Buffer->Width * ctx->Buffer->Height;
310 
311    if (!ctx->Buffer->Accum) {
312       /* try to alloc accumulation buffer */
313       ctx->Buffer->Accum = (GLaccum *)
314 	                   malloc( buffersize * 4 * sizeof(GLaccum) );
315    }
316 
317    if (ctx->Buffer->Accum) {
318       if (ctx->Scissor.Enabled) {
319 	 /* Limit clear to scissor box */
320 	 GLaccum r, g, b, a;
321 	 GLint i, j;
322          GLint width, height;
323          GLaccum *row;
324 	 r = (GLaccum) (ctx->Accum.ClearColor[0] * acc_scale);
325 	 g = (GLaccum) (ctx->Accum.ClearColor[1] * acc_scale);
326 	 b = (GLaccum) (ctx->Accum.ClearColor[2] * acc_scale);
327 	 a = (GLaccum) (ctx->Accum.ClearColor[3] * acc_scale);
328          /* size of region to clear */
329          width = 4 * (ctx->Buffer->Xmax - ctx->Buffer->Xmin + 1);
330          height = ctx->Buffer->Ymax - ctx->Buffer->Ymin + 1;
331          /* ptr to first element to clear */
332          row = ctx->Buffer->Accum
333                + 4 * (ctx->Buffer->Ymin * ctx->Buffer->Width
334                       + ctx->Buffer->Xmin);
335          for (j=0;j<height;j++) {
336             for (i=0;i<width;i+=4) {
337                row[i+0] = r;
338                row[i+1] = g;
339                row[i+2] = b;
340                row[i+3] = a;
341 	    }
342             row += 4 * ctx->Buffer->Width;
343 	 }
344       }
345       else {
346 	 /* clear whole buffer */
347 	 if (ctx->Accum.ClearColor[0]==0.0 &&
348 	     ctx->Accum.ClearColor[1]==0.0 &&
349 	     ctx->Accum.ClearColor[2]==0.0 &&
350 	     ctx->Accum.ClearColor[3]==0.0) {
351 	    /* Black */
352 	    MEMSET( ctx->Buffer->Accum, 0, buffersize * 4 * sizeof(GLaccum) );
353 	 }
354 	 else {
355 	    /* Not black */
356 	    GLaccum *acc, r, g, b, a;
357 	    GLuint i;
358 
359 	    acc = ctx->Buffer->Accum;
360 	    r = (GLaccum) (ctx->Accum.ClearColor[0] * acc_scale);
361 	    g = (GLaccum) (ctx->Accum.ClearColor[1] * acc_scale);
362 	    b = (GLaccum) (ctx->Accum.ClearColor[2] * acc_scale);
363 	    a = (GLaccum) (ctx->Accum.ClearColor[3] * acc_scale);
364 	    for (i=0;i<buffersize;i++) {
365 	       *acc++ = r;
366 	       *acc++ = g;
367 	       *acc++ = b;
368 	       *acc++ = a;
369 	    }
370 	 }
371       }
372    }
373 }
374