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