xref: /reactos/dll/directx/wine/d3d9/query.c (revision 845faec4)
1 /*
2  * IDirect3DQuery9 implementation
3  *
4  * Copyright 2002-2003 Raphael Junqueira
5  * Copyright 2002-2003 Jason Edmeades
6  * Copyright 2005 Oliver Stieber
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21  */
22 
23 #include "config.h"
24 #include "d3d9_private.h"
25 
26 WINE_DEFAULT_DEBUG_CHANNEL(d3d9);
27 
28 static inline struct d3d9_query *impl_from_IDirect3DQuery9(IDirect3DQuery9 *iface)
29 {
30     return CONTAINING_RECORD(iface, struct d3d9_query, IDirect3DQuery9_iface);
31 }
32 
33 static HRESULT WINAPI d3d9_query_QueryInterface(IDirect3DQuery9 *iface, REFIID riid, void **out)
34 {
35     TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
36 
37     if (IsEqualGUID(riid, &IID_IDirect3DQuery9)
38             || IsEqualGUID(riid, &IID_IUnknown))
39     {
40         IDirect3DQuery9_AddRef(iface);
41         *out = iface;
42         return S_OK;
43     }
44 
45     WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
46 
47     *out = NULL;
48     return E_NOINTERFACE;
49 }
50 
51 static ULONG WINAPI d3d9_query_AddRef(IDirect3DQuery9 *iface)
52 {
53     struct d3d9_query *query = impl_from_IDirect3DQuery9(iface);
54     ULONG refcount = InterlockedIncrement(&query->refcount);
55 
56     TRACE("%p increasing refcount to %u.\n", iface, refcount);
57 
58     return refcount;
59 }
60 
61 static ULONG WINAPI d3d9_query_Release(IDirect3DQuery9 *iface)
62 {
63     struct d3d9_query *query = impl_from_IDirect3DQuery9(iface);
64     ULONG refcount = InterlockedDecrement(&query->refcount);
65 
66     TRACE("%p decreasing refcount to %u.\n", iface, refcount);
67 
68     if (!refcount)
69     {
70         wined3d_mutex_lock();
71         wined3d_query_decref(query->wined3d_query);
72         wined3d_mutex_unlock();
73 
74         IDirect3DDevice9Ex_Release(query->parent_device);
75         heap_free(query);
76     }
77     return refcount;
78 }
79 
80 static HRESULT WINAPI d3d9_query_GetDevice(IDirect3DQuery9 *iface, IDirect3DDevice9 **device)
81 {
82     struct d3d9_query *query = impl_from_IDirect3DQuery9(iface);
83 
84     TRACE("iface %p, device %p.\n", iface, device);
85 
86     *device = (IDirect3DDevice9 *)query->parent_device;
87     IDirect3DDevice9_AddRef(*device);
88 
89     TRACE("Returning device %p.\n", *device);
90 
91     return D3D_OK;
92 }
93 
94 static D3DQUERYTYPE WINAPI d3d9_query_GetType(IDirect3DQuery9 *iface)
95 {
96     struct d3d9_query *query = impl_from_IDirect3DQuery9(iface);
97     D3DQUERYTYPE type;
98 
99     TRACE("iface %p.\n", iface);
100 
101     wined3d_mutex_lock();
102     type = wined3d_query_get_type(query->wined3d_query);
103     wined3d_mutex_unlock();
104 
105     return type;
106 }
107 
108 static DWORD WINAPI d3d9_query_GetDataSize(IDirect3DQuery9 *iface)
109 {
110     struct d3d9_query *query = impl_from_IDirect3DQuery9(iface);
111 
112     TRACE("iface %p.\n", iface);
113 
114     return query->data_size;
115 }
116 
117 static HRESULT WINAPI d3d9_query_Issue(IDirect3DQuery9 *iface, DWORD flags)
118 {
119     struct d3d9_query *query = impl_from_IDirect3DQuery9(iface);
120     HRESULT hr;
121 
122     TRACE("iface %p, flags %#x.\n", iface, flags);
123 
124     wined3d_mutex_lock();
125     hr = wined3d_query_issue(query->wined3d_query, flags);
126     wined3d_mutex_unlock();
127 
128     return hr;
129 }
130 
131 static HRESULT WINAPI d3d9_query_GetData(IDirect3DQuery9 *iface, void *data, DWORD size, DWORD flags)
132 {
133     struct d3d9_query *query = impl_from_IDirect3DQuery9(iface);
134     enum wined3d_query_type type;
135     HRESULT hr;
136 
137     TRACE("iface %p, data %p, size %u, flags %#x.\n",
138             iface, data, size, flags);
139 
140     wined3d_mutex_lock();
141     type = wined3d_query_get_type(query->wined3d_query);
142     if (type == WINED3D_QUERY_TYPE_TIMESTAMP_DISJOINT && data)
143     {
144         struct wined3d_query_data_timestamp_disjoint data_disjoint;
145 
146         if (size > sizeof(data_disjoint.disjoint))
147             size = sizeof(data_disjoint.disjoint);
148 
149         hr = wined3d_query_get_data(query->wined3d_query, &data_disjoint, sizeof(data_disjoint), flags);
150         if (SUCCEEDED(hr))
151             memcpy(data, &data_disjoint.disjoint, size);
152     }
153     else
154     {
155         hr = wined3d_query_get_data(query->wined3d_query, data, size, flags);
156     }
157     wined3d_mutex_unlock();
158 
159     if (hr == D3DERR_INVALIDCALL)
160     {
161         if (data)
162         {
163             memset(data, 0, size);
164             memset(data, 0xdd, min(size, query->data_size));
165         }
166         return S_OK;
167     }
168     return hr;
169 }
170 
171 
172 static const struct IDirect3DQuery9Vtbl d3d9_query_vtbl =
173 {
174     d3d9_query_QueryInterface,
175     d3d9_query_AddRef,
176     d3d9_query_Release,
177     d3d9_query_GetDevice,
178     d3d9_query_GetType,
179     d3d9_query_GetDataSize,
180     d3d9_query_Issue,
181     d3d9_query_GetData,
182 };
183 
184 HRESULT query_init(struct d3d9_query *query, struct d3d9_device *device, D3DQUERYTYPE type)
185 {
186     HRESULT hr;
187 
188     if (type > D3DQUERYTYPE_MEMORYPRESSURE)
189     {
190         if (type == 0x16)
191             FIXME("Undocumented query %#x created.\n", type);
192         else
193             WARN("Invalid query type %#x.\n", type);
194 
195         return D3DERR_NOTAVAILABLE;
196     }
197 
198     query->IDirect3DQuery9_iface.lpVtbl = &d3d9_query_vtbl;
199     query->refcount = 1;
200 
201     wined3d_mutex_lock();
202     if (FAILED(hr = wined3d_query_create(device->wined3d_device, type,
203             query, &d3d9_null_wined3d_parent_ops, &query->wined3d_query)))
204     {
205         wined3d_mutex_unlock();
206         WARN("Failed to create wined3d query, hr %#x.\n", hr);
207         return hr;
208     }
209 
210     if (type == D3DQUERYTYPE_OCCLUSION)
211         query->data_size = sizeof(DWORD);
212     else if (type == D3DQUERYTYPE_TIMESTAMPDISJOINT)
213         query->data_size = sizeof(BOOL);
214     else
215         query->data_size = wined3d_query_get_data_size(query->wined3d_query);
216     wined3d_mutex_unlock();
217 
218     query->parent_device = &device->IDirect3DDevice9Ex_iface;
219     IDirect3DDevice9Ex_AddRef(query->parent_device);
220 
221     return D3D_OK;
222 }
223