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 | }>>>>>>>>>=>>>=>>=>>>>=>>>>>>>>>>>>>> |