Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
57 | pj | 1 | /* $Id: s_accum.c,v 1.1 2003-02-28 11:49:40 pj Exp $ */ |
2 | |||
3 | /* |
||
4 | * Mesa 3-D graphics library |
||
5 | * Version: 4.1 |
||
6 | * |
||
7 | * Copyright (C) 1999-2002 Brian Paul All Rights Reserved. |
||
8 | * |
||
9 | * Permission is hereby granted, free of charge, to any person obtaining a |
||
10 | * copy of this software and associated documentation files (the "Software"), |
||
11 | * to deal in the Software without restriction, including without limitation |
||
12 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
||
13 | * and/or sell copies of the Software, and to permit persons to whom the |
||
14 | * Software is furnished to do so, subject to the following conditions: |
||
15 | * |
||
16 | * The above copyright notice and this permission notice shall be included |
||
17 | * in all copies or substantial portions of the Software. |
||
18 | * |
||
19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
||
20 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||
21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
||
22 | * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN |
||
23 | * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
||
24 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
||
25 | */ |
||
26 | |||
27 | |||
28 | #include "glheader.h" |
||
29 | #include "context.h" |
||
30 | #include "macros.h" |
||
31 | #include "mmath.h" |
||
32 | #include "imports.h" |
||
33 | |||
34 | #include "s_accum.h" |
||
35 | #include "s_alphabuf.h" |
||
36 | #include "s_context.h" |
||
37 | #include "s_masking.h" |
||
38 | #include "s_span.h" |
||
39 | |||
40 | |||
41 | /* |
||
42 | * Accumulation buffer notes |
||
43 | * |
||
44 | * Normally, accumulation buffer values are GLshorts with values in |
||
45 | * [-32767, 32767] which represent floating point colors in [-1, 1], |
||
46 | * as suggested by the OpenGL specification. |
||
47 | * |
||
48 | * We optimize for the common case used for full-scene antialiasing: |
||
49 | * // start with accum buffer cleared to zero |
||
50 | * glAccum(GL_LOAD, w); // or GL_ACCUM the first image |
||
51 | * glAccum(GL_ACCUM, w); |
||
52 | * ... |
||
53 | * glAccum(GL_ACCUM, w); |
||
54 | * glAccum(GL_RETURN, 1.0); |
||
55 | * That is, we start with an empty accumulation buffer and accumulate |
||
56 | * n images, each with weight w = 1/n. |
||
57 | * In this scenario, we can simply store unscaled integer values in |
||
58 | * the accum buffer instead of scaled integers. We'll also keep track |
||
59 | * of the w value so when we do GL_RETURN we simply divide the accumulated |
||
60 | * values by n (=1/w). |
||
61 | * This lets us avoid _many_ int->float->int conversions. |
||
62 | */ |
||
63 | |||
64 | |||
65 | #if CHAN_BITS == 8 && ACCUM_BITS < 32 |
||
66 | #define USE_OPTIMIZED_ACCUM /* enable the optimization */ |
||
67 | #endif |
||
68 | |||
69 | |||
70 | void |
||
71 | _mesa_alloc_accum_buffer( GLframebuffer *buffer ) |
||
72 | { |
||
73 | GET_CURRENT_CONTEXT(ctx); |
||
74 | GLint n; |
||
75 | |||
76 | if (buffer->Accum) { |
||
77 | MESA_PBUFFER_FREE( buffer->Accum ); |
||
78 | buffer->Accum = NULL; |
||
79 | } |
||
80 | |||
81 | /* allocate accumulation buffer if not already present */ |
||
82 | n = buffer->Width * buffer->Height * 4 * sizeof(GLaccum); |
||
83 | buffer->Accum = (GLaccum *) MESA_PBUFFER_ALLOC( n ); |
||
84 | if (!buffer->Accum) { |
||
85 | /* unable to setup accumulation buffer */ |
||
86 | _mesa_error( NULL, GL_OUT_OF_MEMORY, "glAccum" ); |
||
87 | } |
||
88 | |||
89 | if (ctx) { |
||
90 | SWcontext *swrast = SWRAST_CONTEXT(ctx); |
||
91 | /* XXX these fields should probably be in the GLframebuffer */ |
||
92 | #ifdef USE_OPTIMIZED_ACCUM |
||
93 | swrast->_IntegerAccumMode = GL_TRUE; |
||
94 | #else |
||
95 | swrast->_IntegerAccumMode = GL_FALSE; |
||
96 | #endif |
||
97 | swrast->_IntegerAccumScaler = 0.0; |
||
98 | } |
||
99 | } |
||
100 | |||
101 | |||
102 | /* |
||
103 | * This is called when we fall out of optimized/unscaled accum buffer mode. |
||
104 | * That is, we convert each unscaled accum buffer value into a scaled value |
||
105 | * representing the range[-1, 1]. |
||
106 | */ |
||
107 | static void rescale_accum( GLcontext *ctx ) |
||
108 | { |
||
109 | SWcontext *swrast = SWRAST_CONTEXT(ctx); |
||
110 | const GLuint n = ctx->DrawBuffer->Width * ctx->DrawBuffer->Height * 4; |
||
111 | const GLfloat s = swrast->_IntegerAccumScaler * (32767.0F / CHAN_MAXF); |
||
112 | GLaccum *accum = ctx->DrawBuffer->Accum; |
||
113 | GLuint i; |
||
114 | |||
115 | assert(swrast->_IntegerAccumMode); |
||
116 | assert(accum); |
||
117 | |||
118 | for (i = 0; i < n; i++) { |
||
119 | accum[i] = (GLaccum) (accum[i] * s); |
||
120 | } |
||
121 | |||
122 | swrast->_IntegerAccumMode = GL_FALSE; |
||
123 | } |
||
124 | |||
125 | |||
126 | |||
127 | |||
128 | |||
129 | |||
130 | /* |
||
131 | * Clear the accumulation Buffer. |
||
132 | */ |
||
133 | void |
||
134 | _mesa_clear_accum_buffer( GLcontext *ctx ) |
||
135 | { |
||
136 | SWcontext *swrast = SWRAST_CONTEXT(ctx); |
||
137 | GLuint buffersize; |
||
138 | GLfloat acc_scale; |
||
139 | |||
140 | if (ctx->Visual.accumRedBits==0) { |
||
141 | /* No accumulation buffer! */ |
||
142 | return; |
||
143 | } |
||
144 | |||
145 | if (sizeof(GLaccum)==1) { |
||
146 | acc_scale = 127.0; |
||
147 | } |
||
148 | else if (sizeof(GLaccum)==2) { |
||
149 | acc_scale = 32767.0; |
||
150 | } |
||
151 | else { |
||
152 | acc_scale = 1.0F; |
||
153 | } |
||
154 | |||
155 | /* number of pixels */ |
||
156 | buffersize = ctx->DrawBuffer->Width * ctx->DrawBuffer->Height; |
||
157 | |||
158 | if (!ctx->DrawBuffer->Accum) { |
||
159 | /* try to alloc accumulation buffer */ |
||
160 | ctx->DrawBuffer->Accum = (GLaccum *) |
||
161 | MALLOC( buffersize * 4 * sizeof(GLaccum) ); |
||
162 | } |
||
163 | |||
164 | if (ctx->DrawBuffer->Accum) { |
||
165 | if (ctx->Scissor.Enabled) { |
||
166 | /* Limit clear to scissor box */ |
||
167 | const GLaccum r = (GLaccum) (ctx->Accum.ClearColor[0] * acc_scale); |
||
168 | const GLaccum g = (GLaccum) (ctx->Accum.ClearColor[1] * acc_scale); |
||
169 | const GLaccum b = (GLaccum) (ctx->Accum.ClearColor[2] * acc_scale); |
||
170 | const GLaccum a = (GLaccum) (ctx->Accum.ClearColor[3] * acc_scale); |
||
171 | GLint i, j; |
||
172 | GLint width, height; |
||
173 | GLaccum *row; |
||
174 | /* size of region to clear */ |
||
175 | width = 4 * (ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin); |
||
176 | height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin; |
||
177 | /* ptr to first element to clear */ |
||
178 | row = ctx->DrawBuffer->Accum |
||
179 | + 4 * (ctx->DrawBuffer->_Ymin * ctx->DrawBuffer->Width |
||
180 | + ctx->DrawBuffer->_Xmin); |
||
181 | for (j=0;j<height;j++) { |
||
182 | for (i=0;i<width;i+=4) { |
||
183 | row[i+0] = r; |
||
184 | row[i+1] = g; |
||
185 | row[i+2] = b; |
||
186 | row[i+3] = a; |
||
187 | } |
||
188 | row += 4 * ctx->DrawBuffer->Width; |
||
189 | } |
||
190 | } |
||
191 | else { |
||
192 | /* clear whole buffer */ |
||
193 | if (ctx->Accum.ClearColor[0]==0.0 && |
||
194 | ctx->Accum.ClearColor[1]==0.0 && |
||
195 | ctx->Accum.ClearColor[2]==0.0 && |
||
196 | ctx->Accum.ClearColor[3]==0.0) { |
||
197 | /* Black */ |
||
198 | _mesa_bzero( ctx->DrawBuffer->Accum, |
||
199 | buffersize * 4 * sizeof(GLaccum) ); |
||
200 | } |
||
201 | else { |
||
202 | /* Not black */ |
||
203 | const GLaccum r = (GLaccum) (ctx->Accum.ClearColor[0] * acc_scale); |
||
204 | const GLaccum g = (GLaccum) (ctx->Accum.ClearColor[1] * acc_scale); |
||
205 | const GLaccum b = (GLaccum) (ctx->Accum.ClearColor[2] * acc_scale); |
||
206 | const GLaccum a = (GLaccum) (ctx->Accum.ClearColor[3] * acc_scale); |
||
207 | GLaccum *acc = ctx->DrawBuffer->Accum; |
||
208 | GLuint i; |
||
209 | for (i=0;i<buffersize;i++) { |
||
210 | *acc++ = r; |
||
211 | *acc++ = g; |
||
212 | *acc++ = b; |
||
213 | *acc++ = a; |
||
214 | } |
||
215 | } |
||
216 | } |
||
217 | |||
218 | /* update optimized accum state vars */ |
||
219 | if (ctx->Accum.ClearColor[0] == 0.0 && ctx->Accum.ClearColor[1] == 0.0 && |
||
220 | ctx->Accum.ClearColor[2] == 0.0 && ctx->Accum.ClearColor[3] == 0.0) { |
||
221 | #ifdef USE_OPTIMIZED_ACCUM |
||
222 | swrast->_IntegerAccumMode = GL_TRUE; |
||
223 | #else |
||
224 | swrast->_IntegerAccumMode = GL_FALSE; |
||
225 | #endif |
||
226 | swrast->_IntegerAccumScaler = 0.0; /* denotes empty accum buffer */ |
||
227 | } |
||
228 | else { |
||
229 | swrast->_IntegerAccumMode = GL_FALSE; |
||
230 | } |
||
231 | } |
||
232 | } |
||
233 | |||
234 | |||
235 | void |
||
236 | _swrast_Accum( GLcontext *ctx, GLenum op, GLfloat value, |
||
237 | GLint xpos, GLint ypos, |
||
238 | GLint width, GLint height ) |
||
239 | |||
240 | { |
||
241 | SWcontext *swrast = SWRAST_CONTEXT(ctx); |
||
242 | GLuint width4; |
||
243 | GLfloat acc_scale; |
||
244 | GLchan rgba[MAX_WIDTH][4]; |
||
245 | const GLuint colorMask = *((GLuint *) &ctx->Color.ColorMask); |
||
246 | |||
247 | |||
248 | if (SWRAST_CONTEXT(ctx)->NewState) |
||
249 | _swrast_validate_derived( ctx ); |
||
250 | |||
251 | if (!ctx->DrawBuffer->Accum) { |
||
252 | _mesa_warning(ctx, |
||
253 | "Calling glAccum() without an accumulation " |
||
254 | "buffer (low memory?)"); |
||
255 | return; |
||
256 | } |
||
257 | |||
258 | if (sizeof(GLaccum)==1) { |
||
259 | acc_scale = 127.0; |
||
260 | } |
||
261 | else if (sizeof(GLaccum)==2) { |
||
262 | acc_scale = 32767.0; |
||
263 | } |
||
264 | else { |
||
265 | acc_scale = 1.0F; |
||
266 | } |
||
267 | |||
268 | width4 = 4 * width; |
||
269 | |||
270 | switch (op) { |
||
271 | case GL_ADD: |
||
272 | if (value != 0.0F) { |
||
273 | const GLaccum val = (GLaccum) (value * acc_scale); |
||
274 | GLint j; |
||
275 | /* Leave optimized accum buffer mode */ |
||
276 | if (swrast->_IntegerAccumMode) |
||
277 | rescale_accum(ctx); |
||
278 | for (j = 0; j < height; j++) { |
||
279 | GLaccum *acc = ctx->DrawBuffer->Accum + ypos * width4 + 4*xpos; |
||
280 | GLuint i; |
||
281 | for (i = 0; i < width4; i++) { |
||
282 | acc[i] += val; |
||
283 | } |
||
284 | ypos++; |
||
285 | } |
||
286 | } |
||
287 | break; |
||
288 | |||
289 | case GL_MULT: |
||
290 | if (value != 1.0F) { |
||
291 | GLint j; |
||
292 | /* Leave optimized accum buffer mode */ |
||
293 | if (swrast->_IntegerAccumMode) |
||
294 | rescale_accum(ctx); |
||
295 | for (j = 0; j < height; j++) { |
||
296 | GLaccum *acc = ctx->DrawBuffer->Accum + ypos * width4 + 4 * xpos; |
||
297 | GLuint i; |
||
298 | for (i = 0; i < width4; i++) { |
||
299 | acc[i] = (GLaccum) ( (GLfloat) acc[i] * value ); |
||
300 | } |
||
301 | ypos++; |
||
302 | } |
||
303 | } |
||
304 | break; |
||
305 | |||
306 | case GL_ACCUM: |
||
307 | if (value == 0.0F) |
||
308 | return; |
||
309 | |||
310 | _swrast_use_read_buffer(ctx); |
||
311 | |||
312 | /* May have to leave optimized accum buffer mode */ |
||
313 | if (swrast->_IntegerAccumScaler == 0.0 && value > 0.0 && value <= 1.0) |
||
314 | swrast->_IntegerAccumScaler = value; |
||
315 | if (swrast->_IntegerAccumMode && value != swrast->_IntegerAccumScaler) |
||
316 | rescale_accum(ctx); |
||
317 | |||
318 | RENDER_START(swrast,ctx); |
||
319 | |||
320 | if (swrast->_IntegerAccumMode) { |
||
321 | /* simply add integer color values into accum buffer */ |
||
322 | GLint j; |
||
323 | GLaccum *acc = ctx->DrawBuffer->Accum + ypos * width4 + xpos * 4; |
||
324 | assert(swrast->_IntegerAccumScaler > 0.0); |
||
325 | assert(swrast->_IntegerAccumScaler <= 1.0); |
||
326 | for (j = 0; j < height; j++) { |
||
327 | |||
328 | GLint i, i4; |
||
329 | _mesa_read_rgba_span(ctx, ctx->DrawBuffer, width, xpos, ypos, rgba); |
||
330 | for (i = i4 = 0; i < width; i++, i4+=4) { |
||
331 | acc[i4+0] += rgba[i][RCOMP]; |
||
332 | acc[i4+1] += rgba[i][GCOMP]; |
||
333 | acc[i4+2] += rgba[i][BCOMP]; |
||
334 | acc[i4+3] += rgba[i][ACOMP]; |
||
335 | } |
||
336 | acc += width4; |
||
337 | ypos++; |
||
338 | } |
||
339 | } |
||
340 | else { |
||
341 | /* scaled integer (or float) accum buffer */ |
||
342 | const GLfloat rscale = value * acc_scale / CHAN_MAXF; |
||
343 | const GLfloat gscale = value * acc_scale / CHAN_MAXF; |
||
344 | const GLfloat bscale = value * acc_scale / CHAN_MAXF; |
||
345 | const GLfloat ascale = value * acc_scale / CHAN_MAXF; |
||
346 | GLint j; |
||
347 | for (j=0;j<height;j++) { |
||
348 | GLaccum *acc = ctx->DrawBuffer->Accum + ypos * width4 + xpos * 4; |
||
349 | GLint i; |
||
350 | _mesa_read_rgba_span(ctx, ctx->DrawBuffer, width, xpos, ypos, rgba); |
||
351 | for (i=0;i<width;i++) { |
||
352 | acc[0] += (GLaccum) ( (GLfloat) rgba[i][RCOMP] * rscale ); |
||
353 | acc[1] += (GLaccum) ( (GLfloat) rgba[i][GCOMP] * gscale ); |
||
354 | acc[2] += (GLaccum) ( (GLfloat) rgba[i][BCOMP] * bscale ); |
||
355 | acc[3] += (GLaccum) ( (GLfloat) rgba[i][ACOMP] * ascale ); |
||
356 | acc += 4; |
||
357 | } |
||
358 | ypos++; |
||
359 | } |
||
360 | } |
||
361 | /* restore read buffer = draw buffer (the default) */ |
||
362 | _swrast_use_draw_buffer(ctx); |
||
363 | |||
364 | RENDER_FINISH(swrast,ctx); |
||
365 | break; |
||
366 | |||
367 | case GL_LOAD: |
||
368 | _swrast_use_read_buffer(ctx); |
||
369 | |||
370 | /* This is a change to go into optimized accum buffer mode */ |
||
371 | if (value > 0.0 && value <= 1.0) { |
||
372 | #ifdef USE_OPTIMIZED_ACCUM |
||
373 | swrast->_IntegerAccumMode = GL_TRUE; |
||
374 | #else |
||
375 | swrast->_IntegerAccumMode = GL_FALSE; |
||
376 | #endif |
||
377 | swrast->_IntegerAccumScaler = value; |
||
378 | } |
||
379 | else { |
||
380 | swrast->_IntegerAccumMode = GL_FALSE; |
||
381 | swrast->_IntegerAccumScaler = 0.0; |
||
382 | } |
||
383 | |||
384 | RENDER_START(swrast,ctx); |
||
385 | if (swrast->_IntegerAccumMode) { |
||
386 | /* just copy values into accum buffer */ |
||
387 | GLint j; |
||
388 | GLaccum *acc = ctx->DrawBuffer->Accum + ypos * width4 + xpos * 4; |
||
389 | assert(swrast->_IntegerAccumScaler > 0.0); |
||
390 | assert(swrast->_IntegerAccumScaler <= 1.0); |
||
391 | for (j = 0; j < height; j++) { |
||
392 | GLint i, i4; |
||
393 | _mesa_read_rgba_span(ctx, ctx->DrawBuffer, width, xpos, ypos, rgba); |
||
394 | for (i = i4 = 0; i < width; i++, i4 += 4) { |
||
395 | acc[i4+0] = rgba[i][RCOMP]; |
||
396 | acc[i4+1] = rgba[i][GCOMP]; |
||
397 | acc[i4+2] = rgba[i][BCOMP]; |
||
398 | acc[i4+3] = rgba[i][ACOMP]; |
||
399 | } |
||
400 | acc += width4; |
||
401 | ypos++; |
||
402 | } |
||
403 | } |
||
404 | else { |
||
405 | /* scaled integer (or float) accum buffer */ |
||
406 | const GLfloat rscale = value * acc_scale / CHAN_MAXF; |
||
407 | const GLfloat gscale = value * acc_scale / CHAN_MAXF; |
||
408 | const GLfloat bscale = value * acc_scale / CHAN_MAXF; |
||
409 | const GLfloat ascale = value * acc_scale / CHAN_MAXF; |
||
410 | #if 0 |
||
411 | const GLfloat d = 3.0 / acc_scale; /* XXX what's this? */ |
||
412 | #endif |
||
413 | GLint i, j; |
||
414 | for (j = 0; j < height; j++) { |
||
415 | GLaccum *acc = ctx->DrawBuffer->Accum + ypos * width4 + xpos * 4; |
||
416 | _mesa_read_rgba_span(ctx, ctx->DrawBuffer, width, xpos, ypos, rgba); |
||
417 | for (i=0;i<width;i++) { |
||
418 | #if 0 |
||
419 | *acc++ = (GLaccum) ((GLfloat) rgba[i][RCOMP] * rscale + d); |
||
420 | *acc++ = (GLaccum) ((GLfloat) rgba[i][GCOMP] * gscale + d); |
||
421 | *acc++ = (GLaccum) ((GLfloat) rgba[i][BCOMP] * bscale + d); |
||
422 | *acc++ = (GLaccum) ((GLfloat) rgba[i][ACOMP] * ascale + d); |
||
423 | #else |
||
424 | *acc++ = (GLaccum) ((GLfloat) rgba[i][RCOMP] * rscale); |
||
425 | *acc++ = (GLaccum) ((GLfloat) rgba[i][GCOMP] * gscale); |
||
426 | *acc++ = (GLaccum) ((GLfloat) rgba[i][BCOMP] * bscale); |
||
427 | *acc++ = (GLaccum) ((GLfloat) rgba[i][ACOMP] * ascale); |
||
428 | #endif |
||
429 | } |
||
430 | ypos++; |
||
431 | } |
||
432 | } |
||
433 | |||
434 | /* restore read buffer = draw buffer (the default) */ |
||
435 | _swrast_use_draw_buffer(ctx); |
||
436 | |||
437 | RENDER_FINISH(swrast,ctx); |
||
438 | break; |
||
439 | |||
440 | case GL_RETURN: |
||
441 | /* May have to leave optimized accum buffer mode */ |
||
442 | if (swrast->_IntegerAccumMode && value != 1.0) |
||
443 | rescale_accum(ctx); |
||
444 | |||
445 | RENDER_START(swrast,ctx); |
||
446 | #ifdef USE_OPTIMIZED_ACCUM |
||
447 | if (swrast->_IntegerAccumMode && swrast->_IntegerAccumScaler > 0) { |
||
448 | /* build lookup table to avoid many floating point multiplies */ |
||
449 | static GLchan multTable[32768]; |
||
450 | static GLfloat prevMult = 0.0; |
||
451 | const GLfloat mult = swrast->_IntegerAccumScaler; |
||
452 | const GLint max = MIN2((GLint) (256 / mult), 32767); |
||
453 | GLint j; |
||
454 | if (mult != prevMult) { |
||
455 | for (j = 0; j < max; j++) |
||
456 | multTable[j] = IROUND((GLfloat) j * mult); |
||
457 | prevMult = mult; |
||
458 | } |
||
459 | |||
460 | assert(swrast->_IntegerAccumScaler > 0.0); |
||
461 | assert(swrast->_IntegerAccumScaler <= 1.0); |
||
462 | for (j = 0; j < height; j++) { |
||
463 | const GLaccum *acc = ctx->DrawBuffer->Accum + ypos * width4 + xpos*4; |
||
464 | GLint i, i4; |
||
465 | for (i = i4 = 0; i < width; i++, i4 += 4) { |
||
466 | ASSERT(acc[i4+0] < max); |
||
467 | ASSERT(acc[i4+1] < max); |
||
468 | ASSERT(acc[i4+2] < max); |
||
469 | ASSERT(acc[i4+3] < max); |
||
470 | rgba[i][RCOMP] = multTable[acc[i4+0]]; |
||
471 | rgba[i][GCOMP] = multTable[acc[i4+1]]; |
||
472 | rgba[i][BCOMP] = multTable[acc[i4+2]]; |
||
473 | rgba[i][ACOMP] = multTable[acc[i4+3]]; |
||
474 | } |
||
475 | if (colorMask != 0xffffffff) { |
||
476 | _mesa_mask_rgba_array( ctx, width, xpos, ypos, rgba ); |
||
477 | } |
||
478 | (*swrast->Driver.WriteRGBASpan)( ctx, width, xpos, ypos, |
||
479 | (const GLchan (*)[4])rgba, NULL ); |
||
480 | if (ctx->DrawBuffer->UseSoftwareAlphaBuffers |
||
481 | && ctx->Color.ColorMask[ACOMP]) { |
||
482 | _mesa_write_alpha_span(ctx, width, xpos, ypos, |
||
483 | (CONST GLchan (*)[4]) rgba, NULL); |
||
484 | } |
||
485 | ypos++; |
||
486 | } |
||
487 | } |
||
488 | else |
||
489 | #endif /* USE_OPTIMIZED_ACCUM */ |
||
490 | { |
||
491 | /* scaled integer (or float) accum buffer */ |
||
492 | const GLfloat rscale = value / acc_scale * CHAN_MAXF; |
||
493 | const GLfloat gscale = value / acc_scale * CHAN_MAXF; |
||
494 | const GLfloat bscale = value / acc_scale * CHAN_MAXF; |
||
495 | const GLfloat ascale = value / acc_scale * CHAN_MAXF; |
||
496 | GLint i, j; |
||
497 | for (j=0;j<height;j++) { |
||
498 | const GLaccum *acc = ctx->DrawBuffer->Accum + ypos * width4 + xpos*4; |
||
499 | for (i=0;i<width;i++) { |
||
500 | GLint r = IROUND( (GLfloat) (acc[0]) * rscale ); |
||
501 | GLint g = IROUND( (GLfloat) (acc[1]) * gscale ); |
||
502 | GLint b = IROUND( (GLfloat) (acc[2]) * bscale ); |
||
503 | GLint a = IROUND( (GLfloat) (acc[3]) * ascale ); |
||
504 | acc += 4; |
||
505 | rgba[i][RCOMP] = CLAMP( r, 0, CHAN_MAX ); |
||
506 | rgba[i][GCOMP] = CLAMP( g, 0, CHAN_MAX ); |
||
507 | rgba[i][BCOMP] = CLAMP( b, 0, CHAN_MAX ); |
||
508 | rgba[i][ACOMP] = CLAMP( a, 0, CHAN_MAX ); |
||
509 | } |
||
510 | if (colorMask != 0xffffffff) { |
||
511 | _mesa_mask_rgba_array( ctx, width, xpos, ypos, rgba ); |
||
512 | } |
||
513 | (*swrast->Driver.WriteRGBASpan)( ctx, width, xpos, ypos, |
||
514 | (const GLchan (*)[4])rgba, NULL ); |
||
515 | if (ctx->DrawBuffer->UseSoftwareAlphaBuffers |
||
516 | && ctx->Color.ColorMask[ACOMP]) { |
||
517 | _mesa_write_alpha_span(ctx, width, xpos, ypos, |
||
518 | (CONST GLchan (*)[4]) rgba, NULL); |
||
519 | } |
||
520 | ypos++; |
||
521 | } |
||
522 | } |
||
523 | RENDER_FINISH(swrast,ctx); |
||
524 | break; |
||
525 | |||
526 | default: |
||
527 | _mesa_error( ctx, GL_INVALID_ENUM, "glAccum" ); |
||
528 | } |
||
529 | } |