d3d1xstutil.h revision cac1565b98c7450ef5c74660e8145e300b3f8d7f
11e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)/************************************************************************** 21e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) * 31e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) * Copyright 2010 Luca Barbieri 41e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) * 51e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) * Permission is hereby granted, free of charge, to any person obtaining 61e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) * a copy of this software and associated documentation files (the 71e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) * "Software"), to deal in the Software without restriction, including 81e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) * without limitation the rights to use, copy, modify, merge, publish, 9f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * distribute, sublicense, and/or sell copies of the Software, and to 101e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) * permit persons to whom the Software is furnished to do so, subject to 111e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) * the following conditions: 121e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) * 131e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) * The above copyright notice and this permission notice (including the 141e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) * next paragraph) shall be included in all copies or substantial 151e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) * portions of the Software. 161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) * 171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 181e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 191e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE 211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 231e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 241e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) * 251e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) **************************************************************************/ 261e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 271e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#ifndef D3D1XSTUTIL_H_ 281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#define D3D1XSTUTIL_H_ 291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#ifdef _MSC_VER 311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include <unordered_map> 321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include <unordered_set> 331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#else 341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include <tr1/unordered_map> 351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include <tr1/unordered_set> 361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)namespace std 371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles){ 381e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) using namespace tr1; 391e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#endif 411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include <map> 421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include <utility> 431e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 441e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#define WIN32_LEAN_AND_MEAN 451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include <objbase.h> 461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include <guiddef.h> 471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include <specstrings.h> 48f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 49f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#ifdef __GNUC__ 501e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#define ATTRIBUTE_UNUSED __attribute__((unused)) 511e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#else 521e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#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 64extern "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 239template<typename T> 240struct com_traits; 241 242#define COM_INTERFACE(intf, base) \ 243template<> \ 244struct 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 250template<> 251struct 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 261struct 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 */ 307struct 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) 367 { 368 __sync_synchronize(); 369 if(!atomic_refcnt && is_zero()) 370 return 0; 371 } 372 return 1; 373 } 374}; 375#else 376// this will result in atomic operations being used while they could have been avoided 377#ifdef __i386__ 378#warning Compile for 586+ using GCC to improve the performance of the Direct3D 10/11 state tracker 379#endif 380typedef refcnt_t dual_refcnt_t; 381#endif 382 383#define IID_MAGIC_DELETE_THIS (*(const IID*)((intptr_t)-(int)(sizeof(IID) - 1))) 384 385template<typename Base = IUnknown, typename RefCnt = refcnt_t> 386struct GalliumComObject : public Base 387{ 388 RefCnt refcnt; 389 390 GalliumComObject() 391 {} 392 393 /* DO NOT CALL this from externally called non-virtual functions in derived classes, since 394 * the vtable position depends on the COM interface being implemented 395 */ 396 virtual ~GalliumComObject() 397 {} 398 399 inline ULONG add_ref() 400 { 401 return refcnt.add_ref(); 402 } 403 404 inline ULONG release() 405 { 406 ULONG v = refcnt.release(); 407 if(!v) 408 { 409 /* this will call execute "delete this", using the correct vtable slot for the destructor */ 410 /* see the initial comment for an explaination of this magic trick */ 411 this->QueryInterface(IID_MAGIC_DELETE_THIS, 0); 412 return 0; 413 } 414 return v; 415 } 416 417 inline void nonatomic_add_ref() 418 { 419 refcnt.nonatomic_add_ref(); 420 } 421 422 inline void nonatomic_release() 423 { 424 if(!refcnt.nonatomic_release()) 425 { 426 /* this will execute "delete this", using the correct vtable slot for the destructor */ 427 /* see the initial comment for an explaination of this magic trick */ 428 this->QueryInterface(IID_MAGIC_DELETE_THIS, 0); 429 } 430 } 431 432 inline HRESULT query_interface(REFIID riid, void **ppvObject) 433 { 434 if(com_traits<Base>::is_self_or_ancestor(riid)) 435 { 436 // must be the virtual AddRef, since it is overridden by some classes 437 this->AddRef(); 438 *ppvObject = this; 439 return S_OK; 440 } 441 else 442 return E_NOINTERFACE; 443 } 444 445 virtual ULONG STDMETHODCALLTYPE AddRef() 446 { 447 return add_ref(); 448 } 449 450 virtual ULONG STDMETHODCALLTYPE Release() 451 { 452 return release(); 453 } 454 455 virtual HRESULT STDMETHODCALLTYPE QueryInterface( 456 REFIID riid, 457 void **ppvObject) 458 { 459 /* see the initial comment for an explaination of this magic trick */ 460 if(&riid == &IID_MAGIC_DELETE_THIS) 461 { 462 delete this; 463 return 0; 464 } 465 if(!this) 466 return E_INVALIDARG; 467 if(!ppvObject) 468 return E_POINTER; 469 return query_interface(riid, ppvObject); 470 } 471}; 472 473template<typename BaseClass, typename SecondaryInterface> 474struct GalliumMultiComObject : public BaseClass, SecondaryInterface 475{ 476 // we could avoid this duplication, but the increased complexity to do so isn't worth it 477 virtual ULONG STDMETHODCALLTYPE AddRef() 478 { 479 return BaseClass::add_ref(); 480 } 481 482 virtual ULONG STDMETHODCALLTYPE Release() 483 { 484 return BaseClass::release(); 485 } 486 487 inline HRESULT query_interface(REFIID riid, void **ppvObject) 488 { 489 HRESULT hr = BaseClass::query_interface(riid, ppvObject); 490 if(SUCCEEDED(hr)) 491 return hr; 492 if(com_traits<SecondaryInterface>::is_self_or_ancestor(riid)) 493 { 494 // must be the virtual AddRef, since it is overridden by some classes 495 this->AddRef(); 496 *ppvObject = (SecondaryInterface*)this; 497 return S_OK; 498 } 499 else 500 return E_NOINTERFACE; 501 } 502 503 virtual HRESULT STDMETHODCALLTYPE QueryInterface( 504 REFIID riid, 505 void **ppvObject) 506 { 507 /* see the initial comment for an explaination of this magic trick */ 508 if(&riid == &IID_MAGIC_DELETE_THIS) 509 { 510 delete this; 511 return 0; 512 } 513 if(!this) 514 return E_INVALIDARG; 515 if(!ppvObject) 516 return E_POINTER; 517 return query_interface(riid, ppvObject); 518 } 519}; 520 521template<typename T, typename Traits> 522struct refcnt_ptr 523{ 524 T* p; 525 526 refcnt_ptr() 527 : p(0) 528 {} 529 530 void add_ref() {Traits::add_ref(p);} 531 void release() {Traits::release(p);} 532 533 template<typename U, typename UTraits> 534 refcnt_ptr(const refcnt_ptr<U, UTraits>& c) 535 { 536 *this = static_cast<U*>(c.ref()); 537 } 538 539 ~refcnt_ptr() 540 { 541 release(); 542 } 543 544 void reset(T* q) 545 { 546 release(); 547 p = q; 548 } 549 550 template<typename U, typename UTraits> 551 refcnt_ptr& operator =(const refcnt_ptr<U, UTraits>& q) 552 { 553 return *this = q.p; 554 } 555 556 template<typename U> 557 refcnt_ptr& operator =(U* q) 558 { 559 release(); 560 p = static_cast<T*>(q); 561 add_ref(); 562 return *this; 563 } 564 565 T* ref() 566 { 567 add_ref(); 568 return p; 569 } 570 571 T* steal() 572 { 573 T* ret = p; 574 p = 0; 575 return ret; 576 } 577 578 T* operator ->() 579 { 580 return p; 581 } 582 583 const T* operator ->() const 584 { 585 return p; 586 } 587 588 T** operator &() 589 { 590 assert(!p); 591 return &p; 592 } 593 594 bool operator !() const 595 { 596 return !p; 597 } 598 599 typedef T* refcnt_ptr::*unspecified_bool_type; 600 601 operator unspecified_bool_type() const 602 { 603 return p ? &refcnt_ptr::p : 0; 604 } 605}; 606 607struct simple_ptr_traits 608{ 609 static void add_ref(void* p) {} 610 static void release(void* p) {} 611}; 612 613struct com_ptr_traits 614{ 615 static void add_ref(void* p) 616 { 617 if(p) 618 ((IUnknown*)p)->AddRef(); 619 } 620 621 static void release(void* p) 622 { 623 if(p) 624 ((IUnknown*)p)->Release(); 625 } 626}; 627 628template<typename T> 629struct ComPtr : public refcnt_ptr<T, com_ptr_traits> 630{ 631 template<typename U, typename UTraits> 632 ComPtr& operator =(const refcnt_ptr<U, UTraits>& q) 633 { 634 return *this = q.p; 635 } 636 637 template<typename U> 638 ComPtr& operator =(U* q) 639 { 640 this->release(); 641 this->p = static_cast<T*>(q); 642 this->add_ref(); 643 return *this; 644 } 645}; 646 647template<typename T, typename TTraits, typename U, typename UTraits> 648bool operator ==(const refcnt_ptr<T, TTraits>& a, const refcnt_ptr<U, UTraits>& b) 649{ 650 return a.p == b.p; 651} 652 653template<typename T, typename TTraits, typename U> 654bool operator ==(const refcnt_ptr<T, TTraits>& a, U* b) 655{ 656 return a.p == b; 657} 658 659template<typename T, typename TTraits, typename U> 660bool operator ==(U* b, const refcnt_ptr<T, TTraits>& a) 661{ 662 return a.p == b; 663} 664 665template<typename T, typename TTraits, typename U, typename UTraits> 666bool operator !=(const refcnt_ptr<T, TTraits>& a, const refcnt_ptr<U, UTraits>& b) 667{ 668 return a.p != b.p; 669} 670 671template<typename T, typename TTraits, typename U> 672bool operator !=(const refcnt_ptr<T, TTraits>& a, U* b) 673{ 674 return a.p != b; 675} 676 677template<typename T, typename TTraits, typename U> 678bool operator !=(U* b, const refcnt_ptr<T, TTraits>& a) 679{ 680 return a.p != b; 681} 682 683template<bool threadsafe> 684struct maybe_mutex_t; 685 686template<> 687struct maybe_mutex_t<true> 688{ 689 pipe_mutex mutex; 690 691 void lock() 692 { 693 pipe_mutex_lock(mutex); 694 } 695 696 void unlock() 697 { 698 pipe_mutex_unlock(mutex); 699 } 700}; 701 702template<> 703struct maybe_mutex_t<false> 704{ 705 void lock() 706 { 707 } 708 709 void unlock() 710 { 711 } 712}; 713 714typedef maybe_mutex_t<true> mutex_t; 715 716template<typename T> 717struct lock_t 718{ 719 T& mutex; 720 lock_t(T& mutex) 721 : mutex(mutex) 722 { 723 mutex.lock(); 724 } 725 726 ~lock_t() 727 { 728 mutex.unlock(); 729 } 730}; 731 732struct c_string 733{ 734 const char* p; 735 c_string(const char* p) 736 : p(p) 737 {} 738 739 operator const char*() const 740 { 741 return p; 742 } 743}; 744 745static inline bool operator ==(const c_string& a, const c_string& b) 746{ 747 return !strcmp(a.p, b.p); 748} 749 750static inline bool operator !=(const c_string& a, const c_string& b) 751{ 752 return strcmp(a.p, b.p); 753} 754 755static inline size_t raw_hash(const char* p, size_t size) 756{ 757 size_t res; 758 if(sizeof(size_t) >= 8) 759 res = (size_t)14695981039346656037ULL; 760 else 761 res = (size_t)2166136261UL; 762 const char* end = p + size; 763 for(; p != end; ++p) 764 { 765 res ^= (size_t)*p; 766 if(sizeof(size_t) >= 8) 767 res *= (size_t)1099511628211ULL; 768 else 769 res *= (size_t)16777619UL; 770 } 771 return res; 772}; 773 774template<typename T> 775static inline size_t raw_hash(const T& t) 776{ 777 return raw_hash((const char*)&t, sizeof(t)); 778} 779 780// TODO: only tested with the gcc libstdc++, might not work elsewhere 781namespace std 782{ 783#ifndef _MSC_VER 784 namespace tr1 785 { 786#endif 787 template<> 788 struct hash<GUID> : public std::unary_function<GUID, size_t> 789 { 790 inline size_t operator()(GUID __val) const; 791 }; 792 793 inline size_t hash<GUID>::operator()(GUID __val) const 794 { 795 return raw_hash(__val); 796 } 797 798 template<> 799 struct hash<c_string> : public std::unary_function<c_string, size_t> 800 { 801 inline size_t operator()(c_string __val) const; 802 }; 803 804 inline size_t hash<c_string>::operator()(c_string __val) const 805 { 806 return raw_hash(__val.p, strlen(__val.p)); 807 } 808 809 template<typename T, typename U> 810 struct hash<std::pair<T, U> > : public std::unary_function<std::pair<T, U>, size_t> 811 { 812 inline size_t operator()(std::pair<T, U> __val) const; 813 }; 814 815 template<typename T, typename U> 816 inline size_t hash<std::pair<T, U> >::operator()(std::pair<T, U> __val) const 817 { 818 std::pair<size_t, size_t> p; 819 p.first = hash<T>()(__val.first); 820 p.second = hash<U>()(__val.second); 821 return raw_hash(p); 822 } 823#ifndef _MSC_VER 824 } 825#endif 826} 827 828template<typename Base, typename RefCnt = refcnt_t> 829struct GalliumPrivateDataComObject : public GalliumComObject<Base, RefCnt> 830{ 831 typedef std::unordered_map<GUID, std::pair<void*, unsigned> > private_data_map_t; 832 private_data_map_t private_data_map; 833 mutex_t private_data_mutex; 834 835 ~GalliumPrivateDataComObject() 836 { 837 for(private_data_map_t::iterator i = private_data_map.begin(), e = private_data_map.end(); i != e; ++i) 838 { 839 if(i->second.second == ~0u) 840 ((IUnknown*)i->second.first)->Release(); 841 else 842 free(i->second.first); 843 } 844 } 845 846 HRESULT get_private_data( 847 __in REFGUID guid, 848 __inout UINT *pDataSize, 849 __out_bcount_opt(*pDataSize) void *pData) 850 { 851 lock_t<mutex_t> lock(private_data_mutex); 852 private_data_map_t::iterator i = private_data_map.find(guid); 853 *pDataSize = 0; 854 if(i == private_data_map.end()) 855 return DXGI_ERROR_NOT_FOUND; 856 if(i->second.second == ~0u) 857 { 858 /* TODO: is GetPrivateData on interface data supposed to do this? */ 859 if(*pDataSize < sizeof(void*)) 860 return E_INVALIDARG; 861 if(pData) 862 { 863 memcpy(pData, &i->second.first, sizeof(void*)); 864 ((IUnknown*)i->second.first)->AddRef(); 865 } 866 *pDataSize = sizeof(void*); 867 } 868 else 869 { 870 unsigned size = std::min(*pDataSize, i->second.second); 871 if(pData) 872 memcpy(pData, i->second.first, size); 873 *pDataSize = size; 874 } 875 return S_OK; 876 } 877 878 HRESULT set_private_data( 879 __in REFGUID guid, 880 __in UINT DataSize, 881 __in_bcount_opt( DataSize ) const void *pData) 882 { 883 void* p = 0; 884 885 if(DataSize && pData) 886 { 887 p = malloc(DataSize); 888 if(!p) 889 return E_OUTOFMEMORY; 890 } 891 892 lock_t<mutex_t> lock(private_data_mutex); 893 std::pair<void*, unsigned>& v = private_data_map[guid]; 894 if(v.first) 895 { 896 if(v.second == ~0u) 897 ((IUnknown*)v.first)->Release(); 898 else 899 free(v.first); 900 } 901 if(DataSize && pData) 902 { 903 memcpy(p, pData, DataSize); 904 v.first = p; 905 v.second = DataSize; 906 } 907 else 908 private_data_map.erase(guid); 909 return S_OK; 910 } 911 912 HRESULT set_private_data_interface( 913 __in REFGUID guid, 914 __in_opt const IUnknown *pData) 915 { 916 lock_t<mutex_t> lock(private_data_mutex); 917 std::pair<void*, unsigned>& v = private_data_map[guid]; 918 if(v.first) 919 { 920 if(v.second == ~0u) 921 ((IUnknown*)v.first)->Release(); 922 else 923 free(v.first); 924 } 925 if(pData) 926 { 927 ((IUnknown*)pData)->AddRef(); 928 v.first = (void*)pData; 929 v.second = ~0; 930 } 931 else 932 private_data_map.erase(guid); 933 return S_OK; 934 } 935 936 virtual HRESULT STDMETHODCALLTYPE GetPrivateData( 937 __in REFGUID guid, 938 __inout UINT *pDataSize, 939 __out_bcount_opt(*pDataSize) void *pData) 940 { 941 return get_private_data(guid, pDataSize, pData); 942 } 943 944 virtual HRESULT STDMETHODCALLTYPE SetPrivateData( 945 __in REFGUID guid, 946 __in UINT DataSize, 947 __in_bcount_opt( DataSize ) const void *pData) 948 { 949 return set_private_data(guid, DataSize, pData); 950 } 951 952 virtual HRESULT STDMETHODCALLTYPE SetPrivateDataInterface( 953 __in REFGUID guid, 954 __in_opt const IUnknown *pData) 955 { 956 return set_private_data_interface(guid, pData); 957 } 958}; 959 960template<typename BaseClass, typename SecondaryInterface> 961struct GalliumMultiPrivateDataComObject : public GalliumMultiComObject<BaseClass, SecondaryInterface> 962{ 963 // we could avoid this duplication, but the increased complexity to do so isn't worth it 964 virtual HRESULT STDMETHODCALLTYPE GetPrivateData( 965 __in REFGUID guid, 966 __inout UINT *pDataSize, 967 __out_bcount_opt(*pDataSize) void *pData) 968 { 969 return BaseClass::get_private_data(guid, pDataSize, pData); 970 } 971 972 virtual HRESULT STDMETHODCALLTYPE SetPrivateData( 973 __in REFGUID guid, 974 __in UINT DataSize, 975 __in_bcount_opt( DataSize ) const void *pData) 976 { 977 return BaseClass::set_private_data(guid, DataSize, pData); 978 } 979 980 virtual HRESULT STDMETHODCALLTYPE SetPrivateDataInterface( 981 __in REFGUID guid, 982 __in_opt const IUnknown *pData) 983 { 984 return BaseClass::set_private_data_interface(guid, pData); 985 } 986}; 987 988#define DXGI_FORMAT_COUNT 100 989extern pipe_format dxgi_to_pipe_format[DXGI_FORMAT_COUNT]; 990extern DXGI_FORMAT pipe_to_dxgi_format[PIPE_FORMAT_COUNT]; 991 992void init_pipe_to_dxgi_format(); 993 994COM_INTERFACE(IGalliumDevice, IUnknown); 995COM_INTERFACE(IGalliumAdapter, IUnknown); 996COM_INTERFACE(IGalliumResource, IUnknown); 997 998// used to make QueryInterface know the IIDs of the interface and its ancestors 999COM_INTERFACE(IDXGIObject, IUnknown) 1000COM_INTERFACE(IDXGIDeviceSubObject, IDXGIObject) 1001COM_INTERFACE(IDXGISurface, IDXGIDeviceSubObject) 1002COM_INTERFACE(IDXGIOutput, IDXGIObject) 1003COM_INTERFACE(IDXGIAdapter, IDXGIObject) 1004COM_INTERFACE(IDXGISwapChain, IDXGIDeviceSubObject) 1005COM_INTERFACE(IDXGIFactory, IDXGIObject) 1006COM_INTERFACE(IDXGIDevice, IDXGIObject) 1007COM_INTERFACE(IDXGIResource, IDXGIDeviceSubObject) 1008COM_INTERFACE(IDXGISurface1, IDXGISurface) 1009COM_INTERFACE(IDXGIDevice1, IDXGIDevice) 1010COM_INTERFACE(IDXGIAdapter1, IDXGIAdapter) 1011COM_INTERFACE(IDXGIFactory1, IDXGIFactory) 1012 1013template<typename Base> 1014struct GalliumDXGIDevice : public GalliumMultiPrivateDataComObject<Base, IDXGIDevice> 1015{ 1016 ComPtr<IDXGIAdapter> adapter; 1017 int priority; 1018 unsigned max_latency; 1019 1020 GalliumDXGIDevice(IDXGIAdapter* p_adapter) 1021 { 1022 adapter = p_adapter; 1023 } 1024 1025 virtual HRESULT STDMETHODCALLTYPE GetParent( 1026 __in REFIID riid, 1027 __out void **ppParent) 1028 { 1029 return adapter.p->QueryInterface(riid, ppParent); 1030 } 1031 1032 virtual HRESULT STDMETHODCALLTYPE GetAdapter( 1033 __out IDXGIAdapter **pAdapter) 1034 { 1035 *pAdapter = adapter.ref(); 1036 return S_OK; 1037 } 1038 1039 virtual HRESULT STDMETHODCALLTYPE QueryResourceResidency( 1040 __in_ecount(NumResources) IUnknown *const *ppResources, 1041 __out_ecount(NumResources) DXGI_RESIDENCY *pResidencyStatus, 1042 UINT NumResources) 1043 { 1044 for(unsigned i = 0; i < NumResources; ++i) 1045 pResidencyStatus[i] = DXGI_RESIDENCY_FULLY_RESIDENT; 1046 return S_OK; 1047 } 1048 1049 virtual HRESULT STDMETHODCALLTYPE SetGPUThreadPriority( 1050 INT Priority) 1051 { 1052 priority = Priority; 1053 return S_OK; 1054 } 1055 1056 virtual HRESULT STDMETHODCALLTYPE GetGPUThreadPriority( 1057 __out INT *pPriority) 1058 { 1059 *pPriority = priority; 1060 return S_OK; 1061 } 1062 1063 HRESULT STDMETHODCALLTYPE GetMaximumFrameLatency( 1064 UINT *pMaxLatency 1065 ) 1066 { 1067 *pMaxLatency = max_latency; 1068 return S_OK; 1069 } 1070 1071 virtual HRESULT STDMETHODCALLTYPE SetMaximumFrameLatency( 1072 UINT MaxLatency) 1073 { 1074 max_latency = MaxLatency; 1075 return S_OK; 1076 } 1077}; 1078 1079COM_INTERFACE(ID3D10Blob, IUnknown); 1080 1081/* NOTE: ID3DBlob implementations may come from a Microsoft native DLL 1082 * (e.g. d3dcompiler), or perhaps even from the application itself. 1083 * 1084 * Hence, never try to access the data/size members directly, which is why they are private. 1085 * In internal code, use std::pair<void*, size_t> instead of this class. 1086 */ 1087class GalliumD3DBlob : public GalliumComObject<ID3DBlob> 1088{ 1089 void* data; 1090 size_t size; 1091 1092public: 1093 GalliumD3DBlob(void* data, size_t size) 1094 : data(data), size(size) 1095 {} 1096 1097 ~GalliumD3DBlob() 1098 { 1099 free(data); 1100 } 1101 1102 virtual LPVOID STDMETHODCALLTYPE GetBufferPointer() 1103 { 1104 return data; 1105 } 1106 1107 virtual SIZE_T STDMETHODCALLTYPE GetBufferSize() 1108 { 1109 return size; 1110 } 1111}; 1112 1113#endif /* D3D1XSTUTIL_H_ */ 1114