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