1 /* 2 * Copyright 2002-2003 Jason Edmeades 3 * Raphael Junqueira 4 * 5 * This library is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU Lesser General Public 7 * License as published by the Free Software Foundation; either 8 * version 2.1 of the License, or (at your option) any later version. 9 * 10 * This library is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 * Lesser General Public License for more details. 14 * 15 * You should have received a copy of the GNU Lesser General Public 16 * License along with this library; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 18 */ 19 20 #include "config.h" 21 #include "d3d9_private.h" 22 23 WINE_DEFAULT_DEBUG_CHANNEL(d3d9); 24 25 static inline struct d3d9_vertexshader *impl_from_IDirect3DVertexShader9(IDirect3DVertexShader9 *iface) 26 { 27 return CONTAINING_RECORD(iface, struct d3d9_vertexshader, IDirect3DVertexShader9_iface); 28 } 29 30 static HRESULT WINAPI d3d9_vertexshader_QueryInterface(IDirect3DVertexShader9 *iface, REFIID riid, void **out) 31 { 32 TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out); 33 34 if (IsEqualGUID(riid, &IID_IDirect3DVertexShader9) 35 || IsEqualGUID(riid, &IID_IUnknown)) 36 { 37 IDirect3DVertexShader9_AddRef(iface); 38 *out = iface; 39 return S_OK; 40 } 41 42 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid)); 43 44 *out = NULL; 45 return E_NOINTERFACE; 46 } 47 48 static ULONG WINAPI d3d9_vertexshader_AddRef(IDirect3DVertexShader9 *iface) 49 { 50 struct d3d9_vertexshader *shader = impl_from_IDirect3DVertexShader9(iface); 51 ULONG refcount = InterlockedIncrement(&shader->refcount); 52 53 TRACE("%p increasing refcount to %u.\n", iface, refcount); 54 55 if (refcount == 1) 56 { 57 IDirect3DDevice9Ex_AddRef(shader->parent_device); 58 wined3d_mutex_lock(); 59 wined3d_shader_incref(shader->wined3d_shader); 60 wined3d_mutex_unlock(); 61 } 62 63 return refcount; 64 } 65 66 static ULONG WINAPI d3d9_vertexshader_Release(IDirect3DVertexShader9 *iface) 67 { 68 struct d3d9_vertexshader *shader = impl_from_IDirect3DVertexShader9(iface); 69 ULONG refcount = InterlockedDecrement(&shader->refcount); 70 71 TRACE("%p decreasing refcount to %u.\n", iface, refcount); 72 73 if (!refcount) 74 { 75 IDirect3DDevice9Ex *device = shader->parent_device; 76 77 wined3d_mutex_lock(); 78 wined3d_shader_decref(shader->wined3d_shader); 79 wined3d_mutex_unlock(); 80 81 /* Release the device last, as it may cause the device to be destroyed. */ 82 IDirect3DDevice9Ex_Release(device); 83 } 84 85 return refcount; 86 } 87 88 static HRESULT WINAPI d3d9_vertexshader_GetDevice(IDirect3DVertexShader9 *iface, IDirect3DDevice9 **device) 89 { 90 struct d3d9_vertexshader *shader = impl_from_IDirect3DVertexShader9(iface); 91 92 TRACE("iface %p, device %p.\n", iface, device); 93 94 *device = (IDirect3DDevice9 *)shader->parent_device; 95 IDirect3DDevice9_AddRef(*device); 96 97 TRACE("Returning device %p.\n", *device); 98 99 return D3D_OK; 100 } 101 102 static HRESULT WINAPI d3d9_vertexshader_GetFunction(IDirect3DVertexShader9 *iface, void *data, UINT *data_size) 103 { 104 struct d3d9_vertexshader *shader = impl_from_IDirect3DVertexShader9(iface); 105 HRESULT hr; 106 107 TRACE("iface %p, data %p, data_size %p.\n", iface, data, data_size); 108 109 wined3d_mutex_lock(); 110 hr = wined3d_shader_get_byte_code(shader->wined3d_shader, data, data_size); 111 wined3d_mutex_unlock(); 112 113 return hr; 114 } 115 116 static const IDirect3DVertexShader9Vtbl d3d9_vertexshader_vtbl = 117 { 118 /* IUnknown */ 119 d3d9_vertexshader_QueryInterface, 120 d3d9_vertexshader_AddRef, 121 d3d9_vertexshader_Release, 122 /* IDirect3DVertexShader9 */ 123 d3d9_vertexshader_GetDevice, 124 d3d9_vertexshader_GetFunction, 125 }; 126 127 static void STDMETHODCALLTYPE d3d9_vertexshader_wined3d_object_destroyed(void *parent) 128 { 129 heap_free(parent); 130 } 131 132 static const struct wined3d_parent_ops d3d9_vertexshader_wined3d_parent_ops = 133 { 134 d3d9_vertexshader_wined3d_object_destroyed, 135 }; 136 137 HRESULT vertexshader_init(struct d3d9_vertexshader *shader, struct d3d9_device *device, const DWORD *byte_code) 138 { 139 struct wined3d_shader_desc desc; 140 HRESULT hr; 141 142 shader->refcount = 1; 143 shader->IDirect3DVertexShader9_iface.lpVtbl = &d3d9_vertexshader_vtbl; 144 145 desc.byte_code = byte_code; 146 desc.byte_code_size = ~(size_t)0; 147 desc.format = WINED3D_SHADER_BYTE_CODE_FORMAT_SM1; 148 desc.input_signature.element_count = 0; 149 desc.output_signature.element_count = 0; 150 desc.patch_constant_signature.element_count = 0; 151 desc.max_version = 3; 152 153 wined3d_mutex_lock(); 154 hr = wined3d_shader_create_vs(device->wined3d_device, &desc, shader, 155 &d3d9_vertexshader_wined3d_parent_ops, &shader->wined3d_shader); 156 wined3d_mutex_unlock(); 157 if (FAILED(hr)) 158 { 159 WARN("Failed to create wined3d vertex shader, hr %#x.\n", hr); 160 return hr; 161 } 162 163 shader->parent_device = &device->IDirect3DDevice9Ex_iface; 164 IDirect3DDevice9Ex_AddRef(shader->parent_device); 165 166 return D3D_OK; 167 } 168 169 struct d3d9_vertexshader *unsafe_impl_from_IDirect3DVertexShader9(IDirect3DVertexShader9 *iface) 170 { 171 if (!iface) 172 return NULL; 173 if (iface->lpVtbl != &d3d9_vertexshader_vtbl) 174 WARN("Vertex shader %p with the wrong vtbl %p\n", iface, iface->lpVtbl); 175 176 return impl_from_IDirect3DVertexShader9(iface); 177 } 178 179 static inline struct d3d9_pixelshader *impl_from_IDirect3DPixelShader9(IDirect3DPixelShader9 *iface) 180 { 181 return CONTAINING_RECORD(iface, struct d3d9_pixelshader, IDirect3DPixelShader9_iface); 182 } 183 184 static HRESULT WINAPI d3d9_pixelshader_QueryInterface(IDirect3DPixelShader9 *iface, REFIID riid, void **out) 185 { 186 TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out); 187 188 if (IsEqualGUID(riid, &IID_IDirect3DPixelShader9) 189 || IsEqualGUID(riid, &IID_IUnknown)) 190 { 191 IDirect3DPixelShader9_AddRef(iface); 192 *out = iface; 193 return S_OK; 194 } 195 196 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid)); 197 198 *out = NULL; 199 return E_NOINTERFACE; 200 } 201 202 static ULONG WINAPI d3d9_pixelshader_AddRef(IDirect3DPixelShader9 *iface) 203 { 204 struct d3d9_pixelshader *shader = impl_from_IDirect3DPixelShader9(iface); 205 ULONG refcount = InterlockedIncrement(&shader->refcount); 206 207 TRACE("%p increasing refcount to %u.\n", iface, refcount); 208 209 if (refcount == 1) 210 { 211 IDirect3DDevice9Ex_AddRef(shader->parent_device); 212 wined3d_mutex_lock(); 213 wined3d_shader_incref(shader->wined3d_shader); 214 wined3d_mutex_unlock(); 215 } 216 217 return refcount; 218 } 219 220 static ULONG WINAPI d3d9_pixelshader_Release(IDirect3DPixelShader9 *iface) 221 { 222 struct d3d9_pixelshader *shader = impl_from_IDirect3DPixelShader9(iface); 223 ULONG refcount = InterlockedDecrement(&shader->refcount); 224 225 TRACE("%p decreasing refcount to %u.\n", iface, refcount); 226 227 if (!refcount) 228 { 229 IDirect3DDevice9Ex *device = shader->parent_device; 230 231 wined3d_mutex_lock(); 232 wined3d_shader_decref(shader->wined3d_shader); 233 wined3d_mutex_unlock(); 234 235 /* Release the device last, as it may cause the device to be destroyed. */ 236 IDirect3DDevice9Ex_Release(device); 237 } 238 239 return refcount; 240 } 241 242 static HRESULT WINAPI d3d9_pixelshader_GetDevice(IDirect3DPixelShader9 *iface, IDirect3DDevice9 **device) 243 { 244 struct d3d9_pixelshader *shader = impl_from_IDirect3DPixelShader9(iface); 245 246 TRACE("iface %p, device %p.\n", iface, device); 247 248 *device = (IDirect3DDevice9 *)shader->parent_device; 249 IDirect3DDevice9_AddRef(*device); 250 251 TRACE("Returning device %p.\n", *device); 252 253 return D3D_OK; 254 } 255 256 static HRESULT WINAPI d3d9_pixelshader_GetFunction(IDirect3DPixelShader9 *iface, void *data, UINT *data_size) 257 { 258 struct d3d9_pixelshader *shader = impl_from_IDirect3DPixelShader9(iface); 259 HRESULT hr; 260 261 TRACE("iface %p, data %p, data_size %p.\n", iface, data, data_size); 262 263 wined3d_mutex_lock(); 264 hr = wined3d_shader_get_byte_code(shader->wined3d_shader, data, data_size); 265 wined3d_mutex_unlock(); 266 267 return hr; 268 } 269 270 static const IDirect3DPixelShader9Vtbl d3d9_pixelshader_vtbl = 271 { 272 /* IUnknown */ 273 d3d9_pixelshader_QueryInterface, 274 d3d9_pixelshader_AddRef, 275 d3d9_pixelshader_Release, 276 /* IDirect3DPixelShader9 */ 277 d3d9_pixelshader_GetDevice, 278 d3d9_pixelshader_GetFunction, 279 }; 280 281 static void STDMETHODCALLTYPE d3d9_pixelshader_wined3d_object_destroyed(void *parent) 282 { 283 heap_free(parent); 284 } 285 286 static const struct wined3d_parent_ops d3d9_pixelshader_wined3d_parent_ops = 287 { 288 d3d9_pixelshader_wined3d_object_destroyed, 289 }; 290 291 HRESULT pixelshader_init(struct d3d9_pixelshader *shader, struct d3d9_device *device, const DWORD *byte_code) 292 { 293 struct wined3d_shader_desc desc; 294 HRESULT hr; 295 296 shader->refcount = 1; 297 shader->IDirect3DPixelShader9_iface.lpVtbl = &d3d9_pixelshader_vtbl; 298 299 desc.byte_code = byte_code; 300 desc.byte_code_size = ~(size_t)0; 301 desc.format = WINED3D_SHADER_BYTE_CODE_FORMAT_SM1; 302 desc.input_signature.element_count = 0; 303 desc.output_signature.element_count = 0; 304 desc.patch_constant_signature.element_count = 0; 305 desc.max_version = 3; 306 307 wined3d_mutex_lock(); 308 hr = wined3d_shader_create_ps(device->wined3d_device, &desc, shader, 309 &d3d9_pixelshader_wined3d_parent_ops, &shader->wined3d_shader); 310 wined3d_mutex_unlock(); 311 if (FAILED(hr)) 312 { 313 WARN("Failed to created wined3d pixel shader, hr %#x.\n", hr); 314 return hr; 315 } 316 317 shader->parent_device = &device->IDirect3DDevice9Ex_iface; 318 IDirect3DDevice9Ex_AddRef(shader->parent_device); 319 320 return D3D_OK; 321 } 322 323 struct d3d9_pixelshader *unsafe_impl_from_IDirect3DPixelShader9(IDirect3DPixelShader9 *iface) 324 { 325 if (!iface) 326 return NULL; 327 if (iface->lpVtbl != &d3d9_pixelshader_vtbl) 328 WARN("Pixel shader %p with the wrong vtbl %p\n", iface, iface->lpVtbl); 329 330 return impl_from_IDirect3DPixelShader9(iface); 331 } 332