Merge commit 'origin/gallium-master-merge'
[mesa.git] / src / mesa / main / renderbuffer.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 6.5
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 /**
27 * Functions for allocating/managing renderbuffers.
28 * Also, routines for reading/writing software-based renderbuffer data as
29 * ubytes, ushorts, uints, etc.
30 *
31 * The 'alpha8' renderbuffer is interesting. It's used to add a software-based
32 * alpha channel to RGB renderbuffers. This is done by wrapping the RGB
33 * renderbuffer with the alpha renderbuffer. We can do this because of the
34 * OO-nature of renderbuffers.
35 *
36 * Down the road we'll use this for run-time support of 8, 16 and 32-bit
37 * color channels. For example, Mesa may use 32-bit/float color channels
38 * internally (swrast) and use wrapper renderbuffers to convert 32-bit
39 * values down to 16 or 8-bit values for whatever kind of framebuffer we have.
40 */
41
42
43 #include "glheader.h"
44 #include "imports.h"
45 #include "context.h"
46 #include "mtypes.h"
47 #include "fbobject.h"
48 #include "renderbuffer.h"
49
50 #include "rbadaptors.h"
51
52
53 /* 32-bit color index format. Not a public format. */
54 #define COLOR_INDEX32 0x424243
55
56
57 /*
58 * Routines for get/put values in common buffer formats follow.
59 * Someday add support for arbitrary row stride to make them more
60 * flexible.
61 */
62
63 /**********************************************************************
64 * Functions for buffers of 1 X GLubyte values.
65 * Typically stencil.
66 */
67
68 static void *
69 get_pointer_ubyte(GLcontext *ctx, struct gl_renderbuffer *rb,
70 GLint x, GLint y)
71 {
72 if (!rb->Data)
73 return NULL;
74 ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
75 /* Can't assert _ActualFormat since these funcs may be used for serveral
76 * different formats (GL_ALPHA8, GL_STENCIL_INDEX8, etc).
77 */
78 return (GLubyte *) rb->Data + y * rb->Width + x;
79 }
80
81
82 static void
83 get_row_ubyte(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
84 GLint x, GLint y, void *values)
85 {
86 const GLubyte *src = (const GLubyte *) rb->Data + y * rb->Width + x;
87 ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
88 _mesa_memcpy(values, src, count * sizeof(GLubyte));
89 }
90
91
92 static void
93 get_values_ubyte(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
94 const GLint x[], const GLint y[], void *values)
95 {
96 GLubyte *dst = (GLubyte *) values;
97 GLuint i;
98 ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
99 for (i = 0; i < count; i++) {
100 const GLubyte *src = (GLubyte *) rb->Data + y[i] * rb->Width + x[i];
101 dst[i] = *src;
102 }
103 }
104
105
106 static void
107 put_row_ubyte(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
108 GLint x, GLint y, const void *values, const GLubyte *mask)
109 {
110 const GLubyte *src = (const GLubyte *) values;
111 GLubyte *dst = (GLubyte *) rb->Data + y * rb->Width + x;
112 ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
113 if (mask) {
114 GLuint i;
115 for (i = 0; i < count; i++) {
116 if (mask[i]) {
117 dst[i] = src[i];
118 }
119 }
120 }
121 else {
122 _mesa_memcpy(dst, values, count * sizeof(GLubyte));
123 }
124 }
125
126
127 static void
128 put_mono_row_ubyte(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
129 GLint x, GLint y, const void *value, const GLubyte *mask)
130 {
131 const GLubyte val = *((const GLubyte *) value);
132 GLubyte *dst = (GLubyte *) rb->Data + y * rb->Width + x;
133 ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
134 if (mask) {
135 GLuint i;
136 for (i = 0; i < count; i++) {
137 if (mask[i]) {
138 dst[i] = val;
139 }
140 }
141 }
142 else {
143 GLuint i;
144 for (i = 0; i < count; i++) {
145 dst[i] = val;
146 }
147 }
148 }
149
150
151 static void
152 put_values_ubyte(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
153 const GLint x[], const GLint y[],
154 const void *values, const GLubyte *mask)
155 {
156 const GLubyte *src = (const GLubyte *) values;
157 GLuint i;
158 ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
159 for (i = 0; i < count; i++) {
160 if (!mask || mask[i]) {
161 GLubyte *dst = (GLubyte *) rb->Data + y[i] * rb->Width + x[i];
162 *dst = src[i];
163 }
164 }
165 }
166
167
168 static void
169 put_mono_values_ubyte(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
170 const GLint x[], const GLint y[],
171 const void *value, const GLubyte *mask)
172 {
173 const GLubyte val = *((const GLubyte *) value);
174 GLuint i;
175 ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
176 for (i = 0; i < count; i++) {
177 if (!mask || mask[i]) {
178 GLubyte *dst = (GLubyte *) rb->Data + y[i] * rb->Width + x[i];
179 *dst = val;
180 }
181 }
182 }
183
184
185 /**********************************************************************
186 * Functions for buffers of 1 X GLushort values.
187 * Typically depth/Z.
188 */
189
190 static void *
191 get_pointer_ushort(GLcontext *ctx, struct gl_renderbuffer *rb,
192 GLint x, GLint y)
193 {
194 if (!rb->Data)
195 return NULL;
196 ASSERT(rb->DataType == GL_UNSIGNED_SHORT);
197 ASSERT(rb->Width > 0);
198 return (GLushort *) rb->Data + y * rb->Width + x;
199 }
200
201
202 static void
203 get_row_ushort(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
204 GLint x, GLint y, void *values)
205 {
206 const void *src = rb->GetPointer(ctx, rb, x, y);
207 ASSERT(rb->DataType == GL_UNSIGNED_SHORT);
208 _mesa_memcpy(values, src, count * sizeof(GLushort));
209 }
210
211
212 static void
213 get_values_ushort(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
214 const GLint x[], const GLint y[], void *values)
215 {
216 GLushort *dst = (GLushort *) values;
217 GLuint i;
218 ASSERT(rb->DataType == GL_UNSIGNED_SHORT);
219 for (i = 0; i < count; i++) {
220 const GLushort *src = (GLushort *) rb->Data + y[i] * rb->Width + x[i];
221 dst[i] = *src;
222 }
223 }
224
225
226 static void
227 put_row_ushort(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
228 GLint x, GLint y, const void *values, const GLubyte *mask)
229 {
230 const GLushort *src = (const GLushort *) values;
231 GLushort *dst = (GLushort *) rb->Data + y * rb->Width + x;
232 ASSERT(rb->DataType == GL_UNSIGNED_SHORT);
233 if (mask) {
234 GLuint i;
235 for (i = 0; i < count; i++) {
236 if (mask[i]) {
237 dst[i] = src[i];
238 }
239 }
240 }
241 else {
242 _mesa_memcpy(dst, src, count * sizeof(GLushort));
243 }
244 }
245
246
247 static void
248 put_mono_row_ushort(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
249 GLint x, GLint y, const void *value, const GLubyte *mask)
250 {
251 const GLushort val = *((const GLushort *) value);
252 GLushort *dst = (GLushort *) rb->Data + y * rb->Width + x;
253 ASSERT(rb->DataType == GL_UNSIGNED_SHORT);
254 if (mask) {
255 GLuint i;
256 for (i = 0; i < count; i++) {
257 if (mask[i]) {
258 dst[i] = val;
259 }
260 }
261 }
262 else {
263 GLuint i;
264 for (i = 0; i < count; i++) {
265 dst[i] = val;
266 }
267 }
268 }
269
270
271 static void
272 put_values_ushort(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
273 const GLint x[], const GLint y[], const void *values,
274 const GLubyte *mask)
275 {
276 const GLushort *src = (const GLushort *) values;
277 GLuint i;
278 ASSERT(rb->DataType == GL_UNSIGNED_SHORT);
279 for (i = 0; i < count; i++) {
280 if (!mask || mask[i]) {
281 GLushort *dst = (GLushort *) rb->Data + y[i] * rb->Width + x[i];
282 *dst = src[i];
283 }
284 }
285 }
286
287
288 static void
289 put_mono_values_ushort(GLcontext *ctx, struct gl_renderbuffer *rb,
290 GLuint count, const GLint x[], const GLint y[],
291 const void *value, const GLubyte *mask)
292 {
293 const GLushort val = *((const GLushort *) value);
294 ASSERT(rb->DataType == GL_UNSIGNED_SHORT);
295 if (mask) {
296 GLuint i;
297 for (i = 0; i < count; i++) {
298 if (mask[i]) {
299 GLushort *dst = (GLushort *) rb->Data + y[i] * rb->Width + x[i];
300 *dst = val;
301 }
302 }
303 }
304 else {
305 GLuint i;
306 for (i = 0; i < count; i++) {
307 GLushort *dst = (GLushort *) rb->Data + y[i] * rb->Width + x[i];
308 *dst = val;
309 }
310 }
311 }
312
313
314 /**********************************************************************
315 * Functions for buffers of 1 X GLuint values.
316 * Typically depth/Z or color index.
317 */
318
319 static void *
320 get_pointer_uint(GLcontext *ctx, struct gl_renderbuffer *rb,
321 GLint x, GLint y)
322 {
323 if (!rb->Data)
324 return NULL;
325 ASSERT(rb->DataType == GL_UNSIGNED_INT ||
326 rb->DataType == GL_UNSIGNED_INT_24_8_EXT);
327 return (GLuint *) rb->Data + y * rb->Width + x;
328 }
329
330
331 static void
332 get_row_uint(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
333 GLint x, GLint y, void *values)
334 {
335 const void *src = rb->GetPointer(ctx, rb, x, y);
336 ASSERT(rb->DataType == GL_UNSIGNED_INT ||
337 rb->DataType == GL_UNSIGNED_INT_24_8_EXT);
338 _mesa_memcpy(values, src, count * sizeof(GLuint));
339 }
340
341
342 static void
343 get_values_uint(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
344 const GLint x[], const GLint y[], void *values)
345 {
346 GLuint *dst = (GLuint *) values;
347 GLuint i;
348 ASSERT(rb->DataType == GL_UNSIGNED_INT ||
349 rb->DataType == GL_UNSIGNED_INT_24_8_EXT);
350 for (i = 0; i < count; i++) {
351 const GLuint *src = (GLuint *) rb->Data + y[i] * rb->Width + x[i];
352 dst[i] = *src;
353 }
354 }
355
356
357 static void
358 put_row_uint(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
359 GLint x, GLint y, const void *values, const GLubyte *mask)
360 {
361 const GLuint *src = (const GLuint *) values;
362 GLuint *dst = (GLuint *) rb->Data + y * rb->Width + x;
363 ASSERT(rb->DataType == GL_UNSIGNED_INT ||
364 rb->DataType == GL_UNSIGNED_INT_24_8_EXT);
365 if (mask) {
366 GLuint i;
367 for (i = 0; i < count; i++) {
368 if (mask[i]) {
369 dst[i] = src[i];
370 }
371 }
372 }
373 else {
374 _mesa_memcpy(dst, src, count * sizeof(GLuint));
375 }
376 }
377
378
379 static void
380 put_mono_row_uint(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
381 GLint x, GLint y, const void *value, const GLubyte *mask)
382 {
383 const GLuint val = *((const GLuint *) value);
384 GLuint *dst = (GLuint *) rb->Data + y * rb->Width + x;
385 ASSERT(rb->DataType == GL_UNSIGNED_INT ||
386 rb->DataType == GL_UNSIGNED_INT_24_8_EXT);
387 if (mask) {
388 GLuint i;
389 for (i = 0; i < count; i++) {
390 if (mask[i]) {
391 dst[i] = val;
392 }
393 }
394 }
395 else {
396 GLuint i;
397 for (i = 0; i < count; i++) {
398 dst[i] = val;
399 }
400 }
401 }
402
403
404 static void
405 put_values_uint(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
406 const GLint x[], const GLint y[], const void *values,
407 const GLubyte *mask)
408 {
409 const GLuint *src = (const GLuint *) values;
410 GLuint i;
411 ASSERT(rb->DataType == GL_UNSIGNED_INT ||
412 rb->DataType == GL_UNSIGNED_INT_24_8_EXT);
413 for (i = 0; i < count; i++) {
414 if (!mask || mask[i]) {
415 GLuint *dst = (GLuint *) rb->Data + y[i] * rb->Width + x[i];
416 *dst = src[i];
417 }
418 }
419 }
420
421
422 static void
423 put_mono_values_uint(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
424 const GLint x[], const GLint y[], const void *value,
425 const GLubyte *mask)
426 {
427 const GLuint val = *((const GLuint *) value);
428 GLuint i;
429 ASSERT(rb->DataType == GL_UNSIGNED_INT ||
430 rb->DataType == GL_UNSIGNED_INT_24_8_EXT);
431 for (i = 0; i < count; i++) {
432 if (!mask || mask[i]) {
433 GLuint *dst = (GLuint *) rb->Data + y[i] * rb->Width + x[i];
434 *dst = val;
435 }
436 }
437 }
438
439
440 /**********************************************************************
441 * Functions for buffers of 3 X GLubyte (or GLbyte) values.
442 * Typically color buffers.
443 * NOTE: the incoming and outgoing colors are RGBA! We ignore incoming
444 * alpha values and return 255 for outgoing alpha values.
445 */
446
447 static void *
448 get_pointer_ubyte3(GLcontext *ctx, struct gl_renderbuffer *rb,
449 GLint x, GLint y)
450 {
451 ASSERT(rb->_ActualFormat == GL_RGB8);
452 /* No direct access since this buffer is RGB but caller will be
453 * treating it as if it were RGBA.
454 */
455 return NULL;
456 }
457
458
459 static void
460 get_row_ubyte3(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
461 GLint x, GLint y, void *values)
462 {
463 const GLubyte *src = (const GLubyte *) rb->Data + 3 * (y * rb->Width + x);
464 GLubyte *dst = (GLubyte *) values;
465 GLuint i;
466 ASSERT(rb->_ActualFormat == GL_RGB8);
467 ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
468 for (i = 0; i < count; i++) {
469 dst[i * 4 + 0] = src[i * 3 + 0];
470 dst[i * 4 + 1] = src[i * 3 + 1];
471 dst[i * 4 + 2] = src[i * 3 + 2];
472 dst[i * 4 + 3] = 255;
473 }
474 }
475
476
477 static void
478 get_values_ubyte3(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
479 const GLint x[], const GLint y[], void *values)
480 {
481 GLubyte *dst = (GLubyte *) values;
482 GLuint i;
483 ASSERT(rb->_ActualFormat == GL_RGB8);
484 ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
485 for (i = 0; i < count; i++) {
486 const GLubyte *src
487 = (GLubyte *) rb->Data + 3 * (y[i] * rb->Width + x[i]);
488 dst[i * 4 + 0] = src[0];
489 dst[i * 4 + 1] = src[1];
490 dst[i * 4 + 2] = src[2];
491 dst[i * 4 + 3] = 255;
492 }
493 }
494
495
496 static void
497 put_row_ubyte3(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
498 GLint x, GLint y, const void *values, const GLubyte *mask)
499 {
500 /* note: incoming values are RGB+A! */
501 const GLubyte *src = (const GLubyte *) values;
502 GLubyte *dst = (GLubyte *) rb->Data + 3 * (y * rb->Width + x);
503 GLuint i;
504 ASSERT(rb->_ActualFormat == GL_RGB8);
505 ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
506 for (i = 0; i < count; i++) {
507 if (!mask || mask[i]) {
508 dst[i * 3 + 0] = src[i * 4 + 0];
509 dst[i * 3 + 1] = src[i * 4 + 1];
510 dst[i * 3 + 2] = src[i * 4 + 2];
511 }
512 }
513 }
514
515
516 static void
517 put_row_rgb_ubyte3(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
518 GLint x, GLint y, const void *values, const GLubyte *mask)
519 {
520 /* note: incoming values are RGB+A! */
521 const GLubyte *src = (const GLubyte *) values;
522 GLubyte *dst = (GLubyte *) rb->Data + 3 * (y * rb->Width + x);
523 GLuint i;
524 ASSERT(rb->_ActualFormat == GL_RGB8);
525 ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
526 for (i = 0; i < count; i++) {
527 if (!mask || mask[i]) {
528 dst[i * 3 + 0] = src[i * 3 + 0];
529 dst[i * 3 + 1] = src[i * 3 + 1];
530 dst[i * 3 + 2] = src[i * 3 + 2];
531 }
532 }
533 }
534
535
536 static void
537 put_mono_row_ubyte3(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
538 GLint x, GLint y, const void *value, const GLubyte *mask)
539 {
540 /* note: incoming value is RGB+A! */
541 const GLubyte val0 = ((const GLubyte *) value)[0];
542 const GLubyte val1 = ((const GLubyte *) value)[1];
543 const GLubyte val2 = ((const GLubyte *) value)[2];
544 GLubyte *dst = (GLubyte *) rb->Data + 3 * (y * rb->Width + x);
545 ASSERT(rb->_ActualFormat == GL_RGB8);
546 ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
547 if (!mask && val0 == val1 && val1 == val2) {
548 /* optimized case */
549 _mesa_memset(dst, val0, 3 * count);
550 }
551 else {
552 GLuint i;
553 for (i = 0; i < count; i++) {
554 if (!mask || mask[i]) {
555 dst[i * 3 + 0] = val0;
556 dst[i * 3 + 1] = val1;
557 dst[i * 3 + 2] = val2;
558 }
559 }
560 }
561 }
562
563
564 static void
565 put_values_ubyte3(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
566 const GLint x[], const GLint y[], const void *values,
567 const GLubyte *mask)
568 {
569 /* note: incoming values are RGB+A! */
570 const GLubyte *src = (const GLubyte *) values;
571 GLuint i;
572 ASSERT(rb->_ActualFormat == GL_RGB8);
573 ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
574 for (i = 0; i < count; i++) {
575 if (!mask || mask[i]) {
576 GLubyte *dst = (GLubyte *) rb->Data + 3 * (y[i] * rb->Width + x[i]);
577 dst[0] = src[i * 4 + 0];
578 dst[1] = src[i * 4 + 1];
579 dst[2] = src[i * 4 + 2];
580 }
581 }
582 }
583
584
585 static void
586 put_mono_values_ubyte3(GLcontext *ctx, struct gl_renderbuffer *rb,
587 GLuint count, const GLint x[], const GLint y[],
588 const void *value, const GLubyte *mask)
589 {
590 /* note: incoming value is RGB+A! */
591 const GLubyte val0 = ((const GLubyte *) value)[0];
592 const GLubyte val1 = ((const GLubyte *) value)[1];
593 const GLubyte val2 = ((const GLubyte *) value)[2];
594 GLuint i;
595 ASSERT(rb->_ActualFormat == GL_RGB8);
596 ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
597 for (i = 0; i < count; i++) {
598 if (!mask || mask[i]) {
599 GLubyte *dst = (GLubyte *) rb->Data + 3 * (y[i] * rb->Width + x[i]);
600 dst[0] = val0;
601 dst[1] = val1;
602 dst[2] = val2;
603 }
604 }
605 }
606
607
608 /**********************************************************************
609 * Functions for buffers of 4 X GLubyte (or GLbyte) values.
610 * Typically color buffers.
611 */
612
613 static void *
614 get_pointer_ubyte4(GLcontext *ctx, struct gl_renderbuffer *rb,
615 GLint x, GLint y)
616 {
617 if (!rb->Data)
618 return NULL;
619 ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
620 ASSERT(rb->_ActualFormat == GL_RGBA8);
621 return (GLubyte *) rb->Data + 4 * (y * rb->Width + x);
622 }
623
624
625 static void
626 get_row_ubyte4(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
627 GLint x, GLint y, void *values)
628 {
629 const GLubyte *src = (const GLubyte *) rb->Data + 4 * (y * rb->Width + x);
630 ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
631 ASSERT(rb->_ActualFormat == GL_RGBA8);
632 _mesa_memcpy(values, src, 4 * count * sizeof(GLubyte));
633 }
634
635
636 static void
637 get_values_ubyte4(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
638 const GLint x[], const GLint y[], void *values)
639 {
640 /* treat 4*GLubyte as 1*GLuint */
641 GLuint *dst = (GLuint *) values;
642 GLuint i;
643 ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
644 ASSERT(rb->_ActualFormat == GL_RGBA8);
645 for (i = 0; i < count; i++) {
646 const GLuint *src = (GLuint *) rb->Data + (y[i] * rb->Width + x[i]);
647 dst[i] = *src;
648 }
649 }
650
651
652 static void
653 put_row_ubyte4(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
654 GLint x, GLint y, const void *values, const GLubyte *mask)
655 {
656 /* treat 4*GLubyte as 1*GLuint */
657 const GLuint *src = (const GLuint *) values;
658 GLuint *dst = (GLuint *) rb->Data + (y * rb->Width + x);
659 ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
660 ASSERT(rb->_ActualFormat == GL_RGBA8);
661 if (mask) {
662 GLuint i;
663 for (i = 0; i < count; i++) {
664 if (mask[i]) {
665 dst[i] = src[i];
666 }
667 }
668 }
669 else {
670 _mesa_memcpy(dst, src, 4 * count * sizeof(GLubyte));
671 }
672 }
673
674
675 static void
676 put_row_rgb_ubyte4(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
677 GLint x, GLint y, const void *values, const GLubyte *mask)
678 {
679 /* Store RGB values in RGBA buffer */
680 const GLubyte *src = (const GLubyte *) values;
681 GLubyte *dst = (GLubyte *) rb->Data + 4 * (y * rb->Width + x);
682 GLuint i;
683 ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
684 ASSERT(rb->_ActualFormat == GL_RGBA8);
685 for (i = 0; i < count; i++) {
686 if (!mask || mask[i]) {
687 dst[i * 4 + 0] = src[i * 3 + 0];
688 dst[i * 4 + 1] = src[i * 3 + 1];
689 dst[i * 4 + 2] = src[i * 3 + 2];
690 dst[i * 4 + 3] = 0xff;
691 }
692 }
693 }
694
695
696 static void
697 put_mono_row_ubyte4(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
698 GLint x, GLint y, const void *value, const GLubyte *mask)
699 {
700 /* treat 4*GLubyte as 1*GLuint */
701 const GLuint val = *((const GLuint *) value);
702 GLuint *dst = (GLuint *) rb->Data + (y * rb->Width + x);
703 ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
704 ASSERT(rb->_ActualFormat == GL_RGBA8);
705 if (!mask && val == 0) {
706 /* common case */
707 _mesa_bzero(dst, count * 4 * sizeof(GLubyte));
708 }
709 else {
710 /* general case */
711 if (mask) {
712 GLuint i;
713 for (i = 0; i < count; i++) {
714 if (mask[i]) {
715 dst[i] = val;
716 }
717 }
718 }
719 else {
720 GLuint i;
721 for (i = 0; i < count; i++) {
722 dst[i] = val;
723 }
724 }
725 }
726 }
727
728
729 static void
730 put_values_ubyte4(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
731 const GLint x[], const GLint y[], const void *values,
732 const GLubyte *mask)
733 {
734 /* treat 4*GLubyte as 1*GLuint */
735 const GLuint *src = (const GLuint *) values;
736 GLuint i;
737 ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
738 ASSERT(rb->_ActualFormat == GL_RGBA8);
739 for (i = 0; i < count; i++) {
740 if (!mask || mask[i]) {
741 GLuint *dst = (GLuint *) rb->Data + (y[i] * rb->Width + x[i]);
742 *dst = src[i];
743 }
744 }
745 }
746
747
748 static void
749 put_mono_values_ubyte4(GLcontext *ctx, struct gl_renderbuffer *rb,
750 GLuint count, const GLint x[], const GLint y[],
751 const void *value, const GLubyte *mask)
752 {
753 /* treat 4*GLubyte as 1*GLuint */
754 const GLuint val = *((const GLuint *) value);
755 GLuint i;
756 ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
757 ASSERT(rb->_ActualFormat == GL_RGBA8);
758 for (i = 0; i < count; i++) {
759 if (!mask || mask[i]) {
760 GLuint *dst = (GLuint *) rb->Data + (y[i] * rb->Width + x[i]);
761 *dst = val;
762 }
763 }
764 }
765
766
767 /**********************************************************************
768 * Functions for buffers of 4 X GLushort (or GLshort) values.
769 * Typically accum buffer.
770 */
771
772 static void *
773 get_pointer_ushort4(GLcontext *ctx, struct gl_renderbuffer *rb,
774 GLint x, GLint y)
775 {
776 if (!rb->Data)
777 return NULL;
778 ASSERT(rb->DataType == GL_UNSIGNED_SHORT || rb->DataType == GL_SHORT);
779 return (GLushort *) rb->Data + 4 * (y * rb->Width + x);
780 }
781
782
783 static void
784 get_row_ushort4(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
785 GLint x, GLint y, void *values)
786 {
787 const GLshort *src = (const GLshort *) rb->Data + 4 * (y * rb->Width + x);
788 ASSERT(rb->DataType == GL_UNSIGNED_SHORT || rb->DataType == GL_SHORT);
789 _mesa_memcpy(values, src, 4 * count * sizeof(GLshort));
790 }
791
792
793 static void
794 get_values_ushort4(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
795 const GLint x[], const GLint y[], void *values)
796 {
797 GLushort *dst = (GLushort *) values;
798 GLuint i;
799 ASSERT(rb->DataType == GL_UNSIGNED_SHORT || rb->DataType == GL_SHORT);
800 for (i = 0; i < count; i++) {
801 const GLushort *src
802 = (GLushort *) rb->Data + 4 * (y[i] * rb->Width + x[i]);
803 dst[i] = *src;
804 }
805 }
806
807
808 static void
809 put_row_ushort4(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
810 GLint x, GLint y, const void *values, const GLubyte *mask)
811 {
812 const GLushort *src = (const GLushort *) values;
813 GLushort *dst = (GLushort *) rb->Data + 4 * (y * rb->Width + x);
814 ASSERT(rb->DataType == GL_UNSIGNED_SHORT || rb->DataType == GL_SHORT);
815 if (mask) {
816 GLuint i;
817 for (i = 0; i < count; i++) {
818 if (mask[i]) {
819 dst[i * 4 + 0] = src[i * 4 + 0];
820 dst[i * 4 + 1] = src[i * 4 + 1];
821 dst[i * 4 + 2] = src[i * 4 + 2];
822 dst[i * 4 + 3] = src[i * 4 + 3];
823 }
824 }
825 }
826 else {
827 _mesa_memcpy(dst, src, 4 * count * sizeof(GLushort));
828 }
829 }
830
831
832 static void
833 put_row_rgb_ushort4(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
834 GLint x, GLint y, const void *values, const GLubyte *mask)
835 {
836 /* Put RGB values in RGBA buffer */
837 const GLushort *src = (const GLushort *) values;
838 GLushort *dst = (GLushort *) rb->Data + 4 * (y * rb->Width + x);
839 ASSERT(rb->DataType == GL_UNSIGNED_SHORT || rb->DataType == GL_SHORT);
840 if (mask) {
841 GLuint i;
842 for (i = 0; i < count; i++) {
843 if (mask[i]) {
844 dst[i * 4 + 0] = src[i * 3 + 0];
845 dst[i * 4 + 1] = src[i * 3 + 1];
846 dst[i * 4 + 2] = src[i * 3 + 2];
847 dst[i * 4 + 3] = 0xffff;
848 }
849 }
850 }
851 else {
852 _mesa_memcpy(dst, src, 4 * count * sizeof(GLushort));
853 }
854 }
855
856
857 static void
858 put_mono_row_ushort4(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
859 GLint x, GLint y, const void *value, const GLubyte *mask)
860 {
861 const GLushort val0 = ((const GLushort *) value)[0];
862 const GLushort val1 = ((const GLushort *) value)[1];
863 const GLushort val2 = ((const GLushort *) value)[2];
864 const GLushort val3 = ((const GLushort *) value)[3];
865 GLushort *dst = (GLushort *) rb->Data + 4 * (y * rb->Width + x);
866 ASSERT(rb->DataType == GL_UNSIGNED_SHORT || rb->DataType == GL_SHORT);
867 if (!mask && val0 == 0 && val1 == 0 && val2 == 0 && val3 == 0) {
868 /* common case for clearing accum buffer */
869 _mesa_bzero(dst, count * 4 * sizeof(GLushort));
870 }
871 else {
872 GLuint i;
873 for (i = 0; i < count; i++) {
874 if (!mask || mask[i]) {
875 dst[i * 4 + 0] = val0;
876 dst[i * 4 + 1] = val1;
877 dst[i * 4 + 2] = val2;
878 dst[i * 4 + 3] = val3;
879 }
880 }
881 }
882 }
883
884
885 static void
886 put_values_ushort4(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
887 const GLint x[], const GLint y[], const void *values,
888 const GLubyte *mask)
889 {
890 const GLushort *src = (const GLushort *) values;
891 GLuint i;
892 ASSERT(rb->DataType == GL_UNSIGNED_SHORT || rb->DataType == GL_SHORT);
893 for (i = 0; i < count; i++) {
894 if (!mask || mask[i]) {
895 GLushort *dst = (GLushort *) rb->Data + 4 * (y[i] * rb->Width + x[i]);
896 dst[0] = src[i * 4 + 0];
897 dst[1] = src[i * 4 + 1];
898 dst[2] = src[i * 4 + 2];
899 dst[3] = src[i * 4 + 3];
900 }
901 }
902 }
903
904
905 static void
906 put_mono_values_ushort4(GLcontext *ctx, struct gl_renderbuffer *rb,
907 GLuint count, const GLint x[], const GLint y[],
908 const void *value, const GLubyte *mask)
909 {
910 const GLushort val0 = ((const GLushort *) value)[0];
911 const GLushort val1 = ((const GLushort *) value)[1];
912 const GLushort val2 = ((const GLushort *) value)[2];
913 const GLushort val3 = ((const GLushort *) value)[3];
914 GLuint i;
915 ASSERT(rb->DataType == GL_UNSIGNED_SHORT || rb->DataType == GL_SHORT);
916 for (i = 0; i < count; i++) {
917 if (!mask || mask[i]) {
918 GLushort *dst = (GLushort *) rb->Data + 4 * (y[i] * rb->Width + x[i]);
919 dst[0] = val0;
920 dst[1] = val1;
921 dst[2] = val2;
922 dst[3] = val3;
923 }
924 }
925 }
926
927
928
929 /**
930 * This is a software fallback for the gl_renderbuffer->AllocStorage
931 * function.
932 * Device drivers will typically override this function for the buffers
933 * which it manages (typically color buffers, Z and stencil).
934 * Other buffers (like software accumulation and aux buffers) which the driver
935 * doesn't manage can be handled with this function.
936 *
937 * This one multi-purpose function can allocate stencil, depth, accum, color
938 * or color-index buffers!
939 *
940 * This function also plugs in the appropriate GetPointer, Get/PutRow and
941 * Get/PutValues functions.
942 */
943 GLboolean
944 _mesa_soft_renderbuffer_storage(GLcontext *ctx, struct gl_renderbuffer *rb,
945 GLenum internalFormat,
946 GLuint width, GLuint height)
947 {
948 GLuint pixelSize;
949
950 /* first clear these fields */
951 rb->RedBits =
952 rb->GreenBits =
953 rb->BlueBits =
954 rb->AlphaBits =
955 rb->IndexBits =
956 rb->DepthBits =
957 rb->StencilBits = 0;
958
959 switch (internalFormat) {
960 case GL_RGB:
961 case GL_R3_G3_B2:
962 case GL_RGB4:
963 case GL_RGB5:
964 case GL_RGB8:
965 case GL_RGB10:
966 case GL_RGB12:
967 case GL_RGB16:
968 rb->_ActualFormat = GL_RGB8;
969 rb->_BaseFormat = GL_RGB;
970 rb->DataType = GL_UNSIGNED_BYTE;
971 rb->GetPointer = get_pointer_ubyte3;
972 rb->GetRow = get_row_ubyte3;
973 rb->GetValues = get_values_ubyte3;
974 rb->PutRow = put_row_ubyte3;
975 rb->PutRowRGB = put_row_rgb_ubyte3;
976 rb->PutMonoRow = put_mono_row_ubyte3;
977 rb->PutValues = put_values_ubyte3;
978 rb->PutMonoValues = put_mono_values_ubyte3;
979 rb->RedBits = 8 * sizeof(GLubyte);
980 rb->GreenBits = 8 * sizeof(GLubyte);
981 rb->BlueBits = 8 * sizeof(GLubyte);
982 rb->AlphaBits = 0;
983 pixelSize = 3 * sizeof(GLubyte);
984 break;
985 case GL_RGBA:
986 case GL_RGBA2:
987 case GL_RGBA4:
988 case GL_RGB5_A1:
989 case GL_RGBA8:
990 rb->_ActualFormat = GL_RGBA8;
991 rb->_BaseFormat = GL_RGBA;
992 rb->DataType = GL_UNSIGNED_BYTE;
993 rb->GetPointer = get_pointer_ubyte4;
994 rb->GetRow = get_row_ubyte4;
995 rb->GetValues = get_values_ubyte4;
996 rb->PutRow = put_row_ubyte4;
997 rb->PutRowRGB = put_row_rgb_ubyte4;
998 rb->PutMonoRow = put_mono_row_ubyte4;
999 rb->PutValues = put_values_ubyte4;
1000 rb->PutMonoValues = put_mono_values_ubyte4;
1001 rb->RedBits = 8 * sizeof(GLubyte);
1002 rb->GreenBits = 8 * sizeof(GLubyte);
1003 rb->BlueBits = 8 * sizeof(GLubyte);
1004 rb->AlphaBits = 8 * sizeof(GLubyte);
1005 pixelSize = 4 * sizeof(GLubyte);
1006 break;
1007 case GL_RGB10_A2:
1008 case GL_RGBA12:
1009 case GL_RGBA16:
1010 rb->_ActualFormat = GL_RGBA16;
1011 rb->_BaseFormat = GL_RGBA;
1012 rb->DataType = GL_UNSIGNED_SHORT;
1013 rb->GetPointer = get_pointer_ushort4;
1014 rb->GetRow = get_row_ushort4;
1015 rb->GetValues = get_values_ushort4;
1016 rb->PutRow = put_row_ushort4;
1017 rb->PutRowRGB = put_row_rgb_ushort4;
1018 rb->PutMonoRow = put_mono_row_ushort4;
1019 rb->PutValues = put_values_ushort4;
1020 rb->PutMonoValues = put_mono_values_ushort4;
1021 rb->RedBits = 8 * sizeof(GLushort);
1022 rb->GreenBits = 8 * sizeof(GLushort);
1023 rb->BlueBits = 8 * sizeof(GLushort);
1024 rb->AlphaBits = 8 * sizeof(GLushort);
1025 pixelSize = 4 * sizeof(GLushort);
1026 break;
1027 #if 00
1028 case GL_ALPHA8:
1029 rb->_ActualFormat = GL_ALPHA8;
1030 rb->_BaseFormat = GL_RGBA; /* Yes, not GL_ALPHA! */
1031 rb->DataType = GL_UNSIGNED_BYTE;
1032 rb->GetPointer = get_pointer_alpha8;
1033 rb->GetRow = get_row_alpha8;
1034 rb->GetValues = get_values_alpha8;
1035 rb->PutRow = put_row_alpha8;
1036 rb->PutRowRGB = NULL;
1037 rb->PutMonoRow = put_mono_row_alpha8;
1038 rb->PutValues = put_values_alpha8;
1039 rb->PutMonoValues = put_mono_values_alpha8;
1040 rb->RedBits = 0; /*red*/
1041 rb->GreenBits = 0; /*green*/
1042 rb->BlueBits = 0; /*blue*/
1043 rb->AlphaBits = 8 * sizeof(GLubyte);
1044 pixelSize = sizeof(GLubyte);
1045 break;
1046 #endif
1047 case GL_STENCIL_INDEX:
1048 case GL_STENCIL_INDEX1_EXT:
1049 case GL_STENCIL_INDEX4_EXT:
1050 case GL_STENCIL_INDEX8_EXT:
1051 rb->_ActualFormat = GL_STENCIL_INDEX8_EXT;
1052 rb->_BaseFormat = GL_STENCIL_INDEX;
1053 rb->DataType = GL_UNSIGNED_BYTE;
1054 rb->GetPointer = get_pointer_ubyte;
1055 rb->GetRow = get_row_ubyte;
1056 rb->GetValues = get_values_ubyte;
1057 rb->PutRow = put_row_ubyte;
1058 rb->PutRowRGB = NULL;
1059 rb->PutMonoRow = put_mono_row_ubyte;
1060 rb->PutValues = put_values_ubyte;
1061 rb->PutMonoValues = put_mono_values_ubyte;
1062 rb->StencilBits = 8 * sizeof(GLubyte);
1063 pixelSize = sizeof(GLubyte);
1064 break;
1065 case GL_STENCIL_INDEX16_EXT:
1066 rb->_ActualFormat = GL_STENCIL_INDEX16_EXT;
1067 rb->_BaseFormat = GL_STENCIL_INDEX;
1068 rb->DataType = GL_UNSIGNED_SHORT;
1069 rb->GetPointer = get_pointer_ushort;
1070 rb->GetRow = get_row_ushort;
1071 rb->GetValues = get_values_ushort;
1072 rb->PutRow = put_row_ushort;
1073 rb->PutRowRGB = NULL;
1074 rb->PutMonoRow = put_mono_row_ushort;
1075 rb->PutValues = put_values_ushort;
1076 rb->PutMonoValues = put_mono_values_ushort;
1077 rb->StencilBits = 8 * sizeof(GLushort);
1078 pixelSize = sizeof(GLushort);
1079 break;
1080 case GL_DEPTH_COMPONENT:
1081 case GL_DEPTH_COMPONENT16:
1082 rb->_ActualFormat = GL_DEPTH_COMPONENT16;
1083 rb->_BaseFormat = GL_DEPTH_COMPONENT;
1084 rb->DataType = GL_UNSIGNED_SHORT;
1085 rb->GetPointer = get_pointer_ushort;
1086 rb->GetRow = get_row_ushort;
1087 rb->GetValues = get_values_ushort;
1088 rb->PutRow = put_row_ushort;
1089 rb->PutRowRGB = NULL;
1090 rb->PutMonoRow = put_mono_row_ushort;
1091 rb->PutValues = put_values_ushort;
1092 rb->PutMonoValues = put_mono_values_ushort;
1093 rb->DepthBits = 8 * sizeof(GLushort);
1094 pixelSize = sizeof(GLushort);
1095 break;
1096 case GL_DEPTH_COMPONENT24:
1097 case GL_DEPTH_COMPONENT32:
1098 rb->_BaseFormat = GL_DEPTH_COMPONENT;
1099 rb->DataType = GL_UNSIGNED_INT;
1100 rb->GetPointer = get_pointer_uint;
1101 rb->GetRow = get_row_uint;
1102 rb->GetValues = get_values_uint;
1103 rb->PutRow = put_row_uint;
1104 rb->PutRowRGB = NULL;
1105 rb->PutMonoRow = put_mono_row_uint;
1106 rb->PutValues = put_values_uint;
1107 rb->PutMonoValues = put_mono_values_uint;
1108 if (internalFormat == GL_DEPTH_COMPONENT24) {
1109 rb->_ActualFormat = GL_DEPTH_COMPONENT24;
1110 rb->DepthBits = 24;
1111 }
1112 else {
1113 rb->_ActualFormat = GL_DEPTH_COMPONENT32;
1114 rb->DepthBits = 32;
1115 }
1116 pixelSize = sizeof(GLuint);
1117 break;
1118 case GL_DEPTH_STENCIL_EXT:
1119 case GL_DEPTH24_STENCIL8_EXT:
1120 rb->_ActualFormat = GL_DEPTH24_STENCIL8_EXT;
1121 rb->_BaseFormat = GL_DEPTH_STENCIL_EXT;
1122 rb->DataType = GL_UNSIGNED_INT_24_8_EXT;
1123 rb->GetPointer = get_pointer_uint;
1124 rb->GetRow = get_row_uint;
1125 rb->GetValues = get_values_uint;
1126 rb->PutRow = put_row_uint;
1127 rb->PutRowRGB = NULL;
1128 rb->PutMonoRow = put_mono_row_uint;
1129 rb->PutValues = put_values_uint;
1130 rb->PutMonoValues = put_mono_values_uint;
1131 rb->DepthBits = 24;
1132 rb->StencilBits = 8;
1133 pixelSize = sizeof(GLuint);
1134 break;
1135 case GL_COLOR_INDEX8_EXT:
1136 rb->_ActualFormat = GL_COLOR_INDEX8_EXT;
1137 rb->_BaseFormat = GL_COLOR_INDEX;
1138 rb->DataType = GL_UNSIGNED_BYTE;
1139 rb->GetPointer = get_pointer_ubyte;
1140 rb->GetRow = get_row_ubyte;
1141 rb->GetValues = get_values_ubyte;
1142 rb->PutRow = put_row_ubyte;
1143 rb->PutRowRGB = NULL;
1144 rb->PutMonoRow = put_mono_row_ubyte;
1145 rb->PutValues = put_values_ubyte;
1146 rb->PutMonoValues = put_mono_values_ubyte;
1147 rb->IndexBits = 8 * sizeof(GLubyte);
1148 pixelSize = sizeof(GLubyte);
1149 break;
1150 case GL_COLOR_INDEX16_EXT:
1151 rb->_ActualFormat = GL_COLOR_INDEX16_EXT;
1152 rb->_BaseFormat = GL_COLOR_INDEX;
1153 rb->DataType = GL_UNSIGNED_SHORT;
1154 rb->GetPointer = get_pointer_ushort;
1155 rb->GetRow = get_row_ushort;
1156 rb->GetValues = get_values_ushort;
1157 rb->PutRow = put_row_ushort;
1158 rb->PutRowRGB = NULL;
1159 rb->PutMonoRow = put_mono_row_ushort;
1160 rb->PutValues = put_values_ushort;
1161 rb->PutMonoValues = put_mono_values_ushort;
1162 rb->IndexBits = 8 * sizeof(GLushort);
1163 pixelSize = sizeof(GLushort);
1164 break;
1165 case COLOR_INDEX32:
1166 rb->_ActualFormat = COLOR_INDEX32;
1167 rb->_BaseFormat = GL_COLOR_INDEX;
1168 rb->DataType = GL_UNSIGNED_INT;
1169 rb->GetPointer = get_pointer_uint;
1170 rb->GetRow = get_row_uint;
1171 rb->GetValues = get_values_uint;
1172 rb->PutRow = put_row_uint;
1173 rb->PutRowRGB = NULL;
1174 rb->PutMonoRow = put_mono_row_uint;
1175 rb->PutValues = put_values_uint;
1176 rb->PutMonoValues = put_mono_values_uint;
1177 rb->IndexBits = 8 * sizeof(GLuint);
1178 pixelSize = sizeof(GLuint);
1179 break;
1180 default:
1181 _mesa_problem(ctx, "Bad internalFormat in _mesa_soft_renderbuffer_storage");
1182 return GL_FALSE;
1183 }
1184
1185 ASSERT(rb->DataType);
1186 ASSERT(rb->GetPointer);
1187 ASSERT(rb->GetRow);
1188 ASSERT(rb->GetValues);
1189 ASSERT(rb->PutRow);
1190 ASSERT(rb->PutMonoRow);
1191 ASSERT(rb->PutValues);
1192 ASSERT(rb->PutMonoValues);
1193
1194 /* free old buffer storage */
1195 if (rb->Data) {
1196 _mesa_free(rb->Data);
1197 rb->Data = NULL;
1198 }
1199
1200 if (width > 0 && height > 0) {
1201 /* allocate new buffer storage */
1202 rb->Data = malloc(width * height * pixelSize);
1203
1204 if (rb->Data == NULL) {
1205 rb->Width = 0;
1206 rb->Height = 0;
1207 _mesa_error(ctx, GL_OUT_OF_MEMORY,
1208 "software renderbuffer allocation (%d x %d x %d)",
1209 width, height, pixelSize);
1210 return GL_FALSE;
1211 }
1212 }
1213
1214 rb->Width = width;
1215 rb->Height = height;
1216
1217 return GL_TRUE;
1218 }
1219
1220
1221
1222 /**********************************************************************/
1223 /**********************************************************************/
1224 /**********************************************************************/
1225
1226
1227 /**
1228 * Here we utilize the gl_renderbuffer->Wrapper field to put an alpha
1229 * buffer wrapper around an existing RGB renderbuffer (hw or sw).
1230 *
1231 * When PutRow is called (for example), we store the alpha values in
1232 * this buffer, then pass on the PutRow call to the wrapped RGB
1233 * buffer.
1234 */
1235
1236
1237 static GLboolean
1238 alloc_storage_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb,
1239 GLenum internalFormat, GLuint width, GLuint height)
1240 {
1241 ASSERT(arb != arb->Wrapped);
1242 ASSERT(arb->_ActualFormat == GL_ALPHA8);
1243
1244 /* first, pass the call to the wrapped RGB buffer */
1245 if (!arb->Wrapped->AllocStorage(ctx, arb->Wrapped, internalFormat,
1246 width, height)) {
1247 return GL_FALSE;
1248 }
1249
1250 /* next, resize my alpha buffer */
1251 if (arb->Data) {
1252 _mesa_free(arb->Data);
1253 }
1254
1255 arb->Data = _mesa_malloc(width * height * sizeof(GLubyte));
1256 if (arb->Data == NULL) {
1257 arb->Width = 0;
1258 arb->Height = 0;
1259 _mesa_error(ctx, GL_OUT_OF_MEMORY, "software alpha buffer allocation");
1260 return GL_FALSE;
1261 }
1262
1263 arb->Width = width;
1264 arb->Height = height;
1265
1266 return GL_TRUE;
1267 }
1268
1269
1270 /**
1271 * Delete an alpha_renderbuffer object, as well as the wrapped RGB buffer.
1272 */
1273 static void
1274 delete_renderbuffer_alpha8(struct gl_renderbuffer *arb)
1275 {
1276 if (arb->Data) {
1277 _mesa_free(arb->Data);
1278 }
1279 ASSERT(arb->Wrapped);
1280 ASSERT(arb != arb->Wrapped);
1281 arb->Wrapped->Delete(arb->Wrapped);
1282 arb->Wrapped = NULL;
1283 _mesa_free(arb);
1284 }
1285
1286
1287 static void *
1288 get_pointer_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb,
1289 GLint x, GLint y)
1290 {
1291 return NULL; /* don't allow direct access! */
1292 }
1293
1294
1295 static void
1296 get_row_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, GLuint count,
1297 GLint x, GLint y, void *values)
1298 {
1299 /* NOTE: 'values' is RGBA format! */
1300 const GLubyte *src = (const GLubyte *) arb->Data + y * arb->Width + x;
1301 GLubyte *dst = (GLubyte *) values;
1302 GLuint i;
1303 ASSERT(arb != arb->Wrapped);
1304 ASSERT(arb->DataType == GL_UNSIGNED_BYTE);
1305 /* first, pass the call to the wrapped RGB buffer */
1306 arb->Wrapped->GetRow(ctx, arb->Wrapped, count, x, y, values);
1307 /* second, fill in alpha values from this buffer! */
1308 for (i = 0; i < count; i++) {
1309 dst[i * 4 + 3] = src[i];
1310 }
1311 }
1312
1313
1314 static void
1315 get_values_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, GLuint count,
1316 const GLint x[], const GLint y[], void *values)
1317 {
1318 GLubyte *dst = (GLubyte *) values;
1319 GLuint i;
1320 ASSERT(arb != arb->Wrapped);
1321 ASSERT(arb->DataType == GL_UNSIGNED_BYTE);
1322 /* first, pass the call to the wrapped RGB buffer */
1323 arb->Wrapped->GetValues(ctx, arb->Wrapped, count, x, y, values);
1324 /* second, fill in alpha values from this buffer! */
1325 for (i = 0; i < count; i++) {
1326 const GLubyte *src = (GLubyte *) arb->Data + y[i] * arb->Width + x[i];
1327 dst[i * 4 + 3] = *src;
1328 }
1329 }
1330
1331
1332 static void
1333 put_row_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, GLuint count,
1334 GLint x, GLint y, const void *values, const GLubyte *mask)
1335 {
1336 const GLubyte *src = (const GLubyte *) values;
1337 GLubyte *dst = (GLubyte *) arb->Data + y * arb->Width + x;
1338 GLuint i;
1339 ASSERT(arb != arb->Wrapped);
1340 ASSERT(arb->DataType == GL_UNSIGNED_BYTE);
1341 /* first, pass the call to the wrapped RGB buffer */
1342 arb->Wrapped->PutRow(ctx, arb->Wrapped, count, x, y, values, mask);
1343 /* second, store alpha in our buffer */
1344 for (i = 0; i < count; i++) {
1345 if (!mask || mask[i]) {
1346 dst[i] = src[i * 4 + 3];
1347 }
1348 }
1349 }
1350
1351
1352 static void
1353 put_row_rgb_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, GLuint count,
1354 GLint x, GLint y, const void *values, const GLubyte *mask)
1355 {
1356 const GLubyte *src = (const GLubyte *) values;
1357 GLubyte *dst = (GLubyte *) arb->Data + y * arb->Width + x;
1358 GLuint i;
1359 ASSERT(arb != arb->Wrapped);
1360 ASSERT(arb->DataType == GL_UNSIGNED_BYTE);
1361 /* first, pass the call to the wrapped RGB buffer */
1362 arb->Wrapped->PutRowRGB(ctx, arb->Wrapped, count, x, y, values, mask);
1363 /* second, store alpha in our buffer */
1364 for (i = 0; i < count; i++) {
1365 if (!mask || mask[i]) {
1366 dst[i] = src[i * 4 + 3];
1367 }
1368 }
1369 }
1370
1371
1372 static void
1373 put_mono_row_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, GLuint count,
1374 GLint x, GLint y, const void *value, const GLubyte *mask)
1375 {
1376 const GLubyte val = ((const GLubyte *) value)[3];
1377 GLubyte *dst = (GLubyte *) arb->Data + y * arb->Width + x;
1378 ASSERT(arb != arb->Wrapped);
1379 ASSERT(arb->DataType == GL_UNSIGNED_BYTE);
1380 /* first, pass the call to the wrapped RGB buffer */
1381 arb->Wrapped->PutMonoRow(ctx, arb->Wrapped, count, x, y, value, mask);
1382 /* second, store alpha in our buffer */
1383 if (mask) {
1384 GLuint i;
1385 for (i = 0; i < count; i++) {
1386 if (mask[i]) {
1387 dst[i] = val;
1388 }
1389 }
1390 }
1391 else {
1392 _mesa_memset(dst, val, count);
1393 }
1394 }
1395
1396
1397 static void
1398 put_values_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, GLuint count,
1399 const GLint x[], const GLint y[],
1400 const void *values, const GLubyte *mask)
1401 {
1402 const GLubyte *src = (const GLubyte *) values;
1403 GLuint i;
1404 ASSERT(arb != arb->Wrapped);
1405 ASSERT(arb->DataType == GL_UNSIGNED_BYTE);
1406 /* first, pass the call to the wrapped RGB buffer */
1407 arb->Wrapped->PutValues(ctx, arb->Wrapped, count, x, y, values, mask);
1408 /* second, store alpha in our buffer */
1409 for (i = 0; i < count; i++) {
1410 if (!mask || mask[i]) {
1411 GLubyte *dst = (GLubyte *) arb->Data + y[i] * arb->Width + x[i];
1412 *dst = src[i * 4 + 3];
1413 }
1414 }
1415 }
1416
1417
1418 static void
1419 put_mono_values_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb,
1420 GLuint count, const GLint x[], const GLint y[],
1421 const void *value, const GLubyte *mask)
1422 {
1423 const GLubyte val = ((const GLubyte *) value)[3];
1424 GLuint i;
1425 ASSERT(arb != arb->Wrapped);
1426 ASSERT(arb->DataType == GL_UNSIGNED_BYTE);
1427 /* first, pass the call to the wrapped RGB buffer */
1428 arb->Wrapped->PutValues(ctx, arb->Wrapped, count, x, y, value, mask);
1429 /* second, store alpha in our buffer */
1430 for (i = 0; i < count; i++) {
1431 if (!mask || mask[i]) {
1432 GLubyte *dst = (GLubyte *) arb->Data + y[i] * arb->Width + x[i];
1433 *dst = val;
1434 }
1435 }
1436 }
1437
1438
1439 static void
1440 copy_buffer_alpha8(struct gl_renderbuffer* dst, struct gl_renderbuffer* src)
1441 {
1442 ASSERT(dst->_ActualFormat == GL_ALPHA8);
1443 ASSERT(src->_ActualFormat == GL_ALPHA8);
1444 ASSERT(dst->Width == src->Width);
1445 ASSERT(dst->Height == src->Height);
1446
1447 _mesa_memcpy(dst->Data, src->Data, dst->Width * dst->Height * sizeof(GLubyte));
1448 }
1449
1450
1451 /**********************************************************************/
1452 /**********************************************************************/
1453 /**********************************************************************/
1454
1455
1456 /**
1457 * Default GetPointer routine. Always return NULL to indicate that
1458 * direct buffer access is not supported.
1459 */
1460 static void *
1461 nop_get_pointer(GLcontext *ctx, struct gl_renderbuffer *rb, GLint x, GLint y)
1462 {
1463 return NULL;
1464 }
1465
1466
1467 /**
1468 * Initialize the fields of a gl_renderbuffer to default values.
1469 */
1470 void
1471 _mesa_init_renderbuffer(struct gl_renderbuffer *rb, GLuint name)
1472 {
1473 _glthread_INIT_MUTEX(rb->Mutex);
1474
1475 rb->Magic = RB_MAGIC;
1476 rb->ClassID = 0;
1477 rb->Name = name;
1478 rb->RefCount = 0;
1479 rb->Delete = _mesa_delete_renderbuffer;
1480
1481 /* The rest of these should be set later by the caller of this function or
1482 * the AllocStorage method:
1483 */
1484 rb->AllocStorage = NULL;
1485
1486 rb->Width = 0;
1487 rb->Height = 0;
1488 rb->InternalFormat = GL_NONE;
1489 rb->_ActualFormat = GL_NONE;
1490 rb->_BaseFormat = GL_NONE;
1491
1492 rb->ComponentType = GL_UNSIGNED_NORMALIZED; /* ARB_fbo */
1493 rb->ColorEncoding = GL_LINEAR; /* ARB_fbo */
1494
1495 rb->RedBits = rb->GreenBits = rb->BlueBits = rb->AlphaBits = 0;
1496 rb->IndexBits = 0;
1497 rb->DepthBits = 0;
1498 rb->StencilBits = 0;
1499
1500 rb->DataType = GL_NONE;
1501 rb->Data = NULL;
1502
1503 /* Point back to ourself so that we don't have to check for Wrapped==NULL
1504 * all over the drivers.
1505 */
1506 rb->Wrapped = rb;
1507
1508 rb->GetPointer = nop_get_pointer;
1509 rb->GetRow = NULL;
1510 rb->GetValues = NULL;
1511 rb->PutRow = NULL;
1512 rb->PutRowRGB = NULL;
1513 rb->PutMonoRow = NULL;
1514 rb->PutValues = NULL;
1515 rb->PutMonoValues = NULL;
1516 }
1517
1518
1519 /**
1520 * Allocate a new gl_renderbuffer object. This can be used for user-created
1521 * renderbuffers or window-system renderbuffers.
1522 */
1523 struct gl_renderbuffer *
1524 _mesa_new_renderbuffer(GLcontext *ctx, GLuint name)
1525 {
1526 struct gl_renderbuffer *rb = CALLOC_STRUCT(gl_renderbuffer);
1527 if (rb) {
1528 _mesa_init_renderbuffer(rb, name);
1529 }
1530 return rb;
1531 }
1532
1533
1534 /**
1535 * Delete a gl_framebuffer.
1536 * This is the default function for renderbuffer->Delete().
1537 */
1538 void
1539 _mesa_delete_renderbuffer(struct gl_renderbuffer *rb)
1540 {
1541 if (rb->Data) {
1542 _mesa_free(rb->Data);
1543 }
1544 _mesa_free(rb);
1545 }
1546
1547
1548 /**
1549 * Allocate a software-based renderbuffer. This is called via the
1550 * ctx->Driver.NewRenderbuffer() function when the user creates a new
1551 * renderbuffer.
1552 * This would not be used for hardware-based renderbuffers.
1553 */
1554 struct gl_renderbuffer *
1555 _mesa_new_soft_renderbuffer(GLcontext *ctx, GLuint name)
1556 {
1557 struct gl_renderbuffer *rb = _mesa_new_renderbuffer(ctx, name);
1558 if (rb) {
1559 rb->AllocStorage = _mesa_soft_renderbuffer_storage;
1560 /* Normally, one would setup the PutRow, GetRow, etc functions here.
1561 * But we're doing that in the _mesa_soft_renderbuffer_storage() function
1562 * instead.
1563 */
1564 }
1565 return rb;
1566 }
1567
1568
1569 /**
1570 * Add software-based color renderbuffers to the given framebuffer.
1571 * This is a helper routine for device drivers when creating a
1572 * window system framebuffer (not a user-created render/framebuffer).
1573 * Once this function is called, you can basically forget about this
1574 * renderbuffer; core Mesa will handle all the buffer management and
1575 * rendering!
1576 */
1577 GLboolean
1578 _mesa_add_color_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb,
1579 GLuint rgbBits, GLuint alphaBits,
1580 GLboolean frontLeft, GLboolean backLeft,
1581 GLboolean frontRight, GLboolean backRight)
1582 {
1583 GLuint b;
1584
1585 if (rgbBits > 16 || alphaBits > 16) {
1586 _mesa_problem(ctx,
1587 "Unsupported bit depth in _mesa_add_color_renderbuffers");
1588 return GL_FALSE;
1589 }
1590
1591 assert(MAX_COLOR_ATTACHMENTS >= 4);
1592
1593 for (b = BUFFER_FRONT_LEFT; b <= BUFFER_BACK_RIGHT; b++) {
1594 struct gl_renderbuffer *rb;
1595
1596 if (b == BUFFER_FRONT_LEFT && !frontLeft)
1597 continue;
1598 else if (b == BUFFER_BACK_LEFT && !backLeft)
1599 continue;
1600 else if (b == BUFFER_FRONT_RIGHT && !frontRight)
1601 continue;
1602 else if (b == BUFFER_BACK_RIGHT && !backRight)
1603 continue;
1604
1605 assert(fb->Attachment[b].Renderbuffer == NULL);
1606
1607 rb = _mesa_new_renderbuffer(ctx, 0);
1608 if (!rb) {
1609 _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating color buffer");
1610 return GL_FALSE;
1611 }
1612
1613 if (rgbBits <= 8) {
1614 if (alphaBits)
1615 rb->_ActualFormat = GL_RGBA8;
1616 else
1617 rb->_ActualFormat = GL_RGB8;
1618 }
1619 else {
1620 assert(rgbBits <= 16);
1621 if (alphaBits)
1622 rb->_ActualFormat = GL_RGBA16;
1623 else
1624 rb->_ActualFormat = GL_RGBA16; /* don't really have RGB16 yet */
1625 }
1626 rb->InternalFormat = rb->_ActualFormat;
1627
1628 rb->AllocStorage = _mesa_soft_renderbuffer_storage;
1629 _mesa_add_renderbuffer(fb, b, rb);
1630 }
1631
1632 return GL_TRUE;
1633 }
1634
1635
1636 /**
1637 * Add software-based color index renderbuffers to the given framebuffer.
1638 * This is a helper routine for device drivers when creating a
1639 * window system framebuffer (not a user-created render/framebuffer).
1640 * Once this function is called, you can basically forget about this
1641 * renderbuffer; core Mesa will handle all the buffer management and
1642 * rendering!
1643 */
1644 GLboolean
1645 _mesa_add_color_index_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb,
1646 GLuint indexBits,
1647 GLboolean frontLeft, GLboolean backLeft,
1648 GLboolean frontRight, GLboolean backRight)
1649 {
1650 GLuint b;
1651
1652 if (indexBits > 8) {
1653 _mesa_problem(ctx,
1654 "Unsupported bit depth in _mesa_add_color_index_renderbuffers");
1655 return GL_FALSE;
1656 }
1657
1658 assert(MAX_COLOR_ATTACHMENTS >= 4);
1659
1660 for (b = BUFFER_FRONT_LEFT; b <= BUFFER_BACK_RIGHT; b++) {
1661 struct gl_renderbuffer *rb;
1662
1663 if (b == BUFFER_FRONT_LEFT && !frontLeft)
1664 continue;
1665 else if (b == BUFFER_BACK_LEFT && !backLeft)
1666 continue;
1667 else if (b == BUFFER_FRONT_RIGHT && !frontRight)
1668 continue;
1669 else if (b == BUFFER_BACK_RIGHT && !backRight)
1670 continue;
1671
1672 assert(fb->Attachment[b].Renderbuffer == NULL);
1673
1674 rb = _mesa_new_renderbuffer(ctx, 0);
1675 if (!rb) {
1676 _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating color buffer");
1677 return GL_FALSE;
1678 }
1679
1680 if (indexBits <= 8) {
1681 /* only support GLuint for now */
1682 /*rb->InternalFormat = GL_COLOR_INDEX8_EXT;*/
1683 rb->_ActualFormat = COLOR_INDEX32;
1684 }
1685 else {
1686 rb->_ActualFormat = COLOR_INDEX32;
1687 }
1688 rb->InternalFormat = rb->_ActualFormat;
1689
1690 rb->AllocStorage = _mesa_soft_renderbuffer_storage;
1691 _mesa_add_renderbuffer(fb, b, rb);
1692 }
1693
1694 return GL_TRUE;
1695 }
1696
1697
1698 /**
1699 * Add software-based alpha renderbuffers to the given framebuffer.
1700 * This is a helper routine for device drivers when creating a
1701 * window system framebuffer (not a user-created render/framebuffer).
1702 * Once this function is called, you can basically forget about this
1703 * renderbuffer; core Mesa will handle all the buffer management and
1704 * rendering!
1705 */
1706 GLboolean
1707 _mesa_add_alpha_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb,
1708 GLuint alphaBits,
1709 GLboolean frontLeft, GLboolean backLeft,
1710 GLboolean frontRight, GLboolean backRight)
1711 {
1712 GLuint b;
1713
1714 /* for window system framebuffers only! */
1715 assert(fb->Name == 0);
1716
1717 if (alphaBits > 8) {
1718 _mesa_problem(ctx,
1719 "Unsupported bit depth in _mesa_add_alpha_renderbuffers");
1720 return GL_FALSE;
1721 }
1722
1723 assert(MAX_COLOR_ATTACHMENTS >= 4);
1724
1725 /* Wrap each of the RGB color buffers with an alpha renderbuffer.
1726 */
1727 for (b = BUFFER_FRONT_LEFT; b <= BUFFER_BACK_RIGHT; b++) {
1728 struct gl_renderbuffer *arb;
1729
1730 if (b == BUFFER_FRONT_LEFT && !frontLeft)
1731 continue;
1732 else if (b == BUFFER_BACK_LEFT && !backLeft)
1733 continue;
1734 else if (b == BUFFER_FRONT_RIGHT && !frontRight)
1735 continue;
1736 else if (b == BUFFER_BACK_RIGHT && !backRight)
1737 continue;
1738
1739 /* the RGB buffer to wrap must already exist!! */
1740 assert(fb->Attachment[b].Renderbuffer);
1741
1742 /* only GLubyte supported for now */
1743 assert(fb->Attachment[b].Renderbuffer->DataType == GL_UNSIGNED_BYTE);
1744
1745 /* allocate alpha renderbuffer */
1746 arb = _mesa_new_renderbuffer(ctx, 0);
1747 if (!arb) {
1748 _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating alpha buffer");
1749 return GL_FALSE;
1750 }
1751
1752 /* wrap the alpha renderbuffer around the RGB renderbuffer */
1753 arb->Wrapped = fb->Attachment[b].Renderbuffer;
1754
1755 /* Set up my alphabuffer fields and plug in my functions.
1756 * The functions will put/get the alpha values from/to RGBA arrays
1757 * and then call the wrapped buffer's functions to handle the RGB
1758 * values.
1759 */
1760 arb->InternalFormat = arb->Wrapped->InternalFormat;
1761 arb->_ActualFormat = GL_ALPHA8;
1762 arb->_BaseFormat = arb->Wrapped->_BaseFormat;
1763 arb->DataType = arb->Wrapped->DataType;
1764 arb->AllocStorage = alloc_storage_alpha8;
1765 arb->Delete = delete_renderbuffer_alpha8;
1766 arb->GetPointer = get_pointer_alpha8;
1767 arb->GetRow = get_row_alpha8;
1768 arb->GetValues = get_values_alpha8;
1769 arb->PutRow = put_row_alpha8;
1770 arb->PutRowRGB = put_row_rgb_alpha8;
1771 arb->PutMonoRow = put_mono_row_alpha8;
1772 arb->PutValues = put_values_alpha8;
1773 arb->PutMonoValues = put_mono_values_alpha8;
1774
1775 /* clear the pointer to avoid assertion/sanity check failure later */
1776 fb->Attachment[b].Renderbuffer = NULL;
1777
1778 /* plug the alpha renderbuffer into the colorbuffer attachment */
1779 _mesa_add_renderbuffer(fb, b, arb);
1780 }
1781
1782 return GL_TRUE;
1783 }
1784
1785
1786 /**
1787 * For framebuffers that use a software alpha channel wrapper
1788 * created by _mesa_add_alpha_renderbuffer or _mesa_add_soft_renderbuffers,
1789 * copy the back buffer alpha channel into the front buffer alpha channel.
1790 */
1791 void
1792 _mesa_copy_soft_alpha_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb)
1793 {
1794 if (fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer &&
1795 fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer)
1796 copy_buffer_alpha8(fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer,
1797 fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer);
1798
1799
1800 if (fb->Attachment[BUFFER_FRONT_RIGHT].Renderbuffer &&
1801 fb->Attachment[BUFFER_BACK_RIGHT].Renderbuffer)
1802 copy_buffer_alpha8(fb->Attachment[BUFFER_FRONT_RIGHT].Renderbuffer,
1803 fb->Attachment[BUFFER_BACK_RIGHT].Renderbuffer);
1804 }
1805
1806
1807 /**
1808 * Add a software-based depth renderbuffer to the given framebuffer.
1809 * This is a helper routine for device drivers when creating a
1810 * window system framebuffer (not a user-created render/framebuffer).
1811 * Once this function is called, you can basically forget about this
1812 * renderbuffer; core Mesa will handle all the buffer management and
1813 * rendering!
1814 */
1815 GLboolean
1816 _mesa_add_depth_renderbuffer(GLcontext *ctx, struct gl_framebuffer *fb,
1817 GLuint depthBits)
1818 {
1819 struct gl_renderbuffer *rb;
1820
1821 if (depthBits > 32) {
1822 _mesa_problem(ctx,
1823 "Unsupported depthBits in _mesa_add_depth_renderbuffer");
1824 return GL_FALSE;
1825 }
1826
1827 assert(fb->Attachment[BUFFER_DEPTH].Renderbuffer == NULL);
1828
1829 rb = _mesa_new_renderbuffer(ctx, 0);
1830 if (!rb) {
1831 _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating depth buffer");
1832 return GL_FALSE;
1833 }
1834
1835 if (depthBits <= 16) {
1836 rb->_ActualFormat = GL_DEPTH_COMPONENT16;
1837 }
1838 else if (depthBits <= 24) {
1839 rb->_ActualFormat = GL_DEPTH_COMPONENT24;
1840 }
1841 else {
1842 rb->_ActualFormat = GL_DEPTH_COMPONENT32;
1843 }
1844 rb->InternalFormat = rb->_ActualFormat;
1845
1846 rb->AllocStorage = _mesa_soft_renderbuffer_storage;
1847 _mesa_add_renderbuffer(fb, BUFFER_DEPTH, rb);
1848
1849 return GL_TRUE;
1850 }
1851
1852
1853 /**
1854 * Add a software-based stencil renderbuffer to the given framebuffer.
1855 * This is a helper routine for device drivers when creating a
1856 * window system framebuffer (not a user-created render/framebuffer).
1857 * Once this function is called, you can basically forget about this
1858 * renderbuffer; core Mesa will handle all the buffer management and
1859 * rendering!
1860 */
1861 GLboolean
1862 _mesa_add_stencil_renderbuffer(GLcontext *ctx, struct gl_framebuffer *fb,
1863 GLuint stencilBits)
1864 {
1865 struct gl_renderbuffer *rb;
1866
1867 if (stencilBits > 16) {
1868 _mesa_problem(ctx,
1869 "Unsupported stencilBits in _mesa_add_stencil_renderbuffer");
1870 return GL_FALSE;
1871 }
1872
1873 assert(fb->Attachment[BUFFER_STENCIL].Renderbuffer == NULL);
1874
1875 rb = _mesa_new_renderbuffer(ctx, 0);
1876 if (!rb) {
1877 _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating stencil buffer");
1878 return GL_FALSE;
1879 }
1880
1881 if (stencilBits <= 8) {
1882 rb->_ActualFormat = GL_STENCIL_INDEX8_EXT;
1883 }
1884 else {
1885 /* not really supported (see s_stencil.c code) */
1886 rb->_ActualFormat = GL_STENCIL_INDEX16_EXT;
1887 }
1888 rb->InternalFormat = rb->_ActualFormat;
1889
1890 rb->AllocStorage = _mesa_soft_renderbuffer_storage;
1891 _mesa_add_renderbuffer(fb, BUFFER_STENCIL, rb);
1892
1893 return GL_TRUE;
1894 }
1895
1896
1897 /**
1898 * Add a software-based accumulation renderbuffer to the given framebuffer.
1899 * This is a helper routine for device drivers when creating a
1900 * window system framebuffer (not a user-created render/framebuffer).
1901 * Once this function is called, you can basically forget about this
1902 * renderbuffer; core Mesa will handle all the buffer management and
1903 * rendering!
1904 */
1905 GLboolean
1906 _mesa_add_accum_renderbuffer(GLcontext *ctx, struct gl_framebuffer *fb,
1907 GLuint redBits, GLuint greenBits,
1908 GLuint blueBits, GLuint alphaBits)
1909 {
1910 struct gl_renderbuffer *rb;
1911
1912 if (redBits > 16 || greenBits > 16 || blueBits > 16 || alphaBits > 16) {
1913 _mesa_problem(ctx,
1914 "Unsupported accumBits in _mesa_add_accum_renderbuffer");
1915 return GL_FALSE;
1916 }
1917
1918 assert(fb->Attachment[BUFFER_ACCUM].Renderbuffer == NULL);
1919
1920 rb = _mesa_new_renderbuffer(ctx, 0);
1921 if (!rb) {
1922 _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating accum buffer");
1923 return GL_FALSE;
1924 }
1925
1926 rb->_ActualFormat = GL_RGBA16;
1927 rb->InternalFormat = GL_RGBA16;
1928 rb->AllocStorage = _mesa_soft_renderbuffer_storage;
1929 _mesa_add_renderbuffer(fb, BUFFER_ACCUM, rb);
1930
1931 return GL_TRUE;
1932 }
1933
1934
1935
1936 /**
1937 * Add a software-based accumulation renderbuffer to the given framebuffer.
1938 * This is a helper routine for device drivers when creating a
1939 * window system framebuffer (not a user-created render/framebuffer).
1940 * Once this function is called, you can basically forget about this
1941 * renderbuffer; core Mesa will handle all the buffer management and
1942 * rendering!
1943 *
1944 * NOTE: color-index aux buffers not supported.
1945 */
1946 GLboolean
1947 _mesa_add_aux_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb,
1948 GLuint colorBits, GLuint numBuffers)
1949 {
1950 GLuint i;
1951
1952 if (colorBits > 16) {
1953 _mesa_problem(ctx,
1954 "Unsupported accumBits in _mesa_add_aux_renderbuffers");
1955 return GL_FALSE;
1956 }
1957
1958 assert(numBuffers < MAX_AUX_BUFFERS);
1959
1960 for (i = 0; i < numBuffers; i++) {
1961 struct gl_renderbuffer *rb = _mesa_new_renderbuffer(ctx, 0);
1962
1963 assert(fb->Attachment[BUFFER_AUX0 + i].Renderbuffer == NULL);
1964
1965 if (!rb) {
1966 _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating accum buffer");
1967 return GL_FALSE;
1968 }
1969
1970 if (colorBits <= 8) {
1971 rb->_ActualFormat = GL_RGBA8;
1972 }
1973 else {
1974 rb->_ActualFormat = GL_RGBA16;
1975 }
1976 rb->InternalFormat = rb->_ActualFormat;
1977
1978 rb->AllocStorage = _mesa_soft_renderbuffer_storage;
1979 _mesa_add_renderbuffer(fb, BUFFER_AUX0 + i, rb);
1980 }
1981 return GL_TRUE;
1982 }
1983
1984
1985 /**
1986 * Create/attach software-based renderbuffers to the given framebuffer.
1987 * This is a helper routine for device drivers. Drivers can just as well
1988 * call the individual _mesa_add_*_renderbuffer() routines directly.
1989 */
1990 void
1991 _mesa_add_soft_renderbuffers(struct gl_framebuffer *fb,
1992 GLboolean color,
1993 GLboolean depth,
1994 GLboolean stencil,
1995 GLboolean accum,
1996 GLboolean alpha,
1997 GLboolean aux)
1998 {
1999 GLboolean frontLeft = GL_TRUE;
2000 GLboolean backLeft = fb->Visual.doubleBufferMode;
2001 GLboolean frontRight = fb->Visual.stereoMode;
2002 GLboolean backRight = fb->Visual.stereoMode && fb->Visual.doubleBufferMode;
2003
2004 if (color) {
2005 if (fb->Visual.rgbMode) {
2006 assert(fb->Visual.redBits == fb->Visual.greenBits);
2007 assert(fb->Visual.redBits == fb->Visual.blueBits);
2008 _mesa_add_color_renderbuffers(NULL, fb,
2009 fb->Visual.redBits,
2010 fb->Visual.alphaBits,
2011 frontLeft, backLeft,
2012 frontRight, backRight);
2013 }
2014 else {
2015 _mesa_add_color_index_renderbuffers(NULL, fb,
2016 fb->Visual.indexBits,
2017 frontLeft, backLeft,
2018 frontRight, backRight);
2019 }
2020 }
2021
2022 if (depth) {
2023 assert(fb->Visual.depthBits > 0);
2024 _mesa_add_depth_renderbuffer(NULL, fb, fb->Visual.depthBits);
2025 }
2026
2027 if (stencil) {
2028 assert(fb->Visual.stencilBits > 0);
2029 _mesa_add_stencil_renderbuffer(NULL, fb, fb->Visual.stencilBits);
2030 }
2031
2032 if (accum) {
2033 assert(fb->Visual.rgbMode);
2034 assert(fb->Visual.accumRedBits > 0);
2035 assert(fb->Visual.accumGreenBits > 0);
2036 assert(fb->Visual.accumBlueBits > 0);
2037 _mesa_add_accum_renderbuffer(NULL, fb,
2038 fb->Visual.accumRedBits,
2039 fb->Visual.accumGreenBits,
2040 fb->Visual.accumBlueBits,
2041 fb->Visual.accumAlphaBits);
2042 }
2043
2044 if (aux) {
2045 assert(fb->Visual.rgbMode);
2046 assert(fb->Visual.numAuxBuffers > 0);
2047 _mesa_add_aux_renderbuffers(NULL, fb, fb->Visual.redBits,
2048 fb->Visual.numAuxBuffers);
2049 }
2050
2051 if (alpha) {
2052 assert(fb->Visual.rgbMode);
2053 assert(fb->Visual.alphaBits > 0);
2054 _mesa_add_alpha_renderbuffers(NULL, fb, fb->Visual.alphaBits,
2055 frontLeft, backLeft,
2056 frontRight, backRight);
2057 }
2058
2059 #if 0
2060 if (multisample) {
2061 /* maybe someday */
2062 }
2063 #endif
2064 }
2065
2066
2067 /**
2068 * Attach a renderbuffer to a framebuffer.
2069 */
2070 void
2071 _mesa_add_renderbuffer(struct gl_framebuffer *fb,
2072 GLuint bufferName, struct gl_renderbuffer *rb)
2073 {
2074 assert(fb);
2075 assert(rb);
2076 assert(bufferName < BUFFER_COUNT);
2077
2078 /* There should be no previous renderbuffer on this attachment point,
2079 * with the exception of depth/stencil since the same renderbuffer may
2080 * be used for both.
2081 */
2082 assert(bufferName == BUFFER_DEPTH ||
2083 bufferName == BUFFER_STENCIL ||
2084 fb->Attachment[bufferName].Renderbuffer == NULL);
2085
2086 /* winsys vs. user-created buffer cross check */
2087 if (fb->Name) {
2088 assert(rb->Name);
2089 }
2090 else {
2091 assert(!rb->Name);
2092 }
2093
2094 /* If Mesa's compiled with deep color channels (16 or 32 bits / channel)
2095 * and the device driver is expecting 8-bit values (GLubyte), we can
2096 * use a "renderbuffer adaptor/wrapper" to do the necessary conversions.
2097 */
2098 if (rb->_BaseFormat == GL_RGBA) {
2099 if (CHAN_BITS == 16 && rb->DataType == GL_UNSIGNED_BYTE) {
2100 GET_CURRENT_CONTEXT(ctx);
2101 rb = _mesa_new_renderbuffer_16wrap8(ctx, rb);
2102 }
2103 else if (CHAN_BITS == 32 && rb->DataType == GL_UNSIGNED_BYTE) {
2104 GET_CURRENT_CONTEXT(ctx);
2105 rb = _mesa_new_renderbuffer_32wrap8(ctx, rb);
2106 }
2107 else if (CHAN_BITS == 32 && rb->DataType == GL_UNSIGNED_SHORT) {
2108 GET_CURRENT_CONTEXT(ctx);
2109 rb = _mesa_new_renderbuffer_32wrap16(ctx, rb);
2110 }
2111 }
2112
2113 fb->Attachment[bufferName].Type = GL_RENDERBUFFER_EXT;
2114 fb->Attachment[bufferName].Complete = GL_TRUE;
2115 _mesa_reference_renderbuffer(&fb->Attachment[bufferName].Renderbuffer, rb);
2116 }
2117
2118
2119 /**
2120 * Remove the named renderbuffer from the given framebuffer.
2121 */
2122 void
2123 _mesa_remove_renderbuffer(struct gl_framebuffer *fb, GLuint bufferName)
2124 {
2125 struct gl_renderbuffer *rb;
2126
2127 assert(bufferName < BUFFER_COUNT);
2128
2129 rb = fb->Attachment[bufferName].Renderbuffer;
2130 if (!rb)
2131 return;
2132
2133 _mesa_reference_renderbuffer(&rb, NULL);
2134
2135 fb->Attachment[bufferName].Renderbuffer = NULL;
2136 }
2137
2138
2139 /**
2140 * Set *ptr to point to rb. If *ptr points to another renderbuffer,
2141 * dereference that buffer first. The new renderbuffer's refcount will
2142 * be incremented. The old renderbuffer's refcount will be decremented.
2143 */
2144 void
2145 _mesa_reference_renderbuffer(struct gl_renderbuffer **ptr,
2146 struct gl_renderbuffer *rb)
2147 {
2148 assert(ptr);
2149 if (*ptr == rb) {
2150 /* no change */
2151 return;
2152 }
2153
2154 if (*ptr) {
2155 /* Unreference the old renderbuffer */
2156 GLboolean deleteFlag = GL_FALSE;
2157 struct gl_renderbuffer *oldRb = *ptr;
2158
2159 assert(oldRb->Magic == RB_MAGIC);
2160 _glthread_LOCK_MUTEX(oldRb->Mutex);
2161 assert(oldRb->Magic == RB_MAGIC);
2162 ASSERT(oldRb->RefCount > 0);
2163 oldRb->RefCount--;
2164 /*printf("RB DECR %p (%d) to %d\n", (void*) oldRb, oldRb->Name, oldRb->RefCount);*/
2165 deleteFlag = (oldRb->RefCount == 0);
2166 _glthread_UNLOCK_MUTEX(oldRb->Mutex);
2167
2168 if (deleteFlag) {
2169 oldRb->Magic = 0; /* now invalid memory! */
2170 oldRb->Delete(oldRb);
2171 }
2172
2173 *ptr = NULL;
2174 }
2175 assert(!*ptr);
2176
2177 if (rb) {
2178 assert(rb->Magic == RB_MAGIC);
2179 /* reference new renderbuffer */
2180 _glthread_LOCK_MUTEX(rb->Mutex);
2181 rb->RefCount++;
2182 /*printf("RB INCR %p (%d) to %d\n", (void*) rb, rb->Name, rb->RefCount);*/
2183 _glthread_UNLOCK_MUTEX(rb->Mutex);
2184 *ptr = rb;
2185 }
2186 }
2187
2188
2189 /**
2190 * Create a new combined depth/stencil renderbuffer for implementing
2191 * the GL_EXT_packed_depth_stencil extension.
2192 * \return new depth/stencil renderbuffer
2193 */
2194 struct gl_renderbuffer *
2195 _mesa_new_depthstencil_renderbuffer(GLcontext *ctx, GLuint name)
2196 {
2197 struct gl_renderbuffer *dsrb;
2198
2199 dsrb = _mesa_new_renderbuffer(ctx, name);
2200 if (!dsrb)
2201 return NULL;
2202
2203 /* init fields not covered by _mesa_new_renderbuffer() */
2204 dsrb->InternalFormat = GL_DEPTH24_STENCIL8_EXT;
2205 dsrb->_ActualFormat = GL_DEPTH24_STENCIL8_EXT;
2206 dsrb->AllocStorage = _mesa_soft_renderbuffer_storage;
2207
2208 return dsrb;
2209 }