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 software-based renderbuffers.
28 * Also, routines for reading/writing software-based renderbuffer data as
29 * ubytes, ushorts, uints, etc.
33 #include "main/glheader.h"
34 #include "main/imports.h"
35 #include "main/context.h"
36 #include "main/fbobject.h"
37 #include "main/formats.h"
38 #include "main/mtypes.h"
39 #include "main/renderbuffer.h"
40 #include "swrast/s_renderbuffer.h"
45 * This is the default software fallback for gl_renderbuffer's span
48 * The assumptions are that rb->Data will be a pointer to (0,0), that pixels
49 * are packed in the type of rb->Format, and that subsequent rows appear
50 * rb->RowStride pixels later.
53 _swrast_set_renderbuffer_accessors(struct gl_renderbuffer
*rb
)
56 case MESA_FORMAT_RGB888
:
57 rb
->DataType
= GL_UNSIGNED_BYTE
;
60 case MESA_FORMAT_RGBA8888
:
61 case MESA_FORMAT_RGBA8888_REV
:
62 rb
->DataType
= GL_UNSIGNED_BYTE
;
66 rb
->DataType
= GL_UNSIGNED_BYTE
;
70 case MESA_FORMAT_GR88
:
71 rb
->DataType
= GL_UNSIGNED_BYTE
;
75 rb
->DataType
= GL_UNSIGNED_SHORT
;
79 case MESA_FORMAT_RG1616
:
80 rb
->DataType
= GL_UNSIGNED_SHORT
;
83 case MESA_FORMAT_SIGNED_RGBA_16
:
84 rb
->DataType
= GL_SHORT
;
88 rb
->DataType
= GL_UNSIGNED_BYTE
;
92 rb
->DataType
= GL_UNSIGNED_SHORT
;
96 case MESA_FORMAT_X8_Z24
:
97 case MESA_FORMAT_Z24_X8
:
98 rb
->DataType
= GL_UNSIGNED_INT
;
101 case MESA_FORMAT_Z24_S8
:
102 case MESA_FORMAT_S8_Z24
:
103 rb
->DataType
= GL_UNSIGNED_INT_24_8_EXT
;
106 case MESA_FORMAT_RGBA_FLOAT32
:
107 rb
->DataType
= GL_FLOAT
;
110 case MESA_FORMAT_INTENSITY_FLOAT32
:
111 rb
->DataType
= GL_FLOAT
;
114 case MESA_FORMAT_LUMINANCE_FLOAT32
:
115 rb
->DataType
= GL_FLOAT
;
118 case MESA_FORMAT_ALPHA_FLOAT32
:
119 rb
->DataType
= GL_FLOAT
;
122 case MESA_FORMAT_RG_FLOAT32
:
123 rb
->DataType
= GL_FLOAT
;
126 case MESA_FORMAT_R_FLOAT32
:
127 rb
->DataType
= GL_FLOAT
;
136 * This is a software fallback for the gl_renderbuffer->AllocStorage
138 * Device drivers will typically override this function for the buffers
139 * which it manages (typically color buffers, Z and stencil).
140 * Other buffers (like software accumulation and aux buffers) which the driver
141 * doesn't manage can be handled with this function.
143 * This one multi-purpose function can allocate stencil, depth, accum, color
144 * or color-index buffers!
147 soft_renderbuffer_storage(struct gl_context
*ctx
, struct gl_renderbuffer
*rb
,
148 GLenum internalFormat
,
149 GLuint width
, GLuint height
)
151 switch (internalFormat
) {
160 rb
->Format
= MESA_FORMAT_RGB888
;
171 if (_mesa_little_endian())
172 rb
->Format
= MESA_FORMAT_RGBA8888_REV
;
174 rb
->Format
= MESA_FORMAT_RGBA8888
;
177 case GL_RGBA16_SNORM
:
178 /* for accum buffer */
179 rb
->Format
= MESA_FORMAT_SIGNED_RGBA_16
;
181 case GL_STENCIL_INDEX
:
182 case GL_STENCIL_INDEX1_EXT
:
183 case GL_STENCIL_INDEX4_EXT
:
184 case GL_STENCIL_INDEX8_EXT
:
185 case GL_STENCIL_INDEX16_EXT
:
186 rb
->Format
= MESA_FORMAT_S8
;
188 case GL_DEPTH_COMPONENT
:
189 case GL_DEPTH_COMPONENT16
:
190 rb
->Format
= MESA_FORMAT_Z16
;
192 case GL_DEPTH_COMPONENT24
:
193 rb
->Format
= MESA_FORMAT_X8_Z24
;
195 case GL_DEPTH_COMPONENT32
:
196 rb
->Format
= MESA_FORMAT_Z32
;
198 case GL_DEPTH_STENCIL_EXT
:
199 case GL_DEPTH24_STENCIL8_EXT
:
200 rb
->Format
= MESA_FORMAT_Z24_S8
;
203 /* unsupported format */
207 _swrast_set_renderbuffer_accessors(rb
);
209 ASSERT(rb
->DataType
);
211 /* free old buffer storage */
217 rb
->RowStrideBytes
= width
* _mesa_get_format_bytes(rb
->Format
);
219 if (width
> 0 && height
> 0) {
220 /* allocate new buffer storage */
221 rb
->Data
= malloc(width
* height
* _mesa_get_format_bytes(rb
->Format
));
223 if (rb
->Data
== NULL
) {
226 _mesa_error(ctx
, GL_OUT_OF_MEMORY
,
227 "software renderbuffer allocation (%d x %d x %d)",
228 width
, height
, _mesa_get_format_bytes(rb
->Format
));
235 rb
->_BaseFormat
= _mesa_base_fbo_format(ctx
, internalFormat
);
238 internalFormat
== GL_RGBA16_SNORM
&&
239 rb
->_BaseFormat
== 0) {
240 /* NOTE: This is a special case just for accumulation buffers.
241 * This is a very limited use case- there's no snorm texturing or
242 * rendering going on.
244 rb
->_BaseFormat
= GL_RGBA
;
247 /* the internalFormat should have been error checked long ago */
248 ASSERT(rb
->_BaseFormat
);
256 _swrast_map_soft_renderbuffer(struct gl_context
*ctx
,
257 struct gl_renderbuffer
*rb
,
258 GLuint x
, GLuint y
, GLuint w
, GLuint h
,
263 GLubyte
*map
= rb
->Data
;
264 int cpp
= _mesa_get_format_bytes(rb
->Format
);
265 int stride
= rb
->Width
* cpp
;
273 *out_stride
= stride
;
278 _swrast_unmap_soft_renderbuffer(struct gl_context
*ctx
,
279 struct gl_renderbuffer
*rb
)
286 * Allocate a software-based renderbuffer. This is called via the
287 * ctx->Driver.NewRenderbuffer() function when the user creates a new
289 * This would not be used for hardware-based renderbuffers.
291 struct gl_renderbuffer
*
292 _swrast_new_soft_renderbuffer(struct gl_context
*ctx
, GLuint name
)
294 struct gl_renderbuffer
*rb
= _mesa_new_renderbuffer(ctx
, name
);
296 rb
->AllocStorage
= soft_renderbuffer_storage
;
303 * Add software-based color renderbuffers to the given framebuffer.
304 * This is a helper routine for device drivers when creating a
305 * window system framebuffer (not a user-created render/framebuffer).
306 * Once this function is called, you can basically forget about this
307 * renderbuffer; core Mesa will handle all the buffer management and
311 add_color_renderbuffers(struct gl_context
*ctx
, struct gl_framebuffer
*fb
,
312 GLuint rgbBits
, GLuint alphaBits
,
313 GLboolean frontLeft
, GLboolean backLeft
,
314 GLboolean frontRight
, GLboolean backRight
)
318 if (rgbBits
> 16 || alphaBits
> 16) {
320 "Unsupported bit depth in add_color_renderbuffers");
324 assert(MAX_COLOR_ATTACHMENTS
>= 4);
326 for (b
= BUFFER_FRONT_LEFT
; b
<= BUFFER_BACK_RIGHT
; b
++) {
327 struct gl_renderbuffer
*rb
;
329 if (b
== BUFFER_FRONT_LEFT
&& !frontLeft
)
331 else if (b
== BUFFER_BACK_LEFT
&& !backLeft
)
333 else if (b
== BUFFER_FRONT_RIGHT
&& !frontRight
)
335 else if (b
== BUFFER_BACK_RIGHT
&& !backRight
)
338 assert(fb
->Attachment
[b
].Renderbuffer
== NULL
);
340 rb
= _mesa_new_renderbuffer(ctx
, 0);
342 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "Allocating color buffer");
346 rb
->InternalFormat
= GL_RGBA
;
348 rb
->AllocStorage
= soft_renderbuffer_storage
;
349 _mesa_add_renderbuffer(fb
, b
, rb
);
357 * Add a software-based depth renderbuffer to the given framebuffer.
358 * This is a helper routine for device drivers when creating a
359 * window system framebuffer (not a user-created render/framebuffer).
360 * Once this function is called, you can basically forget about this
361 * renderbuffer; core Mesa will handle all the buffer management and
365 add_depth_renderbuffer(struct gl_context
*ctx
, struct gl_framebuffer
*fb
,
368 struct gl_renderbuffer
*rb
;
370 if (depthBits
> 32) {
372 "Unsupported depthBits in add_depth_renderbuffer");
376 assert(fb
->Attachment
[BUFFER_DEPTH
].Renderbuffer
== NULL
);
378 rb
= _mesa_new_renderbuffer(ctx
, 0);
380 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "Allocating depth buffer");
384 if (depthBits
<= 16) {
385 rb
->InternalFormat
= GL_DEPTH_COMPONENT16
;
387 else if (depthBits
<= 24) {
388 rb
->InternalFormat
= GL_DEPTH_COMPONENT24
;
391 rb
->InternalFormat
= GL_DEPTH_COMPONENT32
;
394 rb
->AllocStorage
= soft_renderbuffer_storage
;
395 _mesa_add_renderbuffer(fb
, BUFFER_DEPTH
, rb
);
402 * Add a software-based stencil renderbuffer to the given framebuffer.
403 * This is a helper routine for device drivers when creating a
404 * window system framebuffer (not a user-created render/framebuffer).
405 * Once this function is called, you can basically forget about this
406 * renderbuffer; core Mesa will handle all the buffer management and
410 add_stencil_renderbuffer(struct gl_context
*ctx
, struct gl_framebuffer
*fb
,
413 struct gl_renderbuffer
*rb
;
415 if (stencilBits
> 16) {
417 "Unsupported stencilBits in add_stencil_renderbuffer");
421 assert(fb
->Attachment
[BUFFER_STENCIL
].Renderbuffer
== NULL
);
423 rb
= _mesa_new_renderbuffer(ctx
, 0);
425 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "Allocating stencil buffer");
429 assert(stencilBits
<= 8);
430 rb
->InternalFormat
= GL_STENCIL_INDEX8
;
432 rb
->AllocStorage
= soft_renderbuffer_storage
;
433 _mesa_add_renderbuffer(fb
, BUFFER_STENCIL
, rb
);
440 add_depth_stencil_renderbuffer(struct gl_context
*ctx
,
441 struct gl_framebuffer
*fb
)
443 struct gl_renderbuffer
*rb
;
445 assert(fb
->Attachment
[BUFFER_DEPTH
].Renderbuffer
== NULL
);
446 assert(fb
->Attachment
[BUFFER_STENCIL
].Renderbuffer
== NULL
);
448 rb
= _mesa_new_renderbuffer(ctx
, 0);
450 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "Allocating depth+stencil buffer");
454 rb
->InternalFormat
= GL_DEPTH_STENCIL
;
456 rb
->AllocStorage
= soft_renderbuffer_storage
;
457 _mesa_add_renderbuffer(fb
, BUFFER_DEPTH
, rb
);
458 _mesa_add_renderbuffer(fb
, BUFFER_STENCIL
, rb
);
465 * Add a software-based accumulation renderbuffer to the given framebuffer.
466 * This is a helper routine for device drivers when creating a
467 * window system framebuffer (not a user-created render/framebuffer).
468 * Once this function is called, you can basically forget about this
469 * renderbuffer; core Mesa will handle all the buffer management and
473 add_accum_renderbuffer(struct gl_context
*ctx
, struct gl_framebuffer
*fb
,
474 GLuint redBits
, GLuint greenBits
,
475 GLuint blueBits
, GLuint alphaBits
)
477 struct gl_renderbuffer
*rb
;
479 if (redBits
> 16 || greenBits
> 16 || blueBits
> 16 || alphaBits
> 16) {
481 "Unsupported accumBits in add_accum_renderbuffer");
485 assert(fb
->Attachment
[BUFFER_ACCUM
].Renderbuffer
== NULL
);
487 rb
= _mesa_new_renderbuffer(ctx
, 0);
489 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "Allocating accum buffer");
493 rb
->InternalFormat
= GL_RGBA16_SNORM
;
494 rb
->AllocStorage
= soft_renderbuffer_storage
;
495 _mesa_add_renderbuffer(fb
, BUFFER_ACCUM
, rb
);
503 * Add a software-based aux renderbuffer to the given framebuffer.
504 * This is a helper routine for device drivers when creating a
505 * window system framebuffer (not a user-created render/framebuffer).
506 * Once this function is called, you can basically forget about this
507 * renderbuffer; core Mesa will handle all the buffer management and
510 * NOTE: color-index aux buffers not supported.
513 add_aux_renderbuffers(struct gl_context
*ctx
, struct gl_framebuffer
*fb
,
514 GLuint colorBits
, GLuint numBuffers
)
518 if (colorBits
> 16) {
520 "Unsupported colorBits in add_aux_renderbuffers");
524 assert(numBuffers
<= MAX_AUX_BUFFERS
);
526 for (i
= 0; i
< numBuffers
; i
++) {
527 struct gl_renderbuffer
*rb
= _mesa_new_renderbuffer(ctx
, 0);
529 assert(fb
->Attachment
[BUFFER_AUX0
+ i
].Renderbuffer
== NULL
);
532 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "Allocating aux buffer");
536 assert (colorBits
<= 8);
537 rb
->InternalFormat
= GL_RGBA
;
539 rb
->AllocStorage
= soft_renderbuffer_storage
;
540 _mesa_add_renderbuffer(fb
, BUFFER_AUX0
+ i
, rb
);
547 * Create/attach software-based renderbuffers to the given framebuffer.
548 * This is a helper routine for device drivers. Drivers can just as well
549 * call the individual _mesa_add_*_renderbuffer() routines directly.
552 _swrast_add_soft_renderbuffers(struct gl_framebuffer
*fb
,
560 GLboolean frontLeft
= GL_TRUE
;
561 GLboolean backLeft
= fb
->Visual
.doubleBufferMode
;
562 GLboolean frontRight
= fb
->Visual
.stereoMode
;
563 GLboolean backRight
= fb
->Visual
.stereoMode
&& fb
->Visual
.doubleBufferMode
;
566 assert(fb
->Visual
.redBits
== fb
->Visual
.greenBits
);
567 assert(fb
->Visual
.redBits
== fb
->Visual
.blueBits
);
568 add_color_renderbuffers(NULL
, fb
,
570 fb
->Visual
.alphaBits
,
572 frontRight
, backRight
);
576 /* This is pretty much for debugging purposes only since there's a perf
577 * hit for using combined depth/stencil in swrast.
579 if (depth
&& fb
->Visual
.depthBits
== 24 &&
580 stencil
&& fb
->Visual
.stencilBits
== 8) {
581 /* use combined depth/stencil buffer */
582 add_depth_stencil_renderbuffer(NULL
, fb
);
586 (void) add_depth_stencil_renderbuffer
;
590 assert(fb
->Visual
.depthBits
> 0);
591 add_depth_renderbuffer(NULL
, fb
, fb
->Visual
.depthBits
);
595 assert(fb
->Visual
.stencilBits
> 0);
596 add_stencil_renderbuffer(NULL
, fb
, fb
->Visual
.stencilBits
);
601 assert(fb
->Visual
.accumRedBits
> 0);
602 assert(fb
->Visual
.accumGreenBits
> 0);
603 assert(fb
->Visual
.accumBlueBits
> 0);
604 add_accum_renderbuffer(NULL
, fb
,
605 fb
->Visual
.accumRedBits
,
606 fb
->Visual
.accumGreenBits
,
607 fb
->Visual
.accumBlueBits
,
608 fb
->Visual
.accumAlphaBits
);
612 assert(fb
->Visual
.numAuxBuffers
> 0);
613 add_aux_renderbuffers(NULL
, fb
, fb
->Visual
.redBits
,
614 fb
->Visual
.numAuxBuffers
);