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