d3d1xstutil.h revision 77574bf0f46716490be741d8095a8d184eff6076
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/************************************************************************** 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Copyright 2010 Luca Barbieri 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Permission is hereby granted, free of charge, to any person obtaining 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * a copy of this software and associated documentation files (the 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * "Software"), to deal in the Software without restriction, including 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * without limitation the rights to use, copy, modify, merge, publish, 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * distribute, sublicense, and/or sell copies of the Software, and to 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * permit persons to whom the Software is furnished to do so, subject to 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the following conditions: 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The above copyright notice and this permission notice (including the 147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * next paragraph) shall be included in all copies or substantial 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * portions of the Software. 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch * 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) **************************************************************************/ 267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#ifndef D3D1XSTUTIL_H_ 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define D3D1XSTUTIL_H_ 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef _MSC_VER 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <unordered_map> 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <unordered_set> 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <tr1/unordered_map> 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <tr1/unordered_set> 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace std 377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch{ 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) using namespace tr1; 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <map> 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <utility> 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#define WIN32_LEAN_AND_MEAN 457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include <objbase.h> 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "galliumdxgi.h" 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <d3dcommon.h> 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern "C" 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "util/u_atomic.h" 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "pipe/p_format.h" 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "os/os_thread.h" 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <assert.h> 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef min 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef min 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef max 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef max 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define D3D_PRIMITIVE_TOPOLOGY_COUNT 65 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern unsigned d3d_to_pipe_prim[D3D_PRIMITIVE_TOPOLOGY_COUNT]; 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define D3D_PRIMITIVE_COUNT 40 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern unsigned d3d_to_pipe_prim_type[D3D_PRIMITIVE_COUNT]; 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* NOTE: this _depends_ on the vtable layout of the C++ compiler to be 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * binary compatible with Windows. 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Furthermore some absurd vtable layout likely won't work at all, since 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * we perform some casts which are probably not safe by the C++ standard. 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * In particular, the GNU/Linux/Itanium/clang ABI and Microsoft ABIs will work, 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * but others may not. 782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * If in doubt, just switch to the latest version of a widely used C++ compiler. 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * DESIGN of the Gallium COM implementation 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * This state tracker uses somewhat unusual C++ coding patterns, 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * to implement the COM interfaces required by Direct3D. 842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * While it may seem complicated, the effect is that the result 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * generally behaves as intuitively as possible: in particular pointer 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * casts very rarely change the pointer value (only for secondary 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * DXGI/Gallium interfaces) 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Implementing COM is on first sight very easy: after all, it just 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * consists of a reference count, and a dynamic_cast<> equivalent. 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * However, implementing objects with multiple interfaces is actually 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * quite tricky. 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The issue is that the interface pointers can't be equal, since this 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * would place incompatible constraints on the vtable layout and thus 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * multiple inheritance (and the subobjects the C++ compiler creates 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * with it) must be correctly used. 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Furthermore, we must have a single reference count, which means 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * that a naive implementation won't work, and it's necessary to either 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * use virtual inheritance, or the "mixin inheritance" model we use. 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * This solution aims to achieve the following object layout: 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 0: pointer to vtable for primary interface 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 1: reference count 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * ... main class 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * ... vtable pointers for secondary interfaces 1097dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * ... implementation of subclasses assuming secondary interfaces 1107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * 1117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * This allows us to cast pointers by just reinterpreting the value in 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * almost all cases. 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * To achieve this, *all* non-leaf classes must have their parent 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * or the base COM interface as a template parameter, since derived 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * classes may need to change that to support an interface derived 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * from the one implemented by the superclass. 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Note however, that you can cast without regard to the template 1207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * parameter, because only the vtable layout depends on it, since 1217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * interfaces have no data members. 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * For this to work, DON'T USE VIRTUAL FUNCTIONS except to implement 1247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * interfaces, since the vtable layouts would otherwise be mismatched. 1257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * An exception are virtual functions called only from other virtual functions, 1267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * which is currently only used for the virtual destructor. 1277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * 1287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * The base class is GalliumComObject<IFoo>, which implements the 1297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * IUnknown interface, and inherits IFoo. 1307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * 1317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * To support multiple inheritance, we insert GalliumMultiComObject, 1327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * which redirects the secondary interfaces to the GalliumComObject 1337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * superclass. 1347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * 1357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * Gallium(Multi)PrivateDataComObject is like ComObject but also 1367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * implements the Get/SetPrivateData functions present on several 1377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * D3D/DXGI interfaces. 1387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * 1397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * Example class hierarchy: 1407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * 1417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * IUnknown 1427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * (pure interface) 1437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * | 1447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * V 1457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * IAnimal 1467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * (pure interface) 1477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * | 1487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * V 1497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * IDuck 1507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * (pure interface) 1517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * | 1527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * V 1537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * GalliumComObject<IDuck> 1547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * (non-instantiable, only implements IUnknown) 1557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * | 1567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * V 1577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * GalliumAnimal<IDuck> 1587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * (non-instantiable, only implements IAnimal) 1597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * | 1607dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * V 161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * GalliumDuck 162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * (concrete) 1637dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * | 1647dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * V 165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * GalliumMultiComObject<GalliumDuck, IWheeledVehicle> <- IWheeledVehicle <- IVehicle <- IUnknown (second version) 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * (non-instantiable, only implements IDuck and the IUnknown of IWheeledVehicle) 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * | 1687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * V 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * GalliumDuckOnWheels 1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * (concrete) 1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * 1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * This will produce the desired layout. 1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Note that GalliumAnimal<IFoo>* is safely castable to GalliumAnimal<IBar>* 174c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * by reinterpreting, as long as non-interface virtual functions are not used, 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * and that you only call interface functions for the superinterface of IBar 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * that the object actually implements. 1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Instead, if GalliumDuck where to inherit both from GalliumAnimal 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * and IDuck, then (IDuck*)gallium_duck and (IAnimal*)gallium_duck would 1807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * have different pointer values, which the "base class as template parameter" 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * trick avoids. 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The price we pay is that you MUST NOT have virtual functions other than those 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * implementing interfaces (except for leaf classes) since the position of these 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * would depend on the base interface. 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * As mentioned above, virtual functions only called from interface functions 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * are an exception, currently used only for the virtual destructor. 1887dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * If you want virtual functions anyway , put them in a separate interface class, 1897dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * multiply inherit from that and cast the pointer to that interface. 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * You CAN however have virtual functions on any class which does not specify 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * his base as a template parameter, or where you don't need to change the 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * template base interface parameter by casting. 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * --- The magic QueryInterface "delete this" trick --- 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * When the reference count drops to 0, we must delete the class. 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The problem is, that we must call the right virtual destructor (i.e. on the right class). 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * However, we would like to be able to call release() and nonatomic_release() 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * non-virtually for performance (also, the latter cannot be called virtually at all, since 2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * IUnknown does not offer it). 2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * 2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * The naive solution would be to just add a virtual destructor and rely on it. 2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * However, this doesn't work due to the fact that as described above we perform casets 2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * with are unsafe regarding vtable layout. 2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * In particular, consider the case where we try to delete GalliumComObject<ID3D11Texture2D> 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * with a pointer to GalliumComObject<ID3D11Resource>. 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Since we think that this is a GalliumComObject<ID3D11Resource>, we'll look for the 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * destructor in the vtable slot immediately after the ID3D11Resource vtable, but this is 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * actually an ID3D11Texture2D function implemented by the object! 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * So, we must put the destructor somewhere else. 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * We could add it as a data member, but it would be awkward and it would bloat the 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * class. 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Thus, we use this trick: we reuse the vtable slot for QueryInterface, which is always at the 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * same position. 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * To do so, we define a special value for the first pointer argument, that triggers a 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * "delete this". 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * In addition to that, we add a virtual destructor to GalliumComObject. 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * That virtual destructor will be called by QueryInterface, and since that is a virtual 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * function, it will know the correct place for the virtual destructor. 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 223c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * QueryInterface is already slow due to the need to compare several GUIDs, so the 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * additional pointer test should not be significant. 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Of course the ideal solution would be telling the C++ compiler to put the 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * destructor it in a negative vtable slot, but unfortunately GCC doesn't support that 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * yet, and this method is almost as good as that. 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<typename T> 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct com_traits; 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define COM_INTERFACE(intf, base) \ 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<> \ 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct com_traits<intf> \ 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ \ 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static REFIID iid() {return IID_##intf;} \ 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static inline bool is_self_or_ancestor(REFIID riid) {return riid == iid() || com_traits<base>::is_self_or_ancestor(riid);} \ 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<> 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct com_traits<IUnknown> 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static REFIID iid() {return IID_IUnknown;} 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static inline bool is_self_or_ancestor(REFIID riid) {return riid == iid();} 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef _MSC_VER 2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define __uuidof(T) (com_traits<T>::iid()) 251c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif 252c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 253c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)struct refcnt_t 254c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles){ 255c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) uint32_t refcnt; 256c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 257c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) refcnt_t(unsigned v = 1) 258c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) : refcnt(v) 259c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) {} 260c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 261c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) unsigned add_ref() 262c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) { 263c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) p_atomic_inc((int32_t*)&refcnt); 264c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return refcnt; 265c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 266c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 267c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) unsigned release() 268c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) { 269c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if(p_atomic_dec_zero((int32_t*)&refcnt)) 270c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return 0; 271c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return refcnt; 2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void nonatomic_add_ref() 2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) { 2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) p_atomic_inc((int32_t*)&refcnt); 2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) unsigned nonatomic_release() 2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) { 2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if(p_atomic_dec_zero((int32_t*)&refcnt)) 2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return 0; 2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) else 2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return 1; 2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8) 2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/* this should be safe because atomic ops are full memory barriers, and thus a sequence that does: 2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * ++one_refcnt; 2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * --other_refcnt; 2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * should never be reorderable (as seen from another CPU) to: 2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * --other_refcnt 2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * ++one_refcnt 2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * 2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * since one of the ops is atomic. 2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * If this weren't the case, a CPU could incorrectly destroy an object manipulated in that way by another one. 2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */ 2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)struct dual_refcnt_t 3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){ 3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) union 3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) { 3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint64_t refcnt; 3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) struct 3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) { 3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint32_t atomic_refcnt; 3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint32_t nonatomic_refcnt; 308eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch }; 309eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch }; 3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) dual_refcnt_t(unsigned v = 1) 312eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch { 3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) atomic_refcnt = v; 3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) nonatomic_refcnt = 0; 3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool is_zero() 3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) { 319eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if(sizeof(void*) == 8) 3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return *(volatile uint64_t*)&refcnt == 0ULL; 3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) else 3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) { 323c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) uint64_t v; 324c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) do 3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) { 3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) v = refcnt; 3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) while(!__sync_bool_compare_and_swap(&refcnt, v, v)); 3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return v == 0ULL; 3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) unsigned add_ref() 3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) { 3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) //printf("%p add_ref at %u %u\n", this, atomic_refcnt, nonatomic_refcnt); 3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) p_atomic_inc((int32_t*)&atomic_refcnt); 3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return atomic_refcnt + nonatomic_refcnt; 3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) unsigned release() 3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) { 3422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) //printf("%p release at %u %u\n", this, atomic_refcnt, nonatomic_refcnt); 3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if(p_atomic_dec_zero((int32_t*)&atomic_refcnt) && !nonatomic_refcnt && is_zero()) 3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return 0; 3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) unsigned v = atomic_refcnt + nonatomic_refcnt; 3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return v ? v : 1; 3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void nonatomic_add_ref() 3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) { 3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) //printf("%p nonatomic_add_ref at %u %u\n", this, atomic_refcnt, nonatomic_refcnt); 3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ++nonatomic_refcnt; 3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) unsigned nonatomic_release() 3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) { 3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) //printf("%p nonatomic_release at %u %u\n", this, atomic_refcnt, nonatomic_refcnt); 358eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if(!--nonatomic_refcnt) 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) __sync_synchronize(); 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 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 372typedef refcnt_t dual_refcnt_t; 373#endif 374 375#define IID_MAGIC_DELETE_THIS (*(const IID*)((intptr_t)-(int)(sizeof(IID) - 1))) 376 377template<typename Base = IUnknown, typename RefCnt = refcnt_t> 378struct 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 465template<typename BaseClass, typename SecondaryInterface> 466struct 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 513template<typename T, typename Traits> 514struct 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 599struct simple_ptr_traits 600{ 601 static void add_ref(void* p) {} 602 static void release(void* p) {} 603}; 604 605struct 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 620template<typename T> 621struct 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 639template<typename T, typename TTraits, typename U, typename UTraits> 640bool operator ==(const refcnt_ptr<T, TTraits>& a, const refcnt_ptr<U, UTraits>& b) 641{ 642 return a.p == b.p; 643} 644 645template<typename T, typename TTraits, typename U> 646bool operator ==(const refcnt_ptr<T, TTraits>& a, U* b) 647{ 648 return a.p == b; 649} 650 651template<typename T, typename TTraits, typename U> 652bool operator ==(U* b, const refcnt_ptr<T, TTraits>& a) 653{ 654 return a.p == b; 655} 656 657template<typename T, typename TTraits, typename U, typename UTraits> 658bool operator !=(const refcnt_ptr<T, TTraits>& a, const refcnt_ptr<U, UTraits>& b) 659{ 660 return a.p != b.p; 661} 662 663template<typename T, typename TTraits, typename U> 664bool operator !=(const refcnt_ptr<T, TTraits>& a, U* b) 665{ 666 return a.p != b; 667} 668 669template<typename T, typename TTraits, typename U> 670bool operator !=(U* b, const refcnt_ptr<T, TTraits>& a) 671{ 672 return a.p != b; 673} 674 675template<bool threadsafe> 676struct maybe_mutex_t; 677 678template<> 679struct 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 699template<> 700struct maybe_mutex_t<false> 701{ 702 void lock() 703 { 704 } 705 706 void unlock() 707 { 708 } 709}; 710 711typedef maybe_mutex_t<true> mutex_t; 712 713template<typename T> 714struct 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 729struct 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 742static inline bool operator ==(const c_string& a, const c_string& b) 743{ 744 return !strcmp(a.p, b.p); 745} 746 747static inline bool operator !=(const c_string& a, const c_string& b) 748{ 749 return strcmp(a.p, b.p); 750} 751 752static 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 771template<typename T> 772static 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 778namespace 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 825template<typename Base, typename RefCnt = refcnt_t> 826struct 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 957template<typename BaseClass, typename SecondaryInterface> 958struct 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 986extern pipe_format dxgi_to_pipe_format[DXGI_FORMAT_COUNT]; 987extern DXGI_FORMAT pipe_to_dxgi_format[PIPE_FORMAT_COUNT]; 988 989void init_pipe_to_dxgi_format(); 990 991COM_INTERFACE(IGalliumDevice, IUnknown); 992COM_INTERFACE(IGalliumAdapter, IUnknown); 993COM_INTERFACE(IGalliumResource, IUnknown); 994 995// used to make QueryInterface know the IIDs of the interface and its ancestors 996COM_INTERFACE(IDXGIObject, IUnknown) 997COM_INTERFACE(IDXGIDeviceSubObject, IDXGIObject) 998COM_INTERFACE(IDXGISurface, IDXGIDeviceSubObject) 999COM_INTERFACE(IDXGIOutput, IDXGIObject) 1000COM_INTERFACE(IDXGIAdapter, IDXGIObject) 1001COM_INTERFACE(IDXGISwapChain, IDXGIDeviceSubObject) 1002COM_INTERFACE(IDXGIFactory, IDXGIObject) 1003COM_INTERFACE(IDXGIDevice, IDXGIObject) 1004COM_INTERFACE(IDXGIResource, IDXGIDeviceSubObject) 1005COM_INTERFACE(IDXGISurface1, IDXGISurface) 1006COM_INTERFACE(IDXGIDevice1, IDXGIDevice) 1007COM_INTERFACE(IDXGIAdapter1, IDXGIAdapter) 1008COM_INTERFACE(IDXGIFactory1, IDXGIFactory) 1009 1010template<typename Base> 1011struct 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 1076COM_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 */ 1084class GalliumD3DBlob : public GalliumComObject<ID3DBlob> 1085{ 1086 void* data; 1087 size_t size; 1088 1089public: 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