ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

ddraw.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.