1 /* 2 * IDirect3DDevice8 implementation 3 * 4 * Copyright 2002-2004 Jason Edmeades 5 * Copyright 2004 Christian Costa 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with this library; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 20 */ 21 22 #include "config.h" 23 24 #include <math.h> 25 #include <stdarg.h> 26 27 #include "windef.h" 28 #include "winbase.h" 29 #include "winuser.h" 30 #include "wingdi.h" 31 #include "wine/debug.h" 32 33 #include "d3d8_private.h" 34 35 WINE_DEFAULT_DEBUG_CHANNEL(d3d8); 36 37 static void STDMETHODCALLTYPE d3d8_null_wined3d_object_destroyed(void *parent) {} 38 39 static const struct wined3d_parent_ops d3d8_null_wined3d_parent_ops = 40 { 41 d3d8_null_wined3d_object_destroyed, 42 }; 43 44 D3DFORMAT d3dformat_from_wined3dformat(enum wined3d_format_id format) 45 { 46 BYTE *c = (BYTE *)&format; 47 48 /* Don't translate FOURCC formats */ 49 if (isprint(c[0]) && isprint(c[1]) && isprint(c[2]) && isprint(c[3])) return format; 50 51 switch(format) 52 { 53 case WINED3DFMT_UNKNOWN: return D3DFMT_UNKNOWN; 54 case WINED3DFMT_B8G8R8_UNORM: return D3DFMT_R8G8B8; 55 case WINED3DFMT_B8G8R8A8_UNORM: return D3DFMT_A8R8G8B8; 56 case WINED3DFMT_B8G8R8X8_UNORM: return D3DFMT_X8R8G8B8; 57 case WINED3DFMT_B5G6R5_UNORM: return D3DFMT_R5G6B5; 58 case WINED3DFMT_B5G5R5X1_UNORM: return D3DFMT_X1R5G5B5; 59 case WINED3DFMT_B5G5R5A1_UNORM: return D3DFMT_A1R5G5B5; 60 case WINED3DFMT_B4G4R4A4_UNORM: return D3DFMT_A4R4G4B4; 61 case WINED3DFMT_B2G3R3_UNORM: return D3DFMT_R3G3B2; 62 case WINED3DFMT_A8_UNORM: return D3DFMT_A8; 63 case WINED3DFMT_B2G3R3A8_UNORM: return D3DFMT_A8R3G3B2; 64 case WINED3DFMT_B4G4R4X4_UNORM: return D3DFMT_X4R4G4B4; 65 case WINED3DFMT_R10G10B10A2_UNORM: return D3DFMT_A2B10G10R10; 66 case WINED3DFMT_R16G16_UNORM: return D3DFMT_G16R16; 67 case WINED3DFMT_P8_UINT_A8_UNORM: return D3DFMT_A8P8; 68 case WINED3DFMT_P8_UINT: return D3DFMT_P8; 69 case WINED3DFMT_L8_UNORM: return D3DFMT_L8; 70 case WINED3DFMT_L8A8_UNORM: return D3DFMT_A8L8; 71 case WINED3DFMT_L4A4_UNORM: return D3DFMT_A4L4; 72 case WINED3DFMT_R8G8_SNORM: return D3DFMT_V8U8; 73 case WINED3DFMT_R5G5_SNORM_L6_UNORM: return D3DFMT_L6V5U5; 74 case WINED3DFMT_R8G8_SNORM_L8X8_UNORM: return D3DFMT_X8L8V8U8; 75 case WINED3DFMT_R8G8B8A8_SNORM: return D3DFMT_Q8W8V8U8; 76 case WINED3DFMT_R16G16_SNORM: return D3DFMT_V16U16; 77 case WINED3DFMT_R10G11B11_SNORM: return D3DFMT_W11V11U10; 78 case WINED3DFMT_R10G10B10_SNORM_A2_UNORM: return D3DFMT_A2W10V10U10; 79 case WINED3DFMT_D16_LOCKABLE: return D3DFMT_D16_LOCKABLE; 80 case WINED3DFMT_D32_UNORM: return D3DFMT_D32; 81 case WINED3DFMT_S1_UINT_D15_UNORM: return D3DFMT_D15S1; 82 case WINED3DFMT_D24_UNORM_S8_UINT: return D3DFMT_D24S8; 83 case WINED3DFMT_X8D24_UNORM: return D3DFMT_D24X8; 84 case WINED3DFMT_S4X4_UINT_D24_UNORM: return D3DFMT_D24X4S4; 85 case WINED3DFMT_D16_UNORM: return D3DFMT_D16; 86 case WINED3DFMT_R16_UINT: return D3DFMT_INDEX16; 87 case WINED3DFMT_R32_UINT: return D3DFMT_INDEX32; 88 default: 89 FIXME("Unhandled wined3d format %#x.\n", format); 90 return D3DFMT_UNKNOWN; 91 } 92 } 93 94 enum wined3d_format_id wined3dformat_from_d3dformat(D3DFORMAT format) 95 { 96 BYTE *c = (BYTE *)&format; 97 98 /* Don't translate FOURCC formats */ 99 if (isprint(c[0]) && isprint(c[1]) && isprint(c[2]) && isprint(c[3])) return format; 100 101 switch(format) 102 { 103 case D3DFMT_UNKNOWN: return WINED3DFMT_UNKNOWN; 104 case D3DFMT_R8G8B8: return WINED3DFMT_B8G8R8_UNORM; 105 case D3DFMT_A8R8G8B8: return WINED3DFMT_B8G8R8A8_UNORM; 106 case D3DFMT_X8R8G8B8: return WINED3DFMT_B8G8R8X8_UNORM; 107 case D3DFMT_R5G6B5: return WINED3DFMT_B5G6R5_UNORM; 108 case D3DFMT_X1R5G5B5: return WINED3DFMT_B5G5R5X1_UNORM; 109 case D3DFMT_A1R5G5B5: return WINED3DFMT_B5G5R5A1_UNORM; 110 case D3DFMT_A4R4G4B4: return WINED3DFMT_B4G4R4A4_UNORM; 111 case D3DFMT_R3G3B2: return WINED3DFMT_B2G3R3_UNORM; 112 case D3DFMT_A8: return WINED3DFMT_A8_UNORM; 113 case D3DFMT_A8R3G3B2: return WINED3DFMT_B2G3R3A8_UNORM; 114 case D3DFMT_X4R4G4B4: return WINED3DFMT_B4G4R4X4_UNORM; 115 case D3DFMT_A2B10G10R10: return WINED3DFMT_R10G10B10A2_UNORM; 116 case D3DFMT_G16R16: return WINED3DFMT_R16G16_UNORM; 117 case D3DFMT_A8P8: return WINED3DFMT_P8_UINT_A8_UNORM; 118 case D3DFMT_P8: return WINED3DFMT_P8_UINT; 119 case D3DFMT_L8: return WINED3DFMT_L8_UNORM; 120 case D3DFMT_A8L8: return WINED3DFMT_L8A8_UNORM; 121 case D3DFMT_A4L4: return WINED3DFMT_L4A4_UNORM; 122 case D3DFMT_V8U8: return WINED3DFMT_R8G8_SNORM; 123 case D3DFMT_L6V5U5: return WINED3DFMT_R5G5_SNORM_L6_UNORM; 124 case D3DFMT_X8L8V8U8: return WINED3DFMT_R8G8_SNORM_L8X8_UNORM; 125 case D3DFMT_Q8W8V8U8: return WINED3DFMT_R8G8B8A8_SNORM; 126 case D3DFMT_V16U16: return WINED3DFMT_R16G16_SNORM; 127 case D3DFMT_W11V11U10: return WINED3DFMT_R10G11B11_SNORM; 128 case D3DFMT_A2W10V10U10: return WINED3DFMT_R10G10B10_SNORM_A2_UNORM; 129 case D3DFMT_D16_LOCKABLE: return WINED3DFMT_D16_LOCKABLE; 130 case D3DFMT_D32: return WINED3DFMT_D32_UNORM; 131 case D3DFMT_D15S1: return WINED3DFMT_S1_UINT_D15_UNORM; 132 case D3DFMT_D24S8: return WINED3DFMT_D24_UNORM_S8_UINT; 133 case D3DFMT_D24X8: return WINED3DFMT_X8D24_UNORM; 134 case D3DFMT_D24X4S4: return WINED3DFMT_S4X4_UINT_D24_UNORM; 135 case D3DFMT_D16: return WINED3DFMT_D16_UNORM; 136 case D3DFMT_INDEX16: return WINED3DFMT_R16_UINT; 137 case D3DFMT_INDEX32: return WINED3DFMT_R32_UINT; 138 default: 139 FIXME("Unhandled D3DFORMAT %#x.\n", format); 140 return WINED3DFMT_UNKNOWN; 141 } 142 } 143 144 unsigned int wined3dmapflags_from_d3dmapflags(unsigned int flags) 145 { 146 static const unsigned int handled = D3DLOCK_NOSYSLOCK 147 | D3DLOCK_NOOVERWRITE 148 | D3DLOCK_DISCARD 149 | D3DLOCK_NO_DIRTY_UPDATE; 150 unsigned int wined3d_flags; 151 152 wined3d_flags = flags & handled; 153 if (!(flags & (D3DLOCK_NOOVERWRITE | D3DLOCK_DISCARD))) 154 wined3d_flags |= WINED3D_MAP_READ; 155 if (!(flags & D3DLOCK_READONLY)) 156 wined3d_flags |= WINED3D_MAP_WRITE; 157 if (!(wined3d_flags & (WINED3D_MAP_READ | WINED3D_MAP_WRITE))) 158 wined3d_flags |= WINED3D_MAP_READ | WINED3D_MAP_WRITE; 159 flags &= ~(handled | D3DLOCK_READONLY); 160 161 if (flags) 162 FIXME("Unhandled flags %#x.\n", flags); 163 164 return wined3d_flags; 165 } 166 167 static UINT vertex_count_from_primitive_count(D3DPRIMITIVETYPE primitive_type, UINT primitive_count) 168 { 169 switch (primitive_type) 170 { 171 case D3DPT_POINTLIST: 172 return primitive_count; 173 174 case D3DPT_LINELIST: 175 return primitive_count * 2; 176 177 case D3DPT_LINESTRIP: 178 return primitive_count + 1; 179 180 case D3DPT_TRIANGLELIST: 181 return primitive_count * 3; 182 183 case D3DPT_TRIANGLESTRIP: 184 case D3DPT_TRIANGLEFAN: 185 return primitive_count + 2; 186 187 default: 188 FIXME("Unhandled primitive type %#x.\n", primitive_type); 189 return 0; 190 } 191 } 192 193 static D3DSWAPEFFECT d3dswapeffect_from_wined3dswapeffect(enum wined3d_swap_effect effect) 194 { 195 switch (effect) 196 { 197 case WINED3D_SWAP_EFFECT_DISCARD: 198 return D3DSWAPEFFECT_DISCARD; 199 case WINED3D_SWAP_EFFECT_SEQUENTIAL: 200 return D3DSWAPEFFECT_FLIP; 201 case WINED3D_SWAP_EFFECT_COPY: 202 return D3DSWAPEFFECT_COPY; 203 case WINED3D_SWAP_EFFECT_COPY_VSYNC: 204 return D3DSWAPEFFECT_COPY_VSYNC; 205 default: 206 FIXME("Unhandled swap effect %#x.\n", effect); 207 return D3DSWAPEFFECT_FLIP; 208 } 209 } 210 211 static void present_parameters_from_wined3d_swapchain_desc(D3DPRESENT_PARAMETERS *present_parameters, 212 const struct wined3d_swapchain_desc *swapchain_desc, DWORD presentation_interval) 213 { 214 present_parameters->BackBufferWidth = swapchain_desc->backbuffer_width; 215 present_parameters->BackBufferHeight = swapchain_desc->backbuffer_height; 216 present_parameters->BackBufferFormat = d3dformat_from_wined3dformat(swapchain_desc->backbuffer_format); 217 present_parameters->BackBufferCount = swapchain_desc->backbuffer_count; 218 present_parameters->MultiSampleType = swapchain_desc->multisample_type; 219 present_parameters->SwapEffect = d3dswapeffect_from_wined3dswapeffect(swapchain_desc->swap_effect); 220 present_parameters->hDeviceWindow = swapchain_desc->device_window; 221 present_parameters->Windowed = swapchain_desc->windowed; 222 present_parameters->EnableAutoDepthStencil = swapchain_desc->enable_auto_depth_stencil; 223 present_parameters->AutoDepthStencilFormat 224 = d3dformat_from_wined3dformat(swapchain_desc->auto_depth_stencil_format); 225 present_parameters->Flags = swapchain_desc->flags & D3DPRESENTFLAGS_MASK; 226 present_parameters->FullScreen_RefreshRateInHz = swapchain_desc->refresh_rate; 227 present_parameters->FullScreen_PresentationInterval = presentation_interval; 228 } 229 230 static enum wined3d_swap_effect wined3dswapeffect_from_d3dswapeffect(D3DSWAPEFFECT effect) 231 { 232 switch (effect) 233 { 234 case D3DSWAPEFFECT_DISCARD: 235 return WINED3D_SWAP_EFFECT_DISCARD; 236 case D3DSWAPEFFECT_FLIP: 237 return WINED3D_SWAP_EFFECT_SEQUENTIAL; 238 case D3DSWAPEFFECT_COPY: 239 return WINED3D_SWAP_EFFECT_COPY; 240 case D3DSWAPEFFECT_COPY_VSYNC: 241 return WINED3D_SWAP_EFFECT_COPY_VSYNC; 242 default: 243 FIXME("Unhandled swap effect %#x.\n", effect); 244 return WINED3D_SWAP_EFFECT_SEQUENTIAL; 245 } 246 } 247 248 static enum wined3d_swap_interval wined3dswapinterval_from_d3d(DWORD interval) 249 { 250 switch (interval) 251 { 252 case D3DPRESENT_INTERVAL_IMMEDIATE: 253 return WINED3D_SWAP_INTERVAL_IMMEDIATE; 254 case D3DPRESENT_INTERVAL_ONE: 255 return WINED3D_SWAP_INTERVAL_ONE; 256 case D3DPRESENT_INTERVAL_TWO: 257 return WINED3D_SWAP_INTERVAL_TWO; 258 case D3DPRESENT_INTERVAL_THREE: 259 return WINED3D_SWAP_INTERVAL_THREE; 260 case D3DPRESENT_INTERVAL_FOUR: 261 return WINED3D_SWAP_INTERVAL_FOUR; 262 default: 263 FIXME("Unhandled presentation interval %#x.\n", interval); 264 case D3DPRESENT_INTERVAL_DEFAULT: 265 return WINED3D_SWAP_INTERVAL_DEFAULT; 266 } 267 } 268 269 static BOOL wined3d_swapchain_desc_from_present_parameters(struct wined3d_swapchain_desc *swapchain_desc, 270 const D3DPRESENT_PARAMETERS *present_parameters) 271 { 272 if (!present_parameters->SwapEffect || present_parameters->SwapEffect > D3DSWAPEFFECT_COPY_VSYNC) 273 { 274 WARN("Invalid swap effect %u passed.\n", present_parameters->SwapEffect); 275 return FALSE; 276 } 277 if (present_parameters->BackBufferCount > 3 278 || ((present_parameters->SwapEffect == D3DSWAPEFFECT_COPY 279 || present_parameters->SwapEffect == D3DSWAPEFFECT_COPY_VSYNC) 280 && present_parameters->BackBufferCount > 1)) 281 { 282 WARN("Invalid backbuffer count %u.\n", present_parameters->BackBufferCount); 283 return FALSE; 284 } 285 switch (present_parameters->FullScreen_PresentationInterval) 286 { 287 case D3DPRESENT_INTERVAL_DEFAULT: 288 case D3DPRESENT_INTERVAL_ONE: 289 case D3DPRESENT_INTERVAL_TWO: 290 case D3DPRESENT_INTERVAL_THREE: 291 case D3DPRESENT_INTERVAL_FOUR: 292 case D3DPRESENT_INTERVAL_IMMEDIATE: 293 break; 294 default: 295 WARN("Invalid presentation interval %#x.\n", 296 present_parameters->FullScreen_PresentationInterval); 297 return FALSE; 298 } 299 300 swapchain_desc->backbuffer_width = present_parameters->BackBufferWidth; 301 swapchain_desc->backbuffer_height = present_parameters->BackBufferHeight; 302 swapchain_desc->backbuffer_format = wined3dformat_from_d3dformat(present_parameters->BackBufferFormat); 303 swapchain_desc->backbuffer_count = max(1, present_parameters->BackBufferCount); 304 swapchain_desc->backbuffer_usage = WINED3DUSAGE_RENDERTARGET; 305 swapchain_desc->multisample_type = present_parameters->MultiSampleType; 306 swapchain_desc->multisample_quality = 0; /* d3d9 only */ 307 swapchain_desc->swap_effect = wined3dswapeffect_from_d3dswapeffect(present_parameters->SwapEffect); 308 swapchain_desc->device_window = present_parameters->hDeviceWindow; 309 swapchain_desc->windowed = present_parameters->Windowed; 310 swapchain_desc->enable_auto_depth_stencil = present_parameters->EnableAutoDepthStencil; 311 swapchain_desc->auto_depth_stencil_format 312 = wined3dformat_from_d3dformat(present_parameters->AutoDepthStencilFormat); 313 swapchain_desc->flags 314 = (present_parameters->Flags & D3DPRESENTFLAGS_MASK) | WINED3D_SWAPCHAIN_ALLOW_MODE_SWITCH; 315 swapchain_desc->refresh_rate = present_parameters->FullScreen_RefreshRateInHz; 316 swapchain_desc->auto_restore_display_mode = TRUE; 317 318 if (present_parameters->Flags & ~D3DPRESENTFLAGS_MASK) 319 FIXME("Unhandled flags %#x.\n", present_parameters->Flags & ~D3DPRESENTFLAGS_MASK); 320 321 return TRUE; 322 } 323 324 void d3dcaps_from_wined3dcaps(D3DCAPS8 *caps, const WINED3DCAPS *wined3d_caps) 325 { 326 caps->DeviceType = (D3DDEVTYPE)wined3d_caps->DeviceType; 327 caps->AdapterOrdinal = wined3d_caps->AdapterOrdinal; 328 caps->Caps = wined3d_caps->Caps; 329 caps->Caps2 = wined3d_caps->Caps2; 330 caps->Caps3 = wined3d_caps->Caps3; 331 caps->PresentationIntervals = D3DPRESENT_INTERVAL_IMMEDIATE | D3DPRESENT_INTERVAL_ONE; 332 caps->CursorCaps = wined3d_caps->CursorCaps; 333 caps->DevCaps = wined3d_caps->DevCaps; 334 caps->PrimitiveMiscCaps = wined3d_caps->PrimitiveMiscCaps; 335 caps->RasterCaps = wined3d_caps->RasterCaps; 336 caps->ZCmpCaps = wined3d_caps->ZCmpCaps; 337 caps->SrcBlendCaps = wined3d_caps->SrcBlendCaps; 338 caps->DestBlendCaps = wined3d_caps->DestBlendCaps; 339 caps->AlphaCmpCaps = wined3d_caps->AlphaCmpCaps; 340 caps->ShadeCaps = wined3d_caps->ShadeCaps; 341 caps->TextureCaps = wined3d_caps->TextureCaps; 342 caps->TextureFilterCaps = wined3d_caps->TextureFilterCaps; 343 caps->CubeTextureFilterCaps = wined3d_caps->CubeTextureFilterCaps; 344 caps->VolumeTextureFilterCaps = wined3d_caps->VolumeTextureFilterCaps; 345 caps->TextureAddressCaps = wined3d_caps->TextureAddressCaps; 346 caps->VolumeTextureAddressCaps = wined3d_caps->VolumeTextureAddressCaps; 347 caps->LineCaps = wined3d_caps->LineCaps; 348 caps->MaxTextureWidth = wined3d_caps->MaxTextureWidth; 349 caps->MaxTextureHeight = wined3d_caps->MaxTextureHeight; 350 caps->MaxVolumeExtent = wined3d_caps->MaxVolumeExtent; 351 caps->MaxTextureRepeat = wined3d_caps->MaxTextureRepeat; 352 caps->MaxTextureAspectRatio = wined3d_caps->MaxTextureAspectRatio; 353 caps->MaxAnisotropy = wined3d_caps->MaxAnisotropy; 354 caps->MaxVertexW = wined3d_caps->MaxVertexW; 355 caps->GuardBandLeft = wined3d_caps->GuardBandLeft; 356 caps->GuardBandTop = wined3d_caps->GuardBandTop; 357 caps->GuardBandRight = wined3d_caps->GuardBandRight; 358 caps->GuardBandBottom = wined3d_caps->GuardBandBottom; 359 caps->ExtentsAdjust = wined3d_caps->ExtentsAdjust; 360 caps->StencilCaps = wined3d_caps->StencilCaps; 361 caps->FVFCaps = wined3d_caps->FVFCaps; 362 caps->TextureOpCaps = wined3d_caps->TextureOpCaps; 363 caps->MaxTextureBlendStages = wined3d_caps->MaxTextureBlendStages; 364 caps->MaxSimultaneousTextures = wined3d_caps->MaxSimultaneousTextures; 365 caps->VertexProcessingCaps = wined3d_caps->VertexProcessingCaps; 366 caps->MaxActiveLights = wined3d_caps->MaxActiveLights; 367 caps->MaxUserClipPlanes = wined3d_caps->MaxUserClipPlanes; 368 caps->MaxVertexBlendMatrices = wined3d_caps->MaxVertexBlendMatrices; 369 caps->MaxVertexBlendMatrixIndex = wined3d_caps->MaxVertexBlendMatrixIndex; 370 caps->MaxPointSize = wined3d_caps->MaxPointSize; 371 caps->MaxPrimitiveCount = wined3d_caps->MaxPrimitiveCount; 372 caps->MaxVertexIndex = wined3d_caps->MaxVertexIndex; 373 caps->MaxStreams = wined3d_caps->MaxStreams; 374 caps->MaxStreamStride = wined3d_caps->MaxStreamStride; 375 caps->VertexShaderVersion = wined3d_caps->VertexShaderVersion; 376 caps->MaxVertexShaderConst = wined3d_caps->MaxVertexShaderConst; 377 caps->PixelShaderVersion = wined3d_caps->PixelShaderVersion; 378 caps->MaxPixelShaderValue = wined3d_caps->PixelShader1xMaxValue; 379 380 caps->Caps2 &= D3DCAPS2_CANCALIBRATEGAMMA | D3DCAPS2_CANRENDERWINDOWED 381 | D3DCAPS2_CANMANAGERESOURCE | D3DCAPS2_DYNAMICTEXTURES | D3DCAPS2_FULLSCREENGAMMA 382 | D3DCAPS2_NO2DDURING3DSCENE | D3DCAPS2_RESERVED; 383 caps->Caps3 &= D3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD | D3DCAPS3_RESERVED; 384 caps->PrimitiveMiscCaps &= D3DPMISCCAPS_MASKZ | D3DPMISCCAPS_LINEPATTERNREP 385 | D3DPMISCCAPS_CULLNONE | D3DPMISCCAPS_CULLCW | D3DPMISCCAPS_CULLCCW 386 | D3DPMISCCAPS_COLORWRITEENABLE | D3DPMISCCAPS_CLIPPLANESCALEDPOINTS 387 | D3DPMISCCAPS_CLIPTLVERTS | D3DPMISCCAPS_TSSARGTEMP | D3DPMISCCAPS_BLENDOP 388 | D3DPMISCCAPS_NULLREFERENCE; 389 caps->RasterCaps &= D3DPRASTERCAPS_DITHER | D3DPRASTERCAPS_PAT | D3DPRASTERCAPS_ZTEST 390 | D3DPRASTERCAPS_FOGVERTEX | D3DPRASTERCAPS_FOGTABLE | D3DPRASTERCAPS_ANTIALIASEDGES 391 | D3DPRASTERCAPS_MIPMAPLODBIAS | D3DPRASTERCAPS_ZBIAS | D3DPRASTERCAPS_ZBUFFERLESSHSR 392 | D3DPRASTERCAPS_FOGRANGE | D3DPRASTERCAPS_ANISOTROPY | D3DPRASTERCAPS_WBUFFER 393 | D3DPRASTERCAPS_WFOG | D3DPRASTERCAPS_ZFOG | D3DPRASTERCAPS_COLORPERSPECTIVE 394 | D3DPRASTERCAPS_STRETCHBLTMULTISAMPLE; 395 caps->SrcBlendCaps &= D3DPBLENDCAPS_ZERO | D3DPBLENDCAPS_ONE | D3DPBLENDCAPS_SRCCOLOR 396 | D3DPBLENDCAPS_INVSRCCOLOR | D3DPBLENDCAPS_SRCALPHA | D3DPBLENDCAPS_INVSRCALPHA 397 | D3DPBLENDCAPS_DESTALPHA | D3DPBLENDCAPS_INVDESTALPHA | D3DPBLENDCAPS_DESTCOLOR 398 | D3DPBLENDCAPS_INVDESTCOLOR | D3DPBLENDCAPS_SRCALPHASAT | D3DPBLENDCAPS_BOTHSRCALPHA 399 | D3DPBLENDCAPS_BOTHINVSRCALPHA; 400 caps->DestBlendCaps &= D3DPBLENDCAPS_ZERO | D3DPBLENDCAPS_ONE | D3DPBLENDCAPS_SRCCOLOR 401 | D3DPBLENDCAPS_INVSRCCOLOR | D3DPBLENDCAPS_SRCALPHA | D3DPBLENDCAPS_INVSRCALPHA 402 | D3DPBLENDCAPS_DESTALPHA | D3DPBLENDCAPS_INVDESTALPHA | D3DPBLENDCAPS_DESTCOLOR 403 | D3DPBLENDCAPS_INVDESTCOLOR | D3DPBLENDCAPS_SRCALPHASAT | D3DPBLENDCAPS_BOTHSRCALPHA 404 | D3DPBLENDCAPS_BOTHINVSRCALPHA; 405 caps->TextureCaps &= D3DPTEXTURECAPS_PERSPECTIVE | D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_ALPHA 406 | D3DPTEXTURECAPS_SQUAREONLY | D3DPTEXTURECAPS_TEXREPEATNOTSCALEDBYSIZE 407 | D3DPTEXTURECAPS_ALPHAPALETTE | D3DPTEXTURECAPS_NONPOW2CONDITIONAL 408 | D3DPTEXTURECAPS_PROJECTED | D3DPTEXTURECAPS_CUBEMAP | D3DPTEXTURECAPS_VOLUMEMAP 409 | D3DPTEXTURECAPS_MIPMAP | D3DPTEXTURECAPS_MIPVOLUMEMAP | D3DPTEXTURECAPS_MIPCUBEMAP 410 | D3DPTEXTURECAPS_CUBEMAP_POW2 | D3DPTEXTURECAPS_VOLUMEMAP_POW2; 411 caps->TextureFilterCaps &= D3DPTFILTERCAPS_MINFPOINT | D3DPTFILTERCAPS_MINFLINEAR 412 | D3DPTFILTERCAPS_MINFANISOTROPIC | D3DPTFILTERCAPS_MIPFPOINT 413 | D3DPTFILTERCAPS_MIPFLINEAR | D3DPTFILTERCAPS_MAGFPOINT | D3DPTFILTERCAPS_MAGFLINEAR 414 | D3DPTFILTERCAPS_MAGFANISOTROPIC | D3DPTFILTERCAPS_MAGFAFLATCUBIC 415 | D3DPTFILTERCAPS_MAGFGAUSSIANCUBIC; 416 caps->CubeTextureFilterCaps &= D3DPTFILTERCAPS_MINFPOINT | D3DPTFILTERCAPS_MINFLINEAR 417 | D3DPTFILTERCAPS_MINFANISOTROPIC | D3DPTFILTERCAPS_MIPFPOINT 418 | D3DPTFILTERCAPS_MIPFLINEAR | D3DPTFILTERCAPS_MAGFPOINT | D3DPTFILTERCAPS_MAGFLINEAR 419 | D3DPTFILTERCAPS_MAGFANISOTROPIC | D3DPTFILTERCAPS_MAGFAFLATCUBIC 420 | D3DPTFILTERCAPS_MAGFGAUSSIANCUBIC; 421 caps->VolumeTextureFilterCaps &= D3DPTFILTERCAPS_MINFPOINT | D3DPTFILTERCAPS_MINFLINEAR 422 | D3DPTFILTERCAPS_MINFANISOTROPIC | D3DPTFILTERCAPS_MIPFPOINT 423 | D3DPTFILTERCAPS_MIPFLINEAR | D3DPTFILTERCAPS_MAGFPOINT | D3DPTFILTERCAPS_MAGFLINEAR 424 | D3DPTFILTERCAPS_MAGFANISOTROPIC | D3DPTFILTERCAPS_MAGFAFLATCUBIC 425 | D3DPTFILTERCAPS_MAGFGAUSSIANCUBIC; 426 caps->StencilCaps &= ~WINED3DSTENCILCAPS_TWOSIDED; 427 caps->VertexProcessingCaps &= D3DVTXPCAPS_TEXGEN | D3DVTXPCAPS_MATERIALSOURCE7 428 | D3DVTXPCAPS_DIRECTIONALLIGHTS | D3DVTXPCAPS_POSITIONALLIGHTS | D3DVTXPCAPS_LOCALVIEWER 429 | D3DVTXPCAPS_TWEENING | D3DVTXPCAPS_NO_VSDT_UBYTE4; 430 431 /* D3D8 doesn't support SM 2.0 or higher, so clamp to 1.x */ 432 if (caps->PixelShaderVersion) 433 caps->PixelShaderVersion = D3DPS_VERSION(1, 4); 434 else 435 caps->PixelShaderVersion = D3DPS_VERSION(0, 0); 436 if (caps->VertexShaderVersion) 437 caps->VertexShaderVersion = D3DVS_VERSION(1, 1); 438 else 439 caps->VertexShaderVersion = D3DVS_VERSION(0, 0); 440 caps->MaxVertexShaderConst = min(D3D8_MAX_VERTEX_SHADER_CONSTANTF, caps->MaxVertexShaderConst); 441 } 442 443 /* Handle table functions */ 444 static DWORD d3d8_allocate_handle(struct d3d8_handle_table *t, void *object, enum d3d8_handle_type type) 445 { 446 struct d3d8_handle_entry *entry; 447 448 if (t->free_entries) 449 { 450 DWORD index = t->free_entries - t->entries; 451 /* Use a free handle */ 452 entry = t->free_entries; 453 if (entry->type != D3D8_HANDLE_FREE) 454 { 455 ERR("Handle %u(%p) is in the free list, but has type %#x.\n", index, entry, entry->type); 456 return D3D8_INVALID_HANDLE; 457 } 458 t->free_entries = entry->object; 459 entry->object = object; 460 entry->type = type; 461 462 return index; 463 } 464 465 if (!(t->entry_count < t->table_size)) 466 { 467 /* Grow the table */ 468 UINT new_size = t->table_size + (t->table_size >> 1); 469 struct d3d8_handle_entry *new_entries; 470 471 if (!(new_entries = heap_realloc(t->entries, new_size * sizeof(*t->entries)))) 472 { 473 ERR("Failed to grow the handle table.\n"); 474 return D3D8_INVALID_HANDLE; 475 } 476 t->entries = new_entries; 477 t->table_size = new_size; 478 } 479 480 entry = &t->entries[t->entry_count]; 481 entry->object = object; 482 entry->type = type; 483 484 return t->entry_count++; 485 } 486 487 static void *d3d8_free_handle(struct d3d8_handle_table *t, DWORD handle, enum d3d8_handle_type type) 488 { 489 struct d3d8_handle_entry *entry; 490 void *object; 491 492 if (handle == D3D8_INVALID_HANDLE || handle >= t->entry_count) 493 { 494 WARN("Invalid handle %u passed.\n", handle); 495 return NULL; 496 } 497 498 entry = &t->entries[handle]; 499 if (entry->type != type) 500 { 501 WARN("Handle %u(%p) is not of type %#x.\n", handle, entry, type); 502 return NULL; 503 } 504 505 object = entry->object; 506 entry->object = t->free_entries; 507 entry->type = D3D8_HANDLE_FREE; 508 t->free_entries = entry; 509 510 return object; 511 } 512 513 static void *d3d8_get_object(struct d3d8_handle_table *t, DWORD handle, enum d3d8_handle_type type) 514 { 515 struct d3d8_handle_entry *entry; 516 517 if (handle == D3D8_INVALID_HANDLE || handle >= t->entry_count) 518 { 519 WARN("Invalid handle %u passed.\n", handle); 520 return NULL; 521 } 522 523 entry = &t->entries[handle]; 524 if (entry->type != type) 525 { 526 WARN("Handle %u(%p) is not of type %#x.\n", handle, entry, type); 527 return NULL; 528 } 529 530 return entry->object; 531 } 532 533 static HRESULT WINAPI d3d8_device_QueryInterface(IDirect3DDevice8 *iface, REFIID riid, void **out) 534 { 535 TRACE("iface %p, riid %s, out %p.\n", 536 iface, debugstr_guid(riid), out); 537 538 if (IsEqualGUID(riid, &IID_IDirect3DDevice8) 539 || IsEqualGUID(riid, &IID_IUnknown)) 540 { 541 IDirect3DDevice8_AddRef(iface); 542 *out = iface; 543 return S_OK; 544 } 545 546 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid)); 547 548 *out = NULL; 549 return E_NOINTERFACE; 550 } 551 552 static ULONG WINAPI d3d8_device_AddRef(IDirect3DDevice8 *iface) 553 { 554 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); 555 ULONG ref = InterlockedIncrement(&device->ref); 556 557 TRACE("%p increasing refcount to %u.\n", iface, ref); 558 559 return ref; 560 } 561 562 static ULONG WINAPI d3d8_device_Release(IDirect3DDevice8 *iface) 563 { 564 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); 565 ULONG ref; 566 567 if (device->inDestruction) 568 return 0; 569 570 ref = InterlockedDecrement(&device->ref); 571 572 TRACE("%p decreasing refcount to %u.\n", iface, ref); 573 574 if (!ref) 575 { 576 IDirect3D8 *parent = device->d3d_parent; 577 unsigned i; 578 579 TRACE("Releasing wined3d device %p.\n", device->wined3d_device); 580 581 wined3d_mutex_lock(); 582 583 device->inDestruction = TRUE; 584 585 for (i = 0; i < device->numConvertedDecls; ++i) 586 { 587 d3d8_vertex_declaration_destroy(device->decls[i].declaration); 588 } 589 heap_free(device->decls); 590 591 if (device->vertex_buffer) 592 wined3d_buffer_decref(device->vertex_buffer); 593 if (device->index_buffer) 594 wined3d_buffer_decref(device->index_buffer); 595 596 wined3d_device_uninit_3d(device->wined3d_device); 597 wined3d_device_release_focus_window(device->wined3d_device); 598 wined3d_device_decref(device->wined3d_device); 599 heap_free(device->handle_table.entries); 600 heap_free(device); 601 602 wined3d_mutex_unlock(); 603 604 IDirect3D8_Release(parent); 605 } 606 return ref; 607 } 608 609 static HRESULT WINAPI d3d8_device_TestCooperativeLevel(IDirect3DDevice8 *iface) 610 { 611 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); 612 613 TRACE("iface %p.\n", iface); 614 615 TRACE("device state: %#x.\n", device->device_state); 616 617 switch (device->device_state) 618 { 619 default: 620 case D3D8_DEVICE_STATE_OK: 621 return D3D_OK; 622 case D3D8_DEVICE_STATE_LOST: 623 return D3DERR_DEVICELOST; 624 case D3D8_DEVICE_STATE_NOT_RESET: 625 return D3DERR_DEVICENOTRESET; 626 } 627 } 628 629 static UINT WINAPI d3d8_device_GetAvailableTextureMem(IDirect3DDevice8 *iface) 630 { 631 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); 632 UINT ret; 633 634 TRACE("iface %p.\n", iface); 635 636 wined3d_mutex_lock(); 637 ret = wined3d_device_get_available_texture_mem(device->wined3d_device); 638 wined3d_mutex_unlock(); 639 640 return ret; 641 } 642 643 static HRESULT WINAPI d3d8_device_ResourceManagerDiscardBytes(IDirect3DDevice8 *iface, DWORD byte_count) 644 { 645 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); 646 647 TRACE("iface %p, byte_count %u.\n", iface, byte_count); 648 649 if (byte_count) 650 FIXME("Byte count ignored.\n"); 651 652 wined3d_mutex_lock(); 653 wined3d_device_evict_managed_resources(device->wined3d_device); 654 wined3d_mutex_unlock(); 655 656 return D3D_OK; 657 } 658 659 static HRESULT WINAPI d3d8_device_GetDirect3D(IDirect3DDevice8 *iface, IDirect3D8 **d3d8) 660 { 661 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); 662 663 TRACE("iface %p, d3d8 %p.\n", iface, d3d8); 664 665 if (!d3d8) 666 return D3DERR_INVALIDCALL; 667 668 return IDirect3D8_QueryInterface(device->d3d_parent, &IID_IDirect3D8, (void **)d3d8); 669 } 670 671 static HRESULT WINAPI d3d8_device_GetDeviceCaps(IDirect3DDevice8 *iface, D3DCAPS8 *caps) 672 { 673 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); 674 WINED3DCAPS wined3d_caps; 675 HRESULT hr; 676 677 TRACE("iface %p, caps %p.\n", iface, caps); 678 679 if (!caps) 680 return D3DERR_INVALIDCALL; 681 682 wined3d_mutex_lock(); 683 hr = wined3d_device_get_device_caps(device->wined3d_device, &wined3d_caps); 684 wined3d_mutex_unlock(); 685 686 d3dcaps_from_wined3dcaps(caps, &wined3d_caps); 687 688 return hr; 689 } 690 691 static HRESULT WINAPI d3d8_device_GetDisplayMode(IDirect3DDevice8 *iface, D3DDISPLAYMODE *mode) 692 { 693 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); 694 struct wined3d_display_mode wined3d_mode; 695 HRESULT hr; 696 697 TRACE("iface %p, mode %p.\n", iface, mode); 698 699 wined3d_mutex_lock(); 700 hr = wined3d_device_get_display_mode(device->wined3d_device, 0, &wined3d_mode, NULL); 701 wined3d_mutex_unlock(); 702 703 if (SUCCEEDED(hr)) 704 { 705 mode->Width = wined3d_mode.width; 706 mode->Height = wined3d_mode.height; 707 mode->RefreshRate = wined3d_mode.refresh_rate; 708 mode->Format = d3dformat_from_wined3dformat(wined3d_mode.format_id); 709 } 710 711 return hr; 712 } 713 714 static HRESULT WINAPI d3d8_device_GetCreationParameters(IDirect3DDevice8 *iface, 715 D3DDEVICE_CREATION_PARAMETERS *parameters) 716 { 717 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); 718 719 TRACE("iface %p, parameters %p.\n", iface, parameters); 720 721 wined3d_mutex_lock(); 722 wined3d_device_get_creation_parameters(device->wined3d_device, 723 (struct wined3d_device_creation_parameters *)parameters); 724 wined3d_mutex_unlock(); 725 726 return D3D_OK; 727 } 728 729 static HRESULT WINAPI d3d8_device_SetCursorProperties(IDirect3DDevice8 *iface, 730 UINT hotspot_x, UINT hotspot_y, IDirect3DSurface8 *bitmap) 731 { 732 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); 733 struct d3d8_surface *bitmap_impl = unsafe_impl_from_IDirect3DSurface8(bitmap); 734 HRESULT hr; 735 736 TRACE("iface %p, hotspot_x %u, hotspot_y %u, bitmap %p.\n", 737 iface, hotspot_x, hotspot_y, bitmap); 738 739 if (!bitmap) 740 { 741 WARN("No cursor bitmap, returning D3DERR_INVALIDCALL.\n"); 742 return D3DERR_INVALIDCALL; 743 } 744 745 wined3d_mutex_lock(); 746 hr = wined3d_device_set_cursor_properties(device->wined3d_device, 747 hotspot_x, hotspot_y, bitmap_impl->wined3d_texture, bitmap_impl->sub_resource_idx); 748 wined3d_mutex_unlock(); 749 750 return hr; 751 } 752 753 static void WINAPI d3d8_device_SetCursorPosition(IDirect3DDevice8 *iface, UINT x, UINT y, DWORD flags) 754 { 755 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); 756 757 TRACE("iface %p, x %u, y %u, flags %#x.\n", iface, x, y, flags); 758 759 wined3d_mutex_lock(); 760 wined3d_device_set_cursor_position(device->wined3d_device, x, y, flags); 761 wined3d_mutex_unlock(); 762 } 763 764 static BOOL WINAPI d3d8_device_ShowCursor(IDirect3DDevice8 *iface, BOOL show) 765 { 766 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); 767 BOOL ret; 768 769 TRACE("iface %p, show %#x.\n", iface, show); 770 771 wined3d_mutex_lock(); 772 ret = wined3d_device_show_cursor(device->wined3d_device, show); 773 wined3d_mutex_unlock(); 774 775 return ret; 776 } 777 778 static HRESULT WINAPI d3d8_device_CreateAdditionalSwapChain(IDirect3DDevice8 *iface, 779 D3DPRESENT_PARAMETERS *present_parameters, IDirect3DSwapChain8 **swapchain) 780 { 781 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); 782 struct wined3d_swapchain_desc desc; 783 struct d3d8_swapchain *object; 784 unsigned int swap_interval; 785 unsigned int i, count; 786 HRESULT hr; 787 788 TRACE("iface %p, present_parameters %p, swapchain %p.\n", 789 iface, present_parameters, swapchain); 790 791 if (!present_parameters->Windowed) 792 { 793 WARN("Trying to create an additional fullscreen swapchain, returning D3DERR_INVALIDCALL.\n"); 794 return D3DERR_INVALIDCALL; 795 } 796 797 wined3d_mutex_lock(); 798 count = wined3d_device_get_swapchain_count(device->wined3d_device); 799 for (i = 0; i < count; ++i) 800 { 801 struct wined3d_swapchain *wined3d_swapchain; 802 803 wined3d_swapchain = wined3d_device_get_swapchain(device->wined3d_device, i); 804 wined3d_swapchain_get_desc(wined3d_swapchain, &desc); 805 806 if (!desc.windowed) 807 { 808 wined3d_mutex_unlock(); 809 WARN("Trying to create an additional swapchain in fullscreen mode, returning D3DERR_INVALIDCALL.\n"); 810 return D3DERR_INVALIDCALL; 811 } 812 } 813 wined3d_mutex_unlock(); 814 815 if (!wined3d_swapchain_desc_from_present_parameters(&desc, present_parameters)) 816 return D3DERR_INVALIDCALL; 817 swap_interval = wined3dswapinterval_from_d3d(present_parameters->FullScreen_PresentationInterval); 818 if (SUCCEEDED(hr = d3d8_swapchain_create(device, &desc, swap_interval, &object))) 819 *swapchain = &object->IDirect3DSwapChain8_iface; 820 present_parameters_from_wined3d_swapchain_desc(present_parameters, 821 &desc, present_parameters->FullScreen_PresentationInterval); 822 823 return hr; 824 } 825 826 static HRESULT CDECL reset_enum_callback(struct wined3d_resource *resource) 827 { 828 struct wined3d_resource_desc desc; 829 IDirect3DBaseTexture8 *texture; 830 struct d3d8_surface *surface; 831 IUnknown *parent; 832 833 wined3d_resource_get_desc(resource, &desc); 834 if (desc.access & WINED3D_RESOURCE_ACCESS_CPU) 835 return D3D_OK; 836 837 if (desc.resource_type != WINED3D_RTYPE_TEXTURE_2D) 838 { 839 WARN("Resource %p in pool D3DPOOL_DEFAULT blocks the Reset call.\n", resource); 840 return D3DERR_DEVICELOST; 841 } 842 843 parent = wined3d_resource_get_parent(resource); 844 if (parent && SUCCEEDED(IUnknown_QueryInterface(parent, &IID_IDirect3DBaseTexture8, (void **)&texture))) 845 { 846 IDirect3DBaseTexture8_Release(texture); 847 WARN("Texture %p (resource %p) in pool D3DPOOL_DEFAULT blocks the Reset call.\n", texture, resource); 848 return D3DERR_DEVICELOST; 849 } 850 851 surface = wined3d_texture_get_sub_resource_parent(wined3d_texture_from_resource(resource), 0); 852 if (!surface->resource.refcount) 853 return D3D_OK; 854 855 WARN("Surface %p in pool D3DPOOL_DEFAULT blocks the Reset call.\n", surface); 856 return D3DERR_DEVICELOST; 857 } 858 859 static HRESULT WINAPI d3d8_device_Reset(IDirect3DDevice8 *iface, 860 D3DPRESENT_PARAMETERS *present_parameters) 861 { 862 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); 863 struct wined3d_swapchain_desc swapchain_desc; 864 HRESULT hr; 865 866 TRACE("iface %p, present_parameters %p.\n", iface, present_parameters); 867 868 if (device->device_state == D3D8_DEVICE_STATE_LOST) 869 { 870 WARN("App not active, returning D3DERR_DEVICELOST.\n"); 871 return D3DERR_DEVICELOST; 872 } 873 if (!wined3d_swapchain_desc_from_present_parameters(&swapchain_desc, present_parameters)) 874 return D3DERR_INVALIDCALL; 875 876 wined3d_mutex_lock(); 877 878 if (device->vertex_buffer) 879 { 880 wined3d_buffer_decref(device->vertex_buffer); 881 device->vertex_buffer = NULL; 882 device->vertex_buffer_size = 0; 883 } 884 if (device->index_buffer) 885 { 886 wined3d_buffer_decref(device->index_buffer); 887 device->index_buffer = NULL; 888 device->index_buffer_size = 0; 889 } 890 891 if (SUCCEEDED(hr = wined3d_device_reset(device->wined3d_device, &swapchain_desc, 892 NULL, reset_enum_callback, TRUE))) 893 { 894 present_parameters->BackBufferCount = swapchain_desc.backbuffer_count; 895 device->implicit_swapchain->swap_interval 896 = wined3dswapinterval_from_d3d(present_parameters->FullScreen_PresentationInterval); 897 wined3d_device_set_render_state(device->wined3d_device, WINED3D_RS_POINTSIZE_MIN, 0); 898 wined3d_device_set_render_state(device->wined3d_device, WINED3D_RS_ZENABLE, 899 !!swapchain_desc.enable_auto_depth_stencil); 900 device->device_state = D3D8_DEVICE_STATE_OK; 901 } 902 else 903 { 904 device->device_state = D3D8_DEVICE_STATE_NOT_RESET; 905 } 906 wined3d_mutex_unlock(); 907 908 return hr; 909 } 910 911 static HRESULT WINAPI d3d8_device_Present(IDirect3DDevice8 *iface, const RECT *src_rect, 912 const RECT *dst_rect, HWND dst_window_override, const RGNDATA *dirty_region) 913 { 914 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); 915 916 TRACE("iface %p, src_rect %s, dst_rect %s, dst_window_override %p, dirty_region %p.\n", 917 iface, wine_dbgstr_rect(src_rect), wine_dbgstr_rect(dst_rect), dst_window_override, dirty_region); 918 919 /* Fraps does not hook IDirect3DDevice8::Present regardless of the hotpatch 920 * attribute. It only hooks IDirect3DSwapChain8::Present. Yet it properly 921 * shows a framerate on Windows in applications that only call the device 922 * method, like e.g. the dx8 sdk samples. The conclusion is that native 923 * calls the swapchain's public method from the device. */ 924 return IDirect3DSwapChain8_Present(&device->implicit_swapchain->IDirect3DSwapChain8_iface, 925 src_rect, dst_rect, dst_window_override, dirty_region); 926 } 927 928 static HRESULT WINAPI d3d8_device_GetBackBuffer(IDirect3DDevice8 *iface, 929 UINT backbuffer_idx, D3DBACKBUFFER_TYPE backbuffer_type, IDirect3DSurface8 **backbuffer) 930 { 931 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); 932 struct wined3d_swapchain *wined3d_swapchain; 933 struct wined3d_texture *wined3d_texture; 934 struct d3d8_surface *surface_impl; 935 936 TRACE("iface %p, backbuffer_idx %u, backbuffer_type %#x, backbuffer %p.\n", 937 iface, backbuffer_idx, backbuffer_type, backbuffer); 938 939 /* backbuffer_type is ignored by native. */ 940 941 /* No need to check for backbuffer == NULL, Windows crashes in that case. */ 942 wined3d_mutex_lock(); 943 944 wined3d_swapchain = device->implicit_swapchain->wined3d_swapchain; 945 if (!(wined3d_texture = wined3d_swapchain_get_back_buffer(wined3d_swapchain, backbuffer_idx))) 946 { 947 wined3d_mutex_unlock(); 948 *backbuffer = NULL; 949 return D3DERR_INVALIDCALL; 950 } 951 952 surface_impl = wined3d_texture_get_sub_resource_parent(wined3d_texture, 0); 953 *backbuffer = &surface_impl->IDirect3DSurface8_iface; 954 IDirect3DSurface8_AddRef(*backbuffer); 955 956 wined3d_mutex_unlock(); 957 return D3D_OK; 958 } 959 960 static HRESULT WINAPI d3d8_device_GetRasterStatus(IDirect3DDevice8 *iface, D3DRASTER_STATUS *raster_status) 961 { 962 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); 963 HRESULT hr; 964 965 TRACE("iface %p, raster_status %p.\n", iface, raster_status); 966 967 wined3d_mutex_lock(); 968 hr = wined3d_device_get_raster_status(device->wined3d_device, 0, (struct wined3d_raster_status *)raster_status); 969 wined3d_mutex_unlock(); 970 971 return hr; 972 } 973 974 static void WINAPI d3d8_device_SetGammaRamp(IDirect3DDevice8 *iface, DWORD flags, const D3DGAMMARAMP *ramp) 975 { 976 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); 977 978 TRACE("iface %p, flags %#x, ramp %p.\n", iface, flags, ramp); 979 980 /* Note: D3DGAMMARAMP is compatible with struct wined3d_gamma_ramp. */ 981 wined3d_mutex_lock(); 982 wined3d_device_set_gamma_ramp(device->wined3d_device, 0, flags, (const struct wined3d_gamma_ramp *)ramp); 983 wined3d_mutex_unlock(); 984 } 985 986 static void WINAPI d3d8_device_GetGammaRamp(IDirect3DDevice8 *iface, D3DGAMMARAMP *ramp) 987 { 988 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); 989 990 TRACE("iface %p, ramp %p.\n", iface, ramp); 991 992 /* Note: D3DGAMMARAMP is compatible with struct wined3d_gamma_ramp. */ 993 wined3d_mutex_lock(); 994 wined3d_device_get_gamma_ramp(device->wined3d_device, 0, (struct wined3d_gamma_ramp *)ramp); 995 wined3d_mutex_unlock(); 996 } 997 998 static HRESULT WINAPI d3d8_device_CreateTexture(IDirect3DDevice8 *iface, 999 UINT width, UINT height, UINT levels, DWORD usage, D3DFORMAT format, 1000 D3DPOOL pool, IDirect3DTexture8 **texture) 1001 { 1002 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); 1003 struct d3d8_texture *object; 1004 HRESULT hr; 1005 1006 TRACE("iface %p, width %u, height %u, levels %u, usage %#x, format %#x, pool %#x, texture %p.\n", 1007 iface, width, height, levels, usage, format, pool, texture); 1008 1009 if (!format) 1010 return D3DERR_INVALIDCALL; 1011 1012 *texture = NULL; 1013 if (!(object = heap_alloc_zero(sizeof(*object)))) 1014 return D3DERR_OUTOFVIDEOMEMORY; 1015 1016 hr = texture_init(object, device, width, height, levels, usage, format, pool); 1017 if (FAILED(hr)) 1018 { 1019 WARN("Failed to initialize texture, hr %#x.\n", hr); 1020 heap_free(object); 1021 return hr; 1022 } 1023 1024 TRACE("Created texture %p.\n", object); 1025 *texture = (IDirect3DTexture8 *)&object->IDirect3DBaseTexture8_iface; 1026 1027 return D3D_OK; 1028 } 1029 1030 static HRESULT WINAPI d3d8_device_CreateVolumeTexture(IDirect3DDevice8 *iface, 1031 UINT width, UINT height, UINT depth, UINT levels, DWORD usage, D3DFORMAT format, 1032 D3DPOOL pool, IDirect3DVolumeTexture8 **texture) 1033 { 1034 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); 1035 struct d3d8_texture *object; 1036 HRESULT hr; 1037 1038 TRACE("iface %p, width %u, height %u, depth %u, levels %u, usage %#x, format %#x, pool %#x, texture %p.\n", 1039 iface, width, height, depth, levels, usage, format, pool, texture); 1040 1041 if (!format) 1042 return D3DERR_INVALIDCALL; 1043 1044 *texture = NULL; 1045 if (!(object = heap_alloc_zero(sizeof(*object)))) 1046 return D3DERR_OUTOFVIDEOMEMORY; 1047 1048 hr = volumetexture_init(object, device, width, height, depth, levels, usage, format, pool); 1049 if (FAILED(hr)) 1050 { 1051 WARN("Failed to initialize volume texture, hr %#x.\n", hr); 1052 heap_free(object); 1053 return hr; 1054 } 1055 1056 TRACE("Created volume texture %p.\n", object); 1057 *texture = (IDirect3DVolumeTexture8 *)&object->IDirect3DBaseTexture8_iface; 1058 1059 return D3D_OK; 1060 } 1061 1062 static HRESULT WINAPI d3d8_device_CreateCubeTexture(IDirect3DDevice8 *iface, UINT edge_length, 1063 UINT levels, DWORD usage, D3DFORMAT format, D3DPOOL pool, IDirect3DCubeTexture8 **texture) 1064 { 1065 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); 1066 struct d3d8_texture *object; 1067 HRESULT hr; 1068 1069 TRACE("iface %p, edge_length %u, levels %u, usage %#x, format %#x, pool %#x, texture %p.\n", 1070 iface, edge_length, levels, usage, format, pool, texture); 1071 1072 if (!format) 1073 return D3DERR_INVALIDCALL; 1074 1075 *texture = NULL; 1076 if (!(object = heap_alloc_zero(sizeof(*object)))) 1077 return D3DERR_OUTOFVIDEOMEMORY; 1078 1079 hr = cubetexture_init(object, device, edge_length, levels, usage, format, pool); 1080 if (FAILED(hr)) 1081 { 1082 WARN("Failed to initialize cube texture, hr %#x.\n", hr); 1083 heap_free(object); 1084 return hr; 1085 } 1086 1087 TRACE("Created cube texture %p.\n", object); 1088 *texture = (IDirect3DCubeTexture8 *)&object->IDirect3DBaseTexture8_iface; 1089 1090 return hr; 1091 } 1092 1093 static HRESULT WINAPI d3d8_device_CreateVertexBuffer(IDirect3DDevice8 *iface, UINT size, 1094 DWORD usage, DWORD fvf, D3DPOOL pool, IDirect3DVertexBuffer8 **buffer) 1095 { 1096 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); 1097 struct d3d8_vertexbuffer *object; 1098 HRESULT hr; 1099 1100 TRACE("iface %p, size %u, usage %#x, fvf %#x, pool %#x, buffer %p.\n", 1101 iface, size, usage, fvf, pool, buffer); 1102 1103 if (!(object = heap_alloc_zero(sizeof(*object)))) 1104 return D3DERR_OUTOFVIDEOMEMORY; 1105 1106 hr = vertexbuffer_init(object, device, size, usage, fvf, pool); 1107 if (FAILED(hr)) 1108 { 1109 WARN("Failed to initialize vertex buffer, hr %#x.\n", hr); 1110 heap_free(object); 1111 return hr; 1112 } 1113 1114 TRACE("Created vertex buffer %p.\n", object); 1115 *buffer = &object->IDirect3DVertexBuffer8_iface; 1116 1117 return D3D_OK; 1118 } 1119 1120 static HRESULT WINAPI d3d8_device_CreateIndexBuffer(IDirect3DDevice8 *iface, UINT size, 1121 DWORD usage, D3DFORMAT format, D3DPOOL pool, IDirect3DIndexBuffer8 **buffer) 1122 { 1123 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); 1124 struct d3d8_indexbuffer *object; 1125 HRESULT hr; 1126 1127 TRACE("iface %p, size %u, usage %#x, format %#x, pool %#x, buffer %p.\n", 1128 iface, size, usage, format, pool, buffer); 1129 1130 if (!(object = heap_alloc_zero(sizeof(*object)))) 1131 return D3DERR_OUTOFVIDEOMEMORY; 1132 1133 hr = indexbuffer_init(object, device, size, usage, format, pool); 1134 if (FAILED(hr)) 1135 { 1136 WARN("Failed to initialize index buffer, hr %#x.\n", hr); 1137 heap_free(object); 1138 return hr; 1139 } 1140 1141 TRACE("Created index buffer %p.\n", object); 1142 *buffer = &object->IDirect3DIndexBuffer8_iface; 1143 1144 return D3D_OK; 1145 } 1146 1147 static HRESULT d3d8_device_create_surface(struct d3d8_device *device, UINT width, UINT height, 1148 D3DFORMAT format, DWORD flags, IDirect3DSurface8 **surface, UINT usage, D3DPOOL pool, 1149 D3DMULTISAMPLE_TYPE multisample_type, DWORD multisample_quality) 1150 { 1151 struct wined3d_resource_desc desc; 1152 struct d3d8_surface *surface_impl; 1153 struct wined3d_texture *texture; 1154 HRESULT hr; 1155 1156 TRACE("device %p, width %u, height %u, format %#x, flags %#x, surface %p, " 1157 "usage %#x, pool %#x, multisample_type %#x, multisample_quality %u.\n", 1158 device, width, height, format, flags, surface, 1159 usage, pool, multisample_type, multisample_quality); 1160 1161 desc.resource_type = WINED3D_RTYPE_TEXTURE_2D; 1162 desc.format = wined3dformat_from_d3dformat(format); 1163 desc.multisample_type = multisample_type; 1164 desc.multisample_quality = multisample_quality; 1165 desc.usage = usage & WINED3DUSAGE_MASK; 1166 if (pool == D3DPOOL_SCRATCH) 1167 desc.usage |= WINED3DUSAGE_SCRATCH; 1168 desc.access = wined3daccess_from_d3dpool(pool, usage) 1169 | WINED3D_RESOURCE_ACCESS_MAP_R | WINED3D_RESOURCE_ACCESS_MAP_W; 1170 desc.width = width; 1171 desc.height = height; 1172 desc.depth = 1; 1173 desc.size = 0; 1174 1175 wined3d_mutex_lock(); 1176 1177 if (FAILED(hr = wined3d_texture_create(device->wined3d_device, &desc, 1178 1, 1, flags, NULL, NULL, &d3d8_null_wined3d_parent_ops, &texture))) 1179 { 1180 wined3d_mutex_unlock(); 1181 WARN("Failed to create texture, hr %#x.\n", hr); 1182 return hr; 1183 } 1184 1185 surface_impl = wined3d_texture_get_sub_resource_parent(texture, 0); 1186 surface_impl->parent_device = &device->IDirect3DDevice8_iface; 1187 *surface = &surface_impl->IDirect3DSurface8_iface; 1188 IDirect3DSurface8_AddRef(*surface); 1189 wined3d_texture_decref(texture); 1190 1191 wined3d_mutex_unlock(); 1192 1193 return D3D_OK; 1194 } 1195 1196 static HRESULT WINAPI d3d8_device_CreateRenderTarget(IDirect3DDevice8 *iface, UINT width, 1197 UINT height, D3DFORMAT format, D3DMULTISAMPLE_TYPE multisample_type, BOOL lockable, 1198 IDirect3DSurface8 **surface) 1199 { 1200 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); 1201 DWORD flags = 0; 1202 1203 TRACE("iface %p, width %u, height %u, format %#x, multisample_type %#x, lockable %#x, surface %p.\n", 1204 iface, width, height, format, multisample_type, lockable, surface); 1205 1206 if (!format) 1207 return D3DERR_INVALIDCALL; 1208 1209 *surface = NULL; 1210 if (lockable) 1211 flags |= WINED3D_TEXTURE_CREATE_MAPPABLE; 1212 1213 return d3d8_device_create_surface(device, width, height, format, flags, surface, 1214 D3DUSAGE_RENDERTARGET, D3DPOOL_DEFAULT, multisample_type, 0); 1215 } 1216 1217 static HRESULT WINAPI d3d8_device_CreateDepthStencilSurface(IDirect3DDevice8 *iface, 1218 UINT width, UINT height, D3DFORMAT format, D3DMULTISAMPLE_TYPE multisample_type, 1219 IDirect3DSurface8 **surface) 1220 { 1221 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); 1222 1223 TRACE("iface %p, width %u, height %u, format %#x, multisample_type %#x, surface %p.\n", 1224 iface, width, height, format, multisample_type, surface); 1225 1226 if (!format) 1227 return D3DERR_INVALIDCALL; 1228 1229 *surface = NULL; 1230 1231 /* TODO: Verify that Discard is false */ 1232 return d3d8_device_create_surface(device, width, height, format, WINED3D_TEXTURE_CREATE_MAPPABLE, 1233 surface, D3DUSAGE_DEPTHSTENCIL, D3DPOOL_DEFAULT, multisample_type, 0); 1234 } 1235 1236 /* IDirect3DDevice8Impl::CreateImageSurface returns surface with pool type SYSTEMMEM */ 1237 static HRESULT WINAPI d3d8_device_CreateImageSurface(IDirect3DDevice8 *iface, UINT width, 1238 UINT height, D3DFORMAT format, IDirect3DSurface8 **surface) 1239 { 1240 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); 1241 1242 TRACE("iface %p, width %u, height %u, format %#x, surface %p.\n", 1243 iface, width, height, format, surface); 1244 1245 *surface = NULL; 1246 1247 return d3d8_device_create_surface(device, width, height, format, WINED3D_TEXTURE_CREATE_MAPPABLE, 1248 surface, 0, D3DPOOL_SYSTEMMEM, D3DMULTISAMPLE_NONE, 0); 1249 } 1250 1251 static HRESULT WINAPI d3d8_device_CopyRects(IDirect3DDevice8 *iface, 1252 IDirect3DSurface8 *src_surface, const RECT *src_rects, UINT rect_count, 1253 IDirect3DSurface8 *dst_surface, const POINT *dst_points) 1254 { 1255 struct d3d8_surface *src = unsafe_impl_from_IDirect3DSurface8(src_surface); 1256 struct d3d8_surface *dst = unsafe_impl_from_IDirect3DSurface8(dst_surface); 1257 enum wined3d_format_id src_format, dst_format; 1258 struct wined3d_sub_resource_desc wined3d_desc; 1259 UINT src_w, src_h; 1260 1261 TRACE("iface %p, src_surface %p, src_rects %p, rect_count %u, dst_surface %p, dst_points %p.\n", 1262 iface, src_surface, src_rects, rect_count, dst_surface, dst_points); 1263 1264 /* Check that the source texture is in WINED3D_POOL_SYSTEM_MEM and the 1265 * destination texture is in WINED3D_POOL_DEFAULT. */ 1266 1267 wined3d_mutex_lock(); 1268 wined3d_texture_get_sub_resource_desc(src->wined3d_texture, src->sub_resource_idx, &wined3d_desc); 1269 if (wined3d_desc.usage & WINED3DUSAGE_DEPTHSTENCIL) 1270 { 1271 WARN("Source %p is a depth stencil surface, returning D3DERR_INVALIDCALL.\n", src_surface); 1272 wined3d_mutex_unlock(); 1273 return D3DERR_INVALIDCALL; 1274 } 1275 src_format = wined3d_desc.format; 1276 src_w = wined3d_desc.width; 1277 src_h = wined3d_desc.height; 1278 1279 wined3d_texture_get_sub_resource_desc(dst->wined3d_texture, dst->sub_resource_idx, &wined3d_desc); 1280 if (wined3d_desc.usage & WINED3DUSAGE_DEPTHSTENCIL) 1281 { 1282 WARN("Destination %p is a depth stencil surface, returning D3DERR_INVALIDCALL.\n", dst_surface); 1283 wined3d_mutex_unlock(); 1284 return D3DERR_INVALIDCALL; 1285 } 1286 dst_format = wined3d_desc.format; 1287 1288 /* Check that the source and destination formats match */ 1289 if (src_format != dst_format) 1290 { 1291 WARN("Source %p format must match the destination %p format, returning D3DERR_INVALIDCALL.\n", 1292 src_surface, dst_surface); 1293 wined3d_mutex_unlock(); 1294 return D3DERR_INVALIDCALL; 1295 } 1296 1297 /* Quick if complete copy ... */ 1298 if (!rect_count && !src_rects && !dst_points) 1299 { 1300 RECT rect = {0, 0, src_w, src_h}; 1301 wined3d_texture_blt(dst->wined3d_texture, dst->sub_resource_idx, &rect, 1302 src->wined3d_texture, src->sub_resource_idx, &rect, 0, NULL, WINED3D_TEXF_POINT); 1303 } 1304 else 1305 { 1306 unsigned int i; 1307 /* Copy rect by rect */ 1308 if (src_rects && dst_points) 1309 { 1310 for (i = 0; i < rect_count; ++i) 1311 { 1312 UINT w = src_rects[i].right - src_rects[i].left; 1313 UINT h = src_rects[i].bottom - src_rects[i].top; 1314 RECT dst_rect = {dst_points[i].x, dst_points[i].y, 1315 dst_points[i].x + w, dst_points[i].y + h}; 1316 1317 wined3d_texture_blt(dst->wined3d_texture, dst->sub_resource_idx, &dst_rect, 1318 src->wined3d_texture, src->sub_resource_idx, &src_rects[i], 0, NULL, WINED3D_TEXF_POINT); 1319 } 1320 } 1321 else 1322 { 1323 for (i = 0; i < rect_count; ++i) 1324 { 1325 UINT w = src_rects[i].right - src_rects[i].left; 1326 UINT h = src_rects[i].bottom - src_rects[i].top; 1327 RECT dst_rect = {0, 0, w, h}; 1328 1329 wined3d_texture_blt(dst->wined3d_texture, dst->sub_resource_idx, &dst_rect, 1330 src->wined3d_texture, src->sub_resource_idx, &src_rects[i], 0, NULL, WINED3D_TEXF_POINT); 1331 } 1332 } 1333 } 1334 wined3d_mutex_unlock(); 1335 1336 return WINED3D_OK; 1337 } 1338 1339 static HRESULT WINAPI d3d8_device_UpdateTexture(IDirect3DDevice8 *iface, 1340 IDirect3DBaseTexture8 *src_texture, IDirect3DBaseTexture8 *dst_texture) 1341 { 1342 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); 1343 struct d3d8_texture *src_impl, *dst_impl; 1344 HRESULT hr; 1345 1346 TRACE("iface %p, src_texture %p, dst_texture %p.\n", iface, src_texture, dst_texture); 1347 1348 src_impl = unsafe_impl_from_IDirect3DBaseTexture8(src_texture); 1349 dst_impl = unsafe_impl_from_IDirect3DBaseTexture8(dst_texture); 1350 1351 wined3d_mutex_lock(); 1352 hr = wined3d_device_update_texture(device->wined3d_device, 1353 src_impl->wined3d_texture, dst_impl->wined3d_texture); 1354 wined3d_mutex_unlock(); 1355 1356 return hr; 1357 } 1358 1359 static HRESULT WINAPI d3d8_device_GetFrontBuffer(IDirect3DDevice8 *iface, IDirect3DSurface8 *dst_surface) 1360 { 1361 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); 1362 struct d3d8_surface *dst_impl = unsafe_impl_from_IDirect3DSurface8(dst_surface); 1363 HRESULT hr; 1364 1365 TRACE("iface %p, dst_surface %p.\n", iface, dst_surface); 1366 1367 if (!dst_surface) 1368 { 1369 WARN("Invalid destination surface passed.\n"); 1370 return D3DERR_INVALIDCALL; 1371 } 1372 1373 wined3d_mutex_lock(); 1374 hr = wined3d_swapchain_get_front_buffer_data(device->implicit_swapchain->wined3d_swapchain, 1375 dst_impl->wined3d_texture, dst_impl->sub_resource_idx); 1376 wined3d_mutex_unlock(); 1377 1378 return hr; 1379 } 1380 1381 static HRESULT WINAPI d3d8_device_SetRenderTarget(IDirect3DDevice8 *iface, 1382 IDirect3DSurface8 *render_target, IDirect3DSurface8 *depth_stencil) 1383 { 1384 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); 1385 struct d3d8_surface *rt_impl = unsafe_impl_from_IDirect3DSurface8(render_target); 1386 struct d3d8_surface *ds_impl = unsafe_impl_from_IDirect3DSurface8(depth_stencil); 1387 struct wined3d_rendertarget_view *original_dsv, *rtv; 1388 HRESULT hr = D3D_OK; 1389 1390 TRACE("iface %p, render_target %p, depth_stencil %p.\n", iface, render_target, depth_stencil); 1391 1392 if (rt_impl && d3d8_surface_get_device(rt_impl) != device) 1393 { 1394 WARN("Render target surface does not match device.\n"); 1395 return D3DERR_INVALIDCALL; 1396 } 1397 1398 wined3d_mutex_lock(); 1399 1400 if (ds_impl) 1401 { 1402 struct wined3d_sub_resource_desc ds_desc, rt_desc; 1403 struct wined3d_rendertarget_view *original_rtv; 1404 struct d3d8_surface *original_surface; 1405 1406 /* If no render target is passed in check the size against the current RT */ 1407 if (!render_target) 1408 { 1409 if (!(original_rtv = wined3d_device_get_rendertarget_view(device->wined3d_device, 0))) 1410 { 1411 wined3d_mutex_unlock(); 1412 return D3DERR_NOTFOUND; 1413 } 1414 original_surface = wined3d_rendertarget_view_get_sub_resource_parent(original_rtv); 1415 wined3d_texture_get_sub_resource_desc(original_surface->wined3d_texture, 1416 original_surface->sub_resource_idx, &rt_desc); 1417 } 1418 else 1419 wined3d_texture_get_sub_resource_desc(rt_impl->wined3d_texture, 1420 rt_impl->sub_resource_idx, &rt_desc); 1421 1422 wined3d_texture_get_sub_resource_desc(ds_impl->wined3d_texture, ds_impl->sub_resource_idx, &ds_desc); 1423 1424 if (ds_desc.width < rt_desc.width || ds_desc.height < rt_desc.height) 1425 { 1426 WARN("Depth stencil is smaller than the render target, returning D3DERR_INVALIDCALL\n"); 1427 wined3d_mutex_unlock(); 1428 return D3DERR_INVALIDCALL; 1429 } 1430 if (ds_desc.multisample_type != rt_desc.multisample_type 1431 || ds_desc.multisample_quality != rt_desc.multisample_quality) 1432 { 1433 WARN("Multisample settings do not match, returning D3DERR_INVALIDCALL\n"); 1434 wined3d_mutex_unlock(); 1435 return D3DERR_INVALIDCALL; 1436 } 1437 } 1438 1439 original_dsv = wined3d_device_get_depth_stencil_view(device->wined3d_device); 1440 rtv = ds_impl ? d3d8_surface_acquire_rendertarget_view(ds_impl) : NULL; 1441 wined3d_device_set_depth_stencil_view(device->wined3d_device, rtv); 1442 d3d8_surface_release_rendertarget_view(ds_impl, rtv); 1443 rtv = render_target ? d3d8_surface_acquire_rendertarget_view(rt_impl) : NULL; 1444 if (render_target && FAILED(hr = wined3d_device_set_rendertarget_view(device->wined3d_device, 0, rtv, TRUE))) 1445 wined3d_device_set_depth_stencil_view(device->wined3d_device, original_dsv); 1446 d3d8_surface_release_rendertarget_view(rt_impl, rtv); 1447 1448 wined3d_mutex_unlock(); 1449 1450 return hr; 1451 } 1452 1453 static HRESULT WINAPI d3d8_device_GetRenderTarget(IDirect3DDevice8 *iface, IDirect3DSurface8 **render_target) 1454 { 1455 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); 1456 struct wined3d_rendertarget_view *wined3d_rtv; 1457 struct d3d8_surface *surface_impl; 1458 HRESULT hr; 1459 1460 TRACE("iface %p, render_target %p.\n", iface, render_target); 1461 1462 if (!render_target) 1463 return D3DERR_INVALIDCALL; 1464 1465 wined3d_mutex_lock(); 1466 if ((wined3d_rtv = wined3d_device_get_rendertarget_view(device->wined3d_device, 0))) 1467 { 1468 /* We want the sub resource parent here, since the view itself may be 1469 * internal to wined3d and may not have a parent. */ 1470 surface_impl = wined3d_rendertarget_view_get_sub_resource_parent(wined3d_rtv); 1471 *render_target = &surface_impl->IDirect3DSurface8_iface; 1472 IDirect3DSurface8_AddRef(*render_target); 1473 hr = D3D_OK; 1474 } 1475 else 1476 { 1477 ERR("Failed to get wined3d render target.\n"); 1478 *render_target = NULL; 1479 hr = D3DERR_NOTFOUND; 1480 } 1481 wined3d_mutex_unlock(); 1482 1483 return hr; 1484 } 1485 1486 static HRESULT WINAPI d3d8_device_GetDepthStencilSurface(IDirect3DDevice8 *iface, IDirect3DSurface8 **depth_stencil) 1487 { 1488 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); 1489 struct wined3d_rendertarget_view *wined3d_dsv; 1490 struct d3d8_surface *surface_impl; 1491 HRESULT hr = D3D_OK; 1492 1493 TRACE("iface %p, depth_stencil %p.\n", iface, depth_stencil); 1494 1495 if (!depth_stencil) 1496 return D3DERR_INVALIDCALL; 1497 1498 wined3d_mutex_lock(); 1499 if ((wined3d_dsv = wined3d_device_get_depth_stencil_view(device->wined3d_device))) 1500 { 1501 /* We want the sub resource parent here, since the view itself may be 1502 * internal to wined3d and may not have a parent. */ 1503 surface_impl = wined3d_rendertarget_view_get_sub_resource_parent(wined3d_dsv); 1504 *depth_stencil = &surface_impl->IDirect3DSurface8_iface; 1505 IDirect3DSurface8_AddRef(*depth_stencil); 1506 } 1507 else 1508 { 1509 hr = D3DERR_NOTFOUND; 1510 *depth_stencil = NULL; 1511 } 1512 wined3d_mutex_unlock(); 1513 1514 return hr; 1515 } 1516 1517 static HRESULT WINAPI d3d8_device_BeginScene(IDirect3DDevice8 *iface) 1518 { 1519 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); 1520 HRESULT hr; 1521 1522 TRACE("iface %p.\n", iface); 1523 1524 wined3d_mutex_lock(); 1525 hr = wined3d_device_begin_scene(device->wined3d_device); 1526 wined3d_mutex_unlock(); 1527 1528 return hr; 1529 } 1530 1531 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d8_device_EndScene(IDirect3DDevice8 *iface) 1532 { 1533 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); 1534 HRESULT hr; 1535 1536 TRACE("iface %p.\n", iface); 1537 1538 wined3d_mutex_lock(); 1539 hr = wined3d_device_end_scene(device->wined3d_device); 1540 wined3d_mutex_unlock(); 1541 1542 return hr; 1543 } 1544 1545 static HRESULT WINAPI d3d8_device_Clear(IDirect3DDevice8 *iface, DWORD rect_count, 1546 const D3DRECT *rects, DWORD flags, D3DCOLOR color, float z, DWORD stencil) 1547 { 1548 const struct wined3d_color c = 1549 { 1550 ((color >> 16) & 0xff) / 255.0f, 1551 ((color >> 8) & 0xff) / 255.0f, 1552 (color & 0xff) / 255.0f, 1553 ((color >> 24) & 0xff) / 255.0f, 1554 }; 1555 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); 1556 HRESULT hr; 1557 1558 TRACE("iface %p, rect_count %u, rects %p, flags %#x, color 0x%08x, z %.8e, stencil %u.\n", 1559 iface, rect_count, rects, flags, color, z, stencil); 1560 1561 if (rect_count && !rects) 1562 { 1563 WARN("count %u with NULL rects.\n", rect_count); 1564 rect_count = 0; 1565 } 1566 1567 wined3d_mutex_lock(); 1568 hr = wined3d_device_clear(device->wined3d_device, rect_count, (const RECT *)rects, flags, &c, z, stencil); 1569 wined3d_mutex_unlock(); 1570 1571 return hr; 1572 } 1573 1574 static HRESULT WINAPI d3d8_device_SetTransform(IDirect3DDevice8 *iface, 1575 D3DTRANSFORMSTATETYPE state, const D3DMATRIX *matrix) 1576 { 1577 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); 1578 1579 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix); 1580 1581 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */ 1582 wined3d_mutex_lock(); 1583 wined3d_device_set_transform(device->wined3d_device, state, (const struct wined3d_matrix *)matrix); 1584 wined3d_mutex_unlock(); 1585 1586 return D3D_OK; 1587 } 1588 1589 static HRESULT WINAPI d3d8_device_GetTransform(IDirect3DDevice8 *iface, 1590 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix) 1591 { 1592 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); 1593 1594 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix); 1595 1596 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */ 1597 wined3d_mutex_lock(); 1598 wined3d_device_get_transform(device->wined3d_device, state, (struct wined3d_matrix *)matrix); 1599 wined3d_mutex_unlock(); 1600 1601 return D3D_OK; 1602 } 1603 1604 static HRESULT WINAPI d3d8_device_MultiplyTransform(IDirect3DDevice8 *iface, 1605 D3DTRANSFORMSTATETYPE state, const D3DMATRIX *matrix) 1606 { 1607 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); 1608 1609 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix); 1610 1611 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */ 1612 wined3d_mutex_lock(); 1613 wined3d_device_multiply_transform(device->wined3d_device, state, (const struct wined3d_matrix *)matrix); 1614 wined3d_mutex_unlock(); 1615 1616 return D3D_OK; 1617 } 1618 1619 static HRESULT WINAPI d3d8_device_SetViewport(IDirect3DDevice8 *iface, const D3DVIEWPORT8 *viewport) 1620 { 1621 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); 1622 struct wined3d_sub_resource_desc rt_desc; 1623 struct wined3d_rendertarget_view *rtv; 1624 struct d3d8_surface *surface; 1625 struct wined3d_viewport vp; 1626 1627 TRACE("iface %p, viewport %p.\n", iface, viewport); 1628 1629 wined3d_mutex_lock(); 1630 if (!(rtv = wined3d_device_get_rendertarget_view(device->wined3d_device, 0))) 1631 { 1632 wined3d_mutex_unlock(); 1633 return D3DERR_NOTFOUND; 1634 } 1635 surface = wined3d_rendertarget_view_get_sub_resource_parent(rtv); 1636 wined3d_texture_get_sub_resource_desc(surface->wined3d_texture, surface->sub_resource_idx, &rt_desc); 1637 1638 if (viewport->X > rt_desc.width || viewport->Width > rt_desc.width - viewport->X 1639 || viewport->Y > rt_desc.height || viewport->Height > rt_desc.height - viewport->Y) 1640 { 1641 WARN("Invalid viewport, returning D3DERR_INVALIDCALL.\n"); 1642 wined3d_mutex_unlock(); 1643 return D3DERR_INVALIDCALL; 1644 } 1645 1646 vp.x = viewport->X; 1647 vp.y = viewport->Y; 1648 vp.width = viewport->Width; 1649 vp.height = viewport->Height; 1650 vp.min_z = viewport->MinZ; 1651 vp.max_z = viewport->MaxZ; 1652 1653 wined3d_device_set_viewports(device->wined3d_device, 1, &vp); 1654 wined3d_mutex_unlock(); 1655 1656 return D3D_OK; 1657 } 1658 1659 static HRESULT WINAPI d3d8_device_GetViewport(IDirect3DDevice8 *iface, D3DVIEWPORT8 *viewport) 1660 { 1661 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); 1662 struct wined3d_viewport wined3d_viewport; 1663 1664 TRACE("iface %p, viewport %p.\n", iface, viewport); 1665 1666 wined3d_mutex_lock(); 1667 wined3d_device_get_viewports(device->wined3d_device, NULL, &wined3d_viewport); 1668 wined3d_mutex_unlock(); 1669 1670 viewport->X = wined3d_viewport.x; 1671 viewport->Y = wined3d_viewport.y; 1672 viewport->Width = wined3d_viewport.width; 1673 viewport->Height = wined3d_viewport.height; 1674 viewport->MinZ = wined3d_viewport.min_z; 1675 viewport->MaxZ = wined3d_viewport.max_z; 1676 1677 return D3D_OK; 1678 } 1679 1680 static HRESULT WINAPI d3d8_device_SetMaterial(IDirect3DDevice8 *iface, const D3DMATERIAL8 *material) 1681 { 1682 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); 1683 1684 TRACE("iface %p, material %p.\n", iface, material); 1685 1686 /* Note: D3DMATERIAL8 is compatible with struct wined3d_material. */ 1687 wined3d_mutex_lock(); 1688 wined3d_device_set_material(device->wined3d_device, (const struct wined3d_material *)material); 1689 wined3d_mutex_unlock(); 1690 1691 return D3D_OK; 1692 } 1693 1694 static HRESULT WINAPI d3d8_device_GetMaterial(IDirect3DDevice8 *iface, D3DMATERIAL8 *material) 1695 { 1696 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); 1697 1698 TRACE("iface %p, material %p.\n", iface, material); 1699 1700 /* Note: D3DMATERIAL8 is compatible with struct wined3d_material. */ 1701 wined3d_mutex_lock(); 1702 wined3d_device_get_material(device->wined3d_device, (struct wined3d_material *)material); 1703 wined3d_mutex_unlock(); 1704 1705 return D3D_OK; 1706 } 1707 1708 static HRESULT WINAPI d3d8_device_SetLight(IDirect3DDevice8 *iface, DWORD index, const D3DLIGHT8 *light) 1709 { 1710 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); 1711 HRESULT hr; 1712 1713 TRACE("iface %p, index %u, light %p.\n", iface, index, light); 1714 1715 /* Note: D3DLIGHT8 is compatible with struct wined3d_light. */ 1716 wined3d_mutex_lock(); 1717 hr = wined3d_device_set_light(device->wined3d_device, index, (const struct wined3d_light *)light); 1718 wined3d_mutex_unlock(); 1719 1720 return hr; 1721 } 1722 1723 static HRESULT WINAPI d3d8_device_GetLight(IDirect3DDevice8 *iface, DWORD index, D3DLIGHT8 *light) 1724 { 1725 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); 1726 HRESULT hr; 1727 1728 TRACE("iface %p, index %u, light %p.\n", iface, index, light); 1729 1730 /* Note: D3DLIGHT8 is compatible with struct wined3d_light. */ 1731 wined3d_mutex_lock(); 1732 hr = wined3d_device_get_light(device->wined3d_device, index, (struct wined3d_light *)light); 1733 wined3d_mutex_unlock(); 1734 1735 return hr; 1736 } 1737 1738 static HRESULT WINAPI d3d8_device_LightEnable(IDirect3DDevice8 *iface, DWORD index, BOOL enable) 1739 { 1740 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); 1741 HRESULT hr; 1742 1743 TRACE("iface %p, index %u, enable %#x.\n", iface, index, enable); 1744 1745 wined3d_mutex_lock(); 1746 hr = wined3d_device_set_light_enable(device->wined3d_device, index, enable); 1747 wined3d_mutex_unlock(); 1748 1749 return hr; 1750 } 1751 1752 static HRESULT WINAPI d3d8_device_GetLightEnable(IDirect3DDevice8 *iface, DWORD index, BOOL *enable) 1753 { 1754 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); 1755 HRESULT hr; 1756 1757 TRACE("iface %p, index %u, enable %p.\n", iface, index, enable); 1758 1759 wined3d_mutex_lock(); 1760 hr = wined3d_device_get_light_enable(device->wined3d_device, index, enable); 1761 wined3d_mutex_unlock(); 1762 1763 return hr; 1764 } 1765 1766 static HRESULT WINAPI d3d8_device_SetClipPlane(IDirect3DDevice8 *iface, DWORD index, const float *plane) 1767 { 1768 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); 1769 HRESULT hr; 1770 1771 TRACE("iface %p, index %u, plane %p.\n", iface, index, plane); 1772 1773 wined3d_mutex_lock(); 1774 hr = wined3d_device_set_clip_plane(device->wined3d_device, index, (const struct wined3d_vec4 *)plane); 1775 wined3d_mutex_unlock(); 1776 1777 return hr; 1778 } 1779 1780 static HRESULT WINAPI d3d8_device_GetClipPlane(IDirect3DDevice8 *iface, DWORD index, float *plane) 1781 { 1782 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); 1783 HRESULT hr; 1784 1785 TRACE("iface %p, index %u, plane %p.\n", iface, index, plane); 1786 1787 wined3d_mutex_lock(); 1788 hr = wined3d_device_get_clip_plane(device->wined3d_device, index, (struct wined3d_vec4 *)plane); 1789 wined3d_mutex_unlock(); 1790 1791 return hr; 1792 } 1793 1794 static HRESULT WINAPI d3d8_device_SetRenderState(IDirect3DDevice8 *iface, 1795 D3DRENDERSTATETYPE state, DWORD value) 1796 { 1797 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); 1798 1799 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value); 1800 1801 wined3d_mutex_lock(); 1802 switch (state) 1803 { 1804 case D3DRS_ZBIAS: 1805 wined3d_device_set_render_state(device->wined3d_device, WINED3D_RS_DEPTHBIAS, value); 1806 break; 1807 1808 default: 1809 wined3d_device_set_render_state(device->wined3d_device, state, value); 1810 } 1811 wined3d_mutex_unlock(); 1812 1813 return D3D_OK; 1814 } 1815 1816 static HRESULT WINAPI d3d8_device_GetRenderState(IDirect3DDevice8 *iface, 1817 D3DRENDERSTATETYPE state, DWORD *value) 1818 { 1819 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); 1820 1821 TRACE("iface %p, state %#x, value %p.\n", iface, state, value); 1822 1823 wined3d_mutex_lock(); 1824 switch (state) 1825 { 1826 case D3DRS_ZBIAS: 1827 *value = wined3d_device_get_render_state(device->wined3d_device, WINED3D_RS_DEPTHBIAS); 1828 break; 1829 1830 default: 1831 *value = wined3d_device_get_render_state(device->wined3d_device, state); 1832 } 1833 wined3d_mutex_unlock(); 1834 1835 return D3D_OK; 1836 } 1837 1838 static HRESULT WINAPI d3d8_device_BeginStateBlock(IDirect3DDevice8 *iface) 1839 { 1840 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); 1841 HRESULT hr; 1842 1843 TRACE("iface %p.\n", iface); 1844 1845 wined3d_mutex_lock(); 1846 hr = wined3d_device_begin_stateblock(device->wined3d_device); 1847 wined3d_mutex_unlock(); 1848 1849 return hr; 1850 } 1851 1852 static HRESULT WINAPI d3d8_device_EndStateBlock(IDirect3DDevice8 *iface, DWORD *token) 1853 { 1854 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); 1855 struct wined3d_stateblock *stateblock; 1856 HRESULT hr; 1857 1858 TRACE("iface %p, token %p.\n", iface, token); 1859 1860 /* Tell wineD3D to endstateblock before anything else (in case we run out 1861 * of memory later and cause locking problems) 1862 */ 1863 wined3d_mutex_lock(); 1864 hr = wined3d_device_end_stateblock(device->wined3d_device, &stateblock); 1865 if (FAILED(hr)) 1866 { 1867 WARN("Failed to end the state block, %#x.\n", hr); 1868 wined3d_mutex_unlock(); 1869 return hr; 1870 } 1871 1872 *token = d3d8_allocate_handle(&device->handle_table, stateblock, D3D8_HANDLE_SB); 1873 wined3d_mutex_unlock(); 1874 1875 if (*token == D3D8_INVALID_HANDLE) 1876 { 1877 ERR("Failed to create a handle\n"); 1878 wined3d_mutex_lock(); 1879 wined3d_stateblock_decref(stateblock); 1880 wined3d_mutex_unlock(); 1881 return E_FAIL; 1882 } 1883 ++*token; 1884 1885 TRACE("Returning %#x (%p).\n", *token, stateblock); 1886 1887 return hr; 1888 } 1889 1890 static HRESULT WINAPI d3d8_device_ApplyStateBlock(IDirect3DDevice8 *iface, DWORD token) 1891 { 1892 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); 1893 struct wined3d_stateblock *stateblock; 1894 1895 TRACE("iface %p, token %#x.\n", iface, token); 1896 1897 if (!token) 1898 return D3D_OK; 1899 1900 wined3d_mutex_lock(); 1901 stateblock = d3d8_get_object(&device->handle_table, token - 1, D3D8_HANDLE_SB); 1902 if (!stateblock) 1903 { 1904 WARN("Invalid handle (%#x) passed.\n", token); 1905 wined3d_mutex_unlock(); 1906 return D3DERR_INVALIDCALL; 1907 } 1908 wined3d_stateblock_apply(stateblock); 1909 wined3d_mutex_unlock(); 1910 1911 return D3D_OK; 1912 } 1913 1914 static HRESULT WINAPI d3d8_device_CaptureStateBlock(IDirect3DDevice8 *iface, DWORD token) 1915 { 1916 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); 1917 struct wined3d_stateblock *stateblock; 1918 1919 TRACE("iface %p, token %#x.\n", iface, token); 1920 1921 wined3d_mutex_lock(); 1922 stateblock = d3d8_get_object(&device->handle_table, token - 1, D3D8_HANDLE_SB); 1923 if (!stateblock) 1924 { 1925 WARN("Invalid handle (%#x) passed.\n", token); 1926 wined3d_mutex_unlock(); 1927 return D3DERR_INVALIDCALL; 1928 } 1929 wined3d_stateblock_capture(stateblock); 1930 wined3d_mutex_unlock(); 1931 1932 return D3D_OK; 1933 } 1934 1935 static HRESULT WINAPI d3d8_device_DeleteStateBlock(IDirect3DDevice8 *iface, DWORD token) 1936 { 1937 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); 1938 struct wined3d_stateblock *stateblock; 1939 1940 TRACE("iface %p, token %#x.\n", iface, token); 1941 1942 wined3d_mutex_lock(); 1943 stateblock = d3d8_free_handle(&device->handle_table, token - 1, D3D8_HANDLE_SB); 1944 1945 if (!stateblock) 1946 { 1947 WARN("Invalid handle (%#x) passed.\n", token); 1948 wined3d_mutex_unlock(); 1949 return D3DERR_INVALIDCALL; 1950 } 1951 1952 if (wined3d_stateblock_decref(stateblock)) 1953 { 1954 ERR("Stateblock %p has references left, this shouldn't happen.\n", stateblock); 1955 } 1956 wined3d_mutex_unlock(); 1957 1958 return D3D_OK; 1959 } 1960 1961 static HRESULT WINAPI d3d8_device_CreateStateBlock(IDirect3DDevice8 *iface, 1962 D3DSTATEBLOCKTYPE type, DWORD *handle) 1963 { 1964 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); 1965 struct wined3d_stateblock *stateblock; 1966 HRESULT hr; 1967 1968 TRACE("iface %p, type %#x, handle %p.\n", iface, type, handle); 1969 1970 if (type != D3DSBT_ALL 1971 && type != D3DSBT_PIXELSTATE 1972 && type != D3DSBT_VERTEXSTATE) 1973 { 1974 WARN("Unexpected stateblock type, returning D3DERR_INVALIDCALL\n"); 1975 return D3DERR_INVALIDCALL; 1976 } 1977 1978 wined3d_mutex_lock(); 1979 hr = wined3d_stateblock_create(device->wined3d_device, (enum wined3d_stateblock_type)type, &stateblock); 1980 if (FAILED(hr)) 1981 { 1982 wined3d_mutex_unlock(); 1983 ERR("Failed to create the state block, hr %#x\n", hr); 1984 return hr; 1985 } 1986 1987 *handle = d3d8_allocate_handle(&device->handle_table, stateblock, D3D8_HANDLE_SB); 1988 wined3d_mutex_unlock(); 1989 1990 if (*handle == D3D8_INVALID_HANDLE) 1991 { 1992 ERR("Failed to allocate a handle.\n"); 1993 wined3d_mutex_lock(); 1994 wined3d_stateblock_decref(stateblock); 1995 wined3d_mutex_unlock(); 1996 return E_FAIL; 1997 } 1998 ++*handle; 1999 2000 TRACE("Returning %#x (%p).\n", *handle, stateblock); 2001 2002 return hr; 2003 } 2004 2005 static HRESULT WINAPI d3d8_device_SetClipStatus(IDirect3DDevice8 *iface, const D3DCLIPSTATUS8 *clip_status) 2006 { 2007 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); 2008 HRESULT hr; 2009 2010 TRACE("iface %p, clip_status %p.\n", iface, clip_status); 2011 /* FIXME: Verify that D3DCLIPSTATUS8 ~= struct wined3d_clip_status. */ 2012 2013 wined3d_mutex_lock(); 2014 hr = wined3d_device_set_clip_status(device->wined3d_device, (const struct wined3d_clip_status *)clip_status); 2015 wined3d_mutex_unlock(); 2016 2017 return hr; 2018 } 2019 2020 static HRESULT WINAPI d3d8_device_GetClipStatus(IDirect3DDevice8 *iface, D3DCLIPSTATUS8 *clip_status) 2021 { 2022 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); 2023 HRESULT hr; 2024 2025 TRACE("iface %p, clip_status %p.\n", iface, clip_status); 2026 2027 wined3d_mutex_lock(); 2028 hr = wined3d_device_get_clip_status(device->wined3d_device, (struct wined3d_clip_status *)clip_status); 2029 wined3d_mutex_unlock(); 2030 2031 return hr; 2032 } 2033 2034 static HRESULT WINAPI d3d8_device_GetTexture(IDirect3DDevice8 *iface, DWORD stage, IDirect3DBaseTexture8 **texture) 2035 { 2036 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); 2037 struct wined3d_texture *wined3d_texture; 2038 struct d3d8_texture *texture_impl; 2039 2040 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture); 2041 2042 if (!texture) 2043 return D3DERR_INVALIDCALL; 2044 2045 wined3d_mutex_lock(); 2046 if ((wined3d_texture = wined3d_device_get_texture(device->wined3d_device, stage))) 2047 { 2048 texture_impl = wined3d_texture_get_parent(wined3d_texture); 2049 *texture = &texture_impl->IDirect3DBaseTexture8_iface; 2050 IDirect3DBaseTexture8_AddRef(*texture); 2051 } 2052 else 2053 { 2054 *texture = NULL; 2055 } 2056 wined3d_mutex_unlock(); 2057 2058 return D3D_OK; 2059 } 2060 2061 static HRESULT WINAPI d3d8_device_SetTexture(IDirect3DDevice8 *iface, DWORD stage, IDirect3DBaseTexture8 *texture) 2062 { 2063 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); 2064 struct d3d8_texture *texture_impl; 2065 HRESULT hr; 2066 2067 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture); 2068 2069 texture_impl = unsafe_impl_from_IDirect3DBaseTexture8(texture); 2070 2071 wined3d_mutex_lock(); 2072 hr = wined3d_device_set_texture(device->wined3d_device, stage, 2073 texture_impl ? texture_impl->wined3d_texture : NULL); 2074 wined3d_mutex_unlock(); 2075 2076 return hr; 2077 } 2078 2079 static const struct tss_lookup 2080 { 2081 BOOL sampler_state; 2082 union 2083 { 2084 enum wined3d_texture_stage_state texture_state; 2085 enum wined3d_sampler_state sampler_state; 2086 } u; 2087 } 2088 tss_lookup[] = 2089 { 2090 {FALSE, {WINED3D_TSS_INVALID}}, /* 0, unused */ 2091 {FALSE, {WINED3D_TSS_COLOR_OP}}, /* 1, D3DTSS_COLOROP */ 2092 {FALSE, {WINED3D_TSS_COLOR_ARG1}}, /* 2, D3DTSS_COLORARG1 */ 2093 {FALSE, {WINED3D_TSS_COLOR_ARG2}}, /* 3, D3DTSS_COLORARG2 */ 2094 {FALSE, {WINED3D_TSS_ALPHA_OP}}, /* 4, D3DTSS_ALPHAOP */ 2095 {FALSE, {WINED3D_TSS_ALPHA_ARG1}}, /* 5, D3DTSS_ALPHAARG1 */ 2096 {FALSE, {WINED3D_TSS_ALPHA_ARG2}}, /* 6, D3DTSS_ALPHAARG2 */ 2097 {FALSE, {WINED3D_TSS_BUMPENV_MAT00}}, /* 7, D3DTSS_BUMPENVMAT00 */ 2098 {FALSE, {WINED3D_TSS_BUMPENV_MAT01}}, /* 8, D3DTSS_BUMPENVMAT01 */ 2099 {FALSE, {WINED3D_TSS_BUMPENV_MAT10}}, /* 9, D3DTSS_BUMPENVMAT10 */ 2100 {FALSE, {WINED3D_TSS_BUMPENV_MAT11}}, /* 10, D3DTSS_BUMPENVMAT11 */ 2101 {FALSE, {WINED3D_TSS_TEXCOORD_INDEX}}, /* 11, D3DTSS_TEXCOORDINDEX */ 2102 {FALSE, {WINED3D_TSS_INVALID}}, /* 12, unused */ 2103 {TRUE, {WINED3D_SAMP_ADDRESS_U}}, /* 13, D3DTSS_ADDRESSU */ 2104 {TRUE, {WINED3D_SAMP_ADDRESS_V}}, /* 14, D3DTSS_ADDRESSV */ 2105 {TRUE, {WINED3D_SAMP_BORDER_COLOR}}, /* 15, D3DTSS_BORDERCOLOR */ 2106 {TRUE, {WINED3D_SAMP_MAG_FILTER}}, /* 16, D3DTSS_MAGFILTER */ 2107 {TRUE, {WINED3D_SAMP_MIN_FILTER}}, /* 17, D3DTSS_MINFILTER */ 2108 {TRUE, {WINED3D_SAMP_MIP_FILTER}}, /* 18, D3DTSS_MIPFILTER */ 2109 {TRUE, {WINED3D_SAMP_MIPMAP_LOD_BIAS}}, /* 19, D3DTSS_MIPMAPLODBIAS */ 2110 {TRUE, {WINED3D_SAMP_MAX_MIP_LEVEL}}, /* 20, D3DTSS_MAXMIPLEVEL */ 2111 {TRUE, {WINED3D_SAMP_MAX_ANISOTROPY}}, /* 21, D3DTSS_MAXANISOTROPY */ 2112 {FALSE, {WINED3D_TSS_BUMPENV_LSCALE}}, /* 22, D3DTSS_BUMPENVLSCALE */ 2113 {FALSE, {WINED3D_TSS_BUMPENV_LOFFSET}}, /* 23, D3DTSS_BUMPENVLOFFSET */ 2114 {FALSE, {WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS}}, /* 24, D3DTSS_TEXTURETRANSFORMFLAGS */ 2115 {TRUE, {WINED3D_SAMP_ADDRESS_W}}, /* 25, D3DTSS_ADDRESSW */ 2116 {FALSE, {WINED3D_TSS_COLOR_ARG0}}, /* 26, D3DTSS_COLORARG0 */ 2117 {FALSE, {WINED3D_TSS_ALPHA_ARG0}}, /* 27, D3DTSS_ALPHAARG0 */ 2118 {FALSE, {WINED3D_TSS_RESULT_ARG}}, /* 28, D3DTSS_RESULTARG */ 2119 }; 2120 2121 static HRESULT WINAPI d3d8_device_GetTextureStageState(IDirect3DDevice8 *iface, 2122 DWORD stage, D3DTEXTURESTAGESTATETYPE Type, DWORD *value) 2123 { 2124 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); 2125 const struct tss_lookup *l; 2126 2127 TRACE("iface %p, stage %u, state %#x, value %p.\n", iface, stage, Type, value); 2128 2129 if (Type >= sizeof(tss_lookup) / sizeof(*tss_lookup)) 2130 { 2131 WARN("Invalid Type %#x passed.\n", Type); 2132 return D3D_OK; 2133 } 2134 2135 l = &tss_lookup[Type]; 2136 2137 wined3d_mutex_lock(); 2138 if (l->sampler_state) 2139 *value = wined3d_device_get_sampler_state(device->wined3d_device, stage, l->u.sampler_state); 2140 else 2141 *value = wined3d_device_get_texture_stage_state(device->wined3d_device, stage, l->u.texture_state); 2142 wined3d_mutex_unlock(); 2143 2144 return D3D_OK; 2145 } 2146 2147 static HRESULT WINAPI d3d8_device_SetTextureStageState(IDirect3DDevice8 *iface, 2148 DWORD stage, D3DTEXTURESTAGESTATETYPE type, DWORD value) 2149 { 2150 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); 2151 const struct tss_lookup *l; 2152 2153 TRACE("iface %p, stage %u, state %#x, value %#x.\n", iface, stage, type, value); 2154 2155 if (type >= sizeof(tss_lookup) / sizeof(*tss_lookup)) 2156 { 2157 WARN("Invalid type %#x passed.\n", type); 2158 return D3D_OK; 2159 } 2160 2161 l = &tss_lookup[type]; 2162 2163 wined3d_mutex_lock(); 2164 if (l->sampler_state) 2165 wined3d_device_set_sampler_state(device->wined3d_device, stage, l->u.sampler_state, value); 2166 else 2167 wined3d_device_set_texture_stage_state(device->wined3d_device, stage, l->u.texture_state, value); 2168 wined3d_mutex_unlock(); 2169 2170 return D3D_OK; 2171 } 2172 2173 static HRESULT WINAPI d3d8_device_ValidateDevice(IDirect3DDevice8 *iface, DWORD *pass_count) 2174 { 2175 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); 2176 HRESULT hr; 2177 2178 TRACE("iface %p, pass_count %p.\n", iface, pass_count); 2179 2180 wined3d_mutex_lock(); 2181 hr = wined3d_device_validate_device(device->wined3d_device, pass_count); 2182 wined3d_mutex_unlock(); 2183 2184 return hr; 2185 } 2186 2187 static HRESULT WINAPI d3d8_device_GetInfo(IDirect3DDevice8 *iface, 2188 DWORD info_id, void *info, DWORD info_size) 2189 { 2190 TRACE("iface %p, info_id %#x, info %p, info_size %u.\n", iface, info_id, info, info_size); 2191 2192 if (info_id < 4) 2193 return E_FAIL; 2194 return S_FALSE; 2195 } 2196 2197 static HRESULT WINAPI d3d8_device_SetPaletteEntries(IDirect3DDevice8 *iface, 2198 UINT palette_idx, const PALETTEENTRY *entries) 2199 { 2200 WARN("iface %p, palette_idx %u, entries %p unimplemented\n", iface, palette_idx, entries); 2201 2202 /* GPUs stopped supporting palettized textures with the Shader Model 1 generation. Wined3d 2203 * does not have a d3d8/9-style palette API */ 2204 2205 return D3D_OK; 2206 } 2207 2208 static HRESULT WINAPI d3d8_device_GetPaletteEntries(IDirect3DDevice8 *iface, 2209 UINT palette_idx, PALETTEENTRY *entries) 2210 { 2211 FIXME("iface %p, palette_idx %u, entries %p unimplemented.\n", iface, palette_idx, entries); 2212 2213 return D3DERR_INVALIDCALL; 2214 } 2215 2216 static HRESULT WINAPI d3d8_device_SetCurrentTexturePalette(IDirect3DDevice8 *iface, UINT palette_idx) 2217 { 2218 WARN("iface %p, palette_idx %u unimplemented.\n", iface, palette_idx); 2219 2220 return D3D_OK; 2221 } 2222 2223 static HRESULT WINAPI d3d8_device_GetCurrentTexturePalette(IDirect3DDevice8 *iface, UINT *palette_idx) 2224 { 2225 FIXME("iface %p, palette_idx %p unimplemented.\n", iface, palette_idx); 2226 2227 return D3DERR_INVALIDCALL; 2228 } 2229 2230 static HRESULT WINAPI d3d8_device_DrawPrimitive(IDirect3DDevice8 *iface, 2231 D3DPRIMITIVETYPE primitive_type, UINT start_vertex, UINT primitive_count) 2232 { 2233 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); 2234 HRESULT hr; 2235 2236 TRACE("iface %p, primitive_type %#x, start_vertex %u, primitive_count %u.\n", 2237 iface, primitive_type, start_vertex, primitive_count); 2238 2239 wined3d_mutex_lock(); 2240 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type, 0); 2241 hr = wined3d_device_draw_primitive(device->wined3d_device, start_vertex, 2242 vertex_count_from_primitive_count(primitive_type, primitive_count)); 2243 wined3d_mutex_unlock(); 2244 2245 return hr; 2246 } 2247 2248 static HRESULT WINAPI d3d8_device_DrawIndexedPrimitive(IDirect3DDevice8 *iface, 2249 D3DPRIMITIVETYPE primitive_type, UINT min_vertex_idx, UINT vertex_count, 2250 UINT start_idx, UINT primitive_count) 2251 { 2252 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); 2253 HRESULT hr; 2254 2255 TRACE("iface %p, primitive_type %#x, min_vertex_idx %u, vertex_count %u, start_idx %u, primitive_count %u.\n", 2256 iface, primitive_type, min_vertex_idx, vertex_count, start_idx, primitive_count); 2257 2258 wined3d_mutex_lock(); 2259 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type, 0); 2260 hr = wined3d_device_draw_indexed_primitive(device->wined3d_device, start_idx, 2261 vertex_count_from_primitive_count(primitive_type, primitive_count)); 2262 wined3d_mutex_unlock(); 2263 2264 return hr; 2265 } 2266 2267 /* The caller is responsible for wined3d locking */ 2268 static HRESULT d3d8_device_prepare_vertex_buffer(struct d3d8_device *device, UINT min_size) 2269 { 2270 HRESULT hr; 2271 2272 if (device->vertex_buffer_size < min_size || !device->vertex_buffer) 2273 { 2274 UINT size = max(device->vertex_buffer_size * 2, min_size); 2275 struct wined3d_buffer_desc desc; 2276 struct wined3d_buffer *buffer; 2277 2278 TRACE("Growing vertex buffer to %u bytes\n", size); 2279 2280 desc.byte_width = size; 2281 desc.usage = WINED3DUSAGE_DYNAMIC | WINED3DUSAGE_WRITEONLY; 2282 desc.bind_flags = WINED3D_BIND_VERTEX_BUFFER; 2283 desc.access = WINED3D_RESOURCE_ACCESS_GPU | WINED3D_RESOURCE_ACCESS_MAP_R | WINED3D_RESOURCE_ACCESS_MAP_W; 2284 desc.misc_flags = 0; 2285 desc.structure_byte_stride = 0; 2286 2287 if (FAILED(hr = wined3d_buffer_create(device->wined3d_device, &desc, 2288 NULL, NULL, &d3d8_null_wined3d_parent_ops, &buffer))) 2289 { 2290 ERR("Failed to create vertex buffer, hr %#x.\n", hr); 2291 return hr; 2292 } 2293 2294 if (device->vertex_buffer) 2295 wined3d_buffer_decref(device->vertex_buffer); 2296 2297 device->vertex_buffer = buffer; 2298 device->vertex_buffer_size = size; 2299 device->vertex_buffer_pos = 0; 2300 } 2301 return D3D_OK; 2302 } 2303 2304 static HRESULT WINAPI d3d8_device_DrawPrimitiveUP(IDirect3DDevice8 *iface, 2305 D3DPRIMITIVETYPE primitive_type, UINT primitive_count, const void *data, 2306 UINT stride) 2307 { 2308 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); 2309 HRESULT hr; 2310 UINT vtx_count = vertex_count_from_primitive_count(primitive_type, primitive_count); 2311 struct wined3d_map_desc wined3d_map_desc; 2312 struct wined3d_box wined3d_box = {0}; 2313 UINT size = vtx_count * stride; 2314 struct wined3d_resource *vb; 2315 UINT vb_pos, align; 2316 2317 TRACE("iface %p, primitive_type %#x, primitive_count %u, data %p, stride %u.\n", 2318 iface, primitive_type, primitive_count, data, stride); 2319 2320 if (!primitive_count) 2321 { 2322 WARN("primitive_count is 0, returning D3D_OK\n"); 2323 return D3D_OK; 2324 } 2325 2326 wined3d_mutex_lock(); 2327 hr = d3d8_device_prepare_vertex_buffer(device, size); 2328 if (FAILED(hr)) 2329 goto done; 2330 2331 vb_pos = device->vertex_buffer_pos; 2332 align = vb_pos % stride; 2333 if (align) align = stride - align; 2334 if (vb_pos + size + align > device->vertex_buffer_size) 2335 vb_pos = 0; 2336 else 2337 vb_pos += align; 2338 2339 wined3d_box.left = vb_pos; 2340 wined3d_box.right = vb_pos + size; 2341 vb = wined3d_buffer_get_resource(device->vertex_buffer); 2342 if (FAILED(wined3d_resource_map(vb, 0, &wined3d_map_desc, &wined3d_box, 2343 WINED3D_MAP_WRITE | (vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD)))) 2344 goto done; 2345 memcpy(wined3d_map_desc.data, data, size); 2346 wined3d_resource_unmap(vb, 0); 2347 device->vertex_buffer_pos = vb_pos + size; 2348 2349 hr = wined3d_device_set_stream_source(device->wined3d_device, 0, device->vertex_buffer, 0, stride); 2350 if (FAILED(hr)) 2351 goto done; 2352 2353 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type, 0); 2354 hr = wined3d_device_draw_primitive(device->wined3d_device, vb_pos / stride, vtx_count); 2355 wined3d_device_set_stream_source(device->wined3d_device, 0, NULL, 0, 0); 2356 2357 done: 2358 wined3d_mutex_unlock(); 2359 return hr; 2360 } 2361 2362 /* The caller is responsible for wined3d locking */ 2363 static HRESULT d3d8_device_prepare_index_buffer(struct d3d8_device *device, UINT min_size) 2364 { 2365 HRESULT hr; 2366 2367 if (device->index_buffer_size < min_size || !device->index_buffer) 2368 { 2369 UINT size = max(device->index_buffer_size * 2, min_size); 2370 struct wined3d_buffer_desc desc; 2371 struct wined3d_buffer *buffer; 2372 2373 TRACE("Growing index buffer to %u bytes\n", size); 2374 2375 desc.byte_width = size; 2376 desc.usage = WINED3DUSAGE_DYNAMIC | WINED3DUSAGE_WRITEONLY | WINED3DUSAGE_STATICDECL; 2377 desc.bind_flags = WINED3D_BIND_INDEX_BUFFER; 2378 desc.access = WINED3D_RESOURCE_ACCESS_GPU | WINED3D_RESOURCE_ACCESS_MAP_R | WINED3D_RESOURCE_ACCESS_MAP_W; 2379 desc.misc_flags = 0; 2380 desc.structure_byte_stride = 0; 2381 2382 if (FAILED(hr = wined3d_buffer_create(device->wined3d_device, &desc, 2383 NULL, NULL, &d3d8_null_wined3d_parent_ops, &buffer))) 2384 { 2385 ERR("Failed to create index buffer, hr %#x.\n", hr); 2386 return hr; 2387 } 2388 2389 if (device->index_buffer) 2390 wined3d_buffer_decref(device->index_buffer); 2391 2392 device->index_buffer = buffer; 2393 device->index_buffer_size = size; 2394 device->index_buffer_pos = 0; 2395 } 2396 return D3D_OK; 2397 } 2398 2399 static HRESULT WINAPI d3d8_device_DrawIndexedPrimitiveUP(IDirect3DDevice8 *iface, 2400 D3DPRIMITIVETYPE primitive_type, UINT min_vertex_idx, UINT vertex_count, 2401 UINT primitive_count, const void *index_data, D3DFORMAT index_format, 2402 const void *vertex_data, UINT vertex_stride) 2403 { 2404 UINT idx_count = vertex_count_from_primitive_count(primitive_type, primitive_count); 2405 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); 2406 UINT idx_fmt_size = index_format == D3DFMT_INDEX16 ? 2 : 4; 2407 UINT vtx_size = vertex_count * vertex_stride; 2408 UINT idx_size = idx_count * idx_fmt_size; 2409 struct wined3d_map_desc wined3d_map_desc; 2410 struct wined3d_box wined3d_box = {0}; 2411 struct wined3d_resource *ib, *vb; 2412 UINT vb_pos, ib_pos, align; 2413 HRESULT hr; 2414 2415 TRACE("iface %p, primitive_type %#x, min_vertex_idx %u, vertex_count %u, primitive_count %u, " 2416 "index_data %p, index_format %#x, vertex_data %p, vertex_stride %u.\n", 2417 iface, primitive_type, min_vertex_idx, vertex_count, primitive_count, 2418 index_data, index_format, vertex_data, vertex_stride); 2419 2420 if (!primitive_count) 2421 { 2422 WARN("primitive_count is 0, returning D3D_OK\n"); 2423 return D3D_OK; 2424 } 2425 2426 wined3d_mutex_lock(); 2427 2428 hr = d3d8_device_prepare_vertex_buffer(device, vtx_size); 2429 if (FAILED(hr)) 2430 goto done; 2431 2432 vb_pos = device->vertex_buffer_pos; 2433 align = vb_pos % vertex_stride; 2434 if (align) align = vertex_stride - align; 2435 if (vb_pos + vtx_size + align > device->vertex_buffer_size) 2436 vb_pos = 0; 2437 else 2438 vb_pos += align; 2439 2440 wined3d_box.left = vb_pos; 2441 wined3d_box.right = vb_pos + vtx_size; 2442 vb = wined3d_buffer_get_resource(device->vertex_buffer); 2443 if (FAILED(hr = wined3d_resource_map(vb, 0, &wined3d_map_desc, &wined3d_box, 2444 WINED3D_MAP_WRITE | (vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD)))) 2445 goto done; 2446 memcpy(wined3d_map_desc.data, (char *)vertex_data + min_vertex_idx * vertex_stride, vtx_size); 2447 wined3d_resource_unmap(vb, 0); 2448 device->vertex_buffer_pos = vb_pos + vtx_size; 2449 2450 hr = d3d8_device_prepare_index_buffer(device, idx_size); 2451 if (FAILED(hr)) 2452 goto done; 2453 2454 ib_pos = device->index_buffer_pos; 2455 align = ib_pos % idx_fmt_size; 2456 if (align) align = idx_fmt_size - align; 2457 if (ib_pos + idx_size + align > device->index_buffer_size) 2458 ib_pos = 0; 2459 else 2460 ib_pos += align; 2461 2462 wined3d_box.left = ib_pos; 2463 wined3d_box.right = ib_pos + idx_size; 2464 ib = wined3d_buffer_get_resource(device->index_buffer); 2465 if (FAILED(hr = wined3d_resource_map(ib, 0, &wined3d_map_desc, &wined3d_box, 2466 WINED3D_MAP_WRITE | (ib_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD)))) 2467 goto done; 2468 memcpy(wined3d_map_desc.data, index_data, idx_size); 2469 wined3d_resource_unmap(ib, 0); 2470 device->index_buffer_pos = ib_pos + idx_size; 2471 2472 hr = wined3d_device_set_stream_source(device->wined3d_device, 0, device->vertex_buffer, 0, vertex_stride); 2473 if (FAILED(hr)) 2474 goto done; 2475 2476 wined3d_device_set_index_buffer(device->wined3d_device, device->index_buffer, 2477 wined3dformat_from_d3dformat(index_format), 0); 2478 wined3d_device_set_base_vertex_index(device->wined3d_device, vb_pos / vertex_stride - min_vertex_idx); 2479 2480 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type, 0); 2481 hr = wined3d_device_draw_indexed_primitive(device->wined3d_device, ib_pos / idx_fmt_size, idx_count); 2482 2483 wined3d_device_set_stream_source(device->wined3d_device, 0, NULL, 0, 0); 2484 wined3d_device_set_index_buffer(device->wined3d_device, NULL, WINED3DFMT_UNKNOWN, 0); 2485 wined3d_device_set_base_vertex_index(device->wined3d_device, 0); 2486 2487 done: 2488 wined3d_mutex_unlock(); 2489 return hr; 2490 } 2491 2492 static HRESULT WINAPI d3d8_device_ProcessVertices(IDirect3DDevice8 *iface, UINT src_start_idx, 2493 UINT dst_idx, UINT vertex_count, IDirect3DVertexBuffer8 *dst_buffer, DWORD flags) 2494 { 2495 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); 2496 struct d3d8_vertexbuffer *dst = unsafe_impl_from_IDirect3DVertexBuffer8(dst_buffer); 2497 HRESULT hr; 2498 2499 TRACE("iface %p, src_start_idx %u, dst_idx %u, vertex_count %u, dst_buffer %p, flags %#x.\n", 2500 iface, src_start_idx, dst_idx, vertex_count, dst_buffer, flags); 2501 2502 wined3d_mutex_lock(); 2503 hr = wined3d_device_process_vertices(device->wined3d_device, src_start_idx, dst_idx, 2504 vertex_count, dst->wined3d_buffer, NULL, flags, dst->fvf); 2505 wined3d_mutex_unlock(); 2506 2507 return hr; 2508 } 2509 2510 static HRESULT WINAPI d3d8_device_CreateVertexShader(IDirect3DDevice8 *iface, 2511 const DWORD *declaration, const DWORD *byte_code, DWORD *shader, DWORD usage) 2512 { 2513 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); 2514 struct d3d8_vertex_shader *object; 2515 DWORD shader_handle; 2516 DWORD handle; 2517 HRESULT hr; 2518 2519 TRACE("iface %p, declaration %p, byte_code %p, shader %p, usage %#x.\n", 2520 iface, declaration, byte_code, shader, usage); 2521 2522 if (!(object = heap_alloc_zero(sizeof(*object)))) 2523 { 2524 *shader = 0; 2525 return E_OUTOFMEMORY; 2526 } 2527 2528 wined3d_mutex_lock(); 2529 handle = d3d8_allocate_handle(&device->handle_table, object, D3D8_HANDLE_VS); 2530 wined3d_mutex_unlock(); 2531 if (handle == D3D8_INVALID_HANDLE) 2532 { 2533 ERR("Failed to allocate vertex shader handle.\n"); 2534 heap_free(object); 2535 *shader = 0; 2536 return E_OUTOFMEMORY; 2537 } 2538 2539 shader_handle = handle + VS_HIGHESTFIXEDFXF + 1; 2540 2541 hr = d3d8_vertex_shader_init(object, device, declaration, byte_code, shader_handle, usage); 2542 if (FAILED(hr)) 2543 { 2544 WARN("Failed to initialize vertex shader, hr %#x.\n", hr); 2545 wined3d_mutex_lock(); 2546 d3d8_free_handle(&device->handle_table, handle, D3D8_HANDLE_VS); 2547 wined3d_mutex_unlock(); 2548 heap_free(object); 2549 *shader = 0; 2550 return hr; 2551 } 2552 2553 TRACE("Created vertex shader %p (handle %#x).\n", object, shader_handle); 2554 *shader = shader_handle; 2555 2556 return D3D_OK; 2557 } 2558 2559 static struct d3d8_vertex_declaration *d3d8_device_get_fvf_declaration(struct d3d8_device *device, DWORD fvf) 2560 { 2561 struct d3d8_vertex_declaration *d3d8_declaration; 2562 struct FvfToDecl *convertedDecls = device->decls; 2563 int p, low, high; /* deliberately signed */ 2564 HRESULT hr; 2565 2566 TRACE("Searching for declaration for fvf %08x... ", fvf); 2567 2568 low = 0; 2569 high = device->numConvertedDecls - 1; 2570 while (low <= high) 2571 { 2572 p = (low + high) >> 1; 2573 TRACE("%d ", p); 2574 2575 if (convertedDecls[p].fvf == fvf) 2576 { 2577 TRACE("found %p\n", convertedDecls[p].declaration); 2578 return convertedDecls[p].declaration; 2579 } 2580 2581 if (convertedDecls[p].fvf < fvf) 2582 low = p + 1; 2583 else 2584 high = p - 1; 2585 } 2586 TRACE("not found. Creating and inserting at position %d.\n", low); 2587 2588 if (!(d3d8_declaration = heap_alloc(sizeof(*d3d8_declaration)))) 2589 return NULL; 2590 2591 if (FAILED(hr = d3d8_vertex_declaration_init_fvf(d3d8_declaration, device, fvf))) 2592 { 2593 WARN("Failed to initialize vertex declaration, hr %#x.\n", hr); 2594 heap_free(d3d8_declaration); 2595 return NULL; 2596 } 2597 2598 if (device->declArraySize == device->numConvertedDecls) 2599 { 2600 UINT grow = device->declArraySize / 2; 2601 2602 if (!(convertedDecls = heap_realloc(convertedDecls, 2603 sizeof(*convertedDecls) * (device->numConvertedDecls + grow)))) 2604 { 2605 d3d8_vertex_declaration_destroy(d3d8_declaration); 2606 return NULL; 2607 } 2608 device->decls = convertedDecls; 2609 device->declArraySize += grow; 2610 } 2611 2612 memmove(convertedDecls + low + 1, convertedDecls + low, 2613 sizeof(*convertedDecls) * (device->numConvertedDecls - low)); 2614 convertedDecls[low].declaration = d3d8_declaration; 2615 convertedDecls[low].fvf = fvf; 2616 ++device->numConvertedDecls; 2617 2618 TRACE("Returning %p. %u decls in array.\n", d3d8_declaration, device->numConvertedDecls); 2619 2620 return d3d8_declaration; 2621 } 2622 2623 static HRESULT WINAPI d3d8_device_SetVertexShader(IDirect3DDevice8 *iface, DWORD shader) 2624 { 2625 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); 2626 struct d3d8_vertex_shader *shader_impl; 2627 2628 TRACE("iface %p, shader %#x.\n", iface, shader); 2629 2630 if (VS_HIGHESTFIXEDFXF >= shader) 2631 { 2632 TRACE("Setting FVF, %#x\n", shader); 2633 2634 wined3d_mutex_lock(); 2635 wined3d_device_set_vertex_declaration(device->wined3d_device, 2636 d3d8_device_get_fvf_declaration(device, shader)->wined3d_vertex_declaration); 2637 wined3d_device_set_vertex_shader(device->wined3d_device, NULL); 2638 wined3d_mutex_unlock(); 2639 2640 return D3D_OK; 2641 } 2642 2643 TRACE("Setting shader\n"); 2644 2645 wined3d_mutex_lock(); 2646 if (!(shader_impl = d3d8_get_object(&device->handle_table, shader - (VS_HIGHESTFIXEDFXF + 1), D3D8_HANDLE_VS))) 2647 { 2648 WARN("Invalid handle (%#x) passed.\n", shader); 2649 wined3d_mutex_unlock(); 2650 2651 return D3DERR_INVALIDCALL; 2652 } 2653 2654 wined3d_device_set_vertex_declaration(device->wined3d_device, 2655 shader_impl->vertex_declaration->wined3d_vertex_declaration); 2656 wined3d_device_set_vertex_shader(device->wined3d_device, shader_impl->wined3d_shader); 2657 wined3d_mutex_unlock(); 2658 2659 return D3D_OK; 2660 } 2661 2662 static HRESULT WINAPI d3d8_device_GetVertexShader(IDirect3DDevice8 *iface, DWORD *shader) 2663 { 2664 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); 2665 struct wined3d_vertex_declaration *wined3d_declaration; 2666 struct d3d8_vertex_declaration *d3d8_declaration; 2667 2668 TRACE("iface %p, shader %p.\n", iface, shader); 2669 2670 wined3d_mutex_lock(); 2671 if ((wined3d_declaration = wined3d_device_get_vertex_declaration(device->wined3d_device))) 2672 { 2673 d3d8_declaration = wined3d_vertex_declaration_get_parent(wined3d_declaration); 2674 *shader = d3d8_declaration->shader_handle; 2675 } 2676 else 2677 { 2678 *shader = 0; 2679 } 2680 wined3d_mutex_unlock(); 2681 2682 TRACE("Returning %#x.\n", *shader); 2683 2684 return D3D_OK; 2685 } 2686 2687 static HRESULT WINAPI d3d8_device_DeleteVertexShader(IDirect3DDevice8 *iface, DWORD shader) 2688 { 2689 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); 2690 struct d3d8_vertex_shader *shader_impl; 2691 2692 TRACE("iface %p, shader %#x.\n", iface, shader); 2693 2694 wined3d_mutex_lock(); 2695 if (!(shader_impl = d3d8_free_handle(&device->handle_table, shader - (VS_HIGHESTFIXEDFXF + 1), D3D8_HANDLE_VS))) 2696 { 2697 WARN("Invalid handle (%#x) passed.\n", shader); 2698 wined3d_mutex_unlock(); 2699 2700 return D3DERR_INVALIDCALL; 2701 } 2702 2703 if (shader_impl->wined3d_shader 2704 && wined3d_device_get_vertex_shader(device->wined3d_device) == shader_impl->wined3d_shader) 2705 IDirect3DDevice8_SetVertexShader(iface, 0); 2706 2707 wined3d_mutex_unlock(); 2708 2709 d3d8_vertex_shader_destroy(shader_impl); 2710 2711 return D3D_OK; 2712 } 2713 2714 static HRESULT WINAPI d3d8_device_SetVertexShaderConstant(IDirect3DDevice8 *iface, 2715 DWORD start_register, const void *data, DWORD count) 2716 { 2717 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); 2718 HRESULT hr; 2719 2720 TRACE("iface %p, start_register %u, data %p, count %u.\n", 2721 iface, start_register, data, count); 2722 2723 if (start_register + count > D3D8_MAX_VERTEX_SHADER_CONSTANTF) 2724 { 2725 WARN("Trying to access %u constants, but d3d8 only supports %u\n", 2726 start_register + count, D3D8_MAX_VERTEX_SHADER_CONSTANTF); 2727 return D3DERR_INVALIDCALL; 2728 } 2729 2730 wined3d_mutex_lock(); 2731 hr = wined3d_device_set_vs_consts_f(device->wined3d_device, start_register, count, data); 2732 wined3d_mutex_unlock(); 2733 2734 return hr; 2735 } 2736 2737 static HRESULT WINAPI d3d8_device_GetVertexShaderConstant(IDirect3DDevice8 *iface, 2738 DWORD start_register, void *data, DWORD count) 2739 { 2740 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); 2741 HRESULT hr; 2742 2743 TRACE("iface %p, start_register %u, data %p, count %u.\n", 2744 iface, start_register, data, count); 2745 2746 if (start_register + count > D3D8_MAX_VERTEX_SHADER_CONSTANTF) 2747 { 2748 WARN("Trying to access %u constants, but d3d8 only supports %u\n", 2749 start_register + count, D3D8_MAX_VERTEX_SHADER_CONSTANTF); 2750 return D3DERR_INVALIDCALL; 2751 } 2752 2753 wined3d_mutex_lock(); 2754 hr = wined3d_device_get_vs_consts_f(device->wined3d_device, start_register, count, data); 2755 wined3d_mutex_unlock(); 2756 2757 return hr; 2758 } 2759 2760 static HRESULT WINAPI d3d8_device_GetVertexShaderDeclaration(IDirect3DDevice8 *iface, 2761 DWORD shader, void *data, DWORD *data_size) 2762 { 2763 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); 2764 struct d3d8_vertex_declaration *declaration; 2765 struct d3d8_vertex_shader *shader_impl; 2766 2767 TRACE("iface %p, shader %#x, data %p, data_size %p.\n", 2768 iface, shader, data, data_size); 2769 2770 wined3d_mutex_lock(); 2771 shader_impl = d3d8_get_object(&device->handle_table, shader - (VS_HIGHESTFIXEDFXF + 1), D3D8_HANDLE_VS); 2772 wined3d_mutex_unlock(); 2773 2774 if (!shader_impl) 2775 { 2776 WARN("Invalid handle (%#x) passed.\n", shader); 2777 return D3DERR_INVALIDCALL; 2778 } 2779 declaration = shader_impl->vertex_declaration; 2780 2781 if (!data) 2782 { 2783 *data_size = declaration->elements_size; 2784 return D3D_OK; 2785 } 2786 2787 /* MSDN claims that if *data_size is smaller than the required size 2788 * we should write the required size and return D3DERR_MOREDATA. 2789 * That's not actually true. */ 2790 if (*data_size < declaration->elements_size) 2791 return D3DERR_INVALIDCALL; 2792 2793 memcpy(data, declaration->elements, declaration->elements_size); 2794 2795 return D3D_OK; 2796 } 2797 2798 static HRESULT WINAPI d3d8_device_GetVertexShaderFunction(IDirect3DDevice8 *iface, 2799 DWORD shader, void *data, DWORD *data_size) 2800 { 2801 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); 2802 struct d3d8_vertex_shader *shader_impl = NULL; 2803 HRESULT hr; 2804 2805 TRACE("iface %p, shader %#x, data %p, data_size %p.\n", 2806 iface, shader, data, data_size); 2807 2808 wined3d_mutex_lock(); 2809 if (!(shader_impl = d3d8_get_object(&device->handle_table, shader - (VS_HIGHESTFIXEDFXF + 1), D3D8_HANDLE_VS))) 2810 { 2811 WARN("Invalid handle (%#x) passed.\n", shader); 2812 wined3d_mutex_unlock(); 2813 2814 return D3DERR_INVALIDCALL; 2815 } 2816 2817 if (!shader_impl->wined3d_shader) 2818 { 2819 wined3d_mutex_unlock(); 2820 *data_size = 0; 2821 return D3D_OK; 2822 } 2823 2824 hr = wined3d_shader_get_byte_code(shader_impl->wined3d_shader, data, data_size); 2825 wined3d_mutex_unlock(); 2826 2827 return hr; 2828 } 2829 2830 static HRESULT WINAPI d3d8_device_SetIndices(IDirect3DDevice8 *iface, 2831 IDirect3DIndexBuffer8 *buffer, UINT base_vertex_idx) 2832 { 2833 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); 2834 struct d3d8_indexbuffer *ib = unsafe_impl_from_IDirect3DIndexBuffer8(buffer); 2835 2836 TRACE("iface %p, buffer %p, base_vertex_idx %u.\n", iface, buffer, base_vertex_idx); 2837 2838 /* WineD3D takes an INT(due to d3d9), but d3d8 uses UINTs. Do I have to add a check here that 2839 * the UINT doesn't cause an overflow in the INT? It seems rather unlikely because such large 2840 * vertex buffers can't be created to address them with an index that requires the 32nd bit 2841 * (4 Byte minimum vertex size * 2^31-1 -> 8 gb buffer. The index sign would be the least 2842 * problem) 2843 */ 2844 wined3d_mutex_lock(); 2845 wined3d_device_set_base_vertex_index(device->wined3d_device, base_vertex_idx); 2846 wined3d_device_set_index_buffer(device->wined3d_device, 2847 ib ? ib->wined3d_buffer : NULL, ib ? ib->format : WINED3DFMT_UNKNOWN, 0); 2848 wined3d_mutex_unlock(); 2849 2850 return D3D_OK; 2851 } 2852 2853 static HRESULT WINAPI d3d8_device_GetIndices(IDirect3DDevice8 *iface, 2854 IDirect3DIndexBuffer8 **buffer, UINT *base_vertex_index) 2855 { 2856 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); 2857 enum wined3d_format_id wined3d_format; 2858 struct wined3d_buffer *wined3d_buffer; 2859 struct d3d8_indexbuffer *buffer_impl; 2860 2861 TRACE("iface %p, buffer %p, base_vertex_index %p.\n", iface, buffer, base_vertex_index); 2862 2863 if (!buffer) 2864 return D3DERR_INVALIDCALL; 2865 2866 /* The case from UINT to INT is safe because d3d8 will never set negative values */ 2867 wined3d_mutex_lock(); 2868 *base_vertex_index = wined3d_device_get_base_vertex_index(device->wined3d_device); 2869 if ((wined3d_buffer = wined3d_device_get_index_buffer(device->wined3d_device, &wined3d_format, NULL))) 2870 { 2871 buffer_impl = wined3d_buffer_get_parent(wined3d_buffer); 2872 *buffer = &buffer_impl->IDirect3DIndexBuffer8_iface; 2873 IDirect3DIndexBuffer8_AddRef(*buffer); 2874 } 2875 else 2876 { 2877 *buffer = NULL; 2878 } 2879 wined3d_mutex_unlock(); 2880 2881 return D3D_OK; 2882 } 2883 2884 static HRESULT WINAPI d3d8_device_CreatePixelShader(IDirect3DDevice8 *iface, 2885 const DWORD *byte_code, DWORD *shader) 2886 { 2887 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); 2888 struct d3d8_pixel_shader *object; 2889 DWORD shader_handle; 2890 DWORD handle; 2891 HRESULT hr; 2892 2893 TRACE("iface %p, byte_code %p, shader %p.\n", iface, byte_code, shader); 2894 2895 if (!shader) 2896 return D3DERR_INVALIDCALL; 2897 2898 if (!(object = heap_alloc_zero(sizeof(*object)))) 2899 return E_OUTOFMEMORY; 2900 2901 wined3d_mutex_lock(); 2902 handle = d3d8_allocate_handle(&device->handle_table, object, D3D8_HANDLE_PS); 2903 wined3d_mutex_unlock(); 2904 if (handle == D3D8_INVALID_HANDLE) 2905 { 2906 ERR("Failed to allocate pixel shader handle.\n"); 2907 heap_free(object); 2908 return E_OUTOFMEMORY; 2909 } 2910 2911 shader_handle = handle + VS_HIGHESTFIXEDFXF + 1; 2912 2913 hr = d3d8_pixel_shader_init(object, device, byte_code, shader_handle); 2914 if (FAILED(hr)) 2915 { 2916 WARN("Failed to initialize pixel shader, hr %#x.\n", hr); 2917 wined3d_mutex_lock(); 2918 d3d8_free_handle(&device->handle_table, handle, D3D8_HANDLE_PS); 2919 wined3d_mutex_unlock(); 2920 heap_free(object); 2921 *shader = 0; 2922 return hr; 2923 } 2924 2925 TRACE("Created pixel shader %p (handle %#x).\n", object, shader_handle); 2926 *shader = shader_handle; 2927 2928 return D3D_OK; 2929 } 2930 2931 static HRESULT WINAPI d3d8_device_SetPixelShader(IDirect3DDevice8 *iface, DWORD shader) 2932 { 2933 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); 2934 struct d3d8_pixel_shader *shader_impl; 2935 2936 TRACE("iface %p, shader %#x.\n", iface, shader); 2937 2938 wined3d_mutex_lock(); 2939 2940 if (!shader) 2941 { 2942 wined3d_device_set_pixel_shader(device->wined3d_device, NULL); 2943 wined3d_mutex_unlock(); 2944 return D3D_OK; 2945 } 2946 2947 if (!(shader_impl = d3d8_get_object(&device->handle_table, shader - (VS_HIGHESTFIXEDFXF + 1), D3D8_HANDLE_PS))) 2948 { 2949 WARN("Invalid handle (%#x) passed.\n", shader); 2950 wined3d_mutex_unlock(); 2951 return D3DERR_INVALIDCALL; 2952 } 2953 2954 TRACE("Setting shader %p.\n", shader_impl); 2955 wined3d_device_set_pixel_shader(device->wined3d_device, shader_impl->wined3d_shader); 2956 wined3d_mutex_unlock(); 2957 2958 return D3D_OK; 2959 } 2960 2961 static HRESULT WINAPI d3d8_device_GetPixelShader(IDirect3DDevice8 *iface, DWORD *shader) 2962 { 2963 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); 2964 struct wined3d_shader *object; 2965 2966 TRACE("iface %p, shader %p.\n", iface, shader); 2967 2968 if (!shader) 2969 return D3DERR_INVALIDCALL; 2970 2971 wined3d_mutex_lock(); 2972 if ((object = wined3d_device_get_pixel_shader(device->wined3d_device))) 2973 { 2974 struct d3d8_pixel_shader *d3d8_shader; 2975 d3d8_shader = wined3d_shader_get_parent(object); 2976 *shader = d3d8_shader->handle; 2977 } 2978 else 2979 { 2980 *shader = 0; 2981 } 2982 wined3d_mutex_unlock(); 2983 2984 TRACE("Returning %#x.\n", *shader); 2985 2986 return D3D_OK; 2987 } 2988 2989 static HRESULT WINAPI d3d8_device_DeletePixelShader(IDirect3DDevice8 *iface, DWORD shader) 2990 { 2991 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); 2992 struct d3d8_pixel_shader *shader_impl; 2993 2994 TRACE("iface %p, shader %#x.\n", iface, shader); 2995 2996 wined3d_mutex_lock(); 2997 2998 if (!(shader_impl = d3d8_free_handle(&device->handle_table, shader - (VS_HIGHESTFIXEDFXF + 1), D3D8_HANDLE_PS))) 2999 { 3000 WARN("Invalid handle (%#x) passed.\n", shader); 3001 wined3d_mutex_unlock(); 3002 return D3DERR_INVALIDCALL; 3003 } 3004 3005 if (wined3d_device_get_pixel_shader(device->wined3d_device) == shader_impl->wined3d_shader) 3006 IDirect3DDevice8_SetPixelShader(iface, 0); 3007 3008 wined3d_mutex_unlock(); 3009 3010 d3d8_pixel_shader_destroy(shader_impl); 3011 3012 return D3D_OK; 3013 } 3014 3015 static HRESULT WINAPI d3d8_device_SetPixelShaderConstant(IDirect3DDevice8 *iface, 3016 DWORD start_register, const void *data, DWORD count) 3017 { 3018 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); 3019 HRESULT hr; 3020 3021 TRACE("iface %p, start_register %u, data %p, count %u.\n", 3022 iface, start_register, data, count); 3023 3024 wined3d_mutex_lock(); 3025 hr = wined3d_device_set_ps_consts_f(device->wined3d_device, start_register, count, data); 3026 wined3d_mutex_unlock(); 3027 3028 return hr; 3029 } 3030 3031 static HRESULT WINAPI d3d8_device_GetPixelShaderConstant(IDirect3DDevice8 *iface, 3032 DWORD start_register, void *data, DWORD count) 3033 { 3034 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); 3035 HRESULT hr; 3036 3037 TRACE("iface %p, start_register %u, data %p, count %u.\n", 3038 iface, start_register, data, count); 3039 3040 wined3d_mutex_lock(); 3041 hr = wined3d_device_get_ps_consts_f(device->wined3d_device, start_register, count, data); 3042 wined3d_mutex_unlock(); 3043 3044 return hr; 3045 } 3046 3047 static HRESULT WINAPI d3d8_device_GetPixelShaderFunction(IDirect3DDevice8 *iface, 3048 DWORD shader, void *data, DWORD *data_size) 3049 { 3050 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); 3051 struct d3d8_pixel_shader *shader_impl = NULL; 3052 HRESULT hr; 3053 3054 TRACE("iface %p, shader %#x, data %p, data_size %p.\n", 3055 iface, shader, data, data_size); 3056 3057 wined3d_mutex_lock(); 3058 if (!(shader_impl = d3d8_get_object(&device->handle_table, shader - (VS_HIGHESTFIXEDFXF + 1), D3D8_HANDLE_PS))) 3059 { 3060 WARN("Invalid handle (%#x) passed.\n", shader); 3061 wined3d_mutex_unlock(); 3062 3063 return D3DERR_INVALIDCALL; 3064 } 3065 3066 hr = wined3d_shader_get_byte_code(shader_impl->wined3d_shader, data, data_size); 3067 wined3d_mutex_unlock(); 3068 3069 return hr; 3070 } 3071 3072 static HRESULT WINAPI d3d8_device_DrawRectPatch(IDirect3DDevice8 *iface, UINT handle, 3073 const float *segment_count, const D3DRECTPATCH_INFO *patch_info) 3074 { 3075 FIXME("iface %p, handle %#x, segment_count %p, patch_info %p unimplemented.\n", 3076 iface, handle, segment_count, patch_info); 3077 return D3D_OK; 3078 } 3079 3080 static HRESULT WINAPI d3d8_device_DrawTriPatch(IDirect3DDevice8 *iface, UINT handle, 3081 const float *segment_count, const D3DTRIPATCH_INFO *patch_info) 3082 { 3083 FIXME("iface %p, handle %#x, segment_count %p, patch_info %p unimplemented.\n", 3084 iface, handle, segment_count, patch_info); 3085 return D3D_OK; 3086 } 3087 3088 static HRESULT WINAPI d3d8_device_DeletePatch(IDirect3DDevice8 *iface, UINT handle) 3089 { 3090 FIXME("iface %p, handle %#x unimplemented.\n", iface, handle); 3091 return D3DERR_INVALIDCALL; 3092 } 3093 3094 static HRESULT WINAPI d3d8_device_SetStreamSource(IDirect3DDevice8 *iface, 3095 UINT stream_idx, IDirect3DVertexBuffer8 *buffer, UINT stride) 3096 { 3097 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); 3098 struct d3d8_vertexbuffer *buffer_impl = unsafe_impl_from_IDirect3DVertexBuffer8(buffer); 3099 HRESULT hr; 3100 3101 TRACE("iface %p, stream_idx %u, buffer %p, stride %u.\n", 3102 iface, stream_idx, buffer, stride); 3103 3104 wined3d_mutex_lock(); 3105 hr = wined3d_device_set_stream_source(device->wined3d_device, stream_idx, 3106 buffer_impl ? buffer_impl->wined3d_buffer : NULL, 0, stride); 3107 wined3d_mutex_unlock(); 3108 3109 return hr; 3110 } 3111 3112 static HRESULT WINAPI d3d8_device_GetStreamSource(IDirect3DDevice8 *iface, 3113 UINT stream_idx, IDirect3DVertexBuffer8 **buffer, UINT *stride) 3114 { 3115 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); 3116 struct d3d8_vertexbuffer *buffer_impl; 3117 struct wined3d_buffer *wined3d_buffer = NULL; 3118 HRESULT hr; 3119 3120 TRACE("iface %p, stream_idx %u, buffer %p, stride %p.\n", 3121 iface, stream_idx, buffer, stride); 3122 3123 if (!buffer) 3124 return D3DERR_INVALIDCALL; 3125 3126 wined3d_mutex_lock(); 3127 hr = wined3d_device_get_stream_source(device->wined3d_device, stream_idx, &wined3d_buffer, 0, stride); 3128 if (SUCCEEDED(hr) && wined3d_buffer) 3129 { 3130 buffer_impl = wined3d_buffer_get_parent(wined3d_buffer); 3131 *buffer = &buffer_impl->IDirect3DVertexBuffer8_iface; 3132 IDirect3DVertexBuffer8_AddRef(*buffer); 3133 } 3134 else 3135 { 3136 if (FAILED(hr)) 3137 ERR("Failed to get wined3d stream source, hr %#x.\n", hr); 3138 *buffer = NULL; 3139 } 3140 wined3d_mutex_unlock(); 3141 3142 return hr; 3143 } 3144 3145 static const struct IDirect3DDevice8Vtbl d3d8_device_vtbl = 3146 { 3147 d3d8_device_QueryInterface, 3148 d3d8_device_AddRef, 3149 d3d8_device_Release, 3150 d3d8_device_TestCooperativeLevel, 3151 d3d8_device_GetAvailableTextureMem, 3152 d3d8_device_ResourceManagerDiscardBytes, 3153 d3d8_device_GetDirect3D, 3154 d3d8_device_GetDeviceCaps, 3155 d3d8_device_GetDisplayMode, 3156 d3d8_device_GetCreationParameters, 3157 d3d8_device_SetCursorProperties, 3158 d3d8_device_SetCursorPosition, 3159 d3d8_device_ShowCursor, 3160 d3d8_device_CreateAdditionalSwapChain, 3161 d3d8_device_Reset, 3162 d3d8_device_Present, 3163 d3d8_device_GetBackBuffer, 3164 d3d8_device_GetRasterStatus, 3165 d3d8_device_SetGammaRamp, 3166 d3d8_device_GetGammaRamp, 3167 d3d8_device_CreateTexture, 3168 d3d8_device_CreateVolumeTexture, 3169 d3d8_device_CreateCubeTexture, 3170 d3d8_device_CreateVertexBuffer, 3171 d3d8_device_CreateIndexBuffer, 3172 d3d8_device_CreateRenderTarget, 3173 d3d8_device_CreateDepthStencilSurface, 3174 d3d8_device_CreateImageSurface, 3175 d3d8_device_CopyRects, 3176 d3d8_device_UpdateTexture, 3177 d3d8_device_GetFrontBuffer, 3178 d3d8_device_SetRenderTarget, 3179 d3d8_device_GetRenderTarget, 3180 d3d8_device_GetDepthStencilSurface, 3181 d3d8_device_BeginScene, 3182 d3d8_device_EndScene, 3183 d3d8_device_Clear, 3184 d3d8_device_SetTransform, 3185 d3d8_device_GetTransform, 3186 d3d8_device_MultiplyTransform, 3187 d3d8_device_SetViewport, 3188 d3d8_device_GetViewport, 3189 d3d8_device_SetMaterial, 3190 d3d8_device_GetMaterial, 3191 d3d8_device_SetLight, 3192 d3d8_device_GetLight, 3193 d3d8_device_LightEnable, 3194 d3d8_device_GetLightEnable, 3195 d3d8_device_SetClipPlane, 3196 d3d8_device_GetClipPlane, 3197 d3d8_device_SetRenderState, 3198 d3d8_device_GetRenderState, 3199 d3d8_device_BeginStateBlock, 3200 d3d8_device_EndStateBlock, 3201 d3d8_device_ApplyStateBlock, 3202 d3d8_device_CaptureStateBlock, 3203 d3d8_device_DeleteStateBlock, 3204 d3d8_device_CreateStateBlock, 3205 d3d8_device_SetClipStatus, 3206 d3d8_device_GetClipStatus, 3207 d3d8_device_GetTexture, 3208 d3d8_device_SetTexture, 3209 d3d8_device_GetTextureStageState, 3210 d3d8_device_SetTextureStageState, 3211 d3d8_device_ValidateDevice, 3212 d3d8_device_GetInfo, 3213 d3d8_device_SetPaletteEntries, 3214 d3d8_device_GetPaletteEntries, 3215 d3d8_device_SetCurrentTexturePalette, 3216 d3d8_device_GetCurrentTexturePalette, 3217 d3d8_device_DrawPrimitive, 3218 d3d8_device_DrawIndexedPrimitive, 3219 d3d8_device_DrawPrimitiveUP, 3220 d3d8_device_DrawIndexedPrimitiveUP, 3221 d3d8_device_ProcessVertices, 3222 d3d8_device_CreateVertexShader, 3223 d3d8_device_SetVertexShader, 3224 d3d8_device_GetVertexShader, 3225 d3d8_device_DeleteVertexShader, 3226 d3d8_device_SetVertexShaderConstant, 3227 d3d8_device_GetVertexShaderConstant, 3228 d3d8_device_GetVertexShaderDeclaration, 3229 d3d8_device_GetVertexShaderFunction, 3230 d3d8_device_SetStreamSource, 3231 d3d8_device_GetStreamSource, 3232 d3d8_device_SetIndices, 3233 d3d8_device_GetIndices, 3234 d3d8_device_CreatePixelShader, 3235 d3d8_device_SetPixelShader, 3236 d3d8_device_GetPixelShader, 3237 d3d8_device_DeletePixelShader, 3238 d3d8_device_SetPixelShaderConstant, 3239 d3d8_device_GetPixelShaderConstant, 3240 d3d8_device_GetPixelShaderFunction, 3241 d3d8_device_DrawRectPatch, 3242 d3d8_device_DrawTriPatch, 3243 d3d8_device_DeletePatch, 3244 }; 3245 3246 static inline struct d3d8_device *device_from_device_parent(struct wined3d_device_parent *device_parent) 3247 { 3248 return CONTAINING_RECORD(device_parent, struct d3d8_device, device_parent); 3249 } 3250 3251 static void CDECL device_parent_wined3d_device_created(struct wined3d_device_parent *device_parent, 3252 struct wined3d_device *device) 3253 { 3254 TRACE("device_parent %p, device %p\n", device_parent, device); 3255 } 3256 3257 static void CDECL device_parent_mode_changed(struct wined3d_device_parent *device_parent) 3258 { 3259 TRACE("device_parent %p.\n", device_parent); 3260 } 3261 3262 static void CDECL device_parent_activate(struct wined3d_device_parent *device_parent, BOOL activate) 3263 { 3264 struct d3d8_device *device = device_from_device_parent(device_parent); 3265 3266 TRACE("device_parent %p, activate %#x.\n", device_parent, activate); 3267 3268 if (!activate) 3269 InterlockedCompareExchange(&device->device_state, D3D8_DEVICE_STATE_LOST, D3D8_DEVICE_STATE_OK); 3270 else 3271 InterlockedCompareExchange(&device->device_state, D3D8_DEVICE_STATE_NOT_RESET, D3D8_DEVICE_STATE_LOST); 3272 } 3273 3274 static HRESULT CDECL device_parent_texture_sub_resource_created(struct wined3d_device_parent *device_parent, 3275 enum wined3d_resource_type type, struct wined3d_texture *wined3d_texture, unsigned int sub_resource_idx, 3276 void **parent, const struct wined3d_parent_ops **parent_ops) 3277 { 3278 TRACE("device_parent %p, type %#x, wined3d_texture %p, sub_resource_idx %u, parent %p, parent_ops %p.\n", 3279 device_parent, type, wined3d_texture, sub_resource_idx, parent, parent_ops); 3280 3281 if (type == WINED3D_RTYPE_TEXTURE_2D) 3282 { 3283 struct d3d8_surface *d3d_surface; 3284 3285 if (!(d3d_surface = heap_alloc_zero(sizeof(*d3d_surface)))) 3286 return E_OUTOFMEMORY; 3287 3288 surface_init(d3d_surface, wined3d_texture, sub_resource_idx, parent_ops); 3289 *parent = d3d_surface; 3290 TRACE("Created surface %p.\n", d3d_surface); 3291 } 3292 else if (type == WINED3D_RTYPE_TEXTURE_3D) 3293 { 3294 struct d3d8_volume *d3d_volume; 3295 3296 if (!(d3d_volume = heap_alloc_zero(sizeof(*d3d_volume)))) 3297 return E_OUTOFMEMORY; 3298 3299 volume_init(d3d_volume, wined3d_texture, sub_resource_idx, parent_ops); 3300 *parent = d3d_volume; 3301 TRACE("Created volume %p.\n", d3d_volume); 3302 } 3303 else 3304 { 3305 ERR("Unhandled resource type %#x.\n", type); 3306 return E_FAIL; 3307 } 3308 3309 return D3D_OK; 3310 } 3311 3312 static HRESULT CDECL device_parent_create_swapchain_texture(struct wined3d_device_parent *device_parent, 3313 void *container_parent, const struct wined3d_resource_desc *desc, DWORD texture_flags, 3314 struct wined3d_texture **texture) 3315 { 3316 struct d3d8_device *device = device_from_device_parent(device_parent); 3317 struct d3d8_surface *d3d_surface; 3318 HRESULT hr; 3319 3320 TRACE("device_parent %p, container_parent %p, desc %p, texture flags %#x, texture %p.\n", 3321 device_parent, container_parent, desc, texture_flags, texture); 3322 3323 if (FAILED(hr = wined3d_texture_create(device->wined3d_device, desc, 1, 1, 3324 texture_flags | WINED3D_TEXTURE_CREATE_MAPPABLE, NULL, &device->IDirect3DDevice8_iface, 3325 &d3d8_null_wined3d_parent_ops, texture))) 3326 { 3327 WARN("Failed to create texture, hr %#x.\n", hr); 3328 return hr; 3329 } 3330 3331 d3d_surface = wined3d_texture_get_sub_resource_parent(*texture, 0); 3332 d3d_surface->parent_device = &device->IDirect3DDevice8_iface; 3333 3334 return hr; 3335 } 3336 3337 static HRESULT CDECL device_parent_create_swapchain(struct wined3d_device_parent *device_parent, 3338 struct wined3d_swapchain_desc *desc, struct wined3d_swapchain **swapchain) 3339 { 3340 struct d3d8_device *device = device_from_device_parent(device_parent); 3341 struct d3d8_swapchain *d3d_swapchain; 3342 HRESULT hr; 3343 3344 TRACE("device_parent %p, desc %p, swapchain %p.\n", device_parent, desc, swapchain); 3345 3346 if (FAILED(hr = d3d8_swapchain_create(device, desc, WINED3D_SWAP_INTERVAL_DEFAULT, &d3d_swapchain))) 3347 { 3348 WARN("Failed to create swapchain, hr %#x.\n", hr); 3349 *swapchain = NULL; 3350 return hr; 3351 } 3352 3353 *swapchain = d3d_swapchain->wined3d_swapchain; 3354 wined3d_swapchain_incref(*swapchain); 3355 IDirect3DSwapChain8_Release(&d3d_swapchain->IDirect3DSwapChain8_iface); 3356 3357 return hr; 3358 } 3359 3360 static const struct wined3d_device_parent_ops d3d8_wined3d_device_parent_ops = 3361 { 3362 device_parent_wined3d_device_created, 3363 device_parent_mode_changed, 3364 device_parent_activate, 3365 device_parent_texture_sub_resource_created, 3366 device_parent_create_swapchain_texture, 3367 device_parent_create_swapchain, 3368 }; 3369 3370 static void setup_fpu(void) 3371 { 3372 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) 3373 WORD cw; 3374 __asm__ volatile ("fnstcw %0" : "=m" (cw)); 3375 cw = (cw & ~0xf3f) | 0x3f; 3376 __asm__ volatile ("fldcw %0" : : "m" (cw)); 3377 #elif defined(__i386__) && defined(_MSC_VER) 3378 WORD cw; 3379 __asm fnstcw cw; 3380 cw = (cw & ~0xf3f) | 0x3f; 3381 __asm fldcw cw; 3382 #else 3383 FIXME("FPU setup not implemented for this platform.\n"); 3384 #endif 3385 } 3386 3387 HRESULT device_init(struct d3d8_device *device, struct d3d8 *parent, struct wined3d *wined3d, UINT adapter, 3388 D3DDEVTYPE device_type, HWND focus_window, DWORD flags, D3DPRESENT_PARAMETERS *parameters) 3389 { 3390 struct wined3d_swapchain_desc swapchain_desc; 3391 struct wined3d_swapchain *wined3d_swapchain; 3392 HRESULT hr; 3393 3394 device->IDirect3DDevice8_iface.lpVtbl = &d3d8_device_vtbl; 3395 device->device_parent.ops = &d3d8_wined3d_device_parent_ops; 3396 device->ref = 1; 3397 if (!(device->handle_table.entries = heap_alloc_zero(D3D8_INITIAL_HANDLE_TABLE_SIZE 3398 * sizeof(*device->handle_table.entries)))) 3399 { 3400 ERR("Failed to allocate handle table memory.\n"); 3401 return E_OUTOFMEMORY; 3402 } 3403 device->handle_table.table_size = D3D8_INITIAL_HANDLE_TABLE_SIZE; 3404 3405 if (!(flags & D3DCREATE_FPU_PRESERVE)) setup_fpu(); 3406 3407 wined3d_mutex_lock(); 3408 hr = wined3d_device_create(wined3d, adapter, device_type, focus_window, flags, 4, 3409 &device->device_parent, &device->wined3d_device); 3410 if (FAILED(hr)) 3411 { 3412 WARN("Failed to create wined3d device, hr %#x.\n", hr); 3413 wined3d_mutex_unlock(); 3414 heap_free(device->handle_table.entries); 3415 return hr; 3416 } 3417 3418 if (!parameters->Windowed) 3419 { 3420 HWND device_window = parameters->hDeviceWindow; 3421 3422 if (!focus_window) 3423 focus_window = device_window; 3424 if (FAILED(hr = wined3d_device_acquire_focus_window(device->wined3d_device, focus_window))) 3425 { 3426 ERR("Failed to acquire focus window, hr %#x.\n", hr); 3427 wined3d_device_decref(device->wined3d_device); 3428 wined3d_mutex_unlock(); 3429 heap_free(device->handle_table.entries); 3430 return hr; 3431 } 3432 3433 if (!device_window) 3434 device_window = focus_window; 3435 wined3d_device_setup_fullscreen_window(device->wined3d_device, device_window, 3436 parameters->BackBufferWidth, 3437 parameters->BackBufferHeight); 3438 } 3439 3440 if (flags & D3DCREATE_MULTITHREADED) 3441 wined3d_device_set_multithreaded(device->wined3d_device); 3442 3443 if (!wined3d_swapchain_desc_from_present_parameters(&swapchain_desc, parameters)) 3444 { 3445 wined3d_device_release_focus_window(device->wined3d_device); 3446 wined3d_device_decref(device->wined3d_device); 3447 wined3d_mutex_unlock(); 3448 heap_free(device->handle_table.entries); 3449 return D3DERR_INVALIDCALL; 3450 } 3451 3452 if (FAILED(hr = wined3d_device_init_3d(device->wined3d_device, &swapchain_desc))) 3453 { 3454 WARN("Failed to initialize 3D, hr %#x.\n", hr); 3455 wined3d_device_release_focus_window(device->wined3d_device); 3456 wined3d_device_decref(device->wined3d_device); 3457 wined3d_mutex_unlock(); 3458 heap_free(device->handle_table.entries); 3459 return hr; 3460 } 3461 3462 wined3d_device_set_render_state(device->wined3d_device, 3463 WINED3D_RS_ZENABLE, !!swapchain_desc.enable_auto_depth_stencil); 3464 wined3d_device_set_render_state(device->wined3d_device, WINED3D_RS_POINTSIZE_MIN, 0); 3465 wined3d_mutex_unlock(); 3466 3467 present_parameters_from_wined3d_swapchain_desc(parameters, 3468 &swapchain_desc, parameters->FullScreen_PresentationInterval); 3469 3470 device->declArraySize = 16; 3471 if (!(device->decls = heap_alloc(device->declArraySize * sizeof(*device->decls)))) 3472 { 3473 ERR("Failed to allocate FVF vertex declaration map memory.\n"); 3474 hr = E_OUTOFMEMORY; 3475 goto err; 3476 } 3477 3478 wined3d_swapchain = wined3d_device_get_swapchain(device->wined3d_device, 0); 3479 device->implicit_swapchain = wined3d_swapchain_get_parent(wined3d_swapchain); 3480 device->implicit_swapchain->swap_interval 3481 = wined3dswapinterval_from_d3d(parameters->FullScreen_PresentationInterval); 3482 3483 device->d3d_parent = &parent->IDirect3D8_iface; 3484 IDirect3D8_AddRef(device->d3d_parent); 3485 3486 return D3D_OK; 3487 3488 err: 3489 wined3d_mutex_lock(); 3490 wined3d_device_uninit_3d(device->wined3d_device); 3491 wined3d_device_release_focus_window(device->wined3d_device); 3492 wined3d_device_decref(device->wined3d_device); 3493 wined3d_mutex_unlock(); 3494 heap_free(device->handle_table.entries); 3495 return hr; 3496 } 3497