/*
	ZFramebufferRenderTarget.h
	Author: James Russell <jcrussell@762studios.com>

	Purpose:	Interface which defines a FrameBuffer, which is a render target that contains
				a set of Textures or RenderBuffers which can be used for off-screen rendering.

	Changelog
	2011/04/03 - creation (jcrussell)
*/

#pragma once

#ifndef _ZFRAMEBUFFERRENDERTARGET_HPP
#define _ZFRAMEBUFFERRENDERTARGET_HPP

#include <ZUtil/ZUtil.hpp>

#include <ZRenderer/ZRenderTarget.hpp>
#include <ZRenderer/ZTexture.hpp>
#include <ZRenderer/ZRenderBuffer.hpp>

//The maximum number of color buffers supported on a single frame buffer render target
#ifndef ZFBRT_MAX_COLOR_BUFFERS
#define ZFBRT_MAX_COLOR_BUFFERS (16)
#endif

//Frame Buffer Render Target, used for off-screen rendering
class ZFramebufferRenderTarget : public ZRenderTarget
{
public:
	/*
	public ZFramebufferRenderTarget::AttachColorBuffer
	
	Attach a texture to this frame buffer render target as a color buffer.  All textures
	set as color buffers must be of the same dimension, and their dimensions must match
	that of GetWidth() and GetHeight().
	
	@param _buffer - the texture to bind to this render target
	@param _index - the index to bind this color buffer to
	@return (bool) - true if able to attach buffer, false if resource contended
	@context (all)
	*/
	virtual bool AttachColorTexture(ZPtr<ZTexture> _texture, size_t _index) = 0;

	/*
	virtual public ZFramebufferRenderTarget::AttachDepthTexture
	
	Attaches a texture to this frame buffer render target as a depth buffer.  The texture
	set as the depth buffer must be of the same dimension as the color buffers, and it's 
	dimension must match that of GetWidth() and GetHeight().

	A frame buffer render target cannot have a texture attached as a depth buffer as well
	as a render buffer attached for the same purpose.

	@param _texture - the texture to bind
	@return (bool) - true if able to attach, false otherwise
	@context (all)
	*/
	virtual bool AttachDepthTexture(ZPtr<ZTexture> _texture) = 0;

	/*
	virtual public ZFramebufferRenderTarget::AttachRenderBuffer
	
	Attaches a render buffer to this frame buffer render target.  The type of attachment
	is determined by render buffer type.

	A render buffer cannot be attached if another buffer is already attached that would
	perform it's function, i.e., it is not possible to attach a depth buffer when a 
	depth texture is in place, and it is not possible to attach a stencil buffer
	when a depth buffer is acting as depth and stencil buffer.
	
	@param _buffer - the render buffer to attach
	@return (bool) - true if able to attach buffer, false if resource contended
	@context (all)
	*/
	virtual bool AttachRenderBuffer(ZPtr<ZRenderBuffer> _buffer) = 0;

	/*
	virtual public ZFramebufferRenderTarget::IsComplete
	
	Checks to see if this FrameBuffer is in a 'complete' status and can be used.  A 
	'complete' frame buffer requires at least one color buffer (bound at index 0) and
	one depth buffer, and the buffers should be bound by the graphics library to the 
	frame buffer object.
	
	@return (bool) - true if complete, false otherwise
	@context (all)
	*/
	virtual bool IsComplete() = 0;

	/*
	virtual public ZFramebufferRenderTarget::RemoveColorBuffers

	Removes the current set of color buffers attached to this frame buffer render target.

	@return (bool) - true if able to remove buffers, false if resource contended
	@context (all)
	*/
	virtual bool RemoveColorBuffers() = 0;

	/*
	virtual public ZFramebufferRenderTarget::RemoveDepthBuffer

	Removes the current set depth buffers attached to this frame buffer render target.

	@return (bool) - true if able to remove buffer, false if resource contended
	@context (all)
	*/
	virtual bool RemoveDepthBuffer() = 0;

	/*
	virtual public ZFramebufferRenderTarget::RemoveStencilBuffer

	Removes the current set stencil buffer attached to this frame buffer render target.

	@return (bool) - true if able to remove buffer, false if resource contended
	@context (all)
	*/
	virtual bool RemoveStencilBuffer() = 0;

	//Not Implemented
	virtual const ZRenderTargetClearFlags& GetClearFlags() = 0;

	//Not Implemented
	virtual size_t GetHeight() = 0;

	//Not Implemented
	virtual ZRenderTargetType GetType() = 0;

	//Not Implemented
	virtual size_t GetWidth() = 0;

	//Not Implemented
	virtual bool SetClearFlags(const ZRenderTargetClearFlags& _flags) = 0;
};

#endif