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