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