Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

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