source: GTP/trunk/App/Demos/Geom/Shark3D/src/drv_d3d9_enum.cpp @ 2236

Revision 2236, 16.2 KB checked in by gumbau, 17 years ago (diff)
Line 
1///////////////////////////////////////////////////////////////////////////////
2//
3//      ##  ######
4//       ######  ###
5//  ## ###############        Shark 3D Engine (www.shark3d.com)
6//   ########## # # #
7//    ########                Copyright (c) 1996-2006 Spinor GmbH.
8//   ######### # # #          All rights reserved.
9//  ##   ##########
10//      ##
11//
12///////////////////////////////////////////////////////////////////////////////
13
14//@cpp
15
16#include "drv_d3d9_enum.h"
17#include "drv_d3d9_env.h"
18#include "drv_d3d9_util.h"
19#include "sys/core/sys_util.h"
20#include "util/cont/util_arrayalgo.h"
21
22///////////////////////////////////////////////////////////////////////////////
23
24static const D3DFORMAT drv_d3d9_AdapterFmtArray[] =
25{
26    D3DFMT_R5G6B5,
27    D3DFMT_X1R5G5B5,
28    D3DFMT_X8R8G8B8,
29    D3DFMT_A2R10G10B10, //fullscreen only
30};
31
32static const D3DFORMAT drv_d3d9_BackBufFmtArray[] =
33{
34    D3DFMT_X8R8G8B8,
35    D3DFMT_A8R8G8B8,
36    D3DFMT_R5G6B5,
37    D3DFMT_X1R5G5B5,
38    D3DFMT_A1R5G5B5,
39    D3DFMT_A2R10G10B10,
40};
41
42static const D3DFORMAT drv_d3d9_DepthStencilFmtArray[] =
43{
44    D3DFMT_D24S8,
45    D3DFMT_D24X4S4,
46    D3DFMT_D15S1,
47    D3DFMT_D24FS8,
48
49    D3DFMT_D32,
50    D3DFMT_D24X8,
51    D3DFMT_D16,
52    D3DFMT_D16_LOCKABLE,
53    D3DFMT_D32F_LOCKABLE,
54};
55
56static const D3DFORMAT drv_d3d9_DepthFmtArray[] =
57{
58    D3DFMT_D32,
59    D3DFMT_D24X8,
60    D3DFMT_D16,
61    D3DFMT_D16_LOCKABLE,
62    D3DFMT_D32F_LOCKABLE,
63};
64
65///////////////////////////////////////////////////////////////////////////////
66
67int s3d_CDrvD3d9EnumEntry::Compare(
68        const s3d_CDrvD3d9EnumEntry &e) const
69{
70    if(m_Adapter < e.m_Adapter)
71        return -1;
72    if(m_Adapter > e.m_Adapter)
73        return 1;
74   
75    int KeyFmtA = KeyOfFmt(m_AdapterFmt);
76    int KeyFmtB = KeyOfFmt(e.m_AdapterFmt);
77    if(KeyFmtA < KeyFmtB)
78        return -1;
79    if(KeyFmtA > KeyFmtB)
80        return 1;
81
82    const s3d_CDrvGfxEnumEntry *GfxEnumEntryA = &m_GfxEnumEntry;
83    const s3d_CDrvGfxEnumEntry *GfxEnumEntryB = &e.m_GfxEnumEntry;
84    if(GfxEnumEntryA->m_Width < GfxEnumEntryB->m_Width)
85        return -1;
86    if(GfxEnumEntryA->m_Width > GfxEnumEntryB->m_Width)
87        return 1;
88       
89    if(GfxEnumEntryA->m_Height < GfxEnumEntryB->m_Height)
90        return -1;
91    if(GfxEnumEntryA->m_Height > GfxEnumEntryB->m_Height)
92        return 1;
93
94    if(GfxEnumEntryA->m_Depth < GfxEnumEntryB->m_Depth)
95        return -1;
96    if(GfxEnumEntryA->m_Depth > GfxEnumEntryB->m_Depth)
97        return 1;
98
99    if(GfxEnumEntryA->m_Freq < GfxEnumEntryB->m_Freq)
100        return -1;
101    if(GfxEnumEntryA->m_Freq > GfxEnumEntryB->m_Freq)
102        return 1;
103
104    return 0;
105}
106
107bool s3d_CDrvD3d9EnumEntry::operator==(
108        const s3d_CDrvD3d9EnumEntry &e) const
109{
110    return Compare(e) == 0;
111}
112
113bool s3d_CDrvD3d9EnumEntry::operator<(
114        const s3d_CDrvD3d9EnumEntry &e) const
115{
116    return Compare(e) < 0;
117}
118
119int s3d_CDrvD3d9EnumEntry::KeyOfFmt(D3DFORMAT Fmt)
120{
121    switch(Fmt)
122    {
123        case D3DFMT_R5G6B5:
124            return 1;
125        case D3DFMT_A1R5G5B5:
126            return 2;
127        case D3DFMT_X1R5G5B5:
128            return 3;
129        case D3DFMT_A8R8G8B8:
130            return 4;
131        case D3DFMT_X8R8G8B8:
132            return 5;
133        case D3DFMT_A2R10G10B10:
134            return 6;
135    }
136    return -1;
137}
138
139///////////////////////////////////////////////////////////////////////////////
140
141int s3d_CDrvD3d9EnumRef::Compare(
142        const s3d_CDrvD3d9EnumEntry &Entry,
143        const s3d_CDrvD3d9EnumRef &Ref)
144{
145    if(Entry.m_Adapter < Ref.m_Adapter)
146        return -1;
147    if(Entry.m_Adapter > Ref.m_Adapter)
148        return 1;
149   
150    if(!Ref.m_Fullscreen && Ref.m_AdapterFmt == D3DFMT_A2R10G10B10)
151    {
152        S3D_SYS_ASSERT(0);
153        return -1;
154    }
155
156    int KeyFmtA = s3d_CDrvD3d9EnumEntry::KeyOfFmt(Entry.m_AdapterFmt);
157    int KeyFmtB = s3d_CDrvD3d9EnumEntry::KeyOfFmt(Ref.m_AdapterFmt);
158    if(KeyFmtA < KeyFmtB)
159        return -1;
160    if(KeyFmtA > KeyFmtB)
161        return 1;
162
163    const s3d_CDrvGfxEnumEntry *GfxEnumEntry = &Entry.m_GfxEnumEntry;
164    if(GfxEnumEntry->m_Depth < Ref.m_Depth)
165        return -1;
166    if(GfxEnumEntry->m_Depth > Ref.m_Depth)
167        return 1;
168
169    if(Ref.m_Fullscreen)
170    {
171        if(GfxEnumEntry->m_Width < Ref.m_Width)
172            return -1;
173        if(GfxEnumEntry->m_Width > Ref.m_Width)
174            return 1;
175           
176        if(GfxEnumEntry->m_Height < Ref.m_Height)
177            return -1;
178        if(GfxEnumEntry->m_Height > Ref.m_Height)
179            return 1;
180
181        if(Ref.m_Freq != 0)
182        {
183            if(GfxEnumEntry->m_Freq < Ref.m_Freq)
184                return -1;
185            if(GfxEnumEntry->m_Freq > Ref.m_Freq)
186                return 1;
187        }
188    }
189
190    return 0;
191}
192
193///////////////////////////////////////////////////////////////////////////////
194
195bool s3d_CDrvD3d9Enum::Enumerate(
196        s3d_CUtilMsgHandler *MsgHandler, s3d_CUtilStr_cr Info,
197        s3d_CUtilMemPool *MemPool, s3d_CDrvD3d9Param *D3dParam,
198        LPDIRECT3D9 D3d,
199        bool Fullscreen, bool NoStencil)
200{
201    if(!D3d)
202        return false;
203
204    s3d_CDrvD3d9Env Env;
205    Env.Init(MsgHandler, D3dParam);
206
207    m_ModeArray.Reset();
208    m_AdapterFmtArray.Reset();
209
210    D3DDEVTYPE DevType = D3DDEVTYPE_HAL;
211    if(D3dParam->m_RefDriver)
212        DevType = D3DDEVTYPE_REF;
213
214    UINT AdapterCnt = D3d->GetAdapterCount();
215    UINT iAdapter;
216    for(iAdapter = 0; iAdapter < AdapterCnt; iAdapter++)
217    {
218        s3d_CUtilStr Device = s3d_CUtilStrUtil::StrOfIntps(iAdapter);
219
220        D3DADAPTER_IDENTIFIER9 AdapterIdentifier;
221        /*
222           Flags can be set to either 0 or D3DENUM_WHQL_LEVEL.
223           If D3DENUM_WHQL_LEVEL is specified, this call can connect to the
224           Internet to download new Microsoft Windows Hardware Quality
225           Labs (WHQL) certificates.
226        */
227        HRESULT Result;
228        DWORD Flags = 0;
229        S3D_DRV_D3D9_CALLCHECK(
230                &Env, Result, D3d->GetAdapterIdentifier(
231                    iAdapter, Flags, &AdapterIdentifier));
232        if(FAILED(Result))
233            continue;
234       
235        D3DCAPS9 Caps;
236        S3D_DRV_D3D9_CALLCHECK(
237                &Env, Result, D3d->GetDeviceCaps(
238                    iAdapter, DevType, &Caps));
239        if(FAILED(Result))
240            continue;
241
242        if(!CheckRequirements(Caps))
243            continue;
244
245        s3d_CSysIntps AdapterFmtCnt = S3D_SYS_ARRAYCNTS(
246                drv_d3d9_AdapterFmtArray);
247        s3d_CSysIntps iAdapterFmt;
248        for(iAdapterFmt = 0; iAdapterFmt < AdapterFmtCnt; iAdapterFmt++)
249        {
250            D3DFORMAT AdapterFmt = drv_d3d9_AdapterFmtArray[iAdapterFmt];
251            s3d_CUtilStrBuf Desc;
252            Desc.Append(AdapterIdentifier.Description);
253            Desc.Append("@");
254            Desc.Append(AdapterIdentifier.DeviceName);
255            Desc.Append("@");
256            Desc.Append(s3d_CDrvD3d9Util::StrOfFmt(AdapterFmt));
257
258            UINT ModeCnt = D3d->GetAdapterModeCount(iAdapter, AdapterFmt);
259            UINT iMode;
260            for(iMode = 0; iMode < ModeCnt; iMode++)
261            {
262                D3DDISPLAYMODE AdapterMode;
263                S3D_DRV_D3D9_HRESCALL(
264                        &Env, Result, D3d->EnumAdapterModes(
265                            iAdapter, AdapterFmt, iMode, &AdapterMode));
266                if(FAILED(Result))
267                    continue;
268
269                s3d_CDrvD3d9EnumEntry EnumEntry;
270                EnumEntry.m_Adapter = iAdapter;
271                EnumEntry.m_AdapterFmt = AdapterMode.Format;
272                EnumEntry.m_GfxEnumEntry.m_Device = Device;
273                EnumEntry.m_GfxEnumEntry.m_Width = AdapterMode.Width;
274                EnumEntry.m_GfxEnumEntry.m_Height = AdapterMode.Height;
275                EnumEntry.m_GfxEnumEntry.m_Freq = AdapterMode.RefreshRate;
276                EnumEntry.m_GfxEnumEntry.m_Depth = 0;
277                EnumEntry.m_GfxEnumEntry.m_Desc = Desc;
278                switch(AdapterFmt)
279                {
280                    case D3DFMT_R5G6B5:
281                    case D3DFMT_X1R5G5B5:
282                        EnumEntry.m_GfxEnumEntry.m_Depth = 16;
283                        break;
284                    case D3DFMT_A2R10G10B10:
285                    case D3DFMT_X8R8G8B8:
286                        EnumEntry.m_GfxEnumEntry.m_Depth = 32;
287                        break;
288                }
289                m_ModeArray.InsertBack(EnumEntry);
290            }
291        }
292    }
293   
294    s3d_UtilArraySortDefault(m_ModeArray);
295    s3d_UtilArraySortedDeleteDuplicatesDefault(m_ModeArray);
296    m_ModeArray.Compactify();
297
298    if(m_ModeArray.IsEmpty())
299        return false;
300   
301    // Collect all adapters w/ their formats
302    s3d_CUtilArray<s3d_CDrvD3d9FmtArray> AdapterFmtArray;
303    D3DFORMAT LastFmt = D3DFMT_UNKNOWN;
304    int LastAdapter = -1;
305    s3d_CSysIntps nMode = m_ModeArray.GetCnt();
306    s3d_CSysIntps iMode;
307    for(iMode = 0; iMode < nMode; iMode++)
308    {
309        s3d_CDrvD3d9EnumEntry EnumEntry = m_ModeArray.RefAtRaw(iMode);
310        if(EnumEntry.m_AdapterFmt == LastFmt
311                && EnumEntry.m_Adapter == LastAdapter)
312            continue;
313   
314        LastFmt = EnumEntry.m_AdapterFmt;
315        LastAdapter = EnumEntry.m_Adapter;
316       
317        // Collect all supported adapters formats
318        s3d_CDrvD3d9FmtArray FmtArray;
319        FmtArray = AdapterFmtArray.RefAtDefault(LastAdapter, FmtArray);
320        FmtArray.InsertBack(LastFmt);
321        AdapterFmtArray.SetAtGrow(LastAdapter, FmtArray);
322    }
323
324    // Find matching back- and depthstencil buffer formats combinations
325    // for each adapter format.
326    s3d_CSysIntps nAdapter = AdapterFmtArray.GetCnt();
327    for(iAdapter = 0; iAdapter < UINT(nAdapter); iAdapter++)
328    {
329        s3d_CDrvD3d9FmtMap BackBufFmtMap;
330        s3d_CDrvD3d9FmtMap DepthFmtMap;
331
332        s3d_CDrvD3d9FmtArray FmtArray = AdapterFmtArray.RefAtRaw(iAdapter);
333        s3d_CSysIntps nFmt = FmtArray.GetCnt();
334        s3d_CSysIntps iFmt;
335        for(iFmt = 0; iFmt < nFmt; iFmt++)
336        {
337            D3DFORMAT AdapterFmt = FmtArray.RefAtRaw(iFmt);
338
339            // Search for allowed backbuffer formats.
340            s3d_CDrvD3d9FmtArray BackBufFmtArray;
341            s3d_CSysIntps FmtCnt = S3D_SYS_ARRAYCNTS(drv_d3d9_BackBufFmtArray);
342            s3d_CSysIntps iFmt;
343            for(iFmt = 0; iFmt < FmtCnt; iFmt++)
344            {
345                D3DFORMAT BackBufFmt = drv_d3d9_BackBufFmtArray[iFmt];
346
347                HRESULT Result;
348                S3D_DRV_D3D9_HRESCALL(
349                        &Env, Result, D3d->CheckDeviceType(
350                        iAdapter, DevType, AdapterFmt, BackBufFmt,
351                                !Fullscreen));
352                if(FAILED(Result))
353                    continue;
354               
355                if(!Fullscreen)
356                {
357                    // e.g. R5G6B5 <-> X8R8G8B8
358                    S3D_DRV_D3D9_HRESCALL(
359                            &Env, Result, D3d->CheckDeviceFormatConversion(
360                                iAdapter, DevType, AdapterFmt, BackBufFmt));
361                    if(FAILED(Result))
362                        continue;
363                }
364                BackBufFmtArray.InsertBack(BackBufFmt);
365
366                // Search for depth stencil buffer formats that are compatible
367                // w/ found backbuffer format.
368                s3d_CDrvD3d9FmtArray DepthFmtArray;
369                s3d_CSysIntps EnumFmtDepthCnt = S3D_SYS_ARRAYCNTS(
370                        drv_d3d9_DepthStencilFmtArray);
371                const D3DFORMAT *EnumDepthFmtArray =
372                        drv_d3d9_DepthStencilFmtArray;
373                if(NoStencil)
374                {
375                    EnumFmtDepthCnt = S3D_SYS_ARRAYCNTS(
376                            drv_d3d9_DepthFmtArray);
377                    EnumDepthFmtArray = drv_d3d9_DepthFmtArray;
378                }
379                s3d_CSysIntps iEnumFmtDepthCnt;
380                for(iEnumFmtDepthCnt = 0; iEnumFmtDepthCnt < EnumFmtDepthCnt;
381                        iEnumFmtDepthCnt++)
382                {
383                    D3DFORMAT DepthFmt = EnumDepthFmtArray[iEnumFmtDepthCnt];
384
385                    HRESULT Result;
386                    S3D_DRV_D3D9_HRESCALL(
387                            &Env, Result, D3d->CheckDeviceFormat(
388                                iAdapter, DevType, AdapterFmt,
389                                D3DUSAGE_DEPTHSTENCIL,
390                                D3DRTYPE_SURFACE, DepthFmt));
391                    if(FAILED(Result))
392                        continue;
393
394                    S3D_DRV_D3D9_HRESCALL(
395                            &Env, Result, D3d->CheckDepthStencilMatch(
396                                iAdapter, DevType, AdapterFmt,
397                                BackBufFmt, DepthFmt));
398                    if(FAILED(Result))
399                        continue;
400
401                    DepthFmtArray.InsertBack(DepthFmt);
402                }
403                DepthFmtMap.SetAt(BackBufFmt, DepthFmtArray);
404            }
405            BackBufFmtMap.SetAt(AdapterFmt, BackBufFmtArray);
406        }
407
408        s3d_CDrvD3d9EnumAdapterFmt AdapterFmt;
409        AdapterFmt.m_BackBufFmtMap = BackBufFmtMap;
410        AdapterFmt.m_DepthFmtMap = DepthFmtMap;
411        m_AdapterFmtArray.InsertBack(AdapterFmt);
412    }
413
414    return m_AdapterFmtArray.GetCnt() > 0;
415}
416
417void s3d_CDrvD3d9Enum::CollectEntries(
418        s3d_CUtilArray<s3d_CDrvGfxEnumEntry> &EnumArray)
419{
420    s3d_CSysIntps nMode = m_ModeArray.GetCnt();
421    s3d_CSysIntps iMode;
422    for(iMode = 0; iMode < nMode; iMode++)
423    {
424        s3d_CDrvD3d9EnumEntry EnumEntry = m_ModeArray.GetAt(iMode);
425        EnumArray.InsertBack(EnumEntry.m_GfxEnumEntry);
426    }
427}
428
429bool s3d_CDrvD3d9Enum::SearchEntry(
430        s3d_CDrvD3d9EnumEntry &EnumEntry, UINT Adapter,
431        int Prop, int Width, int Height, int Depth, int Frequency,
432        bool Fullscreen)
433{
434    s3d_CDrvD3d9EnumRef EnumRef;
435    EnumRef.m_Adapter = Adapter;
436    EnumRef.m_AdapterFmt = D3DFMT_UNKNOWN;
437    EnumRef.m_Width = Width;
438    EnumRef.m_Height = Height;
439    EnumRef.m_Depth = Depth;
440    EnumRef.m_Freq = Frequency;
441    EnumRef.m_Fullscreen = Fullscreen;
442
443    s3d_CSysIntps Pos = -1;
444    if(Depth > 16)
445    {
446        EnumRef.m_AdapterFmt = D3DFMT_X8R8G8B8;
447        Pos = s3d_UtilArraySortedGetEqual(m_ModeArray, EnumRef);
448        if(Pos < 0 && Fullscreen)
449        {
450            EnumRef.m_AdapterFmt = D3DFMT_A2R10G10B10;
451            Pos = s3d_UtilArraySortedGetEqual(m_ModeArray, EnumRef);
452        }
453    }
454    else
455    {
456        EnumRef.m_AdapterFmt = D3DFMT_R5G6B5;
457        Pos = s3d_UtilArraySortedGetEqual(m_ModeArray, EnumRef);
458        if(Pos < 0)
459        {
460            EnumRef.m_AdapterFmt = D3DFMT_X1R5G5B5;
461            Pos = s3d_UtilArraySortedGetEqual(m_ModeArray, EnumRef);
462        }
463    }
464    if(Pos < 0)
465        return false;
466    EnumEntry = m_ModeArray.GetAt(Pos);
467    return true;
468}
469
470void s3d_CDrvD3d9Enum::GetBufferFmts(
471        int Depth, D3DFORMAT &BackBufFmt, D3DFORMAT &DepthStencilFmt,
472        const s3d_CDrvD3d9EnumEntry &EnumEntry)
473{
474    BackBufFmt = D3DFMT_UNKNOWN;
475    DepthStencilFmt = D3DFMT_UNKNOWN;
476
477    s3d_CDrvD3d9EnumAdapterFmt EnumAdapterFmt
478            = m_AdapterFmtArray.GetAtDefault(EnumEntry.m_Adapter);
479   
480    s3d_CDrvD3d9FmtArray BackBufFmtArray;
481    EnumAdapterFmt.m_BackBufFmtMap.GetAtInto(
482            EnumEntry.m_AdapterFmt, BackBufFmtArray);
483    s3d_CSysIntps nBackBufFmt = BackBufFmtArray.GetCnt();
484    s3d_CSysIntps iBackBufFmt;
485    for(iBackBufFmt = 0; iBackBufFmt < nBackBufFmt; iBackBufFmt++)
486    {
487        BackBufFmt = BackBufFmtArray.GetAtDefault(iBackBufFmt, D3DFMT_UNKNOWN);
488        if(Depth == s3d_CDrvD3d9Util::ColBitsOfFmt(BackBufFmt))
489            break;
490    }
491
492    s3d_CDrvD3d9FmtArray DepthStencilFmtArray;
493    EnumAdapterFmt.m_DepthFmtMap.GetAtInto(BackBufFmt, DepthStencilFmtArray);
494    DepthStencilFmt = DepthStencilFmtArray.GetAtDefault(0, D3DFMT_UNKNOWN);
495}
496
497///////////////////////////////////////////////////////////////////////////////
498
499bool s3d_CDrvD3d9Enum::CheckRequirements(const D3DCAPS9 &Caps)
500{
501    return true;
502}
503
504///////////////////////////////////////////////////////////////////////////////
505
Note: See TracBrowser for help on using the repository browser.