1 /* 2 * IDirect3DDevice9 implementation 3 * 4 * Copyright 2002-2005 Jason Edmeades 5 * Copyright 2002-2005 Raphael Junqueira 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 void STDMETHODCALLTYPE d3d9_null_wined3d_object_destroyed(void *parent) {} 29 30 const struct wined3d_parent_ops d3d9_null_wined3d_parent_ops = 31 { 32 d3d9_null_wined3d_object_destroyed, 33 }; 34 35 D3DFORMAT d3dformat_from_wined3dformat(enum wined3d_format_id format) 36 { 37 BYTE *c = (BYTE *)&format; 38 39 /* Don't translate FOURCC formats */ 40 if (isprint(c[0]) && isprint(c[1]) && isprint(c[2]) && isprint(c[3])) return format; 41 42 switch(format) 43 { 44 case WINED3DFMT_UNKNOWN: return D3DFMT_UNKNOWN; 45 case WINED3DFMT_B8G8R8_UNORM: return D3DFMT_R8G8B8; 46 case WINED3DFMT_B8G8R8A8_UNORM: return D3DFMT_A8R8G8B8; 47 case WINED3DFMT_B8G8R8X8_UNORM: return D3DFMT_X8R8G8B8; 48 case WINED3DFMT_B5G6R5_UNORM: return D3DFMT_R5G6B5; 49 case WINED3DFMT_B5G5R5X1_UNORM: return D3DFMT_X1R5G5B5; 50 case WINED3DFMT_B5G5R5A1_UNORM: return D3DFMT_A1R5G5B5; 51 case WINED3DFMT_B4G4R4A4_UNORM: return D3DFMT_A4R4G4B4; 52 case WINED3DFMT_B2G3R3_UNORM: return D3DFMT_R3G3B2; 53 case WINED3DFMT_A8_UNORM: return D3DFMT_A8; 54 case WINED3DFMT_B2G3R3A8_UNORM: return D3DFMT_A8R3G3B2; 55 case WINED3DFMT_B4G4R4X4_UNORM: return D3DFMT_X4R4G4B4; 56 case WINED3DFMT_R10G10B10A2_UNORM: return D3DFMT_A2B10G10R10; 57 case WINED3DFMT_R8G8B8A8_UNORM: return D3DFMT_A8B8G8R8; 58 case WINED3DFMT_R8G8B8X8_UNORM: return D3DFMT_X8B8G8R8; 59 case WINED3DFMT_R16G16_UNORM: return D3DFMT_G16R16; 60 case WINED3DFMT_B10G10R10A2_UNORM: return D3DFMT_A2R10G10B10; 61 case WINED3DFMT_R16G16B16A16_UNORM: return D3DFMT_A16B16G16R16; 62 case WINED3DFMT_P8_UINT_A8_UNORM: return D3DFMT_A8P8; 63 case WINED3DFMT_P8_UINT: return D3DFMT_P8; 64 case WINED3DFMT_L8_UNORM: return D3DFMT_L8; 65 case WINED3DFMT_L8A8_UNORM: return D3DFMT_A8L8; 66 case WINED3DFMT_L4A4_UNORM: return D3DFMT_A4L4; 67 case WINED3DFMT_R8G8_SNORM: return D3DFMT_V8U8; 68 case WINED3DFMT_R5G5_SNORM_L6_UNORM: return D3DFMT_L6V5U5; 69 case WINED3DFMT_R8G8_SNORM_L8X8_UNORM: return D3DFMT_X8L8V8U8; 70 case WINED3DFMT_R8G8B8A8_SNORM: return D3DFMT_Q8W8V8U8; 71 case WINED3DFMT_R16G16_SNORM: return D3DFMT_V16U16; 72 case WINED3DFMT_R10G10B10_SNORM_A2_UNORM: return D3DFMT_A2W10V10U10; 73 case WINED3DFMT_D16_LOCKABLE: return D3DFMT_D16_LOCKABLE; 74 case WINED3DFMT_D32_UNORM: return D3DFMT_D32; 75 case WINED3DFMT_S1_UINT_D15_UNORM: return D3DFMT_D15S1; 76 case WINED3DFMT_D24_UNORM_S8_UINT: return D3DFMT_D24S8; 77 case WINED3DFMT_X8D24_UNORM: return D3DFMT_D24X8; 78 case WINED3DFMT_S4X4_UINT_D24_UNORM: return D3DFMT_D24X4S4; 79 case WINED3DFMT_D16_UNORM: return D3DFMT_D16; 80 case WINED3DFMT_L16_UNORM: return D3DFMT_L16; 81 case WINED3DFMT_D32_FLOAT: return D3DFMT_D32F_LOCKABLE; 82 case WINED3DFMT_S8_UINT_D24_FLOAT: return D3DFMT_D24FS8; 83 case WINED3DFMT_R16_UINT: return D3DFMT_INDEX16; 84 case WINED3DFMT_R32_UINT: return D3DFMT_INDEX32; 85 case WINED3DFMT_R16G16B16A16_SNORM: return D3DFMT_Q16W16V16U16; 86 case WINED3DFMT_R16_FLOAT: return D3DFMT_R16F; 87 case WINED3DFMT_R16G16_FLOAT: return D3DFMT_G16R16F; 88 case WINED3DFMT_R16G16B16A16_FLOAT: return D3DFMT_A16B16G16R16F; 89 case WINED3DFMT_R32_FLOAT: return D3DFMT_R32F; 90 case WINED3DFMT_R32G32_FLOAT: return D3DFMT_G32R32F; 91 case WINED3DFMT_R32G32B32A32_FLOAT: return D3DFMT_A32B32G32R32F; 92 case WINED3DFMT_R8G8_SNORM_Cx: return D3DFMT_CxV8U8; 93 default: 94 FIXME("Unhandled wined3d format %#x.\n", format); 95 return D3DFMT_UNKNOWN; 96 } 97 } 98 99 enum wined3d_format_id wined3dformat_from_d3dformat(D3DFORMAT format) 100 { 101 BYTE *c = (BYTE *)&format; 102 103 /* Don't translate FOURCC formats */ 104 if (isprint(c[0]) && isprint(c[1]) && isprint(c[2]) && isprint(c[3])) return format; 105 106 switch(format) 107 { 108 case D3DFMT_UNKNOWN: return WINED3DFMT_UNKNOWN; 109 case D3DFMT_R8G8B8: return WINED3DFMT_B8G8R8_UNORM; 110 case D3DFMT_A8R8G8B8: return WINED3DFMT_B8G8R8A8_UNORM; 111 case D3DFMT_X8R8G8B8: return WINED3DFMT_B8G8R8X8_UNORM; 112 case D3DFMT_R5G6B5: return WINED3DFMT_B5G6R5_UNORM; 113 case D3DFMT_X1R5G5B5: return WINED3DFMT_B5G5R5X1_UNORM; 114 case D3DFMT_A1R5G5B5: return WINED3DFMT_B5G5R5A1_UNORM; 115 case D3DFMT_A4R4G4B4: return WINED3DFMT_B4G4R4A4_UNORM; 116 case D3DFMT_R3G3B2: return WINED3DFMT_B2G3R3_UNORM; 117 case D3DFMT_A8: return WINED3DFMT_A8_UNORM; 118 case D3DFMT_A8R3G3B2: return WINED3DFMT_B2G3R3A8_UNORM; 119 case D3DFMT_X4R4G4B4: return WINED3DFMT_B4G4R4X4_UNORM; 120 case D3DFMT_A2B10G10R10: return WINED3DFMT_R10G10B10A2_UNORM; 121 case D3DFMT_A8B8G8R8: return WINED3DFMT_R8G8B8A8_UNORM; 122 case D3DFMT_X8B8G8R8: return WINED3DFMT_R8G8B8X8_UNORM; 123 case D3DFMT_G16R16: return WINED3DFMT_R16G16_UNORM; 124 case D3DFMT_A2R10G10B10: return WINED3DFMT_B10G10R10A2_UNORM; 125 case D3DFMT_A16B16G16R16: return WINED3DFMT_R16G16B16A16_UNORM; 126 case D3DFMT_A8P8: return WINED3DFMT_P8_UINT_A8_UNORM; 127 case D3DFMT_P8: return WINED3DFMT_P8_UINT; 128 case D3DFMT_L8: return WINED3DFMT_L8_UNORM; 129 case D3DFMT_A8L8: return WINED3DFMT_L8A8_UNORM; 130 case D3DFMT_A4L4: return WINED3DFMT_L4A4_UNORM; 131 case D3DFMT_V8U8: return WINED3DFMT_R8G8_SNORM; 132 case D3DFMT_L6V5U5: return WINED3DFMT_R5G5_SNORM_L6_UNORM; 133 case D3DFMT_X8L8V8U8: return WINED3DFMT_R8G8_SNORM_L8X8_UNORM; 134 case D3DFMT_Q8W8V8U8: return WINED3DFMT_R8G8B8A8_SNORM; 135 case D3DFMT_V16U16: return WINED3DFMT_R16G16_SNORM; 136 case D3DFMT_A2W10V10U10: return WINED3DFMT_R10G10B10_SNORM_A2_UNORM; 137 case D3DFMT_D16_LOCKABLE: return WINED3DFMT_D16_LOCKABLE; 138 case D3DFMT_D32: return WINED3DFMT_D32_UNORM; 139 case D3DFMT_D15S1: return WINED3DFMT_S1_UINT_D15_UNORM; 140 case D3DFMT_D24S8: return WINED3DFMT_D24_UNORM_S8_UINT; 141 case D3DFMT_D24X8: return WINED3DFMT_X8D24_UNORM; 142 case D3DFMT_D24X4S4: return WINED3DFMT_S4X4_UINT_D24_UNORM; 143 case D3DFMT_D16: return WINED3DFMT_D16_UNORM; 144 case D3DFMT_L16: return WINED3DFMT_L16_UNORM; 145 case D3DFMT_D32F_LOCKABLE: return WINED3DFMT_D32_FLOAT; 146 case D3DFMT_D24FS8: return WINED3DFMT_S8_UINT_D24_FLOAT; 147 case D3DFMT_INDEX16: return WINED3DFMT_R16_UINT; 148 case D3DFMT_INDEX32: return WINED3DFMT_R32_UINT; 149 case D3DFMT_Q16W16V16U16: return WINED3DFMT_R16G16B16A16_SNORM; 150 case D3DFMT_R16F: return WINED3DFMT_R16_FLOAT; 151 case D3DFMT_G16R16F: return WINED3DFMT_R16G16_FLOAT; 152 case D3DFMT_A16B16G16R16F: return WINED3DFMT_R16G16B16A16_FLOAT; 153 case D3DFMT_R32F: return WINED3DFMT_R32_FLOAT; 154 case D3DFMT_G32R32F: return WINED3DFMT_R32G32_FLOAT; 155 case D3DFMT_A32B32G32R32F: return WINED3DFMT_R32G32B32A32_FLOAT; 156 case D3DFMT_CxV8U8: return WINED3DFMT_R8G8_SNORM_Cx; 157 default: 158 FIXME("Unhandled D3DFORMAT %#x.\n", format); 159 return WINED3DFMT_UNKNOWN; 160 } 161 } 162 163 unsigned int wined3dmapflags_from_d3dmapflags(unsigned int flags) 164 { 165 static const unsigned int handled = D3DLOCK_NOSYSLOCK 166 | D3DLOCK_NOOVERWRITE 167 | D3DLOCK_DISCARD 168 | D3DLOCK_DONOTWAIT 169 | D3DLOCK_NO_DIRTY_UPDATE; 170 unsigned int wined3d_flags; 171 172 wined3d_flags = flags & handled; 173 if (!(flags & (D3DLOCK_NOOVERWRITE | D3DLOCK_DISCARD))) 174 wined3d_flags |= WINED3D_MAP_READ; 175 if (!(flags & D3DLOCK_READONLY)) 176 wined3d_flags |= WINED3D_MAP_WRITE; 177 if (!(wined3d_flags & (WINED3D_MAP_READ | WINED3D_MAP_WRITE))) 178 wined3d_flags |= WINED3D_MAP_READ | WINED3D_MAP_WRITE; 179 flags &= ~(handled | D3DLOCK_READONLY); 180 181 if (flags) 182 FIXME("Unhandled flags %#x.\n", flags); 183 184 return wined3d_flags; 185 } 186 187 static UINT vertex_count_from_primitive_count(D3DPRIMITIVETYPE primitive_type, UINT primitive_count) 188 { 189 switch (primitive_type) 190 { 191 case D3DPT_POINTLIST: 192 return primitive_count; 193 194 case D3DPT_LINELIST: 195 return primitive_count * 2; 196 197 case D3DPT_LINESTRIP: 198 return primitive_count + 1; 199 200 case D3DPT_TRIANGLELIST: 201 return primitive_count * 3; 202 203 case D3DPT_TRIANGLESTRIP: 204 case D3DPT_TRIANGLEFAN: 205 return primitive_count + 2; 206 207 default: 208 FIXME("Unhandled primitive type %#x.\n", primitive_type); 209 return 0; 210 } 211 } 212 213 static D3DSWAPEFFECT d3dswapeffect_from_wined3dswapeffect(enum wined3d_swap_effect effect) 214 { 215 switch (effect) 216 { 217 case WINED3D_SWAP_EFFECT_DISCARD: 218 return D3DSWAPEFFECT_DISCARD; 219 case WINED3D_SWAP_EFFECT_SEQUENTIAL: 220 return D3DSWAPEFFECT_FLIP; 221 case WINED3D_SWAP_EFFECT_COPY: 222 return D3DSWAPEFFECT_COPY; 223 case WINED3D_SWAP_EFFECT_OVERLAY: 224 return D3DSWAPEFFECT_OVERLAY; 225 case WINED3D_SWAP_EFFECT_FLIP_SEQUENTIAL: 226 return D3DSWAPEFFECT_FLIPEX; 227 default: 228 FIXME("Unhandled swap effect %#x.\n", effect); 229 return D3DSWAPEFFECT_FLIP; 230 } 231 } 232 233 void present_parameters_from_wined3d_swapchain_desc(D3DPRESENT_PARAMETERS *present_parameters, 234 const struct wined3d_swapchain_desc *swapchain_desc) 235 { 236 present_parameters->BackBufferWidth = swapchain_desc->backbuffer_width; 237 present_parameters->BackBufferHeight = swapchain_desc->backbuffer_height; 238 present_parameters->BackBufferFormat = d3dformat_from_wined3dformat(swapchain_desc->backbuffer_format); 239 present_parameters->BackBufferCount = swapchain_desc->backbuffer_count; 240 present_parameters->MultiSampleType = swapchain_desc->multisample_type; 241 present_parameters->MultiSampleQuality = swapchain_desc->multisample_quality; 242 present_parameters->SwapEffect = d3dswapeffect_from_wined3dswapeffect(swapchain_desc->swap_effect); 243 present_parameters->hDeviceWindow = swapchain_desc->device_window; 244 present_parameters->Windowed = swapchain_desc->windowed; 245 present_parameters->EnableAutoDepthStencil = swapchain_desc->enable_auto_depth_stencil; 246 present_parameters->AutoDepthStencilFormat 247 = d3dformat_from_wined3dformat(swapchain_desc->auto_depth_stencil_format); 248 present_parameters->Flags = swapchain_desc->flags & D3DPRESENTFLAGS_MASK; 249 present_parameters->FullScreen_RefreshRateInHz = swapchain_desc->refresh_rate; 250 present_parameters->PresentationInterval = swapchain_desc->swap_interval; 251 } 252 253 static enum wined3d_swap_effect wined3dswapeffect_from_d3dswapeffect(D3DSWAPEFFECT effect) 254 { 255 switch (effect) 256 { 257 case D3DSWAPEFFECT_DISCARD: 258 return WINED3D_SWAP_EFFECT_DISCARD; 259 case D3DSWAPEFFECT_FLIP: 260 return WINED3D_SWAP_EFFECT_SEQUENTIAL; 261 case D3DSWAPEFFECT_COPY: 262 return WINED3D_SWAP_EFFECT_COPY; 263 case D3DSWAPEFFECT_OVERLAY: 264 return WINED3D_SWAP_EFFECT_OVERLAY; 265 case D3DSWAPEFFECT_FLIPEX: 266 return WINED3D_SWAP_EFFECT_FLIP_SEQUENTIAL; 267 default: 268 FIXME("Unhandled swap effect %#x.\n", effect); 269 return WINED3D_SWAP_EFFECT_SEQUENTIAL; 270 } 271 } 272 273 static BOOL wined3d_swapchain_desc_from_present_parameters(struct wined3d_swapchain_desc *swapchain_desc, 274 const D3DPRESENT_PARAMETERS *present_parameters, BOOL extended) 275 { 276 D3DSWAPEFFECT highest_swapeffect = extended ? D3DSWAPEFFECT_FLIPEX : D3DSWAPEFFECT_COPY; 277 UINT highest_bb_count = extended ? 30 : 3; 278 279 if (!present_parameters->SwapEffect || present_parameters->SwapEffect > highest_swapeffect) 280 { 281 WARN("Invalid swap effect %u passed.\n", present_parameters->SwapEffect); 282 return FALSE; 283 } 284 if (present_parameters->BackBufferCount > highest_bb_count 285 || (present_parameters->SwapEffect == D3DSWAPEFFECT_COPY 286 && present_parameters->BackBufferCount > 1)) 287 { 288 WARN("Invalid backbuffer count %u.\n", present_parameters->BackBufferCount); 289 return FALSE; 290 } 291 292 swapchain_desc->backbuffer_width = present_parameters->BackBufferWidth; 293 swapchain_desc->backbuffer_height = present_parameters->BackBufferHeight; 294 swapchain_desc->backbuffer_format = wined3dformat_from_d3dformat(present_parameters->BackBufferFormat); 295 swapchain_desc->backbuffer_count = max(1, present_parameters->BackBufferCount); 296 swapchain_desc->backbuffer_usage = WINED3DUSAGE_RENDERTARGET; 297 swapchain_desc->multisample_type = present_parameters->MultiSampleType; 298 swapchain_desc->multisample_quality = present_parameters->MultiSampleQuality; 299 swapchain_desc->swap_effect = wined3dswapeffect_from_d3dswapeffect(present_parameters->SwapEffect); 300 swapchain_desc->device_window = present_parameters->hDeviceWindow; 301 swapchain_desc->windowed = present_parameters->Windowed; 302 swapchain_desc->enable_auto_depth_stencil = present_parameters->EnableAutoDepthStencil; 303 swapchain_desc->auto_depth_stencil_format 304 = wined3dformat_from_d3dformat(present_parameters->AutoDepthStencilFormat); 305 swapchain_desc->flags 306 = (present_parameters->Flags & D3DPRESENTFLAGS_MASK) | WINED3D_SWAPCHAIN_ALLOW_MODE_SWITCH; 307 swapchain_desc->refresh_rate = present_parameters->FullScreen_RefreshRateInHz; 308 swapchain_desc->swap_interval = present_parameters->PresentationInterval; 309 swapchain_desc->auto_restore_display_mode = TRUE; 310 311 if (present_parameters->Flags & ~D3DPRESENTFLAGS_MASK) 312 FIXME("Unhandled flags %#x.\n", present_parameters->Flags & ~D3DPRESENTFLAGS_MASK); 313 314 return TRUE; 315 } 316 317 void d3dcaps_from_wined3dcaps(D3DCAPS9 *caps, const WINED3DCAPS *wined3d_caps) 318 { 319 static const DWORD ps_minor_version[] = {0, 4, 0, 0}; 320 static const DWORD vs_minor_version[] = {0, 1, 0, 0}; 321 static const DWORD texture_filter_caps = 322 D3DPTFILTERCAPS_MINFPOINT | D3DPTFILTERCAPS_MINFLINEAR | D3DPTFILTERCAPS_MINFANISOTROPIC | 323 D3DPTFILTERCAPS_MINFPYRAMIDALQUAD | D3DPTFILTERCAPS_MINFGAUSSIANQUAD| 324 D3DPTFILTERCAPS_MIPFPOINT | D3DPTFILTERCAPS_MIPFLINEAR | D3DPTFILTERCAPS_MAGFPOINT | 325 D3DPTFILTERCAPS_MAGFLINEAR |D3DPTFILTERCAPS_MAGFANISOTROPIC|D3DPTFILTERCAPS_MAGFPYRAMIDALQUAD| 326 D3DPTFILTERCAPS_MAGFGAUSSIANQUAD; 327 328 caps->DeviceType = (D3DDEVTYPE)wined3d_caps->DeviceType; 329 caps->AdapterOrdinal = wined3d_caps->AdapterOrdinal; 330 caps->Caps = wined3d_caps->Caps; 331 caps->Caps2 = wined3d_caps->Caps2; 332 caps->Caps3 = wined3d_caps->Caps3; 333 caps->PresentationIntervals = wined3d_caps->PresentationIntervals; 334 caps->CursorCaps = wined3d_caps->CursorCaps; 335 caps->DevCaps = wined3d_caps->DevCaps; 336 caps->PrimitiveMiscCaps = wined3d_caps->PrimitiveMiscCaps; 337 caps->RasterCaps = wined3d_caps->RasterCaps; 338 caps->ZCmpCaps = wined3d_caps->ZCmpCaps; 339 caps->SrcBlendCaps = wined3d_caps->SrcBlendCaps; 340 caps->DestBlendCaps = wined3d_caps->DestBlendCaps; 341 caps->AlphaCmpCaps = wined3d_caps->AlphaCmpCaps; 342 caps->ShadeCaps = wined3d_caps->ShadeCaps; 343 caps->TextureCaps = wined3d_caps->TextureCaps; 344 caps->TextureFilterCaps = wined3d_caps->TextureFilterCaps; 345 caps->CubeTextureFilterCaps = wined3d_caps->CubeTextureFilterCaps; 346 caps->VolumeTextureFilterCaps = wined3d_caps->VolumeTextureFilterCaps; 347 caps->TextureAddressCaps = wined3d_caps->TextureAddressCaps; 348 caps->VolumeTextureAddressCaps = wined3d_caps->VolumeTextureAddressCaps; 349 caps->LineCaps = wined3d_caps->LineCaps; 350 caps->MaxTextureWidth = wined3d_caps->MaxTextureWidth; 351 caps->MaxTextureHeight = wined3d_caps->MaxTextureHeight; 352 caps->MaxVolumeExtent = wined3d_caps->MaxVolumeExtent; 353 caps->MaxTextureRepeat = wined3d_caps->MaxTextureRepeat; 354 caps->MaxTextureAspectRatio = wined3d_caps->MaxTextureAspectRatio; 355 caps->MaxAnisotropy = wined3d_caps->MaxAnisotropy; 356 caps->MaxVertexW = wined3d_caps->MaxVertexW; 357 caps->GuardBandLeft = wined3d_caps->GuardBandLeft; 358 caps->GuardBandTop = wined3d_caps->GuardBandTop; 359 caps->GuardBandRight = wined3d_caps->GuardBandRight; 360 caps->GuardBandBottom = wined3d_caps->GuardBandBottom; 361 caps->ExtentsAdjust = wined3d_caps->ExtentsAdjust; 362 caps->StencilCaps = wined3d_caps->StencilCaps; 363 caps->FVFCaps = wined3d_caps->FVFCaps; 364 caps->TextureOpCaps = wined3d_caps->TextureOpCaps; 365 caps->MaxTextureBlendStages = wined3d_caps->MaxTextureBlendStages; 366 caps->MaxSimultaneousTextures = wined3d_caps->MaxSimultaneousTextures; 367 caps->VertexProcessingCaps = wined3d_caps->VertexProcessingCaps; 368 caps->MaxActiveLights = wined3d_caps->MaxActiveLights; 369 caps->MaxUserClipPlanes = wined3d_caps->MaxUserClipPlanes; 370 caps->MaxVertexBlendMatrices = wined3d_caps->MaxVertexBlendMatrices; 371 caps->MaxVertexBlendMatrixIndex = wined3d_caps->MaxVertexBlendMatrixIndex; 372 caps->MaxPointSize = wined3d_caps->MaxPointSize; 373 caps->MaxPrimitiveCount = wined3d_caps->MaxPrimitiveCount; 374 caps->MaxVertexIndex = wined3d_caps->MaxVertexIndex; 375 caps->MaxStreams = wined3d_caps->MaxStreams; 376 caps->MaxStreamStride = wined3d_caps->MaxStreamStride; 377 caps->VertexShaderVersion = wined3d_caps->VertexShaderVersion; 378 caps->MaxVertexShaderConst = wined3d_caps->MaxVertexShaderConst; 379 caps->PixelShaderVersion = wined3d_caps->PixelShaderVersion; 380 caps->PixelShader1xMaxValue = wined3d_caps->PixelShader1xMaxValue; 381 caps->DevCaps2 = wined3d_caps->DevCaps2; 382 caps->MaxNpatchTessellationLevel = wined3d_caps->MaxNpatchTessellationLevel; 383 caps->MasterAdapterOrdinal = wined3d_caps->MasterAdapterOrdinal; 384 caps->AdapterOrdinalInGroup = wined3d_caps->AdapterOrdinalInGroup; 385 caps->NumberOfAdaptersInGroup = wined3d_caps->NumberOfAdaptersInGroup; 386 caps->DeclTypes = wined3d_caps->DeclTypes; 387 caps->NumSimultaneousRTs = wined3d_caps->NumSimultaneousRTs; 388 caps->StretchRectFilterCaps = wined3d_caps->StretchRectFilterCaps; 389 caps->VS20Caps.Caps = wined3d_caps->VS20Caps.caps; 390 caps->VS20Caps.DynamicFlowControlDepth = wined3d_caps->VS20Caps.dynamic_flow_control_depth; 391 caps->VS20Caps.NumTemps = wined3d_caps->VS20Caps.temp_count; 392 caps->VS20Caps.StaticFlowControlDepth = wined3d_caps->VS20Caps.static_flow_control_depth; 393 caps->PS20Caps.Caps = wined3d_caps->PS20Caps.caps; 394 caps->PS20Caps.DynamicFlowControlDepth = wined3d_caps->PS20Caps.dynamic_flow_control_depth; 395 caps->PS20Caps.NumTemps = wined3d_caps->PS20Caps.temp_count; 396 caps->PS20Caps.StaticFlowControlDepth = wined3d_caps->PS20Caps.static_flow_control_depth; 397 caps->PS20Caps.NumInstructionSlots = wined3d_caps->PS20Caps.instruction_slot_count; 398 caps->VertexTextureFilterCaps = wined3d_caps->VertexTextureFilterCaps; 399 caps->MaxVShaderInstructionsExecuted = wined3d_caps->MaxVShaderInstructionsExecuted; 400 caps->MaxPShaderInstructionsExecuted = wined3d_caps->MaxPShaderInstructionsExecuted; 401 caps->MaxVertexShader30InstructionSlots = wined3d_caps->MaxVertexShader30InstructionSlots; 402 caps->MaxPixelShader30InstructionSlots = wined3d_caps->MaxPixelShader30InstructionSlots; 403 404 /* Some functionality is implemented in d3d9.dll, not wined3d.dll. Add the needed caps. */ 405 caps->DevCaps2 |= D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES; 406 407 /* Filter wined3d caps. */ 408 caps->TextureFilterCaps &= texture_filter_caps; 409 caps->CubeTextureFilterCaps &= texture_filter_caps; 410 caps->VolumeTextureFilterCaps &= texture_filter_caps; 411 412 caps->DevCaps &= 413 D3DDEVCAPS_EXECUTESYSTEMMEMORY | D3DDEVCAPS_EXECUTEVIDEOMEMORY | D3DDEVCAPS_TLVERTEXSYSTEMMEMORY | 414 D3DDEVCAPS_TLVERTEXVIDEOMEMORY | D3DDEVCAPS_TEXTURESYSTEMMEMORY| D3DDEVCAPS_TEXTUREVIDEOMEMORY | 415 D3DDEVCAPS_DRAWPRIMTLVERTEX | D3DDEVCAPS_CANRENDERAFTERFLIP | D3DDEVCAPS_TEXTURENONLOCALVIDMEM| 416 D3DDEVCAPS_DRAWPRIMITIVES2 | D3DDEVCAPS_SEPARATETEXTUREMEMORIES | 417 D3DDEVCAPS_DRAWPRIMITIVES2EX | D3DDEVCAPS_HWTRANSFORMANDLIGHT| D3DDEVCAPS_CANBLTSYSTONONLOCAL | 418 D3DDEVCAPS_HWRASTERIZATION | D3DDEVCAPS_PUREDEVICE | D3DDEVCAPS_QUINTICRTPATCHES | 419 D3DDEVCAPS_RTPATCHES | D3DDEVCAPS_RTPATCHHANDLEZERO | D3DDEVCAPS_NPATCHES; 420 421 caps->ShadeCaps &= 422 D3DPSHADECAPS_COLORGOURAUDRGB | D3DPSHADECAPS_SPECULARGOURAUDRGB | 423 D3DPSHADECAPS_ALPHAGOURAUDBLEND | D3DPSHADECAPS_FOGGOURAUD; 424 425 caps->RasterCaps &= 426 D3DPRASTERCAPS_DITHER | D3DPRASTERCAPS_ZTEST | D3DPRASTERCAPS_FOGVERTEX | 427 D3DPRASTERCAPS_FOGTABLE | D3DPRASTERCAPS_MIPMAPLODBIAS | D3DPRASTERCAPS_ZBUFFERLESSHSR | 428 D3DPRASTERCAPS_FOGRANGE | D3DPRASTERCAPS_ANISOTROPY | D3DPRASTERCAPS_WBUFFER | 429 D3DPRASTERCAPS_WFOG | D3DPRASTERCAPS_ZFOG | D3DPRASTERCAPS_COLORPERSPECTIVE | 430 D3DPRASTERCAPS_SCISSORTEST | D3DPRASTERCAPS_SLOPESCALEDEPTHBIAS | 431 D3DPRASTERCAPS_DEPTHBIAS | D3DPRASTERCAPS_MULTISAMPLE_TOGGLE; 432 433 caps->DevCaps2 &= 434 D3DDEVCAPS2_STREAMOFFSET | D3DDEVCAPS2_DMAPNPATCH | D3DDEVCAPS2_ADAPTIVETESSRTPATCH | 435 D3DDEVCAPS2_ADAPTIVETESSNPATCH | D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES | 436 D3DDEVCAPS2_PRESAMPLEDDMAPNPATCH| D3DDEVCAPS2_VERTEXELEMENTSCANSHARESTREAMOFFSET; 437 438 caps->Caps2 &= 439 D3DCAPS2_FULLSCREENGAMMA | D3DCAPS2_CANCALIBRATEGAMMA | D3DCAPS2_RESERVED | 440 D3DCAPS2_CANMANAGERESOURCE | D3DCAPS2_DYNAMICTEXTURES | D3DCAPS2_CANAUTOGENMIPMAP; 441 442 caps->VertexProcessingCaps &= 443 D3DVTXPCAPS_TEXGEN | D3DVTXPCAPS_MATERIALSOURCE7 | D3DVTXPCAPS_DIRECTIONALLIGHTS | 444 D3DVTXPCAPS_POSITIONALLIGHTS | D3DVTXPCAPS_LOCALVIEWER | D3DVTXPCAPS_TWEENING | 445 D3DVTXPCAPS_TEXGEN_SPHEREMAP | D3DVTXPCAPS_NO_TEXGEN_NONLOCALVIEWER; 446 447 caps->TextureCaps &= 448 D3DPTEXTURECAPS_PERSPECTIVE | D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_ALPHA | 449 D3DPTEXTURECAPS_SQUAREONLY | D3DPTEXTURECAPS_TEXREPEATNOTSCALEDBYSIZE | 450 D3DPTEXTURECAPS_ALPHAPALETTE | D3DPTEXTURECAPS_NONPOW2CONDITIONAL | 451 D3DPTEXTURECAPS_PROJECTED | D3DPTEXTURECAPS_CUBEMAP | D3DPTEXTURECAPS_VOLUMEMAP | 452 D3DPTEXTURECAPS_MIPMAP | D3DPTEXTURECAPS_MIPVOLUMEMAP | D3DPTEXTURECAPS_MIPCUBEMAP | 453 D3DPTEXTURECAPS_CUBEMAP_POW2 | D3DPTEXTURECAPS_VOLUMEMAP_POW2| D3DPTEXTURECAPS_NOPROJECTEDBUMPENV; 454 455 caps->MaxVertexShaderConst = min(D3D9_MAX_VERTEX_SHADER_CONSTANTF, caps->MaxVertexShaderConst); 456 caps->NumSimultaneousRTs = min(D3D_MAX_SIMULTANEOUS_RENDERTARGETS, caps->NumSimultaneousRTs); 457 458 if (caps->PixelShaderVersion > 3) 459 { 460 caps->PixelShaderVersion = D3DPS_VERSION(3, 0); 461 } 462 else 463 { 464 DWORD major = caps->PixelShaderVersion; 465 caps->PixelShaderVersion = D3DPS_VERSION(major, ps_minor_version[major]); 466 } 467 468 if (caps->VertexShaderVersion > 3) 469 { 470 caps->VertexShaderVersion = D3DVS_VERSION(3, 0); 471 } 472 else 473 { 474 DWORD major = caps->VertexShaderVersion; 475 caps->VertexShaderVersion = D3DVS_VERSION(major, vs_minor_version[major]); 476 } 477 } 478 479 static HRESULT WINAPI d3d9_device_QueryInterface(IDirect3DDevice9Ex *iface, REFIID riid, void **out) 480 { 481 TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out); 482 483 if (IsEqualGUID(riid, &IID_IDirect3DDevice9) 484 || IsEqualGUID(riid, &IID_IUnknown)) 485 { 486 IDirect3DDevice9Ex_AddRef(iface); 487 *out = iface; 488 return S_OK; 489 } 490 491 if (IsEqualGUID(riid, &IID_IDirect3DDevice9Ex)) 492 { 493 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 494 495 /* Find out if the creating d3d9 interface was created with Direct3DCreate9Ex. 496 * It doesn't matter with which function the device was created. */ 497 if (!device->d3d_parent->extended) 498 { 499 WARN("IDirect3D9 instance wasn't created with CreateDirect3D9Ex, returning E_NOINTERFACE.\n"); 500 *out = NULL; 501 return E_NOINTERFACE; 502 } 503 504 IDirect3DDevice9Ex_AddRef(iface); 505 *out = iface; 506 return S_OK; 507 } 508 509 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid)); 510 511 *out = NULL; 512 return E_NOINTERFACE; 513 } 514 515 static ULONG WINAPI d3d9_device_AddRef(IDirect3DDevice9Ex *iface) 516 { 517 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 518 ULONG refcount = InterlockedIncrement(&device->refcount); 519 520 TRACE("%p increasing refcount to %u.\n", iface, refcount); 521 522 return refcount; 523 } 524 525 static ULONG WINAPI DECLSPEC_HOTPATCH d3d9_device_Release(IDirect3DDevice9Ex *iface) 526 { 527 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 528 ULONG refcount; 529 530 if (device->in_destruction) 531 return 0; 532 533 refcount = InterlockedDecrement(&device->refcount); 534 535 TRACE("%p decreasing refcount to %u.\n", iface, refcount); 536 537 if (!refcount) 538 { 539 unsigned i; 540 device->in_destruction = TRUE; 541 542 wined3d_mutex_lock(); 543 for (i = 0; i < device->fvf_decl_count; ++i) 544 { 545 wined3d_vertex_declaration_decref(device->fvf_decls[i].decl); 546 } 547 heap_free(device->fvf_decls); 548 549 if (device->vertex_buffer) 550 wined3d_buffer_decref(device->vertex_buffer); 551 if (device->index_buffer) 552 wined3d_buffer_decref(device->index_buffer); 553 554 heap_free(device->implicit_swapchains); 555 556 wined3d_device_uninit_3d(device->wined3d_device); 557 wined3d_device_release_focus_window(device->wined3d_device); 558 wined3d_device_decref(device->wined3d_device); 559 wined3d_mutex_unlock(); 560 561 IDirect3D9Ex_Release(&device->d3d_parent->IDirect3D9Ex_iface); 562 563 heap_free(device); 564 } 565 566 return refcount; 567 } 568 569 static HRESULT WINAPI d3d9_device_TestCooperativeLevel(IDirect3DDevice9Ex *iface) 570 { 571 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 572 573 TRACE("iface %p.\n", iface); 574 575 TRACE("device state: %#x.\n", device->device_state); 576 577 if (device->d3d_parent->extended) 578 return D3D_OK; 579 580 switch (device->device_state) 581 { 582 default: 583 case D3D9_DEVICE_STATE_OK: 584 return D3D_OK; 585 case D3D9_DEVICE_STATE_LOST: 586 return D3DERR_DEVICELOST; 587 case D3D9_DEVICE_STATE_NOT_RESET: 588 return D3DERR_DEVICENOTRESET; 589 } 590 } 591 592 static UINT WINAPI d3d9_device_GetAvailableTextureMem(IDirect3DDevice9Ex *iface) 593 { 594 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 595 UINT ret; 596 597 TRACE("iface %p.\n", iface); 598 599 wined3d_mutex_lock(); 600 ret = wined3d_device_get_available_texture_mem(device->wined3d_device); 601 wined3d_mutex_unlock(); 602 603 return ret; 604 } 605 606 static HRESULT WINAPI d3d9_device_EvictManagedResources(IDirect3DDevice9Ex *iface) 607 { 608 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 609 610 TRACE("iface %p.\n", iface); 611 612 wined3d_mutex_lock(); 613 wined3d_device_evict_managed_resources(device->wined3d_device); 614 wined3d_mutex_unlock(); 615 616 return D3D_OK; 617 } 618 619 static HRESULT WINAPI d3d9_device_GetDirect3D(IDirect3DDevice9Ex *iface, IDirect3D9 **d3d9) 620 { 621 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 622 623 TRACE("iface %p, d3d9 %p.\n", iface, d3d9); 624 625 if (!d3d9) 626 return D3DERR_INVALIDCALL; 627 628 return IDirect3D9Ex_QueryInterface(&device->d3d_parent->IDirect3D9Ex_iface, &IID_IDirect3D9, (void **)d3d9); 629 } 630 631 static HRESULT WINAPI d3d9_device_GetDeviceCaps(IDirect3DDevice9Ex *iface, D3DCAPS9 *caps) 632 { 633 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 634 WINED3DCAPS wined3d_caps; 635 HRESULT hr; 636 637 TRACE("iface %p, caps %p.\n", iface, caps); 638 639 if (!caps) 640 return D3DERR_INVALIDCALL; 641 642 memset(caps, 0, sizeof(*caps)); 643 644 wined3d_mutex_lock(); 645 hr = wined3d_device_get_device_caps(device->wined3d_device, &wined3d_caps); 646 wined3d_mutex_unlock(); 647 648 d3dcaps_from_wined3dcaps(caps, &wined3d_caps); 649 650 return hr; 651 } 652 653 static HRESULT WINAPI d3d9_device_GetDisplayMode(IDirect3DDevice9Ex *iface, UINT swapchain, D3DDISPLAYMODE *mode) 654 { 655 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 656 struct wined3d_display_mode wined3d_mode; 657 HRESULT hr; 658 659 TRACE("iface %p, swapchain %u, mode %p.\n", iface, swapchain, mode); 660 661 wined3d_mutex_lock(); 662 hr = wined3d_device_get_display_mode(device->wined3d_device, swapchain, &wined3d_mode, NULL); 663 wined3d_mutex_unlock(); 664 665 if (SUCCEEDED(hr)) 666 { 667 mode->Width = wined3d_mode.width; 668 mode->Height = wined3d_mode.height; 669 mode->RefreshRate = wined3d_mode.refresh_rate; 670 mode->Format = d3dformat_from_wined3dformat(wined3d_mode.format_id); 671 } 672 673 return hr; 674 } 675 676 static HRESULT WINAPI d3d9_device_GetCreationParameters(IDirect3DDevice9Ex *iface, 677 D3DDEVICE_CREATION_PARAMETERS *parameters) 678 { 679 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 680 681 TRACE("iface %p, parameters %p.\n", iface, parameters); 682 683 wined3d_mutex_lock(); 684 wined3d_device_get_creation_parameters(device->wined3d_device, 685 (struct wined3d_device_creation_parameters *)parameters); 686 wined3d_mutex_unlock(); 687 688 return D3D_OK; 689 } 690 691 static HRESULT WINAPI d3d9_device_SetCursorProperties(IDirect3DDevice9Ex *iface, 692 UINT hotspot_x, UINT hotspot_y, IDirect3DSurface9 *bitmap) 693 { 694 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 695 struct d3d9_surface *bitmap_impl = unsafe_impl_from_IDirect3DSurface9(bitmap); 696 HRESULT hr; 697 698 TRACE("iface %p, hotspot_x %u, hotspot_y %u, bitmap %p.\n", 699 iface, hotspot_x, hotspot_y, bitmap); 700 701 if (!bitmap) 702 { 703 WARN("No cursor bitmap, returning D3DERR_INVALIDCALL.\n"); 704 return D3DERR_INVALIDCALL; 705 } 706 707 wined3d_mutex_lock(); 708 hr = wined3d_device_set_cursor_properties(device->wined3d_device, 709 hotspot_x, hotspot_y, bitmap_impl->wined3d_texture, bitmap_impl->sub_resource_idx); 710 wined3d_mutex_unlock(); 711 712 return hr; 713 } 714 715 static void WINAPI d3d9_device_SetCursorPosition(IDirect3DDevice9Ex *iface, int x, int y, DWORD flags) 716 { 717 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 718 719 TRACE("iface %p, x %u, y %u, flags %#x.\n", iface, x, y, flags); 720 721 wined3d_mutex_lock(); 722 wined3d_device_set_cursor_position(device->wined3d_device, x, y, flags); 723 wined3d_mutex_unlock(); 724 } 725 726 static BOOL WINAPI d3d9_device_ShowCursor(IDirect3DDevice9Ex *iface, BOOL show) 727 { 728 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 729 BOOL ret; 730 731 TRACE("iface %p, show %#x.\n", iface, show); 732 733 wined3d_mutex_lock(); 734 ret = wined3d_device_show_cursor(device->wined3d_device, show); 735 wined3d_mutex_unlock(); 736 737 return ret; 738 } 739 740 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d9_device_CreateAdditionalSwapChain(IDirect3DDevice9Ex *iface, 741 D3DPRESENT_PARAMETERS *present_parameters, IDirect3DSwapChain9 **swapchain) 742 { 743 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 744 struct wined3d_swapchain_desc desc; 745 struct d3d9_swapchain *object; 746 UINT i, count; 747 HRESULT hr; 748 749 TRACE("iface %p, present_parameters %p, swapchain %p.\n", 750 iface, present_parameters, swapchain); 751 752 if (!present_parameters->Windowed) 753 { 754 WARN("Trying to create an additional fullscreen swapchain, returning D3DERR_INVALIDCALL.\n"); 755 return D3DERR_INVALIDCALL; 756 } 757 758 wined3d_mutex_lock(); 759 count = wined3d_device_get_swapchain_count(device->wined3d_device); 760 for (i = 0; i < count; ++i) 761 { 762 struct wined3d_swapchain *wined3d_swapchain; 763 764 wined3d_swapchain = wined3d_device_get_swapchain(device->wined3d_device, i); 765 wined3d_swapchain_get_desc(wined3d_swapchain, &desc); 766 767 if (!desc.windowed) 768 { 769 wined3d_mutex_unlock(); 770 WARN("Trying to create an additional swapchain in fullscreen mode, returning D3DERR_INVALIDCALL.\n"); 771 return D3DERR_INVALIDCALL; 772 } 773 } 774 wined3d_mutex_unlock(); 775 776 if (!wined3d_swapchain_desc_from_present_parameters(&desc, present_parameters, 777 device->d3d_parent->extended)) 778 return D3DERR_INVALIDCALL; 779 if (SUCCEEDED(hr = d3d9_swapchain_create(device, &desc, &object))) 780 *swapchain = (IDirect3DSwapChain9 *)&object->IDirect3DSwapChain9Ex_iface; 781 present_parameters_from_wined3d_swapchain_desc(present_parameters, &desc); 782 783 return hr; 784 } 785 786 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d9_device_GetSwapChain(IDirect3DDevice9Ex *iface, 787 UINT swapchain_idx, IDirect3DSwapChain9 **swapchain) 788 { 789 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 790 HRESULT hr; 791 792 TRACE("iface %p, swapchain_idx %u, swapchain %p.\n", iface, swapchain_idx, swapchain); 793 794 wined3d_mutex_lock(); 795 if (swapchain_idx < device->implicit_swapchain_count) 796 { 797 *swapchain = (IDirect3DSwapChain9 *)&device->implicit_swapchains[swapchain_idx]->IDirect3DSwapChain9Ex_iface; 798 IDirect3DSwapChain9Ex_AddRef(*swapchain); 799 hr = D3D_OK; 800 } 801 else 802 { 803 *swapchain = NULL; 804 hr = D3DERR_INVALIDCALL; 805 } 806 wined3d_mutex_unlock(); 807 808 return hr; 809 } 810 811 static UINT WINAPI d3d9_device_GetNumberOfSwapChains(IDirect3DDevice9Ex *iface) 812 { 813 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 814 UINT count; 815 816 TRACE("iface %p.\n", iface); 817 818 wined3d_mutex_lock(); 819 count = wined3d_device_get_swapchain_count(device->wined3d_device); 820 wined3d_mutex_unlock(); 821 822 return count; 823 } 824 825 static HRESULT CDECL reset_enum_callback(struct wined3d_resource *resource) 826 { 827 struct wined3d_resource_desc desc; 828 IDirect3DBaseTexture9 *texture; 829 struct d3d9_surface *surface; 830 IUnknown *parent; 831 832 wined3d_resource_get_desc(resource, &desc); 833 if (desc.access & WINED3D_RESOURCE_ACCESS_CPU) 834 return D3D_OK; 835 836 if (desc.resource_type != WINED3D_RTYPE_TEXTURE_2D) 837 { 838 WARN("Resource %p in pool D3DPOOL_DEFAULT blocks the Reset call.\n", resource); 839 return D3DERR_INVALIDCALL; 840 } 841 842 parent = wined3d_resource_get_parent(resource); 843 if (parent && SUCCEEDED(IUnknown_QueryInterface(parent, &IID_IDirect3DBaseTexture9, (void **)&texture))) 844 { 845 IDirect3DBaseTexture9_Release(texture); 846 WARN("Texture %p (resource %p) in pool D3DPOOL_DEFAULT blocks the Reset call.\n", texture, resource); 847 return D3DERR_INVALIDCALL; 848 } 849 850 surface = wined3d_texture_get_sub_resource_parent(wined3d_texture_from_resource(resource), 0); 851 if (!surface->resource.refcount) 852 return D3D_OK; 853 854 WARN("Surface %p in pool D3DPOOL_DEFAULT blocks the Reset call.\n", surface); 855 return D3DERR_INVALIDCALL; 856 } 857 858 static HRESULT d3d9_device_get_swapchains(struct d3d9_device *device) 859 { 860 UINT i, new_swapchain_count = wined3d_device_get_swapchain_count(device->wined3d_device); 861 struct wined3d_swapchain *wined3d_swapchain; 862 863 if (!(device->implicit_swapchains = heap_alloc(new_swapchain_count * sizeof(*device->implicit_swapchains)))) 864 return E_OUTOFMEMORY; 865 866 for (i = 0; i < new_swapchain_count; ++i) 867 { 868 wined3d_swapchain = wined3d_device_get_swapchain(device->wined3d_device, i); 869 device->implicit_swapchains[i] = wined3d_swapchain_get_parent(wined3d_swapchain); 870 } 871 device->implicit_swapchain_count = new_swapchain_count; 872 873 return D3D_OK; 874 } 875 876 static HRESULT d3d9_device_reset(struct d3d9_device *device, 877 D3DPRESENT_PARAMETERS *present_parameters, D3DDISPLAYMODEEX *mode) 878 { 879 BOOL extended = device->d3d_parent->extended; 880 struct wined3d_swapchain_desc swapchain_desc; 881 struct wined3d_display_mode wined3d_mode; 882 struct wined3d_rendertarget_view *rtv; 883 unsigned int i; 884 HRESULT hr; 885 886 if (!extended && device->device_state == D3D9_DEVICE_STATE_LOST) 887 { 888 WARN("App not active, returning D3DERR_DEVICELOST.\n"); 889 return D3DERR_DEVICELOST; 890 } 891 892 if (mode) 893 { 894 wined3d_mode.width = mode->Width; 895 wined3d_mode.height = mode->Height; 896 wined3d_mode.refresh_rate = mode->RefreshRate; 897 wined3d_mode.format_id = wined3dformat_from_d3dformat(mode->Format); 898 wined3d_mode.scanline_ordering = mode->ScanLineOrdering; 899 } 900 901 if (!wined3d_swapchain_desc_from_present_parameters(&swapchain_desc, present_parameters, extended)) 902 return D3DERR_INVALIDCALL; 903 904 wined3d_mutex_lock(); 905 906 if (device->vertex_buffer) 907 { 908 wined3d_buffer_decref(device->vertex_buffer); 909 device->vertex_buffer = NULL; 910 device->vertex_buffer_size = 0; 911 } 912 913 if (device->index_buffer) 914 { 915 wined3d_buffer_decref(device->index_buffer); 916 device->index_buffer = NULL; 917 device->index_buffer_size = 0; 918 } 919 920 if (SUCCEEDED(hr = wined3d_device_reset(device->wined3d_device, &swapchain_desc, 921 mode ? &wined3d_mode : NULL, reset_enum_callback, !extended))) 922 { 923 heap_free(device->implicit_swapchains); 924 925 if (!extended) 926 { 927 wined3d_device_set_render_state(device->wined3d_device, WINED3D_RS_ZENABLE, 928 !!swapchain_desc.enable_auto_depth_stencil); 929 } 930 931 if (FAILED(hr = d3d9_device_get_swapchains(device))) 932 { 933 device->device_state = D3D9_DEVICE_STATE_NOT_RESET; 934 } 935 else 936 { 937 wined3d_swapchain_get_desc(device->implicit_swapchains[0]->wined3d_swapchain, &swapchain_desc); 938 present_parameters->BackBufferWidth = swapchain_desc.backbuffer_width; 939 present_parameters->BackBufferHeight = swapchain_desc.backbuffer_height; 940 present_parameters->BackBufferFormat = d3dformat_from_wined3dformat(swapchain_desc.backbuffer_format); 941 present_parameters->BackBufferCount = swapchain_desc.backbuffer_count; 942 943 device->device_state = D3D9_DEVICE_STATE_OK; 944 } 945 946 if (!device->d3d_parent->extended) 947 for (i = 0; i < ARRAY_SIZE(device->textures); ++i) 948 device->textures[i] = NULL; 949 950 rtv = wined3d_device_get_rendertarget_view(device->wined3d_device, 0); 951 device->render_targets[0] = wined3d_rendertarget_view_get_sub_resource_parent(rtv); 952 for (i = 1; i < ARRAY_SIZE(device->render_targets); ++i) 953 device->render_targets[i] = NULL; 954 } 955 else if (!extended) 956 { 957 device->device_state = D3D9_DEVICE_STATE_NOT_RESET; 958 } 959 960 wined3d_mutex_unlock(); 961 962 return hr; 963 } 964 965 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d9_device_Reset(IDirect3DDevice9Ex *iface, 966 D3DPRESENT_PARAMETERS *present_parameters) 967 { 968 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 969 970 TRACE("iface %p, present_parameters %p.\n", iface, present_parameters); 971 972 return d3d9_device_reset(device, present_parameters, NULL); 973 } 974 975 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d9_device_Present(IDirect3DDevice9Ex *iface, 976 const RECT *src_rect, const RECT *dst_rect, HWND dst_window_override, const RGNDATA *dirty_region) 977 { 978 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 979 UINT i; 980 HRESULT hr; 981 982 TRACE("iface %p, src_rect %p, dst_rect %p, dst_window_override %p, dirty_region %p.\n", 983 iface, src_rect, dst_rect, dst_window_override, dirty_region); 984 985 if (device->device_state != D3D9_DEVICE_STATE_OK) 986 return device->d3d_parent->extended ? S_PRESENT_OCCLUDED : D3DERR_DEVICELOST; 987 988 if (dirty_region) 989 FIXME("Ignoring dirty_region %p.\n", dirty_region); 990 991 wined3d_mutex_lock(); 992 for (i = 0; i < device->implicit_swapchain_count; ++i) 993 { 994 if (FAILED(hr = wined3d_swapchain_present(device->implicit_swapchains[i]->wined3d_swapchain, 995 src_rect, dst_rect, dst_window_override, 0, 0))) 996 { 997 wined3d_mutex_unlock(); 998 return hr; 999 } 1000 } 1001 wined3d_mutex_unlock(); 1002 1003 return D3D_OK; 1004 } 1005 1006 static HRESULT WINAPI d3d9_device_GetBackBuffer(IDirect3DDevice9Ex *iface, UINT swapchain, 1007 UINT backbuffer_idx, D3DBACKBUFFER_TYPE backbuffer_type, IDirect3DSurface9 **backbuffer) 1008 { 1009 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 1010 HRESULT hr; 1011 1012 TRACE("iface %p, swapchain %u, backbuffer_idx %u, backbuffer_type %#x, backbuffer %p.\n", 1013 iface, swapchain, backbuffer_idx, backbuffer_type, backbuffer); 1014 1015 /* backbuffer_type is ignored by native. */ 1016 1017 /* No need to check for backbuffer == NULL, Windows crashes in that case. */ 1018 *backbuffer = NULL; 1019 1020 wined3d_mutex_lock(); 1021 if (swapchain >= device->implicit_swapchain_count) 1022 { 1023 wined3d_mutex_unlock(); 1024 WARN("Swapchain index %u is out of range, returning D3DERR_INVALIDCALL.\n", swapchain); 1025 return D3DERR_INVALIDCALL; 1026 } 1027 1028 hr = IDirect3DSwapChain9Ex_GetBackBuffer(&device->implicit_swapchains[swapchain]->IDirect3DSwapChain9Ex_iface, 1029 backbuffer_idx, backbuffer_type, backbuffer); 1030 wined3d_mutex_unlock(); 1031 1032 return hr; 1033 } 1034 1035 static HRESULT WINAPI d3d9_device_GetRasterStatus(IDirect3DDevice9Ex *iface, 1036 UINT swapchain, D3DRASTER_STATUS *raster_status) 1037 { 1038 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 1039 HRESULT hr; 1040 1041 TRACE("iface %p, swapchain %u, raster_status %p.\n", iface, swapchain, raster_status); 1042 1043 wined3d_mutex_lock(); 1044 hr = wined3d_device_get_raster_status(device->wined3d_device, 1045 swapchain, (struct wined3d_raster_status *)raster_status); 1046 wined3d_mutex_unlock(); 1047 1048 return hr; 1049 } 1050 1051 static HRESULT WINAPI d3d9_device_SetDialogBoxMode(IDirect3DDevice9Ex *iface, BOOL enable) 1052 { 1053 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 1054 HRESULT hr; 1055 1056 TRACE("iface %p, enable %#x.\n", iface, enable); 1057 1058 wined3d_mutex_lock(); 1059 hr = wined3d_device_set_dialog_box_mode(device->wined3d_device, enable); 1060 wined3d_mutex_unlock(); 1061 1062 return hr; 1063 } 1064 1065 static void WINAPI d3d9_device_SetGammaRamp(IDirect3DDevice9Ex *iface, 1066 UINT swapchain, DWORD flags, const D3DGAMMARAMP *ramp) 1067 { 1068 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 1069 1070 TRACE("iface %p, swapchain %u, flags %#x, ramp %p.\n", iface, swapchain, flags, ramp); 1071 1072 /* Note: D3DGAMMARAMP is compatible with struct wined3d_gamma_ramp. */ 1073 wined3d_mutex_lock(); 1074 wined3d_device_set_gamma_ramp(device->wined3d_device, swapchain, flags, (const struct wined3d_gamma_ramp *)ramp); 1075 wined3d_mutex_unlock(); 1076 } 1077 1078 static void WINAPI d3d9_device_GetGammaRamp(IDirect3DDevice9Ex *iface, UINT swapchain, D3DGAMMARAMP *ramp) 1079 { 1080 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 1081 1082 TRACE("iface %p, swapchain %u, ramp %p.\n", iface, swapchain, ramp); 1083 1084 /* Note: D3DGAMMARAMP is compatible with struct wined3d_gamma_ramp. */ 1085 wined3d_mutex_lock(); 1086 wined3d_device_get_gamma_ramp(device->wined3d_device, swapchain, (struct wined3d_gamma_ramp *)ramp); 1087 wined3d_mutex_unlock(); 1088 } 1089 1090 static HRESULT WINAPI d3d9_device_CreateTexture(IDirect3DDevice9Ex *iface, 1091 UINT width, UINT height, UINT levels, DWORD usage, D3DFORMAT format, 1092 D3DPOOL pool, IDirect3DTexture9 **texture, HANDLE *shared_handle) 1093 { 1094 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 1095 struct d3d9_texture *object; 1096 BOOL set_mem = FALSE; 1097 HRESULT hr; 1098 1099 TRACE("iface %p, width %u, height %u, levels %u, usage %#x, format %#x, pool %#x, texture %p, shared_handle %p.\n", 1100 iface, width, height, levels, usage, format, pool, texture, shared_handle); 1101 1102 *texture = NULL; 1103 if (shared_handle) 1104 { 1105 if (!device->d3d_parent->extended) 1106 { 1107 WARN("Trying to create a shared or user memory texture on a non-ex device.\n"); 1108 return E_NOTIMPL; 1109 } 1110 1111 if (pool == D3DPOOL_SYSTEMMEM) 1112 { 1113 if (levels != 1) 1114 return D3DERR_INVALIDCALL; 1115 set_mem = TRUE; 1116 } 1117 else 1118 { 1119 if (pool != D3DPOOL_DEFAULT) 1120 { 1121 WARN("Trying to create a shared texture in pool %#x.\n", pool); 1122 return D3DERR_INVALIDCALL; 1123 } 1124 FIXME("Resource sharing not implemented, *shared_handle %p.\n", *shared_handle); 1125 } 1126 } 1127 1128 if (!(object = heap_alloc_zero(sizeof(*object)))) 1129 return D3DERR_OUTOFVIDEOMEMORY; 1130 1131 hr = texture_init(object, device, width, height, levels, usage, format, pool); 1132 if (FAILED(hr)) 1133 { 1134 WARN("Failed to initialize texture, hr %#x.\n", hr); 1135 heap_free(object); 1136 return hr; 1137 } 1138 1139 if (set_mem) 1140 wined3d_texture_update_desc(object->wined3d_texture, width, height, 1141 wined3dformat_from_d3dformat(format), WINED3D_MULTISAMPLE_NONE, 0, 1142 *shared_handle, 0); 1143 1144 TRACE("Created texture %p.\n", object); 1145 *texture = (IDirect3DTexture9 *)&object->IDirect3DBaseTexture9_iface; 1146 1147 return D3D_OK; 1148 } 1149 1150 static HRESULT WINAPI d3d9_device_CreateVolumeTexture(IDirect3DDevice9Ex *iface, 1151 UINT width, UINT height, UINT depth, UINT levels, DWORD usage, D3DFORMAT format, 1152 D3DPOOL pool, IDirect3DVolumeTexture9 **texture, HANDLE *shared_handle) 1153 { 1154 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 1155 struct d3d9_texture *object; 1156 HRESULT hr; 1157 1158 TRACE("iface %p, width %u, height %u, depth %u, levels %u, " 1159 "usage %#x, format %#x, pool %#x, texture %p, shared_handle %p.\n", 1160 iface, width, height, depth, levels, 1161 usage, format, pool, texture, shared_handle); 1162 1163 *texture = NULL; 1164 if (shared_handle) 1165 { 1166 if (!device->d3d_parent->extended) 1167 { 1168 WARN("Trying to create a shared volume texture on a non-ex device.\n"); 1169 return E_NOTIMPL; 1170 } 1171 1172 if (pool != D3DPOOL_DEFAULT) 1173 { 1174 WARN("Trying to create a shared volume texture in pool %#x.\n", pool); 1175 return D3DERR_INVALIDCALL; 1176 } 1177 FIXME("Resource sharing not implemented, *shared_handle %p.\n", *shared_handle); 1178 } 1179 1180 if (!(object = heap_alloc_zero(sizeof(*object)))) 1181 return D3DERR_OUTOFVIDEOMEMORY; 1182 1183 hr = volumetexture_init(object, device, width, height, depth, levels, usage, format, pool); 1184 if (FAILED(hr)) 1185 { 1186 WARN("Failed to initialize volume texture, hr %#x.\n", hr); 1187 heap_free(object); 1188 return hr; 1189 } 1190 1191 TRACE("Created volume texture %p.\n", object); 1192 *texture = (IDirect3DVolumeTexture9 *)&object->IDirect3DBaseTexture9_iface; 1193 1194 return D3D_OK; 1195 } 1196 1197 static HRESULT WINAPI d3d9_device_CreateCubeTexture(IDirect3DDevice9Ex *iface, 1198 UINT edge_length, UINT levels, DWORD usage, D3DFORMAT format, D3DPOOL pool, 1199 IDirect3DCubeTexture9 **texture, HANDLE *shared_handle) 1200 { 1201 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 1202 struct d3d9_texture *object; 1203 HRESULT hr; 1204 1205 TRACE("iface %p, edge_length %u, levels %u, usage %#x, format %#x, pool %#x, texture %p, shared_handle %p.\n", 1206 iface, edge_length, levels, usage, format, pool, texture, shared_handle); 1207 1208 *texture = NULL; 1209 if (shared_handle) 1210 { 1211 if (!device->d3d_parent->extended) 1212 { 1213 WARN("Trying to create a shared cube texture on a non-ex device.\n"); 1214 return E_NOTIMPL; 1215 } 1216 1217 if (pool != D3DPOOL_DEFAULT) 1218 { 1219 WARN("Trying to create a shared cube texture in pool %#x.\n", pool); 1220 return D3DERR_INVALIDCALL; 1221 } 1222 FIXME("Resource sharing not implemented, *shared_handle %p.\n", *shared_handle); 1223 } 1224 1225 if (!(object = heap_alloc_zero(sizeof(*object)))) 1226 return D3DERR_OUTOFVIDEOMEMORY; 1227 1228 hr = cubetexture_init(object, device, edge_length, levels, usage, format, pool); 1229 if (FAILED(hr)) 1230 { 1231 WARN("Failed to initialize cube texture, hr %#x.\n", hr); 1232 heap_free(object); 1233 return hr; 1234 } 1235 1236 TRACE("Created cube texture %p.\n", object); 1237 *texture = (IDirect3DCubeTexture9 *)&object->IDirect3DBaseTexture9_iface; 1238 1239 return D3D_OK; 1240 } 1241 1242 static HRESULT WINAPI d3d9_device_CreateVertexBuffer(IDirect3DDevice9Ex *iface, UINT size, 1243 DWORD usage, DWORD fvf, D3DPOOL pool, IDirect3DVertexBuffer9 **buffer, 1244 HANDLE *shared_handle) 1245 { 1246 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 1247 struct d3d9_vertexbuffer *object; 1248 HRESULT hr; 1249 1250 TRACE("iface %p, size %u, usage %#x, fvf %#x, pool %#x, buffer %p, shared_handle %p.\n", 1251 iface, size, usage, fvf, pool, buffer, shared_handle); 1252 1253 if (shared_handle) 1254 { 1255 if (!device->d3d_parent->extended) 1256 { 1257 WARN("Trying to create a shared vertex buffer on a non-ex device.\n"); 1258 return E_NOTIMPL; 1259 } 1260 1261 if (pool != D3DPOOL_DEFAULT) 1262 { 1263 WARN("Trying to create a shared vertex buffer in pool %#x.\n", pool); 1264 return D3DERR_NOTAVAILABLE; 1265 } 1266 FIXME("Resource sharing not implemented, *shared_handle %p.\n", *shared_handle); 1267 } 1268 1269 if (!(object = heap_alloc_zero(sizeof(*object)))) 1270 return D3DERR_OUTOFVIDEOMEMORY; 1271 1272 hr = vertexbuffer_init(object, device, size, usage, fvf, pool); 1273 if (FAILED(hr)) 1274 { 1275 WARN("Failed to initialize vertex buffer, hr %#x.\n", hr); 1276 heap_free(object); 1277 return hr; 1278 } 1279 1280 TRACE("Created vertex buffer %p.\n", object); 1281 *buffer = &object->IDirect3DVertexBuffer9_iface; 1282 1283 return D3D_OK; 1284 } 1285 1286 static HRESULT WINAPI d3d9_device_CreateIndexBuffer(IDirect3DDevice9Ex *iface, UINT size, 1287 DWORD usage, D3DFORMAT format, D3DPOOL pool, IDirect3DIndexBuffer9 **buffer, 1288 HANDLE *shared_handle) 1289 { 1290 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 1291 struct d3d9_indexbuffer *object; 1292 HRESULT hr; 1293 1294 TRACE("iface %p, size %u, usage %#x, format %#x, pool %#x, buffer %p, shared_handle %p.\n", 1295 iface, size, usage, format, pool, buffer, shared_handle); 1296 1297 if (shared_handle) 1298 { 1299 if (!device->d3d_parent->extended) 1300 { 1301 WARN("Trying to create a shared index buffer on a non-ex device.\n"); 1302 return E_NOTIMPL; 1303 } 1304 1305 if (pool != D3DPOOL_DEFAULT) 1306 { 1307 WARN("Trying to create a shared index buffer in pool %#x.\n", pool); 1308 return D3DERR_NOTAVAILABLE; 1309 } 1310 FIXME("Resource sharing not implemented, *shared_handle %p.\n", *shared_handle); 1311 } 1312 1313 if (!(object = heap_alloc_zero(sizeof(*object)))) 1314 return D3DERR_OUTOFVIDEOMEMORY; 1315 1316 hr = indexbuffer_init(object, device, size, usage, format, pool); 1317 if (FAILED(hr)) 1318 { 1319 WARN("Failed to initialize index buffer, hr %#x.\n", hr); 1320 heap_free(object); 1321 return hr; 1322 } 1323 1324 TRACE("Created index buffer %p.\n", object); 1325 *buffer = &object->IDirect3DIndexBuffer9_iface; 1326 1327 return D3D_OK; 1328 } 1329 1330 static HRESULT d3d9_device_create_surface(struct d3d9_device *device, UINT width, UINT height, 1331 D3DFORMAT format, DWORD flags, IDirect3DSurface9 **surface, UINT usage, D3DPOOL pool, 1332 D3DMULTISAMPLE_TYPE multisample_type, DWORD multisample_quality, void *user_mem) 1333 { 1334 struct wined3d_resource_desc desc; 1335 struct d3d9_surface *surface_impl; 1336 struct wined3d_texture *texture; 1337 HRESULT hr; 1338 1339 TRACE("device %p, width %u, height %u, format %#x, flags %#x, surface %p.\n" 1340 "usage %#x, pool %#x, multisample_type %#x, multisample_quality %u.\n", 1341 device, width, height, format, flags, surface, usage, pool, 1342 multisample_type, multisample_quality); 1343 1344 desc.resource_type = WINED3D_RTYPE_TEXTURE_2D; 1345 desc.format = wined3dformat_from_d3dformat(format); 1346 desc.multisample_type = multisample_type; 1347 desc.multisample_quality = multisample_quality; 1348 desc.usage = usage & WINED3DUSAGE_MASK; 1349 if (pool == D3DPOOL_SCRATCH) 1350 desc.usage |= WINED3DUSAGE_SCRATCH; 1351 desc.access = wined3daccess_from_d3dpool(pool, usage) 1352 | WINED3D_RESOURCE_ACCESS_MAP_R | WINED3D_RESOURCE_ACCESS_MAP_W; 1353 desc.width = width; 1354 desc.height = height; 1355 desc.depth = 1; 1356 desc.size = 0; 1357 1358 if (is_gdi_compat_wined3dformat(desc.format)) 1359 flags |= WINED3D_TEXTURE_CREATE_GET_DC; 1360 1361 wined3d_mutex_lock(); 1362 1363 if (FAILED(hr = wined3d_texture_create(device->wined3d_device, &desc, 1364 1, 1, flags, NULL, NULL, &d3d9_null_wined3d_parent_ops, &texture))) 1365 { 1366 wined3d_mutex_unlock(); 1367 WARN("Failed to create texture, hr %#x.\n", hr); 1368 if (hr == WINED3DERR_NOTAVAILABLE) 1369 hr = D3DERR_INVALIDCALL; 1370 return hr; 1371 } 1372 1373 surface_impl = wined3d_texture_get_sub_resource_parent(texture, 0); 1374 surface_impl->parent_device = &device->IDirect3DDevice9Ex_iface; 1375 *surface = &surface_impl->IDirect3DSurface9_iface; 1376 IDirect3DSurface9_AddRef(*surface); 1377 1378 if (user_mem) 1379 wined3d_texture_update_desc(texture, width, height, 1380 desc.format, multisample_type, multisample_quality, user_mem, 0); 1381 1382 wined3d_texture_decref(texture); 1383 1384 wined3d_mutex_unlock(); 1385 1386 return D3D_OK; 1387 } 1388 1389 BOOL is_gdi_compat_wined3dformat(enum wined3d_format_id format) 1390 { 1391 switch (format) 1392 { 1393 case WINED3DFMT_B8G8R8A8_UNORM: 1394 case WINED3DFMT_B8G8R8X8_UNORM: 1395 case WINED3DFMT_B5G6R5_UNORM: 1396 case WINED3DFMT_B5G5R5X1_UNORM: 1397 case WINED3DFMT_B5G5R5A1_UNORM: 1398 case WINED3DFMT_B8G8R8_UNORM: 1399 return TRUE; 1400 default: 1401 return FALSE; 1402 } 1403 } 1404 1405 static HRESULT WINAPI d3d9_device_CreateRenderTarget(IDirect3DDevice9Ex *iface, UINT width, UINT height, 1406 D3DFORMAT format, D3DMULTISAMPLE_TYPE multisample_type, DWORD multisample_quality, 1407 BOOL lockable, IDirect3DSurface9 **surface, HANDLE *shared_handle) 1408 { 1409 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 1410 DWORD flags = 0; 1411 1412 TRACE("iface %p, width %u, height %u, format %#x, multisample_type %#x, multisample_quality %u.\n" 1413 "lockable %#x, surface %p, shared_handle %p.\n", 1414 iface, width, height, format, multisample_type, multisample_quality, 1415 lockable, surface, shared_handle); 1416 1417 *surface = NULL; 1418 if (shared_handle) 1419 { 1420 if (!device->d3d_parent->extended) 1421 { 1422 WARN("Trying to create a shared render target on a non-ex device.\n"); 1423 return E_NOTIMPL; 1424 } 1425 1426 FIXME("Resource sharing not implemented, *shared_handle %p.\n", *shared_handle); 1427 } 1428 1429 if (lockable) 1430 flags |= WINED3D_TEXTURE_CREATE_MAPPABLE; 1431 1432 return d3d9_device_create_surface(device, width, height, format, flags, surface, 1433 D3DUSAGE_RENDERTARGET, D3DPOOL_DEFAULT, multisample_type, multisample_quality, NULL); 1434 } 1435 1436 static HRESULT WINAPI d3d9_device_CreateDepthStencilSurface(IDirect3DDevice9Ex *iface, UINT width, UINT height, 1437 D3DFORMAT format, D3DMULTISAMPLE_TYPE multisample_type, DWORD multisample_quality, 1438 BOOL discard, IDirect3DSurface9 **surface, HANDLE *shared_handle) 1439 { 1440 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 1441 DWORD flags = WINED3D_TEXTURE_CREATE_MAPPABLE; 1442 1443 TRACE("iface %p, width %u, height %u, format %#x, multisample_type %#x, multisample_quality %u.\n" 1444 "discard %#x, surface %p, shared_handle %p.\n", 1445 iface, width, height, format, multisample_type, multisample_quality, 1446 discard, surface, shared_handle); 1447 1448 *surface = NULL; 1449 if (shared_handle) 1450 { 1451 if (!device->d3d_parent->extended) 1452 { 1453 WARN("Trying to create a shared depth stencil on a non-ex device.\n"); 1454 return E_NOTIMPL; 1455 } 1456 1457 FIXME("Resource sharing not implemented, *shared_handle %p.\n", *shared_handle); 1458 } 1459 1460 if (discard) 1461 flags |= WINED3D_TEXTURE_CREATE_DISCARD; 1462 1463 return d3d9_device_create_surface(device, width, height, format, flags, surface, 1464 D3DUSAGE_DEPTHSTENCIL, D3DPOOL_DEFAULT, multisample_type, multisample_quality, NULL); 1465 } 1466 1467 1468 static HRESULT WINAPI d3d9_device_UpdateSurface(IDirect3DDevice9Ex *iface, 1469 IDirect3DSurface9 *src_surface, const RECT *src_rect, 1470 IDirect3DSurface9 *dst_surface, const POINT *dst_point) 1471 { 1472 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 1473 struct d3d9_surface *src = unsafe_impl_from_IDirect3DSurface9(src_surface); 1474 struct d3d9_surface *dst = unsafe_impl_from_IDirect3DSurface9(dst_surface); 1475 struct wined3d_sub_resource_desc src_desc, dst_desc; 1476 struct wined3d_box src_box; 1477 HRESULT hr; 1478 1479 TRACE("iface %p, src_surface %p, src_rect %p, dst_surface %p, dst_point %p.\n", 1480 iface, src_surface, src_rect, dst_surface, dst_point); 1481 1482 wined3d_mutex_lock(); 1483 1484 wined3d_texture_get_sub_resource_desc(src->wined3d_texture, src->sub_resource_idx, &src_desc); 1485 wined3d_texture_get_sub_resource_desc(dst->wined3d_texture, dst->sub_resource_idx, &dst_desc); 1486 if (src_desc.format != dst_desc.format) 1487 { 1488 wined3d_mutex_unlock(); 1489 WARN("Surface formats (%#x/%#x) don't match.\n", 1490 d3dformat_from_wined3dformat(src_desc.format), 1491 d3dformat_from_wined3dformat(dst_desc.format)); 1492 return D3DERR_INVALIDCALL; 1493 } 1494 1495 if (src_rect) 1496 wined3d_box_set(&src_box, src_rect->left, src_rect->top, src_rect->right, src_rect->bottom, 0, 1); 1497 else 1498 wined3d_box_set(&src_box, 0, 0, src_desc.width, src_desc.height, 0, 1); 1499 1500 hr = wined3d_device_copy_sub_resource_region(device->wined3d_device, 1501 wined3d_texture_get_resource(dst->wined3d_texture), dst->sub_resource_idx, dst_point ? dst_point->x : 0, 1502 dst_point ? dst_point->y : 0, 0, wined3d_texture_get_resource(src->wined3d_texture), 1503 src->sub_resource_idx, &src_box); 1504 if (SUCCEEDED(hr) && dst->texture) 1505 d3d9_texture_flag_auto_gen_mipmap(dst->texture); 1506 1507 wined3d_mutex_unlock(); 1508 1509 if (FAILED(hr)) 1510 return D3DERR_INVALIDCALL; 1511 1512 return hr; 1513 } 1514 1515 static HRESULT WINAPI d3d9_device_UpdateTexture(IDirect3DDevice9Ex *iface, 1516 IDirect3DBaseTexture9 *src_texture, IDirect3DBaseTexture9 *dst_texture) 1517 { 1518 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 1519 struct d3d9_texture *src_impl, *dst_impl; 1520 HRESULT hr; 1521 1522 TRACE("iface %p, src_texture %p, dst_texture %p.\n", iface, src_texture, dst_texture); 1523 1524 src_impl = unsafe_impl_from_IDirect3DBaseTexture9(src_texture); 1525 dst_impl = unsafe_impl_from_IDirect3DBaseTexture9(dst_texture); 1526 1527 wined3d_mutex_lock(); 1528 hr = wined3d_device_update_texture(device->wined3d_device, 1529 src_impl->wined3d_texture, dst_impl->wined3d_texture); 1530 if (SUCCEEDED(hr)) 1531 d3d9_texture_flag_auto_gen_mipmap(dst_impl); 1532 wined3d_mutex_unlock(); 1533 1534 return hr; 1535 } 1536 1537 static HRESULT WINAPI d3d9_device_GetRenderTargetData(IDirect3DDevice9Ex *iface, 1538 IDirect3DSurface9 *render_target, IDirect3DSurface9 *dst_surface) 1539 { 1540 struct d3d9_surface *rt_impl = unsafe_impl_from_IDirect3DSurface9(render_target); 1541 struct d3d9_surface *dst_impl = unsafe_impl_from_IDirect3DSurface9(dst_surface); 1542 struct wined3d_sub_resource_desc wined3d_desc; 1543 RECT dst_rect, src_rect; 1544 HRESULT hr; 1545 1546 TRACE("iface %p, render_target %p, dst_surface %p.\n", iface, render_target, dst_surface); 1547 1548 if (!render_target || !dst_surface) 1549 return D3DERR_INVALIDCALL; 1550 1551 wined3d_mutex_lock(); 1552 wined3d_texture_get_sub_resource_desc(dst_impl->wined3d_texture, dst_impl->sub_resource_idx, &wined3d_desc); 1553 SetRect(&dst_rect, 0, 0, wined3d_desc.width, wined3d_desc.height); 1554 1555 wined3d_texture_get_sub_resource_desc(rt_impl->wined3d_texture, rt_impl->sub_resource_idx, &wined3d_desc); 1556 SetRect(&src_rect, 0, 0, wined3d_desc.width, wined3d_desc.height); 1557 1558 /* TODO: Check surface sizes, pools, etc. */ 1559 if (wined3d_desc.multisample_type) 1560 hr = D3DERR_INVALIDCALL; 1561 else 1562 hr = wined3d_texture_blt(dst_impl->wined3d_texture, dst_impl->sub_resource_idx, &dst_rect, 1563 rt_impl->wined3d_texture, rt_impl->sub_resource_idx, &src_rect, 0, NULL, WINED3D_TEXF_POINT); 1564 wined3d_mutex_unlock(); 1565 1566 return hr; 1567 } 1568 1569 static HRESULT WINAPI d3d9_device_GetFrontBufferData(IDirect3DDevice9Ex *iface, 1570 UINT swapchain, IDirect3DSurface9 *dst_surface) 1571 { 1572 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 1573 struct d3d9_surface *dst_impl = unsafe_impl_from_IDirect3DSurface9(dst_surface); 1574 HRESULT hr = D3DERR_INVALIDCALL; 1575 1576 TRACE("iface %p, swapchain %u, dst_surface %p.\n", iface, swapchain, dst_surface); 1577 1578 wined3d_mutex_lock(); 1579 if (swapchain < device->implicit_swapchain_count) 1580 hr = wined3d_swapchain_get_front_buffer_data(device->implicit_swapchains[swapchain]->wined3d_swapchain, 1581 dst_impl->wined3d_texture, dst_impl->sub_resource_idx); 1582 wined3d_mutex_unlock(); 1583 1584 return hr; 1585 } 1586 1587 static HRESULT WINAPI d3d9_device_StretchRect(IDirect3DDevice9Ex *iface, IDirect3DSurface9 *src_surface, 1588 const RECT *src_rect, IDirect3DSurface9 *dst_surface, const RECT *dst_rect, D3DTEXTUREFILTERTYPE filter) 1589 { 1590 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 1591 struct d3d9_surface *src = unsafe_impl_from_IDirect3DSurface9(src_surface); 1592 struct d3d9_surface *dst = unsafe_impl_from_IDirect3DSurface9(dst_surface); 1593 struct wined3d_sub_resource_desc src_desc, dst_desc; 1594 HRESULT hr = D3DERR_INVALIDCALL; 1595 RECT d, s; 1596 1597 TRACE("iface %p, src_surface %p, src_rect %p, dst_surface %p, dst_rect %p, filter %#x.\n", 1598 iface, src_surface, src_rect, dst_surface, dst_rect, filter); 1599 1600 wined3d_mutex_lock(); 1601 wined3d_texture_get_sub_resource_desc(dst->wined3d_texture, dst->sub_resource_idx, &dst_desc); 1602 if (!dst_rect) 1603 { 1604 SetRect(&d, 0, 0, dst_desc.width, dst_desc.height); 1605 dst_rect = &d; 1606 } 1607 1608 wined3d_texture_get_sub_resource_desc(src->wined3d_texture, src->sub_resource_idx, &src_desc); 1609 if (!src_rect) 1610 { 1611 SetRect(&s, 0, 0, src_desc.width, src_desc.height); 1612 src_rect = &s; 1613 } 1614 1615 if (dst_desc.access & WINED3D_RESOURCE_ACCESS_CPU) 1616 { 1617 WARN("Destination resource is not in DEFAULT pool.\n"); 1618 goto done; 1619 } 1620 if (src_desc.access & WINED3D_RESOURCE_ACCESS_CPU) 1621 { 1622 WARN("Source resource is not in DEFAULT pool.\n"); 1623 goto done; 1624 } 1625 1626 if (dst->texture && !(dst_desc.usage & (WINED3DUSAGE_RENDERTARGET | WINED3DUSAGE_DEPTHSTENCIL))) 1627 { 1628 WARN("Destination is a regular texture.\n"); 1629 goto done; 1630 } 1631 1632 if (src_desc.usage & WINED3DUSAGE_DEPTHSTENCIL) 1633 { 1634 if (device->in_scene) 1635 { 1636 WARN("Rejecting depth / stencil blit while in scene.\n"); 1637 goto done; 1638 } 1639 1640 if (src_rect->left || src_rect->top || src_rect->right != src_desc.width 1641 || src_rect->bottom != src_desc.height) 1642 { 1643 WARN("Rejecting depth / stencil blit with invalid source rect %s.\n", 1644 wine_dbgstr_rect(src_rect)); 1645 goto done; 1646 } 1647 1648 if (dst_rect->left || dst_rect->top || dst_rect->right != dst_desc.width 1649 || dst_rect->bottom != dst_desc.height) 1650 { 1651 WARN("Rejecting depth / stencil blit with invalid destination rect %s.\n", 1652 wine_dbgstr_rect(dst_rect)); 1653 goto done; 1654 } 1655 1656 if (src_desc.width != dst_desc.width || src_desc.height != dst_desc.height) 1657 { 1658 WARN("Rejecting depth / stencil blit with mismatched surface sizes.\n"); 1659 goto done; 1660 } 1661 } 1662 1663 hr = wined3d_texture_blt(dst->wined3d_texture, dst->sub_resource_idx, dst_rect, 1664 src->wined3d_texture, src->sub_resource_idx, src_rect, 0, NULL, filter); 1665 if (hr == WINEDDERR_INVALIDRECT) 1666 hr = D3DERR_INVALIDCALL; 1667 if (SUCCEEDED(hr) && dst->texture) 1668 d3d9_texture_flag_auto_gen_mipmap(dst->texture); 1669 1670 done: 1671 wined3d_mutex_unlock(); 1672 return hr; 1673 } 1674 1675 static HRESULT WINAPI d3d9_device_ColorFill(IDirect3DDevice9Ex *iface, 1676 IDirect3DSurface9 *surface, const RECT *rect, D3DCOLOR color) 1677 { 1678 const struct wined3d_color c = 1679 { 1680 ((color >> 16) & 0xff) / 255.0f, 1681 ((color >> 8) & 0xff) / 255.0f, 1682 (color & 0xff) / 255.0f, 1683 ((color >> 24) & 0xff) / 255.0f, 1684 }; 1685 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 1686 struct d3d9_surface *surface_impl = unsafe_impl_from_IDirect3DSurface9(surface); 1687 struct wined3d_sub_resource_desc desc; 1688 struct wined3d_rendertarget_view *rtv; 1689 HRESULT hr; 1690 1691 TRACE("iface %p, surface %p, rect %p, color 0x%08x.\n", iface, surface, rect, color); 1692 1693 wined3d_mutex_lock(); 1694 1695 if (FAILED(wined3d_texture_get_sub_resource_desc(surface_impl->wined3d_texture, 1696 surface_impl->sub_resource_idx, &desc))) 1697 { 1698 wined3d_mutex_unlock(); 1699 return D3DERR_INVALIDCALL; 1700 } 1701 1702 if (desc.access & WINED3D_RESOURCE_ACCESS_CPU) 1703 { 1704 wined3d_mutex_unlock(); 1705 WARN("Colour fills are not allowed on surfaces with resource access %#x.\n", desc.access); 1706 return D3DERR_INVALIDCALL; 1707 } 1708 if ((desc.usage & (WINED3DUSAGE_RENDERTARGET | WINED3DUSAGE_TEXTURE)) == WINED3DUSAGE_TEXTURE) 1709 { 1710 wined3d_mutex_unlock(); 1711 WARN("Colorfill is not allowed on non-RT textures, returning D3DERR_INVALIDCALL.\n"); 1712 return D3DERR_INVALIDCALL; 1713 } 1714 if (desc.usage & WINED3DUSAGE_DEPTHSTENCIL) 1715 { 1716 wined3d_mutex_unlock(); 1717 WARN("Colorfill is not allowed on depth stencil surfaces, returning D3DERR_INVALIDCALL.\n"); 1718 return D3DERR_INVALIDCALL; 1719 } 1720 1721 rtv = d3d9_surface_acquire_rendertarget_view(surface_impl); 1722 hr = wined3d_device_clear_rendertarget_view(device->wined3d_device, 1723 rtv, rect, WINED3DCLEAR_TARGET, &c, 0.0f, 0); 1724 d3d9_surface_release_rendertarget_view(surface_impl, rtv); 1725 if (SUCCEEDED(hr) && surface_impl->texture) 1726 d3d9_texture_flag_auto_gen_mipmap(surface_impl->texture); 1727 1728 wined3d_mutex_unlock(); 1729 1730 return hr; 1731 } 1732 1733 static HRESULT WINAPI d3d9_device_CreateOffscreenPlainSurface(IDirect3DDevice9Ex *iface, 1734 UINT width, UINT height, D3DFORMAT format, D3DPOOL pool, IDirect3DSurface9 **surface, 1735 HANDLE *shared_handle) 1736 { 1737 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 1738 void *user_mem = NULL; 1739 1740 TRACE("iface %p, width %u, height %u, format %#x, pool %#x, surface %p, shared_handle %p.\n", 1741 iface, width, height, format, pool, surface, shared_handle); 1742 1743 *surface = NULL; 1744 if (pool == D3DPOOL_MANAGED) 1745 { 1746 WARN("Attempting to create a managed offscreen plain surface.\n"); 1747 return D3DERR_INVALIDCALL; 1748 } 1749 1750 if (shared_handle) 1751 { 1752 if (!device->d3d_parent->extended) 1753 { 1754 WARN("Trying to create a shared or user memory surface on a non-ex device.\n"); 1755 return E_NOTIMPL; 1756 } 1757 1758 if (pool == D3DPOOL_SYSTEMMEM) 1759 user_mem = *shared_handle; 1760 else 1761 { 1762 if (pool != D3DPOOL_DEFAULT) 1763 { 1764 WARN("Trying to create a shared surface in pool %#x.\n", pool); 1765 return D3DERR_INVALIDCALL; 1766 } 1767 FIXME("Resource sharing not implemented, *shared_handle %p.\n", *shared_handle); 1768 } 1769 } 1770 1771 /* FIXME: Offscreen surfaces are supposed to be always lockable, 1772 * regardless of the pool they're created in. Should we set dynamic usage 1773 * here? */ 1774 return d3d9_device_create_surface(device, width, height, format, 1775 WINED3D_TEXTURE_CREATE_MAPPABLE, surface, 0, pool, D3DMULTISAMPLE_NONE, 0, user_mem); 1776 } 1777 1778 static HRESULT WINAPI d3d9_device_SetRenderTarget(IDirect3DDevice9Ex *iface, DWORD idx, IDirect3DSurface9 *surface) 1779 { 1780 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 1781 struct d3d9_surface *surface_impl = unsafe_impl_from_IDirect3DSurface9(surface); 1782 struct wined3d_rendertarget_view *rtv; 1783 HRESULT hr; 1784 1785 TRACE("iface %p, idx %u, surface %p.\n", iface, idx, surface); 1786 1787 if (idx >= D3D_MAX_SIMULTANEOUS_RENDERTARGETS) 1788 { 1789 WARN("Invalid index %u specified.\n", idx); 1790 return D3DERR_INVALIDCALL; 1791 } 1792 1793 if (!idx && !surface_impl) 1794 { 1795 WARN("Trying to set render target 0 to NULL.\n"); 1796 return D3DERR_INVALIDCALL; 1797 } 1798 1799 if (surface_impl && d3d9_surface_get_device(surface_impl) != device) 1800 { 1801 WARN("Render target surface does not match device.\n"); 1802 return D3DERR_INVALIDCALL; 1803 } 1804 1805 wined3d_mutex_lock(); 1806 rtv = surface_impl ? d3d9_surface_acquire_rendertarget_view(surface_impl) : NULL; 1807 hr = wined3d_device_set_rendertarget_view(device->wined3d_device, idx, rtv, TRUE); 1808 d3d9_surface_release_rendertarget_view(surface_impl, rtv); 1809 if (SUCCEEDED(hr)) 1810 device->render_targets[idx] = surface_impl; 1811 wined3d_mutex_unlock(); 1812 1813 return hr; 1814 } 1815 1816 static HRESULT WINAPI d3d9_device_GetRenderTarget(IDirect3DDevice9Ex *iface, DWORD idx, IDirect3DSurface9 **surface) 1817 { 1818 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 1819 struct wined3d_rendertarget_view *wined3d_rtv; 1820 struct d3d9_surface *surface_impl; 1821 HRESULT hr = D3D_OK; 1822 1823 TRACE("iface %p, idx %u, surface %p.\n", iface, idx, surface); 1824 1825 if (!surface) 1826 return D3DERR_INVALIDCALL; 1827 1828 if (idx >= D3D_MAX_SIMULTANEOUS_RENDERTARGETS) 1829 { 1830 WARN("Invalid index %u specified.\n", idx); 1831 return D3DERR_INVALIDCALL; 1832 } 1833 1834 wined3d_mutex_lock(); 1835 if ((wined3d_rtv = wined3d_device_get_rendertarget_view(device->wined3d_device, idx))) 1836 { 1837 /* We want the sub resource parent here, since the view itself may be 1838 * internal to wined3d and may not have a parent. */ 1839 surface_impl = wined3d_rendertarget_view_get_sub_resource_parent(wined3d_rtv); 1840 *surface = &surface_impl->IDirect3DSurface9_iface; 1841 IDirect3DSurface9_AddRef(*surface); 1842 } 1843 else 1844 { 1845 hr = D3DERR_NOTFOUND; 1846 *surface = NULL; 1847 } 1848 wined3d_mutex_unlock(); 1849 1850 return hr; 1851 } 1852 1853 static HRESULT WINAPI d3d9_device_SetDepthStencilSurface(IDirect3DDevice9Ex *iface, IDirect3DSurface9 *depth_stencil) 1854 { 1855 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 1856 struct d3d9_surface *ds_impl = unsafe_impl_from_IDirect3DSurface9(depth_stencil); 1857 struct wined3d_rendertarget_view *rtv; 1858 1859 TRACE("iface %p, depth_stencil %p.\n", iface, depth_stencil); 1860 1861 wined3d_mutex_lock(); 1862 rtv = ds_impl ? d3d9_surface_acquire_rendertarget_view(ds_impl) : NULL; 1863 wined3d_device_set_depth_stencil_view(device->wined3d_device, rtv); 1864 d3d9_surface_release_rendertarget_view(ds_impl, rtv); 1865 wined3d_mutex_unlock(); 1866 1867 return D3D_OK; 1868 } 1869 1870 static HRESULT WINAPI d3d9_device_GetDepthStencilSurface(IDirect3DDevice9Ex *iface, IDirect3DSurface9 **depth_stencil) 1871 { 1872 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 1873 struct wined3d_rendertarget_view *wined3d_dsv; 1874 struct d3d9_surface *surface_impl; 1875 HRESULT hr = D3D_OK; 1876 1877 TRACE("iface %p, depth_stencil %p.\n", iface, depth_stencil); 1878 1879 if (!depth_stencil) 1880 return D3DERR_INVALIDCALL; 1881 1882 wined3d_mutex_lock(); 1883 if ((wined3d_dsv = wined3d_device_get_depth_stencil_view(device->wined3d_device))) 1884 { 1885 /* We want the sub resource parent here, since the view itself may be 1886 * internal to wined3d and may not have a parent. */ 1887 surface_impl = wined3d_rendertarget_view_get_sub_resource_parent(wined3d_dsv); 1888 *depth_stencil = &surface_impl->IDirect3DSurface9_iface; 1889 IDirect3DSurface9_AddRef(*depth_stencil); 1890 } 1891 else 1892 { 1893 hr = D3DERR_NOTFOUND; 1894 *depth_stencil = NULL; 1895 } 1896 wined3d_mutex_unlock(); 1897 1898 return hr; 1899 } 1900 1901 static HRESULT WINAPI d3d9_device_BeginScene(IDirect3DDevice9Ex *iface) 1902 { 1903 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 1904 HRESULT hr; 1905 1906 TRACE("iface %p.\n", iface); 1907 1908 wined3d_mutex_lock(); 1909 if (SUCCEEDED(hr = wined3d_device_begin_scene(device->wined3d_device))) 1910 device->in_scene = TRUE; 1911 wined3d_mutex_unlock(); 1912 1913 return hr; 1914 } 1915 1916 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d9_device_EndScene(IDirect3DDevice9Ex *iface) 1917 { 1918 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 1919 HRESULT hr; 1920 1921 TRACE("iface %p.\n", iface); 1922 1923 wined3d_mutex_lock(); 1924 if (SUCCEEDED(hr = wined3d_device_end_scene(device->wined3d_device))) 1925 device->in_scene = FALSE; 1926 wined3d_mutex_unlock(); 1927 1928 return hr; 1929 } 1930 1931 static void d3d9_rts_flag_auto_gen_mipmap(struct d3d9_device *device) 1932 { 1933 unsigned int i; 1934 1935 for (i = 0; i < ARRAY_SIZE(device->render_targets); ++i) 1936 { 1937 struct d3d9_surface *surface = device->render_targets[i]; 1938 1939 if (surface && surface->texture) 1940 d3d9_texture_flag_auto_gen_mipmap(surface->texture); 1941 } 1942 } 1943 1944 static HRESULT WINAPI d3d9_device_Clear(IDirect3DDevice9Ex *iface, DWORD rect_count, 1945 const D3DRECT *rects, DWORD flags, D3DCOLOR color, float z, DWORD stencil) 1946 { 1947 const struct wined3d_color c = 1948 { 1949 ((color >> 16) & 0xff) / 255.0f, 1950 ((color >> 8) & 0xff) / 255.0f, 1951 (color & 0xff) / 255.0f, 1952 ((color >> 24) & 0xff) / 255.0f, 1953 }; 1954 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 1955 HRESULT hr; 1956 1957 TRACE("iface %p, rect_count %u, rects %p, flags %#x, color 0x%08x, z %.8e, stencil %u.\n", 1958 iface, rect_count, rects, flags, color, z, stencil); 1959 1960 if (rect_count && !rects) 1961 { 1962 WARN("count %u with NULL rects.\n", rect_count); 1963 rect_count = 0; 1964 } 1965 1966 wined3d_mutex_lock(); 1967 hr = wined3d_device_clear(device->wined3d_device, rect_count, (const RECT *)rects, flags, &c, z, stencil); 1968 if (SUCCEEDED(hr)) 1969 d3d9_rts_flag_auto_gen_mipmap(device); 1970 wined3d_mutex_unlock(); 1971 1972 return hr; 1973 } 1974 1975 static HRESULT WINAPI d3d9_device_SetTransform(IDirect3DDevice9Ex *iface, 1976 D3DTRANSFORMSTATETYPE state, const D3DMATRIX *matrix) 1977 { 1978 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 1979 1980 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix); 1981 1982 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */ 1983 wined3d_mutex_lock(); 1984 wined3d_device_set_transform(device->wined3d_device, state, (const struct wined3d_matrix *)matrix); 1985 wined3d_mutex_unlock(); 1986 1987 return D3D_OK; 1988 } 1989 1990 static HRESULT WINAPI d3d9_device_GetTransform(IDirect3DDevice9Ex *iface, 1991 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix) 1992 { 1993 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 1994 1995 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix); 1996 1997 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */ 1998 wined3d_mutex_lock(); 1999 wined3d_device_get_transform(device->wined3d_device, state, (struct wined3d_matrix *)matrix); 2000 wined3d_mutex_unlock(); 2001 2002 return D3D_OK; 2003 } 2004 2005 static HRESULT WINAPI d3d9_device_MultiplyTransform(IDirect3DDevice9Ex *iface, 2006 D3DTRANSFORMSTATETYPE state, const D3DMATRIX *matrix) 2007 { 2008 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 2009 2010 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix); 2011 2012 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */ 2013 wined3d_mutex_lock(); 2014 wined3d_device_multiply_transform(device->wined3d_device, state, (const struct wined3d_matrix *)matrix); 2015 wined3d_mutex_unlock(); 2016 2017 return D3D_OK; 2018 } 2019 2020 static HRESULT WINAPI d3d9_device_SetViewport(IDirect3DDevice9Ex *iface, const D3DVIEWPORT9 *viewport) 2021 { 2022 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 2023 struct wined3d_viewport vp; 2024 2025 TRACE("iface %p, viewport %p.\n", iface, viewport); 2026 2027 vp.x = viewport->X; 2028 vp.y = viewport->Y; 2029 vp.width = viewport->Width; 2030 vp.height = viewport->Height; 2031 vp.min_z = viewport->MinZ; 2032 vp.max_z = viewport->MaxZ; 2033 2034 wined3d_mutex_lock(); 2035 wined3d_device_set_viewport(device->wined3d_device, &vp); 2036 wined3d_mutex_unlock(); 2037 2038 return D3D_OK; 2039 } 2040 2041 static HRESULT WINAPI d3d9_device_GetViewport(IDirect3DDevice9Ex *iface, D3DVIEWPORT9 *viewport) 2042 { 2043 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 2044 struct wined3d_viewport wined3d_viewport; 2045 2046 TRACE("iface %p, viewport %p.\n", iface, viewport); 2047 2048 wined3d_mutex_lock(); 2049 wined3d_device_get_viewport(device->wined3d_device, &wined3d_viewport); 2050 wined3d_mutex_unlock(); 2051 2052 viewport->X = wined3d_viewport.x; 2053 viewport->Y = wined3d_viewport.y; 2054 viewport->Width = wined3d_viewport.width; 2055 viewport->Height = wined3d_viewport.height; 2056 viewport->MinZ = wined3d_viewport.min_z; 2057 viewport->MaxZ = wined3d_viewport.max_z; 2058 2059 return D3D_OK; 2060 } 2061 2062 static HRESULT WINAPI d3d9_device_SetMaterial(IDirect3DDevice9Ex *iface, const D3DMATERIAL9 *material) 2063 { 2064 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 2065 2066 TRACE("iface %p, material %p.\n", iface, material); 2067 2068 /* Note: D3DMATERIAL9 is compatible with struct wined3d_material. */ 2069 wined3d_mutex_lock(); 2070 wined3d_device_set_material(device->wined3d_device, (const struct wined3d_material *)material); 2071 wined3d_mutex_unlock(); 2072 2073 return D3D_OK; 2074 } 2075 2076 static HRESULT WINAPI d3d9_device_GetMaterial(IDirect3DDevice9Ex *iface, D3DMATERIAL9 *material) 2077 { 2078 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 2079 2080 TRACE("iface %p, material %p.\n", iface, material); 2081 2082 /* Note: D3DMATERIAL9 is compatible with struct wined3d_material. */ 2083 wined3d_mutex_lock(); 2084 wined3d_device_get_material(device->wined3d_device, (struct wined3d_material *)material); 2085 wined3d_mutex_unlock(); 2086 2087 return D3D_OK; 2088 } 2089 2090 static HRESULT WINAPI d3d9_device_SetLight(IDirect3DDevice9Ex *iface, DWORD index, const D3DLIGHT9 *light) 2091 { 2092 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 2093 HRESULT hr; 2094 2095 TRACE("iface %p, index %u, light %p.\n", iface, index, light); 2096 2097 /* Note: D3DLIGHT9 is compatible with struct wined3d_light. */ 2098 wined3d_mutex_lock(); 2099 hr = wined3d_device_set_light(device->wined3d_device, index, (const struct wined3d_light *)light); 2100 wined3d_mutex_unlock(); 2101 2102 return hr; 2103 } 2104 2105 static HRESULT WINAPI d3d9_device_GetLight(IDirect3DDevice9Ex *iface, DWORD index, D3DLIGHT9 *light) 2106 { 2107 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 2108 HRESULT hr; 2109 2110 TRACE("iface %p, index %u, light %p.\n", iface, index, light); 2111 2112 /* Note: D3DLIGHT9 is compatible with struct wined3d_light. */ 2113 wined3d_mutex_lock(); 2114 hr = wined3d_device_get_light(device->wined3d_device, index, (struct wined3d_light *)light); 2115 wined3d_mutex_unlock(); 2116 2117 return hr; 2118 } 2119 2120 static HRESULT WINAPI d3d9_device_LightEnable(IDirect3DDevice9Ex *iface, DWORD index, BOOL enable) 2121 { 2122 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 2123 HRESULT hr; 2124 2125 TRACE("iface %p, index %u, enable %#x.\n", iface, index, enable); 2126 2127 wined3d_mutex_lock(); 2128 hr = wined3d_device_set_light_enable(device->wined3d_device, index, enable); 2129 wined3d_mutex_unlock(); 2130 2131 return hr; 2132 } 2133 2134 static HRESULT WINAPI d3d9_device_GetLightEnable(IDirect3DDevice9Ex *iface, DWORD index, BOOL *enable) 2135 { 2136 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 2137 HRESULT hr; 2138 2139 TRACE("iface %p, index %u, enable %p.\n", iface, index, enable); 2140 2141 wined3d_mutex_lock(); 2142 hr = wined3d_device_get_light_enable(device->wined3d_device, index, enable); 2143 wined3d_mutex_unlock(); 2144 2145 return hr; 2146 } 2147 2148 static HRESULT WINAPI d3d9_device_SetClipPlane(IDirect3DDevice9Ex *iface, DWORD index, const float *plane) 2149 { 2150 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 2151 HRESULT hr; 2152 2153 TRACE("iface %p, index %u, plane %p.\n", iface, index, plane); 2154 2155 index = min(index, device->max_user_clip_planes - 1); 2156 2157 wined3d_mutex_lock(); 2158 hr = wined3d_device_set_clip_plane(device->wined3d_device, index, (const struct wined3d_vec4 *)plane); 2159 wined3d_mutex_unlock(); 2160 2161 return hr; 2162 } 2163 2164 static HRESULT WINAPI d3d9_device_GetClipPlane(IDirect3DDevice9Ex *iface, DWORD index, float *plane) 2165 { 2166 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 2167 HRESULT hr; 2168 2169 TRACE("iface %p, index %u, plane %p.\n", iface, index, plane); 2170 2171 index = min(index, device->max_user_clip_planes - 1); 2172 2173 wined3d_mutex_lock(); 2174 hr = wined3d_device_get_clip_plane(device->wined3d_device, index, (struct wined3d_vec4 *)plane); 2175 wined3d_mutex_unlock(); 2176 2177 return hr; 2178 } 2179 2180 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d9_device_SetRenderState(IDirect3DDevice9Ex *iface, 2181 D3DRENDERSTATETYPE state, DWORD value) 2182 { 2183 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 2184 2185 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value); 2186 2187 wined3d_mutex_lock(); 2188 wined3d_device_set_render_state(device->wined3d_device, state, value); 2189 wined3d_mutex_unlock(); 2190 2191 return D3D_OK; 2192 } 2193 2194 static HRESULT WINAPI d3d9_device_GetRenderState(IDirect3DDevice9Ex *iface, 2195 D3DRENDERSTATETYPE state, DWORD *value) 2196 { 2197 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 2198 2199 TRACE("iface %p, state %#x, value %p.\n", iface, state, value); 2200 2201 wined3d_mutex_lock(); 2202 *value = wined3d_device_get_render_state(device->wined3d_device, state); 2203 wined3d_mutex_unlock(); 2204 2205 return D3D_OK; 2206 } 2207 2208 static HRESULT WINAPI d3d9_device_CreateStateBlock(IDirect3DDevice9Ex *iface, 2209 D3DSTATEBLOCKTYPE type, IDirect3DStateBlock9 **stateblock) 2210 { 2211 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 2212 struct d3d9_stateblock *object; 2213 HRESULT hr; 2214 2215 TRACE("iface %p, type %#x, stateblock %p.\n", iface, type, stateblock); 2216 2217 if (type != D3DSBT_ALL && type != D3DSBT_PIXELSTATE && type != D3DSBT_VERTEXSTATE) 2218 { 2219 WARN("Unexpected stateblock type, returning D3DERR_INVALIDCALL.\n"); 2220 return D3DERR_INVALIDCALL; 2221 } 2222 2223 if (!(object = heap_alloc_zero(sizeof(*object)))) 2224 return E_OUTOFMEMORY; 2225 2226 hr = stateblock_init(object, device, type, NULL); 2227 if (FAILED(hr)) 2228 { 2229 WARN("Failed to initialize stateblock, hr %#x.\n", hr); 2230 heap_free(object); 2231 return hr; 2232 } 2233 2234 TRACE("Created stateblock %p.\n", object); 2235 *stateblock = &object->IDirect3DStateBlock9_iface; 2236 2237 return D3D_OK; 2238 } 2239 2240 static HRESULT WINAPI d3d9_device_BeginStateBlock(IDirect3DDevice9Ex *iface) 2241 { 2242 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 2243 HRESULT hr; 2244 2245 TRACE("iface %p.\n", iface); 2246 2247 wined3d_mutex_lock(); 2248 hr = wined3d_device_begin_stateblock(device->wined3d_device); 2249 wined3d_mutex_unlock(); 2250 2251 return hr; 2252 } 2253 2254 static HRESULT WINAPI d3d9_device_EndStateBlock(IDirect3DDevice9Ex *iface, IDirect3DStateBlock9 **stateblock) 2255 { 2256 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 2257 struct wined3d_stateblock *wined3d_stateblock; 2258 struct d3d9_stateblock *object; 2259 HRESULT hr; 2260 2261 TRACE("iface %p, stateblock %p.\n", iface, stateblock); 2262 2263 wined3d_mutex_lock(); 2264 hr = wined3d_device_end_stateblock(device->wined3d_device, &wined3d_stateblock); 2265 wined3d_mutex_unlock(); 2266 if (FAILED(hr)) 2267 { 2268 WARN("Failed to end the state block, hr %#x.\n", hr); 2269 return hr; 2270 } 2271 2272 if (!(object = heap_alloc_zero(sizeof(*object)))) 2273 { 2274 wined3d_mutex_lock(); 2275 wined3d_stateblock_decref(wined3d_stateblock); 2276 wined3d_mutex_unlock(); 2277 return E_OUTOFMEMORY; 2278 } 2279 2280 hr = stateblock_init(object, device, 0, wined3d_stateblock); 2281 if (FAILED(hr)) 2282 { 2283 WARN("Failed to initialize stateblock, hr %#x.\n", hr); 2284 wined3d_mutex_lock(); 2285 wined3d_stateblock_decref(wined3d_stateblock); 2286 wined3d_mutex_unlock(); 2287 heap_free(object); 2288 return hr; 2289 } 2290 2291 TRACE("Created stateblock %p.\n", object); 2292 *stateblock = &object->IDirect3DStateBlock9_iface; 2293 2294 return D3D_OK; 2295 } 2296 2297 static HRESULT WINAPI d3d9_device_SetClipStatus(IDirect3DDevice9Ex *iface, const D3DCLIPSTATUS9 *clip_status) 2298 { 2299 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 2300 HRESULT hr; 2301 2302 TRACE("iface %p, clip_status %p.\n", iface, clip_status); 2303 2304 wined3d_mutex_lock(); 2305 hr = wined3d_device_set_clip_status(device->wined3d_device, (const struct wined3d_clip_status *)clip_status); 2306 wined3d_mutex_unlock(); 2307 2308 return hr; 2309 } 2310 2311 static HRESULT WINAPI d3d9_device_GetClipStatus(IDirect3DDevice9Ex *iface, D3DCLIPSTATUS9 *clip_status) 2312 { 2313 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 2314 HRESULT hr; 2315 2316 TRACE("iface %p, clip_status %p.\n", iface, clip_status); 2317 2318 wined3d_mutex_lock(); 2319 hr = wined3d_device_get_clip_status(device->wined3d_device, (struct wined3d_clip_status *)clip_status); 2320 wined3d_mutex_unlock(); 2321 2322 return hr; 2323 } 2324 2325 static HRESULT WINAPI d3d9_device_GetTexture(IDirect3DDevice9Ex *iface, DWORD stage, IDirect3DBaseTexture9 **texture) 2326 { 2327 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 2328 struct wined3d_texture *wined3d_texture = NULL; 2329 struct d3d9_texture *texture_impl; 2330 2331 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture); 2332 2333 if (!texture) 2334 return D3DERR_INVALIDCALL; 2335 2336 wined3d_mutex_lock(); 2337 if ((wined3d_texture = wined3d_device_get_texture(device->wined3d_device, stage))) 2338 { 2339 texture_impl = wined3d_texture_get_parent(wined3d_texture); 2340 *texture = &texture_impl->IDirect3DBaseTexture9_iface; 2341 IDirect3DBaseTexture9_AddRef(*texture); 2342 } 2343 else 2344 { 2345 *texture = NULL; 2346 } 2347 wined3d_mutex_unlock(); 2348 2349 return D3D_OK; 2350 } 2351 2352 static HRESULT WINAPI d3d9_device_SetTexture(IDirect3DDevice9Ex *iface, DWORD stage, IDirect3DBaseTexture9 *texture) 2353 { 2354 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 2355 struct d3d9_texture *texture_impl; 2356 HRESULT hr; 2357 2358 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture); 2359 2360 texture_impl = unsafe_impl_from_IDirect3DBaseTexture9(texture); 2361 2362 wined3d_mutex_lock(); 2363 hr = wined3d_device_set_texture(device->wined3d_device, stage, 2364 texture_impl ? texture_impl->wined3d_texture : NULL); 2365 if (SUCCEEDED(hr)) 2366 { 2367 unsigned int i = stage >= D3DVERTEXTEXTURESAMPLER0 ? stage - D3DVERTEXTEXTURESAMPLER0 + 16 : stage; 2368 2369 if (stage < ARRAY_SIZE(device->textures)) 2370 device->textures[i] = texture_impl; 2371 } 2372 wined3d_mutex_unlock(); 2373 2374 return hr; 2375 } 2376 2377 static const enum wined3d_texture_stage_state tss_lookup[] = 2378 { 2379 WINED3D_TSS_INVALID, /* 0, unused */ 2380 WINED3D_TSS_COLOR_OP, /* 1, D3DTSS_COLOROP */ 2381 WINED3D_TSS_COLOR_ARG1, /* 2, D3DTSS_COLORARG1 */ 2382 WINED3D_TSS_COLOR_ARG2, /* 3, D3DTSS_COLORARG2 */ 2383 WINED3D_TSS_ALPHA_OP, /* 4, D3DTSS_ALPHAOP */ 2384 WINED3D_TSS_ALPHA_ARG1, /* 5, D3DTSS_ALPHAARG1 */ 2385 WINED3D_TSS_ALPHA_ARG2, /* 6, D3DTSS_ALPHAARG2 */ 2386 WINED3D_TSS_BUMPENV_MAT00, /* 7, D3DTSS_BUMPENVMAT00 */ 2387 WINED3D_TSS_BUMPENV_MAT01, /* 8, D3DTSS_BUMPENVMAT01 */ 2388 WINED3D_TSS_BUMPENV_MAT10, /* 9, D3DTSS_BUMPENVMAT10 */ 2389 WINED3D_TSS_BUMPENV_MAT11, /* 10, D3DTSS_BUMPENVMAT11 */ 2390 WINED3D_TSS_TEXCOORD_INDEX, /* 11, D3DTSS_TEXCOORDINDEX */ 2391 WINED3D_TSS_INVALID, /* 12, unused */ 2392 WINED3D_TSS_INVALID, /* 13, unused */ 2393 WINED3D_TSS_INVALID, /* 14, unused */ 2394 WINED3D_TSS_INVALID, /* 15, unused */ 2395 WINED3D_TSS_INVALID, /* 16, unused */ 2396 WINED3D_TSS_INVALID, /* 17, unused */ 2397 WINED3D_TSS_INVALID, /* 18, unused */ 2398 WINED3D_TSS_INVALID, /* 19, unused */ 2399 WINED3D_TSS_INVALID, /* 20, unused */ 2400 WINED3D_TSS_INVALID, /* 21, unused */ 2401 WINED3D_TSS_BUMPENV_LSCALE, /* 22, D3DTSS_BUMPENVLSCALE */ 2402 WINED3D_TSS_BUMPENV_LOFFSET, /* 23, D3DTSS_BUMPENVLOFFSET */ 2403 WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS, /* 24, D3DTSS_TEXTURETRANSFORMFLAGS */ 2404 WINED3D_TSS_INVALID, /* 25, unused */ 2405 WINED3D_TSS_COLOR_ARG0, /* 26, D3DTSS_COLORARG0 */ 2406 WINED3D_TSS_ALPHA_ARG0, /* 27, D3DTSS_ALPHAARG0 */ 2407 WINED3D_TSS_RESULT_ARG, /* 28, D3DTSS_RESULTARG */ 2408 WINED3D_TSS_INVALID, /* 29, unused */ 2409 WINED3D_TSS_INVALID, /* 30, unused */ 2410 WINED3D_TSS_INVALID, /* 31, unused */ 2411 WINED3D_TSS_CONSTANT, /* 32, D3DTSS_CONSTANT */ 2412 }; 2413 2414 static HRESULT WINAPI d3d9_device_GetTextureStageState(IDirect3DDevice9Ex *iface, 2415 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value) 2416 { 2417 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 2418 2419 TRACE("iface %p, stage %u, state %#x, value %p.\n", iface, stage, state, value); 2420 2421 if (state >= ARRAY_SIZE(tss_lookup)) 2422 { 2423 WARN("Invalid state %#x passed.\n", state); 2424 return D3D_OK; 2425 } 2426 2427 wined3d_mutex_lock(); 2428 *value = wined3d_device_get_texture_stage_state(device->wined3d_device, stage, tss_lookup[state]); 2429 wined3d_mutex_unlock(); 2430 2431 return D3D_OK; 2432 } 2433 2434 static HRESULT WINAPI d3d9_device_SetTextureStageState(IDirect3DDevice9Ex *iface, 2435 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value) 2436 { 2437 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 2438 2439 TRACE("iface %p, stage %u, state %#x, value %#x.\n", iface, stage, state, value); 2440 2441 if (state >= ARRAY_SIZE(tss_lookup)) 2442 { 2443 WARN("Invalid state %#x passed.\n", state); 2444 return D3D_OK; 2445 } 2446 2447 wined3d_mutex_lock(); 2448 wined3d_device_set_texture_stage_state(device->wined3d_device, stage, tss_lookup[state], value); 2449 wined3d_mutex_unlock(); 2450 2451 return D3D_OK; 2452 } 2453 2454 static HRESULT WINAPI d3d9_device_GetSamplerState(IDirect3DDevice9Ex *iface, 2455 DWORD sampler, D3DSAMPLERSTATETYPE state, DWORD *value) 2456 { 2457 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 2458 2459 TRACE("iface %p, sampler %u, state %#x, value %p.\n", iface, sampler, state, value); 2460 2461 wined3d_mutex_lock(); 2462 *value = wined3d_device_get_sampler_state(device->wined3d_device, sampler, state); 2463 wined3d_mutex_unlock(); 2464 2465 return D3D_OK; 2466 } 2467 2468 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d9_device_SetSamplerState(IDirect3DDevice9Ex *iface, 2469 DWORD sampler, D3DSAMPLERSTATETYPE state, DWORD value) 2470 { 2471 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 2472 2473 TRACE("iface %p, sampler %u, state %#x, value %#x.\n", iface, sampler, state, value); 2474 2475 wined3d_mutex_lock(); 2476 wined3d_device_set_sampler_state(device->wined3d_device, sampler, state, value); 2477 wined3d_mutex_unlock(); 2478 2479 return D3D_OK; 2480 } 2481 2482 static HRESULT WINAPI d3d9_device_ValidateDevice(IDirect3DDevice9Ex *iface, DWORD *pass_count) 2483 { 2484 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 2485 HRESULT hr; 2486 2487 TRACE("iface %p, pass_count %p.\n", iface, pass_count); 2488 2489 wined3d_mutex_lock(); 2490 hr = wined3d_device_validate_device(device->wined3d_device, pass_count); 2491 wined3d_mutex_unlock(); 2492 2493 return hr; 2494 } 2495 2496 static HRESULT WINAPI d3d9_device_SetPaletteEntries(IDirect3DDevice9Ex *iface, 2497 UINT palette_idx, const PALETTEENTRY *entries) 2498 { 2499 WARN("iface %p, palette_idx %u, entries %p unimplemented.\n", iface, palette_idx, entries); 2500 2501 /* The d3d9 palette API is non-functional on Windows. Getters and setters are implemented, 2502 * and some drivers allow the creation of P8 surfaces. These surfaces can be copied to 2503 * other P8 surfaces with StretchRect, but cannot be converted to (A)RGB. 2504 * 2505 * Some older(dx7) cards may have support for P8 textures, but games cannot rely on this. */ 2506 return D3D_OK; 2507 } 2508 2509 static HRESULT WINAPI d3d9_device_GetPaletteEntries(IDirect3DDevice9Ex *iface, 2510 UINT palette_idx, PALETTEENTRY *entries) 2511 { 2512 FIXME("iface %p, palette_idx %u, entries %p unimplemented.\n", iface, palette_idx, entries); 2513 2514 return D3DERR_INVALIDCALL; 2515 } 2516 2517 static HRESULT WINAPI d3d9_device_SetCurrentTexturePalette(IDirect3DDevice9Ex *iface, UINT palette_idx) 2518 { 2519 WARN("iface %p, palette_idx %u unimplemented.\n", iface, palette_idx); 2520 2521 return D3D_OK; 2522 } 2523 2524 static HRESULT WINAPI d3d9_device_GetCurrentTexturePalette(IDirect3DDevice9Ex *iface, UINT *palette_idx) 2525 { 2526 FIXME("iface %p, palette_idx %p.\n", iface, palette_idx); 2527 2528 return D3DERR_INVALIDCALL; 2529 } 2530 2531 static HRESULT WINAPI d3d9_device_SetScissorRect(IDirect3DDevice9Ex *iface, const RECT *rect) 2532 { 2533 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 2534 2535 TRACE("iface %p, rect %p.\n", iface, rect); 2536 2537 wined3d_mutex_lock(); 2538 wined3d_device_set_scissor_rect(device->wined3d_device, rect); 2539 wined3d_mutex_unlock(); 2540 2541 return D3D_OK; 2542 } 2543 2544 static HRESULT WINAPI d3d9_device_GetScissorRect(IDirect3DDevice9Ex *iface, RECT *rect) 2545 { 2546 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 2547 2548 TRACE("iface %p, rect %p.\n", iface, rect); 2549 2550 wined3d_mutex_lock(); 2551 wined3d_device_get_scissor_rect(device->wined3d_device, rect); 2552 wined3d_mutex_unlock(); 2553 2554 return D3D_OK; 2555 } 2556 2557 static HRESULT WINAPI d3d9_device_SetSoftwareVertexProcessing(IDirect3DDevice9Ex *iface, BOOL software) 2558 { 2559 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 2560 2561 TRACE("iface %p, software %#x.\n", iface, software); 2562 2563 wined3d_mutex_lock(); 2564 wined3d_device_set_software_vertex_processing(device->wined3d_device, software); 2565 wined3d_mutex_unlock(); 2566 2567 return D3D_OK; 2568 } 2569 2570 static BOOL WINAPI d3d9_device_GetSoftwareVertexProcessing(IDirect3DDevice9Ex *iface) 2571 { 2572 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 2573 BOOL ret; 2574 2575 TRACE("iface %p.\n", iface); 2576 2577 wined3d_mutex_lock(); 2578 ret = wined3d_device_get_software_vertex_processing(device->wined3d_device); 2579 wined3d_mutex_unlock(); 2580 2581 return ret; 2582 } 2583 2584 static HRESULT WINAPI d3d9_device_SetNPatchMode(IDirect3DDevice9Ex *iface, float segment_count) 2585 { 2586 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 2587 HRESULT hr; 2588 2589 TRACE("iface %p, segment_count %.8e.\n", iface, segment_count); 2590 2591 wined3d_mutex_lock(); 2592 hr = wined3d_device_set_npatch_mode(device->wined3d_device, segment_count); 2593 wined3d_mutex_unlock(); 2594 2595 return hr; 2596 } 2597 2598 static float WINAPI d3d9_device_GetNPatchMode(IDirect3DDevice9Ex *iface) 2599 { 2600 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 2601 float ret; 2602 2603 TRACE("iface %p.\n", iface); 2604 2605 wined3d_mutex_lock(); 2606 ret = wined3d_device_get_npatch_mode(device->wined3d_device); 2607 wined3d_mutex_unlock(); 2608 2609 return ret; 2610 } 2611 2612 /* wined3d critical section must be taken by the caller. */ 2613 static void d3d9_generate_auto_mipmaps(struct d3d9_device *device) 2614 { 2615 unsigned int i; 2616 2617 for (i = 0; i < ARRAY_SIZE(device->textures); ++i) 2618 if (device->textures[i]) 2619 d3d9_texture_gen_auto_mipmap(device->textures[i]); 2620 } 2621 2622 static HRESULT WINAPI d3d9_device_DrawPrimitive(IDirect3DDevice9Ex *iface, 2623 D3DPRIMITIVETYPE primitive_type, UINT start_vertex, UINT primitive_count) 2624 { 2625 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 2626 HRESULT hr; 2627 2628 TRACE("iface %p, primitive_type %#x, start_vertex %u, primitive_count %u.\n", 2629 iface, primitive_type, start_vertex, primitive_count); 2630 2631 wined3d_mutex_lock(); 2632 if (!device->has_vertex_declaration) 2633 { 2634 wined3d_mutex_unlock(); 2635 WARN("Called without a valid vertex declaration set.\n"); 2636 return D3DERR_INVALIDCALL; 2637 } 2638 d3d9_generate_auto_mipmaps(device); 2639 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type, 0); 2640 hr = wined3d_device_draw_primitive(device->wined3d_device, start_vertex, 2641 vertex_count_from_primitive_count(primitive_type, primitive_count)); 2642 if (SUCCEEDED(hr)) 2643 d3d9_rts_flag_auto_gen_mipmap(device); 2644 wined3d_mutex_unlock(); 2645 2646 return hr; 2647 } 2648 2649 static HRESULT WINAPI d3d9_device_DrawIndexedPrimitive(IDirect3DDevice9Ex *iface, 2650 D3DPRIMITIVETYPE primitive_type, INT base_vertex_idx, UINT min_vertex_idx, 2651 UINT vertex_count, UINT start_idx, UINT primitive_count) 2652 { 2653 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 2654 HRESULT hr; 2655 2656 TRACE("iface %p, primitive_type %#x, base_vertex_idx %u, min_vertex_idx %u, " 2657 "vertex_count %u, start_idx %u, primitive_count %u.\n", 2658 iface, primitive_type, base_vertex_idx, min_vertex_idx, 2659 vertex_count, start_idx, primitive_count); 2660 2661 wined3d_mutex_lock(); 2662 if (!device->has_vertex_declaration) 2663 { 2664 wined3d_mutex_unlock(); 2665 WARN("Called without a valid vertex declaration set.\n"); 2666 return D3DERR_INVALIDCALL; 2667 } 2668 d3d9_generate_auto_mipmaps(device); 2669 wined3d_device_set_base_vertex_index(device->wined3d_device, base_vertex_idx); 2670 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type, 0); 2671 hr = wined3d_device_draw_indexed_primitive(device->wined3d_device, start_idx, 2672 vertex_count_from_primitive_count(primitive_type, primitive_count)); 2673 if (SUCCEEDED(hr)) 2674 d3d9_rts_flag_auto_gen_mipmap(device); 2675 wined3d_mutex_unlock(); 2676 2677 return hr; 2678 } 2679 2680 /* The caller is responsible for wined3d locking */ 2681 static HRESULT d3d9_device_prepare_vertex_buffer(struct d3d9_device *device, UINT min_size) 2682 { 2683 HRESULT hr; 2684 2685 if (device->vertex_buffer_size < min_size || !device->vertex_buffer) 2686 { 2687 UINT size = max(device->vertex_buffer_size * 2, min_size); 2688 struct wined3d_buffer_desc desc; 2689 struct wined3d_buffer *buffer; 2690 2691 TRACE("Growing vertex buffer to %u bytes.\n", size); 2692 2693 desc.byte_width = size; 2694 desc.usage = WINED3DUSAGE_DYNAMIC | WINED3DUSAGE_WRITEONLY; 2695 desc.bind_flags = WINED3D_BIND_VERTEX_BUFFER; 2696 desc.access = WINED3D_RESOURCE_ACCESS_GPU | WINED3D_RESOURCE_ACCESS_MAP_R | WINED3D_RESOURCE_ACCESS_MAP_W; 2697 desc.misc_flags = 0; 2698 desc.structure_byte_stride = 0; 2699 2700 if (FAILED(hr = wined3d_buffer_create(device->wined3d_device, &desc, 2701 NULL, NULL, &d3d9_null_wined3d_parent_ops, &buffer))) 2702 { 2703 ERR("Failed to create vertex buffer, hr %#x.\n", hr); 2704 return hr; 2705 } 2706 2707 if (device->vertex_buffer) 2708 wined3d_buffer_decref(device->vertex_buffer); 2709 2710 device->vertex_buffer = buffer; 2711 device->vertex_buffer_size = size; 2712 device->vertex_buffer_pos = 0; 2713 } 2714 return D3D_OK; 2715 } 2716 2717 static HRESULT WINAPI d3d9_device_DrawPrimitiveUP(IDirect3DDevice9Ex *iface, 2718 D3DPRIMITIVETYPE primitive_type, UINT primitive_count, const void *data, UINT stride) 2719 { 2720 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 2721 HRESULT hr; 2722 UINT vtx_count = vertex_count_from_primitive_count(primitive_type, primitive_count); 2723 struct wined3d_map_desc wined3d_map_desc; 2724 struct wined3d_box wined3d_box = {0}; 2725 UINT size = vtx_count * stride; 2726 struct wined3d_resource *vb; 2727 UINT vb_pos, align; 2728 2729 TRACE("iface %p, primitive_type %#x, primitive_count %u, data %p, stride %u.\n", 2730 iface, primitive_type, primitive_count, data, stride); 2731 2732 if (!primitive_count) 2733 { 2734 WARN("primitive_count is 0, returning D3D_OK\n"); 2735 return D3D_OK; 2736 } 2737 2738 wined3d_mutex_lock(); 2739 2740 if (!device->has_vertex_declaration) 2741 { 2742 wined3d_mutex_unlock(); 2743 WARN("Called without a valid vertex declaration set.\n"); 2744 return D3DERR_INVALIDCALL; 2745 } 2746 2747 hr = d3d9_device_prepare_vertex_buffer(device, size); 2748 if (FAILED(hr)) 2749 goto done; 2750 2751 vb_pos = device->vertex_buffer_pos; 2752 align = vb_pos % stride; 2753 if (align) align = stride - align; 2754 if (vb_pos + size + align > device->vertex_buffer_size) 2755 vb_pos = 0; 2756 else 2757 vb_pos += align; 2758 2759 wined3d_box.left = vb_pos; 2760 wined3d_box.right = vb_pos + size; 2761 vb = wined3d_buffer_get_resource(device->vertex_buffer); 2762 if (FAILED(hr = wined3d_resource_map(vb, 0, &wined3d_map_desc, &wined3d_box, 2763 WINED3D_MAP_WRITE | (vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD)))) 2764 goto done; 2765 memcpy(wined3d_map_desc.data, data, size); 2766 wined3d_resource_unmap(vb, 0); 2767 device->vertex_buffer_pos = vb_pos + size; 2768 2769 hr = wined3d_device_set_stream_source(device->wined3d_device, 0, device->vertex_buffer, 0, stride); 2770 if (FAILED(hr)) 2771 goto done; 2772 2773 d3d9_generate_auto_mipmaps(device); 2774 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type, 0); 2775 hr = wined3d_device_draw_primitive(device->wined3d_device, vb_pos / stride, vtx_count); 2776 wined3d_device_set_stream_source(device->wined3d_device, 0, NULL, 0, 0); 2777 if (SUCCEEDED(hr)) 2778 d3d9_rts_flag_auto_gen_mipmap(device); 2779 2780 done: 2781 wined3d_mutex_unlock(); 2782 return hr; 2783 } 2784 2785 /* The caller is responsible for wined3d locking */ 2786 static HRESULT d3d9_device_prepare_index_buffer(struct d3d9_device *device, UINT min_size) 2787 { 2788 HRESULT hr; 2789 2790 if (device->index_buffer_size < min_size || !device->index_buffer) 2791 { 2792 UINT size = max(device->index_buffer_size * 2, min_size); 2793 struct wined3d_buffer_desc desc; 2794 struct wined3d_buffer *buffer; 2795 2796 TRACE("Growing index buffer to %u bytes.\n", size); 2797 2798 desc.byte_width = size; 2799 desc.usage = WINED3DUSAGE_DYNAMIC | WINED3DUSAGE_WRITEONLY | WINED3DUSAGE_STATICDECL; 2800 desc.bind_flags = WINED3D_BIND_INDEX_BUFFER; 2801 desc.access = WINED3D_RESOURCE_ACCESS_GPU | WINED3D_RESOURCE_ACCESS_MAP_R | WINED3D_RESOURCE_ACCESS_MAP_W; 2802 desc.misc_flags = 0; 2803 desc.structure_byte_stride = 0; 2804 2805 if (FAILED(hr = wined3d_buffer_create(device->wined3d_device, &desc, 2806 NULL, NULL, &d3d9_null_wined3d_parent_ops, &buffer))) 2807 { 2808 ERR("Failed to create index buffer, hr %#x.\n", hr); 2809 return hr; 2810 } 2811 2812 if (device->index_buffer) 2813 wined3d_buffer_decref(device->index_buffer); 2814 2815 device->index_buffer = buffer; 2816 device->index_buffer_size = size; 2817 device->index_buffer_pos = 0; 2818 } 2819 return D3D_OK; 2820 } 2821 2822 static HRESULT WINAPI d3d9_device_DrawIndexedPrimitiveUP(IDirect3DDevice9Ex *iface, 2823 D3DPRIMITIVETYPE primitive_type, UINT min_vertex_idx, UINT vertex_count, 2824 UINT primitive_count, const void *index_data, D3DFORMAT index_format, 2825 const void *vertex_data, UINT vertex_stride) 2826 { 2827 UINT idx_count = vertex_count_from_primitive_count(primitive_type, primitive_count); 2828 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 2829 UINT idx_fmt_size = index_format == D3DFMT_INDEX16 ? 2 : 4; 2830 UINT vtx_size = vertex_count * vertex_stride; 2831 UINT idx_size = idx_count * idx_fmt_size; 2832 struct wined3d_map_desc wined3d_map_desc; 2833 struct wined3d_box wined3d_box = {0}; 2834 struct wined3d_resource *ib, *vb; 2835 UINT vb_pos, ib_pos, align; 2836 HRESULT hr; 2837 2838 TRACE("iface %p, primitive_type %#x, min_vertex_idx %u, vertex_count %u, primitive_count %u, " 2839 "index_data %p, index_format %#x, vertex_data %p, vertex_stride %u.\n", 2840 iface, primitive_type, min_vertex_idx, vertex_count, primitive_count, 2841 index_data, index_format, vertex_data, vertex_stride); 2842 2843 if (!primitive_count) 2844 { 2845 WARN("primitive_count is 0, returning D3D_OK.\n"); 2846 return D3D_OK; 2847 } 2848 2849 wined3d_mutex_lock(); 2850 2851 if (!device->has_vertex_declaration) 2852 { 2853 wined3d_mutex_unlock(); 2854 WARN("Called without a valid vertex declaration set.\n"); 2855 return D3DERR_INVALIDCALL; 2856 } 2857 2858 hr = d3d9_device_prepare_vertex_buffer(device, vtx_size); 2859 if (FAILED(hr)) 2860 goto done; 2861 2862 vb_pos = device->vertex_buffer_pos; 2863 align = vb_pos % vertex_stride; 2864 if (align) align = vertex_stride - align; 2865 if (vb_pos + vtx_size + align > device->vertex_buffer_size) 2866 vb_pos = 0; 2867 else 2868 vb_pos += align; 2869 2870 wined3d_box.left = vb_pos; 2871 wined3d_box.right = vb_pos + vtx_size; 2872 vb = wined3d_buffer_get_resource(device->vertex_buffer); 2873 if (FAILED(hr = wined3d_resource_map(vb, 0, &wined3d_map_desc, &wined3d_box, 2874 WINED3D_MAP_WRITE | (vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD)))) 2875 goto done; 2876 memcpy(wined3d_map_desc.data, (char *)vertex_data + min_vertex_idx * vertex_stride, vtx_size); 2877 wined3d_resource_unmap(vb, 0); 2878 device->vertex_buffer_pos = vb_pos + vtx_size; 2879 2880 hr = d3d9_device_prepare_index_buffer(device, idx_size); 2881 if (FAILED(hr)) 2882 goto done; 2883 2884 ib_pos = device->index_buffer_pos; 2885 align = ib_pos % idx_fmt_size; 2886 if (align) align = idx_fmt_size - align; 2887 if (ib_pos + idx_size + align > device->index_buffer_size) 2888 ib_pos = 0; 2889 else 2890 ib_pos += align; 2891 2892 wined3d_box.left = ib_pos; 2893 wined3d_box.right = ib_pos + idx_size; 2894 ib = wined3d_buffer_get_resource(device->index_buffer); 2895 if (FAILED(hr = wined3d_resource_map(ib, 0, &wined3d_map_desc, &wined3d_box, 2896 WINED3D_MAP_WRITE | (ib_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD)))) 2897 goto done; 2898 memcpy(wined3d_map_desc.data, index_data, idx_size); 2899 wined3d_resource_unmap(ib, 0); 2900 device->index_buffer_pos = ib_pos + idx_size; 2901 2902 hr = wined3d_device_set_stream_source(device->wined3d_device, 0, device->vertex_buffer, 0, vertex_stride); 2903 if (FAILED(hr)) 2904 goto done; 2905 2906 d3d9_generate_auto_mipmaps(device); 2907 wined3d_device_set_index_buffer(device->wined3d_device, device->index_buffer, 2908 wined3dformat_from_d3dformat(index_format), 0); 2909 wined3d_device_set_base_vertex_index(device->wined3d_device, vb_pos / vertex_stride - min_vertex_idx); 2910 2911 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type, 0); 2912 hr = wined3d_device_draw_indexed_primitive(device->wined3d_device, ib_pos / idx_fmt_size, idx_count); 2913 2914 wined3d_device_set_stream_source(device->wined3d_device, 0, NULL, 0, 0); 2915 wined3d_device_set_index_buffer(device->wined3d_device, NULL, WINED3DFMT_UNKNOWN, 0); 2916 wined3d_device_set_base_vertex_index(device->wined3d_device, 0); 2917 2918 if (SUCCEEDED(hr)) 2919 d3d9_rts_flag_auto_gen_mipmap(device); 2920 2921 done: 2922 wined3d_mutex_unlock(); 2923 return hr; 2924 } 2925 2926 static HRESULT WINAPI d3d9_device_ProcessVertices(IDirect3DDevice9Ex *iface, 2927 UINT src_start_idx, UINT dst_idx, UINT vertex_count, IDirect3DVertexBuffer9 *dst_buffer, 2928 IDirect3DVertexDeclaration9 *declaration, DWORD flags) 2929 { 2930 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 2931 struct d3d9_vertexbuffer *dst_impl = unsafe_impl_from_IDirect3DVertexBuffer9(dst_buffer); 2932 struct d3d9_vertex_declaration *decl_impl = unsafe_impl_from_IDirect3DVertexDeclaration9(declaration); 2933 HRESULT hr; 2934 2935 TRACE("iface %p, src_start_idx %u, dst_idx %u, vertex_count %u, dst_buffer %p, declaration %p, flags %#x.\n", 2936 iface, src_start_idx, dst_idx, vertex_count, dst_buffer, declaration, flags); 2937 2938 wined3d_mutex_lock(); 2939 hr = wined3d_device_process_vertices(device->wined3d_device, src_start_idx, dst_idx, vertex_count, 2940 dst_impl->wined3d_buffer, decl_impl ? decl_impl->wined3d_declaration : NULL, 2941 flags, dst_impl->fvf); 2942 wined3d_mutex_unlock(); 2943 2944 return hr; 2945 } 2946 2947 static HRESULT WINAPI d3d9_device_CreateVertexDeclaration(IDirect3DDevice9Ex *iface, 2948 const D3DVERTEXELEMENT9 *elements, IDirect3DVertexDeclaration9 **declaration) 2949 { 2950 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 2951 struct d3d9_vertex_declaration *object; 2952 HRESULT hr; 2953 2954 TRACE("iface %p, elements %p, declaration %p.\n", iface, elements, declaration); 2955 2956 if (!declaration) 2957 { 2958 WARN("Caller passed a NULL declaration, returning D3DERR_INVALIDCALL.\n"); 2959 return D3DERR_INVALIDCALL; 2960 } 2961 2962 if (SUCCEEDED(hr = d3d9_vertex_declaration_create(device, elements, &object))) 2963 *declaration = &object->IDirect3DVertexDeclaration9_iface; 2964 2965 return hr; 2966 } 2967 2968 static HRESULT WINAPI d3d9_device_SetVertexDeclaration(IDirect3DDevice9Ex *iface, 2969 IDirect3DVertexDeclaration9 *declaration) 2970 { 2971 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 2972 struct d3d9_vertex_declaration *decl_impl = unsafe_impl_from_IDirect3DVertexDeclaration9(declaration); 2973 2974 TRACE("iface %p, declaration %p.\n", iface, declaration); 2975 2976 wined3d_mutex_lock(); 2977 wined3d_device_set_vertex_declaration(device->wined3d_device, 2978 decl_impl ? decl_impl->wined3d_declaration : NULL); 2979 device->has_vertex_declaration = !!decl_impl; 2980 wined3d_mutex_unlock(); 2981 2982 return D3D_OK; 2983 } 2984 2985 static HRESULT WINAPI d3d9_device_GetVertexDeclaration(IDirect3DDevice9Ex *iface, 2986 IDirect3DVertexDeclaration9 **declaration) 2987 { 2988 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 2989 struct wined3d_vertex_declaration *wined3d_declaration; 2990 struct d3d9_vertex_declaration *declaration_impl; 2991 2992 TRACE("iface %p, declaration %p.\n", iface, declaration); 2993 2994 if (!declaration) return D3DERR_INVALIDCALL; 2995 2996 wined3d_mutex_lock(); 2997 if ((wined3d_declaration = wined3d_device_get_vertex_declaration(device->wined3d_device))) 2998 { 2999 declaration_impl = wined3d_vertex_declaration_get_parent(wined3d_declaration); 3000 *declaration = &declaration_impl->IDirect3DVertexDeclaration9_iface; 3001 IDirect3DVertexDeclaration9_AddRef(*declaration); 3002 } 3003 else 3004 { 3005 *declaration = NULL; 3006 } 3007 wined3d_mutex_unlock(); 3008 3009 TRACE("Returning %p.\n", *declaration); 3010 return D3D_OK; 3011 } 3012 3013 static struct wined3d_vertex_declaration *device_get_fvf_declaration(struct d3d9_device *device, DWORD fvf) 3014 { 3015 struct wined3d_vertex_declaration *wined3d_declaration; 3016 struct fvf_declaration *fvf_decls = device->fvf_decls; 3017 struct d3d9_vertex_declaration *d3d9_declaration; 3018 D3DVERTEXELEMENT9 *elements; 3019 int p, low, high; /* deliberately signed */ 3020 HRESULT hr; 3021 3022 TRACE("Searching for declaration for fvf %08x... ", fvf); 3023 3024 low = 0; 3025 high = device->fvf_decl_count - 1; 3026 while (low <= high) 3027 { 3028 p = (low + high) >> 1; 3029 TRACE("%d ", p); 3030 3031 if (fvf_decls[p].fvf == fvf) 3032 { 3033 TRACE("found %p.\n", fvf_decls[p].decl); 3034 return fvf_decls[p].decl; 3035 } 3036 3037 if (fvf_decls[p].fvf < fvf) 3038 low = p + 1; 3039 else 3040 high = p - 1; 3041 } 3042 TRACE("not found. Creating and inserting at position %d.\n", low); 3043 3044 if (FAILED(hr = vdecl_convert_fvf(fvf, &elements))) 3045 return NULL; 3046 3047 hr = d3d9_vertex_declaration_create(device, elements, &d3d9_declaration); 3048 heap_free(elements); 3049 if (FAILED(hr)) 3050 return NULL; 3051 3052 if (device->fvf_decl_size == device->fvf_decl_count) 3053 { 3054 UINT grow = max(device->fvf_decl_size / 2, 8); 3055 3056 if (!(fvf_decls = heap_realloc(fvf_decls, sizeof(*fvf_decls) * (device->fvf_decl_size + grow)))) 3057 { 3058 IDirect3DVertexDeclaration9_Release(&d3d9_declaration->IDirect3DVertexDeclaration9_iface); 3059 return NULL; 3060 } 3061 device->fvf_decls = fvf_decls; 3062 device->fvf_decl_size += grow; 3063 } 3064 3065 d3d9_declaration->fvf = fvf; 3066 wined3d_declaration = d3d9_declaration->wined3d_declaration; 3067 wined3d_vertex_declaration_incref(wined3d_declaration); 3068 IDirect3DVertexDeclaration9_Release(&d3d9_declaration->IDirect3DVertexDeclaration9_iface); 3069 3070 memmove(fvf_decls + low + 1, fvf_decls + low, sizeof(*fvf_decls) * (device->fvf_decl_count - low)); 3071 fvf_decls[low].decl = wined3d_declaration; 3072 fvf_decls[low].fvf = fvf; 3073 ++device->fvf_decl_count; 3074 3075 TRACE("Returning %p. %u declarations in array.\n", wined3d_declaration, device->fvf_decl_count); 3076 3077 return wined3d_declaration; 3078 } 3079 3080 static HRESULT WINAPI d3d9_device_SetFVF(IDirect3DDevice9Ex *iface, DWORD fvf) 3081 { 3082 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 3083 struct wined3d_vertex_declaration *decl; 3084 3085 TRACE("iface %p, fvf %#x.\n", iface, fvf); 3086 3087 if (!fvf) 3088 { 3089 WARN("%#x is not a valid FVF.\n", fvf); 3090 return D3D_OK; 3091 } 3092 3093 wined3d_mutex_lock(); 3094 if (!(decl = device_get_fvf_declaration(device, fvf))) 3095 { 3096 wined3d_mutex_unlock(); 3097 ERR("Failed to create a vertex declaration for fvf %#x.\n", fvf); 3098 return D3DERR_DRIVERINTERNALERROR; 3099 } 3100 3101 wined3d_device_set_vertex_declaration(device->wined3d_device, decl); 3102 device->has_vertex_declaration = TRUE; 3103 wined3d_mutex_unlock(); 3104 3105 return D3D_OK; 3106 } 3107 3108 static HRESULT WINAPI d3d9_device_GetFVF(IDirect3DDevice9Ex *iface, DWORD *fvf) 3109 { 3110 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 3111 struct wined3d_vertex_declaration *wined3d_declaration; 3112 struct d3d9_vertex_declaration *d3d9_declaration; 3113 3114 TRACE("iface %p, fvf %p.\n", iface, fvf); 3115 3116 wined3d_mutex_lock(); 3117 if ((wined3d_declaration = wined3d_device_get_vertex_declaration(device->wined3d_device))) 3118 { 3119 d3d9_declaration = wined3d_vertex_declaration_get_parent(wined3d_declaration); 3120 *fvf = d3d9_declaration->fvf; 3121 } 3122 else 3123 { 3124 *fvf = 0; 3125 } 3126 wined3d_mutex_unlock(); 3127 3128 TRACE("Returning FVF %#x.\n", *fvf); 3129 3130 return D3D_OK; 3131 } 3132 3133 static HRESULT WINAPI d3d9_device_CreateVertexShader(IDirect3DDevice9Ex *iface, 3134 const DWORD *byte_code, IDirect3DVertexShader9 **shader) 3135 { 3136 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 3137 struct d3d9_vertexshader *object; 3138 HRESULT hr; 3139 3140 TRACE("iface %p, byte_code %p, shader %p.\n", iface, byte_code, shader); 3141 3142 if (!(object = heap_alloc_zero(sizeof(*object)))) 3143 return E_OUTOFMEMORY; 3144 3145 hr = vertexshader_init(object, device, byte_code); 3146 if (FAILED(hr)) 3147 { 3148 WARN("Failed to initialize vertex shader, hr %#x.\n", hr); 3149 heap_free(object); 3150 return hr; 3151 } 3152 3153 TRACE("Created vertex shader %p.\n", object); 3154 *shader = &object->IDirect3DVertexShader9_iface; 3155 3156 return D3D_OK; 3157 } 3158 3159 static HRESULT WINAPI d3d9_device_SetVertexShader(IDirect3DDevice9Ex *iface, IDirect3DVertexShader9 *shader) 3160 { 3161 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 3162 struct d3d9_vertexshader *shader_obj = unsafe_impl_from_IDirect3DVertexShader9(shader); 3163 3164 TRACE("iface %p, shader %p.\n", iface, shader); 3165 3166 wined3d_mutex_lock(); 3167 wined3d_device_set_vertex_shader(device->wined3d_device, 3168 shader_obj ? shader_obj->wined3d_shader : NULL); 3169 wined3d_mutex_unlock(); 3170 3171 return D3D_OK; 3172 } 3173 3174 static HRESULT WINAPI d3d9_device_GetVertexShader(IDirect3DDevice9Ex *iface, IDirect3DVertexShader9 **shader) 3175 { 3176 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 3177 struct d3d9_vertexshader *shader_impl; 3178 struct wined3d_shader *wined3d_shader; 3179 3180 TRACE("iface %p, shader %p.\n", iface, shader); 3181 3182 wined3d_mutex_lock(); 3183 if ((wined3d_shader = wined3d_device_get_vertex_shader(device->wined3d_device))) 3184 { 3185 shader_impl = wined3d_shader_get_parent(wined3d_shader); 3186 *shader = &shader_impl->IDirect3DVertexShader9_iface; 3187 IDirect3DVertexShader9_AddRef(*shader); 3188 } 3189 else 3190 { 3191 *shader = NULL; 3192 } 3193 wined3d_mutex_unlock(); 3194 3195 TRACE("Returning %p.\n", *shader); 3196 3197 return D3D_OK; 3198 } 3199 3200 static HRESULT WINAPI d3d9_device_SetVertexShaderConstantF(IDirect3DDevice9Ex *iface, 3201 UINT reg_idx, const float *data, UINT count) 3202 { 3203 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 3204 HRESULT hr; 3205 3206 TRACE("iface %p, reg_idx %u, data %p, count %u.\n", iface, reg_idx, data, count); 3207 3208 if (reg_idx + count > D3D9_MAX_VERTEX_SHADER_CONSTANTF) 3209 { 3210 WARN("Trying to access %u constants, but d3d9 only supports %u\n", 3211 reg_idx + count, D3D9_MAX_VERTEX_SHADER_CONSTANTF); 3212 return D3DERR_INVALIDCALL; 3213 } 3214 3215 wined3d_mutex_lock(); 3216 hr = wined3d_device_set_vs_consts_f(device->wined3d_device, 3217 reg_idx, count, (const struct wined3d_vec4 *)data); 3218 wined3d_mutex_unlock(); 3219 3220 return hr; 3221 } 3222 3223 static HRESULT WINAPI d3d9_device_GetVertexShaderConstantF(IDirect3DDevice9Ex *iface, 3224 UINT reg_idx, float *data, UINT count) 3225 { 3226 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 3227 HRESULT hr; 3228 3229 TRACE("iface %p, reg_idx %u, data %p, count %u.\n", iface, reg_idx, data, count); 3230 3231 if (reg_idx + count > D3D9_MAX_VERTEX_SHADER_CONSTANTF) 3232 { 3233 WARN("Trying to access %u constants, but d3d9 only supports %u\n", 3234 reg_idx + count, D3D9_MAX_VERTEX_SHADER_CONSTANTF); 3235 return D3DERR_INVALIDCALL; 3236 } 3237 3238 wined3d_mutex_lock(); 3239 hr = wined3d_device_get_vs_consts_f(device->wined3d_device, 3240 reg_idx, count, (struct wined3d_vec4 *)data); 3241 wined3d_mutex_unlock(); 3242 3243 return hr; 3244 } 3245 3246 static HRESULT WINAPI d3d9_device_SetVertexShaderConstantI(IDirect3DDevice9Ex *iface, 3247 UINT reg_idx, const int *data, UINT count) 3248 { 3249 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 3250 HRESULT hr; 3251 3252 TRACE("iface %p, reg_idx %u, data %p, count %u.\n", iface, reg_idx, data, count); 3253 3254 wined3d_mutex_lock(); 3255 hr = wined3d_device_set_vs_consts_i(device->wined3d_device, 3256 reg_idx, count, (const struct wined3d_ivec4 *)data); 3257 wined3d_mutex_unlock(); 3258 3259 return hr; 3260 } 3261 3262 static HRESULT WINAPI d3d9_device_GetVertexShaderConstantI(IDirect3DDevice9Ex *iface, 3263 UINT reg_idx, int *data, UINT count) 3264 { 3265 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 3266 HRESULT hr; 3267 3268 TRACE("iface %p, reg_idx %u, data %p, count %u.\n", iface, reg_idx, data, count); 3269 3270 wined3d_mutex_lock(); 3271 hr = wined3d_device_get_vs_consts_i(device->wined3d_device, 3272 reg_idx, count, (struct wined3d_ivec4 *)data); 3273 wined3d_mutex_unlock(); 3274 3275 return hr; 3276 } 3277 3278 static HRESULT WINAPI d3d9_device_SetVertexShaderConstantB(IDirect3DDevice9Ex *iface, 3279 UINT reg_idx, const BOOL *data, UINT count) 3280 { 3281 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 3282 HRESULT hr; 3283 3284 TRACE("iface %p, reg_idx %u, data %p, count %u.\n", iface, reg_idx, data, count); 3285 3286 wined3d_mutex_lock(); 3287 hr = wined3d_device_set_vs_consts_b(device->wined3d_device, reg_idx, count, data); 3288 wined3d_mutex_unlock(); 3289 3290 return hr; 3291 } 3292 3293 static HRESULT WINAPI d3d9_device_GetVertexShaderConstantB(IDirect3DDevice9Ex *iface, 3294 UINT reg_idx, BOOL *data, UINT count) 3295 { 3296 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 3297 HRESULT hr; 3298 3299 TRACE("iface %p, reg_idx %u, data %p, count %u.\n", iface, reg_idx, data, count); 3300 3301 wined3d_mutex_lock(); 3302 hr = wined3d_device_get_vs_consts_b(device->wined3d_device, reg_idx, count, data); 3303 wined3d_mutex_unlock(); 3304 3305 return hr; 3306 } 3307 3308 static HRESULT WINAPI d3d9_device_SetStreamSource(IDirect3DDevice9Ex *iface, 3309 UINT stream_idx, IDirect3DVertexBuffer9 *buffer, UINT offset, UINT stride) 3310 { 3311 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 3312 struct d3d9_vertexbuffer *buffer_impl = unsafe_impl_from_IDirect3DVertexBuffer9(buffer); 3313 HRESULT hr; 3314 3315 TRACE("iface %p, stream_idx %u, buffer %p, offset %u, stride %u.\n", 3316 iface, stream_idx, buffer, offset, stride); 3317 3318 wined3d_mutex_lock(); 3319 hr = wined3d_device_set_stream_source(device->wined3d_device, stream_idx, 3320 buffer_impl ? buffer_impl->wined3d_buffer : NULL, offset, stride); 3321 wined3d_mutex_unlock(); 3322 3323 return hr; 3324 } 3325 3326 static HRESULT WINAPI d3d9_device_GetStreamSource(IDirect3DDevice9Ex *iface, 3327 UINT stream_idx, IDirect3DVertexBuffer9 **buffer, UINT *offset, UINT *stride) 3328 { 3329 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 3330 struct d3d9_vertexbuffer *buffer_impl; 3331 struct wined3d_buffer *wined3d_buffer; 3332 HRESULT hr; 3333 3334 TRACE("iface %p, stream_idx %u, buffer %p, offset %p, stride %p.\n", 3335 iface, stream_idx, buffer, offset, stride); 3336 3337 if (!buffer) 3338 return D3DERR_INVALIDCALL; 3339 3340 wined3d_mutex_lock(); 3341 hr = wined3d_device_get_stream_source(device->wined3d_device, stream_idx, &wined3d_buffer, offset, stride); 3342 if (SUCCEEDED(hr) && wined3d_buffer) 3343 { 3344 buffer_impl = wined3d_buffer_get_parent(wined3d_buffer); 3345 *buffer = &buffer_impl->IDirect3DVertexBuffer9_iface; 3346 IDirect3DVertexBuffer9_AddRef(*buffer); 3347 } 3348 else 3349 { 3350 if (FAILED(hr)) 3351 FIXME("Call to GetStreamSource failed %p %p\n", offset, stride); 3352 *buffer = NULL; 3353 } 3354 wined3d_mutex_unlock(); 3355 3356 return hr; 3357 } 3358 3359 static HRESULT WINAPI d3d9_device_SetStreamSourceFreq(IDirect3DDevice9Ex *iface, UINT stream_idx, UINT freq) 3360 { 3361 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 3362 HRESULT hr; 3363 3364 TRACE("iface %p, stream_idx %u, freq %u.\n", iface, stream_idx, freq); 3365 3366 wined3d_mutex_lock(); 3367 hr = wined3d_device_set_stream_source_freq(device->wined3d_device, stream_idx, freq); 3368 wined3d_mutex_unlock(); 3369 3370 return hr; 3371 } 3372 3373 static HRESULT WINAPI d3d9_device_GetStreamSourceFreq(IDirect3DDevice9Ex *iface, UINT stream_idx, UINT *freq) 3374 { 3375 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 3376 HRESULT hr; 3377 3378 TRACE("iface %p, stream_idx %u, freq %p.\n", iface, stream_idx, freq); 3379 3380 wined3d_mutex_lock(); 3381 hr = wined3d_device_get_stream_source_freq(device->wined3d_device, stream_idx, freq); 3382 wined3d_mutex_unlock(); 3383 3384 return hr; 3385 } 3386 3387 static HRESULT WINAPI d3d9_device_SetIndices(IDirect3DDevice9Ex *iface, IDirect3DIndexBuffer9 *buffer) 3388 { 3389 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 3390 struct d3d9_indexbuffer *ib = unsafe_impl_from_IDirect3DIndexBuffer9(buffer); 3391 3392 TRACE("iface %p, buffer %p.\n", iface, buffer); 3393 3394 wined3d_mutex_lock(); 3395 wined3d_device_set_index_buffer(device->wined3d_device, 3396 ib ? ib->wined3d_buffer : NULL, ib ? ib->format : WINED3DFMT_UNKNOWN, 0); 3397 wined3d_mutex_unlock(); 3398 3399 return D3D_OK; 3400 } 3401 3402 static HRESULT WINAPI d3d9_device_GetIndices(IDirect3DDevice9Ex *iface, IDirect3DIndexBuffer9 **buffer) 3403 { 3404 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 3405 enum wined3d_format_id wined3d_format; 3406 struct wined3d_buffer *wined3d_buffer; 3407 struct d3d9_indexbuffer *buffer_impl; 3408 3409 TRACE("iface %p, buffer %p.\n", iface, buffer); 3410 3411 if (!buffer) 3412 return D3DERR_INVALIDCALL; 3413 3414 wined3d_mutex_lock(); 3415 if ((wined3d_buffer = wined3d_device_get_index_buffer(device->wined3d_device, &wined3d_format, NULL))) 3416 { 3417 buffer_impl = wined3d_buffer_get_parent(wined3d_buffer); 3418 *buffer = &buffer_impl->IDirect3DIndexBuffer9_iface; 3419 IDirect3DIndexBuffer9_AddRef(*buffer); 3420 } 3421 else 3422 { 3423 *buffer = NULL; 3424 } 3425 wined3d_mutex_unlock(); 3426 3427 return D3D_OK; 3428 } 3429 3430 static HRESULT WINAPI d3d9_device_CreatePixelShader(IDirect3DDevice9Ex *iface, 3431 const DWORD *byte_code, IDirect3DPixelShader9 **shader) 3432 { 3433 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 3434 struct d3d9_pixelshader *object; 3435 HRESULT hr; 3436 3437 TRACE("iface %p, byte_code %p, shader %p.\n", iface, byte_code, shader); 3438 3439 if (!(object = heap_alloc_zero(sizeof(*object)))) 3440 { 3441 FIXME("Failed to allocate pixel shader memory.\n"); 3442 return E_OUTOFMEMORY; 3443 } 3444 3445 hr = pixelshader_init(object, device, byte_code); 3446 if (FAILED(hr)) 3447 { 3448 WARN("Failed to initialize pixel shader, hr %#x.\n", hr); 3449 heap_free(object); 3450 return hr; 3451 } 3452 3453 TRACE("Created pixel shader %p.\n", object); 3454 *shader = &object->IDirect3DPixelShader9_iface; 3455 3456 return D3D_OK; 3457 } 3458 3459 static HRESULT WINAPI d3d9_device_SetPixelShader(IDirect3DDevice9Ex *iface, IDirect3DPixelShader9 *shader) 3460 { 3461 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 3462 struct d3d9_pixelshader *shader_obj = unsafe_impl_from_IDirect3DPixelShader9(shader); 3463 3464 TRACE("iface %p, shader %p.\n", iface, shader); 3465 3466 wined3d_mutex_lock(); 3467 wined3d_device_set_pixel_shader(device->wined3d_device, 3468 shader_obj ? shader_obj->wined3d_shader : NULL); 3469 wined3d_mutex_unlock(); 3470 3471 return D3D_OK; 3472 } 3473 3474 static HRESULT WINAPI d3d9_device_GetPixelShader(IDirect3DDevice9Ex *iface, IDirect3DPixelShader9 **shader) 3475 { 3476 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 3477 struct d3d9_pixelshader *shader_impl; 3478 struct wined3d_shader *wined3d_shader; 3479 3480 TRACE("iface %p, shader %p.\n", iface, shader); 3481 3482 if (!shader) return D3DERR_INVALIDCALL; 3483 3484 wined3d_mutex_lock(); 3485 if ((wined3d_shader = wined3d_device_get_pixel_shader(device->wined3d_device))) 3486 { 3487 shader_impl = wined3d_shader_get_parent(wined3d_shader); 3488 *shader = &shader_impl->IDirect3DPixelShader9_iface; 3489 IDirect3DPixelShader9_AddRef(*shader); 3490 } 3491 else 3492 { 3493 *shader = NULL; 3494 } 3495 wined3d_mutex_unlock(); 3496 3497 TRACE("Returning %p.\n", *shader); 3498 3499 return D3D_OK; 3500 } 3501 3502 static HRESULT WINAPI d3d9_device_SetPixelShaderConstantF(IDirect3DDevice9Ex *iface, 3503 UINT reg_idx, const float *data, UINT count) 3504 { 3505 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 3506 HRESULT hr; 3507 3508 TRACE("iface %p, reg_idx %u, data %p, count %u.\n", iface, reg_idx, data, count); 3509 3510 wined3d_mutex_lock(); 3511 hr = wined3d_device_set_ps_consts_f(device->wined3d_device, 3512 reg_idx, count, (const struct wined3d_vec4 *)data); 3513 wined3d_mutex_unlock(); 3514 3515 return hr; 3516 } 3517 3518 static HRESULT WINAPI d3d9_device_GetPixelShaderConstantF(IDirect3DDevice9Ex *iface, 3519 UINT reg_idx, float *data, UINT count) 3520 { 3521 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 3522 HRESULT hr; 3523 3524 TRACE("iface %p, reg_idx %u, data %p, count %u.\n", iface, reg_idx, data, count); 3525 3526 wined3d_mutex_lock(); 3527 hr = wined3d_device_get_ps_consts_f(device->wined3d_device, 3528 reg_idx, count, (struct wined3d_vec4 *)data); 3529 wined3d_mutex_unlock(); 3530 3531 return hr; 3532 } 3533 3534 static HRESULT WINAPI d3d9_device_SetPixelShaderConstantI(IDirect3DDevice9Ex *iface, 3535 UINT reg_idx, const int *data, UINT count) 3536 { 3537 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 3538 HRESULT hr; 3539 3540 TRACE("iface %p, reg_idx %u, data %p, count %u.\n", iface, reg_idx, data, count); 3541 3542 wined3d_mutex_lock(); 3543 hr = wined3d_device_set_ps_consts_i(device->wined3d_device, 3544 reg_idx, count, (const struct wined3d_ivec4 *)data); 3545 wined3d_mutex_unlock(); 3546 3547 return hr; 3548 } 3549 3550 static HRESULT WINAPI d3d9_device_GetPixelShaderConstantI(IDirect3DDevice9Ex *iface, 3551 UINT reg_idx, int *data, UINT count) 3552 { 3553 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 3554 HRESULT hr; 3555 3556 TRACE("iface %p, reg_idx %u, data %p, count %u.\n", iface, reg_idx, data, count); 3557 3558 wined3d_mutex_lock(); 3559 hr = wined3d_device_get_ps_consts_i(device->wined3d_device, 3560 reg_idx, count, (struct wined3d_ivec4 *)data); 3561 wined3d_mutex_unlock(); 3562 3563 return hr; 3564 } 3565 3566 static HRESULT WINAPI d3d9_device_SetPixelShaderConstantB(IDirect3DDevice9Ex *iface, 3567 UINT reg_idx, const BOOL *data, UINT count) 3568 { 3569 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 3570 HRESULT hr; 3571 3572 TRACE("iface %p, reg_idx %u, data %p, count %u.\n", iface, reg_idx, data, count); 3573 3574 wined3d_mutex_lock(); 3575 hr = wined3d_device_set_ps_consts_b(device->wined3d_device, reg_idx, count, data); 3576 wined3d_mutex_unlock(); 3577 3578 return hr; 3579 } 3580 3581 static HRESULT WINAPI d3d9_device_GetPixelShaderConstantB(IDirect3DDevice9Ex *iface, 3582 UINT reg_idx, BOOL *data, UINT count) 3583 { 3584 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 3585 HRESULT hr; 3586 3587 TRACE("iface %p, reg_idx %u, data %p, count %u.\n", iface, reg_idx, data, count); 3588 3589 wined3d_mutex_lock(); 3590 hr = wined3d_device_get_ps_consts_b(device->wined3d_device, reg_idx, count, data); 3591 wined3d_mutex_unlock(); 3592 3593 return hr; 3594 } 3595 3596 static HRESULT WINAPI d3d9_device_DrawRectPatch(IDirect3DDevice9Ex *iface, UINT handle, 3597 const float *segment_count, const D3DRECTPATCH_INFO *patch_info) 3598 { 3599 FIXME("iface %p, handle %#x, segment_count %p, patch_info %p unimplemented.\n", 3600 iface, handle, segment_count, patch_info); 3601 return D3D_OK; 3602 } 3603 3604 static HRESULT WINAPI d3d9_device_DrawTriPatch(IDirect3DDevice9Ex *iface, UINT handle, 3605 const float *segment_count, const D3DTRIPATCH_INFO *patch_info) 3606 { 3607 FIXME("iface %p, handle %#x, segment_count %p, patch_info %p unimplemented.\n", 3608 iface, handle, segment_count, patch_info); 3609 return D3D_OK; 3610 } 3611 3612 static HRESULT WINAPI d3d9_device_DeletePatch(IDirect3DDevice9Ex *iface, UINT handle) 3613 { 3614 FIXME("iface %p, handle %#x unimplemented.\n", iface, handle); 3615 return D3DERR_INVALIDCALL; 3616 } 3617 3618 static HRESULT WINAPI d3d9_device_CreateQuery(IDirect3DDevice9Ex *iface, D3DQUERYTYPE type, IDirect3DQuery9 **query) 3619 { 3620 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 3621 struct d3d9_query *object; 3622 HRESULT hr; 3623 3624 TRACE("iface %p, type %#x, query %p.\n", iface, type, query); 3625 3626 if (!(object = heap_alloc_zero(sizeof(*object)))) 3627 return E_OUTOFMEMORY; 3628 3629 hr = query_init(object, device, type); 3630 if (FAILED(hr)) 3631 { 3632 WARN("Failed to initialize query, hr %#x.\n", hr); 3633 heap_free(object); 3634 return hr; 3635 } 3636 3637 TRACE("Created query %p.\n", object); 3638 if (query) *query = &object->IDirect3DQuery9_iface; 3639 else IDirect3DQuery9_Release(&object->IDirect3DQuery9_iface); 3640 3641 return D3D_OK; 3642 } 3643 3644 static HRESULT WINAPI d3d9_device_SetConvolutionMonoKernel(IDirect3DDevice9Ex *iface, 3645 UINT width, UINT height, float *rows, float *columns) 3646 { 3647 FIXME("iface %p, width %u, height %u, rows %p, columns %p stub!\n", 3648 iface, width, height, rows, columns); 3649 3650 return E_NOTIMPL; 3651 } 3652 3653 static HRESULT WINAPI d3d9_device_ComposeRects(IDirect3DDevice9Ex *iface, 3654 IDirect3DSurface9 *src_surface, IDirect3DSurface9 *dst_surface, IDirect3DVertexBuffer9 *src_descs, 3655 UINT rect_count, IDirect3DVertexBuffer9 *dst_descs, D3DCOMPOSERECTSOP operation, INT offset_x, INT offset_y) 3656 { 3657 FIXME("iface %p, src_surface %p, dst_surface %p, src_descs %p, rect_count %u, " 3658 "dst_descs %p, operation %#x, offset_x %u, offset_y %u stub!\n", 3659 iface, src_surface, dst_surface, src_descs, rect_count, 3660 dst_descs, operation, offset_x, offset_y); 3661 3662 return E_NOTIMPL; 3663 } 3664 3665 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d9_device_PresentEx(IDirect3DDevice9Ex *iface, 3666 const RECT *src_rect, const RECT *dst_rect, HWND dst_window_override, 3667 const RGNDATA *dirty_region, DWORD flags) 3668 { 3669 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 3670 UINT i; 3671 HRESULT hr; 3672 3673 TRACE("iface %p, src_rect %s, dst_rect %s, dst_window_override %p, dirty_region %p, flags %#x.\n", 3674 iface, wine_dbgstr_rect(src_rect), wine_dbgstr_rect(dst_rect), 3675 dst_window_override, dirty_region, flags); 3676 3677 if (device->device_state != D3D9_DEVICE_STATE_OK) 3678 return S_PRESENT_OCCLUDED; 3679 3680 if (dirty_region) 3681 FIXME("Ignoring dirty_region %p.\n", dirty_region); 3682 3683 wined3d_mutex_lock(); 3684 for (i = 0; i < device->implicit_swapchain_count; ++i) 3685 { 3686 if (FAILED(hr = wined3d_swapchain_present(device->implicit_swapchains[i]->wined3d_swapchain, 3687 src_rect, dst_rect, dst_window_override, 0, flags))) 3688 { 3689 wined3d_mutex_unlock(); 3690 return hr; 3691 } 3692 } 3693 wined3d_mutex_unlock(); 3694 3695 return D3D_OK; 3696 } 3697 3698 static HRESULT WINAPI d3d9_device_GetGPUThreadPriority(IDirect3DDevice9Ex *iface, INT *priority) 3699 { 3700 FIXME("iface %p, priority %p stub!\n", iface, priority); 3701 3702 return E_NOTIMPL; 3703 } 3704 3705 static HRESULT WINAPI d3d9_device_SetGPUThreadPriority(IDirect3DDevice9Ex *iface, INT priority) 3706 { 3707 FIXME("iface %p, priority %d stub!\n", iface, priority); 3708 3709 return E_NOTIMPL; 3710 } 3711 3712 static HRESULT WINAPI d3d9_device_WaitForVBlank(IDirect3DDevice9Ex *iface, UINT swapchain_idx) 3713 { 3714 FIXME("iface %p, swapchain_idx %u stub!\n", iface, swapchain_idx); 3715 3716 return E_NOTIMPL; 3717 } 3718 3719 static HRESULT WINAPI d3d9_device_CheckResourceResidency(IDirect3DDevice9Ex *iface, 3720 IDirect3DResource9 **resources, UINT32 resource_count) 3721 { 3722 FIXME("iface %p, resources %p, resource_count %u stub!\n", 3723 iface, resources, resource_count); 3724 3725 return E_NOTIMPL; 3726 } 3727 3728 static HRESULT WINAPI d3d9_device_SetMaximumFrameLatency(IDirect3DDevice9Ex *iface, UINT max_latency) 3729 { 3730 TRACE("iface %p, max_latency %u.\n", iface, max_latency); 3731 3732 if (max_latency) 3733 FIXME("Ignoring max_latency %u.\n", max_latency); 3734 3735 return S_OK; 3736 } 3737 3738 static HRESULT WINAPI d3d9_device_GetMaximumFrameLatency(IDirect3DDevice9Ex *iface, UINT *max_latency) 3739 { 3740 FIXME("iface %p, max_latency %p stub!\n", iface, max_latency); 3741 3742 *max_latency = 2; 3743 3744 return E_NOTIMPL; 3745 } 3746 3747 static HRESULT WINAPI d3d9_device_CheckDeviceState(IDirect3DDevice9Ex *iface, HWND dst_window) 3748 { 3749 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 3750 struct wined3d_swapchain_desc swapchain_desc; 3751 3752 TRACE("iface %p, dst_window %p.\n", iface, dst_window); 3753 3754 wined3d_mutex_lock(); 3755 wined3d_swapchain_get_desc(device->implicit_swapchains[0]->wined3d_swapchain, &swapchain_desc); 3756 wined3d_mutex_unlock(); 3757 3758 if (swapchain_desc.windowed) 3759 return D3D_OK; 3760 3761 /* FIXME: This is actually supposed to check if any other device is in 3762 * fullscreen mode. */ 3763 if (dst_window != swapchain_desc.device_window) 3764 return device->device_state == D3D9_DEVICE_STATE_OK ? S_PRESENT_OCCLUDED : D3D_OK; 3765 3766 return device->device_state == D3D9_DEVICE_STATE_OK ? D3D_OK : S_PRESENT_OCCLUDED; 3767 } 3768 3769 static HRESULT WINAPI d3d9_device_CreateRenderTargetEx(IDirect3DDevice9Ex *iface, 3770 UINT width, UINT height, D3DFORMAT format, D3DMULTISAMPLE_TYPE multisample_type, DWORD multisample_quality, 3771 BOOL lockable, IDirect3DSurface9 **surface, HANDLE *shared_handle, DWORD usage) 3772 { 3773 FIXME("iface %p, width %u, height %u, format %#x, multisample_type %#x, multisample_quality %u, " 3774 "lockable %#x, surface %p, shared_handle %p, usage %#x stub!\n", 3775 iface, width, height, format, multisample_type, multisample_quality, 3776 lockable, surface, shared_handle, usage); 3777 3778 *surface = NULL; 3779 if (shared_handle) 3780 FIXME("Resource sharing not implemented, *shared_handle %p.\n", *shared_handle); 3781 3782 return E_NOTIMPL; 3783 } 3784 3785 static HRESULT WINAPI d3d9_device_CreateOffscreenPlainSurfaceEx(IDirect3DDevice9Ex *iface, 3786 UINT width, UINT height, D3DFORMAT format, D3DPOOL pool, IDirect3DSurface9 **surface, 3787 HANDLE *shared_handle, DWORD usage) 3788 { 3789 FIXME("iface %p, width %u, height %u, format %#x, pool %#x, surface %p, shared_handle %p, usage %#x stub!\n", 3790 iface, width, height, format, pool, surface, shared_handle, usage); 3791 3792 return E_NOTIMPL; 3793 } 3794 3795 static HRESULT WINAPI d3d9_device_CreateDepthStencilSurfaceEx(IDirect3DDevice9Ex *iface, 3796 UINT width, UINT height, D3DFORMAT format, D3DMULTISAMPLE_TYPE multisample_type, DWORD multisample_quality, 3797 BOOL discard, IDirect3DSurface9 **surface, HANDLE *shared_handle, DWORD usage) 3798 { 3799 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 3800 DWORD flags = WINED3D_TEXTURE_CREATE_MAPPABLE; 3801 3802 TRACE("iface %p, width %u, height %u, format %#x, multisample_type %#x, multisample_quality %u, " 3803 "discard %#x, surface %p, shared_handle %p, usage %#x.\n", 3804 iface, width, height, format, multisample_type, multisample_quality, 3805 discard, surface, shared_handle, usage); 3806 3807 if (usage & D3DUSAGE_DEPTHSTENCIL) 3808 { 3809 WARN("Invalid usage %#x.\n", usage); 3810 return D3DERR_INVALIDCALL; 3811 } 3812 3813 if (shared_handle) 3814 FIXME("Resource sharing not implemented, *shared_handle %p.\n", *shared_handle); 3815 3816 if (discard) 3817 flags |= WINED3D_TEXTURE_CREATE_DISCARD; 3818 3819 *surface = NULL; 3820 return d3d9_device_create_surface(device, width, height, format, flags, surface, 3821 D3DUSAGE_DEPTHSTENCIL | usage, D3DPOOL_DEFAULT, multisample_type, multisample_quality, NULL); 3822 } 3823 3824 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d9_device_ResetEx(IDirect3DDevice9Ex *iface, 3825 D3DPRESENT_PARAMETERS *present_parameters, D3DDISPLAYMODEEX *mode) 3826 { 3827 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 3828 3829 TRACE("iface %p, present_parameters %p, mode %p.\n", iface, present_parameters, mode); 3830 3831 if (!present_parameters->Windowed == !mode) 3832 { 3833 WARN("Mode can be passed if and only if Windowed is FALSE.\n"); 3834 return D3DERR_INVALIDCALL; 3835 } 3836 3837 if (mode && (mode->Width != present_parameters->BackBufferWidth 3838 || mode->Height != present_parameters->BackBufferHeight)) 3839 { 3840 WARN("Mode and back buffer mismatch (mode %ux%u, backbuffer %ux%u).\n", 3841 mode->Width, mode->Height, 3842 present_parameters->BackBufferWidth, present_parameters->BackBufferHeight); 3843 return D3DERR_INVALIDCALL; 3844 } 3845 3846 return d3d9_device_reset(device, present_parameters, mode); 3847 } 3848 3849 static HRESULT WINAPI d3d9_device_GetDisplayModeEx(IDirect3DDevice9Ex *iface, 3850 UINT swapchain_idx, D3DDISPLAYMODEEX *mode, D3DDISPLAYROTATION *rotation) 3851 { 3852 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); 3853 struct wined3d_display_mode wined3d_mode; 3854 HRESULT hr; 3855 3856 TRACE("iface %p, swapchain_idx %u, mode %p, rotation %p.\n", 3857 iface, swapchain_idx, mode, rotation); 3858 3859 if (mode->Size != sizeof(*mode)) 3860 return D3DERR_INVALIDCALL; 3861 3862 wined3d_mutex_lock(); 3863 hr = wined3d_device_get_display_mode(device->wined3d_device, swapchain_idx, &wined3d_mode, 3864 (enum wined3d_display_rotation *)rotation); 3865 wined3d_mutex_unlock(); 3866 3867 if (SUCCEEDED(hr)) 3868 { 3869 mode->Width = wined3d_mode.width; 3870 mode->Height = wined3d_mode.height; 3871 mode->RefreshRate = wined3d_mode.refresh_rate; 3872 mode->Format = d3dformat_from_wined3dformat(wined3d_mode.format_id); 3873 mode->ScanLineOrdering = wined3d_mode.scanline_ordering; 3874 } 3875 3876 return hr; 3877 } 3878 3879 static const struct IDirect3DDevice9ExVtbl d3d9_device_vtbl = 3880 { 3881 /* IUnknown */ 3882 d3d9_device_QueryInterface, 3883 d3d9_device_AddRef, 3884 d3d9_device_Release, 3885 /* IDirect3DDevice9 */ 3886 d3d9_device_TestCooperativeLevel, 3887 d3d9_device_GetAvailableTextureMem, 3888 d3d9_device_EvictManagedResources, 3889 d3d9_device_GetDirect3D, 3890 d3d9_device_GetDeviceCaps, 3891 d3d9_device_GetDisplayMode, 3892 d3d9_device_GetCreationParameters, 3893 d3d9_device_SetCursorProperties, 3894 d3d9_device_SetCursorPosition, 3895 d3d9_device_ShowCursor, 3896 d3d9_device_CreateAdditionalSwapChain, 3897 d3d9_device_GetSwapChain, 3898 d3d9_device_GetNumberOfSwapChains, 3899 d3d9_device_Reset, 3900 d3d9_device_Present, 3901 d3d9_device_GetBackBuffer, 3902 d3d9_device_GetRasterStatus, 3903 d3d9_device_SetDialogBoxMode, 3904 d3d9_device_SetGammaRamp, 3905 d3d9_device_GetGammaRamp, 3906 d3d9_device_CreateTexture, 3907 d3d9_device_CreateVolumeTexture, 3908 d3d9_device_CreateCubeTexture, 3909 d3d9_device_CreateVertexBuffer, 3910 d3d9_device_CreateIndexBuffer, 3911 d3d9_device_CreateRenderTarget, 3912 d3d9_device_CreateDepthStencilSurface, 3913 d3d9_device_UpdateSurface, 3914 d3d9_device_UpdateTexture, 3915 d3d9_device_GetRenderTargetData, 3916 d3d9_device_GetFrontBufferData, 3917 d3d9_device_StretchRect, 3918 d3d9_device_ColorFill, 3919 d3d9_device_CreateOffscreenPlainSurface, 3920 d3d9_device_SetRenderTarget, 3921 d3d9_device_GetRenderTarget, 3922 d3d9_device_SetDepthStencilSurface, 3923 d3d9_device_GetDepthStencilSurface, 3924 d3d9_device_BeginScene, 3925 d3d9_device_EndScene, 3926 d3d9_device_Clear, 3927 d3d9_device_SetTransform, 3928 d3d9_device_GetTransform, 3929 d3d9_device_MultiplyTransform, 3930 d3d9_device_SetViewport, 3931 d3d9_device_GetViewport, 3932 d3d9_device_SetMaterial, 3933 d3d9_device_GetMaterial, 3934 d3d9_device_SetLight, 3935 d3d9_device_GetLight, 3936 d3d9_device_LightEnable, 3937 d3d9_device_GetLightEnable, 3938 d3d9_device_SetClipPlane, 3939 d3d9_device_GetClipPlane, 3940 d3d9_device_SetRenderState, 3941 d3d9_device_GetRenderState, 3942 d3d9_device_CreateStateBlock, 3943 d3d9_device_BeginStateBlock, 3944 d3d9_device_EndStateBlock, 3945 d3d9_device_SetClipStatus, 3946 d3d9_device_GetClipStatus, 3947 d3d9_device_GetTexture, 3948 d3d9_device_SetTexture, 3949 d3d9_device_GetTextureStageState, 3950 d3d9_device_SetTextureStageState, 3951 d3d9_device_GetSamplerState, 3952 d3d9_device_SetSamplerState, 3953 d3d9_device_ValidateDevice, 3954 d3d9_device_SetPaletteEntries, 3955 d3d9_device_GetPaletteEntries, 3956 d3d9_device_SetCurrentTexturePalette, 3957 d3d9_device_GetCurrentTexturePalette, 3958 d3d9_device_SetScissorRect, 3959 d3d9_device_GetScissorRect, 3960 d3d9_device_SetSoftwareVertexProcessing, 3961 d3d9_device_GetSoftwareVertexProcessing, 3962 d3d9_device_SetNPatchMode, 3963 d3d9_device_GetNPatchMode, 3964 d3d9_device_DrawPrimitive, 3965 d3d9_device_DrawIndexedPrimitive, 3966 d3d9_device_DrawPrimitiveUP, 3967 d3d9_device_DrawIndexedPrimitiveUP, 3968 d3d9_device_ProcessVertices, 3969 d3d9_device_CreateVertexDeclaration, 3970 d3d9_device_SetVertexDeclaration, 3971 d3d9_device_GetVertexDeclaration, 3972 d3d9_device_SetFVF, 3973 d3d9_device_GetFVF, 3974 d3d9_device_CreateVertexShader, 3975 d3d9_device_SetVertexShader, 3976 d3d9_device_GetVertexShader, 3977 d3d9_device_SetVertexShaderConstantF, 3978 d3d9_device_GetVertexShaderConstantF, 3979 d3d9_device_SetVertexShaderConstantI, 3980 d3d9_device_GetVertexShaderConstantI, 3981 d3d9_device_SetVertexShaderConstantB, 3982 d3d9_device_GetVertexShaderConstantB, 3983 d3d9_device_SetStreamSource, 3984 d3d9_device_GetStreamSource, 3985 d3d9_device_SetStreamSourceFreq, 3986 d3d9_device_GetStreamSourceFreq, 3987 d3d9_device_SetIndices, 3988 d3d9_device_GetIndices, 3989 d3d9_device_CreatePixelShader, 3990 d3d9_device_SetPixelShader, 3991 d3d9_device_GetPixelShader, 3992 d3d9_device_SetPixelShaderConstantF, 3993 d3d9_device_GetPixelShaderConstantF, 3994 d3d9_device_SetPixelShaderConstantI, 3995 d3d9_device_GetPixelShaderConstantI, 3996 d3d9_device_SetPixelShaderConstantB, 3997 d3d9_device_GetPixelShaderConstantB, 3998 d3d9_device_DrawRectPatch, 3999 d3d9_device_DrawTriPatch, 4000 d3d9_device_DeletePatch, 4001 d3d9_device_CreateQuery, 4002 /* IDirect3DDevice9Ex */ 4003 d3d9_device_SetConvolutionMonoKernel, 4004 d3d9_device_ComposeRects, 4005 d3d9_device_PresentEx, 4006 d3d9_device_GetGPUThreadPriority, 4007 d3d9_device_SetGPUThreadPriority, 4008 d3d9_device_WaitForVBlank, 4009 d3d9_device_CheckResourceResidency, 4010 d3d9_device_SetMaximumFrameLatency, 4011 d3d9_device_GetMaximumFrameLatency, 4012 d3d9_device_CheckDeviceState, 4013 d3d9_device_CreateRenderTargetEx, 4014 d3d9_device_CreateOffscreenPlainSurfaceEx, 4015 d3d9_device_CreateDepthStencilSurfaceEx, 4016 d3d9_device_ResetEx, 4017 d3d9_device_GetDisplayModeEx, 4018 }; 4019 4020 static inline struct d3d9_device *device_from_device_parent(struct wined3d_device_parent *device_parent) 4021 { 4022 return CONTAINING_RECORD(device_parent, struct d3d9_device, device_parent); 4023 } 4024 4025 static void CDECL device_parent_wined3d_device_created(struct wined3d_device_parent *device_parent, 4026 struct wined3d_device *device) 4027 { 4028 TRACE("device_parent %p, device %p.\n", device_parent, device); 4029 } 4030 4031 static void CDECL device_parent_mode_changed(struct wined3d_device_parent *device_parent) 4032 { 4033 TRACE("device_parent %p.\n", device_parent); 4034 } 4035 4036 static void CDECL device_parent_activate(struct wined3d_device_parent *device_parent, BOOL activate) 4037 { 4038 struct d3d9_device *device = device_from_device_parent(device_parent); 4039 4040 TRACE("device_parent %p, activate %#x.\n", device_parent, activate); 4041 4042 if (!device->d3d_parent) 4043 return; 4044 4045 if (!activate) 4046 InterlockedCompareExchange(&device->device_state, D3D9_DEVICE_STATE_LOST, D3D9_DEVICE_STATE_OK); 4047 else if (device->d3d_parent->extended) 4048 InterlockedCompareExchange(&device->device_state, D3D9_DEVICE_STATE_OK, D3D9_DEVICE_STATE_LOST); 4049 else 4050 InterlockedCompareExchange(&device->device_state, D3D9_DEVICE_STATE_NOT_RESET, D3D9_DEVICE_STATE_LOST); 4051 } 4052 4053 static HRESULT CDECL device_parent_surface_created(struct wined3d_device_parent *device_parent, 4054 struct wined3d_texture *wined3d_texture, unsigned int sub_resource_idx, 4055 void **parent, const struct wined3d_parent_ops **parent_ops) 4056 { 4057 struct d3d9_surface *d3d_surface; 4058 4059 TRACE("device_parent %p, wined3d_texture %p, sub_resource_idx %u, parent %p, parent_ops %p.\n", 4060 device_parent, wined3d_texture, sub_resource_idx, parent, parent_ops); 4061 4062 if (!(d3d_surface = heap_alloc_zero(sizeof(*d3d_surface)))) 4063 return E_OUTOFMEMORY; 4064 4065 surface_init(d3d_surface, wined3d_texture, sub_resource_idx, parent_ops); 4066 *parent = d3d_surface; 4067 TRACE("Created surface %p.\n", d3d_surface); 4068 4069 return D3D_OK; 4070 } 4071 4072 static HRESULT CDECL device_parent_volume_created(struct wined3d_device_parent *device_parent, 4073 struct wined3d_texture *wined3d_texture, unsigned int sub_resource_idx, 4074 void **parent, const struct wined3d_parent_ops **parent_ops) 4075 { 4076 struct d3d9_volume *d3d_volume; 4077 4078 TRACE("device_parent %p, texture %p, sub_resource_idx %u, parent %p, parent_ops %p.\n", 4079 device_parent, wined3d_texture, sub_resource_idx, parent, parent_ops); 4080 4081 if (!(d3d_volume = heap_alloc_zero(sizeof(*d3d_volume)))) 4082 return E_OUTOFMEMORY; 4083 4084 volume_init(d3d_volume, wined3d_texture, sub_resource_idx, parent_ops); 4085 *parent = d3d_volume; 4086 TRACE("Created volume %p.\n", d3d_volume); 4087 4088 return D3D_OK; 4089 } 4090 4091 static HRESULT CDECL device_parent_create_swapchain_texture(struct wined3d_device_parent *device_parent, 4092 void *container_parent, const struct wined3d_resource_desc *desc, DWORD texture_flags, 4093 struct wined3d_texture **texture) 4094 { 4095 struct d3d9_device *device = device_from_device_parent(device_parent); 4096 struct d3d9_surface *d3d_surface; 4097 HRESULT hr; 4098 4099 TRACE("device_parent %p, container_parent %p, desc %p, texture flags %#x, texture %p.\n", 4100 device_parent, container_parent, desc, texture_flags, texture); 4101 4102 if (container_parent == device_parent) 4103 container_parent = &device->IDirect3DDevice9Ex_iface; 4104 4105 if (is_gdi_compat_wined3dformat(desc->format)) 4106 texture_flags |= WINED3D_TEXTURE_CREATE_GET_DC; 4107 4108 if (FAILED(hr = wined3d_texture_create(device->wined3d_device, desc, 1, 1, 4109 texture_flags | WINED3D_TEXTURE_CREATE_MAPPABLE, NULL, container_parent, 4110 &d3d9_null_wined3d_parent_ops, texture))) 4111 { 4112 WARN("Failed to create texture, hr %#x.\n", hr); 4113 return hr; 4114 } 4115 4116 d3d_surface = wined3d_texture_get_sub_resource_parent(*texture, 0); 4117 d3d_surface->parent_device = &device->IDirect3DDevice9Ex_iface; 4118 4119 return hr; 4120 } 4121 4122 static HRESULT CDECL device_parent_create_swapchain(struct wined3d_device_parent *device_parent, 4123 struct wined3d_swapchain_desc *desc, struct wined3d_swapchain **swapchain) 4124 { 4125 struct d3d9_device *device = device_from_device_parent(device_parent); 4126 struct d3d9_swapchain *d3d_swapchain; 4127 HRESULT hr; 4128 4129 TRACE("device_parent %p, desc %p, swapchain %p\n", device_parent, desc, swapchain); 4130 4131 hr = d3d9_swapchain_create(device, desc, &d3d_swapchain); 4132 if (FAILED(hr)) 4133 { 4134 WARN("Failed to create swapchain, hr %#x.\n", hr); 4135 *swapchain = NULL; 4136 return hr; 4137 } 4138 4139 *swapchain = d3d_swapchain->wined3d_swapchain; 4140 wined3d_swapchain_incref(*swapchain); 4141 IDirect3DSwapChain9Ex_Release(&d3d_swapchain->IDirect3DSwapChain9Ex_iface); 4142 4143 return hr; 4144 } 4145 4146 static const struct wined3d_device_parent_ops d3d9_wined3d_device_parent_ops = 4147 { 4148 device_parent_wined3d_device_created, 4149 device_parent_mode_changed, 4150 device_parent_activate, 4151 device_parent_surface_created, 4152 device_parent_volume_created, 4153 device_parent_create_swapchain_texture, 4154 device_parent_create_swapchain, 4155 }; 4156 4157 static void setup_fpu(void) 4158 { 4159 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) 4160 WORD cw; 4161 __asm__ volatile ("fnstcw %0" : "=m" (cw)); 4162 cw = (cw & ~0xf3f) | 0x3f; 4163 __asm__ volatile ("fldcw %0" : : "m" (cw)); 4164 #elif defined(__i386__) && defined(_MSC_VER) 4165 WORD cw; 4166 __asm fnstcw cw; 4167 cw = (cw & ~0xf3f) | 0x3f; 4168 __asm fldcw cw; 4169 #else 4170 FIXME("FPU setup not implemented for this platform.\n"); 4171 #endif 4172 } 4173 4174 HRESULT device_init(struct d3d9_device *device, struct d3d9 *parent, struct wined3d *wined3d, 4175 UINT adapter, D3DDEVTYPE device_type, HWND focus_window, DWORD flags, 4176 D3DPRESENT_PARAMETERS *parameters, D3DDISPLAYMODEEX *mode) 4177 { 4178 struct wined3d_swapchain_desc *swapchain_desc; 4179 unsigned i, count = 1; 4180 WINED3DCAPS caps; 4181 HRESULT hr; 4182 4183 if (mode) 4184 FIXME("Ignoring display mode.\n"); 4185 4186 device->IDirect3DDevice9Ex_iface.lpVtbl = &d3d9_device_vtbl; 4187 device->device_parent.ops = &d3d9_wined3d_device_parent_ops; 4188 device->refcount = 1; 4189 4190 if (!(flags & D3DCREATE_FPU_PRESERVE)) setup_fpu(); 4191 4192 wined3d_mutex_lock(); 4193 if (FAILED(hr = wined3d_device_create(wined3d, adapter, device_type, focus_window, flags, 4, 4194 &device->device_parent, &device->wined3d_device))) 4195 { 4196 WARN("Failed to create wined3d device, hr %#x.\n", hr); 4197 wined3d_mutex_unlock(); 4198 return hr; 4199 } 4200 4201 wined3d_get_device_caps(wined3d, adapter, device_type, &caps); 4202 device->max_user_clip_planes = caps.MaxUserClipPlanes; 4203 if (flags & D3DCREATE_ADAPTERGROUP_DEVICE) 4204 count = caps.NumberOfAdaptersInGroup; 4205 4206 if (flags & D3DCREATE_MULTITHREADED) 4207 wined3d_device_set_multithreaded(device->wined3d_device); 4208 4209 if (!parameters->Windowed) 4210 { 4211 if (!focus_window) 4212 focus_window = parameters->hDeviceWindow; 4213 if (FAILED(hr = wined3d_device_acquire_focus_window(device->wined3d_device, focus_window))) 4214 { 4215 ERR("Failed to acquire focus window, hr %#x.\n", hr); 4216 wined3d_device_decref(device->wined3d_device); 4217 wined3d_mutex_unlock(); 4218 return hr; 4219 } 4220 4221 for (i = 0; i < count; ++i) 4222 { 4223 HWND device_window = parameters[i].hDeviceWindow; 4224 4225 if (!device_window) device_window = focus_window; 4226 wined3d_device_setup_fullscreen_window(device->wined3d_device, device_window, 4227 parameters[i].BackBufferWidth, 4228 parameters[i].BackBufferHeight); 4229 } 4230 } 4231 4232 if (!(swapchain_desc = heap_alloc(sizeof(*swapchain_desc) * count))) 4233 { 4234 ERR("Failed to allocate wined3d parameters.\n"); 4235 wined3d_device_release_focus_window(device->wined3d_device); 4236 wined3d_device_decref(device->wined3d_device); 4237 wined3d_mutex_unlock(); 4238 return E_OUTOFMEMORY; 4239 } 4240 4241 for (i = 0; i < count; ++i) 4242 { 4243 if (!wined3d_swapchain_desc_from_present_parameters(&swapchain_desc[i], ¶meters[i], 4244 parent->extended)) 4245 { 4246 wined3d_device_release_focus_window(device->wined3d_device); 4247 wined3d_device_decref(device->wined3d_device); 4248 heap_free(swapchain_desc); 4249 wined3d_mutex_unlock(); 4250 return D3DERR_INVALIDCALL; 4251 } 4252 } 4253 4254 if (FAILED(hr = wined3d_device_init_3d(device->wined3d_device, swapchain_desc))) 4255 { 4256 WARN("Failed to initialize 3D, hr %#x.\n", hr); 4257 wined3d_device_release_focus_window(device->wined3d_device); 4258 heap_free(swapchain_desc); 4259 wined3d_device_decref(device->wined3d_device); 4260 wined3d_mutex_unlock(); 4261 return hr; 4262 } 4263 4264 wined3d_device_set_render_state(device->wined3d_device, 4265 WINED3D_RS_ZENABLE, !!swapchain_desc->enable_auto_depth_stencil); 4266 4267 if (FAILED(hr = d3d9_device_get_swapchains(device))) 4268 { 4269 wined3d_device_uninit_3d(device->wined3d_device); 4270 wined3d_device_release_focus_window(device->wined3d_device); 4271 wined3d_device_decref(device->wined3d_device); 4272 wined3d_mutex_unlock(); 4273 return E_OUTOFMEMORY; 4274 } 4275 4276 for (i = 0; i < count; ++i) 4277 { 4278 present_parameters_from_wined3d_swapchain_desc(¶meters[i], &swapchain_desc[i]); 4279 } 4280 4281 wined3d_mutex_unlock(); 4282 4283 heap_free(swapchain_desc); 4284 4285 /* Initialize the converted declaration array. This creates a valid pointer 4286 * and when adding decls HeapReAlloc() can be used without further checking. */ 4287 if (!(device->fvf_decls = heap_alloc(0))) 4288 { 4289 ERR("Failed to allocate FVF vertex declaration map memory.\n"); 4290 wined3d_mutex_lock(); 4291 heap_free(device->implicit_swapchains); 4292 wined3d_device_uninit_3d(device->wined3d_device); 4293 wined3d_device_release_focus_window(device->wined3d_device); 4294 wined3d_device_decref(device->wined3d_device); 4295 wined3d_mutex_unlock(); 4296 return E_OUTOFMEMORY; 4297 } 4298 4299 /* We could also simply ignore the initial rendertarget since it's known 4300 * not to be a texture (we currently use these only for automatic mipmap 4301 * generation). */ 4302 wined3d_mutex_lock(); 4303 device->render_targets[0] = wined3d_rendertarget_view_get_sub_resource_parent( 4304 wined3d_device_get_rendertarget_view(device->wined3d_device, 0)); 4305 wined3d_mutex_unlock(); 4306 4307 IDirect3D9Ex_AddRef(&parent->IDirect3D9Ex_iface); 4308 device->d3d_parent = parent; 4309 4310 return D3D_OK; 4311 } 4312