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