2
* Mesa 3-D graphics library
4
* Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
6
* Permission is hereby granted, free of charge, to any person obtaining a
7
* copy of this software and associated documentation files (the "Software"),
8
* to deal in the Software without restriction, including without limitation
9
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
10
* and/or sell copies of the Software, and to permit persons to whom the
11
* Software is furnished to do so, subject to the following conditions:
13
* The above copyright notice and this permission notice shall be included
14
* in all copies or substantial portions of the Software.
16
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
* OTHER DEALINGS IN THE SOFTWARE.
29
#include "bufferobj.h"
32
#include "glformats.h"
34
#include "renderbuffer.h"
35
#include "util/u_memory.h"
36
#include "util/u_inlines.h"
38
#include "state_tracker/st_context.h"
39
#include "state_tracker/st_format.h"
42
* Called by FBO code to choose a PIPE_FORMAT_ for drawing surfaces.
44
static enum pipe_format
45
choose_renderbuffer_format(struct gl_context *ctx,
46
GLenum internalFormat, unsigned sample_count,
47
unsigned storage_sample_count)
50
if (_mesa_is_depth_or_stencil_format(internalFormat))
51
bindings = PIPE_BIND_DEPTH_STENCIL;
53
bindings = PIPE_BIND_RENDER_TARGET;
54
return st_choose_format(st_context(ctx), internalFormat, GL_NONE, GL_NONE,
55
PIPE_TEXTURE_2D, sample_count,
56
storage_sample_count, bindings,
63
* Delete a gl_framebuffer.
64
* This is the default function for renderbuffer->Delete().
65
* Drivers which subclass gl_renderbuffer should probably implement their
66
* own delete function. But the driver might also call this function to
67
* free the object in the end.
70
delete_renderbuffer(struct gl_context *ctx, struct gl_renderbuffer *rb)
73
pipe_surface_release(ctx->pipe, &rb->surface_srgb);
74
pipe_surface_release(ctx->pipe, &rb->surface_linear);
76
pipe_surface_release_no_context(&rb->surface_srgb);
77
pipe_surface_release_no_context(&rb->surface_linear);
80
pipe_resource_reference(&rb->texture, NULL);
87
renderbuffer_alloc_sw_storage(struct gl_context *ctx,
88
struct gl_renderbuffer *rb,
89
GLenum internalFormat,
90
GLuint width, GLuint height)
92
enum pipe_format format;
98
if (internalFormat == GL_RGBA16_SNORM) {
99
/* Special case for software accum buffers. Otherwise, if the
100
* call to choose_renderbuffer_format() fails (because the
101
* driver doesn't support signed 16-bit/channel colors) we'd
102
* just return without allocating the software accum buffer.
104
format = PIPE_FORMAT_R16G16B16A16_SNORM;
107
format = choose_renderbuffer_format(ctx, internalFormat, 0, 0);
109
/* Not setting gl_renderbuffer::Format here will cause
110
* FRAMEBUFFER_UNSUPPORTED and ValidateFramebuffer will not be called.
112
if (format == PIPE_FORMAT_NONE) {
117
rb->Format = st_pipe_format_to_mesa_format(format);
119
size = _mesa_format_image_size(rb->Format, width, height, 1);
120
rb->data = malloc(size);
121
return rb->data != NULL;
126
* gl_renderbuffer::AllocStorage()
127
* This is called to allocate the original drawing surface, and
128
* during window resize.
131
renderbuffer_alloc_storage(struct gl_context * ctx,
132
struct gl_renderbuffer *rb,
133
GLenum internalFormat,
134
GLuint width, GLuint height)
136
struct st_context *st = st_context(ctx);
137
struct pipe_screen *screen = ctx->screen;
138
enum pipe_format format = PIPE_FORMAT_NONE;
139
struct pipe_resource templ;
141
/* init renderbuffer fields */
144
rb->_BaseFormat = _mesa_base_fbo_format(ctx, internalFormat);
145
rb->defined = GL_FALSE; /* undefined contents now */
148
return renderbuffer_alloc_sw_storage(ctx, rb, internalFormat,
152
/* Free the old surface and texture
154
pipe_surface_reference(&rb->surface_srgb, NULL);
155
pipe_surface_reference(&rb->surface_linear, NULL);
157
pipe_resource_reference(&rb->texture, NULL);
159
/* If an sRGB framebuffer is unsupported, sRGB formats behave like linear
162
if (!ctx->Extensions.EXT_sRGB) {
163
internalFormat = _mesa_get_linear_internalformat(internalFormat);
166
/* Handle multisample renderbuffers first.
168
* From ARB_framebuffer_object:
169
* If <samples> is zero, then RENDERBUFFER_SAMPLES is set to zero.
170
* Otherwise <samples> represents a request for a desired minimum
171
* number of samples. Since different implementations may support
172
* different sample counts for multisampled rendering, the actual
173
* number of samples allocated for the renderbuffer image is
174
* implementation dependent. However, the resulting value for
175
* RENDERBUFFER_SAMPLES is guaranteed to be greater than or equal
176
* to <samples> and no more than the next larger sample count supported
177
* by the implementation.
179
* Find the supported number of samples >= rb->NumSamples
181
if (rb->NumSamples > 0) {
182
unsigned start, start_storage;
184
if (ctx->Const.MaxSamples > 1 && rb->NumSamples == 1) {
185
/* don't try num_samples = 1 with drivers that support real msaa */
189
start = rb->NumSamples;
190
start_storage = rb->NumStorageSamples;
193
if (ctx->Extensions.AMD_framebuffer_multisample_advanced) {
194
if (rb->_BaseFormat == GL_DEPTH_COMPONENT ||
195
rb->_BaseFormat == GL_DEPTH_STENCIL ||
196
rb->_BaseFormat == GL_STENCIL_INDEX) {
197
/* Find a supported depth-stencil format. */
198
for (unsigned samples = start;
199
samples <= ctx->Const.MaxDepthStencilFramebufferSamples;
201
format = choose_renderbuffer_format(ctx, internalFormat,
204
if (format != PIPE_FORMAT_NONE) {
205
rb->NumSamples = samples;
206
rb->NumStorageSamples = samples;
211
/* Find a supported color format, samples >= storage_samples. */
212
for (unsigned storage_samples = start_storage;
213
storage_samples <= ctx->Const.MaxColorFramebufferStorageSamples;
215
for (unsigned samples = MAX2(start, storage_samples);
216
samples <= ctx->Const.MaxColorFramebufferSamples;
218
format = choose_renderbuffer_format(ctx, internalFormat,
222
if (format != PIPE_FORMAT_NONE) {
223
rb->NumSamples = samples;
224
rb->NumStorageSamples = storage_samples;
232
for (unsigned samples = start; samples <= ctx->Const.MaxSamples;
234
format = choose_renderbuffer_format(ctx, internalFormat,
237
if (format != PIPE_FORMAT_NONE) {
238
rb->NumSamples = samples;
239
rb->NumStorageSamples = samples;
245
format = choose_renderbuffer_format(ctx, internalFormat, 0, 0);
248
/* Not setting gl_renderbuffer::Format here will cause
249
* FRAMEBUFFER_UNSUPPORTED and ValidateFramebuffer will not be called.
251
if (format == PIPE_FORMAT_NONE) {
255
rb->Format = st_pipe_format_to_mesa_format(format);
257
if (width == 0 || height == 0) {
258
/* if size is zero, nothing to allocate */
262
/* Setup new texture template.
264
memset(&templ, 0, sizeof(templ));
265
templ.target = st->internal_target;
266
templ.format = format;
267
templ.width0 = width;
268
templ.height0 = height;
270
templ.array_size = 1;
271
templ.nr_samples = rb->NumSamples;
272
templ.nr_storage_samples = rb->NumStorageSamples;
274
if (util_format_is_depth_or_stencil(format)) {
275
templ.bind = PIPE_BIND_DEPTH_STENCIL;
277
else if (rb->Name != 0) {
278
/* this is a user-created renderbuffer */
279
templ.bind = PIPE_BIND_RENDER_TARGET;
282
/* this is a window-system buffer */
283
templ.bind = (PIPE_BIND_DISPLAY_TARGET |
284
PIPE_BIND_RENDER_TARGET);
287
rb->texture = screen->resource_create(screen, &templ);
292
_mesa_update_renderbuffer_surface(ctx, rb);
293
return rb->surface != NULL;
297
* Initialize the fields of a gl_renderbuffer to default values.
300
_mesa_init_renderbuffer(struct gl_renderbuffer *rb, GLuint name)
302
GET_CURRENT_CONTEXT(ctx);
307
rb->Delete = delete_renderbuffer;
309
/* The rest of these should be set later by the caller of this function or
310
* the AllocStorage method:
312
rb->AllocStorage = NULL;
318
/* In GL 3, the initial format is GL_RGBA according to Table 6.26
319
* on page 302 of the GL 3.3 spec.
321
* In GLES 3, the initial format is GL_RGBA4 according to Table 6.15
322
* on page 258 of the GLES 3.0.4 spec.
324
* If the context is current, set the initial format based on the
325
* specs. If the context is not current, we cannot determine the
326
* API, so default to GL_RGBA.
328
if (ctx && _mesa_is_gles(ctx)) {
329
rb->InternalFormat = GL_RGBA4;
331
rb->InternalFormat = GL_RGBA;
334
rb->Format = MESA_FORMAT_NONE;
336
rb->AllocStorage = renderbuffer_alloc_storage;
340
validate_and_init_renderbuffer_attachment(struct gl_framebuffer *fb,
341
gl_buffer_index bufferName,
342
struct gl_renderbuffer *rb)
346
assert(bufferName < BUFFER_COUNT);
348
/* There should be no previous renderbuffer on this attachment point,
349
* with the exception of depth/stencil since the same renderbuffer may
352
assert(bufferName == BUFFER_DEPTH ||
353
bufferName == BUFFER_STENCIL ||
354
fb->Attachment[bufferName].Renderbuffer == NULL);
356
/* winsys vs. user-created buffer cross check */
357
if (_mesa_is_user_fbo(fb)) {
364
fb->Attachment[bufferName].Type = GL_RENDERBUFFER_EXT;
365
fb->Attachment[bufferName].Complete = GL_TRUE;
370
* Attach a renderbuffer to a framebuffer.
371
* \param bufferName one of the BUFFER_x tokens
373
* This function avoids adding a reference and is therefore intended to be
374
* used with a freshly created renderbuffer.
377
_mesa_attach_and_own_rb(struct gl_framebuffer *fb,
378
gl_buffer_index bufferName,
379
struct gl_renderbuffer *rb)
381
assert(rb->RefCount == 1);
383
validate_and_init_renderbuffer_attachment(fb, bufferName, rb);
385
_mesa_reference_renderbuffer(&fb->Attachment[bufferName].Renderbuffer,
387
fb->Attachment[bufferName].Renderbuffer = rb;
391
* Attach a renderbuffer to a framebuffer.
392
* \param bufferName one of the BUFFER_x tokens
395
_mesa_attach_and_reference_rb(struct gl_framebuffer *fb,
396
gl_buffer_index bufferName,
397
struct gl_renderbuffer *rb)
399
validate_and_init_renderbuffer_attachment(fb, bufferName, rb);
400
_mesa_reference_renderbuffer(&fb->Attachment[bufferName].Renderbuffer, rb);
405
* Remove the named renderbuffer from the given framebuffer.
406
* \param bufferName one of the BUFFER_x tokens
409
_mesa_remove_renderbuffer(struct gl_framebuffer *fb,
410
gl_buffer_index bufferName)
412
assert(bufferName < BUFFER_COUNT);
413
_mesa_reference_renderbuffer(&fb->Attachment[bufferName].Renderbuffer,
419
* Set *ptr to point to rb. If *ptr points to another renderbuffer,
420
* dereference that buffer first. The new renderbuffer's refcount will
421
* be incremented. The old renderbuffer's refcount will be decremented.
422
* This is normally only called from the _mesa_reference_renderbuffer() macro
423
* when there's a real pointer change.
426
_mesa_reference_renderbuffer_(struct gl_renderbuffer **ptr,
427
struct gl_renderbuffer *rb)
430
/* Unreference the old renderbuffer */
431
struct gl_renderbuffer *oldRb = *ptr;
433
assert(oldRb->RefCount > 0);
435
if (p_atomic_dec_zero(&oldRb->RefCount)) {
436
GET_CURRENT_CONTEXT(ctx);
437
oldRb->Delete(ctx, oldRb);
442
/* reference new renderbuffer */
443
p_atomic_inc(&rb->RefCount);
450
_mesa_map_renderbuffer(struct gl_context *ctx,
451
struct gl_renderbuffer *rb,
452
GLuint x, GLuint y, GLuint w, GLuint h,
454
GLubyte **mapOut, GLint *rowStrideOut,
457
struct pipe_context *pipe = ctx->pipe;
458
const GLboolean invert = flip_y;
463
/* software-allocated renderbuffer (probably an accum buffer) */
465
GLint bpp = _mesa_get_format_bytes(rb->Format);
466
GLint stride = _mesa_format_row_stride(rb->Format,
468
*mapOut = (GLubyte *) rb->data + y * stride + x * bpp;
469
*rowStrideOut = stride;
478
/* Check for unexpected flags */
479
assert((mode & ~(GL_MAP_READ_BIT |
481
GL_MAP_INVALIDATE_RANGE_BIT)) == 0);
483
const enum pipe_map_flags transfer_flags =
484
_mesa_access_flags_to_transfer_flags(mode, false);
486
/* Note: y=0=bottom of buffer while y2=0=top of buffer.
487
* 'invert' will be true for window-system buffers and false for
488
* user-allocated renderbuffers and textures.
491
y2 = rb->Height - y - h;
495
map = pipe_texture_map(pipe,
497
rb->surface->u.tex.level,
498
rb->surface->u.tex.first_layer,
499
transfer_flags, x, y2, w, h, &rb->transfer);
502
*rowStrideOut = -(int) rb->transfer->stride;
503
map += (h - 1) * rb->transfer->stride;
506
*rowStrideOut = rb->transfer->stride;
517
_mesa_unmap_renderbuffer(struct gl_context *ctx,
518
struct gl_renderbuffer *rb)
520
struct pipe_context *pipe = ctx->pipe;
523
/* software-allocated renderbuffer (probably an accum buffer) */
527
pipe_texture_unmap(pipe, rb->transfer);
532
_mesa_regen_renderbuffer_surface(struct gl_context *ctx,
533
struct gl_renderbuffer *rb)
535
struct pipe_context *pipe = ctx->pipe;
536
struct pipe_resource *resource = rb->texture;
538
struct pipe_surface **psurf =
539
rb->surface_srgb ? &rb->surface_srgb : &rb->surface_linear;
540
struct pipe_surface *surf = *psurf;
541
/* create a new pipe_surface */
542
struct pipe_surface surf_tmpl;
543
memset(&surf_tmpl, 0, sizeof(surf_tmpl));
544
surf_tmpl.format = surf->format;
545
surf_tmpl.nr_samples = rb->rtt_nr_samples;
546
surf_tmpl.u.tex.level = surf->u.tex.level;
547
surf_tmpl.u.tex.first_layer = surf->u.tex.first_layer;
548
surf_tmpl.u.tex.last_layer = surf->u.tex.last_layer;
550
/* create -> destroy to avoid blowing up cached surfaces */
551
surf = pipe->create_surface(pipe, resource, &surf_tmpl);
552
pipe_surface_release(pipe, psurf);
555
rb->surface = *psurf;
559
* Create or update the pipe_surface of a FBO renderbuffer.
560
* This is usually called after st_finalize_texture.
563
_mesa_update_renderbuffer_surface(struct gl_context *ctx,
564
struct gl_renderbuffer *rb)
566
struct pipe_context *pipe = ctx->pipe;
567
struct pipe_resource *resource = rb->texture;
568
const struct gl_texture_object *stTexObj = NULL;
569
unsigned rtt_width = rb->Width;
570
unsigned rtt_height = rb->Height;
571
unsigned rtt_depth = rb->Depth;
574
* For winsys fbo, it is possible that the renderbuffer is sRGB-capable but
575
* the format of rb->texture is linear (because we have no control over
576
* the format). Check rb->Format instead of rb->texture->format
577
* to determine if the rb is sRGB-capable.
579
boolean enable_srgb = ctx->Color.sRGBEnabled &&
580
_mesa_is_format_srgb(rb->Format);
581
enum pipe_format format = resource->format;
584
stTexObj = rb->TexImage->TexObject;
585
if (stTexObj->surface_based)
586
format = stTexObj->surface_format;
589
format = enable_srgb ? util_format_srgb(format) : util_format_linear(format);
591
if (resource->target == PIPE_TEXTURE_1D_ARRAY) {
592
rtt_depth = rtt_height;
596
/* find matching mipmap level size */
598
for (level = 0; level <= resource->last_level; level++) {
599
if (u_minify(resource->width0, level) == rtt_width &&
600
u_minify(resource->height0, level) == rtt_height &&
601
(resource->target != PIPE_TEXTURE_3D ||
602
u_minify(resource->depth0, level) == rtt_depth)) {
606
assert(level <= resource->last_level);
608
/* determine the layer bounds */
609
unsigned first_layer, last_layer;
610
if (rb->rtt_layered) {
612
last_layer = util_max_layer(rb->texture, level);
616
last_layer = rb->rtt_face + rb->rtt_slice;
619
/* Adjust for texture views */
620
if (rb->is_rtt && resource->array_size > 1 &&
621
stTexObj->Immutable) {
622
const struct gl_texture_object *tex = stTexObj;
623
first_layer += tex->Attrib.MinLayer;
624
if (!rb->rtt_layered)
625
last_layer += tex->Attrib.MinLayer;
627
last_layer = MIN2(first_layer + tex->Attrib.NumLayers - 1,
631
struct pipe_surface **psurf =
632
enable_srgb ? &rb->surface_srgb : &rb->surface_linear;
633
struct pipe_surface *surf = *psurf;
636
surf->texture->nr_samples != rb->NumSamples ||
637
surf->texture->nr_storage_samples != rb->NumStorageSamples ||
638
surf->format != format ||
639
surf->texture != resource ||
640
surf->width != rtt_width ||
641
surf->height != rtt_height ||
642
surf->nr_samples != rb->rtt_nr_samples ||
643
surf->u.tex.level != level ||
644
surf->u.tex.first_layer != first_layer ||
645
surf->u.tex.last_layer != last_layer) {
646
/* create a new pipe_surface */
647
struct pipe_surface surf_tmpl;
648
memset(&surf_tmpl, 0, sizeof(surf_tmpl));
649
surf_tmpl.format = format;
650
surf_tmpl.nr_samples = rb->rtt_nr_samples;
651
surf_tmpl.u.tex.level = level;
652
surf_tmpl.u.tex.first_layer = first_layer;
653
surf_tmpl.u.tex.last_layer = last_layer;
655
/* create -> destroy to avoid blowing up cached surfaces */
656
struct pipe_surface *surf = pipe->create_surface(pipe, resource, &surf_tmpl);
657
pipe_surface_release(pipe, psurf);
660
rb->surface = *psurf;