2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
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:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
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.
27 * Functions for allocating/managing renderbuffers.
28 * Also, routines for reading/writing software-based renderbuffer data as
29 * ubytes, ushorts, uints, etc.
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.
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.
49 #include "renderbuffer.h"
53 * Routines for get/put values in common buffer formats follow.
56 /**********************************************************************
57 * Functions for buffers of 1 X GLubyte values.
62 get_pointer_ubyte(struct gl_context
*ctx
, struct gl_renderbuffer
*rb
,
67 ASSERT(rb
->DataType
== GL_UNSIGNED_BYTE
);
68 /* Can't assert rb->Format since these funcs may be used for serveral
69 * different formats (GL_ALPHA8, GL_STENCIL_INDEX8, etc).
71 return (GLubyte
*) rb
->Data
+ y
* rb
->RowStride
+ x
;
76 get_row_ubyte(struct gl_context
*ctx
, struct gl_renderbuffer
*rb
, GLuint count
,
77 GLint x
, GLint y
, void *values
)
79 const GLubyte
*src
= (const GLubyte
*) rb
->Data
+ y
* rb
->RowStride
+ x
;
80 ASSERT(rb
->DataType
== GL_UNSIGNED_BYTE
);
81 memcpy(values
, src
, count
* sizeof(GLubyte
));
86 get_values_ubyte(struct gl_context
*ctx
, struct gl_renderbuffer
*rb
, GLuint count
,
87 const GLint x
[], const GLint y
[], void *values
)
89 GLubyte
*dst
= (GLubyte
*) values
;
91 ASSERT(rb
->DataType
== GL_UNSIGNED_BYTE
);
92 for (i
= 0; i
< count
; i
++) {
93 const GLubyte
*src
= (GLubyte
*) rb
->Data
+ y
[i
] * rb
->RowStride
+ x
[i
];
100 put_row_ubyte(struct gl_context
*ctx
, struct gl_renderbuffer
*rb
, GLuint count
,
101 GLint x
, GLint y
, const void *values
, const GLubyte
*mask
)
103 const GLubyte
*src
= (const GLubyte
*) values
;
104 GLubyte
*dst
= (GLubyte
*) rb
->Data
+ y
* rb
->RowStride
+ x
;
105 ASSERT(rb
->DataType
== GL_UNSIGNED_BYTE
);
108 for (i
= 0; i
< count
; i
++) {
115 memcpy(dst
, values
, count
* sizeof(GLubyte
));
121 put_mono_row_ubyte(struct gl_context
*ctx
, struct gl_renderbuffer
*rb
, GLuint count
,
122 GLint x
, GLint y
, const void *value
, const GLubyte
*mask
)
124 const GLubyte val
= *((const GLubyte
*) value
);
125 GLubyte
*dst
= (GLubyte
*) rb
->Data
+ y
* rb
->RowStride
+ x
;
126 ASSERT(rb
->DataType
== GL_UNSIGNED_BYTE
);
129 for (i
= 0; i
< count
; i
++) {
137 for (i
= 0; i
< count
; i
++) {
145 put_values_ubyte(struct gl_context
*ctx
, struct gl_renderbuffer
*rb
, GLuint count
,
146 const GLint x
[], const GLint y
[],
147 const void *values
, const GLubyte
*mask
)
149 const GLubyte
*src
= (const GLubyte
*) values
;
151 ASSERT(rb
->DataType
== GL_UNSIGNED_BYTE
);
152 for (i
= 0; i
< count
; i
++) {
153 if (!mask
|| mask
[i
]) {
154 GLubyte
*dst
= (GLubyte
*) rb
->Data
+ y
[i
] * rb
->RowStride
+ x
[i
];
162 put_mono_values_ubyte(struct gl_context
*ctx
, struct gl_renderbuffer
*rb
, GLuint count
,
163 const GLint x
[], const GLint y
[],
164 const void *value
, const GLubyte
*mask
)
166 const GLubyte val
= *((const GLubyte
*) value
);
168 ASSERT(rb
->DataType
== GL_UNSIGNED_BYTE
);
169 for (i
= 0; i
< count
; i
++) {
170 if (!mask
|| mask
[i
]) {
171 GLubyte
*dst
= (GLubyte
*) rb
->Data
+ y
[i
] * rb
->RowStride
+ x
[i
];
178 /**********************************************************************
179 * Functions for buffers of 1 X GLushort values.
184 get_pointer_ushort(struct gl_context
*ctx
, struct gl_renderbuffer
*rb
,
189 ASSERT(rb
->DataType
== GL_UNSIGNED_SHORT
);
190 ASSERT(rb
->Width
> 0);
191 return (GLushort
*) rb
->Data
+ y
* rb
->RowStride
+ x
;
196 get_row_ushort(struct gl_context
*ctx
, struct gl_renderbuffer
*rb
, GLuint count
,
197 GLint x
, GLint y
, void *values
)
199 const void *src
= rb
->GetPointer(ctx
, rb
, x
, y
);
200 ASSERT(rb
->DataType
== GL_UNSIGNED_SHORT
);
201 memcpy(values
, src
, count
* sizeof(GLushort
));
206 get_values_ushort(struct gl_context
*ctx
, struct gl_renderbuffer
*rb
, GLuint count
,
207 const GLint x
[], const GLint y
[], void *values
)
209 GLushort
*dst
= (GLushort
*) values
;
211 ASSERT(rb
->DataType
== GL_UNSIGNED_SHORT
);
212 for (i
= 0; i
< count
; i
++) {
213 const GLushort
*src
= (GLushort
*) rb
->Data
+ y
[i
] * rb
->RowStride
+ x
[i
];
220 put_row_ushort(struct gl_context
*ctx
, struct gl_renderbuffer
*rb
, GLuint count
,
221 GLint x
, GLint y
, const void *values
, const GLubyte
*mask
)
223 const GLushort
*src
= (const GLushort
*) values
;
224 GLushort
*dst
= (GLushort
*) rb
->Data
+ y
* rb
->RowStride
+ x
;
225 ASSERT(rb
->DataType
== GL_UNSIGNED_SHORT
);
228 for (i
= 0; i
< count
; i
++) {
235 memcpy(dst
, src
, count
* sizeof(GLushort
));
241 put_mono_row_ushort(struct gl_context
*ctx
, struct gl_renderbuffer
*rb
, GLuint count
,
242 GLint x
, GLint y
, const void *value
, const GLubyte
*mask
)
244 const GLushort val
= *((const GLushort
*) value
);
245 GLushort
*dst
= (GLushort
*) rb
->Data
+ y
* rb
->RowStride
+ x
;
246 ASSERT(rb
->DataType
== GL_UNSIGNED_SHORT
);
249 for (i
= 0; i
< count
; i
++) {
257 for (i
= 0; i
< count
; i
++) {
265 put_values_ushort(struct gl_context
*ctx
, struct gl_renderbuffer
*rb
, GLuint count
,
266 const GLint x
[], const GLint y
[], const void *values
,
269 const GLushort
*src
= (const GLushort
*) values
;
271 ASSERT(rb
->DataType
== GL_UNSIGNED_SHORT
);
272 for (i
= 0; i
< count
; i
++) {
273 if (!mask
|| mask
[i
]) {
274 GLushort
*dst
= (GLushort
*) rb
->Data
+ y
[i
] * rb
->RowStride
+ x
[i
];
282 put_mono_values_ushort(struct gl_context
*ctx
, struct gl_renderbuffer
*rb
,
283 GLuint count
, const GLint x
[], const GLint y
[],
284 const void *value
, const GLubyte
*mask
)
286 const GLushort val
= *((const GLushort
*) value
);
287 ASSERT(rb
->DataType
== GL_UNSIGNED_SHORT
);
290 for (i
= 0; i
< count
; i
++) {
292 GLushort
*dst
= (GLushort
*) rb
->Data
+ y
[i
] * rb
->RowStride
+ x
[i
];
299 for (i
= 0; i
< count
; i
++) {
300 GLushort
*dst
= (GLushort
*) rb
->Data
+ y
[i
] * rb
->RowStride
+ x
[i
];
307 /**********************************************************************
308 * Functions for buffers of 1 X GLuint values.
309 * Typically depth/Z or color index.
313 get_pointer_uint(struct gl_context
*ctx
, struct gl_renderbuffer
*rb
,
318 ASSERT(rb
->DataType
== GL_UNSIGNED_INT
||
319 rb
->DataType
== GL_UNSIGNED_INT_24_8_EXT
);
320 return (GLuint
*) rb
->Data
+ y
* rb
->RowStride
+ x
;
325 get_row_uint(struct gl_context
*ctx
, struct gl_renderbuffer
*rb
, GLuint count
,
326 GLint x
, GLint y
, void *values
)
328 const void *src
= rb
->GetPointer(ctx
, rb
, x
, y
);
329 ASSERT(rb
->DataType
== GL_UNSIGNED_INT
||
330 rb
->DataType
== GL_UNSIGNED_INT_24_8_EXT
);
331 memcpy(values
, src
, count
* sizeof(GLuint
));
336 get_values_uint(struct gl_context
*ctx
, struct gl_renderbuffer
*rb
, GLuint count
,
337 const GLint x
[], const GLint y
[], void *values
)
339 GLuint
*dst
= (GLuint
*) values
;
341 ASSERT(rb
->DataType
== GL_UNSIGNED_INT
||
342 rb
->DataType
== GL_UNSIGNED_INT_24_8_EXT
);
343 for (i
= 0; i
< count
; i
++) {
344 const GLuint
*src
= (GLuint
*) rb
->Data
+ y
[i
] * rb
->RowStride
+ x
[i
];
351 put_row_uint(struct gl_context
*ctx
, struct gl_renderbuffer
*rb
, GLuint count
,
352 GLint x
, GLint y
, const void *values
, const GLubyte
*mask
)
354 const GLuint
*src
= (const GLuint
*) values
;
355 GLuint
*dst
= (GLuint
*) rb
->Data
+ y
* rb
->RowStride
+ x
;
356 ASSERT(rb
->DataType
== GL_UNSIGNED_INT
||
357 rb
->DataType
== GL_UNSIGNED_INT_24_8_EXT
);
360 for (i
= 0; i
< count
; i
++) {
367 memcpy(dst
, src
, count
* sizeof(GLuint
));
373 put_mono_row_uint(struct gl_context
*ctx
, struct gl_renderbuffer
*rb
, GLuint count
,
374 GLint x
, GLint y
, const void *value
, const GLubyte
*mask
)
376 const GLuint val
= *((const GLuint
*) value
);
377 GLuint
*dst
= (GLuint
*) rb
->Data
+ y
* rb
->RowStride
+ x
;
378 ASSERT(rb
->DataType
== GL_UNSIGNED_INT
||
379 rb
->DataType
== GL_UNSIGNED_INT_24_8_EXT
);
382 for (i
= 0; i
< count
; i
++) {
390 for (i
= 0; i
< count
; i
++) {
398 put_values_uint(struct gl_context
*ctx
, struct gl_renderbuffer
*rb
, GLuint count
,
399 const GLint x
[], const GLint y
[], const void *values
,
402 const GLuint
*src
= (const GLuint
*) values
;
404 ASSERT(rb
->DataType
== GL_UNSIGNED_INT
||
405 rb
->DataType
== GL_UNSIGNED_INT_24_8_EXT
);
406 for (i
= 0; i
< count
; i
++) {
407 if (!mask
|| mask
[i
]) {
408 GLuint
*dst
= (GLuint
*) rb
->Data
+ y
[i
] * rb
->RowStride
+ x
[i
];
416 put_mono_values_uint(struct gl_context
*ctx
, struct gl_renderbuffer
*rb
, GLuint count
,
417 const GLint x
[], const GLint y
[], const void *value
,
420 const GLuint val
= *((const GLuint
*) value
);
422 ASSERT(rb
->DataType
== GL_UNSIGNED_INT
||
423 rb
->DataType
== GL_UNSIGNED_INT_24_8_EXT
);
424 for (i
= 0; i
< count
; i
++) {
425 if (!mask
|| mask
[i
]) {
426 GLuint
*dst
= (GLuint
*) rb
->Data
+ y
[i
] * rb
->RowStride
+ x
[i
];
433 /**********************************************************************
434 * Functions for buffers of 3 X GLubyte (or GLbyte) values.
435 * Typically color buffers.
436 * NOTE: the incoming and outgoing colors are RGBA! We ignore incoming
437 * alpha values and return 255 for outgoing alpha values.
441 get_pointer_ubyte3(struct gl_context
*ctx
, struct gl_renderbuffer
*rb
,
444 ASSERT(rb
->Format
== MESA_FORMAT_RGB888
);
445 /* No direct access since this buffer is RGB but caller will be
446 * treating it as if it were RGBA.
453 get_row_ubyte3(struct gl_context
*ctx
, struct gl_renderbuffer
*rb
, GLuint count
,
454 GLint x
, GLint y
, void *values
)
456 const GLubyte
*src
= (const GLubyte
*) (rb
->Data
+
457 3 * (y
* rb
->RowStride
+ x
));
458 GLubyte
*dst
= (GLubyte
*) values
;
460 ASSERT(rb
->Format
== MESA_FORMAT_RGB888
);
461 ASSERT(rb
->DataType
== GL_UNSIGNED_BYTE
);
462 for (i
= 0; i
< count
; i
++) {
463 dst
[i
* 4 + 0] = src
[i
* 3 + 0];
464 dst
[i
* 4 + 1] = src
[i
* 3 + 1];
465 dst
[i
* 4 + 2] = src
[i
* 3 + 2];
466 dst
[i
* 4 + 3] = 255;
472 get_values_ubyte3(struct gl_context
*ctx
, struct gl_renderbuffer
*rb
, GLuint count
,
473 const GLint x
[], const GLint y
[], void *values
)
475 GLubyte
*dst
= (GLubyte
*) values
;
477 ASSERT(rb
->Format
== MESA_FORMAT_RGB888
);
478 ASSERT(rb
->DataType
== GL_UNSIGNED_BYTE
);
479 for (i
= 0; i
< count
; i
++) {
481 = (GLubyte
*) rb
->Data
+ 3 * (y
[i
] * rb
->RowStride
+ x
[i
]);
482 dst
[i
* 4 + 0] = src
[0];
483 dst
[i
* 4 + 1] = src
[1];
484 dst
[i
* 4 + 2] = src
[2];
485 dst
[i
* 4 + 3] = 255;
491 put_row_ubyte3(struct gl_context
*ctx
, struct gl_renderbuffer
*rb
, GLuint count
,
492 GLint x
, GLint y
, const void *values
, const GLubyte
*mask
)
494 /* note: incoming values are RGB+A! */
495 const GLubyte
*src
= (const GLubyte
*) values
;
496 GLubyte
*dst
= (GLubyte
*) rb
->Data
+ 3 * (y
* rb
->RowStride
+ x
);
498 ASSERT(rb
->Format
== MESA_FORMAT_RGB888
);
499 ASSERT(rb
->DataType
== GL_UNSIGNED_BYTE
);
500 for (i
= 0; i
< count
; i
++) {
501 if (!mask
|| mask
[i
]) {
502 dst
[i
* 3 + 0] = src
[i
* 4 + 0];
503 dst
[i
* 3 + 1] = src
[i
* 4 + 1];
504 dst
[i
* 3 + 2] = src
[i
* 4 + 2];
511 put_row_rgb_ubyte3(struct gl_context
*ctx
, struct gl_renderbuffer
*rb
, GLuint count
,
512 GLint x
, GLint y
, const void *values
, const GLubyte
*mask
)
514 /* note: incoming values are RGB+A! */
515 const GLubyte
*src
= (const GLubyte
*) values
;
516 GLubyte
*dst
= (GLubyte
*) rb
->Data
+ 3 * (y
* rb
->RowStride
+ x
);
518 ASSERT(rb
->Format
== MESA_FORMAT_RGB888
);
519 ASSERT(rb
->DataType
== GL_UNSIGNED_BYTE
);
520 for (i
= 0; i
< count
; i
++) {
521 if (!mask
|| mask
[i
]) {
522 dst
[i
* 3 + 0] = src
[i
* 3 + 0];
523 dst
[i
* 3 + 1] = src
[i
* 3 + 1];
524 dst
[i
* 3 + 2] = src
[i
* 3 + 2];
531 put_mono_row_ubyte3(struct gl_context
*ctx
, struct gl_renderbuffer
*rb
, GLuint count
,
532 GLint x
, GLint y
, const void *value
, const GLubyte
*mask
)
534 /* note: incoming value is RGB+A! */
535 const GLubyte val0
= ((const GLubyte
*) value
)[0];
536 const GLubyte val1
= ((const GLubyte
*) value
)[1];
537 const GLubyte val2
= ((const GLubyte
*) value
)[2];
538 GLubyte
*dst
= (GLubyte
*) rb
->Data
+ 3 * (y
* rb
->RowStride
+ x
);
539 ASSERT(rb
->Format
== MESA_FORMAT_RGB888
);
540 ASSERT(rb
->DataType
== GL_UNSIGNED_BYTE
);
541 if (!mask
&& val0
== val1
&& val1
== val2
) {
543 memset(dst
, val0
, 3 * count
);
547 for (i
= 0; i
< count
; i
++) {
548 if (!mask
|| mask
[i
]) {
549 dst
[i
* 3 + 0] = val0
;
550 dst
[i
* 3 + 1] = val1
;
551 dst
[i
* 3 + 2] = val2
;
559 put_values_ubyte3(struct gl_context
*ctx
, struct gl_renderbuffer
*rb
, GLuint count
,
560 const GLint x
[], const GLint y
[], const void *values
,
563 /* note: incoming values are RGB+A! */
564 const GLubyte
*src
= (const GLubyte
*) values
;
566 ASSERT(rb
->Format
== MESA_FORMAT_RGB888
);
567 ASSERT(rb
->DataType
== GL_UNSIGNED_BYTE
);
568 for (i
= 0; i
< count
; i
++) {
569 if (!mask
|| mask
[i
]) {
570 GLubyte
*dst
= (GLubyte
*) rb
->Data
+ 3 * (y
[i
] * rb
->RowStride
+ x
[i
]);
571 dst
[0] = src
[i
* 4 + 0];
572 dst
[1] = src
[i
* 4 + 1];
573 dst
[2] = src
[i
* 4 + 2];
580 put_mono_values_ubyte3(struct gl_context
*ctx
, struct gl_renderbuffer
*rb
,
581 GLuint count
, const GLint x
[], const GLint y
[],
582 const void *value
, const GLubyte
*mask
)
584 /* note: incoming value is RGB+A! */
585 const GLubyte val0
= ((const GLubyte
*) value
)[0];
586 const GLubyte val1
= ((const GLubyte
*) value
)[1];
587 const GLubyte val2
= ((const GLubyte
*) value
)[2];
589 ASSERT(rb
->Format
== MESA_FORMAT_RGB888
);
590 ASSERT(rb
->DataType
== GL_UNSIGNED_BYTE
);
591 for (i
= 0; i
< count
; i
++) {
592 if (!mask
|| mask
[i
]) {
593 GLubyte
*dst
= (GLubyte
*) (rb
->Data
+
594 3 * (y
[i
] * rb
->RowStride
+ x
[i
]));
603 /**********************************************************************
604 * Functions for buffers of 4 X GLubyte (or GLbyte) values.
605 * Typically color buffers.
609 get_pointer_ubyte4(struct gl_context
*ctx
, struct gl_renderbuffer
*rb
,
614 ASSERT(rb
->DataType
== GL_UNSIGNED_BYTE
);
615 ASSERT(rb
->Format
== MESA_FORMAT_RGBA8888
);
616 return (GLubyte
*) rb
->Data
+ 4 * (y
* rb
->RowStride
+ x
);
621 get_row_ubyte4(struct gl_context
*ctx
, struct gl_renderbuffer
*rb
, GLuint count
,
622 GLint x
, GLint y
, void *values
)
624 const GLubyte
*src
= (const GLubyte
*) (rb
->Data
+
625 4 * (y
* rb
->RowStride
+ x
));
626 ASSERT(rb
->DataType
== GL_UNSIGNED_BYTE
);
627 ASSERT(rb
->Format
== MESA_FORMAT_RGBA8888
);
628 memcpy(values
, src
, 4 * count
* sizeof(GLubyte
));
633 get_values_ubyte4(struct gl_context
*ctx
, struct gl_renderbuffer
*rb
, GLuint count
,
634 const GLint x
[], const GLint y
[], void *values
)
636 /* treat 4*GLubyte as 1*GLuint */
637 GLuint
*dst
= (GLuint
*) values
;
639 ASSERT(rb
->DataType
== GL_UNSIGNED_BYTE
);
640 ASSERT(rb
->Format
== MESA_FORMAT_RGBA8888
);
641 for (i
= 0; i
< count
; i
++) {
642 const GLuint
*src
= (GLuint
*) rb
->Data
+ (y
[i
] * rb
->RowStride
+ x
[i
]);
649 put_row_ubyte4(struct gl_context
*ctx
, struct gl_renderbuffer
*rb
, GLuint count
,
650 GLint x
, GLint y
, const void *values
, const GLubyte
*mask
)
652 /* treat 4*GLubyte as 1*GLuint */
653 const GLuint
*src
= (const GLuint
*) values
;
654 GLuint
*dst
= (GLuint
*) rb
->Data
+ (y
* rb
->RowStride
+ x
);
655 ASSERT(rb
->DataType
== GL_UNSIGNED_BYTE
);
656 ASSERT(rb
->Format
== MESA_FORMAT_RGBA8888
);
659 for (i
= 0; i
< count
; i
++) {
666 memcpy(dst
, src
, 4 * count
* sizeof(GLubyte
));
672 put_row_rgb_ubyte4(struct gl_context
*ctx
, struct gl_renderbuffer
*rb
, GLuint count
,
673 GLint x
, GLint y
, const void *values
, const GLubyte
*mask
)
675 /* Store RGB values in RGBA buffer */
676 const GLubyte
*src
= (const GLubyte
*) values
;
677 GLubyte
*dst
= (GLubyte
*) rb
->Data
+ 4 * (y
* rb
->RowStride
+ x
);
679 ASSERT(rb
->DataType
== GL_UNSIGNED_BYTE
);
680 ASSERT(rb
->Format
== MESA_FORMAT_RGBA8888
);
681 for (i
= 0; i
< count
; i
++) {
682 if (!mask
|| mask
[i
]) {
683 dst
[i
* 4 + 0] = src
[i
* 3 + 0];
684 dst
[i
* 4 + 1] = src
[i
* 3 + 1];
685 dst
[i
* 4 + 2] = src
[i
* 3 + 2];
686 dst
[i
* 4 + 3] = 0xff;
693 put_mono_row_ubyte4(struct gl_context
*ctx
, struct gl_renderbuffer
*rb
, GLuint count
,
694 GLint x
, GLint y
, const void *value
, const GLubyte
*mask
)
696 /* treat 4*GLubyte as 1*GLuint */
697 const GLuint val
= *((const GLuint
*) value
);
698 GLuint
*dst
= (GLuint
*) rb
->Data
+ (y
* rb
->RowStride
+ x
);
699 ASSERT(rb
->DataType
== GL_UNSIGNED_BYTE
);
700 ASSERT(rb
->Format
== MESA_FORMAT_RGBA8888
);
701 if (!mask
&& val
== 0) {
703 memset(dst
, 0, count
* 4 * sizeof(GLubyte
));
709 for (i
= 0; i
< count
; i
++) {
717 for (i
= 0; i
< count
; i
++) {
726 put_values_ubyte4(struct gl_context
*ctx
, struct gl_renderbuffer
*rb
, GLuint count
,
727 const GLint x
[], const GLint y
[], const void *values
,
730 /* treat 4*GLubyte as 1*GLuint */
731 const GLuint
*src
= (const GLuint
*) values
;
733 ASSERT(rb
->DataType
== GL_UNSIGNED_BYTE
);
734 ASSERT(rb
->Format
== MESA_FORMAT_RGBA8888
);
735 for (i
= 0; i
< count
; i
++) {
736 if (!mask
|| mask
[i
]) {
737 GLuint
*dst
= (GLuint
*) rb
->Data
+ (y
[i
] * rb
->RowStride
+ x
[i
]);
745 put_mono_values_ubyte4(struct gl_context
*ctx
, struct gl_renderbuffer
*rb
,
746 GLuint count
, const GLint x
[], const GLint y
[],
747 const void *value
, const GLubyte
*mask
)
749 /* treat 4*GLubyte as 1*GLuint */
750 const GLuint val
= *((const GLuint
*) value
);
752 ASSERT(rb
->DataType
== GL_UNSIGNED_BYTE
);
753 ASSERT(rb
->Format
== MESA_FORMAT_RGBA8888
);
754 for (i
= 0; i
< count
; i
++) {
755 if (!mask
|| mask
[i
]) {
756 GLuint
*dst
= (GLuint
*) rb
->Data
+ (y
[i
] * rb
->RowStride
+ x
[i
]);
763 /**********************************************************************
764 * Functions for buffers of 4 X GLushort (or GLshort) values.
765 * Typically accum buffer.
769 get_pointer_ushort4(struct gl_context
*ctx
, struct gl_renderbuffer
*rb
,
774 ASSERT(rb
->DataType
== GL_UNSIGNED_SHORT
|| rb
->DataType
== GL_SHORT
);
775 return (GLushort
*) rb
->Data
+ 4 * (y
* rb
->RowStride
+ x
);
780 get_row_ushort4(struct gl_context
*ctx
, struct gl_renderbuffer
*rb
, GLuint count
,
781 GLint x
, GLint y
, void *values
)
783 const GLshort
*src
= (const GLshort
*) (rb
->Data
+
784 4 * (y
* rb
->RowStride
+ x
));
785 ASSERT(rb
->DataType
== GL_UNSIGNED_SHORT
|| rb
->DataType
== GL_SHORT
);
786 memcpy(values
, src
, 4 * count
* sizeof(GLshort
));
791 get_values_ushort4(struct gl_context
*ctx
, struct gl_renderbuffer
*rb
, GLuint count
,
792 const GLint x
[], const GLint y
[], void *values
)
794 GLushort
*dst
= (GLushort
*) values
;
796 ASSERT(rb
->DataType
== GL_UNSIGNED_SHORT
|| rb
->DataType
== GL_SHORT
);
797 for (i
= 0; i
< count
; i
++) {
799 = (GLushort
*) rb
->Data
+ 4 * (y
[i
] * rb
->RowStride
+ x
[i
]);
806 put_row_ushort4(struct gl_context
*ctx
, struct gl_renderbuffer
*rb
, GLuint count
,
807 GLint x
, GLint y
, const void *values
, const GLubyte
*mask
)
809 const GLushort
*src
= (const GLushort
*) values
;
810 GLushort
*dst
= (GLushort
*) rb
->Data
+ 4 * (y
* rb
->RowStride
+ x
);
811 ASSERT(rb
->DataType
== GL_UNSIGNED_SHORT
|| rb
->DataType
== GL_SHORT
);
814 for (i
= 0; i
< count
; i
++) {
816 dst
[i
* 4 + 0] = src
[i
* 4 + 0];
817 dst
[i
* 4 + 1] = src
[i
* 4 + 1];
818 dst
[i
* 4 + 2] = src
[i
* 4 + 2];
819 dst
[i
* 4 + 3] = src
[i
* 4 + 3];
824 memcpy(dst
, src
, 4 * count
* sizeof(GLushort
));
830 put_row_rgb_ushort4(struct gl_context
*ctx
, struct gl_renderbuffer
*rb
, GLuint count
,
831 GLint x
, GLint y
, const void *values
, const GLubyte
*mask
)
833 /* Put RGB values in RGBA buffer */
834 const GLushort
*src
= (const GLushort
*) values
;
835 GLushort
*dst
= (GLushort
*) rb
->Data
+ 4 * (y
* rb
->RowStride
+ x
);
836 ASSERT(rb
->DataType
== GL_UNSIGNED_SHORT
|| rb
->DataType
== GL_SHORT
);
839 for (i
= 0; i
< count
; i
++) {
841 dst
[i
* 4 + 0] = src
[i
* 3 + 0];
842 dst
[i
* 4 + 1] = src
[i
* 3 + 1];
843 dst
[i
* 4 + 2] = src
[i
* 3 + 2];
844 dst
[i
* 4 + 3] = 0xffff;
849 memcpy(dst
, src
, 4 * count
* sizeof(GLushort
));
855 put_mono_row_ushort4(struct gl_context
*ctx
, struct gl_renderbuffer
*rb
, GLuint count
,
856 GLint x
, GLint y
, const void *value
, const GLubyte
*mask
)
858 const GLushort val0
= ((const GLushort
*) value
)[0];
859 const GLushort val1
= ((const GLushort
*) value
)[1];
860 const GLushort val2
= ((const GLushort
*) value
)[2];
861 const GLushort val3
= ((const GLushort
*) value
)[3];
862 GLushort
*dst
= (GLushort
*) rb
->Data
+ 4 * (y
* rb
->RowStride
+ x
);
863 ASSERT(rb
->DataType
== GL_UNSIGNED_SHORT
|| rb
->DataType
== GL_SHORT
);
864 if (!mask
&& val0
== 0 && val1
== 0 && val2
== 0 && val3
== 0) {
865 /* common case for clearing accum buffer */
866 memset(dst
, 0, count
* 4 * sizeof(GLushort
));
870 for (i
= 0; i
< count
; i
++) {
871 if (!mask
|| mask
[i
]) {
872 dst
[i
* 4 + 0] = val0
;
873 dst
[i
* 4 + 1] = val1
;
874 dst
[i
* 4 + 2] = val2
;
875 dst
[i
* 4 + 3] = val3
;
883 put_values_ushort4(struct gl_context
*ctx
, struct gl_renderbuffer
*rb
, GLuint count
,
884 const GLint x
[], const GLint y
[], const void *values
,
887 const GLushort
*src
= (const GLushort
*) values
;
889 ASSERT(rb
->DataType
== GL_UNSIGNED_SHORT
|| rb
->DataType
== GL_SHORT
);
890 for (i
= 0; i
< count
; i
++) {
891 if (!mask
|| mask
[i
]) {
892 GLushort
*dst
= (GLushort
*) (rb
->Data
+ 4 *
893 (y
[i
] * rb
->RowStride
+ x
[i
]));
894 dst
[0] = src
[i
* 4 + 0];
895 dst
[1] = src
[i
* 4 + 1];
896 dst
[2] = src
[i
* 4 + 2];
897 dst
[3] = src
[i
* 4 + 3];
904 put_mono_values_ushort4(struct gl_context
*ctx
, struct gl_renderbuffer
*rb
,
905 GLuint count
, const GLint x
[], const GLint y
[],
906 const void *value
, const GLubyte
*mask
)
908 const GLushort val0
= ((const GLushort
*) value
)[0];
909 const GLushort val1
= ((const GLushort
*) value
)[1];
910 const GLushort val2
= ((const GLushort
*) value
)[2];
911 const GLushort val3
= ((const GLushort
*) value
)[3];
913 ASSERT(rb
->DataType
== GL_UNSIGNED_SHORT
|| rb
->DataType
== GL_SHORT
);
914 for (i
= 0; i
< count
; i
++) {
915 if (!mask
|| mask
[i
]) {
916 GLushort
*dst
= (GLushort
*) (rb
->Data
+
917 4 * (y
[i
] * rb
->RowStride
+ x
[i
]));
927 * This is the default software fallback for gl_renderbuffer's span
930 * The assumptions are that rb->Data will be a pointer to (0,0), that pixels
931 * are packed in the type of rb->Format, and that subsequent rows appear
932 * rb->RowStride pixels later.
935 _mesa_set_renderbuffer_accessors(struct gl_renderbuffer
*rb
)
937 switch (rb
->Format
) {
938 case MESA_FORMAT_RGB888
:
939 rb
->DataType
= GL_UNSIGNED_BYTE
;
940 rb
->GetPointer
= get_pointer_ubyte3
;
941 rb
->GetRow
= get_row_ubyte3
;
942 rb
->GetValues
= get_values_ubyte3
;
943 rb
->PutRow
= put_row_ubyte3
;
944 rb
->PutRowRGB
= put_row_rgb_ubyte3
;
945 rb
->PutMonoRow
= put_mono_row_ubyte3
;
946 rb
->PutValues
= put_values_ubyte3
;
947 rb
->PutMonoValues
= put_mono_values_ubyte3
;
950 case MESA_FORMAT_RGBA8888
:
951 rb
->DataType
= GL_UNSIGNED_BYTE
;
952 rb
->GetPointer
= get_pointer_ubyte4
;
953 rb
->GetRow
= get_row_ubyte4
;
954 rb
->GetValues
= get_values_ubyte4
;
955 rb
->PutRow
= put_row_ubyte4
;
956 rb
->PutRowRGB
= put_row_rgb_ubyte4
;
957 rb
->PutMonoRow
= put_mono_row_ubyte4
;
958 rb
->PutValues
= put_values_ubyte4
;
959 rb
->PutMonoValues
= put_mono_values_ubyte4
;
962 case MESA_FORMAT_SIGNED_RGBA_16
:
963 rb
->DataType
= GL_SHORT
;
964 rb
->GetPointer
= get_pointer_ushort4
;
965 rb
->GetRow
= get_row_ushort4
;
966 rb
->GetValues
= get_values_ushort4
;
967 rb
->PutRow
= put_row_ushort4
;
968 rb
->PutRowRGB
= put_row_rgb_ushort4
;
969 rb
->PutMonoRow
= put_mono_row_ushort4
;
970 rb
->PutValues
= put_values_ushort4
;
971 rb
->PutMonoValues
= put_mono_values_ushort4
;
976 rb
->DataType
= GL_UNSIGNED_BYTE
;
977 rb
->GetPointer
= get_pointer_alpha8
;
978 rb
->GetRow
= get_row_alpha8
;
979 rb
->GetValues
= get_values_alpha8
;
980 rb
->PutRow
= put_row_alpha8
;
981 rb
->PutRowRGB
= NULL
;
982 rb
->PutMonoRow
= put_mono_row_alpha8
;
983 rb
->PutValues
= put_values_alpha8
;
984 rb
->PutMonoValues
= put_mono_values_alpha8
;
989 rb
->DataType
= GL_UNSIGNED_BYTE
;
990 rb
->GetPointer
= get_pointer_ubyte
;
991 rb
->GetRow
= get_row_ubyte
;
992 rb
->GetValues
= get_values_ubyte
;
993 rb
->PutRow
= put_row_ubyte
;
994 rb
->PutRowRGB
= NULL
;
995 rb
->PutMonoRow
= put_mono_row_ubyte
;
996 rb
->PutValues
= put_values_ubyte
;
997 rb
->PutMonoValues
= put_mono_values_ubyte
;
1000 case MESA_FORMAT_Z16
:
1001 rb
->DataType
= GL_UNSIGNED_SHORT
;
1002 rb
->GetPointer
= get_pointer_ushort
;
1003 rb
->GetRow
= get_row_ushort
;
1004 rb
->GetValues
= get_values_ushort
;
1005 rb
->PutRow
= put_row_ushort
;
1006 rb
->PutRowRGB
= NULL
;
1007 rb
->PutMonoRow
= put_mono_row_ushort
;
1008 rb
->PutValues
= put_values_ushort
;
1009 rb
->PutMonoValues
= put_mono_values_ushort
;
1012 case MESA_FORMAT_Z32
:
1013 case MESA_FORMAT_X8_Z24
:
1014 case MESA_FORMAT_Z24_X8
:
1015 rb
->DataType
= GL_UNSIGNED_INT
;
1016 rb
->GetPointer
= get_pointer_uint
;
1017 rb
->GetRow
= get_row_uint
;
1018 rb
->GetValues
= get_values_uint
;
1019 rb
->PutRow
= put_row_uint
;
1020 rb
->PutRowRGB
= NULL
;
1021 rb
->PutMonoRow
= put_mono_row_uint
;
1022 rb
->PutValues
= put_values_uint
;
1023 rb
->PutMonoValues
= put_mono_values_uint
;
1026 case MESA_FORMAT_Z24_S8
:
1027 case MESA_FORMAT_S8_Z24
:
1028 rb
->DataType
= GL_UNSIGNED_INT_24_8_EXT
;
1029 rb
->GetPointer
= get_pointer_uint
;
1030 rb
->GetRow
= get_row_uint
;
1031 rb
->GetValues
= get_values_uint
;
1032 rb
->PutRow
= put_row_uint
;
1033 rb
->PutRowRGB
= NULL
;
1034 rb
->PutMonoRow
= put_mono_row_uint
;
1035 rb
->PutValues
= put_values_uint
;
1036 rb
->PutMonoValues
= put_mono_values_uint
;
1045 * This is a software fallback for the gl_renderbuffer->AllocStorage
1047 * Device drivers will typically override this function for the buffers
1048 * which it manages (typically color buffers, Z and stencil).
1049 * Other buffers (like software accumulation and aux buffers) which the driver
1050 * doesn't manage can be handled with this function.
1052 * This one multi-purpose function can allocate stencil, depth, accum, color
1053 * or color-index buffers!
1055 * This function also plugs in the appropriate GetPointer, Get/PutRow and
1056 * Get/PutValues functions.
1059 _mesa_soft_renderbuffer_storage(struct gl_context
*ctx
, struct gl_renderbuffer
*rb
,
1060 GLenum internalFormat
,
1061 GLuint width
, GLuint height
)
1063 switch (internalFormat
) {
1072 rb
->Format
= MESA_FORMAT_RGB888
;
1083 rb
->Format
= MESA_FORMAT_RGBA8888
;
1086 case GL_RGBA16_SNORM
:
1087 /* for accum buffer */
1088 rb
->Format
= MESA_FORMAT_SIGNED_RGBA_16
;
1092 rb
->Format
= MESA_FORMAT_A8
;
1095 case GL_STENCIL_INDEX
:
1096 case GL_STENCIL_INDEX1_EXT
:
1097 case GL_STENCIL_INDEX4_EXT
:
1098 case GL_STENCIL_INDEX8_EXT
:
1099 case GL_STENCIL_INDEX16_EXT
:
1100 rb
->Format
= MESA_FORMAT_S8
;
1102 case GL_DEPTH_COMPONENT
:
1103 case GL_DEPTH_COMPONENT16
:
1104 rb
->Format
= MESA_FORMAT_Z16
;
1106 case GL_DEPTH_COMPONENT24
:
1107 rb
->Format
= MESA_FORMAT_X8_Z24
;
1109 case GL_DEPTH_COMPONENT32
:
1110 rb
->Format
= MESA_FORMAT_Z32
;
1112 case GL_DEPTH_STENCIL_EXT
:
1113 case GL_DEPTH24_STENCIL8_EXT
:
1114 rb
->Format
= MESA_FORMAT_Z24_S8
;
1117 /* unsupported format */
1121 _mesa_set_renderbuffer_accessors(rb
);
1123 ASSERT(rb
->DataType
);
1124 ASSERT(rb
->GetPointer
);
1126 ASSERT(rb
->GetValues
);
1128 ASSERT(rb
->PutMonoRow
);
1129 ASSERT(rb
->PutValues
);
1130 ASSERT(rb
->PutMonoValues
);
1132 /* free old buffer storage */
1138 rb
->RowStride
= width
;
1140 if (width
> 0 && height
> 0) {
1141 /* allocate new buffer storage */
1142 rb
->Data
= malloc(width
* height
* _mesa_get_format_bytes(rb
->Format
));
1144 if (rb
->Data
== NULL
) {
1148 _mesa_error(ctx
, GL_OUT_OF_MEMORY
,
1149 "software renderbuffer allocation (%d x %d x %d)",
1150 width
, height
, _mesa_get_format_bytes(rb
->Format
));
1156 rb
->Height
= height
;
1157 rb
->_BaseFormat
= _mesa_base_fbo_format(ctx
, internalFormat
);
1159 if (rb
->Name
== 0 &&
1160 internalFormat
== GL_RGBA16_SNORM
&&
1161 rb
->_BaseFormat
== 0) {
1162 /* NOTE: This is a special case just for accumulation buffers.
1163 * This is a very limited use case- there's no snorm texturing or
1164 * rendering going on.
1166 rb
->_BaseFormat
= GL_RGBA
;
1169 /* the internalFormat should have been error checked long ago */
1170 ASSERT(rb
->_BaseFormat
);
1178 /**********************************************************************/
1179 /**********************************************************************/
1180 /**********************************************************************/
1184 * Here we utilize the gl_renderbuffer->Wrapper field to put an alpha
1185 * buffer wrapper around an existing RGB renderbuffer (hw or sw).
1187 * When PutRow is called (for example), we store the alpha values in
1188 * this buffer, then pass on the PutRow call to the wrapped RGB
1194 alloc_storage_alpha8(struct gl_context
*ctx
, struct gl_renderbuffer
*arb
,
1195 GLenum internalFormat
, GLuint width
, GLuint height
)
1197 ASSERT(arb
!= arb
->Wrapped
);
1198 ASSERT(arb
->Format
== MESA_FORMAT_A8
);
1200 /* first, pass the call to the wrapped RGB buffer */
1201 if (!arb
->Wrapped
->AllocStorage(ctx
, arb
->Wrapped
, internalFormat
,
1206 /* next, resize my alpha buffer */
1211 arb
->Data
= malloc(width
* height
* sizeof(GLubyte
));
1212 if (arb
->Data
== NULL
) {
1215 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "software alpha buffer allocation");
1220 arb
->Height
= height
;
1221 arb
->RowStride
= width
;
1228 * Delete an alpha_renderbuffer object, as well as the wrapped RGB buffer.
1231 delete_renderbuffer_alpha8(struct gl_renderbuffer
*arb
)
1236 ASSERT(arb
->Wrapped
);
1237 ASSERT(arb
!= arb
->Wrapped
);
1238 arb
->Wrapped
->Delete(arb
->Wrapped
);
1239 arb
->Wrapped
= NULL
;
1245 get_pointer_alpha8(struct gl_context
*ctx
, struct gl_renderbuffer
*arb
,
1248 return NULL
; /* don't allow direct access! */
1253 get_row_alpha8(struct gl_context
*ctx
, struct gl_renderbuffer
*arb
, GLuint count
,
1254 GLint x
, GLint y
, void *values
)
1256 /* NOTE: 'values' is RGBA format! */
1257 const GLubyte
*src
= (const GLubyte
*) arb
->Data
+ y
* arb
->RowStride
+ x
;
1258 GLubyte
*dst
= (GLubyte
*) values
;
1260 ASSERT(arb
!= arb
->Wrapped
);
1261 ASSERT(arb
->DataType
== GL_UNSIGNED_BYTE
);
1262 /* first, pass the call to the wrapped RGB buffer */
1263 arb
->Wrapped
->GetRow(ctx
, arb
->Wrapped
, count
, x
, y
, values
);
1264 /* second, fill in alpha values from this buffer! */
1265 for (i
= 0; i
< count
; i
++) {
1266 dst
[i
* 4 + 3] = src
[i
];
1272 get_values_alpha8(struct gl_context
*ctx
, struct gl_renderbuffer
*arb
, GLuint count
,
1273 const GLint x
[], const GLint y
[], void *values
)
1275 GLubyte
*dst
= (GLubyte
*) values
;
1277 ASSERT(arb
!= arb
->Wrapped
);
1278 ASSERT(arb
->DataType
== GL_UNSIGNED_BYTE
);
1279 /* first, pass the call to the wrapped RGB buffer */
1280 arb
->Wrapped
->GetValues(ctx
, arb
->Wrapped
, count
, x
, y
, values
);
1281 /* second, fill in alpha values from this buffer! */
1282 for (i
= 0; i
< count
; i
++) {
1283 const GLubyte
*src
= (GLubyte
*) arb
->Data
+ y
[i
] * arb
->RowStride
+ x
[i
];
1284 dst
[i
* 4 + 3] = *src
;
1290 put_row_alpha8(struct gl_context
*ctx
, struct gl_renderbuffer
*arb
, GLuint count
,
1291 GLint x
, GLint y
, const void *values
, const GLubyte
*mask
)
1293 const GLubyte
*src
= (const GLubyte
*) values
;
1294 GLubyte
*dst
= (GLubyte
*) arb
->Data
+ y
* arb
->RowStride
+ x
;
1296 ASSERT(arb
!= arb
->Wrapped
);
1297 ASSERT(arb
->DataType
== GL_UNSIGNED_BYTE
);
1298 /* first, pass the call to the wrapped RGB buffer */
1299 arb
->Wrapped
->PutRow(ctx
, arb
->Wrapped
, count
, x
, y
, values
, mask
);
1300 /* second, store alpha in our buffer */
1301 for (i
= 0; i
< count
; i
++) {
1302 if (!mask
|| mask
[i
]) {
1303 dst
[i
] = src
[i
* 4 + 3];
1310 put_row_rgb_alpha8(struct gl_context
*ctx
, struct gl_renderbuffer
*arb
, GLuint count
,
1311 GLint x
, GLint y
, const void *values
, const GLubyte
*mask
)
1313 const GLubyte
*src
= (const GLubyte
*) values
;
1314 GLubyte
*dst
= (GLubyte
*) arb
->Data
+ y
* arb
->RowStride
+ x
;
1316 ASSERT(arb
!= arb
->Wrapped
);
1317 ASSERT(arb
->DataType
== GL_UNSIGNED_BYTE
);
1318 /* first, pass the call to the wrapped RGB buffer */
1319 arb
->Wrapped
->PutRowRGB(ctx
, arb
->Wrapped
, count
, x
, y
, values
, mask
);
1320 /* second, store alpha in our buffer */
1321 for (i
= 0; i
< count
; i
++) {
1322 if (!mask
|| mask
[i
]) {
1323 dst
[i
] = src
[i
* 4 + 3];
1330 put_mono_row_alpha8(struct gl_context
*ctx
, struct gl_renderbuffer
*arb
, GLuint count
,
1331 GLint x
, GLint y
, const void *value
, const GLubyte
*mask
)
1333 const GLubyte val
= ((const GLubyte
*) value
)[3];
1334 GLubyte
*dst
= (GLubyte
*) arb
->Data
+ y
* arb
->RowStride
+ x
;
1335 ASSERT(arb
!= arb
->Wrapped
);
1336 ASSERT(arb
->DataType
== GL_UNSIGNED_BYTE
);
1337 /* first, pass the call to the wrapped RGB buffer */
1338 arb
->Wrapped
->PutMonoRow(ctx
, arb
->Wrapped
, count
, x
, y
, value
, mask
);
1339 /* second, store alpha in our buffer */
1342 for (i
= 0; i
< count
; i
++) {
1349 memset(dst
, val
, count
);
1355 put_values_alpha8(struct gl_context
*ctx
, struct gl_renderbuffer
*arb
, GLuint count
,
1356 const GLint x
[], const GLint y
[],
1357 const void *values
, const GLubyte
*mask
)
1359 const GLubyte
*src
= (const GLubyte
*) values
;
1361 ASSERT(arb
!= arb
->Wrapped
);
1362 ASSERT(arb
->DataType
== GL_UNSIGNED_BYTE
);
1363 /* first, pass the call to the wrapped RGB buffer */
1364 arb
->Wrapped
->PutValues(ctx
, arb
->Wrapped
, count
, x
, y
, values
, mask
);
1365 /* second, store alpha in our buffer */
1366 for (i
= 0; i
< count
; i
++) {
1367 if (!mask
|| mask
[i
]) {
1368 GLubyte
*dst
= (GLubyte
*) arb
->Data
+ y
[i
] * arb
->RowStride
+ x
[i
];
1369 *dst
= src
[i
* 4 + 3];
1376 put_mono_values_alpha8(struct gl_context
*ctx
, struct gl_renderbuffer
*arb
,
1377 GLuint count
, const GLint x
[], const GLint y
[],
1378 const void *value
, const GLubyte
*mask
)
1380 const GLubyte val
= ((const GLubyte
*) value
)[3];
1382 ASSERT(arb
!= arb
->Wrapped
);
1383 ASSERT(arb
->DataType
== GL_UNSIGNED_BYTE
);
1384 /* first, pass the call to the wrapped RGB buffer */
1385 arb
->Wrapped
->PutValues(ctx
, arb
->Wrapped
, count
, x
, y
, value
, mask
);
1386 /* second, store alpha in our buffer */
1387 for (i
= 0; i
< count
; i
++) {
1388 if (!mask
|| mask
[i
]) {
1389 GLubyte
*dst
= (GLubyte
*) arb
->Data
+ y
[i
] * arb
->RowStride
+ x
[i
];
1397 copy_buffer_alpha8(struct gl_renderbuffer
* dst
, struct gl_renderbuffer
* src
)
1399 ASSERT(dst
->Format
== MESA_FORMAT_A8
);
1400 ASSERT(src
->Format
== MESA_FORMAT_A8
);
1401 ASSERT(dst
->Width
== src
->Width
);
1402 ASSERT(dst
->Height
== src
->Height
);
1403 ASSERT(dst
->RowStride
== src
->RowStride
);
1405 memcpy(dst
->Data
, src
->Data
, dst
->RowStride
* dst
->Height
* sizeof(GLubyte
));
1409 /**********************************************************************/
1410 /**********************************************************************/
1411 /**********************************************************************/
1415 * Default GetPointer routine. Always return NULL to indicate that
1416 * direct buffer access is not supported.
1419 nop_get_pointer(struct gl_context
*ctx
, struct gl_renderbuffer
*rb
, GLint x
, GLint y
)
1426 * Initialize the fields of a gl_renderbuffer to default values.
1429 _mesa_init_renderbuffer(struct gl_renderbuffer
*rb
, GLuint name
)
1431 _glthread_INIT_MUTEX(rb
->Mutex
);
1436 rb
->Delete
= _mesa_delete_renderbuffer
;
1438 /* The rest of these should be set later by the caller of this function or
1439 * the AllocStorage method:
1441 rb
->AllocStorage
= NULL
;
1445 rb
->InternalFormat
= GL_NONE
;
1446 rb
->Format
= MESA_FORMAT_NONE
;
1448 rb
->DataType
= GL_NONE
;
1451 /* Point back to ourself so that we don't have to check for Wrapped==NULL
1452 * all over the drivers.
1456 rb
->GetPointer
= nop_get_pointer
;
1458 rb
->GetValues
= NULL
;
1460 rb
->PutRowRGB
= NULL
;
1461 rb
->PutMonoRow
= NULL
;
1462 rb
->PutValues
= NULL
;
1463 rb
->PutMonoValues
= NULL
;
1468 * Allocate a new gl_renderbuffer object. This can be used for user-created
1469 * renderbuffers or window-system renderbuffers.
1471 struct gl_renderbuffer
*
1472 _mesa_new_renderbuffer(struct gl_context
*ctx
, GLuint name
)
1474 struct gl_renderbuffer
*rb
= CALLOC_STRUCT(gl_renderbuffer
);
1476 _mesa_init_renderbuffer(rb
, name
);
1483 * Delete a gl_framebuffer.
1484 * This is the default function for renderbuffer->Delete().
1487 _mesa_delete_renderbuffer(struct gl_renderbuffer
*rb
)
1497 * Allocate a software-based renderbuffer. This is called via the
1498 * ctx->Driver.NewRenderbuffer() function when the user creates a new
1500 * This would not be used for hardware-based renderbuffers.
1502 struct gl_renderbuffer
*
1503 _mesa_new_soft_renderbuffer(struct gl_context
*ctx
, GLuint name
)
1505 struct gl_renderbuffer
*rb
= _mesa_new_renderbuffer(ctx
, name
);
1507 rb
->AllocStorage
= _mesa_soft_renderbuffer_storage
;
1508 /* Normally, one would setup the PutRow, GetRow, etc functions here.
1509 * But we're doing that in the _mesa_soft_renderbuffer_storage() function
1518 * Add software-based color renderbuffers to the given framebuffer.
1519 * This is a helper routine for device drivers when creating a
1520 * window system framebuffer (not a user-created render/framebuffer).
1521 * Once this function is called, you can basically forget about this
1522 * renderbuffer; core Mesa will handle all the buffer management and
1526 _mesa_add_color_renderbuffers(struct gl_context
*ctx
, struct gl_framebuffer
*fb
,
1527 GLuint rgbBits
, GLuint alphaBits
,
1528 GLboolean frontLeft
, GLboolean backLeft
,
1529 GLboolean frontRight
, GLboolean backRight
)
1533 if (rgbBits
> 16 || alphaBits
> 16) {
1535 "Unsupported bit depth in _mesa_add_color_renderbuffers");
1539 assert(MAX_COLOR_ATTACHMENTS
>= 4);
1541 for (b
= BUFFER_FRONT_LEFT
; b
<= BUFFER_BACK_RIGHT
; b
++) {
1542 struct gl_renderbuffer
*rb
;
1544 if (b
== BUFFER_FRONT_LEFT
&& !frontLeft
)
1546 else if (b
== BUFFER_BACK_LEFT
&& !backLeft
)
1548 else if (b
== BUFFER_FRONT_RIGHT
&& !frontRight
)
1550 else if (b
== BUFFER_BACK_RIGHT
&& !backRight
)
1553 assert(fb
->Attachment
[b
].Renderbuffer
== NULL
);
1555 rb
= _mesa_new_renderbuffer(ctx
, 0);
1557 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "Allocating color buffer");
1563 rb
->Format
= MESA_FORMAT_RGBA8888
;
1565 rb
->Format
= MESA_FORMAT_RGB888
;
1568 assert(rgbBits
<= 16);
1569 rb
->Format
= MESA_FORMAT_NONE
; /*XXX RGBA16;*/
1571 rb
->InternalFormat
= GL_RGBA
;
1573 rb
->AllocStorage
= _mesa_soft_renderbuffer_storage
;
1574 _mesa_add_renderbuffer(fb
, b
, rb
);
1582 * Add software-based alpha renderbuffers to the given framebuffer.
1583 * This is a helper routine for device drivers when creating a
1584 * window system framebuffer (not a user-created render/framebuffer).
1585 * Once this function is called, you can basically forget about this
1586 * renderbuffer; core Mesa will handle all the buffer management and
1590 _mesa_add_alpha_renderbuffers(struct gl_context
*ctx
, struct gl_framebuffer
*fb
,
1592 GLboolean frontLeft
, GLboolean backLeft
,
1593 GLboolean frontRight
, GLboolean backRight
)
1597 /* for window system framebuffers only! */
1598 assert(fb
->Name
== 0);
1600 if (alphaBits
> 8) {
1602 "Unsupported bit depth in _mesa_add_alpha_renderbuffers");
1606 assert(MAX_COLOR_ATTACHMENTS
>= 4);
1608 /* Wrap each of the RGB color buffers with an alpha renderbuffer.
1610 for (b
= BUFFER_FRONT_LEFT
; b
<= BUFFER_BACK_RIGHT
; b
++) {
1611 struct gl_renderbuffer
*arb
;
1613 if (b
== BUFFER_FRONT_LEFT
&& !frontLeft
)
1615 else if (b
== BUFFER_BACK_LEFT
&& !backLeft
)
1617 else if (b
== BUFFER_FRONT_RIGHT
&& !frontRight
)
1619 else if (b
== BUFFER_BACK_RIGHT
&& !backRight
)
1622 /* the RGB buffer to wrap must already exist!! */
1623 assert(fb
->Attachment
[b
].Renderbuffer
);
1625 /* only GLubyte supported for now */
1626 assert(fb
->Attachment
[b
].Renderbuffer
->DataType
== GL_UNSIGNED_BYTE
);
1628 /* allocate alpha renderbuffer */
1629 arb
= _mesa_new_renderbuffer(ctx
, 0);
1631 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "Allocating alpha buffer");
1635 /* wrap the alpha renderbuffer around the RGB renderbuffer */
1636 arb
->Wrapped
= fb
->Attachment
[b
].Renderbuffer
;
1638 /* Set up my alphabuffer fields and plug in my functions.
1639 * The functions will put/get the alpha values from/to RGBA arrays
1640 * and then call the wrapped buffer's functions to handle the RGB
1643 arb
->InternalFormat
= arb
->Wrapped
->InternalFormat
;
1644 arb
->Format
= MESA_FORMAT_A8
;
1645 arb
->DataType
= arb
->Wrapped
->DataType
;
1646 arb
->AllocStorage
= alloc_storage_alpha8
;
1647 arb
->Delete
= delete_renderbuffer_alpha8
;
1648 arb
->GetPointer
= get_pointer_alpha8
;
1649 arb
->GetRow
= get_row_alpha8
;
1650 arb
->GetValues
= get_values_alpha8
;
1651 arb
->PutRow
= put_row_alpha8
;
1652 arb
->PutRowRGB
= put_row_rgb_alpha8
;
1653 arb
->PutMonoRow
= put_mono_row_alpha8
;
1654 arb
->PutValues
= put_values_alpha8
;
1655 arb
->PutMonoValues
= put_mono_values_alpha8
;
1657 /* clear the pointer to avoid assertion/sanity check failure later */
1658 fb
->Attachment
[b
].Renderbuffer
= NULL
;
1660 /* plug the alpha renderbuffer into the colorbuffer attachment */
1661 _mesa_add_renderbuffer(fb
, b
, arb
);
1669 * For framebuffers that use a software alpha channel wrapper
1670 * created by _mesa_add_alpha_renderbuffer or _mesa_add_soft_renderbuffers,
1671 * copy the back buffer alpha channel into the front buffer alpha channel.
1674 _mesa_copy_soft_alpha_renderbuffers(struct gl_context
*ctx
, struct gl_framebuffer
*fb
)
1676 if (fb
->Attachment
[BUFFER_FRONT_LEFT
].Renderbuffer
&&
1677 fb
->Attachment
[BUFFER_BACK_LEFT
].Renderbuffer
)
1678 copy_buffer_alpha8(fb
->Attachment
[BUFFER_FRONT_LEFT
].Renderbuffer
,
1679 fb
->Attachment
[BUFFER_BACK_LEFT
].Renderbuffer
);
1682 if (fb
->Attachment
[BUFFER_FRONT_RIGHT
].Renderbuffer
&&
1683 fb
->Attachment
[BUFFER_BACK_RIGHT
].Renderbuffer
)
1684 copy_buffer_alpha8(fb
->Attachment
[BUFFER_FRONT_RIGHT
].Renderbuffer
,
1685 fb
->Attachment
[BUFFER_BACK_RIGHT
].Renderbuffer
);
1690 * Add a software-based depth renderbuffer to the given framebuffer.
1691 * This is a helper routine for device drivers when creating a
1692 * window system framebuffer (not a user-created render/framebuffer).
1693 * Once this function is called, you can basically forget about this
1694 * renderbuffer; core Mesa will handle all the buffer management and
1698 _mesa_add_depth_renderbuffer(struct gl_context
*ctx
, struct gl_framebuffer
*fb
,
1701 struct gl_renderbuffer
*rb
;
1703 if (depthBits
> 32) {
1705 "Unsupported depthBits in _mesa_add_depth_renderbuffer");
1709 assert(fb
->Attachment
[BUFFER_DEPTH
].Renderbuffer
== NULL
);
1711 rb
= _mesa_new_renderbuffer(ctx
, 0);
1713 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "Allocating depth buffer");
1717 if (depthBits
<= 16) {
1718 rb
->Format
= MESA_FORMAT_Z16
;
1719 rb
->InternalFormat
= GL_DEPTH_COMPONENT16
;
1721 else if (depthBits
<= 24) {
1722 rb
->Format
= MESA_FORMAT_X8_Z24
;
1723 rb
->InternalFormat
= GL_DEPTH_COMPONENT24
;
1726 rb
->Format
= MESA_FORMAT_Z32
;
1727 rb
->InternalFormat
= GL_DEPTH_COMPONENT32
;
1730 rb
->AllocStorage
= _mesa_soft_renderbuffer_storage
;
1731 _mesa_add_renderbuffer(fb
, BUFFER_DEPTH
, rb
);
1738 * Add a software-based stencil renderbuffer to the given framebuffer.
1739 * This is a helper routine for device drivers when creating a
1740 * window system framebuffer (not a user-created render/framebuffer).
1741 * Once this function is called, you can basically forget about this
1742 * renderbuffer; core Mesa will handle all the buffer management and
1746 _mesa_add_stencil_renderbuffer(struct gl_context
*ctx
, struct gl_framebuffer
*fb
,
1749 struct gl_renderbuffer
*rb
;
1751 if (stencilBits
> 16) {
1753 "Unsupported stencilBits in _mesa_add_stencil_renderbuffer");
1757 assert(fb
->Attachment
[BUFFER_STENCIL
].Renderbuffer
== NULL
);
1759 rb
= _mesa_new_renderbuffer(ctx
, 0);
1761 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "Allocating stencil buffer");
1765 assert(stencilBits
<= 8);
1766 rb
->Format
= MESA_FORMAT_S8
;
1767 rb
->InternalFormat
= GL_STENCIL_INDEX8
;
1769 rb
->AllocStorage
= _mesa_soft_renderbuffer_storage
;
1770 _mesa_add_renderbuffer(fb
, BUFFER_STENCIL
, rb
);
1777 * Add a software-based accumulation renderbuffer to the given framebuffer.
1778 * This is a helper routine for device drivers when creating a
1779 * window system framebuffer (not a user-created render/framebuffer).
1780 * Once this function is called, you can basically forget about this
1781 * renderbuffer; core Mesa will handle all the buffer management and
1785 _mesa_add_accum_renderbuffer(struct gl_context
*ctx
, struct gl_framebuffer
*fb
,
1786 GLuint redBits
, GLuint greenBits
,
1787 GLuint blueBits
, GLuint alphaBits
)
1789 struct gl_renderbuffer
*rb
;
1791 if (redBits
> 16 || greenBits
> 16 || blueBits
> 16 || alphaBits
> 16) {
1793 "Unsupported accumBits in _mesa_add_accum_renderbuffer");
1797 assert(fb
->Attachment
[BUFFER_ACCUM
].Renderbuffer
== NULL
);
1799 rb
= _mesa_new_renderbuffer(ctx
, 0);
1801 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "Allocating accum buffer");
1805 rb
->Format
= MESA_FORMAT_SIGNED_RGBA_16
;
1806 rb
->InternalFormat
= GL_RGBA16_SNORM
;
1807 rb
->AllocStorage
= _mesa_soft_renderbuffer_storage
;
1808 _mesa_add_renderbuffer(fb
, BUFFER_ACCUM
, rb
);
1816 * Add a software-based aux renderbuffer to the given framebuffer.
1817 * This is a helper routine for device drivers when creating a
1818 * window system framebuffer (not a user-created render/framebuffer).
1819 * Once this function is called, you can basically forget about this
1820 * renderbuffer; core Mesa will handle all the buffer management and
1823 * NOTE: color-index aux buffers not supported.
1826 _mesa_add_aux_renderbuffers(struct gl_context
*ctx
, struct gl_framebuffer
*fb
,
1827 GLuint colorBits
, GLuint numBuffers
)
1831 if (colorBits
> 16) {
1833 "Unsupported accumBits in _mesa_add_aux_renderbuffers");
1837 assert(numBuffers
<= MAX_AUX_BUFFERS
);
1839 for (i
= 0; i
< numBuffers
; i
++) {
1840 struct gl_renderbuffer
*rb
= _mesa_new_renderbuffer(ctx
, 0);
1842 assert(fb
->Attachment
[BUFFER_AUX0
+ i
].Renderbuffer
== NULL
);
1845 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "Allocating aux buffer");
1849 assert (colorBits
<= 8);
1850 rb
->Format
= MESA_FORMAT_RGBA8888
;
1851 rb
->InternalFormat
= GL_RGBA
;
1853 rb
->AllocStorage
= _mesa_soft_renderbuffer_storage
;
1854 _mesa_add_renderbuffer(fb
, BUFFER_AUX0
+ i
, rb
);
1861 * Create/attach software-based renderbuffers to the given framebuffer.
1862 * This is a helper routine for device drivers. Drivers can just as well
1863 * call the individual _mesa_add_*_renderbuffer() routines directly.
1866 _mesa_add_soft_renderbuffers(struct gl_framebuffer
*fb
,
1874 GLboolean frontLeft
= GL_TRUE
;
1875 GLboolean backLeft
= fb
->Visual
.doubleBufferMode
;
1876 GLboolean frontRight
= fb
->Visual
.stereoMode
;
1877 GLboolean backRight
= fb
->Visual
.stereoMode
&& fb
->Visual
.doubleBufferMode
;
1880 assert(fb
->Visual
.redBits
== fb
->Visual
.greenBits
);
1881 assert(fb
->Visual
.redBits
== fb
->Visual
.blueBits
);
1882 _mesa_add_color_renderbuffers(NULL
, fb
,
1884 fb
->Visual
.alphaBits
,
1885 frontLeft
, backLeft
,
1886 frontRight
, backRight
);
1890 assert(fb
->Visual
.depthBits
> 0);
1891 _mesa_add_depth_renderbuffer(NULL
, fb
, fb
->Visual
.depthBits
);
1895 assert(fb
->Visual
.stencilBits
> 0);
1896 _mesa_add_stencil_renderbuffer(NULL
, fb
, fb
->Visual
.stencilBits
);
1900 assert(fb
->Visual
.accumRedBits
> 0);
1901 assert(fb
->Visual
.accumGreenBits
> 0);
1902 assert(fb
->Visual
.accumBlueBits
> 0);
1903 _mesa_add_accum_renderbuffer(NULL
, fb
,
1904 fb
->Visual
.accumRedBits
,
1905 fb
->Visual
.accumGreenBits
,
1906 fb
->Visual
.accumBlueBits
,
1907 fb
->Visual
.accumAlphaBits
);
1911 assert(fb
->Visual
.numAuxBuffers
> 0);
1912 _mesa_add_aux_renderbuffers(NULL
, fb
, fb
->Visual
.redBits
,
1913 fb
->Visual
.numAuxBuffers
);
1917 assert(fb
->Visual
.alphaBits
> 0);
1918 _mesa_add_alpha_renderbuffers(NULL
, fb
, fb
->Visual
.alphaBits
,
1919 frontLeft
, backLeft
,
1920 frontRight
, backRight
);
1932 * Attach a renderbuffer to a framebuffer.
1933 * \param bufferName one of the BUFFER_x tokens
1936 _mesa_add_renderbuffer(struct gl_framebuffer
*fb
,
1937 gl_buffer_index bufferName
, struct gl_renderbuffer
*rb
)
1941 assert(bufferName
< BUFFER_COUNT
);
1943 /* There should be no previous renderbuffer on this attachment point,
1944 * with the exception of depth/stencil since the same renderbuffer may
1947 assert(bufferName
== BUFFER_DEPTH
||
1948 bufferName
== BUFFER_STENCIL
||
1949 fb
->Attachment
[bufferName
].Renderbuffer
== NULL
);
1951 /* winsys vs. user-created buffer cross check */
1959 fb
->Attachment
[bufferName
].Type
= GL_RENDERBUFFER_EXT
;
1960 fb
->Attachment
[bufferName
].Complete
= GL_TRUE
;
1961 _mesa_reference_renderbuffer(&fb
->Attachment
[bufferName
].Renderbuffer
, rb
);
1966 * Remove the named renderbuffer from the given framebuffer.
1967 * \param bufferName one of the BUFFER_x tokens
1970 _mesa_remove_renderbuffer(struct gl_framebuffer
*fb
,
1971 gl_buffer_index bufferName
)
1973 struct gl_renderbuffer
*rb
;
1975 assert(bufferName
< BUFFER_COUNT
);
1977 rb
= fb
->Attachment
[bufferName
].Renderbuffer
;
1981 _mesa_reference_renderbuffer(&rb
, NULL
);
1983 fb
->Attachment
[bufferName
].Renderbuffer
= NULL
;
1988 * Set *ptr to point to rb. If *ptr points to another renderbuffer,
1989 * dereference that buffer first. The new renderbuffer's refcount will
1990 * be incremented. The old renderbuffer's refcount will be decremented.
1993 _mesa_reference_renderbuffer(struct gl_renderbuffer
**ptr
,
1994 struct gl_renderbuffer
*rb
)
2003 /* Unreference the old renderbuffer */
2004 GLboolean deleteFlag
= GL_FALSE
;
2005 struct gl_renderbuffer
*oldRb
= *ptr
;
2007 _glthread_LOCK_MUTEX(oldRb
->Mutex
);
2008 ASSERT(oldRb
->RefCount
> 0);
2010 /*printf("RB DECR %p (%d) to %d\n", (void*) oldRb, oldRb->Name, oldRb->RefCount);*/
2011 deleteFlag
= (oldRb
->RefCount
== 0);
2012 _glthread_UNLOCK_MUTEX(oldRb
->Mutex
);
2015 oldRb
->Delete(oldRb
);
2023 /* reference new renderbuffer */
2024 _glthread_LOCK_MUTEX(rb
->Mutex
);
2026 /*printf("RB INCR %p (%d) to %d\n", (void*) rb, rb->Name, rb->RefCount);*/
2027 _glthread_UNLOCK_MUTEX(rb
->Mutex
);
2034 * Create a new combined depth/stencil renderbuffer for implementing
2035 * the GL_EXT_packed_depth_stencil extension.
2036 * \return new depth/stencil renderbuffer
2038 struct gl_renderbuffer
*
2039 _mesa_new_depthstencil_renderbuffer(struct gl_context
*ctx
, GLuint name
)
2041 struct gl_renderbuffer
*dsrb
;
2043 dsrb
= _mesa_new_renderbuffer(ctx
, name
);
2047 /* init fields not covered by _mesa_new_renderbuffer() */
2048 dsrb
->InternalFormat
= GL_DEPTH24_STENCIL8_EXT
;
2049 dsrb
->Format
= MESA_FORMAT_Z24_S8
;
2050 dsrb
->AllocStorage
= _mesa_soft_renderbuffer_storage
;