d3d1xstutil.h revision 6c598c78bd17642d731cf57b8369cc794f64ba2f
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	maybe_mutex_t()
679	{
680		pipe_mutex_init(mutex);
681	}
682
683	void lock()
684	{
685		pipe_mutex_lock(mutex);
686	}
687
688	void unlock()
689	{
690		pipe_mutex_unlock(mutex);
691	}
692};
693
694template<>
695struct maybe_mutex_t<false>
696{
697	void lock()
698	{
699	}
700
701	void unlock()
702	{
703	}
704};
705
706typedef maybe_mutex_t<true> mutex_t;
707
708template<typename T>
709struct lock_t
710{
711	T& mutex;
712	lock_t(T& mutex)
713	: mutex(mutex)
714	{
715		mutex.lock();
716	}
717
718	~lock_t()
719	{
720		mutex.unlock();
721	}
722};
723
724struct c_string
725{
726	const char* p;
727	c_string(const char* p)
728	: p(p)
729	{}
730
731	operator const char*() const
732	{
733		return p;
734	}
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 bool operator !=(const c_string& a, const c_string& b)
743{
744	return strcmp(a.p, b.p);
745}
746
747static inline size_t raw_hash(const char* p, size_t size)
748{
749	size_t res;
750	if(sizeof(size_t) >= 8)
751		res = (size_t)14695981039346656037ULL;
752	else
753		res = (size_t)2166136261UL;
754	const char* end = p + size;
755	for(; p != end; ++p)
756	{
757		res ^= (size_t)*p;
758		if(sizeof(size_t) >= 8)
759			res *= (size_t)1099511628211ULL;
760		else
761			res *= (size_t)16777619UL;
762	}
763	return res;
764};
765
766template<typename T>
767static inline size_t raw_hash(const T& t)
768{
769	return raw_hash((const char*)&t, sizeof(t));
770}
771
772// TODO: only tested with the gcc libstdc++, might not work elsewhere
773namespace std
774{
775#ifndef _MSC_VER
776	namespace tr1
777	{
778#endif
779		template<>
780		struct hash<GUID> : public std::unary_function<GUID, size_t>
781		{
782			inline size_t operator()(GUID __val) const;
783		};
784
785		inline size_t hash<GUID>::operator()(GUID __val) const
786		{
787			return raw_hash(__val);
788		}
789
790		template<>
791		struct hash<c_string> : public std::unary_function<c_string, size_t>
792		{
793			inline size_t operator()(c_string __val) const;
794		};
795
796		inline size_t hash<c_string>::operator()(c_string __val) const
797		{
798			return raw_hash(__val.p, strlen(__val.p));
799		}
800
801		template<typename T, typename U>
802		struct hash<std::pair<T, U> > : public std::unary_function<std::pair<T, U>, size_t>
803		{
804			inline size_t operator()(std::pair<T, U> __val) const;
805		};
806
807		template<typename T, typename U>
808		inline size_t hash<std::pair<T, U> >::operator()(std::pair<T, U> __val) const
809		{
810			std::pair<size_t, size_t> p;
811			p.first = hash<T>()(__val.first);
812			p.second = hash<U>()(__val.second);
813			return raw_hash(p);
814		}
815#ifndef _MSC_VER
816	}
817#endif
818}
819
820template<typename Base, typename RefCnt = refcnt_t>
821struct GalliumPrivateDataComObject : public GalliumComObject<Base, RefCnt>
822{
823	typedef std::unordered_map<GUID, std::pair<void*, unsigned> > private_data_map_t;
824	private_data_map_t private_data_map;
825	mutex_t private_data_mutex;
826
827	~GalliumPrivateDataComObject()
828	{
829		for(private_data_map_t::iterator i = private_data_map.begin(), e = private_data_map.end(); i != e; ++i)
830		{
831			if(i->second.second == ~0u)
832				((IUnknown*)i->second.first)->Release();
833			else
834				free(i->second.first);
835		}
836	}
837
838	HRESULT get_private_data(
839		__in REFGUID guid,
840		__inout UINT *pDataSize,
841		__out_bcount_opt(*pDataSize) void *pData)
842	{
843		lock_t<mutex_t> lock(private_data_mutex);
844		private_data_map_t::iterator i = private_data_map.find(guid);
845		*pDataSize = 0;
846		if(i == private_data_map.end())
847			return DXGI_ERROR_NOT_FOUND;
848		if(i->second.second == ~0u)
849		{
850			/* TODO: is GetPrivateData on interface data supposed to do this? */
851			if(*pDataSize < sizeof(void*))
852				return E_INVALIDARG;
853			if(pData)
854			{
855				memcpy(pData, &i->second.first, sizeof(void*));
856				((IUnknown*)i->second.first)->AddRef();
857			}
858			*pDataSize = sizeof(void*);
859		}
860		else
861		{
862			unsigned size = std::min(*pDataSize, i->second.second);
863			if(pData)
864				memcpy(pData, i->second.first, size);
865			*pDataSize = size;
866		}
867		return S_OK;
868	}
869
870	HRESULT set_private_data(
871		__in REFGUID guid,
872		__in UINT DataSize,
873		__in_bcount_opt( DataSize ) const void *pData)
874	{
875		void* p = 0;
876
877		if(DataSize && pData)
878		{
879			p = malloc(DataSize);
880			if(!p)
881				return E_OUTOFMEMORY;
882		}
883
884		lock_t<mutex_t> lock(private_data_mutex);
885		std::pair<void*, unsigned>& v = private_data_map[guid];
886		if(v.first)
887		{
888			if(v.second == ~0u)
889				((IUnknown*)v.first)->Release();
890			else
891				free(v.first);
892		}
893		if(DataSize && pData)
894		{
895			memcpy(p, pData, DataSize);
896			v.first = p;
897			v.second = DataSize;
898		}
899		else
900			private_data_map.erase(guid);
901		return S_OK;
902	}
903
904	HRESULT set_private_data_interface(
905		__in REFGUID guid,
906		__in_opt const IUnknown *pData)
907	{
908		lock_t<mutex_t> lock(private_data_mutex);
909		std::pair<void*, unsigned>& v = private_data_map[guid];
910		if(v.first)
911		{
912			if(v.second == ~0u)
913				((IUnknown*)v.first)->Release();
914			else
915				free(v.first);
916		}
917		if(pData)
918		{
919			((IUnknown*)pData)->AddRef();
920			v.first = (void*)pData;
921			v.second = ~0;
922		}
923		else
924			private_data_map.erase(guid);
925		return S_OK;
926	}
927
928	virtual HRESULT STDMETHODCALLTYPE GetPrivateData(
929		__in REFGUID guid,
930		__inout UINT *pDataSize,
931		__out_bcount_opt(*pDataSize) void *pData)
932	{
933		return get_private_data(guid, pDataSize, pData);
934	}
935
936	virtual HRESULT STDMETHODCALLTYPE SetPrivateData(
937		__in REFGUID guid,
938		__in UINT DataSize,
939		__in_bcount_opt( DataSize ) const void *pData)
940	{
941		return set_private_data(guid, DataSize, pData);
942	}
943
944	virtual HRESULT STDMETHODCALLTYPE SetPrivateDataInterface(
945		__in REFGUID guid,
946		__in_opt const IUnknown *pData)
947	{
948		return set_private_data_interface(guid, pData);
949	}
950};
951
952template<typename BaseClass, typename SecondaryInterface>
953struct GalliumMultiPrivateDataComObject : public GalliumMultiComObject<BaseClass, SecondaryInterface>
954{
955	// we could avoid this duplication, but the increased complexity to do so isn't worth it
956	virtual HRESULT STDMETHODCALLTYPE GetPrivateData(
957		__in REFGUID guid,
958		__inout UINT *pDataSize,
959		__out_bcount_opt(*pDataSize) void *pData)
960	{
961		return BaseClass::get_private_data(guid, pDataSize, pData);
962	}
963
964	virtual HRESULT STDMETHODCALLTYPE SetPrivateData(
965		__in REFGUID guid,
966		__in UINT DataSize,
967		__in_bcount_opt( DataSize ) const void *pData)
968	{
969		return BaseClass::set_private_data(guid, DataSize, pData);
970	}
971
972	virtual HRESULT STDMETHODCALLTYPE SetPrivateDataInterface(
973		__in REFGUID guid,
974		__in_opt const IUnknown *pData)
975	{
976		return BaseClass::set_private_data_interface(guid, pData);
977	}
978};
979
980#define DXGI_FORMAT_COUNT 100
981extern pipe_format dxgi_to_pipe_format[DXGI_FORMAT_COUNT];
982extern DXGI_FORMAT pipe_to_dxgi_format[PIPE_FORMAT_COUNT];
983
984void init_pipe_to_dxgi_format();
985
986COM_INTERFACE(IGalliumDevice, IUnknown);
987COM_INTERFACE(IGalliumAdapter, IUnknown);
988COM_INTERFACE(IGalliumResource, IUnknown);
989
990// used to make QueryInterface know the IIDs of the interface and its ancestors
991COM_INTERFACE(IDXGIObject, IUnknown)
992COM_INTERFACE(IDXGIDeviceSubObject, IDXGIObject)
993COM_INTERFACE(IDXGISurface, IDXGIDeviceSubObject)
994COM_INTERFACE(IDXGIOutput, IDXGIObject)
995COM_INTERFACE(IDXGIAdapter, IDXGIObject)
996COM_INTERFACE(IDXGISwapChain, IDXGIDeviceSubObject)
997COM_INTERFACE(IDXGIFactory, IDXGIObject)
998COM_INTERFACE(IDXGIDevice, IDXGIObject)
999COM_INTERFACE(IDXGIResource, IDXGIDeviceSubObject)
1000COM_INTERFACE(IDXGISurface1, IDXGISurface)
1001COM_INTERFACE(IDXGIDevice1, IDXGIDevice)
1002COM_INTERFACE(IDXGIAdapter1, IDXGIAdapter)
1003COM_INTERFACE(IDXGIFactory1, IDXGIFactory)
1004
1005template<typename Base>
1006struct GalliumDXGIDevice : public GalliumMultiPrivateDataComObject<Base, IDXGIDevice>
1007{
1008	ComPtr<IDXGIAdapter> adapter;
1009	int priority;
1010	unsigned max_latency;
1011
1012	GalliumDXGIDevice(IDXGIAdapter* p_adapter)
1013	{
1014		adapter = p_adapter;
1015	}
1016
1017	virtual HRESULT STDMETHODCALLTYPE GetParent(
1018		__in REFIID riid,
1019		__out void **ppParent)
1020	{
1021		return adapter.p->QueryInterface(riid, ppParent);
1022	}
1023
1024	virtual HRESULT STDMETHODCALLTYPE GetAdapter(
1025		__out IDXGIAdapter **pAdapter)
1026	{
1027		*pAdapter = adapter.ref();
1028		return S_OK;
1029	}
1030
1031	virtual HRESULT STDMETHODCALLTYPE QueryResourceResidency(
1032		__in_ecount(NumResources) IUnknown *const *ppResources,
1033		__out_ecount(NumResources) DXGI_RESIDENCY *pResidencyStatus,
1034		UINT NumResources)
1035	{
1036		for(unsigned i = 0; i < NumResources; ++i)
1037			pResidencyStatus[i] = DXGI_RESIDENCY_FULLY_RESIDENT;
1038		return S_OK;
1039	}
1040
1041	virtual HRESULT STDMETHODCALLTYPE SetGPUThreadPriority(
1042		INT Priority)
1043	{
1044		priority = Priority;
1045		return S_OK;
1046	}
1047
1048	virtual HRESULT STDMETHODCALLTYPE GetGPUThreadPriority(
1049		__out INT *pPriority)
1050	{
1051		*pPriority = priority;
1052		return S_OK;
1053	}
1054
1055	HRESULT STDMETHODCALLTYPE GetMaximumFrameLatency(
1056		UINT *pMaxLatency
1057	)
1058	{
1059		*pMaxLatency = max_latency;
1060		return S_OK;
1061	}
1062
1063	virtual HRESULT STDMETHODCALLTYPE SetMaximumFrameLatency(
1064		UINT MaxLatency)
1065	{
1066		max_latency = MaxLatency;
1067		return S_OK;
1068	}
1069};
1070
1071COM_INTERFACE(ID3D10Blob, IUnknown);
1072
1073/* NOTE: ID3DBlob implementations may come from a Microsoft native DLL
1074 * (e.g. d3dcompiler), or perhaps even from the application itself.
1075 *
1076 * Hence, never try to access the data/size members directly, which is why they are private.
1077 * In internal code, use std::pair<void*, size_t> instead of this class.
1078 */
1079class GalliumD3DBlob : public GalliumComObject<ID3DBlob>
1080{
1081	void* data;
1082	size_t size;
1083
1084public:
1085	GalliumD3DBlob(void* data, size_t size)
1086	: data(data), size(size)
1087	{}
1088
1089	~GalliumD3DBlob()
1090	{
1091		free(data);
1092	}
1093
1094	virtual LPVOID STDMETHODCALLTYPE GetBufferPointer()
1095	{
1096		return data;
1097	}
1098
1099	virtual SIZE_T STDMETHODCALLTYPE GetBufferSize()
1100	{
1101		return size;
1102	}
1103};
1104
1105#endif /* D3D1XSTUTIL_H_ */
1106