~ubuntu-branches/ubuntu/precise/mesa/precise-updates

« back to all changes in this revision

Viewing changes to src/gallium/state_trackers/d3d1x/d3d1xstutil/include/d3d1xstutil.h

  • Committer: Package Import Robot
  • Author(s): Robert Hooker
  • Date: 2012-02-02 12:05:48 UTC
  • mfrom: (1.7.1) (3.3.27 sid)
  • Revision ID: package-import@ubuntu.com-20120202120548-nvkma85jq0h4coix
Tags: 8.0~rc2-0ubuntu4
Drop drisearchdir handling, it is no longer needed with multiarch
and dri-alternates being removed.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/**************************************************************************
 
2
 *
 
3
 * Copyright 2010 Luca Barbieri
 
4
 *
 
5
 * Permission is hereby granted, free of charge, to any person obtaining
 
6
 * a copy of this software and associated documentation files (the
 
7
 * "Software"), to deal in the Software without restriction, including
 
8
 * without limitation the rights to use, copy, modify, merge, publish,
 
9
 * distribute, sublicense, and/or sell copies of the Software, and to
 
10
 * permit persons to whom the Software is furnished to do so, subject to
 
11
 * the following conditions:
 
12
 *
 
13
 * The above copyright notice and this permission notice (including the
 
14
 * next paragraph) shall be included in all copies or substantial
 
15
 * portions of the Software.
 
16
 *
 
17
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 
18
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 
19
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 
20
 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
 
21
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 
22
 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 
23
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
24
 *
 
25
 **************************************************************************/
 
26
 
 
27
#ifndef D3D1XSTUTIL_H_
 
28
#define D3D1XSTUTIL_H_
 
29
 
 
30
#ifdef _MSC_VER
 
31
#include <unordered_map>
 
32
#include <unordered_set>
 
33
#else
 
34
#include <tr1/unordered_map>
 
35
#include <tr1/unordered_set>
 
36
namespace std
 
37
{
 
38
        using namespace tr1;
 
39
}
 
40
#endif
 
41
#include <map>
 
42
#include <utility>
 
43
 
 
44
#define WIN32_LEAN_AND_MEAN
 
45
#include <objbase.h>
 
46
 
 
47
#include "galliumdxgi.h"
 
48
#include <d3dcommon.h>
 
49
 
 
50
extern "C"
 
51
{
 
52
#include "util/u_atomic.h"
 
53
#include "pipe/p_format.h"
 
54
#include "os/os_thread.h"
 
55
}
 
56
 
 
57
#include <assert.h>
 
58
#ifdef min
 
59
#undef min
 
60
#endif
 
61
#ifdef max
 
62
#undef max
 
63
#endif
 
64
 
 
65
#define D3D_PRIMITIVE_TOPOLOGY_COUNT 65
 
66
extern unsigned d3d_to_pipe_prim[D3D_PRIMITIVE_TOPOLOGY_COUNT];
 
67
 
 
68
#define D3D_PRIMITIVE_COUNT 40
 
69
extern unsigned d3d_to_pipe_prim_type[D3D_PRIMITIVE_COUNT];
 
70
 
 
71
/* NOTE: this _depends_ on the vtable layout of the C++ compiler to be
 
72
 * binary compatible with Windows.
 
73
 * Furthermore some absurd vtable layout likely won't work at all, since
 
74
 * we perform some casts which are probably not safe by the C++ standard.
 
75
 *
 
76
 * In particular, the GNU/Linux/Itanium/clang ABI and Microsoft ABIs will work,
 
77
 * but others may not.
 
78
 * If in doubt, just switch to the latest version of a widely used C++ compiler.
 
79
 *
 
80
 * DESIGN of the Gallium COM implementation
 
81
 *
 
82
 * This state tracker uses somewhat unusual C++ coding patterns,
 
83
 * to implement the COM interfaces required by Direct3D.
 
84
 *
 
85
 * While it may seem complicated, the effect is that the result
 
86
 * generally behaves as intuitively as possible: in particular pointer
 
87
 * casts very rarely change the pointer value (only for secondary
 
88
 * DXGI/Gallium interfaces)
 
89
 *
 
90
 * Implementing COM is on first sight very easy: after all, it just
 
91
 * consists of a reference count, and a dynamic_cast<> equivalent.
 
92
 *
 
93
 * However, implementing objects with multiple interfaces is actually
 
94
 * quite tricky.
 
95
 * The issue is that the interface pointers can't be equal, since this
 
96
 * would place incompatible constraints on the vtable layout and thus
 
97
 * multiple inheritance (and the subobjects the C++ compiler creates
 
98
 * with it) must be correctly used.
 
99
 *
 
100
 * Furthermore, we must have a single reference count, which means
 
101
 * that a naive implementation won't work, and it's necessary to either
 
102
 * use virtual inheritance, or the "mixin inheritance" model we use.
 
103
 *
 
104
 * This solution aims to achieve the following object layout:
 
105
 * 0: pointer to vtable for primary interface
 
106
 * 1: reference count
 
107
 * ... main class
 
108
 * ... vtable pointers for secondary interfaces
 
109
 * ... implementation of subclasses assuming secondary interfaces
 
110
 *
 
111
 * This allows us to cast pointers by just reinterpreting the value in
 
112
 * almost all cases.
 
113
 *
 
114
 * To achieve this, *all* non-leaf classes must have their parent
 
115
 * or the base COM interface as a template parameter, since derived
 
116
 * classes may need to change that to support an interface derived
 
117
 * from the one implemented by the superclass.
 
118
 *
 
119
 * Note however, that you can cast without regard to the template
 
120
 * parameter, because only the vtable layout depends on it, since
 
121
 * interfaces have no data members.
 
122
 *
 
123
 * For this to work, DON'T USE VIRTUAL FUNCTIONS except to implement
 
124
 * interfaces, since the vtable layouts would otherwise be mismatched.
 
125
 * An exception are virtual functions called only from other virtual functions,
 
126
 * which is currently only used for the virtual destructor.
 
127
 *
 
128
 * The base class is GalliumComObject<IFoo>, which implements the
 
129
 * IUnknown interface, and inherits IFoo.
 
130
 *
 
131
 * To support multiple inheritance, we insert GalliumMultiComObject,
 
132
 * which redirects the secondary interfaces to the GalliumComObject
 
133
 * superclass.
 
134
 *
 
135
 * Gallium(Multi)PrivateDataComObject is like ComObject but also
 
136
 * implements the Get/SetPrivateData functions present on several
 
137
 * D3D/DXGI interfaces.
 
138
 *
 
139
 * Example class hierarchy:
 
140
 *
 
141
 * IUnknown
 
142
 * (pure interface)
 
143
 * |
 
144
 * V
 
145
 * IAnimal
 
146
 * (pure interface)
 
147
 * |
 
148
 * V
 
149
 * IDuck
 
150
 * (pure interface)
 
151
 * |
 
152
 * V
 
153
 * GalliumComObject<IDuck>
 
154
 * (non-instantiable, only implements IUnknown)
 
155
 * |
 
156
 * V
 
157
 * GalliumAnimal<IDuck>
 
158
 * (non-instantiable, only implements IAnimal)
 
159
 * |
 
160
 * V
 
161
 * GalliumDuck
 
162
 * (concrete)
 
163
 * |
 
164
 * V
 
165
 * GalliumMultiComObject<GalliumDuck, IWheeledVehicle> <- IWheeledVehicle <- IVehicle <- IUnknown (second version)
 
166
 * (non-instantiable, only implements IDuck and the IUnknown of IWheeledVehicle)
 
167
 * |
 
168
 * V
 
169
 * GalliumDuckOnWheels
 
170
 * (concrete)
 
171
 *
 
172
 * This will produce the desired layout.
 
173
 * Note that GalliumAnimal<IFoo>* is safely castable to GalliumAnimal<IBar>*
 
174
 * by reinterpreting, as long as non-interface virtual functions are not used,
 
175
 * and that you only call interface functions for the superinterface of IBar
 
176
 * that the object actually implements.
 
177
 *
 
178
 * Instead, if GalliumDuck where to inherit both from GalliumAnimal
 
179
 * and IDuck, then (IDuck*)gallium_duck and (IAnimal*)gallium_duck would
 
180
 * have different pointer values, which the "base class as template parameter"
 
181
 * trick avoids.
 
182
 *
 
183
 * The price we pay is that you MUST NOT have virtual functions other than those
 
184
 * implementing interfaces (except for leaf classes) since the position of these
 
185
 * would depend on the base interface.
 
186
 * As mentioned above, virtual functions only called from interface functions
 
187
 * are an exception, currently used only for the virtual destructor.
 
188
 * If you want virtual functions anyway , put them in a separate interface class,
 
189
 * multiply inherit from that and cast the pointer to that interface.
 
190
 *
 
191
 * You CAN however have virtual functions on any class which does not specify
 
192
 * his base as a template parameter, or where you don't need to change the
 
193
 * template base interface parameter by casting.
 
194
 *
 
195
 * --- The magic QueryInterface "delete this" trick ---
 
196
 *
 
197
 * When the reference count drops to 0, we must delete the class.
 
198
 * The problem is, that we must call the right virtual destructor (i.e. on the right class).
 
199
 * However, we would like to be able to call release() and nonatomic_release()
 
200
 * non-virtually for performance (also, the latter cannot be called virtually at all, since
 
201
 * IUnknown does not offer it).
 
202
 *
 
203
 * The naive solution would be to just add a virtual destructor and rely on it.
 
204
 * However, this doesn't work due to the fact that as described above we perform casets
 
205
 * with are unsafe regarding vtable layout.
 
206
 * In particular, consider the case where we try to delete GalliumComObject<ID3D11Texture2D>
 
207
 * with a pointer to GalliumComObject<ID3D11Resource>.
 
208
 * Since we think that this is a GalliumComObject<ID3D11Resource>, we'll look for the
 
209
 * destructor in the vtable slot immediately after the ID3D11Resource vtable, but this is
 
210
 * actually an ID3D11Texture2D function implemented by the object!
 
211
 *
 
212
 * So, we must put the destructor somewhere else.
 
213
 * We could add it as a data member, but it would be awkward and it would bloat the
 
214
 * class.
 
215
 * Thus, we use this trick: we reuse the vtable slot for QueryInterface, which is always at the
 
216
 * same position.
 
217
 * To do so, we define a special value for the first pointer argument, that triggers a
 
218
 * "delete this".
 
219
 * In addition to that, we add a virtual destructor to GalliumComObject.
 
220
 * That virtual destructor will be called by QueryInterface, and since that is a virtual
 
221
 * function, it will know the correct place for the virtual destructor.
 
222
 *
 
223
 * QueryInterface is already slow due to the need to compare several GUIDs, so the
 
224
 * additional pointer test should not be significant.
 
225
 *
 
226
 * Of course the ideal solution would be telling the C++ compiler to put the
 
227
 * destructor it in a negative vtable slot, but unfortunately GCC doesn't support that
 
228
 * yet, and this method is almost as good as that.
 
229
 */
 
230
 
 
231
template<typename T>
 
232
struct com_traits;
 
233
 
 
234
#define COM_INTERFACE(intf, base) \
 
235
template<> \
 
236
struct com_traits<intf> \
 
237
{ \
 
238
        static REFIID iid() {return IID_##intf;} \
 
239
        static inline bool is_self_or_ancestor(REFIID riid) {return riid == iid() || com_traits<base>::is_self_or_ancestor(riid);} \
 
240
};
 
241
 
 
242
template<>
 
243
struct com_traits<IUnknown>
 
244
{
 
245
        static REFIID iid() {return IID_IUnknown;}
 
246
        static inline bool is_self_or_ancestor(REFIID riid) {return riid == iid();}
 
247
};
 
248
 
 
249
#ifndef _MSC_VER
 
250
#define __uuidof(T) (com_traits<T>::iid())
 
251
#endif
 
252
 
 
253
struct refcnt_t
 
254
{
 
255
        uint32_t refcnt;
 
256
 
 
257
        refcnt_t(unsigned v = 1)
 
258
        : refcnt(v)
 
259
        {}
 
260
 
 
261
        unsigned add_ref()
 
262
        {
 
263
                p_atomic_inc((int32_t*)&refcnt);
 
264
                return refcnt;
 
265
        }
 
266
 
 
267
        unsigned release()
 
268
        {
 
269
                if(p_atomic_dec_zero((int32_t*)&refcnt))
 
270
                        return 0;
 
271
                return refcnt;
 
272
        }
 
273
 
 
274
        void nonatomic_add_ref()
 
275
        {
 
276
                p_atomic_inc((int32_t*)&refcnt);
 
277
        }
 
278
 
 
279
        unsigned nonatomic_release()
 
280
        {
 
281
                if(p_atomic_dec_zero((int32_t*)&refcnt))
 
282
                        return 0;
 
283
                else
 
284
                        return 1;
 
285
        }
 
286
};
 
287
 
 
288
#if defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8)
 
289
/* this should be safe because atomic ops are full memory barriers, and thus a sequence that does:
 
290
 * ++one_refcnt;
 
291
 * --other_refcnt;
 
292
 * should never be reorderable (as seen from another CPU) to:
 
293
 * --other_refcnt
 
294
 * ++one_refcnt
 
295
 *
 
296
 * since one of the ops is atomic.
 
297
 * If this weren't the case, a CPU could incorrectly destroy an object manipulated in that way by another one.
 
298
 */
 
299
struct dual_refcnt_t
 
300
{
 
301
        union
 
302
        {
 
303
                uint64_t refcnt;
 
304
                struct
 
305
                {
 
306
                        uint32_t atomic_refcnt;
 
307
                        uint32_t nonatomic_refcnt;
 
308
                };
 
309
        };
 
310
 
 
311
        dual_refcnt_t(unsigned v = 1)
 
312
        {
 
313
                atomic_refcnt = v;
 
314
                nonatomic_refcnt = 0;
 
315
        }
 
316
 
 
317
        bool is_zero()
 
318
        {
 
319
                if(sizeof(void*) == 8)
 
320
                        return *(volatile uint64_t*)&refcnt == 0ULL;
 
321
                else
 
322
                {
 
323
                        uint64_t v;
 
324
                        do
 
325
                        {
 
326
                                v = refcnt;
 
327
                        }
 
328
                        while(!__sync_bool_compare_and_swap(&refcnt, v, v));
 
329
                        return v == 0ULL;
 
330
                }
 
331
        }
 
332
 
 
333
        unsigned add_ref()
 
334
        {
 
335
                //printf("%p add_ref at %u %u\n", this, atomic_refcnt, nonatomic_refcnt);
 
336
                p_atomic_inc((int32_t*)&atomic_refcnt);
 
337
                return atomic_refcnt + nonatomic_refcnt;
 
338
        }
 
339
 
 
340
        unsigned release()
 
341
        {
 
342
                //printf("%p release at %u %u\n", this, atomic_refcnt, nonatomic_refcnt);
 
343
                if(p_atomic_dec_zero((int32_t*)&atomic_refcnt) && !nonatomic_refcnt && is_zero())
 
344
                        return 0;
 
345
                unsigned v = atomic_refcnt + nonatomic_refcnt;
 
346
                return v ? v : 1;
 
347
        }
 
348
 
 
349
        void nonatomic_add_ref()
 
350
        {
 
351
                //printf("%p nonatomic_add_ref at %u %u\n", this, atomic_refcnt, nonatomic_refcnt);
 
352
                ++nonatomic_refcnt;
 
353
        }
 
354
 
 
355
        unsigned nonatomic_release()
 
356
        {
 
357
                //printf("%p nonatomic_release at %u %u\n", this, atomic_refcnt, nonatomic_refcnt);
 
358
                if(!--nonatomic_refcnt)
 
359
                {
 
360
                        __sync_synchronize();
 
361
                        if(!atomic_refcnt && is_zero())
 
362
                                return 0;
 
363
                }
 
364
                return 1;
 
365
        }
 
366
};
 
367
#else
 
368
// this will result in atomic operations being used while they could have been avoided
 
369
#ifdef __i386__
 
370
#warning Compile for 586+ using GCC to improve the performance of the Direct3D 10/11 state tracker
 
371
#endif
 
372
typedef refcnt_t dual_refcnt_t;
 
373
#endif
 
374
 
 
375
#define IID_MAGIC_DELETE_THIS (*(const IID*)((intptr_t)-(int)(sizeof(IID) - 1)))
 
376
 
 
377
template<typename Base = IUnknown, typename RefCnt = refcnt_t>
 
378
struct GalliumComObject : public Base
 
379
{
 
380
        RefCnt refcnt;
 
381
 
 
382
        GalliumComObject()
 
383
        {}
 
384
 
 
385
        /* DO NOT CALL this from externally called non-virtual functions in derived classes, since
 
386
         * the vtable position depends on the COM interface being implemented
 
387
         */
 
388
        virtual ~GalliumComObject()
 
389
        {}
 
390
 
 
391
        inline ULONG add_ref()
 
392
        {
 
393
                return refcnt.add_ref();
 
394
        }
 
395
 
 
396
        inline ULONG release()
 
397
        {
 
398
                ULONG v = refcnt.release();
 
399
                if(!v)
 
400
                {
 
401
                        /* this will call execute "delete this", using the correct vtable slot for the destructor */
 
402
                        /* see the initial comment for an explaination of this magic trick */
 
403
                        this->QueryInterface(IID_MAGIC_DELETE_THIS, 0);
 
404
                        return 0;
 
405
                }
 
406
                return v;
 
407
        }
 
408
 
 
409
        inline void nonatomic_add_ref()
 
410
        {
 
411
                refcnt.nonatomic_add_ref();
 
412
        }
 
413
 
 
414
        inline void nonatomic_release()
 
415
        {
 
416
                if(!refcnt.nonatomic_release())
 
417
                {
 
418
                        /* this will execute "delete this", using the correct vtable slot for the destructor */
 
419
                        /* see the initial comment for an explaination of this magic trick */
 
420
                        this->QueryInterface(IID_MAGIC_DELETE_THIS, 0);
 
421
                }
 
422
        }
 
423
 
 
424
        inline HRESULT query_interface(REFIID riid, void **ppvObject)
 
425
        {
 
426
                if(com_traits<Base>::is_self_or_ancestor(riid))
 
427
                {
 
428
                        // must be the virtual AddRef, since it is overridden by some classes
 
429
                        this->AddRef();
 
430
                        *ppvObject = this;
 
431
                        return S_OK;
 
432
                }
 
433
                else
 
434
                        return E_NOINTERFACE;
 
435
        }
 
436
 
 
437
        virtual ULONG STDMETHODCALLTYPE AddRef()
 
438
        {
 
439
                return add_ref();
 
440
        }
 
441
 
 
442
        virtual ULONG STDMETHODCALLTYPE Release()
 
443
        {
 
444
                return release();
 
445
        }
 
446
 
 
447
        virtual HRESULT STDMETHODCALLTYPE QueryInterface(
 
448
                REFIID riid,
 
449
                void **ppvObject)
 
450
        {
 
451
                /* see the initial comment for an explaination of this magic trick */
 
452
                if(&riid == &IID_MAGIC_DELETE_THIS)
 
453
                {
 
454
                        delete this;
 
455
                        return 0;
 
456
                }
 
457
                if(!this)
 
458
                        return E_INVALIDARG;
 
459
                if(!ppvObject)
 
460
                        return E_POINTER;
 
461
                return query_interface(riid, ppvObject);
 
462
        }
 
463
};
 
464
 
 
465
template<typename BaseClass, typename SecondaryInterface>
 
466
struct GalliumMultiComObject : public BaseClass, SecondaryInterface
 
467
{
 
468
        // we could avoid this duplication, but the increased complexity to do so isn't worth it
 
469
        virtual ULONG STDMETHODCALLTYPE AddRef()
 
470
        {
 
471
                return BaseClass::add_ref();
 
472
        }
 
473
 
 
474
        virtual ULONG STDMETHODCALLTYPE Release()
 
475
        {
 
476
                return BaseClass::release();
 
477
        }
 
478
 
 
479
        inline HRESULT query_interface(REFIID riid, void **ppvObject)
 
480
        {
 
481
                HRESULT hr = BaseClass::query_interface(riid, ppvObject);
 
482
                if(SUCCEEDED(hr))
 
483
                        return hr;
 
484
                if(com_traits<SecondaryInterface>::is_self_or_ancestor(riid))
 
485
                {
 
486
                        // must be the virtual AddRef, since it is overridden by some classes
 
487
                        this->AddRef();
 
488
                        *ppvObject = (SecondaryInterface*)this;
 
489
                        return S_OK;
 
490
                }
 
491
                else
 
492
                        return E_NOINTERFACE;
 
493
        }
 
494
 
 
495
        virtual HRESULT STDMETHODCALLTYPE QueryInterface(
 
496
                REFIID riid,
 
497
                void **ppvObject)
 
498
        {
 
499
                /* see the initial comment for an explaination of this magic trick */
 
500
                if(&riid == &IID_MAGIC_DELETE_THIS)
 
501
                {
 
502
                        delete this;
 
503
                        return 0;
 
504
                }
 
505
                if(!this)
 
506
                        return E_INVALIDARG;
 
507
                if(!ppvObject)
 
508
                        return E_POINTER;
 
509
                return query_interface(riid, ppvObject);
 
510
        }
 
511
};
 
512
 
 
513
template<typename T, typename Traits>
 
514
struct refcnt_ptr
 
515
{
 
516
        T* p;
 
517
 
 
518
        refcnt_ptr()
 
519
        : p(0)
 
520
        {}
 
521
 
 
522
        void add_ref() {Traits::add_ref(p);}
 
523
        void release() {Traits::release(p);}
 
524
 
 
525
        template<typename U, typename UTraits>
 
526
        refcnt_ptr(const refcnt_ptr<U, UTraits>& c)
 
527
        {
 
528
                *this = static_cast<U*>(c.ref());
 
529
        }
 
530
 
 
531
        ~refcnt_ptr()
 
532
        {
 
533
                release();
 
534
        }
 
535
 
 
536
        void reset(T* q)
 
537
        {
 
538
                release();
 
539
                p = q;
 
540
        }
 
541
 
 
542
        template<typename U, typename UTraits>
 
543
        refcnt_ptr& operator =(const refcnt_ptr<U, UTraits>& q)
 
544
        {
 
545
                return *this = q.p;
 
546
        }
 
547
 
 
548
        template<typename U>
 
549
        refcnt_ptr& operator =(U* q)
 
550
        {
 
551
                release();
 
552
                p = static_cast<T*>(q);
 
553
                add_ref();
 
554
                return *this;
 
555
        }
 
556
 
 
557
        T* ref()
 
558
        {
 
559
                add_ref();
 
560
                return p;
 
561
        }
 
562
 
 
563
        T* steal()
 
564
        {
 
565
                T* ret = p;
 
566
                p = 0;
 
567
                return ret;
 
568
        }
 
569
 
 
570
        T* operator ->()
 
571
        {
 
572
                return p;
 
573
        }
 
574
 
 
575
        const T* operator ->() const
 
576
        {
 
577
                return p;
 
578
        }
 
579
 
 
580
        T** operator &()
 
581
        {
 
582
                assert(!p);
 
583
                return &p;
 
584
        }
 
585
 
 
586
        bool operator !() const
 
587
        {
 
588
                return !p;
 
589
        }
 
590
 
 
591
        typedef T* refcnt_ptr::*unspecified_bool_type;
 
592
 
 
593
        operator unspecified_bool_type() const
 
594
        {
 
595
                return p ? &refcnt_ptr::p : 0;
 
596
        }
 
597
};
 
598
 
 
599
struct simple_ptr_traits
 
600
{
 
601
        static void add_ref(void* p) {}
 
602
        static void release(void* p) {}
 
603
};
 
604
 
 
605
struct com_ptr_traits
 
606
{
 
607
        static void add_ref(void* p)
 
608
        {
 
609
                if(p)
 
610
                        ((IUnknown*)p)->AddRef();
 
611
        }
 
612
 
 
613
        static void release(void* p)
 
614
        {
 
615
                if(p)
 
616
                        ((IUnknown*)p)->Release();
 
617
        }
 
618
};
 
619
 
 
620
template<typename T>
 
621
struct ComPtr : public refcnt_ptr<T, com_ptr_traits>
 
622
{
 
623
        template<typename U, typename UTraits>
 
624
        ComPtr& operator =(const refcnt_ptr<U, UTraits>& q)
 
625
        {
 
626
                return *this = q.p;
 
627
        }
 
628
 
 
629
        template<typename U>
 
630
        ComPtr& operator =(U* q)
 
631
        {
 
632
                this->release();
 
633
                this->p = static_cast<T*>(q);
 
634
                this->add_ref();
 
635
                return *this;
 
636
        }
 
637
};
 
638
 
 
639
template<typename T, typename TTraits, typename U, typename UTraits>
 
640
bool operator ==(const refcnt_ptr<T, TTraits>& a, const refcnt_ptr<U, UTraits>& b)
 
641
{
 
642
        return a.p == b.p;
 
643
}
 
644
 
 
645
template<typename T, typename TTraits, typename U>
 
646
bool operator ==(const refcnt_ptr<T, TTraits>& a, U* b)
 
647
{
 
648
        return a.p == b;
 
649
}
 
650
 
 
651
template<typename T, typename TTraits, typename U>
 
652
bool operator ==(U* b, const refcnt_ptr<T, TTraits>& a)
 
653
{
 
654
        return a.p == b;
 
655
}
 
656
 
 
657
template<typename T, typename TTraits, typename U, typename UTraits>
 
658
bool operator !=(const refcnt_ptr<T, TTraits>& a, const refcnt_ptr<U, UTraits>& b)
 
659
{
 
660
        return a.p != b.p;
 
661
}
 
662
 
 
663
template<typename T, typename TTraits, typename U>
 
664
bool operator !=(const refcnt_ptr<T, TTraits>& a, U* b)
 
665
{
 
666
        return a.p != b;
 
667
}
 
668
 
 
669
template<typename T, typename TTraits, typename U>
 
670
bool operator !=(U* b, const refcnt_ptr<T, TTraits>& a)
 
671
{
 
672
        return a.p != b;
 
673
}
 
674
 
 
675
template<bool threadsafe>
 
676
struct maybe_mutex_t;
 
677
 
 
678
template<>
 
679
struct maybe_mutex_t<true>
 
680
{
 
681
        pipe_mutex mutex;
 
682
 
 
683
        maybe_mutex_t()
 
684
        {
 
685
                pipe_mutex_init(mutex);
 
686
        }
 
687
 
 
688
        void lock()
 
689
        {
 
690
                pipe_mutex_lock(mutex);
 
691
        }
 
692
 
 
693
        void unlock()
 
694
        {
 
695
                pipe_mutex_unlock(mutex);
 
696
        }
 
697
};
 
698
 
 
699
template<>
 
700
struct maybe_mutex_t<false>
 
701
{
 
702
        void lock()
 
703
        {
 
704
        }
 
705
 
 
706
        void unlock()
 
707
        {
 
708
        }
 
709
};
 
710
 
 
711
typedef maybe_mutex_t<true> mutex_t;
 
712
 
 
713
template<typename T>
 
714
struct lock_t
 
715
{
 
716
        T& mutex;
 
717
        lock_t(T& mutex)
 
718
        : mutex(mutex)
 
719
        {
 
720
                mutex.lock();
 
721
        }
 
722
 
 
723
        ~lock_t()
 
724
        {
 
725
                mutex.unlock();
 
726
        }
 
727
};
 
728
 
 
729
struct c_string
 
730
{
 
731
        const char* p;
 
732
        c_string(const char* p)
 
733
        : p(p)
 
734
        {}
 
735
 
 
736
        operator const char*() const
 
737
        {
 
738
                return p;
 
739
        }
 
740
};
 
741
 
 
742
static inline bool operator ==(const c_string& a, const c_string& b)
 
743
{
 
744
        return !strcmp(a.p, b.p);
 
745
}
 
746
 
 
747
static inline bool operator !=(const c_string& a, const c_string& b)
 
748
{
 
749
        return strcmp(a.p, b.p);
 
750
}
 
751
 
 
752
static inline size_t raw_hash(const char* p, size_t size)
 
753
{
 
754
        size_t res;
 
755
        if(sizeof(size_t) >= 8)
 
756
                res = (size_t)14695981039346656037ULL;
 
757
        else
 
758
                res = (size_t)2166136261UL;
 
759
        const char* end = p + size;
 
760
        for(; p != end; ++p)
 
761
        {
 
762
                res ^= (size_t)*p;
 
763
                if(sizeof(size_t) >= 8)
 
764
                        res *= (size_t)1099511628211ULL;
 
765
                else
 
766
                        res *= (size_t)16777619UL;
 
767
        }
 
768
        return res;
 
769
};
 
770
 
 
771
template<typename T>
 
772
static inline size_t raw_hash(const T& t)
 
773
{
 
774
        return raw_hash((const char*)&t, sizeof(t));
 
775
}
 
776
 
 
777
// TODO: only tested with the gcc libstdc++, might not work elsewhere
 
778
namespace std
 
779
{
 
780
#ifndef _MSC_VER
 
781
        namespace tr1
 
782
        {
 
783
#endif
 
784
                template<>
 
785
                struct hash<GUID> : public std::unary_function<GUID, size_t>
 
786
                {
 
787
                        inline size_t operator()(GUID __val) const;
 
788
                };
 
789
 
 
790
                inline size_t hash<GUID>::operator()(GUID __val) const
 
791
                {
 
792
                        return raw_hash(__val);
 
793
                }
 
794
 
 
795
                template<>
 
796
                struct hash<c_string> : public std::unary_function<c_string, size_t>
 
797
                {
 
798
                        inline size_t operator()(c_string __val) const;
 
799
                };
 
800
 
 
801
                inline size_t hash<c_string>::operator()(c_string __val) const
 
802
                {
 
803
                        return raw_hash(__val.p, strlen(__val.p));
 
804
                }
 
805
 
 
806
                template<typename T, typename U>
 
807
                struct hash<std::pair<T, U> > : public std::unary_function<std::pair<T, U>, size_t>
 
808
                {
 
809
                        inline size_t operator()(std::pair<T, U> __val) const;
 
810
                };
 
811
 
 
812
                template<typename T, typename U>
 
813
                inline size_t hash<std::pair<T, U> >::operator()(std::pair<T, U> __val) const
 
814
                {
 
815
                        std::pair<size_t, size_t> p;
 
816
                        p.first = hash<T>()(__val.first);
 
817
                        p.second = hash<U>()(__val.second);
 
818
                        return raw_hash(p);
 
819
                }
 
820
#ifndef _MSC_VER
 
821
        }
 
822
#endif
 
823
}
 
824
 
 
825
template<typename Base, typename RefCnt = refcnt_t>
 
826
struct GalliumPrivateDataComObject : public GalliumComObject<Base, RefCnt>
 
827
{
 
828
        typedef std::unordered_map<GUID, std::pair<void*, unsigned> > private_data_map_t;
 
829
        private_data_map_t private_data_map;
 
830
        mutex_t private_data_mutex;
 
831
 
 
832
        ~GalliumPrivateDataComObject()
 
833
        {
 
834
                for(private_data_map_t::iterator i = private_data_map.begin(), e = private_data_map.end(); i != e; ++i)
 
835
                {
 
836
                        if(i->second.second == ~0u)
 
837
                                ((IUnknown*)i->second.first)->Release();
 
838
                        else
 
839
                                free(i->second.first);
 
840
                }
 
841
        }
 
842
 
 
843
        HRESULT get_private_data(
 
844
                REFGUID guid,
 
845
                UINT *pDataSize,
 
846
                void *pData)
 
847
        {
 
848
                lock_t<mutex_t> lock(private_data_mutex);
 
849
                private_data_map_t::iterator i = private_data_map.find(guid);
 
850
                *pDataSize = 0;
 
851
                if(i == private_data_map.end())
 
852
                        return DXGI_ERROR_NOT_FOUND;
 
853
                if(i->second.second == ~0u)
 
854
                {
 
855
                        /* TODO: is GetPrivateData on interface data supposed to do this? */
 
856
                        if(*pDataSize < sizeof(void*))
 
857
                                return E_INVALIDARG;
 
858
                        if(pData)
 
859
                        {
 
860
                                memcpy(pData, &i->second.first, sizeof(void*));
 
861
                                ((IUnknown*)i->second.first)->AddRef();
 
862
                        }
 
863
                        *pDataSize = sizeof(void*);
 
864
                }
 
865
                else
 
866
                {
 
867
                        unsigned size = std::min(*pDataSize, i->second.second);
 
868
                        if(pData)
 
869
                                memcpy(pData, i->second.first, size);
 
870
                        *pDataSize = size;
 
871
                }
 
872
                return S_OK;
 
873
        }
 
874
 
 
875
        HRESULT set_private_data(
 
876
                REFGUID guid,
 
877
                UINT DataSize,
 
878
                const void *pData)
 
879
        {
 
880
                void* p = 0;
 
881
 
 
882
                if(DataSize && pData)
 
883
                {
 
884
                        p = malloc(DataSize);
 
885
                        if(!p)
 
886
                                return E_OUTOFMEMORY;
 
887
                }
 
888
 
 
889
                lock_t<mutex_t> lock(private_data_mutex);
 
890
                std::pair<void*, unsigned>& v = private_data_map[guid];
 
891
                if(v.first)
 
892
                {
 
893
                        if(v.second == ~0u)
 
894
                                ((IUnknown*)v.first)->Release();
 
895
                        else
 
896
                                free(v.first);
 
897
                }
 
898
                if(DataSize && pData)
 
899
                {
 
900
                        memcpy(p, pData, DataSize);
 
901
                        v.first = p;
 
902
                        v.second = DataSize;
 
903
                }
 
904
                else
 
905
                        private_data_map.erase(guid);
 
906
                return S_OK;
 
907
        }
 
908
 
 
909
        HRESULT set_private_data_interface(
 
910
                REFGUID guid,
 
911
                const IUnknown *pData)
 
912
        {
 
913
                lock_t<mutex_t> lock(private_data_mutex);
 
914
                std::pair<void*, unsigned>& v = private_data_map[guid];
 
915
                if(v.first)
 
916
                {
 
917
                        if(v.second == ~0u)
 
918
                                ((IUnknown*)v.first)->Release();
 
919
                        else
 
920
                                free(v.first);
 
921
                }
 
922
                if(pData)
 
923
                {
 
924
                        ((IUnknown*)pData)->AddRef();
 
925
                        v.first = (void*)pData;
 
926
                        v.second = ~0;
 
927
                }
 
928
                else
 
929
                        private_data_map.erase(guid);
 
930
                return S_OK;
 
931
        }
 
932
 
 
933
        virtual HRESULT STDMETHODCALLTYPE GetPrivateData(
 
934
                REFGUID guid,
 
935
                UINT *pDataSize,
 
936
                void *pData)
 
937
        {
 
938
                return get_private_data(guid, pDataSize, pData);
 
939
        }
 
940
 
 
941
        virtual HRESULT STDMETHODCALLTYPE SetPrivateData(
 
942
                REFGUID guid,
 
943
                UINT DataSize,
 
944
                const void *pData)
 
945
        {
 
946
                return set_private_data(guid, DataSize, pData);
 
947
        }
 
948
 
 
949
        virtual HRESULT STDMETHODCALLTYPE SetPrivateDataInterface(
 
950
                REFGUID guid,
 
951
                const IUnknown *pData)
 
952
        {
 
953
                return set_private_data_interface(guid, pData);
 
954
        }
 
955
};
 
956
 
 
957
template<typename BaseClass, typename SecondaryInterface>
 
958
struct GalliumMultiPrivateDataComObject : public GalliumMultiComObject<BaseClass, SecondaryInterface>
 
959
{
 
960
        // we could avoid this duplication, but the increased complexity to do so isn't worth it
 
961
        virtual HRESULT STDMETHODCALLTYPE GetPrivateData(
 
962
                REFGUID guid,
 
963
                UINT *pDataSize,
 
964
                void *pData)
 
965
        {
 
966
                return BaseClass::get_private_data(guid, pDataSize, pData);
 
967
        }
 
968
 
 
969
        virtual HRESULT STDMETHODCALLTYPE SetPrivateData(
 
970
                REFGUID guid,
 
971
                UINT DataSize,
 
972
                const void *pData)
 
973
        {
 
974
                return BaseClass::set_private_data(guid, DataSize, pData);
 
975
        }
 
976
 
 
977
        virtual HRESULT STDMETHODCALLTYPE SetPrivateDataInterface(
 
978
                REFGUID guid,
 
979
                const IUnknown *pData)
 
980
        {
 
981
                return BaseClass::set_private_data_interface(guid, pData);
 
982
        }
 
983
};
 
984
 
 
985
#define DXGI_FORMAT_COUNT 116
 
986
extern pipe_format dxgi_to_pipe_format[DXGI_FORMAT_COUNT];
 
987
extern DXGI_FORMAT pipe_to_dxgi_format[PIPE_FORMAT_COUNT];
 
988
 
 
989
void init_pipe_to_dxgi_format();
 
990
 
 
991
COM_INTERFACE(IGalliumDevice, IUnknown);
 
992
COM_INTERFACE(IGalliumAdapter, IUnknown);
 
993
COM_INTERFACE(IGalliumResource, IUnknown);
 
994
 
 
995
// used to make QueryInterface know the IIDs of the interface and its ancestors
 
996
COM_INTERFACE(IDXGIObject, IUnknown)
 
997
COM_INTERFACE(IDXGIDeviceSubObject, IDXGIObject)
 
998
COM_INTERFACE(IDXGISurface, IDXGIDeviceSubObject)
 
999
COM_INTERFACE(IDXGIOutput, IDXGIObject)
 
1000
COM_INTERFACE(IDXGIAdapter, IDXGIObject)
 
1001
COM_INTERFACE(IDXGISwapChain, IDXGIDeviceSubObject)
 
1002
COM_INTERFACE(IDXGIFactory, IDXGIObject)
 
1003
COM_INTERFACE(IDXGIDevice, IDXGIObject)
 
1004
COM_INTERFACE(IDXGIResource, IDXGIDeviceSubObject)
 
1005
COM_INTERFACE(IDXGISurface1, IDXGISurface)
 
1006
COM_INTERFACE(IDXGIDevice1, IDXGIDevice)
 
1007
COM_INTERFACE(IDXGIAdapter1, IDXGIAdapter)
 
1008
COM_INTERFACE(IDXGIFactory1, IDXGIFactory)
 
1009
 
 
1010
template<typename Base>
 
1011
struct GalliumDXGIDevice : public GalliumMultiPrivateDataComObject<Base, IDXGIDevice1>
 
1012
{
 
1013
        ComPtr<IDXGIAdapter> adapter;
 
1014
        int priority;
 
1015
        unsigned max_latency;
 
1016
 
 
1017
        GalliumDXGIDevice(IDXGIAdapter* p_adapter)
 
1018
        {
 
1019
                adapter = p_adapter;
 
1020
        }
 
1021
 
 
1022
        virtual HRESULT STDMETHODCALLTYPE GetParent(
 
1023
                REFIID riid,
 
1024
                void **ppParent)
 
1025
        {
 
1026
                return adapter.p->QueryInterface(riid, ppParent);
 
1027
        }
 
1028
 
 
1029
        virtual HRESULT STDMETHODCALLTYPE GetAdapter(
 
1030
                IDXGIAdapter **pAdapter)
 
1031
        {
 
1032
                *pAdapter = adapter.ref();
 
1033
                return S_OK;
 
1034
        }
 
1035
 
 
1036
        virtual HRESULT STDMETHODCALLTYPE QueryResourceResidency(
 
1037
                IUnknown *const *ppResources,
 
1038
                DXGI_RESIDENCY *pResidencyStatus,
 
1039
                UINT NumResources)
 
1040
        {
 
1041
                for(unsigned i = 0; i < NumResources; ++i)
 
1042
                        pResidencyStatus[i] = DXGI_RESIDENCY_FULLY_RESIDENT;
 
1043
                return S_OK;
 
1044
        }
 
1045
 
 
1046
        virtual HRESULT STDMETHODCALLTYPE SetGPUThreadPriority(
 
1047
                INT Priority)
 
1048
        {
 
1049
                priority = Priority;
 
1050
                return S_OK;
 
1051
        }
 
1052
 
 
1053
        virtual HRESULT STDMETHODCALLTYPE GetGPUThreadPriority(
 
1054
                INT *pPriority)
 
1055
        {
 
1056
                *pPriority = priority;
 
1057
                return S_OK;
 
1058
        }
 
1059
 
 
1060
        HRESULT STDMETHODCALLTYPE GetMaximumFrameLatency(
 
1061
                UINT *pMaxLatency
 
1062
        )
 
1063
        {
 
1064
                *pMaxLatency = max_latency;
 
1065
                return S_OK;
 
1066
        }
 
1067
 
 
1068
        virtual HRESULT STDMETHODCALLTYPE SetMaximumFrameLatency(
 
1069
                UINT MaxLatency)
 
1070
        {
 
1071
                max_latency = MaxLatency;
 
1072
                return S_OK;
 
1073
        }
 
1074
};
 
1075
 
 
1076
COM_INTERFACE(ID3D10Blob, IUnknown);
 
1077
 
 
1078
/* NOTE: ID3DBlob implementations may come from a Microsoft native DLL
 
1079
 * (e.g. d3dcompiler), or perhaps even from the application itself.
 
1080
 *
 
1081
 * Hence, never try to access the data/size members directly, which is why they are private.
 
1082
 * In internal code, use std::pair<void*, size_t> instead of this class.
 
1083
 */
 
1084
class GalliumD3DBlob : public GalliumComObject<ID3DBlob>
 
1085
{
 
1086
        void* data;
 
1087
        size_t size;
 
1088
 
 
1089
public:
 
1090
        GalliumD3DBlob(void* data, size_t size)
 
1091
        : data(data), size(size)
 
1092
        {}
 
1093
 
 
1094
        ~GalliumD3DBlob()
 
1095
        {
 
1096
                free(data);
 
1097
        }
 
1098
 
 
1099
        virtual LPVOID STDMETHODCALLTYPE GetBufferPointer()
 
1100
        {
 
1101
                return data;
 
1102
        }
 
1103
 
 
1104
        virtual SIZE_T STDMETHODCALLTYPE GetBufferSize()
 
1105
        {
 
1106
                return size;
 
1107
        }
 
1108
};
 
1109
 
 
1110
#endif /* D3D1XSTUTIL_H_ */