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