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