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