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"
44 * This is a software fallback for the gl_renderbuffer->AllocStorage
46 * Device drivers will typically override this function for the buffers
47 * which it manages (typically color buffers, Z and stencil).
48 * Other buffers (like software accumulation and aux buffers) which the driver
49 * doesn't manage can be handled with this function.
51 * This one multi-purpose function can allocate stencil, depth, accum, color
52 * or color-index buffers!
55 soft_renderbuffer_storage(struct gl_context
*ctx
, struct gl_renderbuffer
*rb
,
56 GLenum internalFormat
,
57 GLuint width
, GLuint height
)
59 switch (internalFormat
) {
68 rb
->Format
= MESA_FORMAT_RGB888
;
79 if (_mesa_little_endian())
80 rb
->Format
= MESA_FORMAT_RGBA8888_REV
;
82 rb
->Format
= MESA_FORMAT_RGBA8888
;
86 /* for accum buffer */
87 rb
->Format
= MESA_FORMAT_SIGNED_RGBA_16
;
89 case GL_STENCIL_INDEX
:
90 case GL_STENCIL_INDEX1_EXT
:
91 case GL_STENCIL_INDEX4_EXT
:
92 case GL_STENCIL_INDEX8_EXT
:
93 case GL_STENCIL_INDEX16_EXT
:
94 rb
->Format
= MESA_FORMAT_S8
;
96 case GL_DEPTH_COMPONENT
:
97 case GL_DEPTH_COMPONENT16
:
98 rb
->Format
= MESA_FORMAT_Z16
;
100 case GL_DEPTH_COMPONENT24
:
101 rb
->Format
= MESA_FORMAT_X8_Z24
;
103 case GL_DEPTH_COMPONENT32
:
104 rb
->Format
= MESA_FORMAT_Z32
;
106 case GL_DEPTH_STENCIL_EXT
:
107 case GL_DEPTH24_STENCIL8_EXT
:
108 rb
->Format
= MESA_FORMAT_Z24_S8
;
111 /* unsupported format */
115 /* free old buffer storage */
121 rb
->RowStrideBytes
= width
* _mesa_get_format_bytes(rb
->Format
);
123 if (width
> 0 && height
> 0) {
124 /* allocate new buffer storage */
125 rb
->Buffer
= malloc(width
* height
* _mesa_get_format_bytes(rb
->Format
));
127 if (rb
->Buffer
== NULL
) {
130 _mesa_error(ctx
, GL_OUT_OF_MEMORY
,
131 "software renderbuffer allocation (%d x %d x %d)",
132 width
, height
, _mesa_get_format_bytes(rb
->Format
));
139 rb
->_BaseFormat
= _mesa_base_fbo_format(ctx
, internalFormat
);
142 internalFormat
== GL_RGBA16_SNORM
&&
143 rb
->_BaseFormat
== 0) {
144 /* NOTE: This is a special case just for accumulation buffers.
145 * This is a very limited use case- there's no snorm texturing or
146 * rendering going on.
148 rb
->_BaseFormat
= GL_RGBA
;
151 /* the internalFormat should have been error checked long ago */
152 ASSERT(rb
->_BaseFormat
);
160 * Called via gl_renderbuffer::Delete()
163 soft_renderbuffer_delete(struct gl_renderbuffer
*rb
)
174 _swrast_map_soft_renderbuffer(struct gl_context
*ctx
,
175 struct gl_renderbuffer
*rb
,
176 GLuint x
, GLuint y
, GLuint w
, GLuint h
,
181 GLubyte
*map
= rb
->Buffer
;
182 int cpp
= _mesa_get_format_bytes(rb
->Format
);
183 int stride
= rb
->Width
* cpp
;
194 *out_stride
= stride
;
199 _swrast_unmap_soft_renderbuffer(struct gl_context
*ctx
,
200 struct gl_renderbuffer
*rb
)
207 * Allocate a software-based renderbuffer. This is called via the
208 * ctx->Driver.NewRenderbuffer() function when the user creates a new
210 * This would not be used for hardware-based renderbuffers.
212 struct gl_renderbuffer
*
213 _swrast_new_soft_renderbuffer(struct gl_context
*ctx
, GLuint name
)
215 struct gl_renderbuffer
*rb
= _mesa_new_renderbuffer(ctx
, name
);
217 rb
->AllocStorage
= soft_renderbuffer_storage
;
218 rb
->Delete
= soft_renderbuffer_delete
;
225 * Add software-based color renderbuffers to the given framebuffer.
226 * This is a helper routine for device drivers when creating a
227 * window system framebuffer (not a user-created render/framebuffer).
228 * Once this function is called, you can basically forget about this
229 * renderbuffer; core Mesa will handle all the buffer management and
233 add_color_renderbuffers(struct gl_context
*ctx
, struct gl_framebuffer
*fb
,
234 GLuint rgbBits
, GLuint alphaBits
,
235 GLboolean frontLeft
, GLboolean backLeft
,
236 GLboolean frontRight
, GLboolean backRight
)
240 if (rgbBits
> 16 || alphaBits
> 16) {
242 "Unsupported bit depth in add_color_renderbuffers");
246 assert(MAX_COLOR_ATTACHMENTS
>= 4);
248 for (b
= BUFFER_FRONT_LEFT
; b
<= BUFFER_BACK_RIGHT
; b
++) {
249 struct gl_renderbuffer
*rb
;
251 if (b
== BUFFER_FRONT_LEFT
&& !frontLeft
)
253 else if (b
== BUFFER_BACK_LEFT
&& !backLeft
)
255 else if (b
== BUFFER_FRONT_RIGHT
&& !frontRight
)
257 else if (b
== BUFFER_BACK_RIGHT
&& !backRight
)
260 assert(fb
->Attachment
[b
].Renderbuffer
== NULL
);
262 rb
= ctx
->Driver
.NewRenderbuffer(ctx
, 0);
264 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "Allocating color buffer");
268 rb
->InternalFormat
= GL_RGBA
;
270 rb
->AllocStorage
= soft_renderbuffer_storage
;
271 _mesa_add_renderbuffer(fb
, b
, rb
);
279 * Add a software-based depth renderbuffer to the given framebuffer.
280 * This is a helper routine for device drivers when creating a
281 * window system framebuffer (not a user-created render/framebuffer).
282 * Once this function is called, you can basically forget about this
283 * renderbuffer; core Mesa will handle all the buffer management and
287 add_depth_renderbuffer(struct gl_context
*ctx
, struct gl_framebuffer
*fb
,
290 struct gl_renderbuffer
*rb
;
292 if (depthBits
> 32) {
294 "Unsupported depthBits in add_depth_renderbuffer");
298 assert(fb
->Attachment
[BUFFER_DEPTH
].Renderbuffer
== NULL
);
300 rb
= _swrast_new_soft_renderbuffer(ctx
, 0);
302 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "Allocating depth buffer");
306 if (depthBits
<= 16) {
307 rb
->InternalFormat
= GL_DEPTH_COMPONENT16
;
309 else if (depthBits
<= 24) {
310 rb
->InternalFormat
= GL_DEPTH_COMPONENT24
;
313 rb
->InternalFormat
= GL_DEPTH_COMPONENT32
;
316 rb
->AllocStorage
= soft_renderbuffer_storage
;
317 _mesa_add_renderbuffer(fb
, BUFFER_DEPTH
, rb
);
324 * Add a software-based stencil renderbuffer to the given framebuffer.
325 * This is a helper routine for device drivers when creating a
326 * window system framebuffer (not a user-created render/framebuffer).
327 * Once this function is called, you can basically forget about this
328 * renderbuffer; core Mesa will handle all the buffer management and
332 add_stencil_renderbuffer(struct gl_context
*ctx
, struct gl_framebuffer
*fb
,
335 struct gl_renderbuffer
*rb
;
337 if (stencilBits
> 16) {
339 "Unsupported stencilBits in add_stencil_renderbuffer");
343 assert(fb
->Attachment
[BUFFER_STENCIL
].Renderbuffer
== NULL
);
345 rb
= _swrast_new_soft_renderbuffer(ctx
, 0);
347 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "Allocating stencil buffer");
351 assert(stencilBits
<= 8);
352 rb
->InternalFormat
= GL_STENCIL_INDEX8
;
354 rb
->AllocStorage
= soft_renderbuffer_storage
;
355 _mesa_add_renderbuffer(fb
, BUFFER_STENCIL
, rb
);
362 add_depth_stencil_renderbuffer(struct gl_context
*ctx
,
363 struct gl_framebuffer
*fb
)
365 struct gl_renderbuffer
*rb
;
367 assert(fb
->Attachment
[BUFFER_DEPTH
].Renderbuffer
== NULL
);
368 assert(fb
->Attachment
[BUFFER_STENCIL
].Renderbuffer
== NULL
);
370 rb
= _swrast_new_soft_renderbuffer(ctx
, 0);
372 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "Allocating depth+stencil buffer");
376 rb
->InternalFormat
= GL_DEPTH_STENCIL
;
378 rb
->AllocStorage
= soft_renderbuffer_storage
;
379 _mesa_add_renderbuffer(fb
, BUFFER_DEPTH
, rb
);
380 _mesa_add_renderbuffer(fb
, BUFFER_STENCIL
, rb
);
387 * Add a software-based accumulation renderbuffer to the given framebuffer.
388 * This is a helper routine for device drivers when creating a
389 * window system framebuffer (not a user-created render/framebuffer).
390 * Once this function is called, you can basically forget about this
391 * renderbuffer; core Mesa will handle all the buffer management and
395 add_accum_renderbuffer(struct gl_context
*ctx
, struct gl_framebuffer
*fb
,
396 GLuint redBits
, GLuint greenBits
,
397 GLuint blueBits
, GLuint alphaBits
)
399 struct gl_renderbuffer
*rb
;
401 if (redBits
> 16 || greenBits
> 16 || blueBits
> 16 || alphaBits
> 16) {
403 "Unsupported accumBits in add_accum_renderbuffer");
407 assert(fb
->Attachment
[BUFFER_ACCUM
].Renderbuffer
== NULL
);
409 rb
= _swrast_new_soft_renderbuffer(ctx
, 0);
411 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "Allocating accum buffer");
415 rb
->InternalFormat
= GL_RGBA16_SNORM
;
416 rb
->AllocStorage
= soft_renderbuffer_storage
;
417 _mesa_add_renderbuffer(fb
, BUFFER_ACCUM
, rb
);
425 * Add a software-based aux renderbuffer to the given framebuffer.
426 * This is a helper routine for device drivers when creating a
427 * window system framebuffer (not a user-created render/framebuffer).
428 * Once this function is called, you can basically forget about this
429 * renderbuffer; core Mesa will handle all the buffer management and
432 * NOTE: color-index aux buffers not supported.
435 add_aux_renderbuffers(struct gl_context
*ctx
, struct gl_framebuffer
*fb
,
436 GLuint colorBits
, GLuint numBuffers
)
440 if (colorBits
> 16) {
442 "Unsupported colorBits in add_aux_renderbuffers");
446 assert(numBuffers
<= MAX_AUX_BUFFERS
);
448 for (i
= 0; i
< numBuffers
; i
++) {
449 struct gl_renderbuffer
*rb
= _swrast_new_soft_renderbuffer(ctx
, 0);
451 assert(fb
->Attachment
[BUFFER_AUX0
+ i
].Renderbuffer
== NULL
);
454 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "Allocating aux buffer");
458 assert (colorBits
<= 8);
459 rb
->InternalFormat
= GL_RGBA
;
461 rb
->AllocStorage
= soft_renderbuffer_storage
;
462 _mesa_add_renderbuffer(fb
, BUFFER_AUX0
+ i
, rb
);
469 * Create/attach software-based renderbuffers to the given framebuffer.
470 * This is a helper routine for device drivers. Drivers can just as well
471 * call the individual _mesa_add_*_renderbuffer() routines directly.
474 _swrast_add_soft_renderbuffers(struct gl_framebuffer
*fb
,
482 GLboolean frontLeft
= GL_TRUE
;
483 GLboolean backLeft
= fb
->Visual
.doubleBufferMode
;
484 GLboolean frontRight
= fb
->Visual
.stereoMode
;
485 GLboolean backRight
= fb
->Visual
.stereoMode
&& fb
->Visual
.doubleBufferMode
;
488 assert(fb
->Visual
.redBits
== fb
->Visual
.greenBits
);
489 assert(fb
->Visual
.redBits
== fb
->Visual
.blueBits
);
490 add_color_renderbuffers(NULL
, fb
,
492 fb
->Visual
.alphaBits
,
494 frontRight
, backRight
);
498 /* This is pretty much for debugging purposes only since there's a perf
499 * hit for using combined depth/stencil in swrast.
501 if (depth
&& fb
->Visual
.depthBits
== 24 &&
502 stencil
&& fb
->Visual
.stencilBits
== 8) {
503 /* use combined depth/stencil buffer */
504 add_depth_stencil_renderbuffer(NULL
, fb
);
508 (void) add_depth_stencil_renderbuffer
;
512 assert(fb
->Visual
.depthBits
> 0);
513 add_depth_renderbuffer(NULL
, fb
, fb
->Visual
.depthBits
);
517 assert(fb
->Visual
.stencilBits
> 0);
518 add_stencil_renderbuffer(NULL
, fb
, fb
->Visual
.stencilBits
);
523 assert(fb
->Visual
.accumRedBits
> 0);
524 assert(fb
->Visual
.accumGreenBits
> 0);
525 assert(fb
->Visual
.accumBlueBits
> 0);
526 add_accum_renderbuffer(NULL
, fb
,
527 fb
->Visual
.accumRedBits
,
528 fb
->Visual
.accumGreenBits
,
529 fb
->Visual
.accumBlueBits
,
530 fb
->Visual
.accumAlphaBits
);
534 assert(fb
->Visual
.numAuxBuffers
> 0);
535 add_aux_renderbuffers(NULL
, fb
, fb
->Visual
.redBits
,
536 fb
->Visual
.numAuxBuffers
);