192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri/************************************************************************** 292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * 392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * Copyright 2010 Luca Barbieri 492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * 592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * Permission is hereby granted, free of charge, to any person obtaining 692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * a copy of this software and associated documentation files (the 792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * "Software"), to deal in the Software without restriction, including 892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * without limitation the rights to use, copy, modify, merge, publish, 992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * distribute, sublicense, and/or sell copies of the Software, and to 1092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * permit persons to whom the Software is furnished to do so, subject to 1192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * the following conditions: 1292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * 1392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * The above copyright notice and this permission notice (including the 1492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * next paragraph) shall be included in all copies or substantial 1592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * portions of the Software. 1692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * 1792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 1892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 1992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 2092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE 2192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 2292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 2392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 2492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * 2592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri **************************************************************************/ 2692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 2792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri#ifndef D3D1XSTUTIL_H_ 2892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri#define D3D1XSTUTIL_H_ 2992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 3092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri#ifdef _MSC_VER 3192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri#include <unordered_map> 3292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri#include <unordered_set> 3392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri#else 3492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri#include <tr1/unordered_map> 3592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri#include <tr1/unordered_set> 3692617aeac109481258f0c3863d09c1b8903d438bLuca Barbierinamespace std 3792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri{ 3892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri using namespace tr1; 3992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri} 4092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri#endif 4192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri#include <map> 4292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri#include <utility> 4392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 4492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri#define WIN32_LEAN_AND_MEAN 454f8e38dab88378b0b5f822893dae5b791e53fb46Luca Barbieri#include <objbase.h> 464f8e38dab88378b0b5f822893dae5b791e53fb46Luca Barbieri 4792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri#include "galliumdxgi.h" 4870fed0b0ec8a3ec4f6b9b47f1fe98cc54c6037f0Luca Barbieri#include <d3dcommon.h> 4992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 5092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieriextern "C" 5192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri{ 5292bc1111f3c5dd3616bd591129aebd3f4307e5b4Kai Wasserbäch#include "util/u_atomic.h" 5392bc1111f3c5dd3616bd591129aebd3f4307e5b4Kai Wasserbäch#include "pipe/p_format.h" 5492bc1111f3c5dd3616bd591129aebd3f4307e5b4Kai Wasserbäch#include "os/os_thread.h" 5592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri} 5692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 5792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri#include <assert.h> 5892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri#ifdef min 5992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri#undef min 6092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri#endif 6192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri#ifdef max 6292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri#undef max 6392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri#endif 6492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 654babdc78448f92b8d027a66cd506351a16aef4ecLuca Barbieri#define D3D_PRIMITIVE_TOPOLOGY_COUNT 65 664babdc78448f92b8d027a66cd506351a16aef4ecLuca Barbieriextern unsigned d3d_to_pipe_prim[D3D_PRIMITIVE_TOPOLOGY_COUNT]; 674babdc78448f92b8d027a66cd506351a16aef4ecLuca Barbieri 684babdc78448f92b8d027a66cd506351a16aef4ecLuca Barbieri#define D3D_PRIMITIVE_COUNT 40 694babdc78448f92b8d027a66cd506351a16aef4ecLuca Barbieriextern unsigned d3d_to_pipe_prim_type[D3D_PRIMITIVE_COUNT]; 704babdc78448f92b8d027a66cd506351a16aef4ecLuca Barbieri 7192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri/* NOTE: this _depends_ on the vtable layout of the C++ compiler to be 7292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * binary compatible with Windows. 7392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * Furthermore some absurd vtable layout likely won't work at all, since 7492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * we perform some casts which are probably not safe by the C++ standard. 7592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * 7692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * In particular, the GNU/Linux/Itanium/clang ABI and Microsoft ABIs will work, 7792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * but others may not. 7892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * If in doubt, just switch to the latest version of a widely used C++ compiler. 7992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * 8092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * DESIGN of the Gallium COM implementation 8192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * 8292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * This state tracker uses somewhat unusual C++ coding patterns, 8392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * to implement the COM interfaces required by Direct3D. 8492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * 8592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * While it may seem complicated, the effect is that the result 8692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * generally behaves as intuitively as possible: in particular pointer 8792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * casts very rarely change the pointer value (only for secondary 8892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * DXGI/Gallium interfaces) 8992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * 9092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * Implementing COM is on first sight very easy: after all, it just 9192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * consists of a reference count, and a dynamic_cast<> equivalent. 9292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * 9392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * However, implementing objects with multiple interfaces is actually 9492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * quite tricky. 9592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * The issue is that the interface pointers can't be equal, since this 9692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * would place incompatible constraints on the vtable layout and thus 9792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * multiple inheritance (and the subobjects the C++ compiler creates 9892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * with it) must be correctly used. 9992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * 10092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * Furthermore, we must have a single reference count, which means 10192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * that a naive implementation won't work, and it's necessary to either 10292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * use virtual inheritance, or the "mixin inheritance" model we use. 10392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * 10492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * This solution aims to achieve the following object layout: 10592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * 0: pointer to vtable for primary interface 10692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * 1: reference count 10792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * ... main class 10892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * ... vtable pointers for secondary interfaces 10992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * ... implementation of subclasses assuming secondary interfaces 11092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * 11192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * This allows us to cast pointers by just reinterpreting the value in 11292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * almost all cases. 11392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * 11492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * To achieve this, *all* non-leaf classes must have their parent 11592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * or the base COM interface as a template parameter, since derived 11692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * classes may need to change that to support an interface derived 11792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * from the one implemented by the superclass. 11892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * 11992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * Note however, that you can cast without regard to the template 12092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * parameter, because only the vtable layout depends on it, since 12192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * interfaces have no data members. 12292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * 12392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * For this to work, DON'T USE VIRTUAL FUNCTIONS except to implement 12492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * interfaces, since the vtable layouts would otherwise be mismatched. 12592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * An exception are virtual functions called only from other virtual functions, 12692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * which is currently only used for the virtual destructor. 12792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * 12892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * The base class is GalliumComObject<IFoo>, which implements the 12992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * IUnknown interface, and inherits IFoo. 13092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * 13192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * To support multiple inheritance, we insert GalliumMultiComObject, 13292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * which redirects the secondary interfaces to the GalliumComObject 13392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * superclass. 13492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * 13592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * Gallium(Multi)PrivateDataComObject is like ComObject but also 13692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * implements the Get/SetPrivateData functions present on several 13792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * D3D/DXGI interfaces. 13892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * 13992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * Example class hierarchy: 14092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * 14192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * IUnknown 14292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * (pure interface) 14392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * | 14492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * V 14592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * IAnimal 14692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * (pure interface) 14792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * | 14892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * V 14992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * IDuck 15092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * (pure interface) 15192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * | 15292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * V 15392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * GalliumComObject<IDuck> 15492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * (non-instantiable, only implements IUnknown) 15592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * | 15692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * V 15792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * GalliumAnimal<IDuck> 15892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * (non-instantiable, only implements IAnimal) 15992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * | 16092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * V 16192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * GalliumDuck 16292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * (concrete) 16392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * | 16492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * V 16592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * GalliumMultiComObject<GalliumDuck, IWheeledVehicle> <- IWheeledVehicle <- IVehicle <- IUnknown (second version) 16692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * (non-instantiable, only implements IDuck and the IUnknown of IWheeledVehicle) 16792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * | 16892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * V 16992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * GalliumDuckOnWheels 17092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * (concrete) 17192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * 17292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * This will produce the desired layout. 17392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * Note that GalliumAnimal<IFoo>* is safely castable to GalliumAnimal<IBar>* 17492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * by reinterpreting, as long as non-interface virtual functions are not used, 17592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * and that you only call interface functions for the superinterface of IBar 17692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * that the object actually implements. 17792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * 17892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * Instead, if GalliumDuck where to inherit both from GalliumAnimal 17992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * and IDuck, then (IDuck*)gallium_duck and (IAnimal*)gallium_duck would 18092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * have different pointer values, which the "base class as template parameter" 18192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * trick avoids. 18292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * 18392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * The price we pay is that you MUST NOT have virtual functions other than those 18492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * implementing interfaces (except for leaf classes) since the position of these 18592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * would depend on the base interface. 18692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * As mentioned above, virtual functions only called from interface functions 18792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * are an exception, currently used only for the virtual destructor. 18892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * If you want virtual functions anyway , put them in a separate interface class, 18992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * multiply inherit from that and cast the pointer to that interface. 19092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * 19192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * You CAN however have virtual functions on any class which does not specify 19292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * his base as a template parameter, or where you don't need to change the 19392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * template base interface parameter by casting. 19492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * 19592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * --- The magic QueryInterface "delete this" trick --- 19692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * 19792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * When the reference count drops to 0, we must delete the class. 19892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * The problem is, that we must call the right virtual destructor (i.e. on the right class). 19992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * However, we would like to be able to call release() and nonatomic_release() 20092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * non-virtually for performance (also, the latter cannot be called virtually at all, since 20192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * IUnknown does not offer it). 20292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * 20392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * The naive solution would be to just add a virtual destructor and rely on it. 20492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * However, this doesn't work due to the fact that as described above we perform casets 20592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * with are unsafe regarding vtable layout. 20692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * In particular, consider the case where we try to delete GalliumComObject<ID3D11Texture2D> 20792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * with a pointer to GalliumComObject<ID3D11Resource>. 2086c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri * Since we think that this is a GalliumComObject<ID3D11Resource>, we'll look for the 20992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * destructor in the vtable slot immediately after the ID3D11Resource vtable, but this is 21092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * actually an ID3D11Texture2D function implemented by the object! 21192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * 21292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * So, we must put the destructor somewhere else. 21392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * We could add it as a data member, but it would be awkward and it would bloat the 21492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * class. 21592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * Thus, we use this trick: we reuse the vtable slot for QueryInterface, which is always at the 21692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * same position. 21792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * To do so, we define a special value for the first pointer argument, that triggers a 21892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * "delete this". 21992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * In addition to that, we add a virtual destructor to GalliumComObject. 22092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * That virtual destructor will be called by QueryInterface, and since that is a virtual 22192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * function, it will know the correct place for the virtual destructor. 22292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * 22392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * QueryInterface is already slow due to the need to compare several GUIDs, so the 22492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * additional pointer test should not be significant. 22592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * 22692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * Of course the ideal solution would be telling the C++ compiler to put the 22792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * destructor it in a negative vtable slot, but unfortunately GCC doesn't support that 22892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * yet, and this method is almost as good as that. 22992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri */ 23092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 23192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieritemplate<typename T> 23292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieristruct com_traits; 23392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 23492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri#define COM_INTERFACE(intf, base) \ 23592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieritemplate<> \ 23692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieristruct com_traits<intf> \ 23792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri{ \ 23892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri static REFIID iid() {return IID_##intf;} \ 23992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri static inline bool is_self_or_ancestor(REFIID riid) {return riid == iid() || com_traits<base>::is_self_or_ancestor(riid);} \ 24092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri}; 24192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 24292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieritemplate<> 24392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieristruct com_traits<IUnknown> 24492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri{ 24592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri static REFIID iid() {return IID_IUnknown;} 24692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri static inline bool is_self_or_ancestor(REFIID riid) {return riid == iid();} 24792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri}; 24892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 24992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri#ifndef _MSC_VER 25092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri#define __uuidof(T) (com_traits<T>::iid()) 25192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri#endif 25292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 25392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieristruct refcnt_t 25492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri{ 25592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri uint32_t refcnt; 25692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 25792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri refcnt_t(unsigned v = 1) 25892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri : refcnt(v) 25992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri {} 26092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 26192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri unsigned add_ref() 26292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri { 26392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri p_atomic_inc((int32_t*)&refcnt); 26492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri return refcnt; 26592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri } 26692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 26792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri unsigned release() 26892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri { 26992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri if(p_atomic_dec_zero((int32_t*)&refcnt)) 27092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri return 0; 27192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri return refcnt; 27292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri } 27392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 27492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri void nonatomic_add_ref() 27592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri { 27692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri p_atomic_inc((int32_t*)&refcnt); 27792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri } 27892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 27992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri unsigned nonatomic_release() 28092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri { 28192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri if(p_atomic_dec_zero((int32_t*)&refcnt)) 28292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri return 0; 28392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri else 28492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri return 1; 28592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri } 28692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri}; 28792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 28892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri#if defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8) 28992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri/* this should be safe because atomic ops are full memory barriers, and thus a sequence that does: 29092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * ++one_refcnt; 29192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * --other_refcnt; 29292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * should never be reorderable (as seen from another CPU) to: 29392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * --other_refcnt 29492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * ++one_refcnt 29592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * 29692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * since one of the ops is atomic. 29792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * If this weren't the case, a CPU could incorrectly destroy an object manipulated in that way by another one. 29892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri */ 29992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieristruct dual_refcnt_t 30092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri{ 30192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri union 30292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri { 30392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri uint64_t refcnt; 30492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri struct 30592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri { 30692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri uint32_t atomic_refcnt; 30792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri uint32_t nonatomic_refcnt; 30892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri }; 30992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri }; 31092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 31192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri dual_refcnt_t(unsigned v = 1) 31292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri { 31392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri atomic_refcnt = v; 31492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri nonatomic_refcnt = 0; 31592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri } 31692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 31792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri bool is_zero() 31892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri { 31992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri if(sizeof(void*) == 8) 32092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri return *(volatile uint64_t*)&refcnt == 0ULL; 32192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri else 32292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri { 32392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri uint64_t v; 32492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri do 32592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri { 32692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri v = refcnt; 32792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri } 32892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri while(!__sync_bool_compare_and_swap(&refcnt, v, v)); 32992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri return v == 0ULL; 33092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri } 33192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri } 33292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 33392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri unsigned add_ref() 33492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri { 33592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri //printf("%p add_ref at %u %u\n", this, atomic_refcnt, nonatomic_refcnt); 33692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri p_atomic_inc((int32_t*)&atomic_refcnt); 33792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri return atomic_refcnt + nonatomic_refcnt; 33892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri } 33992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 34092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri unsigned release() 34192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri { 34292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri //printf("%p release at %u %u\n", this, atomic_refcnt, nonatomic_refcnt); 34392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri if(p_atomic_dec_zero((int32_t*)&atomic_refcnt) && !nonatomic_refcnt && is_zero()) 34492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri return 0; 34592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri unsigned v = atomic_refcnt + nonatomic_refcnt; 34692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri return v ? v : 1; 34792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri } 34892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 34992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri void nonatomic_add_ref() 35092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri { 35192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri //printf("%p nonatomic_add_ref at %u %u\n", this, atomic_refcnt, nonatomic_refcnt); 35292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri ++nonatomic_refcnt; 35392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri } 35492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 35592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri unsigned nonatomic_release() 35692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri { 35792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri //printf("%p nonatomic_release at %u %u\n", this, atomic_refcnt, nonatomic_refcnt); 358d092c0c60ddcb56f8c5d2786ae3b61f5339b84e1Luca Barbieri if(!--nonatomic_refcnt) 359d092c0c60ddcb56f8c5d2786ae3b61f5339b84e1Luca Barbieri { 360d092c0c60ddcb56f8c5d2786ae3b61f5339b84e1Luca Barbieri __sync_synchronize(); 361d092c0c60ddcb56f8c5d2786ae3b61f5339b84e1Luca Barbieri if(!atomic_refcnt && is_zero()) 362d092c0c60ddcb56f8c5d2786ae3b61f5339b84e1Luca Barbieri return 0; 363d092c0c60ddcb56f8c5d2786ae3b61f5339b84e1Luca Barbieri } 36492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri return 1; 36592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri } 36692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri}; 36792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri#else 36892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri// this will result in atomic operations being used while they could have been avoided 36992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri#ifdef __i386__ 37092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri#warning Compile for 586+ using GCC to improve the performance of the Direct3D 10/11 state tracker 37192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri#endif 37292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieritypedef refcnt_t dual_refcnt_t; 37392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri#endif 37492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 37592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri#define IID_MAGIC_DELETE_THIS (*(const IID*)((intptr_t)-(int)(sizeof(IID) - 1))) 37692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 37792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieritemplate<typename Base = IUnknown, typename RefCnt = refcnt_t> 37892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieristruct GalliumComObject : public Base 37992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri{ 38092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri RefCnt refcnt; 38192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 38292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri GalliumComObject() 38392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri {} 38492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 38592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri /* DO NOT CALL this from externally called non-virtual functions in derived classes, since 38692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * the vtable position depends on the COM interface being implemented 38792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri */ 38892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri virtual ~GalliumComObject() 38992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri {} 39092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 39192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri inline ULONG add_ref() 39292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri { 39392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri return refcnt.add_ref(); 39492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri } 39592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 39692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri inline ULONG release() 39792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri { 39892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri ULONG v = refcnt.release(); 39992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri if(!v) 40092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri { 40192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri /* this will call execute "delete this", using the correct vtable slot for the destructor */ 40292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri /* see the initial comment for an explaination of this magic trick */ 40392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri this->QueryInterface(IID_MAGIC_DELETE_THIS, 0); 40492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri return 0; 40592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri } 40692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri return v; 40792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri } 40892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 40992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri inline void nonatomic_add_ref() 41092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri { 41192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri refcnt.nonatomic_add_ref(); 41292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri } 41392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 41492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri inline void nonatomic_release() 41592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri { 41692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri if(!refcnt.nonatomic_release()) 41792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri { 41892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri /* this will execute "delete this", using the correct vtable slot for the destructor */ 41992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri /* see the initial comment for an explaination of this magic trick */ 42092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri this->QueryInterface(IID_MAGIC_DELETE_THIS, 0); 42192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri } 42292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri } 42392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 42492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri inline HRESULT query_interface(REFIID riid, void **ppvObject) 42592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri { 42692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri if(com_traits<Base>::is_self_or_ancestor(riid)) 42792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri { 42892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri // must be the virtual AddRef, since it is overridden by some classes 42992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri this->AddRef(); 43092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri *ppvObject = this; 43192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri return S_OK; 43292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri } 43392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri else 43492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri return E_NOINTERFACE; 43592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri } 43692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 43792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri virtual ULONG STDMETHODCALLTYPE AddRef() 43892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri { 43992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri return add_ref(); 44092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri } 44192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 44292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri virtual ULONG STDMETHODCALLTYPE Release() 44392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri { 44492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri return release(); 44592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri } 44692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 44792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri virtual HRESULT STDMETHODCALLTYPE QueryInterface( 44892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri REFIID riid, 4496c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri void **ppvObject) 45092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri { 45192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri /* see the initial comment for an explaination of this magic trick */ 45292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri if(&riid == &IID_MAGIC_DELETE_THIS) 45392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri { 45492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri delete this; 45592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri return 0; 45692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri } 45792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri if(!this) 45892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri return E_INVALIDARG; 45992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri if(!ppvObject) 46092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri return E_POINTER; 46192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri return query_interface(riid, ppvObject); 46292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri } 46392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri}; 46492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 46592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieritemplate<typename BaseClass, typename SecondaryInterface> 46692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieristruct GalliumMultiComObject : public BaseClass, SecondaryInterface 46792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri{ 46892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri // we could avoid this duplication, but the increased complexity to do so isn't worth it 46992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri virtual ULONG STDMETHODCALLTYPE AddRef() 47092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri { 47192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri return BaseClass::add_ref(); 47292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri } 47392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 47492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri virtual ULONG STDMETHODCALLTYPE Release() 47592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri { 47692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri return BaseClass::release(); 47792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri } 47892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 47992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri inline HRESULT query_interface(REFIID riid, void **ppvObject) 48092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri { 48192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri HRESULT hr = BaseClass::query_interface(riid, ppvObject); 48292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri if(SUCCEEDED(hr)) 48392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri return hr; 48492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri if(com_traits<SecondaryInterface>::is_self_or_ancestor(riid)) 48592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri { 48692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri // must be the virtual AddRef, since it is overridden by some classes 48792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri this->AddRef(); 48892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri *ppvObject = (SecondaryInterface*)this; 48992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri return S_OK; 49092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri } 49192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri else 49292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri return E_NOINTERFACE; 49392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri } 49492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 4956c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri virtual HRESULT STDMETHODCALLTYPE QueryInterface( 49692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri REFIID riid, 4976c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri void **ppvObject) 49892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri { 49992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri /* see the initial comment for an explaination of this magic trick */ 50092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri if(&riid == &IID_MAGIC_DELETE_THIS) 50192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri { 50292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri delete this; 50392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri return 0; 50492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri } 50592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri if(!this) 50692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri return E_INVALIDARG; 50792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri if(!ppvObject) 50892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri return E_POINTER; 50992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri return query_interface(riid, ppvObject); 51092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri } 51192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri}; 51292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 51392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieritemplate<typename T, typename Traits> 51492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieristruct refcnt_ptr 51592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri{ 51692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri T* p; 51792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 51892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri refcnt_ptr() 51992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri : p(0) 52092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri {} 52192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 52292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri void add_ref() {Traits::add_ref(p);} 52392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri void release() {Traits::release(p);} 52492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 52592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri template<typename U, typename UTraits> 52692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri refcnt_ptr(const refcnt_ptr<U, UTraits>& c) 52792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri { 52892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri *this = static_cast<U*>(c.ref()); 52992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri } 53092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 53192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri ~refcnt_ptr() 53292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri { 53392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri release(); 53492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri } 53592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 53692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri void reset(T* q) 53792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri { 53892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri release(); 53992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri p = q; 54092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri } 54192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 54292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri template<typename U, typename UTraits> 54392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri refcnt_ptr& operator =(const refcnt_ptr<U, UTraits>& q) 54492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri { 54592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri return *this = q.p; 54692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri } 54792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 54892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri template<typename U> 54992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri refcnt_ptr& operator =(U* q) 55092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri { 55192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri release(); 55292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri p = static_cast<T*>(q); 55392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri add_ref(); 55492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri return *this; 55592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri } 55692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 55792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri T* ref() 55892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri { 55992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri add_ref(); 56092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri return p; 56192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri } 56292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 56392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri T* steal() 56492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri { 56592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri T* ret = p; 56692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri p = 0; 56792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri return ret; 56892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri } 56992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 57092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri T* operator ->() 57192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri { 57292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri return p; 57392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri } 57492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 57592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri const T* operator ->() const 57692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri { 57792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri return p; 57892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri } 57992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 58092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri T** operator &() 58192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri { 58292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri assert(!p); 58392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri return &p; 58492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri } 58592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 58692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri bool operator !() const 58792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri { 58892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri return !p; 58992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri } 59092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 59192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri typedef T* refcnt_ptr::*unspecified_bool_type; 59292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 59392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri operator unspecified_bool_type() const 59492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri { 59592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri return p ? &refcnt_ptr::p : 0; 59692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri } 59792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri}; 59892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 59992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieristruct simple_ptr_traits 60092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri{ 60192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri static void add_ref(void* p) {} 60292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri static void release(void* p) {} 60392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri}; 60492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 60592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieristruct com_ptr_traits 60692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri{ 60792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri static void add_ref(void* p) 60892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri { 60992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri if(p) 61092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri ((IUnknown*)p)->AddRef(); 61192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri } 61292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 61392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri static void release(void* p) 61492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri { 61592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri if(p) 61692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri ((IUnknown*)p)->Release(); 61792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri } 61892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri}; 61992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 62092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieritemplate<typename T> 62192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieristruct ComPtr : public refcnt_ptr<T, com_ptr_traits> 62292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri{ 62392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri template<typename U, typename UTraits> 62492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri ComPtr& operator =(const refcnt_ptr<U, UTraits>& q) 62592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri { 62692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri return *this = q.p; 62792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri } 62892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 62992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri template<typename U> 63092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri ComPtr& operator =(U* q) 63192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri { 63292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri this->release(); 63392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri this->p = static_cast<T*>(q); 63492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri this->add_ref(); 63592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri return *this; 63692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri } 63792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri}; 63892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 63992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieritemplate<typename T, typename TTraits, typename U, typename UTraits> 64092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieribool operator ==(const refcnt_ptr<T, TTraits>& a, const refcnt_ptr<U, UTraits>& b) 64192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri{ 64292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri return a.p == b.p; 64392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri} 64492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 64592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieritemplate<typename T, typename TTraits, typename U> 64692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieribool operator ==(const refcnt_ptr<T, TTraits>& a, U* b) 64792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri{ 64892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri return a.p == b; 64992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri} 65092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 65192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieritemplate<typename T, typename TTraits, typename U> 65292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieribool operator ==(U* b, const refcnt_ptr<T, TTraits>& a) 65392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri{ 65492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri return a.p == b; 65592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri} 65692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 65792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieritemplate<typename T, typename TTraits, typename U, typename UTraits> 65892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieribool operator !=(const refcnt_ptr<T, TTraits>& a, const refcnt_ptr<U, UTraits>& b) 65992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri{ 66092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri return a.p != b.p; 66192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri} 66292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 66392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieritemplate<typename T, typename TTraits, typename U> 66492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieribool operator !=(const refcnt_ptr<T, TTraits>& a, U* b) 66592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri{ 66692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri return a.p != b; 66792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri} 66892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 66992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieritemplate<typename T, typename TTraits, typename U> 67092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieribool operator !=(U* b, const refcnt_ptr<T, TTraits>& a) 67192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri{ 67292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri return a.p != b; 67392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri} 67492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 67592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieritemplate<bool threadsafe> 67692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieristruct maybe_mutex_t; 67792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 67892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieritemplate<> 67992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieristruct maybe_mutex_t<true> 68092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri{ 68192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri pipe_mutex mutex; 68292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 68322762012d1ab4060d8274c1007067c80bb8e806cLuca Barbieri maybe_mutex_t() 68422762012d1ab4060d8274c1007067c80bb8e806cLuca Barbieri { 68522762012d1ab4060d8274c1007067c80bb8e806cLuca Barbieri pipe_mutex_init(mutex); 68622762012d1ab4060d8274c1007067c80bb8e806cLuca Barbieri } 68722762012d1ab4060d8274c1007067c80bb8e806cLuca Barbieri 68892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri void lock() 68992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri { 69092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri pipe_mutex_lock(mutex); 69192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri } 69292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 69392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri void unlock() 69492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri { 69592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri pipe_mutex_unlock(mutex); 69692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri } 69792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri}; 69892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 69992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieritemplate<> 70092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieristruct maybe_mutex_t<false> 70192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri{ 70292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri void lock() 70392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri { 70492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri } 70592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 70692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri void unlock() 70792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri { 70892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri } 70992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri}; 71092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 71192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieritypedef maybe_mutex_t<true> mutex_t; 71292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 71392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieritemplate<typename T> 71492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieristruct lock_t 71592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri{ 71692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri T& mutex; 71792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri lock_t(T& mutex) 71892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri : mutex(mutex) 71992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri { 72092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri mutex.lock(); 72192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri } 72292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 72392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri ~lock_t() 72492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri { 72592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri mutex.unlock(); 72692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri } 72792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri}; 72892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 72992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieristruct c_string 73092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri{ 73192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri const char* p; 73292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri c_string(const char* p) 73392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri : p(p) 73492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri {} 73592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 73692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri operator const char*() const 73792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri { 73892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri return p; 73992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri } 74092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri}; 74192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 74292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieristatic inline bool operator ==(const c_string& a, const c_string& b) 74392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri{ 74492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri return !strcmp(a.p, b.p); 74592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri} 74692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 74792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieristatic inline bool operator !=(const c_string& a, const c_string& b) 74892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri{ 74992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri return strcmp(a.p, b.p); 75092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri} 75192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 75282c346673a78e6cc32e7a1451f2b127128246ef3Luca Barbieristatic inline size_t raw_hash(const char* p, size_t size) 75382c346673a78e6cc32e7a1451f2b127128246ef3Luca Barbieri{ 75482c346673a78e6cc32e7a1451f2b127128246ef3Luca Barbieri size_t res; 75582c346673a78e6cc32e7a1451f2b127128246ef3Luca Barbieri if(sizeof(size_t) >= 8) 75682c346673a78e6cc32e7a1451f2b127128246ef3Luca Barbieri res = (size_t)14695981039346656037ULL; 75782c346673a78e6cc32e7a1451f2b127128246ef3Luca Barbieri else 75882c346673a78e6cc32e7a1451f2b127128246ef3Luca Barbieri res = (size_t)2166136261UL; 75982c346673a78e6cc32e7a1451f2b127128246ef3Luca Barbieri const char* end = p + size; 76082c346673a78e6cc32e7a1451f2b127128246ef3Luca Barbieri for(; p != end; ++p) 76182c346673a78e6cc32e7a1451f2b127128246ef3Luca Barbieri { 762cac1565b98c7450ef5c74660e8145e300b3f8d7fLuca Barbieri res ^= (size_t)*p; 76382c346673a78e6cc32e7a1451f2b127128246ef3Luca Barbieri if(sizeof(size_t) >= 8) 76482c346673a78e6cc32e7a1451f2b127128246ef3Luca Barbieri res *= (size_t)1099511628211ULL; 76582c346673a78e6cc32e7a1451f2b127128246ef3Luca Barbieri else 76682c346673a78e6cc32e7a1451f2b127128246ef3Luca Barbieri res *= (size_t)16777619UL; 76782c346673a78e6cc32e7a1451f2b127128246ef3Luca Barbieri } 76882c346673a78e6cc32e7a1451f2b127128246ef3Luca Barbieri return res; 76982c346673a78e6cc32e7a1451f2b127128246ef3Luca Barbieri}; 77082c346673a78e6cc32e7a1451f2b127128246ef3Luca Barbieri 77182c346673a78e6cc32e7a1451f2b127128246ef3Luca Barbieritemplate<typename T> 77282c346673a78e6cc32e7a1451f2b127128246ef3Luca Barbieristatic inline size_t raw_hash(const T& t) 77382c346673a78e6cc32e7a1451f2b127128246ef3Luca Barbieri{ 77482c346673a78e6cc32e7a1451f2b127128246ef3Luca Barbieri return raw_hash((const char*)&t, sizeof(t)); 77582c346673a78e6cc32e7a1451f2b127128246ef3Luca Barbieri} 77682c346673a78e6cc32e7a1451f2b127128246ef3Luca Barbieri 77782c346673a78e6cc32e7a1451f2b127128246ef3Luca Barbieri// TODO: only tested with the gcc libstdc++, might not work elsewhere 77892617aeac109481258f0c3863d09c1b8903d438bLuca Barbierinamespace std 77992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri{ 78082c346673a78e6cc32e7a1451f2b127128246ef3Luca Barbieri#ifndef _MSC_VER 78192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri namespace tr1 78292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri { 78382c346673a78e6cc32e7a1451f2b127128246ef3Luca Barbieri#endif 78492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri template<> 785c02bf8162981c4b6287098bc33e954519d414326Luca Barbieri struct hash<GUID> : public std::unary_function<GUID, size_t> 786c02bf8162981c4b6287098bc33e954519d414326Luca Barbieri { 787c02bf8162981c4b6287098bc33e954519d414326Luca Barbieri inline size_t operator()(GUID __val) const; 788c02bf8162981c4b6287098bc33e954519d414326Luca Barbieri }; 789c02bf8162981c4b6287098bc33e954519d414326Luca Barbieri 79092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri inline size_t hash<GUID>::operator()(GUID __val) const 79192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri { 79282c346673a78e6cc32e7a1451f2b127128246ef3Luca Barbieri return raw_hash(__val); 79392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri } 79492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 79592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri template<> 796c02bf8162981c4b6287098bc33e954519d414326Luca Barbieri struct hash<c_string> : public std::unary_function<c_string, size_t> 797c02bf8162981c4b6287098bc33e954519d414326Luca Barbieri { 798c02bf8162981c4b6287098bc33e954519d414326Luca Barbieri inline size_t operator()(c_string __val) const; 799c02bf8162981c4b6287098bc33e954519d414326Luca Barbieri }; 800c02bf8162981c4b6287098bc33e954519d414326Luca Barbieri 80192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri inline size_t hash<c_string>::operator()(c_string __val) const 80292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri { 80382c346673a78e6cc32e7a1451f2b127128246ef3Luca Barbieri return raw_hash(__val.p, strlen(__val.p)); 80492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri } 80592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 80692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri template<typename T, typename U> 80792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri struct hash<std::pair<T, U> > : public std::unary_function<std::pair<T, U>, size_t> 80892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri { 809c02bf8162981c4b6287098bc33e954519d414326Luca Barbieri inline size_t operator()(std::pair<T, U> __val) const; 81092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri }; 81192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 81292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri template<typename T, typename U> 81392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri inline size_t hash<std::pair<T, U> >::operator()(std::pair<T, U> __val) const 81492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri { 81592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri std::pair<size_t, size_t> p; 81692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri p.first = hash<T>()(__val.first); 81792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri p.second = hash<U>()(__val.second); 81882c346673a78e6cc32e7a1451f2b127128246ef3Luca Barbieri return raw_hash(p); 81992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri } 82082c346673a78e6cc32e7a1451f2b127128246ef3Luca Barbieri#ifndef _MSC_VER 82192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri } 82292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri#endif 82382c346673a78e6cc32e7a1451f2b127128246ef3Luca Barbieri} 82492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 82592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieritemplate<typename Base, typename RefCnt = refcnt_t> 82692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieristruct GalliumPrivateDataComObject : public GalliumComObject<Base, RefCnt> 82792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri{ 82892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri typedef std::unordered_map<GUID, std::pair<void*, unsigned> > private_data_map_t; 82992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri private_data_map_t private_data_map; 83092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri mutex_t private_data_mutex; 83192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 83292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri ~GalliumPrivateDataComObject() 83392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri { 83492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri for(private_data_map_t::iterator i = private_data_map.begin(), e = private_data_map.end(); i != e; ++i) 83592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri { 83692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri if(i->second.second == ~0u) 83792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri ((IUnknown*)i->second.first)->Release(); 83892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri else 83992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri free(i->second.first); 84092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri } 84192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri } 84292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 84392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri HRESULT get_private_data( 8448224256946619fb25278718bbf4703e3b9d60c93Luca Barbieri REFGUID guid, 8458224256946619fb25278718bbf4703e3b9d60c93Luca Barbieri UINT *pDataSize, 8468224256946619fb25278718bbf4703e3b9d60c93Luca Barbieri void *pData) 8476c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri { 84892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri lock_t<mutex_t> lock(private_data_mutex); 8496c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri private_data_map_t::iterator i = private_data_map.find(guid); 8506c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri *pDataSize = 0; 8516c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri if(i == private_data_map.end()) 8526c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri return DXGI_ERROR_NOT_FOUND; 8536c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri if(i->second.second == ~0u) 8546c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri { 8556c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri /* TODO: is GetPrivateData on interface data supposed to do this? */ 8566c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri if(*pDataSize < sizeof(void*)) 8576c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri return E_INVALIDARG; 8586c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri if(pData) 8596c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri { 8606c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri memcpy(pData, &i->second.first, sizeof(void*)); 86192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri ((IUnknown*)i->second.first)->AddRef(); 8626c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri } 8636c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri *pDataSize = sizeof(void*); 8646c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri } 8656c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri else 8666c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri { 8676c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri unsigned size = std::min(*pDataSize, i->second.second); 8686c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri if(pData) 8696c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri memcpy(pData, i->second.first, size); 8706c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri *pDataSize = size; 8716c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri } 8726c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri return S_OK; 8736c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri } 8746c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri 8756c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri HRESULT set_private_data( 8768224256946619fb25278718bbf4703e3b9d60c93Luca Barbieri REFGUID guid, 8778224256946619fb25278718bbf4703e3b9d60c93Luca Barbieri UINT DataSize, 8788224256946619fb25278718bbf4703e3b9d60c93Luca Barbieri const void *pData) 8796c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri { 8806c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri void* p = 0; 8816c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri 8826c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri if(DataSize && pData) 8836c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri { 8846c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri p = malloc(DataSize); 8856c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri if(!p) 8866c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri return E_OUTOFMEMORY; 8876c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri } 8886c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri 8896c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri lock_t<mutex_t> lock(private_data_mutex); 8906c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri std::pair<void*, unsigned>& v = private_data_map[guid]; 8916c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri if(v.first) 8926c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri { 8936c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri if(v.second == ~0u) 8946c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri ((IUnknown*)v.first)->Release(); 8956c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri else 8966c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri free(v.first); 8976c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri } 8986c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri if(DataSize && pData) 8996c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri { 9006c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri memcpy(p, pData, DataSize); 9016c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri v.first = p; 9026c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri v.second = DataSize; 9036c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri } 9046c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri else 9056c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri private_data_map.erase(guid); 9066c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri return S_OK; 9076c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri } 9086c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri 9096c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri HRESULT set_private_data_interface( 9108224256946619fb25278718bbf4703e3b9d60c93Luca Barbieri REFGUID guid, 9118224256946619fb25278718bbf4703e3b9d60c93Luca Barbieri const IUnknown *pData) 9126c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri { 9136c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri lock_t<mutex_t> lock(private_data_mutex); 9146c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri std::pair<void*, unsigned>& v = private_data_map[guid]; 91592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri if(v.first) 91692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri { 91792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri if(v.second == ~0u) 91892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri ((IUnknown*)v.first)->Release(); 91992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri else 92092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri free(v.first); 92192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri } 92292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri if(pData) 92392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri { 92492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri ((IUnknown*)pData)->AddRef(); 92592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri v.first = (void*)pData; 92692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri v.second = ~0; 92792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri } 92892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri else 92992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri private_data_map.erase(guid); 93092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri return S_OK; 9316c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri } 93292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 93392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri virtual HRESULT STDMETHODCALLTYPE GetPrivateData( 9348224256946619fb25278718bbf4703e3b9d60c93Luca Barbieri REFGUID guid, 9358224256946619fb25278718bbf4703e3b9d60c93Luca Barbieri UINT *pDataSize, 9368224256946619fb25278718bbf4703e3b9d60c93Luca Barbieri void *pData) 9376c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri { 93892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri return get_private_data(guid, pDataSize, pData); 9396c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri } 9406c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri 9416c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri virtual HRESULT STDMETHODCALLTYPE SetPrivateData( 9428224256946619fb25278718bbf4703e3b9d60c93Luca Barbieri REFGUID guid, 9438224256946619fb25278718bbf4703e3b9d60c93Luca Barbieri UINT DataSize, 9448224256946619fb25278718bbf4703e3b9d60c93Luca Barbieri const void *pData) 9456c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri { 9466c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri return set_private_data(guid, DataSize, pData); 9476c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri } 9486c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri 9496c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri virtual HRESULT STDMETHODCALLTYPE SetPrivateDataInterface( 9508224256946619fb25278718bbf4703e3b9d60c93Luca Barbieri REFGUID guid, 9518224256946619fb25278718bbf4703e3b9d60c93Luca Barbieri const IUnknown *pData) 9526c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri { 9536c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri return set_private_data_interface(guid, pData); 9546c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri } 95592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri}; 95692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 95792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieritemplate<typename BaseClass, typename SecondaryInterface> 95892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieristruct GalliumMultiPrivateDataComObject : public GalliumMultiComObject<BaseClass, SecondaryInterface> 95992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri{ 96092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri // we could avoid this duplication, but the increased complexity to do so isn't worth it 96192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri virtual HRESULT STDMETHODCALLTYPE GetPrivateData( 9628224256946619fb25278718bbf4703e3b9d60c93Luca Barbieri REFGUID guid, 9638224256946619fb25278718bbf4703e3b9d60c93Luca Barbieri UINT *pDataSize, 9648224256946619fb25278718bbf4703e3b9d60c93Luca Barbieri void *pData) 9656c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri { 96692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri return BaseClass::get_private_data(guid, pDataSize, pData); 9676c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri } 9686c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri 9696c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri virtual HRESULT STDMETHODCALLTYPE SetPrivateData( 9708224256946619fb25278718bbf4703e3b9d60c93Luca Barbieri REFGUID guid, 9718224256946619fb25278718bbf4703e3b9d60c93Luca Barbieri UINT DataSize, 9728224256946619fb25278718bbf4703e3b9d60c93Luca Barbieri const void *pData) 9736c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri { 9746c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri return BaseClass::set_private_data(guid, DataSize, pData); 9756c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri } 9766c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri 9776c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri virtual HRESULT STDMETHODCALLTYPE SetPrivateDataInterface( 9788224256946619fb25278718bbf4703e3b9d60c93Luca Barbieri REFGUID guid, 9798224256946619fb25278718bbf4703e3b9d60c93Luca Barbieri const IUnknown *pData) 9806c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri { 9816c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri return BaseClass::set_private_data_interface(guid, pData); 9826c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri } 98392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri}; 98492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 98577574bf0f46716490be741d8095a8d184eff6076Christoph Bumiller#define DXGI_FORMAT_COUNT 116 98692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieriextern pipe_format dxgi_to_pipe_format[DXGI_FORMAT_COUNT]; 98792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieriextern DXGI_FORMAT pipe_to_dxgi_format[PIPE_FORMAT_COUNT]; 98892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 98992617aeac109481258f0c3863d09c1b8903d438bLuca Barbierivoid init_pipe_to_dxgi_format(); 99092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 99192617aeac109481258f0c3863d09c1b8903d438bLuca BarbieriCOM_INTERFACE(IGalliumDevice, IUnknown); 99292617aeac109481258f0c3863d09c1b8903d438bLuca BarbieriCOM_INTERFACE(IGalliumAdapter, IUnknown); 99392617aeac109481258f0c3863d09c1b8903d438bLuca BarbieriCOM_INTERFACE(IGalliumResource, IUnknown); 99492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 99592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri// used to make QueryInterface know the IIDs of the interface and its ancestors 99692617aeac109481258f0c3863d09c1b8903d438bLuca BarbieriCOM_INTERFACE(IDXGIObject, IUnknown) 99792617aeac109481258f0c3863d09c1b8903d438bLuca BarbieriCOM_INTERFACE(IDXGIDeviceSubObject, IDXGIObject) 99892617aeac109481258f0c3863d09c1b8903d438bLuca BarbieriCOM_INTERFACE(IDXGISurface, IDXGIDeviceSubObject) 99992617aeac109481258f0c3863d09c1b8903d438bLuca BarbieriCOM_INTERFACE(IDXGIOutput, IDXGIObject) 100092617aeac109481258f0c3863d09c1b8903d438bLuca BarbieriCOM_INTERFACE(IDXGIAdapter, IDXGIObject) 100192617aeac109481258f0c3863d09c1b8903d438bLuca BarbieriCOM_INTERFACE(IDXGISwapChain, IDXGIDeviceSubObject) 100292617aeac109481258f0c3863d09c1b8903d438bLuca BarbieriCOM_INTERFACE(IDXGIFactory, IDXGIObject) 100392617aeac109481258f0c3863d09c1b8903d438bLuca BarbieriCOM_INTERFACE(IDXGIDevice, IDXGIObject) 100492617aeac109481258f0c3863d09c1b8903d438bLuca BarbieriCOM_INTERFACE(IDXGIResource, IDXGIDeviceSubObject) 100592617aeac109481258f0c3863d09c1b8903d438bLuca BarbieriCOM_INTERFACE(IDXGISurface1, IDXGISurface) 100692617aeac109481258f0c3863d09c1b8903d438bLuca BarbieriCOM_INTERFACE(IDXGIDevice1, IDXGIDevice) 100792617aeac109481258f0c3863d09c1b8903d438bLuca BarbieriCOM_INTERFACE(IDXGIAdapter1, IDXGIAdapter) 100892617aeac109481258f0c3863d09c1b8903d438bLuca BarbieriCOM_INTERFACE(IDXGIFactory1, IDXGIFactory) 100992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 101092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieritemplate<typename Base> 1011dfc546c047b0f6df254586e991f656faa781ddbaLuca Barbieristruct GalliumDXGIDevice : public GalliumMultiPrivateDataComObject<Base, IDXGIDevice1> 101292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri{ 101392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri ComPtr<IDXGIAdapter> adapter; 101492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri int priority; 101592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri unsigned max_latency; 101692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 101792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri GalliumDXGIDevice(IDXGIAdapter* p_adapter) 101892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri { 101992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri adapter = p_adapter; 102092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri } 102192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 10226c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri virtual HRESULT STDMETHODCALLTYPE GetParent( 10238224256946619fb25278718bbf4703e3b9d60c93Luca Barbieri REFIID riid, 10248224256946619fb25278718bbf4703e3b9d60c93Luca Barbieri void **ppParent) 10256c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri { 10266c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri return adapter.p->QueryInterface(riid, ppParent); 10276c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri } 102892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 102992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri virtual HRESULT STDMETHODCALLTYPE GetAdapter( 10308224256946619fb25278718bbf4703e3b9d60c93Luca Barbieri IDXGIAdapter **pAdapter) 103192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri { 103292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri *pAdapter = adapter.ref(); 103392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri return S_OK; 103492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri } 103592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 103692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri virtual HRESULT STDMETHODCALLTYPE QueryResourceResidency( 10378224256946619fb25278718bbf4703e3b9d60c93Luca Barbieri IUnknown *const *ppResources, 10388224256946619fb25278718bbf4703e3b9d60c93Luca Barbieri DXGI_RESIDENCY *pResidencyStatus, 103992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri UINT NumResources) 104092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri { 104192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri for(unsigned i = 0; i < NumResources; ++i) 104292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri pResidencyStatus[i] = DXGI_RESIDENCY_FULLY_RESIDENT; 104392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri return S_OK; 104492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri } 104592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 104692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri virtual HRESULT STDMETHODCALLTYPE SetGPUThreadPriority( 104792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri INT Priority) 104892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri { 104992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri priority = Priority; 105092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri return S_OK; 105192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri } 105292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 105392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri virtual HRESULT STDMETHODCALLTYPE GetGPUThreadPriority( 10548224256946619fb25278718bbf4703e3b9d60c93Luca Barbieri INT *pPriority) 105592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri { 105692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri *pPriority = priority; 105792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri return S_OK; 105892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri } 105992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 106092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri HRESULT STDMETHODCALLTYPE GetMaximumFrameLatency( 106192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri UINT *pMaxLatency 106292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri ) 106392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri { 106492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri *pMaxLatency = max_latency; 106592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri return S_OK; 106692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri } 106792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 10686c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri virtual HRESULT STDMETHODCALLTYPE SetMaximumFrameLatency( 10696c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri UINT MaxLatency) 10706c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri { 10716c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri max_latency = MaxLatency; 10726c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri return S_OK; 10736c598c78bd17642d731cf57b8369cc794f64ba2fLuca Barbieri } 107492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri}; 107592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri 107670fed0b0ec8a3ec4f6b9b47f1fe98cc54c6037f0Luca BarbieriCOM_INTERFACE(ID3D10Blob, IUnknown); 107770fed0b0ec8a3ec4f6b9b47f1fe98cc54c6037f0Luca Barbieri 107870fed0b0ec8a3ec4f6b9b47f1fe98cc54c6037f0Luca Barbieri/* NOTE: ID3DBlob implementations may come from a Microsoft native DLL 107970fed0b0ec8a3ec4f6b9b47f1fe98cc54c6037f0Luca Barbieri * (e.g. d3dcompiler), or perhaps even from the application itself. 108070fed0b0ec8a3ec4f6b9b47f1fe98cc54c6037f0Luca Barbieri * 108170fed0b0ec8a3ec4f6b9b47f1fe98cc54c6037f0Luca Barbieri * Hence, never try to access the data/size members directly, which is why they are private. 108270fed0b0ec8a3ec4f6b9b47f1fe98cc54c6037f0Luca Barbieri * In internal code, use std::pair<void*, size_t> instead of this class. 108370fed0b0ec8a3ec4f6b9b47f1fe98cc54c6037f0Luca Barbieri */ 108470fed0b0ec8a3ec4f6b9b47f1fe98cc54c6037f0Luca Barbiericlass GalliumD3DBlob : public GalliumComObject<ID3DBlob> 108570fed0b0ec8a3ec4f6b9b47f1fe98cc54c6037f0Luca Barbieri{ 108670fed0b0ec8a3ec4f6b9b47f1fe98cc54c6037f0Luca Barbieri void* data; 108770fed0b0ec8a3ec4f6b9b47f1fe98cc54c6037f0Luca Barbieri size_t size; 108870fed0b0ec8a3ec4f6b9b47f1fe98cc54c6037f0Luca Barbieri 1089bb26272beaf1d2bddffaad5341235e70abcf483bLuca Barbieripublic: 109070fed0b0ec8a3ec4f6b9b47f1fe98cc54c6037f0Luca Barbieri GalliumD3DBlob(void* data, size_t size) 109170fed0b0ec8a3ec4f6b9b47f1fe98cc54c6037f0Luca Barbieri : data(data), size(size) 109270fed0b0ec8a3ec4f6b9b47f1fe98cc54c6037f0Luca Barbieri {} 109370fed0b0ec8a3ec4f6b9b47f1fe98cc54c6037f0Luca Barbieri 109470fed0b0ec8a3ec4f6b9b47f1fe98cc54c6037f0Luca Barbieri ~GalliumD3DBlob() 109570fed0b0ec8a3ec4f6b9b47f1fe98cc54c6037f0Luca Barbieri { 109670fed0b0ec8a3ec4f6b9b47f1fe98cc54c6037f0Luca Barbieri free(data); 109770fed0b0ec8a3ec4f6b9b47f1fe98cc54c6037f0Luca Barbieri } 1098bb26272beaf1d2bddffaad5341235e70abcf483bLuca Barbieri 109970fed0b0ec8a3ec4f6b9b47f1fe98cc54c6037f0Luca Barbieri virtual LPVOID STDMETHODCALLTYPE GetBufferPointer() 110070fed0b0ec8a3ec4f6b9b47f1fe98cc54c6037f0Luca Barbieri { 110170fed0b0ec8a3ec4f6b9b47f1fe98cc54c6037f0Luca Barbieri return data; 110270fed0b0ec8a3ec4f6b9b47f1fe98cc54c6037f0Luca Barbieri } 110370fed0b0ec8a3ec4f6b9b47f1fe98cc54c6037f0Luca Barbieri 110470fed0b0ec8a3ec4f6b9b47f1fe98cc54c6037f0Luca Barbieri virtual SIZE_T STDMETHODCALLTYPE GetBufferSize() 110570fed0b0ec8a3ec4f6b9b47f1fe98cc54c6037f0Luca Barbieri { 110670fed0b0ec8a3ec4f6b9b47f1fe98cc54c6037f0Luca Barbieri return size; 110770fed0b0ec8a3ec4f6b9b47f1fe98cc54c6037f0Luca Barbieri } 110870fed0b0ec8a3ec4f6b9b47f1fe98cc54c6037f0Luca Barbieri}; 110970fed0b0ec8a3ec4f6b9b47f1fe98cc54c6037f0Luca Barbieri 111092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri#endif /* D3D1XSTUTIL_H_ */ 1111