1 /**************************************************************************
3 * Copyright 2010 Luca Barbieri
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:
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.
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.
25 **************************************************************************/
27 #ifndef D3D1XSTUTIL_H_
28 #define D3D1XSTUTIL_H_
31 #include <unordered_map>
32 #include <unordered_set>
34 #include <tr1/unordered_map>
35 #include <tr1/unordered_set>
44 #define WIN32_LEAN_AND_MEAN
47 #include <specstrings.h>
50 #define ATTRIBUTE_UNUSED __attribute__((unused))
52 #define ATTRIBUTE_UNUSED
55 // just replicate GUIDs in every object file to avoid the hassle of having to pull in a library for them
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 } }
61 #include "galliumdxgi.h"
62 #include <d3dcommon.h>
66 #include <util/u_atomic.h>
67 #include <pipe/p_format.h>
68 #include <os/os_thread.h>
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.
84 * In particular, the GNU/Linux/Itanium/clang ABI and Microsoft ABIs will work,
86 * If in doubt, just switch to the latest version of a widely used C++ compiler.
88 * DESIGN of the Gallium COM implementation
90 * This state tracker uses somewhat unusual C++ coding patterns,
91 * to implement the COM interfaces required by Direct3D.
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)
98 * Implementing COM is on first sight very easy: after all, it just
99 * consists of a reference count, and a dynamic_cast<> equivalent.
101 * However, implementing objects with multiple interfaces is actually
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.
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.
112 * This solution aims to achieve the following object layout:
113 * 0: pointer to vtable for primary interface
116 * ... vtable pointers for secondary interfaces
117 * ... implementation of subclasses assuming secondary interfaces
119 * This allows us to cast pointers by just reinterpreting the value in
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.
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.
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.
136 * The base class is GalliumComObject<IFoo>, which implements the
137 * IUnknown interface, and inherits IFoo.
139 * To support multiple inheritance, we insert GalliumMultiComObject,
140 * which redirects the secondary interfaces to the GalliumComObject
143 * Gallium(Multi)PrivateDataComObject is like ComObject but also
144 * implements the Get/SetPrivateData functions present on several
145 * D3D/DXGI interfaces.
147 * Example class hierarchy:
161 * GalliumComObject<IDuck>
162 * (non-instantiable, only implements IUnknown)
165 * GalliumAnimal<IDuck>
166 * (non-instantiable, only implements IAnimal)
173 * GalliumMultiComObject<GalliumDuck, IWheeledVehicle> <- IWheeledVehicle <- IVehicle <- IUnknown (second version)
174 * (non-instantiable, only implements IDuck and the IUnknown of IWheeledVehicle)
177 * GalliumDuckOnWheels
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.
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"
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.
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.
203 * --- The magic QueryInterface "delete this" trick ---
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).
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!
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
223 * Thus, we use this trick: we reuse the vtable slot for QueryInterface, which is always at the
225 * To do so, we define a special value for the first pointer argument, that triggers a
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.
231 * QueryInterface is already slow due to the need to compare several GUIDs, so the
232 * additional pointer test should not be significant.
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.
242 #define COM_INTERFACE(intf, base) \
244 struct com_traits<intf> \
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);} \
251 struct com_traits
<IUnknown
>
253 static REFIID
iid() {return IID_IUnknown
;}
254 static inline bool is_self_or_ancestor(REFIID riid
) {return riid
== iid();}
258 #define __uuidof(T) (com_traits<T>::iid())
265 refcnt_t(unsigned v
= 1)
271 p_atomic_inc((int32_t*)&refcnt
);
277 if(p_atomic_dec_zero((int32_t*)&refcnt
))
282 void nonatomic_add_ref()
284 p_atomic_inc((int32_t*)&refcnt
);
287 unsigned nonatomic_release()
289 if(p_atomic_dec_zero((int32_t*)&refcnt
))
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:
300 * should never be reorderable (as seen from another CPU) to:
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.
314 uint32_t atomic_refcnt
;
315 uint32_t nonatomic_refcnt
;
319 dual_refcnt_t(unsigned v
= 1)
322 nonatomic_refcnt
= 0;
327 if(sizeof(void*) == 8)
328 return *(volatile uint64_t*)&refcnt
== 0ULL;
336 while(!__sync_bool_compare_and_swap(&refcnt
, v
, v
));
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
;
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())
353 unsigned v
= atomic_refcnt
+ nonatomic_refcnt
;
357 void nonatomic_add_ref()
359 //printf("%p nonatomic_add_ref at %u %u\n", this, atomic_refcnt, nonatomic_refcnt);
363 unsigned nonatomic_release()
365 //printf("%p nonatomic_release at %u %u\n", this, atomic_refcnt, nonatomic_refcnt);
366 if(!--nonatomic_refcnt
&& !atomic_refcnt
&& is_zero())
372 // this will result in atomic operations being used while they could have been avoided
374 #warning Compile for 586+ using GCC to improve the performance of the Direct3D 10/11 state tracker
376 typedef refcnt_t dual_refcnt_t
;
379 #define IID_MAGIC_DELETE_THIS (*(const IID*)((intptr_t)-(int)(sizeof(IID) - 1)))
381 template<typename Base
= IUnknown
, typename RefCnt
= refcnt_t
>
382 struct GalliumComObject
: public Base
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
392 virtual ~GalliumComObject()
395 inline ULONG
add_ref()
397 return refcnt
.add_ref();
400 inline ULONG
release()
402 ULONG v
= refcnt
.release();
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);
413 inline void nonatomic_add_ref()
415 refcnt
.nonatomic_add_ref();
418 inline void nonatomic_release()
420 if(!refcnt
.nonatomic_release())
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);
428 inline HRESULT
query_interface(REFIID riid
, void **ppvObject
)
430 if(com_traits
<Base
>::is_self_or_ancestor(riid
))
432 // must be the virtual AddRef, since it is overridden by some classes
438 return E_NOINTERFACE
;
441 virtual ULONG STDMETHODCALLTYPE
AddRef()
446 virtual ULONG STDMETHODCALLTYPE
Release()
451 virtual HRESULT STDMETHODCALLTYPE
QueryInterface(
455 /* see the initial comment for an explaination of this magic trick */
456 if(&riid
== &IID_MAGIC_DELETE_THIS
)
465 return query_interface(riid
, ppvObject
);
469 template<typename BaseClass
, typename SecondaryInterface
>
470 struct GalliumMultiComObject
: public BaseClass
, SecondaryInterface
472 // we could avoid this duplication, but the increased complexity to do so isn't worth it
473 virtual ULONG STDMETHODCALLTYPE
AddRef()
475 return BaseClass::add_ref();
478 virtual ULONG STDMETHODCALLTYPE
Release()
480 return BaseClass::release();
483 inline HRESULT
query_interface(REFIID riid
, void **ppvObject
)
485 HRESULT hr
= BaseClass::query_interface(riid
, ppvObject
);
488 if(com_traits
<SecondaryInterface
>::is_self_or_ancestor(riid
))
490 // must be the virtual AddRef, since it is overridden by some classes
492 *ppvObject
= (SecondaryInterface
*)this;
496 return E_NOINTERFACE
;
499 virtual HRESULT STDMETHODCALLTYPE
QueryInterface(
503 /* see the initial comment for an explaination of this magic trick */
504 if(&riid
== &IID_MAGIC_DELETE_THIS
)
513 return query_interface(riid
, ppvObject
);
517 template<typename T
, typename Traits
>
526 void add_ref() {Traits::add_ref(p
);}
527 void release() {Traits::release(p
);}
529 template<typename U
, typename UTraits
>
530 refcnt_ptr(const refcnt_ptr
<U
, UTraits
>& c
)
532 *this = static_cast<U
*>(c
.ref());
546 template<typename U
, typename UTraits
>
547 refcnt_ptr
& operator =(const refcnt_ptr
<U
, UTraits
>& q
)
553 refcnt_ptr
& operator =(U
* q
)
556 p
= static_cast<T
*>(q
);
579 const T
* operator ->() const
590 bool operator !() const
595 typedef T
* refcnt_ptr::*unspecified_bool_type
;
597 operator unspecified_bool_type() const
599 return p
? &refcnt_ptr::p
: 0;
603 struct simple_ptr_traits
605 static void add_ref(void* p
) {}
606 static void release(void* p
) {}
609 struct com_ptr_traits
611 static void add_ref(void* p
)
614 ((IUnknown
*)p
)->AddRef();
617 static void release(void* p
)
620 ((IUnknown
*)p
)->Release();
625 struct ComPtr
: public refcnt_ptr
<T
, com_ptr_traits
>
627 template<typename U
, typename UTraits
>
628 ComPtr
& operator =(const refcnt_ptr
<U
, UTraits
>& q
)
634 ComPtr
& operator =(U
* q
)
637 this->p
= static_cast<T
*>(q
);
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
)
649 template<typename T
, typename TTraits
, typename U
>
650 bool operator ==(const refcnt_ptr
<T
, TTraits
>& a
, U
* b
)
655 template<typename T
, typename TTraits
, typename U
>
656 bool operator ==(U
* b
, const refcnt_ptr
<T
, TTraits
>& a
)
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
)
667 template<typename T
, typename TTraits
, typename U
>
668 bool operator !=(const refcnt_ptr
<T
, TTraits
>& a
, U
* b
)
673 template<typename T
, typename TTraits
, typename U
>
674 bool operator !=(U
* b
, const refcnt_ptr
<T
, TTraits
>& a
)
679 template<bool threadsafe
>
680 struct maybe_mutex_t
;
683 struct maybe_mutex_t
<true>
689 pipe_mutex_lock(mutex
);
694 pipe_mutex_unlock(mutex
);
699 struct maybe_mutex_t
<false>
710 typedef maybe_mutex_t
<true> mutex_t
;
731 c_string(const char* p
)
735 operator const char*() const
741 static inline bool operator ==(const c_string
& a
, const c_string
& b
)
743 return !strcmp(a
.p
, b
.p
);
746 static inline bool operator !=(const c_string
& a
, const c_string
& b
)
748 return strcmp(a
.p
, b
.p
);
757 inline size_t hash
<GUID
>::operator()(GUID __val
) const
759 return _Fnv_hash::hash(__val
);
763 inline size_t hash
<c_string
>::operator()(c_string __val
) const
765 return _Fnv_hash::hash(__val
.p
, strlen(__val
.p
));
768 template<typename T
, typename U
>
769 struct hash
<std::pair
<T
, U
> > : public std::unary_function
<std::pair
<T
, U
>, size_t>
771 size_t operator()(std::pair
<T
, U
> __val
) const;
774 template<typename T
, typename U
>
775 inline size_t hash
<std::pair
<T
, U
> >::operator()(std::pair
<T
, U
> __val
) const
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
);
785 #warning "You probably need to add a pair, C string and GUID hash implementation for your C++ library"
788 template<typename Base
, typename RefCnt
= refcnt_t
>
789 struct GalliumPrivateDataComObject
: public GalliumComObject
<Base
, RefCnt
>
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
;
795 ~GalliumPrivateDataComObject()
797 for(private_data_map_t::iterator i
= private_data_map
.begin(), e
= private_data_map
.end(); i
!= e
; ++i
)
799 if(i
->second
.second
== ~0u)
800 ((IUnknown
*)i
->second
.first
)->Release();
802 free(i
->second
.first
);
806 HRESULT
get_private_data(
808 __inout UINT
*pDataSize
,
809 __out_bcount_opt(*pDataSize
) void *pData
)
811 lock_t
<mutex_t
> lock(private_data_mutex
);
812 private_data_map_t::iterator i
= private_data_map
.find(guid
);
814 if(i
== private_data_map
.end())
815 return DXGI_ERROR_NOT_FOUND
;
816 if(i
->second
.second
== ~0u)
818 /* TODO: is GetPrivateData on interface data supposed to do this? */
819 if(*pDataSize
< sizeof(void*))
823 memcpy(pData
, &i
->second
.first
, sizeof(void*));
824 ((IUnknown
*)i
->second
.first
)->AddRef();
826 *pDataSize
= sizeof(void*);
830 unsigned size
= std::min(*pDataSize
, i
->second
.second
);
832 memcpy(pData
, i
->second
.first
, size
);
838 HRESULT
set_private_data(
841 __in_bcount_opt( DataSize
) const void *pData
)
845 if(DataSize
&& pData
)
847 p
= malloc(DataSize
);
849 return E_OUTOFMEMORY
;
852 lock_t
<mutex_t
> lock(private_data_mutex
);
853 std::pair
<void*, unsigned>& v
= private_data_map
[guid
];
857 ((IUnknown
*)v
.first
)->Release();
861 if(DataSize
&& pData
)
863 memcpy(p
, pData
, DataSize
);
868 private_data_map
.erase(guid
);
872 HRESULT
set_private_data_interface(
874 __in_opt
const IUnknown
*pData
)
876 lock_t
<mutex_t
> lock(private_data_mutex
);
877 std::pair
<void*, unsigned>& v
= private_data_map
[guid
];
881 ((IUnknown
*)v
.first
)->Release();
887 ((IUnknown
*)pData
)->AddRef();
888 v
.first
= (void*)pData
;
892 private_data_map
.erase(guid
);
896 virtual HRESULT STDMETHODCALLTYPE
GetPrivateData(
898 __inout UINT
*pDataSize
,
899 __out_bcount_opt(*pDataSize
) void *pData
)
901 return get_private_data(guid
, pDataSize
, pData
);
904 virtual HRESULT STDMETHODCALLTYPE
SetPrivateData(
907 __in_bcount_opt( DataSize
) const void *pData
)
909 return set_private_data(guid
, DataSize
, pData
);
912 virtual HRESULT STDMETHODCALLTYPE
SetPrivateDataInterface(
914 __in_opt
const IUnknown
*pData
)
916 return set_private_data_interface(guid
, pData
);
920 template<typename BaseClass
, typename SecondaryInterface
>
921 struct GalliumMultiPrivateDataComObject
: public GalliumMultiComObject
<BaseClass
, SecondaryInterface
>
923 // we could avoid this duplication, but the increased complexity to do so isn't worth it
924 virtual HRESULT STDMETHODCALLTYPE
GetPrivateData(
926 __inout UINT
*pDataSize
,
927 __out_bcount_opt(*pDataSize
) void *pData
)
929 return BaseClass::get_private_data(guid
, pDataSize
, pData
);
932 virtual HRESULT STDMETHODCALLTYPE
SetPrivateData(
935 __in_bcount_opt( DataSize
) const void *pData
)
937 return BaseClass::set_private_data(guid
, DataSize
, pData
);
940 virtual HRESULT STDMETHODCALLTYPE
SetPrivateDataInterface(
942 __in_opt
const IUnknown
*pData
)
944 return BaseClass::set_private_data_interface(guid
, pData
);
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
];
952 void init_pipe_to_dxgi_format();
954 COM_INTERFACE(IGalliumDevice
, IUnknown
);
955 COM_INTERFACE(IGalliumAdapter
, IUnknown
);
956 COM_INTERFACE(IGalliumResource
, IUnknown
);
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
)
973 template<typename Base
>
974 struct GalliumDXGIDevice
: public GalliumMultiPrivateDataComObject
<Base
, IDXGIDevice
>
976 ComPtr
<IDXGIAdapter
> adapter
;
978 unsigned max_latency
;
980 GalliumDXGIDevice(IDXGIAdapter
* p_adapter
)
985 virtual HRESULT STDMETHODCALLTYPE
GetParent(
987 __out
void **ppParent
)
989 return adapter
.p
->QueryInterface(riid
, ppParent
);
992 virtual HRESULT STDMETHODCALLTYPE
GetAdapter(
993 __out IDXGIAdapter
**pAdapter
)
995 *pAdapter
= adapter
.ref();
999 virtual HRESULT STDMETHODCALLTYPE
QueryResourceResidency(
1000 __in_ecount(NumResources
) IUnknown
*const *ppResources
,
1001 __out_ecount(NumResources
) DXGI_RESIDENCY
*pResidencyStatus
,
1004 for(unsigned i
= 0; i
< NumResources
; ++i
)
1005 pResidencyStatus
[i
] = DXGI_RESIDENCY_FULLY_RESIDENT
;
1009 virtual HRESULT STDMETHODCALLTYPE
SetGPUThreadPriority(
1012 priority
= Priority
;
1016 virtual HRESULT STDMETHODCALLTYPE
GetGPUThreadPriority(
1017 __out INT
*pPriority
)
1019 *pPriority
= priority
;
1023 HRESULT STDMETHODCALLTYPE
GetMaximumFrameLatency(
1027 *pMaxLatency
= max_latency
;
1031 virtual HRESULT STDMETHODCALLTYPE
SetMaximumFrameLatency(
1034 max_latency
= MaxLatency
;
1039 COM_INTERFACE(ID3D10Blob
, IUnknown
);
1041 /* NOTE: ID3DBlob implementations may come from a Microsoft native DLL
1042 * (e.g. d3dcompiler), or perhaps even from the application itself.
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.
1047 class GalliumD3DBlob
: public GalliumComObject
<ID3DBlob
>
1052 GalliumD3DBlob(void* data
, size_t size
)
1053 : data(data
), size(size
)
1061 virtual LPVOID STDMETHODCALLTYPE
GetBufferPointer()
1066 virtual SIZE_T STDMETHODCALLTYPE
GetBufferSize()
1072 #endif /* D3D1XSTUTIL_H_ */