Home | History | Annotate | Download | only in libGLES_CM
      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 namespace es1
     26 {
     27 
     28 Framebuffer::Framebuffer()
     29 {
     30 	mColorbufferType = GL_NONE_OES;
     31 	mDepthbufferType = GL_NONE_OES;
     32 	mStencilbufferType = GL_NONE_OES;
     33 }
     34 
     35 Framebuffer::~Framebuffer()
     36 {
     37 	mColorbufferPointer = nullptr;
     38 	mDepthbufferPointer = nullptr;
     39 	mStencilbufferPointer = nullptr;
     40 }
     41 
     42 Renderbuffer *Framebuffer::lookupRenderbuffer(GLenum type, GLuint handle) const
     43 {
     44 	Context *context = getContext();
     45 	Renderbuffer *buffer = nullptr;
     46 
     47 	if(type == GL_NONE_OES)
     48 	{
     49 		buffer = nullptr;
     50 	}
     51 	else if(type == GL_RENDERBUFFER_OES)
     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 
     64 void Framebuffer::setColorbuffer(GLenum type, GLuint colorbuffer)
     65 {
     66 	mColorbufferType = (colorbuffer != 0) ? type : GL_NONE_OES;
     67 	mColorbufferPointer = lookupRenderbuffer(type, colorbuffer);
     68 }
     69 
     70 void Framebuffer::setDepthbuffer(GLenum type, GLuint depthbuffer)
     71 {
     72 	mDepthbufferType = (depthbuffer != 0) ? type : GL_NONE_OES;
     73 	mDepthbufferPointer = lookupRenderbuffer(type, depthbuffer);
     74 }
     75 
     76 void Framebuffer::setStencilbuffer(GLenum type, GLuint stencilbuffer)
     77 {
     78 	mStencilbufferType = (stencilbuffer != 0) ? type : GL_NONE_OES;
     79 	mStencilbufferPointer = lookupRenderbuffer(type, stencilbuffer);
     80 }
     81 
     82 void Framebuffer::detachTexture(GLuint texture)
     83 {
     84 	if(mColorbufferPointer.name() == texture && IsTextureTarget(mColorbufferType))
     85 	{
     86 		mColorbufferType = GL_NONE_OES;
     87 		mColorbufferPointer = nullptr;
     88 	}
     89 
     90 	if(mDepthbufferPointer.name() == texture && IsTextureTarget(mDepthbufferType))
     91 	{
     92 		mDepthbufferType = GL_NONE_OES;
     93 		mDepthbufferPointer = nullptr;
     94 	}
     95 
     96 	if(mStencilbufferPointer.name() == texture && IsTextureTarget(mStencilbufferType))
     97 	{
     98 		mStencilbufferType = GL_NONE_OES;
     99 		mStencilbufferPointer = nullptr;
    100 	}
    101 }
    102 
    103 void Framebuffer::detachRenderbuffer(GLuint renderbuffer)
    104 {
    105 	if(mColorbufferPointer.name() == renderbuffer && mColorbufferType == GL_RENDERBUFFER_OES)
    106 	{
    107 		mColorbufferType = GL_NONE_OES;
    108 		mColorbufferPointer = nullptr;
    109 	}
    110 
    111 	if(mDepthbufferPointer.name() == renderbuffer && mDepthbufferType == GL_RENDERBUFFER_OES)
    112 	{
    113 		mDepthbufferType = GL_NONE_OES;
    114 		mDepthbufferPointer = nullptr;
    115 	}
    116 
    117 	if(mStencilbufferPointer.name() == renderbuffer && mStencilbufferType == GL_RENDERBUFFER_OES)
    118 	{
    119 		mStencilbufferType = GL_NONE_OES;
    120 		mStencilbufferPointer = nullptr;
    121 	}
    122 }
    123 
    124 // Increments refcount on surface.
    125 // caller must Release() the returned surface
    126 egl::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
    140 egl::Image *Framebuffer::getDepthBuffer()
    141 {
    142 	Renderbuffer *depthbuffer = mDepthbufferPointer;
    143 
    144 	if(depthbuffer)
    145 	{
    146 		return depthbuffer->getRenderTarget();
    147 	}
    148 
    149 	return nullptr;
    150 }
    151 
    152 // Increments refcount on surface.
    153 // caller must Release() the returned surface
    154 egl::Image *Framebuffer::getStencilBuffer()
    155 {
    156 	Renderbuffer *stencilbuffer = mStencilbufferPointer;
    157 
    158 	if(stencilbuffer)
    159 	{
    160 		return stencilbuffer->getRenderTarget();
    161 	}
    162 
    163 	return nullptr;
    164 }
    165 
    166 Renderbuffer *Framebuffer::getColorbuffer()
    167 {
    168 	return mColorbufferPointer;
    169 }
    170 
    171 Renderbuffer *Framebuffer::getDepthbuffer()
    172 {
    173 	return mDepthbufferPointer;
    174 }
    175 
    176 Renderbuffer *Framebuffer::getStencilbuffer()
    177 {
    178 	return mStencilbufferPointer;
    179 }
    180 
    181 GLenum Framebuffer::getColorbufferType()
    182 {
    183 	return mColorbufferType;
    184 }
    185 
    186 GLenum Framebuffer::getDepthbufferType()
    187 {
    188 	return mDepthbufferType;
    189 }
    190 
    191 GLenum Framebuffer::getStencilbufferType()
    192 {
    193 	return mStencilbufferType;
    194 }
    195 
    196 GLuint Framebuffer::getColorbufferName()
    197 {
    198 	return mColorbufferPointer.name();
    199 }
    200 
    201 GLuint Framebuffer::getDepthbufferName()
    202 {
    203 	return mDepthbufferPointer.name();
    204 }
    205 
    206 GLuint Framebuffer::getStencilbufferName()
    207 {
    208 	return mStencilbufferPointer.name();
    209 }
    210 
    211 bool Framebuffer::hasStencil()
    212 {
    213 	if(mStencilbufferType != GL_NONE_OES)
    214 	{
    215 		Renderbuffer *stencilbufferObject = getStencilbuffer();
    216 
    217 		if(stencilbufferObject)
    218 		{
    219 			return stencilbufferObject->getStencilSize() > 0;
    220 		}
    221 	}
    222 
    223 	return false;
    224 }
    225 
    226 GLenum Framebuffer::completeness()
    227 {
    228 	int width;
    229 	int height;
    230 	int samples;
    231 
    232 	return completeness(width, height, samples);
    233 }
    234 
    235 GLenum Framebuffer::completeness(int &width, int &height, int &samples)
    236 {
    237 	width = -1;
    238 	height = -1;
    239 	samples = -1;
    240 
    241 	if(mColorbufferType != GL_NONE_OES)
    242 	{
    243 		Renderbuffer *colorbuffer = getColorbuffer();
    244 
    245 		if(!colorbuffer)
    246 		{
    247 			return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_OES;
    248 		}
    249 
    250 		if(colorbuffer->getWidth() == 0 || colorbuffer->getHeight() == 0)
    251 		{
    252 			return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_OES;
    253 		}
    254 
    255 		if(mColorbufferType == GL_RENDERBUFFER_OES)
    256 		{
    257 			if(!IsColorRenderable(colorbuffer->getFormat()))
    258 			{
    259 				return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_OES;
    260 			}
    261 		}
    262 		else if(IsTextureTarget(mColorbufferType))
    263 		{
    264 			GLenum format = colorbuffer->getFormat();
    265 
    266 			if(!IsColorRenderable(format))
    267 			{
    268 				return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_OES;
    269 			}
    270 
    271 			if(IsDepthTexture(format) || IsStencilTexture(format))
    272 			{
    273 				return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_OES;
    274 			}
    275 		}
    276 		else
    277 		{
    278 			UNREACHABLE(mColorbufferType);
    279 			return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_OES;
    280 		}
    281 
    282 		width = colorbuffer->getWidth();
    283 		height = colorbuffer->getHeight();
    284 		samples = colorbuffer->getSamples();
    285 	}
    286 
    287 	Renderbuffer *depthbuffer = nullptr;
    288 	Renderbuffer *stencilbuffer = nullptr;
    289 
    290 	if(mDepthbufferType != GL_NONE_OES)
    291 	{
    292 		depthbuffer = getDepthbuffer();
    293 
    294 		if(!depthbuffer)
    295 		{
    296 			return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_OES;
    297 		}
    298 
    299 		if(depthbuffer->getWidth() == 0 || depthbuffer->getHeight() == 0)
    300 		{
    301 			return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_OES;
    302 		}
    303 
    304 		if(mDepthbufferType == GL_RENDERBUFFER_OES)
    305 		{
    306 			if(!es1::IsDepthRenderable(depthbuffer->getFormat()))
    307 			{
    308 				return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_OES;
    309 			}
    310 		}
    311 		else if(IsTextureTarget(mDepthbufferType))
    312 		{
    313 			if(!es1::IsDepthTexture(depthbuffer->getFormat()))
    314 			{
    315 				return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_OES;
    316 			}
    317 		}
    318 		else
    319 		{
    320 			UNREACHABLE(mDepthbufferType);
    321 			return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_OES;
    322 		}
    323 
    324 		if(width == -1 || height == -1)
    325 		{
    326 			width = depthbuffer->getWidth();
    327 			height = depthbuffer->getHeight();
    328 			samples = depthbuffer->getSamples();
    329 		}
    330 		else if(width != depthbuffer->getWidth() || height != depthbuffer->getHeight())
    331 		{
    332 			return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_OES;
    333 		}
    334 		else if(samples != depthbuffer->getSamples())
    335 		{
    336 			UNREACHABLE(0);
    337 		}
    338 	}
    339 
    340 	if(mStencilbufferType != GL_NONE_OES)
    341 	{
    342 		stencilbuffer = getStencilbuffer();
    343 
    344 		if(!stencilbuffer)
    345 		{
    346 			return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_OES;
    347 		}
    348 
    349 		if(stencilbuffer->getWidth() == 0 || stencilbuffer->getHeight() == 0)
    350 		{
    351 			return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_OES;
    352 		}
    353 
    354 		if(mStencilbufferType == GL_RENDERBUFFER_OES)
    355 		{
    356 			if(!es1::IsStencilRenderable(stencilbuffer->getFormat()))
    357 			{
    358 				return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_OES;
    359 			}
    360 		}
    361 		else if(IsTextureTarget(mStencilbufferType))
    362 		{
    363 			GLenum internalformat = stencilbuffer->getFormat();
    364 
    365 			if(!es1::IsStencilTexture(internalformat))
    366 			{
    367 				return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_OES;
    368 			}
    369 		}
    370 		else
    371 		{
    372 			UNREACHABLE(mStencilbufferType);
    373 			return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_OES;
    374 		}
    375 
    376 		if(width == -1 || height == -1)
    377 		{
    378 			width = stencilbuffer->getWidth();
    379 			height = stencilbuffer->getHeight();
    380 			samples = stencilbuffer->getSamples();
    381 		}
    382 		else if(width != stencilbuffer->getWidth() || height != stencilbuffer->getHeight())
    383 		{
    384 			return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_OES;
    385 		}
    386 		else if(samples != stencilbuffer->getSamples())
    387 		{
    388 			UNREACHABLE(0);
    389 			return GL_FRAMEBUFFER_UNSUPPORTED_OES;   // GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_OES;
    390 		}
    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_OES;
    397 	}
    398 
    399 	return GL_FRAMEBUFFER_COMPLETE_OES;
    400 }
    401 
    402 GLenum Framebuffer::getImplementationColorReadFormat()
    403 {
    404 	Renderbuffer *colorbuffer = mColorbufferPointer;
    405 
    406 	if(colorbuffer)
    407 	{
    408 		// Don't return GL_RGBA since that's always supported. Provide a second option here.
    409 		switch(colorbuffer->getInternalFormat())
    410 		{
    411 		case sw::FORMAT_A8R8G8B8:      return GL_BGRA_EXT;
    412 		case sw::FORMAT_A8B8G8R8:      return GL_BGRA_EXT;
    413 		case sw::FORMAT_X8R8G8B8:      return 0x80E0;   // GL_BGR_EXT
    414 		case sw::FORMAT_X8B8G8R8:      return 0x80E0;   // GL_BGR_EXT
    415 		case sw::FORMAT_A1R5G5B5:      return GL_BGRA_EXT;
    416 		case sw::FORMAT_R5G6B5:        return 0x80E0;   // GL_BGR_EXT
    417 		default:
    418 			UNREACHABLE(colorbuffer->getInternalFormat());
    419 		}
    420 	}
    421 
    422 	return GL_RGBA;
    423 }
    424 
    425 GLenum Framebuffer::getImplementationColorReadType()
    426 {
    427 	Renderbuffer *colorbuffer = mColorbufferPointer;
    428 
    429 	if(colorbuffer)
    430 	{
    431 		switch(colorbuffer->getInternalFormat())
    432 		{
    433 		case sw::FORMAT_A8R8G8B8:      return GL_UNSIGNED_BYTE;
    434 		case sw::FORMAT_A8B8G8R8:      return GL_UNSIGNED_BYTE;
    435 		case sw::FORMAT_X8R8G8B8:      return GL_UNSIGNED_BYTE;
    436 		case sw::FORMAT_X8B8G8R8:      return GL_UNSIGNED_BYTE;
    437 		case sw::FORMAT_A1R5G5B5:      return GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT;
    438 		case sw::FORMAT_R5G6B5:        return GL_UNSIGNED_SHORT_5_6_5;
    439 		default:
    440 			UNREACHABLE(colorbuffer->getInternalFormat());
    441 		}
    442 	}
    443 
    444 	return GL_UNSIGNED_BYTE;
    445 }
    446 
    447 DefaultFramebuffer::DefaultFramebuffer(Colorbuffer *colorbuffer, DepthStencilbuffer *depthStencil)
    448 {
    449 	mColorbufferPointer = new Renderbuffer(0, colorbuffer);
    450 
    451 	Renderbuffer *depthStencilRenderbuffer = new Renderbuffer(0, depthStencil);
    452 	mDepthbufferPointer = depthStencilRenderbuffer;
    453 	mStencilbufferPointer = depthStencilRenderbuffer;
    454 
    455 	mColorbufferType = GL_RENDERBUFFER_OES;
    456 	mDepthbufferType = (depthStencilRenderbuffer->getDepthSize() != 0) ? GL_RENDERBUFFER_OES : GL_NONE_OES;
    457 	mStencilbufferType = (depthStencilRenderbuffer->getStencilSize() != 0) ? GL_RENDERBUFFER_OES : GL_NONE_OES;
    458 }
    459 
    460 }
    461