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