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