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 = getContext();
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 	GLint version = egl::getClientVersion();
333 
334 	for(int i = 0; i < MAX_COLOR_ATTACHMENTS; i++)
335 	{
336 		if(mColorbufferType[i] != GL_NONE)
337 		{
338 			Renderbuffer *colorbuffer = getColorbuffer(i);
339 
340 			if(!colorbuffer)
341 			{
342 				return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
343 			}
344 
345 			if(colorbuffer->getWidth() == 0 || colorbuffer->getHeight() == 0 || (colorbuffer->getDepth() <= mColorbufferLayer[i]))
346 			{
347 				return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
348 			}
349 
350 			if(IsRenderbuffer(mColorbufferType[i]))
351 			{
352 				if(!IsColorRenderable(colorbuffer->getFormat(), version))
353 				{
354 					return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
355 				}
356 			}
357 			else if(IsTextureTarget(mColorbufferType[i]))
358 			{
359 				GLenum format = colorbuffer->getFormat();
360 
361 				if(!IsColorRenderable(format, version))
362 				{
363 					return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
364 				}
365 
366 				if(IsDepthTexture(format) || IsStencilTexture(format))
367 				{
368 					return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
369 				}
370 			}
371 			else
372 			{
373 				UNREACHABLE(mColorbufferType[i]);
374 				return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
375 			}
376 
377 			if(width == -1 || height == -1)
378 			{
379 				width = colorbuffer->getWidth();
380 				height = colorbuffer->getHeight();
381 				samples = colorbuffer->getSamples();
382 			}
383 			else
384 			{
385 				if(version < 3 && (width != colorbuffer->getWidth() || height != colorbuffer->getHeight()))
386 				{
387 					return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
388 				}
389 
390 				if(samples != colorbuffer->getSamples())
391 				{
392 					return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
393 				}
394 
395 				width = std::min(width, colorbuffer->getWidth());
396 				height = std::min(height, colorbuffer->getHeight());
397 			}
398 		}
399 	}
400 
401 	Renderbuffer *depthbuffer = nullptr;
402 	Renderbuffer *stencilbuffer = nullptr;
403 
404 	if(mDepthbufferType != GL_NONE)
405 	{
406 		depthbuffer = getDepthbuffer();
407 
408 		if(!depthbuffer)
409 		{
410 			return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
411 		}
412 
413 		if(depthbuffer->getWidth() == 0 || depthbuffer->getHeight() == 0 || (depthbuffer->getDepth() <= mDepthbufferLayer))
414 		{
415 			return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
416 		}
417 
418 		if(IsRenderbuffer(mDepthbufferType))
419 		{
420 			if(!es2::IsDepthRenderable(depthbuffer->getFormat(), version))
421 			{
422 				return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
423 			}
424 		}
425 		else if(IsTextureTarget(mDepthbufferType))
426 		{
427 			if(!es2::IsDepthTexture(depthbuffer->getFormat()))
428 			{
429 				return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
430 			}
431 		}
432 		else
433 		{
434 			UNREACHABLE(mDepthbufferType);
435 			return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
436 		}
437 
438 		if(width == -1 || height == -1)
439 		{
440 			width = depthbuffer->getWidth();
441 			height = depthbuffer->getHeight();
442 			samples = depthbuffer->getSamples();
443 		}
444 		else
445 		{
446 			if(version < 3 && (width != depthbuffer->getWidth() || height != depthbuffer->getHeight()))
447 			{
448 				return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
449 			}
450 
451 			if(samples != depthbuffer->getSamples())
452 			{
453 				return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
454 			}
455 
456 			width = std::min(width, depthbuffer->getWidth());
457 			height = std::min(height, depthbuffer->getHeight());
458 		}
459 	}
460 
461 	if(mStencilbufferType != GL_NONE)
462 	{
463 		stencilbuffer = getStencilbuffer();
464 
465 		if(!stencilbuffer)
466 		{
467 			return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
468 		}
469 
470 		if(stencilbuffer->getWidth() == 0 || stencilbuffer->getHeight() == 0 || (stencilbuffer->getDepth() <= mStencilbufferLayer))
471 		{
472 			return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
473 		}
474 
475 		if(IsRenderbuffer(mStencilbufferType))
476 		{
477 			if(!es2::IsStencilRenderable(stencilbuffer->getFormat(), version))
478 			{
479 				return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
480 			}
481 		}
482 		else if(IsTextureTarget(mStencilbufferType))
483 		{
484 			GLenum internalformat = stencilbuffer->getFormat();
485 
486 			if(!es2::IsStencilTexture(internalformat))
487 			{
488 				return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
489 			}
490 		}
491 		else
492 		{
493 			UNREACHABLE(mStencilbufferType);
494 			return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
495 		}
496 
497 		if(width == -1 || height == -1)
498 		{
499 			width = stencilbuffer->getWidth();
500 			height = stencilbuffer->getHeight();
501 			samples = stencilbuffer->getSamples();
502 		}
503 		else
504 		{
505 			if(version < 3 && (width != stencilbuffer->getWidth() || height != stencilbuffer->getHeight()))
506 			{
507 				return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
508 			}
509 
510 			if(samples != stencilbuffer->getSamples())
511 			{
512 				return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
513 			}
514 
515 			width = std::min(width, stencilbuffer->getWidth());
516 			height = std::min(height, stencilbuffer->getHeight());
517 		}
518 	}
519 
520 	if((version >= 3) && depthbuffer && stencilbuffer && (depthbuffer != stencilbuffer))
521 	{
522 		// In the GLES 3.0 spec, section 4.4.4, Framebuffer Completeness:
523 		// "The framebuffer object target is said to be framebuffer complete if all the following conditions are true:
524 		//  [...]
525 		//  Depth and stencil attachments, if present, are the same image.
526 		//  { FRAMEBUFFER_UNSUPPORTED }"
527 		return GL_FRAMEBUFFER_UNSUPPORTED;
528 	}
529 
530 	// We need to have at least one attachment to be complete
531 	if(width == -1 || height == -1)
532 	{
533 		return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
534 	}
535 
536 	return GL_FRAMEBUFFER_COMPLETE;
537 }
538 
getImplementationColorReadFormat() const539 GLenum Framebuffer::getImplementationColorReadFormat() const
540 {
541 	Renderbuffer *colorbuffer = getReadColorbuffer();
542 
543 	if(colorbuffer)
544 	{
545 		switch(colorbuffer->getFormat())
546 		{
547 		case GL_BGRA8_EXT:      return GL_BGRA_EXT;
548 		case GL_RGBA4:          return GL_RGBA;
549 		case GL_RGB5_A1:        return GL_RGBA;
550 		case GL_RGBA8:          return GL_RGBA;
551 		case GL_RGB565:         return GL_RGBA;
552 		case GL_RGB8:           return GL_RGB;
553 		case GL_R8:             return GL_RED;
554 		case GL_RG8:            return GL_RG;
555 		case GL_R8I:            return GL_RED_INTEGER;
556 		case GL_RG8I:           return GL_RG_INTEGER;
557 		case GL_RGB8I:          return GL_RGB_INTEGER;
558 		case GL_RGBA8I:         return GL_RGBA_INTEGER;
559 		case GL_R8UI:           return GL_RED_INTEGER;
560 		case GL_RG8UI:          return GL_RG_INTEGER;
561 		case GL_RGB8UI:         return GL_RGB_INTEGER;
562 		case GL_RGBA8UI:        return GL_RGBA_INTEGER;
563 		case GL_R16I:           return GL_RED_INTEGER;
564 		case GL_RG16I:          return GL_RG_INTEGER;
565 		case GL_RGB16I:         return GL_RGB_INTEGER;
566 		case GL_RGBA16I:        return GL_RGBA_INTEGER;
567 		case GL_R16UI:          return GL_RED_INTEGER;
568 		case GL_RG16UI:         return GL_RG_INTEGER;
569 		case GL_RGB16UI:        return GL_RGB_INTEGER;
570 		case GL_RGB10_A2UI:     return GL_RGBA_INTEGER;
571 		case GL_RGBA16UI:       return GL_RGBA_INTEGER;
572 		case GL_R32I:           return GL_RED_INTEGER;
573 		case GL_RG32I:          return GL_RG_INTEGER;
574 		case GL_RGB32I:         return GL_RGB_INTEGER;
575 		case GL_RGBA32I:        return GL_RGBA_INTEGER;
576 		case GL_R32UI:          return GL_RED_INTEGER;
577 		case GL_RG32UI:         return GL_RG_INTEGER;
578 		case GL_RGB32UI:        return GL_RGB_INTEGER;
579 		case GL_RGBA32UI:       return GL_RGBA_INTEGER;
580 		case GL_R16F:           return GL_RED;
581 		case GL_RG16F:          return GL_RG;
582 		case GL_R11F_G11F_B10F: return GL_RGB;
583 		case GL_RGB16F:         return GL_RGB;
584 		case GL_RGBA16F:        return GL_RGBA;
585 		case GL_R32F:           return GL_RED;
586 		case GL_RG32F:          return GL_RG;
587 		case GL_RGB32F:         return GL_RGB;
588 		case GL_RGBA32F:        return GL_RGBA;
589 		case GL_RGB10_A2:       return GL_RGBA;
590 		case GL_SRGB8:          return GL_RGB;
591 		case GL_SRGB8_ALPHA8:   return GL_RGBA;
592 		default:
593 			UNREACHABLE(colorbuffer->getFormat());
594 		}
595 	}
596 
597 	return GL_RGBA;
598 }
599 
getImplementationColorReadType() const600 GLenum Framebuffer::getImplementationColorReadType() const
601 {
602 	Renderbuffer *colorbuffer = getReadColorbuffer();
603 
604 	if(colorbuffer)
605 	{
606 		switch(colorbuffer->getFormat())
607 		{
608 		case GL_BGRA8_EXT:      return GL_UNSIGNED_BYTE;
609 		case GL_RGBA4:          return GL_UNSIGNED_SHORT_4_4_4_4;
610 		case GL_RGB5_A1:        return GL_UNSIGNED_SHORT_5_5_5_1;
611 		case GL_RGBA8:          return GL_UNSIGNED_BYTE;
612 		case GL_RGB565:         return GL_UNSIGNED_SHORT_5_6_5;
613 		case GL_RGB8:           return GL_UNSIGNED_BYTE;
614 		case GL_R8:             return GL_UNSIGNED_BYTE;
615 		case GL_RG8:            return GL_UNSIGNED_BYTE;
616 		case GL_R8I:            return GL_INT;
617 		case GL_RG8I:           return GL_INT;
618 		case GL_RGB8I:          return GL_INT;
619 		case GL_RGBA8I:         return GL_INT;
620 		case GL_R8UI:           return GL_UNSIGNED_BYTE;
621 		case GL_RG8UI:          return GL_UNSIGNED_BYTE;
622 		case GL_RGB8UI:         return GL_UNSIGNED_BYTE;
623 		case GL_RGBA8UI:        return GL_UNSIGNED_BYTE;
624 		case GL_R16I:           return GL_INT;
625 		case GL_RG16I:          return GL_INT;
626 		case GL_RGB16I:         return GL_INT;
627 		case GL_RGBA16I:        return GL_INT;
628 		case GL_R16UI:          return GL_UNSIGNED_INT;
629 		case GL_RG16UI:         return GL_UNSIGNED_INT;
630 		case GL_RGB16UI:        return GL_UNSIGNED_INT;
631 		case GL_RGB10_A2UI:     return GL_UNSIGNED_INT_2_10_10_10_REV;
632 		case GL_RGBA16UI:       return GL_UNSIGNED_INT;
633 		case GL_R32I:           return GL_INT;
634 		case GL_RG32I:          return GL_INT;
635 		case GL_RGB32I:         return GL_INT;
636 		case GL_RGBA32I:        return GL_INT;
637 		case GL_R32UI:          return GL_UNSIGNED_INT;
638 		case GL_RG32UI:         return GL_UNSIGNED_INT;
639 		case GL_RGB32UI:        return GL_UNSIGNED_INT;
640 		case GL_RGBA32UI:       return GL_UNSIGNED_INT;
641 		case GL_R16F:           return GL_FLOAT;
642 		case GL_RG16F:          return GL_FLOAT;
643 		case GL_R11F_G11F_B10F: return GL_FLOAT;
644 		case GL_RGB16F:         return GL_FLOAT;
645 		case GL_RGBA16F:        return GL_FLOAT;
646 		case GL_R32F:           return GL_FLOAT;
647 		case GL_RG32F:          return GL_FLOAT;
648 		case GL_RGB32F:         return GL_FLOAT;
649 		case GL_RGBA32F:        return GL_FLOAT;
650 		case GL_RGB10_A2:       return GL_UNSIGNED_INT_2_10_10_10_REV;
651 		case GL_SRGB8:          return GL_UNSIGNED_BYTE;
652 		case GL_SRGB8_ALPHA8:   return GL_UNSIGNED_BYTE;
653 		default:
654 			UNREACHABLE(colorbuffer->getFormat());
655 		}
656 	}
657 
658 	return GL_UNSIGNED_BYTE;
659 }
660 
getDepthReadFormat() const661 GLenum Framebuffer::getDepthReadFormat() const
662 {
663 	Renderbuffer *depthbuffer = getDepthbuffer();
664 
665 	if(depthbuffer)
666 	{
667 		// There is only one depth read format.
668 		return GL_DEPTH_COMPONENT;
669 	}
670 
671 	// If there is no depth buffer, GL_INVALID_OPERATION occurs.
672 	return GL_NONE;
673 }
674 
getDepthReadType() const675 GLenum Framebuffer::getDepthReadType() const
676 {
677 	Renderbuffer *depthbuffer = getDepthbuffer();
678 
679 	if(depthbuffer)
680 	{
681 		switch(depthbuffer->getFormat())
682 		{
683 		case GL_DEPTH_COMPONENT16:     return GL_UNSIGNED_SHORT;
684 		case GL_DEPTH_COMPONENT24:     return GL_UNSIGNED_INT;
685 		case GL_DEPTH_COMPONENT32_OES: return GL_UNSIGNED_INT;
686 		case GL_DEPTH_COMPONENT32F:    return GL_FLOAT;
687 		case GL_DEPTH24_STENCIL8:      return GL_UNSIGNED_INT_24_8_OES;
688 		case GL_DEPTH32F_STENCIL8:     return GL_FLOAT;
689 		default:
690 			UNREACHABLE(depthbuffer->getFormat());
691 		}
692 	}
693 
694 	// If there is no depth buffer, GL_INVALID_OPERATION occurs.
695 	return GL_NONE;
696 }
697 
getReadBufferIndex() const698 GLuint Framebuffer::getReadBufferIndex() const
699 {
700 	switch(readBuffer)
701 	{
702 	case GL_BACK:
703 		return 0;
704 	case GL_NONE:
705 		return GL_INVALID_INDEX;
706 	default:
707 		return readBuffer - GL_COLOR_ATTACHMENT0;
708 	}
709 }
710 
DefaultFramebuffer()711 DefaultFramebuffer::DefaultFramebuffer()
712 {
713 	readBuffer = GL_BACK;
714 	drawBuffer[0] = GL_BACK;
715 }
716 
DefaultFramebuffer(Colorbuffer * colorbuffer,DepthStencilbuffer * depthStencil)717 DefaultFramebuffer::DefaultFramebuffer(Colorbuffer *colorbuffer, DepthStencilbuffer *depthStencil)
718 {
719 	GLenum defaultRenderbufferType = egl::getClientVersion() < 3 ? GL_RENDERBUFFER : GL_FRAMEBUFFER_DEFAULT;
720 	mColorbufferPointer[0] = new Renderbuffer(0, colorbuffer);
721 	mColorbufferType[0] = defaultRenderbufferType;
722 
723 	readBuffer = GL_BACK;
724 	drawBuffer[0] = GL_BACK;
725 	for(int i = 1; i < MAX_COLOR_ATTACHMENTS; i++)
726 	{
727 		mColorbufferPointer[i] = nullptr;
728 		mColorbufferType[i] = GL_NONE;
729 	}
730 
731 	Renderbuffer *depthStencilRenderbuffer = new Renderbuffer(0, depthStencil);
732 	mDepthbufferPointer = depthStencilRenderbuffer;
733 	mStencilbufferPointer = depthStencilRenderbuffer;
734 
735 	mDepthbufferType = (depthStencilRenderbuffer->getDepthSize() != 0) ? defaultRenderbufferType : GL_NONE;
736 	mStencilbufferType = (depthStencilRenderbuffer->getStencilSize() != 0) ? defaultRenderbufferType : GL_NONE;
737 }
738 
739 }
740