1 /* 2 * Copyright 2002-2005 Jason Edmeades 3 * Copyright 2002-2005 Raphael Junqueira 4 * Copyright 2005 Oliver Stieber 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 19 */ 20 21 #include "config.h" 22 #include "d3d9_private.h" 23 24 WINE_DEFAULT_DEBUG_CHANNEL(d3d9); 25 26 static inline struct d3d9_texture *impl_from_IDirect3DTexture9(IDirect3DTexture9 *iface) 27 { 28 return CONTAINING_RECORD((IDirect3DBaseTexture9 *)iface, struct d3d9_texture, IDirect3DBaseTexture9_iface); 29 } 30 31 static inline struct d3d9_texture *impl_from_IDirect3DCubeTexture9(IDirect3DCubeTexture9 *iface) 32 { 33 return CONTAINING_RECORD((IDirect3DBaseTexture9 *)iface, struct d3d9_texture, IDirect3DBaseTexture9_iface); 34 } 35 36 static inline struct d3d9_texture *impl_from_IDirect3DVolumeTexture9(IDirect3DVolumeTexture9 *iface) 37 { 38 return CONTAINING_RECORD((IDirect3DBaseTexture9 *)iface, struct d3d9_texture, IDirect3DBaseTexture9_iface); 39 } 40 41 static void STDMETHODCALLTYPE srv_wined3d_object_destroyed(void *parent) 42 { 43 struct d3d9_texture *texture = parent; 44 45 texture->wined3d_srv = NULL; 46 } 47 48 static const struct wined3d_parent_ops d3d9_srv_wined3d_parent_ops = 49 { 50 srv_wined3d_object_destroyed, 51 }; 52 53 /* wined3d critical section must be taken by the caller. */ 54 static struct wined3d_shader_resource_view *d3d9_texture_acquire_shader_resource_view(struct d3d9_texture *texture) 55 { 56 struct wined3d_sub_resource_desc sr_desc; 57 struct wined3d_view_desc desc; 58 HRESULT hr; 59 60 if (texture->wined3d_srv) 61 return texture->wined3d_srv; 62 63 wined3d_texture_get_sub_resource_desc(texture->wined3d_texture, 0, &sr_desc); 64 desc.format_id = sr_desc.format; 65 desc.flags = 0; 66 desc.u.texture.level_idx = 0; 67 desc.u.texture.level_count = wined3d_texture_get_level_count(texture->wined3d_texture); 68 desc.u.texture.layer_idx = 0; 69 desc.u.texture.layer_count = sr_desc.usage & WINED3DUSAGE_LEGACY_CUBEMAP ? 6 : 1; 70 if (FAILED(hr = wined3d_shader_resource_view_create(&desc, 71 wined3d_texture_get_resource(texture->wined3d_texture), texture, 72 &d3d9_srv_wined3d_parent_ops, &texture->wined3d_srv))) 73 { 74 ERR("Failed to create shader resource view, hr %#x.\n", hr); 75 return NULL; 76 } 77 78 return texture->wined3d_srv; 79 } 80 81 static void d3d9_texture_cleanup(struct d3d9_texture *texture) 82 { 83 IDirect3DDevice9Ex *parent_device = texture->parent_device; 84 struct d3d9_surface *surface; 85 86 wined3d_mutex_lock(); 87 if (texture->wined3d_srv) 88 wined3d_shader_resource_view_decref(texture->wined3d_srv); 89 LIST_FOR_EACH_ENTRY(surface, &texture->rtv_list, struct d3d9_surface, rtv_entry) 90 wined3d_rendertarget_view_decref(surface->wined3d_rtv); 91 wined3d_texture_decref(texture->wined3d_texture); 92 wined3d_mutex_unlock(); 93 94 /* Release the device last, as it may cause the device to be destroyed. */ 95 IDirect3DDevice9Ex_Release(parent_device); 96 } 97 98 /* wined3d critical section must be taken by the caller. */ 99 void d3d9_texture_gen_auto_mipmap(struct d3d9_texture *texture) 100 { 101 if (!(texture->flags & D3D9_TEXTURE_MIPMAP_DIRTY)) 102 return; 103 d3d9_texture_acquire_shader_resource_view(texture); 104 wined3d_shader_resource_view_generate_mipmaps(texture->wined3d_srv); 105 texture->flags &= ~D3D9_TEXTURE_MIPMAP_DIRTY; 106 } 107 108 void d3d9_texture_flag_auto_gen_mipmap(struct d3d9_texture *texture) 109 { 110 if (texture->usage & D3DUSAGE_AUTOGENMIPMAP) 111 texture->flags |= D3D9_TEXTURE_MIPMAP_DIRTY; 112 } 113 114 static HRESULT WINAPI d3d9_texture_2d_QueryInterface(IDirect3DTexture9 *iface, REFIID riid, void **out) 115 { 116 TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out); 117 118 if (IsEqualGUID(riid, &IID_IDirect3DTexture9) 119 || IsEqualGUID(riid, &IID_IDirect3DBaseTexture9) 120 || IsEqualGUID(riid, &IID_IDirect3DResource9) 121 || IsEqualGUID(riid, &IID_IUnknown)) 122 { 123 IDirect3DTexture9_AddRef(iface); 124 *out = iface; 125 return S_OK; 126 } 127 128 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid)); 129 130 *out = NULL; 131 return E_NOINTERFACE; 132 } 133 134 static ULONG WINAPI d3d9_texture_2d_AddRef(IDirect3DTexture9 *iface) 135 { 136 struct d3d9_texture *texture = impl_from_IDirect3DTexture9(iface); 137 ULONG ref = InterlockedIncrement(&texture->resource.refcount); 138 139 TRACE("%p increasing refcount to %u.\n", iface, ref); 140 141 if (ref == 1) 142 { 143 struct d3d9_surface *surface; 144 145 IDirect3DDevice9Ex_AddRef(texture->parent_device); 146 wined3d_mutex_lock(); 147 LIST_FOR_EACH_ENTRY(surface, &texture->rtv_list, struct d3d9_surface, rtv_entry) 148 { 149 wined3d_rendertarget_view_incref(surface->wined3d_rtv); 150 } 151 wined3d_texture_incref(texture->wined3d_texture); 152 wined3d_mutex_unlock(); 153 } 154 155 return ref; 156 } 157 158 static ULONG WINAPI d3d9_texture_2d_Release(IDirect3DTexture9 *iface) 159 { 160 struct d3d9_texture *texture = impl_from_IDirect3DTexture9(iface); 161 ULONG ref = InterlockedDecrement(&texture->resource.refcount); 162 163 TRACE("%p decreasing refcount to %u.\n", iface, ref); 164 165 if (!ref) 166 d3d9_texture_cleanup(texture); 167 return ref; 168 } 169 170 static HRESULT WINAPI d3d9_texture_2d_GetDevice(IDirect3DTexture9 *iface, IDirect3DDevice9 **device) 171 { 172 struct d3d9_texture *texture = impl_from_IDirect3DTexture9(iface); 173 174 TRACE("iface %p, device %p.\n", iface, device); 175 176 *device = (IDirect3DDevice9 *)texture->parent_device; 177 IDirect3DDevice9_AddRef(*device); 178 179 TRACE("Returning device %p.\n", *device); 180 181 return D3D_OK; 182 } 183 184 static HRESULT WINAPI d3d9_texture_2d_SetPrivateData(IDirect3DTexture9 *iface, 185 REFGUID guid, const void *data, DWORD data_size, DWORD flags) 186 { 187 struct d3d9_texture *texture = impl_from_IDirect3DTexture9(iface); 188 TRACE("iface %p, guid %s, data %p, data_size %u, flags %#x.\n", 189 iface, debugstr_guid(guid), data, data_size, flags); 190 191 return d3d9_resource_set_private_data(&texture->resource, guid, data, data_size, flags); 192 } 193 194 static HRESULT WINAPI d3d9_texture_2d_GetPrivateData(IDirect3DTexture9 *iface, 195 REFGUID guid, void *data, DWORD *data_size) 196 { 197 struct d3d9_texture *texture = impl_from_IDirect3DTexture9(iface); 198 TRACE("iface %p, guid %s, data %p, data_size %p.\n", 199 iface, debugstr_guid(guid), data, data_size); 200 201 return d3d9_resource_get_private_data(&texture->resource, guid, data, data_size); 202 } 203 204 static HRESULT WINAPI d3d9_texture_2d_FreePrivateData(IDirect3DTexture9 *iface, REFGUID guid) 205 { 206 struct d3d9_texture *texture = impl_from_IDirect3DTexture9(iface); 207 TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid)); 208 209 return d3d9_resource_free_private_data(&texture->resource, guid); 210 } 211 212 static DWORD WINAPI d3d9_texture_2d_SetPriority(IDirect3DTexture9 *iface, DWORD priority) 213 { 214 struct d3d9_texture *texture = impl_from_IDirect3DTexture9(iface); 215 struct wined3d_resource *resource; 216 DWORD ret; 217 218 TRACE("iface %p, priority %u.\n", iface, priority); 219 220 wined3d_mutex_lock(); 221 resource = wined3d_texture_get_resource(texture->wined3d_texture); 222 ret = wined3d_resource_set_priority(resource, priority); 223 wined3d_mutex_unlock(); 224 225 return ret; 226 } 227 228 static DWORD WINAPI d3d9_texture_2d_GetPriority(IDirect3DTexture9 *iface) 229 { 230 struct d3d9_texture *texture = impl_from_IDirect3DTexture9(iface); 231 const struct wined3d_resource *resource; 232 DWORD ret; 233 234 TRACE("iface %p.\n", iface); 235 236 wined3d_mutex_lock(); 237 resource = wined3d_texture_get_resource(texture->wined3d_texture); 238 ret = wined3d_resource_get_priority(resource); 239 wined3d_mutex_unlock(); 240 241 return ret; 242 } 243 244 static void WINAPI d3d9_texture_2d_PreLoad(IDirect3DTexture9 *iface) 245 { 246 struct d3d9_texture *texture = impl_from_IDirect3DTexture9(iface); 247 248 TRACE("iface %p.\n", iface); 249 250 wined3d_mutex_lock(); 251 wined3d_resource_preload(wined3d_texture_get_resource(texture->wined3d_texture)); 252 wined3d_mutex_unlock(); 253 } 254 255 static D3DRESOURCETYPE WINAPI d3d9_texture_2d_GetType(IDirect3DTexture9 *iface) 256 { 257 TRACE("iface %p.\n", iface); 258 259 return D3DRTYPE_TEXTURE; 260 } 261 262 static DWORD WINAPI d3d9_texture_2d_SetLOD(IDirect3DTexture9 *iface, DWORD lod) 263 { 264 struct d3d9_texture *texture = impl_from_IDirect3DTexture9(iface); 265 DWORD ret; 266 267 TRACE("iface %p, lod %u.\n", iface, lod); 268 269 wined3d_mutex_lock(); 270 ret = wined3d_texture_set_lod(texture->wined3d_texture, lod); 271 wined3d_mutex_unlock(); 272 273 return ret; 274 } 275 276 static DWORD WINAPI d3d9_texture_2d_GetLOD(IDirect3DTexture9 *iface) 277 { 278 struct d3d9_texture *texture = impl_from_IDirect3DTexture9(iface); 279 DWORD ret; 280 281 TRACE("iface %p.\n", iface); 282 283 wined3d_mutex_lock(); 284 ret = wined3d_texture_get_lod(texture->wined3d_texture); 285 wined3d_mutex_unlock(); 286 287 return ret; 288 } 289 290 static DWORD WINAPI d3d9_texture_2d_GetLevelCount(IDirect3DTexture9 *iface) 291 { 292 struct d3d9_texture *texture = impl_from_IDirect3DTexture9(iface); 293 DWORD ret; 294 295 TRACE("iface %p.\n", iface); 296 297 if (texture->usage & D3DUSAGE_AUTOGENMIPMAP) 298 return 1; 299 300 wined3d_mutex_lock(); 301 ret = wined3d_texture_get_level_count(texture->wined3d_texture); 302 wined3d_mutex_unlock(); 303 304 return ret; 305 } 306 307 static HRESULT WINAPI d3d9_texture_2d_SetAutoGenFilterType(IDirect3DTexture9 *iface, D3DTEXTUREFILTERTYPE filter_type) 308 { 309 struct d3d9_texture *texture = impl_from_IDirect3DTexture9(iface); 310 311 TRACE("iface %p, filter_type %#x.\n", iface, filter_type); 312 313 if (filter_type == D3DTEXF_NONE) 314 { 315 WARN("Invalid filter type D3DTEXF_NONE specified.\n"); 316 return D3DERR_INVALIDCALL; 317 } 318 if (!(texture->usage & D3DUSAGE_AUTOGENMIPMAP)) 319 WARN("Called on a texture without the D3DUSAGE_AUTOGENMIPMAP flag.\n"); 320 else if (filter_type != D3DTEXF_LINEAR) 321 FIXME("Unsupported filter type %u.\n", filter_type); 322 323 texture->autogen_filter_type = filter_type; 324 return D3D_OK; 325 } 326 327 static D3DTEXTUREFILTERTYPE WINAPI d3d9_texture_2d_GetAutoGenFilterType(IDirect3DTexture9 *iface) 328 { 329 struct d3d9_texture *texture = impl_from_IDirect3DTexture9(iface); 330 331 TRACE("iface %p.\n", iface); 332 333 if (!(texture->usage & D3DUSAGE_AUTOGENMIPMAP)) 334 WARN("Called on a texture without the D3DUSAGE_AUTOGENMIPMAP flag.\n"); 335 336 return texture->autogen_filter_type; 337 } 338 339 static void WINAPI d3d9_texture_2d_GenerateMipSubLevels(IDirect3DTexture9 *iface) 340 { 341 struct d3d9_texture *texture = impl_from_IDirect3DTexture9(iface); 342 343 TRACE("iface %p.\n", iface); 344 345 wined3d_mutex_lock(); 346 d3d9_texture_gen_auto_mipmap(texture); 347 wined3d_mutex_unlock(); 348 } 349 350 static HRESULT WINAPI d3d9_texture_2d_GetLevelDesc(IDirect3DTexture9 *iface, UINT level, D3DSURFACE_DESC *desc) 351 { 352 struct d3d9_texture *texture = impl_from_IDirect3DTexture9(iface); 353 struct wined3d_sub_resource_desc wined3d_desc; 354 HRESULT hr; 355 356 TRACE("iface %p, level %u, desc %p.\n", iface, level, desc); 357 358 if (texture->usage & D3DUSAGE_AUTOGENMIPMAP && level) 359 { 360 WARN("D3DUSAGE_AUTOGENMIPMAP textures have only one accessible level.\n"); 361 return D3DERR_INVALIDCALL; 362 } 363 364 wined3d_mutex_lock(); 365 if (SUCCEEDED(hr = wined3d_texture_get_sub_resource_desc(texture->wined3d_texture, level, &wined3d_desc))) 366 { 367 desc->Format = d3dformat_from_wined3dformat(wined3d_desc.format); 368 desc->Type = D3DRTYPE_SURFACE; 369 desc->Usage = texture->usage; 370 desc->Pool = d3dpool_from_wined3daccess(wined3d_desc.access, wined3d_desc.usage); 371 desc->MultiSampleType = wined3d_desc.multisample_type; 372 desc->MultiSampleQuality = wined3d_desc.multisample_quality; 373 desc->Width = wined3d_desc.width; 374 desc->Height = wined3d_desc.height; 375 } 376 wined3d_mutex_unlock(); 377 378 return hr; 379 } 380 381 static HRESULT WINAPI d3d9_texture_2d_GetSurfaceLevel(IDirect3DTexture9 *iface, 382 UINT level, IDirect3DSurface9 **surface) 383 { 384 struct d3d9_texture *texture = impl_from_IDirect3DTexture9(iface); 385 struct d3d9_surface *surface_impl; 386 387 TRACE("iface %p, level %u, surface %p.\n", iface, level, surface); 388 389 if (texture->usage & D3DUSAGE_AUTOGENMIPMAP && level) 390 { 391 WARN("D3DUSAGE_AUTOGENMIPMAP textures have only one accessible level.\n"); 392 return D3DERR_INVALIDCALL; 393 } 394 395 wined3d_mutex_lock(); 396 if (!(surface_impl = wined3d_texture_get_sub_resource_parent(texture->wined3d_texture, level))) 397 { 398 wined3d_mutex_unlock(); 399 return D3DERR_INVALIDCALL; 400 } 401 402 *surface = &surface_impl->IDirect3DSurface9_iface; 403 IDirect3DSurface9_AddRef(*surface); 404 wined3d_mutex_unlock(); 405 406 return D3D_OK; 407 } 408 409 static HRESULT WINAPI d3d9_texture_2d_LockRect(IDirect3DTexture9 *iface, 410 UINT level, D3DLOCKED_RECT *locked_rect, const RECT *rect, DWORD flags) 411 { 412 struct d3d9_texture *texture = impl_from_IDirect3DTexture9(iface); 413 struct d3d9_surface *surface_impl; 414 HRESULT hr; 415 416 TRACE("iface %p, level %u, locked_rect %p, rect %p, flags %#x.\n", 417 iface, level, locked_rect, rect, flags); 418 419 if (texture->usage & D3DUSAGE_AUTOGENMIPMAP && level) 420 { 421 WARN("D3DUSAGE_AUTOGENMIPMAP textures have only one accessible level.\n"); 422 return D3DERR_INVALIDCALL; 423 } 424 425 wined3d_mutex_lock(); 426 if (!(surface_impl = wined3d_texture_get_sub_resource_parent(texture->wined3d_texture, level))) 427 hr = D3DERR_INVALIDCALL; 428 else 429 hr = IDirect3DSurface9_LockRect(&surface_impl->IDirect3DSurface9_iface, locked_rect, rect, flags); 430 wined3d_mutex_unlock(); 431 432 return hr; 433 } 434 435 static HRESULT WINAPI d3d9_texture_2d_UnlockRect(IDirect3DTexture9 *iface, UINT level) 436 { 437 struct d3d9_texture *texture = impl_from_IDirect3DTexture9(iface); 438 struct d3d9_surface *surface_impl; 439 HRESULT hr; 440 441 TRACE("iface %p, level %u.\n", iface, level); 442 443 if (texture->usage & D3DUSAGE_AUTOGENMIPMAP && level) 444 { 445 WARN("D3DUSAGE_AUTOGENMIPMAP textures have only one accessible level.\n"); 446 return D3DERR_INVALIDCALL; 447 } 448 449 wined3d_mutex_lock(); 450 if (!(surface_impl = wined3d_texture_get_sub_resource_parent(texture->wined3d_texture, level))) 451 hr = D3DERR_INVALIDCALL; 452 else 453 hr = IDirect3DSurface9_UnlockRect(&surface_impl->IDirect3DSurface9_iface); 454 wined3d_mutex_unlock(); 455 456 return hr; 457 } 458 459 static HRESULT WINAPI d3d9_texture_2d_AddDirtyRect(IDirect3DTexture9 *iface, const RECT *dirty_rect) 460 { 461 struct d3d9_texture *texture = impl_from_IDirect3DTexture9(iface); 462 HRESULT hr; 463 464 TRACE("iface %p, dirty_rect %s.\n", 465 iface, wine_dbgstr_rect(dirty_rect)); 466 467 wined3d_mutex_lock(); 468 if (!dirty_rect) 469 hr = wined3d_texture_add_dirty_region(texture->wined3d_texture, 0, NULL); 470 else 471 { 472 struct wined3d_box dirty_region; 473 474 wined3d_box_set(&dirty_region, dirty_rect->left, dirty_rect->top, dirty_rect->right, dirty_rect->bottom, 0, 1); 475 hr = wined3d_texture_add_dirty_region(texture->wined3d_texture, 0, &dirty_region); 476 } 477 wined3d_mutex_unlock(); 478 479 return hr; 480 } 481 482 static const IDirect3DTexture9Vtbl d3d9_texture_2d_vtbl = 483 { 484 /* IUnknown */ 485 d3d9_texture_2d_QueryInterface, 486 d3d9_texture_2d_AddRef, 487 d3d9_texture_2d_Release, 488 /* IDirect3DResource9 */ 489 d3d9_texture_2d_GetDevice, 490 d3d9_texture_2d_SetPrivateData, 491 d3d9_texture_2d_GetPrivateData, 492 d3d9_texture_2d_FreePrivateData, 493 d3d9_texture_2d_SetPriority, 494 d3d9_texture_2d_GetPriority, 495 d3d9_texture_2d_PreLoad, 496 d3d9_texture_2d_GetType, 497 /* IDirect3dBaseTexture9 */ 498 d3d9_texture_2d_SetLOD, 499 d3d9_texture_2d_GetLOD, 500 d3d9_texture_2d_GetLevelCount, 501 d3d9_texture_2d_SetAutoGenFilterType, 502 d3d9_texture_2d_GetAutoGenFilterType, 503 d3d9_texture_2d_GenerateMipSubLevels, 504 /* IDirect3DTexture9 */ 505 d3d9_texture_2d_GetLevelDesc, 506 d3d9_texture_2d_GetSurfaceLevel, 507 d3d9_texture_2d_LockRect, 508 d3d9_texture_2d_UnlockRect, 509 d3d9_texture_2d_AddDirtyRect, 510 }; 511 512 static HRESULT WINAPI d3d9_texture_cube_QueryInterface(IDirect3DCubeTexture9 *iface, REFIID riid, void **out) 513 { 514 TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out); 515 516 if (IsEqualGUID(riid, &IID_IDirect3DCubeTexture9) 517 || IsEqualGUID(riid, &IID_IDirect3DBaseTexture9) 518 || IsEqualGUID(riid, &IID_IDirect3DResource9) 519 || IsEqualGUID(riid, &IID_IUnknown)) 520 { 521 IDirect3DCubeTexture9_AddRef(iface); 522 *out = iface; 523 return S_OK; 524 } 525 526 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid)); 527 528 *out = NULL; 529 return E_NOINTERFACE; 530 } 531 532 static ULONG WINAPI d3d9_texture_cube_AddRef(IDirect3DCubeTexture9 *iface) 533 { 534 struct d3d9_texture *texture = impl_from_IDirect3DCubeTexture9(iface); 535 ULONG ref = InterlockedIncrement(&texture->resource.refcount); 536 537 TRACE("%p increasing refcount to %u.\n", iface, ref); 538 539 if (ref == 1) 540 { 541 struct d3d9_surface *surface; 542 543 IDirect3DDevice9Ex_AddRef(texture->parent_device); 544 wined3d_mutex_lock(); 545 LIST_FOR_EACH_ENTRY(surface, &texture->rtv_list, struct d3d9_surface, rtv_entry) 546 { 547 wined3d_rendertarget_view_decref(surface->wined3d_rtv); 548 } 549 wined3d_texture_incref(texture->wined3d_texture); 550 wined3d_mutex_unlock(); 551 } 552 553 return ref; 554 } 555 556 static ULONG WINAPI d3d9_texture_cube_Release(IDirect3DCubeTexture9 *iface) 557 { 558 struct d3d9_texture *texture = impl_from_IDirect3DCubeTexture9(iface); 559 ULONG ref = InterlockedDecrement(&texture->resource.refcount); 560 561 TRACE("%p decreasing refcount to %u.\n", iface, ref); 562 563 if (!ref) 564 d3d9_texture_cleanup(texture); 565 return ref; 566 } 567 568 static HRESULT WINAPI d3d9_texture_cube_GetDevice(IDirect3DCubeTexture9 *iface, IDirect3DDevice9 **device) 569 { 570 struct d3d9_texture *texture = impl_from_IDirect3DCubeTexture9(iface); 571 572 TRACE("iface %p, device %p.\n", iface, device); 573 574 *device = (IDirect3DDevice9 *)texture->parent_device; 575 IDirect3DDevice9_AddRef(*device); 576 577 TRACE("Returning device %p.\n", *device); 578 579 return D3D_OK; 580 } 581 582 static HRESULT WINAPI d3d9_texture_cube_SetPrivateData(IDirect3DCubeTexture9 *iface, 583 REFGUID guid, const void *data, DWORD data_size, DWORD flags) 584 { 585 struct d3d9_texture *texture = impl_from_IDirect3DCubeTexture9(iface); 586 TRACE("iface %p, guid %s, data %p, data_size %u, flags %#x.\n", 587 iface, debugstr_guid(guid), data, data_size, flags); 588 589 return d3d9_resource_set_private_data(&texture->resource, guid, data, data_size, flags); 590 } 591 592 static HRESULT WINAPI d3d9_texture_cube_GetPrivateData(IDirect3DCubeTexture9 *iface, 593 REFGUID guid, void *data, DWORD *data_size) 594 { 595 struct d3d9_texture *texture = impl_from_IDirect3DCubeTexture9(iface); 596 TRACE("iface %p, guid %s, data %p, data_size %p.\n", 597 iface, debugstr_guid(guid), data, data_size); 598 599 return d3d9_resource_get_private_data(&texture->resource, guid, data, data_size); 600 } 601 602 static HRESULT WINAPI d3d9_texture_cube_FreePrivateData(IDirect3DCubeTexture9 *iface, REFGUID guid) 603 { 604 struct d3d9_texture *texture = impl_from_IDirect3DCubeTexture9(iface); 605 TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid)); 606 607 return d3d9_resource_free_private_data(&texture->resource, guid); 608 } 609 610 static DWORD WINAPI d3d9_texture_cube_SetPriority(IDirect3DCubeTexture9 *iface, DWORD priority) 611 { 612 struct d3d9_texture *texture = impl_from_IDirect3DCubeTexture9(iface); 613 struct wined3d_resource *resource; 614 DWORD ret; 615 616 TRACE("iface %p, priority %u.\n", iface, priority); 617 618 wined3d_mutex_lock(); 619 resource = wined3d_texture_get_resource(texture->wined3d_texture); 620 ret = wined3d_resource_set_priority(resource, priority); 621 wined3d_mutex_unlock(); 622 623 return ret; 624 } 625 626 static DWORD WINAPI d3d9_texture_cube_GetPriority(IDirect3DCubeTexture9 *iface) 627 { 628 struct d3d9_texture *texture = impl_from_IDirect3DCubeTexture9(iface); 629 const struct wined3d_resource *resource; 630 DWORD ret; 631 632 TRACE("iface %p.\n", iface); 633 634 wined3d_mutex_lock(); 635 resource = wined3d_texture_get_resource(texture->wined3d_texture); 636 ret = wined3d_resource_get_priority(resource); 637 wined3d_mutex_unlock(); 638 639 return ret; 640 } 641 642 static void WINAPI d3d9_texture_cube_PreLoad(IDirect3DCubeTexture9 *iface) 643 { 644 struct d3d9_texture *texture = impl_from_IDirect3DCubeTexture9(iface); 645 646 TRACE("iface %p.\n", iface); 647 648 wined3d_mutex_lock(); 649 wined3d_resource_preload(wined3d_texture_get_resource(texture->wined3d_texture)); 650 wined3d_mutex_unlock(); 651 } 652 653 static D3DRESOURCETYPE WINAPI d3d9_texture_cube_GetType(IDirect3DCubeTexture9 *iface) 654 { 655 TRACE("iface %p.\n", iface); 656 657 return D3DRTYPE_CUBETEXTURE; 658 } 659 660 static DWORD WINAPI d3d9_texture_cube_SetLOD(IDirect3DCubeTexture9 *iface, DWORD lod) 661 { 662 struct d3d9_texture *texture = impl_from_IDirect3DCubeTexture9(iface); 663 DWORD ret; 664 665 TRACE("iface %p, lod %u.\n", iface, lod); 666 667 wined3d_mutex_lock(); 668 ret = wined3d_texture_set_lod(texture->wined3d_texture, lod); 669 wined3d_mutex_unlock(); 670 671 return ret; 672 } 673 674 static DWORD WINAPI d3d9_texture_cube_GetLOD(IDirect3DCubeTexture9 *iface) 675 { 676 struct d3d9_texture *texture = impl_from_IDirect3DCubeTexture9(iface); 677 DWORD ret; 678 679 TRACE("iface %p.\n", iface); 680 681 wined3d_mutex_lock(); 682 ret = wined3d_texture_get_lod(texture->wined3d_texture); 683 wined3d_mutex_unlock(); 684 685 return ret; 686 } 687 688 static DWORD WINAPI d3d9_texture_cube_GetLevelCount(IDirect3DCubeTexture9 *iface) 689 { 690 struct d3d9_texture *texture = impl_from_IDirect3DCubeTexture9(iface); 691 DWORD ret; 692 693 TRACE("iface %p.\n", iface); 694 695 if (texture->usage & D3DUSAGE_AUTOGENMIPMAP) 696 return 1; 697 698 wined3d_mutex_lock(); 699 ret = wined3d_texture_get_level_count(texture->wined3d_texture); 700 wined3d_mutex_unlock(); 701 702 return ret; 703 } 704 705 static HRESULT WINAPI d3d9_texture_cube_SetAutoGenFilterType(IDirect3DCubeTexture9 *iface, 706 D3DTEXTUREFILTERTYPE filter_type) 707 { 708 struct d3d9_texture *texture = impl_from_IDirect3DCubeTexture9(iface); 709 710 TRACE("iface %p, filter_type %#x.\n", iface, filter_type); 711 712 if (filter_type == D3DTEXF_NONE) 713 { 714 WARN("Invalid filter type D3DTEXF_NONE specified.\n"); 715 return D3DERR_INVALIDCALL; 716 } 717 if (!(texture->usage & D3DUSAGE_AUTOGENMIPMAP)) 718 WARN("Called on a texture without the D3DUSAGE_AUTOGENMIPMAP flag.\n"); 719 else if (filter_type != D3DTEXF_LINEAR) 720 FIXME("Unsupported filter type %u.\n", filter_type); 721 722 texture->autogen_filter_type = filter_type; 723 return D3D_OK; 724 } 725 726 static D3DTEXTUREFILTERTYPE WINAPI d3d9_texture_cube_GetAutoGenFilterType(IDirect3DCubeTexture9 *iface) 727 { 728 struct d3d9_texture *texture = impl_from_IDirect3DCubeTexture9(iface); 729 730 TRACE("iface %p.\n", iface); 731 732 if (!(texture->usage & D3DUSAGE_AUTOGENMIPMAP)) 733 WARN("Called on a texture without the D3DUSAGE_AUTOGENMIPMAP flag.\n"); 734 735 return texture->autogen_filter_type; 736 } 737 738 static void WINAPI d3d9_texture_cube_GenerateMipSubLevels(IDirect3DCubeTexture9 *iface) 739 { 740 struct d3d9_texture *texture = impl_from_IDirect3DCubeTexture9(iface); 741 742 TRACE("iface %p.\n", iface); 743 744 wined3d_mutex_lock(); 745 d3d9_texture_gen_auto_mipmap(texture); 746 wined3d_mutex_unlock(); 747 } 748 749 static HRESULT WINAPI d3d9_texture_cube_GetLevelDesc(IDirect3DCubeTexture9 *iface, UINT level, D3DSURFACE_DESC *desc) 750 { 751 struct d3d9_texture *texture = impl_from_IDirect3DCubeTexture9(iface); 752 struct wined3d_sub_resource_desc wined3d_desc; 753 DWORD level_count; 754 HRESULT hr; 755 756 TRACE("iface %p, level %u, desc %p.\n", iface, level, desc); 757 758 if (texture->usage & D3DUSAGE_AUTOGENMIPMAP && level) 759 { 760 WARN("D3DUSAGE_AUTOGENMIPMAP textures have only one accessible level.\n"); 761 return D3DERR_INVALIDCALL; 762 } 763 764 wined3d_mutex_lock(); 765 level_count = wined3d_texture_get_level_count(texture->wined3d_texture); 766 if (level >= level_count) 767 { 768 wined3d_mutex_unlock(); 769 return D3DERR_INVALIDCALL; 770 } 771 772 if (SUCCEEDED(hr = wined3d_texture_get_sub_resource_desc(texture->wined3d_texture, level, &wined3d_desc))) 773 { 774 desc->Format = d3dformat_from_wined3dformat(wined3d_desc.format); 775 desc->Type = D3DRTYPE_SURFACE; 776 desc->Usage = texture->usage; 777 desc->Pool = d3dpool_from_wined3daccess(wined3d_desc.access, wined3d_desc.usage); 778 desc->MultiSampleType = wined3d_desc.multisample_type; 779 desc->MultiSampleQuality = wined3d_desc.multisample_quality; 780 desc->Width = wined3d_desc.width; 781 desc->Height = wined3d_desc.height; 782 } 783 wined3d_mutex_unlock(); 784 785 return hr; 786 } 787 788 static HRESULT WINAPI d3d9_texture_cube_GetCubeMapSurface(IDirect3DCubeTexture9 *iface, 789 D3DCUBEMAP_FACES face, UINT level, IDirect3DSurface9 **surface) 790 { 791 struct d3d9_texture *texture = impl_from_IDirect3DCubeTexture9(iface); 792 struct d3d9_surface *surface_impl; 793 UINT sub_resource_idx; 794 DWORD level_count; 795 796 TRACE("iface %p, face %#x, level %u, surface %p.\n", iface, face, level, surface); 797 798 if (texture->usage & D3DUSAGE_AUTOGENMIPMAP && level) 799 { 800 WARN("D3DUSAGE_AUTOGENMIPMAP textures have only one accessible level.\n"); 801 return D3DERR_INVALIDCALL; 802 } 803 804 wined3d_mutex_lock(); 805 level_count = wined3d_texture_get_level_count(texture->wined3d_texture); 806 if (level >= level_count) 807 { 808 wined3d_mutex_unlock(); 809 return D3DERR_INVALIDCALL; 810 } 811 812 sub_resource_idx = level_count * face + level; 813 if (!(surface_impl = wined3d_texture_get_sub_resource_parent(texture->wined3d_texture, sub_resource_idx))) 814 { 815 wined3d_mutex_unlock(); 816 return D3DERR_INVALIDCALL; 817 } 818 819 *surface = &surface_impl->IDirect3DSurface9_iface; 820 IDirect3DSurface9_AddRef(*surface); 821 wined3d_mutex_unlock(); 822 823 return D3D_OK; 824 } 825 826 static HRESULT WINAPI d3d9_texture_cube_LockRect(IDirect3DCubeTexture9 *iface, 827 D3DCUBEMAP_FACES face, UINT level, D3DLOCKED_RECT *locked_rect, const RECT *rect, 828 DWORD flags) 829 { 830 struct d3d9_texture *texture = impl_from_IDirect3DCubeTexture9(iface); 831 struct d3d9_surface *surface_impl; 832 UINT sub_resource_idx; 833 HRESULT hr; 834 835 TRACE("iface %p, face %#x, level %u, locked_rect %p, rect %p, flags %#x.\n", 836 iface, face, level, locked_rect, rect, flags); 837 838 if (texture->usage & D3DUSAGE_AUTOGENMIPMAP && level) 839 { 840 WARN("D3DUSAGE_AUTOGENMIPMAP textures have only one accessible level.\n"); 841 return D3DERR_INVALIDCALL; 842 } 843 844 wined3d_mutex_lock(); 845 sub_resource_idx = wined3d_texture_get_level_count(texture->wined3d_texture) * face + level; 846 if (!(surface_impl = wined3d_texture_get_sub_resource_parent(texture->wined3d_texture, sub_resource_idx))) 847 hr = D3DERR_INVALIDCALL; 848 else 849 hr = IDirect3DSurface9_LockRect(&surface_impl->IDirect3DSurface9_iface, locked_rect, rect, flags); 850 wined3d_mutex_unlock(); 851 852 return hr; 853 } 854 855 static HRESULT WINAPI d3d9_texture_cube_UnlockRect(IDirect3DCubeTexture9 *iface, 856 D3DCUBEMAP_FACES face, UINT level) 857 { 858 struct d3d9_texture *texture = impl_from_IDirect3DCubeTexture9(iface); 859 struct d3d9_surface *surface_impl; 860 UINT sub_resource_idx; 861 HRESULT hr; 862 863 TRACE("iface %p, face %#x, level %u.\n", iface, face, level); 864 865 if (texture->usage & D3DUSAGE_AUTOGENMIPMAP && level) 866 { 867 WARN("D3DUSAGE_AUTOGENMIPMAP textures have only one accessible level.\n"); 868 return D3DERR_INVALIDCALL; 869 } 870 871 wined3d_mutex_lock(); 872 sub_resource_idx = wined3d_texture_get_level_count(texture->wined3d_texture) * face + level; 873 if (!(surface_impl = wined3d_texture_get_sub_resource_parent(texture->wined3d_texture, sub_resource_idx))) 874 hr = D3DERR_INVALIDCALL; 875 else 876 hr = IDirect3DSurface9_UnlockRect(&surface_impl->IDirect3DSurface9_iface); 877 wined3d_mutex_unlock(); 878 879 return hr; 880 } 881 882 static HRESULT WINAPI d3d9_texture_cube_AddDirtyRect(IDirect3DCubeTexture9 *iface, 883 D3DCUBEMAP_FACES face, const RECT *dirty_rect) 884 { 885 struct d3d9_texture *texture = impl_from_IDirect3DCubeTexture9(iface); 886 HRESULT hr; 887 888 TRACE("iface %p, face %#x, dirty_rect %s.\n", 889 iface, face, wine_dbgstr_rect(dirty_rect)); 890 891 wined3d_mutex_lock(); 892 if (!dirty_rect) 893 hr = wined3d_texture_add_dirty_region(texture->wined3d_texture, face, NULL); 894 else 895 { 896 struct wined3d_box dirty_region; 897 898 wined3d_box_set(&dirty_region, dirty_rect->left, dirty_rect->top, dirty_rect->right, dirty_rect->bottom, 0, 1); 899 hr = wined3d_texture_add_dirty_region(texture->wined3d_texture, face, &dirty_region); 900 } 901 wined3d_mutex_unlock(); 902 903 return hr; 904 } 905 906 static const IDirect3DCubeTexture9Vtbl d3d9_texture_cube_vtbl = 907 { 908 /* IUnknown */ 909 d3d9_texture_cube_QueryInterface, 910 d3d9_texture_cube_AddRef, 911 d3d9_texture_cube_Release, 912 /* IDirect3DResource9 */ 913 d3d9_texture_cube_GetDevice, 914 d3d9_texture_cube_SetPrivateData, 915 d3d9_texture_cube_GetPrivateData, 916 d3d9_texture_cube_FreePrivateData, 917 d3d9_texture_cube_SetPriority, 918 d3d9_texture_cube_GetPriority, 919 d3d9_texture_cube_PreLoad, 920 d3d9_texture_cube_GetType, 921 /* IDirect3DBaseTexture9 */ 922 d3d9_texture_cube_SetLOD, 923 d3d9_texture_cube_GetLOD, 924 d3d9_texture_cube_GetLevelCount, 925 d3d9_texture_cube_SetAutoGenFilterType, 926 d3d9_texture_cube_GetAutoGenFilterType, 927 d3d9_texture_cube_GenerateMipSubLevels, 928 /* IDirect3DCubeTexture9 */ 929 d3d9_texture_cube_GetLevelDesc, 930 d3d9_texture_cube_GetCubeMapSurface, 931 d3d9_texture_cube_LockRect, 932 d3d9_texture_cube_UnlockRect, 933 d3d9_texture_cube_AddDirtyRect, 934 }; 935 936 static HRESULT WINAPI d3d9_texture_3d_QueryInterface(IDirect3DVolumeTexture9 *iface, REFIID riid, void **out) 937 { 938 TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out); 939 940 if (IsEqualGUID(riid, &IID_IDirect3DVolumeTexture9) 941 || IsEqualGUID(riid, &IID_IDirect3DBaseTexture9) 942 || IsEqualGUID(riid, &IID_IDirect3DResource9) 943 || IsEqualGUID(riid, &IID_IUnknown)) 944 { 945 IDirect3DVolumeTexture9_AddRef(iface); 946 *out = iface; 947 return S_OK; 948 } 949 950 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid)); 951 952 *out = NULL; 953 return E_NOINTERFACE; 954 } 955 956 static ULONG WINAPI d3d9_texture_3d_AddRef(IDirect3DVolumeTexture9 *iface) 957 { 958 struct d3d9_texture *texture = impl_from_IDirect3DVolumeTexture9(iface); 959 ULONG ref = InterlockedIncrement(&texture->resource.refcount); 960 961 TRACE("%p increasing refcount to %u.\n", iface, ref); 962 963 if (ref == 1) 964 { 965 IDirect3DDevice9Ex_AddRef(texture->parent_device); 966 wined3d_mutex_lock(); 967 wined3d_texture_incref(texture->wined3d_texture); 968 wined3d_mutex_unlock(); 969 } 970 971 return ref; 972 } 973 974 static ULONG WINAPI d3d9_texture_3d_Release(IDirect3DVolumeTexture9 *iface) 975 { 976 struct d3d9_texture *texture = impl_from_IDirect3DVolumeTexture9(iface); 977 ULONG ref = InterlockedDecrement(&texture->resource.refcount); 978 979 TRACE("%p decreasing refcount to %u.\n", iface, ref); 980 981 if (!ref) 982 d3d9_texture_cleanup(texture); 983 return ref; 984 } 985 986 static HRESULT WINAPI d3d9_texture_3d_GetDevice(IDirect3DVolumeTexture9 *iface, IDirect3DDevice9 **device) 987 { 988 struct d3d9_texture *texture = impl_from_IDirect3DVolumeTexture9(iface); 989 990 TRACE("iface %p, device %p.\n", iface, device); 991 992 *device = (IDirect3DDevice9 *)texture->parent_device; 993 IDirect3DDevice9_AddRef(*device); 994 995 TRACE("Returning device %p.\n", *device); 996 997 return D3D_OK; 998 } 999 1000 static HRESULT WINAPI d3d9_texture_3d_SetPrivateData(IDirect3DVolumeTexture9 *iface, 1001 REFGUID guid, const void *data, DWORD data_size, DWORD flags) 1002 { 1003 struct d3d9_texture *texture = impl_from_IDirect3DVolumeTexture9(iface); 1004 TRACE("iface %p, guid %s, data %p, data_size %u, flags %#x.\n", 1005 iface, debugstr_guid(guid), data, data_size, flags); 1006 1007 return d3d9_resource_set_private_data(&texture->resource, guid, data, data_size, flags); 1008 } 1009 1010 static HRESULT WINAPI d3d9_texture_3d_GetPrivateData(IDirect3DVolumeTexture9 *iface, 1011 REFGUID guid, void *data, DWORD *data_size) 1012 { 1013 struct d3d9_texture *texture = impl_from_IDirect3DVolumeTexture9(iface); 1014 TRACE("iface %p, guid %s, data %p, data_size %p.\n", 1015 iface, debugstr_guid(guid), data, data_size); 1016 1017 return d3d9_resource_get_private_data(&texture->resource, guid, data, data_size); 1018 } 1019 1020 static HRESULT WINAPI d3d9_texture_3d_FreePrivateData(IDirect3DVolumeTexture9 *iface, REFGUID guid) 1021 { 1022 struct d3d9_texture *texture = impl_from_IDirect3DVolumeTexture9(iface); 1023 TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid)); 1024 1025 return d3d9_resource_free_private_data(&texture->resource, guid); 1026 } 1027 1028 static DWORD WINAPI d3d9_texture_3d_SetPriority(IDirect3DVolumeTexture9 *iface, DWORD priority) 1029 { 1030 struct d3d9_texture *texture = impl_from_IDirect3DVolumeTexture9(iface); 1031 struct wined3d_resource *resource; 1032 DWORD ret; 1033 1034 TRACE("iface %p, priority %u.\n", iface, priority); 1035 1036 wined3d_mutex_lock(); 1037 resource = wined3d_texture_get_resource(texture->wined3d_texture); 1038 ret = wined3d_resource_set_priority(resource, priority); 1039 wined3d_mutex_unlock(); 1040 1041 return ret; 1042 } 1043 1044 static DWORD WINAPI d3d9_texture_3d_GetPriority(IDirect3DVolumeTexture9 *iface) 1045 { 1046 struct d3d9_texture *texture = impl_from_IDirect3DVolumeTexture9(iface); 1047 const struct wined3d_resource *resource; 1048 DWORD ret; 1049 1050 TRACE("iface %p.\n", iface); 1051 1052 wined3d_mutex_lock(); 1053 resource = wined3d_texture_get_resource(texture->wined3d_texture); 1054 ret = wined3d_resource_get_priority(resource); 1055 wined3d_mutex_unlock(); 1056 1057 return ret; 1058 } 1059 1060 static void WINAPI d3d9_texture_3d_PreLoad(IDirect3DVolumeTexture9 *iface) 1061 { 1062 struct d3d9_texture *texture = impl_from_IDirect3DVolumeTexture9(iface); 1063 1064 TRACE("iface %p.\n", iface); 1065 1066 wined3d_mutex_lock(); 1067 wined3d_resource_preload(wined3d_texture_get_resource(texture->wined3d_texture)); 1068 wined3d_mutex_unlock(); 1069 } 1070 1071 static D3DRESOURCETYPE WINAPI d3d9_texture_3d_GetType(IDirect3DVolumeTexture9 *iface) 1072 { 1073 TRACE("iface %p.\n", iface); 1074 1075 return D3DRTYPE_VOLUMETEXTURE; 1076 } 1077 1078 static DWORD WINAPI d3d9_texture_3d_SetLOD(IDirect3DVolumeTexture9 *iface, DWORD lod) 1079 { 1080 struct d3d9_texture *texture = impl_from_IDirect3DVolumeTexture9(iface); 1081 DWORD ret; 1082 1083 TRACE("iface %p, lod %u.\n", iface, lod); 1084 1085 wined3d_mutex_lock(); 1086 ret = wined3d_texture_set_lod(texture->wined3d_texture, lod); 1087 wined3d_mutex_unlock(); 1088 1089 return ret; 1090 } 1091 1092 static DWORD WINAPI d3d9_texture_3d_GetLOD(IDirect3DVolumeTexture9 *iface) 1093 { 1094 struct d3d9_texture *texture = impl_from_IDirect3DVolumeTexture9(iface); 1095 DWORD ret; 1096 1097 TRACE("iface %p.\n", iface); 1098 1099 wined3d_mutex_lock(); 1100 ret = wined3d_texture_get_lod(texture->wined3d_texture); 1101 wined3d_mutex_unlock(); 1102 1103 return ret; 1104 } 1105 1106 static DWORD WINAPI d3d9_texture_3d_GetLevelCount(IDirect3DVolumeTexture9 *iface) 1107 { 1108 struct d3d9_texture *texture = impl_from_IDirect3DVolumeTexture9(iface); 1109 DWORD ret; 1110 1111 TRACE("iface %p.\n", iface); 1112 1113 wined3d_mutex_lock(); 1114 ret = wined3d_texture_get_level_count(texture->wined3d_texture); 1115 wined3d_mutex_unlock(); 1116 1117 return ret; 1118 } 1119 1120 static HRESULT WINAPI d3d9_texture_3d_SetAutoGenFilterType(IDirect3DVolumeTexture9 *iface, 1121 D3DTEXTUREFILTERTYPE filter_type) 1122 { 1123 TRACE("iface %p, filter_type %#x.\n", iface, filter_type); 1124 1125 return D3DERR_INVALIDCALL; 1126 } 1127 1128 static D3DTEXTUREFILTERTYPE WINAPI d3d9_texture_3d_GetAutoGenFilterType(IDirect3DVolumeTexture9 *iface) 1129 { 1130 TRACE("iface %p.\n", iface); 1131 1132 return D3DTEXF_NONE; 1133 } 1134 1135 static void WINAPI d3d9_texture_3d_GenerateMipSubLevels(IDirect3DVolumeTexture9 *iface) 1136 { 1137 TRACE("iface %p.\n", iface); 1138 } 1139 1140 static HRESULT WINAPI d3d9_texture_3d_GetLevelDesc(IDirect3DVolumeTexture9 *iface, UINT level, D3DVOLUME_DESC *desc) 1141 { 1142 struct d3d9_texture *texture = impl_from_IDirect3DVolumeTexture9(iface); 1143 struct wined3d_sub_resource_desc wined3d_desc; 1144 HRESULT hr; 1145 1146 TRACE("iface %p, level %u, desc %p.\n", iface, level, desc); 1147 1148 wined3d_mutex_lock(); 1149 if (SUCCEEDED(hr = wined3d_texture_get_sub_resource_desc(texture->wined3d_texture, level, &wined3d_desc))) 1150 { 1151 desc->Format = d3dformat_from_wined3dformat(wined3d_desc.format); 1152 desc->Type = D3DRTYPE_VOLUME; 1153 desc->Usage = texture->usage; 1154 desc->Pool = d3dpool_from_wined3daccess(wined3d_desc.access, wined3d_desc.usage); 1155 desc->Width = wined3d_desc.width; 1156 desc->Height = wined3d_desc.height; 1157 desc->Depth = wined3d_desc.depth; 1158 } 1159 wined3d_mutex_unlock(); 1160 1161 return hr; 1162 } 1163 1164 static HRESULT WINAPI d3d9_texture_3d_GetVolumeLevel(IDirect3DVolumeTexture9 *iface, 1165 UINT level, IDirect3DVolume9 **volume) 1166 { 1167 struct d3d9_texture *texture = impl_from_IDirect3DVolumeTexture9(iface); 1168 struct d3d9_volume *volume_impl; 1169 1170 TRACE("iface %p, level %u, volume %p.\n", iface, level, volume); 1171 1172 wined3d_mutex_lock(); 1173 if (!(volume_impl = wined3d_texture_get_sub_resource_parent(texture->wined3d_texture, level))) 1174 { 1175 wined3d_mutex_unlock(); 1176 return D3DERR_INVALIDCALL; 1177 } 1178 1179 *volume = &volume_impl->IDirect3DVolume9_iface; 1180 IDirect3DVolume9_AddRef(*volume); 1181 wined3d_mutex_unlock(); 1182 1183 return D3D_OK; 1184 } 1185 1186 static HRESULT WINAPI d3d9_texture_3d_LockBox(IDirect3DVolumeTexture9 *iface, 1187 UINT level, D3DLOCKED_BOX *locked_box, const D3DBOX *box, DWORD flags) 1188 { 1189 struct d3d9_texture *texture = impl_from_IDirect3DVolumeTexture9(iface); 1190 struct d3d9_volume *volume_impl; 1191 HRESULT hr; 1192 1193 TRACE("iface %p, level %u, locked_box %p, box %p, flags %#x.\n", 1194 iface, level, locked_box, box, flags); 1195 1196 wined3d_mutex_lock(); 1197 if (!(volume_impl = wined3d_texture_get_sub_resource_parent(texture->wined3d_texture, level))) 1198 hr = D3DERR_INVALIDCALL; 1199 else 1200 hr = IDirect3DVolume9_LockBox(&volume_impl->IDirect3DVolume9_iface, locked_box, box, flags); 1201 wined3d_mutex_unlock(); 1202 1203 return hr; 1204 } 1205 1206 static HRESULT WINAPI d3d9_texture_3d_UnlockBox(IDirect3DVolumeTexture9 *iface, UINT level) 1207 { 1208 struct d3d9_texture *texture = impl_from_IDirect3DVolumeTexture9(iface); 1209 struct d3d9_volume *volume_impl; 1210 HRESULT hr; 1211 1212 TRACE("iface %p, level %u.\n", iface, level); 1213 1214 wined3d_mutex_lock(); 1215 if (!(volume_impl = wined3d_texture_get_sub_resource_parent(texture->wined3d_texture, level))) 1216 hr = D3DERR_INVALIDCALL; 1217 else 1218 hr = IDirect3DVolume9_UnlockBox(&volume_impl->IDirect3DVolume9_iface); 1219 wined3d_mutex_unlock(); 1220 1221 return hr; 1222 } 1223 1224 static HRESULT WINAPI d3d9_texture_3d_AddDirtyBox(IDirect3DVolumeTexture9 *iface, const D3DBOX *dirty_box) 1225 { 1226 struct d3d9_texture *texture = impl_from_IDirect3DVolumeTexture9(iface); 1227 HRESULT hr; 1228 1229 TRACE("iface %p, dirty_box %p.\n", iface, dirty_box); 1230 1231 wined3d_mutex_lock(); 1232 hr = wined3d_texture_add_dirty_region(texture->wined3d_texture, 0, (const struct wined3d_box *)dirty_box); 1233 wined3d_mutex_unlock(); 1234 1235 return hr; 1236 } 1237 1238 1239 static const IDirect3DVolumeTexture9Vtbl d3d9_texture_3d_vtbl = 1240 { 1241 /* IUnknown */ 1242 d3d9_texture_3d_QueryInterface, 1243 d3d9_texture_3d_AddRef, 1244 d3d9_texture_3d_Release, 1245 /* IDirect3DResource9 */ 1246 d3d9_texture_3d_GetDevice, 1247 d3d9_texture_3d_SetPrivateData, 1248 d3d9_texture_3d_GetPrivateData, 1249 d3d9_texture_3d_FreePrivateData, 1250 d3d9_texture_3d_SetPriority, 1251 d3d9_texture_3d_GetPriority, 1252 d3d9_texture_3d_PreLoad, 1253 d3d9_texture_3d_GetType, 1254 /* IDirect3DBaseTexture9 */ 1255 d3d9_texture_3d_SetLOD, 1256 d3d9_texture_3d_GetLOD, 1257 d3d9_texture_3d_GetLevelCount, 1258 d3d9_texture_3d_SetAutoGenFilterType, 1259 d3d9_texture_3d_GetAutoGenFilterType, 1260 d3d9_texture_3d_GenerateMipSubLevels, 1261 /* IDirect3DVolumeTexture9 */ 1262 d3d9_texture_3d_GetLevelDesc, 1263 d3d9_texture_3d_GetVolumeLevel, 1264 d3d9_texture_3d_LockBox, 1265 d3d9_texture_3d_UnlockBox, 1266 d3d9_texture_3d_AddDirtyBox, 1267 }; 1268 1269 struct d3d9_texture *unsafe_impl_from_IDirect3DBaseTexture9(IDirect3DBaseTexture9 *iface) 1270 { 1271 if (!iface) 1272 return NULL; 1273 1274 if (iface->lpVtbl != (const IDirect3DBaseTexture9Vtbl *)&d3d9_texture_2d_vtbl 1275 && iface->lpVtbl != (const IDirect3DBaseTexture9Vtbl *)&d3d9_texture_cube_vtbl 1276 && iface->lpVtbl != (const IDirect3DBaseTexture9Vtbl *)&d3d9_texture_3d_vtbl) 1277 { 1278 WARN("%p is not a valid IDirect3DBaseTexture9 interface.\n", iface); 1279 return NULL; 1280 } 1281 1282 return CONTAINING_RECORD(iface, struct d3d9_texture, IDirect3DBaseTexture9_iface); 1283 } 1284 1285 static void STDMETHODCALLTYPE d3d9_texture_wined3d_object_destroyed(void *parent) 1286 { 1287 struct d3d9_texture *texture = parent; 1288 d3d9_resource_cleanup(&texture->resource); 1289 heap_free(texture); 1290 } 1291 1292 static const struct wined3d_parent_ops d3d9_texture_wined3d_parent_ops = 1293 { 1294 d3d9_texture_wined3d_object_destroyed, 1295 }; 1296 1297 HRESULT texture_init(struct d3d9_texture *texture, struct d3d9_device *device, 1298 UINT width, UINT height, UINT levels, DWORD usage, D3DFORMAT format, D3DPOOL pool) 1299 { 1300 struct wined3d_resource_desc desc; 1301 DWORD flags = 0; 1302 HRESULT hr; 1303 1304 texture->IDirect3DBaseTexture9_iface.lpVtbl = (const IDirect3DBaseTexture9Vtbl *)&d3d9_texture_2d_vtbl; 1305 d3d9_resource_init(&texture->resource); 1306 list_init(&texture->rtv_list); 1307 texture->usage = usage; 1308 1309 desc.resource_type = WINED3D_RTYPE_TEXTURE_2D; 1310 desc.format = wined3dformat_from_d3dformat(format); 1311 desc.multisample_type = WINED3D_MULTISAMPLE_NONE; 1312 desc.multisample_quality = 0; 1313 desc.usage = wined3dusage_from_d3dusage(usage); 1314 desc.usage |= WINED3DUSAGE_TEXTURE; 1315 if (pool == D3DPOOL_SCRATCH) 1316 desc.usage |= WINED3DUSAGE_SCRATCH; 1317 desc.access = wined3daccess_from_d3dpool(pool, usage) 1318 | WINED3D_RESOURCE_ACCESS_MAP_R | WINED3D_RESOURCE_ACCESS_MAP_W; 1319 desc.width = width; 1320 desc.height = height; 1321 desc.depth = 1; 1322 desc.size = 0; 1323 1324 if (pool != D3DPOOL_DEFAULT || (usage & D3DUSAGE_DYNAMIC)) 1325 flags |= WINED3D_TEXTURE_CREATE_MAPPABLE; 1326 1327 if (is_gdi_compat_wined3dformat(desc.format)) 1328 flags |= WINED3D_TEXTURE_CREATE_GET_DC; 1329 1330 if (usage & D3DUSAGE_AUTOGENMIPMAP) 1331 { 1332 if (pool == D3DPOOL_SYSTEMMEM) 1333 { 1334 WARN("D3DUSAGE_AUTOGENMIPMAP texture can't be in D3DPOOL_SYSTEMMEM, returning D3DERR_INVALIDCALL.\n"); 1335 return D3DERR_INVALIDCALL; 1336 } 1337 if (levels && levels != 1) 1338 { 1339 WARN("D3DUSAGE_AUTOGENMIPMAP texture with %u levels, returning D3DERR_INVALIDCALL.\n", levels); 1340 return D3DERR_INVALIDCALL; 1341 } 1342 flags |= WINED3D_TEXTURE_CREATE_GENERATE_MIPMAPS; 1343 texture->autogen_filter_type = D3DTEXF_LINEAR; 1344 levels = 0; 1345 } 1346 else 1347 { 1348 texture->autogen_filter_type = D3DTEXF_NONE; 1349 } 1350 if (!levels) 1351 levels = wined3d_log2i(max(width, height)) + 1; 1352 1353 wined3d_mutex_lock(); 1354 hr = wined3d_texture_create(device->wined3d_device, &desc, 1, levels, flags, 1355 NULL, texture, &d3d9_texture_wined3d_parent_ops, &texture->wined3d_texture); 1356 wined3d_mutex_unlock(); 1357 if (FAILED(hr)) 1358 { 1359 WARN("Failed to create wined3d texture, hr %#x.\n", hr); 1360 return hr; 1361 } 1362 1363 texture->parent_device = &device->IDirect3DDevice9Ex_iface; 1364 IDirect3DDevice9Ex_AddRef(texture->parent_device); 1365 1366 return D3D_OK; 1367 } 1368 1369 HRESULT cubetexture_init(struct d3d9_texture *texture, struct d3d9_device *device, 1370 UINT edge_length, UINT levels, DWORD usage, D3DFORMAT format, D3DPOOL pool) 1371 { 1372 struct wined3d_resource_desc desc; 1373 DWORD flags = 0; 1374 HRESULT hr; 1375 1376 texture->IDirect3DBaseTexture9_iface.lpVtbl = (const IDirect3DBaseTexture9Vtbl *)&d3d9_texture_cube_vtbl; 1377 d3d9_resource_init(&texture->resource); 1378 list_init(&texture->rtv_list); 1379 texture->usage = usage; 1380 1381 desc.resource_type = WINED3D_RTYPE_TEXTURE_2D; 1382 desc.format = wined3dformat_from_d3dformat(format); 1383 desc.multisample_type = WINED3D_MULTISAMPLE_NONE; 1384 desc.multisample_quality = 0; 1385 desc.usage = wined3dusage_from_d3dusage(usage); 1386 desc.usage |= WINED3DUSAGE_LEGACY_CUBEMAP | WINED3DUSAGE_TEXTURE; 1387 if (pool == D3DPOOL_SCRATCH) 1388 desc.usage |= WINED3DUSAGE_SCRATCH; 1389 desc.access = wined3daccess_from_d3dpool(pool, usage) 1390 | WINED3D_RESOURCE_ACCESS_MAP_R | WINED3D_RESOURCE_ACCESS_MAP_W; 1391 desc.width = edge_length; 1392 desc.height = edge_length; 1393 desc.depth = 1; 1394 desc.size = 0; 1395 1396 if (pool != D3DPOOL_DEFAULT || (usage & D3DUSAGE_DYNAMIC)) 1397 flags |= WINED3D_TEXTURE_CREATE_MAPPABLE; 1398 1399 if (is_gdi_compat_wined3dformat(desc.format)) 1400 flags |= WINED3D_TEXTURE_CREATE_GET_DC; 1401 1402 if (usage & D3DUSAGE_AUTOGENMIPMAP) 1403 { 1404 if (pool == D3DPOOL_SYSTEMMEM) 1405 { 1406 WARN("D3DUSAGE_AUTOGENMIPMAP texture can't be in D3DPOOL_SYSTEMMEM, returning D3DERR_INVALIDCALL.\n"); 1407 return D3DERR_INVALIDCALL; 1408 } 1409 if (levels && levels != 1) 1410 { 1411 WARN("D3DUSAGE_AUTOGENMIPMAP texture with %u levels, returning D3DERR_INVALIDCALL.\n", levels); 1412 return D3DERR_INVALIDCALL; 1413 } 1414 flags |= WINED3D_TEXTURE_CREATE_GENERATE_MIPMAPS; 1415 texture->autogen_filter_type = D3DTEXF_LINEAR; 1416 levels = 0; 1417 } 1418 else 1419 { 1420 texture->autogen_filter_type = D3DTEXF_NONE; 1421 } 1422 if (!levels) 1423 levels = wined3d_log2i(edge_length) + 1; 1424 1425 wined3d_mutex_lock(); 1426 hr = wined3d_texture_create(device->wined3d_device, &desc, 6, levels, flags, 1427 NULL, texture, &d3d9_texture_wined3d_parent_ops, &texture->wined3d_texture); 1428 wined3d_mutex_unlock(); 1429 if (FAILED(hr)) 1430 { 1431 WARN("Failed to create wined3d cube texture, hr %#x.\n", hr); 1432 return hr; 1433 } 1434 1435 texture->parent_device = &device->IDirect3DDevice9Ex_iface; 1436 IDirect3DDevice9Ex_AddRef(texture->parent_device); 1437 1438 return D3D_OK; 1439 } 1440 1441 HRESULT volumetexture_init(struct d3d9_texture *texture, struct d3d9_device *device, 1442 UINT width, UINT height, UINT depth, UINT levels, DWORD usage, D3DFORMAT format, D3DPOOL pool) 1443 { 1444 struct wined3d_resource_desc desc; 1445 HRESULT hr; 1446 1447 texture->IDirect3DBaseTexture9_iface.lpVtbl = (const IDirect3DBaseTexture9Vtbl *)&d3d9_texture_3d_vtbl; 1448 d3d9_resource_init(&texture->resource); 1449 list_init(&texture->rtv_list); 1450 texture->usage = usage; 1451 1452 desc.resource_type = WINED3D_RTYPE_TEXTURE_3D; 1453 desc.format = wined3dformat_from_d3dformat(format); 1454 desc.multisample_type = WINED3D_MULTISAMPLE_NONE; 1455 desc.multisample_quality = 0; 1456 desc.usage = wined3dusage_from_d3dusage(usage); 1457 desc.usage |= WINED3DUSAGE_TEXTURE; 1458 if (pool == D3DPOOL_SCRATCH) 1459 desc.usage |= WINED3DUSAGE_SCRATCH; 1460 desc.access = wined3daccess_from_d3dpool(pool, usage); 1461 desc.width = width; 1462 desc.height = height; 1463 desc.depth = depth; 1464 desc.size = 0; 1465 1466 if (usage & D3DUSAGE_AUTOGENMIPMAP) 1467 { 1468 WARN("D3DUSAGE_AUTOGENMIPMAP volume texture is not supported, returning D3DERR_INVALIDCALL.\n"); 1469 return D3DERR_INVALIDCALL; 1470 } 1471 if (!levels) 1472 levels = wined3d_log2i(max(max(width, height), depth)) + 1; 1473 1474 wined3d_mutex_lock(); 1475 hr = wined3d_texture_create(device->wined3d_device, &desc, 1, levels, 0, 1476 NULL, texture, &d3d9_texture_wined3d_parent_ops, &texture->wined3d_texture); 1477 wined3d_mutex_unlock(); 1478 if (FAILED(hr)) 1479 { 1480 WARN("Failed to create wined3d volume texture, hr %#x.\n", hr); 1481 return hr; 1482 } 1483 1484 texture->parent_device = &device->IDirect3DDevice9Ex_iface; 1485 IDirect3DDevice9Ex_AddRef(texture->parent_device); 1486 1487 return D3D_OK; 1488 } 1489