~ubuntu-branches/ubuntu/quantal/mesa-glw/quantal

« back to all changes in this revision

Viewing changes to src/mesa/swrast/s_accum.c

  • Committer: Bazaar Package Importer
  • Author(s): Morten Kjeldgaard
  • Date: 2008-05-06 16:19:15 UTC
  • Revision ID: james.westby@ubuntu.com-20080506161915-uynz7nftmfixu6bq
Tags: upstream-7.0.3
ImportĀ upstreamĀ versionĀ 7.0.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Mesa 3-D graphics library
 
3
 * Version:  6.5.2
 
4
 *
 
5
 * Copyright (C) 1999-2006  Brian Paul   All Rights Reserved.
 
6
 *
 
7
 * Permission is hereby granted, free of charge, to any person obtaining a
 
8
 * copy of this software and associated documentation files (the "Software"),
 
9
 * to deal in the Software without restriction, including without limitation
 
10
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 
11
 * and/or sell copies of the Software, and to permit persons to whom the
 
12
 * Software is furnished to do so, subject to the following conditions:
 
13
 *
 
14
 * The above copyright notice and this permission notice shall be included
 
15
 * in all copies or substantial portions of the Software.
 
16
 *
 
17
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 
18
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
19
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 
20
 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 
21
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 
22
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
23
 */
 
24
 
 
25
 
 
26
#include "glheader.h"
 
27
#include "context.h"
 
28
#include "macros.h"
 
29
#include "imports.h"
 
30
#include "fbobject.h"
 
31
 
 
32
#include "s_accum.h"
 
33
#include "s_context.h"
 
34
#include "s_masking.h"
 
35
#include "s_span.h"
 
36
 
 
37
 
 
38
/* XXX this would have to change for accum buffers with more or less
 
39
 * than 16 bits per color channel.
 
40
 */
 
41
#define ACCUM_SCALE16 32767.0
 
42
 
 
43
 
 
44
/*
 
45
 * Accumulation buffer notes
 
46
 *
 
47
 * Normally, accumulation buffer values are GLshorts with values in
 
48
 * [-32767, 32767] which represent floating point colors in [-1, 1],
 
49
 * as defined by the OpenGL specification.
 
50
 *
 
51
 * We optimize for the common case used for full-scene antialiasing:
 
52
 *    // start with accum buffer cleared to zero
 
53
 *    glAccum(GL_LOAD, w);   // or GL_ACCUM the first image
 
54
 *    glAccum(GL_ACCUM, w);
 
55
 *    ...
 
56
 *    glAccum(GL_ACCUM, w);
 
57
 *    glAccum(GL_RETURN, 1.0);
 
58
 * That is, we start with an empty accumulation buffer and accumulate
 
59
 * n images, each with weight w = 1/n.
 
60
 * In this scenario, we can simply store unscaled integer values in
 
61
 * the accum buffer instead of scaled integers.  We'll also keep track
 
62
 * of the w value so when we do GL_RETURN we simply divide the accumulated
 
63
 * values by n (n=1/w).
 
64
 * This lets us avoid _many_ int->float->int conversions.
 
65
 */
 
66
 
 
67
 
 
68
#if CHAN_BITS == 8
 
69
/* enable the optimization */
 
70
#define USE_OPTIMIZED_ACCUM  1
 
71
#else
 
72
#define USE_OPTIMIZED_ACCUM  0
 
73
#endif
 
74
 
 
75
 
 
76
/**
 
77
 * This is called when we fall out of optimized/unscaled accum buffer mode.
 
78
 * That is, we convert each unscaled accum buffer value into a scaled value
 
79
 * representing the range[-1, 1].
 
80
 */
 
81
static void
 
82
rescale_accum( GLcontext *ctx )
 
83
{
 
84
   SWcontext *swrast = SWRAST_CONTEXT(ctx);
 
85
   struct gl_renderbuffer *rb
 
86
      = ctx->DrawBuffer->Attachment[BUFFER_ACCUM].Renderbuffer;
 
87
   const GLfloat s = swrast->_IntegerAccumScaler * (32767.0F / CHAN_MAXF);
 
88
 
 
89
   assert(rb);
 
90
   assert(rb->_BaseFormat == GL_RGBA);
 
91
   /* add other types in future? */
 
92
   assert(rb->DataType == GL_SHORT || rb->DataType == GL_UNSIGNED_SHORT);
 
93
   assert(swrast->_IntegerAccumMode);
 
94
 
 
95
   if (rb->GetPointer(ctx, rb, 0, 0)) {
 
96
      /* directly-addressable memory */
 
97
      GLuint y;
 
98
      for (y = 0; y < rb->Height; y++) {
 
99
         GLuint i;
 
100
         GLshort *acc = (GLshort *) rb->GetPointer(ctx, rb, 0, y);
 
101
         for (i = 0; i < 4 * rb->Width; i++) {
 
102
            acc[i] = (GLshort) (acc[i] * s);
 
103
         }
 
104
      }
 
105
   }
 
106
   else {
 
107
      /* use get/put row funcs */
 
108
      GLuint y;
 
109
      for (y = 0; y < rb->Height; y++) {
 
110
         GLshort accRow[MAX_WIDTH * 4];
 
111
         GLuint i;
 
112
         rb->GetRow(ctx, rb, rb->Width, 0, y, accRow);
 
113
         for (i = 0; i < 4 * rb->Width; i++) {
 
114
            accRow[i] = (GLshort) (accRow[i] * s);
 
115
         }
 
116
         rb->PutRow(ctx, rb, rb->Width, 0, y, accRow, NULL);
 
117
      }
 
118
   }
 
119
 
 
120
   swrast->_IntegerAccumMode = GL_FALSE;
 
121
}
 
122
 
 
123
 
 
124
 
 
125
/**
 
126
 * Clear the accumulation Buffer.
 
127
 */
 
128
void
 
129
_swrast_clear_accum_buffer( GLcontext *ctx, struct gl_renderbuffer *rb )
 
130
{
 
131
   SWcontext *swrast = SWRAST_CONTEXT(ctx);
 
132
   GLuint x, y, width, height;
 
133
 
 
134
   if (ctx->Visual.accumRedBits == 0) {
 
135
      /* No accumulation buffer! Not an error. */
 
136
      return;
 
137
   }
 
138
 
 
139
   if (!rb || !rb->Data)
 
140
      return;
 
141
 
 
142
   assert(rb->_BaseFormat == GL_RGBA);
 
143
   /* add other types in future? */
 
144
   assert(rb->DataType == GL_SHORT || rb->DataType == GL_UNSIGNED_SHORT);
 
145
 
 
146
   /* bounds, with scissor */
 
147
   x = ctx->DrawBuffer->_Xmin;
 
148
   y = ctx->DrawBuffer->_Ymin;
 
149
   width = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
 
150
   height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
 
151
 
 
152
   if (rb->DataType == GL_SHORT || rb->DataType == GL_UNSIGNED_SHORT) {
 
153
      const GLfloat accScale = 32767.0;
 
154
      GLshort clearVal[4];
 
155
      GLuint i;
 
156
 
 
157
      clearVal[0] = (GLshort) (ctx->Accum.ClearColor[0] * accScale);
 
158
      clearVal[1] = (GLshort) (ctx->Accum.ClearColor[1] * accScale);
 
159
      clearVal[2] = (GLshort) (ctx->Accum.ClearColor[2] * accScale);
 
160
      clearVal[3] = (GLshort) (ctx->Accum.ClearColor[3] * accScale);
 
161
 
 
162
      for (i = 0; i < height; i++) {
 
163
         rb->PutMonoRow(ctx, rb, width, x, y + i, clearVal, NULL);
 
164
      }
 
165
   }
 
166
   else {
 
167
      /* someday support other sizes */
 
168
   }
 
169
 
 
170
   /* update optimized accum state vars */
 
171
   if (ctx->Accum.ClearColor[0] == 0.0 && ctx->Accum.ClearColor[1] == 0.0 &&
 
172
       ctx->Accum.ClearColor[2] == 0.0 && ctx->Accum.ClearColor[3] == 0.0) {
 
173
#if USE_OPTIMIZED_ACCUM
 
174
      swrast->_IntegerAccumMode = GL_TRUE;
 
175
#else
 
176
      swrast->_IntegerAccumMode = GL_FALSE;
 
177
#endif
 
178
      swrast->_IntegerAccumScaler = 0.0;  /* denotes empty accum buffer */
 
179
   }
 
180
   else {
 
181
      swrast->_IntegerAccumMode = GL_FALSE;
 
182
   }
 
183
}
 
184
 
 
185
 
 
186
static void
 
187
accum_add(GLcontext *ctx, GLfloat value,
 
188
          GLint xpos, GLint ypos, GLint width, GLint height )
 
189
{
 
190
   SWcontext *swrast = SWRAST_CONTEXT(ctx);
 
191
   struct gl_renderbuffer *rb
 
192
      = ctx->DrawBuffer->Attachment[BUFFER_ACCUM].Renderbuffer;
 
193
 
 
194
   assert(rb);
 
195
 
 
196
   /* Leave optimized accum buffer mode */
 
197
   if (swrast->_IntegerAccumMode)
 
198
      rescale_accum(ctx);
 
199
 
 
200
   if (rb->DataType == GL_SHORT || rb->DataType == GL_UNSIGNED_SHORT) {
 
201
      const GLshort incr = (GLshort) (value * ACCUM_SCALE16);
 
202
      if (rb->GetPointer(ctx, rb, 0, 0)) {
 
203
         GLint i, j;
 
204
         for (i = 0; i < height; i++) {
 
205
            GLshort *acc = (GLshort *) rb->GetPointer(ctx, rb, xpos, ypos + i);
 
206
            for (j = 0; j < 4 * width; j++) {
 
207
               acc[j] += incr;
 
208
            }
 
209
         }
 
210
      }
 
211
      else {
 
212
         GLint i, j;
 
213
         for (i = 0; i < height; i++) {
 
214
            GLshort accRow[4 * MAX_WIDTH];
 
215
            rb->GetRow(ctx, rb, width, xpos, ypos + i, accRow);
 
216
            for (j = 0; j < 4 * width; j++) {
 
217
               accRow[j] += incr;
 
218
            }
 
219
            rb->PutRow(ctx, rb, width, xpos, ypos + i, accRow, NULL);
 
220
         }
 
221
      }
 
222
   }
 
223
   else {
 
224
      /* other types someday */
 
225
   }
 
226
}
 
227
 
 
228
 
 
229
static void
 
230
accum_mult(GLcontext *ctx, GLfloat mult,
 
231
           GLint xpos, GLint ypos, GLint width, GLint height )
 
232
{
 
233
   SWcontext *swrast = SWRAST_CONTEXT(ctx);
 
234
   struct gl_renderbuffer *rb
 
235
      = ctx->DrawBuffer->Attachment[BUFFER_ACCUM].Renderbuffer;
 
236
 
 
237
   assert(rb);
 
238
 
 
239
   /* Leave optimized accum buffer mode */
 
240
   if (swrast->_IntegerAccumMode)
 
241
      rescale_accum(ctx);
 
242
 
 
243
   if (rb->DataType == GL_SHORT || rb->DataType == GL_UNSIGNED_SHORT) {
 
244
      if (rb->GetPointer(ctx, rb, 0, 0)) {
 
245
         GLint i, j;
 
246
         for (i = 0; i < height; i++) {
 
247
            GLshort *acc = (GLshort *) rb->GetPointer(ctx, rb, xpos, ypos + i);
 
248
            for (j = 0; j < 4 * width; j++) {
 
249
               acc[j] = (GLshort) (acc[j] * mult);
 
250
            }
 
251
         }
 
252
      }
 
253
      else {
 
254
         GLint i, j;
 
255
         for (i = 0; i < height; i++) {
 
256
            GLshort accRow[4 * MAX_WIDTH];
 
257
            rb->GetRow(ctx, rb, width, xpos, ypos + i, accRow);
 
258
            for (j = 0; j < 4 * width; j++) {
 
259
               accRow[j] = (GLshort) (accRow[j] * mult);
 
260
            }
 
261
            rb->PutRow(ctx, rb, width, xpos, ypos + i, accRow, NULL);
 
262
         }
 
263
      }
 
264
   }
 
265
   else {
 
266
      /* other types someday */
 
267
   }
 
268
}
 
269
 
 
270
 
 
271
 
 
272
static void
 
273
accum_accum(GLcontext *ctx, GLfloat value,
 
274
            GLint xpos, GLint ypos, GLint width, GLint height )
 
275
{
 
276
   SWcontext *swrast = SWRAST_CONTEXT(ctx);
 
277
   struct gl_renderbuffer *rb
 
278
      = ctx->DrawBuffer->Attachment[BUFFER_ACCUM].Renderbuffer;
 
279
   const GLboolean directAccess = (rb->GetPointer(ctx, rb, 0, 0) != NULL);
 
280
 
 
281
   assert(rb);
 
282
 
 
283
   if (!ctx->ReadBuffer->_ColorReadBuffer) {
 
284
      /* no read buffer - OK */
 
285
      return;
 
286
   }
 
287
 
 
288
   /* May have to leave optimized accum buffer mode */
 
289
   if (swrast->_IntegerAccumScaler == 0.0 && value > 0.0 && value <= 1.0)
 
290
      swrast->_IntegerAccumScaler = value;
 
291
   if (swrast->_IntegerAccumMode && value != swrast->_IntegerAccumScaler)
 
292
      rescale_accum(ctx);
 
293
 
 
294
   if (rb->DataType == GL_SHORT || rb->DataType == GL_UNSIGNED_SHORT) {
 
295
      const GLfloat scale = value * ACCUM_SCALE16 / CHAN_MAXF;
 
296
      GLshort accumRow[4 * MAX_WIDTH];
 
297
      GLchan rgba[MAX_WIDTH][4];
 
298
      GLint i;
 
299
 
 
300
      for (i = 0; i < height; i++) {
 
301
         GLshort *acc;
 
302
         if (directAccess) {
 
303
            acc = (GLshort *) rb->GetPointer(ctx, rb, xpos, ypos + i);
 
304
         }
 
305
         else {
 
306
            rb->GetRow(ctx, rb, width, xpos, ypos + i, accumRow);
 
307
            acc = accumRow;
 
308
         }
 
309
 
 
310
         /* read colors from color buffer */
 
311
         _swrast_read_rgba_span(ctx, ctx->ReadBuffer->_ColorReadBuffer, width,
 
312
                                xpos, ypos + i, CHAN_TYPE, rgba);
 
313
 
 
314
         /* do accumulation */
 
315
         if (swrast->_IntegerAccumMode) {
 
316
            /* simply add integer color values into accum buffer */
 
317
            GLint j;
 
318
            for (j = 0; j < width; j++) {
 
319
               acc[j * 4 + 0] += rgba[j][RCOMP];
 
320
               acc[j * 4 + 1] += rgba[j][GCOMP];
 
321
               acc[j * 4 + 2] += rgba[j][BCOMP];
 
322
               acc[j * 4 + 3] += rgba[j][ACOMP];
 
323
            }
 
324
         }
 
325
         else {
 
326
            /* scaled integer (or float) accum buffer */
 
327
            GLint j;
 
328
            for (j = 0; j < width; j++) {
 
329
               acc[j * 4 + 0] += (GLshort) ((GLfloat) rgba[j][RCOMP] * scale);
 
330
               acc[j * 4 + 1] += (GLshort) ((GLfloat) rgba[j][GCOMP] * scale);
 
331
               acc[j * 4 + 2] += (GLshort) ((GLfloat) rgba[j][BCOMP] * scale);
 
332
               acc[j * 4 + 3] += (GLshort) ((GLfloat) rgba[j][ACOMP] * scale);
 
333
            }
 
334
         }
 
335
 
 
336
         if (!directAccess) {
 
337
            rb->PutRow(ctx, rb, width, xpos, ypos + i, accumRow, NULL);
 
338
         }
 
339
      }
 
340
   }
 
341
   else {
 
342
      /* other types someday */
 
343
   }
 
344
}
 
345
 
 
346
 
 
347
 
 
348
static void
 
349
accum_load(GLcontext *ctx, GLfloat value,
 
350
           GLint xpos, GLint ypos, GLint width, GLint height )
 
351
{
 
352
   SWcontext *swrast = SWRAST_CONTEXT(ctx);
 
353
   struct gl_renderbuffer *rb
 
354
      = ctx->DrawBuffer->Attachment[BUFFER_ACCUM].Renderbuffer;
 
355
   const GLboolean directAccess = (rb->GetPointer(ctx, rb, 0, 0) != NULL);
 
356
 
 
357
   assert(rb);
 
358
 
 
359
   if (!ctx->ReadBuffer->_ColorReadBuffer) {
 
360
      /* no read buffer - OK */
 
361
      return;
 
362
   }
 
363
 
 
364
   /* This is a change to go into optimized accum buffer mode */
 
365
   if (value > 0.0 && value <= 1.0) {
 
366
#if USE_OPTIMIZED_ACCUM
 
367
      swrast->_IntegerAccumMode = GL_TRUE;
 
368
#else
 
369
      swrast->_IntegerAccumMode = GL_FALSE;
 
370
#endif
 
371
      swrast->_IntegerAccumScaler = value;
 
372
   }
 
373
   else {
 
374
      swrast->_IntegerAccumMode = GL_FALSE;
 
375
      swrast->_IntegerAccumScaler = 0.0;
 
376
   }
 
377
 
 
378
   if (rb->DataType == GL_SHORT || rb->DataType == GL_UNSIGNED_SHORT) {
 
379
      const GLfloat scale = value * ACCUM_SCALE16 / CHAN_MAXF;
 
380
      GLshort accumRow[4 * MAX_WIDTH];
 
381
      GLchan rgba[MAX_WIDTH][4];
 
382
      GLint i;
 
383
 
 
384
      for (i = 0; i < height; i++) {
 
385
         GLshort *acc;
 
386
         if (directAccess) {
 
387
            acc = (GLshort *) rb->GetPointer(ctx, rb, xpos, ypos + i);
 
388
         }
 
389
         else {
 
390
            rb->GetRow(ctx, rb, width, xpos, ypos + i, accumRow);
 
391
            acc = accumRow;
 
392
         }
 
393
 
 
394
         /* read colors from color buffer */
 
395
         _swrast_read_rgba_span(ctx, ctx->ReadBuffer->_ColorReadBuffer, width,
 
396
                                xpos, ypos + i, CHAN_TYPE, rgba);
 
397
 
 
398
         /* do load */
 
399
         if (swrast->_IntegerAccumMode) {
 
400
            /* just copy values in */
 
401
            GLint j;
 
402
            assert(swrast->_IntegerAccumScaler > 0.0);
 
403
            assert(swrast->_IntegerAccumScaler <= 1.0);
 
404
            for (j = 0; j < width; j++) {
 
405
               acc[j * 4 + 0] = rgba[j][RCOMP];
 
406
               acc[j * 4 + 1] = rgba[j][GCOMP];
 
407
               acc[j * 4 + 2] = rgba[j][BCOMP];
 
408
               acc[j * 4 + 3] = rgba[j][ACOMP];
 
409
            }
 
410
         }
 
411
         else {
 
412
            /* scaled integer (or float) accum buffer */
 
413
            GLint j;
 
414
            for (j = 0; j < width; j++) {
 
415
               acc[j * 4 + 0] = (GLshort) ((GLfloat) rgba[j][RCOMP] * scale);
 
416
               acc[j * 4 + 1] = (GLshort) ((GLfloat) rgba[j][GCOMP] * scale);
 
417
               acc[j * 4 + 2] = (GLshort) ((GLfloat) rgba[j][BCOMP] * scale);
 
418
               acc[j * 4 + 3] = (GLshort) ((GLfloat) rgba[j][ACOMP] * scale);
 
419
            }
 
420
         }
 
421
 
 
422
         if (!directAccess) {
 
423
            rb->PutRow(ctx, rb, width, xpos, ypos + i, accumRow, NULL);
 
424
         }
 
425
      }
 
426
   }
 
427
}
 
428
 
 
429
 
 
430
static void
 
431
accum_return(GLcontext *ctx, GLfloat value,
 
432
             GLint xpos, GLint ypos, GLint width, GLint height )
 
433
{
 
434
   SWcontext *swrast = SWRAST_CONTEXT(ctx);
 
435
   struct gl_framebuffer *fb = ctx->DrawBuffer;
 
436
   struct gl_renderbuffer *accumRb = fb->Attachment[BUFFER_ACCUM].Renderbuffer;
 
437
   const GLboolean directAccess
 
438
      = (accumRb->GetPointer(ctx, accumRb, 0, 0) != NULL);
 
439
   const GLboolean masking = (!ctx->Color.ColorMask[RCOMP] ||
 
440
                              !ctx->Color.ColorMask[GCOMP] ||
 
441
                              !ctx->Color.ColorMask[BCOMP] ||
 
442
                              !ctx->Color.ColorMask[ACOMP]);
 
443
 
 
444
   static GLchan multTable[32768];
 
445
   static GLfloat prevMult = 0.0;
 
446
   const GLfloat mult = swrast->_IntegerAccumScaler;
 
447
   const GLint max = MIN2((GLint) (256 / mult), 32767);
 
448
 
 
449
   /* May have to leave optimized accum buffer mode */
 
450
   if (swrast->_IntegerAccumMode && value != 1.0)
 
451
      rescale_accum(ctx);
 
452
 
 
453
   if (swrast->_IntegerAccumMode && swrast->_IntegerAccumScaler > 0) {
 
454
      /* build lookup table to avoid many floating point multiplies */
 
455
      GLint j;
 
456
      assert(swrast->_IntegerAccumScaler <= 1.0);
 
457
      if (mult != prevMult) {
 
458
         for (j = 0; j < max; j++)
 
459
            multTable[j] = IROUND((GLfloat) j * mult);
 
460
         prevMult = mult;
 
461
      }
 
462
   }
 
463
 
 
464
   if (accumRb->DataType == GL_SHORT ||
 
465
       accumRb->DataType == GL_UNSIGNED_SHORT) {
 
466
      const GLfloat scale = value * CHAN_MAXF / ACCUM_SCALE16;
 
467
      GLuint buffer;
 
468
      GLint i;
 
469
 
 
470
      /* XXX maybe transpose the 'i' and 'buffer' loops??? */
 
471
      for (i = 0; i < height; i++) {
 
472
         GLshort accumRow[4 * MAX_WIDTH];
 
473
         GLshort *acc;
 
474
         SWspan span;
 
475
 
 
476
         /* init color span */
 
477
         INIT_SPAN(span, GL_BITMAP, width, 0, SPAN_RGBA);
 
478
         span.x = xpos;
 
479
         span.y = ypos + i;
 
480
 
 
481
         if (directAccess) {
 
482
            acc = (GLshort *) accumRb->GetPointer(ctx, accumRb, xpos, ypos +i);
 
483
         }
 
484
         else {
 
485
            accumRb->GetRow(ctx, accumRb, width, xpos, ypos + i, accumRow);
 
486
            acc = accumRow;
 
487
         }
 
488
 
 
489
         /* get the colors to return */
 
490
         if (swrast->_IntegerAccumMode) {
 
491
            GLint j;
 
492
            for (j = 0; j < width; j++) {
 
493
               ASSERT(acc[j * 4 + 0] < max);
 
494
               ASSERT(acc[j * 4 + 1] < max);
 
495
               ASSERT(acc[j * 4 + 2] < max);
 
496
               ASSERT(acc[j * 4 + 3] < max);
 
497
               span.array->rgba[j][RCOMP] = multTable[acc[j * 4 + 0]];
 
498
               span.array->rgba[j][GCOMP] = multTable[acc[j * 4 + 1]];
 
499
               span.array->rgba[j][BCOMP] = multTable[acc[j * 4 + 2]];
 
500
               span.array->rgba[j][ACOMP] = multTable[acc[j * 4 + 3]];
 
501
            }
 
502
         }
 
503
         else {
 
504
            /* scaled integer (or float) accum buffer */
 
505
            GLint j;
 
506
            for (j = 0; j < width; j++) {
 
507
#if CHAN_BITS==32
 
508
               GLchan r = acc[j * 4 + 0] * scale;
 
509
               GLchan g = acc[j * 4 + 1] * scale;
 
510
               GLchan b = acc[j * 4 + 2] * scale;
 
511
               GLchan a = acc[j * 4 + 3] * scale;
 
512
#else
 
513
               GLint r = IROUND( (GLfloat) (acc[j * 4 + 0]) * scale );
 
514
               GLint g = IROUND( (GLfloat) (acc[j * 4 + 1]) * scale );
 
515
               GLint b = IROUND( (GLfloat) (acc[j * 4 + 2]) * scale );
 
516
               GLint a = IROUND( (GLfloat) (acc[j * 4 + 3]) * scale );
 
517
#endif
 
518
               span.array->rgba[j][RCOMP] = CLAMP( r, 0, CHAN_MAX );
 
519
               span.array->rgba[j][GCOMP] = CLAMP( g, 0, CHAN_MAX );
 
520
               span.array->rgba[j][BCOMP] = CLAMP( b, 0, CHAN_MAX );
 
521
               span.array->rgba[j][ACOMP] = CLAMP( a, 0, CHAN_MAX );
 
522
            }
 
523
         }
 
524
 
 
525
         /* store colors */
 
526
         for (buffer = 0; buffer < fb->_NumColorDrawBuffers[0]; buffer++) {
 
527
            struct gl_renderbuffer *rb = fb->_ColorDrawBuffers[0][buffer];
 
528
            if (masking) {
 
529
               _swrast_mask_rgba_span(ctx, rb, &span);
 
530
            }
 
531
            rb->PutRow(ctx, rb, width, xpos, ypos + i, span.array->rgba, NULL);
 
532
         }
 
533
      }
 
534
   }
 
535
   else {
 
536
      /* other types someday */
 
537
   }
 
538
}
 
539
 
 
540
 
 
541
 
 
542
/**
 
543
 * Software fallback for glAccum.
 
544
 */
 
545
void
 
546
_swrast_Accum(GLcontext *ctx, GLenum op, GLfloat value)
 
547
{
 
548
   SWcontext *swrast = SWRAST_CONTEXT(ctx);
 
549
   GLint xpos, ypos, width, height;
 
550
 
 
551
   if (SWRAST_CONTEXT(ctx)->NewState)
 
552
      _swrast_validate_derived( ctx );
 
553
 
 
554
   if (!ctx->DrawBuffer->Attachment[BUFFER_ACCUM].Renderbuffer) {
 
555
      _mesa_warning(ctx, "Calling glAccum() without an accumulation buffer");
 
556
      return;
 
557
   }
 
558
 
 
559
   RENDER_START(swrast, ctx);
 
560
 
 
561
   /* Compute region after calling RENDER_START so that we know the
 
562
    * drawbuffer's size/bounds are up to date.
 
563
    */
 
564
   xpos = ctx->DrawBuffer->_Xmin;
 
565
   ypos = ctx->DrawBuffer->_Ymin;
 
566
   width =  ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
 
567
   height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
 
568
 
 
569
   switch (op) {
 
570
      case GL_ADD:
 
571
         if (value != 0.0F) {
 
572
            accum_add(ctx, value, xpos, ypos, width, height);
 
573
         }
 
574
         break;
 
575
      case GL_MULT:
 
576
         if (value != 1.0F) {
 
577
            accum_mult(ctx, value, xpos, ypos, width, height);
 
578
         }
 
579
         break;
 
580
      case GL_ACCUM:
 
581
         if (value != 0.0F) {
 
582
            accum_accum(ctx, value, xpos, ypos, width, height);
 
583
         }
 
584
         break;
 
585
      case GL_LOAD:
 
586
         accum_load(ctx, value, xpos, ypos, width, height);
 
587
         break;
 
588
      case GL_RETURN:
 
589
         accum_return(ctx, value, xpos, ypos, width, height);
 
590
         break;
 
591
      default:
 
592
         _mesa_problem(ctx, "invalid mode in _swrast_Accum()");
 
593
         break;
 
594
   }
 
595
 
 
596
   RENDER_FINISH(swrast, ctx);
 
597
}