Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenddraw.c
Go to the documentation of this file.
00001 /* 00002 * Copyright 1997-2000 Marcus Meissner 00003 * Copyright 1998-2000 Lionel Ulmer 00004 * Copyright 2000-2001 TransGaming Technologies Inc. 00005 * Copyright 2006 Stefan Dösinger 00006 * Copyright 2008 Denver Gingerich 00007 * 00008 * This library is free software; you can redistribute it and/or 00009 * modify it under the terms of the GNU Lesser General Public 00010 * License as published by the Free Software Foundation; either 00011 * version 2.1 of the License, or (at your option) any later version. 00012 * 00013 * This library is distributed in the hope that it will be useful, 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00016 * Lesser General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU Lesser General Public 00019 * License along with this library; if not, write to the Free Software 00020 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00021 */ 00022 00023 #include "config.h" 00024 #include "wine/port.h" 00025 00026 #include "ddraw_private.h" 00027 00028 WINE_DEFAULT_DEBUG_CHANNEL(ddraw); 00029 00030 /* Device identifier. Don't relay it to WineD3D */ 00031 static const DDDEVICEIDENTIFIER2 deviceidentifier = 00032 { 00033 "display", 00034 "DirectDraw HAL", 00035 { { 0x00010001, 0x00010001 } }, 00036 0, 0, 0, 0, 00037 /* a8373c10-7ac4-4deb-849a-009844d08b2d */ 00038 {0xa8373c10,0x7ac4,0x4deb, {0x84,0x9a,0x00,0x98,0x44,0xd0,0x8b,0x2d}}, 00039 0 00040 }; 00041 00042 static struct enum_device_entry 00043 { 00044 char interface_name[100]; 00045 char device_name[100]; 00046 const GUID *device_guid; 00047 } device_list7[] = 00048 { 00049 /* T&L HAL device */ 00050 { 00051 "WINE Direct3D7 Hardware Transform and Lighting acceleration using WineD3D", 00052 "Wine D3D7 T&L HAL", 00053 &IID_IDirect3DTnLHalDevice, 00054 }, 00055 00056 /* HAL device */ 00057 { 00058 "WINE Direct3D7 Hardware acceleration using WineD3D", 00059 "Direct3D HAL", 00060 &IID_IDirect3DHALDevice, 00061 }, 00062 00063 /* RGB device */ 00064 { 00065 "WINE Direct3D7 RGB Software Emulation using WineD3D", 00066 "Wine D3D7 RGB", 00067 &IID_IDirect3DRGBDevice, 00068 }, 00069 }; 00070 00071 static void STDMETHODCALLTYPE ddraw_null_wined3d_object_destroyed(void *parent) {} 00072 00073 const struct wined3d_parent_ops ddraw_null_wined3d_parent_ops = 00074 { 00075 ddraw_null_wined3d_object_destroyed, 00076 }; 00077 00078 static inline IDirectDrawImpl *impl_from_IDirectDraw(IDirectDraw *iface) 00079 { 00080 return CONTAINING_RECORD(iface, IDirectDrawImpl, IDirectDraw_iface); 00081 } 00082 00083 static inline IDirectDrawImpl *impl_from_IDirectDraw2(IDirectDraw2 *iface) 00084 { 00085 return CONTAINING_RECORD(iface, IDirectDrawImpl, IDirectDraw2_iface); 00086 } 00087 00088 static inline IDirectDrawImpl *impl_from_IDirectDraw4(IDirectDraw4 *iface) 00089 { 00090 return CONTAINING_RECORD(iface, IDirectDrawImpl, IDirectDraw4_iface); 00091 } 00092 00093 static inline IDirectDrawImpl *impl_from_IDirectDraw7(IDirectDraw7 *iface) 00094 { 00095 return CONTAINING_RECORD(iface, IDirectDrawImpl, IDirectDraw7_iface); 00096 } 00097 00098 static inline IDirectDrawImpl *impl_from_IDirect3D(IDirect3D *iface) 00099 { 00100 return CONTAINING_RECORD(iface, IDirectDrawImpl, IDirect3D_iface); 00101 } 00102 00103 static inline IDirectDrawImpl *impl_from_IDirect3D2(IDirect3D2 *iface) 00104 { 00105 return CONTAINING_RECORD(iface, IDirectDrawImpl, IDirect3D2_iface); 00106 } 00107 00108 static inline IDirectDrawImpl *impl_from_IDirect3D3(IDirect3D3 *iface) 00109 { 00110 return CONTAINING_RECORD(iface, IDirectDrawImpl, IDirect3D3_iface); 00111 } 00112 00113 static inline IDirectDrawImpl *impl_from_IDirect3D7(IDirect3D7 *iface) 00114 { 00115 return CONTAINING_RECORD(iface, IDirectDrawImpl, IDirect3D7_iface); 00116 } 00117 00118 /***************************************************************************** 00119 * IUnknown Methods 00120 *****************************************************************************/ 00121 00122 /***************************************************************************** 00123 * IDirectDraw7::QueryInterface 00124 * 00125 * Queries different interfaces of the DirectDraw object. It can return 00126 * IDirectDraw interfaces in version 1, 2, 4 and 7, and IDirect3D interfaces 00127 * in version 1, 2, 3 and 7. An IDirect3DDevice can be created with this 00128 * method. 00129 * The returned interface is AddRef()-ed before it's returned 00130 * 00131 * Used for version 1, 2, 4 and 7 00132 * 00133 * Params: 00134 * refiid: Interface ID asked for 00135 * obj: Used to return the interface pointer 00136 * 00137 * Returns: 00138 * S_OK if an interface was found 00139 * E_NOINTERFACE if the requested interface wasn't found 00140 * 00141 *****************************************************************************/ 00142 static HRESULT WINAPI ddraw7_QueryInterface(IDirectDraw7 *iface, REFIID refiid, void **obj) 00143 { 00144 IDirectDrawImpl *This = impl_from_IDirectDraw7(iface); 00145 00146 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(refiid), obj); 00147 00148 /* Can change surface impl type */ 00149 wined3d_mutex_lock(); 00150 00151 /* According to COM docs, if the QueryInterface fails, obj should be set to NULL */ 00152 *obj = NULL; 00153 00154 if(!refiid) 00155 { 00156 wined3d_mutex_unlock(); 00157 return DDERR_INVALIDPARAMS; 00158 } 00159 00160 /* Check DirectDraw Interfaces */ 00161 if ( IsEqualGUID( &IID_IUnknown, refiid ) || 00162 IsEqualGUID( &IID_IDirectDraw7, refiid ) ) 00163 { 00164 *obj = This; 00165 TRACE("(%p) Returning IDirectDraw7 interface at %p\n", This, *obj); 00166 } 00167 else if ( IsEqualGUID( &IID_IDirectDraw4, refiid ) ) 00168 { 00169 *obj = &This->IDirectDraw4_iface; 00170 TRACE("(%p) Returning IDirectDraw4 interface at %p\n", This, *obj); 00171 } 00172 else if ( IsEqualGUID( &IID_IDirectDraw3, refiid ) ) 00173 { 00174 /* This Interface exists in ddrawex.dll, it is implemented in a wrapper */ 00175 WARN("IDirectDraw3 is not valid in ddraw.dll\n"); 00176 *obj = NULL; 00177 wined3d_mutex_unlock(); 00178 return E_NOINTERFACE; 00179 } 00180 else if ( IsEqualGUID( &IID_IDirectDraw2, refiid ) ) 00181 { 00182 *obj = &This->IDirectDraw2_iface; 00183 TRACE("(%p) Returning IDirectDraw2 interface at %p\n", This, *obj); 00184 } 00185 else if ( IsEqualGUID( &IID_IDirectDraw, refiid ) ) 00186 { 00187 *obj = &This->IDirectDraw_iface; 00188 TRACE("(%p) Returning IDirectDraw interface at %p\n", This, *obj); 00189 } 00190 00191 /* Direct3D 00192 * The refcount unit test revealed that an IDirect3D7 interface can only be queried 00193 * from a DirectDraw object that was created as an IDirectDraw7 interface. No idea 00194 * who had this idea and why. The older interfaces can query and IDirect3D version 00195 * because they are all created as IDirectDraw(1). This isn't really crucial behavior, 00196 * and messy to implement with the common creation function, so it has been left out here. 00197 */ 00198 else if ( IsEqualGUID( &IID_IDirect3D , refiid ) || 00199 IsEqualGUID( &IID_IDirect3D2 , refiid ) || 00200 IsEqualGUID( &IID_IDirect3D3 , refiid ) || 00201 IsEqualGUID( &IID_IDirect3D7 , refiid ) ) 00202 { 00203 /* Check the surface implementation */ 00204 if (DefaultSurfaceType != SURFACE_OPENGL) 00205 { 00206 WARN("The app requests a Direct3D interface, but non-opengl surfaces where set in winecfg\n"); 00207 /* Do not abort here, only reject 3D Device creation */ 00208 } 00209 00210 if ( IsEqualGUID( &IID_IDirect3D , refiid ) ) 00211 { 00212 This->d3dversion = 1; 00213 *obj = &This->IDirect3D_iface; 00214 TRACE(" returning Direct3D interface at %p.\n", *obj); 00215 } 00216 else if ( IsEqualGUID( &IID_IDirect3D2 , refiid ) ) 00217 { 00218 This->d3dversion = 2; 00219 *obj = &This->IDirect3D2_iface; 00220 TRACE(" returning Direct3D2 interface at %p.\n", *obj); 00221 } 00222 else if ( IsEqualGUID( &IID_IDirect3D3 , refiid ) ) 00223 { 00224 This->d3dversion = 3; 00225 *obj = &This->IDirect3D3_iface; 00226 TRACE(" returning Direct3D3 interface at %p.\n", *obj); 00227 } 00228 else if(IsEqualGUID( &IID_IDirect3D7 , refiid )) 00229 { 00230 This->d3dversion = 7; 00231 *obj = &This->IDirect3D7_iface; 00232 TRACE(" returning Direct3D7 interface at %p.\n", *obj); 00233 } 00234 } 00235 /* Unknown interface */ 00236 else 00237 { 00238 ERR("(%p)->(%s, %p): No interface found\n", This, debugstr_guid(refiid), obj); 00239 wined3d_mutex_unlock(); 00240 return E_NOINTERFACE; 00241 } 00242 00243 IUnknown_AddRef( (IUnknown *) *obj ); 00244 wined3d_mutex_unlock(); 00245 00246 return S_OK; 00247 } 00248 00249 static HRESULT WINAPI ddraw4_QueryInterface(IDirectDraw4 *iface, REFIID riid, void **object) 00250 { 00251 IDirectDrawImpl *This = impl_from_IDirectDraw4(iface); 00252 00253 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object); 00254 00255 return ddraw7_QueryInterface(&This->IDirectDraw7_iface, riid, object); 00256 } 00257 00258 static HRESULT WINAPI ddraw2_QueryInterface(IDirectDraw2 *iface, REFIID riid, void **object) 00259 { 00260 IDirectDrawImpl *This = impl_from_IDirectDraw2(iface); 00261 00262 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object); 00263 00264 return ddraw7_QueryInterface(&This->IDirectDraw7_iface, riid, object); 00265 } 00266 00267 static HRESULT WINAPI ddraw1_QueryInterface(IDirectDraw *iface, REFIID riid, void **object) 00268 { 00269 IDirectDrawImpl *This = impl_from_IDirectDraw(iface); 00270 00271 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object); 00272 00273 return ddraw7_QueryInterface(&This->IDirectDraw7_iface, riid, object); 00274 } 00275 00276 static HRESULT WINAPI d3d7_QueryInterface(IDirect3D7 *iface, REFIID riid, void **object) 00277 { 00278 IDirectDrawImpl *This = impl_from_IDirect3D7(iface); 00279 00280 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object); 00281 00282 return ddraw7_QueryInterface(&This->IDirectDraw7_iface, riid, object); 00283 } 00284 00285 static HRESULT WINAPI d3d3_QueryInterface(IDirect3D3 *iface, REFIID riid, void **object) 00286 { 00287 IDirectDrawImpl *This = impl_from_IDirect3D3(iface); 00288 00289 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object); 00290 00291 return ddraw7_QueryInterface(&This->IDirectDraw7_iface, riid, object); 00292 } 00293 00294 static HRESULT WINAPI d3d2_QueryInterface(IDirect3D2 *iface, REFIID riid, void **object) 00295 { 00296 IDirectDrawImpl *This = impl_from_IDirect3D2(iface); 00297 00298 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object); 00299 00300 return ddraw7_QueryInterface(&This->IDirectDraw7_iface, riid, object); 00301 } 00302 00303 static HRESULT WINAPI d3d1_QueryInterface(IDirect3D *iface, REFIID riid, void **object) 00304 { 00305 IDirectDrawImpl *This = impl_from_IDirect3D(iface); 00306 00307 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object); 00308 00309 return ddraw7_QueryInterface(&This->IDirectDraw7_iface, riid, object); 00310 } 00311 00312 /***************************************************************************** 00313 * IDirectDraw7::AddRef 00314 * 00315 * Increases the interfaces refcount, basically 00316 * 00317 * DDraw refcounting is a bit tricky. The different DirectDraw interface 00318 * versions have individual refcounts, but the IDirect3D interfaces do not. 00319 * All interfaces are from one object, that means calling QueryInterface on an 00320 * IDirectDraw7 interface for an IDirectDraw4 interface does not create a new 00321 * IDirectDrawImpl object. 00322 * 00323 * That means all AddRef and Release implementations of IDirectDrawX work 00324 * with their own counter, and IDirect3DX::AddRef thunk to IDirectDraw (1), 00325 * except of IDirect3D7 which thunks to IDirectDraw7 00326 * 00327 * Returns: The new refcount 00328 * 00329 *****************************************************************************/ 00330 static ULONG WINAPI ddraw7_AddRef(IDirectDraw7 *iface) 00331 { 00332 IDirectDrawImpl *This = impl_from_IDirectDraw7(iface); 00333 ULONG ref = InterlockedIncrement(&This->ref7); 00334 00335 TRACE("%p increasing refcount to %u.\n", This, ref); 00336 00337 if(ref == 1) InterlockedIncrement(&This->numIfaces); 00338 00339 return ref; 00340 } 00341 00342 static ULONG WINAPI ddraw4_AddRef(IDirectDraw4 *iface) 00343 { 00344 IDirectDrawImpl *This = impl_from_IDirectDraw4(iface); 00345 ULONG ref = InterlockedIncrement(&This->ref4); 00346 00347 TRACE("%p increasing refcount to %u.\n", This, ref); 00348 00349 if (ref == 1) InterlockedIncrement(&This->numIfaces); 00350 00351 return ref; 00352 } 00353 00354 static ULONG WINAPI ddraw2_AddRef(IDirectDraw2 *iface) 00355 { 00356 IDirectDrawImpl *This = impl_from_IDirectDraw2(iface); 00357 ULONG ref = InterlockedIncrement(&This->ref2); 00358 00359 TRACE("%p increasing refcount to %u.\n", This, ref); 00360 00361 if (ref == 1) InterlockedIncrement(&This->numIfaces); 00362 00363 return ref; 00364 } 00365 00366 static ULONG WINAPI ddraw1_AddRef(IDirectDraw *iface) 00367 { 00368 IDirectDrawImpl *This = impl_from_IDirectDraw(iface); 00369 ULONG ref = InterlockedIncrement(&This->ref1); 00370 00371 TRACE("%p increasing refcount to %u.\n", This, ref); 00372 00373 if (ref == 1) InterlockedIncrement(&This->numIfaces); 00374 00375 return ref; 00376 } 00377 00378 static ULONG WINAPI d3d7_AddRef(IDirect3D7 *iface) 00379 { 00380 IDirectDrawImpl *This = impl_from_IDirect3D7(iface); 00381 00382 TRACE("iface %p.\n", iface); 00383 00384 return ddraw7_AddRef(&This->IDirectDraw7_iface); 00385 } 00386 00387 static ULONG WINAPI d3d3_AddRef(IDirect3D3 *iface) 00388 { 00389 IDirectDrawImpl *This = impl_from_IDirect3D3(iface); 00390 00391 TRACE("iface %p.\n", iface); 00392 00393 return ddraw1_AddRef(&This->IDirectDraw_iface); 00394 } 00395 00396 static ULONG WINAPI d3d2_AddRef(IDirect3D2 *iface) 00397 { 00398 IDirectDrawImpl *This = impl_from_IDirect3D2(iface); 00399 00400 TRACE("iface %p.\n", iface); 00401 00402 return ddraw1_AddRef(&This->IDirectDraw_iface); 00403 } 00404 00405 static ULONG WINAPI d3d1_AddRef(IDirect3D *iface) 00406 { 00407 IDirectDrawImpl *This = impl_from_IDirect3D(iface); 00408 00409 TRACE("iface %p.\n", iface); 00410 00411 return ddraw1_AddRef(&This->IDirectDraw_iface); 00412 } 00413 00414 void ddraw_destroy_swapchain(IDirectDrawImpl *ddraw) 00415 { 00416 TRACE("Destroying the swapchain.\n"); 00417 00418 wined3d_swapchain_decref(ddraw->wined3d_swapchain); 00419 ddraw->wined3d_swapchain = NULL; 00420 00421 if (DefaultSurfaceType == SURFACE_OPENGL) 00422 { 00423 UINT i; 00424 00425 for (i = 0; i < ddraw->numConvertedDecls; ++i) 00426 { 00427 wined3d_vertex_declaration_decref(ddraw->decls[i].decl); 00428 } 00429 HeapFree(GetProcessHeap(), 0, ddraw->decls); 00430 ddraw->numConvertedDecls = 0; 00431 00432 if (FAILED(wined3d_device_uninit_3d(ddraw->wined3d_device))) 00433 { 00434 ERR("Failed to uninit 3D.\n"); 00435 } 00436 else 00437 { 00438 /* Free the d3d window if one was created. */ 00439 if (ddraw->d3d_window && ddraw->d3d_window != ddraw->dest_window) 00440 { 00441 TRACE("Destroying the hidden render window %p.\n", ddraw->d3d_window); 00442 DestroyWindow(ddraw->d3d_window); 00443 ddraw->d3d_window = 0; 00444 } 00445 } 00446 00447 ddraw->d3d_initialized = FALSE; 00448 } 00449 else 00450 { 00451 wined3d_device_uninit_gdi(ddraw->wined3d_device); 00452 } 00453 00454 ddraw_set_swapchain_window(ddraw, NULL); 00455 00456 TRACE("Swapchain destroyed.\n"); 00457 } 00458 00459 /***************************************************************************** 00460 * ddraw_destroy 00461 * 00462 * Destroys a ddraw object if all refcounts are 0. This is to share code 00463 * between the IDirectDrawX::Release functions 00464 * 00465 * Params: 00466 * This: DirectDraw object to destroy 00467 * 00468 *****************************************************************************/ 00469 static void ddraw_destroy(IDirectDrawImpl *This) 00470 { 00471 IDirectDraw7_SetCooperativeLevel(&This->IDirectDraw7_iface, NULL, DDSCL_NORMAL); 00472 IDirectDraw7_RestoreDisplayMode(&This->IDirectDraw7_iface); 00473 00474 /* Destroy the device window if we created one */ 00475 if(This->devicewindow != 0) 00476 { 00477 TRACE(" (%p) Destroying the device window %p\n", This, This->devicewindow); 00478 DestroyWindow(This->devicewindow); 00479 This->devicewindow = 0; 00480 } 00481 00482 wined3d_mutex_lock(); 00483 list_remove(&This->ddraw_list_entry); 00484 wined3d_mutex_unlock(); 00485 00486 if (This->wined3d_swapchain) 00487 ddraw_destroy_swapchain(This); 00488 wined3d_device_decref(This->wined3d_device); 00489 wined3d_decref(This->wined3d); 00490 00491 /* Now free the object */ 00492 HeapFree(GetProcessHeap(), 0, This); 00493 } 00494 00495 /***************************************************************************** 00496 * IDirectDraw7::Release 00497 * 00498 * Decreases the refcount. If the refcount falls to 0, the object is destroyed 00499 * 00500 * Returns: The new refcount 00501 *****************************************************************************/ 00502 static ULONG WINAPI ddraw7_Release(IDirectDraw7 *iface) 00503 { 00504 IDirectDrawImpl *This = impl_from_IDirectDraw7(iface); 00505 ULONG ref = InterlockedDecrement(&This->ref7); 00506 00507 TRACE("%p decreasing refcount to %u.\n", This, ref); 00508 00509 if (!ref && !InterlockedDecrement(&This->numIfaces)) 00510 ddraw_destroy(This); 00511 00512 return ref; 00513 } 00514 00515 static ULONG WINAPI ddraw4_Release(IDirectDraw4 *iface) 00516 { 00517 IDirectDrawImpl *This = impl_from_IDirectDraw4(iface); 00518 ULONG ref = InterlockedDecrement(&This->ref4); 00519 00520 TRACE("%p decreasing refcount to %u.\n", This, ref); 00521 00522 if (!ref && !InterlockedDecrement(&This->numIfaces)) 00523 ddraw_destroy(This); 00524 00525 return ref; 00526 } 00527 00528 static ULONG WINAPI ddraw2_Release(IDirectDraw2 *iface) 00529 { 00530 IDirectDrawImpl *This = impl_from_IDirectDraw2(iface); 00531 ULONG ref = InterlockedDecrement(&This->ref2); 00532 00533 TRACE("%p decreasing refcount to %u.\n", This, ref); 00534 00535 if (!ref && !InterlockedDecrement(&This->numIfaces)) 00536 ddraw_destroy(This); 00537 00538 return ref; 00539 } 00540 00541 static ULONG WINAPI ddraw1_Release(IDirectDraw *iface) 00542 { 00543 IDirectDrawImpl *This = impl_from_IDirectDraw(iface); 00544 ULONG ref = InterlockedDecrement(&This->ref1); 00545 00546 TRACE("%p decreasing refcount to %u.\n", This, ref); 00547 00548 if (!ref && !InterlockedDecrement(&This->numIfaces)) 00549 ddraw_destroy(This); 00550 00551 return ref; 00552 } 00553 00554 static ULONG WINAPI d3d7_Release(IDirect3D7 *iface) 00555 { 00556 IDirectDrawImpl *This = impl_from_IDirect3D7(iface); 00557 00558 TRACE("iface %p.\n", iface); 00559 00560 return ddraw7_Release(&This->IDirectDraw7_iface); 00561 } 00562 00563 static ULONG WINAPI d3d3_Release(IDirect3D3 *iface) 00564 { 00565 IDirectDrawImpl *This = impl_from_IDirect3D3(iface); 00566 00567 TRACE("iface %p.\n", iface); 00568 00569 return ddraw1_Release(&This->IDirectDraw_iface); 00570 } 00571 00572 static ULONG WINAPI d3d2_Release(IDirect3D2 *iface) 00573 { 00574 IDirectDrawImpl *This = impl_from_IDirect3D2(iface); 00575 00576 TRACE("iface %p.\n", iface); 00577 00578 return ddraw1_Release(&This->IDirectDraw_iface); 00579 } 00580 00581 static ULONG WINAPI d3d1_Release(IDirect3D *iface) 00582 { 00583 IDirectDrawImpl *This = impl_from_IDirect3D(iface); 00584 00585 TRACE("iface %p.\n", iface); 00586 00587 return ddraw1_Release(&This->IDirectDraw_iface); 00588 } 00589 00590 /***************************************************************************** 00591 * IDirectDraw methods 00592 *****************************************************************************/ 00593 00594 static HRESULT ddraw_set_focus_window(IDirectDrawImpl *ddraw, HWND window) 00595 { 00596 /* FIXME: This looks wrong, exclusive mode should imply a destination 00597 * window. */ 00598 if ((ddraw->cooperative_level & DDSCL_EXCLUSIVE) && ddraw->dest_window) 00599 { 00600 TRACE("Setting DDSCL_SETFOCUSWINDOW with an already set window, returning DDERR_HWNDALREADYSET.\n"); 00601 return DDERR_HWNDALREADYSET; 00602 } 00603 00604 ddraw->focuswindow = window; 00605 00606 /* Use the focus window for drawing too. */ 00607 ddraw->dest_window = ddraw->focuswindow; 00608 00609 return DD_OK; 00610 } 00611 00612 static HRESULT ddraw_attach_d3d_device(IDirectDrawImpl *ddraw, 00613 struct wined3d_swapchain_desc *swapchain_desc) 00614 { 00615 HWND window = swapchain_desc->device_window; 00616 HRESULT hr; 00617 00618 TRACE("ddraw %p.\n", ddraw); 00619 00620 if (!window || window == GetDesktopWindow()) 00621 { 00622 window = CreateWindowExA(0, DDRAW_WINDOW_CLASS_NAME, "Hidden D3D Window", 00623 WS_DISABLED, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), 00624 NULL, NULL, NULL, NULL); 00625 if (!window) 00626 { 00627 ERR("Failed to create window, last error %#x.\n", GetLastError()); 00628 return E_FAIL; 00629 } 00630 00631 ShowWindow(window, SW_HIDE); /* Just to be sure */ 00632 WARN("No window for the Direct3DDevice, created hidden window %p.\n", window); 00633 00634 swapchain_desc->device_window = window; 00635 } 00636 else 00637 { 00638 TRACE("Using existing window %p for Direct3D rendering.\n", window); 00639 } 00640 ddraw->d3d_window = window; 00641 00642 /* Set this NOW, otherwise creating the depth stencil surface will cause a 00643 * recursive loop until ram or emulated video memory is full. */ 00644 ddraw->d3d_initialized = TRUE; 00645 hr = wined3d_device_init_3d(ddraw->wined3d_device, swapchain_desc); 00646 if (FAILED(hr)) 00647 { 00648 ddraw->d3d_initialized = FALSE; 00649 return hr; 00650 } 00651 00652 ddraw->declArraySize = 2; 00653 ddraw->decls = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ddraw->decls) * ddraw->declArraySize); 00654 if (!ddraw->decls) 00655 { 00656 ERR("Error allocating an array for the converted vertex decls.\n"); 00657 ddraw->declArraySize = 0; 00658 hr = wined3d_device_uninit_3d(ddraw->wined3d_device); 00659 return E_OUTOFMEMORY; 00660 } 00661 00662 TRACE("Successfully initialized 3D.\n"); 00663 00664 return DD_OK; 00665 } 00666 00667 static HRESULT ddraw_create_swapchain(IDirectDrawImpl *ddraw, HWND window, BOOL windowed) 00668 { 00669 struct wined3d_swapchain_desc swapchain_desc; 00670 struct wined3d_display_mode mode; 00671 HRESULT hr = WINED3D_OK; 00672 00673 /* FIXME: wined3d_get_adapter_display_mode() would be more appropriate 00674 * here, since we don't actually have a swapchain yet, but 00675 * wined3d_device_get_display_mode() has some special handling for color 00676 * depth changes. */ 00677 hr = wined3d_device_get_display_mode(ddraw->wined3d_device, 0, &mode); 00678 if (FAILED(hr)) 00679 { 00680 ERR("Failed to get display mode.\n"); 00681 return hr; 00682 } 00683 00684 memset(&swapchain_desc, 0, sizeof(swapchain_desc)); 00685 swapchain_desc.backbuffer_width = mode.width; 00686 swapchain_desc.backbuffer_height = mode.height; 00687 swapchain_desc.backbuffer_format = mode.format_id; 00688 swapchain_desc.swap_effect = WINED3D_SWAP_EFFECT_COPY; 00689 swapchain_desc.device_window = window; 00690 swapchain_desc.windowed = windowed; 00691 00692 if (DefaultSurfaceType == SURFACE_OPENGL) 00693 hr = ddraw_attach_d3d_device(ddraw, &swapchain_desc); 00694 else 00695 hr = wined3d_device_init_gdi(ddraw->wined3d_device, &swapchain_desc); 00696 00697 if (FAILED(hr)) 00698 { 00699 ERR("Failed to create swapchain, hr %#x.\n", hr); 00700 return hr; 00701 } 00702 00703 if (FAILED(hr = wined3d_device_get_swapchain(ddraw->wined3d_device, 0, &ddraw->wined3d_swapchain))) 00704 { 00705 ERR("Failed to get swapchain, hr %#x.\n", hr); 00706 ddraw->wined3d_swapchain = NULL; 00707 return hr; 00708 } 00709 00710 ddraw_set_swapchain_window(ddraw, window); 00711 00712 return DD_OK; 00713 } 00714 00715 /***************************************************************************** 00716 * IDirectDraw7::SetCooperativeLevel 00717 * 00718 * Sets the cooperative level for the DirectDraw object, and the window 00719 * assigned to it. The cooperative level determines the general behavior 00720 * of the DirectDraw application 00721 * 00722 * Warning: This is quite tricky, as it's not really documented which 00723 * cooperative levels can be combined with each other. If a game fails 00724 * after this function, try to check the cooperative levels passed on 00725 * Windows, and if it returns something different. 00726 * 00727 * If you think that this function caused the failure because it writes a 00728 * fixme, be sure to run again with a +ddraw trace. 00729 * 00730 * What is known about cooperative levels (See the ddraw modes test): 00731 * DDSCL_EXCLUSIVE and DDSCL_FULLSCREEN must be used with each other 00732 * DDSCL_NORMAL is not compatible with DDSCL_EXCLUSIVE or DDSCL_FULLSCREEN 00733 * DDSCL_SETFOCUSWINDOW can be passed only in DDSCL_NORMAL mode, but after that 00734 * DDSCL_FULLSCREEN can be activated 00735 * DDSCL_SETFOCUSWINDOW may only be used with DDSCL_NOWINDOWCHANGES 00736 * 00737 * Handled flags: DDSCL_NORMAL, DDSCL_FULLSCREEN, DDSCL_EXCLUSIVE, 00738 * DDSCL_SETFOCUSWINDOW (partially), 00739 * DDSCL_MULTITHREADED (work in progress) 00740 * 00741 * Unhandled flags, which should be implemented 00742 * DDSCL_SETDEVICEWINDOW: Sets a window specially used for rendering (I don't 00743 * expect any difference to a normal window for wine) 00744 * DDSCL_CREATEDEVICEWINDOW: Tells ddraw to create its own window for 00745 * rendering (Possible test case: Half-Life) 00746 * 00747 * Unsure about these: DDSCL_FPUSETUP DDSCL_FPURESERVE 00748 * 00749 * These don't seem very important for wine: 00750 * DDSCL_ALLOWREBOOT, DDSCL_NOWINDOWCHANGES, DDSCL_ALLOWMODEX 00751 * 00752 * Returns: 00753 * DD_OK if the cooperative level was set successfully 00754 * DDERR_INVALIDPARAMS if the passed cooperative level combination is invalid 00755 * DDERR_HWNDALREADYSET if DDSCL_SETFOCUSWINDOW is passed in exclusive mode 00756 * (Probably others too, have to investigate) 00757 * 00758 *****************************************************************************/ 00759 static HRESULT WINAPI ddraw7_SetCooperativeLevel(IDirectDraw7 *iface, HWND hwnd, DWORD cooplevel) 00760 { 00761 IDirectDrawImpl *This = impl_from_IDirectDraw7(iface); 00762 struct wined3d_stateblock *stateblock; 00763 struct wined3d_surface *rt, *ds; 00764 BOOL restore_state = FALSE; 00765 HWND window; 00766 HRESULT hr; 00767 00768 TRACE("iface %p, window %p, flags %#x.\n", iface, hwnd, cooplevel); 00769 DDRAW_dump_cooperativelevel(cooplevel); 00770 00771 wined3d_mutex_lock(); 00772 00773 /* Get the old window */ 00774 window = This->dest_window; 00775 00776 /* Tests suggest that we need one of them: */ 00777 if(!(cooplevel & (DDSCL_SETFOCUSWINDOW | 00778 DDSCL_NORMAL | 00779 DDSCL_EXCLUSIVE ))) 00780 { 00781 TRACE("Incorrect cooplevel flags, returning DDERR_INVALIDPARAMS\n"); 00782 wined3d_mutex_unlock(); 00783 return DDERR_INVALIDPARAMS; 00784 } 00785 00786 if ((cooplevel & DDSCL_CREATEDEVICEWINDOW) && !(cooplevel & DDSCL_EXCLUSIVE)) 00787 { 00788 WARN("DDSCL_CREATEDEVICEWINDOW requires DDSCL_EXCLUSIVE.\n"); 00789 wined3d_mutex_unlock(); 00790 return DDERR_INVALIDPARAMS; 00791 } 00792 00793 /* Handle those levels first which set various hwnds */ 00794 if ((cooplevel & DDSCL_SETFOCUSWINDOW) && !(cooplevel & DDSCL_CREATEDEVICEWINDOW)) 00795 { 00796 /* This isn't compatible with a lot of flags */ 00797 if (cooplevel & (DDSCL_MULTITHREADED 00798 | DDSCL_FPUSETUP 00799 | DDSCL_FPUPRESERVE 00800 | DDSCL_ALLOWREBOOT 00801 | DDSCL_ALLOWMODEX 00802 | DDSCL_SETDEVICEWINDOW 00803 | DDSCL_NORMAL 00804 | DDSCL_EXCLUSIVE 00805 | DDSCL_FULLSCREEN)) 00806 { 00807 WARN("Called with incompatible flags, returning DDERR_INVALIDPARAMS.\n"); 00808 wined3d_mutex_unlock(); 00809 return DDERR_INVALIDPARAMS; 00810 } 00811 00812 hr = ddraw_set_focus_window(This, hwnd); 00813 wined3d_mutex_unlock(); 00814 return hr; 00815 } 00816 00817 if (cooplevel & DDSCL_EXCLUSIVE) 00818 { 00819 if (!(cooplevel & DDSCL_FULLSCREEN) || !(hwnd || (cooplevel & DDSCL_CREATEDEVICEWINDOW))) 00820 { 00821 WARN("DDSCL_EXCLUSIVE requires DDSCL_FULLSCREEN and a window.\n"); 00822 wined3d_mutex_unlock(); 00823 return DDERR_INVALIDPARAMS; 00824 } 00825 00826 if (cooplevel & DDSCL_CREATEDEVICEWINDOW) 00827 { 00828 HWND device_window; 00829 00830 if (!This->focuswindow && !(cooplevel & DDSCL_SETFOCUSWINDOW)) 00831 { 00832 WARN("No focus window set.\n"); 00833 wined3d_mutex_unlock(); 00834 return DDERR_NOFOCUSWINDOW; 00835 } 00836 00837 device_window = CreateWindowExA(0, DDRAW_WINDOW_CLASS_NAME, "DirectDrawDeviceWnd", 00838 WS_POPUP, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), 00839 NULL, NULL, NULL, NULL); 00840 if (!device_window) 00841 { 00842 ERR("Failed to create window, last error %#x.\n", GetLastError()); 00843 wined3d_mutex_unlock(); 00844 return E_FAIL; 00845 } 00846 00847 ShowWindow(device_window, SW_SHOW); 00848 TRACE("Created a device window %p.\n", device_window); 00849 00850 /* Native apparently leaks the created device window if setting the 00851 * focus window below fails. */ 00852 This->cooperative_level |= DDSCL_CREATEDEVICEWINDOW; 00853 This->devicewindow = device_window; 00854 00855 if (cooplevel & DDSCL_SETFOCUSWINDOW) 00856 { 00857 if (!hwnd) 00858 { 00859 wined3d_mutex_unlock(); 00860 return DDERR_NOHWND; 00861 } 00862 00863 if (FAILED(hr = ddraw_set_focus_window(This, hwnd))) 00864 { 00865 wined3d_mutex_unlock(); 00866 return hr; 00867 } 00868 } 00869 00870 hwnd = device_window; 00871 } 00872 } 00873 else 00874 { 00875 if (This->cooperative_level & DDSCL_CREATEDEVICEWINDOW) 00876 DestroyWindow(This->devicewindow); 00877 This->devicewindow = NULL; 00878 This->focuswindow = NULL; 00879 } 00880 00881 if ((This->cooperative_level & DDSCL_EXCLUSIVE) 00882 && (hwnd != window || !(cooplevel & DDSCL_EXCLUSIVE))) 00883 wined3d_device_release_focus_window(This->wined3d_device); 00884 00885 if ((cooplevel & DDSCL_FULLSCREEN) != (This->cooperative_level & DDSCL_FULLSCREEN) || hwnd != window) 00886 { 00887 if (This->cooperative_level & DDSCL_FULLSCREEN) 00888 wined3d_device_restore_fullscreen_window(This->wined3d_device, window); 00889 00890 if (cooplevel & DDSCL_FULLSCREEN) 00891 { 00892 struct wined3d_display_mode display_mode; 00893 00894 wined3d_get_adapter_display_mode(This->wined3d, WINED3DADAPTER_DEFAULT, &display_mode); 00895 wined3d_device_setup_fullscreen_window(This->wined3d_device, hwnd, 00896 display_mode.width, display_mode.height); 00897 } 00898 } 00899 00900 if ((cooplevel & DDSCL_EXCLUSIVE) 00901 && (hwnd != window || !(This->cooperative_level & DDSCL_EXCLUSIVE))) 00902 { 00903 hr = wined3d_device_acquire_focus_window(This->wined3d_device, hwnd); 00904 if (FAILED(hr)) 00905 { 00906 ERR("Failed to acquire focus window, hr %#x.\n", hr); 00907 wined3d_mutex_unlock(); 00908 return hr; 00909 } 00910 } 00911 00912 /* Don't override focus windows or private device windows */ 00913 if (hwnd && !This->focuswindow && !This->devicewindow && (hwnd != window)) 00914 This->dest_window = hwnd; 00915 00916 if (cooplevel & DDSCL_MULTITHREADED && !(This->cooperative_level & DDSCL_MULTITHREADED)) 00917 wined3d_device_set_multithreaded(This->wined3d_device); 00918 00919 if (This->wined3d_swapchain) 00920 { 00921 if (DefaultSurfaceType != SURFACE_GDI) 00922 { 00923 restore_state = TRUE; 00924 00925 if (FAILED(hr = wined3d_stateblock_create(This->wined3d_device, WINED3D_SBT_ALL, &stateblock))) 00926 { 00927 ERR("Failed to create stateblock, hr %#x.\n", hr); 00928 wined3d_mutex_unlock(); 00929 return hr; 00930 } 00931 00932 if (FAILED(hr = wined3d_stateblock_capture(stateblock))) 00933 { 00934 ERR("Failed to capture stateblock, hr %#x.\n", hr); 00935 wined3d_stateblock_decref(stateblock); 00936 wined3d_mutex_unlock(); 00937 return hr; 00938 } 00939 00940 wined3d_device_get_render_target(This->wined3d_device, 0, &rt); 00941 if (rt == This->wined3d_frontbuffer) 00942 { 00943 wined3d_surface_decref(rt); 00944 rt = NULL; 00945 } 00946 00947 wined3d_device_get_depth_stencil(This->wined3d_device, &ds); 00948 } 00949 00950 ddraw_destroy_swapchain(This); 00951 } 00952 00953 if (FAILED(hr = ddraw_create_swapchain(This, This->dest_window, !(cooplevel & DDSCL_FULLSCREEN)))) 00954 ERR("Failed to create swapchain, hr %#x.\n", hr); 00955 00956 if (restore_state) 00957 { 00958 if (ds) 00959 { 00960 wined3d_device_set_depth_stencil(This->wined3d_device, ds); 00961 wined3d_surface_decref(ds); 00962 } 00963 00964 if (rt) 00965 { 00966 wined3d_device_set_render_target(This->wined3d_device, 0, rt, FALSE); 00967 wined3d_surface_decref(rt); 00968 } 00969 00970 hr = wined3d_stateblock_apply(stateblock); 00971 wined3d_stateblock_decref(stateblock); 00972 if (FAILED(hr)) 00973 { 00974 ERR("Failed to apply stateblock, hr %#x.\n", hr); 00975 wined3d_mutex_unlock(); 00976 return hr; 00977 } 00978 } 00979 00980 /* Unhandled flags */ 00981 if(cooplevel & DDSCL_ALLOWREBOOT) 00982 WARN("(%p) Unhandled flag DDSCL_ALLOWREBOOT, harmless\n", This); 00983 if(cooplevel & DDSCL_ALLOWMODEX) 00984 WARN("(%p) Unhandled flag DDSCL_ALLOWMODEX, harmless\n", This); 00985 if(cooplevel & DDSCL_FPUSETUP) 00986 WARN("(%p) Unhandled flag DDSCL_FPUSETUP, harmless\n", This); 00987 00988 /* Store the cooperative_level */ 00989 This->cooperative_level = cooplevel; 00990 TRACE("SetCooperativeLevel retuning DD_OK\n"); 00991 wined3d_mutex_unlock(); 00992 00993 return DD_OK; 00994 } 00995 00996 static HRESULT WINAPI ddraw4_SetCooperativeLevel(IDirectDraw4 *iface, HWND window, DWORD flags) 00997 { 00998 IDirectDrawImpl *This = impl_from_IDirectDraw4(iface); 00999 01000 TRACE("iface %p, window %p, flags %#x.\n", iface, window, flags); 01001 01002 return ddraw7_SetCooperativeLevel(&This->IDirectDraw7_iface, window, flags); 01003 } 01004 01005 static HRESULT WINAPI ddraw2_SetCooperativeLevel(IDirectDraw2 *iface, HWND window, DWORD flags) 01006 { 01007 IDirectDrawImpl *This = impl_from_IDirectDraw2(iface); 01008 01009 TRACE("iface %p, window %p, flags %#x.\n", iface, window, flags); 01010 01011 return ddraw7_SetCooperativeLevel(&This->IDirectDraw7_iface, window, flags); 01012 } 01013 01014 static HRESULT WINAPI ddraw1_SetCooperativeLevel(IDirectDraw *iface, HWND window, DWORD flags) 01015 { 01016 IDirectDrawImpl *This = impl_from_IDirectDraw(iface); 01017 01018 TRACE("iface %p, window %p, flags %#x.\n", iface, window, flags); 01019 01020 return ddraw7_SetCooperativeLevel(&This->IDirectDraw7_iface, window, flags); 01021 } 01022 01023 /***************************************************************************** 01024 * 01025 * Helper function for SetDisplayMode and RestoreDisplayMode 01026 * 01027 * Implements DirectDraw's SetDisplayMode, but ignores the value of 01028 * ForceRefreshRate, since it is already handled by 01029 * ddraw7_SetDisplayMode. RestoreDisplayMode can use this function 01030 * without worrying that ForceRefreshRate will override the refresh rate. For 01031 * argument and return value documentation, see 01032 * ddraw7_SetDisplayMode. 01033 * 01034 *****************************************************************************/ 01035 static HRESULT ddraw_set_display_mode(IDirectDrawImpl *ddraw, DWORD Width, DWORD Height, 01036 DWORD BPP, DWORD RefreshRate, DWORD Flags) 01037 { 01038 struct wined3d_display_mode mode; 01039 enum wined3d_format_id format; 01040 HRESULT hr; 01041 01042 TRACE("ddraw %p, width %u, height %u, bpp %u, refresh_rate %u, flags %#x.\n", ddraw, Width, 01043 Height, BPP, RefreshRate, Flags); 01044 01045 wined3d_mutex_lock(); 01046 if( !Width || !Height ) 01047 { 01048 ERR("Width %u, Height %u, what to do?\n", Width, Height); 01049 /* It looks like Need for Speed Porsche Unleashed expects DD_OK here */ 01050 wined3d_mutex_unlock(); 01051 return DD_OK; 01052 } 01053 01054 switch(BPP) 01055 { 01056 case 8: format = WINED3DFMT_P8_UINT; break; 01057 case 15: format = WINED3DFMT_B5G5R5X1_UNORM; break; 01058 case 16: format = WINED3DFMT_B5G6R5_UNORM; break; 01059 case 24: format = WINED3DFMT_B8G8R8_UNORM; break; 01060 case 32: format = WINED3DFMT_B8G8R8X8_UNORM; break; 01061 default: format = WINED3DFMT_UNKNOWN; break; 01062 } 01063 01064 if (FAILED(hr = wined3d_device_get_display_mode(ddraw->wined3d_device, 0, &mode))) 01065 { 01066 ERR("Failed to get current display mode, hr %#x.\n", hr); 01067 } 01068 else if (mode.width == Width 01069 && mode.height == Height 01070 && mode.format_id == format 01071 && mode.refresh_rate == RefreshRate) 01072 { 01073 TRACE("Skipping redundant mode setting call.\n"); 01074 wined3d_mutex_unlock(); 01075 return DD_OK; 01076 } 01077 01078 /* Check the exclusive mode 01079 if(!(ddraw->cooperative_level & DDSCL_EXCLUSIVE)) 01080 return DDERR_NOEXCLUSIVEMODE; 01081 * This is WRONG. Don't know if the SDK is completely 01082 * wrong and if there are any conditions when DDERR_NOEXCLUSIVE 01083 * is returned, but Half-Life 1.1.1.1 (Steam version) 01084 * depends on this 01085 */ 01086 01087 mode.width = Width; 01088 mode.height = Height; 01089 mode.refresh_rate = RefreshRate; 01090 mode.format_id = format; 01091 01092 /* TODO: The possible return values from msdn suggest that 01093 * the screen mode can't be changed if a surface is locked 01094 * or some drawing is in progress 01095 */ 01096 01097 /* TODO: Lose the primary surface */ 01098 hr = wined3d_device_set_display_mode(ddraw->wined3d_device, 0, &mode); 01099 01100 wined3d_mutex_unlock(); 01101 01102 switch(hr) 01103 { 01104 case WINED3DERR_NOTAVAILABLE: return DDERR_UNSUPPORTED; 01105 default: return hr; 01106 } 01107 } 01108 01109 /***************************************************************************** 01110 * IDirectDraw7::SetDisplayMode 01111 * 01112 * Sets the display screen resolution, color depth and refresh frequency 01113 * when in fullscreen mode (in theory). 01114 * Possible return values listed in the SDK suggest that this method fails 01115 * when not in fullscreen mode, but this is wrong. Windows 2000 happily sets 01116 * the display mode in DDSCL_NORMAL mode without an hwnd specified. 01117 * It seems to be valid to pass 0 for With and Height, this has to be tested 01118 * It could mean that the current video mode should be left as-is. (But why 01119 * call it then?) 01120 * 01121 * Params: 01122 * Height, Width: Screen dimension 01123 * BPP: Color depth in Bits per pixel 01124 * Refreshrate: Screen refresh rate 01125 * Flags: Other stuff 01126 * 01127 * Returns 01128 * DD_OK on success 01129 * 01130 *****************************************************************************/ 01131 static HRESULT WINAPI ddraw7_SetDisplayMode(IDirectDraw7 *iface, DWORD Width, DWORD Height, 01132 DWORD BPP, DWORD RefreshRate, DWORD Flags) 01133 { 01134 IDirectDrawImpl *This = impl_from_IDirectDraw7(iface); 01135 01136 TRACE("iface %p, width %u, height %u, bpp %u, refresh_rate %u, flags %#x.\n", 01137 iface, Width, Height, BPP, RefreshRate, Flags); 01138 01139 if (force_refresh_rate != 0) 01140 { 01141 TRACE("ForceRefreshRate overriding passed-in refresh rate (%u Hz) to %u Hz\n", 01142 RefreshRate, force_refresh_rate); 01143 RefreshRate = force_refresh_rate; 01144 } 01145 01146 return ddraw_set_display_mode(This, Width, Height, BPP, RefreshRate, Flags); 01147 } 01148 01149 static HRESULT WINAPI ddraw4_SetDisplayMode(IDirectDraw4 *iface, DWORD width, DWORD height, 01150 DWORD bpp, DWORD refresh_rate, DWORD flags) 01151 { 01152 IDirectDrawImpl *This = impl_from_IDirectDraw4(iface); 01153 01154 TRACE("iface %p, width %u, height %u, bpp %u, refresh_rate %u, flags %#x.\n", 01155 iface, width, height, bpp, refresh_rate, flags); 01156 01157 return ddraw7_SetDisplayMode(&This->IDirectDraw7_iface, width, height, bpp, refresh_rate, flags); 01158 } 01159 01160 static HRESULT WINAPI ddraw2_SetDisplayMode(IDirectDraw2 *iface, 01161 DWORD width, DWORD height, DWORD bpp, DWORD refresh_rate, DWORD flags) 01162 { 01163 IDirectDrawImpl *This = impl_from_IDirectDraw2(iface); 01164 01165 TRACE("iface %p, width %u, height %u, bpp %u, refresh_rate %u, flags %#x.\n", 01166 iface, width, height, bpp, refresh_rate, flags); 01167 01168 return ddraw7_SetDisplayMode(&This->IDirectDraw7_iface, width, height, bpp, refresh_rate, flags); 01169 } 01170 01171 static HRESULT WINAPI ddraw1_SetDisplayMode(IDirectDraw *iface, DWORD width, DWORD height, DWORD bpp) 01172 { 01173 IDirectDrawImpl *This = impl_from_IDirectDraw(iface); 01174 01175 TRACE("iface %p, width %u, height %u, bpp %u.\n", iface, width, height, bpp); 01176 01177 return ddraw7_SetDisplayMode(&This->IDirectDraw7_iface, width, height, bpp, 0, 0); 01178 } 01179 01180 /***************************************************************************** 01181 * IDirectDraw7::RestoreDisplayMode 01182 * 01183 * Restores the display mode to what it was at creation time. Basically. 01184 * 01185 * A problem arises when there are 2 DirectDraw objects using the same hwnd: 01186 * -> DD_1 finds the screen at 1400x1050x32 when created, sets it to 640x480x16 01187 * -> DD_2 is created, finds the screen at 640x480x16, sets it to 1024x768x32 01188 * -> DD_1 is released. The screen should be left at 1024x768x32. 01189 * -> DD_2 is released. The screen should be set to 1400x1050x32 01190 * This case is unhandled right now, but Empire Earth does it this way. 01191 * (But perhaps there is something in SetCooperativeLevel to prevent this) 01192 * 01193 * The msdn says that this method resets the display mode to what it was before 01194 * SetDisplayMode was called. What if SetDisplayModes is called 2 times?? 01195 * 01196 * Returns 01197 * DD_OK on success 01198 * DDERR_NOEXCLUSIVE mode if the device isn't in fullscreen mode 01199 * 01200 *****************************************************************************/ 01201 static HRESULT WINAPI ddraw7_RestoreDisplayMode(IDirectDraw7 *iface) 01202 { 01203 IDirectDrawImpl *This = impl_from_IDirectDraw7(iface); 01204 01205 TRACE("iface %p.\n", iface); 01206 01207 return ddraw_set_display_mode(This, This->orig_width, This->orig_height, This->orig_bpp, 0, 0); 01208 } 01209 01210 static HRESULT WINAPI ddraw4_RestoreDisplayMode(IDirectDraw4 *iface) 01211 { 01212 IDirectDrawImpl *This = impl_from_IDirectDraw4(iface); 01213 01214 TRACE("iface %p.\n", iface); 01215 01216 return ddraw7_RestoreDisplayMode(&This->IDirectDraw7_iface); 01217 } 01218 01219 static HRESULT WINAPI ddraw2_RestoreDisplayMode(IDirectDraw2 *iface) 01220 { 01221 IDirectDrawImpl *This = impl_from_IDirectDraw2(iface); 01222 01223 TRACE("iface %p.\n", iface); 01224 01225 return ddraw7_RestoreDisplayMode(&This->IDirectDraw7_iface); 01226 } 01227 01228 static HRESULT WINAPI ddraw1_RestoreDisplayMode(IDirectDraw *iface) 01229 { 01230 IDirectDrawImpl *This = impl_from_IDirectDraw(iface); 01231 01232 TRACE("iface %p.\n", iface); 01233 01234 return ddraw7_RestoreDisplayMode(&This->IDirectDraw7_iface); 01235 } 01236 01237 /***************************************************************************** 01238 * IDirectDraw7::GetCaps 01239 * 01240 * Returns the drives capabilities 01241 * 01242 * Used for version 1, 2, 4 and 7 01243 * 01244 * Params: 01245 * DriverCaps: Structure to write the Hardware accelerated caps to 01246 * HelCaps: Structure to write the emulation caps to 01247 * 01248 * Returns 01249 * This implementation returns DD_OK only 01250 * 01251 *****************************************************************************/ 01252 static HRESULT WINAPI ddraw7_GetCaps(IDirectDraw7 *iface, DDCAPS *DriverCaps, DDCAPS *HELCaps) 01253 { 01254 IDirectDrawImpl *This = impl_from_IDirectDraw7(iface); 01255 DDCAPS caps; 01256 WINED3DCAPS winecaps; 01257 HRESULT hr; 01258 DDSCAPS2 ddscaps = {0, 0, 0, {0}}; 01259 01260 TRACE("iface %p, driver_caps %p, hel_caps %p.\n", iface, DriverCaps, HELCaps); 01261 01262 /* One structure must be != NULL */ 01263 if( (!DriverCaps) && (!HELCaps) ) 01264 { 01265 ERR("(%p) Invalid params to ddraw7_GetCaps\n", This); 01266 return DDERR_INVALIDPARAMS; 01267 } 01268 01269 memset(&caps, 0, sizeof(caps)); 01270 memset(&winecaps, 0, sizeof(winecaps)); 01271 caps.dwSize = sizeof(caps); 01272 01273 wined3d_mutex_lock(); 01274 hr = wined3d_device_get_device_caps(This->wined3d_device, &winecaps); 01275 if (FAILED(hr)) 01276 { 01277 WARN("IWineD3DDevice::GetDeviceCaps failed\n"); 01278 wined3d_mutex_unlock(); 01279 return hr; 01280 } 01281 01282 hr = IDirectDraw7_GetAvailableVidMem(iface, &ddscaps, &caps.dwVidMemTotal, &caps.dwVidMemFree); 01283 wined3d_mutex_unlock(); 01284 if(FAILED(hr)) { 01285 WARN("IDirectDraw7::GetAvailableVidMem failed\n"); 01286 return hr; 01287 } 01288 01289 caps.dwCaps = winecaps.ddraw_caps.caps; 01290 caps.dwCaps2 = winecaps.ddraw_caps.caps2; 01291 caps.dwCKeyCaps = winecaps.ddraw_caps.color_key_caps; 01292 caps.dwFXCaps = winecaps.ddraw_caps.fx_caps; 01293 caps.dwPalCaps = winecaps.ddraw_caps.pal_caps; 01294 caps.ddsCaps.dwCaps = winecaps.ddraw_caps.dds_caps; 01295 caps.dwSVBCaps = winecaps.ddraw_caps.svb_caps; 01296 caps.dwSVBCKeyCaps = winecaps.ddraw_caps.svb_color_key_caps; 01297 caps.dwSVBFXCaps = winecaps.ddraw_caps.svb_fx_caps; 01298 caps.dwVSBCaps = winecaps.ddraw_caps.vsb_caps; 01299 caps.dwVSBCKeyCaps = winecaps.ddraw_caps.vsb_color_key_caps; 01300 caps.dwVSBFXCaps = winecaps.ddraw_caps.vsb_fx_caps; 01301 caps.dwSSBCaps = winecaps.ddraw_caps.ssb_caps; 01302 caps.dwSSBCKeyCaps = winecaps.ddraw_caps.ssb_color_key_caps; 01303 caps.dwSSBFXCaps = winecaps.ddraw_caps.ssb_fx_caps; 01304 01305 /* Even if WineD3D supports 3D rendering, remove the cap if ddraw is configured 01306 * not to use it 01307 */ 01308 if(DefaultSurfaceType == SURFACE_GDI) { 01309 caps.dwCaps &= ~DDCAPS_3D; 01310 caps.ddsCaps.dwCaps &= ~(DDSCAPS_3DDEVICE | DDSCAPS_MIPMAP | DDSCAPS_TEXTURE | DDSCAPS_ZBUFFER); 01311 } 01312 if (winecaps.ddraw_caps.stride_align) 01313 { 01314 caps.dwCaps |= DDCAPS_ALIGNSTRIDE; 01315 caps.dwAlignStrideAlign = winecaps.ddraw_caps.stride_align; 01316 } 01317 01318 if(DriverCaps) 01319 { 01320 DD_STRUCT_COPY_BYSIZE(DriverCaps, &caps); 01321 if (TRACE_ON(ddraw)) 01322 { 01323 TRACE("Driver Caps :\n"); 01324 DDRAW_dump_DDCAPS(DriverCaps); 01325 } 01326 01327 } 01328 if(HELCaps) 01329 { 01330 DD_STRUCT_COPY_BYSIZE(HELCaps, &caps); 01331 if (TRACE_ON(ddraw)) 01332 { 01333 TRACE("HEL Caps :\n"); 01334 DDRAW_dump_DDCAPS(HELCaps); 01335 } 01336 } 01337 01338 return DD_OK; 01339 } 01340 01341 static HRESULT WINAPI ddraw4_GetCaps(IDirectDraw4 *iface, DDCAPS *driver_caps, DDCAPS *hel_caps) 01342 { 01343 IDirectDrawImpl *This = impl_from_IDirectDraw4(iface); 01344 01345 TRACE("iface %p, driver_caps %p, hel_caps %p.\n", iface, driver_caps, hel_caps); 01346 01347 return ddraw7_GetCaps(&This->IDirectDraw7_iface, driver_caps, hel_caps); 01348 } 01349 01350 static HRESULT WINAPI ddraw2_GetCaps(IDirectDraw2 *iface, DDCAPS *driver_caps, DDCAPS *hel_caps) 01351 { 01352 IDirectDrawImpl *This = impl_from_IDirectDraw2(iface); 01353 01354 TRACE("iface %p, driver_caps %p, hel_caps %p.\n", iface, driver_caps, hel_caps); 01355 01356 return ddraw7_GetCaps(&This->IDirectDraw7_iface, driver_caps, hel_caps); 01357 } 01358 01359 static HRESULT WINAPI ddraw1_GetCaps(IDirectDraw *iface, DDCAPS *driver_caps, DDCAPS *hel_caps) 01360 { 01361 IDirectDrawImpl *This = impl_from_IDirectDraw(iface); 01362 01363 TRACE("iface %p, driver_caps %p, hel_caps %p.\n", iface, driver_caps, hel_caps); 01364 01365 return ddraw7_GetCaps(&This->IDirectDraw7_iface, driver_caps, hel_caps); 01366 } 01367 01368 /***************************************************************************** 01369 * IDirectDraw7::Compact 01370 * 01371 * No idea what it does, MSDN says it's not implemented. 01372 * 01373 * Returns 01374 * DD_OK, but this is unchecked 01375 * 01376 *****************************************************************************/ 01377 static HRESULT WINAPI ddraw7_Compact(IDirectDraw7 *iface) 01378 { 01379 TRACE("iface %p.\n", iface); 01380 01381 return DD_OK; 01382 } 01383 01384 static HRESULT WINAPI ddraw4_Compact(IDirectDraw4 *iface) 01385 { 01386 IDirectDrawImpl *This = impl_from_IDirectDraw4(iface); 01387 01388 TRACE("iface %p.\n", iface); 01389 01390 return ddraw7_Compact(&This->IDirectDraw7_iface); 01391 } 01392 01393 static HRESULT WINAPI ddraw2_Compact(IDirectDraw2 *iface) 01394 { 01395 IDirectDrawImpl *This = impl_from_IDirectDraw2(iface); 01396 01397 TRACE("iface %p.\n", iface); 01398 01399 return ddraw7_Compact(&This->IDirectDraw7_iface); 01400 } 01401 01402 static HRESULT WINAPI ddraw1_Compact(IDirectDraw *iface) 01403 { 01404 IDirectDrawImpl *This = impl_from_IDirectDraw(iface); 01405 01406 TRACE("iface %p.\n", iface); 01407 01408 return ddraw7_Compact(&This->IDirectDraw7_iface); 01409 } 01410 01411 /***************************************************************************** 01412 * IDirectDraw7::GetDisplayMode 01413 * 01414 * Returns information about the current display mode 01415 * 01416 * Exists in Version 1, 2, 4 and 7 01417 * 01418 * Params: 01419 * DDSD: Address of a surface description structure to write the info to 01420 * 01421 * Returns 01422 * DD_OK 01423 * 01424 *****************************************************************************/ 01425 static HRESULT WINAPI ddraw7_GetDisplayMode(IDirectDraw7 *iface, DDSURFACEDESC2 *DDSD) 01426 { 01427 IDirectDrawImpl *This = impl_from_IDirectDraw7(iface); 01428 struct wined3d_display_mode mode; 01429 HRESULT hr; 01430 DWORD Size; 01431 01432 TRACE("iface %p, surface_desc %p.\n", iface, DDSD); 01433 01434 wined3d_mutex_lock(); 01435 /* This seems sane */ 01436 if (!DDSD) 01437 { 01438 wined3d_mutex_unlock(); 01439 return DDERR_INVALIDPARAMS; 01440 } 01441 01442 /* The necessary members of LPDDSURFACEDESC and LPDDSURFACEDESC2 are equal, 01443 * so one method can be used for all versions (Hopefully) */ 01444 hr = wined3d_device_get_display_mode(This->wined3d_device, 0, &mode); 01445 if (FAILED(hr)) 01446 { 01447 ERR(" (%p) IWineD3DDevice::GetDisplayMode returned %08x\n", This, hr); 01448 wined3d_mutex_unlock(); 01449 return hr; 01450 } 01451 01452 Size = DDSD->dwSize; 01453 memset(DDSD, 0, Size); 01454 01455 DDSD->dwSize = Size; 01456 DDSD->dwFlags |= DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT | DDSD_PITCH | DDSD_REFRESHRATE; 01457 DDSD->dwWidth = mode.width; 01458 DDSD->dwHeight = mode.height; 01459 DDSD->u2.dwRefreshRate = 60; 01460 DDSD->ddsCaps.dwCaps = 0; 01461 DDSD->u4.ddpfPixelFormat.dwSize = sizeof(DDSD->u4.ddpfPixelFormat); 01462 PixelFormat_WineD3DtoDD(&DDSD->u4.ddpfPixelFormat, mode.format_id); 01463 DDSD->u1.lPitch = mode.width * DDSD->u4.ddpfPixelFormat.u1.dwRGBBitCount / 8; 01464 01465 if(TRACE_ON(ddraw)) 01466 { 01467 TRACE("Returning surface desc :\n"); 01468 DDRAW_dump_surface_desc(DDSD); 01469 } 01470 01471 wined3d_mutex_unlock(); 01472 01473 return DD_OK; 01474 } 01475 01476 static HRESULT WINAPI ddraw4_GetDisplayMode(IDirectDraw4 *iface, DDSURFACEDESC2 *surface_desc) 01477 { 01478 IDirectDrawImpl *This = impl_from_IDirectDraw4(iface); 01479 01480 TRACE("iface %p, surface_desc %p.\n", iface, surface_desc); 01481 01482 return ddraw7_GetDisplayMode(&This->IDirectDraw7_iface, surface_desc); 01483 } 01484 01485 static HRESULT WINAPI ddraw2_GetDisplayMode(IDirectDraw2 *iface, DDSURFACEDESC *surface_desc) 01486 { 01487 IDirectDrawImpl *This = impl_from_IDirectDraw2(iface); 01488 01489 TRACE("iface %p, surface_desc %p.\n", iface, surface_desc); 01490 01491 /* FIXME: Test sizes, properly convert surface_desc */ 01492 return ddraw7_GetDisplayMode(&This->IDirectDraw7_iface, (DDSURFACEDESC2 *)surface_desc); 01493 } 01494 01495 static HRESULT WINAPI ddraw1_GetDisplayMode(IDirectDraw *iface, DDSURFACEDESC *surface_desc) 01496 { 01497 IDirectDrawImpl *This = impl_from_IDirectDraw(iface); 01498 01499 TRACE("iface %p, surface_desc %p.\n", iface, surface_desc); 01500 01501 /* FIXME: Test sizes, properly convert surface_desc */ 01502 return ddraw7_GetDisplayMode(&This->IDirectDraw7_iface, (DDSURFACEDESC2 *)surface_desc); 01503 } 01504 01505 /***************************************************************************** 01506 * IDirectDraw7::GetFourCCCodes 01507 * 01508 * Returns an array of supported FourCC codes. 01509 * 01510 * Exists in Version 1, 2, 4 and 7 01511 * 01512 * Params: 01513 * NumCodes: Contains the number of Codes that Codes can carry. Returns the number 01514 * of enumerated codes 01515 * Codes: Pointer to an array of DWORDs where the supported codes are written 01516 * to 01517 * 01518 * Returns 01519 * Always returns DD_OK, as it's a stub for now 01520 * 01521 *****************************************************************************/ 01522 static HRESULT WINAPI ddraw7_GetFourCCCodes(IDirectDraw7 *iface, DWORD *NumCodes, DWORD *Codes) 01523 { 01524 IDirectDrawImpl *This = impl_from_IDirectDraw7(iface); 01525 static const enum wined3d_format_id formats[] = 01526 { 01527 WINED3DFMT_YUY2, WINED3DFMT_UYVY, WINED3DFMT_YV12, 01528 WINED3DFMT_DXT1, WINED3DFMT_DXT2, WINED3DFMT_DXT3, WINED3DFMT_DXT4, WINED3DFMT_DXT5, 01529 WINED3DFMT_ATI2N, WINED3DFMT_NVHU, WINED3DFMT_NVHS 01530 }; 01531 struct wined3d_display_mode mode; 01532 DWORD count = 0, i, outsize; 01533 HRESULT hr; 01534 01535 TRACE("iface %p, codes_count %p, codes %p.\n", iface, NumCodes, Codes); 01536 01537 wined3d_device_get_display_mode(This->wined3d_device, 0, &mode); 01538 01539 outsize = NumCodes && Codes ? *NumCodes : 0; 01540 01541 for (i = 0; i < (sizeof(formats) / sizeof(formats[0])); ++i) 01542 { 01543 hr = wined3d_check_device_format(This->wined3d, WINED3DADAPTER_DEFAULT, WINED3D_DEVICE_TYPE_HAL, 01544 mode.format_id, 0, WINED3D_RTYPE_SURFACE, formats[i], DefaultSurfaceType); 01545 if (SUCCEEDED(hr)) 01546 { 01547 if (count < outsize) 01548 Codes[count] = formats[i]; 01549 ++count; 01550 } 01551 } 01552 if(NumCodes) { 01553 TRACE("Returning %u FourCC codes\n", count); 01554 *NumCodes = count; 01555 } 01556 01557 return DD_OK; 01558 } 01559 01560 static HRESULT WINAPI ddraw4_GetFourCCCodes(IDirectDraw4 *iface, DWORD *codes_count, DWORD *codes) 01561 { 01562 IDirectDrawImpl *This = impl_from_IDirectDraw4(iface); 01563 01564 TRACE("iface %p, codes_count %p, codes %p.\n", iface, codes_count, codes); 01565 01566 return ddraw7_GetFourCCCodes(&This->IDirectDraw7_iface, codes_count, codes); 01567 } 01568 01569 static HRESULT WINAPI ddraw2_GetFourCCCodes(IDirectDraw2 *iface, DWORD *codes_count, DWORD *codes) 01570 { 01571 IDirectDrawImpl *This = impl_from_IDirectDraw2(iface); 01572 01573 TRACE("iface %p, codes_count %p, codes %p.\n", iface, codes_count, codes); 01574 01575 return ddraw7_GetFourCCCodes(&This->IDirectDraw7_iface, codes_count, codes); 01576 } 01577 01578 static HRESULT WINAPI ddraw1_GetFourCCCodes(IDirectDraw *iface, DWORD *codes_count, DWORD *codes) 01579 { 01580 IDirectDrawImpl *This = impl_from_IDirectDraw(iface); 01581 01582 TRACE("iface %p, codes_count %p, codes %p.\n", iface, codes_count, codes); 01583 01584 return ddraw7_GetFourCCCodes(&This->IDirectDraw7_iface, codes_count, codes); 01585 } 01586 01587 /***************************************************************************** 01588 * IDirectDraw7::GetMonitorFrequency 01589 * 01590 * Returns the monitor's frequency 01591 * 01592 * Exists in Version 1, 2, 4 and 7 01593 * 01594 * Params: 01595 * Freq: Pointer to a DWORD to write the frequency to 01596 * 01597 * Returns 01598 * Always returns DD_OK 01599 * 01600 *****************************************************************************/ 01601 static HRESULT WINAPI ddraw7_GetMonitorFrequency(IDirectDraw7 *iface, DWORD *Freq) 01602 { 01603 FIXME("iface %p, frequency %p stub!\n", iface, Freq); 01604 01605 /* Ideally this should be in WineD3D, as it concerns the screen setup, 01606 * but for now this should make the games happy 01607 */ 01608 *Freq = 60; 01609 return DD_OK; 01610 } 01611 01612 static HRESULT WINAPI ddraw4_GetMonitorFrequency(IDirectDraw4 *iface, DWORD *frequency) 01613 { 01614 IDirectDrawImpl *This = impl_from_IDirectDraw4(iface); 01615 01616 TRACE("iface %p, frequency %p.\n", iface, frequency); 01617 01618 return ddraw7_GetMonitorFrequency(&This->IDirectDraw7_iface, frequency); 01619 } 01620 01621 static HRESULT WINAPI ddraw2_GetMonitorFrequency(IDirectDraw2 *iface, DWORD *frequency) 01622 { 01623 IDirectDrawImpl *This = impl_from_IDirectDraw2(iface); 01624 01625 TRACE("iface %p, frequency %p.\n", iface, frequency); 01626 01627 return ddraw7_GetMonitorFrequency(&This->IDirectDraw7_iface, frequency); 01628 } 01629 01630 static HRESULT WINAPI ddraw1_GetMonitorFrequency(IDirectDraw *iface, DWORD *frequency) 01631 { 01632 IDirectDrawImpl *This = impl_from_IDirectDraw(iface); 01633 01634 TRACE("iface %p, frequency %p.\n", iface, frequency); 01635 01636 return ddraw7_GetMonitorFrequency(&This->IDirectDraw7_iface, frequency); 01637 } 01638 01639 /***************************************************************************** 01640 * IDirectDraw7::GetVerticalBlankStatus 01641 * 01642 * Returns the Vertical blank status of the monitor. This should be in WineD3D 01643 * too basically, but as it's a semi stub, I didn't create a function there 01644 * 01645 * Params: 01646 * status: Pointer to a BOOL to be filled with the vertical blank status 01647 * 01648 * Returns 01649 * DD_OK on success 01650 * DDERR_INVALIDPARAMS if status is NULL 01651 * 01652 *****************************************************************************/ 01653 static HRESULT WINAPI ddraw7_GetVerticalBlankStatus(IDirectDraw7 *iface, BOOL *status) 01654 { 01655 static BOOL fake_vblank; 01656 01657 TRACE("iface %p, status %p.\n", iface, status); 01658 01659 if(!status) 01660 return DDERR_INVALIDPARAMS; 01661 01662 *status = fake_vblank; 01663 fake_vblank = !fake_vblank; 01664 01665 return DD_OK; 01666 } 01667 01668 static HRESULT WINAPI ddraw4_GetVerticalBlankStatus(IDirectDraw4 *iface, BOOL *status) 01669 { 01670 IDirectDrawImpl *This = impl_from_IDirectDraw4(iface); 01671 01672 TRACE("iface %p, status %p.\n", iface, status); 01673 01674 return ddraw7_GetVerticalBlankStatus(&This->IDirectDraw7_iface, status); 01675 } 01676 01677 static HRESULT WINAPI ddraw2_GetVerticalBlankStatus(IDirectDraw2 *iface, BOOL *status) 01678 { 01679 IDirectDrawImpl *This = impl_from_IDirectDraw2(iface); 01680 01681 TRACE("iface %p, status %p.\n", iface, status); 01682 01683 return ddraw7_GetVerticalBlankStatus(&This->IDirectDraw7_iface, status); 01684 } 01685 01686 static HRESULT WINAPI ddraw1_GetVerticalBlankStatus(IDirectDraw *iface, BOOL *status) 01687 { 01688 IDirectDrawImpl *This = impl_from_IDirectDraw(iface); 01689 01690 TRACE("iface %p, status %p.\n", iface, status); 01691 01692 return ddraw7_GetVerticalBlankStatus(&This->IDirectDraw7_iface, status); 01693 } 01694 01695 /***************************************************************************** 01696 * IDirectDraw7::GetAvailableVidMem 01697 * 01698 * Returns the total and free video memory 01699 * 01700 * Params: 01701 * Caps: Specifies the memory type asked for 01702 * total: Pointer to a DWORD to be filled with the total memory 01703 * free: Pointer to a DWORD to be filled with the free memory 01704 * 01705 * Returns 01706 * DD_OK on success 01707 * DDERR_INVALIDPARAMS of free and total are NULL 01708 * 01709 *****************************************************************************/ 01710 static HRESULT WINAPI ddraw7_GetAvailableVidMem(IDirectDraw7 *iface, DDSCAPS2 *Caps, DWORD *total, 01711 DWORD *free) 01712 { 01713 IDirectDrawImpl *This = impl_from_IDirectDraw7(iface); 01714 HRESULT hr = DD_OK; 01715 01716 TRACE("iface %p, caps %p, total %p, free %p.\n", iface, Caps, total, free); 01717 01718 if(TRACE_ON(ddraw)) 01719 { 01720 TRACE("(%p) Asked for memory with description: ", This); 01721 DDRAW_dump_DDSCAPS2(Caps); 01722 } 01723 wined3d_mutex_lock(); 01724 01725 /* Todo: System memory vs local video memory vs non-local video memory 01726 * The MSDN also mentions differences between texture memory and other 01727 * resources, but that's not important 01728 */ 01729 01730 if( (!total) && (!free) ) 01731 { 01732 wined3d_mutex_unlock(); 01733 return DDERR_INVALIDPARAMS; 01734 } 01735 01736 if (free) 01737 *free = wined3d_device_get_available_texture_mem(This->wined3d_device); 01738 if (total) 01739 { 01740 struct wined3d_adapter_identifier desc = {0}; 01741 01742 hr = wined3d_get_adapter_identifier(This->wined3d, WINED3DADAPTER_DEFAULT, 0, &desc); 01743 *total = desc.video_memory; 01744 } 01745 01746 wined3d_mutex_unlock(); 01747 01748 return hr; 01749 } 01750 01751 static HRESULT WINAPI ddraw4_GetAvailableVidMem(IDirectDraw4 *iface, 01752 DDSCAPS2 *caps, DWORD *total, DWORD *free) 01753 { 01754 IDirectDrawImpl *This = impl_from_IDirectDraw4(iface); 01755 01756 TRACE("iface %p, caps %p, total %p, free %p.\n", iface, caps, total, free); 01757 01758 return ddraw7_GetAvailableVidMem(&This->IDirectDraw7_iface, caps, total, free); 01759 } 01760 01761 static HRESULT WINAPI ddraw2_GetAvailableVidMem(IDirectDraw2 *iface, 01762 DDSCAPS *caps, DWORD *total, DWORD *free) 01763 { 01764 IDirectDrawImpl *This = impl_from_IDirectDraw2(iface); 01765 DDSCAPS2 caps2; 01766 01767 TRACE("iface %p, caps %p, total %p, free %p.\n", iface, caps, total, free); 01768 01769 DDRAW_Convert_DDSCAPS_1_To_2(caps, &caps2); 01770 return ddraw7_GetAvailableVidMem(&This->IDirectDraw7_iface, &caps2, total, free); 01771 } 01772 01773 /***************************************************************************** 01774 * IDirectDraw7::Initialize 01775 * 01776 * Initializes a DirectDraw interface. 01777 * 01778 * Params: 01779 * GUID: Interface identifier. Well, don't know what this is really good 01780 * for 01781 * 01782 * Returns 01783 * Returns DD_OK on the first call, 01784 * DDERR_ALREADYINITIALIZED on repeated calls 01785 * 01786 *****************************************************************************/ 01787 static HRESULT WINAPI ddraw7_Initialize(IDirectDraw7 *iface, GUID *guid) 01788 { 01789 IDirectDrawImpl *This = impl_from_IDirectDraw7(iface); 01790 01791 TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid)); 01792 01793 if (This->initialized) 01794 return DDERR_ALREADYINITIALIZED; 01795 01796 /* FIXME: To properly take the GUID into account we should call 01797 * ddraw_init() here instead of in DDRAW_Create(). */ 01798 if (guid) 01799 FIXME("Ignoring guid %s.\n", debugstr_guid(guid)); 01800 01801 This->initialized = TRUE; 01802 return DD_OK; 01803 } 01804 01805 static HRESULT WINAPI ddraw4_Initialize(IDirectDraw4 *iface, GUID *guid) 01806 { 01807 IDirectDrawImpl *This = impl_from_IDirectDraw4(iface); 01808 01809 TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid)); 01810 01811 return ddraw7_Initialize(&This->IDirectDraw7_iface, guid); 01812 } 01813 01814 static HRESULT WINAPI ddraw2_Initialize(IDirectDraw2 *iface, GUID *guid) 01815 { 01816 IDirectDrawImpl *This = impl_from_IDirectDraw2(iface); 01817 01818 TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid)); 01819 01820 return ddraw7_Initialize(&This->IDirectDraw7_iface, guid); 01821 } 01822 01823 static HRESULT WINAPI ddraw1_Initialize(IDirectDraw *iface, GUID *guid) 01824 { 01825 IDirectDrawImpl *This = impl_from_IDirectDraw(iface); 01826 01827 TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid)); 01828 01829 return ddraw7_Initialize(&This->IDirectDraw7_iface, guid); 01830 } 01831 01832 static HRESULT WINAPI d3d1_Initialize(IDirect3D *iface, REFIID riid) 01833 { 01834 TRACE("iface %p, riid %s.\n", iface, debugstr_guid(riid)); 01835 01836 return DDERR_ALREADYINITIALIZED; 01837 } 01838 01839 /***************************************************************************** 01840 * IDirectDraw7::FlipToGDISurface 01841 * 01842 * "Makes the surface that the GDI writes to the primary surface" 01843 * Looks like some windows specific thing we don't have to care about. 01844 * According to MSDN it permits GDI dialog boxes in FULLSCREEN mode. Good to 01845 * show error boxes ;) 01846 * Well, just return DD_OK. 01847 * 01848 * Returns: 01849 * Always returns DD_OK 01850 * 01851 *****************************************************************************/ 01852 static HRESULT WINAPI ddraw7_FlipToGDISurface(IDirectDraw7 *iface) 01853 { 01854 FIXME("iface %p stub!\n", iface); 01855 01856 return DD_OK; 01857 } 01858 01859 static HRESULT WINAPI ddraw4_FlipToGDISurface(IDirectDraw4 *iface) 01860 { 01861 IDirectDrawImpl *This = impl_from_IDirectDraw4(iface); 01862 01863 TRACE("iface %p.\n", iface); 01864 01865 return ddraw7_FlipToGDISurface(&This->IDirectDraw7_iface); 01866 } 01867 01868 static HRESULT WINAPI ddraw2_FlipToGDISurface(IDirectDraw2 *iface) 01869 { 01870 IDirectDrawImpl *This = impl_from_IDirectDraw2(iface); 01871 01872 TRACE("iface %p.\n", iface); 01873 01874 return ddraw7_FlipToGDISurface(&This->IDirectDraw7_iface); 01875 } 01876 01877 static HRESULT WINAPI ddraw1_FlipToGDISurface(IDirectDraw *iface) 01878 { 01879 IDirectDrawImpl *This = impl_from_IDirectDraw(iface); 01880 01881 TRACE("iface %p.\n", iface); 01882 01883 return ddraw7_FlipToGDISurface(&This->IDirectDraw7_iface); 01884 } 01885 01886 /***************************************************************************** 01887 * IDirectDraw7::WaitForVerticalBlank 01888 * 01889 * This method allows applications to get in sync with the vertical blank 01890 * interval. 01891 * The wormhole demo in the DirectX 7 sdk uses this call, and it doesn't 01892 * redraw the screen, most likely because of this stub 01893 * 01894 * Parameters: 01895 * Flags: one of DDWAITVB_BLOCKBEGIN, DDWAITVB_BLOCKBEGINEVENT 01896 * or DDWAITVB_BLOCKEND 01897 * h: Not used, according to MSDN 01898 * 01899 * Returns: 01900 * Always returns DD_OK 01901 * 01902 *****************************************************************************/ 01903 static HRESULT WINAPI ddraw7_WaitForVerticalBlank(IDirectDraw7 *iface, DWORD Flags, HANDLE event) 01904 { 01905 static BOOL hide; 01906 01907 TRACE("iface %p, flags %#x, event %p.\n", iface, Flags, event); 01908 01909 /* This function is called often, so print the fixme only once */ 01910 if(!hide) 01911 { 01912 FIXME("iface %p, flags %#x, event %p stub!\n", iface, Flags, event); 01913 hide = TRUE; 01914 } 01915 01916 /* MSDN says DDWAITVB_BLOCKBEGINEVENT is not supported */ 01917 if(Flags & DDWAITVB_BLOCKBEGINEVENT) 01918 return DDERR_UNSUPPORTED; /* unchecked */ 01919 01920 return DD_OK; 01921 } 01922 01923 static HRESULT WINAPI ddraw4_WaitForVerticalBlank(IDirectDraw4 *iface, DWORD flags, HANDLE event) 01924 { 01925 IDirectDrawImpl *This = impl_from_IDirectDraw4(iface); 01926 01927 TRACE("iface %p, flags %#x, event %p.\n", iface, flags, event); 01928 01929 return ddraw7_WaitForVerticalBlank(&This->IDirectDraw7_iface, flags, event); 01930 } 01931 01932 static HRESULT WINAPI ddraw2_WaitForVerticalBlank(IDirectDraw2 *iface, DWORD flags, HANDLE event) 01933 { 01934 IDirectDrawImpl *This = impl_from_IDirectDraw2(iface); 01935 01936 TRACE("iface %p, flags %#x, event %p.\n", iface, flags, event); 01937 01938 return ddraw7_WaitForVerticalBlank(&This->IDirectDraw7_iface, flags, event); 01939 } 01940 01941 static HRESULT WINAPI ddraw1_WaitForVerticalBlank(IDirectDraw *iface, DWORD flags, HANDLE event) 01942 { 01943 IDirectDrawImpl *This = impl_from_IDirectDraw(iface); 01944 01945 TRACE("iface %p, flags %#x, event %p.\n", iface, flags, event); 01946 01947 return ddraw7_WaitForVerticalBlank(&This->IDirectDraw7_iface, flags, event); 01948 } 01949 01950 /***************************************************************************** 01951 * IDirectDraw7::GetScanLine 01952 * 01953 * Returns the scan line that is being drawn on the monitor 01954 * 01955 * Parameters: 01956 * Scanline: Address to write the scan line value to 01957 * 01958 * Returns: 01959 * Always returns DD_OK 01960 * 01961 *****************************************************************************/ 01962 static HRESULT WINAPI ddraw7_GetScanLine(IDirectDraw7 *iface, DWORD *Scanline) 01963 { 01964 IDirectDrawImpl *This = impl_from_IDirectDraw7(iface); 01965 struct wined3d_display_mode mode; 01966 static DWORD cur_scanline; 01967 static BOOL hide = FALSE; 01968 01969 TRACE("iface %p, line %p.\n", iface, Scanline); 01970 01971 /* This function is called often, so print the fixme only once */ 01972 if(!hide) 01973 { 01974 FIXME("iface %p, line %p partial stub!\n", iface, Scanline); 01975 hide = TRUE; 01976 } 01977 01978 wined3d_mutex_lock(); 01979 wined3d_device_get_display_mode(This->wined3d_device, 0, &mode); 01980 wined3d_mutex_unlock(); 01981 01982 /* Fake the line sweeping of the monitor */ 01983 /* FIXME: We should synchronize with a source to keep the refresh rate */ 01984 *Scanline = cur_scanline++; 01985 /* Assume 20 scan lines in the vertical blank */ 01986 if (cur_scanline >= mode.height + 20) 01987 cur_scanline = 0; 01988 01989 return DD_OK; 01990 } 01991 01992 static HRESULT WINAPI ddraw4_GetScanLine(IDirectDraw4 *iface, DWORD *line) 01993 { 01994 IDirectDrawImpl *This = impl_from_IDirectDraw4(iface); 01995 01996 TRACE("iface %p, line %p.\n", iface, line); 01997 01998 return ddraw7_GetScanLine(&This->IDirectDraw7_iface, line); 01999 } 02000 02001 static HRESULT WINAPI ddraw2_GetScanLine(IDirectDraw2 *iface, DWORD *line) 02002 { 02003 IDirectDrawImpl *This = impl_from_IDirectDraw2(iface); 02004 02005 TRACE("iface %p, line %p.\n", iface, line); 02006 02007 return ddraw7_GetScanLine(&This->IDirectDraw7_iface, line); 02008 } 02009 02010 static HRESULT WINAPI ddraw1_GetScanLine(IDirectDraw *iface, DWORD *line) 02011 { 02012 IDirectDrawImpl *This = impl_from_IDirectDraw(iface); 02013 02014 TRACE("iface %p, line %p.\n", iface, line); 02015 02016 return ddraw7_GetScanLine(&This->IDirectDraw7_iface, line); 02017 } 02018 02019 /***************************************************************************** 02020 * IDirectDraw7::TestCooperativeLevel 02021 * 02022 * Informs the application about the state of the video adapter, depending 02023 * on the cooperative level 02024 * 02025 * Returns: 02026 * DD_OK if the device is in a sane state 02027 * DDERR_NOEXCLUSIVEMODE or DDERR_EXCLUSIVEMODEALREADYSET 02028 * if the state is not correct(See below) 02029 * 02030 *****************************************************************************/ 02031 static HRESULT WINAPI ddraw7_TestCooperativeLevel(IDirectDraw7 *iface) 02032 { 02033 TRACE("iface %p.\n", iface); 02034 02035 return DD_OK; 02036 } 02037 02038 static HRESULT WINAPI ddraw4_TestCooperativeLevel(IDirectDraw4 *iface) 02039 { 02040 IDirectDrawImpl *This = impl_from_IDirectDraw4(iface); 02041 02042 TRACE("iface %p.\n", iface); 02043 02044 return ddraw7_TestCooperativeLevel(&This->IDirectDraw7_iface); 02045 } 02046 02047 /***************************************************************************** 02048 * IDirectDraw7::GetGDISurface 02049 * 02050 * Returns the surface that GDI is treating as the primary surface. 02051 * For Wine this is the front buffer 02052 * 02053 * Params: 02054 * GDISurface: Address to write the surface pointer to 02055 * 02056 * Returns: 02057 * DD_OK if the surface was found 02058 * DDERR_NOTFOUND if the GDI surface wasn't found 02059 * 02060 *****************************************************************************/ 02061 static HRESULT WINAPI ddraw7_GetGDISurface(IDirectDraw7 *iface, IDirectDrawSurface7 **GDISurface) 02062 { 02063 IDirectDrawImpl *This = impl_from_IDirectDraw7(iface); 02064 02065 TRACE("iface %p, surface %p.\n", iface, GDISurface); 02066 02067 wined3d_mutex_lock(); 02068 02069 if (!(*GDISurface = &This->primary->IDirectDrawSurface7_iface)) 02070 { 02071 WARN("Primary not created yet.\n"); 02072 wined3d_mutex_unlock(); 02073 return DDERR_NOTFOUND; 02074 } 02075 IDirectDrawSurface7_AddRef(*GDISurface); 02076 02077 wined3d_mutex_unlock(); 02078 02079 return DD_OK; 02080 } 02081 02082 static HRESULT WINAPI ddraw4_GetGDISurface(IDirectDraw4 *iface, IDirectDrawSurface4 **surface) 02083 { 02084 IDirectDrawImpl *This = impl_from_IDirectDraw4(iface); 02085 IDirectDrawSurface7 *surface7; 02086 IDirectDrawSurfaceImpl *surface_impl; 02087 HRESULT hr; 02088 02089 TRACE("iface %p, surface %p.\n", iface, surface); 02090 02091 hr = ddraw7_GetGDISurface(&This->IDirectDraw7_iface, &surface7); 02092 if (FAILED(hr)) 02093 { 02094 *surface = NULL; 02095 return hr; 02096 } 02097 surface_impl = impl_from_IDirectDrawSurface7(surface7); 02098 *surface = &surface_impl->IDirectDrawSurface4_iface; 02099 IDirectDrawSurface4_AddRef(*surface); 02100 IDirectDrawSurface7_Release(surface7); 02101 02102 return hr; 02103 } 02104 02105 static HRESULT WINAPI ddraw2_GetGDISurface(IDirectDraw2 *iface, IDirectDrawSurface **surface) 02106 { 02107 IDirectDrawImpl *This = impl_from_IDirectDraw2(iface); 02108 IDirectDrawSurface7 *surface7; 02109 IDirectDrawSurfaceImpl *surface_impl; 02110 HRESULT hr; 02111 02112 TRACE("iface %p, surface %p.\n", iface, surface); 02113 02114 hr = ddraw7_GetGDISurface(&This->IDirectDraw7_iface, &surface7); 02115 if (FAILED(hr)) 02116 { 02117 *surface = NULL; 02118 return hr; 02119 } 02120 surface_impl = impl_from_IDirectDrawSurface7(surface7); 02121 *surface = &surface_impl->IDirectDrawSurface_iface; 02122 IDirectDrawSurface_AddRef(*surface); 02123 IDirectDrawSurface7_Release(surface7); 02124 02125 return hr; 02126 } 02127 02128 static HRESULT WINAPI ddraw1_GetGDISurface(IDirectDraw *iface, IDirectDrawSurface **surface) 02129 { 02130 IDirectDrawImpl *This = impl_from_IDirectDraw(iface); 02131 IDirectDrawSurface7 *surface7; 02132 IDirectDrawSurfaceImpl *surface_impl; 02133 HRESULT hr; 02134 02135 TRACE("iface %p, surface %p.\n", iface, surface); 02136 02137 hr = ddraw7_GetGDISurface(&This->IDirectDraw7_iface, &surface7); 02138 if (FAILED(hr)) 02139 { 02140 *surface = NULL; 02141 return hr; 02142 } 02143 surface_impl = impl_from_IDirectDrawSurface7(surface7); 02144 *surface = &surface_impl->IDirectDrawSurface_iface; 02145 IDirectDrawSurface_AddRef(*surface); 02146 IDirectDrawSurface7_Release(surface7); 02147 02148 return hr; 02149 } 02150 02151 struct displaymodescallback_context 02152 { 02153 LPDDENUMMODESCALLBACK func; 02154 void *context; 02155 }; 02156 02157 static HRESULT CALLBACK EnumDisplayModesCallbackThunk(DDSURFACEDESC2 *surface_desc, void *context) 02158 { 02159 struct displaymodescallback_context *cbcontext = context; 02160 DDSURFACEDESC desc; 02161 02162 DDSD2_to_DDSD(surface_desc, &desc); 02163 return cbcontext->func(&desc, cbcontext->context); 02164 } 02165 02166 /***************************************************************************** 02167 * IDirectDraw7::EnumDisplayModes 02168 * 02169 * Enumerates the supported Display modes. The modes can be filtered with 02170 * the DDSD parameter. 02171 * 02172 * Params: 02173 * Flags: can be DDEDM_REFRESHRATES and DDEDM_STANDARDVGAMODES. For old ddraw 02174 * versions (3 and older?) this is reserved and must be 0. 02175 * DDSD: Surface description to filter the modes 02176 * Context: Pointer passed back to the callback function 02177 * cb: Application-provided callback function 02178 * 02179 * Returns: 02180 * DD_OK on success 02181 * DDERR_INVALIDPARAMS if the callback wasn't set 02182 * 02183 *****************************************************************************/ 02184 static HRESULT WINAPI ddraw7_EnumDisplayModes(IDirectDraw7 *iface, DWORD Flags, 02185 DDSURFACEDESC2 *DDSD, void *Context, LPDDENUMMODESCALLBACK2 cb) 02186 { 02187 IDirectDrawImpl *This = impl_from_IDirectDraw7(iface); 02188 struct wined3d_display_mode *enum_modes = NULL; 02189 struct wined3d_display_mode mode; 02190 unsigned int modenum, fmt; 02191 DDSURFACEDESC2 callback_sd; 02192 unsigned enum_mode_count = 0, enum_mode_array_size = 0; 02193 DDPIXELFORMAT pixelformat; 02194 02195 static const enum wined3d_format_id checkFormatList[] = 02196 { 02197 WINED3DFMT_B8G8R8X8_UNORM, 02198 WINED3DFMT_B5G6R5_UNORM, 02199 WINED3DFMT_P8_UINT, 02200 }; 02201 02202 TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n", 02203 iface, Flags, DDSD, Context, cb); 02204 02205 if (!cb) 02206 return DDERR_INVALIDPARAMS; 02207 02208 wined3d_mutex_lock(); 02209 if(!(Flags & DDEDM_REFRESHRATES)) 02210 { 02211 enum_mode_array_size = 16; 02212 enum_modes = HeapAlloc(GetProcessHeap(), 0, sizeof(*enum_modes) * enum_mode_array_size); 02213 if (!enum_modes) 02214 { 02215 ERR("Out of memory\n"); 02216 wined3d_mutex_unlock(); 02217 return DDERR_OUTOFMEMORY; 02218 } 02219 } 02220 02221 pixelformat.dwSize = sizeof(pixelformat); 02222 for(fmt = 0; fmt < (sizeof(checkFormatList) / sizeof(checkFormatList[0])); fmt++) 02223 { 02224 modenum = 0; 02225 while (wined3d_enum_adapter_modes(This->wined3d, WINED3DADAPTER_DEFAULT, 02226 checkFormatList[fmt], modenum++, &mode) == WINED3D_OK) 02227 { 02228 PixelFormat_WineD3DtoDD(&pixelformat, mode.format_id); 02229 if (DDSD) 02230 { 02231 if (DDSD->dwFlags & DDSD_WIDTH && mode.width != DDSD->dwWidth) 02232 continue; 02233 if (DDSD->dwFlags & DDSD_HEIGHT && mode.height != DDSD->dwHeight) 02234 continue; 02235 if (DDSD->dwFlags & DDSD_REFRESHRATE && mode.refresh_rate != DDSD->u2.dwRefreshRate) 02236 continue; 02237 if (DDSD->dwFlags & DDSD_PIXELFORMAT 02238 && pixelformat.u1.dwRGBBitCount != DDSD->u4.ddpfPixelFormat.u1.dwRGBBitCount) 02239 continue; 02240 } 02241 02242 if(!(Flags & DDEDM_REFRESHRATES)) 02243 { 02244 /* DX docs state EnumDisplayMode should return only unique modes. If DDEDM_REFRESHRATES is not set, refresh 02245 * rate doesn't matter when determining if the mode is unique. So modes only differing in refresh rate have 02246 * to be reduced to a single unique result in such case. 02247 */ 02248 BOOL found = FALSE; 02249 unsigned i; 02250 02251 for (i = 0; i < enum_mode_count; i++) 02252 { 02253 if (enum_modes[i].width == mode.width && enum_modes[i].height == mode.height 02254 && enum_modes[i].format_id == mode.format_id) 02255 { 02256 found = TRUE; 02257 break; 02258 } 02259 } 02260 02261 if(found) continue; 02262 } 02263 02264 memset(&callback_sd, 0, sizeof(callback_sd)); 02265 callback_sd.dwSize = sizeof(callback_sd); 02266 callback_sd.u4.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT); 02267 02268 callback_sd.dwFlags = DDSD_HEIGHT|DDSD_WIDTH|DDSD_PIXELFORMAT|DDSD_PITCH|DDSD_REFRESHRATE; 02269 if (Flags & DDEDM_REFRESHRATES) 02270 callback_sd.u2.dwRefreshRate = mode.refresh_rate; 02271 02272 callback_sd.dwWidth = mode.width; 02273 callback_sd.dwHeight = mode.height; 02274 02275 callback_sd.u4.ddpfPixelFormat=pixelformat; 02276 02277 /* Calc pitch and DWORD align like MSDN says */ 02278 callback_sd.u1.lPitch = (callback_sd.u4.ddpfPixelFormat.u1.dwRGBBitCount / 8) * mode.width; 02279 callback_sd.u1.lPitch = (callback_sd.u1.lPitch + 3) & ~3; 02280 02281 TRACE("Enumerating %dx%dx%d @%d\n", callback_sd.dwWidth, callback_sd.dwHeight, callback_sd.u4.ddpfPixelFormat.u1.dwRGBBitCount, 02282 callback_sd.u2.dwRefreshRate); 02283 02284 if(cb(&callback_sd, Context) == DDENUMRET_CANCEL) 02285 { 02286 TRACE("Application asked to terminate the enumeration\n"); 02287 HeapFree(GetProcessHeap(), 0, enum_modes); 02288 wined3d_mutex_unlock(); 02289 return DD_OK; 02290 } 02291 02292 if(!(Flags & DDEDM_REFRESHRATES)) 02293 { 02294 if (enum_mode_count == enum_mode_array_size) 02295 { 02296 struct wined3d_display_mode *new_enum_modes; 02297 02298 enum_mode_array_size *= 2; 02299 new_enum_modes = HeapReAlloc(GetProcessHeap(), 0, enum_modes, 02300 sizeof(*new_enum_modes) * enum_mode_array_size); 02301 if (!new_enum_modes) 02302 { 02303 ERR("Out of memory\n"); 02304 HeapFree(GetProcessHeap(), 0, enum_modes); 02305 wined3d_mutex_unlock(); 02306 return DDERR_OUTOFMEMORY; 02307 } 02308 02309 enum_modes = new_enum_modes; 02310 } 02311 02312 enum_modes[enum_mode_count++] = mode; 02313 } 02314 } 02315 } 02316 02317 TRACE("End of enumeration\n"); 02318 HeapFree(GetProcessHeap(), 0, enum_modes); 02319 wined3d_mutex_unlock(); 02320 02321 return DD_OK; 02322 } 02323 02324 static HRESULT WINAPI ddraw4_EnumDisplayModes(IDirectDraw4 *iface, DWORD flags, 02325 DDSURFACEDESC2 *surface_desc, void *context, LPDDENUMMODESCALLBACK2 callback) 02326 { 02327 IDirectDrawImpl *This = impl_from_IDirectDraw4(iface); 02328 02329 TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n", 02330 iface, flags, surface_desc, context, callback); 02331 02332 return ddraw7_EnumDisplayModes(&This->IDirectDraw7_iface, flags, surface_desc, context, callback); 02333 } 02334 02335 static HRESULT WINAPI ddraw2_EnumDisplayModes(IDirectDraw2 *iface, DWORD flags, 02336 DDSURFACEDESC *surface_desc, void *context, LPDDENUMMODESCALLBACK callback) 02337 { 02338 IDirectDrawImpl *This = impl_from_IDirectDraw2(iface); 02339 struct displaymodescallback_context cbcontext; 02340 DDSURFACEDESC2 surface_desc2; 02341 02342 TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n", 02343 iface, flags, surface_desc, context, callback); 02344 02345 cbcontext.func = callback; 02346 cbcontext.context = context; 02347 02348 if (surface_desc) DDSD_to_DDSD2(surface_desc, &surface_desc2); 02349 return ddraw7_EnumDisplayModes(&This->IDirectDraw7_iface, flags, 02350 surface_desc ? &surface_desc2 : NULL, &cbcontext, EnumDisplayModesCallbackThunk); 02351 } 02352 02353 static HRESULT WINAPI ddraw1_EnumDisplayModes(IDirectDraw *iface, DWORD flags, 02354 DDSURFACEDESC *surface_desc, void *context, LPDDENUMMODESCALLBACK callback) 02355 { 02356 IDirectDrawImpl *This = impl_from_IDirectDraw(iface); 02357 struct displaymodescallback_context cbcontext; 02358 DDSURFACEDESC2 surface_desc2; 02359 02360 TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n", 02361 iface, flags, surface_desc, context, callback); 02362 02363 cbcontext.func = callback; 02364 cbcontext.context = context; 02365 02366 if (surface_desc) DDSD_to_DDSD2(surface_desc, &surface_desc2); 02367 return ddraw7_EnumDisplayModes(&This->IDirectDraw7_iface, flags, 02368 surface_desc ? &surface_desc2 : NULL, &cbcontext, EnumDisplayModesCallbackThunk); 02369 } 02370 02371 /***************************************************************************** 02372 * IDirectDraw7::EvaluateMode 02373 * 02374 * Used with IDirectDraw7::StartModeTest to test video modes. 02375 * EvaluateMode is used to pass or fail a mode, and continue with the next 02376 * mode 02377 * 02378 * Params: 02379 * Flags: DDEM_MODEPASSED or DDEM_MODEFAILED 02380 * Timeout: Returns the amount of seconds left before the mode would have 02381 * been failed automatically 02382 * 02383 * Returns: 02384 * This implementation always DD_OK, because it's a stub 02385 * 02386 *****************************************************************************/ 02387 static HRESULT WINAPI ddraw7_EvaluateMode(IDirectDraw7 *iface, DWORD Flags, DWORD *Timeout) 02388 { 02389 FIXME("iface %p, flags %#x, timeout %p stub!\n", iface, Flags, Timeout); 02390 02391 /* When implementing this, implement it in WineD3D */ 02392 02393 return DD_OK; 02394 } 02395 02396 /***************************************************************************** 02397 * IDirectDraw7::GetDeviceIdentifier 02398 * 02399 * Returns the device identifier, which gives information about the driver 02400 * Our device identifier is defined at the beginning of this file. 02401 * 02402 * Params: 02403 * DDDI: Address for the returned structure 02404 * Flags: Can be DDGDI_GETHOSTIDENTIFIER 02405 * 02406 * Returns: 02407 * On success it returns DD_OK 02408 * DDERR_INVALIDPARAMS if DDDI is NULL 02409 * 02410 *****************************************************************************/ 02411 static HRESULT WINAPI ddraw7_GetDeviceIdentifier(IDirectDraw7 *iface, 02412 DDDEVICEIDENTIFIER2 *DDDI, DWORD Flags) 02413 { 02414 TRACE("iface %p, device_identifier %p, flags %#x.\n", iface, DDDI, Flags); 02415 02416 if(!DDDI) 02417 return DDERR_INVALIDPARAMS; 02418 02419 /* The DDGDI_GETHOSTIDENTIFIER returns the information about the 2D 02420 * host adapter, if there's a secondary 3D adapter. This doesn't apply 02421 * to any modern hardware, nor is it interesting for Wine, so ignore it. 02422 * Size of DDDEVICEIDENTIFIER2 may be aligned to 8 bytes and thus 4 02423 * bytes too long. So only copy the relevant part of the structure 02424 */ 02425 02426 memcpy(DDDI, &deviceidentifier, FIELD_OFFSET(DDDEVICEIDENTIFIER2, dwWHQLLevel) + sizeof(DWORD)); 02427 return DD_OK; 02428 } 02429 02430 static HRESULT WINAPI ddraw4_GetDeviceIdentifier(IDirectDraw4 *iface, 02431 DDDEVICEIDENTIFIER *identifier, DWORD flags) 02432 { 02433 IDirectDrawImpl *This = impl_from_IDirectDraw4(iface); 02434 DDDEVICEIDENTIFIER2 identifier2; 02435 HRESULT hr; 02436 02437 TRACE("iface %p, identifier %p, flags %#x.\n", iface, identifier, flags); 02438 02439 hr = ddraw7_GetDeviceIdentifier(&This->IDirectDraw7_iface, &identifier2, flags); 02440 DDRAW_Convert_DDDEVICEIDENTIFIER_2_To_1(&identifier2, identifier); 02441 02442 return hr; 02443 } 02444 02445 /***************************************************************************** 02446 * IDirectDraw7::GetSurfaceFromDC 02447 * 02448 * Returns the Surface for a GDI device context handle. 02449 * Is this related to IDirectDrawSurface::GetDC ??? 02450 * 02451 * Params: 02452 * hdc: hdc to return the surface for 02453 * Surface: Address to write the surface pointer to 02454 * 02455 * Returns: 02456 * Always returns DD_OK because it's a stub 02457 * 02458 *****************************************************************************/ 02459 static HRESULT WINAPI ddraw7_GetSurfaceFromDC(IDirectDraw7 *iface, HDC hdc, 02460 IDirectDrawSurface7 **Surface) 02461 { 02462 IDirectDrawImpl *This = impl_from_IDirectDraw7(iface); 02463 struct wined3d_surface *wined3d_surface; 02464 HRESULT hr; 02465 02466 TRACE("iface %p, dc %p, surface %p.\n", iface, hdc, Surface); 02467 02468 if (!Surface) return E_INVALIDARG; 02469 02470 hr = wined3d_device_get_surface_from_dc(This->wined3d_device, hdc, &wined3d_surface); 02471 if (FAILED(hr)) 02472 { 02473 TRACE("No surface found for dc %p.\n", hdc); 02474 *Surface = NULL; 02475 return DDERR_NOTFOUND; 02476 } 02477 02478 *Surface = wined3d_surface_get_parent(wined3d_surface); 02479 IDirectDrawSurface7_AddRef(*Surface); 02480 TRACE("Returning surface %p.\n", Surface); 02481 return DD_OK; 02482 } 02483 02484 static HRESULT WINAPI ddraw4_GetSurfaceFromDC(IDirectDraw4 *iface, HDC dc, 02485 IDirectDrawSurface4 **surface) 02486 { 02487 IDirectDrawImpl *This = impl_from_IDirectDraw4(iface); 02488 IDirectDrawSurface7 *surface7; 02489 IDirectDrawSurfaceImpl *surface_impl; 02490 HRESULT hr; 02491 02492 TRACE("iface %p, dc %p, surface %p.\n", iface, dc, surface); 02493 02494 if (!surface) return E_INVALIDARG; 02495 02496 hr = ddraw7_GetSurfaceFromDC(&This->IDirectDraw7_iface, dc, &surface7); 02497 if (FAILED(hr)) 02498 { 02499 *surface = NULL; 02500 return hr; 02501 } 02502 surface_impl = impl_from_IDirectDrawSurface7(surface7); 02503 /* Tests say this is true */ 02504 *surface = (IDirectDrawSurface4 *)&surface_impl->IDirectDrawSurface_iface; 02505 IDirectDrawSurface_AddRef(&surface_impl->IDirectDrawSurface_iface); 02506 IDirectDrawSurface7_Release(surface7); 02507 02508 return hr; 02509 } 02510 02511 /***************************************************************************** 02512 * IDirectDraw7::RestoreAllSurfaces 02513 * 02514 * Calls the restore method of all surfaces 02515 * 02516 * Params: 02517 * 02518 * Returns: 02519 * Always returns DD_OK because it's a stub 02520 * 02521 *****************************************************************************/ 02522 static HRESULT WINAPI ddraw7_RestoreAllSurfaces(IDirectDraw7 *iface) 02523 { 02524 FIXME("iface %p stub!\n", iface); 02525 02526 /* This isn't hard to implement: Enumerate all WineD3D surfaces, 02527 * get their parent and call their restore method. Do not implement 02528 * it in WineD3D, as restoring a surface means re-creating the 02529 * WineD3DDSurface 02530 */ 02531 return DD_OK; 02532 } 02533 02534 static HRESULT WINAPI ddraw4_RestoreAllSurfaces(IDirectDraw4 *iface) 02535 { 02536 IDirectDrawImpl *This = impl_from_IDirectDraw4(iface); 02537 02538 TRACE("iface %p.\n", iface); 02539 02540 return ddraw7_RestoreAllSurfaces(&This->IDirectDraw7_iface); 02541 } 02542 02543 /***************************************************************************** 02544 * IDirectDraw7::StartModeTest 02545 * 02546 * Tests the specified video modes to update the system registry with 02547 * refresh rate information. StartModeTest starts the mode test, 02548 * EvaluateMode is used to fail or pass a mode. If EvaluateMode 02549 * isn't called within 15 seconds, the mode is failed automatically 02550 * 02551 * As refresh rates are handled by the X server, I don't think this 02552 * Method is important 02553 * 02554 * Params: 02555 * Modes: An array of mode specifications 02556 * NumModes: The number of modes in Modes 02557 * Flags: Some flags... 02558 * 02559 * Returns: 02560 * Returns DDERR_TESTFINISHED if flags contains DDSMT_ISTESTREQUIRED, 02561 * if no modes are passed, DDERR_INVALIDPARAMS is returned, 02562 * otherwise DD_OK 02563 * 02564 *****************************************************************************/ 02565 static HRESULT WINAPI ddraw7_StartModeTest(IDirectDraw7 *iface, SIZE *Modes, DWORD NumModes, DWORD Flags) 02566 { 02567 FIXME("iface %p, modes %p, mode_count %u, flags %#x partial stub!\n", 02568 iface, Modes, NumModes, Flags); 02569 02570 /* This looks sane */ 02571 if( (!Modes) || (NumModes == 0) ) return DDERR_INVALIDPARAMS; 02572 02573 /* DDSMT_ISTESTREQUIRED asks if a mode test is necessary. 02574 * As it is not, DDERR_TESTFINISHED is returned 02575 * (hopefully that's correct 02576 * 02577 if(Flags & DDSMT_ISTESTREQUIRED) return DDERR_TESTFINISHED; 02578 * well, that value doesn't (yet) exist in the wine headers, so ignore it 02579 */ 02580 02581 return DD_OK; 02582 } 02583 02584 /***************************************************************************** 02585 * ddraw_create_surface 02586 * 02587 * A helper function for IDirectDraw7::CreateSurface. It creates a new surface 02588 * with the passed parameters. 02589 * 02590 * Params: 02591 * DDSD: Description of the surface to create 02592 * Surf: Address to store the interface pointer at 02593 * 02594 * Returns: 02595 * DD_OK on success 02596 * 02597 *****************************************************************************/ 02598 static HRESULT ddraw_create_surface(IDirectDrawImpl *This, DDSURFACEDESC2 *pDDSD, 02599 IDirectDrawSurfaceImpl **ppSurf, UINT level, UINT version) 02600 { 02601 HRESULT hr; 02602 02603 TRACE("ddraw %p, surface_desc %p, surface %p, level %u.\n", 02604 This, pDDSD, ppSurf, level); 02605 02606 if (TRACE_ON(ddraw)) 02607 { 02608 TRACE(" (%p) Requesting surface desc :\n", This); 02609 DDRAW_dump_surface_desc(pDDSD); 02610 } 02611 02612 if ((pDDSD->ddsCaps.dwCaps & DDSCAPS_3DDEVICE) && DefaultSurfaceType != SURFACE_OPENGL) 02613 { 02614 WARN("The application requests a 3D capable surface, but a non-OpenGL surface type was set in the registry.\n"); 02615 /* Do not fail surface creation, only fail 3D device creation. */ 02616 } 02617 02618 /* Create the Surface object */ 02619 *ppSurf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectDrawSurfaceImpl)); 02620 if(!*ppSurf) 02621 { 02622 ERR("(%p) Error allocating memory for a surface\n", This); 02623 return DDERR_OUTOFVIDEOMEMORY; 02624 } 02625 02626 hr = ddraw_surface_init(*ppSurf, This, pDDSD, level, version); 02627 if (FAILED(hr)) 02628 { 02629 WARN("Failed to initialize surface, hr %#x.\n", hr); 02630 HeapFree(GetProcessHeap(), 0, *ppSurf); 02631 return hr; 02632 } 02633 02634 /* Increase the surface counter, and attach the surface */ 02635 list_add_head(&This->surface_list, &(*ppSurf)->surface_list_entry); 02636 02637 TRACE("Created surface %p.\n", *ppSurf); 02638 02639 return DD_OK; 02640 } 02641 /***************************************************************************** 02642 * CreateAdditionalSurfaces 02643 * 02644 * Creates a new mipmap chain. 02645 * 02646 * Params: 02647 * root: Root surface to attach the newly created chain to 02648 * count: number of surfaces to create 02649 * DDSD: Description of the surface. Intentionally not a pointer to avoid side 02650 * effects on the caller 02651 * CubeFaceRoot: Whether the new surface is a root of a cube map face. This 02652 * creates an additional surface without the mipmapping flags 02653 * 02654 *****************************************************************************/ 02655 static HRESULT 02656 CreateAdditionalSurfaces(IDirectDrawImpl *This, 02657 IDirectDrawSurfaceImpl *root, 02658 UINT count, 02659 DDSURFACEDESC2 DDSD, 02660 BOOL CubeFaceRoot, UINT version) 02661 { 02662 UINT i, j, level = 0; 02663 HRESULT hr; 02664 IDirectDrawSurfaceImpl *last = root; 02665 02666 for(i = 0; i < count; i++) 02667 { 02668 IDirectDrawSurfaceImpl *object2 = NULL; 02669 02670 /* increase the mipmap level, but only if a mipmap is created 02671 * In this case, also halve the size 02672 */ 02673 if(DDSD.ddsCaps.dwCaps & DDSCAPS_MIPMAP && !CubeFaceRoot) 02674 { 02675 level++; 02676 if(DDSD.dwWidth > 1) DDSD.dwWidth /= 2; 02677 if(DDSD.dwHeight > 1) DDSD.dwHeight /= 2; 02678 /* Set the mipmap sublevel flag according to msdn */ 02679 DDSD.ddsCaps.dwCaps2 |= DDSCAPS2_MIPMAPSUBLEVEL; 02680 } 02681 else 02682 { 02683 DDSD.ddsCaps.dwCaps2 &= ~DDSCAPS2_MIPMAPSUBLEVEL; 02684 } 02685 CubeFaceRoot = FALSE; 02686 02687 hr = ddraw_create_surface(This, &DDSD, &object2, level, version); 02688 if(hr != DD_OK) 02689 { 02690 return hr; 02691 } 02692 02693 /* Add the new surface to the complex attachment array */ 02694 for(j = 0; j < MAX_COMPLEX_ATTACHED; j++) 02695 { 02696 if(last->complex_array[j]) continue; 02697 last->complex_array[j] = object2; 02698 break; 02699 } 02700 last = object2; 02701 02702 /* Remove the (possible) back buffer cap from the new surface description, 02703 * because only one surface in the flipping chain is a back buffer, one 02704 * is a front buffer, the others are just primary surfaces. 02705 */ 02706 DDSD.ddsCaps.dwCaps &= ~DDSCAPS_BACKBUFFER; 02707 } 02708 return DD_OK; 02709 } 02710 02711 static HRESULT CDECL ddraw_reset_enum_callback(struct wined3d_resource *resource) 02712 { 02713 return DD_OK; 02714 } 02715 02716 /***************************************************************************** 02717 * IDirectDraw7::CreateSurface 02718 * 02719 * Creates a new IDirectDrawSurface object and returns its interface. 02720 * 02721 * The surface connections with wined3d are a bit tricky. Basically it works 02722 * like this: 02723 * 02724 * |------------------------| |-----------------| 02725 * | DDraw surface | | WineD3DSurface | 02726 * | | | | 02727 * | WineD3DSurface |-------------->| | 02728 * | Child |<------------->| Parent | 02729 * |------------------------| |-----------------| 02730 * 02731 * The DDraw surface is the parent of the wined3d surface, and it releases 02732 * the WineD3DSurface when the ddraw surface is destroyed. 02733 * 02734 * However, for all surfaces which can be in a container in WineD3D, 02735 * we have to do this. These surfaces are usually complex surfaces, 02736 * so this concerns primary surfaces with a front and a back buffer, 02737 * and textures. 02738 * 02739 * |------------------------| |-----------------| 02740 * | DDraw surface | | Container | 02741 * | | | | 02742 * | Child |<------------->| Parent | 02743 * | Texture |<------------->| | 02744 * | WineD3DSurface |<----| | Levels |<--| 02745 * | Complex connection | | | | | 02746 * |------------------------| | |-----------------| | 02747 * ^ | | 02748 * | | | 02749 * | | | 02750 * | |------------------| | |-----------------| | 02751 * | | IParent | |-------->| WineD3DSurface | | 02752 * | | | | | | 02753 * | | Child |<------------->| Parent | | 02754 * | | | | Container |<--| 02755 * | |------------------| |-----------------| | 02756 * | | 02757 * | |----------------------| | 02758 * | | DDraw surface 2 | | 02759 * | | | | 02760 * |<->| Complex root Child | | 02761 * | | Texture | | 02762 * | | WineD3DSurface |<----| | 02763 * | |----------------------| | | 02764 * | | | 02765 * | |---------------------| | |-----------------| | 02766 * | | IParent | |----->| WineD3DSurface | | 02767 * | | | | | | 02768 * | | Child |<---------->| Parent | | 02769 * | |---------------------| | Container |<--| 02770 * | |-----------------| | 02771 * | | 02772 * | ---More surfaces can follow--- | 02773 * 02774 * The reason is that the IWineD3DSwapchain(render target container) 02775 * and the IWineD3DTexure(Texture container) release the parents 02776 * of their surface's children, but by releasing the complex root 02777 * the surfaces which are complexly attached to it are destroyed 02778 * too. See IDirectDrawSurface::Release for a more detailed 02779 * explanation. 02780 * 02781 * Params: 02782 * DDSD: Description of the surface to create 02783 * Surf: Address to store the interface pointer at 02784 * UnkOuter: Basically for aggregation support, but ddraw doesn't support 02785 * aggregation, so it has to be NULL 02786 * 02787 * Returns: 02788 * DD_OK on success 02789 * CLASS_E_NOAGGREGATION if UnkOuter != NULL 02790 * DDERR_* if an error occurs 02791 * 02792 *****************************************************************************/ 02793 static HRESULT CreateSurface(IDirectDrawImpl *ddraw, DDSURFACEDESC2 *DDSD, 02794 IDirectDrawSurfaceImpl **Surf, IUnknown *UnkOuter, UINT version) 02795 { 02796 IDirectDrawSurfaceImpl *object = NULL; 02797 struct wined3d_display_mode mode; 02798 HRESULT hr; 02799 LONG extra_surfaces = 0; 02800 DDSURFACEDESC2 desc2; 02801 const DWORD sysvidmem = DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY; 02802 02803 TRACE("ddraw %p, surface_desc %p, surface %p, outer_unknown %p.\n", ddraw, DDSD, Surf, UnkOuter); 02804 02805 /* Some checks before we start */ 02806 if (TRACE_ON(ddraw)) 02807 { 02808 TRACE(" (%p) Requesting surface desc :\n", ddraw); 02809 DDRAW_dump_surface_desc(DDSD); 02810 } 02811 02812 if (UnkOuter != NULL) 02813 { 02814 FIXME("(%p) : outer != NULL?\n", ddraw); 02815 return CLASS_E_NOAGGREGATION; /* unchecked */ 02816 } 02817 02818 if (Surf == NULL) 02819 { 02820 FIXME("(%p) You want to get back a surface? Don't give NULL ptrs!\n", ddraw); 02821 return E_POINTER; /* unchecked */ 02822 } 02823 02824 if (!(DDSD->dwFlags & DDSD_CAPS)) 02825 { 02826 /* DVIDEO.DLL does forget the DDSD_CAPS flag ... *sigh* */ 02827 DDSD->dwFlags |= DDSD_CAPS; 02828 } 02829 02830 if (DDSD->ddsCaps.dwCaps & DDSCAPS_ALLOCONLOAD) 02831 { 02832 /* If the surface is of the 'alloconload' type, ignore the LPSURFACE field */ 02833 DDSD->dwFlags &= ~DDSD_LPSURFACE; 02834 } 02835 02836 if ((DDSD->dwFlags & DDSD_LPSURFACE) && (DDSD->lpSurface == NULL)) 02837 { 02838 /* Frank Herbert's Dune specifies a null pointer for the surface, ignore the LPSURFACE field */ 02839 WARN("(%p) Null surface pointer specified, ignore it!\n", ddraw); 02840 DDSD->dwFlags &= ~DDSD_LPSURFACE; 02841 } 02842 02843 if((DDSD->ddsCaps.dwCaps & (DDSCAPS_FLIP | DDSCAPS_PRIMARYSURFACE)) == (DDSCAPS_FLIP | DDSCAPS_PRIMARYSURFACE) && 02844 !(ddraw->cooperative_level & DDSCL_EXCLUSIVE)) 02845 { 02846 TRACE("(%p): Attempt to create a flipable primary surface without DDSCL_EXCLUSIVE set\n", 02847 ddraw); 02848 *Surf = NULL; 02849 return DDERR_NOEXCLUSIVEMODE; 02850 } 02851 02852 if((DDSD->ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER | DDSCAPS_PRIMARYSURFACE)) == (DDSCAPS_BACKBUFFER | DDSCAPS_PRIMARYSURFACE)) 02853 { 02854 WARN("Application wanted to create back buffer primary surface\n"); 02855 return DDERR_INVALIDCAPS; 02856 } 02857 02858 if((DDSD->ddsCaps.dwCaps & sysvidmem) == sysvidmem) 02859 { 02860 /* This is a special switch in ddrawex.dll, but not allowed in ddraw.dll */ 02861 WARN("Application tries to put the surface in both system and video memory\n"); 02862 *Surf = NULL; 02863 return DDERR_INVALIDCAPS; 02864 } 02865 02866 /* Check cube maps but only if the size includes them */ 02867 if (DDSD->dwSize >= sizeof(DDSURFACEDESC2)) 02868 { 02869 if(DDSD->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES && 02870 !(DDSD->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)) 02871 { 02872 WARN("Cube map faces requested without cube map flag\n"); 02873 return DDERR_INVALIDCAPS; 02874 } 02875 if(DDSD->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP && 02876 (DDSD->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES) == 0) 02877 { 02878 WARN("Cube map without faces requested\n"); 02879 return DDERR_INVALIDPARAMS; 02880 } 02881 02882 /* Quick tests confirm those can be created, but we don't do that yet */ 02883 if(DDSD->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP && 02884 (DDSD->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES) != DDSCAPS2_CUBEMAP_ALLFACES) 02885 { 02886 FIXME("Partial cube maps not supported yet\n"); 02887 } 02888 } 02889 02890 /* According to the msdn this flag is ignored by CreateSurface */ 02891 if (DDSD->dwSize >= sizeof(DDSURFACEDESC2)) 02892 DDSD->ddsCaps.dwCaps2 &= ~DDSCAPS2_MIPMAPSUBLEVEL; 02893 02894 /* Modify some flags */ 02895 copy_to_surfacedesc2(&desc2, DDSD); 02896 desc2.u4.ddpfPixelFormat.dwSize=sizeof(DDPIXELFORMAT); /* Just to be sure */ 02897 02898 /* Get the video mode from WineD3D - we will need it */ 02899 hr = wined3d_device_get_display_mode(ddraw->wined3d_device, 0, &mode); 02900 if (FAILED(hr)) 02901 { 02902 ERR("Failed to read display mode from wined3d\n"); 02903 switch(ddraw->orig_bpp) 02904 { 02905 case 8: 02906 mode.format_id = WINED3DFMT_P8_UINT; 02907 break; 02908 02909 case 15: 02910 mode.format_id = WINED3DFMT_B5G5R5X1_UNORM; 02911 break; 02912 02913 case 16: 02914 mode.format_id = WINED3DFMT_B5G6R5_UNORM; 02915 break; 02916 02917 case 24: 02918 mode.format_id = WINED3DFMT_B8G8R8_UNORM; 02919 break; 02920 02921 case 32: 02922 mode.format_id = WINED3DFMT_B8G8R8X8_UNORM; 02923 break; 02924 } 02925 mode.width = ddraw->orig_width; 02926 mode.height = ddraw->orig_height; 02927 } 02928 02929 /* No pixelformat given? Use the current screen format */ 02930 if(!(desc2.dwFlags & DDSD_PIXELFORMAT)) 02931 { 02932 desc2.dwFlags |= DDSD_PIXELFORMAT; 02933 desc2.u4.ddpfPixelFormat.dwSize=sizeof(DDPIXELFORMAT); 02934 02935 PixelFormat_WineD3DtoDD(&desc2.u4.ddpfPixelFormat, mode.format_id); 02936 } 02937 02938 /* No Width or no Height? Use the original screen size 02939 */ 02940 if(!(desc2.dwFlags & DDSD_WIDTH) || 02941 !(desc2.dwFlags & DDSD_HEIGHT) ) 02942 { 02943 /* Invalid for non-render targets */ 02944 if(!(desc2.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)) 02945 { 02946 WARN("Creating a non-Primary surface without Width or Height info, returning DDERR_INVALIDPARAMS\n"); 02947 *Surf = NULL; 02948 return DDERR_INVALIDPARAMS; 02949 } 02950 02951 desc2.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT; 02952 desc2.dwWidth = mode.width; 02953 desc2.dwHeight = mode.height; 02954 } 02955 02956 if (!desc2.dwWidth || !desc2.dwHeight) 02957 return DDERR_INVALIDPARAMS; 02958 02959 /* Mipmap count fixes */ 02960 if(desc2.ddsCaps.dwCaps & DDSCAPS_MIPMAP) 02961 { 02962 if(desc2.ddsCaps.dwCaps & DDSCAPS_COMPLEX) 02963 { 02964 if(desc2.dwFlags & DDSD_MIPMAPCOUNT) 02965 { 02966 /* Mipmap count is given, should not be 0 */ 02967 if( desc2.u2.dwMipMapCount == 0 ) 02968 return DDERR_INVALIDPARAMS; 02969 } 02970 else 02971 { 02972 /* Undocumented feature: Create sublevels until 02973 * either the width or the height is 1 02974 */ 02975 DWORD min = desc2.dwWidth < desc2.dwHeight ? 02976 desc2.dwWidth : desc2.dwHeight; 02977 desc2.u2.dwMipMapCount = 0; 02978 while( min ) 02979 { 02980 desc2.u2.dwMipMapCount += 1; 02981 min >>= 1; 02982 } 02983 } 02984 } 02985 else 02986 { 02987 /* Not-complex mipmap -> Mipmapcount = 1 */ 02988 desc2.u2.dwMipMapCount = 1; 02989 } 02990 extra_surfaces = desc2.u2.dwMipMapCount - 1; 02991 02992 /* There's a mipmap count in the created surface in any case */ 02993 desc2.dwFlags |= DDSD_MIPMAPCOUNT; 02994 } 02995 /* If no mipmap is given, the texture has only one level */ 02996 02997 /* The first surface is a front buffer, the back buffer is created afterwards */ 02998 if( (desc2.dwFlags & DDSD_CAPS) && (desc2.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) ) 02999 { 03000 desc2.ddsCaps.dwCaps |= DDSCAPS_FRONTBUFFER; 03001 } 03002 03003 /* The root surface in a cube map is positive x */ 03004 if(desc2.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP) 03005 { 03006 desc2.ddsCaps.dwCaps2 &= ~DDSCAPS2_CUBEMAP_ALLFACES; 03007 desc2.ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP_POSITIVEX; 03008 } 03009 03010 if ((desc2.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) && (ddraw->cooperative_level & DDSCL_EXCLUSIVE)) 03011 { 03012 struct wined3d_swapchain_desc swapchain_desc; 03013 03014 hr = wined3d_swapchain_get_desc(ddraw->wined3d_swapchain, &swapchain_desc); 03015 if (FAILED(hr)) 03016 { 03017 ERR("Failed to get present parameters.\n"); 03018 return hr; 03019 } 03020 03021 swapchain_desc.backbuffer_width = mode.width; 03022 swapchain_desc.backbuffer_height = mode.height; 03023 swapchain_desc.backbuffer_format = mode.format_id; 03024 03025 hr = wined3d_device_reset(ddraw->wined3d_device, 03026 &swapchain_desc, ddraw_reset_enum_callback); 03027 if (FAILED(hr)) 03028 { 03029 ERR("Failed to reset device.\n"); 03030 return hr; 03031 } 03032 } 03033 03034 /* Create the first surface */ 03035 hr = ddraw_create_surface(ddraw, &desc2, &object, 0, version); 03036 if (FAILED(hr)) 03037 { 03038 WARN("ddraw_create_surface failed, hr %#x.\n", hr); 03039 return hr; 03040 } 03041 object->is_complex_root = TRUE; 03042 03043 *Surf = object; 03044 03045 /* Create Additional surfaces if necessary 03046 * This applies to Primary surfaces which have a back buffer count 03047 * set, but not to mipmap textures. In case of Mipmap textures, 03048 * wineD3D takes care of the creation of additional surfaces 03049 */ 03050 if(DDSD->dwFlags & DDSD_BACKBUFFERCOUNT) 03051 { 03052 extra_surfaces = DDSD->u5.dwBackBufferCount; 03053 desc2.ddsCaps.dwCaps &= ~DDSCAPS_FRONTBUFFER; /* It's not a front buffer */ 03054 desc2.ddsCaps.dwCaps |= DDSCAPS_BACKBUFFER; 03055 desc2.u5.dwBackBufferCount = 0; 03056 } 03057 03058 hr = DD_OK; 03059 if(desc2.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP) 03060 { 03061 desc2.ddsCaps.dwCaps2 &= ~DDSCAPS2_CUBEMAP_ALLFACES; 03062 desc2.ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP_NEGATIVEZ; 03063 hr |= CreateAdditionalSurfaces(ddraw, object, extra_surfaces + 1, desc2, TRUE, version); 03064 desc2.ddsCaps.dwCaps2 &= ~DDSCAPS2_CUBEMAP_NEGATIVEZ; 03065 desc2.ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP_POSITIVEZ; 03066 hr |= CreateAdditionalSurfaces(ddraw, object, extra_surfaces + 1, desc2, TRUE, version); 03067 desc2.ddsCaps.dwCaps2 &= ~DDSCAPS2_CUBEMAP_POSITIVEZ; 03068 desc2.ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP_NEGATIVEY; 03069 hr |= CreateAdditionalSurfaces(ddraw, object, extra_surfaces + 1, desc2, TRUE, version); 03070 desc2.ddsCaps.dwCaps2 &= ~DDSCAPS2_CUBEMAP_NEGATIVEY; 03071 desc2.ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP_POSITIVEY; 03072 hr |= CreateAdditionalSurfaces(ddraw, object, extra_surfaces + 1, desc2, TRUE, version); 03073 desc2.ddsCaps.dwCaps2 &= ~DDSCAPS2_CUBEMAP_POSITIVEY; 03074 desc2.ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP_NEGATIVEX; 03075 hr |= CreateAdditionalSurfaces(ddraw, object, extra_surfaces + 1, desc2, TRUE, version); 03076 desc2.ddsCaps.dwCaps2 &= ~DDSCAPS2_CUBEMAP_NEGATIVEX; 03077 desc2.ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP_POSITIVEX; 03078 } 03079 03080 hr |= CreateAdditionalSurfaces(ddraw, object, extra_surfaces, desc2, FALSE, version); 03081 if(hr != DD_OK) 03082 { 03083 /* This destroys and possibly created surfaces too */ 03084 if (version == 7) 03085 IDirectDrawSurface7_Release(&object->IDirectDrawSurface7_iface); 03086 else if (version == 4) 03087 IDirectDrawSurface4_Release(&object->IDirectDrawSurface4_iface); 03088 else 03089 IDirectDrawSurface_Release(&object->IDirectDrawSurface_iface); 03090 03091 return hr; 03092 } 03093 03094 if (desc2.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) 03095 ddraw->primary = object; 03096 03097 /* Create a WineD3DTexture if a texture was requested */ 03098 if (desc2.ddsCaps.dwCaps & DDSCAPS_TEXTURE) 03099 { 03100 ddraw->tex_root = object; 03101 ddraw_surface_create_texture(object); 03102 ddraw->tex_root = NULL; 03103 } 03104 03105 return hr; 03106 } 03107 03108 static HRESULT WINAPI ddraw7_CreateSurface(IDirectDraw7 *iface, DDSURFACEDESC2 *surface_desc, 03109 IDirectDrawSurface7 **surface, IUnknown *outer_unknown) 03110 { 03111 IDirectDrawImpl *This = impl_from_IDirectDraw7(iface); 03112 IDirectDrawSurfaceImpl *impl; 03113 HRESULT hr; 03114 03115 TRACE("iface %p, surface_desc %p, surface %p, outer_unknown %p.\n", 03116 iface, surface_desc, surface, outer_unknown); 03117 03118 wined3d_mutex_lock(); 03119 03120 if (!(This->cooperative_level & (DDSCL_NORMAL | DDSCL_EXCLUSIVE))) 03121 { 03122 WARN("Cooperative level not set.\n"); 03123 wined3d_mutex_unlock(); 03124 return DDERR_NOCOOPERATIVELEVELSET; 03125 } 03126 03127 if(surface_desc == NULL || surface_desc->dwSize != sizeof(DDSURFACEDESC2)) 03128 { 03129 WARN("Application supplied invalid surface descriptor\n"); 03130 wined3d_mutex_unlock(); 03131 return DDERR_INVALIDPARAMS; 03132 } 03133 03134 if(surface_desc->ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER | DDSCAPS_BACKBUFFER)) 03135 { 03136 if (TRACE_ON(ddraw)) 03137 { 03138 TRACE(" (%p) Requesting surface desc :\n", iface); 03139 DDRAW_dump_surface_desc(surface_desc); 03140 } 03141 03142 WARN("Application tried to create an explicit front or back buffer\n"); 03143 wined3d_mutex_unlock(); 03144 return DDERR_INVALIDCAPS; 03145 } 03146 03147 hr = CreateSurface(This, surface_desc, &impl, outer_unknown, 7); 03148 wined3d_mutex_unlock(); 03149 if (FAILED(hr)) 03150 { 03151 *surface = NULL; 03152 return hr; 03153 } 03154 03155 *surface = &impl->IDirectDrawSurface7_iface; 03156 IDirectDraw7_AddRef(iface); 03157 impl->ifaceToRelease = (IUnknown *)iface; 03158 03159 return hr; 03160 } 03161 03162 static HRESULT WINAPI ddraw4_CreateSurface(IDirectDraw4 *iface, 03163 DDSURFACEDESC2 *surface_desc, IDirectDrawSurface4 **surface, IUnknown *outer_unknown) 03164 { 03165 IDirectDrawImpl *This = impl_from_IDirectDraw4(iface); 03166 IDirectDrawSurfaceImpl *impl; 03167 HRESULT hr; 03168 03169 TRACE("iface %p, surface_desc %p, surface %p, outer_unknown %p.\n", 03170 iface, surface_desc, surface, outer_unknown); 03171 03172 wined3d_mutex_lock(); 03173 03174 if (!(This->cooperative_level & (DDSCL_NORMAL | DDSCL_EXCLUSIVE))) 03175 { 03176 WARN("Cooperative level not set.\n"); 03177 wined3d_mutex_unlock(); 03178 return DDERR_NOCOOPERATIVELEVELSET; 03179 } 03180 03181 if(surface_desc == NULL || surface_desc->dwSize != sizeof(DDSURFACEDESC2)) 03182 { 03183 WARN("Application supplied invalid surface descriptor\n"); 03184 wined3d_mutex_unlock(); 03185 return DDERR_INVALIDPARAMS; 03186 } 03187 03188 if(surface_desc->ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER | DDSCAPS_BACKBUFFER)) 03189 { 03190 if (TRACE_ON(ddraw)) 03191 { 03192 TRACE(" (%p) Requesting surface desc :\n", iface); 03193 DDRAW_dump_surface_desc(surface_desc); 03194 } 03195 03196 WARN("Application tried to create an explicit front or back buffer\n"); 03197 wined3d_mutex_unlock(); 03198 return DDERR_INVALIDCAPS; 03199 } 03200 03201 hr = CreateSurface(This, surface_desc, &impl, outer_unknown, 4); 03202 wined3d_mutex_unlock(); 03203 if (FAILED(hr)) 03204 { 03205 *surface = NULL; 03206 return hr; 03207 } 03208 03209 *surface = &impl->IDirectDrawSurface4_iface; 03210 IDirectDraw4_AddRef(iface); 03211 impl->ifaceToRelease = (IUnknown *)iface; 03212 03213 return hr; 03214 } 03215 03216 static HRESULT WINAPI ddraw2_CreateSurface(IDirectDraw2 *iface, 03217 DDSURFACEDESC *surface_desc, IDirectDrawSurface **surface, IUnknown *outer_unknown) 03218 { 03219 IDirectDrawImpl *This = impl_from_IDirectDraw2(iface); 03220 IDirectDrawSurfaceImpl *impl; 03221 HRESULT hr; 03222 DDSURFACEDESC2 surface_desc2; 03223 03224 TRACE("iface %p, surface_desc %p, surface %p, outer_unknown %p.\n", 03225 iface, surface_desc, surface, outer_unknown); 03226 03227 wined3d_mutex_lock(); 03228 03229 if (!(This->cooperative_level & (DDSCL_NORMAL | DDSCL_EXCLUSIVE))) 03230 { 03231 WARN("Cooperative level not set.\n"); 03232 wined3d_mutex_unlock(); 03233 return DDERR_NOCOOPERATIVELEVELSET; 03234 } 03235 03236 if(surface_desc == NULL || surface_desc->dwSize != sizeof(DDSURFACEDESC)) 03237 { 03238 WARN("Application supplied invalid surface descriptor\n"); 03239 wined3d_mutex_unlock(); 03240 return DDERR_INVALIDPARAMS; 03241 } 03242 03243 DDSD_to_DDSD2(surface_desc, &surface_desc2); 03244 if(surface_desc->ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER | DDSCAPS_BACKBUFFER)) 03245 { 03246 if (TRACE_ON(ddraw)) 03247 { 03248 TRACE(" (%p) Requesting surface desc :\n", iface); 03249 DDRAW_dump_surface_desc((LPDDSURFACEDESC2)surface_desc); 03250 } 03251 03252 WARN("Application tried to create an explicit front or back buffer\n"); 03253 wined3d_mutex_unlock(); 03254 return DDERR_INVALIDCAPS; 03255 } 03256 03257 hr = CreateSurface(This, &surface_desc2, &impl, outer_unknown, 2); 03258 wined3d_mutex_unlock(); 03259 if (FAILED(hr)) 03260 { 03261 *surface = NULL; 03262 return hr; 03263 } 03264 03265 *surface = &impl->IDirectDrawSurface_iface; 03266 impl->ifaceToRelease = NULL; 03267 03268 return hr; 03269 } 03270 03271 static HRESULT WINAPI ddraw1_CreateSurface(IDirectDraw *iface, 03272 DDSURFACEDESC *surface_desc, IDirectDrawSurface **surface, IUnknown *outer_unknown) 03273 { 03274 IDirectDrawImpl *This = impl_from_IDirectDraw(iface); 03275 IDirectDrawSurfaceImpl *impl; 03276 HRESULT hr; 03277 DDSURFACEDESC2 surface_desc2; 03278 03279 TRACE("iface %p, surface_desc %p, surface %p, outer_unknown %p.\n", 03280 iface, surface_desc, surface, outer_unknown); 03281 03282 wined3d_mutex_lock(); 03283 03284 if (!(This->cooperative_level & (DDSCL_NORMAL | DDSCL_EXCLUSIVE))) 03285 { 03286 WARN("Cooperative level not set.\n"); 03287 wined3d_mutex_unlock(); 03288 return DDERR_NOCOOPERATIVELEVELSET; 03289 } 03290 03291 if(surface_desc == NULL || surface_desc->dwSize != sizeof(DDSURFACEDESC)) 03292 { 03293 WARN("Application supplied invalid surface descriptor\n"); 03294 wined3d_mutex_unlock(); 03295 return DDERR_INVALIDPARAMS; 03296 } 03297 03298 /* Remove front buffer flag, this causes failure in v7, and its added to normal 03299 * primaries anyway. */ 03300 surface_desc->ddsCaps.dwCaps &= ~DDSCAPS_FRONTBUFFER; 03301 DDSD_to_DDSD2(surface_desc, &surface_desc2); 03302 hr = CreateSurface(This, &surface_desc2, &impl, outer_unknown, 1); 03303 wined3d_mutex_unlock(); 03304 if (FAILED(hr)) 03305 { 03306 *surface = NULL; 03307 return hr; 03308 } 03309 03310 *surface = &impl->IDirectDrawSurface_iface; 03311 impl->ifaceToRelease = NULL; 03312 03313 return hr; 03314 } 03315 03316 #define DDENUMSURFACES_SEARCHTYPE (DDENUMSURFACES_CANBECREATED|DDENUMSURFACES_DOESEXIST) 03317 #define DDENUMSURFACES_MATCHTYPE (DDENUMSURFACES_ALL|DDENUMSURFACES_MATCH|DDENUMSURFACES_NOMATCH) 03318 03319 static BOOL 03320 Main_DirectDraw_DDPIXELFORMAT_Match(const DDPIXELFORMAT *requested, 03321 const DDPIXELFORMAT *provided) 03322 { 03323 /* Some flags must be present in both or neither for a match. */ 03324 static const DWORD must_match = DDPF_PALETTEINDEXED1 | DDPF_PALETTEINDEXED2 03325 | DDPF_PALETTEINDEXED4 | DDPF_PALETTEINDEXED8 | DDPF_FOURCC 03326 | DDPF_ZBUFFER | DDPF_STENCILBUFFER; 03327 03328 if ((requested->dwFlags & provided->dwFlags) != requested->dwFlags) 03329 return FALSE; 03330 03331 if ((requested->dwFlags & must_match) != (provided->dwFlags & must_match)) 03332 return FALSE; 03333 03334 if (requested->dwFlags & DDPF_FOURCC) 03335 if (requested->dwFourCC != provided->dwFourCC) 03336 return FALSE; 03337 03338 if (requested->dwFlags & (DDPF_RGB|DDPF_YUV|DDPF_ZBUFFER|DDPF_ALPHA 03339 |DDPF_LUMINANCE|DDPF_BUMPDUDV)) 03340 if (requested->u1.dwRGBBitCount != provided->u1.dwRGBBitCount) 03341 return FALSE; 03342 03343 if (requested->dwFlags & (DDPF_RGB|DDPF_YUV|DDPF_STENCILBUFFER 03344 |DDPF_LUMINANCE|DDPF_BUMPDUDV)) 03345 if (requested->u2.dwRBitMask != provided->u2.dwRBitMask) 03346 return FALSE; 03347 03348 if (requested->dwFlags & (DDPF_RGB|DDPF_YUV|DDPF_ZBUFFER|DDPF_BUMPDUDV)) 03349 if (requested->u3.dwGBitMask != provided->u3.dwGBitMask) 03350 return FALSE; 03351 03352 /* I could be wrong about the bumpmapping. MSDN docs are vague. */ 03353 if (requested->dwFlags & (DDPF_RGB|DDPF_YUV|DDPF_STENCILBUFFER 03354 |DDPF_BUMPDUDV)) 03355 if (requested->u4.dwBBitMask != provided->u4.dwBBitMask) 03356 return FALSE; 03357 03358 if (requested->dwFlags & (DDPF_ALPHAPIXELS|DDPF_ZPIXELS)) 03359 if (requested->u5.dwRGBAlphaBitMask != provided->u5.dwRGBAlphaBitMask) 03360 return FALSE; 03361 03362 return TRUE; 03363 } 03364 03365 static BOOL ddraw_match_surface_desc(const DDSURFACEDESC2 *requested, const DDSURFACEDESC2 *provided) 03366 { 03367 struct compare_info 03368 { 03369 DWORD flag; 03370 ptrdiff_t offset; 03371 size_t size; 03372 }; 03373 03374 #define CMP(FLAG, FIELD) \ 03375 { DDSD_##FLAG, offsetof(DDSURFACEDESC2, FIELD), \ 03376 sizeof(((DDSURFACEDESC2 *)(NULL))->FIELD) } 03377 03378 static const struct compare_info compare[] = 03379 { 03380 CMP(ALPHABITDEPTH, dwAlphaBitDepth), 03381 CMP(BACKBUFFERCOUNT, u5.dwBackBufferCount), 03382 CMP(CAPS, ddsCaps), 03383 CMP(CKDESTBLT, ddckCKDestBlt), 03384 CMP(CKDESTOVERLAY, u3 /* ddckCKDestOverlay */), 03385 CMP(CKSRCBLT, ddckCKSrcBlt), 03386 CMP(CKSRCOVERLAY, ddckCKSrcOverlay), 03387 CMP(HEIGHT, dwHeight), 03388 CMP(LINEARSIZE, u1 /* dwLinearSize */), 03389 CMP(LPSURFACE, lpSurface), 03390 CMP(MIPMAPCOUNT, u2 /* dwMipMapCount */), 03391 CMP(PITCH, u1 /* lPitch */), 03392 /* PIXELFORMAT: manual */ 03393 CMP(REFRESHRATE, u2 /* dwRefreshRate */), 03394 CMP(TEXTURESTAGE, dwTextureStage), 03395 CMP(WIDTH, dwWidth), 03396 /* ZBUFFERBITDEPTH: "obsolete" */ 03397 }; 03398 03399 #undef CMP 03400 03401 unsigned int i; 03402 03403 if ((requested->dwFlags & provided->dwFlags) != requested->dwFlags) 03404 return FALSE; 03405 03406 for (i=0; i < sizeof(compare)/sizeof(compare[0]); i++) 03407 { 03408 if (requested->dwFlags & compare[i].flag 03409 && memcmp((const char *)provided + compare[i].offset, 03410 (const char *)requested + compare[i].offset, 03411 compare[i].size) != 0) 03412 return FALSE; 03413 } 03414 03415 if (requested->dwFlags & DDSD_PIXELFORMAT) 03416 { 03417 if (!Main_DirectDraw_DDPIXELFORMAT_Match(&requested->u4.ddpfPixelFormat, 03418 &provided->u4.ddpfPixelFormat)) 03419 return FALSE; 03420 } 03421 03422 return TRUE; 03423 } 03424 03425 #undef DDENUMSURFACES_SEARCHTYPE 03426 #undef DDENUMSURFACES_MATCHTYPE 03427 03428 struct surfacescallback2_context 03429 { 03430 LPDDENUMSURFACESCALLBACK2 func; 03431 void *context; 03432 }; 03433 03434 struct surfacescallback_context 03435 { 03436 LPDDENUMSURFACESCALLBACK func; 03437 void *context; 03438 }; 03439 03440 static HRESULT CALLBACK EnumSurfacesCallback2Thunk(IDirectDrawSurface7 *surface, 03441 DDSURFACEDESC2 *surface_desc, void *context) 03442 { 03443 IDirectDrawSurfaceImpl *surface_impl = impl_from_IDirectDrawSurface7(surface); 03444 struct surfacescallback2_context *cbcontext = context; 03445 03446 IDirectDrawSurface4_AddRef(&surface_impl->IDirectDrawSurface4_iface); 03447 IDirectDrawSurface7_Release(surface); 03448 03449 return cbcontext->func(&surface_impl->IDirectDrawSurface4_iface, 03450 surface_desc, cbcontext->context); 03451 } 03452 03453 static HRESULT CALLBACK EnumSurfacesCallbackThunk(IDirectDrawSurface7 *surface, 03454 DDSURFACEDESC2 *surface_desc, void *context) 03455 { 03456 IDirectDrawSurfaceImpl *surface_impl = impl_from_IDirectDrawSurface7(surface); 03457 struct surfacescallback_context *cbcontext = context; 03458 03459 IDirectDrawSurface_AddRef(&surface_impl->IDirectDrawSurface_iface); 03460 IDirectDrawSurface7_Release(surface); 03461 03462 return cbcontext->func(&surface_impl->IDirectDrawSurface_iface, 03463 (DDSURFACEDESC *)surface_desc, cbcontext->context); 03464 } 03465 03466 /***************************************************************************** 03467 * IDirectDraw7::EnumSurfaces 03468 * 03469 * Loops through all surfaces attached to this device and calls the 03470 * application callback. This can't be relayed to WineD3DDevice, 03471 * because some WineD3DSurfaces' parents are IParent objects 03472 * 03473 * Params: 03474 * Flags: Some filtering flags. See IDirectDrawImpl_EnumSurfacesCallback 03475 * DDSD: Description to filter for 03476 * Context: Application-provided pointer, it's passed unmodified to the 03477 * Callback function 03478 * Callback: Address to call for each surface 03479 * 03480 * Returns: 03481 * DDERR_INVALIDPARAMS if the callback is NULL 03482 * DD_OK on success 03483 * 03484 *****************************************************************************/ 03485 static HRESULT WINAPI ddraw7_EnumSurfaces(IDirectDraw7 *iface, DWORD Flags, 03486 DDSURFACEDESC2 *DDSD, void *Context, LPDDENUMSURFACESCALLBACK7 Callback) 03487 { 03488 /* The surface enumeration is handled by WineDDraw, 03489 * because it keeps track of all surfaces attached to 03490 * it. The filtering is done by our callback function, 03491 * because WineDDraw doesn't handle ddraw-like surface 03492 * caps structures 03493 */ 03494 IDirectDrawImpl *This = impl_from_IDirectDraw7(iface); 03495 IDirectDrawSurfaceImpl *surf; 03496 BOOL all, nomatch; 03497 DDSURFACEDESC2 desc; 03498 struct list *entry, *entry2; 03499 03500 TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n", 03501 iface, Flags, DDSD, Context, Callback); 03502 03503 all = Flags & DDENUMSURFACES_ALL; 03504 nomatch = Flags & DDENUMSURFACES_NOMATCH; 03505 03506 if (!Callback) 03507 return DDERR_INVALIDPARAMS; 03508 03509 wined3d_mutex_lock(); 03510 03511 /* Use the _SAFE enumeration, the app may destroy enumerated surfaces */ 03512 LIST_FOR_EACH_SAFE(entry, entry2, &This->surface_list) 03513 { 03514 surf = LIST_ENTRY(entry, IDirectDrawSurfaceImpl, surface_list_entry); 03515 03516 if (!surf->iface_count) 03517 { 03518 WARN("Not enumerating surface %p because it doesn't have any references.\n", surf); 03519 continue; 03520 } 03521 03522 if (all || (nomatch != ddraw_match_surface_desc(DDSD, &surf->surface_desc))) 03523 { 03524 TRACE("Enumerating surface %p.\n", surf); 03525 desc = surf->surface_desc; 03526 IDirectDrawSurface7_AddRef(&surf->IDirectDrawSurface7_iface); 03527 if (Callback(&surf->IDirectDrawSurface7_iface, &desc, Context) != DDENUMRET_OK) 03528 { 03529 wined3d_mutex_unlock(); 03530 return DD_OK; 03531 } 03532 } 03533 } 03534 03535 wined3d_mutex_unlock(); 03536 03537 return DD_OK; 03538 } 03539 03540 static HRESULT WINAPI ddraw4_EnumSurfaces(IDirectDraw4 *iface, DWORD flags, 03541 DDSURFACEDESC2 *surface_desc, void *context, LPDDENUMSURFACESCALLBACK2 callback) 03542 { 03543 IDirectDrawImpl *This = impl_from_IDirectDraw4(iface); 03544 struct surfacescallback2_context cbcontext; 03545 03546 TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n", 03547 iface, flags, surface_desc, context, callback); 03548 03549 cbcontext.func = callback; 03550 cbcontext.context = context; 03551 03552 return ddraw7_EnumSurfaces(&This->IDirectDraw7_iface, flags, surface_desc, 03553 &cbcontext, EnumSurfacesCallback2Thunk); 03554 } 03555 03556 static HRESULT WINAPI ddraw2_EnumSurfaces(IDirectDraw2 *iface, DWORD flags, 03557 DDSURFACEDESC *surface_desc, void *context, LPDDENUMSURFACESCALLBACK callback) 03558 { 03559 IDirectDrawImpl *This = impl_from_IDirectDraw2(iface); 03560 struct surfacescallback_context cbcontext; 03561 DDSURFACEDESC2 surface_desc2; 03562 03563 TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n", 03564 iface, flags, surface_desc, context, callback); 03565 03566 cbcontext.func = callback; 03567 cbcontext.context = context; 03568 03569 if (surface_desc) DDSD_to_DDSD2(surface_desc, &surface_desc2); 03570 return ddraw7_EnumSurfaces(&This->IDirectDraw7_iface, flags, 03571 surface_desc ? &surface_desc2 : NULL, &cbcontext, EnumSurfacesCallbackThunk); 03572 } 03573 03574 static HRESULT WINAPI ddraw1_EnumSurfaces(IDirectDraw *iface, DWORD flags, 03575 DDSURFACEDESC *surface_desc, void *context, LPDDENUMSURFACESCALLBACK callback) 03576 { 03577 IDirectDrawImpl *This = impl_from_IDirectDraw(iface); 03578 struct surfacescallback_context cbcontext; 03579 DDSURFACEDESC2 surface_desc2; 03580 03581 TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n", 03582 iface, flags, surface_desc, context, callback); 03583 03584 cbcontext.func = callback; 03585 cbcontext.context = context; 03586 03587 if (surface_desc) DDSD_to_DDSD2(surface_desc, &surface_desc2); 03588 return ddraw7_EnumSurfaces(&This->IDirectDraw7_iface, flags, 03589 surface_desc ? &surface_desc2 : NULL, &cbcontext, EnumSurfacesCallbackThunk); 03590 } 03591 03592 /***************************************************************************** 03593 * DirectDrawCreateClipper (DDRAW.@) 03594 * 03595 * Creates a new IDirectDrawClipper object. 03596 * 03597 * Params: 03598 * Clipper: Address to write the interface pointer to 03599 * UnkOuter: For aggregation support, which ddraw doesn't have. Has to be 03600 * NULL 03601 * 03602 * Returns: 03603 * CLASS_E_NOAGGREGATION if UnkOuter != NULL 03604 * E_OUTOFMEMORY if allocating the object failed 03605 * 03606 *****************************************************************************/ 03607 HRESULT WINAPI DirectDrawCreateClipper(DWORD flags, IDirectDrawClipper **clipper, IUnknown *outer_unknown) 03608 { 03609 struct ddraw_clipper *object; 03610 HRESULT hr; 03611 03612 TRACE("flags %#x, clipper %p, outer_unknown %p.\n", 03613 flags, clipper, outer_unknown); 03614 03615 if (outer_unknown) 03616 return CLASS_E_NOAGGREGATION; 03617 03618 wined3d_mutex_lock(); 03619 03620 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object)); 03621 if (!object) 03622 { 03623 wined3d_mutex_unlock(); 03624 return E_OUTOFMEMORY; 03625 } 03626 03627 hr = ddraw_clipper_init(object); 03628 if (FAILED(hr)) 03629 { 03630 WARN("Failed to initialize clipper, hr %#x.\n", hr); 03631 HeapFree(GetProcessHeap(), 0, object); 03632 wined3d_mutex_unlock(); 03633 return hr; 03634 } 03635 03636 TRACE("Created clipper %p.\n", object); 03637 *clipper = &object->IDirectDrawClipper_iface; 03638 wined3d_mutex_unlock(); 03639 03640 return DD_OK; 03641 } 03642 03643 /***************************************************************************** 03644 * IDirectDraw7::CreateClipper 03645 * 03646 * Creates a DDraw clipper. See DirectDrawCreateClipper for details 03647 * 03648 *****************************************************************************/ 03649 static HRESULT WINAPI ddraw7_CreateClipper(IDirectDraw7 *iface, DWORD Flags, 03650 IDirectDrawClipper **Clipper, IUnknown *UnkOuter) 03651 { 03652 TRACE("iface %p, flags %#x, clipper %p, outer_unknown %p.\n", 03653 iface, Flags, Clipper, UnkOuter); 03654 03655 return DirectDrawCreateClipper(Flags, Clipper, UnkOuter); 03656 } 03657 03658 static HRESULT WINAPI ddraw4_CreateClipper(IDirectDraw4 *iface, DWORD flags, 03659 IDirectDrawClipper **clipper, IUnknown *outer_unknown) 03660 { 03661 IDirectDrawImpl *This = impl_from_IDirectDraw4(iface); 03662 03663 TRACE("iface %p, flags %#x, clipper %p, outer_unknown %p.\n", 03664 iface, flags, clipper, outer_unknown); 03665 03666 return ddraw7_CreateClipper(&This->IDirectDraw7_iface, flags, clipper, outer_unknown); 03667 } 03668 03669 static HRESULT WINAPI ddraw2_CreateClipper(IDirectDraw2 *iface, 03670 DWORD flags, IDirectDrawClipper **clipper, IUnknown *outer_unknown) 03671 { 03672 IDirectDrawImpl *This = impl_from_IDirectDraw2(iface); 03673 03674 TRACE("iface %p, flags %#x, clipper %p, outer_unknown %p.\n", 03675 iface, flags, clipper, outer_unknown); 03676 03677 return ddraw7_CreateClipper(&This->IDirectDraw7_iface, flags, clipper, outer_unknown); 03678 } 03679 03680 static HRESULT WINAPI ddraw1_CreateClipper(IDirectDraw *iface, 03681 DWORD flags, IDirectDrawClipper **clipper, IUnknown *outer_unknown) 03682 { 03683 IDirectDrawImpl *This = impl_from_IDirectDraw(iface); 03684 03685 TRACE("iface %p, flags %#x, clipper %p, outer_unknown %p.\n", 03686 iface, flags, clipper, outer_unknown); 03687 03688 return ddraw7_CreateClipper(&This->IDirectDraw7_iface, flags, clipper, outer_unknown); 03689 } 03690 03691 /***************************************************************************** 03692 * IDirectDraw7::CreatePalette 03693 * 03694 * Creates a new IDirectDrawPalette object 03695 * 03696 * Params: 03697 * Flags: The flags for the new clipper 03698 * ColorTable: Color table to assign to the new clipper 03699 * Palette: Address to write the interface pointer to 03700 * UnkOuter: For aggregation support, which ddraw doesn't have. Has to be 03701 * NULL 03702 * 03703 * Returns: 03704 * CLASS_E_NOAGGREGATION if UnkOuter != NULL 03705 * E_OUTOFMEMORY if allocating the object failed 03706 * 03707 *****************************************************************************/ 03708 static HRESULT WINAPI ddraw7_CreatePalette(IDirectDraw7 *iface, DWORD Flags, 03709 PALETTEENTRY *ColorTable, IDirectDrawPalette **Palette, IUnknown *pUnkOuter) 03710 { 03711 IDirectDrawImpl *This = impl_from_IDirectDraw7(iface); 03712 IDirectDrawPaletteImpl *object; 03713 HRESULT hr; 03714 03715 TRACE("iface %p, flags %#x, color_table %p, palette %p, outer_unknown %p.\n", 03716 iface, Flags, ColorTable, Palette, pUnkOuter); 03717 03718 if (pUnkOuter) 03719 return CLASS_E_NOAGGREGATION; 03720 03721 wined3d_mutex_lock(); 03722 03723 /* The refcount test shows that a cooplevel is required for this */ 03724 if(!This->cooperative_level) 03725 { 03726 WARN("No cooperative level set, returning DDERR_NOCOOPERATIVELEVELSET\n"); 03727 wined3d_mutex_unlock(); 03728 return DDERR_NOCOOPERATIVELEVELSET; 03729 } 03730 03731 object = HeapAlloc(GetProcessHeap(), 0, sizeof(IDirectDrawPaletteImpl)); 03732 if(!object) 03733 { 03734 ERR("Out of memory when allocating memory for a palette implementation\n"); 03735 wined3d_mutex_unlock(); 03736 return E_OUTOFMEMORY; 03737 } 03738 03739 hr = ddraw_palette_init(object, This, Flags, ColorTable); 03740 if (FAILED(hr)) 03741 { 03742 WARN("Failed to initialize palette, hr %#x.\n", hr); 03743 HeapFree(GetProcessHeap(), 0, object); 03744 wined3d_mutex_unlock(); 03745 return hr; 03746 } 03747 03748 TRACE("Created palette %p.\n", object); 03749 *Palette = &object->IDirectDrawPalette_iface; 03750 wined3d_mutex_unlock(); 03751 03752 return DD_OK; 03753 } 03754 03755 static HRESULT WINAPI ddraw4_CreatePalette(IDirectDraw4 *iface, DWORD flags, PALETTEENTRY *entries, 03756 IDirectDrawPalette **palette, IUnknown *outer_unknown) 03757 { 03758 IDirectDrawImpl *This = impl_from_IDirectDraw4(iface); 03759 HRESULT hr; 03760 03761 TRACE("iface %p, flags %#x, entries %p, palette %p, outer_unknown %p.\n", 03762 iface, flags, entries, palette, outer_unknown); 03763 03764 hr = ddraw7_CreatePalette(&This->IDirectDraw7_iface, flags, entries, palette, outer_unknown); 03765 if (SUCCEEDED(hr) && *palette) 03766 { 03767 IDirectDrawPaletteImpl *impl = impl_from_IDirectDrawPalette(*palette); 03768 IDirectDraw7_Release(&This->IDirectDraw7_iface); 03769 IDirectDraw4_AddRef(iface); 03770 impl->ifaceToRelease = (IUnknown *)iface; 03771 } 03772 return hr; 03773 } 03774 03775 static HRESULT WINAPI ddraw2_CreatePalette(IDirectDraw2 *iface, DWORD flags, 03776 PALETTEENTRY *entries, IDirectDrawPalette **palette, IUnknown *outer_unknown) 03777 { 03778 IDirectDrawImpl *This = impl_from_IDirectDraw2(iface); 03779 HRESULT hr; 03780 03781 TRACE("iface %p, flags %#x, entries %p, palette %p, outer_unknown %p.\n", 03782 iface, flags, entries, palette, outer_unknown); 03783 03784 hr = ddraw7_CreatePalette(&This->IDirectDraw7_iface, flags, entries, palette, outer_unknown); 03785 if (SUCCEEDED(hr) && *palette) 03786 { 03787 IDirectDrawPaletteImpl *impl = impl_from_IDirectDrawPalette(*palette); 03788 IDirectDraw7_Release(&This->IDirectDraw7_iface); 03789 impl->ifaceToRelease = NULL; 03790 } 03791 03792 return hr; 03793 } 03794 03795 static HRESULT WINAPI ddraw1_CreatePalette(IDirectDraw *iface, DWORD flags, 03796 PALETTEENTRY *entries, IDirectDrawPalette **palette, IUnknown *outer_unknown) 03797 { 03798 IDirectDrawImpl *This = impl_from_IDirectDraw(iface); 03799 HRESULT hr; 03800 03801 TRACE("iface %p, flags %#x, entries %p, palette %p, outer_unknown %p.\n", 03802 iface, flags, entries, palette, outer_unknown); 03803 03804 hr = ddraw7_CreatePalette(&This->IDirectDraw7_iface, flags, entries, palette, outer_unknown); 03805 if (SUCCEEDED(hr) && *palette) 03806 { 03807 IDirectDrawPaletteImpl *impl = impl_from_IDirectDrawPalette(*palette); 03808 IDirectDraw7_Release(&This->IDirectDraw7_iface); 03809 impl->ifaceToRelease = NULL; 03810 } 03811 03812 return hr; 03813 } 03814 03815 /***************************************************************************** 03816 * IDirectDraw7::DuplicateSurface 03817 * 03818 * Duplicates a surface. The surface memory points to the same memory as 03819 * the original surface, and it's released when the last surface referencing 03820 * it is released. I guess that's beyond Wine's surface management right now 03821 * (Idea: create a new DDraw surface with the same WineD3DSurface. I need a 03822 * test application to implement this) 03823 * 03824 * Params: 03825 * Src: Address of the source surface 03826 * Dest: Address to write the new surface pointer to 03827 * 03828 * Returns: 03829 * See IDirectDraw7::CreateSurface 03830 * 03831 *****************************************************************************/ 03832 static HRESULT WINAPI ddraw7_DuplicateSurface(IDirectDraw7 *iface, 03833 IDirectDrawSurface7 *Src, IDirectDrawSurface7 **Dest) 03834 { 03835 IDirectDrawSurfaceImpl *Surf = unsafe_impl_from_IDirectDrawSurface7(Src); 03836 03837 FIXME("iface %p, src %p, dst %p partial stub!\n", iface, Src, Dest); 03838 03839 /* For now, simply create a new, independent surface */ 03840 return IDirectDraw7_CreateSurface(iface, 03841 &Surf->surface_desc, 03842 Dest, 03843 NULL); 03844 } 03845 03846 static HRESULT WINAPI ddraw4_DuplicateSurface(IDirectDraw4 *iface, IDirectDrawSurface4 *src, 03847 IDirectDrawSurface4 **dst) 03848 { 03849 IDirectDrawImpl *This = impl_from_IDirectDraw4(iface); 03850 IDirectDrawSurfaceImpl *src_impl = unsafe_impl_from_IDirectDrawSurface4(src); 03851 IDirectDrawSurface7 *dst7; 03852 IDirectDrawSurfaceImpl *dst_impl; 03853 HRESULT hr; 03854 03855 TRACE("iface %p, src %p, dst %p.\n", iface, src, dst); 03856 hr = ddraw7_DuplicateSurface(&This->IDirectDraw7_iface, 03857 src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, &dst7); 03858 if (FAILED(hr)) 03859 { 03860 *dst = NULL; 03861 return hr; 03862 } 03863 dst_impl = impl_from_IDirectDrawSurface7(dst7); 03864 *dst = &dst_impl->IDirectDrawSurface4_iface; 03865 IDirectDrawSurface4_AddRef(*dst); 03866 IDirectDrawSurface7_Release(dst7); 03867 03868 return hr; 03869 } 03870 03871 static HRESULT WINAPI ddraw2_DuplicateSurface(IDirectDraw2 *iface, 03872 IDirectDrawSurface *src, IDirectDrawSurface **dst) 03873 { 03874 IDirectDrawImpl *This = impl_from_IDirectDraw2(iface); 03875 IDirectDrawSurfaceImpl *src_impl = unsafe_impl_from_IDirectDrawSurface(src); 03876 IDirectDrawSurface7 *dst7; 03877 IDirectDrawSurfaceImpl *dst_impl; 03878 HRESULT hr; 03879 03880 TRACE("iface %p, src %p, dst %p.\n", iface, src, dst); 03881 hr = ddraw7_DuplicateSurface(&This->IDirectDraw7_iface, 03882 src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, &dst7); 03883 if (FAILED(hr)) 03884 return hr; 03885 dst_impl = impl_from_IDirectDrawSurface7(dst7); 03886 *dst = &dst_impl->IDirectDrawSurface_iface; 03887 IDirectDrawSurface_AddRef(*dst); 03888 IDirectDrawSurface7_Release(dst7); 03889 03890 return hr; 03891 } 03892 03893 static HRESULT WINAPI ddraw1_DuplicateSurface(IDirectDraw *iface, IDirectDrawSurface *src, 03894 IDirectDrawSurface **dst) 03895 { 03896 IDirectDrawImpl *This = impl_from_IDirectDraw(iface); 03897 IDirectDrawSurfaceImpl *src_impl = unsafe_impl_from_IDirectDrawSurface(src); 03898 IDirectDrawSurface7 *dst7; 03899 IDirectDrawSurfaceImpl *dst_impl; 03900 HRESULT hr; 03901 03902 TRACE("iface %p, src %p, dst %p.\n", iface, src, dst); 03903 hr = ddraw7_DuplicateSurface(&This->IDirectDraw7_iface, 03904 src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, &dst7); 03905 if (FAILED(hr)) 03906 return hr; 03907 dst_impl = impl_from_IDirectDrawSurface7(dst7); 03908 *dst = &dst_impl->IDirectDrawSurface_iface; 03909 IDirectDrawSurface_AddRef(*dst); 03910 IDirectDrawSurface7_Release(dst7); 03911 03912 return hr; 03913 } 03914 03915 /***************************************************************************** 03916 * IDirect3D7::EnumDevices 03917 * 03918 * The EnumDevices method for IDirect3D7. It enumerates all supported 03919 * D3D7 devices. Currently the T&L, HAL and RGB devices are enumerated. 03920 * 03921 * Params: 03922 * callback: Function to call for each enumerated device 03923 * context: Pointer to pass back to the app 03924 * 03925 * Returns: 03926 * D3D_OK, or the return value of the GetCaps call 03927 * 03928 *****************************************************************************/ 03929 static HRESULT WINAPI d3d7_EnumDevices(IDirect3D7 *iface, LPD3DENUMDEVICESCALLBACK7 callback, void *context) 03930 { 03931 IDirectDrawImpl *This = impl_from_IDirect3D7(iface); 03932 D3DDEVICEDESC7 device_desc7; 03933 D3DDEVICEDESC device_desc1; 03934 HRESULT hr; 03935 size_t i; 03936 03937 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context); 03938 03939 if (!callback) 03940 return DDERR_INVALIDPARAMS; 03941 03942 wined3d_mutex_lock(); 03943 03944 hr = IDirect3DImpl_GetCaps(This->wined3d, &device_desc1, &device_desc7); 03945 if (hr != D3D_OK) 03946 { 03947 wined3d_mutex_unlock(); 03948 return hr; 03949 } 03950 03951 for (i = 0; i < sizeof(device_list7)/sizeof(device_list7[0]); i++) 03952 { 03953 HRESULT ret; 03954 03955 device_desc7.deviceGUID = *device_list7[i].device_guid; 03956 ret = callback(device_list7[i].interface_name, device_list7[i].device_name, &device_desc7, context); 03957 if (ret != DDENUMRET_OK) 03958 { 03959 TRACE("Application cancelled the enumeration.\n"); 03960 wined3d_mutex_unlock(); 03961 return D3D_OK; 03962 } 03963 } 03964 03965 TRACE("End of enumeration.\n"); 03966 03967 wined3d_mutex_unlock(); 03968 03969 return D3D_OK; 03970 } 03971 03972 /***************************************************************************** 03973 * IDirect3D3::EnumDevices 03974 * 03975 * Enumerates all supported Direct3DDevice interfaces. This is the 03976 * implementation for Direct3D 1 to Direc3D 3, Version 7 has its own. 03977 * 03978 * Version 1, 2 and 3 03979 * 03980 * Params: 03981 * callback: Application-provided routine to call for each enumerated device 03982 * Context: Pointer to pass to the callback 03983 * 03984 * Returns: 03985 * D3D_OK on success, 03986 * The result of IDirect3DImpl_GetCaps if it failed 03987 * 03988 *****************************************************************************/ 03989 static HRESULT WINAPI d3d3_EnumDevices(IDirect3D3 *iface, LPD3DENUMDEVICESCALLBACK callback, void *context) 03990 { 03991 static CHAR wined3d_description[] = "Wine D3DDevice using WineD3D and OpenGL"; 03992 03993 IDirectDrawImpl *This = impl_from_IDirect3D3(iface); 03994 D3DDEVICEDESC device_desc1, hal_desc, hel_desc; 03995 D3DDEVICEDESC7 device_desc7; 03996 HRESULT hr; 03997 03998 /* Some games (Motoracer 2 demo) have the bad idea to modify the device 03999 * name string. Let's put the string in a sufficiently sized array in 04000 * writable memory. */ 04001 char device_name[50]; 04002 strcpy(device_name,"Direct3D HEL"); 04003 04004 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context); 04005 04006 if (!callback) 04007 return DDERR_INVALIDPARAMS; 04008 04009 wined3d_mutex_lock(); 04010 04011 hr = IDirect3DImpl_GetCaps(This->wined3d, &device_desc1, &device_desc7); 04012 if (hr != D3D_OK) 04013 { 04014 wined3d_mutex_unlock(); 04015 return hr; 04016 } 04017 04018 /* Do I have to enumerate the reference id? Note from old d3d7: 04019 * "It seems that enumerating the reference IID on Direct3D 1 games 04020 * (AvP / Motoracer2) breaks them". So do not enumerate this iid in V1 04021 * 04022 * There's a registry key HKLM\Software\Microsoft\Direct3D\Drivers, 04023 * EnumReference which enables / disables enumerating the reference 04024 * rasterizer. It's a DWORD, 0 means disabled, 2 means enabled. The 04025 * enablerefrast.reg and disablerefrast.reg files in the DirectX 7.0 sdk 04026 * demo directory suggest this. 04027 * 04028 * Some games(GTA 2) seem to use the second enumerated device, so I have 04029 * to enumerate at least 2 devices. So enumerate the reference device to 04030 * have 2 devices. 04031 * 04032 * Other games (Rollcage) tell emulation and hal device apart by certain 04033 * flags. Rollcage expects D3DPTEXTURECAPS_POW2 to be set (yeah, it is a 04034 * limitation flag), and it refuses all devices that have the perspective 04035 * flag set. This way it refuses the emulation device, and HAL devices 04036 * never have POW2 unset in d3d7 on windows. */ 04037 if (This->d3dversion != 1) 04038 { 04039 static CHAR reference_description[] = "RGB Direct3D emulation"; 04040 04041 TRACE("Enumerating WineD3D D3DDevice interface.\n"); 04042 hal_desc = device_desc1; 04043 hel_desc = device_desc1; 04044 /* The rgb device has the pow2 flag set in the hel caps, but not in the hal caps. */ 04045 hal_desc.dpcLineCaps.dwTextureCaps &= ~(D3DPTEXTURECAPS_POW2 04046 | D3DPTEXTURECAPS_NONPOW2CONDITIONAL | D3DPTEXTURECAPS_PERSPECTIVE); 04047 hal_desc.dpcTriCaps.dwTextureCaps &= ~(D3DPTEXTURECAPS_POW2 04048 | D3DPTEXTURECAPS_NONPOW2CONDITIONAL | D3DPTEXTURECAPS_PERSPECTIVE); 04049 /* RGB, RAMP and MMX devices have a HAL dcmColorModel of 0 */ 04050 hal_desc.dcmColorModel = 0; 04051 04052 hr = callback((GUID *)&IID_IDirect3DRGBDevice, reference_description, 04053 device_name, &hal_desc, &hel_desc, context); 04054 if (hr != D3DENUMRET_OK) 04055 { 04056 TRACE("Application cancelled the enumeration.\n"); 04057 wined3d_mutex_unlock(); 04058 return D3D_OK; 04059 } 04060 } 04061 04062 strcpy(device_name,"Direct3D HAL"); 04063 04064 TRACE("Enumerating HAL Direct3D device.\n"); 04065 hal_desc = device_desc1; 04066 hel_desc = device_desc1; 04067 04068 /* The hal device does not have the pow2 flag set in hel, but in hal. */ 04069 hel_desc.dpcLineCaps.dwTextureCaps &= ~(D3DPTEXTURECAPS_POW2 04070 | D3DPTEXTURECAPS_NONPOW2CONDITIONAL | D3DPTEXTURECAPS_PERSPECTIVE); 04071 hel_desc.dpcTriCaps.dwTextureCaps &= ~(D3DPTEXTURECAPS_POW2 04072 | D3DPTEXTURECAPS_NONPOW2CONDITIONAL | D3DPTEXTURECAPS_PERSPECTIVE); 04073 /* HAL devices have a HEL dcmColorModel of 0 */ 04074 hel_desc.dcmColorModel = 0; 04075 04076 hr = callback((GUID *)&IID_IDirect3DHALDevice, wined3d_description, 04077 device_name, &hal_desc, &hel_desc, context); 04078 if (hr != D3DENUMRET_OK) 04079 { 04080 TRACE("Application cancelled the enumeration.\n"); 04081 wined3d_mutex_unlock(); 04082 return D3D_OK; 04083 } 04084 04085 TRACE("End of enumeration.\n"); 04086 04087 wined3d_mutex_unlock(); 04088 04089 return D3D_OK; 04090 } 04091 04092 static HRESULT WINAPI d3d2_EnumDevices(IDirect3D2 *iface, LPD3DENUMDEVICESCALLBACK callback, void *context) 04093 { 04094 IDirectDrawImpl *This = impl_from_IDirect3D2(iface); 04095 04096 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context); 04097 04098 return d3d3_EnumDevices(&This->IDirect3D3_iface, callback, context); 04099 } 04100 04101 static HRESULT WINAPI d3d1_EnumDevices(IDirect3D *iface, LPD3DENUMDEVICESCALLBACK callback, void *context) 04102 { 04103 IDirectDrawImpl *This = impl_from_IDirect3D(iface); 04104 04105 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context); 04106 04107 return d3d3_EnumDevices(&This->IDirect3D3_iface, callback, context); 04108 } 04109 04110 /***************************************************************************** 04111 * IDirect3D3::CreateLight 04112 * 04113 * Creates an IDirect3DLight interface. This interface is used in 04114 * Direct3D3 or earlier for lighting. In Direct3D7 it has been replaced 04115 * by the DIRECT3DLIGHT7 structure. Wine's Direct3DLight implementation 04116 * uses the IDirect3DDevice7 interface with D3D7 lights. 04117 * 04118 * Version 1, 2 and 3 04119 * 04120 * Params: 04121 * light: Address to store the new interface pointer 04122 * outer_unknown: Basically for aggregation, but ddraw doesn't support it. 04123 * Must be NULL 04124 * 04125 * Returns: 04126 * D3D_OK on success 04127 * DDERR_OUTOFMEMORY if memory allocation failed 04128 * CLASS_E_NOAGGREGATION if outer_unknown != NULL 04129 * 04130 *****************************************************************************/ 04131 static HRESULT WINAPI d3d3_CreateLight(IDirect3D3 *iface, IDirect3DLight **light, 04132 IUnknown *outer_unknown) 04133 { 04134 IDirectDrawImpl *This = impl_from_IDirect3D3(iface); 04135 IDirect3DLightImpl *object; 04136 04137 TRACE("iface %p, light %p, outer_unknown %p.\n", iface, light, outer_unknown); 04138 04139 if (outer_unknown) return CLASS_E_NOAGGREGATION; 04140 04141 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object)); 04142 if (!object) 04143 { 04144 ERR("Failed to allocate light memory.\n"); 04145 return DDERR_OUTOFMEMORY; 04146 } 04147 04148 d3d_light_init(object, This); 04149 04150 TRACE("Created light %p.\n", object); 04151 *light = &object->IDirect3DLight_iface; 04152 04153 return D3D_OK; 04154 } 04155 04156 static HRESULT WINAPI d3d2_CreateLight(IDirect3D2 *iface, IDirect3DLight **light, IUnknown *outer_unknown) 04157 { 04158 IDirectDrawImpl *This = impl_from_IDirect3D2(iface); 04159 04160 TRACE("iface %p, light %p, outer_unknown %p.\n", iface, light, outer_unknown); 04161 04162 return d3d3_CreateLight(&This->IDirect3D3_iface, light, outer_unknown); 04163 } 04164 04165 static HRESULT WINAPI d3d1_CreateLight(IDirect3D *iface, IDirect3DLight **light, IUnknown *outer_unknown) 04166 { 04167 IDirectDrawImpl *This = impl_from_IDirect3D(iface); 04168 04169 TRACE("iface %p, light %p, outer_unknown %p.\n", iface, light, outer_unknown); 04170 04171 return d3d3_CreateLight(&This->IDirect3D3_iface, light, outer_unknown); 04172 } 04173 04174 /***************************************************************************** 04175 * IDirect3D3::CreateMaterial 04176 * 04177 * Creates an IDirect3DMaterial interface. This interface is used by Direct3D3 04178 * and older versions. The IDirect3DMaterial implementation wraps its 04179 * functionality to IDirect3DDevice7::SetMaterial and friends. 04180 * 04181 * Version 1, 2 and 3 04182 * 04183 * Params: 04184 * material: Address to store the new interface's pointer to 04185 * outer_unknown: Basically for aggregation, but ddraw doesn't support it. 04186 * Must be NULL 04187 * 04188 * Returns: 04189 * D3D_OK on success 04190 * DDERR_OUTOFMEMORY if memory allocation failed 04191 * CLASS_E_NOAGGREGATION if outer_unknown != NULL 04192 * 04193 *****************************************************************************/ 04194 static HRESULT WINAPI d3d3_CreateMaterial(IDirect3D3 *iface, IDirect3DMaterial3 **material, 04195 IUnknown *outer_unknown) 04196 { 04197 IDirectDrawImpl *This = impl_from_IDirect3D3(iface); 04198 IDirect3DMaterialImpl *object; 04199 04200 TRACE("iface %p, material %p, outer_unknown %p.\n", iface, material, outer_unknown); 04201 04202 if (outer_unknown) return CLASS_E_NOAGGREGATION; 04203 04204 object = d3d_material_create(This); 04205 if (!object) 04206 { 04207 ERR("Failed to allocate material memory.\n"); 04208 return DDERR_OUTOFMEMORY; 04209 } 04210 04211 TRACE("Created material %p.\n", object); 04212 *material = &object->IDirect3DMaterial3_iface; 04213 04214 return D3D_OK; 04215 } 04216 04217 static HRESULT WINAPI d3d2_CreateMaterial(IDirect3D2 *iface, IDirect3DMaterial2 **material, 04218 IUnknown *outer_unknown) 04219 { 04220 IDirectDrawImpl *This = impl_from_IDirect3D2(iface); 04221 IDirect3DMaterialImpl *object; 04222 04223 TRACE("iface %p, material %p, outer_unknown %p.\n", iface, material, outer_unknown); 04224 04225 object = d3d_material_create(This); 04226 if (!object) 04227 { 04228 ERR("Failed to allocate material memory.\n"); 04229 return DDERR_OUTOFMEMORY; 04230 } 04231 04232 TRACE("Created material %p.\n", object); 04233 *material = &object->IDirect3DMaterial2_iface; 04234 04235 return D3D_OK; 04236 } 04237 04238 static HRESULT WINAPI d3d1_CreateMaterial(IDirect3D *iface, IDirect3DMaterial **material, 04239 IUnknown *outer_unknown) 04240 { 04241 IDirectDrawImpl *This = impl_from_IDirect3D(iface); 04242 IDirect3DMaterialImpl *object; 04243 04244 TRACE("iface %p, material %p, outer_unknown %p.\n", iface, material, outer_unknown); 04245 04246 object = d3d_material_create(This); 04247 if (!object) 04248 { 04249 ERR("Failed to allocate material memory.\n"); 04250 return DDERR_OUTOFMEMORY; 04251 } 04252 04253 TRACE("Created material %p.\n", object); 04254 *material = &object->IDirect3DMaterial_iface; 04255 04256 return D3D_OK; 04257 } 04258 04259 /***************************************************************************** 04260 * IDirect3D3::CreateViewport 04261 * 04262 * Creates an IDirect3DViewport interface. This interface is used 04263 * by Direct3D and earlier versions for Viewport management. In Direct3D7 04264 * it has been replaced by a viewport structure and 04265 * IDirect3DDevice7::*Viewport. Wine's IDirect3DViewport implementation 04266 * uses the IDirect3DDevice7 methods for its functionality 04267 * 04268 * Params: 04269 * Viewport: Address to store the new interface pointer 04270 * outer_unknown: Basically for aggregation, but ddraw doesn't support it. 04271 * Must be NULL 04272 * 04273 * Returns: 04274 * D3D_OK on success 04275 * DDERR_OUTOFMEMORY if memory allocation failed 04276 * CLASS_E_NOAGGREGATION if outer_unknown != NULL 04277 * 04278 *****************************************************************************/ 04279 static HRESULT WINAPI d3d3_CreateViewport(IDirect3D3 *iface, IDirect3DViewport3 **viewport, 04280 IUnknown *outer_unknown) 04281 { 04282 IDirectDrawImpl *This = impl_from_IDirect3D3(iface); 04283 IDirect3DViewportImpl *object; 04284 04285 TRACE("iface %p, viewport %p, outer_unknown %p.\n", iface, viewport, outer_unknown); 04286 04287 if (outer_unknown) return CLASS_E_NOAGGREGATION; 04288 04289 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object)); 04290 if (!object) 04291 { 04292 ERR("Failed to allocate viewport memory.\n"); 04293 return DDERR_OUTOFMEMORY; 04294 } 04295 04296 d3d_viewport_init(object, This); 04297 04298 TRACE("Created viewport %p.\n", object); 04299 *viewport = &object->IDirect3DViewport3_iface; 04300 04301 return D3D_OK; 04302 } 04303 04304 static HRESULT WINAPI d3d2_CreateViewport(IDirect3D2 *iface, IDirect3DViewport2 **viewport, IUnknown *outer_unknown) 04305 { 04306 IDirectDrawImpl *This = impl_from_IDirect3D2(iface); 04307 04308 TRACE("iface %p, viewport %p, outer_unknown %p.\n", iface, viewport, outer_unknown); 04309 04310 return d3d3_CreateViewport(&This->IDirect3D3_iface, (IDirect3DViewport3 **)viewport, 04311 outer_unknown); 04312 } 04313 04314 static HRESULT WINAPI d3d1_CreateViewport(IDirect3D *iface, IDirect3DViewport **viewport, IUnknown *outer_unknown) 04315 { 04316 IDirectDrawImpl *This = impl_from_IDirect3D(iface); 04317 04318 TRACE("iface %p, viewport %p, outer_unknown %p.\n", iface, viewport, outer_unknown); 04319 04320 return d3d3_CreateViewport(&This->IDirect3D3_iface, (IDirect3DViewport3 **)viewport, 04321 outer_unknown); 04322 } 04323 04324 /***************************************************************************** 04325 * IDirect3D3::FindDevice 04326 * 04327 * This method finds a device with the requested properties and returns a 04328 * device description 04329 * 04330 * Verion 1, 2 and 3 04331 * Params: 04332 * fds: Describes the requested device characteristics 04333 * fdr: Returns the device description 04334 * 04335 * Returns: 04336 * D3D_OK on success 04337 * DDERR_INVALIDPARAMS if no device was found 04338 * 04339 *****************************************************************************/ 04340 static HRESULT WINAPI d3d3_FindDevice(IDirect3D3 *iface, D3DFINDDEVICESEARCH *fds, D3DFINDDEVICERESULT *fdr) 04341 { 04342 IDirectDrawImpl *This = impl_from_IDirect3D3(iface); 04343 D3DDEVICEDESC7 desc7; 04344 D3DDEVICEDESC desc1; 04345 HRESULT hr; 04346 04347 TRACE("iface %p, fds %p, fdr %p.\n", iface, fds, fdr); 04348 04349 if (!fds || !fdr) return DDERR_INVALIDPARAMS; 04350 04351 if (fds->dwSize != sizeof(D3DFINDDEVICESEARCH) 04352 || fdr->dwSize != sizeof(D3DFINDDEVICERESULT)) 04353 return DDERR_INVALIDPARAMS; 04354 04355 if ((fds->dwFlags & D3DFDS_COLORMODEL) 04356 && fds->dcmColorModel != D3DCOLOR_RGB) 04357 { 04358 WARN("Trying to request a non-RGB D3D color model. Not supported.\n"); 04359 return DDERR_INVALIDPARAMS; /* No real idea what to return here :-) */ 04360 } 04361 04362 if (fds->dwFlags & D3DFDS_GUID) 04363 { 04364 TRACE("Trying to match guid %s.\n", debugstr_guid(&(fds->guid))); 04365 if (!IsEqualGUID(&IID_D3DDEVICE_WineD3D, &fds->guid) 04366 && !IsEqualGUID(&IID_IDirect3DHALDevice, &fds->guid) 04367 && !IsEqualGUID(&IID_IDirect3DRGBDevice, &fds->guid)) 04368 { 04369 WARN("No match for this GUID.\n"); 04370 return DDERR_NOTFOUND; 04371 } 04372 } 04373 04374 /* Get the caps */ 04375 hr = IDirect3DImpl_GetCaps(This->wined3d, &desc1, &desc7); 04376 if (hr != D3D_OK) return hr; 04377 04378 /* Now return our own GUID */ 04379 fdr->guid = IID_D3DDEVICE_WineD3D; 04380 fdr->ddHwDesc = desc1; 04381 fdr->ddSwDesc = desc1; 04382 04383 TRACE("Returning Wine's wined3d device with (undumped) capabilities.\n"); 04384 04385 return D3D_OK; 04386 } 04387 04388 static HRESULT WINAPI d3d2_FindDevice(IDirect3D2 *iface, D3DFINDDEVICESEARCH *fds, D3DFINDDEVICERESULT *fdr) 04389 { 04390 IDirectDrawImpl *This = impl_from_IDirect3D2(iface); 04391 04392 TRACE("iface %p, fds %p, fdr %p.\n", iface, fds, fdr); 04393 04394 return d3d3_FindDevice(&This->IDirect3D3_iface, fds, fdr); 04395 } 04396 04397 static HRESULT WINAPI d3d1_FindDevice(IDirect3D *iface, D3DFINDDEVICESEARCH *fds, D3DFINDDEVICERESULT *fdr) 04398 { 04399 IDirectDrawImpl *This = impl_from_IDirect3D(iface); 04400 04401 TRACE("iface %p, fds %p, fdr %p.\n", iface, fds, fdr); 04402 04403 return d3d3_FindDevice(&This->IDirect3D3_iface, fds, fdr); 04404 } 04405 04406 /***************************************************************************** 04407 * IDirect3D7::CreateDevice 04408 * 04409 * Creates an IDirect3DDevice7 interface. 04410 * 04411 * Version 2, 3 and 7. IDirect3DDevice 1 interfaces are interfaces to 04412 * DirectDraw surfaces and are created with 04413 * IDirectDrawSurface::QueryInterface. This method uses CreateDevice to 04414 * create the device object and QueryInterfaces for IDirect3DDevice 04415 * 04416 * Params: 04417 * refiid: IID of the device to create 04418 * Surface: Initial rendertarget 04419 * Device: Address to return the interface pointer 04420 * 04421 * Returns: 04422 * D3D_OK on success 04423 * DDERR_OUTOFMEMORY if memory allocation failed 04424 * DDERR_INVALIDPARAMS if a device exists already 04425 * 04426 *****************************************************************************/ 04427 static HRESULT WINAPI d3d7_CreateDevice(IDirect3D7 *iface, REFCLSID riid, 04428 IDirectDrawSurface7 *surface, IDirect3DDevice7 **device) 04429 { 04430 IDirectDrawSurfaceImpl *target = unsafe_impl_from_IDirectDrawSurface7(surface); 04431 IDirectDrawImpl *This = impl_from_IDirect3D7(iface); 04432 IDirect3DDeviceImpl *object; 04433 HRESULT hr; 04434 04435 TRACE("iface %p, riid %s, surface %p, device %p.\n", iface, debugstr_guid(riid), surface, device); 04436 04437 wined3d_mutex_lock(); 04438 *device = NULL; 04439 04440 /* Fail device creation if non-opengl surfaces are used. */ 04441 if (DefaultSurfaceType != SURFACE_OPENGL) 04442 { 04443 ERR("The application wants to create a Direct3D device, but non-opengl surfaces are set in the registry.\n"); 04444 ERR("Please set the surface implementation to opengl or autodetection to allow 3D rendering.\n"); 04445 04446 /* We only hit this path if a default surface is set in the registry. Incorrect autodetection 04447 * is caught in CreateSurface or QueryInterface. */ 04448 wined3d_mutex_unlock(); 04449 return DDERR_NO3D; 04450 } 04451 04452 if (This->d3ddevice) 04453 { 04454 FIXME("Only one Direct3D device per DirectDraw object supported.\n"); 04455 wined3d_mutex_unlock(); 04456 return DDERR_INVALIDPARAMS; 04457 } 04458 04459 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object)); 04460 if (!object) 04461 { 04462 ERR("Failed to allocate device memory.\n"); 04463 wined3d_mutex_unlock(); 04464 return DDERR_OUTOFMEMORY; 04465 } 04466 04467 hr = d3d_device_init(object, This, target); 04468 if (FAILED(hr)) 04469 { 04470 WARN("Failed to initialize device, hr %#x.\n", hr); 04471 HeapFree(GetProcessHeap(), 0, object); 04472 wined3d_mutex_unlock(); 04473 return hr; 04474 } 04475 04476 TRACE("Created device %p.\n", object); 04477 *device = &object->IDirect3DDevice7_iface; 04478 04479 wined3d_mutex_unlock(); 04480 04481 return D3D_OK; 04482 } 04483 04484 static HRESULT WINAPI d3d3_CreateDevice(IDirect3D3 *iface, REFCLSID riid, 04485 IDirectDrawSurface4 *surface, IDirect3DDevice3 **device, IUnknown *outer_unknown) 04486 { 04487 IDirectDrawImpl *This = impl_from_IDirect3D3(iface); 04488 IDirectDrawSurfaceImpl *surface_impl = unsafe_impl_from_IDirectDrawSurface4(surface); 04489 IDirect3DDevice7 *device7; 04490 IDirect3DDeviceImpl *device_impl; 04491 HRESULT hr; 04492 04493 TRACE("iface %p, riid %s, surface %p, device %p, outer_unknown %p.\n", 04494 iface, debugstr_guid(riid), surface, device, outer_unknown); 04495 04496 if (outer_unknown) return CLASS_E_NOAGGREGATION; 04497 04498 hr = d3d7_CreateDevice(&This->IDirect3D7_iface, riid, 04499 surface_impl ? &surface_impl->IDirectDrawSurface7_iface : NULL, device ? &device7 : NULL); 04500 if (SUCCEEDED(hr)) 04501 { 04502 device_impl = impl_from_IDirect3DDevice7(device7); 04503 *device = &device_impl->IDirect3DDevice3_iface; 04504 } 04505 04506 return hr; 04507 } 04508 04509 static HRESULT WINAPI d3d2_CreateDevice(IDirect3D2 *iface, REFCLSID riid, 04510 IDirectDrawSurface *surface, IDirect3DDevice2 **device) 04511 { 04512 IDirectDrawImpl *This = impl_from_IDirect3D2(iface); 04513 IDirectDrawSurfaceImpl *surface_impl = unsafe_impl_from_IDirectDrawSurface(surface); 04514 IDirect3DDevice7 *device7; 04515 IDirect3DDeviceImpl *device_impl; 04516 HRESULT hr; 04517 04518 TRACE("iface %p, riid %s, surface %p, device %p.\n", 04519 iface, debugstr_guid(riid), surface, device); 04520 04521 hr = d3d7_CreateDevice(&This->IDirect3D7_iface, riid, 04522 surface_impl ? &surface_impl->IDirectDrawSurface7_iface : NULL, device ? &device7 : NULL); 04523 if (SUCCEEDED(hr)) 04524 { 04525 device_impl = impl_from_IDirect3DDevice7(device7); 04526 *device = &device_impl->IDirect3DDevice2_iface; 04527 } 04528 04529 return hr; 04530 } 04531 04532 /***************************************************************************** 04533 * IDirect3D7::CreateVertexBuffer 04534 * 04535 * Creates a new vertex buffer object and returns a IDirect3DVertexBuffer7 04536 * interface. 04537 * 04538 * Version 3 and 7 04539 * 04540 * Params: 04541 * desc: Requested Vertex buffer properties 04542 * vertex_buffer: Address to return the interface pointer at 04543 * flags: Some flags, should be 0 04544 * 04545 * Returns 04546 * D3D_OK on success 04547 * DDERR_OUTOFMEMORY if memory allocation failed 04548 * The return value of IWineD3DDevice::CreateVertexBuffer if this call fails 04549 * DDERR_INVALIDPARAMS if desc or vertex_buffer are NULL 04550 * 04551 *****************************************************************************/ 04552 static HRESULT WINAPI d3d7_CreateVertexBuffer(IDirect3D7 *iface, D3DVERTEXBUFFERDESC *desc, 04553 IDirect3DVertexBuffer7 **vertex_buffer, DWORD flags) 04554 { 04555 IDirectDrawImpl *This = impl_from_IDirect3D7(iface); 04556 IDirect3DVertexBufferImpl *object; 04557 HRESULT hr; 04558 04559 TRACE("iface %p, desc %p, vertex_buffer %p, flags %#x.\n", 04560 iface, desc, vertex_buffer, flags); 04561 04562 if (!vertex_buffer || !desc) return DDERR_INVALIDPARAMS; 04563 04564 hr = d3d_vertex_buffer_create(&object, This, desc); 04565 if (hr == D3D_OK) 04566 { 04567 TRACE("Created vertex buffer %p.\n", object); 04568 *vertex_buffer = &object->IDirect3DVertexBuffer7_iface; 04569 } 04570 else 04571 WARN("Failed to create vertex buffer, hr %#x.\n", hr); 04572 04573 return hr; 04574 } 04575 04576 static HRESULT WINAPI d3d3_CreateVertexBuffer(IDirect3D3 *iface, D3DVERTEXBUFFERDESC *desc, 04577 IDirect3DVertexBuffer **vertex_buffer, DWORD flags, IUnknown *outer_unknown) 04578 { 04579 IDirectDrawImpl *This = impl_from_IDirect3D3(iface); 04580 IDirect3DVertexBufferImpl *object; 04581 HRESULT hr; 04582 04583 TRACE("iface %p, desc %p, vertex_buffer %p, flags %#x, outer_unknown %p.\n", 04584 iface, desc, vertex_buffer, flags, outer_unknown); 04585 04586 if (outer_unknown) 04587 return CLASS_E_NOAGGREGATION; 04588 if (!vertex_buffer || !desc) 04589 return DDERR_INVALIDPARAMS; 04590 04591 hr = d3d_vertex_buffer_create(&object, This, desc); 04592 if (hr == D3D_OK) 04593 { 04594 TRACE("Created vertex buffer %p.\n", object); 04595 *vertex_buffer = &object->IDirect3DVertexBuffer_iface; 04596 } 04597 else 04598 WARN("Failed to create vertex buffer, hr %#x.\n", hr); 04599 04600 return hr; 04601 } 04602 04603 /***************************************************************************** 04604 * IDirect3D7::EnumZBufferFormats 04605 * 04606 * Enumerates all supported Z buffer pixel formats 04607 * 04608 * Version 3 and 7 04609 * 04610 * Params: 04611 * device_iid: 04612 * callback: callback to call for each pixel format 04613 * context: Pointer to pass back to the callback 04614 * 04615 * Returns: 04616 * D3D_OK on success 04617 * DDERR_INVALIDPARAMS if callback is NULL 04618 * For details, see IWineD3DDevice::EnumZBufferFormats 04619 * 04620 *****************************************************************************/ 04621 static HRESULT WINAPI d3d7_EnumZBufferFormats(IDirect3D7 *iface, REFCLSID device_iid, 04622 LPD3DENUMPIXELFORMATSCALLBACK callback, void *context) 04623 { 04624 IDirectDrawImpl *This = impl_from_IDirect3D7(iface); 04625 struct wined3d_display_mode mode; 04626 enum wined3d_device_type type; 04627 unsigned int i; 04628 HRESULT hr; 04629 04630 /* Order matters. Specifically, BattleZone II (full version) expects the 04631 * 16-bit depth formats to be listed before the 24 and 32 ones. */ 04632 static const enum wined3d_format_id formats[] = 04633 { 04634 WINED3DFMT_S1_UINT_D15_UNORM, 04635 WINED3DFMT_D16_UNORM, 04636 WINED3DFMT_X8D24_UNORM, 04637 WINED3DFMT_S4X4_UINT_D24_UNORM, 04638 WINED3DFMT_D24_UNORM_S8_UINT, 04639 WINED3DFMT_D32_UNORM, 04640 }; 04641 04642 TRACE("iface %p, device_iid %s, callback %p, context %p.\n", 04643 iface, debugstr_guid(device_iid), callback, context); 04644 04645 if (!callback) return DDERR_INVALIDPARAMS; 04646 04647 if (IsEqualGUID(device_iid, &IID_IDirect3DHALDevice) 04648 || IsEqualGUID(device_iid, &IID_IDirect3DTnLHalDevice) 04649 || IsEqualGUID(device_iid, &IID_D3DDEVICE_WineD3D)) 04650 { 04651 TRACE("Asked for HAL device.\n"); 04652 type = WINED3D_DEVICE_TYPE_HAL; 04653 } 04654 else if (IsEqualGUID(device_iid, &IID_IDirect3DRGBDevice) 04655 || IsEqualGUID(device_iid, &IID_IDirect3DMMXDevice)) 04656 { 04657 TRACE("Asked for SW device.\n"); 04658 type = WINED3D_DEVICE_TYPE_SW; 04659 } 04660 else if (IsEqualGUID(device_iid, &IID_IDirect3DRefDevice)) 04661 { 04662 TRACE("Asked for REF device.\n"); 04663 type = WINED3D_DEVICE_TYPE_REF; 04664 } 04665 else if (IsEqualGUID(device_iid, &IID_IDirect3DNullDevice)) 04666 { 04667 TRACE("Asked for NULLREF device.\n"); 04668 type = WINED3D_DEVICE_TYPE_NULLREF; 04669 } 04670 else 04671 { 04672 FIXME("Unexpected device GUID %s.\n", debugstr_guid(device_iid)); 04673 type = WINED3D_DEVICE_TYPE_HAL; 04674 } 04675 04676 wined3d_mutex_lock(); 04677 /* We need an adapter format from somewhere to please wined3d and WGL. 04678 * Use the current display mode. So far all cards offer the same depth 04679 * stencil format for all modes, but if some do not and applications do 04680 * not like that we'll have to find some workaround, like iterating over 04681 * all imaginable formats and collecting all the depth stencil formats we 04682 * can get. */ 04683 hr = wined3d_device_get_display_mode(This->wined3d_device, 0, &mode); 04684 04685 for (i = 0; i < (sizeof(formats) / sizeof(*formats)); ++i) 04686 { 04687 hr = wined3d_check_device_format(This->wined3d, WINED3DADAPTER_DEFAULT, type, mode.format_id, 04688 WINED3DUSAGE_DEPTHSTENCIL, WINED3D_RTYPE_SURFACE, formats[i], SURFACE_OPENGL); 04689 if (SUCCEEDED(hr)) 04690 { 04691 DDPIXELFORMAT pformat; 04692 04693 memset(&pformat, 0, sizeof(pformat)); 04694 pformat.dwSize = sizeof(pformat); 04695 PixelFormat_WineD3DtoDD(&pformat, formats[i]); 04696 04697 TRACE("Enumerating wined3d format %#x.\n", formats[i]); 04698 hr = callback(&pformat, context); 04699 if (hr != DDENUMRET_OK) 04700 { 04701 TRACE("Format enumeration cancelled by application.\n"); 04702 wined3d_mutex_unlock(); 04703 return D3D_OK; 04704 } 04705 } 04706 } 04707 04708 /* Historically some windows drivers used dwZBufferBitDepth=24 for WINED3DFMT_X8D24_UNORM, 04709 * while others used dwZBufferBitDepth=32. In either case the pitch matches a 32 bits per 04710 * pixel format, so we use dwZBufferBitDepth=32. Some games expect 24. Windows Vista and 04711 * newer enumerate both versions, so we do the same(bug 22434) */ 04712 hr = wined3d_check_device_format(This->wined3d, WINED3DADAPTER_DEFAULT, type, mode.format_id, 04713 WINED3DUSAGE_DEPTHSTENCIL, WINED3D_RTYPE_SURFACE, WINED3DFMT_X8D24_UNORM, SURFACE_OPENGL); 04714 if (SUCCEEDED(hr)) 04715 { 04716 DDPIXELFORMAT x8d24 = 04717 { 04718 sizeof(x8d24), DDPF_ZBUFFER, 0, 04719 {24}, {0x00000000}, {0x00ffffff}, {0x00000000} 04720 }; 04721 TRACE("Enumerating WINED3DFMT_X8D24_UNORM, dwZBufferBitDepth=24 version\n"); 04722 callback(&x8d24, context); 04723 } 04724 04725 TRACE("End of enumeration.\n"); 04726 04727 wined3d_mutex_unlock(); 04728 04729 return D3D_OK; 04730 } 04731 04732 static HRESULT WINAPI d3d3_EnumZBufferFormats(IDirect3D3 *iface, REFCLSID device_iid, 04733 LPD3DENUMPIXELFORMATSCALLBACK callback, void *context) 04734 { 04735 IDirectDrawImpl *This = impl_from_IDirect3D3(iface); 04736 04737 TRACE("iface %p, device_iid %s, callback %p, context %p.\n", 04738 iface, debugstr_guid(device_iid), callback, context); 04739 04740 return d3d7_EnumZBufferFormats(&This->IDirect3D7_iface, device_iid, callback, context); 04741 } 04742 04743 /***************************************************************************** 04744 * IDirect3D7::EvictManagedTextures 04745 * 04746 * Removes all managed textures (=surfaces with DDSCAPS2_TEXTUREMANAGE or 04747 * DDSCAPS2_D3DTEXTUREMANAGE caps) to be removed from video memory. 04748 * 04749 * Version 3 and 7 04750 * 04751 * Returns: 04752 * D3D_OK, because it's a stub 04753 * 04754 *****************************************************************************/ 04755 static HRESULT WINAPI d3d7_EvictManagedTextures(IDirect3D7 *iface) 04756 { 04757 IDirectDrawImpl *This = impl_from_IDirect3D7(iface); 04758 04759 TRACE("iface %p!\n", iface); 04760 04761 wined3d_mutex_lock(); 04762 if (This->d3d_initialized) 04763 wined3d_device_evict_managed_resources(This->wined3d_device); 04764 wined3d_mutex_unlock(); 04765 04766 return D3D_OK; 04767 } 04768 04769 static HRESULT WINAPI d3d3_EvictManagedTextures(IDirect3D3 *iface) 04770 { 04771 IDirectDrawImpl *This = impl_from_IDirect3D3(iface); 04772 04773 TRACE("iface %p.\n", iface); 04774 04775 return d3d7_EvictManagedTextures(&This->IDirect3D7_iface); 04776 } 04777 04778 /***************************************************************************** 04779 * IDirect3DImpl_GetCaps 04780 * 04781 * This function retrieves the device caps from wined3d 04782 * and converts it into a D3D7 and D3D - D3D3 structure 04783 * This is a helper function called from various places in ddraw 04784 * 04785 * Params: 04786 * wined3d: The interface to get the caps from 04787 * desc1: Old D3D <3 structure to fill (needed) 04788 * desc7: D3D7 device desc structure to fill (needed) 04789 * 04790 * Returns 04791 * D3D_OK on success, or the return value of IWineD3D::GetCaps 04792 * 04793 *****************************************************************************/ 04794 HRESULT IDirect3DImpl_GetCaps(const struct wined3d *wined3d, D3DDEVICEDESC *desc1, D3DDEVICEDESC7 *desc7) 04795 { 04796 WINED3DCAPS wined3d_caps; 04797 HRESULT hr; 04798 04799 TRACE("wined3d %p, desc1 %p, desc7 %p.\n", wined3d, desc1, desc7); 04800 04801 memset(&wined3d_caps, 0, sizeof(wined3d_caps)); 04802 04803 wined3d_mutex_lock(); 04804 hr = wined3d_get_device_caps(wined3d, 0, WINED3D_DEVICE_TYPE_HAL, &wined3d_caps); 04805 wined3d_mutex_unlock(); 04806 if (FAILED(hr)) 04807 { 04808 WARN("Failed to get device caps, hr %#x.\n", hr); 04809 return hr; 04810 } 04811 04812 /* Copy the results into the d3d7 and d3d3 structures */ 04813 desc7->dwDevCaps = wined3d_caps.DevCaps; 04814 desc7->dpcLineCaps.dwMiscCaps = wined3d_caps.PrimitiveMiscCaps; 04815 desc7->dpcLineCaps.dwRasterCaps = wined3d_caps.RasterCaps; 04816 desc7->dpcLineCaps.dwZCmpCaps = wined3d_caps.ZCmpCaps; 04817 desc7->dpcLineCaps.dwSrcBlendCaps = wined3d_caps.SrcBlendCaps; 04818 desc7->dpcLineCaps.dwDestBlendCaps = wined3d_caps.DestBlendCaps; 04819 desc7->dpcLineCaps.dwAlphaCmpCaps = wined3d_caps.AlphaCmpCaps; 04820 desc7->dpcLineCaps.dwShadeCaps = wined3d_caps.ShadeCaps; 04821 desc7->dpcLineCaps.dwTextureCaps = wined3d_caps.TextureCaps; 04822 desc7->dpcLineCaps.dwTextureFilterCaps = wined3d_caps.TextureFilterCaps; 04823 desc7->dpcLineCaps.dwTextureAddressCaps = wined3d_caps.TextureAddressCaps; 04824 04825 desc7->dwMaxTextureWidth = wined3d_caps.MaxTextureWidth; 04826 desc7->dwMaxTextureHeight = wined3d_caps.MaxTextureHeight; 04827 04828 desc7->dwMaxTextureRepeat = wined3d_caps.MaxTextureRepeat; 04829 desc7->dwMaxTextureAspectRatio = wined3d_caps.MaxTextureAspectRatio; 04830 desc7->dwMaxAnisotropy = wined3d_caps.MaxAnisotropy; 04831 desc7->dvMaxVertexW = wined3d_caps.MaxVertexW; 04832 04833 desc7->dvGuardBandLeft = wined3d_caps.GuardBandLeft; 04834 desc7->dvGuardBandTop = wined3d_caps.GuardBandTop; 04835 desc7->dvGuardBandRight = wined3d_caps.GuardBandRight; 04836 desc7->dvGuardBandBottom = wined3d_caps.GuardBandBottom; 04837 04838 desc7->dvExtentsAdjust = wined3d_caps.ExtentsAdjust; 04839 desc7->dwStencilCaps = wined3d_caps.StencilCaps; 04840 04841 desc7->dwFVFCaps = wined3d_caps.FVFCaps; 04842 desc7->dwTextureOpCaps = wined3d_caps.TextureOpCaps; 04843 04844 desc7->dwVertexProcessingCaps = wined3d_caps.VertexProcessingCaps; 04845 desc7->dwMaxActiveLights = wined3d_caps.MaxActiveLights; 04846 04847 /* Remove all non-d3d7 caps */ 04848 desc7->dwDevCaps &= ( 04849 D3DDEVCAPS_FLOATTLVERTEX | D3DDEVCAPS_SORTINCREASINGZ | D3DDEVCAPS_SORTDECREASINGZ | 04850 D3DDEVCAPS_SORTEXACT | D3DDEVCAPS_EXECUTESYSTEMMEMORY | D3DDEVCAPS_EXECUTEVIDEOMEMORY | 04851 D3DDEVCAPS_TLVERTEXSYSTEMMEMORY | D3DDEVCAPS_TLVERTEXVIDEOMEMORY | D3DDEVCAPS_TEXTURESYSTEMMEMORY | 04852 D3DDEVCAPS_TEXTUREVIDEOMEMORY | D3DDEVCAPS_DRAWPRIMTLVERTEX | D3DDEVCAPS_CANRENDERAFTERFLIP | 04853 D3DDEVCAPS_TEXTURENONLOCALVIDMEM | D3DDEVCAPS_DRAWPRIMITIVES2 | D3DDEVCAPS_SEPARATETEXTUREMEMORIES | 04854 D3DDEVCAPS_DRAWPRIMITIVES2EX | D3DDEVCAPS_HWTRANSFORMANDLIGHT | D3DDEVCAPS_CANBLTSYSTONONLOCAL | 04855 D3DDEVCAPS_HWRASTERIZATION); 04856 04857 desc7->dwStencilCaps &= ( 04858 D3DSTENCILCAPS_KEEP | D3DSTENCILCAPS_ZERO | D3DSTENCILCAPS_REPLACE | 04859 D3DSTENCILCAPS_INCRSAT | D3DSTENCILCAPS_DECRSAT | D3DSTENCILCAPS_INVERT | 04860 D3DSTENCILCAPS_INCR | D3DSTENCILCAPS_DECR); 04861 04862 /* FVF caps ?*/ 04863 04864 desc7->dwTextureOpCaps &= ( 04865 D3DTEXOPCAPS_DISABLE | D3DTEXOPCAPS_SELECTARG1 | D3DTEXOPCAPS_SELECTARG2 | 04866 D3DTEXOPCAPS_MODULATE | D3DTEXOPCAPS_MODULATE2X | D3DTEXOPCAPS_MODULATE4X | 04867 D3DTEXOPCAPS_ADD | D3DTEXOPCAPS_ADDSIGNED | D3DTEXOPCAPS_ADDSIGNED2X | 04868 D3DTEXOPCAPS_SUBTRACT | D3DTEXOPCAPS_ADDSMOOTH | D3DTEXOPCAPS_BLENDTEXTUREALPHA | 04869 D3DTEXOPCAPS_BLENDFACTORALPHA | D3DTEXOPCAPS_BLENDTEXTUREALPHAPM | D3DTEXOPCAPS_BLENDCURRENTALPHA | 04870 D3DTEXOPCAPS_PREMODULATE | D3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR | D3DTEXOPCAPS_MODULATECOLOR_ADDALPHA | 04871 D3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR | D3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA | D3DTEXOPCAPS_BUMPENVMAP | 04872 D3DTEXOPCAPS_BUMPENVMAPLUMINANCE | D3DTEXOPCAPS_DOTPRODUCT3); 04873 04874 desc7->dwVertexProcessingCaps &= ( 04875 D3DVTXPCAPS_TEXGEN | D3DVTXPCAPS_MATERIALSOURCE7 | D3DVTXPCAPS_VERTEXFOG | 04876 D3DVTXPCAPS_DIRECTIONALLIGHTS | D3DVTXPCAPS_POSITIONALLIGHTS | D3DVTXPCAPS_LOCALVIEWER); 04877 04878 desc7->dpcLineCaps.dwMiscCaps &= ( 04879 D3DPMISCCAPS_MASKPLANES | D3DPMISCCAPS_MASKZ | D3DPMISCCAPS_LINEPATTERNREP | 04880 D3DPMISCCAPS_CONFORMANT | D3DPMISCCAPS_CULLNONE | D3DPMISCCAPS_CULLCW | 04881 D3DPMISCCAPS_CULLCCW); 04882 04883 desc7->dpcLineCaps.dwRasterCaps &= ( 04884 D3DPRASTERCAPS_DITHER | D3DPRASTERCAPS_ROP2 | D3DPRASTERCAPS_XOR | 04885 D3DPRASTERCAPS_PAT | D3DPRASTERCAPS_ZTEST | D3DPRASTERCAPS_SUBPIXEL | 04886 D3DPRASTERCAPS_SUBPIXELX | D3DPRASTERCAPS_FOGVERTEX | D3DPRASTERCAPS_FOGTABLE | 04887 D3DPRASTERCAPS_STIPPLE | D3DPRASTERCAPS_ANTIALIASSORTDEPENDENT | D3DPRASTERCAPS_ANTIALIASSORTINDEPENDENT | 04888 D3DPRASTERCAPS_ANTIALIASEDGES | D3DPRASTERCAPS_MIPMAPLODBIAS | D3DPRASTERCAPS_ZBIAS | 04889 D3DPRASTERCAPS_ZBUFFERLESSHSR | D3DPRASTERCAPS_FOGRANGE | D3DPRASTERCAPS_ANISOTROPY | 04890 D3DPRASTERCAPS_WBUFFER | D3DPRASTERCAPS_TRANSLUCENTSORTINDEPENDENT | D3DPRASTERCAPS_WFOG | 04891 D3DPRASTERCAPS_ZFOG); 04892 04893 desc7->dpcLineCaps.dwZCmpCaps &= ( 04894 D3DPCMPCAPS_NEVER | D3DPCMPCAPS_LESS | D3DPCMPCAPS_EQUAL | 04895 D3DPCMPCAPS_LESSEQUAL | D3DPCMPCAPS_GREATER | D3DPCMPCAPS_NOTEQUAL | 04896 D3DPCMPCAPS_GREATEREQUAL | D3DPCMPCAPS_ALWAYS); 04897 04898 desc7->dpcLineCaps.dwSrcBlendCaps &= ( 04899 D3DPBLENDCAPS_ZERO | D3DPBLENDCAPS_ONE | D3DPBLENDCAPS_SRCCOLOR | 04900 D3DPBLENDCAPS_INVSRCCOLOR | D3DPBLENDCAPS_SRCALPHA | D3DPBLENDCAPS_INVSRCALPHA | 04901 D3DPBLENDCAPS_DESTALPHA | D3DPBLENDCAPS_INVDESTALPHA | D3DPBLENDCAPS_DESTCOLOR | 04902 D3DPBLENDCAPS_INVDESTCOLOR | D3DPBLENDCAPS_SRCALPHASAT | D3DPBLENDCAPS_BOTHSRCALPHA | 04903 D3DPBLENDCAPS_BOTHINVSRCALPHA); 04904 04905 desc7->dpcLineCaps.dwDestBlendCaps &= ( 04906 D3DPBLENDCAPS_ZERO | D3DPBLENDCAPS_ONE | D3DPBLENDCAPS_SRCCOLOR | 04907 D3DPBLENDCAPS_INVSRCCOLOR | D3DPBLENDCAPS_SRCALPHA | D3DPBLENDCAPS_INVSRCALPHA | 04908 D3DPBLENDCAPS_DESTALPHA | D3DPBLENDCAPS_INVDESTALPHA | D3DPBLENDCAPS_DESTCOLOR | 04909 D3DPBLENDCAPS_INVDESTCOLOR | D3DPBLENDCAPS_SRCALPHASAT | D3DPBLENDCAPS_BOTHSRCALPHA | 04910 D3DPBLENDCAPS_BOTHINVSRCALPHA); 04911 04912 desc7->dpcLineCaps.dwAlphaCmpCaps &= ( 04913 D3DPCMPCAPS_NEVER | D3DPCMPCAPS_LESS | D3DPCMPCAPS_EQUAL | 04914 D3DPCMPCAPS_LESSEQUAL | D3DPCMPCAPS_GREATER | D3DPCMPCAPS_NOTEQUAL | 04915 D3DPCMPCAPS_GREATEREQUAL | D3DPCMPCAPS_ALWAYS); 04916 04917 desc7->dpcLineCaps.dwShadeCaps &= ( 04918 D3DPSHADECAPS_COLORFLATMONO | D3DPSHADECAPS_COLORFLATRGB | D3DPSHADECAPS_COLORGOURAUDMONO | 04919 D3DPSHADECAPS_COLORGOURAUDRGB | D3DPSHADECAPS_COLORPHONGMONO | D3DPSHADECAPS_COLORPHONGRGB | 04920 D3DPSHADECAPS_SPECULARFLATMONO | D3DPSHADECAPS_SPECULARFLATRGB | D3DPSHADECAPS_SPECULARGOURAUDMONO | 04921 D3DPSHADECAPS_SPECULARGOURAUDRGB | D3DPSHADECAPS_SPECULARPHONGMONO | D3DPSHADECAPS_SPECULARPHONGRGB | 04922 D3DPSHADECAPS_ALPHAFLATBLEND | D3DPSHADECAPS_ALPHAFLATSTIPPLED | D3DPSHADECAPS_ALPHAGOURAUDBLEND | 04923 D3DPSHADECAPS_ALPHAGOURAUDSTIPPLED | D3DPSHADECAPS_ALPHAPHONGBLEND | D3DPSHADECAPS_ALPHAPHONGSTIPPLED | 04924 D3DPSHADECAPS_FOGFLAT | D3DPSHADECAPS_FOGGOURAUD | D3DPSHADECAPS_FOGPHONG); 04925 04926 desc7->dpcLineCaps.dwTextureCaps &= ( 04927 D3DPTEXTURECAPS_PERSPECTIVE | D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_ALPHA | 04928 D3DPTEXTURECAPS_TRANSPARENCY | D3DPTEXTURECAPS_BORDER | D3DPTEXTURECAPS_SQUAREONLY | 04929 D3DPTEXTURECAPS_TEXREPEATNOTSCALEDBYSIZE | D3DPTEXTURECAPS_ALPHAPALETTE| D3DPTEXTURECAPS_NONPOW2CONDITIONAL | 04930 D3DPTEXTURECAPS_PROJECTED | D3DPTEXTURECAPS_CUBEMAP | D3DPTEXTURECAPS_COLORKEYBLEND); 04931 04932 desc7->dpcLineCaps.dwTextureFilterCaps &= ( 04933 D3DPTFILTERCAPS_NEAREST | D3DPTFILTERCAPS_LINEAR | D3DPTFILTERCAPS_MIPNEAREST | 04934 D3DPTFILTERCAPS_MIPLINEAR | D3DPTFILTERCAPS_LINEARMIPNEAREST | D3DPTFILTERCAPS_LINEARMIPLINEAR | 04935 D3DPTFILTERCAPS_MINFPOINT | D3DPTFILTERCAPS_MINFLINEAR | D3DPTFILTERCAPS_MINFANISOTROPIC | 04936 D3DPTFILTERCAPS_MIPFPOINT | D3DPTFILTERCAPS_MIPFLINEAR | D3DPTFILTERCAPS_MAGFPOINT | 04937 D3DPTFILTERCAPS_MAGFLINEAR | D3DPTFILTERCAPS_MAGFANISOTROPIC | D3DPTFILTERCAPS_MAGFAFLATCUBIC | 04938 D3DPTFILTERCAPS_MAGFGAUSSIANCUBIC); 04939 04940 desc7->dpcLineCaps.dwTextureBlendCaps &= ( 04941 D3DPTBLENDCAPS_DECAL | D3DPTBLENDCAPS_MODULATE | D3DPTBLENDCAPS_DECALALPHA | 04942 D3DPTBLENDCAPS_MODULATEALPHA | D3DPTBLENDCAPS_DECALMASK | D3DPTBLENDCAPS_MODULATEMASK | 04943 D3DPTBLENDCAPS_COPY | D3DPTBLENDCAPS_ADD); 04944 04945 desc7->dpcLineCaps.dwTextureAddressCaps &= ( 04946 D3DPTADDRESSCAPS_WRAP | D3DPTADDRESSCAPS_MIRROR | D3DPTADDRESSCAPS_CLAMP | 04947 D3DPTADDRESSCAPS_BORDER | D3DPTADDRESSCAPS_INDEPENDENTUV); 04948 04949 if (!(desc7->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2)) 04950 { 04951 /* DirectX7 always has the np2 flag set, no matter what the card 04952 * supports. Some old games (Rollcage) check the caps incorrectly. 04953 * If wined3d supports nonpow2 textures it also has np2 conditional 04954 * support. */ 04955 desc7->dpcLineCaps.dwTextureCaps |= D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_NONPOW2CONDITIONAL; 04956 } 04957 04958 /* Fill the missing members, and do some fixup */ 04959 desc7->dpcLineCaps.dwSize = sizeof(desc7->dpcLineCaps); 04960 desc7->dpcLineCaps.dwTextureBlendCaps = D3DPTBLENDCAPS_ADD | D3DPTBLENDCAPS_MODULATEMASK | 04961 D3DPTBLENDCAPS_COPY | D3DPTBLENDCAPS_DECAL | 04962 D3DPTBLENDCAPS_DECALALPHA | D3DPTBLENDCAPS_DECALMASK | 04963 D3DPTBLENDCAPS_MODULATE | D3DPTBLENDCAPS_MODULATEALPHA; 04964 desc7->dpcLineCaps.dwStippleWidth = 32; 04965 desc7->dpcLineCaps.dwStippleHeight = 32; 04966 /* Use the same for the TriCaps */ 04967 desc7->dpcTriCaps = desc7->dpcLineCaps; 04968 04969 desc7->dwDeviceRenderBitDepth = DDBD_16 | DDBD_24 | DDBD_32; 04970 desc7->dwDeviceZBufferBitDepth = DDBD_16 | DDBD_24; 04971 desc7->dwMinTextureWidth = 1; 04972 desc7->dwMinTextureHeight = 1; 04973 04974 /* Convert DWORDs safely to WORDs */ 04975 if (wined3d_caps.MaxTextureBlendStages > 0xffff) desc7->wMaxTextureBlendStages = 0xffff; 04976 else desc7->wMaxTextureBlendStages = (WORD)wined3d_caps.MaxTextureBlendStages; 04977 if (wined3d_caps.MaxSimultaneousTextures > 0xffff) desc7->wMaxSimultaneousTextures = 0xffff; 04978 else desc7->wMaxSimultaneousTextures = (WORD)wined3d_caps.MaxSimultaneousTextures; 04979 04980 if (wined3d_caps.MaxUserClipPlanes > 0xffff) desc7->wMaxUserClipPlanes = 0xffff; 04981 else desc7->wMaxUserClipPlanes = (WORD)wined3d_caps.MaxUserClipPlanes; 04982 if (wined3d_caps.MaxVertexBlendMatrices > 0xffff) desc7->wMaxVertexBlendMatrices = 0xffff; 04983 else desc7->wMaxVertexBlendMatrices = (WORD)wined3d_caps.MaxVertexBlendMatrices; 04984 04985 desc7->deviceGUID = IID_IDirect3DTnLHalDevice; 04986 04987 desc7->dwReserved1 = 0; 04988 desc7->dwReserved2 = 0; 04989 desc7->dwReserved3 = 0; 04990 desc7->dwReserved4 = 0; 04991 04992 /* Fill the old structure */ 04993 memset(desc1, 0, sizeof(*desc1)); 04994 desc1->dwSize = sizeof(D3DDEVICEDESC); 04995 desc1->dwFlags = D3DDD_COLORMODEL 04996 | D3DDD_DEVCAPS 04997 | D3DDD_TRANSFORMCAPS 04998 | D3DDD_BCLIPPING 04999 | D3DDD_LIGHTINGCAPS 05000 | D3DDD_LINECAPS 05001 | D3DDD_TRICAPS 05002 | D3DDD_DEVICERENDERBITDEPTH 05003 | D3DDD_DEVICEZBUFFERBITDEPTH 05004 | D3DDD_MAXBUFFERSIZE 05005 | D3DDD_MAXVERTEXCOUNT; 05006 05007 desc1->dcmColorModel = D3DCOLOR_RGB; 05008 desc1->dwDevCaps = desc7->dwDevCaps; 05009 desc1->dtcTransformCaps.dwSize = sizeof(D3DTRANSFORMCAPS); 05010 desc1->dtcTransformCaps.dwCaps = D3DTRANSFORMCAPS_CLIP; 05011 desc1->bClipping = TRUE; 05012 desc1->dlcLightingCaps.dwSize = sizeof(D3DLIGHTINGCAPS); 05013 desc1->dlcLightingCaps.dwCaps = D3DLIGHTCAPS_DIRECTIONAL 05014 | D3DLIGHTCAPS_PARALLELPOINT 05015 | D3DLIGHTCAPS_POINT 05016 | D3DLIGHTCAPS_SPOT; 05017 05018 desc1->dlcLightingCaps.dwLightingModel = D3DLIGHTINGMODEL_RGB; 05019 desc1->dlcLightingCaps.dwNumLights = desc7->dwMaxActiveLights; 05020 05021 desc1->dpcLineCaps.dwSize = sizeof(D3DPRIMCAPS); 05022 desc1->dpcLineCaps.dwMiscCaps = desc7->dpcLineCaps.dwMiscCaps; 05023 desc1->dpcLineCaps.dwRasterCaps = desc7->dpcLineCaps.dwRasterCaps; 05024 desc1->dpcLineCaps.dwZCmpCaps = desc7->dpcLineCaps.dwZCmpCaps; 05025 desc1->dpcLineCaps.dwSrcBlendCaps = desc7->dpcLineCaps.dwSrcBlendCaps; 05026 desc1->dpcLineCaps.dwDestBlendCaps = desc7->dpcLineCaps.dwDestBlendCaps; 05027 desc1->dpcLineCaps.dwShadeCaps = desc7->dpcLineCaps.dwShadeCaps; 05028 desc1->dpcLineCaps.dwTextureCaps = desc7->dpcLineCaps.dwTextureCaps; 05029 desc1->dpcLineCaps.dwTextureFilterCaps = desc7->dpcLineCaps.dwTextureFilterCaps; 05030 desc1->dpcLineCaps.dwTextureBlendCaps = desc7->dpcLineCaps.dwTextureBlendCaps; 05031 desc1->dpcLineCaps.dwTextureAddressCaps = desc7->dpcLineCaps.dwTextureAddressCaps; 05032 desc1->dpcLineCaps.dwStippleWidth = desc7->dpcLineCaps.dwStippleWidth; 05033 desc1->dpcLineCaps.dwAlphaCmpCaps = desc7->dpcLineCaps.dwAlphaCmpCaps; 05034 05035 desc1->dpcTriCaps.dwSize = sizeof(D3DPRIMCAPS); 05036 desc1->dpcTriCaps.dwMiscCaps = desc7->dpcTriCaps.dwMiscCaps; 05037 desc1->dpcTriCaps.dwRasterCaps = desc7->dpcTriCaps.dwRasterCaps; 05038 desc1->dpcTriCaps.dwZCmpCaps = desc7->dpcTriCaps.dwZCmpCaps; 05039 desc1->dpcTriCaps.dwSrcBlendCaps = desc7->dpcTriCaps.dwSrcBlendCaps; 05040 desc1->dpcTriCaps.dwDestBlendCaps = desc7->dpcTriCaps.dwDestBlendCaps; 05041 desc1->dpcTriCaps.dwShadeCaps = desc7->dpcTriCaps.dwShadeCaps; 05042 desc1->dpcTriCaps.dwTextureCaps = desc7->dpcTriCaps.dwTextureCaps; 05043 desc1->dpcTriCaps.dwTextureFilterCaps = desc7->dpcTriCaps.dwTextureFilterCaps; 05044 desc1->dpcTriCaps.dwTextureBlendCaps = desc7->dpcTriCaps.dwTextureBlendCaps; 05045 desc1->dpcTriCaps.dwTextureAddressCaps = desc7->dpcTriCaps.dwTextureAddressCaps; 05046 desc1->dpcTriCaps.dwStippleWidth = desc7->dpcTriCaps.dwStippleWidth; 05047 desc1->dpcTriCaps.dwAlphaCmpCaps = desc7->dpcTriCaps.dwAlphaCmpCaps; 05048 05049 desc1->dwDeviceRenderBitDepth = desc7->dwDeviceRenderBitDepth; 05050 desc1->dwDeviceZBufferBitDepth = desc7->dwDeviceZBufferBitDepth; 05051 desc1->dwMaxBufferSize = 0; 05052 desc1->dwMaxVertexCount = 65536; 05053 desc1->dwMinTextureWidth = desc7->dwMinTextureWidth; 05054 desc1->dwMinTextureHeight = desc7->dwMinTextureHeight; 05055 desc1->dwMaxTextureWidth = desc7->dwMaxTextureWidth; 05056 desc1->dwMaxTextureHeight = desc7->dwMaxTextureHeight; 05057 desc1->dwMinStippleWidth = 1; 05058 desc1->dwMinStippleHeight = 1; 05059 desc1->dwMaxStippleWidth = 32; 05060 desc1->dwMaxStippleHeight = 32; 05061 desc1->dwMaxTextureRepeat = desc7->dwMaxTextureRepeat; 05062 desc1->dwMaxTextureAspectRatio = desc7->dwMaxTextureAspectRatio; 05063 desc1->dwMaxAnisotropy = desc7->dwMaxAnisotropy; 05064 desc1->dvGuardBandLeft = desc7->dvGuardBandLeft; 05065 desc1->dvGuardBandRight = desc7->dvGuardBandRight; 05066 desc1->dvGuardBandTop = desc7->dvGuardBandTop; 05067 desc1->dvGuardBandBottom = desc7->dvGuardBandBottom; 05068 desc1->dvExtentsAdjust = desc7->dvExtentsAdjust; 05069 desc1->dwStencilCaps = desc7->dwStencilCaps; 05070 desc1->dwFVFCaps = desc7->dwFVFCaps; 05071 desc1->dwTextureOpCaps = desc7->dwTextureOpCaps; 05072 desc1->wMaxTextureBlendStages = desc7->wMaxTextureBlendStages; 05073 desc1->wMaxSimultaneousTextures = desc7->wMaxSimultaneousTextures; 05074 05075 return DD_OK; 05076 } 05077 05078 /***************************************************************************** 05079 * IDirectDraw7 VTable 05080 *****************************************************************************/ 05081 static const struct IDirectDraw7Vtbl ddraw7_vtbl = 05082 { 05083 /* IUnknown */ 05084 ddraw7_QueryInterface, 05085 ddraw7_AddRef, 05086 ddraw7_Release, 05087 /* IDirectDraw */ 05088 ddraw7_Compact, 05089 ddraw7_CreateClipper, 05090 ddraw7_CreatePalette, 05091 ddraw7_CreateSurface, 05092 ddraw7_DuplicateSurface, 05093 ddraw7_EnumDisplayModes, 05094 ddraw7_EnumSurfaces, 05095 ddraw7_FlipToGDISurface, 05096 ddraw7_GetCaps, 05097 ddraw7_GetDisplayMode, 05098 ddraw7_GetFourCCCodes, 05099 ddraw7_GetGDISurface, 05100 ddraw7_GetMonitorFrequency, 05101 ddraw7_GetScanLine, 05102 ddraw7_GetVerticalBlankStatus, 05103 ddraw7_Initialize, 05104 ddraw7_RestoreDisplayMode, 05105 ddraw7_SetCooperativeLevel, 05106 ddraw7_SetDisplayMode, 05107 ddraw7_WaitForVerticalBlank, 05108 /* IDirectDraw2 */ 05109 ddraw7_GetAvailableVidMem, 05110 /* IDirectDraw3 */ 05111 ddraw7_GetSurfaceFromDC, 05112 /* IDirectDraw4 */ 05113 ddraw7_RestoreAllSurfaces, 05114 ddraw7_TestCooperativeLevel, 05115 ddraw7_GetDeviceIdentifier, 05116 /* IDirectDraw7 */ 05117 ddraw7_StartModeTest, 05118 ddraw7_EvaluateMode 05119 }; 05120 05121 static const struct IDirectDraw4Vtbl ddraw4_vtbl = 05122 { 05123 /* IUnknown */ 05124 ddraw4_QueryInterface, 05125 ddraw4_AddRef, 05126 ddraw4_Release, 05127 /* IDirectDraw */ 05128 ddraw4_Compact, 05129 ddraw4_CreateClipper, 05130 ddraw4_CreatePalette, 05131 ddraw4_CreateSurface, 05132 ddraw4_DuplicateSurface, 05133 ddraw4_EnumDisplayModes, 05134 ddraw4_EnumSurfaces, 05135 ddraw4_FlipToGDISurface, 05136 ddraw4_GetCaps, 05137 ddraw4_GetDisplayMode, 05138 ddraw4_GetFourCCCodes, 05139 ddraw4_GetGDISurface, 05140 ddraw4_GetMonitorFrequency, 05141 ddraw4_GetScanLine, 05142 ddraw4_GetVerticalBlankStatus, 05143 ddraw4_Initialize, 05144 ddraw4_RestoreDisplayMode, 05145 ddraw4_SetCooperativeLevel, 05146 ddraw4_SetDisplayMode, 05147 ddraw4_WaitForVerticalBlank, 05148 /* IDirectDraw2 */ 05149 ddraw4_GetAvailableVidMem, 05150 /* IDirectDraw3 */ 05151 ddraw4_GetSurfaceFromDC, 05152 /* IDirectDraw4 */ 05153 ddraw4_RestoreAllSurfaces, 05154 ddraw4_TestCooperativeLevel, 05155 ddraw4_GetDeviceIdentifier, 05156 }; 05157 05158 static const struct IDirectDraw2Vtbl ddraw2_vtbl = 05159 { 05160 /* IUnknown */ 05161 ddraw2_QueryInterface, 05162 ddraw2_AddRef, 05163 ddraw2_Release, 05164 /* IDirectDraw */ 05165 ddraw2_Compact, 05166 ddraw2_CreateClipper, 05167 ddraw2_CreatePalette, 05168 ddraw2_CreateSurface, 05169 ddraw2_DuplicateSurface, 05170 ddraw2_EnumDisplayModes, 05171 ddraw2_EnumSurfaces, 05172 ddraw2_FlipToGDISurface, 05173 ddraw2_GetCaps, 05174 ddraw2_GetDisplayMode, 05175 ddraw2_GetFourCCCodes, 05176 ddraw2_GetGDISurface, 05177 ddraw2_GetMonitorFrequency, 05178 ddraw2_GetScanLine, 05179 ddraw2_GetVerticalBlankStatus, 05180 ddraw2_Initialize, 05181 ddraw2_RestoreDisplayMode, 05182 ddraw2_SetCooperativeLevel, 05183 ddraw2_SetDisplayMode, 05184 ddraw2_WaitForVerticalBlank, 05185 /* IDirectDraw2 */ 05186 ddraw2_GetAvailableVidMem, 05187 }; 05188 05189 static const struct IDirectDrawVtbl ddraw1_vtbl = 05190 { 05191 /* IUnknown */ 05192 ddraw1_QueryInterface, 05193 ddraw1_AddRef, 05194 ddraw1_Release, 05195 /* IDirectDraw */ 05196 ddraw1_Compact, 05197 ddraw1_CreateClipper, 05198 ddraw1_CreatePalette, 05199 ddraw1_CreateSurface, 05200 ddraw1_DuplicateSurface, 05201 ddraw1_EnumDisplayModes, 05202 ddraw1_EnumSurfaces, 05203 ddraw1_FlipToGDISurface, 05204 ddraw1_GetCaps, 05205 ddraw1_GetDisplayMode, 05206 ddraw1_GetFourCCCodes, 05207 ddraw1_GetGDISurface, 05208 ddraw1_GetMonitorFrequency, 05209 ddraw1_GetScanLine, 05210 ddraw1_GetVerticalBlankStatus, 05211 ddraw1_Initialize, 05212 ddraw1_RestoreDisplayMode, 05213 ddraw1_SetCooperativeLevel, 05214 ddraw1_SetDisplayMode, 05215 ddraw1_WaitForVerticalBlank, 05216 }; 05217 05218 static const struct IDirect3D7Vtbl d3d7_vtbl = 05219 { 05220 /* IUnknown methods */ 05221 d3d7_QueryInterface, 05222 d3d7_AddRef, 05223 d3d7_Release, 05224 /* IDirect3D7 methods */ 05225 d3d7_EnumDevices, 05226 d3d7_CreateDevice, 05227 d3d7_CreateVertexBuffer, 05228 d3d7_EnumZBufferFormats, 05229 d3d7_EvictManagedTextures 05230 }; 05231 05232 static const struct IDirect3D3Vtbl d3d3_vtbl = 05233 { 05234 /* IUnknown methods */ 05235 d3d3_QueryInterface, 05236 d3d3_AddRef, 05237 d3d3_Release, 05238 /* IDirect3D3 methods */ 05239 d3d3_EnumDevices, 05240 d3d3_CreateLight, 05241 d3d3_CreateMaterial, 05242 d3d3_CreateViewport, 05243 d3d3_FindDevice, 05244 d3d3_CreateDevice, 05245 d3d3_CreateVertexBuffer, 05246 d3d3_EnumZBufferFormats, 05247 d3d3_EvictManagedTextures 05248 }; 05249 05250 static const struct IDirect3D2Vtbl d3d2_vtbl = 05251 { 05252 /* IUnknown methods */ 05253 d3d2_QueryInterface, 05254 d3d2_AddRef, 05255 d3d2_Release, 05256 /* IDirect3D2 methods */ 05257 d3d2_EnumDevices, 05258 d3d2_CreateLight, 05259 d3d2_CreateMaterial, 05260 d3d2_CreateViewport, 05261 d3d2_FindDevice, 05262 d3d2_CreateDevice 05263 }; 05264 05265 static const struct IDirect3DVtbl d3d1_vtbl = 05266 { 05267 /* IUnknown methods */ 05268 d3d1_QueryInterface, 05269 d3d1_AddRef, 05270 d3d1_Release, 05271 /* IDirect3D methods */ 05272 d3d1_Initialize, 05273 d3d1_EnumDevices, 05274 d3d1_CreateLight, 05275 d3d1_CreateMaterial, 05276 d3d1_CreateViewport, 05277 d3d1_FindDevice 05278 }; 05279 05280 /***************************************************************************** 05281 * ddraw_find_decl 05282 * 05283 * Finds the WineD3D vertex declaration for a specific fvf, and creates one 05284 * if none was found. 05285 * 05286 * This function is in ddraw.c and the DDraw object space because D3D7 05287 * vertex buffers are created using the IDirect3D interface to the ddraw 05288 * object, so they can be valid across D3D devices(theoretically. The ddraw 05289 * object also owns the wined3d device 05290 * 05291 * Parameters: 05292 * This: Device 05293 * fvf: Fvf to find the decl for 05294 * 05295 * Returns: 05296 * NULL in case of an error, the vertex declaration for the FVF otherwise. 05297 * 05298 *****************************************************************************/ 05299 struct wined3d_vertex_declaration *ddraw_find_decl(IDirectDrawImpl *This, DWORD fvf) 05300 { 05301 struct wined3d_vertex_declaration *pDecl = NULL; 05302 HRESULT hr; 05303 int p, low, high; /* deliberately signed */ 05304 struct FvfToDecl *convertedDecls = This->decls; 05305 05306 TRACE("Searching for declaration for fvf %08x... ", fvf); 05307 05308 low = 0; 05309 high = This->numConvertedDecls - 1; 05310 while(low <= high) { 05311 p = (low + high) >> 1; 05312 TRACE("%d ", p); 05313 if(convertedDecls[p].fvf == fvf) { 05314 TRACE("found %p\n", convertedDecls[p].decl); 05315 return convertedDecls[p].decl; 05316 } else if(convertedDecls[p].fvf < fvf) { 05317 low = p + 1; 05318 } else { 05319 high = p - 1; 05320 } 05321 } 05322 TRACE("not found. Creating and inserting at position %d.\n", low); 05323 05324 hr = wined3d_vertex_declaration_create_from_fvf(This->wined3d_device, 05325 fvf, This, &ddraw_null_wined3d_parent_ops, &pDecl); 05326 if (hr != S_OK) return NULL; 05327 05328 if(This->declArraySize == This->numConvertedDecls) { 05329 int grow = max(This->declArraySize / 2, 8); 05330 convertedDecls = HeapReAlloc(GetProcessHeap(), 0, convertedDecls, 05331 sizeof(convertedDecls[0]) * (This->numConvertedDecls + grow)); 05332 if (!convertedDecls) 05333 { 05334 wined3d_vertex_declaration_decref(pDecl); 05335 return NULL; 05336 } 05337 This->decls = convertedDecls; 05338 This->declArraySize += grow; 05339 } 05340 05341 memmove(convertedDecls + low + 1, convertedDecls + low, sizeof(convertedDecls[0]) * (This->numConvertedDecls - low)); 05342 convertedDecls[low].decl = pDecl; 05343 convertedDecls[low].fvf = fvf; 05344 This->numConvertedDecls++; 05345 05346 TRACE("Returning %p. %d decls in array\n", pDecl, This->numConvertedDecls); 05347 return pDecl; 05348 } 05349 05350 static inline struct IDirectDrawImpl *ddraw_from_device_parent(struct wined3d_device_parent *device_parent) 05351 { 05352 return CONTAINING_RECORD(device_parent, struct IDirectDrawImpl, device_parent); 05353 } 05354 05355 static void CDECL device_parent_wined3d_device_created(struct wined3d_device_parent *device_parent, 05356 struct wined3d_device *device) 05357 { 05358 TRACE("device_parent %p, device %p.\n", device_parent, device); 05359 } 05360 05361 static void CDECL device_parent_mode_changed(struct wined3d_device_parent *device_parent) 05362 { 05363 struct IDirectDrawImpl *ddraw = ddraw_from_device_parent(device_parent); 05364 MONITORINFO monitor_info; 05365 HMONITOR monitor; 05366 BOOL ret; 05367 RECT *r; 05368 05369 TRACE("device_parent %p.\n", device_parent); 05370 05371 if (!(ddraw->cooperative_level & DDSCL_EXCLUSIVE) || !ddraw->swapchain_window) 05372 { 05373 TRACE("Nothing to resize.\n"); 05374 return; 05375 } 05376 05377 monitor = MonitorFromWindow(ddraw->swapchain_window, MONITOR_DEFAULTTOPRIMARY); 05378 monitor_info.cbSize = sizeof(monitor_info); 05379 if (!(ret = GetMonitorInfoW(monitor, &monitor_info))) 05380 { 05381 ERR("Failed to get monitor info.\n"); 05382 return; 05383 } 05384 05385 r = &monitor_info.rcMonitor; 05386 TRACE("Resizing window %p to %s.\n", ddraw->swapchain_window, wine_dbgstr_rect(r)); 05387 05388 if (!(ret = SetWindowPos(ddraw->swapchain_window, HWND_TOP, r->left, r->top, 05389 r->right - r->left, r->bottom - r->top, SWP_SHOWWINDOW | SWP_NOACTIVATE))) 05390 ERR("Failed to resize window.\n"); 05391 } 05392 05393 static HRESULT CDECL device_parent_create_surface(struct wined3d_device_parent *device_parent, 05394 void *container_parent, UINT width, UINT height, enum wined3d_format_id format, DWORD usage, 05395 enum wined3d_pool pool, UINT level, enum wined3d_cubemap_face face, struct wined3d_surface **surface) 05396 { 05397 struct IDirectDrawImpl *ddraw = ddraw_from_device_parent(device_parent); 05398 IDirectDrawSurfaceImpl *surf = NULL; 05399 UINT i = 0; 05400 DDSCAPS2 searchcaps = ddraw->tex_root->surface_desc.ddsCaps; 05401 05402 TRACE("device_parent %p, container_parent %p, width %u, height %u, format %#x, usage %#x,\n" 05403 "\tpool %#x, level %u, face %u, surface %p.\n", 05404 device_parent, container_parent, width, height, format, usage, pool, level, face, surface); 05405 05406 searchcaps.dwCaps2 &= ~DDSCAPS2_CUBEMAP_ALLFACES; 05407 switch (face) 05408 { 05409 case WINED3D_CUBEMAP_FACE_POSITIVE_X: 05410 TRACE("Asked for positive x\n"); 05411 if (searchcaps.dwCaps2 & DDSCAPS2_CUBEMAP) 05412 { 05413 searchcaps.dwCaps2 |= DDSCAPS2_CUBEMAP_POSITIVEX; 05414 } 05415 surf = ddraw->tex_root; break; 05416 case WINED3D_CUBEMAP_FACE_NEGATIVE_X: 05417 TRACE("Asked for negative x\n"); 05418 searchcaps.dwCaps2 |= DDSCAPS2_CUBEMAP_NEGATIVEX; break; 05419 case WINED3D_CUBEMAP_FACE_POSITIVE_Y: 05420 TRACE("Asked for positive y\n"); 05421 searchcaps.dwCaps2 |= DDSCAPS2_CUBEMAP_POSITIVEY; break; 05422 case WINED3D_CUBEMAP_FACE_NEGATIVE_Y: 05423 TRACE("Asked for negative y\n"); 05424 searchcaps.dwCaps2 |= DDSCAPS2_CUBEMAP_NEGATIVEY; break; 05425 case WINED3D_CUBEMAP_FACE_POSITIVE_Z: 05426 TRACE("Asked for positive z\n"); 05427 searchcaps.dwCaps2 |= DDSCAPS2_CUBEMAP_POSITIVEZ; break; 05428 case WINED3D_CUBEMAP_FACE_NEGATIVE_Z: 05429 TRACE("Asked for negative z\n"); 05430 searchcaps.dwCaps2 |= DDSCAPS2_CUBEMAP_NEGATIVEZ; break; 05431 default: 05432 ERR("Unexpected cube face.\n"); 05433 } 05434 05435 if (!surf) 05436 { 05437 IDirectDrawSurface7 *attached; 05438 IDirectDrawSurface7_GetAttachedSurface(&ddraw->tex_root->IDirectDrawSurface7_iface, &searchcaps, &attached); 05439 surf = unsafe_impl_from_IDirectDrawSurface7(attached); 05440 IDirectDrawSurface7_Release(attached); 05441 } 05442 if (!surf) ERR("root search surface not found\n"); 05443 05444 /* Find the wanted mipmap. There are enough mipmaps in the chain */ 05445 while (i < level) 05446 { 05447 IDirectDrawSurface7 *attached; 05448 IDirectDrawSurface7_GetAttachedSurface(&surf->IDirectDrawSurface7_iface, &searchcaps, &attached); 05449 if(!attached) ERR("Surface not found\n"); 05450 surf = impl_from_IDirectDrawSurface7(attached); 05451 IDirectDrawSurface7_Release(attached); 05452 ++i; 05453 } 05454 05455 /* Return the surface */ 05456 *surface = surf->wined3d_surface; 05457 wined3d_surface_incref(*surface); 05458 05459 TRACE("Returning wineD3DSurface %p, it belongs to surface %p\n", *surface, surf); 05460 05461 return D3D_OK; 05462 } 05463 05464 static void STDMETHODCALLTYPE ddraw_frontbuffer_destroyed(void *parent) 05465 { 05466 struct IDirectDrawImpl *ddraw = parent; 05467 ddraw->wined3d_frontbuffer = NULL; 05468 } 05469 05470 static const struct wined3d_parent_ops ddraw_frontbuffer_parent_ops = 05471 { 05472 ddraw_frontbuffer_destroyed, 05473 }; 05474 05475 static HRESULT CDECL device_parent_create_rendertarget(struct wined3d_device_parent *device_parent, 05476 void *container_parent, UINT width, UINT height, enum wined3d_format_id format, 05477 enum wined3d_multisample_type multisample_type, DWORD multisample_quality, BOOL lockable, 05478 struct wined3d_surface **surface) 05479 { 05480 struct IDirectDrawImpl *ddraw = ddraw_from_device_parent(device_parent); 05481 DWORD flags = 0; 05482 HRESULT hr; 05483 05484 TRACE("device_parent %p, container_parent %p, width %u, height %u, format %#x, multisample_type %#x,\n" 05485 "\tmultisample_quality %u, lockable %u, surface %p.\n", 05486 device_parent, container_parent, width, height, format, multisample_type, 05487 multisample_quality, lockable, surface); 05488 05489 if (ddraw->wined3d_frontbuffer) 05490 { 05491 ERR("Frontbuffer already created.\n"); 05492 return E_FAIL; 05493 } 05494 05495 if (lockable) 05496 flags |= WINED3D_SURFACE_MAPPABLE; 05497 05498 hr = wined3d_surface_create(ddraw->wined3d_device, width, height, format, 0, 05499 WINED3DUSAGE_RENDERTARGET, WINED3D_POOL_DEFAULT, multisample_type, multisample_quality, 05500 DefaultSurfaceType, flags, ddraw, &ddraw_frontbuffer_parent_ops, surface); 05501 if (SUCCEEDED(hr)) 05502 ddraw->wined3d_frontbuffer = *surface; 05503 05504 return hr; 05505 } 05506 05507 static HRESULT CDECL device_parent_create_depth_stencil(struct wined3d_device_parent *device_parent, 05508 UINT width, UINT height, enum wined3d_format_id format, enum wined3d_multisample_type multisample_type, 05509 DWORD multisample_quality, BOOL discard, struct wined3d_surface **surface) 05510 { 05511 ERR("DirectDraw doesn't have and shouldn't try creating implicit depth buffers.\n"); 05512 return E_NOTIMPL; 05513 } 05514 05515 static HRESULT CDECL device_parent_create_volume(struct wined3d_device_parent *device_parent, 05516 void *container_parent, UINT width, UINT height, UINT depth, enum wined3d_format_id format, 05517 enum wined3d_pool pool, DWORD usage, struct wined3d_volume **volume) 05518 { 05519 TRACE("device_parent %p, container_parent %p, width %u, height %u, depth %u, " 05520 "format %#x, pool %#x, usage %#x, volume %p.\n", 05521 device_parent, container_parent, width, height, depth, 05522 format, pool, usage, volume); 05523 05524 ERR("Not implemented!\n"); 05525 05526 return E_NOTIMPL; 05527 } 05528 05529 static HRESULT CDECL device_parent_create_swapchain(struct wined3d_device_parent *device_parent, 05530 struct wined3d_swapchain_desc *desc, struct wined3d_swapchain **swapchain) 05531 { 05532 struct IDirectDrawImpl *ddraw = ddraw_from_device_parent(device_parent); 05533 HRESULT hr; 05534 05535 TRACE("device_parent %p, desc %p, swapchain %p.\n", device_parent, desc, swapchain); 05536 05537 if (ddraw->wined3d_swapchain) 05538 { 05539 ERR("Swapchain already created.\n"); 05540 return E_FAIL; 05541 } 05542 05543 hr = wined3d_swapchain_create(ddraw->wined3d_device, desc, 05544 DefaultSurfaceType, NULL, &ddraw_null_wined3d_parent_ops, swapchain); 05545 if (FAILED(hr)) 05546 WARN("Failed to create swapchain, hr %#x.\n", hr); 05547 05548 return hr; 05549 } 05550 05551 static const struct wined3d_device_parent_ops ddraw_wined3d_device_parent_ops = 05552 { 05553 device_parent_wined3d_device_created, 05554 device_parent_mode_changed, 05555 device_parent_create_surface, 05556 device_parent_create_rendertarget, 05557 device_parent_create_depth_stencil, 05558 device_parent_create_volume, 05559 device_parent_create_swapchain, 05560 }; 05561 05562 HRESULT ddraw_init(IDirectDrawImpl *ddraw, enum wined3d_device_type device_type) 05563 { 05564 HRESULT hr; 05565 HDC hDC; 05566 05567 ddraw->IDirectDraw7_iface.lpVtbl = &ddraw7_vtbl; 05568 ddraw->IDirectDraw_iface.lpVtbl = &ddraw1_vtbl; 05569 ddraw->IDirectDraw2_iface.lpVtbl = &ddraw2_vtbl; 05570 ddraw->IDirectDraw4_iface.lpVtbl = &ddraw4_vtbl; 05571 ddraw->IDirect3D_iface.lpVtbl = &d3d1_vtbl; 05572 ddraw->IDirect3D2_iface.lpVtbl = &d3d2_vtbl; 05573 ddraw->IDirect3D3_iface.lpVtbl = &d3d3_vtbl; 05574 ddraw->IDirect3D7_iface.lpVtbl = &d3d7_vtbl; 05575 ddraw->device_parent.ops = &ddraw_wined3d_device_parent_ops; 05576 ddraw->numIfaces = 1; 05577 ddraw->ref7 = 1; 05578 05579 /* Get the current screen settings. */ 05580 hDC = GetDC(0); 05581 ddraw->orig_bpp = GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES); 05582 ReleaseDC(0, hDC); 05583 ddraw->orig_width = GetSystemMetrics(SM_CXSCREEN); 05584 ddraw->orig_height = GetSystemMetrics(SM_CYSCREEN); 05585 05586 ddraw->wined3d = wined3d_create(7, WINED3D_LEGACY_DEPTH_BIAS, 05587 &ddraw->IDirectDraw7_iface); 05588 if (!ddraw->wined3d) 05589 { 05590 WARN("Failed to create a wined3d object.\n"); 05591 return E_OUTOFMEMORY; 05592 } 05593 05594 hr = wined3d_device_create(ddraw->wined3d, WINED3DADAPTER_DEFAULT, device_type, 05595 NULL, 0, 8, &ddraw->device_parent, &ddraw->wined3d_device); 05596 if (FAILED(hr)) 05597 { 05598 WARN("Failed to create a wined3d device, hr %#x.\n", hr); 05599 wined3d_decref(ddraw->wined3d); 05600 return hr; 05601 } 05602 05603 list_init(&ddraw->surface_list); 05604 05605 return DD_OK; 05606 } Generated on Sun May 27 2012 04:22:14 for ReactOS by
1.7.6.1
|