1 /*
2 * Mesa 3-D graphics library
3 *
4 * Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
5 *
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:
12 *
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
15 *
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.
23 */
24
25
26 #include "glheader.h"
27
28 #include "context.h"
29 #include "fbobject.h"
30 #include "formats.h"
31 #include "mtypes.h"
32 #include "renderbuffer.h"
33 #include "util/u_memory.h"
34
35
36 /**
37 * Initialize the fields of a gl_renderbuffer to default values.
38 */
39 void
_mesa_init_renderbuffer(struct gl_renderbuffer * rb,GLuint name)40 _mesa_init_renderbuffer(struct gl_renderbuffer *rb, GLuint name)
41 {
42 GET_CURRENT_CONTEXT(ctx);
43
44 rb->ClassID = 0;
45 rb->Name = name;
46 rb->RefCount = 1;
47 rb->Delete = _mesa_delete_renderbuffer;
48
49 /* The rest of these should be set later by the caller of this function or
50 * the AllocStorage method:
51 */
52 rb->AllocStorage = NULL;
53
54 rb->Width = 0;
55 rb->Height = 0;
56 rb->Depth = 0;
57
58 /* In GL 3, the initial format is GL_RGBA according to Table 6.26
59 * on page 302 of the GL 3.3 spec.
60 *
61 * In GLES 3, the initial format is GL_RGBA4 according to Table 6.15
62 * on page 258 of the GLES 3.0.4 spec.
63 *
64 * If the context is current, set the initial format based on the
65 * specs. If the context is not current, we cannot determine the
66 * API, so default to GL_RGBA.
67 */
68 if (ctx && _mesa_is_gles(ctx)) {
69 rb->InternalFormat = GL_RGBA4;
70 } else {
71 rb->InternalFormat = GL_RGBA;
72 }
73
74 rb->Format = MESA_FORMAT_NONE;
75 }
76
77
78 /**
79 * Allocate a new gl_renderbuffer object. This can be used for user-created
80 * renderbuffers or window-system renderbuffers.
81 */
82 struct gl_renderbuffer *
_mesa_new_renderbuffer(struct gl_context * ctx,GLuint name)83 _mesa_new_renderbuffer(struct gl_context *ctx, GLuint name)
84 {
85 struct gl_renderbuffer *rb = CALLOC_STRUCT(gl_renderbuffer);
86 if (rb) {
87 _mesa_init_renderbuffer(rb, name);
88 }
89 return rb;
90 }
91
92
93 /**
94 * Delete a gl_framebuffer.
95 * This is the default function for renderbuffer->Delete().
96 * Drivers which subclass gl_renderbuffer should probably implement their
97 * own delete function. But the driver might also call this function to
98 * free the object in the end.
99 */
100 void
_mesa_delete_renderbuffer(struct gl_context * ctx,struct gl_renderbuffer * rb)101 _mesa_delete_renderbuffer(struct gl_context *ctx, struct gl_renderbuffer *rb)
102 {
103 free(rb->Label);
104 free(rb);
105 }
106
107 static void
validate_and_init_renderbuffer_attachment(struct gl_framebuffer * fb,gl_buffer_index bufferName,struct gl_renderbuffer * rb)108 validate_and_init_renderbuffer_attachment(struct gl_framebuffer *fb,
109 gl_buffer_index bufferName,
110 struct gl_renderbuffer *rb)
111 {
112 assert(fb);
113 assert(rb);
114 assert(bufferName < BUFFER_COUNT);
115
116 /* There should be no previous renderbuffer on this attachment point,
117 * with the exception of depth/stencil since the same renderbuffer may
118 * be used for both.
119 */
120 assert(bufferName == BUFFER_DEPTH ||
121 bufferName == BUFFER_STENCIL ||
122 fb->Attachment[bufferName].Renderbuffer == NULL);
123
124 /* winsys vs. user-created buffer cross check */
125 if (_mesa_is_user_fbo(fb)) {
126 assert(rb->Name);
127 }
128 else {
129 assert(!rb->Name);
130 }
131
132 fb->Attachment[bufferName].Type = GL_RENDERBUFFER_EXT;
133 fb->Attachment[bufferName].Complete = GL_TRUE;
134 }
135
136
137 /**
138 * Attach a renderbuffer to a framebuffer.
139 * \param bufferName one of the BUFFER_x tokens
140 *
141 * This function avoids adding a reference and is therefore intended to be
142 * used with a freshly created renderbuffer.
143 */
144 void
_mesa_attach_and_own_rb(struct gl_framebuffer * fb,gl_buffer_index bufferName,struct gl_renderbuffer * rb)145 _mesa_attach_and_own_rb(struct gl_framebuffer *fb,
146 gl_buffer_index bufferName,
147 struct gl_renderbuffer *rb)
148 {
149 assert(rb->RefCount == 1);
150
151 validate_and_init_renderbuffer_attachment(fb, bufferName, rb);
152
153 _mesa_reference_renderbuffer(&fb->Attachment[bufferName].Renderbuffer,
154 NULL);
155 fb->Attachment[bufferName].Renderbuffer = rb;
156 }
157
158 /**
159 * Attach a renderbuffer to a framebuffer.
160 * \param bufferName one of the BUFFER_x tokens
161 */
162 void
_mesa_attach_and_reference_rb(struct gl_framebuffer * fb,gl_buffer_index bufferName,struct gl_renderbuffer * rb)163 _mesa_attach_and_reference_rb(struct gl_framebuffer *fb,
164 gl_buffer_index bufferName,
165 struct gl_renderbuffer *rb)
166 {
167 validate_and_init_renderbuffer_attachment(fb, bufferName, rb);
168 _mesa_reference_renderbuffer(&fb->Attachment[bufferName].Renderbuffer, rb);
169 }
170
171
172 /**
173 * Remove the named renderbuffer from the given framebuffer.
174 * \param bufferName one of the BUFFER_x tokens
175 */
176 void
_mesa_remove_renderbuffer(struct gl_framebuffer * fb,gl_buffer_index bufferName)177 _mesa_remove_renderbuffer(struct gl_framebuffer *fb,
178 gl_buffer_index bufferName)
179 {
180 assert(bufferName < BUFFER_COUNT);
181 _mesa_reference_renderbuffer(&fb->Attachment[bufferName].Renderbuffer,
182 NULL);
183 }
184
185
186 /**
187 * Set *ptr to point to rb. If *ptr points to another renderbuffer,
188 * dereference that buffer first. The new renderbuffer's refcount will
189 * be incremented. The old renderbuffer's refcount will be decremented.
190 * This is normally only called from the _mesa_reference_renderbuffer() macro
191 * when there's a real pointer change.
192 */
193 void
_mesa_reference_renderbuffer_(struct gl_renderbuffer ** ptr,struct gl_renderbuffer * rb)194 _mesa_reference_renderbuffer_(struct gl_renderbuffer **ptr,
195 struct gl_renderbuffer *rb)
196 {
197 if (*ptr) {
198 /* Unreference the old renderbuffer */
199 struct gl_renderbuffer *oldRb = *ptr;
200
201 assert(oldRb->RefCount > 0);
202
203 if (p_atomic_dec_zero(&oldRb->RefCount)) {
204 GET_CURRENT_CONTEXT(ctx);
205 oldRb->Delete(ctx, oldRb);
206 }
207 }
208
209 if (rb) {
210 /* reference new renderbuffer */
211 p_atomic_inc(&rb->RefCount);
212 }
213
214 *ptr = rb;
215 }
216