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