/dlls/d3d9/shader.c

https://github.com/perj/wine · C · 311 lines · 217 code · 70 blank · 24 comment · 16 complexity · c4998fdf5799ca7b113fc2f9f7fb4687 MD5 · raw file

  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. #include "config.h"
  20. #include "d3d9_private.h"
  21. WINE_DEFAULT_DEBUG_CHANNEL(d3d9);
  22. static inline struct d3d9_vertexshader *impl_from_IDirect3DVertexShader9(IDirect3DVertexShader9 *iface)
  23. {
  24. return CONTAINING_RECORD(iface, struct d3d9_vertexshader, IDirect3DVertexShader9_iface);
  25. }
  26. static HRESULT WINAPI d3d9_vertexshader_QueryInterface(IDirect3DVertexShader9 *iface, REFIID riid, void **out)
  27. {
  28. TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
  29. if (IsEqualGUID(riid, &IID_IDirect3DVertexShader9)
  30. || IsEqualGUID(riid, &IID_IUnknown))
  31. {
  32. IDirect3DVertexShader9_AddRef(iface);
  33. *out = iface;
  34. return S_OK;
  35. }
  36. WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
  37. *out = NULL;
  38. return E_NOINTERFACE;
  39. }
  40. static ULONG WINAPI d3d9_vertexshader_AddRef(IDirect3DVertexShader9 *iface)
  41. {
  42. struct d3d9_vertexshader *shader = impl_from_IDirect3DVertexShader9(iface);
  43. ULONG refcount = InterlockedIncrement(&shader->refcount);
  44. TRACE("%p increasing refcount to %u.\n", iface, refcount);
  45. if (refcount == 1)
  46. {
  47. IDirect3DDevice9Ex_AddRef(shader->parent_device);
  48. wined3d_mutex_lock();
  49. wined3d_shader_incref(shader->wined3d_shader);
  50. wined3d_mutex_unlock();
  51. }
  52. return refcount;
  53. }
  54. static ULONG WINAPI d3d9_vertexshader_Release(IDirect3DVertexShader9 *iface)
  55. {
  56. struct d3d9_vertexshader *shader = impl_from_IDirect3DVertexShader9(iface);
  57. ULONG refcount = InterlockedDecrement(&shader->refcount);
  58. TRACE("%p decreasing refcount to %u.\n", iface, refcount);
  59. if (!refcount)
  60. {
  61. IDirect3DDevice9Ex *device = shader->parent_device;
  62. wined3d_mutex_lock();
  63. wined3d_shader_decref(shader->wined3d_shader);
  64. wined3d_mutex_unlock();
  65. /* Release the device last, as it may cause the device to be destroyed. */
  66. IDirect3DDevice9Ex_Release(device);
  67. }
  68. return refcount;
  69. }
  70. static HRESULT WINAPI d3d9_vertexshader_GetDevice(IDirect3DVertexShader9 *iface, IDirect3DDevice9 **device)
  71. {
  72. struct d3d9_vertexshader *shader = impl_from_IDirect3DVertexShader9(iface);
  73. TRACE("iface %p, device %p.\n", iface, device);
  74. *device = (IDirect3DDevice9 *)shader->parent_device;
  75. IDirect3DDevice9_AddRef(*device);
  76. TRACE("Returning device %p.\n", *device);
  77. return D3D_OK;
  78. }
  79. static HRESULT WINAPI d3d9_vertexshader_GetFunction(IDirect3DVertexShader9 *iface, void *data, UINT *data_size)
  80. {
  81. struct d3d9_vertexshader *shader = impl_from_IDirect3DVertexShader9(iface);
  82. HRESULT hr;
  83. TRACE("iface %p, data %p, data_size %p.\n", iface, data, data_size);
  84. wined3d_mutex_lock();
  85. hr = wined3d_shader_get_byte_code(shader->wined3d_shader, data, data_size);
  86. wined3d_mutex_unlock();
  87. return hr;
  88. }
  89. static const IDirect3DVertexShader9Vtbl d3d9_vertexshader_vtbl =
  90. {
  91. /* IUnknown */
  92. d3d9_vertexshader_QueryInterface,
  93. d3d9_vertexshader_AddRef,
  94. d3d9_vertexshader_Release,
  95. /* IDirect3DVertexShader9 */
  96. d3d9_vertexshader_GetDevice,
  97. d3d9_vertexshader_GetFunction,
  98. };
  99. static void STDMETHODCALLTYPE d3d9_vertexshader_wined3d_object_destroyed(void *parent)
  100. {
  101. HeapFree(GetProcessHeap(), 0, parent);
  102. }
  103. static const struct wined3d_parent_ops d3d9_vertexshader_wined3d_parent_ops =
  104. {
  105. d3d9_vertexshader_wined3d_object_destroyed,
  106. };
  107. HRESULT vertexshader_init(struct d3d9_vertexshader *shader, struct d3d9_device *device, const DWORD *byte_code)
  108. {
  109. HRESULT hr;
  110. shader->refcount = 1;
  111. shader->IDirect3DVertexShader9_iface.lpVtbl = &d3d9_vertexshader_vtbl;
  112. wined3d_mutex_lock();
  113. hr = wined3d_shader_create_vs(device->wined3d_device, byte_code, NULL,
  114. shader, &d3d9_vertexshader_wined3d_parent_ops, &shader->wined3d_shader, 3);
  115. wined3d_mutex_unlock();
  116. if (FAILED(hr))
  117. {
  118. WARN("Failed to create wined3d vertex shader, hr %#x.\n", hr);
  119. return hr;
  120. }
  121. shader->parent_device = &device->IDirect3DDevice9Ex_iface;
  122. IDirect3DDevice9Ex_AddRef(shader->parent_device);
  123. return D3D_OK;
  124. }
  125. struct d3d9_vertexshader *unsafe_impl_from_IDirect3DVertexShader9(IDirect3DVertexShader9 *iface)
  126. {
  127. if (!iface)
  128. return NULL;
  129. assert(iface->lpVtbl == &d3d9_vertexshader_vtbl);
  130. return impl_from_IDirect3DVertexShader9(iface);
  131. }
  132. static inline struct d3d9_pixelshader *impl_from_IDirect3DPixelShader9(IDirect3DPixelShader9 *iface)
  133. {
  134. return CONTAINING_RECORD(iface, struct d3d9_pixelshader, IDirect3DPixelShader9_iface);
  135. }
  136. static HRESULT WINAPI d3d9_pixelshader_QueryInterface(IDirect3DPixelShader9 *iface, REFIID riid, void **out)
  137. {
  138. TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
  139. if (IsEqualGUID(riid, &IID_IDirect3DPixelShader9)
  140. || IsEqualGUID(riid, &IID_IUnknown))
  141. {
  142. IDirect3DPixelShader9_AddRef(iface);
  143. *out = iface;
  144. return S_OK;
  145. }
  146. WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
  147. *out = NULL;
  148. return E_NOINTERFACE;
  149. }
  150. static ULONG WINAPI d3d9_pixelshader_AddRef(IDirect3DPixelShader9 *iface)
  151. {
  152. struct d3d9_pixelshader *shader = impl_from_IDirect3DPixelShader9(iface);
  153. ULONG refcount = InterlockedIncrement(&shader->refcount);
  154. TRACE("%p increasing refcount to %u.\n", iface, refcount);
  155. if (refcount == 1)
  156. {
  157. IDirect3DDevice9Ex_AddRef(shader->parent_device);
  158. wined3d_mutex_lock();
  159. wined3d_shader_incref(shader->wined3d_shader);
  160. wined3d_mutex_unlock();
  161. }
  162. return refcount;
  163. }
  164. static ULONG WINAPI d3d9_pixelshader_Release(IDirect3DPixelShader9 *iface)
  165. {
  166. struct d3d9_pixelshader *shader = impl_from_IDirect3DPixelShader9(iface);
  167. ULONG refcount = InterlockedDecrement(&shader->refcount);
  168. TRACE("%p decreasing refcount to %u.\n", iface, refcount);
  169. if (!refcount)
  170. {
  171. IDirect3DDevice9Ex *device = shader->parent_device;
  172. wined3d_mutex_lock();
  173. wined3d_shader_decref(shader->wined3d_shader);
  174. wined3d_mutex_unlock();
  175. /* Release the device last, as it may cause the device to be destroyed. */
  176. IDirect3DDevice9Ex_Release(device);
  177. }
  178. return refcount;
  179. }
  180. static HRESULT WINAPI d3d9_pixelshader_GetDevice(IDirect3DPixelShader9 *iface, IDirect3DDevice9 **device)
  181. {
  182. struct d3d9_pixelshader *shader = impl_from_IDirect3DPixelShader9(iface);
  183. TRACE("iface %p, device %p.\n", iface, device);
  184. *device = (IDirect3DDevice9 *)shader->parent_device;
  185. IDirect3DDevice9_AddRef(*device);
  186. TRACE("Returning device %p.\n", *device);
  187. return D3D_OK;
  188. }
  189. static HRESULT WINAPI d3d9_pixelshader_GetFunction(IDirect3DPixelShader9 *iface, void *data, UINT *data_size)
  190. {
  191. struct d3d9_pixelshader *shader = impl_from_IDirect3DPixelShader9(iface);
  192. HRESULT hr;
  193. TRACE("iface %p, data %p, data_size %p.\n", iface, data, data_size);
  194. wined3d_mutex_lock();
  195. hr = wined3d_shader_get_byte_code(shader->wined3d_shader, data, data_size);
  196. wined3d_mutex_unlock();
  197. return hr;
  198. }
  199. static const IDirect3DPixelShader9Vtbl d3d9_pixelshader_vtbl =
  200. {
  201. /* IUnknown */
  202. d3d9_pixelshader_QueryInterface,
  203. d3d9_pixelshader_AddRef,
  204. d3d9_pixelshader_Release,
  205. /* IDirect3DPixelShader9 */
  206. d3d9_pixelshader_GetDevice,
  207. d3d9_pixelshader_GetFunction,
  208. };
  209. static void STDMETHODCALLTYPE d3d9_pixelshader_wined3d_object_destroyed(void *parent)
  210. {
  211. HeapFree(GetProcessHeap(), 0, parent);
  212. }
  213. static const struct wined3d_parent_ops d3d9_pixelshader_wined3d_parent_ops =
  214. {
  215. d3d9_pixelshader_wined3d_object_destroyed,
  216. };
  217. HRESULT pixelshader_init(struct d3d9_pixelshader *shader, struct d3d9_device *device, const DWORD *byte_code)
  218. {
  219. HRESULT hr;
  220. shader->refcount = 1;
  221. shader->IDirect3DPixelShader9_iface.lpVtbl = &d3d9_pixelshader_vtbl;
  222. wined3d_mutex_lock();
  223. hr = wined3d_shader_create_ps(device->wined3d_device, byte_code, NULL, shader,
  224. &d3d9_pixelshader_wined3d_parent_ops, &shader->wined3d_shader, 3);
  225. wined3d_mutex_unlock();
  226. if (FAILED(hr))
  227. {
  228. WARN("Failed to created wined3d pixel shader, hr %#x.\n", hr);
  229. return hr;
  230. }
  231. shader->parent_device = &device->IDirect3DDevice9Ex_iface;
  232. IDirect3DDevice9Ex_AddRef(shader->parent_device);
  233. return D3D_OK;
  234. }
  235. struct d3d9_pixelshader *unsafe_impl_from_IDirect3DPixelShader9(IDirect3DPixelShader9 *iface)
  236. {
  237. if (!iface)
  238. return NULL;
  239. assert(iface->lpVtbl == &d3d9_pixelshader_vtbl);
  240. return impl_from_IDirect3DPixelShader9(iface);
  241. }