/****************************************************************************************

		I3DExFinalRenderer.h

		Copyright: (c) 2001 Eovia Corp. All rights reserved.

		I3DExFinalRenderer definition

		Author:	Ray Dream
		Date:	3/2/98

		Revision History

		when		who					what & why
		==========	================	======================================================
		08/26/99	cph					Added family ids
		08/11/99	Guillaume&Christy	Added inheritance to all the Basic* classes
		09/01/98	Eml					I3dExRenderer API change

*****************************************************************************************/

#ifndef __I3DExFinalRenderer__
#define __I3DExFinalRenderer__

#if CP_PRAGMA_ONCE
#pragma once
#endif

#include "APITypes.h"
#include "InterfaceIDs.h"
#include "IExtension.h"

//for I3DShRasterBuffer
#include "IShUtilities.h"
#include "MCPtrArray.h"

//****** Globally Unique Ids *************************************************

MCDEFINE_GUID2	(IID_I3DExFinalRenderer,	R_IID_I3DExFinalRenderer);
MCDEFINE_GUID	(IID_I3DExGBufferRenderer,	0xAD619EE1L, 0x3A02, 0x101C, 0x88, 0x5F, 0x04, 0x02, 0x1C, 0x00, 0x70, 0x02);
MCDEFINE_GUID	(IID_I3DRenderStatistics,	0xAD619EE7L, 0x3A02, 0x101C, 0x88, 0x5F, 0x04, 0x02, 0x1C, 0x00, 0x70, 0x02);

//****** Family Id *************************************************

const FourCharT kFinalRendererFamilyID = kRID_FinalRendererFamilyID;

//*****************************************************************************

struct I3DShScene;
struct I3DShGroup;
struct I3DShCamera;
struct I3DShEnvironment;
struct I3DExRaytracer;
struct ISMPUtils;
class  TBBox2D;

/// \addtogroup Data
/// \{

/// Pointers to the various buffers that the renderer must fill. Note that the GBuffers
/// count and Ids are specified by I3DExGBufferRenderer::SetGBufferNeed().
///
struct RTData : public TMCObject
{
	RTData();

	uint8* red;			///< pointer to the red buffer
	uint8* green;		///< pointer to the green buffer
	uint8* blue;		///< pointer to the blue buffer
	uint8* alpha;		///< pointer to the alpha buffer. Null if we do need the alpha channel

	uint32  **buffers;		///< array of pointers to the GBuffers data (for each GBuffer calculated, on buffer)
	uint32	rowBytes;		///< offset to the next line
};

/// \}


/// \addtogroup ExternalInterface
/// \{

/// Represents the abstraction of the rendering statistics. You can derive your own
/// class from this interface to implement rendering statistics for your final renderer.
/// See I3DExFinalRenderer::GetRenderStatistics().
///
struct I3DRenderStatistics: public IMCUnknown
{
	// ****************************************************************************
	//								Clone
	// 
	/// Makes a copy of the rendering statistics.
	/// 
	/// \param clone  A pointer to the copy.
	/// 
	virtual void     MCCOMAPI Clone					(I3DRenderStatistics** clone) = 0;
	
	// ****************************************************************************
	//								GetDataBuffer
	// 
	/// Returns a pointer to the parameter map of the rendering statistics. See GetResID().
	/// 
	virtual void*	 MCCOMAPI GetDataBuffer			() = 0;


	// ****************************************************************************
	//								GetResID
	// 
	/// Return the resource ID of the parameter map and view associated with these
	/// rendering statistics.
	/// 
	virtual int16	 MCCOMAPI GetResID				() = 0;


	// ****************************************************************************
	//								GetParamsBufferSize
	// 
	/// returns the size of the buffer based on the C code (eg sizeof(fPmap))
	/// so that the application can check the calculated pmap size
	/// 
	virtual int32	MCCOMAPI GetParamsBufferSize	() const = 0;
};


// ****************************************************************************
//						I3DExTileRenderer		
// 
/// <P>A Tile Renderer renders a number of tiles of an image by subTile. A Tile
/// Renderer is created by calling I3DExFinalRenderer::GetTileRenderer() for
/// each of the rendering thread.</P>
///
/// <P>Pseudo code to use a Tile Renderer:</P>
///\code
/// TMCCountedPtr<I3DExTileRenderer> tileRenderer;
/// finalRenderer->GetTileRenderer(&tileRenderer);
/// ThrowIfNil(tileRenderer);
/// 
/// while (MoreTiles(&rect,&uvBox))
/// {
///     tileRenderer->Init(rect,uvBox);
/// 
///     TMCRect subTileRect;
///     while (tileRenderer->GetNextSubTile(subTileRect)
///     {
///         GetPixelPointers(pixels,subTileRect);
/// 
///         tileRenderer->RenderSubTile(pixels);
///         DisplaySubTile(rect);
///     }
///     GetTilePixels(pixels,TileRect);
///     tileRenderer->FinishRender(pixels);
/// }
/// \endcode
///
struct I3DExTileRenderer : public IMCUnknown
{
	// ****************************************************************************
	//							Init	
	// 
	/// Initialiase the tileRenderer for the rendering of a new tile
	/// 
	/// \param rect		The rectangle of the tile to render (in pixels)
	/// \param uvBox	The screen coordinates of this tile
	///
	virtual void	MCCOMAPI Init(const TMCRect& rect,const TBBox2D& uvBox) = 0;
	
	// ****************************************************************************
	//							GetNextSubTile	
	// 
	/// Returns the next subTile to render (returns the same rectangle as long as
	/// RenderSubTile has not been called)
	/// 
	/// \param rect		The rectangle of the next sub Tile in pixel.
	///
	/// \return True if there are more sub tiles to render, false if the last sub tile has
	/// already been rendered
	//
	virtual boolean MCCOMAPI GetNextSubTile(TMCRect& rect) = 0;

	// ****************************************************************************
	//								RenderSubTile
	// 
	/// Renders a sub tile of the current tile
	///
	/// \param pixels	Pointer to the pixels of the tile (color and GBuffers)
	///
	virtual void MCCOMAPI RenderSubTile(RTData& pixels) = 0;

	// ****************************************************************************
	//								FinishRender
	// 
	// Called at the end of the rendering of this tile
	//
	// \param pixels:	Pointer to the pixels of the tile (color and GBuffers)
	//
	virtual void MCCOMAPI FinishRender(const RTData& pixels) = 0;
};


// ****************************************************************************
//								I3DExFinalRenderer
//
/// The final renderer is the component that takes care of the rendering of an frame. It is driven by
/// the rendering module that takes cares of all the high level tasks (animation, tiling, multithreading...).
///
/// \see I3DExGBufferRenderer
/// \see I3DExTileRenderer
///
struct I3DExFinalRenderer: public IMCUnknown
{
	// ****************************************************************************
	//								SetTreeTop
	// 
	/// Specifies which tree needs to be rendered (generally the universe).
	///
	/// \param treeTop A pointer to the top of the tree hierarchy.
	///
	virtual MCCOMErr MCCOMAPI SetTreeTop			(I3DShGroup* treeTop) = 0;

	// ****************************************************************************
	//								SetCamera
	// 
	/// Specifies the rendering camera.
	///
	/// \param camera The rendering camera.
	///
	virtual MCCOMErr MCCOMAPI SetCamera				(I3DShCamera* camera) = 0;

	// ****************************************************************************
	//								SetEnvironment
	// 
	/// Sets up the background, backdrop, and atmospheric shader
	///
	/// \param environment The specified environment.
	///
	virtual MCCOMErr MCCOMAPI SetEnvironment		(I3DShEnvironment* environment) = 0;


	// ****************************************************************************
	//								SetAmbientLight
	// 
	/// Sets the ambient light color
	///
	/// \param ambiantColor the color of the ambient light.
	///
	virtual MCCOMErr MCCOMAPI SetAmbientLight		(const TMCColorRGB& ambiantColor) = 0;


	// ****************************************************************************
	//								SetFieldRenderingData
	// 
	/// \deprecated Initializes FieldRendering for video output. This function is called once before the rendering starts.
	/// If FieldRendering is on, the rendering Module will render twice as many frames as it will output, then it
	/// will mix the even and odd lines from two frames to build one frame.
	///
	/// \param fieldRenderingSettings Not documented
	/// \param firstFrame Not documented
	///
	virtual MCCOMErr MCCOMAPI SetFieldRenderingData	(int32 fieldRenderingSettings,int16 firstFrame) = 0;


	// ****************************************************************************
	//								GetRenderStatistics
	// 
	/// Returns a pointer to the rendering statistics object.
	///
	/// \param renderstats A pointer to next render statistics.
	///
	virtual void	 MCCOMAPI GetRenderStatistics	(I3DRenderStatistics** renderstats) = 0;


	// ****************************************************************************
	//								PrepareDraw
	// 
	/// <P>Called at the beginning of the rendering of each frame. You can use it to precalculate
	/// and store some information that will be needed for each tile of the frame. For example
	/// you can get the list of the instances and some information about them.</P>
	/// <P>Note: this function is called only once per frame even in SMP (multi processor mode).</P>
	/// <P>If you want to use the shadow features of the lights you want to initialize them here by calling
	/// I3DExShadowFeature::BeginRenderFrame on each of them.</P>
	///
	/// \param size:				Size of the image to render in pixels
	///
	/// \param uvBox:				uvBox is the is the box in screen coordinates (camera uv) corresponding to the image being rendered.
	///								Note that it is not always within the Production Frame (For example, when you do a Test Render in
	///								the Assemble room).
	///
	/// \param productionFrame:		The box in screen coordinates (camera uv) corresponding to the Production Frame
	///								(the image being rendered in final rendering). You can use this parameter to make
	///								sure that the size of some effects does not change when you use the Test Render tool.
	///								(For example, when you do a Test Render of the backdrop which expects screen coordinates
	///								between 0 and 1 matching the Production Frame.)
	///
	///
	/// \param callback				Not Used. Should be NULL
	///
	/// \param priv					Not Used. Should be NULL
	///
	virtual MCCOMErr MCCOMAPI PrepareDraw(
								const TMCPoint	&size,								// defines the size of the image to render
								const TBBox2D	&uvBox,
								const TBBox2D	&productionFrame,
								boolean			(*callback) (int16 vv, void* priv),
								void*			priv) = 0;
	
	// ****************************************************************************
	//								FinishDraw
	// 
	/// <P>Called at the end of the rendering of each frame. You can use this function to delete
	/// the temporary rendering caches.</P>
	/// <P>Note, that it is called only once even in SMP.</P>
	///
	virtual MCCOMErr MCCOMAPI FinishDraw			() = 0;

	// ****************************************************************************
	//								IsSMPAware
	// 
	/// <P>Returns True if the renderer supports SMP (multiprocessors) which means that
	/// several tiles can be rendered at the same time in different preemptive threads.</P>
	/// <P>You should returns false if the renderer does not support reentrant calls.</P>
	///
	virtual boolean  MCCOMAPI IsSMPAware			() = 0;
	
	// ****************************************************************************
	//								RenderVolumetrics
	// 
	/// <P>This call is called by the shell to enable/disable the rendering of
	/// volumetric effects (like light cones and light spheres)</P>
	///
	///
	/// \param renderEffects	True if the volumetric effects should be rendered.
	///
	virtual void     MCCOMAPI RenderVolumetrics(boolean renderEffects)=0;

	// ****************************************************************************
	//								RenderBackGround
	// 
	// -Description:
	//
	/// Turn on/off the rendering of the background of the image. (When the background
	/// rendering is turned off it should be black). This is used for alpha channel
	/// rendering/compositing. By "background" it is meant anything that is not hidden
	/// by an object, so backdrop, background, ...
	///
	/// \param enable	True if the background should be rendered
	///
	virtual void	 MCCOMAPI RenderBackGround(boolean enable)=0;

	// ****************************************************************************
	//								SeparateShadow
	// 
	// -Description:
	//
	/// Turn on/off separation of the shadow in lighting computation.
	///
	/// \param enable	True if the shadows should be separated
	///
	virtual void	 MCCOMAPI SeparateShadow(boolean enable)=0;

	// ****************************************************************************
	//								OptimizeTileSize
	// 
	/// Optimize the size of the tiles for rendering speed by increasing the tile
	/// if necessary
	///
	/// \param inOutTileSize	Should contain the proposed tile size when the function is
	///							called. Contains the optimized tile size when the function returns.
	///
	virtual void MCCOMAPI OptimizeTileSize(TMCPoint& inOutTileSize) = 0;

	// ****************************************************************************
	//								GetTileRenderer
	// 
	/// <P>Creates a new tile renderer. This function is called after PrepareDraw()
	/// and before FinishDraw().</P>
	/// <P>Note that you should always return a new renderer if your renderer is
	/// SMP compliant since tile renderer is created for each rendering
	/// thread.</P>
	///
	/// \param tileRenderer	A pointer to the tile renderer created
	///
	/// \see I3DExTileRenderer
	///
	virtual void MCCOMAPI GetTileRenderer(I3DExTileRenderer** tileRenderer) = 0;

	// ****************************************************************************
	//								BeginRendering
	// 
	/// Called at the beginning of the rendering of an animation
	/// 
	virtual void MCCOMAPI BeginRendering() = 0;

	// ****************************************************************************
	//								EndRendering
	// 
	/// Called at the end of the rendering of an animation
	/// 
	virtual void MCCOMAPI EndRendering(boolean aborting) = 0;

	// ****************************************************************************
	//								CreateRaytracer
	// 
	/// Returns a pointer to a Raytracer (or Lighting Model). This function should
	/// only be called after PrepareDraw and before FinishDraw. You cannot keep the
	/// raytracer between two frames, you need a new raytracer for each frame.
	/// 
	/// \param raytracer  The pointer to the raytracer that is returned
	/// 
	virtual	void MCCOMAPI CreateRaytracer(I3DExRaytracer** raytracer) = 0;

	// ****************************************************************************
	//								SetLightingDetailOptions
	// 
	/// Sets the lighting details options used for multipass rendering
	/// 
	/// \param atmosphereDetails			True if it wants atmosphere details
	/// \param volumePrimitivesDetails		True if it wants volume primitive details
	/// \param volumetricEffectsDetails		True if it wants volume effect details
	/// 
	virtual void	 MCCOMAPI SetLightingDetailOptions(boolean atmosphereDetails, boolean volumePrimitivesDetails, boolean volumetricEffectsDetails)=0;
};

/// A final renderer can implement this interface so as to support GBuffer rendering. If the
/// renderer implement this interface
///
struct I3DExGBufferRenderer: public IMCUnknown
{
	struct TGBufferInfo
	{
		uint32		fBufferID;
		boolean		fFiltered;
	};

	/// Sets the number of GBuffers that needs to be rendered as well as the ID of each buffer.
	/// These buffers are in the same orders as the ones that are given to the tileRenderer in
	/// the RTData struct.
	///
	/// \see I3DExFinalRenderer
	///
	/// \param bufferNbr The number of GBuffers to be rendered.
	/// \param bufferID	A pointer to an array of buffer IDs.
	///
	virtual MCCOMErr MCCOMAPI SetGBufferNeed		(const TMCArray<TGBufferInfo>& bufferInfos) = 0;
};
/// \}



#endif