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

surface.c
Go to the documentation of this file.
00001 /* DirectDraw Surface Implementation
00002  *
00003  * Copyright (c) 1997-2000 Marcus Meissner
00004  * Copyright (c) 1998-2000 Lionel Ulmer
00005  * Copyright (c) 2000-2001 TransGaming Technologies Inc.
00006  * Copyright (c) 2006 Stefan Dösinger
00007  * Copyright (c) 2011 Ričardas Barkauskas for CodeWeavers
00008  *
00009  * This library is free software; you can redistribute it and/or
00010  * modify it under the terms of the GNU Lesser General Public
00011  * License as published by the Free Software Foundation; either
00012  * version 2.1 of the License, or (at your option) any later version.
00013  *
00014  * This library is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017  * Lesser General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU Lesser General Public
00020  * License along with this library; if not, write to the Free Software
00021  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00022  */
00023 
00024 #include "config.h"
00025 #include "wine/port.h"
00026 
00027 #include "ddraw_private.h"
00028 
00029 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
00030 
00031 static IDirectDrawSurfaceImpl *unsafe_impl_from_IDirectDrawSurface2(IDirectDrawSurface2 *iface);
00032 static IDirectDrawSurfaceImpl *unsafe_impl_from_IDirectDrawSurface3(IDirectDrawSurface3 *iface);
00033 
00034 static inline IDirectDrawSurfaceImpl *impl_from_IDirectDrawGammaControl(IDirectDrawGammaControl *iface)
00035 {
00036     return CONTAINING_RECORD(iface, IDirectDrawSurfaceImpl, IDirectDrawGammaControl_iface);
00037 }
00038 
00039 /* This is slow, of course. Also, in case of locks, we can't prevent other
00040  * applications from drawing to the screen while we've locked the frontbuffer.
00041  * We'd like to do this in wined3d instead, but for that to work wined3d needs
00042  * to support windowless rendering first. */
00043 static HRESULT ddraw_surface_update_frontbuffer(IDirectDrawSurfaceImpl *surface, const RECT *rect, BOOL read)
00044 {
00045     HDC surface_dc, screen_dc;
00046     int x, y, w, h;
00047     HRESULT hr;
00048     BOOL ret;
00049 
00050     if (!rect)
00051     {
00052         x = 0;
00053         y = 0;
00054         w = surface->surface_desc.dwWidth;
00055         h = surface->surface_desc.dwHeight;
00056     }
00057     else
00058     {
00059         x = rect->left;
00060         y = rect->top;
00061         w = rect->right - rect->left;
00062         h = rect->bottom - rect->top;
00063     }
00064 
00065     if (w <= 0 || h <= 0)
00066         return DD_OK;
00067 
00068     if (surface->ddraw->swapchain_window)
00069     {
00070         /* Nothing to do, we control the frontbuffer, or at least the parts we
00071          * care about. */
00072         if (read)
00073             return DD_OK;
00074 
00075         return wined3d_surface_blt(surface->ddraw->wined3d_frontbuffer, rect,
00076                 surface->wined3d_surface, rect, 0, NULL, WINED3D_TEXF_POINT);
00077     }
00078 
00079     if (FAILED(hr = wined3d_surface_getdc(surface->wined3d_surface, &surface_dc)))
00080     {
00081         ERR("Failed to get surface DC, hr %#x.\n", hr);
00082         return hr;
00083     }
00084 
00085     if (!(screen_dc = GetDC(NULL)))
00086     {
00087         wined3d_surface_releasedc(surface->wined3d_surface, surface_dc);
00088         ERR("Failed to get screen DC.\n");
00089         return E_FAIL;
00090     }
00091 
00092     if (read)
00093         ret = BitBlt(surface_dc, x, y, w, h,
00094                 screen_dc, x, y, SRCCOPY);
00095     else
00096         ret = BitBlt(screen_dc, x, y, w, h,
00097                 surface_dc, x, y, SRCCOPY);
00098 
00099     ReleaseDC(NULL, screen_dc);
00100     wined3d_surface_releasedc(surface->wined3d_surface, surface_dc);
00101 
00102     if (!ret)
00103     {
00104         ERR("Failed to blit to/from screen.\n");
00105         return E_FAIL;
00106     }
00107 
00108     return DD_OK;
00109 }
00110 
00111 /*****************************************************************************
00112  * IUnknown parts follow
00113  *****************************************************************************/
00114 
00115 /*****************************************************************************
00116  * IDirectDrawSurface7::QueryInterface
00117  *
00118  * A normal QueryInterface implementation. For QueryInterface rules
00119  * see ddraw.c, IDirectDraw7::QueryInterface. This method
00120  * can Query IDirectDrawSurface interfaces in all version, IDirect3DTexture
00121  * in all versions, the IDirectDrawGammaControl interface and it can
00122  * create an IDirect3DDevice. (Uses IDirect3D7::CreateDevice)
00123  *
00124  * Params:
00125  *  riid: The interface id queried for
00126  *  obj: Address to write the pointer to
00127  *
00128  * Returns:
00129  *  S_OK on success
00130  *  E_NOINTERFACE if the requested interface wasn't found
00131  *
00132  *****************************************************************************/
00133 static HRESULT WINAPI ddraw_surface7_QueryInterface(IDirectDrawSurface7 *iface, REFIID riid, void **obj)
00134 {
00135     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
00136 
00137     TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obj);
00138 
00139     /* According to COM docs, if the QueryInterface fails, obj should be set to NULL */
00140     *obj = NULL;
00141 
00142     if(!riid)
00143         return DDERR_INVALIDPARAMS;
00144 
00145     if (IsEqualGUID(riid, &IID_IUnknown)
00146      || IsEqualGUID(riid, &IID_IDirectDrawSurface7) )
00147     {
00148         IDirectDrawSurface7_AddRef(iface);
00149         *obj = iface;
00150         TRACE("(%p) returning IDirectDrawSurface7 interface at %p\n", This, *obj);
00151         return S_OK;
00152     }
00153     else if (IsEqualGUID(riid, &IID_IDirectDrawSurface4))
00154     {
00155         IDirectDrawSurface4_AddRef(&This->IDirectDrawSurface4_iface);
00156         *obj = &This->IDirectDrawSurface4_iface;
00157         TRACE("(%p) returning IDirectDrawSurface4 interface at %p\n", This, *obj);
00158         return S_OK;
00159     }
00160     else if (IsEqualGUID(riid, &IID_IDirectDrawSurface3))
00161     {
00162         IDirectDrawSurface3_AddRef(&This->IDirectDrawSurface3_iface);
00163         *obj = &This->IDirectDrawSurface3_iface;
00164         TRACE("(%p) returning IDirectDrawSurface3 interface at %p\n", This, *obj);
00165         return S_OK;
00166     }
00167     else if (IsEqualGUID(riid, &IID_IDirectDrawSurface2))
00168     {
00169         IDirectDrawSurface2_AddRef(&This->IDirectDrawSurface2_iface);
00170         *obj = &This->IDirectDrawSurface2_iface;
00171         TRACE("(%p) returning IDirectDrawSurface2 interface at %p\n", This, *obj);
00172         return S_OK;
00173     }
00174     else if (IsEqualGUID(riid, &IID_IDirectDrawSurface))
00175     {
00176         IDirectDrawSurface_AddRef(&This->IDirectDrawSurface_iface);
00177         *obj = &This->IDirectDrawSurface_iface;
00178         TRACE("(%p) returning IDirectDrawSurface interface at %p\n", This, *obj);
00179         return S_OK;
00180     }
00181     else if( IsEqualGUID(riid, &IID_IDirectDrawGammaControl) )
00182     {
00183         IDirectDrawGammaControl_AddRef(&This->IDirectDrawGammaControl_iface);
00184         *obj = &This->IDirectDrawGammaControl_iface;
00185         TRACE("(%p) returning IDirectDrawGammaControl interface at %p\n", This, *obj);
00186         return S_OK;
00187     }
00188     else if( IsEqualGUID(riid, &IID_D3DDEVICE_WineD3D) ||
00189              IsEqualGUID(riid, &IID_IDirect3DHALDevice)||
00190              IsEqualGUID(riid, &IID_IDirect3DRGBDevice) )
00191     {
00192         IDirect3DDevice7 *d3d;
00193         IDirect3DDeviceImpl *device_impl;
00194 
00195         /* Call into IDirect3D7 for creation */
00196         IDirect3D7_CreateDevice(&This->ddraw->IDirect3D7_iface, riid, &This->IDirectDrawSurface7_iface,
00197                 &d3d);
00198 
00199         if (d3d)
00200         {
00201             device_impl = impl_from_IDirect3DDevice7(d3d);
00202             device_impl->from_surface = TRUE;
00203             *obj = &device_impl->IDirect3DDevice_iface;
00204             TRACE("(%p) Returning IDirect3DDevice interface at %p\n", This, *obj);
00205             return S_OK;
00206         }
00207 
00208         WARN("Unable to create a IDirect3DDevice instance, returning E_NOINTERFACE\n");
00209         return E_NOINTERFACE;
00210     }
00211     else if (IsEqualGUID( &IID_IDirect3DTexture, riid ) ||
00212              IsEqualGUID( &IID_IDirect3DTexture2, riid ))
00213     {
00214         if (IsEqualGUID( &IID_IDirect3DTexture, riid ))
00215         {
00216             *obj = &This->IDirect3DTexture_iface;
00217             TRACE(" returning Direct3DTexture interface at %p.\n", *obj);
00218         }
00219         else
00220         {
00221             *obj = &This->IDirect3DTexture2_iface;
00222             TRACE(" returning Direct3DTexture2 interface at %p.\n", *obj);
00223         }
00224         IUnknown_AddRef( (IUnknown *) *obj);
00225         return S_OK;
00226     }
00227 
00228     ERR("No interface\n");
00229     return E_NOINTERFACE;
00230 }
00231 
00232 static HRESULT WINAPI ddraw_surface4_QueryInterface(IDirectDrawSurface4 *iface, REFIID riid, void **object)
00233 {
00234     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
00235     TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
00236 
00237     return ddraw_surface7_QueryInterface(&This->IDirectDrawSurface7_iface, riid, object);
00238 }
00239 
00240 static HRESULT WINAPI ddraw_surface3_QueryInterface(IDirectDrawSurface3 *iface, REFIID riid, void **object)
00241 {
00242     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
00243     TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
00244 
00245     return ddraw_surface7_QueryInterface(&This->IDirectDrawSurface7_iface, riid, object);
00246 }
00247 
00248 static HRESULT WINAPI ddraw_surface2_QueryInterface(IDirectDrawSurface2 *iface, REFIID riid, void **object)
00249 {
00250     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
00251     TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
00252 
00253     return ddraw_surface7_QueryInterface(&This->IDirectDrawSurface7_iface, riid, object);
00254 }
00255 
00256 static HRESULT WINAPI ddraw_surface1_QueryInterface(IDirectDrawSurface *iface, REFIID riid, void **object)
00257 {
00258     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
00259     TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
00260 
00261     return ddraw_surface7_QueryInterface(&This->IDirectDrawSurface7_iface, riid, object);
00262 }
00263 
00264 static HRESULT WINAPI ddraw_gamma_control_QueryInterface(IDirectDrawGammaControl *iface,
00265         REFIID riid, void **object)
00266 {
00267     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawGammaControl(iface);
00268 
00269     TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
00270 
00271     return ddraw_surface7_QueryInterface(&This->IDirectDrawSurface7_iface, riid, object);
00272 }
00273 
00274 static HRESULT WINAPI d3d_texture2_QueryInterface(IDirect3DTexture2 *iface, REFIID riid, void **object)
00275 {
00276     IDirectDrawSurfaceImpl *This = impl_from_IDirect3DTexture2(iface);
00277     TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
00278 
00279     return ddraw_surface7_QueryInterface(&This->IDirectDrawSurface7_iface, riid, object);
00280 }
00281 
00282 static HRESULT WINAPI d3d_texture1_QueryInterface(IDirect3DTexture *iface, REFIID riid, void **object)
00283 {
00284     IDirectDrawSurfaceImpl *This = impl_from_IDirect3DTexture(iface);
00285     TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
00286 
00287     return ddraw_surface7_QueryInterface(&This->IDirectDrawSurface7_iface, riid, object);
00288 }
00289 
00290 static void ddraw_surface_add_iface(IDirectDrawSurfaceImpl *This)
00291 {
00292     ULONG iface_count = InterlockedIncrement(&This->iface_count);
00293     TRACE("%p increasing iface count to %u.\n", This, iface_count);
00294 
00295     if (iface_count == 1)
00296     {
00297         wined3d_mutex_lock();
00298         if (This->wined3d_surface)
00299             wined3d_surface_incref(This->wined3d_surface);
00300         if (This->wined3d_texture)
00301             wined3d_texture_incref(This->wined3d_texture);
00302         wined3d_mutex_unlock();
00303     }
00304 }
00305 
00306 /*****************************************************************************
00307  * IDirectDrawSurface7::AddRef
00308  *
00309  * A normal addref implementation
00310  *
00311  * Returns:
00312  *  The new refcount
00313  *
00314  *****************************************************************************/
00315 static ULONG WINAPI ddraw_surface7_AddRef(IDirectDrawSurface7 *iface)
00316 {
00317     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
00318     ULONG refcount = InterlockedIncrement(&This->ref7);
00319 
00320     TRACE("iface %p increasing refcount to %u.\n", iface, refcount);
00321 
00322     if (refcount == 1)
00323     {
00324         ddraw_surface_add_iface(This);
00325     }
00326 
00327     return refcount;
00328 }
00329 
00330 static ULONG WINAPI ddraw_surface4_AddRef(IDirectDrawSurface4 *iface)
00331 {
00332     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
00333     ULONG refcount = InterlockedIncrement(&This->ref4);
00334 
00335     TRACE("iface %p increasing refcount to %u.\n", iface, refcount);
00336 
00337     if (refcount == 1)
00338     {
00339         ddraw_surface_add_iface(This);
00340     }
00341 
00342     return refcount;
00343 }
00344 
00345 static ULONG WINAPI ddraw_surface3_AddRef(IDirectDrawSurface3 *iface)
00346 {
00347     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
00348     ULONG refcount = InterlockedIncrement(&This->ref3);
00349 
00350     TRACE("iface %p increasing refcount to %u.\n", iface, refcount);
00351 
00352     if (refcount == 1)
00353     {
00354         ddraw_surface_add_iface(This);
00355     }
00356 
00357     return refcount;
00358 }
00359 
00360 static ULONG WINAPI ddraw_surface2_AddRef(IDirectDrawSurface2 *iface)
00361 {
00362     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
00363     ULONG refcount = InterlockedIncrement(&This->ref2);
00364 
00365     TRACE("iface %p increasing refcount to %u.\n", iface, refcount);
00366 
00367     if (refcount == 1)
00368     {
00369         ddraw_surface_add_iface(This);
00370     }
00371 
00372     return refcount;
00373 }
00374 
00375 static ULONG WINAPI ddraw_surface1_AddRef(IDirectDrawSurface *iface)
00376 {
00377     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
00378     ULONG refcount = InterlockedIncrement(&This->ref1);
00379 
00380     TRACE("iface %p increasing refcount to %u.\n", iface, refcount);
00381 
00382     if (refcount == 1)
00383     {
00384         ddraw_surface_add_iface(This);
00385     }
00386 
00387     return refcount;
00388 }
00389 
00390 static ULONG WINAPI ddraw_gamma_control_AddRef(IDirectDrawGammaControl *iface)
00391 {
00392     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawGammaControl(iface);
00393     ULONG refcount = InterlockedIncrement(&This->gamma_count);
00394 
00395     TRACE("iface %p increasing refcount to %u.\n", iface, refcount);
00396 
00397     if (refcount == 1)
00398     {
00399         ddraw_surface_add_iface(This);
00400     }
00401 
00402     return refcount;
00403 }
00404 
00405 static ULONG WINAPI d3d_texture2_AddRef(IDirect3DTexture2 *iface)
00406 {
00407     IDirectDrawSurfaceImpl *This = impl_from_IDirect3DTexture2(iface);
00408     TRACE("iface %p.\n", iface);
00409 
00410     return ddraw_surface1_AddRef(&This->IDirectDrawSurface_iface);
00411 }
00412 
00413 static ULONG WINAPI d3d_texture1_AddRef(IDirect3DTexture *iface)
00414 {
00415     IDirectDrawSurfaceImpl *This = impl_from_IDirect3DTexture(iface);
00416     TRACE("iface %p.\n", iface);
00417 
00418     return ddraw_surface1_AddRef(&This->IDirectDrawSurface_iface);
00419 }
00420 
00421 /*****************************************************************************
00422  * ddraw_surface_destroy
00423  *
00424  * A helper function for IDirectDrawSurface7::Release
00425  *
00426  * Frees the surface, regardless of its refcount.
00427  *  See IDirectDrawSurface7::Release for more information
00428  *
00429  * Params:
00430  *  This: Surface to free
00431  *
00432  *****************************************************************************/
00433 static void ddraw_surface_destroy(IDirectDrawSurfaceImpl *This)
00434 {
00435     TRACE("surface %p.\n", This);
00436 
00437     /* Check the iface count and give a warning */
00438     if(This->iface_count > 1)
00439     {
00440         /* This can happen when a complex surface is destroyed,
00441          * because the 2nd surface was addref()ed when the app
00442          * called GetAttachedSurface
00443          */
00444         WARN("(%p): Destroying surface with refcounts 7: %d 4: %d 3: %d 2: %d 1: %d\n",
00445                 This, This->ref7, This->ref4, This->ref3, This->ref2, This->ref1);
00446     }
00447 
00448     if (This->wined3d_surface)
00449         wined3d_surface_decref(This->wined3d_surface);
00450 }
00451 
00452 static void ddraw_surface_cleanup(IDirectDrawSurfaceImpl *surface)
00453 {
00454     IDirectDrawSurfaceImpl *surf;
00455     IUnknown *ifaceToRelease;
00456     UINT i;
00457 
00458     TRACE("surface %p.\n", surface);
00459 
00460     /* The refcount test shows that the palette is detached when the surface
00461      * is destroyed. */
00462     IDirectDrawSurface7_SetPalette(&surface->IDirectDrawSurface7_iface, NULL);
00463 
00464     /* Loop through all complex attached surfaces and destroy them.
00465      *
00466      * Yet again, only the root can have more than one complexly attached
00467      * surface, all the others have a total of one. */
00468     for (i = 0; i < MAX_COMPLEX_ATTACHED; ++i)
00469     {
00470         if (!surface->complex_array[i])
00471             break;
00472 
00473         surf = surface->complex_array[i];
00474         surface->complex_array[i] = NULL;
00475         while (surf)
00476         {
00477             IDirectDrawSurfaceImpl *destroy = surf;
00478             surf = surf->complex_array[0];              /* Iterate through the "tree" */
00479             ddraw_surface_destroy(destroy);             /* Destroy it */
00480         }
00481     }
00482 
00483     ifaceToRelease = surface->ifaceToRelease;
00484 
00485     /* Destroy the root surface. */
00486     ddraw_surface_destroy(surface);
00487 
00488     /* Reduce the ddraw refcount */
00489     if (ifaceToRelease)
00490         IUnknown_Release(ifaceToRelease);
00491 }
00492 
00493 ULONG ddraw_surface_release_iface(IDirectDrawSurfaceImpl *This)
00494 {
00495     ULONG iface_count = InterlockedDecrement(&This->iface_count);
00496     TRACE("%p decreasing iface count to %u.\n", This, iface_count);
00497 
00498     if (iface_count == 0)
00499     {
00500         /* Complex attached surfaces are destroyed implicitly when the root is released */
00501         wined3d_mutex_lock();
00502         if(!This->is_complex_root)
00503         {
00504             WARN("(%p) Attempt to destroy a surface that is not a complex root\n", This);
00505             wined3d_mutex_unlock();
00506             return iface_count;
00507         }
00508         if (This->wined3d_texture) /* If it's a texture, destroy the wined3d texture. */
00509             wined3d_texture_decref(This->wined3d_texture);
00510         else
00511             ddraw_surface_cleanup(This);
00512         wined3d_mutex_unlock();
00513     }
00514 
00515     return iface_count;
00516 }
00517 
00518 /*****************************************************************************
00519  * IDirectDrawSurface7::Release
00520  *
00521  * Reduces the surface's refcount by 1. If the refcount falls to 0, the
00522  * surface is destroyed.
00523  *
00524  * Destroying the surface is a bit tricky. For the connection between
00525  * WineD3DSurfaces and DirectDrawSurfaces see IDirectDraw7::CreateSurface
00526  * It has a nice graph explaining the connection.
00527  *
00528  * What happens here is basically this:
00529  * When a surface is destroyed, its WineD3DSurface is released,
00530  * and the refcount of the DirectDraw interface is reduced by 1. If it has
00531  * complex surfaces attached to it, then these surfaces are destroyed too,
00532  * regardless of their refcount. If any surface being destroyed has another
00533  * surface attached to it (with a "soft" attachment, not complex), then
00534  * this surface is detached with DeleteAttachedSurface.
00535  *
00536  * When the surface is a texture, the WineD3DTexture is released.
00537  * If the surface is the Direct3D render target, then the D3D
00538  * capabilities of the WineD3DDevice are uninitialized, which causes the
00539  * swapchain to be released.
00540  *
00541  * When a complex sublevel falls to ref zero, then this is ignored.
00542  *
00543  * Returns:
00544  *  The new refcount
00545  *
00546  *****************************************************************************/
00547 static ULONG WINAPI ddraw_surface7_Release(IDirectDrawSurface7 *iface)
00548 {
00549     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
00550     ULONG refcount = InterlockedDecrement(&This->ref7);
00551 
00552     TRACE("iface %p decreasing refcount to %u.\n", iface, refcount);
00553 
00554     if (refcount == 0)
00555     {
00556         ddraw_surface_release_iface(This);
00557     }
00558 
00559     return refcount;
00560 }
00561 
00562 static ULONG WINAPI ddraw_surface4_Release(IDirectDrawSurface4 *iface)
00563 {
00564     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
00565     ULONG refcount = InterlockedDecrement(&This->ref4);
00566 
00567     TRACE("iface %p decreasing refcount to %u.\n", iface, refcount);
00568 
00569     if (refcount == 0)
00570     {
00571         ddraw_surface_release_iface(This);
00572     }
00573 
00574     return refcount;
00575 }
00576 
00577 static ULONG WINAPI ddraw_surface3_Release(IDirectDrawSurface3 *iface)
00578 {
00579     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
00580     ULONG refcount = InterlockedDecrement(&This->ref3);
00581 
00582     TRACE("iface %p decreasing refcount to %u.\n", iface, refcount);
00583 
00584     if (refcount == 0)
00585     {
00586         ddraw_surface_release_iface(This);
00587     }
00588 
00589     return refcount;
00590 }
00591 
00592 static ULONG WINAPI ddraw_surface2_Release(IDirectDrawSurface2 *iface)
00593 {
00594     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
00595     ULONG refcount = InterlockedDecrement(&This->ref2);
00596 
00597     TRACE("iface %p decreasing refcount to %u.\n", iface, refcount);
00598 
00599     if (refcount == 0)
00600     {
00601         ddraw_surface_release_iface(This);
00602     }
00603 
00604     return refcount;
00605 }
00606 
00607 static ULONG WINAPI ddraw_surface1_Release(IDirectDrawSurface *iface)
00608 {
00609     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
00610     ULONG refcount = InterlockedDecrement(&This->ref1);
00611 
00612     TRACE("iface %p decreasing refcount to %u.\n", iface, refcount);
00613 
00614     if (refcount == 0)
00615     {
00616         ddraw_surface_release_iface(This);
00617     }
00618 
00619     return refcount;
00620 }
00621 
00622 static ULONG WINAPI ddraw_gamma_control_Release(IDirectDrawGammaControl *iface)
00623 {
00624     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawGammaControl(iface);
00625     ULONG refcount = InterlockedDecrement(&This->gamma_count);
00626 
00627     TRACE("iface %p decreasing refcount to %u.\n", iface, refcount);
00628 
00629     if (refcount == 0)
00630     {
00631         ddraw_surface_release_iface(This);
00632     }
00633 
00634     return refcount;
00635 }
00636 
00637 static ULONG WINAPI d3d_texture2_Release(IDirect3DTexture2 *iface)
00638 {
00639     IDirectDrawSurfaceImpl *This = impl_from_IDirect3DTexture2(iface);
00640     TRACE("iface %p.\n", iface);
00641 
00642     return ddraw_surface1_Release(&This->IDirectDrawSurface_iface);
00643 }
00644 
00645 static ULONG WINAPI d3d_texture1_Release(IDirect3DTexture *iface)
00646 {
00647     IDirectDrawSurfaceImpl *This = impl_from_IDirect3DTexture(iface);
00648     TRACE("iface %p.\n", iface);
00649 
00650     return ddraw_surface1_Release(&This->IDirectDrawSurface_iface);
00651 }
00652 
00653 /*****************************************************************************
00654  * IDirectDrawSurface7::GetAttachedSurface
00655  *
00656  * Returns an attached surface with the requested caps. Surface attachment
00657  * and complex surfaces are not clearly described by the MSDN or sdk,
00658  * so this method is tricky and likely to contain problems.
00659  * This implementation searches the complex list first, then the
00660  * attachment chain.
00661  *
00662  * The chains are searched from This down to the last surface in the chain,
00663  * not from the first element in the chain. The first surface found is
00664  * returned. The MSDN says that this method fails if more than one surface
00665  * matches the caps, but it is not sure if that is right. The attachment
00666  * structure may not even allow two matching surfaces.
00667  *
00668  * The found surface is AddRef-ed before it is returned.
00669  *
00670  * Params:
00671  *  Caps: Pointer to a DDCAPS2 structure describing the caps asked for
00672  *  Surface: Address to store the found surface
00673  *
00674  * Returns:
00675  *  DD_OK on success
00676  *  DDERR_INVALIDPARAMS if Caps or Surface is NULL
00677  *  DDERR_NOTFOUND if no surface was found
00678  *
00679  *****************************************************************************/
00680 static HRESULT WINAPI ddraw_surface7_GetAttachedSurface(IDirectDrawSurface7 *iface,
00681         DDSCAPS2 *Caps, IDirectDrawSurface7 **Surface)
00682 {
00683     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
00684     IDirectDrawSurfaceImpl *surf;
00685     DDSCAPS2 our_caps;
00686     int i;
00687 
00688     TRACE("iface %p, caps %p, attachment %p.\n", iface, Caps, Surface);
00689 
00690     wined3d_mutex_lock();
00691 
00692     if(This->version < 7)
00693     {
00694         /* Earlier dx apps put garbage into these members, clear them */
00695         our_caps.dwCaps = Caps->dwCaps;
00696         our_caps.dwCaps2 = 0;
00697         our_caps.dwCaps3 = 0;
00698         our_caps.u1.dwCaps4 = 0;
00699     }
00700     else
00701     {
00702         our_caps = *Caps;
00703     }
00704 
00705     TRACE("(%p): Looking for caps: %x,%x,%x,%x\n", This, our_caps.dwCaps, our_caps.dwCaps2, our_caps.dwCaps3, our_caps.u1.dwCaps4); /* FIXME: Better debugging */
00706 
00707     for(i = 0; i < MAX_COMPLEX_ATTACHED; i++)
00708     {
00709         surf = This->complex_array[i];
00710         if(!surf) break;
00711 
00712         if (TRACE_ON(ddraw))
00713         {
00714             TRACE("Surface: (%p) caps: %x,%x,%x,%x\n", surf,
00715                    surf->surface_desc.ddsCaps.dwCaps,
00716                    surf->surface_desc.ddsCaps.dwCaps2,
00717                    surf->surface_desc.ddsCaps.dwCaps3,
00718                    surf->surface_desc.ddsCaps.u1.dwCaps4);
00719         }
00720 
00721         if (((surf->surface_desc.ddsCaps.dwCaps & our_caps.dwCaps) == our_caps.dwCaps) &&
00722             ((surf->surface_desc.ddsCaps.dwCaps2 & our_caps.dwCaps2) == our_caps.dwCaps2)) {
00723 
00724             /* MSDN: "This method fails if more than one surface is attached
00725              * that matches the capabilities requested."
00726              *
00727              * Not sure how to test this.
00728              */
00729 
00730             TRACE("(%p): Returning surface %p\n", This, surf);
00731             TRACE("(%p): mipmapcount=%d\n", This, surf->mipmap_level);
00732             *Surface = &surf->IDirectDrawSurface7_iface;
00733             ddraw_surface7_AddRef(*Surface);
00734             wined3d_mutex_unlock();
00735 
00736             return DD_OK;
00737         }
00738     }
00739 
00740     /* Next, look at the attachment chain */
00741     surf = This;
00742 
00743     while( (surf = surf->next_attached) )
00744     {
00745         if (TRACE_ON(ddraw))
00746         {
00747             TRACE("Surface: (%p) caps: %x,%x,%x,%x\n", surf,
00748                    surf->surface_desc.ddsCaps.dwCaps,
00749                    surf->surface_desc.ddsCaps.dwCaps2,
00750                    surf->surface_desc.ddsCaps.dwCaps3,
00751                    surf->surface_desc.ddsCaps.u1.dwCaps4);
00752         }
00753 
00754         if (((surf->surface_desc.ddsCaps.dwCaps & our_caps.dwCaps) == our_caps.dwCaps) &&
00755             ((surf->surface_desc.ddsCaps.dwCaps2 & our_caps.dwCaps2) == our_caps.dwCaps2)) {
00756 
00757             TRACE("(%p): Returning surface %p\n", This, surf);
00758             *Surface = &surf->IDirectDrawSurface7_iface;
00759             ddraw_surface7_AddRef(*Surface);
00760             wined3d_mutex_unlock();
00761             return DD_OK;
00762         }
00763     }
00764 
00765     TRACE("(%p) Didn't find a valid surface\n", This);
00766 
00767     wined3d_mutex_unlock();
00768 
00769     *Surface = NULL;
00770     return DDERR_NOTFOUND;
00771 }
00772 
00773 static HRESULT WINAPI ddraw_surface4_GetAttachedSurface(IDirectDrawSurface4 *iface,
00774         DDSCAPS2 *caps, IDirectDrawSurface4 **attachment)
00775 {
00776     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
00777     IDirectDrawSurface7 *attachment7;
00778     IDirectDrawSurfaceImpl *attachment_impl;
00779     HRESULT hr;
00780 
00781     TRACE("iface %p, caps %p, attachment %p.\n", iface, caps, attachment);
00782 
00783     hr = ddraw_surface7_GetAttachedSurface(&This->IDirectDrawSurface7_iface,
00784             caps, &attachment7);
00785     if (FAILED(hr))
00786     {
00787         *attachment = NULL;
00788         return hr;
00789     }
00790     attachment_impl = impl_from_IDirectDrawSurface7(attachment7);
00791     *attachment = &attachment_impl->IDirectDrawSurface4_iface;
00792     ddraw_surface4_AddRef(*attachment);
00793     ddraw_surface7_Release(attachment7);
00794 
00795     return hr;
00796 }
00797 
00798 static HRESULT WINAPI ddraw_surface3_GetAttachedSurface(IDirectDrawSurface3 *iface,
00799         DDSCAPS *caps, IDirectDrawSurface3 **attachment)
00800 {
00801     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
00802     IDirectDrawSurface7 *attachment7;
00803     IDirectDrawSurfaceImpl *attachment_impl;
00804     DDSCAPS2 caps2;
00805     HRESULT hr;
00806 
00807     TRACE("iface %p, caps %p, attachment %p.\n", iface, caps, attachment);
00808 
00809     caps2.dwCaps  = caps->dwCaps;
00810     caps2.dwCaps2 = 0;
00811     caps2.dwCaps3 = 0;
00812     caps2.u1.dwCaps4 = 0;
00813 
00814     hr = ddraw_surface7_GetAttachedSurface(&This->IDirectDrawSurface7_iface,
00815             &caps2, &attachment7);
00816     if (FAILED(hr))
00817     {
00818         *attachment = NULL;
00819         return hr;
00820     }
00821     attachment_impl = impl_from_IDirectDrawSurface7(attachment7);
00822     *attachment = &attachment_impl->IDirectDrawSurface3_iface;
00823     ddraw_surface3_AddRef(*attachment);
00824     ddraw_surface7_Release(attachment7);
00825 
00826     return hr;
00827 }
00828 
00829 static HRESULT WINAPI ddraw_surface2_GetAttachedSurface(IDirectDrawSurface2 *iface,
00830         DDSCAPS *caps, IDirectDrawSurface2 **attachment)
00831 {
00832     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
00833     IDirectDrawSurface7 *attachment7;
00834     IDirectDrawSurfaceImpl *attachment_impl;
00835     DDSCAPS2 caps2;
00836     HRESULT hr;
00837 
00838     TRACE("iface %p, caps %p, attachment %p.\n", iface, caps, attachment);
00839 
00840     caps2.dwCaps  = caps->dwCaps;
00841     caps2.dwCaps2 = 0;
00842     caps2.dwCaps3 = 0;
00843     caps2.u1.dwCaps4 = 0;
00844 
00845     hr = ddraw_surface7_GetAttachedSurface(&This->IDirectDrawSurface7_iface,
00846             &caps2, &attachment7);
00847     if (FAILED(hr))
00848     {
00849         *attachment = NULL;
00850         return hr;
00851     }
00852     attachment_impl = impl_from_IDirectDrawSurface7(attachment7);
00853     *attachment = &attachment_impl->IDirectDrawSurface2_iface;
00854     ddraw_surface2_AddRef(*attachment);
00855     ddraw_surface7_Release(attachment7);
00856 
00857     return hr;
00858 }
00859 
00860 static HRESULT WINAPI ddraw_surface1_GetAttachedSurface(IDirectDrawSurface *iface,
00861         DDSCAPS *caps, IDirectDrawSurface **attachment)
00862 {
00863     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
00864     IDirectDrawSurface7 *attachment7;
00865     IDirectDrawSurfaceImpl *attachment_impl;
00866     DDSCAPS2 caps2;
00867     HRESULT hr;
00868 
00869     TRACE("iface %p, caps %p, attachment %p.\n", iface, caps, attachment);
00870 
00871     caps2.dwCaps  = caps->dwCaps;
00872     caps2.dwCaps2 = 0;
00873     caps2.dwCaps3 = 0;
00874     caps2.u1.dwCaps4 = 0;
00875 
00876     hr = ddraw_surface7_GetAttachedSurface(&This->IDirectDrawSurface7_iface,
00877             &caps2, &attachment7);
00878     if (FAILED(hr))
00879     {
00880         *attachment = NULL;
00881         return hr;
00882     }
00883     attachment_impl = impl_from_IDirectDrawSurface7(attachment7);
00884     *attachment = &attachment_impl->IDirectDrawSurface_iface;
00885     ddraw_surface1_AddRef(*attachment);
00886     ddraw_surface7_Release(attachment7);
00887 
00888     return hr;
00889 }
00890 
00891 /*****************************************************************************
00892  * IDirectDrawSurface7::Lock
00893  *
00894  * Locks the surface and returns a pointer to the surface's memory
00895  *
00896  * Params:
00897  *  Rect: Rectangle to lock. If NULL, the whole surface is locked
00898  *  DDSD: Pointer to a DDSURFACEDESC2 which shall receive the surface's desc.
00899  *  Flags: Locking flags, e.g Read only or write only
00900  *  h: An event handle that's not used and must be NULL
00901  *
00902  * Returns:
00903  *  DD_OK on success
00904  *  DDERR_INVALIDPARAMS if DDSD is NULL
00905  *  For more details, see IWineD3DSurface::LockRect
00906  *
00907  *****************************************************************************/
00908 static HRESULT surface_lock(IDirectDrawSurfaceImpl *This,
00909         RECT *Rect, DDSURFACEDESC2 *DDSD, DWORD Flags, HANDLE h)
00910 {
00911     struct wined3d_mapped_rect mapped_rect;
00912     HRESULT hr = DD_OK;
00913 
00914     TRACE("This %p, rect %s, surface_desc %p, flags %#x, h %p.\n",
00915             This, wine_dbgstr_rect(Rect), DDSD, Flags, h);
00916 
00917     /* This->surface_desc.dwWidth and dwHeight are changeable, thus lock */
00918     wined3d_mutex_lock();
00919 
00920     /* Should I check for the handle to be NULL?
00921      *
00922      * The DDLOCK flags and the D3DLOCK flags are equal
00923      * for the supported values. The others are ignored by WineD3D
00924      */
00925 
00926     /* Windows zeroes this if the rect is invalid */
00927     DDSD->lpSurface = 0;
00928 
00929     if (Rect)
00930     {
00931         if ((Rect->left < 0)
00932                 || (Rect->top < 0)
00933                 || (Rect->left > Rect->right)
00934                 || (Rect->top > Rect->bottom)
00935                 || (Rect->right > This->surface_desc.dwWidth)
00936                 || (Rect->bottom > This->surface_desc.dwHeight))
00937         {
00938             WARN("Trying to lock an invalid rectangle, returning DDERR_INVALIDPARAMS\n");
00939             wined3d_mutex_unlock();
00940             return DDERR_INVALIDPARAMS;
00941         }
00942     }
00943 
00944     if (This->surface_desc.ddsCaps.dwCaps & DDSCAPS_FRONTBUFFER)
00945         hr = ddraw_surface_update_frontbuffer(This, Rect, TRUE);
00946     if (SUCCEEDED(hr))
00947         hr = wined3d_surface_map(This->wined3d_surface, &mapped_rect, Rect, Flags);
00948     if (FAILED(hr))
00949     {
00950         wined3d_mutex_unlock();
00951         switch(hr)
00952         {
00953             /* D3D8 and D3D9 return the general D3DERR_INVALIDCALL error, but ddraw has a more
00954              * specific error. But since IWineD3DSurface::LockRect returns that error in this
00955              * only occasion, keep d3d8 and d3d9 free from the return value override. There are
00956              * many different places where d3d8/9 would have to catch the DDERR_SURFACEBUSY, it
00957              * is much easier to do it in one place in ddraw
00958              */
00959             case WINED3DERR_INVALIDCALL:    return DDERR_SURFACEBUSY;
00960             default:                        return hr;
00961         }
00962     }
00963 
00964     if (This->surface_desc.ddsCaps.dwCaps & DDSCAPS_FRONTBUFFER)
00965     {
00966         if (Flags & DDLOCK_READONLY)
00967             memset(&This->ddraw->primary_lock, 0, sizeof(This->ddraw->primary_lock));
00968         else if (Rect)
00969             This->ddraw->primary_lock = *Rect;
00970         else
00971             SetRect(&This->ddraw->primary_lock, 0, 0, This->surface_desc.dwWidth, This->surface_desc.dwHeight);
00972     }
00973 
00974     /* Override the memory area. The pitch should be set already. Strangely windows
00975      * does not set the LPSURFACE flag on locked surfaces !?!.
00976      * DDSD->dwFlags |= DDSD_LPSURFACE;
00977      */
00978     This->surface_desc.lpSurface = mapped_rect.data;
00979     DD_STRUCT_COPY_BYSIZE(DDSD,&(This->surface_desc));
00980 
00981     TRACE("locked surface returning description :\n");
00982     if (TRACE_ON(ddraw)) DDRAW_dump_surface_desc(DDSD);
00983 
00984     wined3d_mutex_unlock();
00985 
00986     return DD_OK;
00987 }
00988 
00989 static HRESULT WINAPI ddraw_surface7_Lock(IDirectDrawSurface7 *iface,
00990         RECT *rect, DDSURFACEDESC2 *surface_desc, DWORD flags, HANDLE h)
00991 {
00992     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
00993     TRACE("iface %p, rect %s, surface_desc %p, flags %#x, h %p.\n",
00994             iface, wine_dbgstr_rect(rect), surface_desc, flags, h);
00995 
00996     if (!surface_desc) return DDERR_INVALIDPARAMS;
00997     if (surface_desc->dwSize != sizeof(DDSURFACEDESC) &&
00998             surface_desc->dwSize != sizeof(DDSURFACEDESC2))
00999     {
01000         WARN("Invalid structure size %d, returning DDERR_INVALIDPARAMS\n", surface_desc->dwSize);
01001         return DDERR_INVALIDPARAMS;
01002     }
01003     return surface_lock(This, rect, surface_desc, flags, h);
01004 }
01005 
01006 static HRESULT WINAPI ddraw_surface4_Lock(IDirectDrawSurface4 *iface, RECT *rect,
01007         DDSURFACEDESC2 *surface_desc, DWORD flags, HANDLE h)
01008 {
01009     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
01010     TRACE("iface %p, rect %s, surface_desc %p, flags %#x, h %p.\n",
01011             iface, wine_dbgstr_rect(rect), surface_desc, flags, h);
01012 
01013     if (!surface_desc) return DDERR_INVALIDPARAMS;
01014     if (surface_desc->dwSize != sizeof(DDSURFACEDESC) &&
01015             surface_desc->dwSize != sizeof(DDSURFACEDESC2))
01016     {
01017         WARN("Invalid structure size %d, returning DDERR_INVALIDPARAMS\n", surface_desc->dwSize);
01018         return DDERR_INVALIDPARAMS;
01019     }
01020     return surface_lock(This, rect, surface_desc, flags, h);
01021 }
01022 
01023 static HRESULT WINAPI ddraw_surface3_Lock(IDirectDrawSurface3 *iface, RECT *rect,
01024         DDSURFACEDESC *surface_desc, DWORD flags, HANDLE h)
01025 {
01026     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
01027     DDSURFACEDESC2 surface_desc2;
01028     HRESULT hr;
01029     TRACE("iface %p, rect %s, surface_desc %p, flags %#x, h %p.\n",
01030             iface, wine_dbgstr_rect(rect), surface_desc, flags, h);
01031 
01032     if (!surface_desc) return DDERR_INVALIDPARAMS;
01033     if (surface_desc->dwSize != sizeof(DDSURFACEDESC) &&
01034             surface_desc->dwSize != sizeof(DDSURFACEDESC2))
01035     {
01036         WARN("Invalid structure size %d, returning DDERR_INVALIDPARAMS\n", surface_desc->dwSize);
01037         return DDERR_INVALIDPARAMS;
01038     }
01039 
01040     surface_desc2.dwSize = surface_desc->dwSize;
01041     surface_desc2.dwFlags = 0;
01042     hr = surface_lock(This, rect, &surface_desc2, flags, h);
01043     DDSD2_to_DDSD(&surface_desc2, surface_desc);
01044     surface_desc->dwSize = surface_desc2.dwSize;
01045     return hr;
01046 }
01047 
01048 static HRESULT WINAPI ddraw_surface2_Lock(IDirectDrawSurface2 *iface, RECT *rect,
01049         DDSURFACEDESC *surface_desc, DWORD flags, HANDLE h)
01050 {
01051     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
01052     DDSURFACEDESC2 surface_desc2;
01053     HRESULT hr;
01054     TRACE("iface %p, rect %s, surface_desc %p, flags %#x, h %p.\n",
01055             iface, wine_dbgstr_rect(rect), surface_desc, flags, h);
01056 
01057     if (!surface_desc) return DDERR_INVALIDPARAMS;
01058     if (surface_desc->dwSize != sizeof(DDSURFACEDESC) &&
01059             surface_desc->dwSize != sizeof(DDSURFACEDESC2))
01060     {
01061         WARN("Invalid structure size %d, returning DDERR_INVALIDPARAMS\n", surface_desc->dwSize);
01062         return DDERR_INVALIDPARAMS;
01063     }
01064 
01065     surface_desc2.dwSize = surface_desc->dwSize;
01066     surface_desc2.dwFlags = 0;
01067     hr = surface_lock(This, rect, &surface_desc2, flags, h);
01068     DDSD2_to_DDSD(&surface_desc2, surface_desc);
01069     surface_desc->dwSize = surface_desc2.dwSize;
01070     return hr;
01071 }
01072 
01073 static HRESULT WINAPI ddraw_surface1_Lock(IDirectDrawSurface *iface, RECT *rect,
01074         DDSURFACEDESC *surface_desc, DWORD flags, HANDLE h)
01075 {
01076     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
01077     DDSURFACEDESC2 surface_desc2;
01078     HRESULT hr;
01079     TRACE("iface %p, rect %s, surface_desc %p, flags %#x, h %p.\n",
01080             iface, wine_dbgstr_rect(rect), surface_desc, flags, h);
01081 
01082     if (!surface_desc) return DDERR_INVALIDPARAMS;
01083     if (surface_desc->dwSize != sizeof(DDSURFACEDESC) &&
01084             surface_desc->dwSize != sizeof(DDSURFACEDESC2))
01085     {
01086         WARN("Invalid structure size %d, returning DDERR_INVALIDPARAMS\n", surface_desc->dwSize);
01087         return DDERR_INVALIDPARAMS;
01088     }
01089 
01090     surface_desc2.dwSize = surface_desc->dwSize;
01091     surface_desc2.dwFlags = 0;
01092     hr = surface_lock(This, rect, &surface_desc2, flags, h);
01093     DDSD2_to_DDSD(&surface_desc2, surface_desc);
01094     surface_desc->dwSize = surface_desc2.dwSize;
01095     return hr;
01096 }
01097 
01098 /*****************************************************************************
01099  * IDirectDrawSurface7::Unlock
01100  *
01101  * Unlocks an locked surface
01102  *
01103  * Params:
01104  *  Rect: Not used by this implementation
01105  *
01106  * Returns:
01107  *  D3D_OK on success
01108  *  For more details, see IWineD3DSurface::UnlockRect
01109  *
01110  *****************************************************************************/
01111 static HRESULT WINAPI ddraw_surface7_Unlock(IDirectDrawSurface7 *iface, RECT *pRect)
01112 {
01113     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
01114     HRESULT hr;
01115 
01116     TRACE("iface %p, rect %s.\n", iface, wine_dbgstr_rect(pRect));
01117 
01118     wined3d_mutex_lock();
01119     hr = wined3d_surface_unmap(This->wined3d_surface);
01120     if (SUCCEEDED(hr))
01121     {
01122         if (This->surface_desc.ddsCaps.dwCaps & DDSCAPS_FRONTBUFFER)
01123             hr = ddraw_surface_update_frontbuffer(This, &This->ddraw->primary_lock, FALSE);
01124         This->surface_desc.lpSurface = NULL;
01125     }
01126     wined3d_mutex_unlock();
01127 
01128     return hr;
01129 }
01130 
01131 static HRESULT WINAPI ddraw_surface4_Unlock(IDirectDrawSurface4 *iface, RECT *pRect)
01132 {
01133     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
01134     TRACE("iface %p, rect %p.\n", iface, pRect);
01135 
01136     return ddraw_surface7_Unlock(&This->IDirectDrawSurface7_iface, pRect);
01137 }
01138 
01139 static HRESULT WINAPI ddraw_surface3_Unlock(IDirectDrawSurface3 *iface, void *data)
01140 {
01141     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
01142     TRACE("iface %p, data %p.\n", iface, data);
01143 
01144     /* data might not be the LPRECT of later versions, so drop it. */
01145     return ddraw_surface7_Unlock(&This->IDirectDrawSurface7_iface, NULL);
01146 }
01147 
01148 static HRESULT WINAPI ddraw_surface2_Unlock(IDirectDrawSurface2 *iface, void *data)
01149 {
01150     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
01151     TRACE("iface %p, data %p.\n", iface, data);
01152 
01153     /* data might not be the LPRECT of later versions, so drop it. */
01154     return ddraw_surface7_Unlock(&This->IDirectDrawSurface7_iface, NULL);
01155 }
01156 
01157 static HRESULT WINAPI ddraw_surface1_Unlock(IDirectDrawSurface *iface, void *data)
01158 {
01159     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
01160     TRACE("iface %p, data %p.\n", iface, data);
01161 
01162     /* data might not be the LPRECT of later versions, so drop it. */
01163     return ddraw_surface7_Unlock(&This->IDirectDrawSurface7_iface, NULL);
01164 }
01165 
01166 /*****************************************************************************
01167  * IDirectDrawSurface7::Flip
01168  *
01169  * Flips a surface with the DDSCAPS_FLIP flag. The flip is relayed to
01170  * IWineD3DSurface::Flip. Because WineD3D doesn't handle attached surfaces,
01171  * the flip target is passed to WineD3D, even if the app didn't specify one
01172  *
01173  * Params:
01174  *  DestOverride: Specifies the surface that will become the new front
01175  *                buffer. If NULL, the current back buffer is used
01176  *  Flags: some DirectDraw flags, see include/ddraw.h
01177  *
01178  * Returns:
01179  *  DD_OK on success
01180  *  DDERR_NOTFLIPPABLE if no flip target could be found
01181  *  DDERR_INVALIDOBJECT if the surface isn't a front buffer
01182  *  For more details, see IWineD3DSurface::Flip
01183  *
01184  *****************************************************************************/
01185 static HRESULT WINAPI ddraw_surface7_Flip(IDirectDrawSurface7 *iface, IDirectDrawSurface7 *DestOverride, DWORD Flags)
01186 {
01187     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
01188     IDirectDrawSurfaceImpl *Override = unsafe_impl_from_IDirectDrawSurface7(DestOverride);
01189     IDirectDrawSurface7 *Override7;
01190     HRESULT hr;
01191 
01192     TRACE("iface %p, dst %p, flags %#x.\n", iface, DestOverride, Flags);
01193 
01194     /* Flip has to be called from a front buffer
01195      * What about overlay surfaces, AFAIK they can flip too?
01196      */
01197     if( !(This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER | DDSCAPS_OVERLAY)) )
01198         return DDERR_INVALIDOBJECT; /* Unchecked */
01199 
01200     wined3d_mutex_lock();
01201 
01202     /* WineD3D doesn't keep track of attached surface, so find the target */
01203     if(!Override)
01204     {
01205         DDSCAPS2 Caps;
01206 
01207         memset(&Caps, 0, sizeof(Caps));
01208         Caps.dwCaps |= DDSCAPS_BACKBUFFER;
01209         hr = ddraw_surface7_GetAttachedSurface(iface, &Caps, &Override7);
01210         if(hr != DD_OK)
01211         {
01212             ERR("Can't find a flip target\n");
01213             wined3d_mutex_unlock();
01214             return DDERR_NOTFLIPPABLE; /* Unchecked */
01215         }
01216         Override = impl_from_IDirectDrawSurface7(Override7);
01217 
01218         /* For the GetAttachedSurface */
01219         ddraw_surface7_Release(Override7);
01220     }
01221 
01222     hr = wined3d_surface_flip(This->wined3d_surface, Override->wined3d_surface, Flags);
01223     if (SUCCEEDED(hr) && This->surface_desc.ddsCaps.dwCaps & DDSCAPS_FRONTBUFFER)
01224         hr = ddraw_surface_update_frontbuffer(This, NULL, FALSE);
01225 
01226     wined3d_mutex_unlock();
01227 
01228     return hr;
01229 }
01230 
01231 static HRESULT WINAPI ddraw_surface4_Flip(IDirectDrawSurface4 *iface, IDirectDrawSurface4 *dst, DWORD flags)
01232 {
01233     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
01234     IDirectDrawSurfaceImpl *dst_impl = unsafe_impl_from_IDirectDrawSurface4(dst);
01235     TRACE("iface %p, dst %p, flags %#x.\n", iface, dst, flags);
01236 
01237     return ddraw_surface7_Flip(&This->IDirectDrawSurface7_iface,
01238             dst_impl ? &dst_impl->IDirectDrawSurface7_iface : NULL, flags);
01239 }
01240 
01241 static HRESULT WINAPI ddraw_surface3_Flip(IDirectDrawSurface3 *iface, IDirectDrawSurface3 *dst, DWORD flags)
01242 {
01243     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
01244     IDirectDrawSurfaceImpl *dst_impl = unsafe_impl_from_IDirectDrawSurface3(dst);
01245     TRACE("iface %p, dst %p, flags %#x.\n", iface, dst, flags);
01246 
01247     return ddraw_surface7_Flip(&This->IDirectDrawSurface7_iface,
01248             dst_impl ? &dst_impl->IDirectDrawSurface7_iface : NULL, flags);
01249 }
01250 
01251 static HRESULT WINAPI ddraw_surface2_Flip(IDirectDrawSurface2 *iface, IDirectDrawSurface2 *dst, DWORD flags)
01252 {
01253     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
01254     IDirectDrawSurfaceImpl *dst_impl = unsafe_impl_from_IDirectDrawSurface2(dst);
01255     TRACE("iface %p, dst %p, flags %#x.\n", iface, dst, flags);
01256 
01257     return ddraw_surface7_Flip(&This->IDirectDrawSurface7_iface,
01258             dst_impl ? &dst_impl->IDirectDrawSurface7_iface : NULL, flags);
01259 }
01260 
01261 static HRESULT WINAPI ddraw_surface1_Flip(IDirectDrawSurface *iface, IDirectDrawSurface *dst, DWORD flags)
01262 {
01263     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
01264     IDirectDrawSurfaceImpl *dst_impl = unsafe_impl_from_IDirectDrawSurface(dst);
01265     TRACE("iface %p, dst %p, flags %#x.\n", iface, dst, flags);
01266 
01267     return ddraw_surface7_Flip(&This->IDirectDrawSurface7_iface,
01268             dst_impl ? &dst_impl->IDirectDrawSurface7_iface : NULL, flags);
01269 }
01270 
01271 static HRESULT ddraw_surface_blt_clipped(IDirectDrawSurfaceImpl *dst_surface, const RECT *dst_rect_in,
01272         IDirectDrawSurfaceImpl *src_surface, const RECT *src_rect_in, DWORD flags,
01273         const WINEDDBLTFX *fx, enum wined3d_texture_filter_type filter)
01274 {
01275     struct wined3d_surface *wined3d_src_surface = src_surface ? src_surface->wined3d_surface : NULL;
01276     RECT src_rect, dst_rect;
01277     float scale_x, scale_y;
01278     const RECT *clip_rect;
01279     UINT clip_list_size;
01280     RGNDATA *clip_list;
01281     HRESULT hr = DD_OK;
01282     UINT i;
01283 
01284     if (!dst_surface->clipper)
01285     {
01286         if (src_surface && src_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_FRONTBUFFER)
01287             hr = ddraw_surface_update_frontbuffer(src_surface, src_rect_in, TRUE);
01288         if (SUCCEEDED(hr))
01289             hr = wined3d_surface_blt(dst_surface->wined3d_surface, dst_rect_in,
01290                     wined3d_src_surface, src_rect_in, flags, fx, filter);
01291         if (SUCCEEDED(hr) && (dst_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_FRONTBUFFER))
01292             hr = ddraw_surface_update_frontbuffer(dst_surface, dst_rect_in, FALSE);
01293 
01294         return hr;
01295     }
01296 
01297     if (!dst_rect_in)
01298     {
01299         dst_rect.left = 0;
01300         dst_rect.top = 0;
01301         dst_rect.right = dst_surface->surface_desc.dwWidth;
01302         dst_rect.bottom = dst_surface->surface_desc.dwHeight;
01303     }
01304     else
01305     {
01306         dst_rect = *dst_rect_in;
01307     }
01308 
01309     if (IsRectEmpty(&dst_rect))
01310         return DDERR_INVALIDRECT;
01311 
01312     if (src_surface)
01313     {
01314         if (!src_rect_in)
01315         {
01316             src_rect.left = 0;
01317             src_rect.top = 0;
01318             src_rect.right = src_surface->surface_desc.dwWidth;
01319             src_rect.bottom = src_surface->surface_desc.dwHeight;
01320         }
01321         else
01322         {
01323             src_rect = *src_rect_in;
01324         }
01325 
01326         if (IsRectEmpty(&src_rect))
01327             return DDERR_INVALIDRECT;
01328     }
01329     else
01330     {
01331         SetRect(&src_rect, 0, 0, 0, 0);
01332     }
01333 
01334     scale_x = (float)(src_rect.right - src_rect.left) / (float)(dst_rect.right - dst_rect.left);
01335     scale_y = (float)(src_rect.bottom - src_rect.top) / (float)(dst_rect.bottom - dst_rect.top);
01336 
01337     if (FAILED(hr = IDirectDrawClipper_GetClipList(&dst_surface->clipper->IDirectDrawClipper_iface,
01338             &dst_rect, NULL, &clip_list_size)))
01339     {
01340         WARN("Failed to get clip list size, hr %#x.\n", hr);
01341         return hr;
01342     }
01343 
01344     if (!(clip_list = HeapAlloc(GetProcessHeap(), 0, clip_list_size)))
01345     {
01346         WARN("Failed to allocate clip list.\n");
01347         return E_OUTOFMEMORY;
01348     }
01349 
01350     if (FAILED(hr = IDirectDrawClipper_GetClipList(&dst_surface->clipper->IDirectDrawClipper_iface,
01351             &dst_rect, clip_list, &clip_list_size)))
01352     {
01353         WARN("Failed to get clip list, hr %#x.\n", hr);
01354         HeapFree(GetProcessHeap(), 0, clip_list);
01355         return hr;
01356     }
01357 
01358     clip_rect = (RECT *)clip_list->Buffer;
01359     for (i = 0; i < clip_list->rdh.nCount; ++i)
01360     {
01361         RECT src_rect_clipped = src_rect;
01362 
01363         if (src_surface)
01364         {
01365             src_rect_clipped.left += (LONG)((clip_rect[i].left - dst_rect.left) * scale_x);
01366             src_rect_clipped.top += (LONG)((clip_rect[i].top - dst_rect.top) * scale_y);
01367             src_rect_clipped.right -= (LONG)((dst_rect.right - clip_rect[i].right) * scale_x);
01368             src_rect_clipped.bottom -= (LONG)((dst_rect.bottom - clip_rect[i].bottom) * scale_y);
01369 
01370             if (src_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_FRONTBUFFER)
01371             {
01372                 if (FAILED(hr = ddraw_surface_update_frontbuffer(src_surface, &src_rect_clipped, TRUE)))
01373                     break;
01374             }
01375         }
01376 
01377         if (FAILED(hr = wined3d_surface_blt(dst_surface->wined3d_surface, &clip_rect[i],
01378                 wined3d_src_surface, &src_rect_clipped, flags, fx, filter)))
01379             break;
01380 
01381         if (dst_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_FRONTBUFFER)
01382         {
01383             if (FAILED(hr = ddraw_surface_update_frontbuffer(dst_surface, &clip_rect[i], FALSE)))
01384                 break;
01385         }
01386     }
01387 
01388     HeapFree(GetProcessHeap(), 0, clip_list);
01389     return hr;
01390 }
01391 
01392 /*****************************************************************************
01393  * IDirectDrawSurface7::Blt
01394  *
01395  * Performs a blit on the surface
01396  *
01397  * Params:
01398  *  DestRect: Destination rectangle, can be NULL
01399  *  SrcSurface: Source surface, can be NULL
01400  *  SrcRect: Source rectangle, can be NULL
01401  *  Flags: Blt flags
01402  *  DDBltFx: Some extended blt parameters, connected to the flags
01403  *
01404  * Returns:
01405  *  D3D_OK on success
01406  *  See IWineD3DSurface::Blt for more details
01407  *
01408  *****************************************************************************/
01409 static HRESULT WINAPI ddraw_surface7_Blt(IDirectDrawSurface7 *iface, RECT *DestRect,
01410         IDirectDrawSurface7 *SrcSurface, RECT *SrcRect, DWORD Flags, DDBLTFX *DDBltFx)
01411 {
01412     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
01413     IDirectDrawSurfaceImpl *Src = unsafe_impl_from_IDirectDrawSurface7(SrcSurface);
01414     HRESULT hr = DD_OK;
01415 
01416     TRACE("iface %p, dst_rect %s, src_surface %p, src_rect %s, flags %#x, fx %p.\n",
01417             iface, wine_dbgstr_rect(DestRect), SrcSurface, wine_dbgstr_rect(SrcRect), Flags, DDBltFx);
01418 
01419     /* Check for validity of the flags here. WineD3D Has the software-opengl selection path and would have
01420      * to check at 2 places, and sometimes do double checks. This also saves the call to wined3d :-)
01421      */
01422     if((Flags & DDBLT_KEYSRCOVERRIDE) && (!DDBltFx || Flags & DDBLT_KEYSRC)) {
01423         WARN("Invalid source color key parameters, returning DDERR_INVALIDPARAMS\n");
01424         return DDERR_INVALIDPARAMS;
01425     }
01426 
01427     if((Flags & DDBLT_KEYDESTOVERRIDE) && (!DDBltFx || Flags & DDBLT_KEYDEST)) {
01428         WARN("Invalid destination color key parameters, returning DDERR_INVALIDPARAMS\n");
01429         return DDERR_INVALIDPARAMS;
01430     }
01431 
01432     wined3d_mutex_lock();
01433 
01434     if(Flags & DDBLT_KEYSRC && (!Src || !(Src->surface_desc.dwFlags & DDSD_CKSRCBLT))) {
01435         WARN("DDBLT_KEYDEST blit without color key in surface, returning DDERR_INVALIDPARAMS\n");
01436         wined3d_mutex_unlock();
01437         return DDERR_INVALIDPARAMS;
01438     }
01439 
01440     /* TODO: Check if the DDBltFx contains any ddraw surface pointers. If it
01441      * does, copy the struct, and replace the ddraw surfaces with the wined3d
01442      * surfaces. So far no blitting operations using surfaces in the bltfx
01443      * struct are supported anyway. */
01444     hr = ddraw_surface_blt_clipped(This, DestRect, Src, SrcRect,
01445             Flags, (WINEDDBLTFX *)DDBltFx, WINED3D_TEXF_LINEAR);
01446 
01447     wined3d_mutex_unlock();
01448     switch(hr)
01449     {
01450         case WINED3DERR_NOTAVAILABLE:       return DDERR_UNSUPPORTED;
01451         case WINED3DERR_WRONGTEXTUREFORMAT: return DDERR_INVALIDPIXELFORMAT;
01452         default:                            return hr;
01453     }
01454 }
01455 
01456 static HRESULT WINAPI ddraw_surface4_Blt(IDirectDrawSurface4 *iface, RECT *dst_rect,
01457         IDirectDrawSurface4 *src_surface, RECT *src_rect, DWORD flags, DDBLTFX *fx)
01458 {
01459     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
01460     IDirectDrawSurfaceImpl *src = unsafe_impl_from_IDirectDrawSurface4(src_surface);
01461     TRACE("iface %p, dst_rect %s, src_surface %p, src_rect %s, flags %#x, fx %p.\n",
01462             iface, wine_dbgstr_rect(dst_rect), src_surface, wine_dbgstr_rect(src_rect), flags, fx);
01463 
01464     return ddraw_surface7_Blt(&This->IDirectDrawSurface7_iface, dst_rect,
01465             src ? &src->IDirectDrawSurface7_iface : NULL, src_rect, flags, fx);
01466 }
01467 
01468 static HRESULT WINAPI ddraw_surface3_Blt(IDirectDrawSurface3 *iface, RECT *dst_rect,
01469         IDirectDrawSurface3 *src_surface, RECT *src_rect, DWORD flags, DDBLTFX *fx)
01470 {
01471     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
01472     IDirectDrawSurfaceImpl *src_impl = unsafe_impl_from_IDirectDrawSurface3(src_surface);
01473     TRACE("iface %p, dst_rect %s, src_surface %p, src_rect %s, flags %#x, fx %p.\n",
01474             iface, wine_dbgstr_rect(dst_rect), src_surface, wine_dbgstr_rect(src_rect), flags, fx);
01475 
01476     return ddraw_surface7_Blt(&This->IDirectDrawSurface7_iface, dst_rect,
01477             src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, src_rect, flags, fx);
01478 }
01479 
01480 static HRESULT WINAPI ddraw_surface2_Blt(IDirectDrawSurface2 *iface, RECT *dst_rect,
01481         IDirectDrawSurface2 *src_surface, RECT *src_rect, DWORD flags, DDBLTFX *fx)
01482 {
01483     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
01484     IDirectDrawSurfaceImpl *src_impl = unsafe_impl_from_IDirectDrawSurface2(src_surface);
01485     TRACE("iface %p, dst_rect %s, src_surface %p, src_rect %s, flags %#x, fx %p.\n",
01486             iface, wine_dbgstr_rect(dst_rect), src_surface, wine_dbgstr_rect(src_rect), flags, fx);
01487 
01488     return ddraw_surface7_Blt(&This->IDirectDrawSurface7_iface, dst_rect,
01489             src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, src_rect, flags, fx);
01490 }
01491 
01492 static HRESULT WINAPI ddraw_surface1_Blt(IDirectDrawSurface *iface, RECT *dst_rect,
01493         IDirectDrawSurface *src_surface, RECT *src_rect, DWORD flags, DDBLTFX *fx)
01494 {
01495     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
01496     IDirectDrawSurfaceImpl *src_impl = unsafe_impl_from_IDirectDrawSurface(src_surface);
01497     TRACE("iface %p, dst_rect %s, src_surface %p, src_rect %s, flags %#x, fx %p.\n",
01498             iface, wine_dbgstr_rect(dst_rect), src_surface, wine_dbgstr_rect(src_rect), flags, fx);
01499 
01500     return ddraw_surface7_Blt(&This->IDirectDrawSurface7_iface, dst_rect,
01501             src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, src_rect, flags, fx);
01502 }
01503 
01504 /*****************************************************************************
01505  * IDirectDrawSurface7::AddAttachedSurface
01506  *
01507  * Attaches a surface to another surface. How the surface attachments work
01508  * is not totally understood yet, and this method is prone to problems.
01509  * The surface that is attached is AddRef-ed.
01510  *
01511  * Tests with complex surfaces suggest that the surface attachments form a
01512  * tree, but no method to test this has been found yet.
01513  *
01514  * The attachment list consists of a first surface (first_attached) and
01515  * for each surface a pointer to the next attached surface (next_attached).
01516  * For the first surface, and a surface that has no attachments
01517  * first_attached points to the surface itself. A surface that has
01518  * no successors in the chain has next_attached set to NULL.
01519  *
01520  * Newly attached surfaces are attached right after the root surface.
01521  * If a surface is attached to a complex surface compound, it's attached to
01522  * the surface that the app requested, not the complex root. See
01523  * GetAttachedSurface for a description how surfaces are found.
01524  *
01525  * This is how the current implementation works, and it was coded by looking
01526  * at the needs of the applications.
01527  *
01528  * So far only Z-Buffer attachments are tested, and they are activated in
01529  * WineD3D. Mipmaps could be tricky to activate in WineD3D.
01530  * Back buffers should work in 2D mode, but they are not tested(They can be
01531  * attached in older iface versions). Rendering to the front buffer and
01532  * switching between that and double buffering is not yet implemented in
01533  * WineD3D, so for 3D it might have unexpected results.
01534  *
01535  * ddraw_surface_attach_surface is the real thing,
01536  * ddraw_surface7_AddAttachedSurface is a wrapper around it that
01537  * performs additional checks. Version 7 of this interface is much more restrictive
01538  * than its predecessors.
01539  *
01540  * Params:
01541  *  Attach: Surface to attach to iface
01542  *
01543  * Returns:
01544  *  DD_OK on success
01545  *  DDERR_CANNOTATTACHSURFACE if the surface can't be attached for some reason
01546  *
01547  *****************************************************************************/
01548 static HRESULT ddraw_surface_attach_surface(IDirectDrawSurfaceImpl *This, IDirectDrawSurfaceImpl *Surf)
01549 {
01550     TRACE("surface %p, attachment %p.\n", This, Surf);
01551 
01552     if(Surf == This)
01553         return DDERR_CANNOTATTACHSURFACE; /* unchecked */
01554 
01555     wined3d_mutex_lock();
01556 
01557     /* Check if the surface is already attached somewhere */
01558     if (Surf->next_attached || Surf->first_attached != Surf)
01559     {
01560         /* TODO: Test for the structure of the manual attachment. Is it a
01561          * chain or a list? What happens if one surface is attached to 2
01562          * different surfaces? */
01563         WARN("Surface %p is already attached somewhere. next_attached %p, first_attached %p.\n",
01564                 Surf, Surf->next_attached, Surf->first_attached);
01565 
01566         wined3d_mutex_unlock();
01567         return DDERR_SURFACEALREADYATTACHED;
01568     }
01569 
01570     /* This inserts the new surface at the 2nd position in the chain, right after the root surface */
01571     Surf->next_attached = This->next_attached;
01572     Surf->first_attached = This->first_attached;
01573     This->next_attached = Surf;
01574 
01575     /* Check if the WineD3D depth stencil needs updating */
01576     if(This->ddraw->d3ddevice)
01577     {
01578         IDirect3DDeviceImpl_UpdateDepthStencil(This->ddraw->d3ddevice);
01579     }
01580 
01581     wined3d_mutex_unlock();
01582 
01583     return DD_OK;
01584 }
01585 
01586 static HRESULT WINAPI ddraw_surface7_AddAttachedSurface(IDirectDrawSurface7 *iface, IDirectDrawSurface7 *attachment)
01587 {
01588     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
01589     IDirectDrawSurfaceImpl *attachment_impl = unsafe_impl_from_IDirectDrawSurface7(attachment);
01590     HRESULT hr;
01591 
01592     TRACE("iface %p, attachment %p.\n", iface, attachment);
01593 
01594     /* Version 7 of this interface seems to refuse everything except z buffers, as per msdn */
01595     if(!(attachment_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER))
01596     {
01597 
01598         WARN("Application tries to attach a non Z buffer surface. caps %08x\n",
01599               attachment_impl->surface_desc.ddsCaps.dwCaps);
01600         return DDERR_CANNOTATTACHSURFACE;
01601     }
01602 
01603     hr = ddraw_surface_attach_surface(This, attachment_impl);
01604     if (FAILED(hr))
01605     {
01606         return hr;
01607     }
01608     ddraw_surface7_AddRef(attachment);
01609     attachment_impl->attached_iface = (IUnknown *)attachment;
01610     return hr;
01611 }
01612 
01613 static HRESULT WINAPI ddraw_surface4_AddAttachedSurface(IDirectDrawSurface4 *iface, IDirectDrawSurface4 *attachment)
01614 {
01615     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
01616     IDirectDrawSurfaceImpl *attachment_impl = unsafe_impl_from_IDirectDrawSurface4(attachment);
01617     HRESULT hr;
01618 
01619     TRACE("iface %p, attachment %p.\n", iface, attachment);
01620 
01621     hr = ddraw_surface7_AddAttachedSurface(&This->IDirectDrawSurface7_iface,
01622             attachment_impl ? &attachment_impl->IDirectDrawSurface7_iface : NULL);
01623     if (FAILED(hr))
01624     {
01625         return hr;
01626     }
01627     ddraw_surface4_AddRef(attachment);
01628     ddraw_surface7_Release(&attachment_impl->IDirectDrawSurface7_iface);
01629     attachment_impl->attached_iface = (IUnknown *)attachment;
01630     return hr;
01631 }
01632 static HRESULT WINAPI ddraw_surface3_AddAttachedSurface(IDirectDrawSurface3 *iface, IDirectDrawSurface3 *attachment)
01633 {
01634     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
01635     IDirectDrawSurfaceImpl *attachment_impl = unsafe_impl_from_IDirectDrawSurface3(attachment);
01636     HRESULT hr;
01637 
01638     TRACE("iface %p, attachment %p.\n", iface, attachment);
01639 
01640     /* Tests suggest that
01641      * -> offscreen plain surfaces can be attached to other offscreen plain surfaces
01642      * -> offscreen plain surfaces can be attached to primaries
01643      * -> primaries can be attached to offscreen plain surfaces
01644      * -> z buffers can be attached to primaries */
01645     if (This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_PRIMARYSURFACE | DDSCAPS_OFFSCREENPLAIN)
01646             && attachment_impl->surface_desc.ddsCaps.dwCaps & (DDSCAPS_PRIMARYSURFACE | DDSCAPS_OFFSCREENPLAIN))
01647     {
01648         /* Sizes have to match */
01649         if (attachment_impl->surface_desc.dwWidth != This->surface_desc.dwWidth
01650                 || attachment_impl->surface_desc.dwHeight != This->surface_desc.dwHeight)
01651         {
01652             WARN("Surface sizes do not match.\n");
01653             return DDERR_CANNOTATTACHSURFACE;
01654         }
01655         /* OK */
01656     }
01657     else if (This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_PRIMARYSURFACE | DDSCAPS_3DDEVICE)
01658             && attachment_impl->surface_desc.ddsCaps.dwCaps & (DDSCAPS_ZBUFFER))
01659     {
01660         /* OK */
01661     }
01662     else
01663     {
01664         WARN("Invalid attachment combination.\n");
01665         return DDERR_CANNOTATTACHSURFACE;
01666     }
01667 
01668     hr = ddraw_surface_attach_surface(This, attachment_impl);
01669     if (FAILED(hr))
01670     {
01671         return hr;
01672     }
01673     ddraw_surface3_AddRef(attachment);
01674     attachment_impl->attached_iface = (IUnknown *)attachment;
01675     return hr;
01676 }
01677 
01678 static HRESULT WINAPI ddraw_surface2_AddAttachedSurface(IDirectDrawSurface2 *iface, IDirectDrawSurface2 *attachment)
01679 {
01680     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
01681     IDirectDrawSurfaceImpl *attachment_impl = unsafe_impl_from_IDirectDrawSurface2(attachment);
01682     HRESULT hr;
01683 
01684     TRACE("iface %p, attachment %p.\n", iface, attachment);
01685 
01686     hr = ddraw_surface3_AddAttachedSurface(&This->IDirectDrawSurface3_iface,
01687             attachment_impl ? &attachment_impl->IDirectDrawSurface3_iface : NULL);
01688     if (FAILED(hr))
01689     {
01690         return hr;
01691     }
01692     ddraw_surface2_AddRef(attachment);
01693     ddraw_surface3_Release(&attachment_impl->IDirectDrawSurface3_iface);
01694     attachment_impl->attached_iface = (IUnknown *)attachment;
01695     return hr;
01696 }
01697 
01698 static HRESULT WINAPI ddraw_surface1_AddAttachedSurface(IDirectDrawSurface *iface, IDirectDrawSurface *attachment)
01699 {
01700     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
01701     IDirectDrawSurfaceImpl *attachment_impl = unsafe_impl_from_IDirectDrawSurface(attachment);
01702     HRESULT hr;
01703 
01704     TRACE("iface %p, attachment %p.\n", iface, attachment);
01705 
01706     hr = ddraw_surface3_AddAttachedSurface(&This->IDirectDrawSurface3_iface,
01707             attachment_impl ? &attachment_impl->IDirectDrawSurface3_iface : NULL);
01708     if (FAILED(hr))
01709     {
01710         return hr;
01711     }
01712     ddraw_surface1_AddRef(attachment);
01713     ddraw_surface3_Release(&attachment_impl->IDirectDrawSurface3_iface);
01714     attachment_impl->attached_iface = (IUnknown *)attachment;
01715     return hr;
01716 }
01717 
01718 /*****************************************************************************
01719  * IDirectDrawSurface7::DeleteAttachedSurface
01720  *
01721  * Removes a surface from the attachment chain. The surface's refcount
01722  * is decreased by one after it has been removed
01723  *
01724  * Params:
01725  *  Flags: Some flags, not used by this implementation
01726  *  Attach: Surface to detach
01727  *
01728  * Returns:
01729  *  DD_OK on success
01730  *  DDERR_SURFACENOTATTACHED if the surface isn't attached to
01731  *
01732  *****************************************************************************/
01733 static HRESULT ddraw_surface_delete_attached_surface(IDirectDrawSurfaceImpl *This,
01734         IDirectDrawSurfaceImpl *Surf, IUnknown *detach_iface)
01735 {
01736     IDirectDrawSurfaceImpl *Prev = This;
01737 
01738     TRACE("surface %p, attachment %p, detach_iface %p.\n", This, Surf, detach_iface);
01739 
01740     wined3d_mutex_lock();
01741     if (!Surf || (Surf->first_attached != This) || (Surf == This) )
01742     {
01743         wined3d_mutex_unlock();
01744         return DDERR_CANNOTDETACHSURFACE;
01745     }
01746 
01747     if (Surf->attached_iface != detach_iface)
01748     {
01749         WARN("Surf->attach_iface %p != detach_iface %p.\n", Surf->attached_iface, detach_iface);
01750         wined3d_mutex_unlock();
01751         return DDERR_SURFACENOTATTACHED;
01752     }
01753 
01754     /* Remove MIPMAPSUBLEVEL if this seemed to be one */
01755     if (This->surface_desc.ddsCaps.dwCaps &
01756         Surf->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP)
01757     {
01758         Surf->surface_desc.ddsCaps.dwCaps2 &= ~DDSCAPS2_MIPMAPSUBLEVEL;
01759         /* FIXME: we should probably also subtract from dwMipMapCount of this
01760          * and all parent surfaces */
01761     }
01762 
01763     /* Find the predecessor of the detached surface */
01764     while(Prev)
01765     {
01766         if(Prev->next_attached == Surf) break;
01767         Prev = Prev->next_attached;
01768     }
01769 
01770     /* There must be a surface, otherwise there's a bug */
01771     assert(Prev != NULL);
01772 
01773     /* Unchain the surface */
01774     Prev->next_attached = Surf->next_attached;
01775     Surf->next_attached = NULL;
01776     Surf->first_attached = Surf;
01777 
01778     /* Check if the WineD3D depth stencil needs updating */
01779     if(This->ddraw->d3ddevice)
01780     {
01781         IDirect3DDeviceImpl_UpdateDepthStencil(This->ddraw->d3ddevice);
01782     }
01783     wined3d_mutex_unlock();
01784 
01785     /* Set attached_iface to NULL before releasing it, the surface may go
01786      * away. */
01787     Surf->attached_iface = NULL;
01788     IUnknown_Release(detach_iface);
01789 
01790     return DD_OK;
01791 }
01792 
01793 static HRESULT WINAPI ddraw_surface7_DeleteAttachedSurface(IDirectDrawSurface7 *iface,
01794         DWORD flags, IDirectDrawSurface7 *attachment)
01795 {
01796     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
01797     IDirectDrawSurfaceImpl *attachment_impl = unsafe_impl_from_IDirectDrawSurface7(attachment);
01798 
01799     TRACE("iface %p, flags %#x, attachment %p.\n", iface, flags, attachment);
01800 
01801     return ddraw_surface_delete_attached_surface(This, attachment_impl, (IUnknown *)attachment);
01802 }
01803 
01804 static HRESULT WINAPI ddraw_surface4_DeleteAttachedSurface(IDirectDrawSurface4 *iface,
01805         DWORD flags, IDirectDrawSurface4 *attachment)
01806 {
01807     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
01808     IDirectDrawSurfaceImpl *attachment_impl = unsafe_impl_from_IDirectDrawSurface4(attachment);
01809 
01810     TRACE("iface %p, flags %#x, attachment %p.\n", iface, flags, attachment);
01811 
01812     return ddraw_surface_delete_attached_surface(This, attachment_impl, (IUnknown *)attachment);
01813 }
01814 
01815 static HRESULT WINAPI ddraw_surface3_DeleteAttachedSurface(IDirectDrawSurface3 *iface,
01816         DWORD flags, IDirectDrawSurface3 *attachment)
01817 {
01818     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
01819     IDirectDrawSurfaceImpl *attachment_impl = unsafe_impl_from_IDirectDrawSurface3(attachment);
01820 
01821     TRACE("iface %p, flags %#x, attachment %p.\n", iface, flags, attachment);
01822 
01823     return ddraw_surface_delete_attached_surface(This, attachment_impl, (IUnknown *)attachment);
01824 }
01825 
01826 static HRESULT WINAPI ddraw_surface2_DeleteAttachedSurface(IDirectDrawSurface2 *iface,
01827         DWORD flags, IDirectDrawSurface2 *attachment)
01828 {
01829     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
01830     IDirectDrawSurfaceImpl *attachment_impl = unsafe_impl_from_IDirectDrawSurface2(attachment);
01831 
01832     TRACE("iface %p, flags %#x, attachment %p.\n", iface, flags, attachment);
01833 
01834     return ddraw_surface_delete_attached_surface(This, attachment_impl, (IUnknown *)attachment);
01835 }
01836 
01837 static HRESULT WINAPI ddraw_surface1_DeleteAttachedSurface(IDirectDrawSurface *iface,
01838         DWORD flags, IDirectDrawSurface *attachment)
01839 {
01840     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
01841     IDirectDrawSurfaceImpl *attachment_impl = unsafe_impl_from_IDirectDrawSurface(attachment);
01842 
01843     TRACE("iface %p, flags %#x, attachment %p.\n", iface, flags, attachment);
01844 
01845     return ddraw_surface_delete_attached_surface(This, attachment_impl, (IUnknown *)attachment);
01846 }
01847 
01848 /*****************************************************************************
01849  * IDirectDrawSurface7::AddOverlayDirtyRect
01850  *
01851  * "This method is not currently implemented"
01852  *
01853  * Params:
01854  *  Rect: ?
01855  *
01856  * Returns:
01857  *  DDERR_UNSUPPORTED
01858  *
01859  *****************************************************************************/
01860 static HRESULT WINAPI ddraw_surface7_AddOverlayDirtyRect(IDirectDrawSurface7 *iface, RECT *Rect)
01861 {
01862     TRACE("iface %p, rect %s.\n", iface, wine_dbgstr_rect(Rect));
01863 
01864     return DDERR_UNSUPPORTED; /* unchecked */
01865 }
01866 
01867 static HRESULT WINAPI ddraw_surface4_AddOverlayDirtyRect(IDirectDrawSurface4 *iface, RECT *rect)
01868 {
01869     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
01870     TRACE("iface %p, rect %s.\n", iface, wine_dbgstr_rect(rect));
01871 
01872     return ddraw_surface7_AddOverlayDirtyRect(&This->IDirectDrawSurface7_iface, rect);
01873 }
01874 
01875 static HRESULT WINAPI ddraw_surface3_AddOverlayDirtyRect(IDirectDrawSurface3 *iface, RECT *rect)
01876 {
01877     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
01878     TRACE("iface %p, rect %s.\n", iface, wine_dbgstr_rect(rect));
01879 
01880     return ddraw_surface7_AddOverlayDirtyRect(&This->IDirectDrawSurface7_iface, rect);
01881 }
01882 
01883 static HRESULT WINAPI ddraw_surface2_AddOverlayDirtyRect(IDirectDrawSurface2 *iface, RECT *rect)
01884 {
01885     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
01886     TRACE("iface %p, rect %s.\n", iface, wine_dbgstr_rect(rect));
01887 
01888     return ddraw_surface7_AddOverlayDirtyRect(&This->IDirectDrawSurface7_iface, rect);
01889 }
01890 
01891 static HRESULT WINAPI ddraw_surface1_AddOverlayDirtyRect(IDirectDrawSurface *iface, RECT *rect)
01892 {
01893     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
01894     TRACE("iface %p, rect %s.\n", iface, wine_dbgstr_rect(rect));
01895 
01896     return ddraw_surface7_AddOverlayDirtyRect(&This->IDirectDrawSurface7_iface, rect);
01897 }
01898 
01899 /*****************************************************************************
01900  * IDirectDrawSurface7::GetDC
01901  *
01902  * Returns a GDI device context for the surface
01903  *
01904  * Params:
01905  *  hdc: Address of a HDC variable to store the dc to
01906  *
01907  * Returns:
01908  *  DD_OK on success
01909  *  DDERR_INVALIDPARAMS if hdc is NULL
01910  *  For details, see IWineD3DSurface::GetDC
01911  *
01912  *****************************************************************************/
01913 static HRESULT WINAPI ddraw_surface7_GetDC(IDirectDrawSurface7 *iface, HDC *hdc)
01914 {
01915     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
01916     HRESULT hr = DD_OK;
01917 
01918     TRACE("iface %p, dc %p.\n", iface, hdc);
01919 
01920     if(!hdc)
01921         return DDERR_INVALIDPARAMS;
01922 
01923     wined3d_mutex_lock();
01924     if (This->surface_desc.ddsCaps.dwCaps & DDSCAPS_FRONTBUFFER)
01925         hr = ddraw_surface_update_frontbuffer(This, NULL, TRUE);
01926     if (SUCCEEDED(hr))
01927         hr = wined3d_surface_getdc(This->wined3d_surface, hdc);
01928     wined3d_mutex_unlock();
01929     switch(hr)
01930     {
01931         /* Some, but not all errors set *hdc to NULL. E.g. DCALREADYCREATED does not
01932          * touch *hdc
01933          */
01934         case WINED3DERR_INVALIDCALL:
01935             if(hdc) *hdc = NULL;
01936             return DDERR_INVALIDPARAMS;
01937 
01938         default: return hr;
01939     }
01940 }
01941 
01942 static HRESULT WINAPI ddraw_surface4_GetDC(IDirectDrawSurface4 *iface, HDC *dc)
01943 {
01944     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
01945     TRACE("iface %p, dc %p.\n", iface, dc);
01946 
01947     return ddraw_surface7_GetDC(&This->IDirectDrawSurface7_iface, dc);
01948 }
01949 
01950 static HRESULT WINAPI ddraw_surface3_GetDC(IDirectDrawSurface3 *iface, HDC *dc)
01951 {
01952     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
01953     TRACE("iface %p, dc %p.\n", iface, dc);
01954 
01955     return ddraw_surface7_GetDC(&This->IDirectDrawSurface7_iface, dc);
01956 }
01957 
01958 static HRESULT WINAPI ddraw_surface2_GetDC(IDirectDrawSurface2 *iface, HDC *dc)
01959 {
01960     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
01961     TRACE("iface %p, dc %p.\n", iface, dc);
01962 
01963     return ddraw_surface7_GetDC(&This->IDirectDrawSurface7_iface, dc);
01964 }
01965 
01966 static HRESULT WINAPI ddraw_surface1_GetDC(IDirectDrawSurface *iface, HDC *dc)
01967 {
01968     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
01969     TRACE("iface %p, dc %p.\n", iface, dc);
01970 
01971     return ddraw_surface7_GetDC(&This->IDirectDrawSurface7_iface, dc);
01972 }
01973 
01974 /*****************************************************************************
01975  * IDirectDrawSurface7::ReleaseDC
01976  *
01977  * Releases the DC that was constructed with GetDC
01978  *
01979  * Params:
01980  *  hdc: HDC to release
01981  *
01982  * Returns:
01983  *  DD_OK on success
01984  *  For more details, see IWineD3DSurface::ReleaseDC
01985  *
01986  *****************************************************************************/
01987 static HRESULT WINAPI ddraw_surface7_ReleaseDC(IDirectDrawSurface7 *iface, HDC hdc)
01988 {
01989     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
01990     HRESULT hr;
01991 
01992     TRACE("iface %p, dc %p.\n", iface, hdc);
01993 
01994     wined3d_mutex_lock();
01995     hr = wined3d_surface_releasedc(This->wined3d_surface, hdc);
01996     if (SUCCEEDED(hr) && (This->surface_desc.ddsCaps.dwCaps & DDSCAPS_FRONTBUFFER))
01997         hr = ddraw_surface_update_frontbuffer(This, NULL, FALSE);
01998     wined3d_mutex_unlock();
01999 
02000     return hr;
02001 }
02002 
02003 static HRESULT WINAPI ddraw_surface4_ReleaseDC(IDirectDrawSurface4 *iface, HDC dc)
02004 {
02005     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
02006     TRACE("iface %p, dc %p.\n", iface, dc);
02007 
02008     return ddraw_surface7_ReleaseDC(&This->IDirectDrawSurface7_iface, dc);
02009 }
02010 
02011 static HRESULT WINAPI ddraw_surface3_ReleaseDC(IDirectDrawSurface3 *iface, HDC dc)
02012 {
02013     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
02014     TRACE("iface %p, dc %p.\n", iface, dc);
02015 
02016     return ddraw_surface7_ReleaseDC(&This->IDirectDrawSurface7_iface, dc);
02017 }
02018 
02019 static HRESULT WINAPI ddraw_surface2_ReleaseDC(IDirectDrawSurface2 *iface, HDC dc)
02020 {
02021     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
02022     TRACE("iface %p, dc %p.\n", iface, dc);
02023 
02024     return ddraw_surface7_ReleaseDC(&This->IDirectDrawSurface7_iface, dc);
02025 }
02026 
02027 static HRESULT WINAPI ddraw_surface1_ReleaseDC(IDirectDrawSurface *iface, HDC dc)
02028 {
02029     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
02030     TRACE("iface %p, dc %p.\n", iface, dc);
02031 
02032     return ddraw_surface7_ReleaseDC(&This->IDirectDrawSurface7_iface, dc);
02033 }
02034 
02035 /*****************************************************************************
02036  * IDirectDrawSurface7::GetCaps
02037  *
02038  * Returns the surface's caps
02039  *
02040  * Params:
02041  *  Caps: Address to write the caps to
02042  *
02043  * Returns:
02044  *  DD_OK on success
02045  *  DDERR_INVALIDPARAMS if Caps is NULL
02046  *
02047  *****************************************************************************/
02048 static HRESULT WINAPI ddraw_surface7_GetCaps(IDirectDrawSurface7 *iface, DDSCAPS2 *Caps)
02049 {
02050     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
02051 
02052     TRACE("iface %p, caps %p.\n", iface, Caps);
02053 
02054     if(!Caps)
02055         return DDERR_INVALIDPARAMS;
02056 
02057     *Caps = This->surface_desc.ddsCaps;
02058     return DD_OK;
02059 }
02060 
02061 static HRESULT WINAPI ddraw_surface4_GetCaps(IDirectDrawSurface4 *iface, DDSCAPS2 *caps)
02062 {
02063     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
02064     TRACE("iface %p, caps %p.\n", iface, caps);
02065 
02066     return ddraw_surface7_GetCaps(&This->IDirectDrawSurface7_iface, caps);
02067 }
02068 
02069 static HRESULT WINAPI ddraw_surface3_GetCaps(IDirectDrawSurface3 *iface, DDSCAPS *caps)
02070 {
02071     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
02072     DDSCAPS2 caps2;
02073     HRESULT hr;
02074 
02075     TRACE("iface %p, caps %p.\n", iface, caps);
02076 
02077     hr = ddraw_surface7_GetCaps(&This->IDirectDrawSurface7_iface, &caps2);
02078     if (FAILED(hr)) return hr;
02079 
02080     caps->dwCaps = caps2.dwCaps;
02081     return hr;
02082 }
02083 
02084 static HRESULT WINAPI ddraw_surface2_GetCaps(IDirectDrawSurface2 *iface, DDSCAPS *caps)
02085 {
02086     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
02087     DDSCAPS2 caps2;
02088     HRESULT hr;
02089 
02090     TRACE("iface %p, caps %p.\n", iface, caps);
02091 
02092     hr = ddraw_surface7_GetCaps(&This->IDirectDrawSurface7_iface, &caps2);
02093     if (FAILED(hr)) return hr;
02094 
02095     caps->dwCaps = caps2.dwCaps;
02096     return hr;
02097 }
02098 
02099 static HRESULT WINAPI ddraw_surface1_GetCaps(IDirectDrawSurface *iface, DDSCAPS *caps)
02100 {
02101     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
02102     DDSCAPS2 caps2;
02103     HRESULT hr;
02104 
02105     TRACE("iface %p, caps %p.\n", iface, caps);
02106 
02107     hr = ddraw_surface7_GetCaps(&This->IDirectDrawSurface7_iface, &caps2);
02108     if (FAILED(hr)) return hr;
02109 
02110     caps->dwCaps = caps2.dwCaps;
02111     return hr;
02112 }
02113 
02114 /*****************************************************************************
02115  * IDirectDrawSurface7::SetPriority
02116  *
02117  * Sets a texture priority for managed textures.
02118  *
02119  * Params:
02120  *  Priority: The new priority
02121  *
02122  * Returns:
02123  *  DD_OK on success
02124  *  For more details, see IWineD3DSurface::SetPriority
02125  *
02126  *****************************************************************************/
02127 static HRESULT WINAPI ddraw_surface7_SetPriority(IDirectDrawSurface7 *iface, DWORD Priority)
02128 {
02129     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
02130     HRESULT hr;
02131 
02132     TRACE("iface %p, priority %u.\n", iface, Priority);
02133 
02134     wined3d_mutex_lock();
02135     hr = wined3d_surface_set_priority(This->wined3d_surface, Priority);
02136     wined3d_mutex_unlock();
02137 
02138     return hr;
02139 }
02140 
02141 /*****************************************************************************
02142  * IDirectDrawSurface7::GetPriority
02143  *
02144  * Returns the surface's priority
02145  *
02146  * Params:
02147  *  Priority: Address of a variable to write the priority to
02148  *
02149  * Returns:
02150  *  D3D_OK on success
02151  *  DDERR_INVALIDPARAMS if Priority == NULL
02152  *  For more details, see IWineD3DSurface::GetPriority
02153  *
02154  *****************************************************************************/
02155 static HRESULT WINAPI ddraw_surface7_GetPriority(IDirectDrawSurface7 *iface, DWORD *Priority)
02156 {
02157     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
02158 
02159     TRACE("iface %p, priority %p.\n", iface, Priority);
02160 
02161     if(!Priority)
02162     {
02163         return DDERR_INVALIDPARAMS;
02164     }
02165 
02166     wined3d_mutex_lock();
02167     *Priority = wined3d_surface_get_priority(This->wined3d_surface);
02168     wined3d_mutex_unlock();
02169 
02170     return DD_OK;
02171 }
02172 
02173 /*****************************************************************************
02174  * IDirectDrawSurface7::SetPrivateData
02175  *
02176  * Stores some data in the surface that is intended for the application's
02177  * use.
02178  *
02179  * Params:
02180  *  tag: GUID that identifies the data
02181  *  Data: Pointer to the private data
02182  *  Size: Size of the private data
02183  *  Flags: Some flags
02184  *
02185  * Returns:
02186  *  D3D_OK on success
02187  *  For more details, see IWineD3DSurface::SetPrivateData
02188  *
02189  *****************************************************************************/
02190 static HRESULT WINAPI ddraw_surface7_SetPrivateData(IDirectDrawSurface7 *iface,
02191         REFGUID tag, void *Data, DWORD Size, DWORD Flags)
02192 {
02193     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
02194     struct wined3d_resource *resource;
02195     HRESULT hr;
02196 
02197     TRACE("iface %p, tag %s, data %p, data_size %u, flags %#x.\n",
02198             iface, debugstr_guid(tag), Data, Size, Flags);
02199 
02200     wined3d_mutex_lock();
02201     resource = wined3d_surface_get_resource(This->wined3d_surface);
02202     hr = wined3d_resource_set_private_data(resource, tag, Data, Size, Flags);
02203     wined3d_mutex_unlock();
02204 
02205     switch(hr)
02206     {
02207         case WINED3DERR_INVALIDCALL:        return DDERR_INVALIDPARAMS;
02208         default:                            return hr;
02209     }
02210 }
02211 
02212 static HRESULT WINAPI ddraw_surface4_SetPrivateData(IDirectDrawSurface4 *iface,
02213         REFGUID tag, void *data, DWORD size, DWORD flags)
02214 {
02215     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
02216     TRACE("iface %p, tag %s, data %p, data_size %u, flags %#x.\n",
02217                 iface, debugstr_guid(tag), data, size, flags);
02218 
02219     return ddraw_surface7_SetPrivateData(&This->IDirectDrawSurface7_iface, tag, data, size, flags);
02220 }
02221 
02222 /*****************************************************************************
02223  * IDirectDrawSurface7::GetPrivateData
02224  *
02225  * Returns the private data set with IDirectDrawSurface7::SetPrivateData
02226  *
02227  * Params:
02228  *  tag: GUID of the data to return
02229  *  Data: Address where to write the data to
02230  *  Size: Size of the buffer at Data
02231  *
02232  * Returns:
02233  *  DD_OK on success
02234  *  DDERR_INVALIDPARAMS if Data is NULL
02235  *  For more details, see IWineD3DSurface::GetPrivateData
02236  *
02237  *****************************************************************************/
02238 static HRESULT WINAPI ddraw_surface7_GetPrivateData(IDirectDrawSurface7 *iface, REFGUID tag, void *Data, DWORD *Size)
02239 {
02240     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
02241     struct wined3d_resource *resource;
02242     HRESULT hr;
02243 
02244     TRACE("iface %p, tag %s, data %p, data_size %p.\n",
02245             iface, debugstr_guid(tag), Data, Size);
02246 
02247     if(!Data)
02248         return DDERR_INVALIDPARAMS;
02249 
02250     wined3d_mutex_lock();
02251     resource = wined3d_surface_get_resource(This->wined3d_surface);
02252     hr = wined3d_resource_get_private_data(resource, tag, Data, Size);
02253     wined3d_mutex_unlock();
02254 
02255     return hr;
02256 }
02257 
02258 static HRESULT WINAPI ddraw_surface4_GetPrivateData(IDirectDrawSurface4 *iface, REFGUID tag, void *data, DWORD *size)
02259 {
02260     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
02261     TRACE("iface %p, tag %s, data %p, data_size %p.\n",
02262                 iface, debugstr_guid(tag), data, size);
02263 
02264     return ddraw_surface7_GetPrivateData(&This->IDirectDrawSurface7_iface, tag, data, size);
02265 }
02266 
02267 /*****************************************************************************
02268  * IDirectDrawSurface7::FreePrivateData
02269  *
02270  * Frees private data stored in the surface
02271  *
02272  * Params:
02273  *  tag: Tag of the data to free
02274  *
02275  * Returns:
02276  *  D3D_OK on success
02277  *  For more details, see IWineD3DSurface::FreePrivateData
02278  *
02279  *****************************************************************************/
02280 static HRESULT WINAPI ddraw_surface7_FreePrivateData(IDirectDrawSurface7 *iface, REFGUID tag)
02281 {
02282     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
02283     struct wined3d_resource *resource;
02284     HRESULT hr;
02285 
02286     TRACE("iface %p, tag %s.\n", iface, debugstr_guid(tag));
02287 
02288     wined3d_mutex_lock();
02289     resource = wined3d_surface_get_resource(This->wined3d_surface);
02290     hr = wined3d_resource_free_private_data(resource, tag);
02291     wined3d_mutex_unlock();
02292 
02293     return hr;
02294 }
02295 
02296 static HRESULT WINAPI ddraw_surface4_FreePrivateData(IDirectDrawSurface4 *iface, REFGUID tag)
02297 {
02298     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
02299     TRACE("iface %p, tag %s.\n", iface, debugstr_guid(tag));
02300 
02301     return ddraw_surface7_FreePrivateData(&This->IDirectDrawSurface7_iface, tag);
02302 }
02303 
02304 /*****************************************************************************
02305  * IDirectDrawSurface7::PageLock
02306  *
02307  * Prevents a sysmem surface from being paged out
02308  *
02309  * Params:
02310  *  Flags: Not used, must be 0(unchecked)
02311  *
02312  * Returns:
02313  *  DD_OK, because it's a stub
02314  *
02315  *****************************************************************************/
02316 static HRESULT WINAPI ddraw_surface7_PageLock(IDirectDrawSurface7 *iface, DWORD Flags)
02317 {
02318     TRACE("iface %p, flags %#x.\n", iface, Flags);
02319 
02320     /* This is Windows memory management related - we don't need this */
02321     return DD_OK;
02322 }
02323 
02324 static HRESULT WINAPI ddraw_surface4_PageLock(IDirectDrawSurface4 *iface, DWORD flags)
02325 {
02326     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
02327     TRACE("iface %p, flags %#x.\n", iface, flags);
02328 
02329     return ddraw_surface7_PageLock(&This->IDirectDrawSurface7_iface, flags);
02330 }
02331 
02332 static HRESULT WINAPI ddraw_surface3_PageLock(IDirectDrawSurface3 *iface, DWORD flags)
02333 {
02334     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
02335     TRACE("iface %p, flags %#x.\n", iface, flags);
02336 
02337     return ddraw_surface7_PageLock(&This->IDirectDrawSurface7_iface, flags);
02338 }
02339 
02340 static HRESULT WINAPI ddraw_surface2_PageLock(IDirectDrawSurface2 *iface, DWORD flags)
02341 {
02342     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
02343     TRACE("iface %p, flags %#x.\n", iface, flags);
02344 
02345     return ddraw_surface7_PageLock(&This->IDirectDrawSurface7_iface, flags);
02346 }
02347 
02348 /*****************************************************************************
02349  * IDirectDrawSurface7::PageUnlock
02350  *
02351  * Allows a sysmem surface to be paged out
02352  *
02353  * Params:
02354  *  Flags: Not used, must be 0(unchecked)
02355  *
02356  * Returns:
02357  *  DD_OK, because it's a stub
02358  *
02359  *****************************************************************************/
02360 static HRESULT WINAPI ddraw_surface7_PageUnlock(IDirectDrawSurface7 *iface, DWORD Flags)
02361 {
02362     TRACE("iface %p, flags %#x.\n", iface, Flags);
02363 
02364     return DD_OK;
02365 }
02366 
02367 static HRESULT WINAPI ddraw_surface4_PageUnlock(IDirectDrawSurface4 *iface, DWORD flags)
02368 {
02369     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
02370     TRACE("iface %p, flags %#x.\n", iface, flags);
02371 
02372     return ddraw_surface7_PageUnlock(&This->IDirectDrawSurface7_iface, flags);
02373 }
02374 
02375 static HRESULT WINAPI ddraw_surface3_PageUnlock(IDirectDrawSurface3 *iface, DWORD flags)
02376 {
02377     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
02378     TRACE("iface %p, flags %#x.\n", iface, flags);
02379 
02380     return ddraw_surface7_PageUnlock(&This->IDirectDrawSurface7_iface, flags);
02381 }
02382 
02383 static HRESULT WINAPI ddraw_surface2_PageUnlock(IDirectDrawSurface2 *iface, DWORD flags)
02384 {
02385     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
02386     TRACE("iface %p, flags %#x.\n", iface, flags);
02387 
02388     return ddraw_surface7_PageUnlock(&This->IDirectDrawSurface7_iface, flags);
02389 }
02390 
02391 /*****************************************************************************
02392  * IDirectDrawSurface7::BltBatch
02393  *
02394  * An unimplemented function
02395  *
02396  * Params:
02397  *  ?
02398  *
02399  * Returns:
02400  *  DDERR_UNSUPPORTED
02401  *
02402  *****************************************************************************/
02403 static HRESULT WINAPI ddraw_surface7_BltBatch(IDirectDrawSurface7 *iface, DDBLTBATCH *Batch, DWORD Count, DWORD Flags)
02404 {
02405     TRACE("iface %p, batch %p, count %u, flags %#x.\n", iface, Batch, Count, Flags);
02406 
02407     /* MSDN: "not currently implemented" */
02408     return DDERR_UNSUPPORTED;
02409 }
02410 
02411 static HRESULT WINAPI ddraw_surface4_BltBatch(IDirectDrawSurface4 *iface, DDBLTBATCH *batch, DWORD count, DWORD flags)
02412 {
02413     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
02414     TRACE("iface %p, batch %p, count %u, flags %#x.\n", iface, batch, count, flags);
02415 
02416     return ddraw_surface7_BltBatch(&This->IDirectDrawSurface7_iface, batch, count, flags);
02417 }
02418 
02419 static HRESULT WINAPI ddraw_surface3_BltBatch(IDirectDrawSurface3 *iface, DDBLTBATCH *batch, DWORD count, DWORD flags)
02420 {
02421     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
02422     TRACE("iface %p, batch %p, count %u, flags %#x.\n", iface, batch, count, flags);
02423 
02424     return ddraw_surface7_BltBatch(&This->IDirectDrawSurface7_iface, batch, count, flags);
02425 }
02426 
02427 static HRESULT WINAPI ddraw_surface2_BltBatch(IDirectDrawSurface2 *iface, DDBLTBATCH *batch, DWORD count, DWORD flags)
02428 {
02429     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
02430     TRACE("iface %p, batch %p, count %u, flags %#x.\n", iface, batch, count, flags);
02431 
02432     return ddraw_surface7_BltBatch(&This->IDirectDrawSurface7_iface, batch, count, flags);
02433 }
02434 
02435 static HRESULT WINAPI ddraw_surface1_BltBatch(IDirectDrawSurface *iface, DDBLTBATCH *batch, DWORD count, DWORD flags)
02436 {
02437     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
02438     TRACE("iface %p, batch %p, count %u, flags %#x.\n", iface, batch, count, flags);
02439 
02440     return ddraw_surface7_BltBatch(&This->IDirectDrawSurface7_iface, batch, count, flags);
02441 }
02442 
02443 /*****************************************************************************
02444  * IDirectDrawSurface7::EnumAttachedSurfaces
02445  *
02446  * Enumerates all surfaces attached to this surface
02447  *
02448  * Params:
02449  *  context: Pointer to pass unmodified to the callback
02450  *  cb: Callback function to call for each surface
02451  *
02452  * Returns:
02453  *  DD_OK on success
02454  *  DDERR_INVALIDPARAMS if cb is NULL
02455  *
02456  *****************************************************************************/
02457 static HRESULT WINAPI ddraw_surface7_EnumAttachedSurfaces(IDirectDrawSurface7 *iface,
02458         void *context, LPDDENUMSURFACESCALLBACK7 cb)
02459 {
02460     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
02461     IDirectDrawSurfaceImpl *surf;
02462     DDSURFACEDESC2 desc;
02463     int i;
02464 
02465     /* Attached surfaces aren't handled in WineD3D */
02466     TRACE("iface %p, context %p, callback %p.\n", iface, context, cb);
02467 
02468     if(!cb)
02469         return DDERR_INVALIDPARAMS;
02470 
02471     wined3d_mutex_lock();
02472 
02473     for(i = 0; i < MAX_COMPLEX_ATTACHED; i++)
02474     {
02475         surf = This->complex_array[i];
02476         if(!surf) break;
02477 
02478         ddraw_surface7_AddRef(&surf->IDirectDrawSurface7_iface);
02479         desc = surf->surface_desc;
02480         /* check: != DDENUMRET_OK or == DDENUMRET_CANCEL? */
02481         if (cb(&surf->IDirectDrawSurface7_iface, &desc, context) == DDENUMRET_CANCEL)
02482         {
02483             wined3d_mutex_unlock();
02484             return DD_OK;
02485         }
02486     }
02487 
02488     for (surf = This->next_attached; surf != NULL; surf = surf->next_attached)
02489     {
02490         ddraw_surface7_AddRef(&surf->IDirectDrawSurface7_iface);
02491         desc = surf->surface_desc;
02492         /* check: != DDENUMRET_OK or == DDENUMRET_CANCEL? */
02493         if (cb(&surf->IDirectDrawSurface7_iface, &desc, context) == DDENUMRET_CANCEL)
02494         {
02495             wined3d_mutex_unlock();
02496             return DD_OK;
02497         }
02498     }
02499 
02500     TRACE(" end of enumeration.\n");
02501 
02502     wined3d_mutex_unlock();
02503 
02504     return DD_OK;
02505 }
02506 
02507 struct callback_info2
02508 {
02509     LPDDENUMSURFACESCALLBACK2 callback;
02510     void *context;
02511 };
02512 
02513 struct callback_info
02514 {
02515     LPDDENUMSURFACESCALLBACK callback;
02516     void *context;
02517 };
02518 
02519 static HRESULT CALLBACK EnumCallback2(IDirectDrawSurface7 *surface, DDSURFACEDESC2 *surface_desc, void *context)
02520 {
02521     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(surface);
02522     const struct callback_info2 *info = context;
02523 
02524     ddraw_surface4_AddRef(&This->IDirectDrawSurface4_iface);
02525     ddraw_surface7_Release(surface);
02526 
02527     return info->callback(&This->IDirectDrawSurface4_iface, surface_desc, info->context);
02528 }
02529 
02530 static HRESULT CALLBACK EnumCallback(IDirectDrawSurface7 *surface, DDSURFACEDESC2 *surface_desc, void *context)
02531 {
02532     IDirectDrawSurfaceImpl *surface_impl = impl_from_IDirectDrawSurface7(surface);
02533     const struct callback_info *info = context;
02534 
02535     ddraw_surface1_AddRef(&surface_impl->IDirectDrawSurface_iface);
02536     ddraw_surface7_Release(surface);
02537 
02538     /* FIXME: Check surface_test.dwSize */
02539     return info->callback(&surface_impl->IDirectDrawSurface_iface,
02540             (DDSURFACEDESC *)surface_desc, info->context);
02541 }
02542 
02543 static HRESULT WINAPI ddraw_surface4_EnumAttachedSurfaces(IDirectDrawSurface4 *iface,
02544         void *context, LPDDENUMSURFACESCALLBACK2 callback)
02545 {
02546     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
02547     struct callback_info2 info;
02548 
02549     TRACE("iface %p, context %p, callback %p.\n", iface, context, callback);
02550 
02551     info.callback = callback;
02552     info.context  = context;
02553 
02554     return ddraw_surface7_EnumAttachedSurfaces(&This->IDirectDrawSurface7_iface,
02555             &info, EnumCallback2);
02556 }
02557 
02558 static HRESULT WINAPI ddraw_surface3_EnumAttachedSurfaces(IDirectDrawSurface3 *iface,
02559         void *context, LPDDENUMSURFACESCALLBACK callback)
02560 {
02561     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
02562     struct callback_info info;
02563 
02564     TRACE("iface %p, context %p, callback %p.\n", iface, context, callback);
02565 
02566     info.callback = callback;
02567     info.context  = context;
02568 
02569     return ddraw_surface7_EnumAttachedSurfaces(&This->IDirectDrawSurface7_iface,
02570             &info, EnumCallback);
02571 }
02572 
02573 static HRESULT WINAPI ddraw_surface2_EnumAttachedSurfaces(IDirectDrawSurface2 *iface,
02574         void *context, LPDDENUMSURFACESCALLBACK callback)
02575 {
02576     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
02577     struct callback_info info;
02578 
02579     TRACE("iface %p, context %p, callback %p.\n", iface, context, callback);
02580 
02581     info.callback = callback;
02582     info.context  = context;
02583 
02584     return ddraw_surface7_EnumAttachedSurfaces(&This->IDirectDrawSurface7_iface,
02585             &info, EnumCallback);
02586 }
02587 
02588 static HRESULT WINAPI ddraw_surface1_EnumAttachedSurfaces(IDirectDrawSurface *iface,
02589         void *context, LPDDENUMSURFACESCALLBACK callback)
02590 {
02591     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
02592     struct callback_info info;
02593 
02594     TRACE("iface %p, context %p, callback %p.\n", iface, context, callback);
02595 
02596     info.callback = callback;
02597     info.context  = context;
02598 
02599     return ddraw_surface7_EnumAttachedSurfaces(&This->IDirectDrawSurface7_iface,
02600             &info, EnumCallback);
02601 }
02602 
02603 /*****************************************************************************
02604  * IDirectDrawSurface7::EnumOverlayZOrders
02605  *
02606  * "Enumerates the overlay surfaces on the specified destination"
02607  *
02608  * Params:
02609  *  Flags: DDENUMOVERLAYZ_BACKTOFRONT  or DDENUMOVERLAYZ_FRONTTOBACK
02610  *  context: context to pass back to the callback
02611  *  cb: callback function to call for each enumerated surface
02612  *
02613  * Returns:
02614  *  DD_OK, because it's a stub
02615  *
02616  *****************************************************************************/
02617 static HRESULT WINAPI ddraw_surface7_EnumOverlayZOrders(IDirectDrawSurface7 *iface,
02618         DWORD Flags, void *context, LPDDENUMSURFACESCALLBACK7 cb)
02619 {
02620     FIXME("iface %p, flags %#x, context %p, callback %p stub!\n", iface, Flags, context, cb);
02621 
02622     return DD_OK;
02623 }
02624 
02625 static HRESULT WINAPI ddraw_surface4_EnumOverlayZOrders(IDirectDrawSurface4 *iface,
02626         DWORD flags, void *context, LPDDENUMSURFACESCALLBACK2 callback)
02627 {
02628     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
02629     struct callback_info2 info;
02630 
02631     TRACE("iface %p, flags %#x, context %p, callback %p.\n", iface, flags, context, callback);
02632 
02633     info.callback = callback;
02634     info.context  = context;
02635 
02636     return ddraw_surface7_EnumOverlayZOrders(&This->IDirectDrawSurface7_iface,
02637             flags, &info, EnumCallback2);
02638 }
02639 
02640 static HRESULT WINAPI ddraw_surface3_EnumOverlayZOrders(IDirectDrawSurface3 *iface,
02641         DWORD flags, void *context, LPDDENUMSURFACESCALLBACK callback)
02642 {
02643     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
02644     struct callback_info info;
02645 
02646     TRACE("iface %p, flags %#x, context %p, callback %p.\n", iface, flags, context, callback);
02647 
02648     info.callback = callback;
02649     info.context  = context;
02650 
02651     return ddraw_surface7_EnumOverlayZOrders(&This->IDirectDrawSurface7_iface,
02652             flags, &info, EnumCallback);
02653 }
02654 
02655 static HRESULT WINAPI ddraw_surface2_EnumOverlayZOrders(IDirectDrawSurface2 *iface,
02656         DWORD flags, void *context, LPDDENUMSURFACESCALLBACK callback)
02657 {
02658     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
02659     struct callback_info info;
02660 
02661     TRACE("iface %p, flags %#x, context %p, callback %p.\n", iface, flags, context, callback);
02662 
02663     info.callback = callback;
02664     info.context  = context;
02665 
02666     return ddraw_surface7_EnumOverlayZOrders(&This->IDirectDrawSurface7_iface,
02667             flags, &info, EnumCallback);
02668 }
02669 
02670 static HRESULT WINAPI ddraw_surface1_EnumOverlayZOrders(IDirectDrawSurface *iface,
02671         DWORD flags, void *context, LPDDENUMSURFACESCALLBACK callback)
02672 {
02673     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
02674     struct callback_info info;
02675 
02676     TRACE("iface %p, flags %#x, context %p, callback %p.\n", iface, flags, context, callback);
02677 
02678     info.callback = callback;
02679     info.context  = context;
02680 
02681     return ddraw_surface7_EnumOverlayZOrders(&This->IDirectDrawSurface7_iface,
02682             flags, &info, EnumCallback);
02683 }
02684 
02685 /*****************************************************************************
02686  * IDirectDrawSurface7::GetBltStatus
02687  *
02688  * Returns the blitting status
02689  *
02690  * Params:
02691  *  Flags: DDGBS_CANBLT or DDGBS_ISBLTDONE
02692  *
02693  * Returns:
02694  *  See IWineD3DSurface::Blt
02695  *
02696  *****************************************************************************/
02697 static HRESULT WINAPI ddraw_surface7_GetBltStatus(IDirectDrawSurface7 *iface, DWORD Flags)
02698 {
02699     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
02700     HRESULT hr;
02701 
02702     TRACE("iface %p, flags %#x.\n", iface, Flags);
02703 
02704     wined3d_mutex_lock();
02705     hr = wined3d_surface_get_blt_status(This->wined3d_surface, Flags);
02706     wined3d_mutex_unlock();
02707     switch(hr)
02708     {
02709         case WINED3DERR_INVALIDCALL:        return DDERR_INVALIDPARAMS;
02710         default:                            return hr;
02711     }
02712 }
02713 
02714 static HRESULT WINAPI ddraw_surface4_GetBltStatus(IDirectDrawSurface4 *iface, DWORD flags)
02715 {
02716     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
02717     TRACE("iface %p, flags %#x.\n", iface, flags);
02718 
02719     return ddraw_surface7_GetBltStatus(&This->IDirectDrawSurface7_iface, flags);
02720 }
02721 
02722 static HRESULT WINAPI ddraw_surface3_GetBltStatus(IDirectDrawSurface3 *iface, DWORD flags)
02723 {
02724     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
02725     TRACE("iface %p, flags %#x.\n", iface, flags);
02726 
02727     return ddraw_surface7_GetBltStatus(&This->IDirectDrawSurface7_iface, flags);
02728 }
02729 
02730 static HRESULT WINAPI ddraw_surface2_GetBltStatus(IDirectDrawSurface2 *iface, DWORD flags)
02731 {
02732     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
02733     TRACE("iface %p, flags %#x.\n", iface, flags);
02734 
02735     return ddraw_surface7_GetBltStatus(&This->IDirectDrawSurface7_iface, flags);
02736 }
02737 
02738 static HRESULT WINAPI ddraw_surface1_GetBltStatus(IDirectDrawSurface *iface, DWORD flags)
02739 {
02740     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
02741     TRACE("iface %p, flags %#x.\n", iface, flags);
02742 
02743     return ddraw_surface7_GetBltStatus(&This->IDirectDrawSurface7_iface, flags);
02744 }
02745 
02746 /*****************************************************************************
02747  * IDirectDrawSurface7::GetColorKey
02748  *
02749  * Returns the color key assigned to the surface
02750  *
02751  * Params:
02752  *  Flags: Some flags
02753  *  CKey: Address to store the key to
02754  *
02755  * Returns:
02756  *  DD_OK on success
02757  *  DDERR_INVALIDPARAMS if CKey is NULL
02758  *
02759  *****************************************************************************/
02760 static HRESULT WINAPI ddraw_surface7_GetColorKey(IDirectDrawSurface7 *iface, DWORD Flags, DDCOLORKEY *CKey)
02761 {
02762     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
02763 
02764     TRACE("iface %p, flags %#x, color_key %p.\n", iface, Flags, CKey);
02765 
02766     if(!CKey)
02767         return DDERR_INVALIDPARAMS;
02768 
02769     wined3d_mutex_lock();
02770 
02771     switch (Flags)
02772     {
02773     case DDCKEY_DESTBLT:
02774         if (!(This->surface_desc.dwFlags & DDSD_CKDESTBLT))
02775         {
02776             wined3d_mutex_unlock();
02777             return DDERR_NOCOLORKEY;
02778         }
02779         *CKey = This->surface_desc.ddckCKDestBlt;
02780         break;
02781 
02782     case DDCKEY_DESTOVERLAY:
02783         if (!(This->surface_desc.dwFlags & DDSD_CKDESTOVERLAY))
02784         {
02785             wined3d_mutex_unlock();
02786             return DDERR_NOCOLORKEY;
02787         }
02788         *CKey = This->surface_desc.u3.ddckCKDestOverlay;
02789         break;
02790 
02791     case DDCKEY_SRCBLT:
02792         if (!(This->surface_desc.dwFlags & DDSD_CKSRCBLT))
02793         {
02794             wined3d_mutex_unlock();
02795             return DDERR_NOCOLORKEY;
02796         }
02797         *CKey = This->surface_desc.ddckCKSrcBlt;
02798         break;
02799 
02800     case DDCKEY_SRCOVERLAY:
02801         if (!(This->surface_desc.dwFlags & DDSD_CKSRCOVERLAY))
02802         {
02803             wined3d_mutex_unlock();
02804             return DDERR_NOCOLORKEY;
02805         }
02806         *CKey = This->surface_desc.ddckCKSrcOverlay;
02807         break;
02808 
02809     default:
02810         wined3d_mutex_unlock();
02811         return DDERR_INVALIDPARAMS;
02812     }
02813 
02814     wined3d_mutex_unlock();
02815 
02816     return DD_OK;
02817 }
02818 
02819 static HRESULT WINAPI ddraw_surface4_GetColorKey(IDirectDrawSurface4 *iface, DWORD flags, DDCOLORKEY *color_key)
02820 {
02821     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
02822     TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key);
02823 
02824     return ddraw_surface7_GetColorKey(&This->IDirectDrawSurface7_iface, flags, color_key);
02825 }
02826 
02827 static HRESULT WINAPI ddraw_surface3_GetColorKey(IDirectDrawSurface3 *iface, DWORD flags, DDCOLORKEY *color_key)
02828 {
02829     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
02830     TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key);
02831 
02832     return ddraw_surface7_GetColorKey(&This->IDirectDrawSurface7_iface, flags, color_key);
02833 }
02834 
02835 static HRESULT WINAPI ddraw_surface2_GetColorKey(IDirectDrawSurface2 *iface, DWORD flags, DDCOLORKEY *color_key)
02836 {
02837     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
02838     TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key);
02839 
02840     return ddraw_surface7_GetColorKey(&This->IDirectDrawSurface7_iface, flags, color_key);
02841 }
02842 
02843 static HRESULT WINAPI ddraw_surface1_GetColorKey(IDirectDrawSurface *iface, DWORD flags, DDCOLORKEY *color_key)
02844 {
02845     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
02846     TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key);
02847 
02848     return ddraw_surface7_GetColorKey(&This->IDirectDrawSurface7_iface, flags, color_key);
02849 }
02850 
02851 /*****************************************************************************
02852  * IDirectDrawSurface7::GetFlipStatus
02853  *
02854  * Returns the flipping status of the surface
02855  *
02856  * Params:
02857  *  Flags: DDGFS_CANFLIP of DDGFS_ISFLIPDONE
02858  *
02859  * Returns:
02860  *  See IWineD3DSurface::GetFlipStatus
02861  *
02862  *****************************************************************************/
02863 static HRESULT WINAPI ddraw_surface7_GetFlipStatus(IDirectDrawSurface7 *iface, DWORD Flags)
02864 {
02865     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
02866     HRESULT hr;
02867 
02868     TRACE("iface %p, flags %#x.\n", iface, Flags);
02869 
02870     wined3d_mutex_lock();
02871     hr = wined3d_surface_get_flip_status(This->wined3d_surface, Flags);
02872     wined3d_mutex_unlock();
02873 
02874     switch(hr)
02875     {
02876         case WINED3DERR_INVALIDCALL:        return DDERR_INVALIDPARAMS;
02877         default:                            return hr;
02878     }
02879 }
02880 
02881 static HRESULT WINAPI ddraw_surface4_GetFlipStatus(IDirectDrawSurface4 *iface, DWORD flags)
02882 {
02883     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
02884     TRACE("iface %p, flags %#x.\n", iface, flags);
02885 
02886     return ddraw_surface7_GetFlipStatus(&This->IDirectDrawSurface7_iface, flags);
02887 }
02888 
02889 static HRESULT WINAPI ddraw_surface3_GetFlipStatus(IDirectDrawSurface3 *iface, DWORD flags)
02890 {
02891     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
02892     TRACE("iface %p, flags %#x.\n", iface, flags);
02893 
02894     return ddraw_surface7_GetFlipStatus(&This->IDirectDrawSurface7_iface, flags);
02895 }
02896 
02897 static HRESULT WINAPI ddraw_surface2_GetFlipStatus(IDirectDrawSurface2 *iface, DWORD flags)
02898 {
02899     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
02900     TRACE("iface %p, flags %#x.\n", iface, flags);
02901 
02902     return ddraw_surface7_GetFlipStatus(&This->IDirectDrawSurface7_iface, flags);
02903 }
02904 
02905 static HRESULT WINAPI ddraw_surface1_GetFlipStatus(IDirectDrawSurface *iface, DWORD flags)
02906 {
02907     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
02908     TRACE("iface %p, flags %#x.\n", iface, flags);
02909 
02910     return ddraw_surface7_GetFlipStatus(&This->IDirectDrawSurface7_iface, flags);
02911 }
02912 
02913 /*****************************************************************************
02914  * IDirectDrawSurface7::GetOverlayPosition
02915  *
02916  * Returns the display coordinates of a visible and active overlay surface
02917  *
02918  * Params:
02919  *  X
02920  *  Y
02921  *
02922  * Returns:
02923  *  DDERR_NOTAOVERLAYSURFACE, because it's a stub
02924  *****************************************************************************/
02925 static HRESULT WINAPI ddraw_surface7_GetOverlayPosition(IDirectDrawSurface7 *iface, LONG *X, LONG *Y)
02926 {
02927     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
02928     HRESULT hr;
02929 
02930     TRACE("iface %p, x %p, y %p.\n", iface, X, Y);
02931 
02932     wined3d_mutex_lock();
02933     hr = wined3d_surface_get_overlay_position(This->wined3d_surface, X, Y);
02934     wined3d_mutex_unlock();
02935 
02936     return hr;
02937 }
02938 
02939 static HRESULT WINAPI ddraw_surface4_GetOverlayPosition(IDirectDrawSurface4 *iface, LONG *x, LONG *y)
02940 {
02941     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
02942     TRACE("iface %p, x %p, y %p.\n", iface, x, y);
02943 
02944     return ddraw_surface7_GetOverlayPosition(&This->IDirectDrawSurface7_iface, x, y);
02945 }
02946 
02947 static HRESULT WINAPI ddraw_surface3_GetOverlayPosition(IDirectDrawSurface3 *iface, LONG *x, LONG *y)
02948 {
02949     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
02950     TRACE("iface %p, x %p, y %p.\n", iface, x, y);
02951 
02952     return ddraw_surface7_GetOverlayPosition(&This->IDirectDrawSurface7_iface, x, y);
02953 }
02954 
02955 static HRESULT WINAPI ddraw_surface2_GetOverlayPosition(IDirectDrawSurface2 *iface, LONG *x, LONG *y)
02956 {
02957     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
02958     TRACE("iface %p, x %p, y %p.\n", iface, x, y);
02959 
02960     return ddraw_surface7_GetOverlayPosition(&This->IDirectDrawSurface7_iface, x, y);
02961 }
02962 
02963 static HRESULT WINAPI ddraw_surface1_GetOverlayPosition(IDirectDrawSurface *iface, LONG *x, LONG *y)
02964 {
02965     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
02966     TRACE("iface %p, x %p, y %p.\n", iface, x, y);
02967 
02968     return ddraw_surface7_GetOverlayPosition(&This->IDirectDrawSurface7_iface, x, y);
02969 }
02970 
02971 /*****************************************************************************
02972  * IDirectDrawSurface7::GetPixelFormat
02973  *
02974  * Returns the pixel format of the Surface
02975  *
02976  * Params:
02977  *  PixelFormat: Pointer to a DDPIXELFORMAT structure to which the pixel
02978  *               format should be written
02979  *
02980  * Returns:
02981  *  DD_OK on success
02982  *  DDERR_INVALIDPARAMS if PixelFormat is NULL
02983  *
02984  *****************************************************************************/
02985 static HRESULT WINAPI ddraw_surface7_GetPixelFormat(IDirectDrawSurface7 *iface, DDPIXELFORMAT *PixelFormat)
02986 {
02987     /* What is DDERR_INVALIDSURFACETYPE for here? */
02988     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
02989 
02990     TRACE("iface %p, pixel_format %p.\n", iface, PixelFormat);
02991 
02992     if(!PixelFormat)
02993         return DDERR_INVALIDPARAMS;
02994 
02995     wined3d_mutex_lock();
02996     DD_STRUCT_COPY_BYSIZE(PixelFormat,&This->surface_desc.u4.ddpfPixelFormat);
02997     wined3d_mutex_unlock();
02998 
02999     return DD_OK;
03000 }
03001 
03002 static HRESULT WINAPI ddraw_surface4_GetPixelFormat(IDirectDrawSurface4 *iface, DDPIXELFORMAT *pixel_format)
03003 {
03004     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
03005     TRACE("iface %p, pixel_format %p.\n", iface, pixel_format);
03006 
03007     return ddraw_surface7_GetPixelFormat(&This->IDirectDrawSurface7_iface, pixel_format);
03008 }
03009 
03010 static HRESULT WINAPI ddraw_surface3_GetPixelFormat(IDirectDrawSurface3 *iface, DDPIXELFORMAT *pixel_format)
03011 {
03012     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
03013     TRACE("iface %p, pixel_format %p.\n", iface, pixel_format);
03014 
03015     return ddraw_surface7_GetPixelFormat(&This->IDirectDrawSurface7_iface, pixel_format);
03016 }
03017 
03018 static HRESULT WINAPI ddraw_surface2_GetPixelFormat(IDirectDrawSurface2 *iface, DDPIXELFORMAT *pixel_format)
03019 {
03020     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
03021     TRACE("iface %p, pixel_format %p.\n", iface, pixel_format);
03022 
03023     return ddraw_surface7_GetPixelFormat(&This->IDirectDrawSurface7_iface, pixel_format);
03024 }
03025 
03026 static HRESULT WINAPI ddraw_surface1_GetPixelFormat(IDirectDrawSurface *iface, DDPIXELFORMAT *pixel_format)
03027 {
03028     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
03029     TRACE("iface %p, pixel_format %p.\n", iface, pixel_format);
03030 
03031     return ddraw_surface7_GetPixelFormat(&This->IDirectDrawSurface7_iface, pixel_format);
03032 }
03033 
03034 /*****************************************************************************
03035  * IDirectDrawSurface7::GetSurfaceDesc
03036  *
03037  * Returns the description of this surface
03038  *
03039  * Params:
03040  *  DDSD: Address of a DDSURFACEDESC2 structure that is to be filled with the
03041  *        surface desc
03042  *
03043  * Returns:
03044  *  DD_OK on success
03045  *  DDERR_INVALIDPARAMS if DDSD is NULL
03046  *
03047  *****************************************************************************/
03048 static HRESULT WINAPI ddraw_surface7_GetSurfaceDesc(IDirectDrawSurface7 *iface, DDSURFACEDESC2 *DDSD)
03049 {
03050     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
03051 
03052     TRACE("iface %p, surface_desc %p.\n", iface, DDSD);
03053 
03054     if(!DDSD)
03055         return DDERR_INVALIDPARAMS;
03056 
03057     if (DDSD->dwSize != sizeof(DDSURFACEDESC2))
03058     {
03059         WARN("Incorrect struct size %d, returning DDERR_INVALIDPARAMS\n",DDSD->dwSize);
03060         return DDERR_INVALIDPARAMS;
03061     }
03062 
03063     wined3d_mutex_lock();
03064     DD_STRUCT_COPY_BYSIZE(DDSD,&This->surface_desc);
03065     TRACE("Returning surface desc:\n");
03066     if (TRACE_ON(ddraw)) DDRAW_dump_surface_desc(DDSD);
03067     wined3d_mutex_unlock();
03068 
03069     return DD_OK;
03070 }
03071 
03072 static HRESULT WINAPI ddraw_surface4_GetSurfaceDesc(IDirectDrawSurface4 *iface, DDSURFACEDESC2 *DDSD)
03073 {
03074     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
03075     TRACE("iface %p, surface_desc %p.\n", iface, DDSD);
03076 
03077     return ddraw_surface7_GetSurfaceDesc(&This->IDirectDrawSurface7_iface, DDSD);
03078 }
03079 
03080 static HRESULT WINAPI ddraw_surface3_GetSurfaceDesc(IDirectDrawSurface3 *iface, DDSURFACEDESC *surface_desc)
03081 {
03082     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
03083 
03084     TRACE("iface %p, surface_desc %p.\n", iface, surface_desc);
03085 
03086     if (!surface_desc) return DDERR_INVALIDPARAMS;
03087 
03088     if (surface_desc->dwSize != sizeof(DDSURFACEDESC))
03089     {
03090         WARN("Incorrect structure size %u, returning DDERR_INVALIDPARAMS.\n", surface_desc->dwSize);
03091         return DDERR_INVALIDPARAMS;
03092     }
03093 
03094     wined3d_mutex_lock();
03095     DDSD2_to_DDSD(&This->surface_desc, surface_desc);
03096     TRACE("Returning surface desc:\n");
03097     if (TRACE_ON(ddraw))
03098     {
03099         /* DDRAW_dump_surface_desc handles the smaller size */
03100         DDRAW_dump_surface_desc((DDSURFACEDESC2 *)surface_desc);
03101     }
03102     wined3d_mutex_unlock();
03103 
03104     return DD_OK;
03105 }
03106 
03107 static HRESULT WINAPI ddraw_surface2_GetSurfaceDesc(IDirectDrawSurface2 *iface, DDSURFACEDESC *DDSD)
03108 {
03109     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
03110     TRACE("iface %p, surface_desc %p.\n", iface, DDSD);
03111 
03112     return ddraw_surface3_GetSurfaceDesc(&This->IDirectDrawSurface3_iface, DDSD);
03113 }
03114 
03115 static HRESULT WINAPI ddraw_surface1_GetSurfaceDesc(IDirectDrawSurface *iface, DDSURFACEDESC *DDSD)
03116 {
03117     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
03118     TRACE("iface %p, surface_desc %p.\n", iface, DDSD);
03119 
03120     return ddraw_surface3_GetSurfaceDesc(&This->IDirectDrawSurface3_iface, DDSD);
03121 }
03122 
03123 /*****************************************************************************
03124  * IDirectDrawSurface7::Initialize
03125  *
03126  * Initializes the surface. This is a no-op in Wine
03127  *
03128  * Params:
03129  *  DD: Pointer to an DirectDraw interface
03130  *  DDSD: Surface description for initialization
03131  *
03132  * Returns:
03133  *  DDERR_ALREADYINITIALIZED
03134  *
03135  *****************************************************************************/
03136 static HRESULT WINAPI ddraw_surface7_Initialize(IDirectDrawSurface7 *iface,
03137         IDirectDraw *ddraw, DDSURFACEDESC2 *surface_desc)
03138 {
03139     TRACE("iface %p, ddraw %p, surface_desc %p.\n", iface, ddraw, surface_desc);
03140 
03141     return DDERR_ALREADYINITIALIZED;
03142 }
03143 
03144 static HRESULT WINAPI ddraw_surface4_Initialize(IDirectDrawSurface4 *iface,
03145         IDirectDraw *ddraw, DDSURFACEDESC2 *surface_desc)
03146 {
03147     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
03148     TRACE("iface %p, ddraw %p, surface_desc %p.\n", iface, ddraw, surface_desc);
03149 
03150     return ddraw_surface7_Initialize(&This->IDirectDrawSurface7_iface,
03151             ddraw, surface_desc);
03152 }
03153 
03154 static HRESULT WINAPI ddraw_surface3_Initialize(IDirectDrawSurface3 *iface,
03155         IDirectDraw *ddraw, DDSURFACEDESC *surface_desc)
03156 {
03157     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
03158     DDSURFACEDESC2 surface_desc2;
03159     TRACE("iface %p, ddraw %p, surface_desc %p.\n", iface, ddraw, surface_desc);
03160 
03161     if (surface_desc) DDSD_to_DDSD2(surface_desc, &surface_desc2);
03162     return ddraw_surface7_Initialize(&This->IDirectDrawSurface7_iface,
03163             ddraw, surface_desc ? &surface_desc2 : NULL);
03164 }
03165 
03166 static HRESULT WINAPI ddraw_surface2_Initialize(IDirectDrawSurface2 *iface,
03167         IDirectDraw *ddraw, DDSURFACEDESC *surface_desc)
03168 {
03169     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
03170     DDSURFACEDESC2 surface_desc2;
03171     TRACE("iface %p, ddraw %p, surface_desc %p.\n", iface, ddraw, surface_desc);
03172 
03173     if (surface_desc) DDSD_to_DDSD2(surface_desc, &surface_desc2);
03174     return ddraw_surface7_Initialize(&This->IDirectDrawSurface7_iface,
03175             ddraw, surface_desc ? &surface_desc2 : NULL);
03176 }
03177 
03178 static HRESULT WINAPI ddraw_surface1_Initialize(IDirectDrawSurface *iface,
03179         IDirectDraw *ddraw, DDSURFACEDESC *surface_desc)
03180 {
03181     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
03182     DDSURFACEDESC2 surface_desc2;
03183     TRACE("iface %p, ddraw %p, surface_desc %p.\n", iface, ddraw, surface_desc);
03184 
03185     if (surface_desc) DDSD_to_DDSD2(surface_desc, &surface_desc2);
03186     return ddraw_surface7_Initialize(&This->IDirectDrawSurface7_iface,
03187             ddraw, surface_desc ? &surface_desc2 : NULL);
03188 }
03189 
03190 /*****************************************************************************
03191  * IDirect3DTexture1::Initialize
03192  *
03193  * The sdk says it's not implemented
03194  *
03195  * Params:
03196  *  ?
03197  *
03198  * Returns
03199  *  DDERR_UNSUPPORTED
03200  *
03201  *****************************************************************************/
03202 static HRESULT WINAPI d3d_texture1_Initialize(IDirect3DTexture *iface,
03203         IDirect3DDevice *device, IDirectDrawSurface *surface)
03204 {
03205     TRACE("iface %p, device %p, surface %p.\n", iface, device, surface);
03206 
03207     return DDERR_UNSUPPORTED; /* Unchecked */
03208 }
03209 
03210 /*****************************************************************************
03211  * IDirectDrawSurface7::IsLost
03212  *
03213  * Checks if the surface is lost
03214  *
03215  * Returns:
03216  *  DD_OK, if the surface is usable
03217  *  DDERR_ISLOST if the surface is lost
03218  *  See IWineD3DSurface::IsLost for more details
03219  *
03220  *****************************************************************************/
03221 static HRESULT WINAPI ddraw_surface7_IsLost(IDirectDrawSurface7 *iface)
03222 {
03223     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
03224     HRESULT hr;
03225 
03226     TRACE("iface %p.\n", iface);
03227 
03228     wined3d_mutex_lock();
03229     hr = wined3d_surface_is_lost(This->wined3d_surface);
03230     wined3d_mutex_unlock();
03231 
03232     switch(hr)
03233     {
03234         /* D3D8 and 9 loose full devices, thus there's only a DEVICELOST error.
03235          * WineD3D uses the same error for surfaces
03236          */
03237         case WINED3DERR_DEVICELOST:         return DDERR_SURFACELOST;
03238         default:                            return hr;
03239     }
03240 }
03241 
03242 static HRESULT WINAPI ddraw_surface4_IsLost(IDirectDrawSurface4 *iface)
03243 {
03244     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
03245     TRACE("iface %p.\n", iface);
03246 
03247     return ddraw_surface7_IsLost(&This->IDirectDrawSurface7_iface);
03248 }
03249 
03250 static HRESULT WINAPI ddraw_surface3_IsLost(IDirectDrawSurface3 *iface)
03251 {
03252     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
03253     TRACE("iface %p.\n", iface);
03254 
03255     return ddraw_surface7_IsLost(&This->IDirectDrawSurface7_iface);
03256 }
03257 
03258 static HRESULT WINAPI ddraw_surface2_IsLost(IDirectDrawSurface2 *iface)
03259 {
03260     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
03261     TRACE("iface %p.\n", iface);
03262 
03263     return ddraw_surface7_IsLost(&This->IDirectDrawSurface7_iface);
03264 }
03265 
03266 static HRESULT WINAPI ddraw_surface1_IsLost(IDirectDrawSurface *iface)
03267 {
03268     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
03269     TRACE("iface %p.\n", iface);
03270 
03271     return ddraw_surface7_IsLost(&This->IDirectDrawSurface7_iface);
03272 }
03273 
03274 /*****************************************************************************
03275  * IDirectDrawSurface7::Restore
03276  *
03277  * Restores a lost surface. This makes the surface usable again, but
03278  * doesn't reload its old contents
03279  *
03280  * Returns:
03281  *  DD_OK on success
03282  *  See IWineD3DSurface::Restore for more details
03283  *
03284  *****************************************************************************/
03285 static HRESULT WINAPI ddraw_surface7_Restore(IDirectDrawSurface7 *iface)
03286 {
03287     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
03288     HRESULT hr;
03289 
03290     TRACE("iface %p.\n", iface);
03291 
03292     wined3d_mutex_lock();
03293     hr = wined3d_surface_restore(This->wined3d_surface);
03294     wined3d_mutex_unlock();
03295 
03296     return hr;
03297 }
03298 
03299 static HRESULT WINAPI ddraw_surface4_Restore(IDirectDrawSurface4 *iface)
03300 {
03301     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
03302     TRACE("iface %p.\n", iface);
03303 
03304     return ddraw_surface7_Restore(&This->IDirectDrawSurface7_iface);
03305 }
03306 
03307 static HRESULT WINAPI ddraw_surface3_Restore(IDirectDrawSurface3 *iface)
03308 {
03309     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
03310     TRACE("iface %p.\n", iface);
03311 
03312     return ddraw_surface7_Restore(&This->IDirectDrawSurface7_iface);
03313 }
03314 
03315 static HRESULT WINAPI ddraw_surface2_Restore(IDirectDrawSurface2 *iface)
03316 {
03317     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
03318     TRACE("iface %p.\n", iface);
03319 
03320     return ddraw_surface7_Restore(&This->IDirectDrawSurface7_iface);
03321 }
03322 
03323 static HRESULT WINAPI ddraw_surface1_Restore(IDirectDrawSurface *iface)
03324 {
03325     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
03326     TRACE("iface %p.\n", iface);
03327 
03328     return ddraw_surface7_Restore(&This->IDirectDrawSurface7_iface);
03329 }
03330 
03331 /*****************************************************************************
03332  * IDirectDrawSurface7::SetOverlayPosition
03333  *
03334  * Changes the display coordinates of an overlay surface
03335  *
03336  * Params:
03337  *  X:
03338  *  Y:
03339  *
03340  * Returns:
03341  *   DDERR_NOTAOVERLAYSURFACE, because we don't support overlays right now
03342  *****************************************************************************/
03343 static HRESULT WINAPI ddraw_surface7_SetOverlayPosition(IDirectDrawSurface7 *iface, LONG X, LONG Y)
03344 {
03345     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
03346     HRESULT hr;
03347 
03348     TRACE("iface %p, x %d, y %d.\n", iface, X, Y);
03349 
03350     wined3d_mutex_lock();
03351     hr = wined3d_surface_set_overlay_position(This->wined3d_surface, X, Y);
03352     wined3d_mutex_unlock();
03353 
03354     return hr;
03355 }
03356 
03357 static HRESULT WINAPI ddraw_surface4_SetOverlayPosition(IDirectDrawSurface4 *iface, LONG x, LONG y)
03358 {
03359     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
03360     TRACE("iface %p, x %d, y %d.\n", iface, x, y);
03361 
03362     return ddraw_surface7_SetOverlayPosition(&This->IDirectDrawSurface7_iface, x, y);
03363 }
03364 
03365 static HRESULT WINAPI ddraw_surface3_SetOverlayPosition(IDirectDrawSurface3 *iface, LONG x, LONG y)
03366 {
03367     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
03368     TRACE("iface %p, x %d, y %d.\n", iface, x, y);
03369 
03370     return ddraw_surface7_SetOverlayPosition(&This->IDirectDrawSurface7_iface, x, y);
03371 }
03372 
03373 static HRESULT WINAPI ddraw_surface2_SetOverlayPosition(IDirectDrawSurface2 *iface, LONG x, LONG y)
03374 {
03375     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
03376     TRACE("iface %p, x %d, y %d.\n", iface, x, y);
03377 
03378     return ddraw_surface7_SetOverlayPosition(&This->IDirectDrawSurface7_iface, x, y);
03379 }
03380 
03381 static HRESULT WINAPI ddraw_surface1_SetOverlayPosition(IDirectDrawSurface *iface, LONG x, LONG y)
03382 {
03383     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
03384     TRACE("iface %p, x %d, y %d.\n", iface, x, y);
03385 
03386     return ddraw_surface7_SetOverlayPosition(&This->IDirectDrawSurface7_iface, x, y);
03387 }
03388 
03389 /*****************************************************************************
03390  * IDirectDrawSurface7::UpdateOverlay
03391  *
03392  * Modifies the attributes of an overlay surface.
03393  *
03394  * Params:
03395  *  SrcRect: The section of the source being used for the overlay
03396  *  DstSurface: Address of the surface that is overlaid
03397  *  DstRect: Place of the overlay
03398  *  Flags: some DDOVER_* flags
03399  *
03400  * Returns:
03401  *  DDERR_UNSUPPORTED, because we don't support overlays
03402  *
03403  *****************************************************************************/
03404 static HRESULT WINAPI ddraw_surface7_UpdateOverlay(IDirectDrawSurface7 *iface, RECT *SrcRect,
03405         IDirectDrawSurface7 *DstSurface, RECT *DstRect, DWORD Flags, DDOVERLAYFX *FX)
03406 {
03407     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
03408     IDirectDrawSurfaceImpl *Dst = unsafe_impl_from_IDirectDrawSurface7(DstSurface);
03409     HRESULT hr;
03410 
03411     TRACE("iface %p, src_rect %s, dst_surface %p, dst_rect %s, flags %#x, fx %p.\n",
03412             iface, wine_dbgstr_rect(SrcRect), DstSurface, wine_dbgstr_rect(DstRect), Flags, FX);
03413 
03414     wined3d_mutex_lock();
03415     hr = wined3d_surface_update_overlay(This->wined3d_surface, SrcRect,
03416             Dst ? Dst->wined3d_surface : NULL, DstRect, Flags, (WINEDDOVERLAYFX *)FX);
03417     wined3d_mutex_unlock();
03418 
03419     switch(hr) {
03420         case WINED3DERR_INVALIDCALL:        return DDERR_INVALIDPARAMS;
03421         case WINEDDERR_NOTAOVERLAYSURFACE:  return DDERR_NOTAOVERLAYSURFACE;
03422         case WINEDDERR_OVERLAYNOTVISIBLE:   return DDERR_OVERLAYNOTVISIBLE;
03423         default:
03424             return hr;
03425     }
03426 }
03427 
03428 static HRESULT WINAPI ddraw_surface4_UpdateOverlay(IDirectDrawSurface4 *iface, RECT *src_rect,
03429         IDirectDrawSurface4 *dst_surface, RECT *dst_rect, DWORD flags, DDOVERLAYFX *fx)
03430 {
03431     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
03432     IDirectDrawSurfaceImpl *dst_impl = unsafe_impl_from_IDirectDrawSurface4(dst_surface);
03433     TRACE("iface %p, src_rect %s, dst_surface %p, dst_rect %s, flags %#x, fx %p.\n",
03434             iface, wine_dbgstr_rect(src_rect), dst_surface, wine_dbgstr_rect(dst_rect), flags, fx);
03435 
03436     return ddraw_surface7_UpdateOverlay(&This->IDirectDrawSurface7_iface, src_rect,
03437             dst_impl ? &dst_impl->IDirectDrawSurface7_iface : NULL, dst_rect, flags, fx);
03438 }
03439 
03440 static HRESULT WINAPI ddraw_surface3_UpdateOverlay(IDirectDrawSurface3 *iface, RECT *src_rect,
03441         IDirectDrawSurface3 *dst_surface, RECT *dst_rect, DWORD flags, DDOVERLAYFX *fx)
03442 {
03443     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
03444     IDirectDrawSurfaceImpl *dst_impl = unsafe_impl_from_IDirectDrawSurface3(dst_surface);
03445     TRACE("iface %p, src_rect %s, dst_surface %p, dst_rect %s, flags %#x, fx %p.\n",
03446             iface, wine_dbgstr_rect(src_rect), dst_surface, wine_dbgstr_rect(dst_rect), flags, fx);
03447 
03448     return ddraw_surface7_UpdateOverlay(&This->IDirectDrawSurface7_iface, src_rect,
03449             dst_impl ? &dst_impl->IDirectDrawSurface7_iface : NULL, dst_rect, flags, fx);
03450 }
03451 
03452 static HRESULT WINAPI ddraw_surface2_UpdateOverlay(IDirectDrawSurface2 *iface, RECT *src_rect,
03453         IDirectDrawSurface2 *dst_surface, RECT *dst_rect, DWORD flags, DDOVERLAYFX *fx)
03454 {
03455     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
03456     IDirectDrawSurfaceImpl *dst_impl = unsafe_impl_from_IDirectDrawSurface2(dst_surface);
03457     TRACE("iface %p, src_rect %s, dst_surface %p, dst_rect %s, flags %#x, fx %p.\n",
03458             iface, wine_dbgstr_rect(src_rect), dst_surface, wine_dbgstr_rect(dst_rect), flags, fx);
03459 
03460     return ddraw_surface7_UpdateOverlay(&This->IDirectDrawSurface7_iface, src_rect,
03461             dst_impl ? &dst_impl->IDirectDrawSurface7_iface : NULL, dst_rect, flags, fx);
03462 }
03463 
03464 static HRESULT WINAPI ddraw_surface1_UpdateOverlay(IDirectDrawSurface *iface, RECT *src_rect,
03465         IDirectDrawSurface *dst_surface, RECT *dst_rect, DWORD flags, DDOVERLAYFX *fx)
03466 {
03467     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
03468     IDirectDrawSurfaceImpl *dst_impl = unsafe_impl_from_IDirectDrawSurface(dst_surface);
03469     TRACE("iface %p, src_rect %s, dst_surface %p, dst_rect %s, flags %#x, fx %p.\n",
03470             iface, wine_dbgstr_rect(src_rect), dst_surface, wine_dbgstr_rect(dst_rect), flags, fx);
03471 
03472     return ddraw_surface7_UpdateOverlay(&This->IDirectDrawSurface7_iface, src_rect,
03473             dst_impl ? &dst_impl->IDirectDrawSurface7_iface : NULL, dst_rect, flags, fx);
03474 }
03475 
03476 /*****************************************************************************
03477  * IDirectDrawSurface7::UpdateOverlayDisplay
03478  *
03479  * The DX7 sdk says that it's not implemented
03480  *
03481  * Params:
03482  *  Flags: ?
03483  *
03484  * Returns: DDERR_UNSUPPORTED, because we don't support overlays
03485  *
03486  *****************************************************************************/
03487 static HRESULT WINAPI ddraw_surface7_UpdateOverlayDisplay(IDirectDrawSurface7 *iface, DWORD Flags)
03488 {
03489     TRACE("iface %p, flags %#x.\n", iface, Flags);
03490 
03491     return DDERR_UNSUPPORTED;
03492 }
03493 
03494 static HRESULT WINAPI ddraw_surface4_UpdateOverlayDisplay(IDirectDrawSurface4 *iface, DWORD flags)
03495 {
03496     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
03497     TRACE("iface %p, flags %#x.\n", iface, flags);
03498 
03499     return ddraw_surface7_UpdateOverlayDisplay(&This->IDirectDrawSurface7_iface, flags);
03500 }
03501 
03502 static HRESULT WINAPI ddraw_surface3_UpdateOverlayDisplay(IDirectDrawSurface3 *iface, DWORD flags)
03503 {
03504     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
03505     TRACE("iface %p, flags %#x.\n", iface, flags);
03506 
03507     return ddraw_surface7_UpdateOverlayDisplay(&This->IDirectDrawSurface7_iface, flags);
03508 }
03509 
03510 static HRESULT WINAPI ddraw_surface2_UpdateOverlayDisplay(IDirectDrawSurface2 *iface, DWORD flags)
03511 {
03512     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
03513     TRACE("iface %p, flags %#x.\n", iface, flags);
03514 
03515     return ddraw_surface7_UpdateOverlayDisplay(&This->IDirectDrawSurface7_iface, flags);
03516 }
03517 
03518 static HRESULT WINAPI ddraw_surface1_UpdateOverlayDisplay(IDirectDrawSurface *iface, DWORD flags)
03519 {
03520     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
03521     TRACE("iface %p, flags %#x.\n", iface, flags);
03522 
03523     return ddraw_surface7_UpdateOverlayDisplay(&This->IDirectDrawSurface7_iface, flags);
03524 }
03525 
03526 /*****************************************************************************
03527  * IDirectDrawSurface7::UpdateOverlayZOrder
03528  *
03529  * Sets an overlay's Z order
03530  *
03531  * Params:
03532  *  Flags: DDOVERZ_* flags
03533  *  DDSRef: Defines the relative position in the overlay chain
03534  *
03535  * Returns:
03536  *  DDERR_NOTOVERLAYSURFACE, because we don't support overlays
03537  *
03538  *****************************************************************************/
03539 static HRESULT WINAPI ddraw_surface7_UpdateOverlayZOrder(IDirectDrawSurface7 *iface,
03540         DWORD Flags, IDirectDrawSurface7 *DDSRef)
03541 {
03542     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
03543     IDirectDrawSurfaceImpl *Ref = unsafe_impl_from_IDirectDrawSurface7(DDSRef);
03544     HRESULT hr;
03545 
03546     TRACE("iface %p, flags %#x, reference %p.\n", iface, Flags, DDSRef);
03547 
03548     wined3d_mutex_lock();
03549     hr = wined3d_surface_update_overlay_z_order(This->wined3d_surface,
03550             Flags, Ref ? Ref->wined3d_surface : NULL);
03551     wined3d_mutex_unlock();
03552 
03553     return hr;
03554 }
03555 
03556 static HRESULT WINAPI ddraw_surface4_UpdateOverlayZOrder(IDirectDrawSurface4 *iface,
03557         DWORD flags, IDirectDrawSurface4 *reference)
03558 {
03559     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
03560     IDirectDrawSurfaceImpl *reference_impl = unsafe_impl_from_IDirectDrawSurface4(reference);
03561     TRACE("iface %p, flags %#x, reference %p.\n", iface, flags, reference);
03562 
03563     return ddraw_surface7_UpdateOverlayZOrder(&This->IDirectDrawSurface7_iface, flags,
03564             reference_impl ? &reference_impl->IDirectDrawSurface7_iface : NULL);
03565 }
03566 
03567 static HRESULT WINAPI ddraw_surface3_UpdateOverlayZOrder(IDirectDrawSurface3 *iface,
03568         DWORD flags, IDirectDrawSurface3 *reference)
03569 {
03570     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
03571     IDirectDrawSurfaceImpl *reference_impl = unsafe_impl_from_IDirectDrawSurface3(reference);
03572     TRACE("iface %p, flags %#x, reference %p.\n", iface, flags, reference);
03573 
03574     return ddraw_surface7_UpdateOverlayZOrder(&This->IDirectDrawSurface7_iface, flags,
03575             reference_impl ? &reference_impl->IDirectDrawSurface7_iface : NULL);
03576 }
03577 
03578 static HRESULT WINAPI ddraw_surface2_UpdateOverlayZOrder(IDirectDrawSurface2 *iface,
03579         DWORD flags, IDirectDrawSurface2 *reference)
03580 {
03581     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
03582     IDirectDrawSurfaceImpl *reference_impl = unsafe_impl_from_IDirectDrawSurface2(reference);
03583     TRACE("iface %p, flags %#x, reference %p.\n", iface, flags, reference);
03584 
03585     return ddraw_surface7_UpdateOverlayZOrder(&This->IDirectDrawSurface7_iface, flags,
03586             reference_impl ? &reference_impl->IDirectDrawSurface7_iface : NULL);
03587 }
03588 
03589 static HRESULT WINAPI ddraw_surface1_UpdateOverlayZOrder(IDirectDrawSurface *iface,
03590         DWORD flags, IDirectDrawSurface *reference)
03591 {
03592     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
03593     IDirectDrawSurfaceImpl *reference_impl = unsafe_impl_from_IDirectDrawSurface(reference);
03594     TRACE("iface %p, flags %#x, reference %p.\n", iface, flags, reference);
03595 
03596     return ddraw_surface7_UpdateOverlayZOrder(&This->IDirectDrawSurface7_iface, flags,
03597             reference_impl ? &reference_impl->IDirectDrawSurface7_iface : NULL);
03598 }
03599 
03600 /*****************************************************************************
03601  * IDirectDrawSurface7::GetDDInterface
03602  *
03603  * Returns the IDirectDraw7 interface pointer of the DirectDraw object this
03604  * surface belongs to
03605  *
03606  * Params:
03607  *  DD: Address to write the interface pointer to
03608  *
03609  * Returns:
03610  *  DD_OK on success
03611  *  DDERR_INVALIDPARAMS if DD is NULL
03612  *
03613  *****************************************************************************/
03614 static HRESULT WINAPI ddraw_surface7_GetDDInterface(IDirectDrawSurface7 *iface, void **DD)
03615 {
03616     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
03617 
03618     TRACE("iface %p, ddraw %p.\n", iface, DD);
03619 
03620     if(!DD)
03621         return DDERR_INVALIDPARAMS;
03622 
03623     switch(This->version)
03624     {
03625         case 7:
03626             *DD = &This->ddraw->IDirectDraw7_iface;
03627             break;
03628 
03629         case 4:
03630             *DD = &This->ddraw->IDirectDraw4_iface;
03631             break;
03632 
03633         case 2:
03634             *DD = &This->ddraw->IDirectDraw2_iface;
03635             break;
03636 
03637         case 1:
03638             *DD = &This->ddraw->IDirectDraw_iface;
03639             break;
03640 
03641     }
03642     IUnknown_AddRef((IUnknown *)*DD);
03643 
03644     return DD_OK;
03645 }
03646 
03647 static HRESULT WINAPI ddraw_surface4_GetDDInterface(IDirectDrawSurface4 *iface, void **ddraw)
03648 {
03649     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
03650     TRACE("iface %p, ddraw %p.\n", iface, ddraw);
03651 
03652     return ddraw_surface7_GetDDInterface(&This->IDirectDrawSurface7_iface, ddraw);
03653 }
03654 
03655 static HRESULT WINAPI ddraw_surface3_GetDDInterface(IDirectDrawSurface3 *iface, void **ddraw)
03656 {
03657     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
03658     TRACE("iface %p, ddraw %p.\n", iface, ddraw);
03659 
03660     return ddraw_surface7_GetDDInterface(&This->IDirectDrawSurface7_iface, ddraw);
03661 }
03662 
03663 static HRESULT WINAPI ddraw_surface2_GetDDInterface(IDirectDrawSurface2 *iface, void **ddraw)
03664 {
03665     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
03666     TRACE("iface %p, ddraw %p.\n", iface, ddraw);
03667 
03668     return ddraw_surface7_GetDDInterface(&This->IDirectDrawSurface7_iface, ddraw);
03669 }
03670 
03671 /* This seems also windows implementation specific - I don't think WineD3D needs this */
03672 static HRESULT WINAPI ddraw_surface7_ChangeUniquenessValue(IDirectDrawSurface7 *iface)
03673 {
03674     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
03675     volatile IDirectDrawSurfaceImpl* vThis = This;
03676 
03677     TRACE("iface %p.\n", iface);
03678 
03679     wined3d_mutex_lock();
03680     /* A uniqueness value of 0 is apparently special.
03681      * This needs to be checked.
03682      * TODO: Write tests for this code and check if the volatile, interlocked stuff is really needed
03683      */
03684     while (1) {
03685         DWORD old_uniqueness_value = vThis->uniqueness_value;
03686         DWORD new_uniqueness_value = old_uniqueness_value+1;
03687 
03688         if (old_uniqueness_value == 0) break;
03689         if (new_uniqueness_value == 0) new_uniqueness_value = 1;
03690 
03691         if (InterlockedCompareExchange((LONG*)&vThis->uniqueness_value,
03692                                       old_uniqueness_value,
03693                                       new_uniqueness_value)
03694             == old_uniqueness_value)
03695             break;
03696     }
03697 
03698     wined3d_mutex_unlock();
03699 
03700     return DD_OK;
03701 }
03702 
03703 static HRESULT WINAPI ddraw_surface4_ChangeUniquenessValue(IDirectDrawSurface4 *iface)
03704 {
03705     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
03706     TRACE("iface %p.\n", iface);
03707 
03708     return ddraw_surface7_ChangeUniquenessValue(&This->IDirectDrawSurface7_iface);
03709 }
03710 
03711 static HRESULT WINAPI ddraw_surface7_GetUniquenessValue(IDirectDrawSurface7 *iface, DWORD *pValue)
03712 {
03713     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
03714 
03715     TRACE("iface %p, value %p.\n", iface, pValue);
03716 
03717     wined3d_mutex_lock();
03718     *pValue = This->uniqueness_value;
03719     wined3d_mutex_unlock();
03720 
03721     return DD_OK;
03722 }
03723 
03724 static HRESULT WINAPI ddraw_surface4_GetUniquenessValue(IDirectDrawSurface4 *iface, DWORD *pValue)
03725 {
03726     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
03727     TRACE("iface %p, value %p.\n", iface, pValue);
03728 
03729     return ddraw_surface7_GetUniquenessValue(&This->IDirectDrawSurface7_iface, pValue);
03730 }
03731 
03732 /*****************************************************************************
03733  * IDirectDrawSurface7::SetLOD
03734  *
03735  * Sets the level of detail of a texture
03736  *
03737  * Params:
03738  *  MaxLOD: LOD to set
03739  *
03740  * Returns:
03741  *  DD_OK on success
03742  *  DDERR_INVALIDOBJECT if the surface is invalid for this method
03743  *
03744  *****************************************************************************/
03745 static HRESULT WINAPI ddraw_surface7_SetLOD(IDirectDrawSurface7 *iface, DWORD MaxLOD)
03746 {
03747     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
03748     HRESULT hr;
03749 
03750     TRACE("iface %p, lod %u.\n", iface, MaxLOD);
03751 
03752     wined3d_mutex_lock();
03753     if (!(This->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_TEXTUREMANAGE))
03754     {
03755         wined3d_mutex_unlock();
03756         return DDERR_INVALIDOBJECT;
03757     }
03758 
03759     if (!This->wined3d_texture)
03760     {
03761         ERR("(%p) The DirectDraw texture has no WineD3DTexture!\n", This);
03762         wined3d_mutex_unlock();
03763         return DDERR_INVALIDOBJECT;
03764     }
03765 
03766     hr = wined3d_texture_set_lod(This->wined3d_texture, MaxLOD);
03767     wined3d_mutex_unlock();
03768 
03769     return hr;
03770 }
03771 
03772 /*****************************************************************************
03773  * IDirectDrawSurface7::GetLOD
03774  *
03775  * Returns the level of detail of a Direct3D texture
03776  *
03777  * Params:
03778  *  MaxLOD: Address to write the LOD to
03779  *
03780  * Returns:
03781  *  DD_OK on success
03782  *  DDERR_INVALIDPARAMS if MaxLOD is NULL
03783  *  DDERR_INVALIDOBJECT if the surface is invalid for this method
03784  *
03785  *****************************************************************************/
03786 static HRESULT WINAPI ddraw_surface7_GetLOD(IDirectDrawSurface7 *iface, DWORD *MaxLOD)
03787 {
03788     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
03789 
03790     TRACE("iface %p, lod %p.\n", iface, MaxLOD);
03791 
03792     if(!MaxLOD)
03793         return DDERR_INVALIDPARAMS;
03794 
03795     wined3d_mutex_lock();
03796     if (!(This->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_TEXTUREMANAGE))
03797     {
03798         wined3d_mutex_unlock();
03799         return DDERR_INVALIDOBJECT;
03800     }
03801 
03802     *MaxLOD = wined3d_texture_get_lod(This->wined3d_texture);
03803     wined3d_mutex_unlock();
03804 
03805     return DD_OK;
03806 }
03807 
03808 /*****************************************************************************
03809  * IDirectDrawSurface7::BltFast
03810  *
03811  * Performs a fast Blit.
03812  *
03813  * Params:
03814  *  dstx: The x coordinate to blit to on the destination
03815  *  dsty: The y coordinate to blit to on the destination
03816  *  Source: The source surface
03817  *  rsrc: The source rectangle
03818  *  trans: Type of transfer. Some DDBLTFAST_* flags
03819  *
03820  * Returns:
03821  *  DD_OK on success
03822  *  For more details, see IWineD3DSurface::BltFast
03823  *
03824  *****************************************************************************/
03825 static HRESULT WINAPI ddraw_surface7_BltFast(IDirectDrawSurface7 *iface, DWORD dstx, DWORD dsty,
03826         IDirectDrawSurface7 *Source, RECT *rsrc, DWORD trans)
03827 {
03828     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
03829     IDirectDrawSurfaceImpl *src = unsafe_impl_from_IDirectDrawSurface7(Source);
03830     DWORD src_w, src_h, dst_w, dst_h;
03831     HRESULT hr = DD_OK;
03832     DWORD flags = 0;
03833     RECT dst_rect;
03834 
03835     TRACE("iface %p, dst_x %u, dst_y %u, src_surface %p, src_rect %s, flags %#x.\n",
03836             iface, dstx, dsty, Source, wine_dbgstr_rect(rsrc), trans);
03837 
03838     dst_w = This->surface_desc.dwWidth;
03839     dst_h = This->surface_desc.dwHeight;
03840 
03841     /* Source must be != NULL, This is not checked by windows. Windows happily throws a 0xc0000005
03842      * in that case
03843      */
03844     if(rsrc)
03845     {
03846         src_w = rsrc->right - rsrc->left;
03847         src_h = rsrc->bottom - rsrc->top;
03848     }
03849     else
03850     {
03851         src_w = src->surface_desc.dwWidth;
03852         src_h = src->surface_desc.dwHeight;
03853     }
03854 
03855     if (src_w > dst_w || dstx > dst_w - src_w
03856             || src_h > dst_h || dsty > dst_h - src_h)
03857     {
03858         WARN("Destination area out of bounds, returning DDERR_INVALIDRECT.\n");
03859         return DDERR_INVALIDRECT;
03860     }
03861 
03862     SetRect(&dst_rect, dstx, dsty, dstx + src_w, dsty + src_h);
03863     if (trans & DDBLTFAST_SRCCOLORKEY)
03864         flags |= WINEDDBLT_KEYSRC;
03865     if (trans & DDBLTFAST_DESTCOLORKEY)
03866         flags |= WINEDDBLT_KEYDEST;
03867     if (trans & DDBLTFAST_WAIT)
03868         flags |= WINEDDBLT_WAIT;
03869     if (trans & DDBLTFAST_DONOTWAIT)
03870         flags |= WINEDDBLT_DONOTWAIT;
03871 
03872     wined3d_mutex_lock();
03873     if (This->clipper)
03874     {
03875         wined3d_mutex_unlock();
03876         WARN("Destination surface has a clipper set, returning DDERR_BLTFASTCANTCLIP.\n");
03877         return DDERR_BLTFASTCANTCLIP;
03878     }
03879 
03880     if (src->surface_desc.ddsCaps.dwCaps & DDSCAPS_FRONTBUFFER)
03881         hr = ddraw_surface_update_frontbuffer(src, rsrc, TRUE);
03882     if (SUCCEEDED(hr))
03883         hr = wined3d_surface_blt(This->wined3d_surface, &dst_rect,
03884                 src->wined3d_surface, rsrc, flags, NULL, WINED3D_TEXF_POINT);
03885     if (SUCCEEDED(hr) && (This->surface_desc.ddsCaps.dwCaps & DDSCAPS_FRONTBUFFER))
03886         hr = ddraw_surface_update_frontbuffer(This, &dst_rect, FALSE);
03887     wined3d_mutex_unlock();
03888 
03889     switch(hr)
03890     {
03891         case WINED3DERR_NOTAVAILABLE:           return DDERR_UNSUPPORTED;
03892         case WINED3DERR_WRONGTEXTUREFORMAT:     return DDERR_INVALIDPIXELFORMAT;
03893         default:                                return hr;
03894     }
03895 }
03896 
03897 static HRESULT WINAPI ddraw_surface4_BltFast(IDirectDrawSurface4 *iface, DWORD dst_x, DWORD dst_y,
03898         IDirectDrawSurface4 *src_surface, RECT *src_rect, DWORD flags)
03899 {
03900     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
03901     IDirectDrawSurfaceImpl *src_impl = unsafe_impl_from_IDirectDrawSurface4(src_surface);
03902     TRACE("iface %p, dst_x %u, dst_y %u, src_surface %p, src_rect %s, flags %#x.\n",
03903             iface, dst_x, dst_y, src_surface, wine_dbgstr_rect(src_rect), flags);
03904 
03905     return ddraw_surface7_BltFast(&This->IDirectDrawSurface7_iface, dst_x, dst_y,
03906             src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, src_rect, flags);
03907 }
03908 
03909 static HRESULT WINAPI ddraw_surface3_BltFast(IDirectDrawSurface3 *iface, DWORD dst_x, DWORD dst_y,
03910         IDirectDrawSurface3 *src_surface, RECT *src_rect, DWORD flags)
03911 {
03912     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
03913     IDirectDrawSurfaceImpl *src_impl = unsafe_impl_from_IDirectDrawSurface3(src_surface);
03914     TRACE("iface %p, dst_x %u, dst_y %u, src_surface %p, src_rect %s, flags %#x.\n",
03915             iface, dst_x, dst_y, src_surface, wine_dbgstr_rect(src_rect), flags);
03916 
03917     return ddraw_surface7_BltFast(&This->IDirectDrawSurface7_iface, dst_x, dst_y,
03918             src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, src_rect, flags);
03919 }
03920 
03921 static HRESULT WINAPI ddraw_surface2_BltFast(IDirectDrawSurface2 *iface, DWORD dst_x, DWORD dst_y,
03922         IDirectDrawSurface2 *src_surface, RECT *src_rect, DWORD flags)
03923 {
03924     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
03925     IDirectDrawSurfaceImpl *src_impl = unsafe_impl_from_IDirectDrawSurface2(src_surface);
03926     TRACE("iface %p, dst_x %u, dst_y %u, src_surface %p, src_rect %s, flags %#x.\n",
03927             iface, dst_x, dst_y, src_surface, wine_dbgstr_rect(src_rect), flags);
03928 
03929     return ddraw_surface7_BltFast(&This->IDirectDrawSurface7_iface, dst_x, dst_y,
03930             src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, src_rect, flags);
03931 }
03932 
03933 static HRESULT WINAPI ddraw_surface1_BltFast(IDirectDrawSurface *iface, DWORD dst_x, DWORD dst_y,
03934         IDirectDrawSurface *src_surface, RECT *src_rect, DWORD flags)
03935 {
03936     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
03937     IDirectDrawSurfaceImpl *src_impl = unsafe_impl_from_IDirectDrawSurface(src_surface);
03938     TRACE("iface %p, dst_x %u, dst_y %u, src_surface %p, src_rect %s, flags %#x.\n",
03939             iface, dst_x, dst_y, src_surface, wine_dbgstr_rect(src_rect), flags);
03940 
03941     return ddraw_surface7_BltFast(&This->IDirectDrawSurface7_iface, dst_x, dst_y,
03942             src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, src_rect, flags);
03943 }
03944 
03945 /*****************************************************************************
03946  * IDirectDrawSurface7::GetClipper
03947  *
03948  * Returns the IDirectDrawClipper interface of the clipper assigned to this
03949  * surface
03950  *
03951  * Params:
03952  *  Clipper: Address to store the interface pointer at
03953  *
03954  * Returns:
03955  *  DD_OK on success
03956  *  DDERR_INVALIDPARAMS if Clipper is NULL
03957  *  DDERR_NOCLIPPERATTACHED if there's no clipper attached
03958  *
03959  *****************************************************************************/
03960 static HRESULT WINAPI ddraw_surface7_GetClipper(IDirectDrawSurface7 *iface, IDirectDrawClipper **Clipper)
03961 {
03962     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
03963 
03964     TRACE("iface %p, clipper %p.\n", iface, Clipper);
03965 
03966     if (!Clipper)
03967         return DDERR_INVALIDPARAMS;
03968 
03969     wined3d_mutex_lock();
03970     if(This->clipper == NULL)
03971     {
03972         wined3d_mutex_unlock();
03973         return DDERR_NOCLIPPERATTACHED;
03974     }
03975 
03976     *Clipper = (IDirectDrawClipper *)This->clipper;
03977     IDirectDrawClipper_AddRef(*Clipper);
03978     wined3d_mutex_unlock();
03979 
03980     return DD_OK;
03981 }
03982 
03983 static HRESULT WINAPI ddraw_surface4_GetClipper(IDirectDrawSurface4 *iface, IDirectDrawClipper **clipper)
03984 {
03985     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
03986     TRACE("iface %p, clipper %p.\n", iface, clipper);
03987 
03988     return ddraw_surface7_GetClipper(&This->IDirectDrawSurface7_iface, clipper);
03989 }
03990 
03991 static HRESULT WINAPI ddraw_surface3_GetClipper(IDirectDrawSurface3 *iface, IDirectDrawClipper **clipper)
03992 {
03993     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
03994     TRACE("iface %p, clipper %p.\n", iface, clipper);
03995 
03996     return ddraw_surface7_GetClipper(&This->IDirectDrawSurface7_iface, clipper);
03997 }
03998 
03999 static HRESULT WINAPI ddraw_surface2_GetClipper(IDirectDrawSurface2 *iface, IDirectDrawClipper **clipper)
04000 {
04001     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
04002     TRACE("iface %p, clipper %p.\n", iface, clipper);
04003 
04004     return ddraw_surface7_GetClipper(&This->IDirectDrawSurface7_iface, clipper);
04005 }
04006 
04007 static HRESULT WINAPI ddraw_surface1_GetClipper(IDirectDrawSurface *iface, IDirectDrawClipper **clipper)
04008 {
04009     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
04010     TRACE("iface %p, clipper %p.\n", iface, clipper);
04011 
04012     return ddraw_surface7_GetClipper(&This->IDirectDrawSurface7_iface, clipper);
04013 }
04014 
04015 /*****************************************************************************
04016  * IDirectDrawSurface7::SetClipper
04017  *
04018  * Sets a clipper for the surface
04019  *
04020  * Params:
04021  *  Clipper: IDirectDrawClipper interface of the clipper to set
04022  *
04023  * Returns:
04024  *  DD_OK on success
04025  *
04026  *****************************************************************************/
04027 static HRESULT WINAPI ddraw_surface7_SetClipper(IDirectDrawSurface7 *iface,
04028         IDirectDrawClipper *iclipper)
04029 {
04030     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
04031     struct ddraw_clipper *clipper = unsafe_impl_from_IDirectDrawClipper(iclipper);
04032     struct ddraw_clipper *old_clipper = This->clipper;
04033     HWND clipWindow;
04034 
04035     TRACE("iface %p, clipper %p.\n", iface, iclipper);
04036 
04037     wined3d_mutex_lock();
04038     if (clipper == This->clipper)
04039     {
04040         wined3d_mutex_unlock();
04041         return DD_OK;
04042     }
04043 
04044     This->clipper = clipper;
04045 
04046     if (clipper != NULL)
04047         IDirectDrawClipper_AddRef(iclipper);
04048     if (old_clipper)
04049         IDirectDrawClipper_Release(&old_clipper->IDirectDrawClipper_iface);
04050 
04051     if ((This->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) && This->ddraw->wined3d_swapchain)
04052     {
04053         clipWindow = NULL;
04054         if(clipper) {
04055             IDirectDrawClipper_GetHWnd(iclipper, &clipWindow);
04056         }
04057 
04058         if (clipWindow)
04059         {
04060             wined3d_swapchain_set_window(This->ddraw->wined3d_swapchain, clipWindow);
04061             ddraw_set_swapchain_window(This->ddraw, clipWindow);
04062         }
04063         else
04064         {
04065             wined3d_swapchain_set_window(This->ddraw->wined3d_swapchain, This->ddraw->d3d_window);
04066             ddraw_set_swapchain_window(This->ddraw, This->ddraw->dest_window);
04067         }
04068     }
04069 
04070     wined3d_mutex_unlock();
04071 
04072     return DD_OK;
04073 }
04074 
04075 static HRESULT WINAPI ddraw_surface4_SetClipper(IDirectDrawSurface4 *iface, IDirectDrawClipper *clipper)
04076 {
04077     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
04078     TRACE("iface %p, clipper %p.\n", iface, clipper);
04079 
04080     return ddraw_surface7_SetClipper(&This->IDirectDrawSurface7_iface, clipper);
04081 }
04082 
04083 static HRESULT WINAPI ddraw_surface3_SetClipper(IDirectDrawSurface3 *iface, IDirectDrawClipper *clipper)
04084 {
04085     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
04086     TRACE("iface %p, clipper %p.\n", iface, clipper);
04087 
04088     return ddraw_surface7_SetClipper(&This->IDirectDrawSurface7_iface, clipper);
04089 }
04090 
04091 static HRESULT WINAPI ddraw_surface2_SetClipper(IDirectDrawSurface2 *iface, IDirectDrawClipper *clipper)
04092 {
04093     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
04094     TRACE("iface %p, clipper %p.\n", iface, clipper);
04095 
04096     return ddraw_surface7_SetClipper(&This->IDirectDrawSurface7_iface, clipper);
04097 }
04098 
04099 static HRESULT WINAPI ddraw_surface1_SetClipper(IDirectDrawSurface *iface, IDirectDrawClipper *clipper)
04100 {
04101     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
04102     TRACE("iface %p, clipper %p.\n", iface, clipper);
04103 
04104     return ddraw_surface7_SetClipper(&This->IDirectDrawSurface7_iface, clipper);
04105 }
04106 
04107 /*****************************************************************************
04108  * IDirectDrawSurface7::SetSurfaceDesc
04109  *
04110  * Sets the surface description. It can override the pixel format, the surface
04111  * memory, ...
04112  * It's not really tested.
04113  *
04114  * Params:
04115  * DDSD: Pointer to the new surface description to set
04116  * Flags: Some flags
04117  *
04118  * Returns:
04119  *  DD_OK on success
04120  *  DDERR_INVALIDPARAMS if DDSD is NULL
04121  *
04122  *****************************************************************************/
04123 static HRESULT WINAPI ddraw_surface7_SetSurfaceDesc(IDirectDrawSurface7 *iface, DDSURFACEDESC2 *DDSD, DWORD Flags)
04124 {
04125     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
04126     HRESULT hr;
04127     const DWORD allowed_flags = DDSD_LPSURFACE | DDSD_PIXELFORMAT | DDSD_WIDTH
04128             | DDSD_HEIGHT | DDSD_PITCH | DDSD_CAPS;
04129     enum wined3d_format_id format_id;
04130     BOOL update_wined3d = FALSE;
04131     UINT width, height;
04132 
04133     TRACE("iface %p, surface_desc %p, flags %#x.\n", iface, DDSD, Flags);
04134 
04135     if (!DDSD)
04136     {
04137         WARN("DDSD is NULL, returning DDERR_INVALIDPARAMS\n");
04138         return DDERR_INVALIDPARAMS;
04139     }
04140     if (Flags)
04141     {
04142         WARN("Flags is %x, returning DDERR_INVALIDPARAMS\n", Flags);
04143         return DDERR_INVALIDPARAMS;
04144     }
04145     if (!(This->surface_desc.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY))
04146     {
04147         WARN("Surface is not in system memory, returning DDERR_INVALIDSURFACETYPE.\n");
04148         return DDERR_INVALIDSURFACETYPE;
04149     }
04150 
04151     /* Tests show that only LPSURFACE and PIXELFORMAT can be set, and LPSURFACE is required
04152      * for PIXELFORMAT to work */
04153     if (DDSD->dwFlags & ~allowed_flags)
04154     {
04155         WARN("Invalid flags (0x%08x) set, returning DDERR_INVALIDPARAMS\n", DDSD->dwFlags);
04156         return DDERR_INVALIDPARAMS;
04157     }
04158     if (!(DDSD->dwFlags & DDSD_LPSURFACE))
04159     {
04160         WARN("DDSD_LPSURFACE is not set, returning DDERR_INVALIDPARAMS\n");
04161         return DDERR_INVALIDPARAMS;
04162     }
04163     if (DDSD->dwFlags & DDSD_CAPS)
04164     {
04165         WARN("DDSD_CAPS is set, returning DDERR_INVALIDCAPS.\n");
04166         return DDERR_INVALIDCAPS;
04167     }
04168     if (DDSD->dwFlags & DDSD_WIDTH)
04169     {
04170         if (!(DDSD->dwFlags & DDSD_PITCH))
04171         {
04172             WARN("DDSD_WIDTH is set, but DDSD_PITCH is not, returning DDERR_INVALIDPARAMS.\n");
04173             return DDERR_INVALIDPARAMS;
04174         }
04175         if (!DDSD->dwWidth || DDSD->u1.lPitch <= 0 || DDSD->u1.lPitch & 0x3)
04176         {
04177             WARN("Pitch is %d, width is %u, returning DDERR_INVALIDPARAMS.\n",
04178                     DDSD->u1.lPitch, DDSD->dwWidth);
04179             return DDERR_INVALIDPARAMS;
04180         }
04181         if (DDSD->dwWidth != This->surface_desc.dwWidth)
04182         {
04183             TRACE("Surface width changed from %u to %u.\n", This->surface_desc.dwWidth, DDSD->dwWidth);
04184             update_wined3d = TRUE;
04185         }
04186         if (DDSD->u1.lPitch != This->surface_desc.u1.lPitch)
04187         {
04188             TRACE("Surface pitch changed from %u to %u.\n", This->surface_desc.u1.lPitch, DDSD->u1.lPitch);
04189             update_wined3d = TRUE;
04190         }
04191         width = DDSD->dwWidth;
04192     }
04193     else if (DDSD->dwFlags & DDSD_PITCH)
04194     {
04195         WARN("DDSD_PITCH is set, but DDSD_WIDTH is not, returning DDERR_INVALIDPARAMS.\n");
04196         return DDERR_INVALIDPARAMS;
04197     }
04198     else
04199     {
04200         width = This->surface_desc.dwWidth;
04201     }
04202 
04203     if (DDSD->dwFlags & DDSD_HEIGHT)
04204     {
04205         if (!DDSD->dwHeight)
04206         {
04207             WARN("Height is 0, returning DDERR_INVALIDPARAMS.\n");
04208             return DDERR_INVALIDPARAMS;
04209         }
04210         if (DDSD->dwHeight != This->surface_desc.dwHeight)
04211         {
04212             TRACE("Surface height changed from %u to %u.\n", This->surface_desc.dwHeight, DDSD->dwHeight);
04213             update_wined3d = TRUE;
04214         }
04215         height = DDSD->dwHeight;
04216     }
04217     else
04218     {
04219         height = This->surface_desc.dwHeight;
04220     }
04221 
04222     wined3d_mutex_lock();
04223     if (DDSD->dwFlags & DDSD_PIXELFORMAT)
04224     {
04225         enum wined3d_format_id current_format_id;
04226         format_id = PixelFormat_DD2WineD3D(&DDSD->u4.ddpfPixelFormat);
04227 
04228         if (format_id == WINED3DFMT_UNKNOWN)
04229         {
04230             ERR("Requested to set an unknown pixelformat\n");
04231             wined3d_mutex_unlock();
04232             return DDERR_INVALIDPARAMS;
04233         }
04234         current_format_id = PixelFormat_DD2WineD3D(&This->surface_desc.u4.ddpfPixelFormat);
04235         if (format_id != current_format_id)
04236         {
04237             TRACE("Surface format changed from %#x to %#x.\n", current_format_id, format_id);
04238             update_wined3d = TRUE;
04239         }
04240     }
04241     else
04242     {
04243         format_id = PixelFormat_DD2WineD3D(&This->surface_desc.u4.ddpfPixelFormat);
04244     }
04245 
04246     if (update_wined3d)
04247     {
04248         if (FAILED(hr = wined3d_surface_update_desc(This->wined3d_surface, width, height,
04249                 format_id, WINED3D_MULTISAMPLE_NONE, 0)))
04250         {
04251             WARN("Failed to update surface desc, hr %#x.\n", hr);
04252             wined3d_mutex_unlock();
04253             return hr;
04254         }
04255 
04256         if (DDSD->dwFlags & DDSD_WIDTH)
04257             This->surface_desc.dwWidth = width;
04258         if (DDSD->dwFlags & DDSD_PITCH)
04259             This->surface_desc.u1.lPitch = DDSD->u1.lPitch;
04260         if (DDSD->dwFlags & DDSD_HEIGHT)
04261             This->surface_desc.dwHeight = height;
04262         if (DDSD->dwFlags & DDSD_PIXELFORMAT)
04263             This->surface_desc.u4.ddpfPixelFormat = DDSD->u4.ddpfPixelFormat;
04264     }
04265 
04266     if (DDSD->dwFlags & DDSD_LPSURFACE && DDSD->lpSurface)
04267     {
04268         hr = wined3d_surface_set_mem(This->wined3d_surface, DDSD->lpSurface);
04269         if (FAILED(hr))
04270         {
04271             /* No need for a trace here, wined3d does that for us */
04272             switch(hr)
04273             {
04274                 case WINED3DERR_INVALIDCALL:
04275                     wined3d_mutex_unlock();
04276                     return DDERR_INVALIDPARAMS;
04277                 default:
04278                     break; /* Go on */
04279             }
04280         }
04281         /* DDSD->lpSurface is set by Lock() */
04282     }
04283 
04284     wined3d_mutex_unlock();
04285 
04286     return DD_OK;
04287 }
04288 
04289 static HRESULT WINAPI ddraw_surface4_SetSurfaceDesc(IDirectDrawSurface4 *iface,
04290         DDSURFACEDESC2 *surface_desc, DWORD flags)
04291 {
04292     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
04293     TRACE("iface %p, surface_desc %p, flags %#x.\n", iface, surface_desc, flags);
04294 
04295     return ddraw_surface7_SetSurfaceDesc(&This->IDirectDrawSurface7_iface,
04296             surface_desc, flags);
04297 }
04298 
04299 static HRESULT WINAPI ddraw_surface3_SetSurfaceDesc(IDirectDrawSurface3 *iface,
04300         DDSURFACEDESC *surface_desc, DWORD flags)
04301 {
04302     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
04303     DDSURFACEDESC2 surface_desc2;
04304     TRACE("iface %p, surface_desc %p, flags %#x.\n", iface, surface_desc, flags);
04305 
04306     if (surface_desc) DDSD_to_DDSD2(surface_desc, &surface_desc2);
04307     return ddraw_surface7_SetSurfaceDesc(&This->IDirectDrawSurface7_iface,
04308             surface_desc ? &surface_desc2 : NULL, flags);
04309 }
04310 
04311 /*****************************************************************************
04312  * IDirectDrawSurface7::GetPalette
04313  *
04314  * Returns the IDirectDrawPalette interface of the palette currently assigned
04315  * to the surface
04316  *
04317  * Params:
04318  *  Pal: Address to write the interface pointer to
04319  *
04320  * Returns:
04321  *  DD_OK on success
04322  *  DDERR_INVALIDPARAMS if Pal is NULL
04323  *
04324  *****************************************************************************/
04325 static HRESULT WINAPI ddraw_surface7_GetPalette(IDirectDrawSurface7 *iface, IDirectDrawPalette **Pal)
04326 {
04327     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
04328     struct wined3d_palette *wined3d_palette;
04329     HRESULT hr = DD_OK;
04330 
04331     TRACE("iface %p, palette %p.\n", iface, Pal);
04332 
04333     if(!Pal)
04334         return DDERR_INVALIDPARAMS;
04335 
04336     wined3d_mutex_lock();
04337     wined3d_palette = wined3d_surface_get_palette(This->wined3d_surface);
04338     if (wined3d_palette)
04339     {
04340         *Pal = wined3d_palette_get_parent(wined3d_palette);
04341         IDirectDrawPalette_AddRef(*Pal);
04342     }
04343     else
04344     {
04345         *Pal = NULL;
04346         hr = DDERR_NOPALETTEATTACHED;
04347     }
04348 
04349     wined3d_mutex_unlock();
04350 
04351     return hr;
04352 }
04353 
04354 static HRESULT WINAPI ddraw_surface4_GetPalette(IDirectDrawSurface4 *iface, IDirectDrawPalette **palette)
04355 {
04356     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
04357     TRACE("iface %p, palette %p.\n", iface, palette);
04358 
04359     return ddraw_surface7_GetPalette(&This->IDirectDrawSurface7_iface, palette);
04360 }
04361 
04362 static HRESULT WINAPI ddraw_surface3_GetPalette(IDirectDrawSurface3 *iface, IDirectDrawPalette **palette)
04363 {
04364     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
04365     TRACE("iface %p, palette %p.\n", iface, palette);
04366 
04367     return ddraw_surface7_GetPalette(&This->IDirectDrawSurface7_iface, palette);
04368 }
04369 
04370 static HRESULT WINAPI ddraw_surface2_GetPalette(IDirectDrawSurface2 *iface, IDirectDrawPalette **palette)
04371 {
04372     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
04373     TRACE("iface %p, palette %p.\n", iface, palette);
04374 
04375     return ddraw_surface7_GetPalette(&This->IDirectDrawSurface7_iface, palette);
04376 }
04377 
04378 static HRESULT WINAPI ddraw_surface1_GetPalette(IDirectDrawSurface *iface, IDirectDrawPalette **palette)
04379 {
04380     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
04381     TRACE("iface %p, palette %p.\n", iface, palette);
04382 
04383     return ddraw_surface7_GetPalette(&This->IDirectDrawSurface7_iface, palette);
04384 }
04385 
04386 /*****************************************************************************
04387  * SetColorKeyEnum
04388  *
04389  * EnumAttachedSurface callback for SetColorKey. Used to set color keys
04390  * recursively in the surface tree
04391  *
04392  *****************************************************************************/
04393 struct SCKContext
04394 {
04395     HRESULT ret;
04396     struct wined3d_color_key *color_key;
04397     DWORD Flags;
04398 };
04399 
04400 static HRESULT WINAPI
04401 SetColorKeyEnum(IDirectDrawSurface7 *surface,
04402                 DDSURFACEDESC2 *desc,
04403                 void *context)
04404 {
04405     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(surface);
04406     struct SCKContext *ctx = context;
04407     HRESULT hr;
04408 
04409     hr = wined3d_surface_set_color_key(This->wined3d_surface, ctx->Flags, ctx->color_key);
04410     if (FAILED(hr))
04411     {
04412         WARN("IWineD3DSurface_SetColorKey failed, hr = %08x\n", hr);
04413         ctx->ret = hr;
04414     }
04415 
04416     ddraw_surface7_EnumAttachedSurfaces(surface, context, SetColorKeyEnum);
04417     ddraw_surface7_Release(surface);
04418 
04419     return DDENUMRET_OK;
04420 }
04421 
04422 /*****************************************************************************
04423  * IDirectDrawSurface7::SetColorKey
04424  *
04425  * Sets the color keying options for the surface. Observations showed that
04426  * in case of complex surfaces the color key has to be assigned to all
04427  * sublevels.
04428  *
04429  * Params:
04430  *  Flags: DDCKEY_*
04431  *  CKey: The new color key
04432  *
04433  * Returns:
04434  *  DD_OK on success
04435  *  See IWineD3DSurface::SetColorKey for details
04436  *
04437  *****************************************************************************/
04438 static HRESULT WINAPI ddraw_surface7_SetColorKey(IDirectDrawSurface7 *iface, DWORD Flags, DDCOLORKEY *CKey)
04439 {
04440     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
04441     DDCOLORKEY FixedCKey;
04442     struct SCKContext ctx = { DD_OK, (struct wined3d_color_key *)(CKey ? &FixedCKey : NULL), Flags };
04443 
04444     TRACE("iface %p, flags %#x, color_key %p.\n", iface, Flags, CKey);
04445 
04446     wined3d_mutex_lock();
04447     if (CKey)
04448     {
04449         FixedCKey = *CKey;
04450         /* Handle case where dwColorSpaceHighValue < dwColorSpaceLowValue */
04451         if (FixedCKey.dwColorSpaceHighValue < FixedCKey.dwColorSpaceLowValue)
04452             FixedCKey.dwColorSpaceHighValue = FixedCKey.dwColorSpaceLowValue;
04453 
04454         switch (Flags & ~DDCKEY_COLORSPACE)
04455         {
04456         case DDCKEY_DESTBLT:
04457             This->surface_desc.ddckCKDestBlt = FixedCKey;
04458             This->surface_desc.dwFlags |= DDSD_CKDESTBLT;
04459             break;
04460 
04461         case DDCKEY_DESTOVERLAY:
04462             This->surface_desc.u3.ddckCKDestOverlay = FixedCKey;
04463             This->surface_desc.dwFlags |= DDSD_CKDESTOVERLAY;
04464             break;
04465 
04466         case DDCKEY_SRCOVERLAY:
04467             This->surface_desc.ddckCKSrcOverlay = FixedCKey;
04468             This->surface_desc.dwFlags |= DDSD_CKSRCOVERLAY;
04469             break;
04470 
04471         case DDCKEY_SRCBLT:
04472             This->surface_desc.ddckCKSrcBlt = FixedCKey;
04473             This->surface_desc.dwFlags |= DDSD_CKSRCBLT;
04474             break;
04475 
04476         default:
04477             wined3d_mutex_unlock();
04478             return DDERR_INVALIDPARAMS;
04479         }
04480     }
04481     else
04482     {
04483         switch (Flags & ~DDCKEY_COLORSPACE)
04484         {
04485         case DDCKEY_DESTBLT:
04486             This->surface_desc.dwFlags &= ~DDSD_CKDESTBLT;
04487             break;
04488 
04489         case DDCKEY_DESTOVERLAY:
04490             This->surface_desc.dwFlags &= ~DDSD_CKDESTOVERLAY;
04491             break;
04492 
04493         case DDCKEY_SRCOVERLAY:
04494             This->surface_desc.dwFlags &= ~DDSD_CKSRCOVERLAY;
04495             break;
04496 
04497         case DDCKEY_SRCBLT:
04498             This->surface_desc.dwFlags &= ~DDSD_CKSRCBLT;
04499             break;
04500 
04501         default:
04502             wined3d_mutex_unlock();
04503             return DDERR_INVALIDPARAMS;
04504         }
04505     }
04506     ctx.ret = wined3d_surface_set_color_key(This->wined3d_surface, Flags, ctx.color_key);
04507     ddraw_surface7_EnumAttachedSurfaces(iface, &ctx, SetColorKeyEnum);
04508     wined3d_mutex_unlock();
04509 
04510     switch(ctx.ret)
04511     {
04512         case WINED3DERR_INVALIDCALL:        return DDERR_INVALIDPARAMS;
04513         default:                            return ctx.ret;
04514     }
04515 }
04516 
04517 static HRESULT WINAPI ddraw_surface4_SetColorKey(IDirectDrawSurface4 *iface, DWORD flags, DDCOLORKEY *color_key)
04518 {
04519     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
04520     TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key);
04521 
04522     return ddraw_surface7_SetColorKey(&This->IDirectDrawSurface7_iface, flags, color_key);
04523 }
04524 
04525 static HRESULT WINAPI ddraw_surface3_SetColorKey(IDirectDrawSurface3 *iface, DWORD flags, DDCOLORKEY *color_key)
04526 {
04527     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
04528     TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key);
04529 
04530     return ddraw_surface7_SetColorKey(&This->IDirectDrawSurface7_iface, flags, color_key);
04531 }
04532 
04533 static HRESULT WINAPI ddraw_surface2_SetColorKey(IDirectDrawSurface2 *iface, DWORD flags, DDCOLORKEY *color_key)
04534 {
04535     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
04536     TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key);
04537 
04538     return ddraw_surface7_SetColorKey(&This->IDirectDrawSurface7_iface, flags, color_key);
04539 }
04540 
04541 static HRESULT WINAPI ddraw_surface1_SetColorKey(IDirectDrawSurface *iface, DWORD flags, DDCOLORKEY *color_key)
04542 {
04543     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
04544     TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key);
04545 
04546     return ddraw_surface7_SetColorKey(&This->IDirectDrawSurface7_iface, flags, color_key);
04547 }
04548 
04549 /*****************************************************************************
04550  * IDirectDrawSurface7::SetPalette
04551  *
04552  * Assigns a DirectDrawPalette object to the surface
04553  *
04554  * Params:
04555  *  Pal: Interface to the palette to set
04556  *
04557  * Returns:
04558  *  DD_OK on success
04559  *
04560  *****************************************************************************/
04561 static HRESULT WINAPI ddraw_surface7_SetPalette(IDirectDrawSurface7 *iface, IDirectDrawPalette *Pal)
04562 {
04563     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
04564     IDirectDrawPalette *oldPal;
04565     IDirectDrawSurfaceImpl *surf;
04566     IDirectDrawPaletteImpl *PalImpl = unsafe_impl_from_IDirectDrawPalette(Pal);
04567     HRESULT hr;
04568 
04569     TRACE("iface %p, palette %p.\n", iface, Pal);
04570 
04571     if (!(This->surface_desc.u4.ddpfPixelFormat.dwFlags & (DDPF_PALETTEINDEXED1 | DDPF_PALETTEINDEXED2 |
04572             DDPF_PALETTEINDEXED4 | DDPF_PALETTEINDEXED8 | DDPF_PALETTEINDEXEDTO8))) {
04573         return DDERR_INVALIDPIXELFORMAT;
04574     }
04575 
04576     if (This->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL)
04577     {
04578         return DDERR_NOTONMIPMAPSUBLEVEL;
04579     }
04580 
04581     /* Find the old palette */
04582     wined3d_mutex_lock();
04583     hr = IDirectDrawSurface_GetPalette(iface, &oldPal);
04584     if(hr != DD_OK && hr != DDERR_NOPALETTEATTACHED)
04585     {
04586         wined3d_mutex_unlock();
04587         return hr;
04588     }
04589     if(oldPal) IDirectDrawPalette_Release(oldPal);  /* For the GetPalette */
04590 
04591     /* Set the new Palette */
04592     wined3d_surface_set_palette(This->wined3d_surface, PalImpl ? PalImpl->wineD3DPalette : NULL);
04593     /* AddRef the Palette */
04594     if(Pal) IDirectDrawPalette_AddRef(Pal);
04595 
04596     /* Release the old palette */
04597     if(oldPal) IDirectDrawPalette_Release(oldPal);
04598 
04599     /* Update the wined3d frontbuffer if this is the frontbuffer. */
04600     if ((This->surface_desc.ddsCaps.dwCaps & DDSCAPS_FRONTBUFFER) && This->ddraw->wined3d_frontbuffer)
04601     {
04602         hr = wined3d_surface_set_palette(This->ddraw->wined3d_frontbuffer, PalImpl ? PalImpl->wineD3DPalette : NULL);
04603         if (FAILED(hr))
04604             ERR("Failed to set frontbuffer palette, hr %#x.\n", hr);
04605     }
04606 
04607     /* If this is a front buffer, also update the back buffers
04608      * TODO: How do things work for palettized cube textures?
04609      */
04610     if(This->surface_desc.ddsCaps.dwCaps & DDSCAPS_FRONTBUFFER)
04611     {
04612         /* For primary surfaces the tree is just a list, so the simpler scheme fits too */
04613         DDSCAPS2 caps2 = { DDSCAPS_PRIMARYSURFACE, 0, 0, {0} };
04614 
04615         surf = This;
04616         while(1)
04617         {
04618             IDirectDrawSurface7 *attach;
04619             HRESULT hr;
04620             hr = ddraw_surface7_GetAttachedSurface(&surf->IDirectDrawSurface7_iface, &caps2, &attach);
04621             if(hr != DD_OK)
04622             {
04623                 break;
04624             }
04625 
04626             TRACE("Setting palette on %p\n", attach);
04627             ddraw_surface7_SetPalette(attach, Pal);
04628             surf = impl_from_IDirectDrawSurface7(attach);
04629             ddraw_surface7_Release(attach);
04630         }
04631     }
04632 
04633     wined3d_mutex_unlock();
04634 
04635     return DD_OK;
04636 }
04637 
04638 static HRESULT WINAPI ddraw_surface4_SetPalette(IDirectDrawSurface4 *iface, IDirectDrawPalette *palette)
04639 {
04640     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
04641     TRACE("iface %p, palette %p.\n", iface, palette);
04642 
04643     return ddraw_surface7_SetPalette(&This->IDirectDrawSurface7_iface, palette);
04644 }
04645 
04646 static HRESULT WINAPI ddraw_surface3_SetPalette(IDirectDrawSurface3 *iface, IDirectDrawPalette *palette)
04647 {
04648     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
04649     TRACE("iface %p, palette %p.\n", iface, palette);
04650 
04651     return ddraw_surface7_SetPalette(&This->IDirectDrawSurface7_iface, palette);
04652 }
04653 
04654 static HRESULT WINAPI ddraw_surface2_SetPalette(IDirectDrawSurface2 *iface, IDirectDrawPalette *palette)
04655 {
04656     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
04657     TRACE("iface %p, palette %p.\n", iface, palette);
04658 
04659     return ddraw_surface7_SetPalette(&This->IDirectDrawSurface7_iface, palette);
04660 }
04661 
04662 static HRESULT WINAPI ddraw_surface1_SetPalette(IDirectDrawSurface *iface, IDirectDrawPalette *palette)
04663 {
04664     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
04665     TRACE("iface %p, palette %p.\n", iface, palette);
04666 
04667     return ddraw_surface7_SetPalette(&This->IDirectDrawSurface7_iface, palette);
04668 }
04669 
04670 /**********************************************************
04671  * IDirectDrawGammaControl::GetGammaRamp
04672  *
04673  * Returns the current gamma ramp for a surface
04674  *
04675  * Params:
04676  *  flags: Ignored
04677  *  gamma_ramp: Address to write the ramp to
04678  *
04679  * Returns:
04680  *  DD_OK on success
04681  *  DDERR_INVALIDPARAMS if gamma_ramp is NULL
04682  *
04683  **********************************************************/
04684 static HRESULT WINAPI ddraw_gamma_control_GetGammaRamp(IDirectDrawGammaControl *iface,
04685         DWORD flags, DDGAMMARAMP *gamma_ramp)
04686 {
04687     IDirectDrawSurfaceImpl *surface = impl_from_IDirectDrawGammaControl(iface);
04688 
04689     TRACE("iface %p, flags %#x, gamma_ramp %p.\n", iface, flags, gamma_ramp);
04690 
04691     if (!gamma_ramp)
04692     {
04693         WARN("Invalid gamma_ramp passed.\n");
04694         return DDERR_INVALIDPARAMS;
04695     }
04696 
04697     wined3d_mutex_lock();
04698     if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
04699     {
04700         /* Note: DDGAMMARAMP is compatible with struct wined3d_gamma_ramp. */
04701         wined3d_device_get_gamma_ramp(surface->ddraw->wined3d_device, 0, (struct wined3d_gamma_ramp *)gamma_ramp);
04702     }
04703     else
04704     {
04705         ERR("Not implemented for non-primary surfaces.\n");
04706     }
04707     wined3d_mutex_unlock();
04708 
04709     return DD_OK;
04710 }
04711 
04712 /**********************************************************
04713  * IDirectDrawGammaControl::SetGammaRamp
04714  *
04715  * Sets the red, green and blue gamma ramps for
04716  *
04717  * Params:
04718  *  flags: Can be DDSGR_CALIBRATE to request calibration
04719  *  gamma_ramp: Structure containing the new gamma ramp
04720  *
04721  * Returns:
04722  *  DD_OK on success
04723  *  DDERR_INVALIDPARAMS if gamma_ramp is NULL
04724  *
04725  **********************************************************/
04726 static HRESULT WINAPI ddraw_gamma_control_SetGammaRamp(IDirectDrawGammaControl *iface,
04727         DWORD flags, DDGAMMARAMP *gamma_ramp)
04728 {
04729     IDirectDrawSurfaceImpl *surface = impl_from_IDirectDrawGammaControl(iface);
04730 
04731     TRACE("iface %p, flags %#x, gamma_ramp %p.\n", iface, flags, gamma_ramp);
04732 
04733     if (!gamma_ramp)
04734     {
04735         WARN("Invalid gamma_ramp passed.\n");
04736         return DDERR_INVALIDPARAMS;
04737     }
04738 
04739     wined3d_mutex_lock();
04740     if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
04741     {
04742         /* Note: DDGAMMARAMP is compatible with struct wined3d_gamma_ramp. */
04743         wined3d_device_set_gamma_ramp(surface->ddraw->wined3d_device,
04744                 0, flags, (struct wined3d_gamma_ramp *)gamma_ramp);
04745     }
04746     else
04747     {
04748         ERR("Not implemented for non-primary surfaces.\n");
04749     }
04750     wined3d_mutex_unlock();
04751 
04752     return DD_OK;
04753 }
04754 
04755 /*****************************************************************************
04756  * IDirect3DTexture2::PaletteChanged
04757  *
04758  * Informs the texture about a palette change
04759  *
04760  * Params:
04761  *  start: Start index of the change
04762  *  count: The number of changed entries
04763  *
04764  * Returns
04765  *  D3D_OK, because it's a stub
04766  *
04767  *****************************************************************************/
04768 static HRESULT WINAPI d3d_texture2_PaletteChanged(IDirect3DTexture2 *iface, DWORD start, DWORD count)
04769 {
04770     FIXME("iface %p, start %u, count %u stub!\n", iface, start, count);
04771 
04772     return D3D_OK;
04773 }
04774 
04775 static HRESULT WINAPI d3d_texture1_PaletteChanged(IDirect3DTexture *iface, DWORD start, DWORD count)
04776 {
04777     IDirectDrawSurfaceImpl *surface = impl_from_IDirect3DTexture(iface);
04778 
04779     TRACE("iface %p, start %u, count %u.\n", iface, start, count);
04780 
04781     return d3d_texture2_PaletteChanged(&surface->IDirect3DTexture2_iface, start, count);
04782 }
04783 
04784 /*****************************************************************************
04785  * IDirect3DTexture::Unload
04786  *
04787  * DX5 SDK: "The IDirect3DTexture2::Unload method is not implemented
04788  *
04789  *
04790  * Returns:
04791  *  DDERR_UNSUPPORTED
04792  *
04793  *****************************************************************************/
04794 static HRESULT WINAPI d3d_texture1_Unload(IDirect3DTexture *iface)
04795 {
04796     WARN("iface %p. Not implemented.\n", iface);
04797 
04798     return DDERR_UNSUPPORTED;
04799 }
04800 
04801 /*****************************************************************************
04802  * IDirect3DTexture2::GetHandle
04803  *
04804  * Returns handle for the texture. At the moment, the interface
04805  * to the IWineD3DTexture is used.
04806  *
04807  * Params:
04808  *  device: Device this handle is assigned to
04809  *  handle: Address to store the handle at.
04810  *
04811  * Returns:
04812  *  D3D_OK
04813  *
04814  *****************************************************************************/
04815 static HRESULT WINAPI d3d_texture2_GetHandle(IDirect3DTexture2 *iface,
04816         IDirect3DDevice2 *device, D3DTEXTUREHANDLE *handle)
04817 {
04818     IDirectDrawSurfaceImpl *surface = impl_from_IDirect3DTexture2(iface);
04819     IDirect3DDeviceImpl *device_impl = unsafe_impl_from_IDirect3DDevice2(device);
04820 
04821     TRACE("iface %p, device %p, handle %p.\n", iface, device, handle);
04822 
04823     wined3d_mutex_lock();
04824 
04825     if (!surface->Handle)
04826     {
04827         DWORD h = ddraw_allocate_handle(&device_impl->handle_table, surface, DDRAW_HANDLE_SURFACE);
04828         if (h == DDRAW_INVALID_HANDLE)
04829         {
04830             ERR("Failed to allocate a texture handle.\n");
04831             wined3d_mutex_unlock();
04832             return DDERR_OUTOFMEMORY;
04833         }
04834 
04835         surface->Handle = h + 1;
04836     }
04837 
04838     TRACE("Returning handle %08x.\n", surface->Handle);
04839     *handle = surface->Handle;
04840 
04841     wined3d_mutex_unlock();
04842 
04843     return D3D_OK;
04844 }
04845 
04846 static HRESULT WINAPI d3d_texture1_GetHandle(IDirect3DTexture *iface,
04847         IDirect3DDevice *device, D3DTEXTUREHANDLE *handle)
04848 {
04849     IDirectDrawSurfaceImpl *This = impl_from_IDirect3DTexture(iface);
04850     IDirect3DDeviceImpl *device_impl = unsafe_impl_from_IDirect3DDevice(device);
04851 
04852     TRACE("iface %p, device %p, handle %p.\n", iface, device, handle);
04853 
04854     return d3d_texture2_GetHandle(&This->IDirect3DTexture2_iface,
04855             device_impl ? &device_impl->IDirect3DDevice2_iface : NULL, handle);
04856 }
04857 
04858 /*****************************************************************************
04859  * get_sub_mimaplevel
04860  *
04861  * Helper function that returns the next mipmap level
04862  *
04863  * tex_ptr: Surface of which to return the next level
04864  *
04865  *****************************************************************************/
04866 static IDirectDrawSurfaceImpl *get_sub_mimaplevel(IDirectDrawSurfaceImpl *surface)
04867 {
04868     /* Now go down the mipmap chain to the next surface */
04869     static DDSCAPS2 mipmap_caps = { DDSCAPS_MIPMAP | DDSCAPS_TEXTURE, 0, 0, {0} };
04870     IDirectDrawSurface7 *next_level;
04871     HRESULT hr;
04872 
04873     hr = ddraw_surface7_GetAttachedSurface(&surface->IDirectDrawSurface7_iface, &mipmap_caps, &next_level);
04874     if (FAILED(hr)) return NULL;
04875 
04876     ddraw_surface7_Release(next_level);
04877 
04878     return impl_from_IDirectDrawSurface7(next_level);
04879 }
04880 
04881 /*****************************************************************************
04882  * IDirect3DTexture2::Load
04883  *
04884  * Loads a texture created with the DDSCAPS_ALLOCONLOAD
04885  *
04886  * This function isn't relayed to WineD3D because the whole interface is
04887  * implemented in DDraw only. For speed improvements a implementation which
04888  * takes OpenGL more into account could be placed into WineD3D.
04889  *
04890  * Params:
04891  *  src_texture: Address of the texture to load
04892  *
04893  * Returns:
04894  *  D3D_OK on success
04895  *  D3DERR_TEXTURE_LOAD_FAILED.
04896  *
04897  *****************************************************************************/
04898 static HRESULT WINAPI d3d_texture2_Load(IDirect3DTexture2 *iface, IDirect3DTexture2 *src_texture)
04899 {
04900     IDirectDrawSurfaceImpl *dst_surface = impl_from_IDirect3DTexture2(iface);
04901     IDirectDrawSurfaceImpl *src_surface = unsafe_impl_from_IDirect3DTexture2(src_texture);
04902     HRESULT hr;
04903 
04904     TRACE("iface %p, src_texture %p.\n", iface, src_texture);
04905 
04906     if (src_surface == dst_surface)
04907     {
04908         TRACE("copying surface %p to surface %p, why?\n", src_surface, dst_surface);
04909         return D3D_OK;
04910     }
04911 
04912     wined3d_mutex_lock();
04913 
04914     if (((src_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP)
04915             != (dst_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP))
04916             || (src_surface->surface_desc.u2.dwMipMapCount != dst_surface->surface_desc.u2.dwMipMapCount))
04917     {
04918         ERR("Trying to load surfaces with different mip-map counts.\n");
04919     }
04920 
04921     for (;;)
04922     {
04923         struct wined3d_palette *wined3d_dst_pal, *wined3d_src_pal;
04924         IDirectDrawPalette *dst_pal = NULL, *src_pal = NULL;
04925         DDSURFACEDESC *src_desc, *dst_desc;
04926 
04927         TRACE("Copying surface %p to surface %p (mipmap level %d).\n",
04928                 src_surface, dst_surface, src_surface->mipmap_level);
04929 
04930         /* Suppress the ALLOCONLOAD flag */
04931         dst_surface->surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_ALLOCONLOAD;
04932 
04933         /* Get the palettes */
04934         wined3d_dst_pal = wined3d_surface_get_palette(dst_surface->wined3d_surface);
04935         if (wined3d_dst_pal)
04936             dst_pal = wined3d_palette_get_parent(wined3d_dst_pal);
04937 
04938         wined3d_src_pal = wined3d_surface_get_palette(src_surface->wined3d_surface);
04939         if (wined3d_src_pal)
04940             src_pal = wined3d_palette_get_parent(wined3d_src_pal);
04941 
04942         if (src_pal)
04943         {
04944             PALETTEENTRY palent[256];
04945 
04946             if (!dst_pal)
04947             {
04948                 wined3d_mutex_unlock();
04949                 return DDERR_NOPALETTEATTACHED;
04950             }
04951             IDirectDrawPalette_GetEntries(src_pal, 0, 0, 256, palent);
04952             IDirectDrawPalette_SetEntries(dst_pal, 0, 0, 256, palent);
04953         }
04954 
04955         /* Copy one surface on the other */
04956         dst_desc = (DDSURFACEDESC *)&(dst_surface->surface_desc);
04957         src_desc = (DDSURFACEDESC *)&(src_surface->surface_desc);
04958 
04959         if ((src_desc->dwWidth != dst_desc->dwWidth) || (src_desc->dwHeight != dst_desc->dwHeight))
04960         {
04961             /* Should also check for same pixel format, u1.lPitch, ... */
04962             ERR("Error in surface sizes.\n");
04963             wined3d_mutex_unlock();
04964             return D3DERR_TEXTURE_LOAD_FAILED;
04965         }
04966         else
04967         {
04968             struct wined3d_mapped_rect src_rect, dst_rect;
04969 
04970             /* Copy also the ColorKeying stuff */
04971             if (src_desc->dwFlags & DDSD_CKSRCBLT)
04972             {
04973                 dst_desc->dwFlags |= DDSD_CKSRCBLT;
04974                 dst_desc->ddckCKSrcBlt.dwColorSpaceLowValue = src_desc->ddckCKSrcBlt.dwColorSpaceLowValue;
04975                 dst_desc->ddckCKSrcBlt.dwColorSpaceHighValue = src_desc->ddckCKSrcBlt.dwColorSpaceHighValue;
04976             }
04977 
04978             /* Copy the main memory texture into the surface that corresponds
04979              * to the OpenGL texture object. */
04980 
04981             hr = wined3d_surface_map(src_surface->wined3d_surface, &src_rect, NULL, 0);
04982             if (FAILED(hr))
04983             {
04984                 ERR("Failed to lock source surface, hr %#x.\n", hr);
04985                 wined3d_mutex_unlock();
04986                 return D3DERR_TEXTURE_LOAD_FAILED;
04987             }
04988 
04989             hr = wined3d_surface_map(dst_surface->wined3d_surface, &dst_rect, NULL, 0);
04990             if (FAILED(hr))
04991             {
04992                 ERR("Failed to lock destination surface, hr %#x.\n", hr);
04993                 wined3d_surface_unmap(src_surface->wined3d_surface);
04994                 wined3d_mutex_unlock();
04995                 return D3DERR_TEXTURE_LOAD_FAILED;
04996             }
04997 
04998             if (dst_surface->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_FOURCC)
04999                 memcpy(dst_rect.data, src_rect.data, src_surface->surface_desc.u1.dwLinearSize);
05000             else
05001                 memcpy(dst_rect.data, src_rect.data, src_rect.row_pitch * src_desc->dwHeight);
05002 
05003             wined3d_surface_unmap(src_surface->wined3d_surface);
05004             wined3d_surface_unmap(dst_surface->wined3d_surface);
05005         }
05006 
05007         if (src_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP)
05008             src_surface = get_sub_mimaplevel(src_surface);
05009         else
05010             src_surface = NULL;
05011 
05012         if (dst_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP)
05013             dst_surface = get_sub_mimaplevel(dst_surface);
05014         else
05015             dst_surface = NULL;
05016 
05017         if (!src_surface || !dst_surface)
05018         {
05019             if (src_surface != dst_surface)
05020                 ERR("Loading surface with different mipmap structure.\n");
05021             break;
05022         }
05023     }
05024 
05025     wined3d_mutex_unlock();
05026 
05027     return hr;
05028 }
05029 
05030 static HRESULT WINAPI d3d_texture1_Load(IDirect3DTexture *iface, IDirect3DTexture *src_texture)
05031 {
05032     IDirectDrawSurfaceImpl* This = impl_from_IDirect3DTexture(iface);
05033     IDirectDrawSurfaceImpl* src_surface = unsafe_impl_from_IDirect3DTexture(src_texture);
05034     TRACE("iface %p, src_texture %p.\n", iface, src_texture);
05035 
05036     return d3d_texture2_Load(&This->IDirect3DTexture2_iface,
05037             src_surface ? &src_surface->IDirect3DTexture2_iface : NULL);
05038 }
05039 
05040 /*****************************************************************************
05041  * The VTable
05042  *****************************************************************************/
05043 
05044 static const struct IDirectDrawSurface7Vtbl ddraw_surface7_vtbl =
05045 {
05046     /* IUnknown */
05047     ddraw_surface7_QueryInterface,
05048     ddraw_surface7_AddRef,
05049     ddraw_surface7_Release,
05050     /* IDirectDrawSurface */
05051     ddraw_surface7_AddAttachedSurface,
05052     ddraw_surface7_AddOverlayDirtyRect,
05053     ddraw_surface7_Blt,
05054     ddraw_surface7_BltBatch,
05055     ddraw_surface7_BltFast,
05056     ddraw_surface7_DeleteAttachedSurface,
05057     ddraw_surface7_EnumAttachedSurfaces,
05058     ddraw_surface7_EnumOverlayZOrders,
05059     ddraw_surface7_Flip,
05060     ddraw_surface7_GetAttachedSurface,
05061     ddraw_surface7_GetBltStatus,
05062     ddraw_surface7_GetCaps,
05063     ddraw_surface7_GetClipper,
05064     ddraw_surface7_GetColorKey,
05065     ddraw_surface7_GetDC,
05066     ddraw_surface7_GetFlipStatus,
05067     ddraw_surface7_GetOverlayPosition,
05068     ddraw_surface7_GetPalette,
05069     ddraw_surface7_GetPixelFormat,
05070     ddraw_surface7_GetSurfaceDesc,
05071     ddraw_surface7_Initialize,
05072     ddraw_surface7_IsLost,
05073     ddraw_surface7_Lock,
05074     ddraw_surface7_ReleaseDC,
05075     ddraw_surface7_Restore,
05076     ddraw_surface7_SetClipper,
05077     ddraw_surface7_SetColorKey,
05078     ddraw_surface7_SetOverlayPosition,
05079     ddraw_surface7_SetPalette,
05080     ddraw_surface7_Unlock,
05081     ddraw_surface7_UpdateOverlay,
05082     ddraw_surface7_UpdateOverlayDisplay,
05083     ddraw_surface7_UpdateOverlayZOrder,
05084     /* IDirectDrawSurface2 */
05085     ddraw_surface7_GetDDInterface,
05086     ddraw_surface7_PageLock,
05087     ddraw_surface7_PageUnlock,
05088     /* IDirectDrawSurface3 */
05089     ddraw_surface7_SetSurfaceDesc,
05090     /* IDirectDrawSurface4 */
05091     ddraw_surface7_SetPrivateData,
05092     ddraw_surface7_GetPrivateData,
05093     ddraw_surface7_FreePrivateData,
05094     ddraw_surface7_GetUniquenessValue,
05095     ddraw_surface7_ChangeUniquenessValue,
05096     /* IDirectDrawSurface7 */
05097     ddraw_surface7_SetPriority,
05098     ddraw_surface7_GetPriority,
05099     ddraw_surface7_SetLOD,
05100     ddraw_surface7_GetLOD,
05101 };
05102 
05103 static const struct IDirectDrawSurface4Vtbl ddraw_surface4_vtbl =
05104 {
05105     /* IUnknown */
05106     ddraw_surface4_QueryInterface,
05107     ddraw_surface4_AddRef,
05108     ddraw_surface4_Release,
05109     /* IDirectDrawSurface */
05110     ddraw_surface4_AddAttachedSurface,
05111     ddraw_surface4_AddOverlayDirtyRect,
05112     ddraw_surface4_Blt,
05113     ddraw_surface4_BltBatch,
05114     ddraw_surface4_BltFast,
05115     ddraw_surface4_DeleteAttachedSurface,
05116     ddraw_surface4_EnumAttachedSurfaces,
05117     ddraw_surface4_EnumOverlayZOrders,
05118     ddraw_surface4_Flip,
05119     ddraw_surface4_GetAttachedSurface,
05120     ddraw_surface4_GetBltStatus,
05121     ddraw_surface4_GetCaps,
05122     ddraw_surface4_GetClipper,
05123     ddraw_surface4_GetColorKey,
05124     ddraw_surface4_GetDC,
05125     ddraw_surface4_GetFlipStatus,
05126     ddraw_surface4_GetOverlayPosition,
05127     ddraw_surface4_GetPalette,
05128     ddraw_surface4_GetPixelFormat,
05129     ddraw_surface4_GetSurfaceDesc,
05130     ddraw_surface4_Initialize,
05131     ddraw_surface4_IsLost,
05132     ddraw_surface4_Lock,
05133     ddraw_surface4_ReleaseDC,
05134     ddraw_surface4_Restore,
05135     ddraw_surface4_SetClipper,
05136     ddraw_surface4_SetColorKey,
05137     ddraw_surface4_SetOverlayPosition,
05138     ddraw_surface4_SetPalette,
05139     ddraw_surface4_Unlock,
05140     ddraw_surface4_UpdateOverlay,
05141     ddraw_surface4_UpdateOverlayDisplay,
05142     ddraw_surface4_UpdateOverlayZOrder,
05143     /* IDirectDrawSurface2 */
05144     ddraw_surface4_GetDDInterface,
05145     ddraw_surface4_PageLock,
05146     ddraw_surface4_PageUnlock,
05147     /* IDirectDrawSurface3 */
05148     ddraw_surface4_SetSurfaceDesc,
05149     /* IDirectDrawSurface4 */
05150     ddraw_surface4_SetPrivateData,
05151     ddraw_surface4_GetPrivateData,
05152     ddraw_surface4_FreePrivateData,
05153     ddraw_surface4_GetUniquenessValue,
05154     ddraw_surface4_ChangeUniquenessValue,
05155 };
05156 
05157 static const struct IDirectDrawSurface3Vtbl ddraw_surface3_vtbl =
05158 {
05159     /* IUnknown */
05160     ddraw_surface3_QueryInterface,
05161     ddraw_surface3_AddRef,
05162     ddraw_surface3_Release,
05163     /* IDirectDrawSurface */
05164     ddraw_surface3_AddAttachedSurface,
05165     ddraw_surface3_AddOverlayDirtyRect,
05166     ddraw_surface3_Blt,
05167     ddraw_surface3_BltBatch,
05168     ddraw_surface3_BltFast,
05169     ddraw_surface3_DeleteAttachedSurface,
05170     ddraw_surface3_EnumAttachedSurfaces,
05171     ddraw_surface3_EnumOverlayZOrders,
05172     ddraw_surface3_Flip,
05173     ddraw_surface3_GetAttachedSurface,
05174     ddraw_surface3_GetBltStatus,
05175     ddraw_surface3_GetCaps,
05176     ddraw_surface3_GetClipper,
05177     ddraw_surface3_GetColorKey,
05178     ddraw_surface3_GetDC,
05179     ddraw_surface3_GetFlipStatus,
05180     ddraw_surface3_GetOverlayPosition,
05181     ddraw_surface3_GetPalette,
05182     ddraw_surface3_GetPixelFormat,
05183     ddraw_surface3_GetSurfaceDesc,
05184     ddraw_surface3_Initialize,
05185     ddraw_surface3_IsLost,
05186     ddraw_surface3_Lock,
05187     ddraw_surface3_ReleaseDC,
05188     ddraw_surface3_Restore,
05189     ddraw_surface3_SetClipper,
05190     ddraw_surface3_SetColorKey,
05191     ddraw_surface3_SetOverlayPosition,
05192     ddraw_surface3_SetPalette,
05193     ddraw_surface3_Unlock,
05194     ddraw_surface3_UpdateOverlay,
05195     ddraw_surface3_UpdateOverlayDisplay,
05196     ddraw_surface3_UpdateOverlayZOrder,
05197     /* IDirectDrawSurface2 */
05198     ddraw_surface3_GetDDInterface,
05199     ddraw_surface3_PageLock,
05200     ddraw_surface3_PageUnlock,
05201     /* IDirectDrawSurface3 */
05202     ddraw_surface3_SetSurfaceDesc,
05203 };
05204 
05205 static const struct IDirectDrawSurface2Vtbl ddraw_surface2_vtbl =
05206 {
05207     /* IUnknown */
05208     ddraw_surface2_QueryInterface,
05209     ddraw_surface2_AddRef,
05210     ddraw_surface2_Release,
05211     /* IDirectDrawSurface */
05212     ddraw_surface2_AddAttachedSurface,
05213     ddraw_surface2_AddOverlayDirtyRect,
05214     ddraw_surface2_Blt,
05215     ddraw_surface2_BltBatch,
05216     ddraw_surface2_BltFast,
05217     ddraw_surface2_DeleteAttachedSurface,
05218     ddraw_surface2_EnumAttachedSurfaces,
05219     ddraw_surface2_EnumOverlayZOrders,
05220     ddraw_surface2_Flip,
05221     ddraw_surface2_GetAttachedSurface,
05222     ddraw_surface2_GetBltStatus,
05223     ddraw_surface2_GetCaps,
05224     ddraw_surface2_GetClipper,
05225     ddraw_surface2_GetColorKey,
05226     ddraw_surface2_GetDC,
05227     ddraw_surface2_GetFlipStatus,
05228     ddraw_surface2_GetOverlayPosition,
05229     ddraw_surface2_GetPalette,
05230     ddraw_surface2_GetPixelFormat,
05231     ddraw_surface2_GetSurfaceDesc,
05232     ddraw_surface2_Initialize,
05233     ddraw_surface2_IsLost,
05234     ddraw_surface2_Lock,
05235     ddraw_surface2_ReleaseDC,
05236     ddraw_surface2_Restore,
05237     ddraw_surface2_SetClipper,
05238     ddraw_surface2_SetColorKey,
05239     ddraw_surface2_SetOverlayPosition,
05240     ddraw_surface2_SetPalette,
05241     ddraw_surface2_Unlock,
05242     ddraw_surface2_UpdateOverlay,
05243     ddraw_surface2_UpdateOverlayDisplay,
05244     ddraw_surface2_UpdateOverlayZOrder,
05245     /* IDirectDrawSurface2 */
05246     ddraw_surface2_GetDDInterface,
05247     ddraw_surface2_PageLock,
05248     ddraw_surface2_PageUnlock,
05249 };
05250 
05251 static const struct IDirectDrawSurfaceVtbl ddraw_surface1_vtbl =
05252 {
05253     /* IUnknown */
05254     ddraw_surface1_QueryInterface,
05255     ddraw_surface1_AddRef,
05256     ddraw_surface1_Release,
05257     /* IDirectDrawSurface */
05258     ddraw_surface1_AddAttachedSurface,
05259     ddraw_surface1_AddOverlayDirtyRect,
05260     ddraw_surface1_Blt,
05261     ddraw_surface1_BltBatch,
05262     ddraw_surface1_BltFast,
05263     ddraw_surface1_DeleteAttachedSurface,
05264     ddraw_surface1_EnumAttachedSurfaces,
05265     ddraw_surface1_EnumOverlayZOrders,
05266     ddraw_surface1_Flip,
05267     ddraw_surface1_GetAttachedSurface,
05268     ddraw_surface1_GetBltStatus,
05269     ddraw_surface1_GetCaps,
05270     ddraw_surface1_GetClipper,
05271     ddraw_surface1_GetColorKey,
05272     ddraw_surface1_GetDC,
05273     ddraw_surface1_GetFlipStatus,
05274     ddraw_surface1_GetOverlayPosition,
05275     ddraw_surface1_GetPalette,
05276     ddraw_surface1_GetPixelFormat,
05277     ddraw_surface1_GetSurfaceDesc,
05278     ddraw_surface1_Initialize,
05279     ddraw_surface1_IsLost,
05280     ddraw_surface1_Lock,
05281     ddraw_surface1_ReleaseDC,
05282     ddraw_surface1_Restore,
05283     ddraw_surface1_SetClipper,
05284     ddraw_surface1_SetColorKey,
05285     ddraw_surface1_SetOverlayPosition,
05286     ddraw_surface1_SetPalette,
05287     ddraw_surface1_Unlock,
05288     ddraw_surface1_UpdateOverlay,
05289     ddraw_surface1_UpdateOverlayDisplay,
05290     ddraw_surface1_UpdateOverlayZOrder,
05291 };
05292 
05293 static const struct IDirectDrawGammaControlVtbl ddraw_gamma_control_vtbl =
05294 {
05295     ddraw_gamma_control_QueryInterface,
05296     ddraw_gamma_control_AddRef,
05297     ddraw_gamma_control_Release,
05298     ddraw_gamma_control_GetGammaRamp,
05299     ddraw_gamma_control_SetGammaRamp,
05300 };
05301 
05302 static const struct IDirect3DTexture2Vtbl d3d_texture2_vtbl =
05303 {
05304     d3d_texture2_QueryInterface,
05305     d3d_texture2_AddRef,
05306     d3d_texture2_Release,
05307     d3d_texture2_GetHandle,
05308     d3d_texture2_PaletteChanged,
05309     d3d_texture2_Load,
05310 };
05311 
05312 static const struct IDirect3DTextureVtbl d3d_texture1_vtbl =
05313 {
05314     d3d_texture1_QueryInterface,
05315     d3d_texture1_AddRef,
05316     d3d_texture1_Release,
05317     d3d_texture1_Initialize,
05318     d3d_texture1_GetHandle,
05319     d3d_texture1_PaletteChanged,
05320     d3d_texture1_Load,
05321     d3d_texture1_Unload,
05322 };
05323 
05324 IDirectDrawSurfaceImpl *unsafe_impl_from_IDirectDrawSurface7(IDirectDrawSurface7 *iface)
05325 {
05326     if (!iface) return NULL;
05327     assert(iface->lpVtbl == &ddraw_surface7_vtbl);
05328     return CONTAINING_RECORD(iface, IDirectDrawSurfaceImpl, IDirectDrawSurface7_iface);
05329 }
05330 
05331 IDirectDrawSurfaceImpl *unsafe_impl_from_IDirectDrawSurface4(IDirectDrawSurface4 *iface)
05332 {
05333     if (!iface) return NULL;
05334     assert(iface->lpVtbl == &ddraw_surface4_vtbl);
05335     return CONTAINING_RECORD(iface, IDirectDrawSurfaceImpl, IDirectDrawSurface4_iface);
05336 }
05337 
05338 static IDirectDrawSurfaceImpl *unsafe_impl_from_IDirectDrawSurface3(IDirectDrawSurface3 *iface)
05339 {
05340     if (!iface) return NULL;
05341     assert(iface->lpVtbl == &ddraw_surface3_vtbl);
05342     return CONTAINING_RECORD(iface, IDirectDrawSurfaceImpl, IDirectDrawSurface3_iface);
05343 }
05344 
05345 static IDirectDrawSurfaceImpl *unsafe_impl_from_IDirectDrawSurface2(IDirectDrawSurface2 *iface)
05346 {
05347     if (!iface) return NULL;
05348     assert(iface->lpVtbl == &ddraw_surface2_vtbl);
05349     return CONTAINING_RECORD(iface, IDirectDrawSurfaceImpl, IDirectDrawSurface2_iface);
05350 }
05351 
05352 IDirectDrawSurfaceImpl *unsafe_impl_from_IDirectDrawSurface(IDirectDrawSurface *iface)
05353 {
05354     if (!iface) return NULL;
05355     assert(iface->lpVtbl == &ddraw_surface1_vtbl);
05356     return CONTAINING_RECORD(iface, IDirectDrawSurfaceImpl, IDirectDrawSurface_iface);
05357 }
05358 
05359 IDirectDrawSurfaceImpl *unsafe_impl_from_IDirect3DTexture2(IDirect3DTexture2 *iface)
05360 {
05361     if (!iface) return NULL;
05362     assert(iface->lpVtbl == &d3d_texture2_vtbl);
05363     return CONTAINING_RECORD(iface, IDirectDrawSurfaceImpl, IDirect3DTexture2_iface);
05364 }
05365 
05366 IDirectDrawSurfaceImpl *unsafe_impl_from_IDirect3DTexture(IDirect3DTexture *iface)
05367 {
05368     if (!iface) return NULL;
05369     assert(iface->lpVtbl == &d3d_texture1_vtbl);
05370     return CONTAINING_RECORD(iface, IDirectDrawSurfaceImpl, IDirect3DTexture_iface);
05371 }
05372 
05373 static void STDMETHODCALLTYPE ddraw_surface_wined3d_object_destroyed(void *parent)
05374 {
05375     IDirectDrawSurfaceImpl *surface = parent;
05376 
05377     TRACE("surface %p.\n", surface);
05378 
05379     /* Check for attached surfaces and detach them. */
05380     if (surface->first_attached != surface)
05381     {
05382         /* Well, this shouldn't happen: The surface being attached is
05383          * referenced in AddAttachedSurface(), so it shouldn't be released
05384          * until DeleteAttachedSurface() is called, because the refcount is
05385          * held. It looks like the application released it often enough to
05386          * force this. */
05387         WARN("Surface is still attached to surface %p.\n", surface->first_attached);
05388 
05389         /* The refcount will drop to -1 here */
05390         if (FAILED(ddraw_surface_delete_attached_surface(surface->first_attached, surface, surface->attached_iface)))
05391             ERR("DeleteAttachedSurface failed.\n");
05392     }
05393 
05394     while (surface->next_attached)
05395         if (FAILED(ddraw_surface_delete_attached_surface(surface,
05396                 surface->next_attached, surface->next_attached->attached_iface)))
05397             ERR("DeleteAttachedSurface failed.\n");
05398 
05399     /* Having a texture handle set implies that the device still exists. */
05400     if (surface->Handle)
05401         ddraw_free_handle(&surface->ddraw->d3ddevice->handle_table, surface->Handle - 1, DDRAW_HANDLE_SURFACE);
05402 
05403     /* Reduce the ddraw surface count. */
05404     list_remove(&surface->surface_list_entry);
05405 
05406     if (surface == surface->ddraw->primary)
05407         surface->ddraw->primary = NULL;
05408 
05409     HeapFree(GetProcessHeap(), 0, surface);
05410 }
05411 
05412 const struct wined3d_parent_ops ddraw_surface_wined3d_parent_ops =
05413 {
05414     ddraw_surface_wined3d_object_destroyed,
05415 };
05416 
05417 static void STDMETHODCALLTYPE ddraw_texture_wined3d_object_destroyed(void *parent)
05418 {
05419     IDirectDrawSurfaceImpl *surface = parent;
05420 
05421     TRACE("surface %p.\n", surface);
05422 
05423     ddraw_surface_cleanup(surface);
05424 }
05425 
05426 static const struct wined3d_parent_ops ddraw_texture_wined3d_parent_ops =
05427 {
05428     ddraw_texture_wined3d_object_destroyed,
05429 };
05430 
05431 HRESULT ddraw_surface_create_texture(IDirectDrawSurfaceImpl *surface)
05432 {
05433     const DDSURFACEDESC2 *desc = &surface->surface_desc;
05434     enum wined3d_format_id format;
05435     enum wined3d_pool pool;
05436     UINT levels;
05437 
05438     if (desc->ddsCaps.dwCaps & DDSCAPS_MIPMAP)
05439         levels = desc->u2.dwMipMapCount;
05440     else
05441         levels = 1;
05442 
05443     /* DDSCAPS_SYSTEMMEMORY textures are in WINED3D_POOL_SYSTEM_MEM.
05444      * Should I forward the MANAGED cap to the managed pool? */
05445     if (desc->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
05446         pool = WINED3D_POOL_SYSTEM_MEM;
05447     else
05448         pool = WINED3D_POOL_DEFAULT;
05449 
05450     format = PixelFormat_DD2WineD3D(&surface->surface_desc.u4.ddpfPixelFormat);
05451     if (desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
05452         return wined3d_texture_create_cube(surface->ddraw->wined3d_device, desc->dwWidth,
05453                 levels, 0, format, pool, surface, &ddraw_texture_wined3d_parent_ops, &surface->wined3d_texture);
05454     else
05455         return wined3d_texture_create_2d(surface->ddraw->wined3d_device, desc->dwWidth, desc->dwHeight,
05456                 levels, 0, format, pool, surface, &ddraw_texture_wined3d_parent_ops, &surface->wined3d_texture);
05457 }
05458 
05459 HRESULT ddraw_surface_init(IDirectDrawSurfaceImpl *surface, IDirectDrawImpl *ddraw,
05460         DDSURFACEDESC2 *desc, UINT mip_level, UINT version)
05461 {
05462     enum wined3d_pool pool = WINED3D_POOL_DEFAULT;
05463     DWORD flags = WINED3D_SURFACE_MAPPABLE;
05464     enum wined3d_format_id format;
05465     DWORD usage = 0;
05466     HRESULT hr;
05467 
05468     if (!(desc->ddsCaps.dwCaps & (DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY))
05469             && !((desc->ddsCaps.dwCaps & DDSCAPS_TEXTURE)
05470             && (desc->ddsCaps.dwCaps2 & DDSCAPS2_TEXTUREMANAGE)))
05471     {
05472         /* Tests show surfaces without memory flags get these flags added
05473          * right after creation. */
05474         desc->ddsCaps.dwCaps |= DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY;
05475     }
05476 
05477     if (desc->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
05478     {
05479         /* Some applications assume that the primary surface will always be
05480          * mapped at the same address. Some of those also assume that this
05481          * address is valid even when the surface isn't mapped, and that
05482          * updates done this way will be visible on the screen. The game Nox
05483          * is such an application. */
05484         if (version == 1)
05485             flags |= WINED3D_SURFACE_PIN_SYSMEM;
05486         usage |= WINED3DUSAGE_RENDERTARGET;
05487         desc->ddsCaps.dwCaps |= DDSCAPS_VISIBLE;
05488     }
05489 
05490     if ((desc->ddsCaps.dwCaps & DDSCAPS_3DDEVICE) && !(desc->ddsCaps.dwCaps & DDSCAPS_ZBUFFER))
05491     {
05492         usage |= WINED3DUSAGE_RENDERTARGET;
05493     }
05494 
05495     if (desc->ddsCaps.dwCaps & (DDSCAPS_OVERLAY))
05496     {
05497         usage |= WINED3DUSAGE_OVERLAY;
05498     }
05499 
05500     if (desc->ddsCaps.dwCaps & DDSCAPS_ZBUFFER)
05501         usage |= WINED3DUSAGE_DEPTHSTENCIL;
05502 
05503     if (desc->ddsCaps.dwCaps & DDSCAPS_OWNDC)
05504         usage |= WINED3DUSAGE_OWNDC;
05505 
05506     if (desc->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
05507     {
05508         pool = WINED3D_POOL_SYSTEM_MEM;
05509     }
05510     else if (desc->ddsCaps.dwCaps2 & DDSCAPS2_TEXTUREMANAGE)
05511     {
05512         pool = WINED3D_POOL_MANAGED;
05513         /* Managed textures have the system memory flag set. */
05514         desc->ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
05515     }
05516     else if (desc->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)
05517     {
05518         /* Videomemory adds localvidmem. This is mutually exclusive with
05519          * systemmemory and texturemanage. */
05520         desc->ddsCaps.dwCaps |= DDSCAPS_LOCALVIDMEM;
05521     }
05522 
05523     format = PixelFormat_DD2WineD3D(&desc->u4.ddpfPixelFormat);
05524     if (format == WINED3DFMT_UNKNOWN)
05525     {
05526         WARN("Unsupported / unknown pixelformat.\n");
05527         return DDERR_INVALIDPIXELFORMAT;
05528     }
05529 
05530     surface->IDirectDrawSurface7_iface.lpVtbl = &ddraw_surface7_vtbl;
05531     surface->IDirectDrawSurface4_iface.lpVtbl = &ddraw_surface4_vtbl;
05532     surface->IDirectDrawSurface3_iface.lpVtbl = &ddraw_surface3_vtbl;
05533     surface->IDirectDrawSurface2_iface.lpVtbl = &ddraw_surface2_vtbl;
05534     surface->IDirectDrawSurface_iface.lpVtbl = &ddraw_surface1_vtbl;
05535     surface->IDirectDrawGammaControl_iface.lpVtbl = &ddraw_gamma_control_vtbl;
05536     surface->IDirect3DTexture2_iface.lpVtbl = &d3d_texture2_vtbl;
05537     surface->IDirect3DTexture_iface.lpVtbl = &d3d_texture1_vtbl;
05538     surface->iface_count = 1;
05539     surface->version = version;
05540     surface->ddraw = ddraw;
05541 
05542     if (version == 7)
05543     {
05544         surface->ref7 = 1;
05545     }
05546     else if (version == 4)
05547     {
05548         surface->ref4 = 1;
05549     }
05550     else
05551     {
05552         surface->ref1 = 1;
05553     }
05554 
05555     copy_to_surfacedesc2(&surface->surface_desc, desc);
05556 
05557     surface->first_attached = surface;
05558 
05559     hr = wined3d_surface_create(ddraw->wined3d_device, desc->dwWidth, desc->dwHeight, format, mip_level,
05560             usage, pool, WINED3D_MULTISAMPLE_NONE, 0, DefaultSurfaceType, flags,
05561             surface, &ddraw_surface_wined3d_parent_ops, &surface->wined3d_surface);
05562     if (FAILED(hr))
05563     {
05564         WARN("Failed to create wined3d surface, hr %#x.\n", hr);
05565         return hr;
05566     }
05567 
05568     /* Anno 1602 stores the pitch right after surface creation, so make sure
05569      * it's there. TODO: Test other fourcc formats. */
05570     if (format == WINED3DFMT_DXT1 || format == WINED3DFMT_DXT2 || format == WINED3DFMT_DXT3
05571             || format == WINED3DFMT_DXT4 || format == WINED3DFMT_DXT5)
05572     {
05573         surface->surface_desc.dwFlags |= DDSD_LINEARSIZE;
05574         if (format == WINED3DFMT_DXT1)
05575         {
05576             surface->surface_desc.u1.dwLinearSize = max(4, desc->dwWidth) * max(4, desc->dwHeight) / 2;
05577         }
05578         else
05579         {
05580             surface->surface_desc.u1.dwLinearSize = max(4, desc->dwWidth) * max(4, desc->dwHeight);
05581         }
05582     }
05583     else
05584     {
05585         surface->surface_desc.dwFlags |= DDSD_PITCH;
05586         surface->surface_desc.u1.lPitch = wined3d_surface_get_pitch(surface->wined3d_surface);
05587     }
05588 
05589     if (desc->dwFlags & DDSD_CKDESTOVERLAY)
05590     {
05591         wined3d_surface_set_color_key(surface->wined3d_surface, DDCKEY_DESTOVERLAY,
05592                 (struct wined3d_color_key *)&desc->u3.ddckCKDestOverlay);
05593     }
05594     if (desc->dwFlags & DDSD_CKDESTBLT)
05595     {
05596         wined3d_surface_set_color_key(surface->wined3d_surface, DDCKEY_DESTBLT,
05597                 (struct wined3d_color_key *)&desc->ddckCKDestBlt);
05598     }
05599     if (desc->dwFlags & DDSD_CKSRCOVERLAY)
05600     {
05601         wined3d_surface_set_color_key(surface->wined3d_surface, DDCKEY_SRCOVERLAY,
05602                 (struct wined3d_color_key *)&desc->ddckCKSrcOverlay);
05603     }
05604     if (desc->dwFlags & DDSD_CKSRCBLT)
05605     {
05606         wined3d_surface_set_color_key(surface->wined3d_surface, DDCKEY_SRCBLT,
05607                 (struct wined3d_color_key *)&desc->ddckCKSrcBlt);
05608     }
05609     if (desc->dwFlags & DDSD_LPSURFACE)
05610     {
05611         hr = wined3d_surface_set_mem(surface->wined3d_surface, desc->lpSurface);
05612         if (FAILED(hr))
05613         {
05614             ERR("Failed to set surface memory, hr %#x.\n", hr);
05615             wined3d_surface_decref(surface->wined3d_surface);
05616             return hr;
05617         }
05618     }
05619 
05620     return DD_OK;
05621 }

Generated on Sat May 26 2012 04:20:38 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.