• 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. [OpenGL ES 2.0.24] section 4.4 page 105.
17 
18 #include "Framebuffer.h"
19 
20 #include "main.h"
21 #include "Renderbuffer.h"
22 #include "Texture.h"
23 #include "utilities.h"
24 
25 #include <algorithm>
26 
27 namespace es2
28 {
29 
IsRenderbuffer(GLenum type)30 bool Framebuffer::IsRenderbuffer(GLenum type)
31 {
32 	return type == GL_RENDERBUFFER || type == GL_FRAMEBUFFER_DEFAULT;
33 }
34 
Framebuffer()35 Framebuffer::Framebuffer()
36 {
37 	readBuffer = GL_COLOR_ATTACHMENT0;
38 	drawBuffer[0] = GL_COLOR_ATTACHMENT0;
39 	for(int i = 1; i < MAX_COLOR_ATTACHMENTS; i++)
40 	{
41 		drawBuffer[i] = GL_NONE;
42 	}
43 
44 	for(int i = 0; i < MAX_COLOR_ATTACHMENTS; i++)
45 	{
46 		mColorbufferType[i] = GL_NONE;
47 		mColorbufferLayer[i] = 0;
48 	}
49 
50 	mDepthbufferType = GL_NONE;
51 	mDepthbufferLayer = 0;
52 	mStencilbufferType = GL_NONE;
53 	mStencilbufferLayer = 0;
54 }
55 
~Framebuffer()56 Framebuffer::~Framebuffer()
57 {
58 	for(int i = 0; i < MAX_COLOR_ATTACHMENTS; i++)
59 	{
60 		mColorbufferPointer[i] = nullptr;
61 	}
62 	mDepthbufferPointer = nullptr;
63 	mStencilbufferPointer = nullptr;
64 }
65 
lookupRenderbuffer(GLenum type,GLuint handle,GLint level) const66 Renderbuffer *Framebuffer::lookupRenderbuffer(GLenum type, GLuint handle, GLint level) const
67 {
68 	Context *context = getContextLocked();
69 	Renderbuffer *buffer = nullptr;
70 
71 	if(type == GL_NONE)
72 	{
73 		buffer = nullptr;
74 	}
75 	else if(IsRenderbuffer(type))
76 	{
77 		buffer = context->getRenderbuffer(handle);
78 	}
79 	else if(IsTextureTarget(type))
80 	{
81 		buffer = context->getTexture(handle)->getRenderbuffer(type, level);
82 	}
83 	else UNREACHABLE(type);
84 
85 	return buffer;
86 }
87 
setColorbuffer(GLenum type,GLuint colorbuffer,GLuint index,GLint level,GLint layer)88 void Framebuffer::setColorbuffer(GLenum type, GLuint colorbuffer, GLuint index, GLint level, GLint layer)
89 {
90 	mColorbufferType[index] = (colorbuffer != 0) ? type : GL_NONE;
91 	mColorbufferPointer[index] = lookupRenderbuffer(type, colorbuffer, level);
92 	mColorbufferLayer[index] = layer;
93 }
94 
setDepthbuffer(GLenum type,GLuint depthbuffer,GLint level,GLint layer)95 void Framebuffer::setDepthbuffer(GLenum type, GLuint depthbuffer, GLint level, GLint layer)
96 {
97 	mDepthbufferType = (depthbuffer != 0) ? type : GL_NONE;
98 	mDepthbufferPointer = lookupRenderbuffer(type, depthbuffer, level);
99 	mDepthbufferLayer = layer;
100 }
101 
setStencilbuffer(GLenum type,GLuint stencilbuffer,GLint level,GLint layer)102 void Framebuffer::setStencilbuffer(GLenum type, GLuint stencilbuffer, GLint level, GLint layer)
103 {
104 	mStencilbufferType = (stencilbuffer != 0) ? type : GL_NONE;
105 	mStencilbufferPointer = lookupRenderbuffer(type, stencilbuffer, level);
106 	mStencilbufferLayer = layer;
107 }
108 
setReadBuffer(GLenum buf)109 void Framebuffer::setReadBuffer(GLenum buf)
110 {
111 	readBuffer = buf;
112 }
113 
setDrawBuffer(GLuint index,GLenum buf)114 void Framebuffer::setDrawBuffer(GLuint index, GLenum buf)
115 {
116 	drawBuffer[index] = buf;
117 }
118 
getReadBuffer() const119 GLenum Framebuffer::getReadBuffer() const
120 {
121 	return readBuffer;
122 }
123 
getDrawBuffer(GLuint index) const124 GLenum Framebuffer::getDrawBuffer(GLuint index) const
125 {
126 	return drawBuffer[index];
127 }
128 
detachTexture(GLuint texture)129 void Framebuffer::detachTexture(GLuint texture)
130 {
131 	for(int i = 0; i < MAX_COLOR_ATTACHMENTS; i++)
132 	{
133 		if(mColorbufferPointer[i].name() == texture && IsTextureTarget(mColorbufferType[i]))
134 		{
135 			mColorbufferType[i] = GL_NONE;
136 			mColorbufferPointer[i] = nullptr;
137 		}
138 	}
139 
140 	if(mDepthbufferPointer.name() == texture && IsTextureTarget(mDepthbufferType))
141 	{
142 		mDepthbufferType = GL_NONE;
143 		mDepthbufferPointer = nullptr;
144 	}
145 
146 	if(mStencilbufferPointer.name() == texture && IsTextureTarget(mStencilbufferType))
147 	{
148 		mStencilbufferType = GL_NONE;
149 		mStencilbufferPointer = nullptr;
150 	}
151 }
152 
detachRenderbuffer(GLuint renderbuffer)153 void Framebuffer::detachRenderbuffer(GLuint renderbuffer)
154 {
155 	for(int i = 0; i < MAX_COLOR_ATTACHMENTS; i++)
156 	{
157 		if(mColorbufferPointer[i].name() == renderbuffer && IsRenderbuffer(mColorbufferType[i]))
158 		{
159 			mColorbufferType[i] = GL_NONE;
160 			mColorbufferPointer[i] = nullptr;
161 		}
162 	}
163 
164 	if(mDepthbufferPointer.name() == renderbuffer && IsRenderbuffer(mDepthbufferType))
165 	{
166 		mDepthbufferType = GL_NONE;
167 		mDepthbufferPointer = nullptr;
168 	}
169 
170 	if(mStencilbufferPointer.name() == renderbuffer && IsRenderbuffer(mStencilbufferType))
171 	{
172 		mStencilbufferType = GL_NONE;
173 		mStencilbufferPointer = nullptr;
174 	}
175 }
176 
177 // Increments refcount on surface.
178 // caller must Release() the returned surface
getRenderTarget(GLuint index)179 egl::Image *Framebuffer::getRenderTarget(GLuint index)
180 {
181 	if(index < MAX_COLOR_ATTACHMENTS)
182 	{
183 		Renderbuffer *colorbuffer = mColorbufferPointer[index];
184 
185 		if(colorbuffer)
186 		{
187 			return colorbuffer->getRenderTarget();
188 		}
189 	}
190 
191 	return nullptr;
192 }
193 
getReadRenderTarget()194 egl::Image *Framebuffer::getReadRenderTarget()
195 {
196 	return getRenderTarget(getReadBufferIndex());
197 }
198 
199 // Increments refcount on surface.
200 // caller must Release() the returned surface
getDepthBuffer()201 egl::Image *Framebuffer::getDepthBuffer()
202 {
203 	Renderbuffer *depthbuffer = mDepthbufferPointer;
204 
205 	if(depthbuffer)
206 	{
207 		return depthbuffer->getRenderTarget();
208 	}
209 
210 	return nullptr;
211 }
212 
213 // Increments refcount on surface.
214 // caller must Release() the returned surface
getStencilBuffer()215 egl::Image *Framebuffer::getStencilBuffer()
216 {
217 	Renderbuffer *stencilbuffer = mStencilbufferPointer;
218 
219 	if(stencilbuffer)
220 	{
221 		return stencilbuffer->getRenderTarget();
222 	}
223 
224 	return nullptr;
225 }
226 
getColorbuffer(GLuint index) const227 Renderbuffer *Framebuffer::getColorbuffer(GLuint index) const
228 {
229 	return (index < MAX_COLOR_ATTACHMENTS) ? mColorbufferPointer[index] : (Renderbuffer*)nullptr;
230 }
231 
getReadColorbuffer() const232 Renderbuffer *Framebuffer::getReadColorbuffer() const
233 {
234 	return getColorbuffer(getReadBufferIndex());
235 }
236 
getDepthbuffer() const237 Renderbuffer *Framebuffer::getDepthbuffer() const
238 {
239 	return mDepthbufferPointer;
240 }
241 
getStencilbuffer() const242 Renderbuffer *Framebuffer::getStencilbuffer() const
243 {
244 	return mStencilbufferPointer;
245 }
246 
getReadBufferType()247 GLenum Framebuffer::getReadBufferType()
248 {
249 	if(readBuffer == GL_NONE)
250 	{
251 		return GL_NONE;
252 	}
253 
254 	return mColorbufferType[getReadBufferIndex()];
255 }
256 
getColorbufferType(GLuint index)257 GLenum Framebuffer::getColorbufferType(GLuint index)
258 {
259 	return mColorbufferType[index];
260 }
261 
getDepthbufferType()262 GLenum Framebuffer::getDepthbufferType()
263 {
264 	return mDepthbufferType;
265 }
266 
getStencilbufferType()267 GLenum Framebuffer::getStencilbufferType()
268 {
269 	return mStencilbufferType;
270 }
271 
getColorbufferName(GLuint index)272 GLuint Framebuffer::getColorbufferName(GLuint index)
273 {
274 	return mColorbufferPointer[index].name();
275 }
276 
getDepthbufferName()277 GLuint Framebuffer::getDepthbufferName()
278 {
279 	return mDepthbufferPointer.name();
280 }
281 
getStencilbufferName()282 GLuint Framebuffer::getStencilbufferName()
283 {
284 	return mStencilbufferPointer.name();
285 }
286 
getColorbufferLayer(GLuint index)287 GLint Framebuffer::getColorbufferLayer(GLuint index)
288 {
289 	return mColorbufferLayer[index];
290 }
291 
getDepthbufferLayer()292 GLint Framebuffer::getDepthbufferLayer()
293 {
294 	return mDepthbufferLayer;
295 }
296 
getStencilbufferLayer()297 GLint Framebuffer::getStencilbufferLayer()
298 {
299 	return mStencilbufferLayer;
300 }
301 
hasStencil()302 bool Framebuffer::hasStencil()
303 {
304 	if(mStencilbufferType != GL_NONE)
305 	{
306 		Renderbuffer *stencilbufferObject = getStencilbuffer();
307 
308 		if(stencilbufferObject)
309 		{
310 			return stencilbufferObject->getStencilSize() > 0;
311 		}
312 	}
313 
314 	return false;
315 }
316 
completeness()317 GLenum Framebuffer::completeness()
318 {
319 	int width;
320 	int height;
321 	int samples;
322 
323 	return completeness(width, height, samples);
324 }
325 
completeness(int & width,int & height,int & samples)326 GLenum Framebuffer::completeness(int &width, int &height, int &samples)
327 {
328 	width = -1;
329 	height = -1;
330 	samples = -1;
331 
332 	for(int i = 0; i < MAX_COLOR_ATTACHMENTS; i++)
333 	{
334 		if(mColorbufferType[i] != GL_NONE)
335 		{
336 			Renderbuffer *colorbuffer = getColorbuffer(i);
337 
338 			if(!colorbuffer)
339 			{
340 				return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
341 			}
342 
343 			if(colorbuffer->getWidth() == 0 || colorbuffer->getHeight() == 0 || (colorbuffer->getDepth() <= mColorbufferLayer[i]))
344 			{
345 				return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
346 			}
347 
348 			if(IsRenderbuffer(mColorbufferType[i]))
349 			{
350 				if(!IsColorRenderable(colorbuffer->getFormat()))
351 				{
352 					return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
353 				}
354 			}
355 			else if(IsTextureTarget(mColorbufferType[i]))
356 			{
357 				GLint format = colorbuffer->getFormat();
358 
359 				if(!IsColorRenderable(format))
360 				{
361 					return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
362 				}
363 
364 				if(IsDepthTexture(format) || IsStencilTexture(format))
365 				{
366 					return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
367 				}
368 			}
369 			else
370 			{
371 				UNREACHABLE(mColorbufferType[i]);
372 				return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
373 			}
374 
375 			if(width == -1 || height == -1)
376 			{
377 				width = colorbuffer->getWidth();
378 				height = colorbuffer->getHeight();
379 				samples = colorbuffer->getSamples();
380 			}
381 			else
382 			{
383 				if(samples != colorbuffer->getSamples())
384 				{
385 					return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
386 				}
387 
388 				width = std::min(width, colorbuffer->getWidth());
389 				height = std::min(height, colorbuffer->getHeight());
390 			}
391 		}
392 	}
393 
394 	Renderbuffer *depthbuffer = nullptr;
395 	Renderbuffer *stencilbuffer = nullptr;
396 
397 	if(mDepthbufferType != GL_NONE)
398 	{
399 		depthbuffer = getDepthbuffer();
400 
401 		if(!depthbuffer)
402 		{
403 			return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
404 		}
405 
406 		if(depthbuffer->getWidth() == 0 || depthbuffer->getHeight() == 0 || (depthbuffer->getDepth() <= mDepthbufferLayer))
407 		{
408 			return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
409 		}
410 
411 		if(IsRenderbuffer(mDepthbufferType))
412 		{
413 			if(!es2::IsDepthRenderable(depthbuffer->getFormat()))
414 			{
415 				return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
416 			}
417 		}
418 		else if(IsTextureTarget(mDepthbufferType))
419 		{
420 			if(!es2::IsDepthTexture(depthbuffer->getFormat()))
421 			{
422 				return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
423 			}
424 		}
425 		else
426 		{
427 			UNREACHABLE(mDepthbufferType);
428 			return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
429 		}
430 
431 		if(width == -1 || height == -1)
432 		{
433 			width = depthbuffer->getWidth();
434 			height = depthbuffer->getHeight();
435 			samples = depthbuffer->getSamples();
436 		}
437 		else
438 		{
439 			if(samples != depthbuffer->getSamples())
440 			{
441 				return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
442 			}
443 
444 			width = std::min(width, depthbuffer->getWidth());
445 			height = std::min(height, depthbuffer->getHeight());
446 		}
447 	}
448 
449 	if(mStencilbufferType != GL_NONE)
450 	{
451 		stencilbuffer = getStencilbuffer();
452 
453 		if(!stencilbuffer)
454 		{
455 			return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
456 		}
457 
458 		if(stencilbuffer->getWidth() == 0 || stencilbuffer->getHeight() == 0 || (stencilbuffer->getDepth() <= mStencilbufferLayer))
459 		{
460 			return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
461 		}
462 
463 		if(IsRenderbuffer(mStencilbufferType))
464 		{
465 			if(!es2::IsStencilRenderable(stencilbuffer->getFormat()))
466 			{
467 				return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
468 			}
469 		}
470 		else if(IsTextureTarget(mStencilbufferType))
471 		{
472 			GLenum internalformat = stencilbuffer->getFormat();
473 
474 			if(!es2::IsStencilTexture(internalformat))
475 			{
476 				return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
477 			}
478 		}
479 		else
480 		{
481 			UNREACHABLE(mStencilbufferType);
482 			return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
483 		}
484 
485 		if(width == -1 || height == -1)
486 		{
487 			width = stencilbuffer->getWidth();
488 			height = stencilbuffer->getHeight();
489 			samples = stencilbuffer->getSamples();
490 		}
491 		else
492 		{
493 			if(samples != stencilbuffer->getSamples())
494 			{
495 				return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
496 			}
497 
498 			width = std::min(width, stencilbuffer->getWidth());
499 			height = std::min(height, stencilbuffer->getHeight());
500 		}
501 	}
502 
503 	if(depthbuffer && stencilbuffer && (depthbuffer != stencilbuffer))
504 	{
505 		// In the GLES 3.0 spec, section 4.4.4, Framebuffer Completeness:
506 		// "The framebuffer object target is said to be framebuffer complete if all the following conditions are true:
507 		//  [...]
508 		//  Depth and stencil attachments, if present, are the same image.
509 		//  { FRAMEBUFFER_UNSUPPORTED }"
510 		return GL_FRAMEBUFFER_UNSUPPORTED;
511 	}
512 
513 	// We need to have at least one attachment to be complete
514 	if(width == -1 || height == -1)
515 	{
516 		return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
517 	}
518 
519 	return GL_FRAMEBUFFER_COMPLETE;
520 }
521 
getImplementationColorReadFormat() const522 GLenum Framebuffer::getImplementationColorReadFormat() const
523 {
524 	Renderbuffer *colorbuffer = getReadColorbuffer();
525 
526 	if(colorbuffer)
527 	{
528 		switch(colorbuffer->getFormat())
529 		{
530 		case GL_BGRA8_EXT:      return GL_BGRA_EXT;
531 		case GL_RGBA4:          return GL_RGBA;
532 		case GL_RGB5_A1:        return GL_RGBA;
533 		case GL_RGBA8:          return GL_RGBA;
534 		case GL_RGB565:         return GL_RGBA;
535 		case GL_RGB8:           return GL_RGB;
536 		case GL_R8:             return GL_RED;
537 		case GL_RG8:            return GL_RG;
538 		case GL_R8I:            return GL_RED_INTEGER;
539 		case GL_RG8I:           return GL_RG_INTEGER;
540 		case GL_RGB8I:          return GL_RGB_INTEGER;
541 		case GL_RGBA8I:         return GL_RGBA_INTEGER;
542 		case GL_R8UI:           return GL_RED_INTEGER;
543 		case GL_RG8UI:          return GL_RG_INTEGER;
544 		case GL_RGB8UI:         return GL_RGB_INTEGER;
545 		case GL_RGBA8UI:        return GL_RGBA_INTEGER;
546 		case GL_R16I:           return GL_RED_INTEGER;
547 		case GL_RG16I:          return GL_RG_INTEGER;
548 		case GL_RGB16I:         return GL_RGB_INTEGER;
549 		case GL_RGBA16I:        return GL_RGBA_INTEGER;
550 		case GL_R16UI:          return GL_RED_INTEGER;
551 		case GL_RG16UI:         return GL_RG_INTEGER;
552 		case GL_RGB16UI:        return GL_RGB_INTEGER;
553 		case GL_RGB10_A2UI:     return GL_RGBA_INTEGER;
554 		case GL_RGBA16UI:       return GL_RGBA_INTEGER;
555 		case GL_R32I:           return GL_RED_INTEGER;
556 		case GL_RG32I:          return GL_RG_INTEGER;
557 		case GL_RGB32I:         return GL_RGB_INTEGER;
558 		case GL_RGBA32I:        return GL_RGBA_INTEGER;
559 		case GL_R32UI:          return GL_RED_INTEGER;
560 		case GL_RG32UI:         return GL_RG_INTEGER;
561 		case GL_RGB32UI:        return GL_RGB_INTEGER;
562 		case GL_RGBA32UI:       return GL_RGBA_INTEGER;
563 		case GL_R16F:           return GL_RED;
564 		case GL_RG16F:          return GL_RG;
565 		case GL_R11F_G11F_B10F: return GL_RGB;
566 		case GL_RGB16F:         return GL_RGB;
567 		case GL_RGBA16F:        return GL_RGBA;
568 		case GL_R32F:           return GL_RED;
569 		case GL_RG32F:          return GL_RG;
570 		case GL_RGB32F:         return GL_RGB;
571 		case GL_RGBA32F:        return GL_RGBA;
572 		case GL_RGB10_A2:       return GL_RGBA;
573 		case GL_SRGB8:          return GL_RGB;
574 		case GL_SRGB8_ALPHA8:   return GL_RGBA;
575 		default:
576 			UNREACHABLE(colorbuffer->getFormat());
577 		}
578 	}
579 
580 	return GL_RGBA;
581 }
582 
getImplementationColorReadType() const583 GLenum Framebuffer::getImplementationColorReadType() const
584 {
585 	Renderbuffer *colorbuffer = getReadColorbuffer();
586 
587 	if(colorbuffer)
588 	{
589 		switch(colorbuffer->getFormat())
590 		{
591 		case GL_BGRA8_EXT:      return GL_UNSIGNED_BYTE;
592 		case GL_RGBA4:          return GL_UNSIGNED_SHORT_4_4_4_4;
593 		case GL_RGB5_A1:        return GL_UNSIGNED_SHORT_5_5_5_1;
594 		case GL_RGBA8:          return GL_UNSIGNED_BYTE;
595 		case GL_RGB565:         return GL_UNSIGNED_SHORT_5_6_5;
596 		case GL_RGB8:           return GL_UNSIGNED_BYTE;
597 		case GL_R8:             return GL_UNSIGNED_BYTE;
598 		case GL_RG8:            return GL_UNSIGNED_BYTE;
599 		case GL_R8I:            return GL_INT;
600 		case GL_RG8I:           return GL_INT;
601 		case GL_RGB8I:          return GL_INT;
602 		case GL_RGBA8I:         return GL_INT;
603 		case GL_R8UI:           return GL_UNSIGNED_BYTE;
604 		case GL_RG8UI:          return GL_UNSIGNED_BYTE;
605 		case GL_RGB8UI:         return GL_UNSIGNED_BYTE;
606 		case GL_RGBA8UI:        return GL_UNSIGNED_BYTE;
607 		case GL_R16I:           return GL_INT;
608 		case GL_RG16I:          return GL_INT;
609 		case GL_RGB16I:         return GL_INT;
610 		case GL_RGBA16I:        return GL_INT;
611 		case GL_R16UI:          return GL_UNSIGNED_INT;
612 		case GL_RG16UI:         return GL_UNSIGNED_INT;
613 		case GL_RGB16UI:        return GL_UNSIGNED_INT;
614 		case GL_RGB10_A2UI:     return GL_UNSIGNED_INT_2_10_10_10_REV;
615 		case GL_RGBA16UI:       return GL_UNSIGNED_INT;
616 		case GL_R32I:           return GL_INT;
617 		case GL_RG32I:          return GL_INT;
618 		case GL_RGB32I:         return GL_INT;
619 		case GL_RGBA32I:        return GL_INT;
620 		case GL_R32UI:          return GL_UNSIGNED_INT;
621 		case GL_RG32UI:         return GL_UNSIGNED_INT;
622 		case GL_RGB32UI:        return GL_UNSIGNED_INT;
623 		case GL_RGBA32UI:       return GL_UNSIGNED_INT;
624 		case GL_R16F:           return GL_HALF_FLOAT;
625 		case GL_RG16F:          return GL_HALF_FLOAT;
626 		case GL_R11F_G11F_B10F: return GL_HALF_FLOAT;
627 		case GL_RGB16F:         return GL_HALF_FLOAT;
628 		case GL_RGBA16F:        return GL_HALF_FLOAT;
629 		case GL_R32F:           return GL_FLOAT;
630 		case GL_RG32F:          return GL_FLOAT;
631 		case GL_RGB32F:         return GL_FLOAT;
632 		case GL_RGBA32F:        return GL_FLOAT;
633 		case GL_RGB10_A2:       return GL_UNSIGNED_INT_2_10_10_10_REV;
634 		case GL_SRGB8:          return GL_UNSIGNED_BYTE;
635 		case GL_SRGB8_ALPHA8:   return GL_UNSIGNED_BYTE;
636 		default:
637 			UNREACHABLE(colorbuffer->getFormat());
638 		}
639 	}
640 
641 	return GL_UNSIGNED_BYTE;
642 }
643 
getDepthReadFormat() const644 GLenum Framebuffer::getDepthReadFormat() const
645 {
646 	Renderbuffer *depthbuffer = getDepthbuffer();
647 
648 	if(depthbuffer)
649 	{
650 		// There is only one depth read format.
651 		return GL_DEPTH_COMPONENT;
652 	}
653 
654 	// If there is no depth buffer, GL_INVALID_OPERATION occurs.
655 	return GL_NONE;
656 }
657 
getDepthReadType() const658 GLenum Framebuffer::getDepthReadType() const
659 {
660 	Renderbuffer *depthbuffer = getDepthbuffer();
661 
662 	if(depthbuffer)
663 	{
664 		switch(depthbuffer->getFormat())
665 		{
666 		case GL_DEPTH_COMPONENT16:     return GL_UNSIGNED_SHORT;
667 		case GL_DEPTH_COMPONENT24:     return GL_UNSIGNED_INT;
668 		case GL_DEPTH_COMPONENT32_OES: return GL_UNSIGNED_INT;
669 		case GL_DEPTH_COMPONENT32F:    return GL_FLOAT;
670 		case GL_DEPTH24_STENCIL8:      return GL_UNSIGNED_INT_24_8_OES;
671 		case GL_DEPTH32F_STENCIL8:     return GL_FLOAT_32_UNSIGNED_INT_24_8_REV;
672 		default:
673 			UNREACHABLE(depthbuffer->getFormat());
674 		}
675 	}
676 
677 	// If there is no depth buffer, GL_INVALID_OPERATION occurs.
678 	return GL_NONE;
679 }
680 
getReadBufferIndex() const681 GLuint Framebuffer::getReadBufferIndex() const
682 {
683 	switch(readBuffer)
684 	{
685 	case GL_BACK:
686 		return 0;
687 	case GL_NONE:
688 		return GL_INVALID_INDEX;
689 	default:
690 		return readBuffer - GL_COLOR_ATTACHMENT0;
691 	}
692 }
693 
DefaultFramebuffer()694 DefaultFramebuffer::DefaultFramebuffer()
695 {
696 	readBuffer = GL_BACK;
697 	drawBuffer[0] = GL_BACK;
698 }
699 
DefaultFramebuffer(Colorbuffer * colorbuffer,DepthStencilbuffer * depthStencil)700 DefaultFramebuffer::DefaultFramebuffer(Colorbuffer *colorbuffer, DepthStencilbuffer *depthStencil)
701 {
702 	GLenum defaultRenderbufferType = GL_FRAMEBUFFER_DEFAULT;
703 	mColorbufferPointer[0] = new Renderbuffer(0, colorbuffer);
704 	mColorbufferType[0] = defaultRenderbufferType;
705 
706 	readBuffer = GL_BACK;
707 	drawBuffer[0] = GL_BACK;
708 	for(int i = 1; i < MAX_COLOR_ATTACHMENTS; i++)
709 	{
710 		mColorbufferPointer[i] = nullptr;
711 		mColorbufferType[i] = GL_NONE;
712 	}
713 
714 	Renderbuffer *depthStencilRenderbuffer = new Renderbuffer(0, depthStencil);
715 	mDepthbufferPointer = depthStencilRenderbuffer;
716 	mStencilbufferPointer = depthStencilRenderbuffer;
717 
718 	mDepthbufferType = (depthStencilRenderbuffer->getDepthSize() != 0) ? GL_FRAMEBUFFER_DEFAULT : GL_NONE;
719 	mStencilbufferType = (depthStencilRenderbuffer->getStencilSize() != 0) ? GL_FRAMEBUFFER_DEFAULT : GL_NONE;
720 }
721 
722 }
723