~baltix/+junk/irrlicht-test

« back to all changes in this revision

Viewing changes to source/Irrlicht/CD3D9Driver.cpp

  • Committer: Mantas Kriaučiūnas
  • Date: 2011-07-18 13:06:25 UTC
  • Revision ID: mantas@akl.lt-20110718130625-c5pvifp61e7kj1ol
Included whole irrlicht SVN libraries to work around launchpad recipe issue with quilt, see https://answers.launchpad.net/launchpad/+question/165193

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright (C) 2002-2011 Nikolaus Gebhardt
 
2
// This file is part of the "Irrlicht Engine".
 
3
// For conditions of distribution and use, see copyright notice in irrlicht.h
 
4
 
 
5
#define _IRR_DONT_DO_MEMORY_DEBUGGING_HERE
 
6
#include "CD3D9Driver.h"
 
7
 
 
8
#ifdef _IRR_COMPILE_WITH_DIRECT3D_9_
 
9
 
 
10
#include "os.h"
 
11
#include "S3DVertex.h"
 
12
#include "CD3D9Texture.h"
 
13
#include "CD3D9MaterialRenderer.h"
 
14
#include "CD3D9ShaderMaterialRenderer.h"
 
15
#include "CD3D9NormalMapRenderer.h"
 
16
#include "CD3D9ParallaxMapRenderer.h"
 
17
#include "CD3D9HLSLMaterialRenderer.h"
 
18
#include "SIrrCreationParameters.h"
 
19
 
 
20
namespace irr
 
21
{
 
22
namespace video
 
23
{
 
24
 
 
25
namespace
 
26
{
 
27
        inline DWORD F2DW( FLOAT f ) { return *((DWORD*)&f); }
 
28
}
 
29
 
 
30
//! constructor
 
31
CD3D9Driver::CD3D9Driver(const SIrrlichtCreationParameters& params, io::IFileSystem* io)
 
32
        : CNullDriver(io, params.WindowSize), CurrentRenderMode(ERM_NONE),
 
33
        ResetRenderStates(true), Transformation3DChanged(false),
 
34
        D3DLibrary(0), pID3D(0), pID3DDevice(0), PrevRenderTarget(0),
 
35
        WindowId(0), SceneSourceRect(0),
 
36
        LastVertexType((video::E_VERTEX_TYPE)-1), VendorID(0),
 
37
        MaxTextureUnits(0), MaxUserClipPlanes(0), MaxMRTs(1), NumSetMRTs(1),
 
38
        MaxLightDistance(0.f), LastSetLight(-1),
 
39
        ColorFormat(ECF_A8R8G8B8), DeviceLost(false),
 
40
        DriverWasReset(true), OcclusionQuerySupport(false),
 
41
        AlphaToCoverageSupport(false), Params(params)
 
42
{
 
43
        #ifdef _DEBUG
 
44
        setDebugName("CD3D9Driver");
 
45
        #endif
 
46
 
 
47
        printVersion();
 
48
 
 
49
        for (u32 i=0; i<MATERIAL_MAX_TEXTURES; ++i)
 
50
        {
 
51
                CurrentTexture[i] = 0;
 
52
                LastTextureMipMapsAvailable[i] = false;
 
53
        }
 
54
        MaxLightDistance = sqrtf(FLT_MAX);
 
55
        // create sphere map matrix
 
56
 
 
57
        SphereMapMatrixD3D9._11 = 0.5f; SphereMapMatrixD3D9._12 = 0.0f;
 
58
        SphereMapMatrixD3D9._13 = 0.0f; SphereMapMatrixD3D9._14 = 0.0f;
 
59
        SphereMapMatrixD3D9._21 = 0.0f; SphereMapMatrixD3D9._22 =-0.5f;
 
60
        SphereMapMatrixD3D9._23 = 0.0f; SphereMapMatrixD3D9._24 = 0.0f;
 
61
        SphereMapMatrixD3D9._31 = 0.0f; SphereMapMatrixD3D9._32 = 0.0f;
 
62
        SphereMapMatrixD3D9._33 = 1.0f; SphereMapMatrixD3D9._34 = 0.0f;
 
63
        SphereMapMatrixD3D9._41 = 0.5f; SphereMapMatrixD3D9._42 = 0.5f;
 
64
        SphereMapMatrixD3D9._43 = 0.0f; SphereMapMatrixD3D9._44 = 1.0f;
 
65
 
 
66
        core::matrix4 mat;
 
67
        UnitMatrixD3D9 = *(D3DMATRIX*)((void*)mat.pointer());
 
68
 
 
69
        // init direct 3d is done in the factory function
 
70
}
 
71
 
 
72
 
 
73
//! destructor
 
74
CD3D9Driver::~CD3D9Driver()
 
75
{
 
76
        deleteMaterialRenders();
 
77
        deleteAllTextures();
 
78
        removeAllOcclusionQueries();
 
79
        removeAllHardwareBuffers();
 
80
        for (u32 i=0; i<DepthBuffers.size(); ++i)
 
81
        {
 
82
                DepthBuffers[i]->drop();
 
83
        }
 
84
        DepthBuffers.clear();
 
85
 
 
86
        // drop d3d9
 
87
 
 
88
        if (pID3DDevice)
 
89
                pID3DDevice->Release();
 
90
 
 
91
        if (pID3D)
 
92
                pID3D->Release();
 
93
}
 
94
 
 
95
 
 
96
void CD3D9Driver::createMaterialRenderers()
 
97
{
 
98
        // create D3D9 material renderers
 
99
 
 
100
        addAndDropMaterialRenderer(new CD3D9MaterialRenderer_SOLID(pID3DDevice, this));
 
101
        addAndDropMaterialRenderer(new CD3D9MaterialRenderer_SOLID_2_LAYER(pID3DDevice, this));
 
102
 
 
103
        // add the same renderer for all lightmap types
 
104
 
 
105
        CD3D9MaterialRenderer_LIGHTMAP* lmr = new CD3D9MaterialRenderer_LIGHTMAP(pID3DDevice, this);
 
106
        addMaterialRenderer(lmr); // for EMT_LIGHTMAP:
 
107
        addMaterialRenderer(lmr); // for EMT_LIGHTMAP_ADD:
 
108
        addMaterialRenderer(lmr); // for EMT_LIGHTMAP_M2:
 
109
        addMaterialRenderer(lmr); // for EMT_LIGHTMAP_M4:
 
110
        addMaterialRenderer(lmr); // for EMT_LIGHTMAP_LIGHTING:
 
111
        addMaterialRenderer(lmr); // for EMT_LIGHTMAP_LIGHTING_M2:
 
112
        addMaterialRenderer(lmr); // for EMT_LIGHTMAP_LIGHTING_M4:
 
113
        lmr->drop();
 
114
 
 
115
        // add remaining fixed function pipeline material renderers
 
116
 
 
117
        addAndDropMaterialRenderer(new CD3D9MaterialRenderer_DETAIL_MAP(pID3DDevice, this));
 
118
        addAndDropMaterialRenderer(new CD3D9MaterialRenderer_SPHERE_MAP(pID3DDevice, this));
 
119
        addAndDropMaterialRenderer(new CD3D9MaterialRenderer_REFLECTION_2_LAYER(pID3DDevice, this));
 
120
        addAndDropMaterialRenderer(new CD3D9MaterialRenderer_TRANSPARENT_ADD_COLOR(pID3DDevice, this));
 
121
        addAndDropMaterialRenderer(new CD3D9MaterialRenderer_TRANSPARENT_ALPHA_CHANNEL(pID3DDevice, this));
 
122
        addAndDropMaterialRenderer(new CD3D9MaterialRenderer_TRANSPARENT_ALPHA_CHANNEL_REF(pID3DDevice, this));
 
123
        addAndDropMaterialRenderer(new CD3D9MaterialRenderer_TRANSPARENT_VERTEX_ALPHA(pID3DDevice, this));
 
124
        addAndDropMaterialRenderer(new CD3D9MaterialRenderer_TRANSPARENT_REFLECTION_2_LAYER(pID3DDevice, this));
 
125
 
 
126
        // add normal map renderers
 
127
 
 
128
        s32 tmp = 0;
 
129
        video::IMaterialRenderer* renderer = 0;
 
130
 
 
131
        renderer = new CD3D9NormalMapRenderer(pID3DDevice, this, tmp,
 
132
                MaterialRenderers[EMT_SOLID].Renderer);
 
133
        renderer->drop();
 
134
 
 
135
        renderer = new CD3D9NormalMapRenderer(pID3DDevice, this, tmp,
 
136
                MaterialRenderers[EMT_TRANSPARENT_ADD_COLOR].Renderer);
 
137
        renderer->drop();
 
138
 
 
139
        renderer = new CD3D9NormalMapRenderer(pID3DDevice, this, tmp,
 
140
                MaterialRenderers[EMT_TRANSPARENT_VERTEX_ALPHA].Renderer);
 
141
        renderer->drop();
 
142
 
 
143
        // add parallax map renderers
 
144
 
 
145
        renderer = new CD3D9ParallaxMapRenderer(pID3DDevice, this, tmp,
 
146
                MaterialRenderers[EMT_SOLID].Renderer);
 
147
        renderer->drop();
 
148
 
 
149
        renderer = new CD3D9ParallaxMapRenderer(pID3DDevice, this, tmp,
 
150
                MaterialRenderers[EMT_TRANSPARENT_ADD_COLOR].Renderer);
 
151
        renderer->drop();
 
152
 
 
153
        renderer = new CD3D9ParallaxMapRenderer(pID3DDevice, this, tmp,
 
154
                MaterialRenderers[EMT_TRANSPARENT_VERTEX_ALPHA].Renderer);
 
155
        renderer->drop();
 
156
 
 
157
        // add basic 1 texture blending
 
158
        addAndDropMaterialRenderer(new CD3D9MaterialRenderer_ONETEXTURE_BLEND(pID3DDevice, this));
 
159
}
 
160
 
 
161
 
 
162
//! initialises the Direct3D API
 
163
bool CD3D9Driver::initDriver(HWND hwnd, bool pureSoftware)
 
164
{
 
165
        if (!pID3D)
 
166
        {
 
167
                D3DLibrary = LoadLibrary( __TEXT("d3d9.dll") );
 
168
 
 
169
                if (!D3DLibrary)
 
170
                {
 
171
                        os::Printer::log("Error, could not load d3d9.dll.", ELL_ERROR);
 
172
                        return false;
 
173
                }
 
174
 
 
175
                typedef IDirect3D9 * (__stdcall *D3DCREATETYPE)(UINT);
 
176
                D3DCREATETYPE d3dCreate = (D3DCREATETYPE) GetProcAddress(D3DLibrary, "Direct3DCreate9");
 
177
 
 
178
                if (!d3dCreate)
 
179
                {
 
180
                        os::Printer::log("Error, could not get proc adress of Direct3DCreate9.", ELL_ERROR);
 
181
                        return false;
 
182
                }
 
183
 
 
184
                //just like pID3D = Direct3DCreate9(D3D_SDK_VERSION);
 
185
                pID3D = (*d3dCreate)(D3D_SDK_VERSION);
 
186
 
 
187
                if (!pID3D)
 
188
                {
 
189
                        os::Printer::log("Error initializing D3D.", ELL_ERROR);
 
190
                        return false;
 
191
                }
 
192
        }
 
193
 
 
194
        // print device information
 
195
        D3DADAPTER_IDENTIFIER9 dai;
 
196
        if (!FAILED(pID3D->GetAdapterIdentifier(Params.DisplayAdapter, 0, &dai)))
 
197
        {
 
198
                char tmp[512];
 
199
 
 
200
                s32 Product = HIWORD(dai.DriverVersion.HighPart);
 
201
                s32 Version = LOWORD(dai.DriverVersion.HighPart);
 
202
                s32 SubVersion = HIWORD(dai.DriverVersion.LowPart);
 
203
                s32 Build = LOWORD(dai.DriverVersion.LowPart);
 
204
 
 
205
                sprintf(tmp, "%s %s %d.%d.%d.%d", dai.Description, dai.Driver, Product, Version,
 
206
                        SubVersion, Build);
 
207
                os::Printer::log(tmp, ELL_INFORMATION);
 
208
 
 
209
                // Assign vendor name based on vendor id.
 
210
                VendorID= static_cast<u16>(dai.VendorId);
 
211
                switch(dai.VendorId)
 
212
                {
 
213
                        case 0x1002 : VendorName = "ATI Technologies Inc."; break;
 
214
                        case 0x10DE : VendorName = "NVIDIA Corporation"; break;
 
215
                        case 0x102B : VendorName = "Matrox Electronic Systems Ltd."; break;
 
216
                        case 0x121A : VendorName = "3dfx Interactive Inc"; break;
 
217
                        case 0x5333 : VendorName = "S3 Graphics Co., Ltd."; break;
 
218
                        case 0x8086 : VendorName = "Intel Corporation"; break;
 
219
                        default: VendorName = "Unknown VendorId: ";VendorName += (u32)dai.VendorId; break;
 
220
                }
 
221
        }
 
222
 
 
223
        D3DDISPLAYMODE d3ddm;
 
224
        if (FAILED(pID3D->GetAdapterDisplayMode(Params.DisplayAdapter, &d3ddm)))
 
225
        {
 
226
                os::Printer::log("Error: Could not get Adapter Display mode.", ELL_ERROR);
 
227
                return false;
 
228
        }
 
229
 
 
230
        ZeroMemory(&present, sizeof(present));
 
231
 
 
232
        present.BackBufferCount = 1;
 
233
        present.EnableAutoDepthStencil = TRUE;
 
234
        if (Params.Vsync)
 
235
                present.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
 
236
        else
 
237
                present.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
 
238
 
 
239
        if (Params.Fullscreen)
 
240
        {
 
241
                present.BackBufferWidth = Params.WindowSize.Width;
 
242
                present.BackBufferHeight = Params.WindowSize.Height;
 
243
                // request 32bit mode if user specified 32 bit, added by Thomas Stuefe
 
244
                if (Params.Bits == 32)
 
245
                        present.BackBufferFormat = D3DFMT_X8R8G8B8;
 
246
                else
 
247
                        present.BackBufferFormat = D3DFMT_R5G6B5;
 
248
                present.SwapEffect      = D3DSWAPEFFECT_FLIP;
 
249
                present.Windowed        = FALSE;
 
250
                present.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
 
251
        }
 
252
        else
 
253
        {
 
254
                present.BackBufferFormat        = d3ddm.Format;
 
255
                present.SwapEffect              = D3DSWAPEFFECT_DISCARD;
 
256
                present.Windowed                = TRUE;
 
257
        }
 
258
 
 
259
        UINT adapter = Params.DisplayAdapter;
 
260
        D3DDEVTYPE devtype = D3DDEVTYPE_HAL;
 
261
        #ifndef _IRR_D3D_NO_SHADER_DEBUGGING
 
262
        devtype = D3DDEVTYPE_REF;
 
263
        #elif defined(_IRR_USE_NVIDIA_PERFHUD_)
 
264
        for (UINT adapter_i = 0; adapter_i < pID3D->GetAdapterCount(); ++adapter_i)
 
265
        {
 
266
                D3DADAPTER_IDENTIFIER9 identifier;
 
267
                pID3D->GetAdapterIdentifier(adapter_i,0,&identifier);
 
268
                if (strstr(identifier.Description,"PerfHUD") != 0)
 
269
                {
 
270
                        adapter = adapter_i;
 
271
                        devtype = D3DDEVTYPE_REF;
 
272
                        break;
 
273
                }
 
274
        }
 
275
        #endif
 
276
 
 
277
        // enable anti alias if possible and desired
 
278
        if (Params.AntiAlias > 0)
 
279
        {
 
280
                if (Params.AntiAlias > 32)
 
281
                        Params.AntiAlias = 32;
 
282
 
 
283
                DWORD qualityLevels = 0;
 
284
 
 
285
                while(Params.AntiAlias > 0)
 
286
                {
 
287
                        if(SUCCEEDED(pID3D->CheckDeviceMultiSampleType(adapter,
 
288
                                devtype, present.BackBufferFormat, !Params.Fullscreen,
 
289
                                (D3DMULTISAMPLE_TYPE)Params.AntiAlias, &qualityLevels)))
 
290
                        {
 
291
                                present.MultiSampleType = (D3DMULTISAMPLE_TYPE)Params.AntiAlias;
 
292
                                present.MultiSampleQuality = qualityLevels-1;
 
293
                                present.SwapEffect       = D3DSWAPEFFECT_DISCARD;
 
294
                                break;
 
295
                        }
 
296
                        --Params.AntiAlias;
 
297
                }
 
298
 
 
299
                if (Params.AntiAlias==0)
 
300
                {
 
301
                        os::Printer::log("Anti aliasing disabled because hardware/driver lacks necessary caps.", ELL_WARNING);
 
302
                }
 
303
        }
 
304
 
 
305
        // check stencil buffer compatibility
 
306
        if (Params.Stencilbuffer)
 
307
        {
 
308
                present.AutoDepthStencilFormat = D3DFMT_D24S8;
 
309
                if(FAILED(pID3D->CheckDeviceFormat(adapter, devtype,
 
310
                        present.BackBufferFormat, D3DUSAGE_DEPTHSTENCIL,
 
311
                        D3DRTYPE_SURFACE, present.AutoDepthStencilFormat)))
 
312
                {
 
313
                        present.AutoDepthStencilFormat = D3DFMT_D24X4S4;
 
314
                        if(FAILED(pID3D->CheckDeviceFormat(adapter, devtype,
 
315
                                present.BackBufferFormat, D3DUSAGE_DEPTHSTENCIL,
 
316
                                D3DRTYPE_SURFACE, present.AutoDepthStencilFormat)))
 
317
                        {
 
318
                                present.AutoDepthStencilFormat = D3DFMT_D15S1;
 
319
                                if(FAILED(pID3D->CheckDeviceFormat(adapter, devtype,
 
320
                                        present.BackBufferFormat, D3DUSAGE_DEPTHSTENCIL,
 
321
                                        D3DRTYPE_SURFACE, present.AutoDepthStencilFormat)))
 
322
                                {
 
323
                                        os::Printer::log("Device does not support stencilbuffer, disabling stencil buffer.", ELL_WARNING);
 
324
                                        Params.Stencilbuffer = false;
 
325
                                }
 
326
                        }
 
327
                }
 
328
                else
 
329
                if(FAILED(pID3D->CheckDepthStencilMatch(adapter, devtype,
 
330
                        present.BackBufferFormat, present.BackBufferFormat, present.AutoDepthStencilFormat)))
 
331
                {
 
332
                        os::Printer::log("Depth-stencil format is not compatible with display format, disabling stencil buffer.", ELL_WARNING);
 
333
                        Params.Stencilbuffer = false;
 
334
                }
 
335
        }
 
336
        // do not use else here to cope with flag change in previous block
 
337
        if (!Params.Stencilbuffer)
 
338
        {
 
339
                present.AutoDepthStencilFormat = D3DFMT_D32;
 
340
                if(FAILED(pID3D->CheckDeviceFormat(adapter, devtype,
 
341
                        present.BackBufferFormat, D3DUSAGE_DEPTHSTENCIL,
 
342
                        D3DRTYPE_SURFACE, present.AutoDepthStencilFormat)))
 
343
                {
 
344
                        present.AutoDepthStencilFormat = D3DFMT_D24X8;
 
345
                        if(FAILED(pID3D->CheckDeviceFormat(adapter, devtype,
 
346
                                present.BackBufferFormat, D3DUSAGE_DEPTHSTENCIL,
 
347
                                D3DRTYPE_SURFACE, present.AutoDepthStencilFormat)))
 
348
                        {
 
349
                                present.AutoDepthStencilFormat = D3DFMT_D16;
 
350
                                if(FAILED(pID3D->CheckDeviceFormat(adapter, devtype,
 
351
                                        present.BackBufferFormat, D3DUSAGE_DEPTHSTENCIL,
 
352
                                        D3DRTYPE_SURFACE, present.AutoDepthStencilFormat)))
 
353
                                {
 
354
                                        os::Printer::log("Device does not support required depth buffer.", ELL_WARNING);
 
355
                                        return false;
 
356
                                }
 
357
                        }
 
358
                }
 
359
        }
 
360
 
 
361
        // create device
 
362
 
 
363
        DWORD fpuPrecision = Params.HighPrecisionFPU ? D3DCREATE_FPU_PRESERVE : 0;
 
364
        if (pureSoftware)
 
365
        {
 
366
                if (FAILED(pID3D->CreateDevice(Params.DisplayAdapter, D3DDEVTYPE_REF, hwnd,
 
367
                                fpuPrecision | D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present, &pID3DDevice)))
 
368
                        os::Printer::log("Was not able to create Direct3D9 software device.", ELL_ERROR);
 
369
        }
 
370
        else
 
371
        {
 
372
                HRESULT hr = pID3D->CreateDevice(adapter, devtype, hwnd,
 
373
                                fpuPrecision | D3DCREATE_HARDWARE_VERTEXPROCESSING, &present, &pID3DDevice);
 
374
 
 
375
                if(FAILED(hr))
 
376
                        hr = pID3D->CreateDevice(adapter, devtype, hwnd,
 
377
                                        fpuPrecision | D3DCREATE_MIXED_VERTEXPROCESSING , &present, &pID3DDevice);
 
378
 
 
379
                if(FAILED(hr))
 
380
                        hr = pID3D->CreateDevice(adapter, devtype, hwnd,
 
381
                                        fpuPrecision | D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present, &pID3DDevice);
 
382
 
 
383
                if (FAILED(hr))
 
384
                        os::Printer::log("Was not able to create Direct3D9 device.", ELL_ERROR);
 
385
        }
 
386
 
 
387
        if (!pID3DDevice)
 
388
        {
 
389
                os::Printer::log("Was not able to create DIRECT3D9 device.", ELL_ERROR);
 
390
                return false;
 
391
        }
 
392
 
 
393
        // get caps
 
394
        pID3DDevice->GetDeviceCaps(&Caps);
 
395
 
 
396
        os::Printer::log("Currently available Video Memory (kB)", core::stringc(pID3DDevice->GetAvailableTextureMem()/1024).c_str());
 
397
 
 
398
        // disable stencilbuffer if necessary
 
399
        if (Params.Stencilbuffer &&
 
400
                (!(Caps.StencilCaps & D3DSTENCILCAPS_DECRSAT) ||
 
401
                !(Caps.StencilCaps & D3DSTENCILCAPS_INCRSAT) ||
 
402
                !(Caps.StencilCaps & D3DSTENCILCAPS_KEEP)))
 
403
        {
 
404
                os::Printer::log("Device not able to use stencil buffer, disabling stencil buffer.", ELL_WARNING);
 
405
                Params.Stencilbuffer = false;
 
406
        }
 
407
 
 
408
        // set default vertex shader
 
409
        setVertexShader(EVT_STANDARD);
 
410
 
 
411
        // set fog mode
 
412
        setFog(FogColor, FogType, FogStart, FogEnd, FogDensity, PixelFog, RangeFog);
 
413
 
 
414
        // set exposed data
 
415
        ExposedData.D3D9.D3D9 = pID3D;
 
416
        ExposedData.D3D9.D3DDev9 = pID3DDevice;
 
417
        ExposedData.D3D9.HWnd = hwnd;
 
418
 
 
419
        ResetRenderStates = true;
 
420
 
 
421
        // create materials
 
422
        createMaterialRenderers();
 
423
 
 
424
        MaxTextureUnits = core::min_((u32)Caps.MaxSimultaneousTextures, MATERIAL_MAX_TEXTURES);
 
425
        MaxUserClipPlanes = (u32)Caps.MaxUserClipPlanes;
 
426
        MaxMRTs = (s32)Caps.NumSimultaneousRTs;
 
427
        OcclusionQuerySupport=(pID3DDevice->CreateQuery(D3DQUERYTYPE_OCCLUSION, NULL) == S_OK);
 
428
 
 
429
        if (VendorID==0x10DE)//NVidia
 
430
                AlphaToCoverageSupport = (pID3D->CheckDeviceFormat(adapter, D3DDEVTYPE_HAL,
 
431
                                D3DFMT_X8R8G8B8, 0,D3DRTYPE_SURFACE,
 
432
                                (D3DFORMAT)MAKEFOURCC('A', 'T', 'O', 'C')) == S_OK);
 
433
        else if (VendorID==0x1002)//ATI
 
434
                AlphaToCoverageSupport = true; // TODO: Check unknown
 
435
#if 0
 
436
                AlphaToCoverageSupport = (pID3D->CheckDeviceFormat(adapter, D3DDEVTYPE_HAL,
 
437
                                D3DFMT_X8R8G8B8, 0,D3DRTYPE_SURFACE,
 
438
                                (D3DFORMAT)MAKEFOURCC('A','2','M','1')) == S_OK);
 
439
#endif
 
440
 
 
441
        DriverAttributes->setAttribute("MaxTextures", (s32)MaxTextureUnits);
 
442
        DriverAttributes->setAttribute("MaxSupportedTextures", (s32)Caps.MaxSimultaneousTextures);
 
443
        DriverAttributes->setAttribute("MaxLights", (s32)Caps.MaxActiveLights);
 
444
        DriverAttributes->setAttribute("MaxAnisotropy", (s32)Caps.MaxAnisotropy);
 
445
        DriverAttributes->setAttribute("MaxUserClipPlanes", (s32)Caps.MaxUserClipPlanes);
 
446
        DriverAttributes->setAttribute("MaxMultipleRenderTargets", (s32)Caps.NumSimultaneousRTs);
 
447
        DriverAttributes->setAttribute("MaxIndices", (s32)Caps.MaxVertexIndex);
 
448
        DriverAttributes->setAttribute("MaxTextureSize", (s32)core::min_(Caps.MaxTextureHeight,Caps.MaxTextureWidth));
 
449
        DriverAttributes->setAttribute("MaxTextureLODBias", 16);
 
450
        DriverAttributes->setAttribute("Version", 901);
 
451
        DriverAttributes->setAttribute("ShaderLanguageVersion", (s32)(((0x00ff00 & Caps.VertexShaderVersion)>>8)*100 + (Caps.VertexShaderVersion&0xff)));
 
452
        DriverAttributes->setAttribute("AntiAlias", Params.AntiAlias);
 
453
 
 
454
        // set the renderstates
 
455
        setRenderStates3DMode();
 
456
 
 
457
        // store the screen's depth buffer
 
458
        DepthBuffers.push_back(new SDepthSurface());
 
459
        if (SUCCEEDED(pID3DDevice->GetDepthStencilSurface(&(DepthBuffers[0]->Surface))))
 
460
        {
 
461
                D3DSURFACE_DESC desc;
 
462
                DepthBuffers[0]->Surface->GetDesc(&desc);
 
463
                DepthBuffers[0]->Size.set(desc.Width, desc.Height);
 
464
        }
 
465
        else
 
466
        {
 
467
                os::Printer::log("Was not able to get main depth buffer.", ELL_ERROR);
 
468
                return false;
 
469
        }
 
470
 
 
471
        D3DColorFormat = D3DFMT_A8R8G8B8;
 
472
        IDirect3DSurface9* bb=0;
 
473
        if (SUCCEEDED(pID3DDevice->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &bb)))
 
474
        {
 
475
                D3DSURFACE_DESC desc;
 
476
                bb->GetDesc(&desc);
 
477
                D3DColorFormat = desc.Format;
 
478
 
 
479
                if (D3DColorFormat == D3DFMT_X8R8G8B8)
 
480
                        D3DColorFormat = D3DFMT_A8R8G8B8;
 
481
 
 
482
                bb->Release();
 
483
        }
 
484
        ColorFormat = getColorFormatFromD3DFormat(D3DColorFormat);
 
485
 
 
486
        // so far so good.
 
487
        return true;
 
488
}
 
489
 
 
490
 
 
491
//! applications must call this method before performing any rendering. returns false if failed.
 
492
bool CD3D9Driver::beginScene(bool backBuffer, bool zBuffer, SColor color,
 
493
                const SExposedVideoData& videoData, core::rect<s32>* sourceRect)
 
494
{
 
495
        CNullDriver::beginScene(backBuffer, zBuffer, color, videoData, sourceRect);
 
496
        WindowId = (HWND)videoData.D3D9.HWnd;
 
497
        SceneSourceRect = sourceRect;
 
498
 
 
499
        if (!pID3DDevice)
 
500
                return false;
 
501
 
 
502
        HRESULT hr;
 
503
        if (DeviceLost)
 
504
        {
 
505
                if (FAILED(hr = pID3DDevice->TestCooperativeLevel()))
 
506
                {
 
507
                        if (hr == D3DERR_DEVICELOST)
 
508
                        {
 
509
                                Sleep(100);
 
510
                                hr = pID3DDevice->TestCooperativeLevel();
 
511
                                if (hr == D3DERR_DEVICELOST)
 
512
                                        return false;
 
513
                        }
 
514
 
 
515
                        if ((hr == D3DERR_DEVICENOTRESET) && !reset())
 
516
                                return false;
 
517
                }
 
518
        }
 
519
 
 
520
        DWORD flags = 0;
 
521
 
 
522
        if (backBuffer)
 
523
                flags |= D3DCLEAR_TARGET;
 
524
 
 
525
        if (zBuffer)
 
526
                flags |= D3DCLEAR_ZBUFFER;
 
527
 
 
528
        if (Params.Stencilbuffer)
 
529
                flags |= D3DCLEAR_STENCIL;
 
530
 
 
531
        if (flags)
 
532
        {
 
533
                hr = pID3DDevice->Clear( 0, NULL, flags, color.color, 1.0, 0);
 
534
                if (FAILED(hr))
 
535
                        os::Printer::log("DIRECT3D9 clear failed.", ELL_WARNING);
 
536
        }
 
537
 
 
538
        hr = pID3DDevice->BeginScene();
 
539
        if (FAILED(hr))
 
540
        {
 
541
                os::Printer::log("DIRECT3D9 begin scene failed.", ELL_WARNING);
 
542
                return false;
 
543
        }
 
544
 
 
545
        return true;
 
546
}
 
547
 
 
548
 
 
549
//! applications must call this method after performing any rendering. returns false if failed.
 
550
bool CD3D9Driver::endScene()
 
551
{
 
552
        CNullDriver::endScene();
 
553
        DriverWasReset=false;
 
554
 
 
555
        HRESULT hr = pID3DDevice->EndScene();
 
556
        if (FAILED(hr))
 
557
        {
 
558
                os::Printer::log("DIRECT3D9 end scene failed.", ELL_WARNING);
 
559
                return false;
 
560
        }
 
561
 
 
562
        RECT* srcRct = 0;
 
563
        RECT sourceRectData;
 
564
        if ( SceneSourceRect )
 
565
        {
 
566
                srcRct = &sourceRectData;
 
567
                sourceRectData.left = SceneSourceRect->UpperLeftCorner.X;
 
568
                sourceRectData.top = SceneSourceRect->UpperLeftCorner.Y;
 
569
                sourceRectData.right = SceneSourceRect->LowerRightCorner.X;
 
570
                sourceRectData.bottom = SceneSourceRect->LowerRightCorner.Y;
 
571
        }
 
572
 
 
573
        IDirect3DSwapChain9* swChain;
 
574
        hr = pID3DDevice->GetSwapChain(0, &swChain);
 
575
        DWORD flags = (Params.HandleSRGB && (Caps.Caps3&D3DCAPS3_LINEAR_TO_SRGB_PRESENTATION))?D3DPRESENT_LINEAR_CONTENT:0;
 
576
        hr = swChain->Present(srcRct, NULL, WindowId, NULL, flags);
 
577
 
 
578
        if (SUCCEEDED(hr))
 
579
                return true;
 
580
 
 
581
        if (hr == D3DERR_DEVICELOST)
 
582
        {
 
583
                DeviceLost = true;
 
584
                os::Printer::log("Present failed", "DIRECT3D9 device lost.", ELL_WARNING);
 
585
        }
 
586
#ifdef D3DERR_DEVICEREMOVED
 
587
        else if (hr == D3DERR_DEVICEREMOVED)
 
588
        {
 
589
                os::Printer::log("Present failed", "Device removed.", ELL_WARNING);
 
590
        }
 
591
#endif
 
592
        else if (hr == D3DERR_INVALIDCALL)
 
593
        {
 
594
                os::Printer::log("Present failed", "Invalid Call", ELL_WARNING);
 
595
        }
 
596
        else
 
597
                os::Printer::log("DIRECT3D9 present failed.", ELL_WARNING);
 
598
        return false;
 
599
}
 
600
 
 
601
 
 
602
//! queries the features of the driver, returns true if feature is available
 
603
bool CD3D9Driver::queryFeature(E_VIDEO_DRIVER_FEATURE feature) const
 
604
{
 
605
        if (!FeatureEnabled[feature])
 
606
                return false;
 
607
 
 
608
        switch (feature)
 
609
        {
 
610
        case EVDF_MULTITEXTURE:
 
611
        case EVDF_BILINEAR_FILTER:
 
612
                return true;
 
613
        case EVDF_RENDER_TO_TARGET:
 
614
                return Caps.NumSimultaneousRTs > 0;
 
615
        case EVDF_HARDWARE_TL:
 
616
                return (Caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) != 0;
 
617
        case EVDF_MIP_MAP:
 
618
                return (Caps.TextureCaps & D3DPTEXTURECAPS_MIPMAP) != 0;
 
619
        case EVDF_MIP_MAP_AUTO_UPDATE:
 
620
                // always return false because a lot of drivers claim they do
 
621
                // this but actually don't do this at all.
 
622
                return false; //(Caps.Caps2 & D3DCAPS2_CANAUTOGENMIPMAP) != 0;
 
623
        case EVDF_STENCIL_BUFFER:
 
624
                return Params.Stencilbuffer && Caps.StencilCaps;
 
625
        case EVDF_VERTEX_SHADER_1_1:
 
626
                return Caps.VertexShaderVersion >= D3DVS_VERSION(1,1);
 
627
        case EVDF_VERTEX_SHADER_2_0:
 
628
                return Caps.VertexShaderVersion >= D3DVS_VERSION(2,0);
 
629
        case EVDF_VERTEX_SHADER_3_0:
 
630
                return Caps.VertexShaderVersion >= D3DVS_VERSION(3,0);
 
631
        case EVDF_PIXEL_SHADER_1_1:
 
632
                return Caps.PixelShaderVersion >= D3DPS_VERSION(1,1);
 
633
        case EVDF_PIXEL_SHADER_1_2:
 
634
                return Caps.PixelShaderVersion >= D3DPS_VERSION(1,2);
 
635
        case EVDF_PIXEL_SHADER_1_3:
 
636
                return Caps.PixelShaderVersion >= D3DPS_VERSION(1,3);
 
637
        case EVDF_PIXEL_SHADER_1_4:
 
638
                return Caps.PixelShaderVersion >= D3DPS_VERSION(1,4);
 
639
        case EVDF_PIXEL_SHADER_2_0:
 
640
                return Caps.PixelShaderVersion >= D3DPS_VERSION(2,0);
 
641
        case EVDF_PIXEL_SHADER_3_0:
 
642
                return Caps.PixelShaderVersion >= D3DPS_VERSION(3,0);
 
643
        case EVDF_HLSL:
 
644
                return Caps.VertexShaderVersion >= D3DVS_VERSION(1,1);
 
645
        case EVDF_TEXTURE_NSQUARE:
 
646
                return (Caps.TextureCaps & D3DPTEXTURECAPS_SQUAREONLY) == 0;
 
647
        case EVDF_TEXTURE_NPOT:
 
648
                return (Caps.TextureCaps & D3DPTEXTURECAPS_POW2) == 0;
 
649
        case EVDF_COLOR_MASK:
 
650
                return (Caps.PrimitiveMiscCaps & D3DPMISCCAPS_COLORWRITEENABLE) != 0;
 
651
        case EVDF_MULTIPLE_RENDER_TARGETS:
 
652
                return Caps.NumSimultaneousRTs > 1;
 
653
        case EVDF_MRT_COLOR_MASK:
 
654
                return (Caps.PrimitiveMiscCaps & D3DPMISCCAPS_INDEPENDENTWRITEMASKS) != 0;
 
655
        case EVDF_MRT_BLEND:
 
656
                return (Caps.PrimitiveMiscCaps & D3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING) != 0;
 
657
        case EVDF_OCCLUSION_QUERY:
 
658
                return OcclusionQuerySupport;
 
659
        case EVDF_POLYGON_OFFSET:
 
660
                return (Caps.RasterCaps & (D3DPRASTERCAPS_DEPTHBIAS|D3DPRASTERCAPS_SLOPESCALEDEPTHBIAS)) != 0;
 
661
        case EVDF_BLEND_OPERATIONS:
 
662
        case EVDF_TEXTURE_MATRIX:
 
663
                return true;
 
664
        default:
 
665
                return false;
 
666
        };
 
667
}
 
668
 
 
669
 
 
670
//! sets transformation
 
671
void CD3D9Driver::setTransform(E_TRANSFORMATION_STATE state,
 
672
                const core::matrix4& mat)
 
673
{
 
674
        Transformation3DChanged = true;
 
675
 
 
676
        switch(state)
 
677
        {
 
678
        case ETS_VIEW:
 
679
                pID3DDevice->SetTransform(D3DTS_VIEW, (D3DMATRIX*)((void*)mat.pointer()));
 
680
                break;
 
681
        case ETS_WORLD:
 
682
                pID3DDevice->SetTransform(D3DTS_WORLD, (D3DMATRIX*)((void*)mat.pointer()));
 
683
                break;
 
684
        case ETS_PROJECTION:
 
685
                pID3DDevice->SetTransform( D3DTS_PROJECTION, (D3DMATRIX*)((void*)mat.pointer()));
 
686
                break;
 
687
        case ETS_COUNT:
 
688
                return;
 
689
        default:
 
690
                if (state-ETS_TEXTURE_0 < MATERIAL_MAX_TEXTURES)
 
691
                {
 
692
                        if (mat.isIdentity())
 
693
                                pID3DDevice->SetTextureStageState( state - ETS_TEXTURE_0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE );
 
694
                        else
 
695
                        {
 
696
                                pID3DDevice->SetTextureStageState( state - ETS_TEXTURE_0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2 );
 
697
                                pID3DDevice->SetTransform((D3DTRANSFORMSTATETYPE)(D3DTS_TEXTURE0+ ( state - ETS_TEXTURE_0 )),
 
698
                                        (D3DMATRIX*)((void*)mat.pointer()));
 
699
                        }
 
700
                }
 
701
                break;
 
702
        }
 
703
 
 
704
        Matrices[state] = mat;
 
705
}
 
706
 
 
707
 
 
708
//! sets the current Texture
 
709
bool CD3D9Driver::setActiveTexture(u32 stage, const video::ITexture* texture)
 
710
{
 
711
        if (CurrentTexture[stage] == texture)
 
712
                return true;
 
713
 
 
714
        if (texture && texture->getDriverType() != EDT_DIRECT3D9)
 
715
        {
 
716
                os::Printer::log("Fatal Error: Tried to set a texture not owned by this driver.", ELL_ERROR);
 
717
                return false;
 
718
        }
 
719
 
 
720
        CurrentTexture[stage] = texture;
 
721
 
 
722
        if (!texture)
 
723
        {
 
724
                pID3DDevice->SetTexture(stage, 0);
 
725
                pID3DDevice->SetTextureStageState( stage, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE );
 
726
        }
 
727
        else
 
728
        {
 
729
                pID3DDevice->SetTexture(stage, ((const CD3D9Texture*)texture)->getDX9Texture());
 
730
        }
 
731
        return true;
 
732
}
 
733
 
 
734
 
 
735
//! sets a material
 
736
void CD3D9Driver::setMaterial(const SMaterial& material)
 
737
{
 
738
        Material = material;
 
739
        OverrideMaterial.apply(Material);
 
740
 
 
741
        for (u32 i=0; i<MaxTextureUnits; ++i)
 
742
        {
 
743
                setActiveTexture(i, Material.getTexture(i));
 
744
                setTransform((E_TRANSFORMATION_STATE) ( ETS_TEXTURE_0 + i ),
 
745
                                material.getTextureMatrix(i));
 
746
        }
 
747
}
 
748
 
 
749
 
 
750
//! returns a device dependent texture from a software surface (IImage)
 
751
video::ITexture* CD3D9Driver::createDeviceDependentTexture(IImage* surface,const io::path& name, void* mipmapData)
 
752
{
 
753
        return new CD3D9Texture(surface, this, TextureCreationFlags, name, mipmapData);
 
754
}
 
755
 
 
756
 
 
757
//! Enables or disables a texture creation flag.
 
758
void CD3D9Driver::setTextureCreationFlag(E_TEXTURE_CREATION_FLAG flag,
 
759
                bool enabled)
 
760
{
 
761
        if (flag == video::ETCF_CREATE_MIP_MAPS && !queryFeature(EVDF_MIP_MAP))
 
762
                enabled = false;
 
763
 
 
764
        CNullDriver::setTextureCreationFlag(flag, enabled);
 
765
}
 
766
 
 
767
 
 
768
//! sets a render target
 
769
bool CD3D9Driver::setRenderTarget(video::ITexture* texture,
 
770
                bool clearBackBuffer, bool clearZBuffer, SColor color)
 
771
{
 
772
        // check for right driver type
 
773
 
 
774
        if (texture && texture->getDriverType() != EDT_DIRECT3D9)
 
775
        {
 
776
                os::Printer::log("Fatal Error: Tried to set a texture not owned by this driver.", ELL_ERROR);
 
777
                return false;
 
778
        }
 
779
 
 
780
        // check for valid render target
 
781
 
 
782
        if (texture && !texture->isRenderTarget())
 
783
        {
 
784
                os::Printer::log("Fatal Error: Tried to set a non render target texture as render target.", ELL_ERROR);
 
785
                return false;
 
786
        }
 
787
 
 
788
        CD3D9Texture* tex = static_cast<CD3D9Texture*>(texture);
 
789
 
 
790
        // check if we should set the previous RT back
 
791
 
 
792
        bool ret = true;
 
793
 
 
794
        for(u32 i = 1; i < NumSetMRTs; i++)
 
795
        {
 
796
                // First texture handled elsewhere
 
797
                pID3DDevice->SetRenderTarget(i, NULL);
 
798
        }
 
799
        if (tex == 0)
 
800
        {
 
801
                if (PrevRenderTarget)
 
802
                {
 
803
                        if (FAILED(pID3DDevice->SetRenderTarget(0, PrevRenderTarget)))
 
804
                        {
 
805
                                os::Printer::log("Error: Could not set back to previous render target.", ELL_ERROR);
 
806
                                ret = false;
 
807
                        }
 
808
                        if (FAILED(pID3DDevice->SetDepthStencilSurface(DepthBuffers[0]->Surface)))
 
809
                        {
 
810
                                os::Printer::log("Error: Could not set main depth buffer.", ELL_ERROR);
 
811
                        }
 
812
 
 
813
                        CurrentRendertargetSize = core::dimension2d<u32>(0,0);
 
814
                        PrevRenderTarget->Release();
 
815
                        PrevRenderTarget = 0;
 
816
                }
 
817
        }
 
818
        else
 
819
        {
 
820
                // we want to set a new target. so do this.
 
821
 
 
822
                // store previous target
 
823
 
 
824
                if (!PrevRenderTarget)
 
825
                {
 
826
                        if (FAILED(pID3DDevice->GetRenderTarget(0, &PrevRenderTarget)))
 
827
                        {
 
828
                                os::Printer::log("Could not get previous render target.", ELL_ERROR);
 
829
                                return false;
 
830
                        }
 
831
                }
 
832
 
 
833
                // set new render target
 
834
 
 
835
                if (FAILED(pID3DDevice->SetRenderTarget(0, tex->getRenderTargetSurface())))
 
836
                {
 
837
                        os::Printer::log("Error: Could not set render target.", ELL_ERROR);
 
838
                        return false;
 
839
                }
 
840
                CurrentRendertargetSize = tex->getSize();
 
841
 
 
842
                if (FAILED(pID3DDevice->SetDepthStencilSurface(tex->DepthSurface->Surface)))
 
843
                {
 
844
                        os::Printer::log("Error: Could not set new depth buffer.", ELL_ERROR);
 
845
                }
 
846
        }
 
847
        Transformation3DChanged=true;
 
848
 
 
849
        if (clearBackBuffer || clearZBuffer)
 
850
        {
 
851
                DWORD flags = 0;
 
852
 
 
853
                if (clearBackBuffer)
 
854
                        flags |= D3DCLEAR_TARGET;
 
855
 
 
856
                if (clearZBuffer)
 
857
                        flags |= D3DCLEAR_ZBUFFER;
 
858
 
 
859
                pID3DDevice->Clear(0, NULL, flags, color.color, 1.0f, 0);
 
860
        }
 
861
 
 
862
        return ret;
 
863
}
 
864
 
 
865
 
 
866
//! Sets multiple render targets
 
867
bool CD3D9Driver::setRenderTarget(const core::array<video::IRenderTarget>& targets,
 
868
                                bool clearBackBuffer, bool clearZBuffer, SColor color)
 
869
{
 
870
        if (targets.size()==0)
 
871
                return setRenderTarget(0, clearBackBuffer, clearZBuffer, color);
 
872
 
 
873
        u32 maxMultipleRTTs = core::min_(MaxMRTs, targets.size());
 
874
 
 
875
        for (u32 i = 0; i < maxMultipleRTTs; ++i)
 
876
        {
 
877
                if (targets[i].TargetType != ERT_RENDER_TEXTURE || !targets[i].RenderTexture)
 
878
                {
 
879
                        maxMultipleRTTs = i;
 
880
                        os::Printer::log("Missing texture for MRT.", ELL_WARNING);
 
881
                        break;
 
882
                }
 
883
 
 
884
                // check for right driver type
 
885
 
 
886
                if (targets[i].RenderTexture->getDriverType() != EDT_DIRECT3D9)
 
887
                {
 
888
                        maxMultipleRTTs = i;
 
889
                        os::Printer::log("Tried to set a texture not owned by this driver.", ELL_WARNING);
 
890
                        break;
 
891
                }
 
892
 
 
893
                // check for valid render target
 
894
 
 
895
                if (!targets[i].RenderTexture->isRenderTarget())
 
896
                {
 
897
                        maxMultipleRTTs = i;
 
898
                        os::Printer::log("Tried to set a non render target texture as render target.", ELL_WARNING);
 
899
                        break;
 
900
                }
 
901
 
 
902
                // check for valid size
 
903
 
 
904
                if (targets[0].RenderTexture->getSize() != targets[i].RenderTexture->getSize())
 
905
                {
 
906
                        maxMultipleRTTs = i;
 
907
                        os::Printer::log("Render target texture has wrong size.", ELL_WARNING);
 
908
                        break;
 
909
                }
 
910
        }
 
911
        if (maxMultipleRTTs==0)
 
912
        {
 
913
                os::Printer::log("Fatal Error: No valid MRT found.", ELL_ERROR);
 
914
                return false;
 
915
        }
 
916
 
 
917
        CD3D9Texture* tex = static_cast<CD3D9Texture*>(targets[0].RenderTexture);
 
918
 
 
919
        // check if we should set the previous RT back
 
920
 
 
921
        bool ret = true;
 
922
 
 
923
        // we want to set a new target. so do this.
 
924
        // store previous target
 
925
 
 
926
        if (!PrevRenderTarget)
 
927
        {
 
928
                if (FAILED(pID3DDevice->GetRenderTarget(0, &PrevRenderTarget)))
 
929
                {
 
930
                        os::Printer::log("Could not get previous render target.", ELL_ERROR);
 
931
                        return false;
 
932
                }
 
933
        }
 
934
 
 
935
        // set new render target
 
936
 
 
937
        // In d3d9 we have at most 4 MRTs, so the following is enough
 
938
        D3DRENDERSTATETYPE colorWrite[4]={D3DRS_COLORWRITEENABLE, D3DRS_COLORWRITEENABLE1, D3DRS_COLORWRITEENABLE2, D3DRS_COLORWRITEENABLE3};
 
939
        for (u32 i = 0; i < maxMultipleRTTs; ++i)
 
940
        {
 
941
                if (FAILED(pID3DDevice->SetRenderTarget(i, static_cast<CD3D9Texture*>(targets[i].RenderTexture)->getRenderTargetSurface())))
 
942
                {
 
943
                        os::Printer::log("Error: Could not set render target.", ELL_ERROR);
 
944
                        return false;
 
945
                }
 
946
                if (i<4 && (i==0 || queryFeature(EVDF_MRT_COLOR_MASK)))
 
947
                {
 
948
                        const DWORD flag =
 
949
                                ((targets[i].ColorMask & ECP_RED)?D3DCOLORWRITEENABLE_RED:0) |
 
950
                                ((targets[i].ColorMask & ECP_GREEN)?D3DCOLORWRITEENABLE_GREEN:0) |
 
951
                                ((targets[i].ColorMask & ECP_BLUE)?D3DCOLORWRITEENABLE_BLUE:0) |
 
952
                                ((targets[i].ColorMask & ECP_ALPHA)?D3DCOLORWRITEENABLE_ALPHA:0);
 
953
                        pID3DDevice->SetRenderState(colorWrite[i], flag);
 
954
                }
 
955
        }
 
956
        for(u32 i = maxMultipleRTTs; i < NumSetMRTs; i++)
 
957
        {
 
958
                pID3DDevice->SetRenderTarget(i, NULL);
 
959
        }
 
960
        NumSetMRTs=maxMultipleRTTs;
 
961
 
 
962
        CurrentRendertargetSize = tex->getSize();
 
963
 
 
964
        if (FAILED(pID3DDevice->SetDepthStencilSurface(tex->DepthSurface->Surface)))
 
965
        {
 
966
                os::Printer::log("Error: Could not set new depth buffer.", ELL_ERROR);
 
967
        }
 
968
 
 
969
        if (clearBackBuffer || clearZBuffer)
 
970
        {
 
971
                DWORD flags = 0;
 
972
 
 
973
                if (clearBackBuffer)
 
974
                        flags |= D3DCLEAR_TARGET;
 
975
 
 
976
                if (clearZBuffer)
 
977
                        flags |= D3DCLEAR_ZBUFFER;
 
978
 
 
979
                pID3DDevice->Clear(0, NULL, flags, color.color, 1.0f, 0);
 
980
        }
 
981
 
 
982
        return ret;
 
983
}
 
984
 
 
985
 
 
986
//! sets a viewport
 
987
void CD3D9Driver::setViewPort(const core::rect<s32>& area)
 
988
{
 
989
        core::rect<s32> vp = area;
 
990
        core::rect<s32> rendert(0,0, getCurrentRenderTargetSize().Width, getCurrentRenderTargetSize().Height);
 
991
        vp.clipAgainst(rendert);
 
992
        if (vp.getHeight()>0 && vp.getWidth()>0)
 
993
        {
 
994
                D3DVIEWPORT9 viewPort;
 
995
                viewPort.X = vp.UpperLeftCorner.X;
 
996
                viewPort.Y = vp.UpperLeftCorner.Y;
 
997
                viewPort.Width = vp.getWidth();
 
998
                viewPort.Height = vp.getHeight();
 
999
                viewPort.MinZ = 0.0f;
 
1000
                viewPort.MaxZ = 1.0f;
 
1001
 
 
1002
                HRESULT hr = pID3DDevice->SetViewport(&viewPort);
 
1003
                if (FAILED(hr))
 
1004
                        os::Printer::log("Failed setting the viewport.", ELL_WARNING);
 
1005
                else
 
1006
                        ViewPort = vp;
 
1007
        }
 
1008
}
 
1009
 
 
1010
 
 
1011
//! gets the area of the current viewport
 
1012
const core::rect<s32>& CD3D9Driver::getViewPort() const
 
1013
{
 
1014
        return ViewPort;
 
1015
}
 
1016
 
 
1017
 
 
1018
bool CD3D9Driver::updateVertexHardwareBuffer(SHWBufferLink_d3d9 *hwBuffer)
 
1019
{
 
1020
        if (!hwBuffer)
 
1021
                return false;
 
1022
 
 
1023
        const scene::IMeshBuffer* mb = hwBuffer->MeshBuffer;
 
1024
        const void* vertices=mb->getVertices();
 
1025
        const u32 vertexCount=mb->getVertexCount();
 
1026
        const E_VERTEX_TYPE vType=mb->getVertexType();
 
1027
        const u32 vertexSize = getVertexPitchFromType(vType);
 
1028
        const u32 bufSize = vertexSize * vertexCount;
 
1029
 
 
1030
        if (!hwBuffer->vertexBuffer || (bufSize > hwBuffer->vertexBufferSize))
 
1031
        {
 
1032
                if (hwBuffer->vertexBuffer)
 
1033
                {
 
1034
                        hwBuffer->vertexBuffer->Release();
 
1035
                        hwBuffer->vertexBuffer=0;
 
1036
                }
 
1037
 
 
1038
                DWORD FVF;
 
1039
                // Get the vertex sizes and cvf
 
1040
                switch (vType)
 
1041
                {
 
1042
                        case EVT_STANDARD:
 
1043
                                FVF = D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_TEX1;
 
1044
                                break;
 
1045
                        case EVT_2TCOORDS:
 
1046
                                FVF = D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_TEX2;
 
1047
                                break;
 
1048
                        case EVT_TANGENTS:
 
1049
                                FVF = D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_TEX3;
 
1050
                                break;
 
1051
                        default:
 
1052
                                return false;
 
1053
                }
 
1054
 
 
1055
                DWORD flags = D3DUSAGE_WRITEONLY; // SIO2: Default to D3DUSAGE_WRITEONLY
 
1056
                if(hwBuffer->Mapped_Vertex != scene::EHM_STATIC)
 
1057
                        flags |= D3DUSAGE_DYNAMIC;
 
1058
 
 
1059
                if (FAILED(pID3DDevice->CreateVertexBuffer(bufSize, flags, FVF, D3DPOOL_DEFAULT, &hwBuffer->vertexBuffer, NULL)))
 
1060
                        return false;
 
1061
                hwBuffer->vertexBufferSize = bufSize;
 
1062
 
 
1063
                flags = 0; // SIO2: Reset flags before Lock
 
1064
                if(hwBuffer->Mapped_Vertex != scene::EHM_STATIC)
 
1065
                        flags = D3DLOCK_DISCARD;
 
1066
 
 
1067
                void* lockedBuffer = 0;
 
1068
                hwBuffer->vertexBuffer->Lock(0, bufSize, (void**)&lockedBuffer, flags);
 
1069
                memcpy(lockedBuffer, vertices, bufSize);
 
1070
                hwBuffer->vertexBuffer->Unlock();
 
1071
        }
 
1072
        else
 
1073
        {
 
1074
                void* lockedBuffer = 0;
 
1075
                hwBuffer->vertexBuffer->Lock(0, bufSize, (void**)&lockedBuffer, D3DLOCK_DISCARD);
 
1076
                memcpy(lockedBuffer, vertices, bufSize);
 
1077
                hwBuffer->vertexBuffer->Unlock();
 
1078
        }
 
1079
 
 
1080
        return true;
 
1081
}
 
1082
 
 
1083
 
 
1084
bool CD3D9Driver::updateIndexHardwareBuffer(SHWBufferLink_d3d9 *hwBuffer)
 
1085
{
 
1086
        if (!hwBuffer)
 
1087
                return false;
 
1088
 
 
1089
        const scene::IMeshBuffer* mb = hwBuffer->MeshBuffer;
 
1090
        const u16* indices=mb->getIndices();
 
1091
        const u32 indexCount=mb->getIndexCount();
 
1092
        u32 indexSize = 2;
 
1093
        D3DFORMAT indexType=D3DFMT_UNKNOWN;
 
1094
        switch (mb->getIndexType())
 
1095
        {
 
1096
                case EIT_16BIT:
 
1097
                {
 
1098
                        indexType=D3DFMT_INDEX16;
 
1099
                        indexSize = 2;
 
1100
                        break;
 
1101
                }
 
1102
                case EIT_32BIT:
 
1103
                {
 
1104
                        indexType=D3DFMT_INDEX32;
 
1105
                        indexSize = 4;
 
1106
                        break;
 
1107
                }
 
1108
        }
 
1109
 
 
1110
        const u32 bufSize = indexSize * indexCount;
 
1111
        if (!hwBuffer->indexBuffer || (bufSize > hwBuffer->indexBufferSize))
 
1112
        {
 
1113
                if (hwBuffer->indexBuffer)
 
1114
                {
 
1115
                        hwBuffer->indexBuffer->Release();
 
1116
                        hwBuffer->indexBuffer=0;
 
1117
                }
 
1118
 
 
1119
                DWORD flags = D3DUSAGE_WRITEONLY; // SIO2: Default to D3DUSAGE_WRITEONLY
 
1120
                if (hwBuffer->Mapped_Index != scene::EHM_STATIC)
 
1121
                        flags |= D3DUSAGE_DYNAMIC; // SIO2: Add DYNAMIC flag for dynamic buffer data
 
1122
 
 
1123
                if (FAILED(pID3DDevice->CreateIndexBuffer(bufSize, flags, indexType, D3DPOOL_DEFAULT, &hwBuffer->indexBuffer, NULL)))
 
1124
                        return false;
 
1125
 
 
1126
                flags = 0; // SIO2: Reset flags before Lock
 
1127
                if (hwBuffer->Mapped_Index != scene::EHM_STATIC)
 
1128
                        flags = D3DLOCK_DISCARD;
 
1129
 
 
1130
                void* lockedBuffer = 0;
 
1131
                if (FAILED(hwBuffer->indexBuffer->Lock( 0, 0, (void**)&lockedBuffer, flags)))
 
1132
                        return false;
 
1133
 
 
1134
                memcpy(lockedBuffer, indices, bufSize);
 
1135
                hwBuffer->indexBuffer->Unlock();
 
1136
 
 
1137
                hwBuffer->indexBufferSize = bufSize;
 
1138
        }
 
1139
        else
 
1140
        {
 
1141
                void* lockedBuffer = 0;
 
1142
                if( SUCCEEDED(hwBuffer->indexBuffer->Lock( 0, 0, (void**)&lockedBuffer, D3DLOCK_DISCARD)))
 
1143
                {
 
1144
                        memcpy(lockedBuffer, indices, bufSize);
 
1145
                        hwBuffer->indexBuffer->Unlock();
 
1146
                }
 
1147
        }
 
1148
 
 
1149
        return true;
 
1150
}
 
1151
 
 
1152
 
 
1153
//! updates hardware buffer if needed
 
1154
bool CD3D9Driver::updateHardwareBuffer(SHWBufferLink *hwBuffer)
 
1155
{
 
1156
        if (!hwBuffer)
 
1157
                return false;
 
1158
 
 
1159
        if (hwBuffer->Mapped_Vertex!=scene::EHM_NEVER)
 
1160
        {
 
1161
                if (hwBuffer->ChangedID_Vertex != hwBuffer->MeshBuffer->getChangedID_Vertex()
 
1162
                        || !((SHWBufferLink_d3d9*)hwBuffer)->vertexBuffer)
 
1163
                {
 
1164
                        hwBuffer->ChangedID_Vertex = hwBuffer->MeshBuffer->getChangedID_Vertex();
 
1165
 
 
1166
                        if (!updateVertexHardwareBuffer((SHWBufferLink_d3d9*)hwBuffer))
 
1167
                                return false;
 
1168
                }
 
1169
        }
 
1170
 
 
1171
        if (hwBuffer->Mapped_Index!=scene::EHM_NEVER)
 
1172
        {
 
1173
                if (hwBuffer->ChangedID_Index != hwBuffer->MeshBuffer->getChangedID_Index()
 
1174
                        || !((SHWBufferLink_d3d9*)hwBuffer)->indexBuffer)
 
1175
                {
 
1176
                        hwBuffer->ChangedID_Index = hwBuffer->MeshBuffer->getChangedID_Index();
 
1177
 
 
1178
                        if (!updateIndexHardwareBuffer((SHWBufferLink_d3d9*)hwBuffer))
 
1179
                                return false;
 
1180
                }
 
1181
        }
 
1182
 
 
1183
        return true;
 
1184
}
 
1185
 
 
1186
 
 
1187
//! Create hardware buffer from meshbuffer
 
1188
CD3D9Driver::SHWBufferLink *CD3D9Driver::createHardwareBuffer(const scene::IMeshBuffer* mb)
 
1189
{
 
1190
        if (!mb || (mb->getHardwareMappingHint_Index()==scene::EHM_NEVER && mb->getHardwareMappingHint_Vertex()==scene::EHM_NEVER))
 
1191
                return 0;
 
1192
 
 
1193
        SHWBufferLink_d3d9 *hwBuffer=new SHWBufferLink_d3d9(mb);
 
1194
 
 
1195
        //add to map
 
1196
        HWBufferMap.insert(hwBuffer->MeshBuffer, hwBuffer);
 
1197
 
 
1198
        hwBuffer->ChangedID_Vertex=hwBuffer->MeshBuffer->getChangedID_Vertex();
 
1199
        hwBuffer->ChangedID_Index=hwBuffer->MeshBuffer->getChangedID_Index();
 
1200
        hwBuffer->Mapped_Vertex=mb->getHardwareMappingHint_Vertex();
 
1201
        hwBuffer->Mapped_Index=mb->getHardwareMappingHint_Index();
 
1202
        hwBuffer->LastUsed=0;
 
1203
        hwBuffer->vertexBuffer=0;
 
1204
        hwBuffer->indexBuffer=0;
 
1205
        hwBuffer->vertexBufferSize=0;
 
1206
        hwBuffer->indexBufferSize=0;
 
1207
 
 
1208
        if (!updateHardwareBuffer(hwBuffer))
 
1209
        {
 
1210
                deleteHardwareBuffer(hwBuffer);
 
1211
                return 0;
 
1212
        }
 
1213
 
 
1214
        return hwBuffer;
 
1215
}
 
1216
 
 
1217
 
 
1218
void CD3D9Driver::deleteHardwareBuffer(SHWBufferLink *_HWBuffer)
 
1219
{
 
1220
        if (!_HWBuffer)
 
1221
                return;
 
1222
 
 
1223
        SHWBufferLink_d3d9 *HWBuffer=(SHWBufferLink_d3d9*)_HWBuffer;
 
1224
        if (HWBuffer->indexBuffer)
 
1225
        {
 
1226
                HWBuffer->indexBuffer->Release();
 
1227
                HWBuffer->indexBuffer = 0;
 
1228
        }
 
1229
 
 
1230
        if (HWBuffer->vertexBuffer)
 
1231
        {
 
1232
                HWBuffer->vertexBuffer->Release();
 
1233
                HWBuffer->vertexBuffer = 0;
 
1234
        }
 
1235
 
 
1236
        CNullDriver::deleteHardwareBuffer(_HWBuffer);
 
1237
}
 
1238
 
 
1239
 
 
1240
//! Draw hardware buffer
 
1241
void CD3D9Driver::drawHardwareBuffer(SHWBufferLink *_HWBuffer)
 
1242
{
 
1243
        if (!_HWBuffer)
 
1244
                return;
 
1245
 
 
1246
        SHWBufferLink_d3d9 *HWBuffer=(SHWBufferLink_d3d9*)_HWBuffer;
 
1247
 
 
1248
        updateHardwareBuffer(HWBuffer); //check if update is needed
 
1249
 
 
1250
        HWBuffer->LastUsed=0;//reset count
 
1251
 
 
1252
        const scene::IMeshBuffer* mb = HWBuffer->MeshBuffer;
 
1253
        const E_VERTEX_TYPE vType = mb->getVertexType();
 
1254
        const u32 stride = getVertexPitchFromType(vType);
 
1255
        if (HWBuffer->vertexBuffer)
 
1256
                pID3DDevice->SetStreamSource(0, HWBuffer->vertexBuffer, 0, stride);
 
1257
        if (HWBuffer->indexBuffer)
 
1258
                pID3DDevice->SetIndices(HWBuffer->indexBuffer);
 
1259
 
 
1260
        drawVertexPrimitiveList(0, mb->getVertexCount(), 0, mb->getIndexCount()/3, mb->getVertexType(), scene::EPT_TRIANGLES, mb->getIndexType());
 
1261
 
 
1262
        if (HWBuffer->vertexBuffer)
 
1263
                pID3DDevice->SetStreamSource(0, 0, 0, 0);
 
1264
        if (HWBuffer->indexBuffer)
 
1265
                pID3DDevice->SetIndices(0);
 
1266
}
 
1267
 
 
1268
 
 
1269
//! Create occlusion query.
 
1270
/** Use node for identification and mesh for occlusion test. */
 
1271
void CD3D9Driver::addOcclusionQuery(scene::ISceneNode* node,
 
1272
                const scene::IMesh* mesh)
 
1273
{
 
1274
        if (!queryFeature(EVDF_OCCLUSION_QUERY))
 
1275
                return;
 
1276
        CNullDriver::addOcclusionQuery(node, mesh);
 
1277
        const s32 index = OcclusionQueries.linear_search(SOccQuery(node));
 
1278
        if ((index != -1) && (OcclusionQueries[index].PID == 0))
 
1279
                pID3DDevice->CreateQuery(D3DQUERYTYPE_OCCLUSION, reinterpret_cast<IDirect3DQuery9**>(&OcclusionQueries[index].PID));
 
1280
}
 
1281
 
 
1282
 
 
1283
//! Remove occlusion query.
 
1284
void CD3D9Driver::removeOcclusionQuery(scene::ISceneNode* node)
 
1285
{
 
1286
        const s32 index = OcclusionQueries.linear_search(SOccQuery(node));
 
1287
        if (index != -1)
 
1288
        {
 
1289
                if (OcclusionQueries[index].PID != 0)
 
1290
                        reinterpret_cast<IDirect3DQuery9*>(OcclusionQueries[index].PID)->Release();
 
1291
                CNullDriver::removeOcclusionQuery(node);
 
1292
        }
 
1293
}
 
1294
 
 
1295
 
 
1296
//! Run occlusion query. Draws mesh stored in query.
 
1297
/** If the mesh shall not be rendered visible, use
 
1298
overrideMaterial to disable the color and depth buffer. */
 
1299
void CD3D9Driver::runOcclusionQuery(scene::ISceneNode* node, bool visible)
 
1300
{
 
1301
        if (!node)
 
1302
                return;
 
1303
 
 
1304
        const s32 index = OcclusionQueries.linear_search(SOccQuery(node));
 
1305
        if (index != -1)
 
1306
        {
 
1307
                if (OcclusionQueries[index].PID)
 
1308
                        reinterpret_cast<IDirect3DQuery9*>(OcclusionQueries[index].PID)->Issue(D3DISSUE_BEGIN);
 
1309
                CNullDriver::runOcclusionQuery(node,visible);
 
1310
                if (OcclusionQueries[index].PID)
 
1311
                        reinterpret_cast<IDirect3DQuery9*>(OcclusionQueries[index].PID)->Issue(D3DISSUE_END);
 
1312
        }
 
1313
}
 
1314
 
 
1315
 
 
1316
//! Update occlusion query. Retrieves results from GPU.
 
1317
/** If the query shall not block, set the flag to false.
 
1318
Update might not occur in this case, though */
 
1319
void CD3D9Driver::updateOcclusionQuery(scene::ISceneNode* node, bool block)
 
1320
{
 
1321
        const s32 index = OcclusionQueries.linear_search(SOccQuery(node));
 
1322
        if (index != -1)
 
1323
        {
 
1324
                // not yet started
 
1325
                if (OcclusionQueries[index].Run==u32(~0))
 
1326
                        return;
 
1327
                bool available = block?true:false;
 
1328
                int tmp=0;
 
1329
                if (!block)
 
1330
                        available=(reinterpret_cast<IDirect3DQuery9*>(OcclusionQueries[index].PID)->GetData(&tmp, sizeof(DWORD), 0)==S_OK);
 
1331
                else
 
1332
                {
 
1333
                        do
 
1334
                        {
 
1335
                                HRESULT hr = reinterpret_cast<IDirect3DQuery9*>(OcclusionQueries[index].PID)->GetData(&tmp, sizeof(DWORD), D3DGETDATA_FLUSH);
 
1336
                                available = (hr == S_OK);
 
1337
                                if (hr!=S_FALSE)
 
1338
                                        break;
 
1339
                        } while (!available);
 
1340
                }
 
1341
                if (available)
 
1342
                        OcclusionQueries[index].Result = tmp;
 
1343
        }
 
1344
}
 
1345
 
 
1346
 
 
1347
//! Return query result.
 
1348
/** Return value is the number of visible pixels/fragments.
 
1349
The value is a safe approximation, i.e. can be larger than the
 
1350
actual value of pixels. */
 
1351
u32 CD3D9Driver::getOcclusionQueryResult(scene::ISceneNode* node) const
 
1352
{
 
1353
        const s32 index = OcclusionQueries.linear_search(SOccQuery(node));
 
1354
        if (index != -1)
 
1355
                return OcclusionQueries[index].Result;
 
1356
        else
 
1357
                return ~0;
 
1358
}
 
1359
 
 
1360
 
 
1361
//! draws a vertex primitive list
 
1362
void CD3D9Driver::drawVertexPrimitiveList(const void* vertices,
 
1363
                u32 vertexCount, const void* indexList, u32 primitiveCount,
 
1364
                E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType,
 
1365
                E_INDEX_TYPE iType)
 
1366
{
 
1367
        if (!checkPrimitiveCount(primitiveCount))
 
1368
                return;
 
1369
 
 
1370
        CNullDriver::drawVertexPrimitiveList(vertices, vertexCount, indexList, primitiveCount, vType, pType,iType);
 
1371
 
 
1372
        if (!vertexCount || !primitiveCount)
 
1373
                return;
 
1374
 
 
1375
        draw2D3DVertexPrimitiveList(vertices, vertexCount, indexList, primitiveCount,
 
1376
                vType, pType, iType, true);
 
1377
}
 
1378
 
 
1379
 
 
1380
//! draws a vertex primitive list
 
1381
void CD3D9Driver::draw2DVertexPrimitiveList(const void* vertices,
 
1382
                u32 vertexCount, const void* indexList, u32 primitiveCount,
 
1383
                E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType,
 
1384
                E_INDEX_TYPE iType)
 
1385
{
 
1386
        if (!checkPrimitiveCount(primitiveCount))
 
1387
                return;
 
1388
 
 
1389
        CNullDriver::draw2DVertexPrimitiveList(vertices, vertexCount, indexList, primitiveCount, vType, pType,iType);
 
1390
 
 
1391
        if (!vertexCount || !primitiveCount)
 
1392
                return;
 
1393
 
 
1394
        draw2D3DVertexPrimitiveList(vertices, vertexCount, indexList, primitiveCount,
 
1395
                vType, pType, iType, false);
 
1396
}
 
1397
 
 
1398
 
 
1399
void CD3D9Driver::draw2D3DVertexPrimitiveList(const void* vertices,
 
1400
                u32 vertexCount, const void* indexList, u32 primitiveCount,
 
1401
                E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType,
 
1402
                E_INDEX_TYPE iType, bool is3D)
 
1403
{
 
1404
        setVertexShader(vType);
 
1405
 
 
1406
        const u32 stride = getVertexPitchFromType(vType);
 
1407
 
 
1408
        D3DFORMAT indexType=D3DFMT_UNKNOWN;
 
1409
        switch (iType)
 
1410
        {
 
1411
                case (EIT_16BIT):
 
1412
                {
 
1413
                        indexType=D3DFMT_INDEX16;
 
1414
                        break;
 
1415
                }
 
1416
                case (EIT_32BIT):
 
1417
                {
 
1418
                        indexType=D3DFMT_INDEX32;
 
1419
                        break;
 
1420
                }
 
1421
        }
 
1422
 
 
1423
        if (is3D)
 
1424
        {
 
1425
                if (!setRenderStates3DMode())
 
1426
                        return;
 
1427
        }
 
1428
        else
 
1429
        {
 
1430
                if (Material.MaterialType==EMT_ONETEXTURE_BLEND)
 
1431
                {
 
1432
                        E_BLEND_FACTOR srcFact;
 
1433
                        E_BLEND_FACTOR dstFact;
 
1434
                        E_MODULATE_FUNC modulo;
 
1435
                        u32 alphaSource;
 
1436
                        unpack_texureBlendFunc ( srcFact, dstFact, modulo, alphaSource, Material.MaterialTypeParam);
 
1437
                        setRenderStates2DMode(alphaSource&video::EAS_VERTEX_COLOR, (Material.getTexture(0) != 0), (alphaSource&video::EAS_TEXTURE) != 0);
 
1438
                }
 
1439
                else
 
1440
                        setRenderStates2DMode(Material.MaterialType==EMT_TRANSPARENT_VERTEX_ALPHA, (Material.getTexture(0) != 0), Material.MaterialType==EMT_TRANSPARENT_ALPHA_CHANNEL);
 
1441
        }
 
1442
 
 
1443
        switch (pType)
 
1444
        {
 
1445
                case scene::EPT_POINT_SPRITES:
 
1446
                case scene::EPT_POINTS:
 
1447
                {
 
1448
                        f32 tmp=Material.Thickness/getScreenSize().Height;
 
1449
                        if (pType==scene::EPT_POINT_SPRITES)
 
1450
                                pID3DDevice->SetRenderState(D3DRS_POINTSPRITEENABLE, TRUE);
 
1451
                        pID3DDevice->SetRenderState(D3DRS_POINTSCALEENABLE, TRUE);
 
1452
                        pID3DDevice->SetRenderState(D3DRS_POINTSIZE, F2DW(tmp));
 
1453
                        tmp=1.0f;
 
1454
                        pID3DDevice->SetRenderState(D3DRS_POINTSCALE_A, F2DW(tmp));
 
1455
                        pID3DDevice->SetRenderState(D3DRS_POINTSCALE_B, F2DW(tmp));
 
1456
                        pID3DDevice->SetRenderState(D3DRS_POINTSIZE_MIN, F2DW(tmp));
 
1457
                        tmp=0.0f;
 
1458
                        pID3DDevice->SetRenderState(D3DRS_POINTSCALE_C, F2DW(tmp));
 
1459
 
 
1460
                        if (!vertices)
 
1461
                        {
 
1462
                                pID3DDevice->DrawIndexedPrimitive(D3DPT_POINTLIST, 0, 0, vertexCount, 0, primitiveCount);
 
1463
                        }
 
1464
                        else
 
1465
                        {
 
1466
                                pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_POINTLIST, 0, vertexCount,
 
1467
                                primitiveCount, indexList, indexType, vertices, stride);
 
1468
                        }
 
1469
 
 
1470
                        pID3DDevice->SetRenderState(D3DRS_POINTSCALEENABLE, FALSE);
 
1471
                        if (pType==scene::EPT_POINT_SPRITES)
 
1472
                                pID3DDevice->SetRenderState(D3DRS_POINTSPRITEENABLE, FALSE);
 
1473
                }
 
1474
                        break;
 
1475
                case scene::EPT_LINE_STRIP:
 
1476
                        if(!vertices)
 
1477
                                pID3DDevice->DrawIndexedPrimitive(D3DPT_LINESTRIP, 0, 0, vertexCount, 0, primitiveCount);
 
1478
                        else
 
1479
                                pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_LINESTRIP, 0, vertexCount,
 
1480
                                        primitiveCount, indexList, indexType, vertices, stride);
 
1481
                        break;
 
1482
                case scene::EPT_LINE_LOOP:
 
1483
                        if(!vertices)
 
1484
                        {
 
1485
                                // TODO: Implement proper hardware support for this primitive type.
 
1486
                                // (No looping occurs currently because this would require a way to
 
1487
                                // draw the hardware buffer with a custom set of indices. We may even
 
1488
                                // need to create a new mini index buffer specifically for this
 
1489
                                // primitive type.)
 
1490
                                pID3DDevice->DrawIndexedPrimitive(D3DPT_LINELIST, 0, 0, vertexCount, 0, primitiveCount);
 
1491
                        }
 
1492
                        else
 
1493
                        {
 
1494
                                pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_LINESTRIP, 0, vertexCount,
 
1495
                                primitiveCount - 1, indexList, indexType, vertices, stride);
 
1496
 
 
1497
                                u16 tmpIndices[] = {primitiveCount - 1, 0};
 
1498
 
 
1499
                                pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_LINELIST, 0, vertexCount,
 
1500
                                        1, tmpIndices, indexType, vertices, stride);
 
1501
                        }
 
1502
                        break;
 
1503
                case scene::EPT_LINES:
 
1504
                        if(!vertices)
 
1505
                                pID3DDevice->DrawIndexedPrimitive(D3DPT_LINELIST, 0, 0, vertexCount, 0, primitiveCount);
 
1506
                        else
 
1507
                                pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_LINELIST, 0, vertexCount,
 
1508
                                        primitiveCount, indexList, indexType, vertices, stride);
 
1509
                        break;
 
1510
                case scene::EPT_TRIANGLE_STRIP:
 
1511
                        if(!vertices)
 
1512
                                pID3DDevice->DrawIndexedPrimitive(D3DPT_TRIANGLESTRIP, 0, 0, vertexCount, 0, primitiveCount);
 
1513
                        else
 
1514
                                pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_TRIANGLESTRIP, 0, vertexCount, primitiveCount,
 
1515
                                                indexList, indexType, vertices, stride);
 
1516
                        break;
 
1517
                case scene::EPT_TRIANGLE_FAN:
 
1518
                        if(!vertices)
 
1519
                                pID3DDevice->DrawIndexedPrimitive(D3DPT_TRIANGLEFAN, 0, 0, vertexCount, 0, primitiveCount);
 
1520
                        else
 
1521
                                pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_TRIANGLEFAN, 0, vertexCount, primitiveCount,
 
1522
                                                indexList, indexType, vertices, stride);
 
1523
                                break;
 
1524
                case scene::EPT_TRIANGLES:
 
1525
                        if(!vertices)
 
1526
                        {
 
1527
                                pID3DDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, vertexCount, 0, primitiveCount);
 
1528
                        }
 
1529
                        else
 
1530
                        {
 
1531
                                pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST, 0, vertexCount,
 
1532
                                        primitiveCount, indexList, indexType, vertices, stride);
 
1533
                        }
 
1534
                        break;
 
1535
        }
 
1536
}
 
1537
 
 
1538
 
 
1539
void CD3D9Driver::draw2DImage(const video::ITexture* texture,
 
1540
                const core::rect<s32>& destRect,
 
1541
                const core::rect<s32>& sourceRect,
 
1542
                const core::rect<s32>* clipRect,
 
1543
                const video::SColor* const colors,
 
1544
                bool useAlphaChannelOfTexture)
 
1545
{
 
1546
        if(!texture)
 
1547
                return;
 
1548
 
 
1549
        const core::dimension2d<u32>& ss = texture->getOriginalSize();
 
1550
        core::rect<f32> tcoords;
 
1551
        tcoords.UpperLeftCorner.X = (f32)sourceRect.UpperLeftCorner.X / (f32)ss.Width;
 
1552
        tcoords.UpperLeftCorner.Y = (f32)sourceRect.UpperLeftCorner.Y / (f32)ss.Height;
 
1553
        tcoords.LowerRightCorner.X = (f32)sourceRect.LowerRightCorner.X / (f32)ss.Width;
 
1554
        tcoords.LowerRightCorner.Y = (f32)sourceRect.LowerRightCorner.Y / (f32)ss.Height;
 
1555
 
 
1556
        const core::dimension2d<u32>& renderTargetSize = getCurrentRenderTargetSize();
 
1557
 
 
1558
        const video::SColor temp[4] =
 
1559
        {
 
1560
                0xFFFFFFFF,
 
1561
                0xFFFFFFFF,
 
1562
                0xFFFFFFFF,
 
1563
                0xFFFFFFFF
 
1564
        };
 
1565
 
 
1566
        const video::SColor* const useColor = colors ? colors : temp;
 
1567
 
 
1568
        S3DVertex vtx[4]; // clock wise
 
1569
        vtx[0] = S3DVertex((f32)destRect.UpperLeftCorner.X, (f32)destRect.UpperLeftCorner.Y, 0.0f,
 
1570
                        0.0f, 0.0f, 0.0f, useColor[0],
 
1571
                        tcoords.UpperLeftCorner.X, tcoords.UpperLeftCorner.Y);
 
1572
        vtx[1] = S3DVertex((f32)destRect.LowerRightCorner.X, (f32)destRect.UpperLeftCorner.Y, 0.0f,
 
1573
                        0.0f, 0.0f, 0.0f, useColor[3],
 
1574
                        tcoords.LowerRightCorner.X, tcoords.UpperLeftCorner.Y);
 
1575
        vtx[2] = S3DVertex((f32)destRect.LowerRightCorner.X, (f32)destRect.LowerRightCorner.Y, 0.0f,
 
1576
                        0.0f, 0.0f, 0.0f, useColor[2],
 
1577
                        tcoords.LowerRightCorner.X, tcoords.LowerRightCorner.Y);
 
1578
        vtx[3] = S3DVertex((f32)destRect.UpperLeftCorner.X, (f32)destRect.LowerRightCorner.Y, 0.0f,
 
1579
                        0.0f, 0.0f, 0.0f, useColor[1],
 
1580
                        tcoords.UpperLeftCorner.X, tcoords.LowerRightCorner.Y);
 
1581
 
 
1582
        s16 indices[6] = {0,1,2,0,2,3};
 
1583
 
 
1584
        setActiveTexture(0, const_cast<video::ITexture*>(texture));
 
1585
 
 
1586
        setRenderStates2DMode(useColor[0].getAlpha()<255 || useColor[1].getAlpha()<255 ||
 
1587
                        useColor[2].getAlpha()<255 || useColor[3].getAlpha()<255,
 
1588
                        true, useAlphaChannelOfTexture);
 
1589
 
 
1590
        setVertexShader(EVT_STANDARD);
 
1591
 
 
1592
        if (clipRect)
 
1593
        {
 
1594
                pID3DDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
 
1595
                RECT scissor;
 
1596
                scissor.left = clipRect->UpperLeftCorner.X;
 
1597
                scissor.top = clipRect->UpperLeftCorner.Y;
 
1598
                scissor.right = clipRect->LowerRightCorner.X;
 
1599
                scissor.bottom = clipRect->LowerRightCorner.Y;
 
1600
                pID3DDevice->SetScissorRect(&scissor);
 
1601
        }
 
1602
 
 
1603
        pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST, 0, 4, 2, &indices[0],
 
1604
                                D3DFMT_INDEX16,&vtx[0], sizeof(S3DVertex));
 
1605
 
 
1606
        if (clipRect)
 
1607
                pID3DDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
 
1608
}
 
1609
 
 
1610
 
 
1611
void CD3D9Driver::draw2DImageBatch(const video::ITexture* texture,
 
1612
                                const core::array<core::position2d<s32> >& positions,
 
1613
                                const core::array<core::rect<s32> >& sourceRects,
 
1614
                                const core::rect<s32>* clipRect,
 
1615
                                SColor color,
 
1616
                                bool useAlphaChannelOfTexture)
 
1617
{
 
1618
        if (!texture)
 
1619
                return;
 
1620
 
 
1621
        if (!setActiveTexture(0, const_cast<video::ITexture*>(texture)))
 
1622
                return;
 
1623
 
 
1624
        setRenderStates2DMode(color.getAlpha()<255, true, useAlphaChannelOfTexture);
 
1625
 
 
1626
        const irr::u32 drawCount = core::min_<u32>(positions.size(), sourceRects.size());
 
1627
 
 
1628
        core::array<S3DVertex> vtx(drawCount * 4);
 
1629
        core::array<u16> indices(drawCount * 6);
 
1630
 
 
1631
        for(u32 i = 0;i < drawCount;i++)
 
1632
        {
 
1633
                core::position2d<s32> targetPos = positions[i];
 
1634
                core::position2d<s32> sourcePos = sourceRects[i].UpperLeftCorner;
 
1635
                // This needs to be signed as it may go negative.
 
1636
                core::dimension2d<s32> sourceSize(sourceRects[i].getSize());
 
1637
 
 
1638
                if (clipRect)
 
1639
                {
 
1640
                        if (targetPos.X < clipRect->UpperLeftCorner.X)
 
1641
                        {
 
1642
                                sourceSize.Width += targetPos.X - clipRect->UpperLeftCorner.X;
 
1643
                                if (sourceSize.Width <= 0)
 
1644
                                        continue;
 
1645
 
 
1646
                                sourcePos.X -= targetPos.X - clipRect->UpperLeftCorner.X;
 
1647
                                targetPos.X = clipRect->UpperLeftCorner.X;
 
1648
                        }
 
1649
 
 
1650
                        if (targetPos.X + (s32)sourceSize.Width > clipRect->LowerRightCorner.X)
 
1651
                        {
 
1652
                                sourceSize.Width -= (targetPos.X + sourceSize.Width) - clipRect->LowerRightCorner.X;
 
1653
                                if (sourceSize.Width <= 0)
 
1654
                                        continue;
 
1655
                        }
 
1656
 
 
1657
                        if (targetPos.Y < clipRect->UpperLeftCorner.Y)
 
1658
                        {
 
1659
                                sourceSize.Height += targetPos.Y - clipRect->UpperLeftCorner.Y;
 
1660
                                if (sourceSize.Height <= 0)
 
1661
                                        continue;
 
1662
 
 
1663
                                sourcePos.Y -= targetPos.Y - clipRect->UpperLeftCorner.Y;
 
1664
                                targetPos.Y = clipRect->UpperLeftCorner.Y;
 
1665
                        }
 
1666
 
 
1667
                        if (targetPos.Y + (s32)sourceSize.Height > clipRect->LowerRightCorner.Y)
 
1668
                        {
 
1669
                                sourceSize.Height -= (targetPos.Y + sourceSize.Height) - clipRect->LowerRightCorner.Y;
 
1670
                                if (sourceSize.Height <= 0)
 
1671
                                        continue;
 
1672
                        }
 
1673
                }
 
1674
 
 
1675
                // clip these coordinates
 
1676
 
 
1677
                if (targetPos.X<0)
 
1678
                {
 
1679
                        sourceSize.Width += targetPos.X;
 
1680
                        if (sourceSize.Width <= 0)
 
1681
                                continue;
 
1682
 
 
1683
                        sourcePos.X -= targetPos.X;
 
1684
                        targetPos.X = 0;
 
1685
                }
 
1686
 
 
1687
                const core::dimension2d<u32>& renderTargetSize = getCurrentRenderTargetSize();
 
1688
 
 
1689
                if (targetPos.X + sourceSize.Width > (s32)renderTargetSize.Width)
 
1690
                {
 
1691
                        sourceSize.Width -= (targetPos.X + sourceSize.Width) - renderTargetSize.Width;
 
1692
                        if (sourceSize.Width <= 0)
 
1693
                                continue;
 
1694
                }
 
1695
 
 
1696
                if (targetPos.Y<0)
 
1697
                {
 
1698
                        sourceSize.Height += targetPos.Y;
 
1699
                        if (sourceSize.Height <= 0)
 
1700
                                continue;
 
1701
 
 
1702
                        sourcePos.Y -= targetPos.Y;
 
1703
                        targetPos.Y = 0;
 
1704
                }
 
1705
 
 
1706
                if (targetPos.Y + sourceSize.Height > (s32)renderTargetSize.Height)
 
1707
                {
 
1708
                        sourceSize.Height -= (targetPos.Y + sourceSize.Height) - renderTargetSize.Height;
 
1709
                        if (sourceSize.Height <= 0)
 
1710
                                continue;
 
1711
                }
 
1712
 
 
1713
                // ok, we've clipped everything.
 
1714
                // now draw it.
 
1715
 
 
1716
                core::rect<f32> tcoords;
 
1717
                tcoords.UpperLeftCorner.X = (((f32)sourcePos.X)) / texture->getOriginalSize().Width ;
 
1718
                tcoords.UpperLeftCorner.Y = (((f32)sourcePos.Y)) / texture->getOriginalSize().Height;
 
1719
                tcoords.LowerRightCorner.X = tcoords.UpperLeftCorner.X + ((f32)(sourceSize.Width) / texture->getOriginalSize().Width);
 
1720
                tcoords.LowerRightCorner.Y = tcoords.UpperLeftCorner.Y + ((f32)(sourceSize.Height) / texture->getOriginalSize().Height);
 
1721
 
 
1722
                const core::rect<s32> poss(targetPos, sourceSize);
 
1723
 
 
1724
                vtx.push_back(S3DVertex((f32)poss.UpperLeftCorner.X, (f32)poss.UpperLeftCorner.Y, 0.0f,
 
1725
                                0.0f, 0.0f, 0.0f, color,
 
1726
                                tcoords.UpperLeftCorner.X, tcoords.UpperLeftCorner.Y));
 
1727
                vtx.push_back(S3DVertex((f32)poss.LowerRightCorner.X, (f32)poss.UpperLeftCorner.Y, 0.0f,
 
1728
                                0.0f, 0.0f, 0.0f, color,
 
1729
                                tcoords.LowerRightCorner.X, tcoords.UpperLeftCorner.Y));
 
1730
                vtx.push_back(S3DVertex((f32)poss.LowerRightCorner.X, (f32)poss.LowerRightCorner.Y, 0.0f,
 
1731
                                0.0f, 0.0f, 0.0f, color,
 
1732
                                tcoords.LowerRightCorner.X, tcoords.LowerRightCorner.Y));
 
1733
                vtx.push_back(S3DVertex((f32)poss.UpperLeftCorner.X, (f32)poss.LowerRightCorner.Y, 0.0f,
 
1734
                                0.0f, 0.0f, 0.0f, color,
 
1735
                                tcoords.UpperLeftCorner.X, tcoords.LowerRightCorner.Y));
 
1736
 
 
1737
                const u32 curPos = vtx.size()-4;
 
1738
                indices.push_back(0+curPos);
 
1739
                indices.push_back(1+curPos);
 
1740
                indices.push_back(2+curPos);
 
1741
 
 
1742
                indices.push_back(0+curPos);
 
1743
                indices.push_back(2+curPos);
 
1744
                indices.push_back(3+curPos);
 
1745
        }
 
1746
 
 
1747
        if (vtx.size())
 
1748
        {
 
1749
                setVertexShader(EVT_STANDARD);
 
1750
 
 
1751
                pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST, 0, vtx.size(), indices.size() / 3, indices.pointer(),
 
1752
                        D3DFMT_INDEX16,vtx.pointer(), sizeof(S3DVertex));
 
1753
        }
 
1754
}
 
1755
 
 
1756
 
 
1757
//! draws a 2d image, using a color and the alpha channel of the texture if
 
1758
//! desired. The image is drawn at pos and clipped against clipRect (if != 0).
 
1759
void CD3D9Driver::draw2DImage(const video::ITexture* texture,
 
1760
                                const core::position2d<s32>& pos,
 
1761
                                const core::rect<s32>& sourceRect,
 
1762
                                const core::rect<s32>* clipRect, SColor color,
 
1763
                                bool useAlphaChannelOfTexture)
 
1764
{
 
1765
        if (!texture)
 
1766
                return;
 
1767
 
 
1768
        if (!sourceRect.isValid())
 
1769
                return;
 
1770
 
 
1771
        if (!setActiveTexture(0, const_cast<video::ITexture*>(texture)))
 
1772
                return;
 
1773
 
 
1774
        core::position2d<s32> targetPos = pos;
 
1775
        core::position2d<s32> sourcePos = sourceRect.UpperLeftCorner;
 
1776
        // This needs to be signed as it may go negative.
 
1777
        core::dimension2d<s32> sourceSize(sourceRect.getSize());
 
1778
 
 
1779
        if (clipRect)
 
1780
        {
 
1781
                if (targetPos.X < clipRect->UpperLeftCorner.X)
 
1782
                {
 
1783
                        sourceSize.Width += targetPos.X - clipRect->UpperLeftCorner.X;
 
1784
                        if (sourceSize.Width <= 0)
 
1785
                                return;
 
1786
 
 
1787
                        sourcePos.X -= targetPos.X - clipRect->UpperLeftCorner.X;
 
1788
                        targetPos.X = clipRect->UpperLeftCorner.X;
 
1789
                }
 
1790
 
 
1791
                if (targetPos.X + (s32)sourceSize.Width > clipRect->LowerRightCorner.X)
 
1792
                {
 
1793
                        sourceSize.Width -= (targetPos.X + sourceSize.Width) - clipRect->LowerRightCorner.X;
 
1794
                        if (sourceSize.Width <= 0)
 
1795
                                return;
 
1796
                }
 
1797
 
 
1798
                if (targetPos.Y < clipRect->UpperLeftCorner.Y)
 
1799
                {
 
1800
                        sourceSize.Height += targetPos.Y - clipRect->UpperLeftCorner.Y;
 
1801
                        if (sourceSize.Height <= 0)
 
1802
                                return;
 
1803
 
 
1804
                        sourcePos.Y -= targetPos.Y - clipRect->UpperLeftCorner.Y;
 
1805
                        targetPos.Y = clipRect->UpperLeftCorner.Y;
 
1806
                }
 
1807
 
 
1808
                if (targetPos.Y + (s32)sourceSize.Height > clipRect->LowerRightCorner.Y)
 
1809
                {
 
1810
                        sourceSize.Height -= (targetPos.Y + sourceSize.Height) - clipRect->LowerRightCorner.Y;
 
1811
                        if (sourceSize.Height <= 0)
 
1812
                                return;
 
1813
                }
 
1814
        }
 
1815
 
 
1816
        // clip these coordinates
 
1817
 
 
1818
        if (targetPos.X<0)
 
1819
        {
 
1820
                sourceSize.Width += targetPos.X;
 
1821
                if (sourceSize.Width <= 0)
 
1822
                        return;
 
1823
 
 
1824
                sourcePos.X -= targetPos.X;
 
1825
                targetPos.X = 0;
 
1826
        }
 
1827
 
 
1828
        const core::dimension2d<u32>& renderTargetSize = getCurrentRenderTargetSize();
 
1829
 
 
1830
        if (targetPos.X + sourceSize.Width > (s32)renderTargetSize.Width)
 
1831
        {
 
1832
                sourceSize.Width -= (targetPos.X + sourceSize.Width) - renderTargetSize.Width;
 
1833
                if (sourceSize.Width <= 0)
 
1834
                        return;
 
1835
        }
 
1836
 
 
1837
        if (targetPos.Y<0)
 
1838
        {
 
1839
                sourceSize.Height += targetPos.Y;
 
1840
                if (sourceSize.Height <= 0)
 
1841
                        return;
 
1842
 
 
1843
                sourcePos.Y -= targetPos.Y;
 
1844
                targetPos.Y = 0;
 
1845
        }
 
1846
 
 
1847
        if (targetPos.Y + sourceSize.Height > (s32)renderTargetSize.Height)
 
1848
        {
 
1849
                sourceSize.Height -= (targetPos.Y + sourceSize.Height) - renderTargetSize.Height;
 
1850
                if (sourceSize.Height <= 0)
 
1851
                        return;
 
1852
        }
 
1853
 
 
1854
        // ok, we've clipped everything.
 
1855
        // now draw it.
 
1856
 
 
1857
        core::rect<f32> tcoords;
 
1858
        tcoords.UpperLeftCorner.X = (((f32)sourcePos.X)) / texture->getOriginalSize().Width ;
 
1859
        tcoords.UpperLeftCorner.Y = (((f32)sourcePos.Y)) / texture->getOriginalSize().Height;
 
1860
        tcoords.LowerRightCorner.X = tcoords.UpperLeftCorner.X + ((f32)(sourceSize.Width) / texture->getOriginalSize().Width);
 
1861
        tcoords.LowerRightCorner.Y = tcoords.UpperLeftCorner.Y + ((f32)(sourceSize.Height) / texture->getOriginalSize().Height);
 
1862
 
 
1863
        const core::rect<s32> poss(targetPos, sourceSize);
 
1864
 
 
1865
        setRenderStates2DMode(color.getAlpha()<255, true, useAlphaChannelOfTexture);
 
1866
 
 
1867
        S3DVertex vtx[4];
 
1868
        vtx[0] = S3DVertex((f32)poss.UpperLeftCorner.X, (f32)poss.UpperLeftCorner.Y, 0.0f,
 
1869
                        0.0f, 0.0f, 0.0f, color,
 
1870
                        tcoords.UpperLeftCorner.X, tcoords.UpperLeftCorner.Y);
 
1871
        vtx[1] = S3DVertex((f32)poss.LowerRightCorner.X, (f32)poss.UpperLeftCorner.Y, 0.0f,
 
1872
                        0.0f, 0.0f, 0.0f, color,
 
1873
                        tcoords.LowerRightCorner.X, tcoords.UpperLeftCorner.Y);
 
1874
        vtx[2] = S3DVertex((f32)poss.LowerRightCorner.X, (f32)poss.LowerRightCorner.Y, 0.0f,
 
1875
                        0.0f, 0.0f, 0.0f, color,
 
1876
                        tcoords.LowerRightCorner.X, tcoords.LowerRightCorner.Y);
 
1877
        vtx[3] = S3DVertex((f32)poss.UpperLeftCorner.X, (f32)poss.LowerRightCorner.Y, 0.0f,
 
1878
                        0.0f, 0.0f, 0.0f, color,
 
1879
                        tcoords.UpperLeftCorner.X, tcoords.LowerRightCorner.Y);
 
1880
 
 
1881
        s16 indices[6] = {0,1,2,0,2,3};
 
1882
 
 
1883
        setVertexShader(EVT_STANDARD);
 
1884
 
 
1885
        pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST, 0, 4, 2, &indices[0],
 
1886
                D3DFMT_INDEX16,&vtx[0], sizeof(S3DVertex));
 
1887
}
 
1888
 
 
1889
 
 
1890
//!Draws a 2d rectangle with a gradient.
 
1891
void CD3D9Driver::draw2DRectangle(const core::rect<s32>& position,
 
1892
        SColor colorLeftUp, SColor colorRightUp, SColor colorLeftDown, SColor colorRightDown,
 
1893
        const core::rect<s32>* clip)
 
1894
{
 
1895
        core::rect<s32> pos(position);
 
1896
 
 
1897
        if (clip)
 
1898
                pos.clipAgainst(*clip);
 
1899
 
 
1900
        if (!pos.isValid())
 
1901
                return;
 
1902
 
 
1903
        S3DVertex vtx[4];
 
1904
        vtx[0] = S3DVertex((f32)pos.UpperLeftCorner.X, (f32)pos.UpperLeftCorner.Y, 0.0f,
 
1905
                        0.0f, 0.0f, 0.0f, colorLeftUp, 0.0f, 0.0f);
 
1906
        vtx[1] = S3DVertex((f32)pos.LowerRightCorner.X, (f32)pos.UpperLeftCorner.Y, 0.0f,
 
1907
                        0.0f, 0.0f, 0.0f, colorRightUp, 0.0f, 1.0f);
 
1908
        vtx[2] = S3DVertex((f32)pos.LowerRightCorner.X, (f32)pos.LowerRightCorner.Y, 0.0f,
 
1909
                        0.0f, 0.0f, 0.0f, colorRightDown, 1.0f, 0.0f);
 
1910
        vtx[3] = S3DVertex((f32)pos.UpperLeftCorner.X, (f32)pos.LowerRightCorner.Y, 0.0f,
 
1911
                        0.0f, 0.0f, 0.0f, colorLeftDown, 1.0f, 1.0f);
 
1912
 
 
1913
        s16 indices[6] = {0,1,2,0,2,3};
 
1914
 
 
1915
        setRenderStates2DMode(
 
1916
                colorLeftUp.getAlpha() < 255 ||
 
1917
                colorRightUp.getAlpha() < 255 ||
 
1918
                colorLeftDown.getAlpha() < 255 ||
 
1919
                colorRightDown.getAlpha() < 255, false, false);
 
1920
 
 
1921
        setActiveTexture(0,0);
 
1922
 
 
1923
        setVertexShader(EVT_STANDARD);
 
1924
 
 
1925
        pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST, 0, 4, 2, &indices[0],
 
1926
                D3DFMT_INDEX16, &vtx[0], sizeof(S3DVertex));
 
1927
}
 
1928
 
 
1929
 
 
1930
//! Draws a 2d line.
 
1931
void CD3D9Driver::draw2DLine(const core::position2d<s32>& start,
 
1932
                                const core::position2d<s32>& end,
 
1933
                                SColor color)
 
1934
{
 
1935
        // thanks to Vash TheStampede who sent in his implementation
 
1936
        S3DVertex vtx[2];
 
1937
        vtx[0] = S3DVertex((f32)start.X, (f32)start.Y, 0.0f,
 
1938
                                                0.0f, 0.0f, 0.0f, // normal
 
1939
                                                color, 0.0f, 0.0f); // texture
 
1940
 
 
1941
        vtx[1] = S3DVertex((f32)end.X, (f32)end.Y, 0.0f,
 
1942
                                                0.0f, 0.0f, 0.0f,
 
1943
                                                color, 0.0f, 0.0f);
 
1944
 
 
1945
        setRenderStates2DMode(color.getAlpha() < 255, false, false);
 
1946
        setActiveTexture(0,0);
 
1947
 
 
1948
        setVertexShader(EVT_STANDARD);
 
1949
 
 
1950
        pID3DDevice->DrawPrimitiveUP(D3DPT_LINELIST, 1,
 
1951
                                        &vtx[0], sizeof(S3DVertex) );
 
1952
}
 
1953
 
 
1954
 
 
1955
//! Draws a pixel
 
1956
void CD3D9Driver::drawPixel(u32 x, u32 y, const SColor & color)
 
1957
{
 
1958
        const core::dimension2d<u32>& renderTargetSize = getCurrentRenderTargetSize();
 
1959
        if(x > (u32)renderTargetSize.Width || y > (u32)renderTargetSize.Height)
 
1960
                return;
 
1961
 
 
1962
        setRenderStates2DMode(color.getAlpha() < 255, false, false);
 
1963
        setActiveTexture(0,0);
 
1964
 
 
1965
        setVertexShader(EVT_STANDARD);
 
1966
 
 
1967
        S3DVertex vertex((f32)x, (f32)y, 0.f, 0.f, 0.f, 0.f, color, 0.f, 0.f);
 
1968
 
 
1969
        pID3DDevice->DrawPrimitiveUP(D3DPT_POINTLIST, 1, &vertex, sizeof(vertex));
 
1970
}
 
1971
 
 
1972
 
 
1973
//! sets right vertex shader
 
1974
void CD3D9Driver::setVertexShader(E_VERTEX_TYPE newType)
 
1975
{
 
1976
        if (newType != LastVertexType)
 
1977
        {
 
1978
                LastVertexType = newType;
 
1979
                HRESULT hr = 0;
 
1980
 
 
1981
                switch(newType)
 
1982
                {
 
1983
                case EVT_STANDARD:
 
1984
                        hr = pID3DDevice->SetFVF(D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_TEX1);
 
1985
                        break;
 
1986
                case EVT_2TCOORDS:
 
1987
                        hr = pID3DDevice->SetFVF(D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_TEX2);
 
1988
                        break;
 
1989
                case EVT_TANGENTS:
 
1990
                        hr = pID3DDevice->SetFVF(D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_TEX3 |
 
1991
                                D3DFVF_TEXCOORDSIZE2(0) | // real texture coord
 
1992
                                D3DFVF_TEXCOORDSIZE3(1) | // misuse texture coord 2 for tangent
 
1993
                                D3DFVF_TEXCOORDSIZE3(2) // misuse texture coord 3 for binormal
 
1994
                                );
 
1995
                        break;
 
1996
                }
 
1997
 
 
1998
                if (FAILED(hr))
 
1999
                {
 
2000
                        os::Printer::log("Could not set vertex Shader.", ELL_ERROR);
 
2001
                        return;
 
2002
                }
 
2003
        }
 
2004
}
 
2005
 
 
2006
 
 
2007
//! sets the needed renderstates
 
2008
bool CD3D9Driver::setRenderStates3DMode()
 
2009
{
 
2010
        if (!pID3DDevice)
 
2011
                return false;
 
2012
 
 
2013
        if (CurrentRenderMode != ERM_3D)
 
2014
        {
 
2015
                // switch back the matrices
 
2016
                pID3DDevice->SetTransform(D3DTS_VIEW, (D3DMATRIX*)((void*)&Matrices[ETS_VIEW]));
 
2017
                pID3DDevice->SetTransform(D3DTS_WORLD, (D3DMATRIX*)((void*)&Matrices[ETS_WORLD]));
 
2018
                pID3DDevice->SetTransform(D3DTS_PROJECTION, (D3DMATRIX*)((void*)&Matrices[ETS_PROJECTION]));
 
2019
 
 
2020
                pID3DDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE);
 
2021
                pID3DDevice->SetRenderState(D3DRS_CLIPPING, TRUE);
 
2022
 
 
2023
                ResetRenderStates = true;
 
2024
        }
 
2025
 
 
2026
        if (ResetRenderStates || LastMaterial != Material)
 
2027
        {
 
2028
                // unset old material
 
2029
 
 
2030
                if (CurrentRenderMode == ERM_3D &&
 
2031
                        LastMaterial.MaterialType != Material.MaterialType &&
 
2032
                        LastMaterial.MaterialType >= 0 && LastMaterial.MaterialType < (s32)MaterialRenderers.size())
 
2033
                        MaterialRenderers[LastMaterial.MaterialType].Renderer->OnUnsetMaterial();
 
2034
 
 
2035
                // set new material.
 
2036
 
 
2037
                if (Material.MaterialType >= 0 && Material.MaterialType < (s32)MaterialRenderers.size())
 
2038
                        MaterialRenderers[Material.MaterialType].Renderer->OnSetMaterial(
 
2039
                                Material, LastMaterial, ResetRenderStates, this);
 
2040
        }
 
2041
 
 
2042
        bool shaderOK = true;
 
2043
        if (Material.MaterialType >= 0 && Material.MaterialType < (s32)MaterialRenderers.size())
 
2044
                shaderOK = MaterialRenderers[Material.MaterialType].Renderer->OnRender(this, LastVertexType);
 
2045
 
 
2046
        LastMaterial = Material;
 
2047
 
 
2048
        ResetRenderStates = false;
 
2049
 
 
2050
        CurrentRenderMode = ERM_3D;
 
2051
 
 
2052
        return shaderOK;
 
2053
}
 
2054
 
 
2055
 
 
2056
//! Map Irrlicht texture wrap mode to native values
 
2057
D3DTEXTUREADDRESS CD3D9Driver::getTextureWrapMode(const u8 clamp)
 
2058
{
 
2059
        switch (clamp)
 
2060
        {
 
2061
                case ETC_REPEAT:
 
2062
                        if (Caps.TextureAddressCaps & D3DPTADDRESSCAPS_WRAP)
 
2063
                                return D3DTADDRESS_WRAP;
 
2064
                case ETC_CLAMP:
 
2065
                case ETC_CLAMP_TO_EDGE:
 
2066
                        if (Caps.TextureAddressCaps & D3DPTADDRESSCAPS_CLAMP)
 
2067
                                return D3DTADDRESS_CLAMP;
 
2068
                case ETC_MIRROR:
 
2069
                        if (Caps.TextureAddressCaps & D3DPTADDRESSCAPS_MIRROR)
 
2070
                                return D3DTADDRESS_MIRROR;
 
2071
                case ETC_CLAMP_TO_BORDER:
 
2072
                        if (Caps.TextureAddressCaps & D3DPTADDRESSCAPS_BORDER)
 
2073
                                return D3DTADDRESS_BORDER;
 
2074
                        else
 
2075
                                return D3DTADDRESS_CLAMP;
 
2076
                case ETC_MIRROR_CLAMP:
 
2077
                case ETC_MIRROR_CLAMP_TO_EDGE:
 
2078
                case ETC_MIRROR_CLAMP_TO_BORDER:
 
2079
                        if (Caps.TextureAddressCaps & D3DPTADDRESSCAPS_MIRRORONCE)
 
2080
                                return D3DTADDRESS_MIRRORONCE;
 
2081
                        else
 
2082
                                return D3DTADDRESS_CLAMP;
 
2083
                default:
 
2084
                        return D3DTADDRESS_WRAP;
 
2085
        }
 
2086
}
 
2087
 
 
2088
 
 
2089
//! Can be called by an IMaterialRenderer to make its work easier.
 
2090
void CD3D9Driver::setBasicRenderStates(const SMaterial& material, const SMaterial& lastmaterial,
 
2091
        bool resetAllRenderstates)
 
2092
{
 
2093
        // This needs only to be updated onresets
 
2094
        if (Params.HandleSRGB && resetAllRenderstates)
 
2095
                pID3DDevice->SetRenderState(D3DRS_SRGBWRITEENABLE, TRUE);
 
2096
 
 
2097
        if (resetAllRenderstates ||
 
2098
                lastmaterial.AmbientColor != material.AmbientColor ||
 
2099
                lastmaterial.DiffuseColor != material.DiffuseColor ||
 
2100
                lastmaterial.SpecularColor != material.SpecularColor ||
 
2101
                lastmaterial.EmissiveColor != material.EmissiveColor ||
 
2102
                lastmaterial.Shininess != material.Shininess)
 
2103
        {
 
2104
                D3DMATERIAL9 mat;
 
2105
                mat.Diffuse = colorToD3D(material.DiffuseColor);
 
2106
                mat.Ambient = colorToD3D(material.AmbientColor);
 
2107
                mat.Specular = colorToD3D(material.SpecularColor);
 
2108
                mat.Emissive = colorToD3D(material.EmissiveColor);
 
2109
                mat.Power = material.Shininess;
 
2110
                pID3DDevice->SetMaterial(&mat);
 
2111
        }
 
2112
 
 
2113
        if (lastmaterial.ColorMaterial != material.ColorMaterial)
 
2114
        {
 
2115
                pID3DDevice->SetRenderState(D3DRS_COLORVERTEX, (material.ColorMaterial != ECM_NONE));
 
2116
                pID3DDevice->SetRenderState(D3DRS_DIFFUSEMATERIALSOURCE,
 
2117
                        ((material.ColorMaterial == ECM_DIFFUSE)||
 
2118
                        (material.ColorMaterial == ECM_DIFFUSE_AND_AMBIENT))?D3DMCS_COLOR1:D3DMCS_MATERIAL);
 
2119
                pID3DDevice->SetRenderState(D3DRS_AMBIENTMATERIALSOURCE,
 
2120
                        ((material.ColorMaterial == ECM_AMBIENT)||
 
2121
                        (material.ColorMaterial == ECM_DIFFUSE_AND_AMBIENT))?D3DMCS_COLOR1:D3DMCS_MATERIAL);
 
2122
                pID3DDevice->SetRenderState(D3DRS_EMISSIVEMATERIALSOURCE,
 
2123
                        (material.ColorMaterial == ECM_EMISSIVE)?D3DMCS_COLOR1:D3DMCS_MATERIAL);
 
2124
                pID3DDevice->SetRenderState(D3DRS_SPECULARMATERIALSOURCE,
 
2125
                        (material.ColorMaterial == ECM_SPECULAR)?D3DMCS_COLOR1:D3DMCS_MATERIAL);
 
2126
        }
 
2127
 
 
2128
        // fillmode
 
2129
        if (resetAllRenderstates || lastmaterial.Wireframe != material.Wireframe || lastmaterial.PointCloud != material.PointCloud)
 
2130
        {
 
2131
                if (material.Wireframe)
 
2132
                        pID3DDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME);
 
2133
                else
 
2134
                if (material.PointCloud)
 
2135
                        pID3DDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_POINT);
 
2136
                else
 
2137
                        pID3DDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
 
2138
        }
 
2139
 
 
2140
        // shademode
 
2141
 
 
2142
        if (resetAllRenderstates || lastmaterial.GouraudShading != material.GouraudShading)
 
2143
        {
 
2144
                if (material.GouraudShading)
 
2145
                        pID3DDevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_GOURAUD);
 
2146
                else
 
2147
                        pID3DDevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_FLAT);
 
2148
        }
 
2149
 
 
2150
        // lighting
 
2151
 
 
2152
        if (resetAllRenderstates || lastmaterial.Lighting != material.Lighting)
 
2153
        {
 
2154
                if (material.Lighting)
 
2155
                        pID3DDevice->SetRenderState(D3DRS_LIGHTING, TRUE);
 
2156
                else
 
2157
                        pID3DDevice->SetRenderState(D3DRS_LIGHTING, FALSE);
 
2158
        }
 
2159
 
 
2160
        // zbuffer
 
2161
 
 
2162
        if (resetAllRenderstates || lastmaterial.ZBuffer != material.ZBuffer)
 
2163
        {
 
2164
                switch (material.ZBuffer)
 
2165
                {
 
2166
                case ECFN_NEVER:
 
2167
                        pID3DDevice->SetRenderState(D3DRS_ZENABLE, FALSE);
 
2168
                        break;
 
2169
                case ECFN_LESSEQUAL:
 
2170
                        pID3DDevice->SetRenderState(D3DRS_ZENABLE, TRUE);
 
2171
                        pID3DDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL);
 
2172
                        break;
 
2173
                case ECFN_EQUAL:
 
2174
                        pID3DDevice->SetRenderState(D3DRS_ZENABLE, TRUE);
 
2175
                        pID3DDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_EQUAL);
 
2176
                        break;
 
2177
                case ECFN_LESS:
 
2178
                        pID3DDevice->SetRenderState(D3DRS_ZENABLE, TRUE);
 
2179
                        pID3DDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESS);
 
2180
                        break;
 
2181
                case ECFN_NOTEQUAL:
 
2182
                        pID3DDevice->SetRenderState(D3DRS_ZENABLE, TRUE);
 
2183
                        pID3DDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_NOTEQUAL);
 
2184
                        break;
 
2185
                case ECFN_GREATEREQUAL:
 
2186
                        pID3DDevice->SetRenderState(D3DRS_ZENABLE, TRUE);
 
2187
                        pID3DDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_GREATEREQUAL);
 
2188
                        break;
 
2189
                case ECFN_GREATER:
 
2190
                        pID3DDevice->SetRenderState(D3DRS_ZENABLE, TRUE);
 
2191
                        pID3DDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_GREATER);
 
2192
                        break;
 
2193
                case ECFN_ALWAYS:
 
2194
                        pID3DDevice->SetRenderState(D3DRS_ZENABLE, TRUE);
 
2195
                        pID3DDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
 
2196
                        break;
 
2197
                }
 
2198
        }
 
2199
 
 
2200
        // zwrite
 
2201
//      if (resetAllRenderstates || (lastmaterial.ZWriteEnable != material.ZWriteEnable))
 
2202
        {
 
2203
                if ( material.ZWriteEnable && (AllowZWriteOnTransparent || !material.isTransparent()))
 
2204
                        pID3DDevice->SetRenderState( D3DRS_ZWRITEENABLE, TRUE);
 
2205
                else
 
2206
                        pID3DDevice->SetRenderState( D3DRS_ZWRITEENABLE, FALSE);
 
2207
        }
 
2208
 
 
2209
        // back face culling
 
2210
 
 
2211
        if (resetAllRenderstates || (lastmaterial.FrontfaceCulling != material.FrontfaceCulling) || (lastmaterial.BackfaceCulling != material.BackfaceCulling))
 
2212
        {
 
2213
//              if (material.FrontfaceCulling && material.BackfaceCulling)
 
2214
//                      pID3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW|D3DCULL_CCW);
 
2215
//              else
 
2216
                if (material.FrontfaceCulling)
 
2217
                        pID3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW);
 
2218
                else
 
2219
                if (material.BackfaceCulling)
 
2220
                        pID3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
 
2221
                else
 
2222
                        pID3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
 
2223
        }
 
2224
 
 
2225
        // fog
 
2226
        if (resetAllRenderstates || lastmaterial.FogEnable != material.FogEnable)
 
2227
        {
 
2228
                pID3DDevice->SetRenderState(D3DRS_FOGENABLE, material.FogEnable);
 
2229
        }
 
2230
 
 
2231
        // specular highlights
 
2232
        if (resetAllRenderstates || !core::equals(lastmaterial.Shininess,material.Shininess))
 
2233
        {
 
2234
                const bool enable = (material.Shininess!=0.0f);
 
2235
                pID3DDevice->SetRenderState(D3DRS_SPECULARENABLE, enable);
 
2236
                pID3DDevice->SetRenderState(D3DRS_SPECULARMATERIALSOURCE, D3DMCS_MATERIAL);
 
2237
        }
 
2238
 
 
2239
        // normalization
 
2240
        if (resetAllRenderstates || lastmaterial.NormalizeNormals != material.NormalizeNormals)
 
2241
        {
 
2242
                pID3DDevice->SetRenderState(D3DRS_NORMALIZENORMALS, material.NormalizeNormals);
 
2243
        }
 
2244
 
 
2245
        // Color Mask
 
2246
        if (queryFeature(EVDF_COLOR_MASK) &&
 
2247
                (resetAllRenderstates || lastmaterial.ColorMask != material.ColorMask))
 
2248
        {
 
2249
                const DWORD flag =
 
2250
                        ((material.ColorMask & ECP_RED)?D3DCOLORWRITEENABLE_RED:0) |
 
2251
                        ((material.ColorMask & ECP_GREEN)?D3DCOLORWRITEENABLE_GREEN:0) |
 
2252
                        ((material.ColorMask & ECP_BLUE)?D3DCOLORWRITEENABLE_BLUE:0) |
 
2253
                        ((material.ColorMask & ECP_ALPHA)?D3DCOLORWRITEENABLE_ALPHA:0);
 
2254
                pID3DDevice->SetRenderState(D3DRS_COLORWRITEENABLE, flag);
 
2255
        }
 
2256
 
 
2257
        if (queryFeature(EVDF_BLEND_OPERATIONS) &&
 
2258
                (resetAllRenderstates|| lastmaterial.BlendOperation != material.BlendOperation))
 
2259
        {
 
2260
                if (material.BlendOperation==EBO_NONE)
 
2261
                        pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
 
2262
                else
 
2263
                {
 
2264
                        pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
 
2265
                        switch (material.BlendOperation)
 
2266
                        {
 
2267
                        case EBO_SUBTRACT:
 
2268
                                pID3DDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_SUBTRACT);
 
2269
                                break;
 
2270
                        case EBO_REVSUBTRACT:
 
2271
                                pID3DDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_REVSUBTRACT);
 
2272
                                break;
 
2273
                        case EBO_MIN:
 
2274
                        case EBO_MIN_FACTOR:
 
2275
                        case EBO_MIN_ALPHA:
 
2276
                                pID3DDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_MIN);
 
2277
                                break;
 
2278
                        case EBO_MAX:
 
2279
                        case EBO_MAX_FACTOR:
 
2280
                        case EBO_MAX_ALPHA:
 
2281
                                pID3DDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_MAX);
 
2282
                                break;
 
2283
                        default:
 
2284
                                pID3DDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
 
2285
                                break;
 
2286
                        }
 
2287
                }
 
2288
        }
 
2289
 
 
2290
        // Polygon offset
 
2291
        if (queryFeature(EVDF_POLYGON_OFFSET) && (resetAllRenderstates ||
 
2292
                lastmaterial.PolygonOffsetDirection != material.PolygonOffsetDirection ||
 
2293
                lastmaterial.PolygonOffsetFactor != material.PolygonOffsetFactor))
 
2294
        {
 
2295
                if (material.PolygonOffsetFactor)
 
2296
                {
 
2297
                        if (material.PolygonOffsetDirection==EPO_BACK)
 
2298
                        {
 
2299
                                pID3DDevice->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, F2DW(1.f));
 
2300
                                pID3DDevice->SetRenderState(D3DRS_DEPTHBIAS, F2DW((FLOAT)material.PolygonOffsetFactor));
 
2301
                        }
 
2302
                        else
 
2303
                        {
 
2304
                                pID3DDevice->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, F2DW(-1.f));
 
2305
                                pID3DDevice->SetRenderState(D3DRS_DEPTHBIAS, F2DW((FLOAT)-material.PolygonOffsetFactor));
 
2306
                        }
 
2307
                }
 
2308
                else
 
2309
                {
 
2310
                        pID3DDevice->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, 0);
 
2311
                        pID3DDevice->SetRenderState(D3DRS_DEPTHBIAS, 0);
 
2312
                }
 
2313
        }
 
2314
 
 
2315
        // Anti Aliasing
 
2316
        if (resetAllRenderstates || lastmaterial.AntiAliasing != material.AntiAliasing)
 
2317
        {
 
2318
                if (AlphaToCoverageSupport && (material.AntiAliasing & EAAM_ALPHA_TO_COVERAGE))
 
2319
                {
 
2320
                        if (VendorID==0x10DE)//NVidia
 
2321
                                pID3DDevice->SetRenderState(D3DRS_ADAPTIVETESS_Y, MAKEFOURCC('A','T','O','C'));
 
2322
                        // SSAA could give better results on NVidia cards
 
2323
                        else if (VendorID==0x1002)//ATI
 
2324
                                pID3DDevice->SetRenderState(D3DRS_POINTSIZE, MAKEFOURCC('A','2','M','1'));
 
2325
                }
 
2326
                else if (AlphaToCoverageSupport && (lastmaterial.AntiAliasing & EAAM_ALPHA_TO_COVERAGE))
 
2327
                {
 
2328
                        if (VendorID==0x10DE)
 
2329
                                pID3DDevice->SetRenderState(D3DRS_ADAPTIVETESS_Y, D3DFMT_UNKNOWN);
 
2330
                        else if (VendorID==0x1002)
 
2331
                                pID3DDevice->SetRenderState(D3DRS_POINTSIZE, MAKEFOURCC('A','2','M','0'));
 
2332
                }
 
2333
 
 
2334
                // enable antialiasing
 
2335
                if (Params.AntiAlias)
 
2336
                {
 
2337
                        if (material.AntiAliasing & (EAAM_SIMPLE|EAAM_QUALITY))
 
2338
                                pID3DDevice->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, TRUE);
 
2339
                        else if (lastmaterial.AntiAliasing & (EAAM_SIMPLE|EAAM_QUALITY))
 
2340
                                pID3DDevice->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, FALSE);
 
2341
                        if (material.AntiAliasing & (EAAM_LINE_SMOOTH))
 
2342
                                pID3DDevice->SetRenderState(D3DRS_ANTIALIASEDLINEENABLE, TRUE);
 
2343
                        else if (lastmaterial.AntiAliasing & (EAAM_LINE_SMOOTH))
 
2344
                                pID3DDevice->SetRenderState(D3DRS_ANTIALIASEDLINEENABLE, FALSE);
 
2345
                }
 
2346
        }
 
2347
 
 
2348
        // thickness
 
2349
        if (resetAllRenderstates || lastmaterial.Thickness != material.Thickness)
 
2350
        {
 
2351
                pID3DDevice->SetRenderState(D3DRS_POINTSIZE, F2DW(material.Thickness));
 
2352
        }
 
2353
 
 
2354
        // texture address mode
 
2355
        for (u32 st=0; st<MaxTextureUnits; ++st)
 
2356
        {
 
2357
                if (resetAllRenderstates && Params.HandleSRGB)
 
2358
                        pID3DDevice->SetSamplerState(st, D3DSAMP_SRGBTEXTURE, TRUE);
 
2359
 
 
2360
                if (resetAllRenderstates || lastmaterial.TextureLayer[st].LODBias != material.TextureLayer[st].LODBias)
 
2361
                {
 
2362
                        const float tmp = material.TextureLayer[st].LODBias * 0.125f;
 
2363
                        pID3DDevice->SetSamplerState(st, D3DSAMP_MIPMAPLODBIAS, F2DW(tmp));
 
2364
                }
 
2365
 
 
2366
                if (resetAllRenderstates || lastmaterial.TextureLayer[st].TextureWrapU != material.TextureLayer[st].TextureWrapU)
 
2367
                        pID3DDevice->SetSamplerState(st, D3DSAMP_ADDRESSU, getTextureWrapMode(material.TextureLayer[st].TextureWrapU));
 
2368
                // If separate UV not supported reuse U for V
 
2369
                if (!(Caps.TextureAddressCaps & D3DPTADDRESSCAPS_INDEPENDENTUV))
 
2370
                        pID3DDevice->SetSamplerState(st, D3DSAMP_ADDRESSV, getTextureWrapMode(material.TextureLayer[st].TextureWrapU));
 
2371
                else if (resetAllRenderstates || lastmaterial.TextureLayer[st].TextureWrapV != material.TextureLayer[st].TextureWrapV)
 
2372
                        pID3DDevice->SetSamplerState(st, D3DSAMP_ADDRESSV, getTextureWrapMode(material.TextureLayer[st].TextureWrapV));
 
2373
 
 
2374
                // Bilinear, trilinear, and anisotropic filter
 
2375
                if (resetAllRenderstates ||
 
2376
                        lastmaterial.TextureLayer[st].BilinearFilter != material.TextureLayer[st].BilinearFilter ||
 
2377
                        lastmaterial.TextureLayer[st].TrilinearFilter != material.TextureLayer[st].TrilinearFilter ||
 
2378
                        lastmaterial.TextureLayer[st].AnisotropicFilter != material.TextureLayer[st].AnisotropicFilter ||
 
2379
                        lastmaterial.UseMipMaps != material.UseMipMaps)
 
2380
                {
 
2381
                        if (material.TextureLayer[st].BilinearFilter || material.TextureLayer[st].TrilinearFilter || material.TextureLayer[st].AnisotropicFilter)
 
2382
                        {
 
2383
                                D3DTEXTUREFILTERTYPE tftMag = ((Caps.TextureFilterCaps & D3DPTFILTERCAPS_MAGFANISOTROPIC) &&
 
2384
                                                material.TextureLayer[st].AnisotropicFilter) ? D3DTEXF_ANISOTROPIC : D3DTEXF_LINEAR;
 
2385
                                D3DTEXTUREFILTERTYPE tftMin = ((Caps.TextureFilterCaps & D3DPTFILTERCAPS_MINFANISOTROPIC) &&
 
2386
                                                material.TextureLayer[st].AnisotropicFilter) ? D3DTEXF_ANISOTROPIC : D3DTEXF_LINEAR;
 
2387
                                D3DTEXTUREFILTERTYPE tftMip = material.UseMipMaps? (material.TextureLayer[st].TrilinearFilter ? D3DTEXF_LINEAR : D3DTEXF_POINT) : D3DTEXF_NONE;
 
2388
 
 
2389
                                if (tftMag==D3DTEXF_ANISOTROPIC || tftMin == D3DTEXF_ANISOTROPIC)
 
2390
                                        pID3DDevice->SetSamplerState(st, D3DSAMP_MAXANISOTROPY, core::min_((DWORD)material.TextureLayer[st].AnisotropicFilter, Caps.MaxAnisotropy));
 
2391
                                pID3DDevice->SetSamplerState(st, D3DSAMP_MAGFILTER, tftMag);
 
2392
                                pID3DDevice->SetSamplerState(st, D3DSAMP_MINFILTER, tftMin);
 
2393
                                pID3DDevice->SetSamplerState(st, D3DSAMP_MIPFILTER, tftMip);
 
2394
                        }
 
2395
                        else
 
2396
                        {
 
2397
                                pID3DDevice->SetSamplerState(st, D3DSAMP_MINFILTER, D3DTEXF_POINT);
 
2398
                                pID3DDevice->SetSamplerState(st, D3DSAMP_MIPFILTER, D3DTEXF_NONE);
 
2399
                                pID3DDevice->SetSamplerState(st, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
 
2400
                        }
 
2401
                }
 
2402
        }
 
2403
}
 
2404
 
 
2405
 
 
2406
//! sets the needed renderstates
 
2407
void CD3D9Driver::setRenderStatesStencilShadowMode(bool zfail)
 
2408
{
 
2409
        if ((CurrentRenderMode != ERM_SHADOW_VOLUME_ZFAIL &&
 
2410
                CurrentRenderMode != ERM_SHADOW_VOLUME_ZPASS) ||
 
2411
                Transformation3DChanged)
 
2412
        {
 
2413
                // switch back the matrices
 
2414
                pID3DDevice->SetTransform(D3DTS_VIEW, (D3DMATRIX*)((void*)&Matrices[ETS_VIEW]));
 
2415
                pID3DDevice->SetTransform(D3DTS_WORLD, (D3DMATRIX*)((void*)&Matrices[ETS_WORLD]));
 
2416
                pID3DDevice->SetTransform(D3DTS_PROJECTION, (D3DMATRIX*)((void*)&Matrices[ETS_PROJECTION]));
 
2417
 
 
2418
                Transformation3DChanged = false;
 
2419
 
 
2420
                setActiveTexture(0,0);
 
2421
                setActiveTexture(1,0);
 
2422
                setActiveTexture(2,0);
 
2423
                setActiveTexture(3,0);
 
2424
 
 
2425
                pID3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_DISABLE);
 
2426
 
 
2427
                pID3DDevice->SetFVF(D3DFVF_XYZ);
 
2428
                LastVertexType = (video::E_VERTEX_TYPE)(-1);
 
2429
 
 
2430
                pID3DDevice->SetRenderState( D3DRS_ZWRITEENABLE, FALSE );
 
2431
                pID3DDevice->SetRenderState( D3DRS_STENCILENABLE, TRUE );
 
2432
                pID3DDevice->SetRenderState( D3DRS_SHADEMODE, D3DSHADE_FLAT);
 
2433
 
 
2434
                // unset last 3d material
 
2435
                if (CurrentRenderMode == ERM_3D &&
 
2436
                        Material.MaterialType >= 0 && Material.MaterialType < (s32)MaterialRenderers.size())
 
2437
                        MaterialRenderers[Material.MaterialType].Renderer->OnUnsetMaterial();
 
2438
 
 
2439
                //pID3DDevice->SetRenderState(D3DRS_FOGENABLE, FALSE);
 
2440
                //pID3DDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
 
2441
        }
 
2442
 
 
2443
        if (CurrentRenderMode != ERM_SHADOW_VOLUME_ZPASS && !zfail)
 
2444
        {
 
2445
                // USE THE ZPASS METHOD
 
2446
 
 
2447
                pID3DDevice->SetRenderState( D3DRS_STENCILFUNC, D3DCMP_ALWAYS );
 
2448
                pID3DDevice->SetRenderState( D3DRS_STENCILFAIL, D3DSTENCILOP_KEEP );
 
2449
                pID3DDevice->SetRenderState( D3DRS_STENCILZFAIL, D3DSTENCILOP_KEEP );
 
2450
                pID3DDevice->SetRenderState( D3DRS_STENCILPASS, D3DSTENCILOP_INCR );
 
2451
 
 
2452
                pID3DDevice->SetRenderState( D3DRS_STENCILREF, 0x0 );
 
2453
                pID3DDevice->SetRenderState( D3DRS_STENCILMASK, 0xffffffff );
 
2454
                pID3DDevice->SetRenderState( D3DRS_STENCILWRITEMASK, 0xffffffff );
 
2455
 
 
2456
                pID3DDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE);
 
2457
                pID3DDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_ZERO );
 
2458
                pID3DDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_ONE );
 
2459
        }
 
2460
        else
 
2461
        if (CurrentRenderMode != ERM_SHADOW_VOLUME_ZFAIL && zfail)
 
2462
        {
 
2463
                // USE THE ZFAIL METHOD
 
2464
 
 
2465
                pID3DDevice->SetRenderState( D3DRS_STENCILFUNC, D3DCMP_ALWAYS );
 
2466
                pID3DDevice->SetRenderState( D3DRS_STENCILFAIL, D3DSTENCILOP_KEEP );
 
2467
                pID3DDevice->SetRenderState( D3DRS_STENCILZFAIL, D3DSTENCILOP_INCR );
 
2468
                pID3DDevice->SetRenderState( D3DRS_STENCILPASS, D3DSTENCILOP_KEEP );
 
2469
 
 
2470
                pID3DDevice->SetRenderState( D3DRS_STENCILREF, 0x0 );
 
2471
                pID3DDevice->SetRenderState( D3DRS_STENCILMASK, 0xffffffff );
 
2472
                pID3DDevice->SetRenderState( D3DRS_STENCILWRITEMASK, 0xffffffff );
 
2473
 
 
2474
                pID3DDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
 
2475
                pID3DDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_ZERO );
 
2476
                pID3DDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_ONE );
 
2477
        }
 
2478
 
 
2479
        CurrentRenderMode = zfail ? ERM_SHADOW_VOLUME_ZFAIL : ERM_SHADOW_VOLUME_ZPASS;
 
2480
}
 
2481
 
 
2482
 
 
2483
//! sets the needed renderstates
 
2484
void CD3D9Driver::setRenderStatesStencilFillMode(bool alpha)
 
2485
{
 
2486
        if (CurrentRenderMode != ERM_STENCIL_FILL || Transformation3DChanged)
 
2487
        {
 
2488
                core::matrix4 mat;
 
2489
                pID3DDevice->SetTransform(D3DTS_VIEW, &UnitMatrixD3D9);
 
2490
                pID3DDevice->SetTransform(D3DTS_WORLD, &UnitMatrixD3D9);
 
2491
                pID3DDevice->SetTransform(D3DTS_PROJECTION, &UnitMatrixD3D9);
 
2492
 
 
2493
                pID3DDevice->SetRenderState(D3DRS_ZENABLE, FALSE);
 
2494
                pID3DDevice->SetRenderState(D3DRS_LIGHTING, FALSE);
 
2495
                pID3DDevice->SetRenderState(D3DRS_FOGENABLE, FALSE);
 
2496
 
 
2497
                pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
 
2498
 
 
2499
                pID3DDevice->SetRenderState(D3DRS_STENCILREF, 0x1);
 
2500
                pID3DDevice->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_LESSEQUAL);
 
2501
                //pID3DDevice->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_GREATEREQUAL);
 
2502
                pID3DDevice->SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_KEEP );
 
2503
                pID3DDevice->SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_KEEP );
 
2504
                pID3DDevice->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_KEEP );
 
2505
                pID3DDevice->SetRenderState(D3DRS_STENCILMASK, 0xffffffff );
 
2506
                pID3DDevice->SetRenderState(D3DRS_STENCILWRITEMASK, 0xffffffff );
 
2507
 
 
2508
                pID3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
 
2509
 
 
2510
                Transformation3DChanged = false;
 
2511
 
 
2512
                pID3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
 
2513
                pID3DDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
 
2514
                pID3DDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
 
2515
                pID3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
 
2516
                pID3DDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE);
 
2517
                if (alpha)
 
2518
                {
 
2519
                        pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
 
2520
                        pID3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
 
2521
                        pID3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
 
2522
                }
 
2523
                else
 
2524
                {
 
2525
                        pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
 
2526
                }
 
2527
        }
 
2528
 
 
2529
        CurrentRenderMode = ERM_STENCIL_FILL;
 
2530
}
 
2531
 
 
2532
 
 
2533
//! Enable the 2d override material
 
2534
void CD3D9Driver::enableMaterial2D(bool enable)
 
2535
{
 
2536
        if (!enable)
 
2537
                CurrentRenderMode = ERM_NONE;
 
2538
        CNullDriver::enableMaterial2D(enable);
 
2539
}
 
2540
 
 
2541
 
 
2542
//! sets the needed renderstates
 
2543
void CD3D9Driver::setRenderStates2DMode(bool alpha, bool texture, bool alphaChannel)
 
2544
{
 
2545
        if (!pID3DDevice)
 
2546
                return;
 
2547
 
 
2548
        if (CurrentRenderMode != ERM_2D || Transformation3DChanged)
 
2549
        {
 
2550
                // unset last 3d material
 
2551
                if (CurrentRenderMode == ERM_3D)
 
2552
                {
 
2553
                        if (static_cast<u32>(LastMaterial.MaterialType) < MaterialRenderers.size())
 
2554
                                MaterialRenderers[LastMaterial.MaterialType].Renderer->OnUnsetMaterial();
 
2555
                }
 
2556
                if (!OverrideMaterial2DEnabled)
 
2557
                {
 
2558
                        setBasicRenderStates(InitMaterial2D, LastMaterial, true);
 
2559
                        LastMaterial=InitMaterial2D;
 
2560
 
 
2561
                        // fix everything that is wrongly set by InitMaterial2D default
 
2562
                        pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
 
2563
 
 
2564
                        pID3DDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE);
 
2565
                }
 
2566
                pID3DDevice->SetTransform(D3DTS_WORLD, &UnitMatrixD3D9);
 
2567
 
 
2568
                core::matrix4 m;
 
2569
                m.setTranslation(core::vector3df(-0.5f,-0.5f,0));
 
2570
                pID3DDevice->SetTransform(D3DTS_VIEW, (D3DMATRIX*)((void*)m.pointer()));
 
2571
 
 
2572
                const core::dimension2d<u32>& renderTargetSize = getCurrentRenderTargetSize();
 
2573
                m.buildProjectionMatrixOrthoLH(f32(renderTargetSize.Width), f32(-(s32)(renderTargetSize.Height)), -1.0, 1.0);
 
2574
                m.setTranslation(core::vector3df(-1,1,0));
 
2575
                pID3DDevice->SetTransform(D3DTS_PROJECTION, (D3DMATRIX*)((void*)m.pointer()));
 
2576
 
 
2577
                pID3DDevice->SetRenderState(D3DRS_CLIPPING, FALSE);
 
2578
 
 
2579
                Transformation3DChanged = false;
 
2580
        }
 
2581
        if (OverrideMaterial2DEnabled)
 
2582
        {
 
2583
                OverrideMaterial2D.Lighting=false;
 
2584
                setBasicRenderStates(OverrideMaterial2D, LastMaterial, false);
 
2585
                LastMaterial = OverrideMaterial2D;
 
2586
        }
 
2587
 
 
2588
        // no alphaChannel without texture
 
2589
        alphaChannel &= texture;
 
2590
 
 
2591
        if (alpha || alphaChannel)
 
2592
        {
 
2593
                pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
 
2594
                pID3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
 
2595
                pID3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
 
2596
        }
 
2597
        else
 
2598
                pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
 
2599
        pID3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
 
2600
        pID3DDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
 
2601
        pID3DDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
 
2602
        if (texture)
 
2603
        {
 
2604
                setTransform(ETS_TEXTURE_0, core::IdentityMatrix);
 
2605
                // Due to the transformation change, the previous line would call a reset each frame
 
2606
                // but we can safely reset the variable as it was false before
 
2607
                Transformation3DChanged=false;
 
2608
        }
 
2609
        if (alphaChannel)
 
2610
        {
 
2611
                pID3DDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
 
2612
 
 
2613
                if (alpha)
 
2614
                {
 
2615
                        pID3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
 
2616
                        pID3DDevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
 
2617
                }
 
2618
                else
 
2619
                {
 
2620
                        pID3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
 
2621
                }
 
2622
        }
 
2623
        else
 
2624
        {
 
2625
                pID3DDevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
 
2626
                if (alpha)
 
2627
                {
 
2628
                        pID3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG2);
 
2629
                }
 
2630
                else
 
2631
                {
 
2632
                        pID3DDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
 
2633
                        pID3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
 
2634
                }
 
2635
        }
 
2636
 
 
2637
        CurrentRenderMode = ERM_2D;
 
2638
}
 
2639
 
 
2640
 
 
2641
//! deletes all dynamic lights there are
 
2642
void CD3D9Driver::deleteAllDynamicLights()
 
2643
{
 
2644
        for (s32 i=0; i<LastSetLight+1; ++i)
 
2645
                pID3DDevice->LightEnable(i, false);
 
2646
 
 
2647
        LastSetLight = -1;
 
2648
 
 
2649
        CNullDriver::deleteAllDynamicLights();
 
2650
}
 
2651
 
 
2652
 
 
2653
//! adds a dynamic light
 
2654
s32 CD3D9Driver::addDynamicLight(const SLight& dl)
 
2655
{
 
2656
        CNullDriver::addDynamicLight(dl);
 
2657
 
 
2658
        D3DLIGHT9 light;
 
2659
 
 
2660
        switch (dl.Type)
 
2661
        {
 
2662
        case ELT_POINT:
 
2663
                light.Type = D3DLIGHT_POINT;
 
2664
        break;
 
2665
        case ELT_SPOT:
 
2666
                light.Type = D3DLIGHT_SPOT;
 
2667
        break;
 
2668
        case ELT_DIRECTIONAL:
 
2669
                light.Type = D3DLIGHT_DIRECTIONAL;
 
2670
        break;
 
2671
        }
 
2672
 
 
2673
        light.Position = *(D3DVECTOR*)((void*)(&dl.Position));
 
2674
        light.Direction = *(D3DVECTOR*)((void*)(&dl.Direction));
 
2675
 
 
2676
        light.Range = core::min_(dl.Radius, MaxLightDistance);
 
2677
        light.Falloff = dl.Falloff;
 
2678
 
 
2679
        light.Diffuse = *(D3DCOLORVALUE*)((void*)(&dl.DiffuseColor));
 
2680
        light.Specular = *(D3DCOLORVALUE*)((void*)(&dl.SpecularColor));
 
2681
        light.Ambient = *(D3DCOLORVALUE*)((void*)(&dl.AmbientColor));
 
2682
 
 
2683
        light.Attenuation0 = dl.Attenuation.X;
 
2684
        light.Attenuation1 = dl.Attenuation.Y;
 
2685
        light.Attenuation2 = dl.Attenuation.Z;
 
2686
 
 
2687
        light.Theta = dl.InnerCone * 2.0f * core::DEGTORAD;
 
2688
        light.Phi = dl.OuterCone * 2.0f * core::DEGTORAD;
 
2689
 
 
2690
        ++LastSetLight;
 
2691
 
 
2692
        if(D3D_OK == pID3DDevice->SetLight(LastSetLight, &light))
 
2693
        {
 
2694
                // I don't care if this succeeds
 
2695
                (void)pID3DDevice->LightEnable(LastSetLight, true);
 
2696
                return LastSetLight;
 
2697
        }
 
2698
 
 
2699
        return -1;
 
2700
}
 
2701
 
 
2702
//! Turns a dynamic light on or off
 
2703
//! \param lightIndex: the index returned by addDynamicLight
 
2704
//! \param turnOn: true to turn the light on, false to turn it off
 
2705
void CD3D9Driver::turnLightOn(s32 lightIndex, bool turnOn)
 
2706
{
 
2707
        if(lightIndex < 0 || lightIndex > LastSetLight)
 
2708
                return;
 
2709
 
 
2710
        (void)pID3DDevice->LightEnable(lightIndex, turnOn);
 
2711
}
 
2712
 
 
2713
 
 
2714
//! returns the maximal amount of dynamic lights the device can handle
 
2715
u32 CD3D9Driver::getMaximalDynamicLightAmount() const
 
2716
{
 
2717
        return Caps.MaxActiveLights;
 
2718
}
 
2719
 
 
2720
 
 
2721
//! Sets the dynamic ambient light color. The default color is
 
2722
//! (0,0,0,0) which means it is dark.
 
2723
//! \param color: New color of the ambient light.
 
2724
void CD3D9Driver::setAmbientLight(const SColorf& color)
 
2725
{
 
2726
        if (!pID3DDevice)
 
2727
                return;
 
2728
 
 
2729
        AmbientLight = color;
 
2730
        D3DCOLOR col = color.toSColor().color;
 
2731
        pID3DDevice->SetRenderState(D3DRS_AMBIENT, col);
 
2732
}
 
2733
 
 
2734
 
 
2735
//! \return Returns the name of the video driver. Example: In case of the DIRECT3D9
 
2736
//! driver, it would return "Direct3D9.0".
 
2737
const wchar_t* CD3D9Driver::getName() const
 
2738
{
 
2739
        return L"Direct3D 9.0";
 
2740
}
 
2741
 
 
2742
 
 
2743
//! Draws a shadow volume into the stencil buffer. To draw a stencil shadow, do
 
2744
//! this: Frist, draw all geometry. Then use this method, to draw the shadow
 
2745
//! volume. Then, use IVideoDriver::drawStencilShadow() to visualize the shadow.
 
2746
void CD3D9Driver::drawStencilShadowVolume(const core::vector3df* triangles, s32 count, bool zfail)
 
2747
{
 
2748
        if (!Params.Stencilbuffer || !count)
 
2749
                return;
 
2750
 
 
2751
        setRenderStatesStencilShadowMode(zfail);
 
2752
 
 
2753
        if (!zfail)
 
2754
        {
 
2755
                // ZPASS Method
 
2756
 
 
2757
                // Draw front-side of shadow volume in stencil/z only
 
2758
                pID3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
 
2759
                pID3DDevice->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_INCR);
 
2760
                pID3DDevice->DrawPrimitiveUP(D3DPT_TRIANGLELIST, count / 3, triangles, sizeof(core::vector3df));
 
2761
 
 
2762
                // Now reverse cull order so front sides of shadow volume are written.
 
2763
                pID3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW);
 
2764
                pID3DDevice->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_DECR);
 
2765
                pID3DDevice->DrawPrimitiveUP(D3DPT_TRIANGLELIST, count / 3, triangles, sizeof(core::vector3df));
 
2766
        }
 
2767
        else
 
2768
        {
 
2769
                // ZFAIL Method
 
2770
 
 
2771
                // Draw front-side of shadow volume in stencil/z only
 
2772
                pID3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW);
 
2773
                pID3DDevice->SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_INCR);
 
2774
                pID3DDevice->DrawPrimitiveUP(D3DPT_TRIANGLELIST, count / 3, triangles, sizeof(core::vector3df));
 
2775
 
 
2776
                // Now reverse cull order so front sides of shadow volume are written.
 
2777
                pID3DDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CCW);
 
2778
                pID3DDevice->SetRenderState( D3DRS_STENCILZFAIL, D3DSTENCILOP_DECR);
 
2779
                pID3DDevice->DrawPrimitiveUP(D3DPT_TRIANGLELIST, count / 3, triangles, sizeof(core::vector3df));
 
2780
        }
 
2781
}
 
2782
 
 
2783
 
 
2784
//! Fills the stencil shadow with color. After the shadow volume has been drawn
 
2785
//! into the stencil buffer using IVideoDriver::drawStencilShadowVolume(), use this
 
2786
//! to draw the color of the shadow.
 
2787
void CD3D9Driver::drawStencilShadow(bool clearStencilBuffer, video::SColor leftUpEdge,
 
2788
                        video::SColor rightUpEdge, video::SColor leftDownEdge, video::SColor rightDownEdge)
 
2789
{
 
2790
        if (!Params.Stencilbuffer)
 
2791
                return;
 
2792
 
 
2793
        S3DVertex vtx[4];
 
2794
        vtx[0] = S3DVertex(1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, leftUpEdge, 0.0f, 0.0f);
 
2795
        vtx[1] = S3DVertex(1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, rightUpEdge, 0.0f, 1.0f);
 
2796
        vtx[2] = S3DVertex(-1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, leftDownEdge, 1.0f, 0.0f);
 
2797
        vtx[3] = S3DVertex(-1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, rightDownEdge, 1.0f, 1.0f);
 
2798
 
 
2799
        s16 indices[6] = {0,1,2,1,3,2};
 
2800
 
 
2801
        setRenderStatesStencilFillMode(
 
2802
                leftUpEdge.getAlpha() < 255 ||
 
2803
                rightUpEdge.getAlpha() < 255 ||
 
2804
                leftDownEdge.getAlpha() < 255 ||
 
2805
                rightDownEdge.getAlpha() < 255);
 
2806
 
 
2807
        setActiveTexture(0,0);
 
2808
 
 
2809
        setVertexShader(EVT_STANDARD);
 
2810
 
 
2811
        pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST, 0, 4, 2, &indices[0],
 
2812
                D3DFMT_INDEX16, &vtx[0], sizeof(S3DVertex));
 
2813
 
 
2814
        if (clearStencilBuffer)
 
2815
                pID3DDevice->Clear( 0, NULL, D3DCLEAR_STENCIL,0, 1.0, 0);
 
2816
}
 
2817
 
 
2818
 
 
2819
//! Returns the maximum amount of primitives (mostly vertices) which
 
2820
//! the device is able to render with one drawIndexedTriangleList
 
2821
//! call.
 
2822
u32 CD3D9Driver::getMaximalPrimitiveCount() const
 
2823
{
 
2824
        return Caps.MaxPrimitiveCount;
 
2825
}
 
2826
 
 
2827
 
 
2828
//! Sets the fog mode.
 
2829
void CD3D9Driver::setFog(SColor color, E_FOG_TYPE fogType, f32 start,
 
2830
        f32 end, f32 density, bool pixelFog, bool rangeFog)
 
2831
{
 
2832
        CNullDriver::setFog(color, fogType, start, end, density, pixelFog, rangeFog);
 
2833
 
 
2834
        if (!pID3DDevice)
 
2835
                return;
 
2836
 
 
2837
        pID3DDevice->SetRenderState(D3DRS_FOGCOLOR, color.color);
 
2838
 
 
2839
        pID3DDevice->SetRenderState(
 
2840
                pixelFog ? D3DRS_FOGTABLEMODE : D3DRS_FOGVERTEXMODE,
 
2841
                (fogType==EFT_FOG_LINEAR)? D3DFOG_LINEAR : (fogType==EFT_FOG_EXP)?D3DFOG_EXP:D3DFOG_EXP2);
 
2842
 
 
2843
        if (fogType==EFT_FOG_LINEAR)
 
2844
        {
 
2845
                pID3DDevice->SetRenderState(D3DRS_FOGSTART, F2DW(start));
 
2846
                pID3DDevice->SetRenderState(D3DRS_FOGEND, F2DW(end));
 
2847
        }
 
2848
        else
 
2849
                pID3DDevice->SetRenderState(D3DRS_FOGDENSITY, F2DW(density));
 
2850
 
 
2851
        if(!pixelFog)
 
2852
                pID3DDevice->SetRenderState(D3DRS_RANGEFOGENABLE, rangeFog);
 
2853
}
 
2854
 
 
2855
 
 
2856
//! Draws a 3d line.
 
2857
void CD3D9Driver::draw3DLine(const core::vector3df& start,
 
2858
        const core::vector3df& end, SColor color)
 
2859
{
 
2860
        setVertexShader(EVT_STANDARD);
 
2861
        setRenderStates3DMode();
 
2862
        video::S3DVertex v[2];
 
2863
        v[0].Color = color;
 
2864
        v[1].Color = color;
 
2865
        v[0].Pos = start;
 
2866
        v[1].Pos = end;
 
2867
 
 
2868
        pID3DDevice->DrawPrimitiveUP(D3DPT_LINELIST, 1, v, sizeof(S3DVertex));
 
2869
}
 
2870
 
 
2871
 
 
2872
//! resets the device
 
2873
bool CD3D9Driver::reset()
 
2874
{
 
2875
        u32 i;
 
2876
        os::Printer::log("Resetting D3D9 device.", ELL_INFORMATION);
 
2877
 
 
2878
        for (i=0; i<Textures.size(); ++i)
 
2879
        {
 
2880
                if (Textures[i].Surface->isRenderTarget())
 
2881
                {
 
2882
                        IDirect3DBaseTexture9* tex = ((CD3D9Texture*)(Textures[i].Surface))->getDX9Texture();
 
2883
                        if (tex)
 
2884
                                tex->Release();
 
2885
                }
 
2886
        }
 
2887
        for (i=0; i<DepthBuffers.size(); ++i)
 
2888
        {
 
2889
                if (DepthBuffers[i]->Surface)
 
2890
                        DepthBuffers[i]->Surface->Release();
 
2891
        }
 
2892
        for (i=0; i<OcclusionQueries.size(); ++i)
 
2893
        {
 
2894
                if (OcclusionQueries[i].PID)
 
2895
                {
 
2896
                        reinterpret_cast<IDirect3DQuery9*>(OcclusionQueries[i].PID)->Release();
 
2897
                        OcclusionQueries[i].PID=0;
 
2898
                }
 
2899
        }
 
2900
        // this does not require a restore in the reset method, it's updated
 
2901
        // automatically in the next render cycle.
 
2902
        removeAllHardwareBuffers();
 
2903
 
 
2904
        DriverWasReset=true;
 
2905
 
 
2906
        HRESULT hr = pID3DDevice->Reset(&present);
 
2907
 
 
2908
        // restore RTTs
 
2909
        for (i=0; i<Textures.size(); ++i)
 
2910
        {
 
2911
                if (Textures[i].Surface->isRenderTarget())
 
2912
                        ((CD3D9Texture*)(Textures[i].Surface))->createRenderTarget();
 
2913
        }
 
2914
 
 
2915
        // restore screen depthbuffer
 
2916
        pID3DDevice->GetDepthStencilSurface(&(DepthBuffers[0]->Surface));
 
2917
        D3DSURFACE_DESC desc;
 
2918
        // restore other depth buffers
 
2919
        // depth format is taken from main depth buffer
 
2920
        DepthBuffers[0]->Surface->GetDesc(&desc);
 
2921
        // multisampling is taken from rendertarget
 
2922
        D3DSURFACE_DESC desc2;
 
2923
        for (i=1; i<DepthBuffers.size(); ++i)
 
2924
        {
 
2925
                for (u32 j=0; j<Textures.size(); ++j)
 
2926
                {
 
2927
                        // all textures sharing this depth buffer must have the same setting
 
2928
                        // so take first one
 
2929
                        if (((CD3D9Texture*)(Textures[j].Surface))->DepthSurface==DepthBuffers[i])
 
2930
                        {
 
2931
                                ((CD3D9Texture*)(Textures[j].Surface))->Texture->GetLevelDesc(0,&desc2);
 
2932
                                break;
 
2933
                        }
 
2934
                }
 
2935
 
 
2936
                pID3DDevice->CreateDepthStencilSurface(DepthBuffers[i]->Size.Width,
 
2937
                                DepthBuffers[i]->Size.Height,
 
2938
                                desc.Format,
 
2939
                                desc2.MultiSampleType,
 
2940
                                desc2.MultiSampleQuality,
 
2941
                                TRUE,
 
2942
                                &(DepthBuffers[i]->Surface),
 
2943
                                NULL);
 
2944
        }
 
2945
        for (i=0; i<OcclusionQueries.size(); ++i)
 
2946
        {
 
2947
                pID3DDevice->CreateQuery(D3DQUERYTYPE_OCCLUSION, reinterpret_cast<IDirect3DQuery9**>(&OcclusionQueries[i].PID));
 
2948
        }
 
2949
 
 
2950
        if (FAILED(hr))
 
2951
        {
 
2952
                if (hr == D3DERR_DEVICELOST)
 
2953
                {
 
2954
                        DeviceLost = true;
 
2955
                        os::Printer::log("Resetting failed due to device lost.", ELL_WARNING);
 
2956
                }
 
2957
#ifdef D3DERR_DEVICEREMOVED
 
2958
                else if (hr == D3DERR_DEVICEREMOVED)
 
2959
                {
 
2960
                        os::Printer::log("Resetting failed due to device removed.", ELL_WARNING);
 
2961
                }
 
2962
#endif
 
2963
                else if (hr == D3DERR_DRIVERINTERNALERROR)
 
2964
                {
 
2965
                        os::Printer::log("Resetting failed due to internal error.", ELL_WARNING);
 
2966
                }
 
2967
                else if (hr == D3DERR_OUTOFVIDEOMEMORY)
 
2968
                {
 
2969
                        os::Printer::log("Resetting failed due to out of memory.", ELL_WARNING);
 
2970
                }
 
2971
                else if (hr == D3DERR_DEVICENOTRESET)
 
2972
                {
 
2973
                        os::Printer::log("Resetting failed due to not reset.", ELL_WARNING);
 
2974
                }
 
2975
                else if (hr == D3DERR_INVALIDCALL)
 
2976
                {
 
2977
                        os::Printer::log("Resetting failed due to invalid call", "You need to release some more surfaces.", ELL_WARNING);
 
2978
                }
 
2979
                else
 
2980
                {
 
2981
                        os::Printer::log("Resetting failed due to unknown reason.", core::stringc((int)hr).c_str(), ELL_WARNING);
 
2982
                }
 
2983
                return false;
 
2984
        }
 
2985
 
 
2986
        DeviceLost = false;
 
2987
        ResetRenderStates = true;
 
2988
        LastVertexType = (E_VERTEX_TYPE)-1;
 
2989
 
 
2990
        for (u32 i=0; i<MATERIAL_MAX_TEXTURES; ++i)
 
2991
                CurrentTexture[i] = 0;
 
2992
 
 
2993
        setVertexShader(EVT_STANDARD);
 
2994
        setRenderStates3DMode();
 
2995
        setFog(FogColor, FogType, FogStart, FogEnd, FogDensity, PixelFog, RangeFog);
 
2996
        setAmbientLight(AmbientLight);
 
2997
 
 
2998
        return true;
 
2999
}
 
3000
 
 
3001
 
 
3002
void CD3D9Driver::OnResize(const core::dimension2d<u32>& size)
 
3003
{
 
3004
        if (!pID3DDevice)
 
3005
                return;
 
3006
 
 
3007
        CNullDriver::OnResize(size);
 
3008
        present.BackBufferWidth = size.Width;
 
3009
        present.BackBufferHeight = size.Height;
 
3010
 
 
3011
        reset();
 
3012
}
 
3013
 
 
3014
 
 
3015
//! Returns type of video driver
 
3016
E_DRIVER_TYPE CD3D9Driver::getDriverType() const
 
3017
{
 
3018
        return EDT_DIRECT3D9;
 
3019
}
 
3020
 
 
3021
 
 
3022
//! Returns the transformation set by setTransform
 
3023
const core::matrix4& CD3D9Driver::getTransform(E_TRANSFORMATION_STATE state) const
 
3024
{
 
3025
        return Matrices[state];
 
3026
}
 
3027
 
 
3028
 
 
3029
//! Sets a vertex shader constant.
 
3030
void CD3D9Driver::setVertexShaderConstant(const f32* data, s32 startRegister, s32 constantAmount)
 
3031
{
 
3032
        if (data)
 
3033
                pID3DDevice->SetVertexShaderConstantF(startRegister, data, constantAmount);
 
3034
}
 
3035
 
 
3036
 
 
3037
//! Sets a pixel shader constant.
 
3038
void CD3D9Driver::setPixelShaderConstant(const f32* data, s32 startRegister, s32 constantAmount)
 
3039
{
 
3040
        if (data)
 
3041
                pID3DDevice->SetPixelShaderConstantF(startRegister, data, constantAmount);
 
3042
}
 
3043
 
 
3044
 
 
3045
//! Sets a constant for the vertex shader based on a name.
 
3046
bool CD3D9Driver::setVertexShaderConstant(const c8* name, const f32* floats, int count)
 
3047
{
 
3048
        if (Material.MaterialType >= 0 && Material.MaterialType < (s32)MaterialRenderers.size())
 
3049
        {
 
3050
                CD3D9MaterialRenderer* r = (CD3D9MaterialRenderer*)MaterialRenderers[Material.MaterialType].Renderer;
 
3051
                return r->setVariable(true, name, floats, count);
 
3052
        }
 
3053
 
 
3054
        return false;
 
3055
}
 
3056
 
 
3057
 
 
3058
//! Sets a constant for the pixel shader based on a name.
 
3059
bool CD3D9Driver::setPixelShaderConstant(const c8* name, const f32* floats, int count)
 
3060
{
 
3061
        if (Material.MaterialType >= 0 && Material.MaterialType < (s32)MaterialRenderers.size())
 
3062
        {
 
3063
                CD3D9MaterialRenderer* r = (CD3D9MaterialRenderer*)MaterialRenderers[Material.MaterialType].Renderer;
 
3064
                return r->setVariable(false, name, floats, count);
 
3065
        }
 
3066
 
 
3067
        return false;
 
3068
}
 
3069
 
 
3070
 
 
3071
//! Adds a new material renderer to the VideoDriver, using pixel and/or
 
3072
//! vertex shaders to render geometry.
 
3073
s32 CD3D9Driver::addShaderMaterial(const c8* vertexShaderProgram,
 
3074
        const c8* pixelShaderProgram,
 
3075
        IShaderConstantSetCallBack* callback,
 
3076
        E_MATERIAL_TYPE baseMaterial, s32 userData)
 
3077
{
 
3078
        s32 nr = -1;
 
3079
        CD3D9ShaderMaterialRenderer* r = new CD3D9ShaderMaterialRenderer(
 
3080
                pID3DDevice, this, nr, vertexShaderProgram, pixelShaderProgram,
 
3081
                callback, getMaterialRenderer(baseMaterial), userData);
 
3082
 
 
3083
        r->drop();
 
3084
        return nr;
 
3085
}
 
3086
 
 
3087
 
 
3088
//! Adds a new material renderer to the VideoDriver, based on a high level shading
 
3089
//! language.
 
3090
s32 CD3D9Driver::addHighLevelShaderMaterial(
 
3091
                const c8* vertexShaderProgram,
 
3092
                const c8* vertexShaderEntryPointName,
 
3093
                E_VERTEX_SHADER_TYPE vsCompileTarget,
 
3094
                const c8* pixelShaderProgram,
 
3095
                const c8* pixelShaderEntryPointName,
 
3096
                E_PIXEL_SHADER_TYPE psCompileTarget,
 
3097
                const c8* geometryShaderProgram,
 
3098
                const c8* geometryShaderEntryPointName,
 
3099
                E_GEOMETRY_SHADER_TYPE gsCompileTarget,
 
3100
                scene::E_PRIMITIVE_TYPE inType, scene::E_PRIMITIVE_TYPE outType,
 
3101
                u32 verticesOut,
 
3102
                IShaderConstantSetCallBack* callback,
 
3103
                E_MATERIAL_TYPE baseMaterial, s32 userData)
 
3104
{
 
3105
        s32 nr = -1;
 
3106
 
 
3107
        CD3D9HLSLMaterialRenderer* hlsl = new CD3D9HLSLMaterialRenderer(
 
3108
                pID3DDevice, this, nr,
 
3109
                vertexShaderProgram,
 
3110
                vertexShaderEntryPointName,
 
3111
                vsCompileTarget,
 
3112
                pixelShaderProgram,
 
3113
                pixelShaderEntryPointName,
 
3114
                psCompileTarget,
 
3115
                callback,
 
3116
                getMaterialRenderer(baseMaterial),
 
3117
                userData);
 
3118
 
 
3119
        hlsl->drop();
 
3120
        return nr;
 
3121
}
 
3122
 
 
3123
 
 
3124
//! Returns a pointer to the IVideoDriver interface. (Implementation for
 
3125
//! IMaterialRendererServices)
 
3126
IVideoDriver* CD3D9Driver::getVideoDriver()
 
3127
{
 
3128
        return this;
 
3129
}
 
3130
 
 
3131
 
 
3132
//! Creates a render target texture.
 
3133
ITexture* CD3D9Driver::addRenderTargetTexture(const core::dimension2d<u32>& size,
 
3134
                                                                                          const io::path& name,
 
3135
                                                                                          const ECOLOR_FORMAT format)
 
3136
{
 
3137
        CD3D9Texture* tex = new CD3D9Texture(this, size, name, format);
 
3138
        if (tex)
 
3139
        {
 
3140
                if (!tex->Texture)
 
3141
                {
 
3142
                        tex->drop();
 
3143
                        return 0;
 
3144
                }
 
3145
                checkDepthBuffer(tex);
 
3146
                addTexture(tex);
 
3147
                tex->drop();
 
3148
        }
 
3149
        return tex;
 
3150
}
 
3151
 
 
3152
 
 
3153
//! Clears the ZBuffer.
 
3154
void CD3D9Driver::clearZBuffer()
 
3155
{
 
3156
        HRESULT hr = pID3DDevice->Clear( 0, NULL, D3DCLEAR_ZBUFFER, 0, 1.0, 0);
 
3157
 
 
3158
        if (FAILED(hr))
 
3159
                os::Printer::log("CD3D9Driver clearZBuffer() failed.", ELL_WARNING);
 
3160
}
 
3161
 
 
3162
 
 
3163
//! Returns an image created from the last rendered frame.
 
3164
IImage* CD3D9Driver::createScreenShot(video::ECOLOR_FORMAT format, video::E_RENDER_TARGET target)
 
3165
{
 
3166
        if (target != video::ERT_FRAME_BUFFER)
 
3167
                return 0;
 
3168
 
 
3169
        // query the screen dimensions of the current adapter
 
3170
        D3DDISPLAYMODE displayMode;
 
3171
        pID3DDevice->GetDisplayMode(0, &displayMode);
 
3172
 
 
3173
        if (format==video::ECF_UNKNOWN)
 
3174
                format=video::ECF_A8R8G8B8;
 
3175
 
 
3176
        // create the image surface to store the front buffer image [always A8R8G8B8]
 
3177
        HRESULT hr;
 
3178
        LPDIRECT3DSURFACE9 lpSurface;
 
3179
        if (FAILED(hr = pID3DDevice->CreateOffscreenPlainSurface(displayMode.Width, displayMode.Height, D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &lpSurface, 0)))
 
3180
                return 0;
 
3181
 
 
3182
        // read the front buffer into the image surface
 
3183
        if (FAILED(hr = pID3DDevice->GetFrontBufferData(0, lpSurface)))
 
3184
        {
 
3185
                lpSurface->Release();
 
3186
                return 0;
 
3187
        }
 
3188
 
 
3189
        RECT clientRect;
 
3190
        {
 
3191
                POINT clientPoint;
 
3192
                clientPoint.x = 0;
 
3193
                clientPoint.y = 0;
 
3194
 
 
3195
                ClientToScreen((HWND)getExposedVideoData().D3D9.HWnd, &clientPoint);
 
3196
 
 
3197
                clientRect.left   = clientPoint.x;
 
3198
                clientRect.top  = clientPoint.y;
 
3199
                clientRect.right  = clientRect.left + ScreenSize.Width;
 
3200
                clientRect.bottom = clientRect.top  + ScreenSize.Height;
 
3201
 
 
3202
                // window can be off-screen partly, we can't take screenshots from that
 
3203
                clientRect.left = core::max_(clientRect.left, 0l);
 
3204
                clientRect.top = core::max_(clientRect.top, 0l);
 
3205
                clientRect.right = core::min_(clientRect.right, (long)displayMode.Width);
 
3206
                clientRect.bottom = core::min_(clientRect.bottom, (long)displayMode.Height );
 
3207
        }
 
3208
 
 
3209
        // lock our area of the surface
 
3210
        D3DLOCKED_RECT lockedRect;
 
3211
        if (FAILED(lpSurface->LockRect(&lockedRect, &clientRect, D3DLOCK_READONLY)))
 
3212
        {
 
3213
                lpSurface->Release();
 
3214
                return 0;
 
3215
        }
 
3216
 
 
3217
        irr::core::dimension2d<u32> shotSize;
 
3218
        shotSize.Width = core::min_( ScreenSize.Width, (u32)(clientRect.right-clientRect.left) );
 
3219
        shotSize.Height = core::min_( ScreenSize.Height, (u32)(clientRect.bottom-clientRect.top) );
 
3220
 
 
3221
        // this could throw, but we aren't going to worry about that case very much
 
3222
        IImage* newImage = createImage(format, shotSize);
 
3223
 
 
3224
        if (newImage)
 
3225
        {
 
3226
                // d3d pads the image, so we need to copy the correct number of bytes
 
3227
                u32* dP = (u32*)newImage->lock();
 
3228
                u8 * sP = (u8 *)lockedRect.pBits;
 
3229
 
 
3230
                // If the display mode format doesn't promise anything about the Alpha value
 
3231
                // and it appears that it's not presenting 255, then we should manually
 
3232
                // set each pixel alpha value to 255.
 
3233
                if (D3DFMT_X8R8G8B8 == displayMode.Format && (0xFF000000 != (*dP & 0xFF000000)))
 
3234
                {
 
3235
                        for (u32 y = 0; y < shotSize.Height; ++y)
 
3236
                        {
 
3237
                                for (u32 x = 0; x < shotSize.Width; ++x)
 
3238
                                {
 
3239
                                        newImage->setPixel(x,y,*((u32*)sP) | 0xFF000000);
 
3240
                                        sP += 4;
 
3241
                                }
 
3242
 
 
3243
                                sP += lockedRect.Pitch - (4 * shotSize.Width);
 
3244
                        }
 
3245
                }
 
3246
                else
 
3247
                {
 
3248
                        for (u32 y = 0; y < shotSize.Height; ++y)
 
3249
                        {
 
3250
                                convertColor(sP, video::ECF_A8R8G8B8, shotSize.Width, dP, format);
 
3251
                                sP += lockedRect.Pitch;
 
3252
                                dP += shotSize.Width;
 
3253
                        }
 
3254
                }
 
3255
 
 
3256
                newImage->unlock();
 
3257
        }
 
3258
 
 
3259
        // we can unlock and release the surface
 
3260
        lpSurface->UnlockRect();
 
3261
 
 
3262
        // release the image surface
 
3263
        lpSurface->Release();
 
3264
 
 
3265
        // return status of save operation to caller
 
3266
        return newImage;
 
3267
}
 
3268
 
 
3269
 
 
3270
//! returns color format
 
3271
ECOLOR_FORMAT CD3D9Driver::getColorFormat() const
 
3272
{
 
3273
        return ColorFormat;
 
3274
}
 
3275
 
 
3276
 
 
3277
//! returns color format
 
3278
D3DFORMAT CD3D9Driver::getD3DColorFormat() const
 
3279
{
 
3280
        return D3DColorFormat;
 
3281
}
 
3282
 
 
3283
 
 
3284
// returns the current size of the screen or rendertarget
 
3285
const core::dimension2d<u32>& CD3D9Driver::getCurrentRenderTargetSize() const
 
3286
{
 
3287
        if ( CurrentRendertargetSize.Width == 0 )
 
3288
                return ScreenSize;
 
3289
        else
 
3290
                return CurrentRendertargetSize;
 
3291
}
 
3292
 
 
3293
 
 
3294
// Set/unset a clipping plane.
 
3295
bool CD3D9Driver::setClipPlane(u32 index, const core::plane3df& plane, bool enable)
 
3296
{
 
3297
        if (index >= MaxUserClipPlanes)
 
3298
                return false;
 
3299
 
 
3300
        pID3DDevice->SetClipPlane(index, (const float*)&plane);
 
3301
        enableClipPlane(index, enable);
 
3302
        return true;
 
3303
}
 
3304
 
 
3305
 
 
3306
// Enable/disable a clipping plane.
 
3307
void CD3D9Driver::enableClipPlane(u32 index, bool enable)
 
3308
{
 
3309
        if (index >= MaxUserClipPlanes)
 
3310
                return;
 
3311
        DWORD renderstate;
 
3312
        pID3DDevice->GetRenderState(D3DRS_CLIPPLANEENABLE, &renderstate);
 
3313
        if (enable)
 
3314
                renderstate |= (1 << index);
 
3315
        else
 
3316
                renderstate &= ~(1 << index);
 
3317
        pID3DDevice->SetRenderState(D3DRS_CLIPPLANEENABLE, renderstate);
 
3318
}
 
3319
 
 
3320
 
 
3321
D3DFORMAT CD3D9Driver::getD3DFormatFromColorFormat(ECOLOR_FORMAT format) const
 
3322
{
 
3323
        switch(format)
 
3324
        {
 
3325
                case ECF_A1R5G5B5:
 
3326
                        return D3DFMT_A1R5G5B5;
 
3327
                case ECF_R5G6B5:
 
3328
                        return D3DFMT_R5G6B5;
 
3329
                case ECF_R8G8B8:
 
3330
                        return D3DFMT_R8G8B8;
 
3331
                case ECF_A8R8G8B8:
 
3332
                        return D3DFMT_A8R8G8B8;
 
3333
 
 
3334
                // Floating Point formats. Thanks to Patryk "Nadro" Nadrowski.
 
3335
                case ECF_R16F:
 
3336
                        return D3DFMT_R16F;
 
3337
                case ECF_G16R16F:
 
3338
                        return D3DFMT_G16R16F;
 
3339
                case ECF_A16B16G16R16F:
 
3340
                        return D3DFMT_A16B16G16R16F;
 
3341
                case ECF_R32F:
 
3342
                        return D3DFMT_R32F;
 
3343
                case ECF_G32R32F:
 
3344
                        return D3DFMT_G32R32F;
 
3345
                case ECF_A32B32G32R32F:
 
3346
                        return D3DFMT_A32B32G32R32F;
 
3347
        }
 
3348
        return D3DFMT_UNKNOWN;
 
3349
}
 
3350
 
 
3351
 
 
3352
ECOLOR_FORMAT CD3D9Driver::getColorFormatFromD3DFormat(D3DFORMAT format) const
 
3353
{
 
3354
        switch(format)
 
3355
        {
 
3356
                case D3DFMT_X1R5G5B5:
 
3357
                case D3DFMT_A1R5G5B5:
 
3358
                        return ECF_A1R5G5B5;
 
3359
                case D3DFMT_A8B8G8R8:
 
3360
                case D3DFMT_A8R8G8B8:
 
3361
                case D3DFMT_X8R8G8B8:
 
3362
                        return ECF_A8R8G8B8;
 
3363
                case D3DFMT_R5G6B5:
 
3364
                        return ECF_R5G6B5;
 
3365
                case D3DFMT_R8G8B8:
 
3366
                        return ECF_R8G8B8;
 
3367
 
 
3368
                // Floating Point formats. Thanks to Patryk "Nadro" Nadrowski.
 
3369
                case D3DFMT_R16F:
 
3370
                        return ECF_R16F;
 
3371
                case D3DFMT_G16R16F:
 
3372
                        return ECF_G16R16F;
 
3373
                case D3DFMT_A16B16G16R16F:
 
3374
                        return ECF_A16B16G16R16F;
 
3375
                case D3DFMT_R32F:
 
3376
                        return ECF_R32F;
 
3377
                case D3DFMT_G32R32F:
 
3378
                        return ECF_G32R32F;
 
3379
                case D3DFMT_A32B32G32R32F:
 
3380
                        return ECF_A32B32G32R32F;
 
3381
                default:
 
3382
                        return (ECOLOR_FORMAT)0;
 
3383
        };
 
3384
}
 
3385
 
 
3386
 
 
3387
void CD3D9Driver::checkDepthBuffer(ITexture* tex)
 
3388
{
 
3389
        if (!tex)
 
3390
                return;
 
3391
        const core::dimension2du optSize = tex->getSize().getOptimalSize(
 
3392
                        !queryFeature(EVDF_TEXTURE_NPOT),
 
3393
                        !queryFeature(EVDF_TEXTURE_NSQUARE), true);
 
3394
        SDepthSurface* depth=0;
 
3395
        core::dimension2du destSize(0x7fffffff, 0x7fffffff);
 
3396
        for (u32 i=0; i<DepthBuffers.size(); ++i)
 
3397
        {
 
3398
                if ((DepthBuffers[i]->Size.Width>=optSize.Width) &&
 
3399
                        (DepthBuffers[i]->Size.Height>=optSize.Height))
 
3400
                {
 
3401
                        if ((DepthBuffers[i]->Size.Width<destSize.Width) &&
 
3402
                                (DepthBuffers[i]->Size.Height<destSize.Height))
 
3403
                        {
 
3404
                                depth = DepthBuffers[i];
 
3405
                                destSize=DepthBuffers[i]->Size;
 
3406
                        }
 
3407
                }
 
3408
        }
 
3409
        if (!depth)
 
3410
        {
 
3411
                D3DSURFACE_DESC desc;
 
3412
                DepthBuffers[0]->Surface->GetDesc(&desc);
 
3413
                // the multisampling needs to match the RTT
 
3414
                D3DSURFACE_DESC desc2;
 
3415
                ((CD3D9Texture*)tex)->Texture->GetLevelDesc(0,&desc2);
 
3416
                DepthBuffers.push_back(new SDepthSurface());
 
3417
                HRESULT hr=pID3DDevice->CreateDepthStencilSurface(optSize.Width,
 
3418
                                optSize.Height,
 
3419
                                desc.Format,
 
3420
                                desc2.MultiSampleType,
 
3421
                                desc2.MultiSampleQuality,
 
3422
                                TRUE,
 
3423
                                &(DepthBuffers.getLast()->Surface),
 
3424
                                NULL);
 
3425
                if (SUCCEEDED(hr))
 
3426
                {
 
3427
                        depth=DepthBuffers.getLast();
 
3428
                        depth->Surface->GetDesc(&desc);
 
3429
                        depth->Size.set(desc.Width, desc.Height);
 
3430
                }
 
3431
                else
 
3432
                {
 
3433
                        if (hr == D3DERR_OUTOFVIDEOMEMORY)
 
3434
                                os::Printer::log("Could not create DepthBuffer","out of video memory",ELL_ERROR);
 
3435
                        else if( hr == E_OUTOFMEMORY )
 
3436
                                os::Printer::log("Could not create DepthBuffer","out of memory",ELL_ERROR);
 
3437
                        else
 
3438
                        {
 
3439
                                char buffer[128];
 
3440
                                sprintf(buffer,"Could not create DepthBuffer of %ix%i",optSize.Width,optSize.Height);
 
3441
                                os::Printer::log(buffer,ELL_ERROR);
 
3442
                        }
 
3443
                        DepthBuffers.erase(DepthBuffers.size()-1);
 
3444
                }
 
3445
        }
 
3446
        else
 
3447
                depth->grab();
 
3448
 
 
3449
        static_cast<CD3D9Texture*>(tex)->DepthSurface=depth;
 
3450
}
 
3451
 
 
3452
 
 
3453
void CD3D9Driver::removeDepthSurface(SDepthSurface* depth)
 
3454
{
 
3455
        for (u32 i=0; i<DepthBuffers.size(); ++i)
 
3456
        {
 
3457
                if (DepthBuffers[i]==depth)
 
3458
                {
 
3459
                        DepthBuffers.erase(i);
 
3460
                        return;
 
3461
                }
 
3462
        }
 
3463
}
 
3464
 
 
3465
 
 
3466
core::dimension2du CD3D9Driver::getMaxTextureSize() const
 
3467
{
 
3468
        return core::dimension2du(Caps.MaxTextureWidth, Caps.MaxTextureHeight);
 
3469
}
 
3470
 
 
3471
 
 
3472
} // end namespace video
 
3473
} // end namespace irr
 
3474
 
 
3475
#endif // _IRR_COMPILE_WITH_DIRECT3D_9_
 
3476
 
 
3477
 
 
3478
 
 
3479
namespace irr
 
3480
{
 
3481
namespace video
 
3482
{
 
3483
 
 
3484
#ifdef _IRR_COMPILE_WITH_DIRECT3D_9_
 
3485
//! creates a video driver
 
3486
IVideoDriver* createDirectX9Driver(const SIrrlichtCreationParameters& params,
 
3487
                        io::IFileSystem* io, HWND window)
 
3488
{
 
3489
        const bool pureSoftware = false;
 
3490
        CD3D9Driver* dx9 = new CD3D9Driver(params, io);
 
3491
        if (!dx9->initDriver(window, pureSoftware))
 
3492
        {
 
3493
                dx9->drop();
 
3494
                dx9 = 0;
 
3495
        }
 
3496
 
 
3497
        return dx9;
 
3498
}
 
3499
#endif // _IRR_COMPILE_WITH_DIRECT3D_9_
 
3500
 
 
3501
} // end namespace video
 
3502
} // end namespace irr
 
3503