gfxDevice.h
Classes:
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