// SwiftShader Software Renderer
//
// Copyright(c) 2005-2013 TransGaming Inc.
//
// All rights reserved. No part of this software may be copied, distributed, transmitted,
// transcribed, stored in a retrieval system, translated into any human or computer
// language by any means, or disclosed to third parties without the explicit written
// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express
// or implied, including but not limited to any patent rights, are granted to you.
//

// Framebuffer.cpp: Implements the Framebuffer class. Implements GL framebuffer
// objects and related functionality. [OpenGL ES 2.0.24] section 4.4 page 105.

#include "Framebuffer.h"

#include "main.h"
#include "Renderbuffer.h"
#include "Texture.h"
#include "utilities.h"

namespace es2
{

Framebuffer::Framebuffer()
{
	for(int i = 0; i < IMPLEMENTATION_MAX_COLOR_ATTACHMENTS; ++i)
	{
		mColorbufferType[i] = GL_NONE;
	}
	mDepthbufferType = GL_NONE;
	mStencilbufferType = GL_NONE;
}

Framebuffer::~Framebuffer()
{
	for(int i = 0; i < IMPLEMENTATION_MAX_COLOR_ATTACHMENTS; ++i)
	{
		mColorbufferPointer[i] = NULL;
	}
	mDepthbufferPointer = NULL;
	mStencilbufferPointer = NULL;
}

Renderbuffer *Framebuffer::lookupRenderbuffer(GLenum type, GLuint handle, GLint level, GLint layer) const
{
	Context *context = getContext();
	Renderbuffer *buffer = NULL;

	if(type == GL_NONE)
	{
		buffer = NULL;
	}
	else if(type == GL_RENDERBUFFER)
	{
		buffer = context->getRenderbuffer(handle);
	}
	else if(IsTextureTarget(type))
	{
		buffer = context->getTexture(handle)->getRenderbuffer(type, level, layer);
	}
	else UNREACHABLE(type);

	return buffer;
}

void Framebuffer::setColorbuffer(GLenum type, GLuint colorbuffer, GLuint index, GLint level, GLint layer)
{
	mColorbufferType[index] = (colorbuffer != 0) ? type : GL_NONE;
	mColorbufferPointer[index] = lookupRenderbuffer(type, colorbuffer, level, layer);
}

void Framebuffer::setDepthbuffer(GLenum type, GLuint depthbuffer, GLint level, GLint layer)
{
	mDepthbufferType = (depthbuffer != 0) ? type : GL_NONE;
	mDepthbufferPointer = lookupRenderbuffer(type, depthbuffer, level, layer);
}

void Framebuffer::setStencilbuffer(GLenum type, GLuint stencilbuffer, GLint level, GLint layer)
{
	mStencilbufferType = (stencilbuffer != 0) ? type : GL_NONE;
	mStencilbufferPointer = lookupRenderbuffer(type, stencilbuffer, level, layer);
}

void Framebuffer::detachTexture(GLuint texture)
{
	for(int i = 0; i < IMPLEMENTATION_MAX_COLOR_ATTACHMENTS; ++i)
	{
		if(mColorbufferPointer[i].name() == texture && IsTextureTarget(mColorbufferType[i]))
		{
			mColorbufferType[i] = GL_NONE;
			mColorbufferPointer[i] = NULL;
		}
	}

	if(mDepthbufferPointer.name() == texture && IsTextureTarget(mDepthbufferType))
	{
		mDepthbufferType = GL_NONE;
		mDepthbufferPointer = NULL;
	}

	if(mStencilbufferPointer.name() == texture && IsTextureTarget(mStencilbufferType))
	{
		mStencilbufferType = GL_NONE;
		mStencilbufferPointer = NULL;
	}
}

void Framebuffer::detachRenderbuffer(GLuint renderbuffer)
{
	for(int i = 0; i < IMPLEMENTATION_MAX_COLOR_ATTACHMENTS; ++i)
	{
		if(mColorbufferPointer[i].name() == renderbuffer && mColorbufferType[i] == GL_RENDERBUFFER)
		{
			mColorbufferType[i] = GL_NONE;
			mColorbufferPointer[i] = NULL;
		}
	}

	if(mDepthbufferPointer.name() == renderbuffer && mDepthbufferType == GL_RENDERBUFFER)
	{
		mDepthbufferType = GL_NONE;
		mDepthbufferPointer = NULL;
	}

	if(mStencilbufferPointer.name() == renderbuffer && mStencilbufferType == GL_RENDERBUFFER)
	{
		mStencilbufferType = GL_NONE;
		mStencilbufferPointer = NULL;
	}
}

// Increments refcount on surface.
// caller must Release() the returned surface
egl::Image *Framebuffer::getRenderTarget(GLuint index)
{
	Renderbuffer *colorbuffer = mColorbufferPointer[index];

	if(colorbuffer)
	{
		return colorbuffer->getRenderTarget();
	}

	return NULL;
}

egl::Image *Framebuffer::getReadRenderTarget()
{
	Context *context = getContext();
	return getRenderTarget(context->getReadFramebufferColorIndex());
}

// Increments refcount on surface.
// caller must Release() the returned surface
egl::Image *Framebuffer::getDepthStencil()
{
	Renderbuffer *depthstencilbuffer = mDepthbufferPointer;
	
	if(!depthstencilbuffer)
	{
		depthstencilbuffer = mStencilbufferPointer;
	}

	if(depthstencilbuffer)
	{
		return depthstencilbuffer->getRenderTarget();
	}

	return NULL;
}

Renderbuffer *Framebuffer::getColorbuffer(GLuint index)
{
	return (index < MAX_COLOR_ATTACHMENTS) ? mColorbufferPointer[index] : (Renderbuffer*)NULL;
}

Renderbuffer *Framebuffer::getReadColorbuffer()
{
	Context *context = getContext();
	return getColorbuffer(context->getReadFramebufferColorIndex());
}

Renderbuffer *Framebuffer::getDepthbuffer()
{
	return mDepthbufferPointer;
}

Renderbuffer *Framebuffer::getStencilbuffer()
{
	return mStencilbufferPointer;
}

GLenum Framebuffer::getColorbufferType(GLuint index)
{
	return mColorbufferType[index];
}

GLenum Framebuffer::getDepthbufferType()
{
	return mDepthbufferType;
}

GLenum Framebuffer::getStencilbufferType()
{
	return mStencilbufferType;
}

GLuint Framebuffer::getColorbufferName(GLuint index)
{
	return mColorbufferPointer[index].name();
}

GLuint Framebuffer::getDepthbufferName()
{
	return mDepthbufferPointer.name();
}

GLuint Framebuffer::getStencilbufferName()
{
	return mStencilbufferPointer.name();
}

GLint Framebuffer::getColorbufferLayer(GLuint index)
{
	Renderbuffer *colorbuffer = mColorbufferPointer[index];
	return colorbuffer ? colorbuffer->getLayer() : 0;
}

GLint Framebuffer::getDepthbufferLayer()
{
	return mDepthbufferPointer ? mDepthbufferPointer->getLayer() : 0;
}

GLint Framebuffer::getStencilbufferLayer()
{
	return mStencilbufferPointer ? mStencilbufferPointer->getLayer() : 0;
}

bool Framebuffer::hasStencil()
{
	if(mStencilbufferType != GL_NONE)
	{
		Renderbuffer *stencilbufferObject = getStencilbuffer();

		if(stencilbufferObject)
		{
			return stencilbufferObject->getStencilSize() > 0;
		}
	}

	return false;
}

GLenum Framebuffer::completeness()
{
	int width;
	int height;
	int samples;

	return completeness(width, height, samples);
}

GLenum Framebuffer::completeness(int &width, int &height, int &samples)
{
	width = -1;
	height = -1;
	samples = -1;

	for(int i = 0; i < IMPLEMENTATION_MAX_COLOR_ATTACHMENTS; ++i)
	{
		if(mColorbufferType[i] != GL_NONE)
		{
			Renderbuffer *colorbuffer = getColorbuffer(i);

			if(!colorbuffer)
			{
				return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
			}

			if(colorbuffer->getWidth() == 0 || colorbuffer->getHeight() == 0 || (colorbuffer->getDepth() <= colorbuffer->getLayer()))
			{
				return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
			}

			if(mColorbufferType[i] == GL_RENDERBUFFER)
			{
				if(!es2::IsColorRenderable(colorbuffer->getFormat(), egl::getClientVersion()))
				{
					return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
				}
			}
			else if(IsTextureTarget(mColorbufferType[i]))
			{
				GLenum format = colorbuffer->getFormat();

				if(IsCompressed(format, egl::getClientVersion()) ||
					format == GL_ALPHA ||
					format == GL_LUMINANCE ||
					format == GL_LUMINANCE_ALPHA)
				{
					return GL_FRAMEBUFFER_UNSUPPORTED;
				}

				if(es2::IsDepthTexture(format) || es2::IsStencilTexture(format))
				{
					return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
				}
			}
			else
			{
				UNREACHABLE(mColorbufferType[i]);
				return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
			}

			width = colorbuffer->getWidth();
			height = colorbuffer->getHeight();

			if(samples == -1)
			{
				samples = colorbuffer->getSamples();
			}
			else if(samples != colorbuffer->getSamples())
			{
				return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
			}

		}
	}

	Renderbuffer *depthbuffer = NULL;
	Renderbuffer *stencilbuffer = NULL;

	if(mDepthbufferType != GL_NONE)
	{
		depthbuffer = getDepthbuffer();

		if(!depthbuffer)
		{
			return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
		}

		if(depthbuffer->getWidth() == 0 || depthbuffer->getHeight() == 0)
		{
			return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
		}

		if(mDepthbufferType == GL_RENDERBUFFER)
		{
			if(!es2::IsDepthRenderable(depthbuffer->getFormat()))
			{
				return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
			}
		}
		else if(IsTextureTarget(mDepthbufferType))
		{
			if(!es2::IsDepthTexture(depthbuffer->getFormat()))
			{
				return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
			}
		}
		else
		{
			UNREACHABLE(mDepthbufferType);
			return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
		}

		if(width == -1 || height == -1)
		{
			width = depthbuffer->getWidth();
			height = depthbuffer->getHeight();
			samples = depthbuffer->getSamples();
		}
		else if(width != depthbuffer->getWidth() || height != depthbuffer->getHeight())
		{
			return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
		}
		else if(samples != depthbuffer->getSamples())
		{
			return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
		}
	}

	if(mStencilbufferType != GL_NONE)
	{
		stencilbuffer = getStencilbuffer();

		if(!stencilbuffer)
		{
			return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
		}

		if(stencilbuffer->getWidth() == 0 || stencilbuffer->getHeight() == 0)
		{
			return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
		}

		if(mStencilbufferType == GL_RENDERBUFFER)
		{
			if(!es2::IsStencilRenderable(stencilbuffer->getFormat()))
			{
				return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
			}
		}
		else if(IsTextureTarget(mStencilbufferType))
		{
			GLenum internalformat = stencilbuffer->getFormat();

			if(!es2::IsStencilTexture(internalformat))
			{
				return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
			}
		}
		else
		{
			UNREACHABLE(mStencilbufferType);
			return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
		}

		if(width == -1 || height == -1)
		{
			width = stencilbuffer->getWidth();
			height = stencilbuffer->getHeight();
			samples = stencilbuffer->getSamples();
		}
		else if(width != stencilbuffer->getWidth() || height != stencilbuffer->getHeight())
		{
			return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
		}
		else if(samples != stencilbuffer->getSamples())
		{
			return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
		}
	}

	// If we have both a depth and stencil buffer, they must refer to the same object
	// since we only support packed_depth_stencil and not separate depth and stencil
	if(depthbuffer && stencilbuffer && (depthbuffer != stencilbuffer))
	{
		return GL_FRAMEBUFFER_UNSUPPORTED;
	}

	// We need to have at least one attachment to be complete
	if(width == -1 || height == -1)
	{
		return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
	}

	return GL_FRAMEBUFFER_COMPLETE;
}

GLenum Framebuffer::getImplementationColorReadFormat()
{
	Renderbuffer *colorbuffer = getReadColorbuffer();
	
	if(colorbuffer)
	{
		// Don't return GL_RGBA since that's always supported. Provide a second option here.
		switch(colorbuffer->getInternalFormat())
		{
		case sw::FORMAT_A8B8G8R8I:
		case sw::FORMAT_A8B8G8R8UI:
		case sw::FORMAT_A16B16G16R16I:
		case sw::FORMAT_A16B16G16R16UI:
		case sw::FORMAT_A32B32G32R32I:
		case sw::FORMAT_A32B32G32R32UI:return GL_RGBA_INTEGER;
		case sw::FORMAT_A2B10G10R10:   return GL_RGB10_A2;
		case sw::FORMAT_A8B8G8R8I_SNORM:
		case sw::FORMAT_A16B16G16R16F:
		case sw::FORMAT_A32B32G32R32F:
		case sw::FORMAT_A8R8G8B8:
		case sw::FORMAT_A8B8G8R8:
		case sw::FORMAT_A1R5G5B5:      return GL_BGRA_EXT;
		case sw::FORMAT_X8B8G8R8I:
		case sw::FORMAT_X8B8G8R8UI:
		case sw::FORMAT_X16B16G16R16I:
		case sw::FORMAT_X16B16G16R16UI:
		case sw::FORMAT_X32B32G32R32I:
		case sw::FORMAT_X32B32G32R32UI:return GL_RGB_INTEGER;
		case sw::FORMAT_B16G16R16F:
		case sw::FORMAT_X8B8G8R8I_SNORM:
		case sw::FORMAT_X8B8G8R8:
		case sw::FORMAT_X8R8G8B8:
		case sw::FORMAT_R5G6B5:        return 0x80E0;   // GL_BGR_EXT
		case sw::FORMAT_G8R8I:
		case sw::FORMAT_G8R8UI:
		case sw::FORMAT_G16R16I:
		case sw::FORMAT_G16R16UI:
		case sw::FORMAT_G32R32I:
		case sw::FORMAT_G32R32UI:      return GL_RG_INTEGER;
		case sw::FORMAT_G8R8:
		case sw::FORMAT_G8R8I_SNORM:
		case sw::FORMAT_G16R16F:
		case sw::FORMAT_G32R32F:       return GL_RG;
		case sw::FORMAT_R8I:
		case sw::FORMAT_R8UI:
		case sw::FORMAT_R16I:
		case sw::FORMAT_R16UI:
		case sw::FORMAT_R32I:
		case sw::FORMAT_R32UI:         return GL_RED_INTEGER;
		case sw::FORMAT_R8:
		case sw::FORMAT_R8I_SNORM:
		case sw::FORMAT_R16F:
		case sw::FORMAT_R32F:          return GL_RED;
		default:
			UNREACHABLE(colorbuffer->getInternalFormat());
		}
	}

	return GL_RGBA;
}

GLenum Framebuffer::getImplementationColorReadType()
{
	Renderbuffer *colorbuffer = getReadColorbuffer();
	
	if(colorbuffer)
	{
		switch(colorbuffer->getInternalFormat())
		{
		case sw::FORMAT_R16F:
		case sw::FORMAT_G16R16F:
		case sw::FORMAT_B16G16R16F:
		case sw::FORMAT_A16B16G16R16F:
		case sw::FORMAT_R32F:
		case sw::FORMAT_G32R32F:
		case sw::FORMAT_B32G32R32F:
		case sw::FORMAT_A32B32G32R32F: return GL_FLOAT;
		case sw::FORMAT_R8I_SNORM:
		case sw::FORMAT_G8R8I_SNORM:
		case sw::FORMAT_X8B8G8R8I_SNORM:
		case sw::FORMAT_A8B8G8R8I_SNORM:return GL_BYTE;
		case sw::FORMAT_R8:
		case sw::FORMAT_G8R8:
		case sw::FORMAT_A8R8G8B8:
		case sw::FORMAT_A8B8G8R8:
		case sw::FORMAT_X8R8G8B8:
		case sw::FORMAT_X8B8G8R8:      return GL_UNSIGNED_BYTE;
		case sw::FORMAT_R8I:
		case sw::FORMAT_G8R8I:
		case sw::FORMAT_X8B8G8R8I:
		case sw::FORMAT_A8B8G8R8I:
		case sw::FORMAT_R16I:
		case sw::FORMAT_G16R16I:
		case sw::FORMAT_X16B16G16R16I:
		case sw::FORMAT_A16B16G16R16I:
		case sw::FORMAT_R32I:
		case sw::FORMAT_G32R32I:
		case sw::FORMAT_X32B32G32R32I:
		case sw::FORMAT_A32B32G32R32I: return GL_INT;
		case sw::FORMAT_R8UI:
		case sw::FORMAT_G8R8UI:
		case sw::FORMAT_X8B8G8R8UI:
		case sw::FORMAT_A8B8G8R8UI:
		case sw::FORMAT_R16UI:
		case sw::FORMAT_G16R16UI:
		case sw::FORMAT_X16B16G16R16UI:
		case sw::FORMAT_A16B16G16R16UI:
		case sw::FORMAT_R32UI:
		case sw::FORMAT_G32R32UI:
		case sw::FORMAT_X32B32G32R32UI:
		case sw::FORMAT_A32B32G32R32UI:return GL_UNSIGNED_INT;
		case sw::FORMAT_A2B10G10R10:   return GL_UNSIGNED_INT_10_10_10_2_OES;
		case sw::FORMAT_A1R5G5B5:      return GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT;
		case sw::FORMAT_R5G6B5:        return GL_UNSIGNED_SHORT_5_6_5;
		default:
			UNREACHABLE(colorbuffer->getInternalFormat());
		}
	}

	return GL_UNSIGNED_BYTE;
}

DefaultFramebuffer::DefaultFramebuffer(Colorbuffer *colorbuffer, DepthStencilbuffer *depthStencil)
{
	mColorbufferPointer[0] = new Renderbuffer(0, colorbuffer);
	mColorbufferType[0] = GL_RENDERBUFFER;

	for(int i = 1; i < IMPLEMENTATION_MAX_COLOR_ATTACHMENTS; ++i)
	{
		mColorbufferPointer[i] = nullptr;
		mColorbufferType[i] = GL_NONE;
	}

	Renderbuffer *depthStencilRenderbuffer = new Renderbuffer(0, depthStencil);
	mDepthbufferPointer = depthStencilRenderbuffer;
	mStencilbufferPointer = depthStencilRenderbuffer;

	mDepthbufferType = (depthStencilRenderbuffer->getDepthSize() != 0) ? GL_RENDERBUFFER : GL_NONE;
	mStencilbufferType = (depthStencilRenderbuffer->getStencilSize() != 0) ? GL_RENDERBUFFER : GL_NONE;
}

}
