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