Home | History | Annotate | Download | only in include
      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_ */
   1111