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_context.h"
41 #include "swrast/s_renderbuffer.h"
45 * This is a software fallback for the gl_renderbuffer->AllocStorage
47 * Device drivers will typically override this function for the buffers
48 * which it manages (typically color buffers, Z and stencil).
49 * Other buffers (like software accumulation and aux buffers) which the driver
50 * doesn't manage can be handled with this function.
52 * This one multi-purpose function can allocate stencil, depth, accum, color
53 * or color-index buffers!
56 soft_renderbuffer_storage(struct gl_context
*ctx
, struct gl_renderbuffer
*rb
,
57 GLenum internalFormat
,
58 GLuint width
, GLuint height
)
60 struct swrast_renderbuffer
*srb
= swrast_renderbuffer(rb
);
62 switch (internalFormat
) {
71 rb
->Format
= MESA_FORMAT_RGB888
;
82 if (_mesa_little_endian())
83 rb
->Format
= MESA_FORMAT_RGBA8888_REV
;
85 rb
->Format
= MESA_FORMAT_RGBA8888
;
89 /* for accum buffer */
90 rb
->Format
= MESA_FORMAT_SIGNED_RGBA_16
;
92 case GL_STENCIL_INDEX
:
93 case GL_STENCIL_INDEX1_EXT
:
94 case GL_STENCIL_INDEX4_EXT
:
95 case GL_STENCIL_INDEX8_EXT
:
96 case GL_STENCIL_INDEX16_EXT
:
97 rb
->Format
= MESA_FORMAT_S8
;
99 case GL_DEPTH_COMPONENT
:
100 case GL_DEPTH_COMPONENT16
:
101 rb
->Format
= MESA_FORMAT_Z16
;
103 case GL_DEPTH_COMPONENT24
:
104 rb
->Format
= MESA_FORMAT_X8_Z24
;
106 case GL_DEPTH_COMPONENT32
:
107 rb
->Format
= MESA_FORMAT_Z32
;
109 case GL_DEPTH_STENCIL_EXT
:
110 case GL_DEPTH24_STENCIL8_EXT
:
111 rb
->Format
= MESA_FORMAT_Z24_S8
;
114 /* unsupported format */
118 /* free old buffer storage */
124 srb
->RowStride
= width
* _mesa_get_format_bytes(rb
->Format
);
126 if (width
> 0 && height
> 0) {
127 /* allocate new buffer storage */
128 srb
->Buffer
= malloc(width
* height
129 * _mesa_get_format_bytes(rb
->Format
));
131 if (srb
->Buffer
== NULL
) {
134 _mesa_error(ctx
, GL_OUT_OF_MEMORY
,
135 "software renderbuffer allocation (%d x %d x %d)",
136 width
, height
, _mesa_get_format_bytes(rb
->Format
));
143 rb
->_BaseFormat
= _mesa_base_fbo_format(ctx
, internalFormat
);
146 internalFormat
== GL_RGBA16_SNORM
&&
147 rb
->_BaseFormat
== 0) {
148 /* NOTE: This is a special case just for accumulation buffers.
149 * This is a very limited use case- there's no snorm texturing or
150 * rendering going on.
152 rb
->_BaseFormat
= GL_RGBA
;
155 /* the internalFormat should have been error checked long ago */
156 ASSERT(rb
->_BaseFormat
);
164 * Called via gl_renderbuffer::Delete()
167 soft_renderbuffer_delete(struct gl_renderbuffer
*rb
)
169 struct swrast_renderbuffer
*srb
= swrast_renderbuffer(rb
);
180 _swrast_map_soft_renderbuffer(struct gl_context
*ctx
,
181 struct gl_renderbuffer
*rb
,
182 GLuint x
, GLuint y
, GLuint w
, GLuint h
,
187 struct swrast_renderbuffer
*srb
= swrast_renderbuffer(rb
);
188 GLubyte
*map
= srb
->Buffer
;
189 int cpp
= _mesa_get_format_bytes(rb
->Format
);
190 int stride
= rb
->Width
* cpp
;
201 *out_stride
= stride
;
206 _swrast_unmap_soft_renderbuffer(struct gl_context
*ctx
,
207 struct gl_renderbuffer
*rb
)
214 * Allocate a software-based renderbuffer. This is called via the
215 * ctx->Driver.NewRenderbuffer() function when the user creates a new
217 * This would not be used for hardware-based renderbuffers.
219 struct gl_renderbuffer
*
220 _swrast_new_soft_renderbuffer(struct gl_context
*ctx
, GLuint name
)
222 struct swrast_renderbuffer
*srb
= CALLOC_STRUCT(swrast_renderbuffer
);
224 _mesa_init_renderbuffer(&srb
->Base
, name
);
225 srb
->Base
.AllocStorage
= soft_renderbuffer_storage
;
226 srb
->Base
.Delete
= soft_renderbuffer_delete
;
233 * Add software-based color renderbuffers to the given framebuffer.
234 * This is a helper routine for device drivers when creating a
235 * window system framebuffer (not a user-created render/framebuffer).
236 * Once this function is called, you can basically forget about this
237 * renderbuffer; core Mesa will handle all the buffer management and
241 add_color_renderbuffers(struct gl_context
*ctx
, struct gl_framebuffer
*fb
,
242 GLuint rgbBits
, GLuint alphaBits
,
243 GLboolean frontLeft
, GLboolean backLeft
,
244 GLboolean frontRight
, GLboolean backRight
)
248 if (rgbBits
> 16 || alphaBits
> 16) {
250 "Unsupported bit depth in add_color_renderbuffers");
254 assert(MAX_COLOR_ATTACHMENTS
>= 4);
256 for (b
= BUFFER_FRONT_LEFT
; b
<= BUFFER_BACK_RIGHT
; b
++) {
257 struct gl_renderbuffer
*rb
;
259 if (b
== BUFFER_FRONT_LEFT
&& !frontLeft
)
261 else if (b
== BUFFER_BACK_LEFT
&& !backLeft
)
263 else if (b
== BUFFER_FRONT_RIGHT
&& !frontRight
)
265 else if (b
== BUFFER_BACK_RIGHT
&& !backRight
)
268 assert(fb
->Attachment
[b
].Renderbuffer
== NULL
);
270 rb
= ctx
->Driver
.NewRenderbuffer(ctx
, 0);
272 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "Allocating color buffer");
276 rb
->InternalFormat
= GL_RGBA
;
278 rb
->AllocStorage
= soft_renderbuffer_storage
;
279 _mesa_add_renderbuffer(fb
, b
, rb
);
287 * Add a software-based depth renderbuffer to the given framebuffer.
288 * This is a helper routine for device drivers when creating a
289 * window system framebuffer (not a user-created render/framebuffer).
290 * Once this function is called, you can basically forget about this
291 * renderbuffer; core Mesa will handle all the buffer management and
295 add_depth_renderbuffer(struct gl_context
*ctx
, struct gl_framebuffer
*fb
,
298 struct gl_renderbuffer
*rb
;
300 if (depthBits
> 32) {
302 "Unsupported depthBits in add_depth_renderbuffer");
306 assert(fb
->Attachment
[BUFFER_DEPTH
].Renderbuffer
== NULL
);
308 rb
= _swrast_new_soft_renderbuffer(ctx
, 0);
310 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "Allocating depth buffer");
314 if (depthBits
<= 16) {
315 rb
->InternalFormat
= GL_DEPTH_COMPONENT16
;
317 else if (depthBits
<= 24) {
318 rb
->InternalFormat
= GL_DEPTH_COMPONENT24
;
321 rb
->InternalFormat
= GL_DEPTH_COMPONENT32
;
324 rb
->AllocStorage
= soft_renderbuffer_storage
;
325 _mesa_add_renderbuffer(fb
, BUFFER_DEPTH
, rb
);
332 * Add a software-based stencil renderbuffer to the given framebuffer.
333 * This is a helper routine for device drivers when creating a
334 * window system framebuffer (not a user-created render/framebuffer).
335 * Once this function is called, you can basically forget about this
336 * renderbuffer; core Mesa will handle all the buffer management and
340 add_stencil_renderbuffer(struct gl_context
*ctx
, struct gl_framebuffer
*fb
,
343 struct gl_renderbuffer
*rb
;
345 if (stencilBits
> 16) {
347 "Unsupported stencilBits in add_stencil_renderbuffer");
351 assert(fb
->Attachment
[BUFFER_STENCIL
].Renderbuffer
== NULL
);
353 rb
= _swrast_new_soft_renderbuffer(ctx
, 0);
355 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "Allocating stencil buffer");
359 assert(stencilBits
<= 8);
360 rb
->InternalFormat
= GL_STENCIL_INDEX8
;
362 rb
->AllocStorage
= soft_renderbuffer_storage
;
363 _mesa_add_renderbuffer(fb
, BUFFER_STENCIL
, rb
);
370 add_depth_stencil_renderbuffer(struct gl_context
*ctx
,
371 struct gl_framebuffer
*fb
)
373 struct gl_renderbuffer
*rb
;
375 assert(fb
->Attachment
[BUFFER_DEPTH
].Renderbuffer
== NULL
);
376 assert(fb
->Attachment
[BUFFER_STENCIL
].Renderbuffer
== NULL
);
378 rb
= _swrast_new_soft_renderbuffer(ctx
, 0);
380 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "Allocating depth+stencil buffer");
384 rb
->InternalFormat
= GL_DEPTH_STENCIL
;
386 rb
->AllocStorage
= soft_renderbuffer_storage
;
387 _mesa_add_renderbuffer(fb
, BUFFER_DEPTH
, rb
);
388 _mesa_add_renderbuffer(fb
, BUFFER_STENCIL
, rb
);
395 * Add a software-based accumulation renderbuffer to the given framebuffer.
396 * This is a helper routine for device drivers when creating a
397 * window system framebuffer (not a user-created render/framebuffer).
398 * Once this function is called, you can basically forget about this
399 * renderbuffer; core Mesa will handle all the buffer management and
403 add_accum_renderbuffer(struct gl_context
*ctx
, struct gl_framebuffer
*fb
,
404 GLuint redBits
, GLuint greenBits
,
405 GLuint blueBits
, GLuint alphaBits
)
407 struct gl_renderbuffer
*rb
;
409 if (redBits
> 16 || greenBits
> 16 || blueBits
> 16 || alphaBits
> 16) {
411 "Unsupported accumBits in add_accum_renderbuffer");
415 assert(fb
->Attachment
[BUFFER_ACCUM
].Renderbuffer
== NULL
);
417 rb
= _swrast_new_soft_renderbuffer(ctx
, 0);
419 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "Allocating accum buffer");
423 rb
->InternalFormat
= GL_RGBA16_SNORM
;
424 rb
->AllocStorage
= soft_renderbuffer_storage
;
425 _mesa_add_renderbuffer(fb
, BUFFER_ACCUM
, rb
);
433 * Add a software-based aux renderbuffer to the given framebuffer.
434 * This is a helper routine for device drivers when creating a
435 * window system framebuffer (not a user-created render/framebuffer).
436 * Once this function is called, you can basically forget about this
437 * renderbuffer; core Mesa will handle all the buffer management and
440 * NOTE: color-index aux buffers not supported.
443 add_aux_renderbuffers(struct gl_context
*ctx
, struct gl_framebuffer
*fb
,
444 GLuint colorBits
, GLuint numBuffers
)
448 if (colorBits
> 16) {
450 "Unsupported colorBits in add_aux_renderbuffers");
454 assert(numBuffers
<= MAX_AUX_BUFFERS
);
456 for (i
= 0; i
< numBuffers
; i
++) {
457 struct gl_renderbuffer
*rb
= _swrast_new_soft_renderbuffer(ctx
, 0);
459 assert(fb
->Attachment
[BUFFER_AUX0
+ i
].Renderbuffer
== NULL
);
462 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "Allocating aux buffer");
466 assert (colorBits
<= 8);
467 rb
->InternalFormat
= GL_RGBA
;
469 rb
->AllocStorage
= soft_renderbuffer_storage
;
470 _mesa_add_renderbuffer(fb
, BUFFER_AUX0
+ i
, rb
);
477 * Create/attach software-based renderbuffers to the given framebuffer.
478 * This is a helper routine for device drivers. Drivers can just as well
479 * call the individual _mesa_add_*_renderbuffer() routines directly.
482 _swrast_add_soft_renderbuffers(struct gl_framebuffer
*fb
,
490 GLboolean frontLeft
= GL_TRUE
;
491 GLboolean backLeft
= fb
->Visual
.doubleBufferMode
;
492 GLboolean frontRight
= fb
->Visual
.stereoMode
;
493 GLboolean backRight
= fb
->Visual
.stereoMode
&& fb
->Visual
.doubleBufferMode
;
496 assert(fb
->Visual
.redBits
== fb
->Visual
.greenBits
);
497 assert(fb
->Visual
.redBits
== fb
->Visual
.blueBits
);
498 add_color_renderbuffers(NULL
, fb
,
500 fb
->Visual
.alphaBits
,
502 frontRight
, backRight
);
506 /* This is pretty much for debugging purposes only since there's a perf
507 * hit for using combined depth/stencil in swrast.
509 if (depth
&& fb
->Visual
.depthBits
== 24 &&
510 stencil
&& fb
->Visual
.stencilBits
== 8) {
511 /* use combined depth/stencil buffer */
512 add_depth_stencil_renderbuffer(NULL
, fb
);
516 (void) add_depth_stencil_renderbuffer
;
520 assert(fb
->Visual
.depthBits
> 0);
521 add_depth_renderbuffer(NULL
, fb
, fb
->Visual
.depthBits
);
525 assert(fb
->Visual
.stencilBits
> 0);
526 add_stencil_renderbuffer(NULL
, fb
, fb
->Visual
.stencilBits
);
531 assert(fb
->Visual
.accumRedBits
> 0);
532 assert(fb
->Visual
.accumGreenBits
> 0);
533 assert(fb
->Visual
.accumBlueBits
> 0);
534 add_accum_renderbuffer(NULL
, fb
,
535 fb
->Visual
.accumRedBits
,
536 fb
->Visual
.accumGreenBits
,
537 fb
->Visual
.accumBlueBits
,
538 fb
->Visual
.accumAlphaBits
);
542 assert(fb
->Visual
.numAuxBuffers
> 0);
543 add_aux_renderbuffers(NULL
, fb
, fb
->Visual
.redBits
,
544 fb
->Visual
.numAuxBuffers
);