• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2016 The SwiftShader Authors. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //    http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 // Framebuffer.cpp: Implements the Framebuffer class. Implements GL framebuffer
16 // objects and related functionality.
17 
18 #include "Framebuffer.h"
19 
20 #include "main.h"
21 #include "Renderbuffer.h"
22 #include "Texture.h"
23 #include "utilities.h"
24 
25 namespace gl
26 {
27 
Framebuffer()28 Framebuffer::Framebuffer()
29 {
30 	mColorbufferType = GL_NONE;
31 	mDepthbufferType = GL_NONE;
32 	mStencilbufferType = GL_NONE;
33 }
34 
~Framebuffer()35 Framebuffer::~Framebuffer()
36 {
37 	mColorbufferPointer = nullptr;
38 	mDepthbufferPointer = nullptr;
39 	mStencilbufferPointer = nullptr;
40 }
41 
lookupRenderbuffer(GLenum type,GLuint handle) const42 Renderbuffer *Framebuffer::lookupRenderbuffer(GLenum type, GLuint handle) const
43 {
44 	Context *context = getContext();
45 	Renderbuffer *buffer = nullptr;
46 
47 	if(type == GL_NONE)
48 	{
49 		buffer = nullptr;
50 	}
51 	else if(type == GL_RENDERBUFFER)
52 	{
53 		buffer = context->getRenderbuffer(handle);
54 	}
55 	else if(IsTextureTarget(type))
56 	{
57 		buffer = context->getTexture(handle)->getRenderbuffer(type);
58 	}
59 	else UNREACHABLE(type);
60 
61 	return buffer;
62 }
63 
setColorbuffer(GLenum type,GLuint colorbuffer)64 void Framebuffer::setColorbuffer(GLenum type, GLuint colorbuffer)
65 {
66 	mColorbufferType = (colorbuffer != 0) ? type : GL_NONE;
67 	mColorbufferPointer = lookupRenderbuffer(type, colorbuffer);
68 }
69 
setDepthbuffer(GLenum type,GLuint depthbuffer)70 void Framebuffer::setDepthbuffer(GLenum type, GLuint depthbuffer)
71 {
72 	mDepthbufferType = (depthbuffer != 0) ? type : GL_NONE;
73 	mDepthbufferPointer = lookupRenderbuffer(type, depthbuffer);
74 }
75 
setStencilbuffer(GLenum type,GLuint stencilbuffer)76 void Framebuffer::setStencilbuffer(GLenum type, GLuint stencilbuffer)
77 {
78 	mStencilbufferType = (stencilbuffer != 0) ? type : GL_NONE;
79 	mStencilbufferPointer = lookupRenderbuffer(type, stencilbuffer);
80 }
81 
detachTexture(GLuint texture)82 void Framebuffer::detachTexture(GLuint texture)
83 {
84 	if(mColorbufferPointer.name() == texture && IsTextureTarget(mColorbufferType))
85 	{
86 		mColorbufferType = GL_NONE;
87 		mColorbufferPointer = nullptr;
88 	}
89 
90 	if(mDepthbufferPointer.name() == texture && IsTextureTarget(mDepthbufferType))
91 	{
92 		mDepthbufferType = GL_NONE;
93 		mDepthbufferPointer = nullptr;
94 	}
95 
96 	if(mStencilbufferPointer.name() == texture && IsTextureTarget(mStencilbufferType))
97 	{
98 		mStencilbufferType = GL_NONE;
99 		mStencilbufferPointer = nullptr;
100 	}
101 }
102 
detachRenderbuffer(GLuint renderbuffer)103 void Framebuffer::detachRenderbuffer(GLuint renderbuffer)
104 {
105 	if(mColorbufferPointer.name() == renderbuffer && mColorbufferType == GL_RENDERBUFFER)
106 	{
107 		mColorbufferType = GL_NONE;
108 		mColorbufferPointer = nullptr;
109 	}
110 
111 	if(mDepthbufferPointer.name() == renderbuffer && mDepthbufferType == GL_RENDERBUFFER)
112 	{
113 		mDepthbufferType = GL_NONE;
114 		mDepthbufferPointer = nullptr;
115 	}
116 
117 	if(mStencilbufferPointer.name() == renderbuffer && mStencilbufferType == GL_RENDERBUFFER)
118 	{
119 		mStencilbufferType = GL_NONE;
120 		mStencilbufferPointer = nullptr;
121 	}
122 }
123 
124 // Increments refcount on surface.
125 // caller must Release() the returned surface
getRenderTarget()126 Image *Framebuffer::getRenderTarget()
127 {
128 	Renderbuffer *colorbuffer = mColorbufferPointer;
129 
130 	if(colorbuffer)
131 	{
132 		return colorbuffer->getRenderTarget();
133 	}
134 
135 	return nullptr;
136 }
137 
138 // Increments refcount on surface.
139 // caller must Release() the returned surface
getDepthStencil()140 Image *Framebuffer::getDepthStencil()
141 {
142 	Renderbuffer *depthstencilbuffer = mDepthbufferPointer;
143 
144 	if(!depthstencilbuffer)
145 	{
146 		depthstencilbuffer = mStencilbufferPointer;
147 	}
148 
149 	if(depthstencilbuffer)
150 	{
151 		return depthstencilbuffer->getRenderTarget();
152 	}
153 
154 	return nullptr;
155 }
156 
getColorbuffer()157 Renderbuffer *Framebuffer::getColorbuffer()
158 {
159 	return mColorbufferPointer;
160 }
161 
getDepthbuffer()162 Renderbuffer *Framebuffer::getDepthbuffer()
163 {
164 	return mDepthbufferPointer;
165 }
166 
getStencilbuffer()167 Renderbuffer *Framebuffer::getStencilbuffer()
168 {
169 	return mStencilbufferPointer;
170 }
171 
getColorbufferType()172 GLenum Framebuffer::getColorbufferType()
173 {
174 	return mColorbufferType;
175 }
176 
getDepthbufferType()177 GLenum Framebuffer::getDepthbufferType()
178 {
179 	return mDepthbufferType;
180 }
181 
getStencilbufferType()182 GLenum Framebuffer::getStencilbufferType()
183 {
184 	return mStencilbufferType;
185 }
186 
getColorbufferName()187 GLuint Framebuffer::getColorbufferName()
188 {
189 	return mColorbufferPointer.name();
190 }
191 
getDepthbufferName()192 GLuint Framebuffer::getDepthbufferName()
193 {
194 	return mDepthbufferPointer.name();
195 }
196 
getStencilbufferName()197 GLuint Framebuffer::getStencilbufferName()
198 {
199 	return mStencilbufferPointer.name();
200 }
201 
hasStencil()202 bool Framebuffer::hasStencil()
203 {
204 	if(mStencilbufferType != GL_NONE)
205 	{
206 		Renderbuffer *stencilbufferObject = getStencilbuffer();
207 
208 		if(stencilbufferObject)
209 		{
210 			return stencilbufferObject->getStencilSize() > 0;
211 		}
212 	}
213 
214 	return false;
215 }
216 
completeness()217 GLenum Framebuffer::completeness()
218 {
219 	int width;
220 	int height;
221 	int samples;
222 
223 	return completeness(width, height, samples);
224 }
225 
completeness(int & width,int & height,int & samples)226 GLenum Framebuffer::completeness(int &width, int &height, int &samples)
227 {
228 	width = -1;
229 	height = -1;
230 	samples = -1;
231 
232 	if(mColorbufferType != GL_NONE)
233 	{
234 		Renderbuffer *colorbuffer = getColorbuffer();
235 
236 		if(!colorbuffer)
237 		{
238 			return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
239 		}
240 
241 		if(colorbuffer->getWidth() == 0 || colorbuffer->getHeight() == 0)
242 		{
243 			return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
244 		}
245 
246 		if(mColorbufferType == GL_RENDERBUFFER)
247 		{
248 			if(!gl::IsColorRenderable(colorbuffer->getFormat()))
249 			{
250 				return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
251 			}
252 		}
253 		else if(IsTextureTarget(mColorbufferType))
254 		{
255 			GLenum format = colorbuffer->getFormat();
256 
257 			if(IsCompressed(format) ||
258 			   format == GL_ALPHA ||
259 			   format == GL_LUMINANCE ||
260 			   format == GL_LUMINANCE_ALPHA)
261 			{
262 				return GL_FRAMEBUFFER_UNSUPPORTED;
263 			}
264 
265 			if(gl::IsDepthTexture(format) || gl::IsStencilTexture(format))
266 			{
267 				return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
268 			}
269 		}
270 		else
271 		{
272 			UNREACHABLE(mColorbufferType);
273 			return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
274 		}
275 
276 		width = colorbuffer->getWidth();
277 		height = colorbuffer->getHeight();
278 		samples = colorbuffer->getSamples();
279 	}
280 
281 	Renderbuffer *depthbuffer = nullptr;
282 	Renderbuffer *stencilbuffer = nullptr;
283 
284 	if(mDepthbufferType != GL_NONE)
285 	{
286 		depthbuffer = getDepthbuffer();
287 
288 		if(!depthbuffer)
289 		{
290 			return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
291 		}
292 
293 		if(depthbuffer->getWidth() == 0 || depthbuffer->getHeight() == 0)
294 		{
295 			return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
296 		}
297 
298 		if(mDepthbufferType == GL_RENDERBUFFER)
299 		{
300 			if(!gl::IsDepthRenderable(depthbuffer->getFormat()))
301 			{
302 				return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
303 			}
304 		}
305 		else if(IsTextureTarget(mDepthbufferType))
306 		{
307 			if(!gl::IsDepthTexture(depthbuffer->getFormat()))
308 			{
309 				return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
310 			}
311 		}
312 		else
313 		{
314 			UNREACHABLE(mDepthbufferType);
315 			return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
316 		}
317 
318 		if(width == -1 || height == -1)
319 		{
320 			width = depthbuffer->getWidth();
321 			height = depthbuffer->getHeight();
322 			samples = depthbuffer->getSamples();
323 		}
324 		else if(width != depthbuffer->getWidth() || height != depthbuffer->getHeight())
325 		{
326 			return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT;
327 		}
328 		else if(samples != depthbuffer->getSamples())
329 		{
330 			return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT;
331 		}
332 	}
333 
334 	if(mStencilbufferType != GL_NONE)
335 	{
336 		stencilbuffer = getStencilbuffer();
337 
338 		if(!stencilbuffer)
339 		{
340 			return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
341 		}
342 
343 		if(stencilbuffer->getWidth() == 0 || stencilbuffer->getHeight() == 0)
344 		{
345 			return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
346 		}
347 
348 		if(mStencilbufferType == GL_RENDERBUFFER)
349 		{
350 			if(!gl::IsStencilRenderable(stencilbuffer->getFormat()))
351 			{
352 				return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
353 			}
354 		}
355 		else if(IsTextureTarget(mStencilbufferType))
356 		{
357 			GLenum internalformat = stencilbuffer->getFormat();
358 
359 			if(!gl::IsStencilTexture(internalformat))
360 			{
361 				return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
362 			}
363 		}
364 		else
365 		{
366 			UNREACHABLE(mStencilbufferType);
367 			return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
368 		}
369 
370 		if(width == -1 || height == -1)
371 		{
372 			width = stencilbuffer->getWidth();
373 			height = stencilbuffer->getHeight();
374 			samples = stencilbuffer->getSamples();
375 		}
376 		else if(width != stencilbuffer->getWidth() || height != stencilbuffer->getHeight())
377 		{
378 			return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT;
379 		}
380 		else if(samples != stencilbuffer->getSamples())
381 		{
382 			return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT;
383 		}
384 	}
385 
386 	// If we have both a depth and stencil buffer, they must refer to the same object
387 	// since we only support packed_depth_stencil and not separate depth and stencil
388 	if(depthbuffer && stencilbuffer && (depthbuffer != stencilbuffer))
389 	{
390 		return GL_FRAMEBUFFER_UNSUPPORTED;
391 	}
392 
393 	// We need to have at least one attachment to be complete
394 	if(width == -1 || height == -1)
395 	{
396 		return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
397 	}
398 
399 	return GL_FRAMEBUFFER_COMPLETE;
400 }
401 
DefaultFramebuffer(Colorbuffer * colorbuffer,DepthStencilbuffer * depthStencil)402 DefaultFramebuffer::DefaultFramebuffer(Colorbuffer *colorbuffer, DepthStencilbuffer *depthStencil)
403 {
404 	mColorbufferPointer = new Renderbuffer(0, colorbuffer);
405 
406 	Renderbuffer *depthStencilRenderbuffer = new Renderbuffer(0, depthStencil);
407 	mDepthbufferPointer = depthStencilRenderbuffer;
408 	mStencilbufferPointer = depthStencilRenderbuffer;
409 
410 	mColorbufferType = GL_RENDERBUFFER;
411 	mDepthbufferType = (depthStencilRenderbuffer->getDepthSize() != 0) ? GL_RENDERBUFFER : GL_NONE;
412 	mStencilbufferType = (depthStencilRenderbuffer->getStencilSize() != 0) ? GL_RENDERBUFFER : GL_NONE;
413 }
414 
completeness()415 GLenum DefaultFramebuffer::completeness()
416 {
417 	// The default framebuffer should always be complete
418 	ASSERT(Framebuffer::completeness() == GL_FRAMEBUFFER_COMPLETE);
419 
420 	return GL_FRAMEBUFFER_COMPLETE;
421 }
422 
423 }
424