1b8e80941Smrg/*
2b8e80941Smrg * Copyright 2011 Joakim Sindholt <opensource@zhasha.com>
3b8e80941Smrg *
4b8e80941Smrg * Permission is hereby granted, free of charge, to any person obtaining a
5b8e80941Smrg * copy of this software and associated documentation files (the "Software"),
6b8e80941Smrg * to deal in the Software without restriction, including without limitation
7b8e80941Smrg * on the rights to use, copy, modify, merge, publish, distribute, sub
8b8e80941Smrg * license, and/or sell copies of the Software, and to permit persons to whom
9b8e80941Smrg * the Software is furnished to do so, subject to the following conditions:
10b8e80941Smrg *
11b8e80941Smrg * The above copyright notice and this permission notice (including the next
12b8e80941Smrg * paragraph) shall be included in all copies or substantial portions of the
13b8e80941Smrg * Software.
14b8e80941Smrg *
15b8e80941Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16b8e80941Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17b8e80941Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18b8e80941Smrg * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
19b8e80941Smrg * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20b8e80941Smrg * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
21b8e80941Smrg * USE OR OTHER DEALINGS IN THE SOFTWARE. */
22b8e80941Smrg
23b8e80941Smrg#ifndef _NINE_IUNKNOWN_H_
24b8e80941Smrg#define _NINE_IUNKNOWN_H_
25b8e80941Smrg
26b8e80941Smrg#include "pipe/p_compiler.h"
27b8e80941Smrg
28b8e80941Smrg#include "util/u_atomic.h"
29b8e80941Smrg#include "util/u_memory.h"
30b8e80941Smrg
31b8e80941Smrg#include "guid.h"
32b8e80941Smrg#include "nine_flags.h"
33b8e80941Smrg#include "nine_debug.h"
34b8e80941Smrg#include "nine_quirk.h"
35b8e80941Smrg
36b8e80941Smrg#include "d3d9.h"
37b8e80941Smrg
38b8e80941Smrgstruct Nine9;
39b8e80941Smrgstruct NineDevice9;
40b8e80941Smrg
41b8e80941Smrgstruct NineUnknown
42b8e80941Smrg{
43b8e80941Smrg    /* pointer to vtable (can be overriden outside gallium nine) */
44b8e80941Smrg    void *vtable;
45b8e80941Smrg    /* pointer to internal vtable  */
46b8e80941Smrg    void *vtable_internal;
47b8e80941Smrg
48b8e80941Smrg    int32_t refs; /* external reference count */
49b8e80941Smrg    int32_t bind; /* internal bind count */
50b8e80941Smrg    boolean forward; /* whether to forward references to the container */
51b8e80941Smrg
52b8e80941Smrg    /* container: for surfaces and volumes only.
53b8e80941Smrg     * Can be a texture, a volume texture or a swapchain.
54b8e80941Smrg     * forward is set to false for the swapchain case.
55b8e80941Smrg     * If forward is set, refs are passed to the container if forward is set
56b8e80941Smrg     * and the container has bind increased if the object has non null bind. */
57b8e80941Smrg    struct NineUnknown *container;
58b8e80941Smrg    struct NineDevice9 *device;    /* referenced if (refs) */
59b8e80941Smrg
60b8e80941Smrg    const GUID **guids; /* for QueryInterface */
61b8e80941Smrg
62b8e80941Smrg    /* for [GS]etPrivateData/FreePrivateData */
63b8e80941Smrg    struct util_hash_table *pdata;
64b8e80941Smrg
65b8e80941Smrg    void (*dtor)(void *data); /* top-level dtor */
66b8e80941Smrg};
67b8e80941Smrgstatic inline struct NineUnknown *
68b8e80941SmrgNineUnknown( void *data )
69b8e80941Smrg{
70b8e80941Smrg    return (struct NineUnknown *)data;
71b8e80941Smrg}
72b8e80941Smrg
73b8e80941Smrg/* Use this instead of a shitload of arguments: */
74b8e80941Smrgstruct NineUnknownParams
75b8e80941Smrg{
76b8e80941Smrg    void *vtable;
77b8e80941Smrg    const GUID **guids;
78b8e80941Smrg    void (*dtor)(void *data);
79b8e80941Smrg    struct NineUnknown *container;
80b8e80941Smrg    struct NineDevice9 *device;
81b8e80941Smrg    bool start_with_bind_not_ref;
82b8e80941Smrg};
83b8e80941Smrg
84b8e80941SmrgHRESULT
85b8e80941SmrgNineUnknown_ctor( struct NineUnknown *This,
86b8e80941Smrg                  struct NineUnknownParams *pParams );
87b8e80941Smrg
88b8e80941Smrgvoid
89b8e80941SmrgNineUnknown_dtor( struct NineUnknown *This );
90b8e80941Smrg
91b8e80941Smrg/*** Direct3D public methods ***/
92b8e80941Smrg
93b8e80941SmrgHRESULT NINE_WINAPI
94b8e80941SmrgNineUnknown_QueryInterface( struct NineUnknown *This,
95b8e80941Smrg                            REFIID riid,
96b8e80941Smrg                            void **ppvObject );
97b8e80941Smrg
98b8e80941SmrgULONG NINE_WINAPI
99b8e80941SmrgNineUnknown_AddRef( struct NineUnknown *This );
100b8e80941Smrg
101b8e80941SmrgULONG NINE_WINAPI
102b8e80941SmrgNineUnknown_Release( struct NineUnknown *This );
103b8e80941Smrg
104b8e80941SmrgULONG NINE_WINAPI
105b8e80941SmrgNineUnknown_ReleaseWithDtorLock( struct NineUnknown *This );
106b8e80941Smrg
107b8e80941SmrgHRESULT NINE_WINAPI
108b8e80941SmrgNineUnknown_GetDevice( struct NineUnknown *This,
109b8e80941Smrg                       IDirect3DDevice9 **ppDevice );
110b8e80941Smrg
111b8e80941SmrgHRESULT NINE_WINAPI
112b8e80941SmrgNineUnknown_SetPrivateData( struct NineUnknown *This,
113b8e80941Smrg                            REFGUID refguid,
114b8e80941Smrg                            const void *pData,
115b8e80941Smrg                            DWORD SizeOfData,
116b8e80941Smrg                            DWORD Flags );
117b8e80941Smrg
118b8e80941SmrgHRESULT NINE_WINAPI
119b8e80941SmrgNineUnknown_GetPrivateData( struct NineUnknown *This,
120b8e80941Smrg                            REFGUID refguid,
121b8e80941Smrg                            void *pData,
122b8e80941Smrg                            DWORD *pSizeOfData );
123b8e80941Smrg
124b8e80941SmrgHRESULT NINE_WINAPI
125b8e80941SmrgNineUnknown_FreePrivateData( struct NineUnknown *This,
126b8e80941Smrg                             REFGUID refguid );
127b8e80941Smrg
128b8e80941Smrg/*** Nine private methods ***/
129b8e80941Smrg
130b8e80941Smrgstatic inline void
131b8e80941SmrgNineUnknown_Destroy( struct NineUnknown *This )
132b8e80941Smrg{
133b8e80941Smrg    assert(!(This->refs | This->bind));
134b8e80941Smrg    This->dtor(This);
135b8e80941Smrg}
136b8e80941Smrg
137b8e80941Smrgstatic inline UINT
138b8e80941SmrgNineUnknown_Bind( struct NineUnknown *This )
139b8e80941Smrg{
140b8e80941Smrg    UINT b = p_atomic_inc_return(&This->bind);
141b8e80941Smrg    assert(b);
142b8e80941Smrg
143b8e80941Smrg    if (b == 1 && This->forward)
144b8e80941Smrg        NineUnknown_Bind(This->container);
145b8e80941Smrg
146b8e80941Smrg    return b;
147b8e80941Smrg}
148b8e80941Smrg
149b8e80941Smrgstatic inline UINT
150b8e80941SmrgNineUnknown_Unbind( struct NineUnknown *This )
151b8e80941Smrg{
152b8e80941Smrg    UINT b = p_atomic_dec_return(&This->bind);
153b8e80941Smrg
154b8e80941Smrg    if (b == 0 && This->forward)
155b8e80941Smrg        NineUnknown_Unbind(This->container);
156b8e80941Smrg    else if (b == 0 && This->refs == 0 && !This->container)
157b8e80941Smrg        This->dtor(This);
158b8e80941Smrg
159b8e80941Smrg    return b;
160b8e80941Smrg}
161b8e80941Smrg
162b8e80941Smrgstatic inline void
163b8e80941SmrgNineUnknown_ConvertRefToBind( struct NineUnknown *This )
164b8e80941Smrg{
165b8e80941Smrg    NineUnknown_Bind(This);
166b8e80941Smrg    NineUnknown_Release(This);
167b8e80941Smrg}
168b8e80941Smrg
169b8e80941Smrg/* Detach from container. */
170b8e80941Smrgstatic inline void
171b8e80941SmrgNineUnknown_Detach( struct NineUnknown *This )
172b8e80941Smrg{
173b8e80941Smrg    assert(This->container && !This->forward);
174b8e80941Smrg
175b8e80941Smrg    This->container = NULL;
176b8e80941Smrg    if (!(This->refs | This->bind))
177b8e80941Smrg        This->dtor(This);
178b8e80941Smrg}
179b8e80941Smrg
180b8e80941Smrg#endif /* _NINE_IUNKNOWN_H_ */
181