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