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