1848b8605Smrg/* 2848b8605Smrg * Mesa 3-D graphics library 3848b8605Smrg * 4848b8605Smrg * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. 5848b8605Smrg * 6848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a 7848b8605Smrg * copy of this software and associated documentation files (the "Software"), 8848b8605Smrg * to deal in the Software without restriction, including without limitation 9848b8605Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10848b8605Smrg * and/or sell copies of the Software, and to permit persons to whom the 11848b8605Smrg * Software is furnished to do so, subject to the following conditions: 12848b8605Smrg * 13848b8605Smrg * The above copyright notice and this permission notice shall be included 14848b8605Smrg * in all copies or substantial portions of the Software. 15848b8605Smrg * 16848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 17848b8605Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18848b8605Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19848b8605Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20848b8605Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21848b8605Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22848b8605Smrg * OTHER DEALINGS IN THE SOFTWARE. 23848b8605Smrg */ 24848b8605Smrg 25848b8605Smrg 26848b8605Smrg#include "glheader.h" 27848b8605Smrg#include "imports.h" 28848b8605Smrg#include "context.h" 29848b8605Smrg#include "fbobject.h" 30848b8605Smrg#include "formats.h" 31848b8605Smrg#include "mtypes.h" 32848b8605Smrg#include "renderbuffer.h" 33848b8605Smrg 34848b8605Smrg 35848b8605Smrg/** 36848b8605Smrg * Initialize the fields of a gl_renderbuffer to default values. 37848b8605Smrg */ 38848b8605Smrgvoid 39848b8605Smrg_mesa_init_renderbuffer(struct gl_renderbuffer *rb, GLuint name) 40848b8605Smrg{ 41b8e80941Smrg GET_CURRENT_CONTEXT(ctx); 42b8e80941Smrg 43b8e80941Smrg simple_mtx_init(&rb->Mutex, mtx_plain); 44848b8605Smrg 45848b8605Smrg rb->ClassID = 0; 46848b8605Smrg rb->Name = name; 47b8e80941Smrg rb->RefCount = 1; 48848b8605Smrg rb->Delete = _mesa_delete_renderbuffer; 49848b8605Smrg 50848b8605Smrg /* The rest of these should be set later by the caller of this function or 51848b8605Smrg * the AllocStorage method: 52848b8605Smrg */ 53848b8605Smrg rb->AllocStorage = NULL; 54848b8605Smrg 55848b8605Smrg rb->Width = 0; 56848b8605Smrg rb->Height = 0; 57848b8605Smrg rb->Depth = 0; 58b8e80941Smrg 59b8e80941Smrg /* In GL 3, the initial format is GL_RGBA according to Table 6.26 60b8e80941Smrg * on page 302 of the GL 3.3 spec. 61b8e80941Smrg * 62b8e80941Smrg * In GLES 3, the initial format is GL_RGBA4 according to Table 6.15 63b8e80941Smrg * on page 258 of the GLES 3.0.4 spec. 64b8e80941Smrg * 65b8e80941Smrg * If the context is current, set the initial format based on the 66b8e80941Smrg * specs. If the context is not current, we cannot determine the 67b8e80941Smrg * API, so default to GL_RGBA. 68b8e80941Smrg */ 69b8e80941Smrg if (ctx && _mesa_is_gles(ctx)) { 70b8e80941Smrg rb->InternalFormat = GL_RGBA4; 71b8e80941Smrg } else { 72b8e80941Smrg rb->InternalFormat = GL_RGBA; 73b8e80941Smrg } 74b8e80941Smrg 75848b8605Smrg rb->Format = MESA_FORMAT_NONE; 76848b8605Smrg} 77848b8605Smrg 78848b8605Smrg 79848b8605Smrg/** 80848b8605Smrg * Allocate a new gl_renderbuffer object. This can be used for user-created 81848b8605Smrg * renderbuffers or window-system renderbuffers. 82848b8605Smrg */ 83848b8605Smrgstruct gl_renderbuffer * 84848b8605Smrg_mesa_new_renderbuffer(struct gl_context *ctx, GLuint name) 85848b8605Smrg{ 86848b8605Smrg struct gl_renderbuffer *rb = CALLOC_STRUCT(gl_renderbuffer); 87848b8605Smrg if (rb) { 88848b8605Smrg _mesa_init_renderbuffer(rb, name); 89848b8605Smrg } 90848b8605Smrg return rb; 91848b8605Smrg} 92848b8605Smrg 93848b8605Smrg 94848b8605Smrg/** 95848b8605Smrg * Delete a gl_framebuffer. 96848b8605Smrg * This is the default function for renderbuffer->Delete(). 97848b8605Smrg * Drivers which subclass gl_renderbuffer should probably implement their 98848b8605Smrg * own delete function. But the driver might also call this function to 99848b8605Smrg * free the object in the end. 100848b8605Smrg */ 101848b8605Smrgvoid 102848b8605Smrg_mesa_delete_renderbuffer(struct gl_context *ctx, struct gl_renderbuffer *rb) 103848b8605Smrg{ 104b8e80941Smrg simple_mtx_destroy(&rb->Mutex); 105848b8605Smrg free(rb->Label); 106848b8605Smrg free(rb); 107848b8605Smrg} 108848b8605Smrg 109b8e80941Smrgstatic void 110b8e80941Smrgvalidate_and_init_renderbuffer_attachment(struct gl_framebuffer *fb, 111b8e80941Smrg gl_buffer_index bufferName, 112b8e80941Smrg struct gl_renderbuffer *rb) 113848b8605Smrg{ 114848b8605Smrg assert(fb); 115848b8605Smrg assert(rb); 116848b8605Smrg assert(bufferName < BUFFER_COUNT); 117848b8605Smrg 118848b8605Smrg /* There should be no previous renderbuffer on this attachment point, 119848b8605Smrg * with the exception of depth/stencil since the same renderbuffer may 120848b8605Smrg * be used for both. 121848b8605Smrg */ 122848b8605Smrg assert(bufferName == BUFFER_DEPTH || 123848b8605Smrg bufferName == BUFFER_STENCIL || 124848b8605Smrg fb->Attachment[bufferName].Renderbuffer == NULL); 125848b8605Smrg 126848b8605Smrg /* winsys vs. user-created buffer cross check */ 127848b8605Smrg if (_mesa_is_user_fbo(fb)) { 128848b8605Smrg assert(rb->Name); 129848b8605Smrg } 130848b8605Smrg else { 131848b8605Smrg assert(!rb->Name); 132848b8605Smrg } 133848b8605Smrg 134848b8605Smrg fb->Attachment[bufferName].Type = GL_RENDERBUFFER_EXT; 135848b8605Smrg fb->Attachment[bufferName].Complete = GL_TRUE; 136b8e80941Smrg} 137b8e80941Smrg 138b8e80941Smrg 139b8e80941Smrg/** 140b8e80941Smrg * Attach a renderbuffer to a framebuffer. 141b8e80941Smrg * \param bufferName one of the BUFFER_x tokens 142b8e80941Smrg * 143b8e80941Smrg * This function avoids adding a reference and is therefore intended to be 144b8e80941Smrg * used with a freshly created renderbuffer. 145b8e80941Smrg */ 146b8e80941Smrgvoid 147b8e80941Smrg_mesa_attach_and_own_rb(struct gl_framebuffer *fb, 148b8e80941Smrg gl_buffer_index bufferName, 149b8e80941Smrg struct gl_renderbuffer *rb) 150b8e80941Smrg{ 151b8e80941Smrg assert(rb->RefCount == 1); 152b8e80941Smrg 153b8e80941Smrg validate_and_init_renderbuffer_attachment(fb, bufferName, rb); 154b8e80941Smrg 155b8e80941Smrg _mesa_reference_renderbuffer(&fb->Attachment[bufferName].Renderbuffer, 156b8e80941Smrg NULL); 157b8e80941Smrg fb->Attachment[bufferName].Renderbuffer = rb; 158b8e80941Smrg} 159b8e80941Smrg 160b8e80941Smrg/** 161b8e80941Smrg * Attach a renderbuffer to a framebuffer. 162b8e80941Smrg * \param bufferName one of the BUFFER_x tokens 163b8e80941Smrg */ 164b8e80941Smrgvoid 165b8e80941Smrg_mesa_attach_and_reference_rb(struct gl_framebuffer *fb, 166b8e80941Smrg gl_buffer_index bufferName, 167b8e80941Smrg struct gl_renderbuffer *rb) 168b8e80941Smrg{ 169b8e80941Smrg validate_and_init_renderbuffer_attachment(fb, bufferName, rb); 170848b8605Smrg _mesa_reference_renderbuffer(&fb->Attachment[bufferName].Renderbuffer, rb); 171848b8605Smrg} 172848b8605Smrg 173848b8605Smrg 174848b8605Smrg/** 175848b8605Smrg * Remove the named renderbuffer from the given framebuffer. 176848b8605Smrg * \param bufferName one of the BUFFER_x tokens 177848b8605Smrg */ 178848b8605Smrgvoid 179848b8605Smrg_mesa_remove_renderbuffer(struct gl_framebuffer *fb, 180848b8605Smrg gl_buffer_index bufferName) 181848b8605Smrg{ 182848b8605Smrg assert(bufferName < BUFFER_COUNT); 183848b8605Smrg _mesa_reference_renderbuffer(&fb->Attachment[bufferName].Renderbuffer, 184848b8605Smrg NULL); 185848b8605Smrg} 186848b8605Smrg 187848b8605Smrg 188848b8605Smrg/** 189848b8605Smrg * Set *ptr to point to rb. If *ptr points to another renderbuffer, 190848b8605Smrg * dereference that buffer first. The new renderbuffer's refcount will 191848b8605Smrg * be incremented. The old renderbuffer's refcount will be decremented. 192848b8605Smrg * This is normally only called from the _mesa_reference_renderbuffer() macro 193848b8605Smrg * when there's a real pointer change. 194848b8605Smrg */ 195848b8605Smrgvoid 196848b8605Smrg_mesa_reference_renderbuffer_(struct gl_renderbuffer **ptr, 197848b8605Smrg struct gl_renderbuffer *rb) 198848b8605Smrg{ 199848b8605Smrg if (*ptr) { 200848b8605Smrg /* Unreference the old renderbuffer */ 201848b8605Smrg GLboolean deleteFlag = GL_FALSE; 202848b8605Smrg struct gl_renderbuffer *oldRb = *ptr; 203848b8605Smrg 204b8e80941Smrg simple_mtx_lock(&oldRb->Mutex); 205b8e80941Smrg assert(oldRb->RefCount > 0); 206848b8605Smrg oldRb->RefCount--; 207848b8605Smrg deleteFlag = (oldRb->RefCount == 0); 208b8e80941Smrg simple_mtx_unlock(&oldRb->Mutex); 209848b8605Smrg 210848b8605Smrg if (deleteFlag) { 211848b8605Smrg GET_CURRENT_CONTEXT(ctx); 212848b8605Smrg oldRb->Delete(ctx, oldRb); 213848b8605Smrg } 214848b8605Smrg 215848b8605Smrg *ptr = NULL; 216848b8605Smrg } 217848b8605Smrg assert(!*ptr); 218848b8605Smrg 219848b8605Smrg if (rb) { 220848b8605Smrg /* reference new renderbuffer */ 221b8e80941Smrg simple_mtx_lock(&rb->Mutex); 222848b8605Smrg rb->RefCount++; 223b8e80941Smrg simple_mtx_unlock(&rb->Mutex); 224848b8605Smrg *ptr = rb; 225848b8605Smrg } 226848b8605Smrg} 227