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