Home | History | Annotate | Download | only in libGLESv2
      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 
     30 bool Framebuffer::IsRenderbuffer(GLenum type)
     31 {
     32 	return type == GL_RENDERBUFFER || type == GL_FRAMEBUFFER_DEFAULT;
     33 }
     34 
     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 
     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 
     66 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 
     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 
     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 
    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 
    109 void Framebuffer::setReadBuffer(GLenum buf)
    110 {
    111 	readBuffer = buf;
    112 }
    113 
    114 void Framebuffer::setDrawBuffer(GLuint index, GLenum buf)
    115 {
    116 	drawBuffer[index] = buf;
    117 }
    118 
    119 GLenum Framebuffer::getReadBuffer() const
    120 {
    121 	return readBuffer;
    122 }
    123 
    124 GLenum Framebuffer::getDrawBuffer(GLuint index) const
    125 {
    126 	return drawBuffer[index];
    127 }
    128 
    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 
    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
    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 
    194 egl::Image *Framebuffer::getReadRenderTarget()
    195 {
    196 	return getRenderTarget(getReadBufferIndex());
    197 }
    198 
    199 // Increments refcount on surface.
    200 // caller must Release() the returned surface
    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
    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 
    227 Renderbuffer *Framebuffer::getColorbuffer(GLuint index) const
    228 {
    229 	return (index < MAX_COLOR_ATTACHMENTS) ? mColorbufferPointer[index] : (Renderbuffer*)nullptr;
    230 }
    231 
    232 Renderbuffer *Framebuffer::getReadColorbuffer() const
    233 {
    234 	return getColorbuffer(getReadBufferIndex());
    235 }
    236 
    237 Renderbuffer *Framebuffer::getDepthbuffer() const
    238 {
    239 	return mDepthbufferPointer;
    240 }
    241 
    242 Renderbuffer *Framebuffer::getStencilbuffer() const
    243 {
    244 	return mStencilbufferPointer;
    245 }
    246 
    247 GLenum Framebuffer::getReadBufferType()
    248 {
    249 	if(readBuffer == GL_NONE)
    250 	{
    251 		return GL_NONE;
    252 	}
    253 
    254 	return mColorbufferType[getReadBufferIndex()];
    255 }
    256 
    257 GLenum Framebuffer::getColorbufferType(GLuint index)
    258 {
    259 	return mColorbufferType[index];
    260 }
    261 
    262 GLenum Framebuffer::getDepthbufferType()
    263 {
    264 	return mDepthbufferType;
    265 }
    266 
    267 GLenum Framebuffer::getStencilbufferType()
    268 {
    269 	return mStencilbufferType;
    270 }
    271 
    272 GLuint Framebuffer::getColorbufferName(GLuint index)
    273 {
    274 	return mColorbufferPointer[index].name();
    275 }
    276 
    277 GLuint Framebuffer::getDepthbufferName()
    278 {
    279 	return mDepthbufferPointer.name();
    280 }
    281 
    282 GLuint Framebuffer::getStencilbufferName()
    283 {
    284 	return mStencilbufferPointer.name();
    285 }
    286 
    287 GLint Framebuffer::getColorbufferLayer(GLuint index)
    288 {
    289 	return mColorbufferLayer[index];
    290 }
    291 
    292 GLint Framebuffer::getDepthbufferLayer()
    293 {
    294 	return mDepthbufferLayer;
    295 }
    296 
    297 GLint Framebuffer::getStencilbufferLayer()
    298 {
    299 	return mStencilbufferLayer;
    300 }
    301 
    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 
    317 GLenum Framebuffer::completeness()
    318 {
    319 	int width;
    320 	int height;
    321 	int samples;
    322 
    323 	return completeness(width, height, samples);
    324 }
    325 
    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 
    522 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 
    583 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 
    644 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 
    658 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 
    681 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 
    694 DefaultFramebuffer::DefaultFramebuffer()
    695 {
    696 	readBuffer = GL_BACK;
    697 	drawBuffer[0] = GL_BACK;
    698 }
    699 
    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