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