gallium: remove pipe parameter from pipe_texture_reference()
[mesa.git] / src / mesa / main / renderbuffer.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 6.5
4 *
5 * Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25
26 /**
27 * Functions for allocating/managing renderbuffers.
28 * Also, routines for reading/writing software-based renderbuffer data as
29 * ubytes, ushorts, uints, etc.
30 *
31 * The 'alpha8' renderbuffer is interesting. It's used to add a software-based
32 * alpha channel to RGB renderbuffers. This is done by wrapping the RGB
33 * renderbuffer with the alpha renderbuffer. We can do this because of the
34 * OO-nature of renderbuffers.
35 *
36 * Down the road we'll use this for run-time support of 8, 16 and 32-bit
37 * color channels. For example, Mesa may use 32-bit/float color channels
38 * internally (swrast) and use wrapper renderbuffers to convert 32-bit
39 * values down to 16 or 8-bit values for whatever kind of framebuffer we have.
40 */
41
42
43 #include "glheader.h"
44 #include "imports.h"
45 #include "context.h"
46 #include "mtypes.h"
47 #include "fbobject.h"
48 #include "renderbuffer.h"
49
50 #include "rbadaptors.h"
51
52 #include "state_tracker/st_context.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 _ActualFormat 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->_ActualFormat == GL_RGB8);
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->_ActualFormat == GL_RGB8);
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->_ActualFormat == GL_RGB8);
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->_ActualFormat == GL_RGB8);
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->_ActualFormat == GL_RGB8);
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->_ActualFormat == GL_RGB8);
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->_ActualFormat == GL_RGB8);
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->_ActualFormat == GL_RGB8);
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->_ActualFormat == GL_RGBA8);
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->_ActualFormat == GL_RGBA8);
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->_ActualFormat == GL_RGBA8);
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->_ActualFormat == GL_RGBA8);
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->_ActualFormat == GL_RGBA8);
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->_ActualFormat == GL_RGBA8);
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->_ActualFormat == GL_RGBA8);
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->_ActualFormat == GL_RGBA8);
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 /* first clear these fields */
953 rb->RedBits =
954 rb->GreenBits =
955 rb->BlueBits =
956 rb->AlphaBits =
957 rb->IndexBits =
958 rb->DepthBits =
959 rb->StencilBits = 0;
960
961 switch (internalFormat) {
962 case GL_RGB:
963 case GL_R3_G3_B2:
964 case GL_RGB4:
965 case GL_RGB5:
966 case GL_RGB8:
967 case GL_RGB10:
968 case GL_RGB12:
969 case GL_RGB16:
970 rb->_ActualFormat = GL_RGB8;
971 rb->_BaseFormat = GL_RGB;
972 rb->DataType = GL_UNSIGNED_BYTE;
973 rb->GetPointer = get_pointer_ubyte3;
974 rb->GetRow = get_row_ubyte3;
975 rb->GetValues = get_values_ubyte3;
976 rb->PutRow = put_row_ubyte3;
977 rb->PutRowRGB = put_row_rgb_ubyte3;
978 rb->PutMonoRow = put_mono_row_ubyte3;
979 rb->PutValues = put_values_ubyte3;
980 rb->PutMonoValues = put_mono_values_ubyte3;
981 rb->RedBits = 8 * sizeof(GLubyte);
982 rb->GreenBits = 8 * sizeof(GLubyte);
983 rb->BlueBits = 8 * sizeof(GLubyte);
984 rb->AlphaBits = 0;
985 pixelSize = 3 * sizeof(GLubyte);
986 break;
987 case GL_RGBA:
988 case GL_RGBA2:
989 case GL_RGBA4:
990 case GL_RGB5_A1:
991 case GL_RGBA8:
992 rb->_ActualFormat = GL_RGBA8;
993 rb->_BaseFormat = GL_RGBA;
994 rb->DataType = GL_UNSIGNED_BYTE;
995 rb->GetPointer = get_pointer_ubyte4;
996 rb->GetRow = get_row_ubyte4;
997 rb->GetValues = get_values_ubyte4;
998 rb->PutRow = put_row_ubyte4;
999 rb->PutRowRGB = put_row_rgb_ubyte4;
1000 rb->PutMonoRow = put_mono_row_ubyte4;
1001 rb->PutValues = put_values_ubyte4;
1002 rb->PutMonoValues = put_mono_values_ubyte4;
1003 rb->RedBits = 8 * sizeof(GLubyte);
1004 rb->GreenBits = 8 * sizeof(GLubyte);
1005 rb->BlueBits = 8 * sizeof(GLubyte);
1006 rb->AlphaBits = 8 * sizeof(GLubyte);
1007 pixelSize = 4 * sizeof(GLubyte);
1008 break;
1009 case GL_RGB10_A2:
1010 case GL_RGBA12:
1011 case GL_RGBA16:
1012 rb->_ActualFormat = GL_RGBA16;
1013 rb->_BaseFormat = GL_RGBA;
1014 rb->DataType = GL_UNSIGNED_SHORT;
1015 rb->GetPointer = get_pointer_ushort4;
1016 rb->GetRow = get_row_ushort4;
1017 rb->GetValues = get_values_ushort4;
1018 rb->PutRow = put_row_ushort4;
1019 rb->PutRowRGB = put_row_rgb_ushort4;
1020 rb->PutMonoRow = put_mono_row_ushort4;
1021 rb->PutValues = put_values_ushort4;
1022 rb->PutMonoValues = put_mono_values_ushort4;
1023 rb->RedBits = 8 * sizeof(GLushort);
1024 rb->GreenBits = 8 * sizeof(GLushort);
1025 rb->BlueBits = 8 * sizeof(GLushort);
1026 rb->AlphaBits = 8 * sizeof(GLushort);
1027 pixelSize = 4 * sizeof(GLushort);
1028 break;
1029 #if 00
1030 case GL_ALPHA8:
1031 rb->_ActualFormat = GL_ALPHA8;
1032 rb->_BaseFormat = GL_RGBA; /* Yes, not GL_ALPHA! */
1033 rb->DataType = GL_UNSIGNED_BYTE;
1034 rb->GetPointer = get_pointer_alpha8;
1035 rb->GetRow = get_row_alpha8;
1036 rb->GetValues = get_values_alpha8;
1037 rb->PutRow = put_row_alpha8;
1038 rb->PutRowRGB = NULL;
1039 rb->PutMonoRow = put_mono_row_alpha8;
1040 rb->PutValues = put_values_alpha8;
1041 rb->PutMonoValues = put_mono_values_alpha8;
1042 rb->RedBits = 0; /*red*/
1043 rb->GreenBits = 0; /*green*/
1044 rb->BlueBits = 0; /*blue*/
1045 rb->AlphaBits = 8 * sizeof(GLubyte);
1046 pixelSize = sizeof(GLubyte);
1047 break;
1048 #endif
1049 case GL_STENCIL_INDEX:
1050 case GL_STENCIL_INDEX1_EXT:
1051 case GL_STENCIL_INDEX4_EXT:
1052 case GL_STENCIL_INDEX8_EXT:
1053 rb->_ActualFormat = GL_STENCIL_INDEX8_EXT;
1054 rb->_BaseFormat = GL_STENCIL_INDEX;
1055 rb->DataType = GL_UNSIGNED_BYTE;
1056 rb->GetPointer = get_pointer_ubyte;
1057 rb->GetRow = get_row_ubyte;
1058 rb->GetValues = get_values_ubyte;
1059 rb->PutRow = put_row_ubyte;
1060 rb->PutRowRGB = NULL;
1061 rb->PutMonoRow = put_mono_row_ubyte;
1062 rb->PutValues = put_values_ubyte;
1063 rb->PutMonoValues = put_mono_values_ubyte;
1064 rb->StencilBits = 8 * sizeof(GLubyte);
1065 pixelSize = sizeof(GLubyte);
1066 break;
1067 case GL_STENCIL_INDEX16_EXT:
1068 rb->_ActualFormat = GL_STENCIL_INDEX16_EXT;
1069 rb->_BaseFormat = GL_STENCIL_INDEX;
1070 rb->DataType = GL_UNSIGNED_SHORT;
1071 rb->GetPointer = get_pointer_ushort;
1072 rb->GetRow = get_row_ushort;
1073 rb->GetValues = get_values_ushort;
1074 rb->PutRow = put_row_ushort;
1075 rb->PutRowRGB = NULL;
1076 rb->PutMonoRow = put_mono_row_ushort;
1077 rb->PutValues = put_values_ushort;
1078 rb->PutMonoValues = put_mono_values_ushort;
1079 rb->StencilBits = 8 * sizeof(GLushort);
1080 pixelSize = sizeof(GLushort);
1081 break;
1082 case GL_DEPTH_COMPONENT:
1083 case GL_DEPTH_COMPONENT16:
1084 rb->_ActualFormat = GL_DEPTH_COMPONENT16;
1085 rb->_BaseFormat = GL_DEPTH_COMPONENT;
1086 rb->DataType = GL_UNSIGNED_SHORT;
1087 rb->GetPointer = get_pointer_ushort;
1088 rb->GetRow = get_row_ushort;
1089 rb->GetValues = get_values_ushort;
1090 rb->PutRow = put_row_ushort;
1091 rb->PutRowRGB = NULL;
1092 rb->PutMonoRow = put_mono_row_ushort;
1093 rb->PutValues = put_values_ushort;
1094 rb->PutMonoValues = put_mono_values_ushort;
1095 rb->DepthBits = 8 * sizeof(GLushort);
1096 pixelSize = sizeof(GLushort);
1097 break;
1098 case GL_DEPTH_COMPONENT24:
1099 case GL_DEPTH_COMPONENT32:
1100 rb->_BaseFormat = GL_DEPTH_COMPONENT;
1101 rb->DataType = GL_UNSIGNED_INT;
1102 rb->GetPointer = get_pointer_uint;
1103 rb->GetRow = get_row_uint;
1104 rb->GetValues = get_values_uint;
1105 rb->PutRow = put_row_uint;
1106 rb->PutRowRGB = NULL;
1107 rb->PutMonoRow = put_mono_row_uint;
1108 rb->PutValues = put_values_uint;
1109 rb->PutMonoValues = put_mono_values_uint;
1110 if (internalFormat == GL_DEPTH_COMPONENT24) {
1111 rb->_ActualFormat = GL_DEPTH_COMPONENT24;
1112 rb->DepthBits = 24;
1113 }
1114 else {
1115 rb->_ActualFormat = GL_DEPTH_COMPONENT32;
1116 rb->DepthBits = 32;
1117 }
1118 pixelSize = sizeof(GLuint);
1119 break;
1120 case GL_DEPTH_STENCIL_EXT:
1121 case GL_DEPTH24_STENCIL8_EXT:
1122 rb->_ActualFormat = GL_DEPTH24_STENCIL8_EXT;
1123 rb->_BaseFormat = GL_DEPTH_STENCIL_EXT;
1124 rb->DataType = GL_UNSIGNED_INT_24_8_EXT;
1125 rb->GetPointer = get_pointer_uint;
1126 rb->GetRow = get_row_uint;
1127 rb->GetValues = get_values_uint;
1128 rb->PutRow = put_row_uint;
1129 rb->PutRowRGB = NULL;
1130 rb->PutMonoRow = put_mono_row_uint;
1131 rb->PutValues = put_values_uint;
1132 rb->PutMonoValues = put_mono_values_uint;
1133 rb->DepthBits = 24;
1134 rb->StencilBits = 8;
1135 pixelSize = sizeof(GLuint);
1136 break;
1137 case GL_COLOR_INDEX8_EXT:
1138 rb->_ActualFormat = GL_COLOR_INDEX8_EXT;
1139 rb->_BaseFormat = GL_COLOR_INDEX;
1140 rb->DataType = GL_UNSIGNED_BYTE;
1141 rb->GetPointer = get_pointer_ubyte;
1142 rb->GetRow = get_row_ubyte;
1143 rb->GetValues = get_values_ubyte;
1144 rb->PutRow = put_row_ubyte;
1145 rb->PutRowRGB = NULL;
1146 rb->PutMonoRow = put_mono_row_ubyte;
1147 rb->PutValues = put_values_ubyte;
1148 rb->PutMonoValues = put_mono_values_ubyte;
1149 rb->IndexBits = 8 * sizeof(GLubyte);
1150 pixelSize = sizeof(GLubyte);
1151 break;
1152 case GL_COLOR_INDEX16_EXT:
1153 rb->_ActualFormat = GL_COLOR_INDEX16_EXT;
1154 rb->_BaseFormat = GL_COLOR_INDEX;
1155 rb->DataType = GL_UNSIGNED_SHORT;
1156 rb->GetPointer = get_pointer_ushort;
1157 rb->GetRow = get_row_ushort;
1158 rb->GetValues = get_values_ushort;
1159 rb->PutRow = put_row_ushort;
1160 rb->PutRowRGB = NULL;
1161 rb->PutMonoRow = put_mono_row_ushort;
1162 rb->PutValues = put_values_ushort;
1163 rb->PutMonoValues = put_mono_values_ushort;
1164 rb->IndexBits = 8 * sizeof(GLushort);
1165 pixelSize = sizeof(GLushort);
1166 break;
1167 case COLOR_INDEX32:
1168 rb->_ActualFormat = COLOR_INDEX32;
1169 rb->_BaseFormat = GL_COLOR_INDEX;
1170 rb->DataType = GL_UNSIGNED_INT;
1171 rb->GetPointer = get_pointer_uint;
1172 rb->GetRow = get_row_uint;
1173 rb->GetValues = get_values_uint;
1174 rb->PutRow = put_row_uint;
1175 rb->PutRowRGB = NULL;
1176 rb->PutMonoRow = put_mono_row_uint;
1177 rb->PutValues = put_values_uint;
1178 rb->PutMonoValues = put_mono_values_uint;
1179 rb->IndexBits = 8 * sizeof(GLuint);
1180 pixelSize = sizeof(GLuint);
1181 break;
1182 default:
1183 _mesa_problem(ctx, "Bad internalFormat in _mesa_soft_renderbuffer_storage");
1184 return GL_FALSE;
1185 }
1186
1187 ASSERT(rb->DataType);
1188 ASSERT(rb->GetPointer);
1189 ASSERT(rb->GetRow);
1190 ASSERT(rb->GetValues);
1191 ASSERT(rb->PutRow);
1192 ASSERT(rb->PutMonoRow);
1193 ASSERT(rb->PutValues);
1194 ASSERT(rb->PutMonoValues);
1195
1196 /* free old buffer storage */
1197 if (rb->Data) {
1198 _mesa_free(rb->Data);
1199 rb->Data = NULL;
1200 }
1201
1202 if (width > 0 && height > 0) {
1203 /* allocate new buffer storage */
1204 rb->Data = malloc(width * height * pixelSize);
1205
1206 if (rb->Data == NULL) {
1207 rb->Width = 0;
1208 rb->Height = 0;
1209 _mesa_error(ctx, GL_OUT_OF_MEMORY,
1210 "software renderbuffer allocation (%d x %d x %d)",
1211 width, height, pixelSize);
1212 return GL_FALSE;
1213 }
1214 }
1215
1216 rb->Width = width;
1217 rb->Height = height;
1218
1219 return GL_TRUE;
1220 }
1221
1222
1223
1224 /**********************************************************************/
1225 /**********************************************************************/
1226 /**********************************************************************/
1227
1228
1229 /**
1230 * Here we utilize the gl_renderbuffer->Wrapper field to put an alpha
1231 * buffer wrapper around an existing RGB renderbuffer (hw or sw).
1232 *
1233 * When PutRow is called (for example), we store the alpha values in
1234 * this buffer, then pass on the PutRow call to the wrapped RGB
1235 * buffer.
1236 */
1237
1238
1239 static GLboolean
1240 alloc_storage_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb,
1241 GLenum internalFormat, GLuint width, GLuint height)
1242 {
1243 ASSERT(arb != arb->Wrapped);
1244 ASSERT(arb->_ActualFormat == GL_ALPHA8);
1245
1246 /* first, pass the call to the wrapped RGB buffer */
1247 if (!arb->Wrapped->AllocStorage(ctx, arb->Wrapped, internalFormat,
1248 width, height)) {
1249 return GL_FALSE;
1250 }
1251
1252 /* next, resize my alpha buffer */
1253 if (arb->Data) {
1254 _mesa_free(arb->Data);
1255 }
1256
1257 arb->Data = _mesa_malloc(width * height * sizeof(GLubyte));
1258 if (arb->Data == NULL) {
1259 arb->Width = 0;
1260 arb->Height = 0;
1261 _mesa_error(ctx, GL_OUT_OF_MEMORY, "software alpha buffer allocation");
1262 return GL_FALSE;
1263 }
1264
1265 arb->Width = width;
1266 arb->Height = height;
1267
1268 return GL_TRUE;
1269 }
1270
1271
1272 /**
1273 * Delete an alpha_renderbuffer object, as well as the wrapped RGB buffer.
1274 */
1275 static void
1276 delete_renderbuffer_alpha8(struct gl_renderbuffer *arb)
1277 {
1278 if (arb->Data) {
1279 _mesa_free(arb->Data);
1280 }
1281 ASSERT(arb->Wrapped);
1282 ASSERT(arb != arb->Wrapped);
1283 arb->Wrapped->Delete(arb->Wrapped);
1284 arb->Wrapped = NULL;
1285 _mesa_free(arb);
1286 }
1287
1288
1289 static void *
1290 get_pointer_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb,
1291 GLint x, GLint y)
1292 {
1293 return NULL; /* don't allow direct access! */
1294 }
1295
1296
1297 static void
1298 get_row_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, GLuint count,
1299 GLint x, GLint y, void *values)
1300 {
1301 /* NOTE: 'values' is RGBA format! */
1302 const GLubyte *src = (const GLubyte *) arb->Data + y * arb->Width + x;
1303 GLubyte *dst = (GLubyte *) values;
1304 GLuint i;
1305 ASSERT(arb != arb->Wrapped);
1306 ASSERT(arb->DataType == GL_UNSIGNED_BYTE);
1307 /* first, pass the call to the wrapped RGB buffer */
1308 arb->Wrapped->GetRow(ctx, arb->Wrapped, count, x, y, values);
1309 /* second, fill in alpha values from this buffer! */
1310 for (i = 0; i < count; i++) {
1311 dst[i * 4 + 3] = src[i];
1312 }
1313 }
1314
1315
1316 static void
1317 get_values_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, GLuint count,
1318 const GLint x[], const GLint y[], void *values)
1319 {
1320 GLubyte *dst = (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->GetValues(ctx, arb->Wrapped, count, x, y, values);
1326 /* second, fill in alpha values from this buffer! */
1327 for (i = 0; i < count; i++) {
1328 const GLubyte *src = (GLubyte *) arb->Data + y[i] * arb->Width + x[i];
1329 dst[i * 4 + 3] = *src;
1330 }
1331 }
1332
1333
1334 static void
1335 put_row_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, GLuint count,
1336 GLint x, GLint y, const void *values, const GLubyte *mask)
1337 {
1338 const GLubyte *src = (const GLubyte *) values;
1339 GLubyte *dst = (GLubyte *) arb->Data + y * arb->Width + x;
1340 GLuint i;
1341 ASSERT(arb != arb->Wrapped);
1342 ASSERT(arb->DataType == GL_UNSIGNED_BYTE);
1343 /* first, pass the call to the wrapped RGB buffer */
1344 arb->Wrapped->PutRow(ctx, arb->Wrapped, count, x, y, values, mask);
1345 /* second, store alpha in our buffer */
1346 for (i = 0; i < count; i++) {
1347 if (!mask || mask[i]) {
1348 dst[i] = src[i * 4 + 3];
1349 }
1350 }
1351 }
1352
1353
1354 static void
1355 put_row_rgb_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, GLuint count,
1356 GLint x, GLint y, const void *values, const GLubyte *mask)
1357 {
1358 const GLubyte *src = (const GLubyte *) values;
1359 GLubyte *dst = (GLubyte *) arb->Data + y * arb->Width + x;
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->PutRowRGB(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 dst[i] = src[i * 4 + 3];
1369 }
1370 }
1371 }
1372
1373
1374 static void
1375 put_mono_row_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, GLuint count,
1376 GLint x, GLint y, const void *value, const GLubyte *mask)
1377 {
1378 const GLubyte val = ((const GLubyte *) value)[3];
1379 GLubyte *dst = (GLubyte *) arb->Data + y * arb->Width + x;
1380 ASSERT(arb != arb->Wrapped);
1381 ASSERT(arb->DataType == GL_UNSIGNED_BYTE);
1382 /* first, pass the call to the wrapped RGB buffer */
1383 arb->Wrapped->PutMonoRow(ctx, arb->Wrapped, count, x, y, value, mask);
1384 /* second, store alpha in our buffer */
1385 if (mask) {
1386 GLuint i;
1387 for (i = 0; i < count; i++) {
1388 if (mask[i]) {
1389 dst[i] = val;
1390 }
1391 }
1392 }
1393 else {
1394 _mesa_memset(dst, val, count);
1395 }
1396 }
1397
1398
1399 static void
1400 put_values_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, GLuint count,
1401 const GLint x[], const GLint y[],
1402 const void *values, const GLubyte *mask)
1403 {
1404 const GLubyte *src = (const GLubyte *) values;
1405 GLuint i;
1406 ASSERT(arb != arb->Wrapped);
1407 ASSERT(arb->DataType == GL_UNSIGNED_BYTE);
1408 /* first, pass the call to the wrapped RGB buffer */
1409 arb->Wrapped->PutValues(ctx, arb->Wrapped, count, x, y, values, mask);
1410 /* second, store alpha in our buffer */
1411 for (i = 0; i < count; i++) {
1412 if (!mask || mask[i]) {
1413 GLubyte *dst = (GLubyte *) arb->Data + y[i] * arb->Width + x[i];
1414 *dst = src[i * 4 + 3];
1415 }
1416 }
1417 }
1418
1419
1420 static void
1421 put_mono_values_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb,
1422 GLuint count, const GLint x[], const GLint y[],
1423 const void *value, const GLubyte *mask)
1424 {
1425 const GLubyte val = ((const GLubyte *) value)[3];
1426 GLuint i;
1427 ASSERT(arb != arb->Wrapped);
1428 ASSERT(arb->DataType == GL_UNSIGNED_BYTE);
1429 /* first, pass the call to the wrapped RGB buffer */
1430 arb->Wrapped->PutValues(ctx, arb->Wrapped, count, x, y, value, mask);
1431 /* second, store alpha in our buffer */
1432 for (i = 0; i < count; i++) {
1433 if (!mask || mask[i]) {
1434 GLubyte *dst = (GLubyte *) arb->Data + y[i] * arb->Width + x[i];
1435 *dst = val;
1436 }
1437 }
1438 }
1439
1440
1441 static void
1442 copy_buffer_alpha8(struct gl_renderbuffer* dst, struct gl_renderbuffer* src)
1443 {
1444 ASSERT(dst->_ActualFormat == GL_ALPHA8);
1445 ASSERT(src->_ActualFormat == GL_ALPHA8);
1446 ASSERT(dst->Width == src->Width);
1447 ASSERT(dst->Height == src->Height);
1448
1449 _mesa_memcpy(dst->Data, src->Data, dst->Width * dst->Height * sizeof(GLubyte));
1450 }
1451
1452
1453 /**********************************************************************/
1454 /**********************************************************************/
1455 /**********************************************************************/
1456
1457
1458 /**
1459 * Default GetPointer routine. Always return NULL to indicate that
1460 * direct buffer access is not supported.
1461 */
1462 static void *
1463 nop_get_pointer(GLcontext *ctx, struct gl_renderbuffer *rb, GLint x, GLint y)
1464 {
1465 return NULL;
1466 }
1467
1468
1469 /**
1470 * Initialize the fields of a gl_renderbuffer to default values.
1471 */
1472 void
1473 _mesa_init_renderbuffer(struct gl_renderbuffer *rb, GLuint name)
1474 {
1475 _glthread_INIT_MUTEX(rb->Mutex);
1476
1477 rb->Magic = RB_MAGIC;
1478 rb->ClassID = 0;
1479 rb->Name = name;
1480 rb->RefCount = 0;
1481 rb->Delete = _mesa_delete_renderbuffer;
1482
1483 /* The rest of these should be set later by the caller of this function or
1484 * the AllocStorage method:
1485 */
1486 rb->AllocStorage = NULL;
1487
1488 rb->Width = 0;
1489 rb->Height = 0;
1490 rb->InternalFormat = GL_NONE;
1491 rb->_ActualFormat = GL_NONE;
1492 rb->_BaseFormat = GL_NONE;
1493 rb->DataType = GL_NONE;
1494 rb->RedBits = rb->GreenBits = rb->BlueBits = rb->AlphaBits = 0;
1495 rb->IndexBits = 0;
1496 rb->DepthBits = 0;
1497 rb->StencilBits = 0;
1498 rb->Data = NULL;
1499
1500 /* Point back to ourself so that we don't have to check for Wrapped==NULL
1501 * all over the drivers.
1502 */
1503 rb->Wrapped = rb;
1504
1505 rb->GetPointer = nop_get_pointer;
1506 rb->GetRow = NULL;
1507 rb->GetValues = NULL;
1508 rb->PutRow = NULL;
1509 rb->PutRowRGB = NULL;
1510 rb->PutMonoRow = NULL;
1511 rb->PutValues = NULL;
1512 rb->PutMonoValues = NULL;
1513 }
1514
1515
1516 /**
1517 * Allocate a new gl_renderbuffer object. This can be used for user-created
1518 * renderbuffers or window-system renderbuffers.
1519 */
1520 struct gl_renderbuffer *
1521 _mesa_new_renderbuffer(GLcontext *ctx, GLuint name)
1522 {
1523 struct gl_renderbuffer *rb = CALLOC_STRUCT(gl_renderbuffer);
1524 if (rb) {
1525 _mesa_init_renderbuffer(rb, name);
1526 }
1527 return rb;
1528 }
1529
1530
1531 /**
1532 * Delete a gl_framebuffer.
1533 * This is the default function for renderbuffer->Delete().
1534 */
1535 void
1536 _mesa_delete_renderbuffer(struct gl_renderbuffer *rb)
1537 {
1538 if (rb->Data) {
1539 _mesa_free(rb->Data);
1540 }
1541 _mesa_free(rb);
1542 }
1543
1544
1545 /**
1546 * Allocate a software-based renderbuffer. This is called via the
1547 * ctx->Driver.NewRenderbuffer() function when the user creates a new
1548 * renderbuffer.
1549 * This would not be used for hardware-based renderbuffers.
1550 */
1551 struct gl_renderbuffer *
1552 _mesa_new_soft_renderbuffer(GLcontext *ctx, GLuint name)
1553 {
1554 struct gl_renderbuffer *rb = _mesa_new_renderbuffer(ctx, name);
1555 if (rb) {
1556 rb->AllocStorage = _mesa_soft_renderbuffer_storage;
1557 /* Normally, one would setup the PutRow, GetRow, etc functions here.
1558 * But we're doing that in the _mesa_soft_renderbuffer_storage() function
1559 * instead.
1560 */
1561 }
1562 return rb;
1563 }
1564
1565
1566 /**
1567 * Add software-based color renderbuffers to the given framebuffer.
1568 * This is a helper routine for device drivers when creating a
1569 * window system framebuffer (not a user-created render/framebuffer).
1570 * Once this function is called, you can basically forget about this
1571 * renderbuffer; core Mesa will handle all the buffer management and
1572 * rendering!
1573 */
1574 GLboolean
1575 _mesa_add_color_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb,
1576 GLuint rgbBits, GLuint alphaBits,
1577 GLboolean frontLeft, GLboolean backLeft,
1578 GLboolean frontRight, GLboolean backRight)
1579 {
1580 GLuint b;
1581
1582 if (rgbBits > 16 || alphaBits > 16) {
1583 _mesa_problem(ctx,
1584 "Unsupported bit depth in _mesa_add_color_renderbuffers");
1585 return GL_FALSE;
1586 }
1587
1588 assert(MAX_COLOR_ATTACHMENTS >= 4);
1589
1590 for (b = BUFFER_FRONT_LEFT; b <= BUFFER_BACK_RIGHT; b++) {
1591 struct gl_renderbuffer *rb;
1592
1593 if (b == BUFFER_FRONT_LEFT && !frontLeft)
1594 continue;
1595 else if (b == BUFFER_BACK_LEFT && !backLeft)
1596 continue;
1597 else if (b == BUFFER_FRONT_RIGHT && !frontRight)
1598 continue;
1599 else if (b == BUFFER_BACK_RIGHT && !backRight)
1600 continue;
1601
1602 assert(fb->Attachment[b].Renderbuffer == NULL);
1603
1604 rb = _mesa_new_renderbuffer(ctx, 0);
1605 if (!rb) {
1606 _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating color buffer");
1607 return GL_FALSE;
1608 }
1609
1610 if (rgbBits <= 8) {
1611 if (alphaBits)
1612 rb->_ActualFormat = GL_RGBA8;
1613 else
1614 rb->_ActualFormat = GL_RGB8;
1615 }
1616 else {
1617 assert(rgbBits <= 16);
1618 if (alphaBits)
1619 rb->_ActualFormat = GL_RGBA16;
1620 else
1621 rb->_ActualFormat = GL_RGBA16; /* don't really have RGB16 yet */
1622 }
1623 rb->InternalFormat = rb->_ActualFormat;
1624
1625 rb->AllocStorage = _mesa_soft_renderbuffer_storage;
1626 _mesa_add_renderbuffer(fb, b, rb);
1627 }
1628
1629 return GL_TRUE;
1630 }
1631
1632
1633 /**
1634 * Add software-based color index renderbuffers to the given framebuffer.
1635 * This is a helper routine for device drivers when creating a
1636 * window system framebuffer (not a user-created render/framebuffer).
1637 * Once this function is called, you can basically forget about this
1638 * renderbuffer; core Mesa will handle all the buffer management and
1639 * rendering!
1640 */
1641 GLboolean
1642 _mesa_add_color_index_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb,
1643 GLuint indexBits,
1644 GLboolean frontLeft, GLboolean backLeft,
1645 GLboolean frontRight, GLboolean backRight)
1646 {
1647 GLuint b;
1648
1649 if (indexBits > 8) {
1650 _mesa_problem(ctx,
1651 "Unsupported bit depth in _mesa_add_color_index_renderbuffers");
1652 return GL_FALSE;
1653 }
1654
1655 assert(MAX_COLOR_ATTACHMENTS >= 4);
1656
1657 for (b = BUFFER_FRONT_LEFT; b <= BUFFER_BACK_RIGHT; b++) {
1658 struct gl_renderbuffer *rb;
1659
1660 if (b == BUFFER_FRONT_LEFT && !frontLeft)
1661 continue;
1662 else if (b == BUFFER_BACK_LEFT && !backLeft)
1663 continue;
1664 else if (b == BUFFER_FRONT_RIGHT && !frontRight)
1665 continue;
1666 else if (b == BUFFER_BACK_RIGHT && !backRight)
1667 continue;
1668
1669 assert(fb->Attachment[b].Renderbuffer == NULL);
1670
1671 rb = _mesa_new_renderbuffer(ctx, 0);
1672 if (!rb) {
1673 _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating color buffer");
1674 return GL_FALSE;
1675 }
1676
1677 if (indexBits <= 8) {
1678 /* only support GLuint for now */
1679 /*rb->InternalFormat = GL_COLOR_INDEX8_EXT;*/
1680 rb->_ActualFormat = COLOR_INDEX32;
1681 }
1682 else {
1683 rb->_ActualFormat = COLOR_INDEX32;
1684 }
1685 rb->InternalFormat = rb->_ActualFormat;
1686
1687 rb->AllocStorage = _mesa_soft_renderbuffer_storage;
1688 _mesa_add_renderbuffer(fb, b, rb);
1689 }
1690
1691 return GL_TRUE;
1692 }
1693
1694
1695 /**
1696 * Add software-based alpha renderbuffers to the given framebuffer.
1697 * This is a helper routine for device drivers when creating a
1698 * window system framebuffer (not a user-created render/framebuffer).
1699 * Once this function is called, you can basically forget about this
1700 * renderbuffer; core Mesa will handle all the buffer management and
1701 * rendering!
1702 */
1703 GLboolean
1704 _mesa_add_alpha_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb,
1705 GLuint alphaBits,
1706 GLboolean frontLeft, GLboolean backLeft,
1707 GLboolean frontRight, GLboolean backRight)
1708 {
1709 GLuint b;
1710
1711 /* for window system framebuffers only! */
1712 assert(fb->Name == 0);
1713
1714 if (alphaBits > 8) {
1715 _mesa_problem(ctx,
1716 "Unsupported bit depth in _mesa_add_alpha_renderbuffers");
1717 return GL_FALSE;
1718 }
1719
1720 assert(MAX_COLOR_ATTACHMENTS >= 4);
1721
1722 /* Wrap each of the RGB color buffers with an alpha renderbuffer.
1723 */
1724 for (b = BUFFER_FRONT_LEFT; b <= BUFFER_BACK_RIGHT; b++) {
1725 struct gl_renderbuffer *arb;
1726
1727 if (b == BUFFER_FRONT_LEFT && !frontLeft)
1728 continue;
1729 else if (b == BUFFER_BACK_LEFT && !backLeft)
1730 continue;
1731 else if (b == BUFFER_FRONT_RIGHT && !frontRight)
1732 continue;
1733 else if (b == BUFFER_BACK_RIGHT && !backRight)
1734 continue;
1735
1736 /* the RGB buffer to wrap must already exist!! */
1737 assert(fb->Attachment[b].Renderbuffer);
1738
1739 /* only GLubyte supported for now */
1740 assert(fb->Attachment[b].Renderbuffer->DataType == GL_UNSIGNED_BYTE);
1741
1742 /* allocate alpha renderbuffer */
1743 arb = _mesa_new_renderbuffer(ctx, 0);
1744 if (!arb) {
1745 _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating alpha buffer");
1746 return GL_FALSE;
1747 }
1748
1749 /* wrap the alpha renderbuffer around the RGB renderbuffer */
1750 arb->Wrapped = fb->Attachment[b].Renderbuffer;
1751
1752 /* Set up my alphabuffer fields and plug in my functions.
1753 * The functions will put/get the alpha values from/to RGBA arrays
1754 * and then call the wrapped buffer's functions to handle the RGB
1755 * values.
1756 */
1757 arb->InternalFormat = arb->Wrapped->InternalFormat;
1758 arb->_ActualFormat = GL_ALPHA8;
1759 arb->_BaseFormat = arb->Wrapped->_BaseFormat;
1760 arb->DataType = arb->Wrapped->DataType;
1761 arb->AllocStorage = alloc_storage_alpha8;
1762 arb->Delete = delete_renderbuffer_alpha8;
1763 arb->GetPointer = get_pointer_alpha8;
1764 arb->GetRow = get_row_alpha8;
1765 arb->GetValues = get_values_alpha8;
1766 arb->PutRow = put_row_alpha8;
1767 arb->PutRowRGB = put_row_rgb_alpha8;
1768 arb->PutMonoRow = put_mono_row_alpha8;
1769 arb->PutValues = put_values_alpha8;
1770 arb->PutMonoValues = put_mono_values_alpha8;
1771
1772 /* clear the pointer to avoid assertion/sanity check failure later */
1773 fb->Attachment[b].Renderbuffer = NULL;
1774
1775 /* plug the alpha renderbuffer into the colorbuffer attachment */
1776 _mesa_add_renderbuffer(fb, b, arb);
1777 }
1778
1779 return GL_TRUE;
1780 }
1781
1782
1783 /**
1784 * For framebuffers that use a software alpha channel wrapper
1785 * created by _mesa_add_alpha_renderbuffer or _mesa_add_soft_renderbuffers,
1786 * copy the back buffer alpha channel into the front buffer alpha channel.
1787 */
1788 void
1789 _mesa_copy_soft_alpha_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb)
1790 {
1791 if (fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer &&
1792 fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer)
1793 copy_buffer_alpha8(fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer,
1794 fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer);
1795
1796
1797 if (fb->Attachment[BUFFER_FRONT_RIGHT].Renderbuffer &&
1798 fb->Attachment[BUFFER_BACK_RIGHT].Renderbuffer)
1799 copy_buffer_alpha8(fb->Attachment[BUFFER_FRONT_RIGHT].Renderbuffer,
1800 fb->Attachment[BUFFER_BACK_RIGHT].Renderbuffer);
1801 }
1802
1803
1804 /**
1805 * Add a software-based depth renderbuffer to the given framebuffer.
1806 * This is a helper routine for device drivers when creating a
1807 * window system framebuffer (not a user-created render/framebuffer).
1808 * Once this function is called, you can basically forget about this
1809 * renderbuffer; core Mesa will handle all the buffer management and
1810 * rendering!
1811 */
1812 GLboolean
1813 _mesa_add_depth_renderbuffer(GLcontext *ctx, struct gl_framebuffer *fb,
1814 GLuint depthBits)
1815 {
1816 struct gl_renderbuffer *rb;
1817
1818 if (depthBits > 32) {
1819 _mesa_problem(ctx,
1820 "Unsupported depthBits in _mesa_add_depth_renderbuffer");
1821 return GL_FALSE;
1822 }
1823
1824 assert(fb->Attachment[BUFFER_DEPTH].Renderbuffer == NULL);
1825
1826 rb = _mesa_new_renderbuffer(ctx, 0);
1827 if (!rb) {
1828 _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating depth buffer");
1829 return GL_FALSE;
1830 }
1831
1832 if (depthBits <= 16) {
1833 rb->_ActualFormat = GL_DEPTH_COMPONENT16;
1834 }
1835 else if (depthBits <= 24) {
1836 rb->_ActualFormat = GL_DEPTH_COMPONENT24;
1837 }
1838 else {
1839 rb->_ActualFormat = GL_DEPTH_COMPONENT32;
1840 }
1841 rb->InternalFormat = rb->_ActualFormat;
1842
1843 rb->AllocStorage = _mesa_soft_renderbuffer_storage;
1844 _mesa_add_renderbuffer(fb, BUFFER_DEPTH, rb);
1845
1846 return GL_TRUE;
1847 }
1848
1849
1850 /**
1851 * Add a software-based stencil renderbuffer to the given framebuffer.
1852 * This is a helper routine for device drivers when creating a
1853 * window system framebuffer (not a user-created render/framebuffer).
1854 * Once this function is called, you can basically forget about this
1855 * renderbuffer; core Mesa will handle all the buffer management and
1856 * rendering!
1857 */
1858 GLboolean
1859 _mesa_add_stencil_renderbuffer(GLcontext *ctx, struct gl_framebuffer *fb,
1860 GLuint stencilBits)
1861 {
1862 struct gl_renderbuffer *rb;
1863
1864 if (stencilBits > 16) {
1865 _mesa_problem(ctx,
1866 "Unsupported stencilBits in _mesa_add_stencil_renderbuffer");
1867 return GL_FALSE;
1868 }
1869
1870 assert(fb->Attachment[BUFFER_STENCIL].Renderbuffer == NULL);
1871
1872 rb = _mesa_new_renderbuffer(ctx, 0);
1873 if (!rb) {
1874 _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating stencil buffer");
1875 return GL_FALSE;
1876 }
1877
1878 if (stencilBits <= 8) {
1879 rb->_ActualFormat = GL_STENCIL_INDEX8_EXT;
1880 }
1881 else {
1882 /* not really supported (see s_stencil.c code) */
1883 rb->_ActualFormat = GL_STENCIL_INDEX16_EXT;
1884 }
1885 rb->InternalFormat = rb->_ActualFormat;
1886
1887 rb->AllocStorage = _mesa_soft_renderbuffer_storage;
1888 _mesa_add_renderbuffer(fb, BUFFER_STENCIL, rb);
1889
1890 return GL_TRUE;
1891 }
1892
1893
1894 /**
1895 * Add a software-based accumulation renderbuffer to the given framebuffer.
1896 * This is a helper routine for device drivers when creating a
1897 * window system framebuffer (not a user-created render/framebuffer).
1898 * Once this function is called, you can basically forget about this
1899 * renderbuffer; core Mesa will handle all the buffer management and
1900 * rendering!
1901 */
1902 GLboolean
1903 _mesa_add_accum_renderbuffer(GLcontext *ctx, struct gl_framebuffer *fb,
1904 GLuint redBits, GLuint greenBits,
1905 GLuint blueBits, GLuint alphaBits)
1906 {
1907 struct gl_renderbuffer *rb;
1908
1909 if (redBits > 16 || greenBits > 16 || blueBits > 16 || alphaBits > 16) {
1910 _mesa_problem(ctx,
1911 "Unsupported accumBits in _mesa_add_accum_renderbuffer");
1912 return GL_FALSE;
1913 }
1914
1915 assert(fb->Attachment[BUFFER_ACCUM].Renderbuffer == NULL);
1916
1917 rb = _mesa_new_renderbuffer(ctx, 0);
1918 if (!rb) {
1919 _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating accum buffer");
1920 return GL_FALSE;
1921 }
1922
1923 rb->_ActualFormat = GL_RGBA16;
1924 rb->InternalFormat = GL_RGBA16;
1925 rb->AllocStorage = _mesa_soft_renderbuffer_storage;
1926 _mesa_add_renderbuffer(fb, BUFFER_ACCUM, rb);
1927
1928 return GL_TRUE;
1929 }
1930
1931
1932
1933 /**
1934 * Add a software-based accumulation renderbuffer to the given framebuffer.
1935 * This is a helper routine for device drivers when creating a
1936 * window system framebuffer (not a user-created render/framebuffer).
1937 * Once this function is called, you can basically forget about this
1938 * renderbuffer; core Mesa will handle all the buffer management and
1939 * rendering!
1940 *
1941 * NOTE: color-index aux buffers not supported.
1942 */
1943 GLboolean
1944 _mesa_add_aux_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb,
1945 GLuint colorBits, GLuint numBuffers)
1946 {
1947 GLuint i;
1948
1949 if (colorBits > 16) {
1950 _mesa_problem(ctx,
1951 "Unsupported accumBits in _mesa_add_aux_renderbuffers");
1952 return GL_FALSE;
1953 }
1954
1955 assert(numBuffers < MAX_AUX_BUFFERS);
1956
1957 for (i = 0; i < numBuffers; i++) {
1958 struct gl_renderbuffer *rb = _mesa_new_renderbuffer(ctx, 0);
1959
1960 assert(fb->Attachment[BUFFER_AUX0 + i].Renderbuffer == NULL);
1961
1962 if (!rb) {
1963 _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating accum buffer");
1964 return GL_FALSE;
1965 }
1966
1967 if (colorBits <= 8) {
1968 rb->_ActualFormat = GL_RGBA8;
1969 }
1970 else {
1971 rb->_ActualFormat = GL_RGBA16;
1972 }
1973 rb->InternalFormat = rb->_ActualFormat;
1974
1975 rb->AllocStorage = _mesa_soft_renderbuffer_storage;
1976 _mesa_add_renderbuffer(fb, BUFFER_AUX0 + i, rb);
1977 }
1978 return GL_TRUE;
1979 }
1980
1981
1982 /**
1983 * Create/attach software-based renderbuffers to the given framebuffer.
1984 * This is a helper routine for device drivers. Drivers can just as well
1985 * call the individual _mesa_add_*_renderbuffer() routines directly.
1986 */
1987 void
1988 _mesa_add_soft_renderbuffers(struct gl_framebuffer *fb,
1989 GLboolean color,
1990 GLboolean depth,
1991 GLboolean stencil,
1992 GLboolean accum,
1993 GLboolean alpha,
1994 GLboolean aux)
1995 {
1996 GLboolean frontLeft = GL_TRUE;
1997 GLboolean backLeft = fb->Visual.doubleBufferMode;
1998 GLboolean frontRight = fb->Visual.stereoMode;
1999 GLboolean backRight = fb->Visual.stereoMode && fb->Visual.doubleBufferMode;
2000
2001 if (color) {
2002 if (fb->Visual.rgbMode) {
2003 assert(fb->Visual.redBits == fb->Visual.greenBits);
2004 assert(fb->Visual.redBits == fb->Visual.blueBits);
2005 _mesa_add_color_renderbuffers(NULL, fb,
2006 fb->Visual.redBits,
2007 fb->Visual.alphaBits,
2008 frontLeft, backLeft,
2009 frontRight, backRight);
2010 }
2011 else {
2012 _mesa_add_color_index_renderbuffers(NULL, fb,
2013 fb->Visual.indexBits,
2014 frontLeft, backLeft,
2015 frontRight, backRight);
2016 }
2017 }
2018
2019 if (depth) {
2020 assert(fb->Visual.depthBits > 0);
2021 _mesa_add_depth_renderbuffer(NULL, fb, fb->Visual.depthBits);
2022 }
2023
2024 if (stencil) {
2025 assert(fb->Visual.stencilBits > 0);
2026 _mesa_add_stencil_renderbuffer(NULL, fb, fb->Visual.stencilBits);
2027 }
2028
2029 if (accum) {
2030 assert(fb->Visual.rgbMode);
2031 assert(fb->Visual.accumRedBits > 0);
2032 assert(fb->Visual.accumGreenBits > 0);
2033 assert(fb->Visual.accumBlueBits > 0);
2034 _mesa_add_accum_renderbuffer(NULL, fb,
2035 fb->Visual.accumRedBits,
2036 fb->Visual.accumGreenBits,
2037 fb->Visual.accumBlueBits,
2038 fb->Visual.accumAlphaBits);
2039 }
2040
2041 if (aux) {
2042 assert(fb->Visual.rgbMode);
2043 assert(fb->Visual.numAuxBuffers > 0);
2044 _mesa_add_aux_renderbuffers(NULL, fb, fb->Visual.redBits,
2045 fb->Visual.numAuxBuffers);
2046 }
2047
2048 if (alpha) {
2049 assert(fb->Visual.rgbMode);
2050 assert(fb->Visual.alphaBits > 0);
2051 _mesa_add_alpha_renderbuffers(NULL, fb, fb->Visual.alphaBits,
2052 frontLeft, backLeft,
2053 frontRight, backRight);
2054 }
2055
2056 #if 0
2057 if (multisample) {
2058 /* maybe someday */
2059 }
2060 #endif
2061 }
2062
2063
2064 /**
2065 * Attach a renderbuffer to a framebuffer.
2066 */
2067 void
2068 _mesa_add_renderbuffer(struct gl_framebuffer *fb,
2069 GLuint bufferName, struct gl_renderbuffer *rb)
2070 {
2071 assert(fb);
2072 assert(rb);
2073 assert(bufferName < BUFFER_COUNT);
2074
2075 /* There should be no previous renderbuffer on this attachment point,
2076 * with the exception of depth/stencil since the same renderbuffer may
2077 * be used for both.
2078 */
2079 assert(bufferName == BUFFER_DEPTH ||
2080 bufferName == BUFFER_STENCIL ||
2081 fb->Attachment[bufferName].Renderbuffer == NULL);
2082
2083 /* winsys vs. user-created buffer cross check */
2084 if (fb->Name) {
2085 assert(rb->Name);
2086 }
2087 else {
2088 assert(!rb->Name);
2089 }
2090
2091 /* If Mesa's compiled with deep color channels (16 or 32 bits / channel)
2092 * and the device driver is expecting 8-bit values (GLubyte), we can
2093 * use a "renderbuffer adaptor/wrapper" to do the necessary conversions.
2094 */
2095 if (rb->_BaseFormat == GL_RGBA) {
2096 if (CHAN_BITS == 16 && rb->DataType == GL_UNSIGNED_BYTE) {
2097 GET_CURRENT_CONTEXT(ctx);
2098 rb = _mesa_new_renderbuffer_16wrap8(ctx, rb);
2099 }
2100 else if (CHAN_BITS == 32 && rb->DataType == GL_UNSIGNED_BYTE) {
2101 GET_CURRENT_CONTEXT(ctx);
2102 rb = _mesa_new_renderbuffer_32wrap8(ctx, rb);
2103 }
2104 else if (CHAN_BITS == 32 && rb->DataType == GL_UNSIGNED_SHORT) {
2105 GET_CURRENT_CONTEXT(ctx);
2106 rb = _mesa_new_renderbuffer_32wrap16(ctx, rb);
2107 }
2108 }
2109
2110 fb->Attachment[bufferName].Type = GL_RENDERBUFFER_EXT;
2111 fb->Attachment[bufferName].Complete = GL_TRUE;
2112 _mesa_reference_renderbuffer(&fb->Attachment[bufferName].Renderbuffer, rb);
2113 }
2114
2115
2116 /**
2117 * Remove the named renderbuffer from the given framebuffer.
2118 */
2119 void
2120 _mesa_remove_renderbuffer(struct gl_framebuffer *fb, GLuint bufferName)
2121 {
2122 struct gl_renderbuffer *rb;
2123
2124 assert(bufferName < BUFFER_COUNT);
2125
2126 rb = fb->Attachment[bufferName].Renderbuffer;
2127 if (!rb)
2128 return;
2129
2130 _mesa_reference_renderbuffer(&rb, NULL);
2131
2132 fb->Attachment[bufferName].Renderbuffer = NULL;
2133 }
2134
2135
2136 /**
2137 * Set *ptr to point to rb. If *ptr points to another renderbuffer,
2138 * dereference that buffer first. The new renderbuffer's refcount will
2139 * be incremented. The old renderbuffer's refcount will be decremented.
2140 */
2141 void
2142 _mesa_reference_renderbuffer(struct gl_renderbuffer **ptr,
2143 struct gl_renderbuffer *rb)
2144 {
2145 assert(ptr);
2146 if (*ptr == rb) {
2147 /* no change */
2148 return;
2149 }
2150
2151 if (*ptr) {
2152 /* Unreference the old renderbuffer */
2153 GLboolean deleteFlag = GL_FALSE;
2154 struct gl_renderbuffer *oldRb = *ptr;
2155
2156 assert(oldRb->Magic == RB_MAGIC);
2157 _glthread_LOCK_MUTEX(oldRb->Mutex);
2158 assert(oldRb->Magic == RB_MAGIC);
2159 ASSERT(oldRb->RefCount > 0);
2160 oldRb->RefCount--;
2161 /*printf("RB DECR %p (%d) to %d\n", (void*) oldRb, oldRb->Name, oldRb->RefCount);*/
2162 deleteFlag = (oldRb->RefCount == 0);
2163 _glthread_UNLOCK_MUTEX(oldRb->Mutex);
2164
2165 if (deleteFlag) {
2166 oldRb->Magic = 0; /* now invalid memory! */
2167 oldRb->Delete(oldRb);
2168 }
2169
2170 *ptr = NULL;
2171 }
2172 assert(!*ptr);
2173
2174 if (rb) {
2175 assert(rb->Magic == RB_MAGIC);
2176 /* reference new renderbuffer */
2177 _glthread_LOCK_MUTEX(rb->Mutex);
2178 rb->RefCount++;
2179 /*printf("RB INCR %p (%d) to %d\n", (void*) rb, rb->Name, rb->RefCount);*/
2180 _glthread_UNLOCK_MUTEX(rb->Mutex);
2181 *ptr = rb;
2182 }
2183 }
2184
2185
2186 /**
2187 * Create a new combined depth/stencil renderbuffer for implementing
2188 * the GL_EXT_packed_depth_stencil extension.
2189 * \return new depth/stencil renderbuffer
2190 */
2191 struct gl_renderbuffer *
2192 _mesa_new_depthstencil_renderbuffer(GLcontext *ctx, GLuint name)
2193 {
2194 struct gl_renderbuffer *dsrb;
2195
2196 dsrb = _mesa_new_renderbuffer(ctx, name);
2197 if (!dsrb)
2198 return NULL;
2199
2200 /* init fields not covered by _mesa_new_renderbuffer() */
2201 dsrb->InternalFormat = GL_DEPTH24_STENCIL8_EXT;
2202 dsrb->_ActualFormat = GL_DEPTH24_STENCIL8_EXT;
2203 dsrb->AllocStorage = _mesa_soft_renderbuffer_storage;
2204
2205 return dsrb;
2206 }