gfxDevice.h

Engine/source/gfx/gfxDevice.h

More...

Classes:

class

GFXDevice is the TSE graphics interface layer.

Public Defines

define
GFX() ()
define
GFXAssertFatal(x, error) 

Detailed Description

Public Defines

GFX() ()
GFXAssertFatal(x, error) 
   1
   2//-----------------------------------------------------------------------------
   3// Copyright (c) 2012 GarageGames, LLC
   4//
   5// Permission is hereby granted, free of charge, to any person obtaining a copy
   6// of this software and associated documentation files (the "Software"), to
   7// deal in the Software without restriction, including without limitation the
   8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
   9// sell copies of the Software, and to permit persons to whom the Software is
  10// furnished to do so, subject to the following conditions:
  11//
  12// The above copyright notice and this permission notice shall be included in
  13// all copies or substantial portions of the Software.
  14//
  15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  21// IN THE SOFTWARE.
  22//-----------------------------------------------------------------------------
  23
  24#ifndef _GFXDEVICE_H_
  25#define _GFXDEVICE_H_
  26
  27#ifndef _GFXADAPTER_H_
  28#include "gfx/gfxAdapter.h"
  29#endif
  30#ifndef _GFXTARGET_H_
  31#include "gfx/gfxTarget.h"
  32#endif
  33#ifndef _GFXVERTEXBUFFER_H_
  34#include "gfx/gfxVertexBuffer.h"
  35#endif
  36#ifndef _GFXSTATEBLOCK_H_
  37#include "gfx/gfxStateBlock.h"
  38#endif
  39#ifndef _GFXSHADER_H_
  40#include "gfx/gfxShader.h"
  41#endif
  42#ifndef _GFXCUBEMAP_H_
  43#include "gfx/gfxCubemap.h"
  44#endif
  45#ifndef _TDICTIONARY_H_
  46#include "core/util/tDictionary.h"
  47#endif
  48#ifndef _TSIGNAL_H_
  49#include "core/util/tSignal.h"
  50#endif
  51#ifndef _GFXDEVICESTATISTICS_H_
  52#include "gfx/gfxDeviceStatistics.h"
  53#endif
  54#ifndef _MATHUTIL_FRUSTUM_H_
  55#include "math/util/frustum.h"
  56#endif
  57
  58#ifndef _PLATFORM_PLATFORMTIMER_H_
  59#include "platform/platformTimer.h"
  60#endif
  61#include "gfxTextureArray.h"
  62
  63class FontRenderBatcher;
  64class GFont;
  65class GFXCardProfiler;
  66class GFXDrawUtil;
  67class GFXFence;
  68class GFXOcclusionQuery;
  69class GFXPrimitiveBuffer;
  70class GFXShader;
  71class GFXStateBlock;
  72class GFXShaderConstBuffer;
  73class GFXTextureManager;
  74
  75// Global macro
  76#define GFX GFXDevice::get() 
  77
  78//-----------------------------------------------------------------------------
  79
  80/// GFXDevice is the TSE graphics interface layer. This allows the TSE to
  81/// do many things, such as use multiple render devices for multi-head systems,
  82/// and allow a game to render in DirectX 9, OpenGL or any other API which has
  83/// a GFX implementation seamlessly. There are many concepts in GFX device which
  84/// may not be familiar to you, especially if you have not used DirectX.
  85/// @n
  86/// <b>Buffers</b>
  87/// There are three types of buffers in GFX: vertex, index and primitive. Please
  88/// note that index buffers are not accessable outside the GFX layer, they are wrapped
  89/// by primitive buffers. Primitive buffers will be explained in detail later.
  90/// Buffers are allocated and deallocated using their associated allocXBuffer and
  91/// freeXBuffer methods on the device. When a buffer is allocated you pass in a
  92/// pointer to, depending on the buffer, a vertex type pointer or a U16 pointer. 
  93/// During allocation, this pointer is set to the address of where you should
  94/// copy in the information for this buffer. You must the tell the GFXDevice
  95/// that the information is in, and it should prepare the buffer for use by calling
  96/// the prepare method on it. Dynamic vertex buffer example:
  97/// @code
  98/// GFXVertexP *verts;        // Making a buffer containing verticies with only position
  99///
 100/// // Allocate a dynamic vertex buffer to hold 3 vertices and use *verts as the location to copy information into
 101/// GFXVertexBufferHandle vb = GFX->allocVertexBuffer( 3, &verts, true ); 
 102///
 103/// // Now set the information, we're making a triangle
 104/// verts[0].point = Point3F( 200.f, 200.f, 0.f );
 105/// verts[1].point = Point3F( 200.f, 400.f, 0.f );
 106/// verts[2].point = Point3F( 400.f, 200.f, 0.f );
 107///
 108/// // Tell GFX that the information is in and it should be made ready for use
 109/// // Note that nothing is done with verts, this should not and MUST NOT be deleted
 110/// // stored, or otherwise used after prepare is called.
 111/// GFX->prepare( vb );
 112///
 113/// // Because this is a dynamic vertex buffer, it is only assured to be valid until someone 
 114/// // else allocates a dynamic vertex buffer, so we will render it now
 115/// GFX->setVertexBuffer( vb );
 116/// GFX->drawPrimitive( GFXTriangleStrip, 0, 1 );
 117///
 118/// // Now because this is a dynamic vertex buffer it MUST NOT BE FREED you are only
 119/// // given a handle to a vertex buffer which belongs to the device
 120/// @endcode
 121/// 
 122/// To use a static vertex buffer, it is very similar, this is an example using a
 123/// static primitive buffer:
 124/// @n
 125/// This takes place inside a constructor for a class which has a member variable
 126/// called mPB which is the primitive buffer for the class instance.
 127/// @code
 128/// U16 *idx;                          // This is going to be where to write indices
 129/// GFXPrimitiveInfo *primitiveInfo;   // This will be where to write primitive information
 130///
 131/// // Allocate a primitive buffer with 4 indices, and 1 primitive described for use
 132/// mPB = GFX->allocPrimitiveBuffer( 4, &idx, 1, &primitiveInfo );
 133///
 134/// // Write the index information, this is going to be for the outline of a triangle using
 135/// // a line strip
 136/// idx[0] = 0;
 137/// idx[1] = 1;
 138/// idx[2] = 2;
 139/// idx[3] = 0;
 140///
 141/// // Write the information for the primitive
 142/// primitiveInfo->indexStart = 0;            // Starting with index 0
 143/// primitiveInfo->minVertex = 0;             // The minimum vertex index is 0
 144/// primitiveInfo->maxVertex = 3;             // The maximum vertex index is 3
 145/// primitiveInfo->primitiveCount = 3;        // There are 3 lines we are drawing
 146/// primitiveInfo->type = GFXLineStrip;       // This primitive info describes a line strip
 147/// @endcode
 148/// The following code takes place in the destructor for the same class
 149/// @code
 150/// // Because this is a static buffer it's our responsibility to free it when we are done
 151/// GFX->freePrimitiveBuffer( mPB );
 152/// @endcode
 153/// This last bit takes place in the rendering function for the class
 154/// @code
 155/// // You need to set a vertex buffer as well, primitive buffers contain indexing
 156/// // information, not vertex information. This is so you could have, say, a static
 157/// // vertex buffer, and a dynamic primitive buffer.
 158///
 159/// // This sets the primitive buffer to the static buffer we allocated in the constructor
 160/// GFX->setPrimitiveBuffer( mPB );
 161/// 
 162/// // Draw the first primitive contained in the set primitive buffer, our primitive buffer
 163/// // has only one primitive, so we could also technically call GFX->drawPrimitives(); and
 164/// // get the same result. 
 165/// GFX->drawPrimitive( 0 );
 166/// @endcode
 167/// If you need any more examples on how to use these buffers please see the rest of the engine.
 168/// @n
 169/// <b>Primitive Buffers</b>
 170/// @n
 171/// Primitive buffers wrap and extend the concept of index buffers. The purpose of a primitive
 172/// buffer is to let objects store all information they have to render their primitives in
 173/// a central place. Say that a shape is made up of triangle strips and triangle fans, it would
 174/// still have only one primitive buffer which contained primitive information for each strip
 175/// and fan. It could then draw itself with one call.
 176///
 177/// TO BE FINISHED LATER
 178class GFXDevice
 179{
 180private:
 181   friend class GFXInit;
 182   friend class GFXPrimitiveBufferHandle;
 183   friend class GFXVertexBufferHandleBase;
 184   friend class GFXTextureObject;
 185   friend class GFXTexHandle;
 186   friend class GFXVertexFormat;
 187   friend class GFXResource;
 188   friend class LightMatInstance; // For stencil interface
 189
 190   //--------------------------------------------------------------------------
 191   // Static GFX interface
 192   //--------------------------------------------------------------------------
 193public:
 194
 195   enum GFXDeviceEventType
 196   {
 197      /// The device has been created, but not initialized
 198      deCreate,
 199      
 200      /// The device has been initialized
 201      deInit,
 202      
 203      /// The device is about to be destroyed.
 204      deDestroy,
 205      
 206      /// The device has started rendering a frame
 207      deStartOfFrame,
 208      
 209      /// The device is about to finish rendering a frame
 210      deEndOfFrame,
 211
 212      /// The device has rendered a frame and ended the scene
 213      dePostFrame,
 214
 215      /// The device has started rendering a frame's field (such as for side-by-side rendering)
 216      deStartOfField,
 217
 218      /// left stereo frame has been rendered
 219      deLeftStereoFrameRendered,
 220
 221      /// right stereo frame has been rendered
 222      deRightStereoFrameRendered,
 223
 224      /// The device is about to finish rendering a frame's field
 225      deEndOfField,
 226   };
 227
 228   typedef Signal <bool (GFXDeviceEventType)> DeviceEventSignal;
 229   static DeviceEventSignal& getDeviceEventSignal();
 230   
 231   static GFXDevice *get() { return smGFXDevice; }
 232
 233   static void initConsole();
 234   static bool destroy();
 235   
 236   static bool devicePresent() { return (smGFXDevice && smGFXDevice->getAdapterType() != NullDevice); }
 237
 238private:
 239   /// @name Device management variables
 240   /// @{
 241   static GFXDevice * smGFXDevice; ///< Global GFXDevice 
 242 
 243   /// @}
 244
 245   //--------------------------------------------------------------------------
 246   // Core GFX interface
 247   //--------------------------------------------------------------------------
 248public:
 249   enum GFXDeviceRenderStyles
 250   {
 251      RS_Standard          = 0,
 252      RS_StereoSideBySide  = (1<<0),     // Render into current Render Target side-by-side
 253      RS_StereoSeparate    = (1<<1)      // Render in two separate passes (then combined by vr compositor)
 254   };
 255
 256   enum GFXDeviceLimits
 257   {
 258      NumStereoPorts = 2
 259   };
 260
 261private:
 262
 263   /// Adapter for this device.
 264   GFXAdapter mAdapter;
 265
 266protected:
 267   /// List of valid video modes for this device.
 268   Vector<GFXVideoMode> mVideoModes;
 269
 270   /// The CardProfiler for this device.
 271   GFXCardProfiler *mCardProfiler;
 272
 273   /// Head of the resource list.
 274   ///
 275   /// @see GFXResource
 276   GFXResource *mResourceListHead;
 277
 278   /// Set once the device is active.
 279   bool mCanCurrentlyRender;
 280
 281   /// Set if we're in a mode where we want rendering to occur.
 282   bool mAllowRender;
 283
 284   /// The style of rendering that is to be performed, based on GFXDeviceRenderStyles
 285   U32 mCurrentRenderStyle;
 286
 287   /// Current stereo target being rendered to
 288   S32 mCurrentStereoTarget;
 289
 290   /// Eye offset used when using a stereo rendering style
 291   Point3F mStereoEyeOffset[NumStereoPorts];
 292
 293   /// Center matrix for head
 294   MatrixF mStereoHeadTransform;
 295
 296   /// Left and right matrix for eyes
 297   MatrixF mStereoEyeTransforms[NumStereoPorts];
 298
 299   /// Inverse of mStereoEyeTransforms
 300   MatrixF mInverseStereoEyeTransforms[NumStereoPorts];
 301
 302   /// Fov port settings
 303   FovPort mFovPorts[NumStereoPorts];
 304
 305   /// Destination viewports for stereo rendering
 306   RectI mStereoViewports[NumStereoPorts];
 307
 308   /// Destination targets for stereo rendering
 309   GFXTextureTarget* mStereoTargets[NumStereoPorts];
 310
 311   /// This will allow querying to see if a device is initialized and ready to
 312   /// have operations performed on it.
 313   bool mInitialized;
 314   bool mReset;
 315
 316   /// This is called before this, or any other device, is deleted in the global destroy()
 317   /// method. It allows the device to clean up anything while everything is still valid.
 318   virtual void preDestroy();
 319
 320   /// Set the adapter that this device is using.  For use by GFXInit::createDevice only.
 321   virtual void setAdapter(const GFXAdapter& adapter) { mAdapter = adapter; }
 322
 323   /// Notify GFXDevice that we are initialized
 324   virtual void deviceInited();
 325public:
 326   GFXDevice();
 327   virtual ~GFXDevice();
 328
 329   /// Initialize this GFXDevice, optionally specifying a platform window to
 330   /// bind to.
 331   virtual void init( const GFXVideoMode &mode, PlatformWindow *window = NULL ) = 0;
 332
 333   /// Returns true if the scene has begun and its
 334   /// safe to make rendering calls.
 335   /// @see beginScene
 336   /// @see endScene
 337   bool canCurrentlyRender() const { return mCanCurrentlyRender; }
 338
 339   bool recentlyReset(){ return mReset; }
 340   void beginReset(){ mReset = true; }
 341   void finalizeReset(){ mReset = false; }
 342
 343   void setAllowRender( bool render ) { mAllowRender = render; }
 344
 345   inline bool allowRender() const { return mAllowRender; }
 346   
 347   /// Retrieve the current rendering style based on GFXDeviceRenderStyles
 348   U32 getCurrentRenderStyle() const { return mCurrentRenderStyle; }
 349
 350   /// Retrieve the current stereo target being rendered to
 351   S32 getCurrentStereoTarget() const { return mCurrentStereoTarget; }
 352
 353   /// Set the current rendering style, based on GFXDeviceRenderStyles
 354   void setCurrentRenderStyle(U32 style) { mCurrentRenderStyle = style; }
 355
 356   /// Set the current stereo target being rendered to (in case we're doing anything with postfx)
 357   void setCurrentStereoTarget(const F32 targetId) { mCurrentStereoTarget = targetId; }
 358
 359   /// Get the current eye offset used during stereo rendering
 360   const Point3F* getStereoEyeOffsets() { return mStereoEyeOffset; }
 361
 362   const MatrixF& getStereoHeadTransform() { return mStereoHeadTransform;  }
 363   const MatrixF* getStereoEyeTransforms() { return mStereoEyeTransforms; }
 364   const MatrixF* getInverseStereoEyeTransforms() { return mInverseStereoEyeTransforms; }
 365
 366   /// Sets the head matrix for stereo rendering
 367   void setStereoHeadTransform(const MatrixF &mat) { mStereoHeadTransform = mat; }
 368
 369   /// Set the current eye offset used during stereo rendering
 370   void setStereoEyeOffsets(Point3F *offsets) { dMemcpy(mStereoEyeOffset, offsets, sizeof(Point3F) * NumStereoPorts); }
 371
 372   void setStereoEyeTransforms(MatrixF *transforms) { dMemcpy(mStereoEyeTransforms, transforms, sizeof(mStereoEyeTransforms)); dMemcpy(mInverseStereoEyeTransforms, transforms, sizeof(mInverseStereoEyeTransforms)); mInverseStereoEyeTransforms[0].inverse(); mInverseStereoEyeTransforms[1].inverse();  }
 373
 374   /// Set the current eye offset used during stereo rendering. Assumes NumStereoPorts are available.
 375   void setStereoFovPort(const FovPort *ports) { dMemcpy(mFovPorts, ports, sizeof(mFovPorts)); }
 376
 377   /// Get the current eye offset used during stereo rendering
 378   const FovPort* getStereoFovPort() { return mFovPorts; }
 379
 380   /// Sets stereo viewports
 381   void setSteroViewports(const RectI *ports) { dMemcpy(mStereoViewports, ports, sizeof(RectI) * NumStereoPorts); }
 382
 383   /// Sets stereo render targets
 384   void setStereoTargets(GFXTextureTarget **targets) { mStereoTargets[0] = targets[0]; mStereoTargets[1] = targets[1]; }
 385
 386   RectI* getStereoViewports() { return mStereoViewports; }
 387
 388   /// Activates a stereo render target, setting the correct viewport to render eye contents.
 389   /// If eyeId is -1, set a viewport encompassing the entire size of the render targets.
 390   void activateStereoTarget(S32 eyeId)
 391   {
 392      if (eyeId == -1)
 393      {
 394         if (mStereoTargets[0])
 395         {
 396            setActiveRenderTarget(mStereoTargets[0], true);
 397         }
 398      }
 399      else
 400      {
 401         if (mStereoTargets[eyeId])
 402         {
 403            setActiveRenderTarget(mStereoTargets[eyeId], false);
 404         }
 405         setViewport(mStereoViewports[eyeId]);
 406      }
 407
 408      mCurrentStereoTarget = eyeId;
 409   }
 410
 411   GFXCardProfiler* getCardProfiler() const { return mCardProfiler; }
 412
 413   /// Returns active graphics adapter type.
 414   virtual GFXAdapterType getAdapterType()=0;
 415
 416   /// Returns the Adapter that was used to create this device
 417   virtual const GFXAdapter& getAdapter() { return mAdapter; }
 418
 419   /// @}
 420
 421   /// @name Debug Methods
 422   /// @{
 423
 424   virtual void enterDebugEvent(ColorI color, const char *name) = 0;
 425   virtual void leaveDebugEvent() = 0;
 426   virtual void setDebugMarker(ColorI color, const char *name) = 0;
 427   virtual const char* interpretDebugResult(long result) { return "Not Implemented"; };
 428   /// @}
 429
 430   /// @name Resource debug methods
 431   /// @{
 432   
 433   /// Lists how many of each GFX resource (e.g. textures, texture targets, shaders, etc.) GFX is aware of
 434   /// @param unflaggedOnly   If true, this method only counts unflagged resources
 435   virtual void listResources(bool unflaggedOnly);
 436
 437   /// Flags all resources GFX is currently aware of
 438   virtual void flagCurrentResources();
 439
 440   /// Clears the flag on all resources GFX is currently aware of
 441   virtual void clearResourceFlags();
 442
 443   /// Dumps a description of the specified resource types to the console
 444   /// @param resNames     A string of space separated class names (e.g. "GFXTextureObject GFXTextureTarget GFXShader")
 445   ///                     to describe to the console
 446   /// @param file         A path to the file to write the descriptions to.  If it is NULL or "", descriptions are
 447   ///                     written to the console.
 448   /// @param unflaggedOnly If true, this method only counts unflagged resources
 449   /// @note resNames is case sensitive because there is no dStristr function.
 450   virtual void describeResources(const char* resName, const char* file, bool unflaggedOnly);
 451
 452   /// Returns the current GFXDeviceStatistics, stats are cleared every ::beginScene call.
 453   GFXDeviceStatistics* getDeviceStatistics() { return &mDeviceStatistics; }
 454protected:
 455   GFXDeviceStatistics mDeviceStatistics;
 456
 457   /// This is a helper method for describeResourcesToFile.  It walks through the
 458   /// GFXResource list and sorts it by item type, putting the resources into the proper vector.
 459   /// @see describeResources
 460   virtual void fillResourceVectors(const char* resNames, bool unflaggedOnly, Vector<GFXResource*> &textureObjects,
 461      Vector<GFXResource*> &textureTargets, Vector<GFXResource*> &windowTargets, Vector<GFXResource*> &vertexBuffers, 
 462      Vector<GFXResource*> &primitiveBuffers, Vector<GFXResource*> &fences, Vector<GFXResource*> &cubemaps, 
 463      Vector<GFXResource*> &shaders, Vector<GFXResource*> &stateblocks);
 464public:
 465
 466   /// @}
 467
 468   /// @name Video Mode Functions
 469   /// @{
 470   /// Enumerates the supported video modes of the device
 471   virtual void enumerateVideoModes() = 0;
 472
 473   /// Returns the video mode list.
 474   /// @see GFXVideoMode
 475   const Vector<GFXVideoMode>* const getVideoModeList() const { return &mVideoModes; }
 476
 477   /// Returns the first format from the list which meets all 
 478   /// the criteria of the texture profile and query options.      
 479   virtual GFXFormat selectSupportedFormat(GFXTextureProfile *profile,
 480      const Vector<GFXFormat> &formats, bool texture, bool mustblend, bool mustfilter) = 0;
 481
 482   /// @}
 483
 484   //-----------------------------------------------------------------------------
 485protected:
 486
 487   /// @name State tracking variables
 488   /// @{
 489
 490   /// Set if ANY state is dirty, including matrices or primitive buffers.
 491   bool mStateDirty;     
 492   
 493   enum TexDirtyType
 494   {
 495      GFXTDT_Normal,
 496      GFXTDT_Cube,
 497      GFXTDT_CubeArray,
 498      GFXTDT_TextureArray
 499   };
 500   
 501   GFXTexHandle mCurrentTexture[GFX_TEXTURE_STAGE_COUNT];
 502   GFXTexHandle mNewTexture[GFX_TEXTURE_STAGE_COUNT];
 503   GFXCubemapHandle mCurrentCubemap[GFX_TEXTURE_STAGE_COUNT];
 504   GFXCubemapHandle mNewCubemap[GFX_TEXTURE_STAGE_COUNT];
 505   GFXCubemapArrayHandle mCurrentCubemapArray[GFX_TEXTURE_STAGE_COUNT];
 506   GFXCubemapArrayHandle mNewCubemapArray[GFX_TEXTURE_STAGE_COUNT];
 507   GFXTextureArrayHandle mCurrentTextureArray[GFX_TEXTURE_STAGE_COUNT];
 508   GFXTextureArrayHandle mNewTextureArray[GFX_TEXTURE_STAGE_COUNT];
 509
 510   TexDirtyType   mTexType[GFX_TEXTURE_STAGE_COUNT];
 511   bool           mTextureDirty[GFX_TEXTURE_STAGE_COUNT];
 512   bool           mTexturesDirty;
 513
 514   // This maps a GFXStateBlockDesc hash value to a GFXStateBlockRef
 515   typedef Map<U32, GFXStateBlockRef> StateBlockMap;
 516   StateBlockMap mCurrentStateBlocks;
 517
 518   // This tracks whether or not our state block is dirty.
 519   bool  mStateBlockDirty;
 520   GFXStateBlockRef mCurrentStateBlock;
 521   GFXStateBlockRef mNewStateBlock;
 522
 523   GFXShaderConstBuffer *mCurrentShaderConstBuffer;
 524
 525   /// A global forced wireframe mode.
 526   static bool smWireframe;
 527
 528   /// The global vsync state.
 529   static bool smDisableVSync;
 530
 531   /// The forced shader model version if non-zero.
 532   static F32 smForcedPixVersion;
 533
 534   /// Disable all hardware occlusion queries causing 
 535   /// them to return only the visibile state.
 536   static bool smDisableOcclusionQuery;
 537
 538   /// @}
 539
 540   /// @see getDeviceSwizzle32
 541   Swizzle<U8, 4> *mDeviceSwizzle32;
 542
 543   /// @see getDeviceSwizzle24
 544   Swizzle<U8, 3> *mDeviceSwizzle24;
 545
 546   //-----------------------------------------------------------------------------
 547
 548   /// @name Matrix managing variables
 549   /// @{
 550
 551   ///
 552   MatrixF mWorldMatrix[GFX_WORLD_STACK_MAX];
 553
 554   S32     mWorldStackSize;
 555
 556   MatrixF mProjectionMatrix;
 557
 558   MatrixF mViewMatrix;
 559
 560   /// @}
 561
 562   /// @name Current frustum planes
 563   /// @{
 564
 565   ///
 566   Frustum mFrustum;
 567
 568   //-----------------------------------------------------------------------------
 569
 570   /// @name Stateblock functions
 571   /// @{
 572
 573   /// Called by GFXDevice to create a device specific stateblock
 574   virtual GFXStateBlockRef createStateBlockInternal(const GFXStateBlockDesc& desc) = 0;
 575   /// Called by GFXDevice to actually set a stateblock.
 576   /// @param force If true, set all states 
 577   virtual void setStateBlockInternal(GFXStateBlock* block, bool force) = 0;
 578   /// @}
 579
 580   /// Called by base GFXDevice to actually set a const buffer
 581   virtual void setShaderConstBufferInternal(GFXShaderConstBuffer* buffer) = 0;
 582
 583   virtual void setTextureInternal(U32 textureUnit, const GFXTextureObject*texture) = 0;
 584
 585   virtual bool beginSceneInternal() = 0;
 586   virtual void endSceneInternal() = 0;
 587
 588   /// @name State Initialization.
 589   /// @{
 590
 591   /// State initialization. This MUST BE CALLED in setVideoMode after the device
 592   /// is created.
 593   virtual void initStates() = 0;
 594   /// @}
 595
 596   //-----------------------------------------------------------------------------
 597protected:
 598
 599
 600   /// @name Buffer Allocation 
 601   /// These methods are implemented per-device and are called by the GFX layer
 602   /// when a user calls an alloc
 603   ///
 604   /// @note Primitive Buffers are NOT implemented per device, they wrap index buffers
 605   /// @{
 606
 607   /// This allocates a vertex buffer and returns a pointer to the allocated buffer.
 608   /// This function should not be called directly - rather it should be used by
 609   /// the GFXVertexBufferHandle class.
 610   virtual GFXVertexBuffer *allocVertexBuffer(  U32 numVerts, 
 611                                                const GFXVertexFormat *vertexFormat, 
 612                                                U32 vertSize, 
 613                                                GFXBufferType bufferType,
 614                                                void* data = NULL ) = 0;
 615
 616   /// Called from GFXVertexFormat to allocate the hardware 
 617   /// specific vertex declaration for rendering.
 618   virtual GFXVertexDecl* allocVertexDecl( const GFXVertexFormat *vertexFormat ) = 0;
 619
 620   /// Sets the current vertex declaration on the device.
 621   virtual void setVertexDecl( const GFXVertexDecl *decl ) = 0;
 622
 623   /// Sets the vertex buffer on the device.
 624   virtual void setVertexStream( U32 stream, GFXVertexBuffer *buffer ) = 0;
 625
 626   /// Set the vertex stream frequency on the device.
 627   virtual void setVertexStreamFrequency( U32 stream, U32 frequency ) = 0;
 628
 629   /// The maximum number of supported vertex streams which
 630   /// may be more than the device supports.
 631   static const U32 VERTEX_STREAM_COUNT = 4;
 632
 633   StrongRefPtr<GFXVertexBuffer> mCurrentVertexBuffer[VERTEX_STREAM_COUNT];
 634   bool mVertexBufferDirty[VERTEX_STREAM_COUNT];
 635   U32 mVertexBufferFrequency[VERTEX_STREAM_COUNT];
 636   bool mVertexBufferFrequencyDirty[VERTEX_STREAM_COUNT];
 637
 638   const GFXVertexDecl *mCurrVertexDecl;
 639   bool mVertexDeclDirty;
 640
 641   StrongRefPtr<GFXPrimitiveBuffer> mCurrentPrimitiveBuffer;
 642   bool mPrimitiveBufferDirty;
 643
 644   /// This allocates a primitive buffer and returns a pointer to the allocated buffer.
 645   /// A primitive buffer's type argument refers to the index data - the primitive data will
 646   /// always be preserved from call to call.
 647   ///
 648   /// @note All index buffers use unsigned 16-bit indices.
 649   virtual GFXPrimitiveBuffer *allocPrimitiveBuffer(  U32 numIndices, 
 650                                                      U32 numPrimitives, 
 651                                                      GFXBufferType bufferType,
 652                                                      void* data = NULL ) = 0;
 653
 654   /// @}
 655
 656protected:
 657
 658   //---------------------------------------
 659   // Render target related
 660   //---------------------------------------
 661   
 662   /// A stack of previously active render targets.
 663   Vector<GFXTargetRef> mRTStack;
 664
 665   /// The current render target which may or may not 
 666   /// not be yet activated.
 667   /// @see mRTDirty
 668   GFXTargetRef mCurrentRT;
 669   
 670   /// This tracks a previously activated render target
 671   /// which need to be deactivated. 
 672   GFXTargetRef mRTDeactivate;
 673   
 674   /// This is set when the current and/or deactivate render
 675   /// targets have changed and the device need to update
 676   /// its state on the next draw/clear.
 677   bool mRTDirty;
 678
 679   /// Updates the render targets and viewport in a device
 680   /// specific manner when they are dirty.
 681   virtual void _updateRenderTargets() = 0;
 682
 683   /// The current viewport rect.
 684   RectI mViewport;
 685
 686   /// If true the viewport has been changed and
 687   /// it must be updated on the next draw/clear.
 688   bool mViewportDirty;
 689
 690public:
 691
 692   /// @name Texture functions
 693   /// @{
 694protected:
 695   GFXTextureManager * mTextureManager;
 696
 697public:   
 698   virtual GFXCubemap * createCubemap() = 0;
 699   virtual GFXCubemapArray *createCubemapArray() = 0;
 700   virtual GFXTextureArray *createTextureArray() = 0;
 701
 702   inline GFXTextureManager *getTextureManager()
 703   {
 704      return mTextureManager;
 705   }
 706
 707   ///@}
 708
 709   /// Swizzle to convert 32bpp bitmaps from RGBA to the native device format.
 710   const Swizzle<U8, 4> *getDeviceSwizzle32() const 
 711   { 
 712      return mDeviceSwizzle32;
 713   }
 714
 715   /// Swizzle to convert 24bpp bitmaps from RGB to the native device format.
 716   const Swizzle<U8, 3> *getDeviceSwizzle24() const 
 717   { 
 718      return mDeviceSwizzle24;
 719   }
 720
 721   /// @name Render Target functions
 722   /// @{
 723
 724   /// Allocate a target for doing render to texture operations, with no
 725   /// depth/stencil buffer.
 726   virtual GFXTextureTarget *allocRenderToTextureTarget(bool genMips = true) = 0;
 727
 728   /// Allocate a target for a given window.
 729   virtual GFXWindowTarget *allocWindowTarget(PlatformWindow *window)=0;
 730
 731   /// Store the current render target to restore later.
 732   void pushActiveRenderTarget();
 733
 734   /// Restore the previous render target.
 735   void popActiveRenderTarget();
 736
 737   /// Assign a new active render target.
 738   void setActiveRenderTarget( GFXTarget *target, bool updateViewport=true );
 739
 740   /// Returns the current active render target.
 741   inline GFXTarget* getActiveRenderTarget() { return mCurrentRT; }
 742
 743   ///@}
 744
 745   /// @name Shader functions
 746   /// @{
 747   virtual F32   getPixelShaderVersion() const = 0;
 748   virtual void  setPixelShaderVersion( F32 version ) = 0;
 749
 750   /// Returns the number of texture samplers that can be used in a shader rendering pass
 751   virtual U32 getNumSamplers() const = 0;
 752
 753   /// Returns the number of simultaneous render targets supported by the device.
 754   virtual U32 getNumRenderTargets() const = 0;
 755
 756   virtual void setShader( GFXShader *shader, bool force = false ) {}
 757
 758   /// Set the buffer! (Actual set happens on the next draw call, just like textures, state blocks, etc)
 759   void setShaderConstBuffer(GFXShaderConstBuffer* buffer);
 760   
 761   /// Creates a new empty shader which must be initialized 
 762   /// and deleted by the caller.
 763   /// @see GFXShader::init
 764   virtual GFXShader* createShader() = 0;
 765   
 766   /// @}
 767 
 768   //-----------------------------------------------------------------------------
 769
 770   /// @name Copying methods
 771   /// @{
 772
 773   virtual void copyResource(GFXTextureObject *pDst, GFXCubemap *pSrc, const U32 face) = 0;
 774
 775   /// @}
 776
 777   /// @name Rendering methods
 778   /// @{
 779
 780   ///
 781   virtual void clear( U32 flags, const LinearColorF& color, F32 z, U32 stencil ) = 0;
 782   virtual void clearColorAttachment(const U32 attachment, const LinearColorF& color) = 0;
 783   virtual bool beginScene();
 784   virtual void endScene();
 785   virtual void beginField();
 786   virtual void endField();
 787   PlatformTimer *mFrameTime;
 788
 789   void setPrimitiveBuffer( GFXPrimitiveBuffer *buffer );
 790
 791   /// Sets the vertex buffer.
 792   ///
 793   /// When setting the stream 0 vertex buffer it will automatically
 794   /// set its associated vertex format as the active format.
 795   ///
 796   /// @param buffer    The vertex buffer or NULL to clear the buffer.
 797   /// @param stream    The stream index of the vertex source stream to place the buffer.
 798   /// @param frequency The stream frequency of the vertex buffer.
 799   void setVertexBuffer( GFXVertexBuffer *buffer, U32 stream = 0, U32 frequency = 0 );
 800
 801   /// Sets the current vertex format.
 802   ///
 803   /// This should only be used if the vertex format of the stream 0 vertex 
 804   /// buffer is different from the one associated to it.  Typically this
 805   /// is used when rendering from multiple vertex streams.
 806   ///
 807   void setVertexFormat( const GFXVertexFormat *vertexFormat );
 808
 809   virtual void drawPrimitive( GFXPrimitiveType primType, U32 vertexStart, U32 primitiveCount ) = 0;
 810
 811   /// The parameters to drawIndexedPrimitive are somewhat complicated. From a raw-data stand point
 812   /// they evaluate to something like the following:
 813   /// @code
 814   /// U16 indicies[] = { 0, 1, 2, 1, 0, 0, 2 }; 
 815   /// Point3F verts[] = { Point3F( 0.0f, 0.0f, 0.0f ), Point3F( 0.0f, 1.0f, 0.0f ), Point3F( 0.0f, 0.0f, 1.0f ) };
 816   /// 
 817   /// GFX->drawIndexedPrimitive( GFXLineList, // Drawing a list of lines, each line is two verts
 818   ///                            0, // vertex 0 will be referenced so minIndex = 0
 819   ///                            3, // 3 verticies will be used for this draw call
 820   ///                            1, // We want index 1 to be the first index used, so indicies 1-6 will be used
 821   ///                            3  // Drawing 3 LineList primitives, meaning 6 verts will be drawn
 822   ///                             );
 823   ///
 824   /// U16 *idxPtr = &indicies[1];  // 1 = startIndex, so the pointer is offset such that:
 825   ///                              //    idxPtr[0] is the same as indicies[1]
 826   ///
 827   /// U32 numVertsToDrawFromBuffer = primitiveCount * 2; // 2 verts define a line in the GFXLineList primitive type (6)
 828   /// @endcode
 829   ///
 830   /// @param  primType    Type of primitive to draw
 831   ///
 832   /// @param  startVertex This defines index zero.  Its the offset from the start of
 833   ///                     the vertex buffer to the first vertex.
 834   ///
 835   /// @param  minIndex    The smallest index into the vertex stream which will be used for this draw call.
 836   ///                     This is a zero based index relative to startVertex.  It is strictly a performance
 837   ///                     hint for implementations. No vertex below minIndex will be referenced by this draw
 838   ///                     call. For device implementors, this should _not_ be used to offset the vertex buffer,
 839   ///                     or index buffer.
 840   ///
 841   /// @param  numVerts    The number of verticies which will be referenced in this draw call. This is not
 842   ///                     the number of verticies which will be drawn. That is a function of 'primType' and 
 843   ///                     'primitiveCount'.
 844   ///
 845   /// @param  startIndex  An offset from the start of the index buffer to specify where to start. If
 846   ///                     'idxBuffer' is a pointer to an array of integers, this could be written as
 847   ///                     int *offsetIdx = idxBuffer + startIndex;
 848   ///
 849   /// @param  primitiveCount The number of primitives of type 'primType' to draw.
 850   ///
 851   virtual void drawIndexedPrimitive(  GFXPrimitiveType primType, 
 852                                       U32 startVertex, 
 853                                       U32 minIndex, 
 854                                       U32 numVerts, 
 855                                       U32 startIndex, 
 856                                       U32 primitiveCount ) = 0;
 857
 858   void drawPrimitive( const GFXPrimitive &prim );
 859   void drawPrimitive( U32 primitiveIndex );
 860   void drawPrimitives();
 861   /// @}
 862
 863   //-----------------------------------------------------------------------------
 864
 865   /// Allocate a fence. The API specific implementation of GFXDevice is responsible
 866   /// to make sure that the proper type is used. GFXGeneralFence should work in
 867   /// all cases. 
 868   virtual GFXFence *createFence() = 0;
 869
 870   /// Returns a hardware occlusion query object or NULL
 871   /// if this device does not support them.   
 872   virtual GFXOcclusionQuery* createOcclusionQuery() { return NULL; }   
 873  
 874   /// @name Texture State Settings
 875   /// NONE of these should be overridden by API implementations
 876   /// because of the state caching stuff.
 877   /// @{
 878
 879   ///
 880   void setTexture(U32 stage, GFXTextureObject *texture);
 881   void setCubeTexture( U32 stage, GFXCubemap *cubemap );
 882   void setCubeArrayTexture( U32 stage, GFXCubemapArray *cubemapArray);
 883   void setTextureArray( U32 stage, GFXTextureArray *textureArray);
 884   inline GFXTextureObject* getCurrentTexture( U32 stage ) { return mCurrentTexture[stage]; }
 885
 886   /// @}
 887
 888   /// @name State Block Interface
 889   /// @{
 890
 891   /// Creates a state block object based on the desc passed in.  This object
 892   /// represents an immutable state.
 893   virtual GFXStateBlockRef createStateBlock( const GFXStateBlockDesc &desc );
 894
 895   /// Sets the current stateblock (actually activated in ::updateStates)
 896   virtual void setStateBlock( GFXStateBlock *block );
 897
 898   GFXStateBlock* getStateBlock() { return mNewStateBlock; }
 899
 900   /// This sets a stateblock directly from the description
 901   /// structure.  Its acceptable to use this for debug rendering
 902   /// and other low frequency rendering tasks.
 903   virtual void setStateBlockByDesc( const GFXStateBlockDesc &desc );
 904
 905   /// @}
 906
 907   /// @name General state interface
 908   /// @{
 909   /// Sets the dirty Render/Texture/Sampler states from the caching system
 910   void updateStates(bool forceSetAll = false);
 911   void clearTextureStateImmediate(U32 stage);
 912
 913   /// Returns the forced global wireframe state.
 914   static bool getWireframe() { return smWireframe; }
 915
 916   /// Returns true if the occlusion query is disabled.
 917   static bool getDisableOcclusionQuery() { return smDisableOcclusionQuery; }
 918   /// @}
 919
 920   //-----------------------------------------------------------------------------
 921
 922   /// @name Matrix interface
 923   /// @{
 924
 925   /// Sets the top of the world matrix stack
 926   /// @param   newWorld   New world matrix to set
 927   void setWorldMatrix( const MatrixF &newWorld );
 928
 929   /// Gets the matrix on the top of the world matrix stack
 930   inline const MatrixF &getWorldMatrix() const { return mWorldMatrix[mWorldStackSize]; }
 931
 932   /// Pushes the world matrix stack and copies the current top
 933   /// matrix to the new top of the stack
 934   void pushWorldMatrix();
 935
 936   /// Pops the world matrix stack
 937   void popWorldMatrix();
 938
 939   /// Sets the projection matrix
 940   /// @param   newProj   New projection matrix to set
 941   void setProjectionMatrix( const MatrixF &newProj );
 942
 943   /// Gets the projection matrix
 944   inline const MatrixF &getProjectionMatrix() const { return mProjectionMatrix; }
 945
 946   /// Sets the view matrix
 947   /// @param   newView   New view matrix to set
 948   void setViewMatrix( const MatrixF &newView );
 949
 950   /// Gets the view matrix
 951   inline const MatrixF &getViewMatrix() const { return mViewMatrix; }
 952
 953   /// Multiplies the matrix at the top of the world matrix stack by a matrix
 954   /// and replaces the top of the matrix stack with the result
 955   /// @param   mat   Matrix to multiply
 956   void multWorld( const MatrixF &mat );
 957
 958   /// Set texture matrix for a sampler
 959   void setTextureMatrix( const U32 stage, const MatrixF &texMat );
 960
 961   /// Set an area of the target to render to.
 962   void setViewport( const RectI &rect );
 963
 964   /// Get the current area of the target we will render to.   
 965   const RectI &getViewport() const { return mViewport; }
 966
 967   virtual void setClipRect( const RectI &rect ) = 0;
 968   virtual const RectI &getClipRect() const = 0;
 969
 970   /// Set the projection frustum.
 971   ///
 972   /// @see MathUtils::makeFrustum()
 973   virtual void setFrustum( F32 left, F32 right,
 974                            F32 bottom, F32 top,
 975                            F32 nearPlane, F32 farPlane,
 976                            bool bRotate = true);
 977
 978   ///
 979   virtual void setFrustum( const Frustum& frust,
 980                            bool bRotate = true );
 981
 982   /// Get the projection frustum.
 983   void getFrustum(  F32 *left, 
 984                     F32 *right, 
 985                     F32 *bottom, 
 986                     F32 *top, 
 987                     F32 *nearPlane, 
 988                     F32 *farPlane, 
 989                     bool *isOrtho ) const;
 990
 991   /// Get the projection frustum.
 992   const Frustum& getFrustum() const { return mFrustum; }
 993
 994   /// This will construct and apply an orthographic projection matrix with the provided parameters
 995   /// @param doRotate If set to true, the resulting matrix will be rotated PI/2 around the X axis
 996   //                  for support in tsShapeInstance. You probably want to leave this as 'false'.
 997   void setOrtho(F32 left, F32 right, F32 bottom, F32 top, F32 nearPlane, F32 farPlane, bool doRotate = false);
 998   
 999   /// Return true if the current frustum uses orthographic projection rather than perspective projection.
1000   bool isFrustumOrtho() const { return mFrustum.isOrtho(); }
1001
1002   /// @}
1003   
1004   /// Returns the scale for converting world space 
1005   /// units to screen space units... aka pixels.
1006   ///
1007   /// This is the true scale which is best used for GUI
1008   /// drawing.  For doing lod calculations you should be
1009   /// using the functions in SceneState which is adjusted
1010   /// for special cases like shadows and reflections.
1011   ///
1012   /// @see SceneState::getWorldToScreenScale()
1013   /// @see SceneState::projectRadius()
1014   ///
1015   Point2F getWorldToScreenScale() const;
1016
1017public:
1018   enum GenericShaderType
1019   {
1020      GSColor = 0,
1021      GSTexture,
1022      GSModColorTexture,
1023      GSAddColorTexture,
1024      GSTargetRestore,
1025      GS_COUNT
1026   };
1027
1028   /// This is a helper function to set a default shader for rendering GUI elements
1029   /// on systems which do not support fixed-function operations as well as for
1030   /// things which need just generic position/texture/color shaders
1031   ///
1032   /// @param  type  Type of generic shader, add your own if you need
1033   virtual void setupGenericShaders( GenericShaderType type = GSColor ) {};
1034
1035   /// Get the fill convention for this device
1036   virtual F32 getFillConventionOffset() const = 0;
1037
1038   virtual U32 getMaxDynamicVerts() = 0;
1039   virtual U32 getMaxDynamicIndices() = 0;
1040
1041   virtual void doParanoidStateCheck(){};
1042
1043   /// Get access to this device's drawing utility class.
1044   GFXDrawUtil *getDrawUtil();
1045
1046#ifndef TORQUE_SHIPPING
1047   /// This is a method designed for debugging. It will allow you to dump the states
1048   /// in the render manager out to a file so that it can be diffed and examined.
1049   void dumpStates( const char *fileName ) const;
1050#else
1051   void dumpStates( const char *fileName ) const {};
1052#endif
1053   protected:
1054      GFXDrawUtil *mDrawer;
1055}; 
1056
1057//-----------------------------------------------------------------------------
1058// Matrix interface
1059
1060inline void GFXDevice::setWorldMatrix( const MatrixF &newWorld )
1061{
1062   mStateDirty = true;
1063   mWorldMatrix[mWorldStackSize] = newWorld;
1064}
1065
1066inline void GFXDevice::pushWorldMatrix()
1067{
1068   mStateDirty = true;
1069   mWorldStackSize++;
1070   AssertFatal( mWorldStackSize < GFX_WORLD_STACK_MAX, "GFX: Exceeded world matrix stack size" );
1071   mWorldMatrix[mWorldStackSize] = mWorldMatrix[mWorldStackSize - 1];
1072}
1073
1074inline void GFXDevice::popWorldMatrix()
1075{
1076   mStateDirty = true;
1077   mWorldStackSize--;
1078   AssertFatal( mWorldStackSize >= 0, "GFX: Negative WorldStackSize!" );
1079}
1080
1081inline void GFXDevice::multWorld( const MatrixF &mat )
1082{
1083   mStateDirty = true;
1084   mWorldMatrix[mWorldStackSize].mul(mat);
1085}
1086
1087inline void GFXDevice::setProjectionMatrix( const MatrixF &newProj )
1088{
1089   mStateDirty = true;
1090   mProjectionMatrix = newProj;
1091}
1092
1093inline void GFXDevice::setViewMatrix( const MatrixF &newView )
1094{
1095   mStateDirty = true;
1096   mViewMatrix = newView;
1097}
1098
1099//-----------------------------------------------------------------------------
1100// Buffer management
1101
1102inline void GFXDevice::setVertexBuffer( GFXVertexBuffer *buffer, U32 stream, U32 frequency )
1103{
1104   AssertFatal( stream < VERTEX_STREAM_COUNT, "GFXDevice::setVertexBuffer - Bad stream index!" );
1105
1106   if ( buffer && stream == 0 )
1107      setVertexFormat( &buffer->mVertexFormat );
1108
1109   if ( buffer != mCurrentVertexBuffer[stream] )
1110   {
1111      mCurrentVertexBuffer[stream] = buffer;
1112      mVertexBufferDirty[stream] = true;
1113      mStateDirty = true;
1114   }
1115
1116   if ( mVertexBufferFrequency[stream] != frequency )
1117   {
1118      mVertexBufferFrequency[stream] = frequency;
1119      mVertexBufferFrequencyDirty[stream] = true;
1120      mStateDirty = true;
1121   }   
1122}
1123
1124inline void GFXDevice::setVertexFormat( const GFXVertexFormat *vertexFormat )
1125{
1126   if ( vertexFormat->getDecl() == mCurrVertexDecl )
1127      return;
1128
1129   mCurrVertexDecl = vertexFormat->getDecl();
1130   mVertexDeclDirty = true;
1131   mStateDirty = true;
1132}
1133
1134
1135#if defined(TORQUE_DEBUG) && defined(TORQUE_DEBUG_GFX)
1136#define GFXAssertFatal(x, error) AssertFatal(x, error)
1137#else
1138#define GFXAssertFatal(x, error)
1139#endif
1140
1141#endif // _GFXDEVICE_H_
1142