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

device.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 1998-2004 Lionel Ulmer
00003  * Copyright (c) 2002-2005 Christian Costa
00004  * Copyright (c) 2006 Stefan Dösinger
00005  * Copyright (c) 2008 Alexander Dorofeyev
00006  *
00007  * This library is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * This library is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with this library; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00020  *
00021  * IDirect3DDevice implementation, version 1, 2, 3 and 7. Rendering is relayed
00022  * to WineD3D, some minimal DirectDraw specific management is handled here.
00023  * The Direct3DDevice is NOT the parent of the WineD3DDevice, because d3d
00024  * is initialized when DirectDraw creates the primary surface.
00025  * Some type management is necessary, because some D3D types changed between
00026  * D3D7 and D3D9.
00027  *
00028  */
00029 
00030 #include "config.h"
00031 #include "wine/port.h"
00032 
00033 #include "ddraw_private.h"
00034 
00035 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
00036 
00037 /* The device ID */
00038 const GUID IID_D3DDEVICE_WineD3D = {
00039   0xaef72d43,
00040   0xb09a,
00041   0x4b7b,
00042   { 0xb7,0x98,0xc6,0x8a,0x77,0x2d,0x72,0x2a }
00043 };
00044 
00045 static inline void set_fpu_control_word(WORD fpucw)
00046 {
00047 #if defined(__i386__) && defined(__GNUC__)
00048     __asm__ volatile ("fldcw %0" : : "m" (fpucw));
00049 #elif defined(__i386__) && defined(_MSC_VER)
00050     __asm fldcw fpucw;
00051 #endif
00052 }
00053 
00054 static inline WORD d3d_fpu_setup(void)
00055 {
00056     WORD oldcw;
00057 
00058 #if defined(__i386__) && defined(__GNUC__)
00059     __asm__ volatile ("fnstcw %0" : "=m" (oldcw));
00060 #elif defined(__i386__) && defined(_MSC_VER)
00061     __asm fnstcw oldcw;
00062 #else
00063     static BOOL warned = FALSE;
00064     if(!warned)
00065     {
00066         FIXME("FPUPRESERVE not implemented for this platform / compiler\n");
00067         warned = TRUE;
00068     }
00069     return 0;
00070 #endif
00071 
00072     set_fpu_control_word(0x37f);
00073 
00074     return oldcw;
00075 }
00076 
00077 /*****************************************************************************
00078  * IUnknown Methods. Common for Version 1, 2, 3 and 7
00079  *****************************************************************************/
00080 
00081 /*****************************************************************************
00082  * IDirect3DDevice7::QueryInterface
00083  *
00084  * Used to query other interfaces from a Direct3DDevice interface.
00085  * It can return interface pointers to all Direct3DDevice versions as well
00086  * as IDirectDraw and IDirect3D. For a link to QueryInterface
00087  * rules see ddraw.c, IDirectDraw7::QueryInterface
00088  *
00089  * Exists in Version 1, 2, 3 and 7
00090  *
00091  * Params:
00092  *  refiid: Interface ID queried for
00093  *  obj: Used to return the interface pointer
00094  *
00095  * Returns:
00096  *  D3D_OK or E_NOINTERFACE
00097  *
00098  *****************************************************************************/
00099 static HRESULT WINAPI
00100 IDirect3DDeviceImpl_7_QueryInterface(IDirect3DDevice7 *iface,
00101                                      REFIID refiid,
00102                                      void **obj)
00103 {
00104     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
00105 
00106     TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(refiid), obj);
00107 
00108     /* According to COM docs, if the QueryInterface fails, obj should be set to NULL */
00109     *obj = NULL;
00110 
00111     if(!refiid)
00112         return DDERR_INVALIDPARAMS;
00113 
00114     if ( IsEqualGUID( &IID_IUnknown, refiid ) )
00115     {
00116         *obj = iface;
00117     }
00118 
00119     /* Check DirectDraw Interfaces. */
00120     else if( IsEqualGUID( &IID_IDirectDraw7, refiid ) )
00121     {
00122         *obj = &This->ddraw->IDirectDraw7_iface;
00123         TRACE("(%p) Returning IDirectDraw7 interface at %p\n", This, *obj);
00124     }
00125     else if ( IsEqualGUID( &IID_IDirectDraw4, refiid ) )
00126     {
00127         *obj = &This->ddraw->IDirectDraw4_iface;
00128         TRACE("(%p) Returning IDirectDraw4 interface at %p\n", This, *obj);
00129     }
00130     else if ( IsEqualGUID( &IID_IDirectDraw2, refiid ) )
00131     {
00132         *obj = &This->ddraw->IDirectDraw2_iface;
00133         TRACE("(%p) Returning IDirectDraw2 interface at %p\n", This, *obj);
00134     }
00135     else if( IsEqualGUID( &IID_IDirectDraw, refiid ) )
00136     {
00137         *obj = &This->ddraw->IDirectDraw_iface;
00138         TRACE("(%p) Returning IDirectDraw interface at %p\n", This, *obj);
00139     }
00140 
00141     /* Direct3D */
00142     else if ( IsEqualGUID( &IID_IDirect3D  , refiid ) )
00143     {
00144         *obj = &This->ddraw->IDirect3D_iface;
00145         TRACE("(%p) Returning IDirect3D interface at %p\n", This, *obj);
00146     }
00147     else if ( IsEqualGUID( &IID_IDirect3D2 , refiid ) )
00148     {
00149         *obj = &This->ddraw->IDirect3D2_iface;
00150         TRACE("(%p) Returning IDirect3D2 interface at %p\n", This, *obj);
00151     }
00152     else if ( IsEqualGUID( &IID_IDirect3D3 , refiid ) )
00153     {
00154         *obj = &This->ddraw->IDirect3D3_iface;
00155         TRACE("(%p) Returning IDirect3D3 interface at %p\n", This, *obj);
00156     }
00157     else if ( IsEqualGUID( &IID_IDirect3D7 , refiid ) )
00158     {
00159         *obj = &This->ddraw->IDirect3D7_iface;
00160         TRACE("(%p) Returning IDirect3D7 interface at %p\n", This, *obj);
00161     }
00162 
00163     /* Direct3DDevice */
00164     else if ( IsEqualGUID( &IID_IDirect3DDevice  , refiid ) )
00165     {
00166         *obj = &This->IDirect3DDevice_iface;
00167         TRACE("(%p) Returning IDirect3DDevice interface at %p\n", This, *obj);
00168     }
00169     else if ( IsEqualGUID( &IID_IDirect3DDevice2  , refiid ) ) {
00170         *obj = &This->IDirect3DDevice2_iface;
00171         TRACE("(%p) Returning IDirect3DDevice2 interface at %p\n", This, *obj);
00172     }
00173     else if ( IsEqualGUID( &IID_IDirect3DDevice3  , refiid ) ) {
00174         *obj = &This->IDirect3DDevice3_iface;
00175         TRACE("(%p) Returning IDirect3DDevice3 interface at %p\n", This, *obj);
00176     }
00177     else if ( IsEqualGUID( &IID_IDirect3DDevice7  , refiid ) ) {
00178         *obj = This;
00179         TRACE("(%p) Returning IDirect3DDevice7 interface at %p\n", This, *obj);
00180     }
00181 
00182     /* DirectDrawSurface */
00183     else if (IsEqualGUID(&IID_IDirectDrawSurface, refiid) && This->from_surface)
00184     {
00185         *obj = &This->target->IDirectDrawSurface_iface;
00186         TRACE("Returning IDirectDrawSurface interface %p.\n", *obj);
00187     }
00188 
00189     /* Unknown interface */
00190     else
00191     {
00192         ERR("(%p)->(%s, %p): No interface found\n", This, debugstr_guid(refiid), obj);
00193         return E_NOINTERFACE;
00194     }
00195 
00196     /* AddRef the returned interface */
00197     IUnknown_AddRef( (IUnknown *) *obj);
00198     return D3D_OK;
00199 }
00200 
00201 static HRESULT WINAPI IDirect3DDeviceImpl_3_QueryInterface(IDirect3DDevice3 *iface, REFIID riid,
00202         void **obj)
00203 {
00204     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
00205     TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obj);
00206 
00207     return IDirect3DDevice7_QueryInterface(&This->IDirect3DDevice7_iface, riid, obj);
00208 }
00209 
00210 static HRESULT WINAPI IDirect3DDeviceImpl_2_QueryInterface(IDirect3DDevice2 *iface, REFIID riid,
00211         void **obj)
00212 {
00213     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
00214     TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obj);
00215 
00216     return IDirect3DDevice7_QueryInterface(&This->IDirect3DDevice7_iface, riid, obj);
00217 }
00218 
00219 static HRESULT WINAPI IDirect3DDeviceImpl_1_QueryInterface(IDirect3DDevice *iface, REFIID riid,
00220         void **obp)
00221 {
00222     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
00223     TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obp);
00224 
00225     return IDirect3DDevice7_QueryInterface(&This->IDirect3DDevice7_iface, riid, obp);
00226 }
00227 
00228 /*****************************************************************************
00229  * IDirect3DDevice7::AddRef
00230  *
00231  * Increases the refcount....
00232  * The most exciting Method, definitely
00233  *
00234  * Exists in Version 1, 2, 3 and 7
00235  *
00236  * Returns:
00237  *  The new refcount
00238  *
00239  *****************************************************************************/
00240 static ULONG WINAPI
00241 IDirect3DDeviceImpl_7_AddRef(IDirect3DDevice7 *iface)
00242 {
00243     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
00244     ULONG ref = InterlockedIncrement(&This->ref);
00245 
00246     TRACE("%p increasing refcount to %u.\n", This, ref);
00247 
00248     return ref;
00249 }
00250 
00251 static ULONG WINAPI IDirect3DDeviceImpl_3_AddRef(IDirect3DDevice3 *iface)
00252 {
00253     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
00254     TRACE("iface %p.\n", iface);
00255 
00256     return IDirect3DDevice7_AddRef(&This->IDirect3DDevice7_iface);
00257 }
00258 
00259 static ULONG WINAPI IDirect3DDeviceImpl_2_AddRef(IDirect3DDevice2 *iface)
00260 {
00261     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
00262     TRACE("iface %p.\n", iface);
00263 
00264     return IDirect3DDevice7_AddRef(&This->IDirect3DDevice7_iface);
00265 }
00266 
00267 static ULONG WINAPI IDirect3DDeviceImpl_1_AddRef(IDirect3DDevice *iface)
00268 {
00269     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
00270     TRACE("iface %p.\n", iface);
00271 
00272     return IDirect3DDevice7_AddRef(&This->IDirect3DDevice7_iface);
00273 }
00274 
00275 /*****************************************************************************
00276  * IDirect3DDevice7::Release
00277  *
00278  * Decreases the refcount of the interface
00279  * When the refcount is reduced to 0, the object is destroyed.
00280  *
00281  * Exists in Version 1, 2, 3 and 7
00282  *
00283  * Returns:d
00284  *  The new refcount
00285  *
00286  *****************************************************************************/
00287 static ULONG WINAPI
00288 IDirect3DDeviceImpl_7_Release(IDirect3DDevice7 *iface)
00289 {
00290     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
00291     ULONG ref = InterlockedDecrement(&This->ref);
00292 
00293     TRACE("%p decreasing refcount to %u.\n", This, ref);
00294 
00295     /* This method doesn't destroy the WineD3DDevice, because it's still in use for
00296      * 2D rendering. IDirectDrawSurface7::Release will destroy the WineD3DDevice
00297      * when the render target is released
00298      */
00299     if (ref == 0)
00300     {
00301         DWORD i;
00302 
00303         wined3d_mutex_lock();
00304 
00305         /* There is no need to unset any resources here, wined3d will take
00306          * care of that on Uninit3D(). */
00307 
00308         /* Free the index buffer. */
00309         wined3d_buffer_decref(This->indexbuffer);
00310 
00311         /* Set the device up to render to the front buffer since the back
00312          * buffer will vanish soon. */
00313         wined3d_device_set_render_target(This->wined3d_device, 0,
00314                 This->ddraw->wined3d_frontbuffer, TRUE);
00315 
00316         /* Release the WineD3DDevice. This won't destroy it. */
00317         if (!wined3d_device_decref(This->wined3d_device))
00318             ERR("The wined3d device (%p) was destroyed unexpectedly.\n", This->wined3d_device);
00319 
00320         /* The texture handles should be unset by now, but there might be some bits
00321          * missing in our reference counting(needs test). Do a sanity check. */
00322         for (i = 0; i < This->handle_table.entry_count; ++i)
00323         {
00324             struct ddraw_handle_entry *entry = &This->handle_table.entries[i];
00325 
00326             switch (entry->type)
00327             {
00328                 case DDRAW_HANDLE_FREE:
00329                     break;
00330 
00331                 case DDRAW_HANDLE_MATERIAL:
00332                 {
00333                     IDirect3DMaterialImpl *m = entry->object;
00334                     FIXME("Material handle %#x (%p) not unset properly.\n", i + 1, m);
00335                     m->Handle = 0;
00336                     break;
00337                 }
00338 
00339                 case DDRAW_HANDLE_MATRIX:
00340                 {
00341                     /* No FIXME here because this might happen because of sloppy applications. */
00342                     WARN("Leftover matrix handle %#x (%p), deleting.\n", i + 1, entry->object);
00343                     IDirect3DDevice_DeleteMatrix(&This->IDirect3DDevice_iface, i + 1);
00344                     break;
00345                 }
00346 
00347                 case DDRAW_HANDLE_STATEBLOCK:
00348                 {
00349                     /* No FIXME here because this might happen because of sloppy applications. */
00350                     WARN("Leftover stateblock handle %#x (%p), deleting.\n", i + 1, entry->object);
00351                     IDirect3DDevice7_DeleteStateBlock(iface, i + 1);
00352                     break;
00353                 }
00354 
00355                 case DDRAW_HANDLE_SURFACE:
00356                 {
00357                     IDirectDrawSurfaceImpl *surf = entry->object;
00358                     FIXME("Texture handle %#x (%p) not unset properly.\n", i + 1, surf);
00359                     surf->Handle = 0;
00360                     break;
00361                 }
00362 
00363                 default:
00364                     FIXME("Handle %#x (%p) has unknown type %#x.\n", i + 1, entry->object, entry->type);
00365                     break;
00366             }
00367         }
00368 
00369         ddraw_handle_table_destroy(&This->handle_table);
00370 
00371         TRACE("Releasing target %p.\n", This->target);
00372         /* Release the render target and the WineD3D render target
00373          * (See IDirect3D7::CreateDevice for more comments on this)
00374          */
00375         IDirectDrawSurface7_Release(&This->target->IDirectDrawSurface7_iface);
00376         TRACE("Target release done\n");
00377 
00378         This->ddraw->d3ddevice = NULL;
00379 
00380         /* Now free the structure */
00381         HeapFree(GetProcessHeap(), 0, This);
00382         wined3d_mutex_unlock();
00383     }
00384 
00385     TRACE("Done\n");
00386     return ref;
00387 }
00388 
00389 static ULONG WINAPI IDirect3DDeviceImpl_3_Release(IDirect3DDevice3 *iface)
00390 {
00391     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
00392     TRACE("iface %p.\n", iface);
00393 
00394     return IDirect3DDevice7_Release(&This->IDirect3DDevice7_iface);
00395 }
00396 
00397 static ULONG WINAPI IDirect3DDeviceImpl_2_Release(IDirect3DDevice2 *iface)
00398 {
00399     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
00400     TRACE("iface %p.\n", iface);
00401 
00402     return IDirect3DDevice7_Release(&This->IDirect3DDevice7_iface);
00403 }
00404 
00405 static ULONG WINAPI IDirect3DDeviceImpl_1_Release(IDirect3DDevice *iface)
00406 {
00407     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
00408     TRACE("iface %p.\n", iface);
00409 
00410     return IDirect3DDevice7_Release(&This->IDirect3DDevice7_iface);
00411 }
00412 
00413 /*****************************************************************************
00414  * IDirect3DDevice Methods
00415  *****************************************************************************/
00416 
00417 /*****************************************************************************
00418  * IDirect3DDevice::Initialize
00419  *
00420  * Initializes a Direct3DDevice. This implementation is a no-op, as all
00421  * initialization is done at create time.
00422  *
00423  * Exists in Version 1
00424  *
00425  * Parameters:
00426  *  No idea what they mean, as the MSDN page is gone
00427  *
00428  * Returns: DD_OK
00429  *
00430  *****************************************************************************/
00431 static HRESULT WINAPI
00432 IDirect3DDeviceImpl_1_Initialize(IDirect3DDevice *iface,
00433                                  IDirect3D *Direct3D, GUID *guid,
00434                                  D3DDEVICEDESC *Desc)
00435 {
00436     /* It shouldn't be crucial, but print a FIXME, I'm interested if
00437      * any game calls it and when. */
00438     FIXME("iface %p, d3d %p, guid %s, device_desc %p nop!\n",
00439             iface, Direct3D, debugstr_guid(guid), Desc);
00440 
00441     return D3D_OK;
00442 }
00443 
00444 /*****************************************************************************
00445  * IDirect3DDevice7::GetCaps
00446  *
00447  * Retrieves the device's capabilities
00448  *
00449  * This implementation is used for Version 7 only, the older versions have
00450  * their own implementation.
00451  *
00452  * Parameters:
00453  *  Desc: Pointer to a D3DDEVICEDESC7 structure to fill
00454  *
00455  * Returns:
00456  *  D3D_OK on success
00457  *  D3DERR_* if a problem occurs. See WineD3D
00458  *
00459  *****************************************************************************/
00460 static HRESULT
00461 IDirect3DDeviceImpl_7_GetCaps(IDirect3DDevice7 *iface,
00462                               D3DDEVICEDESC7 *Desc)
00463 {
00464     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
00465     D3DDEVICEDESC OldDesc;
00466 
00467     TRACE("iface %p, device_desc %p.\n", iface, Desc);
00468 
00469     if (!Desc)
00470     {
00471         WARN("Desc is NULL, returning DDERR_INVALIDPARAMS.\n");
00472         return DDERR_INVALIDPARAMS;
00473     }
00474 
00475     /* Call the same function used by IDirect3D, this saves code */
00476     return IDirect3DImpl_GetCaps(This->ddraw->wined3d, &OldDesc, Desc);
00477 }
00478 
00479 static HRESULT WINAPI
00480 IDirect3DDeviceImpl_7_GetCaps_FPUSetup(IDirect3DDevice7 *iface,
00481                               D3DDEVICEDESC7 *Desc)
00482 {
00483     return IDirect3DDeviceImpl_7_GetCaps(iface, Desc);
00484 }
00485 
00486 static HRESULT WINAPI
00487 IDirect3DDeviceImpl_7_GetCaps_FPUPreserve(IDirect3DDevice7 *iface,
00488                               D3DDEVICEDESC7 *Desc)
00489 {
00490     HRESULT hr;
00491     WORD old_fpucw;
00492 
00493     old_fpucw = d3d_fpu_setup();
00494     hr = IDirect3DDeviceImpl_7_GetCaps(iface, Desc);
00495     set_fpu_control_word(old_fpucw);
00496 
00497     return hr;
00498 }
00499 /*****************************************************************************
00500  * IDirect3DDevice3::GetCaps
00501  *
00502  * Retrieves the capabilities of the hardware device and the emulation
00503  * device. For Wine, hardware and emulation are the same (it's all HW).
00504  *
00505  * This implementation is used for Version 1, 2, and 3. Version 7 has its own
00506  *
00507  * Parameters:
00508  *  HWDesc: Structure to fill with the HW caps
00509  *  HelDesc: Structure to fill with the hardware emulation caps
00510  *
00511  * Returns:
00512  *  D3D_OK on success
00513  *  D3DERR_* if a problem occurs. See WineD3D
00514  *
00515  *****************************************************************************/
00516 
00517 /* There are 3 versions of D3DDEVICEDESC. All 3 share the same name because
00518  * Microsoft just expanded the existing structure without naming them
00519  * D3DDEVICEDESC2 and D3DDEVICEDESC3. Which version is used have depends
00520  * on the version of the DirectX SDK. DirectX 6+ and Wine use the latest
00521  * one with 252 bytes.
00522  *
00523  * All 3 versions are allowed as parameters and only the specified amount of
00524  * bytes is written.
00525  *
00526  * Note that Direct3D7 and earlier are not available in native Win64
00527  * ddraw.dll builds, so possible size differences between 32 bit and
00528  * 64 bit are a non-issue.
00529  */
00530 static inline BOOL check_d3ddevicedesc_size(DWORD size)
00531 {
00532     if (size == FIELD_OFFSET(D3DDEVICEDESC, dwMinTextureWidth) /* 172 */
00533             || size == FIELD_OFFSET(D3DDEVICEDESC, dwMaxTextureRepeat) /* 204 */
00534             || size == sizeof(D3DDEVICEDESC) /* 252 */) return TRUE;
00535     return FALSE;
00536 }
00537 
00538 static HRESULT WINAPI
00539 IDirect3DDeviceImpl_3_GetCaps(IDirect3DDevice3 *iface,
00540                               D3DDEVICEDESC *HWDesc,
00541                               D3DDEVICEDESC *HelDesc)
00542 {
00543     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
00544     D3DDEVICEDESC oldDesc;
00545     D3DDEVICEDESC7 newDesc;
00546     HRESULT hr;
00547 
00548     TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, HWDesc, HelDesc);
00549 
00550     if (!HWDesc)
00551     {
00552         WARN("HWDesc is NULL, returning DDERR_INVALIDPARAMS.\n");
00553         return DDERR_INVALIDPARAMS;
00554     }
00555     if (!check_d3ddevicedesc_size(HWDesc->dwSize))
00556     {
00557         WARN("HWDesc->dwSize is %u, returning DDERR_INVALIDPARAMS.\n", HWDesc->dwSize);
00558         return DDERR_INVALIDPARAMS;
00559     }
00560     if (!HelDesc)
00561     {
00562         WARN("HelDesc is NULL, returning DDERR_INVALIDPARAMS.\n");
00563         return DDERR_INVALIDPARAMS;
00564     }
00565     if (!check_d3ddevicedesc_size(HelDesc->dwSize))
00566     {
00567         WARN("HelDesc->dwSize is %u, returning DDERR_INVALIDPARAMS.\n", HelDesc->dwSize);
00568         return DDERR_INVALIDPARAMS;
00569     }
00570 
00571     hr = IDirect3DImpl_GetCaps(This->ddraw->wined3d, &oldDesc, &newDesc);
00572     if(hr != D3D_OK) return hr;
00573 
00574     DD_STRUCT_COPY_BYSIZE(HWDesc, &oldDesc);
00575     DD_STRUCT_COPY_BYSIZE(HelDesc, &oldDesc);
00576     return D3D_OK;
00577 }
00578 
00579 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetCaps(IDirect3DDevice2 *iface,
00580         D3DDEVICEDESC *D3DHWDevDesc, D3DDEVICEDESC *D3DHELDevDesc)
00581 {
00582     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
00583     TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, D3DHWDevDesc, D3DHELDevDesc);
00584     return IDirect3DDevice3_GetCaps(&This->IDirect3DDevice3_iface, D3DHWDevDesc, D3DHELDevDesc);
00585 }
00586 
00587 static HRESULT WINAPI IDirect3DDeviceImpl_1_GetCaps(IDirect3DDevice *iface,
00588         D3DDEVICEDESC *D3DHWDevDesc, D3DDEVICEDESC *D3DHELDevDesc)
00589 {
00590     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
00591     TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, D3DHWDevDesc, D3DHELDevDesc);
00592     return IDirect3DDevice3_GetCaps(&This->IDirect3DDevice3_iface, D3DHWDevDesc, D3DHELDevDesc);
00593 }
00594 
00595 /*****************************************************************************
00596  * IDirect3DDevice2::SwapTextureHandles
00597  *
00598  * Swaps the texture handles of 2 Texture interfaces. Version 1 and 2
00599  *
00600  * Parameters:
00601  *  Tex1, Tex2: The 2 Textures to swap
00602  *
00603  * Returns:
00604  *  D3D_OK
00605  *
00606  *****************************************************************************/
00607 static HRESULT WINAPI
00608 IDirect3DDeviceImpl_2_SwapTextureHandles(IDirect3DDevice2 *iface,
00609                                          IDirect3DTexture2 *Tex1,
00610                                          IDirect3DTexture2 *Tex2)
00611 {
00612     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
00613     IDirectDrawSurfaceImpl *surf1 = unsafe_impl_from_IDirect3DTexture2(Tex1);
00614     IDirectDrawSurfaceImpl *surf2 = unsafe_impl_from_IDirect3DTexture2(Tex2);
00615     DWORD h1, h2;
00616 
00617     TRACE("iface %p, tex1 %p, tex2 %p.\n", iface, Tex1, Tex2);
00618 
00619     wined3d_mutex_lock();
00620 
00621     h1 = surf1->Handle - 1;
00622     h2 = surf2->Handle - 1;
00623     This->handle_table.entries[h1].object = surf2;
00624     This->handle_table.entries[h2].object = surf1;
00625     surf2->Handle = h1 + 1;
00626     surf1->Handle = h2 + 1;
00627 
00628     wined3d_mutex_unlock();
00629 
00630     return D3D_OK;
00631 }
00632 
00633 static HRESULT WINAPI IDirect3DDeviceImpl_1_SwapTextureHandles(IDirect3DDevice *iface,
00634         IDirect3DTexture *D3DTex1, IDirect3DTexture *D3DTex2)
00635 {
00636     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
00637     IDirectDrawSurfaceImpl *surf1 = unsafe_impl_from_IDirect3DTexture(D3DTex1);
00638     IDirectDrawSurfaceImpl *surf2 = unsafe_impl_from_IDirect3DTexture(D3DTex2);
00639     IDirect3DTexture2 *t1 = surf1 ? &surf1->IDirect3DTexture2_iface : NULL;
00640     IDirect3DTexture2 *t2 = surf2 ? &surf2->IDirect3DTexture2_iface : NULL;
00641 
00642     TRACE("iface %p, tex1 %p, tex2 %p.\n", iface, D3DTex1, D3DTex2);
00643 
00644     return IDirect3DDevice2_SwapTextureHandles(&This->IDirect3DDevice2_iface, t1, t2);
00645 }
00646 
00647 /*****************************************************************************
00648  * IDirect3DDevice3::GetStats
00649  *
00650  * This method seems to retrieve some stats from the device.
00651  * The MSDN documentation doesn't exist any more, but the D3DSTATS
00652  * structure suggests that the amount of drawn primitives and processed
00653  * vertices is returned.
00654  *
00655  * Exists in Version 1, 2 and 3
00656  *
00657  * Parameters:
00658  *  Stats: Pointer to a D3DSTATS structure to be filled
00659  *
00660  * Returns:
00661  *  D3D_OK on success
00662  *  DDERR_INVALIDPARAMS if Stats == NULL
00663  *
00664  *****************************************************************************/
00665 static HRESULT WINAPI
00666 IDirect3DDeviceImpl_3_GetStats(IDirect3DDevice3 *iface,
00667                                D3DSTATS *Stats)
00668 {
00669     FIXME("iface %p, stats %p stub!\n", iface, Stats);
00670 
00671     if(!Stats)
00672         return DDERR_INVALIDPARAMS;
00673 
00674     /* Fill the Stats with 0 */
00675     Stats->dwTrianglesDrawn = 0;
00676     Stats->dwLinesDrawn = 0;
00677     Stats->dwPointsDrawn = 0;
00678     Stats->dwSpansDrawn = 0;
00679     Stats->dwVerticesProcessed = 0;
00680 
00681     return D3D_OK;
00682 }
00683 
00684 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetStats(IDirect3DDevice2 *iface, D3DSTATS *Stats)
00685 {
00686     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
00687 
00688     TRACE("iface %p, stats %p.\n", iface, Stats);
00689 
00690     return IDirect3DDevice3_GetStats(&This->IDirect3DDevice3_iface, Stats);
00691 }
00692 
00693 static HRESULT WINAPI IDirect3DDeviceImpl_1_GetStats(IDirect3DDevice *iface, D3DSTATS *Stats)
00694 {
00695     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
00696 
00697     TRACE("iface %p, stats %p.\n", iface, Stats);
00698 
00699     return IDirect3DDevice3_GetStats(&This->IDirect3DDevice3_iface, Stats);
00700 }
00701 
00702 /*****************************************************************************
00703  * IDirect3DDevice::CreateExecuteBuffer
00704  *
00705  * Creates an IDirect3DExecuteBuffer, used for rendering with a
00706  * Direct3DDevice.
00707  *
00708  * Version 1 only.
00709  *
00710  * Params:
00711  *  Desc: Buffer description
00712  *  ExecuteBuffer: Address to return the Interface pointer at
00713  *  UnkOuter: Must be NULL. Basically for aggregation, which ddraw doesn't
00714  *            support
00715  *
00716  * Returns:
00717  *  CLASS_E_NOAGGREGATION if UnkOuter != NULL
00718  *  DDERR_OUTOFMEMORY if we ran out of memory
00719  *  D3D_OK on success
00720  *
00721  *****************************************************************************/
00722 static HRESULT WINAPI
00723 IDirect3DDeviceImpl_1_CreateExecuteBuffer(IDirect3DDevice *iface,
00724                                           D3DEXECUTEBUFFERDESC *Desc,
00725                                           IDirect3DExecuteBuffer **ExecuteBuffer,
00726                                           IUnknown *UnkOuter)
00727 {
00728     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
00729     IDirect3DExecuteBufferImpl* object;
00730     HRESULT hr;
00731 
00732     TRACE("iface %p, buffer_desc %p, buffer %p, outer_unknown %p.\n",
00733             iface, Desc, ExecuteBuffer, UnkOuter);
00734 
00735     if(UnkOuter)
00736         return CLASS_E_NOAGGREGATION;
00737 
00738     /* Allocate the new Execute Buffer */
00739     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DExecuteBufferImpl));
00740     if(!object)
00741     {
00742         ERR("Out of memory when allocating a IDirect3DExecuteBufferImpl structure\n");
00743         return DDERR_OUTOFMEMORY;
00744     }
00745 
00746     hr = d3d_execute_buffer_init(object, This, Desc);
00747     if (FAILED(hr))
00748     {
00749         WARN("Failed to initialize execute buffer, hr %#x.\n", hr);
00750         HeapFree(GetProcessHeap(), 0, object);
00751         return hr;
00752     }
00753 
00754     *ExecuteBuffer = &object->IDirect3DExecuteBuffer_iface;
00755 
00756     TRACE(" Returning IDirect3DExecuteBuffer at %p, implementation is at %p\n", *ExecuteBuffer, object);
00757 
00758     return D3D_OK;
00759 }
00760 
00761 /*****************************************************************************
00762  * IDirect3DDevice::Execute
00763  *
00764  * Executes all the stuff in an execute buffer.
00765  *
00766  * Params:
00767  *  ExecuteBuffer: The buffer to execute
00768  *  Viewport: The viewport used for rendering
00769  *  Flags: Some flags
00770  *
00771  * Returns:
00772  *  DDERR_INVALIDPARAMS if ExecuteBuffer == NULL
00773  *  D3D_OK on success
00774  *
00775  *****************************************************************************/
00776 static HRESULT WINAPI IDirect3DDeviceImpl_1_Execute(IDirect3DDevice *iface,
00777         IDirect3DExecuteBuffer *ExecuteBuffer, IDirect3DViewport *Viewport, DWORD Flags)
00778 {
00779     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
00780     IDirect3DExecuteBufferImpl *buffer = unsafe_impl_from_IDirect3DExecuteBuffer(ExecuteBuffer);
00781     IDirect3DViewportImpl *Direct3DViewportImpl = unsafe_impl_from_IDirect3DViewport(Viewport);
00782     HRESULT hr;
00783 
00784     TRACE("iface %p, buffer %p, viewport %p, flags %#x.\n", iface, ExecuteBuffer, Viewport, Flags);
00785 
00786     if(!buffer)
00787         return DDERR_INVALIDPARAMS;
00788 
00789     /* Execute... */
00790     wined3d_mutex_lock();
00791     hr = d3d_execute_buffer_execute(buffer, This, Direct3DViewportImpl);
00792     wined3d_mutex_unlock();
00793 
00794     return hr;
00795 }
00796 
00797 /*****************************************************************************
00798  * IDirect3DDevice3::AddViewport
00799  *
00800  * Add a Direct3DViewport to the device's viewport list. These viewports
00801  * are wrapped to IDirect3DDevice7 viewports in viewport.c
00802  *
00803  * Exists in Version 1, 2 and 3. Note that IDirect3DViewport 1, 2 and 3
00804  * are the same interfaces.
00805  *
00806  * Params:
00807  *  Viewport: The viewport to add
00808  *
00809  * Returns:
00810  *  DDERR_INVALIDPARAMS if Viewport == NULL
00811  *  D3D_OK on success
00812  *
00813  *****************************************************************************/
00814 static HRESULT WINAPI
00815 IDirect3DDeviceImpl_3_AddViewport(IDirect3DDevice3 *iface,
00816                                   IDirect3DViewport3 *Viewport)
00817 {
00818     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
00819     IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport3(Viewport);
00820 
00821     TRACE("iface %p, viewport %p.\n", iface, Viewport);
00822 
00823     /* Sanity check */
00824     if(!vp)
00825         return DDERR_INVALIDPARAMS;
00826 
00827     wined3d_mutex_lock();
00828     list_add_head(&This->viewport_list, &vp->entry);
00829     vp->active_device = This; /* Viewport must be usable for Clear() after AddViewport,
00830                                     so set active_device here. */
00831     wined3d_mutex_unlock();
00832 
00833     return D3D_OK;
00834 }
00835 
00836 static HRESULT WINAPI IDirect3DDeviceImpl_2_AddViewport(IDirect3DDevice2 *iface,
00837         IDirect3DViewport2 *Direct3DViewport2)
00838 {
00839     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
00840     IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport2(Direct3DViewport2);
00841 
00842     TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
00843 
00844     return IDirect3DDevice3_AddViewport(&This->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
00845 }
00846 
00847 static HRESULT WINAPI IDirect3DDeviceImpl_1_AddViewport(IDirect3DDevice *iface,
00848         IDirect3DViewport *Direct3DViewport)
00849 {
00850     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
00851     IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport(Direct3DViewport);
00852 
00853     TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport);
00854 
00855     return IDirect3DDevice3_AddViewport(&This->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
00856 }
00857 
00858 /*****************************************************************************
00859  * IDirect3DDevice3::DeleteViewport
00860  *
00861  * Deletes a Direct3DViewport from the device's viewport list.
00862  *
00863  * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
00864  * are equal.
00865  *
00866  * Params:
00867  *  Viewport: The viewport to delete
00868  *
00869  * Returns:
00870  *  D3D_OK on success
00871  *  DDERR_INVALIDPARAMS if the viewport wasn't found in the list
00872  *
00873  *****************************************************************************/
00874 static HRESULT WINAPI IDirect3DDeviceImpl_3_DeleteViewport(IDirect3DDevice3 *iface, IDirect3DViewport3 *viewport)
00875 {
00876     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
00877     IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport3(viewport);
00878 
00879     TRACE("iface %p, viewport %p.\n", iface, viewport);
00880 
00881     wined3d_mutex_lock();
00882 
00883     if (vp->active_device != This)
00884     {
00885         WARN("Viewport %p active device is %p.\n", vp, vp->active_device);
00886         wined3d_mutex_unlock();
00887         return DDERR_INVALIDPARAMS;
00888     }
00889 
00890     vp->active_device = NULL;
00891     list_remove(&vp->entry);
00892 
00893     wined3d_mutex_unlock();
00894 
00895     return D3D_OK;
00896 }
00897 
00898 static HRESULT WINAPI IDirect3DDeviceImpl_2_DeleteViewport(IDirect3DDevice2 *iface,
00899         IDirect3DViewport2 *Direct3DViewport2)
00900 {
00901     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
00902     IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport2(Direct3DViewport2);
00903 
00904     TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
00905 
00906     return IDirect3DDevice3_DeleteViewport(&This->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
00907 }
00908 
00909 static HRESULT WINAPI IDirect3DDeviceImpl_1_DeleteViewport(IDirect3DDevice *iface,
00910         IDirect3DViewport *Direct3DViewport)
00911 {
00912     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
00913     IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport(Direct3DViewport);
00914 
00915     TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport);
00916 
00917     return IDirect3DDevice3_DeleteViewport(&This->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
00918 }
00919 
00920 /*****************************************************************************
00921  * IDirect3DDevice3::NextViewport
00922  *
00923  * Returns a viewport from the viewport list, depending on the
00924  * passed viewport and the flags.
00925  *
00926  * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
00927  * are equal.
00928  *
00929  * Params:
00930  *  Viewport: Viewport to use for beginning the search
00931  *  Flags: D3DNEXT_NEXT, D3DNEXT_HEAD or D3DNEXT_TAIL
00932  *
00933  * Returns:
00934  *  D3D_OK on success
00935  *  DDERR_INVALIDPARAMS if the flags were wrong, or Viewport was NULL
00936  *
00937  *****************************************************************************/
00938 static HRESULT WINAPI
00939 IDirect3DDeviceImpl_3_NextViewport(IDirect3DDevice3 *iface,
00940                                    IDirect3DViewport3 *Viewport3,
00941                                    IDirect3DViewport3 **lplpDirect3DViewport3,
00942                                    DWORD Flags)
00943 {
00944     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
00945     IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport3(Viewport3);
00946     IDirect3DViewportImpl *next;
00947     struct list *entry;
00948 
00949     TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
00950             iface, Viewport3, lplpDirect3DViewport3, Flags);
00951 
00952     if(!vp)
00953     {
00954         *lplpDirect3DViewport3 = NULL;
00955         return DDERR_INVALIDPARAMS;
00956     }
00957 
00958 
00959     wined3d_mutex_lock();
00960     switch (Flags)
00961     {
00962         case D3DNEXT_NEXT:
00963             entry = list_next(&This->viewport_list, &vp->entry);
00964             break;
00965 
00966         case D3DNEXT_HEAD:
00967             entry = list_head(&This->viewport_list);
00968             break;
00969 
00970         case D3DNEXT_TAIL:
00971             entry = list_tail(&This->viewport_list);
00972             break;
00973 
00974         default:
00975             WARN("Invalid flags %#x.\n", Flags);
00976             *lplpDirect3DViewport3 = NULL;
00977             wined3d_mutex_unlock();
00978             return DDERR_INVALIDPARAMS;
00979     }
00980 
00981     if (entry)
00982     {
00983         next = LIST_ENTRY(entry, IDirect3DViewportImpl, entry);
00984         *lplpDirect3DViewport3 = &next->IDirect3DViewport3_iface;
00985     }
00986     else
00987         *lplpDirect3DViewport3 = NULL;
00988 
00989     wined3d_mutex_unlock();
00990 
00991     return D3D_OK;
00992 }
00993 
00994 static HRESULT WINAPI IDirect3DDeviceImpl_2_NextViewport(IDirect3DDevice2 *iface,
00995         IDirect3DViewport2 *Viewport2, IDirect3DViewport2 **lplpDirect3DViewport2, DWORD Flags)
00996 {
00997     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
00998     IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport2(Viewport2);
00999     IDirect3DViewport3 *res;
01000     HRESULT hr;
01001 
01002     TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
01003             iface, Viewport2, lplpDirect3DViewport2, Flags);
01004 
01005     hr = IDirect3DDevice3_NextViewport(&This->IDirect3DDevice3_iface,
01006             &vp->IDirect3DViewport3_iface, &res, Flags);
01007     *lplpDirect3DViewport2 = (IDirect3DViewport2 *)res;
01008     return hr;
01009 }
01010 
01011 static HRESULT WINAPI IDirect3DDeviceImpl_1_NextViewport(IDirect3DDevice *iface,
01012         IDirect3DViewport *Viewport, IDirect3DViewport **lplpDirect3DViewport, DWORD Flags)
01013 {
01014     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
01015     IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport(Viewport);
01016     IDirect3DViewport3 *res;
01017     HRESULT hr;
01018 
01019     TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
01020             iface, Viewport, lplpDirect3DViewport, Flags);
01021 
01022     hr = IDirect3DDevice3_NextViewport(&This->IDirect3DDevice3_iface,
01023             &vp->IDirect3DViewport3_iface, &res, Flags);
01024     *lplpDirect3DViewport = (IDirect3DViewport *)res;
01025     return hr;
01026 }
01027 
01028 /*****************************************************************************
01029  * IDirect3DDevice::Pick
01030  *
01031  * Executes an execute buffer without performing rendering. Instead, a
01032  * list of primitives that intersect with (x1,y1) of the passed rectangle
01033  * is created. IDirect3DDevice::GetPickRecords can be used to retrieve
01034  * this list.
01035  *
01036  * Version 1 only
01037  *
01038  * Params:
01039  *  ExecuteBuffer: Buffer to execute
01040  *  Viewport: Viewport to use for execution
01041  *  Flags: None are defined, according to the SDK
01042  *  Rect: Specifies the coordinates to be picked. Only x1 and y2 are used,
01043  *        x2 and y2 are ignored.
01044  *
01045  * Returns:
01046  *  D3D_OK because it's a stub
01047  *
01048  *****************************************************************************/
01049 static HRESULT WINAPI
01050 IDirect3DDeviceImpl_1_Pick(IDirect3DDevice *iface,
01051                            IDirect3DExecuteBuffer *ExecuteBuffer,
01052                            IDirect3DViewport *Viewport,
01053                            DWORD Flags,
01054                            D3DRECT *Rect)
01055 {
01056     FIXME("iface %p, buffer %p, viewport %p, flags %#x, rect %s stub!\n",
01057             iface, ExecuteBuffer, Viewport, Flags, wine_dbgstr_rect((RECT *)Rect));
01058 
01059     return D3D_OK;
01060 }
01061 
01062 /*****************************************************************************
01063  * IDirect3DDevice::GetPickRecords
01064  *
01065  * Retrieves the pick records generated by IDirect3DDevice::GetPickRecords
01066  *
01067  * Version 1 only
01068  *
01069  * Params:
01070  *  Count: Pointer to a DWORD containing the numbers of pick records to
01071  *         retrieve
01072  *  D3DPickRec: Address to store the resulting D3DPICKRECORD array.
01073  *
01074  * Returns:
01075  *  D3D_OK, because it's a stub
01076  *
01077  *****************************************************************************/
01078 static HRESULT WINAPI
01079 IDirect3DDeviceImpl_1_GetPickRecords(IDirect3DDevice *iface,
01080                                      DWORD *Count,
01081                                      D3DPICKRECORD *D3DPickRec)
01082 {
01083     FIXME("iface %p, count %p, records %p stub!\n", iface, Count, D3DPickRec);
01084 
01085     return D3D_OK;
01086 }
01087 
01088 /*****************************************************************************
01089  * IDirect3DDevice7::EnumTextureformats
01090  *
01091  * Enumerates the supported texture formats. It has a list of all possible
01092  * formats and calls IWineD3D::CheckDeviceFormat for each format to see if
01093  * WineD3D supports it. If so, then it is passed to the app.
01094  *
01095  * This is for Version 7 and 3, older versions have a different
01096  * callback function and their own implementation
01097  *
01098  * Params:
01099  *  Callback: Callback to call for each enumerated format
01100  *  Arg: Argument to pass to the callback
01101  *
01102  * Returns:
01103  *  D3D_OK on success
01104  *  DDERR_INVALIDPARAMS if Callback == NULL
01105  *
01106  *****************************************************************************/
01107 static HRESULT
01108 IDirect3DDeviceImpl_7_EnumTextureFormats(IDirect3DDevice7 *iface,
01109                                          LPD3DENUMPIXELFORMATSCALLBACK Callback,
01110                                          void *Arg)
01111 {
01112     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
01113     struct wined3d_display_mode mode;
01114     HRESULT hr;
01115     unsigned int i;
01116 
01117     static const enum wined3d_format_id FormatList[] =
01118     {
01119         /* 16 bit */
01120         WINED3DFMT_B5G5R5X1_UNORM,
01121         WINED3DFMT_B5G5R5A1_UNORM,
01122         WINED3DFMT_B4G4R4A4_UNORM,
01123         WINED3DFMT_B5G6R5_UNORM,
01124         /* 32 bit */
01125         WINED3DFMT_B8G8R8X8_UNORM,
01126         WINED3DFMT_B8G8R8A8_UNORM,
01127         /* 8 bit */
01128         WINED3DFMT_B2G3R3_UNORM,
01129         WINED3DFMT_P8_UINT,
01130         /* FOURCC codes */
01131         WINED3DFMT_DXT1,
01132         WINED3DFMT_DXT3,
01133         WINED3DFMT_DXT5,
01134     };
01135 
01136     static const enum wined3d_format_id BumpFormatList[] =
01137     {
01138         WINED3DFMT_R8G8_SNORM,
01139         WINED3DFMT_R5G5_SNORM_L6_UNORM,
01140         WINED3DFMT_R8G8_SNORM_L8X8_UNORM,
01141         WINED3DFMT_R16G16_SNORM,
01142         WINED3DFMT_R10G11B11_SNORM,
01143         WINED3DFMT_R10G10B10_SNORM_A2_UNORM
01144     };
01145 
01146     TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
01147 
01148     if(!Callback)
01149         return DDERR_INVALIDPARAMS;
01150 
01151     wined3d_mutex_lock();
01152 
01153     memset(&mode, 0, sizeof(mode));
01154     hr = wined3d_device_get_display_mode(This->ddraw->wined3d_device, 0, &mode);
01155     if (FAILED(hr))
01156     {
01157         wined3d_mutex_unlock();
01158         WARN("Cannot get the current adapter format\n");
01159         return hr;
01160     }
01161 
01162     for (i = 0; i < sizeof(FormatList) / sizeof(*FormatList); ++i)
01163     {
01164         hr = wined3d_check_device_format(This->ddraw->wined3d, WINED3DADAPTER_DEFAULT, WINED3D_DEVICE_TYPE_HAL,
01165                 mode.format_id, 0, WINED3D_RTYPE_TEXTURE, FormatList[i], SURFACE_OPENGL);
01166         if (hr == D3D_OK)
01167         {
01168             DDPIXELFORMAT pformat;
01169 
01170             memset(&pformat, 0, sizeof(pformat));
01171             pformat.dwSize = sizeof(pformat);
01172             PixelFormat_WineD3DtoDD(&pformat, FormatList[i]);
01173 
01174             TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
01175             hr = Callback(&pformat, Arg);
01176             if(hr != DDENUMRET_OK)
01177             {
01178                 TRACE("Format enumeration cancelled by application\n");
01179                 wined3d_mutex_unlock();
01180                 return D3D_OK;
01181             }
01182         }
01183     }
01184 
01185     for (i = 0; i < sizeof(BumpFormatList) / sizeof(*BumpFormatList); ++i)
01186     {
01187         hr = wined3d_check_device_format(This->ddraw->wined3d, WINED3DADAPTER_DEFAULT,
01188                 WINED3D_DEVICE_TYPE_HAL, mode.format_id, WINED3DUSAGE_QUERY_LEGACYBUMPMAP,
01189                 WINED3D_RTYPE_TEXTURE, BumpFormatList[i], SURFACE_OPENGL);
01190         if (hr == D3D_OK)
01191         {
01192             DDPIXELFORMAT pformat;
01193 
01194             memset(&pformat, 0, sizeof(pformat));
01195             pformat.dwSize = sizeof(pformat);
01196             PixelFormat_WineD3DtoDD(&pformat, BumpFormatList[i]);
01197 
01198             TRACE("Enumerating WineD3DFormat %d\n", BumpFormatList[i]);
01199             hr = Callback(&pformat, Arg);
01200             if(hr != DDENUMRET_OK)
01201             {
01202                 TRACE("Format enumeration cancelled by application\n");
01203                 wined3d_mutex_unlock();
01204                 return D3D_OK;
01205             }
01206         }
01207     }
01208     TRACE("End of enumeration\n");
01209     wined3d_mutex_unlock();
01210 
01211     return D3D_OK;
01212 }
01213 
01214 static HRESULT WINAPI
01215 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUSetup(IDirect3DDevice7 *iface,
01216                                          LPD3DENUMPIXELFORMATSCALLBACK Callback,
01217                                          void *Arg)
01218 {
01219     return IDirect3DDeviceImpl_7_EnumTextureFormats(iface, Callback, Arg);
01220 }
01221 
01222 static HRESULT WINAPI
01223 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUPreserve(IDirect3DDevice7 *iface,
01224                                          LPD3DENUMPIXELFORMATSCALLBACK Callback,
01225                                          void *Arg)
01226 {
01227     HRESULT hr;
01228     WORD old_fpucw;
01229 
01230     old_fpucw = d3d_fpu_setup();
01231     hr = IDirect3DDeviceImpl_7_EnumTextureFormats(iface, Callback, Arg);
01232     set_fpu_control_word(old_fpucw);
01233 
01234     return hr;
01235 }
01236 
01237 static HRESULT WINAPI IDirect3DDeviceImpl_3_EnumTextureFormats(IDirect3DDevice3 *iface,
01238         LPD3DENUMPIXELFORMATSCALLBACK Callback, void *Arg)
01239 {
01240     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
01241 
01242     TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
01243 
01244     return IDirect3DDevice7_EnumTextureFormats(&This->IDirect3DDevice7_iface, Callback, Arg);
01245 }
01246 
01247 /*****************************************************************************
01248  * IDirect3DDevice2::EnumTextureformats
01249  *
01250  * EnumTextureFormats for Version 1 and 2, see
01251  * IDirect3DDevice7::EnumTexureFormats for a more detailed description.
01252  *
01253  * This version has a different callback and does not enumerate FourCC
01254  * formats
01255  *
01256  *****************************************************************************/
01257 static HRESULT WINAPI
01258 IDirect3DDeviceImpl_2_EnumTextureFormats(IDirect3DDevice2 *iface,
01259                                          LPD3DENUMTEXTUREFORMATSCALLBACK Callback,
01260                                          void *Arg)
01261 {
01262     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
01263     struct wined3d_display_mode mode;
01264     HRESULT hr;
01265     unsigned int i;
01266 
01267     static const enum wined3d_format_id FormatList[] =
01268     {
01269         /* 16 bit */
01270         WINED3DFMT_B5G5R5X1_UNORM,
01271         WINED3DFMT_B5G5R5A1_UNORM,
01272         WINED3DFMT_B4G4R4A4_UNORM,
01273         WINED3DFMT_B5G6R5_UNORM,
01274         /* 32 bit */
01275         WINED3DFMT_B8G8R8X8_UNORM,
01276         WINED3DFMT_B8G8R8A8_UNORM,
01277         /* 8 bit */
01278         WINED3DFMT_B2G3R3_UNORM,
01279         WINED3DFMT_P8_UINT,
01280         /* FOURCC codes - Not in this version*/
01281     };
01282 
01283     TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
01284 
01285     if(!Callback)
01286         return DDERR_INVALIDPARAMS;
01287 
01288     wined3d_mutex_lock();
01289 
01290     memset(&mode, 0, sizeof(mode));
01291     hr = wined3d_device_get_display_mode(This->ddraw->wined3d_device, 0, &mode);
01292     if (FAILED(hr))
01293     {
01294         wined3d_mutex_unlock();
01295         WARN("Cannot get the current adapter format\n");
01296         return hr;
01297     }
01298 
01299     for (i = 0; i < sizeof(FormatList) / sizeof(*FormatList); ++i)
01300     {
01301         hr = wined3d_check_device_format(This->ddraw->wined3d, 0, WINED3D_DEVICE_TYPE_HAL,
01302                 mode.format_id, 0, WINED3D_RTYPE_TEXTURE, FormatList[i], SURFACE_OPENGL);
01303         if (hr == D3D_OK)
01304         {
01305             DDSURFACEDESC sdesc;
01306 
01307             memset(&sdesc, 0, sizeof(sdesc));
01308             sdesc.dwSize = sizeof(sdesc);
01309             sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
01310             sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
01311             sdesc.ddpfPixelFormat.dwSize = sizeof(sdesc.ddpfPixelFormat);
01312             PixelFormat_WineD3DtoDD(&sdesc.ddpfPixelFormat, FormatList[i]);
01313 
01314             TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
01315             hr = Callback(&sdesc, Arg);
01316             if(hr != DDENUMRET_OK)
01317             {
01318                 TRACE("Format enumeration cancelled by application\n");
01319                 wined3d_mutex_unlock();
01320                 return D3D_OK;
01321             }
01322         }
01323     }
01324     TRACE("End of enumeration\n");
01325     wined3d_mutex_unlock();
01326 
01327     return D3D_OK;
01328 }
01329 
01330 static HRESULT WINAPI IDirect3DDeviceImpl_1_EnumTextureFormats(IDirect3DDevice *iface,
01331         LPD3DENUMTEXTUREFORMATSCALLBACK Callback, void *Arg)
01332 {
01333     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
01334 
01335     TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
01336 
01337     return IDirect3DDevice2_EnumTextureFormats(&This->IDirect3DDevice2_iface, Callback, Arg);
01338 }
01339 
01340 /*****************************************************************************
01341  * IDirect3DDevice::CreateMatrix
01342  *
01343  * Creates a matrix handle. A handle is created and memory for a D3DMATRIX is
01344  * allocated for the handle.
01345  *
01346  * Version 1 only
01347  *
01348  * Params
01349  *  D3DMatHandle: Address to return the handle at
01350  *
01351  * Returns:
01352  *  D3D_OK on success
01353  *  DDERR_INVALIDPARAMS if D3DMatHandle = NULL
01354  *
01355  *****************************************************************************/
01356 static HRESULT WINAPI
01357 IDirect3DDeviceImpl_1_CreateMatrix(IDirect3DDevice *iface, D3DMATRIXHANDLE *D3DMatHandle)
01358 {
01359     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
01360     D3DMATRIX *Matrix;
01361     DWORD h;
01362 
01363     TRACE("iface %p, matrix_handle %p.\n", iface, D3DMatHandle);
01364 
01365     if(!D3DMatHandle)
01366         return DDERR_INVALIDPARAMS;
01367 
01368     Matrix = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(D3DMATRIX));
01369     if(!Matrix)
01370     {
01371         ERR("Out of memory when allocating a D3DMATRIX\n");
01372         return DDERR_OUTOFMEMORY;
01373     }
01374 
01375     wined3d_mutex_lock();
01376 
01377     h = ddraw_allocate_handle(&This->handle_table, Matrix, DDRAW_HANDLE_MATRIX);
01378     if (h == DDRAW_INVALID_HANDLE)
01379     {
01380         ERR("Failed to allocate a matrix handle.\n");
01381         HeapFree(GetProcessHeap(), 0, Matrix);
01382         wined3d_mutex_unlock();
01383         return DDERR_OUTOFMEMORY;
01384     }
01385 
01386     *D3DMatHandle = h + 1;
01387 
01388     TRACE(" returning matrix handle %d\n", *D3DMatHandle);
01389 
01390     wined3d_mutex_unlock();
01391 
01392     return D3D_OK;
01393 }
01394 
01395 /*****************************************************************************
01396  * IDirect3DDevice::SetMatrix
01397  *
01398  * Sets a matrix for a matrix handle. The matrix is copied into the memory
01399  * allocated for the handle
01400  *
01401  * Version 1 only
01402  *
01403  * Params:
01404  *  D3DMatHandle: Handle to set the matrix to
01405  *  D3DMatrix: Matrix to set
01406  *
01407  * Returns:
01408  *  D3D_OK on success
01409  *  DDERR_INVALIDPARAMS if the handle of the matrix is invalid or the matrix
01410  *   to set is NULL
01411  *
01412  *****************************************************************************/
01413 static HRESULT WINAPI
01414 IDirect3DDeviceImpl_1_SetMatrix(IDirect3DDevice *iface,
01415                                 D3DMATRIXHANDLE D3DMatHandle,
01416                                 D3DMATRIX *D3DMatrix)
01417 {
01418     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
01419     D3DMATRIX *m;
01420 
01421     TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
01422 
01423     if (!D3DMatrix) return DDERR_INVALIDPARAMS;
01424 
01425     wined3d_mutex_lock();
01426 
01427     m = ddraw_get_object(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
01428     if (!m)
01429     {
01430         WARN("Invalid matrix handle.\n");
01431         wined3d_mutex_unlock();
01432         return DDERR_INVALIDPARAMS;
01433     }
01434 
01435     if (TRACE_ON(ddraw))
01436         dump_D3DMATRIX(D3DMatrix);
01437 
01438     *m = *D3DMatrix;
01439 
01440     if (D3DMatHandle == This->world)
01441         wined3d_device_set_transform(This->wined3d_device,
01442                 WINED3D_TS_WORLD_MATRIX(0), (struct wined3d_matrix *)D3DMatrix);
01443 
01444     if (D3DMatHandle == This->view)
01445         wined3d_device_set_transform(This->wined3d_device,
01446                 WINED3D_TS_VIEW, (struct wined3d_matrix *)D3DMatrix);
01447 
01448     if (D3DMatHandle == This->proj)
01449         wined3d_device_set_transform(This->wined3d_device,
01450                 WINED3D_TS_PROJECTION, (struct wined3d_matrix *)D3DMatrix);
01451 
01452     wined3d_mutex_unlock();
01453 
01454     return D3D_OK;
01455 }
01456 
01457 /*****************************************************************************
01458  * IDirect3DDevice::GetMatrix
01459  *
01460  * Returns the content of a D3DMATRIX handle
01461  *
01462  * Version 1 only
01463  *
01464  * Params:
01465  *  D3DMatHandle: Matrix handle to read the content from
01466  *  D3DMatrix: Address to store the content at
01467  *
01468  * Returns:
01469  *  D3D_OK on success
01470  *  DDERR_INVALIDPARAMS if D3DMatHandle is invalid or D3DMatrix is NULL
01471  *
01472  *****************************************************************************/
01473 static HRESULT WINAPI
01474 IDirect3DDeviceImpl_1_GetMatrix(IDirect3DDevice *iface,
01475                                 D3DMATRIXHANDLE D3DMatHandle,
01476                                 D3DMATRIX *D3DMatrix)
01477 {
01478     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
01479     D3DMATRIX *m;
01480 
01481     TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
01482 
01483     if (!D3DMatrix) return DDERR_INVALIDPARAMS;
01484 
01485     wined3d_mutex_lock();
01486 
01487     m = ddraw_get_object(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
01488     if (!m)
01489     {
01490         WARN("Invalid matrix handle.\n");
01491         wined3d_mutex_unlock();
01492         return DDERR_INVALIDPARAMS;
01493     }
01494 
01495     *D3DMatrix = *m;
01496 
01497     wined3d_mutex_unlock();
01498 
01499     return D3D_OK;
01500 }
01501 
01502 /*****************************************************************************
01503  * IDirect3DDevice::DeleteMatrix
01504  *
01505  * Destroys a Matrix handle. Frees the memory and unsets the handle data
01506  *
01507  * Version 1 only
01508  *
01509  * Params:
01510  *  D3DMatHandle: Handle to destroy
01511  *
01512  * Returns:
01513  *  D3D_OK on success
01514  *  DDERR_INVALIDPARAMS if D3DMatHandle is invalid
01515  *
01516  *****************************************************************************/
01517 static HRESULT WINAPI
01518 IDirect3DDeviceImpl_1_DeleteMatrix(IDirect3DDevice *iface,
01519                                    D3DMATRIXHANDLE D3DMatHandle)
01520 {
01521     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
01522     D3DMATRIX *m;
01523 
01524     TRACE("iface %p, matrix_handle %#x.\n", iface, D3DMatHandle);
01525 
01526     wined3d_mutex_lock();
01527 
01528     m = ddraw_free_handle(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
01529     if (!m)
01530     {
01531         WARN("Invalid matrix handle.\n");
01532         wined3d_mutex_unlock();
01533         return DDERR_INVALIDPARAMS;
01534     }
01535 
01536     wined3d_mutex_unlock();
01537 
01538     HeapFree(GetProcessHeap(), 0, m);
01539 
01540     return D3D_OK;
01541 }
01542 
01543 /*****************************************************************************
01544  * IDirect3DDevice7::BeginScene
01545  *
01546  * This method must be called before any rendering is performed.
01547  * IDirect3DDevice::EndScene has to be called after the scene is complete
01548  *
01549  * Version 1, 2, 3 and 7
01550  *
01551  * Returns:
01552  *  D3D_OK on success, for details see IWineD3DDevice::BeginScene
01553  *  D3DERR_SCENE_IN_SCENE if WineD3D returns an error(Only in case of an already
01554  *  started scene).
01555  *
01556  *****************************************************************************/
01557 static HRESULT
01558 IDirect3DDeviceImpl_7_BeginScene(IDirect3DDevice7 *iface)
01559 {
01560     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
01561     HRESULT hr;
01562 
01563     TRACE("iface %p.\n", iface);
01564 
01565     wined3d_mutex_lock();
01566     hr = wined3d_device_begin_scene(This->wined3d_device);
01567     wined3d_mutex_unlock();
01568 
01569     if(hr == WINED3D_OK) return D3D_OK;
01570     else return D3DERR_SCENE_IN_SCENE; /* TODO: Other possible causes of failure */
01571 }
01572 
01573 static HRESULT WINAPI
01574 IDirect3DDeviceImpl_7_BeginScene_FPUSetup(IDirect3DDevice7 *iface)
01575 {
01576     return IDirect3DDeviceImpl_7_BeginScene(iface);
01577 }
01578 
01579 static HRESULT WINAPI
01580 IDirect3DDeviceImpl_7_BeginScene_FPUPreserve(IDirect3DDevice7 *iface)
01581 {
01582     HRESULT hr;
01583     WORD old_fpucw;
01584 
01585     old_fpucw = d3d_fpu_setup();
01586     hr = IDirect3DDeviceImpl_7_BeginScene(iface);
01587     set_fpu_control_word(old_fpucw);
01588 
01589     return hr;
01590 }
01591 
01592 static HRESULT WINAPI IDirect3DDeviceImpl_3_BeginScene(IDirect3DDevice3 *iface)
01593 {
01594     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
01595     TRACE("iface %p.\n", iface);
01596 
01597     return IDirect3DDevice7_BeginScene(&This->IDirect3DDevice7_iface);
01598 }
01599 
01600 static HRESULT WINAPI IDirect3DDeviceImpl_2_BeginScene(IDirect3DDevice2 *iface)
01601 {
01602     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
01603     TRACE("iface %p.\n", iface);
01604 
01605     return IDirect3DDevice7_BeginScene(&This->IDirect3DDevice7_iface);
01606 }
01607 
01608 static HRESULT WINAPI IDirect3DDeviceImpl_1_BeginScene(IDirect3DDevice *iface)
01609 {
01610     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
01611     TRACE("iface %p.\n", iface);
01612 
01613     return IDirect3DDevice7_BeginScene(&This->IDirect3DDevice7_iface);
01614 }
01615 
01616 /*****************************************************************************
01617  * IDirect3DDevice7::EndScene
01618  *
01619  * Ends a scene that has been begun with IDirect3DDevice7::BeginScene.
01620  * This method must be called after rendering is finished.
01621  *
01622  * Version 1, 2, 3 and 7
01623  *
01624  * Returns:
01625  *  D3D_OK on success, for details see IWineD3DDevice::EndScene
01626  *  D3DERR_SCENE_NOT_IN_SCENE is returned if WineD3D returns an error. It does
01627  *  that only if the scene was already ended.
01628  *
01629  *****************************************************************************/
01630 static HRESULT
01631 IDirect3DDeviceImpl_7_EndScene(IDirect3DDevice7 *iface)
01632 {
01633     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
01634     HRESULT hr;
01635 
01636     TRACE("iface %p.\n", iface);
01637 
01638     wined3d_mutex_lock();
01639     hr = wined3d_device_end_scene(This->wined3d_device);
01640     wined3d_mutex_unlock();
01641 
01642     if(hr == WINED3D_OK) return D3D_OK;
01643     else return D3DERR_SCENE_NOT_IN_SCENE;
01644 }
01645 
01646 static HRESULT WINAPI DECLSPEC_HOTPATCH
01647 IDirect3DDeviceImpl_7_EndScene_FPUSetup(IDirect3DDevice7 *iface)
01648 {
01649     return IDirect3DDeviceImpl_7_EndScene(iface);
01650 }
01651 
01652 static HRESULT WINAPI DECLSPEC_HOTPATCH
01653 IDirect3DDeviceImpl_7_EndScene_FPUPreserve(IDirect3DDevice7 *iface)
01654 {
01655     HRESULT hr;
01656     WORD old_fpucw;
01657 
01658     old_fpucw = d3d_fpu_setup();
01659     hr = IDirect3DDeviceImpl_7_EndScene(iface);
01660     set_fpu_control_word(old_fpucw);
01661 
01662     return hr;
01663 }
01664 
01665 static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDeviceImpl_3_EndScene(IDirect3DDevice3 *iface)
01666 {
01667     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
01668     TRACE("iface %p.\n", iface);
01669 
01670     return IDirect3DDevice7_EndScene(&This->IDirect3DDevice7_iface);
01671 }
01672 
01673 static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDeviceImpl_2_EndScene(IDirect3DDevice2 *iface)
01674 {
01675     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
01676     TRACE("iface %p.\n", iface);
01677 
01678     return IDirect3DDevice7_EndScene(&This->IDirect3DDevice7_iface);
01679 }
01680 
01681 static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDeviceImpl_1_EndScene(IDirect3DDevice *iface)
01682 {
01683     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
01684     TRACE("iface %p.\n", iface);
01685 
01686     return IDirect3DDevice7_EndScene(&This->IDirect3DDevice7_iface);
01687 }
01688 
01689 /*****************************************************************************
01690  * IDirect3DDevice7::GetDirect3D
01691  *
01692  * Returns the IDirect3D(= interface to the DirectDraw object) used to create
01693  * this device.
01694  *
01695  * Params:
01696  *  Direct3D7: Address to store the interface pointer at
01697  *
01698  * Returns:
01699  *  D3D_OK on success
01700  *  DDERR_INVALIDPARAMS if Direct3D7 == NULL
01701  *
01702  *****************************************************************************/
01703 static HRESULT WINAPI
01704 IDirect3DDeviceImpl_7_GetDirect3D(IDirect3DDevice7 *iface,
01705                                   IDirect3D7 **Direct3D7)
01706 {
01707     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
01708 
01709     TRACE("iface %p, d3d %p.\n", iface, Direct3D7);
01710 
01711     if(!Direct3D7)
01712         return DDERR_INVALIDPARAMS;
01713 
01714     *Direct3D7 = &This->ddraw->IDirect3D7_iface;
01715     IDirect3D7_AddRef(*Direct3D7);
01716 
01717     TRACE(" returning interface %p\n", *Direct3D7);
01718     return D3D_OK;
01719 }
01720 
01721 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetDirect3D(IDirect3DDevice3 *iface,
01722         IDirect3D3 **Direct3D3)
01723 {
01724     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
01725 
01726     TRACE("iface %p, d3d %p.\n", iface, Direct3D3);
01727 
01728     if(!Direct3D3)
01729         return DDERR_INVALIDPARAMS;
01730 
01731     IDirect3D3_AddRef(&This->ddraw->IDirect3D3_iface);
01732     *Direct3D3 = &This->ddraw->IDirect3D3_iface;
01733     TRACE(" returning interface %p\n", *Direct3D3);
01734     return D3D_OK;
01735 }
01736 
01737 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetDirect3D(IDirect3DDevice2 *iface,
01738         IDirect3D2 **Direct3D2)
01739 {
01740     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
01741 
01742     TRACE("iface %p, d3d %p.\n", iface, Direct3D2);
01743 
01744     if(!Direct3D2)
01745         return DDERR_INVALIDPARAMS;
01746 
01747     IDirect3D2_AddRef(&This->ddraw->IDirect3D2_iface);
01748     *Direct3D2 = &This->ddraw->IDirect3D2_iface;
01749     TRACE(" returning interface %p\n", *Direct3D2);
01750     return D3D_OK;
01751 }
01752 
01753 static HRESULT WINAPI IDirect3DDeviceImpl_1_GetDirect3D(IDirect3DDevice *iface,
01754         IDirect3D **Direct3D)
01755 {
01756     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
01757 
01758     TRACE("iface %p, d3d %p.\n", iface, Direct3D);
01759 
01760     if(!Direct3D)
01761         return DDERR_INVALIDPARAMS;
01762 
01763     IDirect3D_AddRef(&This->ddraw->IDirect3D_iface);
01764     *Direct3D = &This->ddraw->IDirect3D_iface;
01765     TRACE(" returning interface %p\n", *Direct3D);
01766     return D3D_OK;
01767 }
01768 
01769 /*****************************************************************************
01770  * IDirect3DDevice3::SetCurrentViewport
01771  *
01772  * Sets a Direct3DViewport as the current viewport.
01773  * For the thunks note that all viewport interface versions are equal
01774  *
01775  * Params:
01776  *  Direct3DViewport3: The viewport to set
01777  *
01778  * Version 2 and 3
01779  *
01780  * Returns:
01781  *  D3D_OK on success
01782  *  (Is a NULL viewport valid?)
01783  *
01784  *****************************************************************************/
01785 static HRESULT WINAPI
01786 IDirect3DDeviceImpl_3_SetCurrentViewport(IDirect3DDevice3 *iface,
01787                                          IDirect3DViewport3 *Direct3DViewport3)
01788 {
01789     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
01790     IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport3(Direct3DViewport3);
01791 
01792     TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport3);
01793 
01794     wined3d_mutex_lock();
01795     /* Do nothing if the specified viewport is the same as the current one */
01796     if (This->current_viewport == vp )
01797     {
01798         wined3d_mutex_unlock();
01799         return D3D_OK;
01800     }
01801 
01802     if (vp->active_device != This)
01803     {
01804         WARN("Viewport %p active device is %p.\n", vp, vp->active_device);
01805         wined3d_mutex_unlock();
01806         return DDERR_INVALIDPARAMS;
01807     }
01808 
01809     /* Release previous viewport and AddRef the new one */
01810     if (This->current_viewport)
01811     {
01812         TRACE("ViewportImpl is at %p, interface is at %p\n", This->current_viewport,
01813                 &This->current_viewport->IDirect3DViewport3_iface);
01814         IDirect3DViewport3_Release(&This->current_viewport->IDirect3DViewport3_iface);
01815     }
01816     IDirect3DViewport3_AddRef(Direct3DViewport3);
01817 
01818     /* Set this viewport as the current viewport */
01819     This->current_viewport = vp;
01820 
01821     /* Activate this viewport */
01822     viewport_activate(This->current_viewport, FALSE);
01823 
01824     wined3d_mutex_unlock();
01825 
01826     return D3D_OK;
01827 }
01828 
01829 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetCurrentViewport(IDirect3DDevice2 *iface,
01830         IDirect3DViewport2 *Direct3DViewport2)
01831 {
01832     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
01833     IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport2(Direct3DViewport2);
01834 
01835     TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
01836 
01837     return IDirect3DDevice3_SetCurrentViewport(&This->IDirect3DDevice3_iface,
01838             &vp->IDirect3DViewport3_iface);
01839 }
01840 
01841 /*****************************************************************************
01842  * IDirect3DDevice3::GetCurrentViewport
01843  *
01844  * Returns the currently active viewport.
01845  *
01846  * Version 2 and 3
01847  *
01848  * Params:
01849  *  Direct3DViewport3: Address to return the interface pointer at
01850  *
01851  * Returns:
01852  *  D3D_OK on success
01853  *  DDERR_INVALIDPARAMS if Direct3DViewport == NULL
01854  *
01855  *****************************************************************************/
01856 static HRESULT WINAPI
01857 IDirect3DDeviceImpl_3_GetCurrentViewport(IDirect3DDevice3 *iface,
01858                                          IDirect3DViewport3 **Direct3DViewport3)
01859 {
01860     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
01861 
01862     TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport3);
01863 
01864     if(!Direct3DViewport3)
01865         return DDERR_INVALIDPARAMS;
01866 
01867     wined3d_mutex_lock();
01868     *Direct3DViewport3 = &This->current_viewport->IDirect3DViewport3_iface;
01869 
01870     /* AddRef the returned viewport */
01871     if(*Direct3DViewport3) IDirect3DViewport3_AddRef(*Direct3DViewport3);
01872 
01873     TRACE(" returning interface %p\n", *Direct3DViewport3);
01874 
01875     wined3d_mutex_unlock();
01876 
01877     return D3D_OK;
01878 }
01879 
01880 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetCurrentViewport(IDirect3DDevice2 *iface,
01881         IDirect3DViewport2 **Direct3DViewport2)
01882 {
01883     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
01884     HRESULT hr;
01885 
01886     TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
01887 
01888     hr = IDirect3DDevice3_GetCurrentViewport(&This->IDirect3DDevice3_iface,
01889             (IDirect3DViewport3 **)Direct3DViewport2);
01890     if(hr != D3D_OK) return hr;
01891     return D3D_OK;
01892 }
01893 
01894 /*****************************************************************************
01895  * IDirect3DDevice7::SetRenderTarget
01896  *
01897  * Sets the render target for the Direct3DDevice.
01898  * For the thunks note that IDirectDrawSurface7 == IDirectDrawSurface4 and
01899  * IDirectDrawSurface3 == IDirectDrawSurface
01900  *
01901  * Version 2, 3 and 7
01902  *
01903  * Params:
01904  *  NewTarget: Pointer to an IDirectDrawSurface7 interface to set as the new
01905  *             render target
01906  *  Flags: Some flags
01907  *
01908  * Returns:
01909  *  D3D_OK on success, for details see IWineD3DDevice::SetRenderTarget
01910  *
01911  *****************************************************************************/
01912 static HRESULT d3d_device_set_render_target(IDirect3DDeviceImpl *This, IDirectDrawSurfaceImpl *Target)
01913 {
01914     HRESULT hr;
01915 
01916     wined3d_mutex_lock();
01917 
01918     if(This->target == Target)
01919     {
01920         TRACE("No-op SetRenderTarget operation, not doing anything\n");
01921         wined3d_mutex_unlock();
01922         return D3D_OK;
01923     }
01924     This->target = Target;
01925     hr = wined3d_device_set_render_target(This->wined3d_device, 0,
01926             Target ? Target->wined3d_surface : NULL, FALSE);
01927     if(hr != D3D_OK)
01928     {
01929         wined3d_mutex_unlock();
01930         return hr;
01931     }
01932     IDirect3DDeviceImpl_UpdateDepthStencil(This);
01933 
01934     wined3d_mutex_unlock();
01935 
01936     return D3D_OK;
01937 }
01938 
01939 static HRESULT
01940 IDirect3DDeviceImpl_7_SetRenderTarget(IDirect3DDevice7 *iface,
01941                                       IDirectDrawSurface7 *NewTarget,
01942                                       DWORD Flags)
01943 {
01944     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
01945     IDirectDrawSurfaceImpl *Target = unsafe_impl_from_IDirectDrawSurface7(NewTarget);
01946 
01947     TRACE("iface %p, target %p, flags %#x.\n", iface, NewTarget, Flags);
01948     /* Flags: Not used */
01949 
01950     IDirectDrawSurface7_AddRef(NewTarget);
01951     IDirectDrawSurface7_Release(&This->target->IDirectDrawSurface7_iface);
01952     return d3d_device_set_render_target(This, Target);
01953 }
01954 
01955 static HRESULT WINAPI
01956 IDirect3DDeviceImpl_7_SetRenderTarget_FPUSetup(IDirect3DDevice7 *iface,
01957                                       IDirectDrawSurface7 *NewTarget,
01958                                       DWORD Flags)
01959 {
01960     return IDirect3DDeviceImpl_7_SetRenderTarget(iface, NewTarget, Flags);
01961 }
01962 
01963 static HRESULT WINAPI
01964 IDirect3DDeviceImpl_7_SetRenderTarget_FPUPreserve(IDirect3DDevice7 *iface,
01965                                       IDirectDrawSurface7 *NewTarget,
01966                                       DWORD Flags)
01967 {
01968     HRESULT hr;
01969     WORD old_fpucw;
01970 
01971     old_fpucw = d3d_fpu_setup();
01972     hr = IDirect3DDeviceImpl_7_SetRenderTarget(iface, NewTarget, Flags);
01973     set_fpu_control_word(old_fpucw);
01974 
01975     return hr;
01976 }
01977 
01978 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetRenderTarget(IDirect3DDevice3 *iface,
01979         IDirectDrawSurface4 *NewRenderTarget, DWORD Flags)
01980 {
01981     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
01982     IDirectDrawSurfaceImpl *Target = unsafe_impl_from_IDirectDrawSurface4(NewRenderTarget);
01983 
01984     TRACE("iface %p, target %p, flags %#x.\n", iface, NewRenderTarget, Flags);
01985 
01986     IDirectDrawSurface4_AddRef(NewRenderTarget);
01987     IDirectDrawSurface4_Release(&This->target->IDirectDrawSurface4_iface);
01988     return d3d_device_set_render_target(This, Target);
01989 }
01990 
01991 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetRenderTarget(IDirect3DDevice2 *iface,
01992         IDirectDrawSurface *NewRenderTarget, DWORD Flags)
01993 {
01994     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
01995     IDirectDrawSurfaceImpl *Target = unsafe_impl_from_IDirectDrawSurface(NewRenderTarget);
01996 
01997     TRACE("iface %p, target %p, flags %#x.\n", iface, NewRenderTarget, Flags);
01998 
01999     IDirectDrawSurface_AddRef(NewRenderTarget);
02000     IDirectDrawSurface_Release(&This->target->IDirectDrawSurface_iface);
02001     return d3d_device_set_render_target(This, Target);
02002 }
02003 
02004 /*****************************************************************************
02005  * IDirect3DDevice7::GetRenderTarget
02006  *
02007  * Returns the current render target.
02008  * This is handled locally, because the WineD3D render target's parent
02009  * is an IParent
02010  *
02011  * Version 2, 3 and 7
02012  *
02013  * Params:
02014  *  RenderTarget: Address to store the surface interface pointer
02015  *
02016  * Returns:
02017  *  D3D_OK on success
02018  *  DDERR_INVALIDPARAMS if RenderTarget == NULL
02019  *
02020  *****************************************************************************/
02021 static HRESULT WINAPI
02022 IDirect3DDeviceImpl_7_GetRenderTarget(IDirect3DDevice7 *iface,
02023                                       IDirectDrawSurface7 **RenderTarget)
02024 {
02025     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
02026 
02027     TRACE("iface %p, target %p.\n", iface, RenderTarget);
02028 
02029     if(!RenderTarget)
02030         return DDERR_INVALIDPARAMS;
02031 
02032     wined3d_mutex_lock();
02033     *RenderTarget = &This->target->IDirectDrawSurface7_iface;
02034     IDirectDrawSurface7_AddRef(*RenderTarget);
02035     wined3d_mutex_unlock();
02036 
02037     return D3D_OK;
02038 }
02039 
02040 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetRenderTarget(IDirect3DDevice3 *iface,
02041         IDirectDrawSurface4 **RenderTarget)
02042 {
02043     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
02044     IDirectDrawSurface7 *RenderTarget7;
02045     IDirectDrawSurfaceImpl *RenderTargetImpl;
02046     HRESULT hr;
02047 
02048     TRACE("iface %p, target %p.\n", iface, RenderTarget);
02049 
02050     if(!RenderTarget)
02051         return DDERR_INVALIDPARAMS;
02052 
02053     hr = IDirect3DDevice7_GetRenderTarget(&This->IDirect3DDevice7_iface, &RenderTarget7);
02054     if(hr != D3D_OK) return hr;
02055     RenderTargetImpl = impl_from_IDirectDrawSurface7(RenderTarget7);
02056     *RenderTarget = &RenderTargetImpl->IDirectDrawSurface4_iface;
02057     IDirectDrawSurface4_AddRef(*RenderTarget);
02058     IDirectDrawSurface7_Release(RenderTarget7);
02059     return D3D_OK;
02060 }
02061 
02062 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetRenderTarget(IDirect3DDevice2 *iface,
02063         IDirectDrawSurface **RenderTarget)
02064 {
02065     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
02066     IDirectDrawSurface7 *RenderTarget7;
02067     IDirectDrawSurfaceImpl *RenderTargetImpl;
02068     HRESULT hr;
02069 
02070     TRACE("iface %p, target %p.\n", iface, RenderTarget);
02071 
02072     if(!RenderTarget)
02073         return DDERR_INVALIDPARAMS;
02074 
02075     hr = IDirect3DDevice7_GetRenderTarget(&This->IDirect3DDevice7_iface, &RenderTarget7);
02076     if(hr != D3D_OK) return hr;
02077     RenderTargetImpl = impl_from_IDirectDrawSurface7(RenderTarget7);
02078     *RenderTarget = &RenderTargetImpl->IDirectDrawSurface_iface;
02079     IDirectDrawSurface_AddRef(*RenderTarget);
02080     IDirectDrawSurface7_Release(RenderTarget7);
02081     return D3D_OK;
02082 }
02083 
02084 /*****************************************************************************
02085  * IDirect3DDevice3::Begin
02086  *
02087  * Begins a description block of vertices. This is similar to glBegin()
02088  * and glEnd(). After a call to IDirect3DDevice3::End, the vertices
02089  * described with IDirect3DDevice::Vertex are drawn.
02090  *
02091  * Version 2 and 3
02092  *
02093  * Params:
02094  *  PrimitiveType: The type of primitives to draw
02095  *  VertexTypeDesc: A flexible vertex format description of the vertices
02096  *  Flags: Some flags..
02097  *
02098  * Returns:
02099  *  D3D_OK on success
02100  *
02101  *****************************************************************************/
02102 static HRESULT WINAPI
02103 IDirect3DDeviceImpl_3_Begin(IDirect3DDevice3 *iface,
02104                             D3DPRIMITIVETYPE PrimitiveType,
02105                             DWORD VertexTypeDesc,
02106                             DWORD Flags)
02107 {
02108     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
02109 
02110     TRACE("iface %p, primitive_type %#x, FVF %#x, flags %#x.\n",
02111             iface, PrimitiveType, VertexTypeDesc, Flags);
02112 
02113     wined3d_mutex_lock();
02114     This->primitive_type = PrimitiveType;
02115     This->vertex_type = VertexTypeDesc;
02116     This->render_flags = Flags;
02117     This->vertex_size = get_flexible_vertex_size(This->vertex_type);
02118     This->nb_vertices = 0;
02119     wined3d_mutex_unlock();
02120 
02121     return D3D_OK;
02122 }
02123 
02124 static HRESULT WINAPI IDirect3DDeviceImpl_2_Begin(IDirect3DDevice2 *iface, D3DPRIMITIVETYPE d3dpt,
02125         D3DVERTEXTYPE dwVertexTypeDesc, DWORD dwFlags)
02126 {
02127     DWORD FVF;
02128     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
02129 
02130     TRACE("iface %p, primitive_type %#x, vertex_type %#x, flags %#x.\n",
02131             iface, d3dpt, dwVertexTypeDesc, dwFlags);
02132 
02133     switch(dwVertexTypeDesc)
02134     {
02135         case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
02136         case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
02137         case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
02138         default:
02139             ERR("Unexpected vertex type %d\n", dwVertexTypeDesc);
02140             return DDERR_INVALIDPARAMS;  /* Should never happen */
02141     };
02142 
02143     return IDirect3DDevice3_Begin(&This->IDirect3DDevice3_iface, d3dpt, FVF, dwFlags);
02144 }
02145 
02146 /*****************************************************************************
02147  * IDirect3DDevice3::BeginIndexed
02148  *
02149  * Draws primitives based on vertices in a vertex array which are specified
02150  * by indices.
02151  *
02152  * Version 2 and 3
02153  *
02154  * Params:
02155  *  PrimitiveType: Primitive type to draw
02156  *  VertexType: A FVF description of the vertex format
02157  *  Vertices: pointer to an array containing the vertices
02158  *  NumVertices: The number of vertices in the vertex array
02159  *  Flags: Some flags ...
02160  *
02161  * Returns:
02162  *  D3D_OK, because it's a stub
02163  *
02164  *****************************************************************************/
02165 static HRESULT WINAPI
02166 IDirect3DDeviceImpl_3_BeginIndexed(IDirect3DDevice3 *iface,
02167                                    D3DPRIMITIVETYPE PrimitiveType,
02168                                    DWORD VertexType,
02169                                    void *Vertices,
02170                                    DWORD NumVertices,
02171                                    DWORD Flags)
02172 {
02173     FIXME("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
02174             iface, PrimitiveType, VertexType, Vertices, NumVertices, Flags);
02175 
02176     return D3D_OK;
02177 }
02178 
02179 
02180 static HRESULT WINAPI IDirect3DDeviceImpl_2_BeginIndexed(IDirect3DDevice2 *iface,
02181         D3DPRIMITIVETYPE d3dptPrimitiveType, D3DVERTEXTYPE d3dvtVertexType,
02182         void *lpvVertices, DWORD dwNumVertices, DWORD dwFlags)
02183 {
02184     DWORD FVF;
02185     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
02186 
02187     TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
02188             iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwNumVertices, dwFlags);
02189 
02190     switch(d3dvtVertexType)
02191     {
02192         case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
02193         case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
02194         case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
02195         default:
02196             ERR("Unexpected vertex type %d\n", d3dvtVertexType);
02197             return DDERR_INVALIDPARAMS;  /* Should never happen */
02198     };
02199 
02200     return IDirect3DDevice3_BeginIndexed(&This->IDirect3DDevice3_iface,
02201             d3dptPrimitiveType, FVF, lpvVertices, dwNumVertices, dwFlags);
02202 }
02203 
02204 /*****************************************************************************
02205  * IDirect3DDevice3::Vertex
02206  *
02207  * Draws a vertex as described by IDirect3DDevice3::Begin. It places all
02208  * drawn vertices in a vertex buffer. If the buffer is too small, its
02209  * size is increased.
02210  *
02211  * Version 2 and 3
02212  *
02213  * Params:
02214  *  Vertex: Pointer to the vertex
02215  *
02216  * Returns:
02217  *  D3D_OK, on success
02218  *  DDERR_INVALIDPARAMS if Vertex is NULL
02219  *
02220  *****************************************************************************/
02221 static HRESULT WINAPI
02222 IDirect3DDeviceImpl_3_Vertex(IDirect3DDevice3 *iface,
02223                              void *Vertex)
02224 {
02225     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
02226 
02227     TRACE("iface %p, vertex %p.\n", iface, Vertex);
02228 
02229     if(!Vertex)
02230         return DDERR_INVALIDPARAMS;
02231 
02232     wined3d_mutex_lock();
02233     if ((This->nb_vertices+1)*This->vertex_size > This->buffer_size)
02234     {
02235         BYTE *old_buffer;
02236         This->buffer_size = This->buffer_size ? This->buffer_size * 2 : This->vertex_size * 3;
02237         old_buffer = This->vertex_buffer;
02238         This->vertex_buffer = HeapAlloc(GetProcessHeap(), 0, This->buffer_size);
02239         if (old_buffer)
02240         {
02241             CopyMemory(This->vertex_buffer, old_buffer, This->nb_vertices * This->vertex_size);
02242             HeapFree(GetProcessHeap(), 0, old_buffer);
02243         }
02244     }
02245 
02246     CopyMemory(This->vertex_buffer + This->nb_vertices++ * This->vertex_size, Vertex, This->vertex_size);
02247     wined3d_mutex_unlock();
02248 
02249     return D3D_OK;
02250 }
02251 
02252 static HRESULT WINAPI IDirect3DDeviceImpl_2_Vertex(IDirect3DDevice2 *iface, void *lpVertexType)
02253 {
02254     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
02255 
02256     TRACE("iface %p, vertex %p.\n", iface, lpVertexType);
02257 
02258     return IDirect3DDevice3_Vertex(&This->IDirect3DDevice3_iface, lpVertexType);
02259 }
02260 
02261 /*****************************************************************************
02262  * IDirect3DDevice3::Index
02263  *
02264  * Specifies an index to a vertex to be drawn. The vertex array has to
02265  * be specified with BeginIndexed first.
02266  *
02267  * Parameters:
02268  *  VertexIndex: The index of the vertex to draw
02269  *
02270  * Returns:
02271  *  D3D_OK because it's a stub
02272  *
02273  *****************************************************************************/
02274 static HRESULT WINAPI
02275 IDirect3DDeviceImpl_3_Index(IDirect3DDevice3 *iface,
02276                             WORD VertexIndex)
02277 {
02278     FIXME("iface %p, index %#x stub!\n", iface, VertexIndex);
02279 
02280     return D3D_OK;
02281 }
02282 
02283 static HRESULT WINAPI IDirect3DDeviceImpl_2_Index(IDirect3DDevice2 *iface, WORD wVertexIndex)
02284 {
02285     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
02286 
02287     TRACE("iface %p, index %#x.\n", iface, wVertexIndex);
02288 
02289     return IDirect3DDevice3_Index(&This->IDirect3DDevice3_iface, wVertexIndex);
02290 }
02291 
02292 /*****************************************************************************
02293  * IDirect3DDevice3::End
02294  *
02295  * Ends a draw begun with IDirect3DDevice3::Begin or
02296  * IDirect3DDevice::BeginIndexed. The vertices specified with
02297  * IDirect3DDevice::Vertex or IDirect3DDevice::Index are drawn using
02298  * the IDirect3DDevice7::DrawPrimitive method. So far only
02299  * non-indexed mode is supported
02300  *
02301  * Version 2 and 3
02302  *
02303  * Params:
02304  *  Flags: Some flags, as usual. Don't know which are defined
02305  *
02306  * Returns:
02307  *  The return value of IDirect3DDevice7::DrawPrimitive
02308  *
02309  *****************************************************************************/
02310 static HRESULT WINAPI
02311 IDirect3DDeviceImpl_3_End(IDirect3DDevice3 *iface,
02312                           DWORD Flags)
02313 {
02314     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
02315 
02316     TRACE("iface %p, flags %#x.\n", iface, Flags);
02317 
02318     return IDirect3DDevice7_DrawPrimitive(&This->IDirect3DDevice7_iface, This->primitive_type,
02319             This->vertex_type, This->vertex_buffer, This->nb_vertices, This->render_flags);
02320 }
02321 
02322 static HRESULT WINAPI IDirect3DDeviceImpl_2_End(IDirect3DDevice2 *iface, DWORD dwFlags)
02323 {
02324     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
02325 
02326     TRACE("iface %p, flags %#x.\n", iface, dwFlags);
02327 
02328     return IDirect3DDevice3_End(&This->IDirect3DDevice3_iface, dwFlags);
02329 }
02330 
02331 /*****************************************************************************
02332  * IDirect3DDevice7::GetRenderState
02333  *
02334  * Returns the value of a render state. The possible render states are
02335  * defined in include/d3dtypes.h
02336  *
02337  * Version 2, 3 and 7
02338  *
02339  * Params:
02340  *  RenderStateType: Render state to return the current setting of
02341  *  Value: Address to store the value at
02342  *
02343  * Returns:
02344  *  D3D_OK on success, for details see IWineD3DDevice::GetRenderState
02345  *  DDERR_INVALIDPARAMS if Value == NULL
02346  *
02347  *****************************************************************************/
02348 static HRESULT IDirect3DDeviceImpl_7_GetRenderState(IDirect3DDevice7 *iface,
02349         D3DRENDERSTATETYPE RenderStateType, DWORD *Value)
02350 {
02351     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
02352     HRESULT hr;
02353 
02354     TRACE("iface %p, state %#x, value %p.\n", iface, RenderStateType, Value);
02355 
02356     if(!Value)
02357         return DDERR_INVALIDPARAMS;
02358 
02359     wined3d_mutex_lock();
02360     switch(RenderStateType)
02361     {
02362         case D3DRENDERSTATE_TEXTUREMAG:
02363         {
02364             enum wined3d_texture_filter_type tex_mag;
02365 
02366             hr = wined3d_device_get_sampler_state(This->wined3d_device, 0, WINED3D_SAMP_MAG_FILTER, &tex_mag);
02367 
02368             switch (tex_mag)
02369             {
02370                 case WINED3D_TEXF_POINT:
02371                     *Value = D3DFILTER_NEAREST;
02372                     break;
02373                 case WINED3D_TEXF_LINEAR:
02374                     *Value = D3DFILTER_LINEAR;
02375                     break;
02376                 default:
02377                     ERR("Unhandled texture mag %d !\n",tex_mag);
02378                     *Value = 0;
02379             }
02380             break;
02381         }
02382 
02383         case D3DRENDERSTATE_TEXTUREMIN:
02384         {
02385             enum wined3d_texture_filter_type tex_min;
02386             enum wined3d_texture_filter_type tex_mip;
02387 
02388             hr = wined3d_device_get_sampler_state(This->wined3d_device,
02389                     0, WINED3D_SAMP_MIN_FILTER, &tex_min);
02390             if (FAILED(hr))
02391             {
02392                 wined3d_mutex_unlock();
02393                 return hr;
02394             }
02395             hr = wined3d_device_get_sampler_state(This->wined3d_device,
02396                     0, WINED3D_SAMP_MIP_FILTER, &tex_mip);
02397 
02398             switch (tex_min)
02399             {
02400                 case WINED3D_TEXF_POINT:
02401                     switch (tex_mip)
02402                     {
02403                         case WINED3D_TEXF_NONE:
02404                             *Value = D3DFILTER_NEAREST;
02405                             break;
02406                         case WINED3D_TEXF_POINT:
02407                             *Value = D3DFILTER_MIPNEAREST;
02408                             break;
02409                         case WINED3D_TEXF_LINEAR:
02410                             *Value = D3DFILTER_LINEARMIPNEAREST;
02411                             break;
02412                         default:
02413                             ERR("Unhandled mip filter %#x.\n", tex_mip);
02414                             *Value = D3DFILTER_NEAREST;
02415                             break;
02416                     }
02417                     break;
02418                 case WINED3D_TEXF_LINEAR:
02419                     switch (tex_mip)
02420                     {
02421                         case WINED3D_TEXF_NONE:
02422                             *Value = D3DFILTER_LINEAR;
02423                             break;
02424                         case WINED3D_TEXF_POINT:
02425                             *Value = D3DFILTER_MIPLINEAR;
02426                             break;
02427                         case WINED3D_TEXF_LINEAR:
02428                             *Value = D3DFILTER_LINEARMIPLINEAR;
02429                             break;
02430                         default:
02431                             ERR("Unhandled mip filter %#x.\n", tex_mip);
02432                             *Value = D3DFILTER_LINEAR;
02433                             break;
02434                     }
02435                     break;
02436                 default:
02437                     ERR("Unhandled texture min filter %#x.\n",tex_min);
02438                     *Value = D3DFILTER_NEAREST;
02439                     break;
02440             }
02441             break;
02442         }
02443 
02444         case D3DRENDERSTATE_TEXTUREADDRESS:
02445         case D3DRENDERSTATE_TEXTUREADDRESSU:
02446             hr = wined3d_device_get_sampler_state(This->wined3d_device,
02447                     0, WINED3D_SAMP_ADDRESS_U, Value);
02448             break;
02449         case D3DRENDERSTATE_TEXTUREADDRESSV:
02450             hr = wined3d_device_get_sampler_state(This->wined3d_device,
02451                     0, WINED3D_SAMP_ADDRESS_V, Value);
02452             break;
02453 
02454         case D3DRENDERSTATE_BORDERCOLOR:
02455             FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
02456             hr = E_NOTIMPL;
02457             break;
02458 
02459         case D3DRENDERSTATE_TEXTUREHANDLE:
02460         case D3DRENDERSTATE_TEXTUREMAPBLEND:
02461             WARN("Render state %#x is invalid in d3d7.\n", RenderStateType);
02462             hr = DDERR_INVALIDPARAMS;
02463             break;
02464 
02465         case D3DRENDERSTATE_ZBIAS:
02466             hr = wined3d_device_get_render_state(This->wined3d_device, WINED3D_RS_DEPTHBIAS, Value);
02467             break;
02468 
02469         default:
02470             if (RenderStateType >= D3DRENDERSTATE_STIPPLEPATTERN00
02471                     && RenderStateType <= D3DRENDERSTATE_STIPPLEPATTERN31)
02472             {
02473                 FIXME("Unhandled stipple pattern render state (%#x).\n",
02474                         RenderStateType);
02475                 hr = E_NOTIMPL;
02476                 break;
02477             }
02478             hr = wined3d_device_get_render_state(This->wined3d_device, RenderStateType, Value);
02479     }
02480     wined3d_mutex_unlock();
02481 
02482     return hr;
02483 }
02484 
02485 static HRESULT WINAPI
02486 IDirect3DDeviceImpl_7_GetRenderState_FPUSetup(IDirect3DDevice7 *iface,
02487                                      D3DRENDERSTATETYPE RenderStateType,
02488                                      DWORD *Value)
02489 {
02490     return IDirect3DDeviceImpl_7_GetRenderState(iface, RenderStateType, Value);
02491 }
02492 
02493 static HRESULT WINAPI
02494 IDirect3DDeviceImpl_7_GetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
02495                                      D3DRENDERSTATETYPE RenderStateType,
02496                                      DWORD *Value)
02497 {
02498     HRESULT hr;
02499     WORD old_fpucw;
02500 
02501     old_fpucw = d3d_fpu_setup();
02502     hr = IDirect3DDeviceImpl_7_GetRenderState(iface, RenderStateType, Value);
02503     set_fpu_control_word(old_fpucw);
02504 
02505     return hr;
02506 }
02507 
02508 static HRESULT WINAPI
02509 IDirect3DDeviceImpl_3_GetRenderState(IDirect3DDevice3 *iface,
02510                                      D3DRENDERSTATETYPE dwRenderStateType,
02511                                      DWORD *lpdwRenderState)
02512 {
02513     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
02514     HRESULT hr;
02515 
02516     TRACE("iface %p, state %#x, value %p.\n", iface, dwRenderStateType, lpdwRenderState);
02517 
02518     switch(dwRenderStateType)
02519     {
02520         case D3DRENDERSTATE_TEXTUREHANDLE:
02521         {
02522             /* This state is wrapped to SetTexture in SetRenderState, so
02523              * it has to be wrapped to GetTexture here. */
02524             struct wined3d_texture *tex = NULL;
02525             *lpdwRenderState = 0;
02526 
02527             wined3d_mutex_lock();
02528             hr = wined3d_device_get_texture(This->wined3d_device, 0, &tex);
02529             if (SUCCEEDED(hr) && tex)
02530             {
02531                 /* The parent of the texture is the IDirectDrawSurface7
02532                  * interface of the ddraw surface. */
02533                 IDirectDrawSurfaceImpl *parent = wined3d_texture_get_parent(tex);
02534                 if (parent) *lpdwRenderState = parent->Handle;
02535                 wined3d_texture_decref(tex);
02536             }
02537             wined3d_mutex_unlock();
02538 
02539             return hr;
02540         }
02541 
02542         case D3DRENDERSTATE_TEXTUREMAPBLEND:
02543         {
02544             /* D3DRENDERSTATE_TEXTUREMAPBLEND is mapped to texture state stages in SetRenderState; reverse
02545                the mapping to get the value. */
02546             DWORD colorop, colorarg1, colorarg2;
02547             DWORD alphaop, alphaarg1, alphaarg2;
02548 
02549             wined3d_mutex_lock();
02550 
02551             This->legacyTextureBlending = TRUE;
02552 
02553             wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3D_TSS_COLOR_OP, &colorop);
02554             wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3D_TSS_COLOR_ARG1, &colorarg1);
02555             wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3D_TSS_COLOR_ARG2, &colorarg2);
02556             wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3D_TSS_ALPHA_OP, &alphaop);
02557             wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3D_TSS_ALPHA_ARG1, &alphaarg1);
02558             wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3D_TSS_ALPHA_ARG2, &alphaarg2);
02559 
02560             if (colorop == WINED3D_TOP_SELECT_ARG1 && colorarg1 == WINED3DTA_TEXTURE
02561                     && alphaop == WINED3D_TOP_SELECT_ARG1 && alphaarg1 == WINED3DTA_TEXTURE)
02562                 *lpdwRenderState = D3DTBLEND_DECAL;
02563             else if (colorop == WINED3D_TOP_SELECT_ARG1 && colorarg1 == WINED3DTA_TEXTURE
02564                     && alphaop == WINED3D_TOP_MODULATE
02565                     && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
02566                 *lpdwRenderState = D3DTBLEND_DECALALPHA;
02567             else if (colorop == WINED3D_TOP_MODULATE
02568                     && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT
02569                     && alphaop == WINED3D_TOP_MODULATE
02570                     && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
02571                 *lpdwRenderState = D3DTBLEND_MODULATEALPHA;
02572             else
02573             {
02574                 struct wined3d_texture *tex = NULL;
02575                 HRESULT hr;
02576                 BOOL tex_alpha = FALSE;
02577                 DDPIXELFORMAT ddfmt;
02578 
02579                 hr = wined3d_device_get_texture(This->wined3d_device, 0, &tex);
02580 
02581                 if(hr == WINED3D_OK && tex)
02582                 {
02583                     struct wined3d_resource *sub_resource;
02584 
02585                     if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
02586                     {
02587                         struct wined3d_resource_desc desc;
02588 
02589                         wined3d_resource_get_desc(sub_resource, &desc);
02590                         ddfmt.dwSize = sizeof(ddfmt);
02591                         PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
02592                         if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
02593                     }
02594 
02595                     wined3d_texture_decref(tex);
02596                 }
02597 
02598                 if (!(colorop == WINED3D_TOP_MODULATE
02599                         && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT
02600                         && alphaop == (tex_alpha ? WINED3D_TOP_SELECT_ARG1 : WINED3D_TOP_SELECT_ARG2)
02601                         && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT))
02602                     ERR("Unexpected texture stage state setup, returning D3DTBLEND_MODULATE - likely erroneous.\n");
02603 
02604                 *lpdwRenderState = D3DTBLEND_MODULATE;
02605             }
02606 
02607             wined3d_mutex_unlock();
02608 
02609             return D3D_OK;
02610         }
02611 
02612         default:
02613             return IDirect3DDevice7_GetRenderState(&This->IDirect3DDevice7_iface, dwRenderStateType, lpdwRenderState);
02614     }
02615 }
02616 
02617 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetRenderState(IDirect3DDevice2 *iface,
02618         D3DRENDERSTATETYPE dwRenderStateType, DWORD *lpdwRenderState)
02619 {
02620     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
02621 
02622     TRACE("iface %p, state %#x, value %p.\n", iface, dwRenderStateType, lpdwRenderState);
02623 
02624     return IDirect3DDevice3_GetRenderState(&This->IDirect3DDevice3_iface,
02625             dwRenderStateType, lpdwRenderState);
02626 }
02627 
02628 /*****************************************************************************
02629  * IDirect3DDevice7::SetRenderState
02630  *
02631  * Sets a render state. The possible render states are defined in
02632  * include/d3dtypes.h
02633  *
02634  * Version 2, 3 and 7
02635  *
02636  * Params:
02637  *  RenderStateType: State to set
02638  *  Value: Value to assign to that state
02639  *
02640  * Returns:
02641  *  D3D_OK on success,
02642  *  for details see IWineD3DDevice::SetRenderState
02643  *
02644  *****************************************************************************/
02645 static HRESULT
02646 IDirect3DDeviceImpl_7_SetRenderState(IDirect3DDevice7 *iface,
02647                                      D3DRENDERSTATETYPE RenderStateType,
02648                                      DWORD Value)
02649 {
02650     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
02651     HRESULT hr;
02652 
02653     TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
02654 
02655     wined3d_mutex_lock();
02656     /* Some render states need special care */
02657     switch(RenderStateType)
02658     {
02659         /*
02660          * The ddraw texture filter mapping works like this:
02661          *     D3DFILTER_NEAREST            Point min/mag, no mip
02662          *     D3DFILTER_MIPNEAREST         Point min/mag, point mip
02663          *     D3DFILTER_LINEARMIPNEAREST:  Point min/mag, linear mip
02664          *
02665          *     D3DFILTER_LINEAR             Linear min/mag, no mip
02666          *     D3DFILTER_MIPLINEAR          Linear min/mag, point mip
02667          *     D3DFILTER_LINEARMIPLINEAR    Linear min/mag, linear mip
02668          *
02669          * This is the opposite of the GL naming convention,
02670          * D3DFILTER_LINEARMIPNEAREST corresponds to GL_NEAREST_MIPMAP_LINEAR.
02671          */
02672         case D3DRENDERSTATE_TEXTUREMAG:
02673         {
02674             enum wined3d_texture_filter_type tex_mag;
02675 
02676             switch (Value)
02677             {
02678                 case D3DFILTER_NEAREST:
02679                 case D3DFILTER_MIPNEAREST:
02680                 case D3DFILTER_LINEARMIPNEAREST:
02681                     tex_mag = WINED3D_TEXF_POINT;
02682                     break;
02683                 case D3DFILTER_LINEAR:
02684                 case D3DFILTER_MIPLINEAR:
02685                 case D3DFILTER_LINEARMIPLINEAR:
02686                     tex_mag = WINED3D_TEXF_LINEAR;
02687                     break;
02688                 default:
02689                     tex_mag = WINED3D_TEXF_POINT;
02690                     ERR("Unhandled texture mag %d !\n",Value);
02691                     break;
02692             }
02693 
02694             hr = wined3d_device_set_sampler_state(This->wined3d_device, 0, WINED3D_SAMP_MAG_FILTER, tex_mag);
02695             break;
02696         }
02697 
02698         case D3DRENDERSTATE_TEXTUREMIN:
02699         {
02700             enum wined3d_texture_filter_type tex_min;
02701             enum wined3d_texture_filter_type tex_mip;
02702 
02703             switch ((D3DTEXTUREFILTER)Value)
02704             {
02705                 case D3DFILTER_NEAREST:
02706                     tex_min = WINED3D_TEXF_POINT;
02707                     tex_mip = WINED3D_TEXF_NONE;
02708                     break;
02709                 case D3DFILTER_LINEAR:
02710                     tex_min = WINED3D_TEXF_LINEAR;
02711                     tex_mip = WINED3D_TEXF_NONE;
02712                     break;
02713                 case D3DFILTER_MIPNEAREST:
02714                     tex_min = WINED3D_TEXF_POINT;
02715                     tex_mip = WINED3D_TEXF_POINT;
02716                     break;
02717                 case D3DFILTER_MIPLINEAR:
02718                     tex_min = WINED3D_TEXF_LINEAR;
02719                     tex_mip = WINED3D_TEXF_POINT;
02720                     break;
02721                 case D3DFILTER_LINEARMIPNEAREST:
02722                     tex_min = WINED3D_TEXF_POINT;
02723                     tex_mip = WINED3D_TEXF_LINEAR;
02724                     break;
02725                 case D3DFILTER_LINEARMIPLINEAR:
02726                     tex_min = WINED3D_TEXF_LINEAR;
02727                     tex_mip = WINED3D_TEXF_LINEAR;
02728                     break;
02729 
02730                 default:
02731                     ERR("Unhandled texture min %d !\n",Value);
02732                     tex_min = WINED3D_TEXF_POINT;
02733                     tex_mip = WINED3D_TEXF_NONE;
02734                     break;
02735             }
02736 
02737             wined3d_device_set_sampler_state(This->wined3d_device,
02738                     0, WINED3D_SAMP_MIP_FILTER, tex_mip);
02739             hr = wined3d_device_set_sampler_state(This->wined3d_device,
02740                     0, WINED3D_SAMP_MIN_FILTER, tex_min);
02741             break;
02742         }
02743 
02744         case D3DRENDERSTATE_TEXTUREADDRESS:
02745             wined3d_device_set_sampler_state(This->wined3d_device,
02746                     0, WINED3D_SAMP_ADDRESS_V, Value);
02747             /* Drop through */
02748         case D3DRENDERSTATE_TEXTUREADDRESSU:
02749             hr = wined3d_device_set_sampler_state(This->wined3d_device,
02750                     0, WINED3D_SAMP_ADDRESS_U, Value);
02751             break;
02752         case D3DRENDERSTATE_TEXTUREADDRESSV:
02753             hr = wined3d_device_set_sampler_state(This->wined3d_device,
02754                     0, WINED3D_SAMP_ADDRESS_V, Value);
02755             break;
02756 
02757         case D3DRENDERSTATE_BORDERCOLOR:
02758             /* This should probably just forward to the corresponding sampler
02759              * state. Needs tests. */
02760             FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
02761             hr = E_NOTIMPL;
02762             break;
02763 
02764         case D3DRENDERSTATE_TEXTUREHANDLE:
02765         case D3DRENDERSTATE_TEXTUREMAPBLEND:
02766             WARN("Render state %#x is invalid in d3d7.\n", RenderStateType);
02767             hr = DDERR_INVALIDPARAMS;
02768             break;
02769 
02770         case D3DRENDERSTATE_ZBIAS:
02771             hr = wined3d_device_set_render_state(This->wined3d_device, WINED3D_RS_DEPTHBIAS, Value);
02772             break;
02773 
02774         default:
02775             if (RenderStateType >= D3DRENDERSTATE_STIPPLEPATTERN00
02776                     && RenderStateType <= D3DRENDERSTATE_STIPPLEPATTERN31)
02777             {
02778                 FIXME("Unhandled stipple pattern render state (%#x).\n",
02779                         RenderStateType);
02780                 hr = E_NOTIMPL;
02781                 break;
02782             }
02783 
02784             hr = wined3d_device_set_render_state(This->wined3d_device, RenderStateType, Value);
02785             break;
02786     }
02787     wined3d_mutex_unlock();
02788 
02789     return hr;
02790 }
02791 
02792 static HRESULT WINAPI
02793 IDirect3DDeviceImpl_7_SetRenderState_FPUSetup(IDirect3DDevice7 *iface,
02794                                      D3DRENDERSTATETYPE RenderStateType,
02795                                      DWORD Value)
02796 {
02797     return IDirect3DDeviceImpl_7_SetRenderState(iface, RenderStateType, Value);
02798 }
02799 
02800 static HRESULT WINAPI
02801 IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
02802                                      D3DRENDERSTATETYPE RenderStateType,
02803                                      DWORD Value)
02804 {
02805     HRESULT hr;
02806     WORD old_fpucw;
02807 
02808     old_fpucw = d3d_fpu_setup();
02809     hr = IDirect3DDeviceImpl_7_SetRenderState(iface, RenderStateType, Value);
02810     set_fpu_control_word(old_fpucw);
02811 
02812     return hr;
02813 }
02814 
02815 static HRESULT WINAPI
02816 IDirect3DDeviceImpl_3_SetRenderState(IDirect3DDevice3 *iface,
02817                                      D3DRENDERSTATETYPE RenderStateType,
02818                                      DWORD Value)
02819 {
02820     /* Note about D3DRENDERSTATE_TEXTUREMAPBLEND implementation: most of values
02821     for this state can be directly mapped to texture stage colorop and alphaop, but
02822     D3DTBLEND_MODULATE is tricky: it uses alpha from texture when available and alpha
02823     from diffuse otherwise. So changing the texture must be monitored in SetTexture to modify
02824     alphaarg when needed.
02825 
02826     Aliens vs Predator 1 depends on accurate D3DTBLEND_MODULATE emulation
02827 
02828     Legacy texture blending (TEXTUREMAPBLEND) and texture stage states: directx6 docs state that
02829     TEXTUREMAPBLEND is deprecated, yet can still be used. Games must not use both or results
02830     are undefined. D3DTBLEND_MODULATE mode in particular is dependent on texture pixel format and
02831     requires fixup of stage 0 texture states when texture changes, but this fixup can interfere
02832     with games not using this deprecated state. So a flag 'legacyTextureBlending' has to be kept
02833     in device - TRUE if the app is using TEXTUREMAPBLEND.
02834 
02835     Tests show that setting TEXTUREMAPBLEND on native doesn't seem to change values returned by
02836     GetTextureStageState and vice versa. Not so on Wine, but it is 'undefined' anyway so, probably, ok,
02837     unless some broken game will be found that cares. */
02838 
02839     HRESULT hr;
02840     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
02841 
02842     TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
02843 
02844     wined3d_mutex_lock();
02845 
02846     switch(RenderStateType)
02847     {
02848         case D3DRENDERSTATE_TEXTUREHANDLE:
02849         {
02850             IDirectDrawSurfaceImpl *surf;
02851 
02852             if(Value == 0)
02853             {
02854                 hr = wined3d_device_set_texture(This->wined3d_device, 0, NULL);
02855                 break;
02856             }
02857 
02858             surf = ddraw_get_object(&This->handle_table, Value - 1, DDRAW_HANDLE_SURFACE);
02859             if (!surf)
02860             {
02861                 WARN("Invalid texture handle.\n");
02862                 hr = DDERR_INVALIDPARAMS;
02863                 break;
02864             }
02865 
02866             hr = IDirect3DDevice3_SetTexture(iface, 0, &surf->IDirect3DTexture2_iface);
02867             break;
02868         }
02869 
02870         case D3DRENDERSTATE_TEXTUREMAPBLEND:
02871         {
02872             This->legacyTextureBlending = TRUE;
02873 
02874             switch ( (D3DTEXTUREBLEND) Value)
02875             {
02876                 case D3DTBLEND_MODULATE:
02877                 {
02878                     struct wined3d_texture *tex = NULL;
02879                     BOOL tex_alpha = FALSE;
02880                     DDPIXELFORMAT ddfmt;
02881 
02882                     hr = wined3d_device_get_texture(This->wined3d_device, 0, &tex);
02883 
02884                     if(hr == WINED3D_OK && tex)
02885                     {
02886                         struct wined3d_resource *sub_resource;
02887 
02888                         if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
02889                         {
02890                             struct wined3d_resource_desc desc;
02891 
02892                             wined3d_resource_get_desc(sub_resource, &desc);
02893                             ddfmt.dwSize = sizeof(ddfmt);
02894                             PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
02895                             if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
02896                         }
02897 
02898                         wined3d_texture_decref(tex);
02899                     }
02900 
02901                     if (tex_alpha)
02902                         wined3d_device_set_texture_stage_state(This->wined3d_device,
02903                                 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG1);
02904                     else
02905                         wined3d_device_set_texture_stage_state(This->wined3d_device,
02906                                 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
02907                     wined3d_device_set_texture_stage_state(This->wined3d_device,
02908                             0, WINED3D_TSS_ALPHA_ARG1, WINED3DTA_TEXTURE);
02909                     wined3d_device_set_texture_stage_state(This->wined3d_device,
02910                             0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
02911                     wined3d_device_set_texture_stage_state(This->wined3d_device,
02912                             0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
02913                     wined3d_device_set_texture_stage_state(This->wined3d_device,
02914                             0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
02915                     wined3d_device_set_texture_stage_state(This->wined3d_device,
02916                             0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_MODULATE);
02917                     break;
02918                 }
02919 
02920                 case D3DTBLEND_ADD:
02921                     wined3d_device_set_texture_stage_state(This->wined3d_device,
02922                             0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_ADD);
02923                     wined3d_device_set_texture_stage_state(This->wined3d_device,
02924                             0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
02925                     wined3d_device_set_texture_stage_state(This->wined3d_device,
02926                             0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
02927                     wined3d_device_set_texture_stage_state(This->wined3d_device,
02928                             0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
02929                     wined3d_device_set_texture_stage_state(This->wined3d_device,
02930                             0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
02931                     break;
02932 
02933                 case D3DTBLEND_MODULATEALPHA:
02934                     wined3d_device_set_texture_stage_state(This->wined3d_device,
02935                             0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
02936                     wined3d_device_set_texture_stage_state(This->wined3d_device,
02937                             0, WINED3D_TSS_ALPHA_ARG1, WINED3DTA_TEXTURE);
02938                     wined3d_device_set_texture_stage_state(This->wined3d_device,
02939                             0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
02940                     wined3d_device_set_texture_stage_state(This->wined3d_device,
02941                             0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
02942                     wined3d_device_set_texture_stage_state(This->wined3d_device,
02943                             0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_MODULATE);
02944                     wined3d_device_set_texture_stage_state(This->wined3d_device,
02945                             0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_MODULATE);
02946                     break;
02947 
02948                 case D3DTBLEND_COPY:
02949                 case D3DTBLEND_DECAL:
02950                     wined3d_device_set_texture_stage_state(This->wined3d_device,
02951                             0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
02952                     wined3d_device_set_texture_stage_state(This->wined3d_device,
02953                             0, WINED3D_TSS_ALPHA_ARG1, WINED3DTA_TEXTURE);
02954                     wined3d_device_set_texture_stage_state(This->wined3d_device,
02955                             0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_SELECT_ARG1);
02956                     wined3d_device_set_texture_stage_state(This->wined3d_device,
02957                             0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG1);
02958                     break;
02959 
02960                 case D3DTBLEND_DECALALPHA:
02961                     wined3d_device_set_texture_stage_state(This->wined3d_device,
02962                             0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_BLEND_TEXTURE_ALPHA);
02963                     wined3d_device_set_texture_stage_state(This->wined3d_device,
02964                             0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
02965                     wined3d_device_set_texture_stage_state(This->wined3d_device,
02966                             0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
02967                     wined3d_device_set_texture_stage_state(This->wined3d_device,
02968                             0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
02969                     wined3d_device_set_texture_stage_state(This->wined3d_device,
02970                             0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
02971                     break;
02972 
02973                 default:
02974                     ERR("Unhandled texture environment %d !\n",Value);
02975             }
02976 
02977             hr = D3D_OK;
02978             break;
02979         }
02980 
02981         default:
02982             hr = IDirect3DDevice7_SetRenderState(&This->IDirect3DDevice7_iface, RenderStateType, Value);
02983             break;
02984     }
02985     wined3d_mutex_unlock();
02986 
02987     return hr;
02988 }
02989 
02990 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetRenderState(IDirect3DDevice2 *iface,
02991         D3DRENDERSTATETYPE RenderStateType, DWORD Value)
02992 {
02993     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
02994 
02995     TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
02996 
02997     return IDirect3DDevice3_SetRenderState(&This->IDirect3DDevice3_iface, RenderStateType, Value);
02998 }
02999 
03000 /*****************************************************************************
03001  * Direct3DDevice3::SetLightState
03002  *
03003  * Sets a light state for Direct3DDevice3 and Direct3DDevice2. The
03004  * light states are forwarded to Direct3DDevice7 render states
03005  *
03006  * Version 2 and 3
03007  *
03008  * Params:
03009  *  LightStateType: The light state to change
03010  *  Value: The value to assign to that light state
03011  *
03012  * Returns:
03013  *  D3D_OK on success
03014  *  DDERR_INVALIDPARAMS if the parameters were incorrect
03015  *  Also check IDirect3DDevice7::SetRenderState
03016  *
03017  *****************************************************************************/
03018 static HRESULT WINAPI
03019 IDirect3DDeviceImpl_3_SetLightState(IDirect3DDevice3 *iface,
03020                                     D3DLIGHTSTATETYPE LightStateType,
03021                                     DWORD Value)
03022 {
03023     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
03024     HRESULT hr;
03025 
03026     TRACE("iface %p, state %#x, value %#x.\n", iface, LightStateType, Value);
03027 
03028     if (!LightStateType || (LightStateType > D3DLIGHTSTATE_COLORVERTEX))
03029     {
03030         TRACE("Unexpected Light State Type\n");
03031         return DDERR_INVALIDPARAMS;
03032     }
03033 
03034     wined3d_mutex_lock();
03035     if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
03036     {
03037         IDirect3DMaterialImpl *m = ddraw_get_object(&This->handle_table, Value - 1, DDRAW_HANDLE_MATERIAL);
03038         if (!m)
03039         {
03040             WARN("Invalid material handle.\n");
03041             wined3d_mutex_unlock();
03042             return DDERR_INVALIDPARAMS;
03043         }
03044 
03045         TRACE(" activating material %p.\n", m);
03046         material_activate(m);
03047 
03048         This->material = Value;
03049     }
03050     else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
03051     {
03052         switch (Value)
03053         {
03054             case D3DCOLOR_MONO:
03055                 ERR("DDCOLOR_MONO should not happen!\n");
03056                 break;
03057             case D3DCOLOR_RGB:
03058                 /* We are already in this mode */
03059                 TRACE("Setting color model to RGB (no-op).\n");
03060                 break;
03061             default:
03062                 ERR("Unknown color model!\n");
03063                 wined3d_mutex_unlock();
03064                 return DDERR_INVALIDPARAMS;
03065         }
03066     }
03067     else
03068     {
03069         D3DRENDERSTATETYPE rs;
03070         switch (LightStateType)
03071         {
03072             case D3DLIGHTSTATE_AMBIENT:       /* 2 */
03073                 rs = D3DRENDERSTATE_AMBIENT;
03074                 break;
03075             case D3DLIGHTSTATE_FOGMODE:       /* 4 */
03076                 rs = D3DRENDERSTATE_FOGVERTEXMODE;
03077                 break;
03078             case D3DLIGHTSTATE_FOGSTART:      /* 5 */
03079                 rs = D3DRENDERSTATE_FOGSTART;
03080                 break;
03081             case D3DLIGHTSTATE_FOGEND:        /* 6 */
03082                 rs = D3DRENDERSTATE_FOGEND;
03083                 break;
03084             case D3DLIGHTSTATE_FOGDENSITY:    /* 7 */
03085                 rs = D3DRENDERSTATE_FOGDENSITY;
03086                 break;
03087             case D3DLIGHTSTATE_COLORVERTEX:   /* 8 */
03088                 rs = D3DRENDERSTATE_COLORVERTEX;
03089                 break;
03090             default:
03091                 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", LightStateType);
03092                 wined3d_mutex_unlock();
03093                 return DDERR_INVALIDPARAMS;
03094         }
03095 
03096         hr = IDirect3DDevice7_SetRenderState(&This->IDirect3DDevice7_iface, rs, Value);
03097         wined3d_mutex_unlock();
03098         return hr;
03099     }
03100     wined3d_mutex_unlock();
03101 
03102     return D3D_OK;
03103 }
03104 
03105 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetLightState(IDirect3DDevice2 *iface,
03106         D3DLIGHTSTATETYPE LightStateType, DWORD Value)
03107 {
03108     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
03109 
03110     TRACE("iface %p, state %#x, value %#x.\n", iface, LightStateType, Value);
03111 
03112     return IDirect3DDevice3_SetLightState(&This->IDirect3DDevice3_iface, LightStateType, Value);
03113 }
03114 
03115 /*****************************************************************************
03116  * IDirect3DDevice3::GetLightState
03117  *
03118  * Returns the current setting of a light state. The state is read from
03119  * the Direct3DDevice7 render state.
03120  *
03121  * Version 2 and 3
03122  *
03123  * Params:
03124  *  LightStateType: The light state to return
03125  *  Value: The address to store the light state setting at
03126  *
03127  * Returns:
03128  *  D3D_OK on success
03129  *  DDDERR_INVALIDPARAMS if the parameters were incorrect
03130  *  Also see IDirect3DDevice7::GetRenderState
03131  *
03132  *****************************************************************************/
03133 static HRESULT WINAPI
03134 IDirect3DDeviceImpl_3_GetLightState(IDirect3DDevice3 *iface,
03135                                     D3DLIGHTSTATETYPE LightStateType,
03136                                     DWORD *Value)
03137 {
03138     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
03139     HRESULT hr;
03140 
03141     TRACE("iface %p, state %#x, value %p.\n", iface, LightStateType, Value);
03142 
03143     if (!LightStateType || (LightStateType > D3DLIGHTSTATE_COLORVERTEX))
03144     {
03145         TRACE("Unexpected Light State Type\n");
03146         return DDERR_INVALIDPARAMS;
03147     }
03148 
03149     if(!Value)
03150         return DDERR_INVALIDPARAMS;
03151 
03152     wined3d_mutex_lock();
03153     if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
03154     {
03155         *Value = This->material;
03156     }
03157     else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
03158     {
03159         *Value = D3DCOLOR_RGB;
03160     }
03161     else
03162     {
03163         D3DRENDERSTATETYPE rs;
03164         switch (LightStateType)
03165         {
03166             case D3DLIGHTSTATE_AMBIENT:       /* 2 */
03167                 rs = D3DRENDERSTATE_AMBIENT;
03168                 break;
03169             case D3DLIGHTSTATE_FOGMODE:       /* 4 */
03170                 rs = D3DRENDERSTATE_FOGVERTEXMODE;
03171                 break;
03172             case D3DLIGHTSTATE_FOGSTART:      /* 5 */
03173                 rs = D3DRENDERSTATE_FOGSTART;
03174                 break;
03175             case D3DLIGHTSTATE_FOGEND:        /* 6 */
03176                 rs = D3DRENDERSTATE_FOGEND;
03177                 break;
03178             case D3DLIGHTSTATE_FOGDENSITY:    /* 7 */
03179                 rs = D3DRENDERSTATE_FOGDENSITY;
03180                 break;
03181             case D3DLIGHTSTATE_COLORVERTEX:   /* 8 */
03182                 rs = D3DRENDERSTATE_COLORVERTEX;
03183                 break;
03184             default:
03185                 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", LightStateType);
03186                 wined3d_mutex_unlock();
03187                 return DDERR_INVALIDPARAMS;
03188         }
03189 
03190         hr = IDirect3DDevice7_GetRenderState(&This->IDirect3DDevice7_iface, rs, Value);
03191         wined3d_mutex_unlock();
03192         return hr;
03193     }
03194     wined3d_mutex_unlock();
03195 
03196     return D3D_OK;
03197 }
03198 
03199 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetLightState(IDirect3DDevice2 *iface,
03200         D3DLIGHTSTATETYPE LightStateType, DWORD *Value)
03201 {
03202     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
03203 
03204     TRACE("iface %p, state %#x, value %p.\n", iface, LightStateType, Value);
03205 
03206     return IDirect3DDevice3_GetLightState(&This->IDirect3DDevice3_iface, LightStateType, Value);
03207 }
03208 
03209 /*****************************************************************************
03210  * IDirect3DDevice7::SetTransform
03211  *
03212  * Assigns a D3DMATRIX to a transform type. The transform types are defined
03213  * in include/d3dtypes.h.
03214  * The D3DTRANSFORMSTATE_WORLD (=1) is translated to D3DTS_WORLDMATRIX(0)
03215  * (=255) for wined3d, because the 1 transform state was removed in d3d8
03216  * and WineD3D already understands the replacement D3DTS_WORLDMATRIX(0)
03217  *
03218  * Version 2, 3 and 7
03219  *
03220  * Params:
03221  *  TransformStateType: transform state to set
03222  *  Matrix: Matrix to assign to the state
03223  *
03224  * Returns:
03225  *  D3D_OK on success
03226  *  DDERR_INVALIDPARAMS if Matrix == NULL
03227  *  For details see IWineD3DDevice::SetTransform
03228  *
03229  *****************************************************************************/
03230 static HRESULT
03231 IDirect3DDeviceImpl_7_SetTransform(IDirect3DDevice7 *iface,
03232                                    D3DTRANSFORMSTATETYPE TransformStateType,
03233                                    D3DMATRIX *Matrix)
03234 {
03235     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
03236     D3DTRANSFORMSTATETYPE type;
03237     HRESULT hr;
03238 
03239     TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, Matrix);
03240 
03241     switch (TransformStateType)
03242     {
03243         case D3DTRANSFORMSTATE_WORLD:
03244             type = WINED3D_TS_WORLD_MATRIX(0);
03245             break;
03246         case D3DTRANSFORMSTATE_WORLD1:
03247             type = WINED3D_TS_WORLD_MATRIX(1);
03248             break;
03249         case D3DTRANSFORMSTATE_WORLD2:
03250             type = WINED3D_TS_WORLD_MATRIX(2);
03251             break;
03252         case D3DTRANSFORMSTATE_WORLD3:
03253             type = WINED3D_TS_WORLD_MATRIX(3);
03254             break;
03255         default:
03256             type = TransformStateType;
03257     }
03258 
03259     if (!Matrix)
03260         return DDERR_INVALIDPARAMS;
03261 
03262     /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
03263     wined3d_mutex_lock();
03264     hr = wined3d_device_set_transform(This->wined3d_device, type, (struct wined3d_matrix *)Matrix);
03265     wined3d_mutex_unlock();
03266 
03267     return hr;
03268 }
03269 
03270 static HRESULT WINAPI
03271 IDirect3DDeviceImpl_7_SetTransform_FPUSetup(IDirect3DDevice7 *iface,
03272                                    D3DTRANSFORMSTATETYPE TransformStateType,
03273                                    D3DMATRIX *Matrix)
03274 {
03275     return IDirect3DDeviceImpl_7_SetTransform(iface, TransformStateType, Matrix);
03276 }
03277 
03278 static HRESULT WINAPI
03279 IDirect3DDeviceImpl_7_SetTransform_FPUPreserve(IDirect3DDevice7 *iface,
03280                                    D3DTRANSFORMSTATETYPE TransformStateType,
03281                                    D3DMATRIX *Matrix)
03282 {
03283     HRESULT hr;
03284     WORD old_fpucw;
03285 
03286     old_fpucw = d3d_fpu_setup();
03287     hr = IDirect3DDeviceImpl_7_SetTransform(iface, TransformStateType, Matrix);
03288     set_fpu_control_word(old_fpucw);
03289 
03290     return hr;
03291 }
03292 
03293 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetTransform(IDirect3DDevice3 *iface,
03294         D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
03295 {
03296     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
03297 
03298     TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
03299 
03300     if (!matrix)
03301         return DDERR_INVALIDPARAMS;
03302 
03303     if (state == D3DTRANSFORMSTATE_PROJECTION)
03304     {
03305         D3DMATRIX projection;
03306         HRESULT hr;
03307 
03308         wined3d_mutex_lock();
03309         multiply_matrix(&projection, &This->legacy_clipspace, matrix);
03310         hr = wined3d_device_set_transform(This->wined3d_device,
03311                 WINED3D_TS_PROJECTION, (struct wined3d_matrix *)&projection);
03312         if (SUCCEEDED(hr))
03313             This->legacy_projection = *matrix;
03314         wined3d_mutex_unlock();
03315 
03316         return hr;
03317     }
03318 
03319     return IDirect3DDevice7_SetTransform(&This->IDirect3DDevice7_iface, state, matrix);
03320 }
03321 
03322 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetTransform(IDirect3DDevice2 *iface,
03323         D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
03324 {
03325     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
03326 
03327     TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
03328 
03329     return IDirect3DDevice7_SetTransform(&This->IDirect3DDevice7_iface, TransformStateType, D3DMatrix);
03330 }
03331 
03332 /*****************************************************************************
03333  * IDirect3DDevice7::GetTransform
03334  *
03335  * Returns the matrix assigned to a transform state
03336  * D3DTRANSFORMSTATE_WORLD is translated to D3DTS_WORLDMATRIX(0), see
03337  * SetTransform
03338  *
03339  * Params:
03340  *  TransformStateType: State to read the matrix from
03341  *  Matrix: Address to store the matrix at
03342  *
03343  * Returns:
03344  *  D3D_OK on success
03345  *  DDERR_INVALIDPARAMS if Matrix == NULL
03346  *  For details, see IWineD3DDevice::GetTransform
03347  *
03348  *****************************************************************************/
03349 static HRESULT
03350 IDirect3DDeviceImpl_7_GetTransform(IDirect3DDevice7 *iface,
03351                                    D3DTRANSFORMSTATETYPE TransformStateType,
03352                                    D3DMATRIX *Matrix)
03353 {
03354     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
03355     D3DTRANSFORMSTATETYPE type;
03356     HRESULT hr;
03357 
03358     TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, Matrix);
03359 
03360     switch(TransformStateType)
03361     {
03362         case D3DTRANSFORMSTATE_WORLD:
03363             type = WINED3D_TS_WORLD_MATRIX(0);
03364             break;
03365         case D3DTRANSFORMSTATE_WORLD1:
03366             type = WINED3D_TS_WORLD_MATRIX(1);
03367             break;
03368         case D3DTRANSFORMSTATE_WORLD2:
03369             type = WINED3D_TS_WORLD_MATRIX(2);
03370             break;
03371         case D3DTRANSFORMSTATE_WORLD3:
03372             type = WINED3D_TS_WORLD_MATRIX(3);
03373             break;
03374         default:
03375             type = TransformStateType;
03376     }
03377 
03378     if(!Matrix)
03379         return DDERR_INVALIDPARAMS;
03380 
03381     /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
03382     wined3d_mutex_lock();
03383     hr = wined3d_device_get_transform(This->wined3d_device, type, (struct wined3d_matrix *)Matrix);
03384     wined3d_mutex_unlock();
03385 
03386     return hr;
03387 }
03388 
03389 static HRESULT WINAPI
03390 IDirect3DDeviceImpl_7_GetTransform_FPUSetup(IDirect3DDevice7 *iface,
03391                                    D3DTRANSFORMSTATETYPE TransformStateType,
03392                                    D3DMATRIX *Matrix)
03393 {
03394     return IDirect3DDeviceImpl_7_GetTransform(iface, TransformStateType, Matrix);
03395 }
03396 
03397 static HRESULT WINAPI
03398 IDirect3DDeviceImpl_7_GetTransform_FPUPreserve(IDirect3DDevice7 *iface,
03399                                    D3DTRANSFORMSTATETYPE TransformStateType,
03400                                    D3DMATRIX *Matrix)
03401 {
03402     HRESULT hr;
03403     WORD old_fpucw;
03404 
03405     old_fpucw = d3d_fpu_setup();
03406     hr = IDirect3DDeviceImpl_7_GetTransform(iface, TransformStateType, Matrix);
03407     set_fpu_control_word(old_fpucw);
03408 
03409     return hr;
03410 }
03411 
03412 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetTransform(IDirect3DDevice3 *iface,
03413         D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
03414 {
03415     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
03416 
03417     TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
03418 
03419     if (!matrix)
03420         return DDERR_INVALIDPARAMS;
03421 
03422     if (state == D3DTRANSFORMSTATE_PROJECTION)
03423     {
03424         wined3d_mutex_lock();
03425         *matrix = This->legacy_projection;
03426         wined3d_mutex_unlock();
03427         return DD_OK;
03428     }
03429 
03430     return IDirect3DDevice7_GetTransform(&This->IDirect3DDevice7_iface, state, matrix);
03431 }
03432 
03433 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetTransform(IDirect3DDevice2 *iface,
03434         D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
03435 {
03436     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
03437 
03438     TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
03439 
03440     return IDirect3DDevice7_GetTransform(&This->IDirect3DDevice7_iface, TransformStateType, D3DMatrix);
03441 }
03442 
03443 /*****************************************************************************
03444  * IDirect3DDevice7::MultiplyTransform
03445  *
03446  * Multiplies the already-set transform matrix of a transform state
03447  * with another matrix. For the world matrix, see SetTransform
03448  *
03449  * Version 2, 3 and 7
03450  *
03451  * Params:
03452  *  TransformStateType: Transform state to multiply
03453  *  D3DMatrix Matrix to multiply with.
03454  *
03455  * Returns
03456  *  D3D_OK on success
03457  *  DDERR_INVALIDPARAMS if D3DMatrix is NULL
03458  *  For details, see IWineD3DDevice::MultiplyTransform
03459  *
03460  *****************************************************************************/
03461 static HRESULT
03462 IDirect3DDeviceImpl_7_MultiplyTransform(IDirect3DDevice7 *iface,
03463                                         D3DTRANSFORMSTATETYPE TransformStateType,
03464                                         D3DMATRIX *D3DMatrix)
03465 {
03466     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
03467     HRESULT hr;
03468     D3DTRANSFORMSTATETYPE type;
03469 
03470     TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
03471 
03472     switch(TransformStateType)
03473     {
03474         case D3DTRANSFORMSTATE_WORLD:
03475             type = WINED3D_TS_WORLD_MATRIX(0);
03476             break;
03477         case D3DTRANSFORMSTATE_WORLD1:
03478             type = WINED3D_TS_WORLD_MATRIX(1);
03479             break;
03480         case D3DTRANSFORMSTATE_WORLD2:
03481             type = WINED3D_TS_WORLD_MATRIX(2);
03482             break;
03483         case D3DTRANSFORMSTATE_WORLD3:
03484             type = WINED3D_TS_WORLD_MATRIX(3);
03485             break;
03486         default:
03487             type = TransformStateType;
03488     }
03489 
03490     /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
03491     wined3d_mutex_lock();
03492     hr = wined3d_device_multiply_transform(This->wined3d_device,
03493             type, (struct wined3d_matrix *)D3DMatrix);
03494     wined3d_mutex_unlock();
03495 
03496     return hr;
03497 }
03498 
03499 static HRESULT WINAPI
03500 IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup(IDirect3DDevice7 *iface,
03501                                         D3DTRANSFORMSTATETYPE TransformStateType,
03502                                         D3DMATRIX *D3DMatrix)
03503 {
03504     return IDirect3DDeviceImpl_7_MultiplyTransform(iface, TransformStateType, D3DMatrix);
03505 }
03506 
03507 static HRESULT WINAPI
03508 IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve(IDirect3DDevice7 *iface,
03509                                         D3DTRANSFORMSTATETYPE TransformStateType,
03510                                         D3DMATRIX *D3DMatrix)
03511 {
03512     HRESULT hr;
03513     WORD old_fpucw;
03514 
03515     old_fpucw = d3d_fpu_setup();
03516     hr = IDirect3DDeviceImpl_7_MultiplyTransform(iface, TransformStateType, D3DMatrix);
03517     set_fpu_control_word(old_fpucw);
03518 
03519     return hr;
03520 }
03521 
03522 static HRESULT WINAPI IDirect3DDeviceImpl_3_MultiplyTransform(IDirect3DDevice3 *iface,
03523         D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
03524 {
03525     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
03526 
03527     TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
03528 
03529     if (state == D3DTRANSFORMSTATE_PROJECTION)
03530     {
03531         D3DMATRIX projection, tmp;
03532         HRESULT hr;
03533 
03534         wined3d_mutex_lock();
03535         multiply_matrix(&tmp, &This->legacy_projection, matrix);
03536         multiply_matrix(&projection, &This->legacy_clipspace, &tmp);
03537         hr = wined3d_device_set_transform(This->wined3d_device,
03538                 WINED3D_TS_PROJECTION, (struct wined3d_matrix *)&projection);
03539         if (SUCCEEDED(hr))
03540             This->legacy_projection = tmp;
03541         wined3d_mutex_unlock();
03542 
03543         return hr;
03544     }
03545 
03546     return IDirect3DDevice7_MultiplyTransform(&This->IDirect3DDevice7_iface, state, matrix);
03547 }
03548 
03549 static HRESULT WINAPI IDirect3DDeviceImpl_2_MultiplyTransform(IDirect3DDevice2 *iface,
03550         D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
03551 {
03552     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
03553 
03554     TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
03555 
03556     return IDirect3DDevice7_MultiplyTransform(&This->IDirect3DDevice7_iface, TransformStateType, D3DMatrix);
03557 }
03558 
03559 /*****************************************************************************
03560  * IDirect3DDevice7::DrawPrimitive
03561  *
03562  * Draws primitives based on vertices in an application-provided pointer
03563  *
03564  * Version 2, 3 and 7. The IDirect3DDevice2 thunk converts the fixed vertex type into
03565  * an FVF format for D3D7
03566  *
03567  * Params:
03568  *  PrimitiveType: The type of the primitives to draw
03569  *  Vertex type: Flexible vertex format vertex description
03570  *  Vertices: Pointer to the vertex array
03571  *  VertexCount: The number of vertices to draw
03572  *  Flags: As usual a few flags
03573  *
03574  * Returns:
03575  *  D3D_OK on success
03576  *  DDERR_INVALIDPARAMS if Vertices is NULL
03577  *  For details, see IWineD3DDevice::DrawPrimitiveUP
03578  *
03579  *****************************************************************************/
03580 static HRESULT
03581 IDirect3DDeviceImpl_7_DrawPrimitive(IDirect3DDevice7 *iface,
03582                                     D3DPRIMITIVETYPE PrimitiveType,
03583                                     DWORD VertexType,
03584                                     void *Vertices,
03585                                     DWORD VertexCount,
03586                                     DWORD Flags)
03587 {
03588     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
03589     UINT stride;
03590     HRESULT hr;
03591 
03592     TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x.\n",
03593             iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
03594 
03595     if(!Vertices)
03596         return DDERR_INVALIDPARAMS;
03597 
03598     /* Get the stride */
03599     stride = get_flexible_vertex_size(VertexType);
03600 
03601     /* Set the FVF */
03602     wined3d_mutex_lock();
03603     hr = wined3d_device_set_vertex_declaration(This->wined3d_device, ddraw_find_decl(This->ddraw, VertexType));
03604     if(hr != D3D_OK)
03605     {
03606         wined3d_mutex_unlock();
03607         return hr;
03608     }
03609 
03610     /* This method translates to the user pointer draw of WineD3D */
03611     wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
03612     hr = wined3d_device_draw_primitive_up(This->wined3d_device, VertexCount, Vertices, stride);
03613     wined3d_mutex_unlock();
03614 
03615     return hr;
03616 }
03617 
03618 static HRESULT WINAPI
03619 IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup(IDirect3DDevice7 *iface,
03620                                     D3DPRIMITIVETYPE PrimitiveType,
03621                                     DWORD VertexType,
03622                                     void *Vertices,
03623                                     DWORD VertexCount,
03624                                     DWORD Flags)
03625 {
03626     return IDirect3DDeviceImpl_7_DrawPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
03627 }
03628 
03629 static HRESULT WINAPI
03630 IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
03631                                     D3DPRIMITIVETYPE PrimitiveType,
03632                                     DWORD VertexType,
03633                                     void *Vertices,
03634                                     DWORD VertexCount,
03635                                     DWORD Flags)
03636 {
03637     HRESULT hr;
03638     WORD old_fpucw;
03639 
03640     old_fpucw = d3d_fpu_setup();
03641     hr = IDirect3DDeviceImpl_7_DrawPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
03642     set_fpu_control_word(old_fpucw);
03643 
03644     return hr;
03645 }
03646 
03647 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawPrimitive(IDirect3DDevice3 *iface,
03648         D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType, void *Vertices, DWORD VertexCount,
03649         DWORD Flags)
03650 {
03651     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
03652     TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x.\n",
03653             iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
03654 
03655     return IDirect3DDevice7_DrawPrimitive(&This->IDirect3DDevice7_iface,
03656             PrimitiveType, VertexType, Vertices, VertexCount, Flags);
03657 }
03658 
03659 static HRESULT WINAPI IDirect3DDeviceImpl_2_DrawPrimitive(IDirect3DDevice2 *iface,
03660         D3DPRIMITIVETYPE PrimitiveType, D3DVERTEXTYPE VertexType, void *Vertices,
03661         DWORD VertexCount, DWORD Flags)
03662 {
03663     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
03664     DWORD FVF;
03665 
03666     TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x.\n",
03667             iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
03668 
03669     switch(VertexType)
03670     {
03671         case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
03672         case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
03673         case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
03674         default:
03675             ERR("Unexpected vertex type %d\n", VertexType);
03676             return DDERR_INVALIDPARAMS;  /* Should never happen */
03677     }
03678 
03679     return IDirect3DDevice7_DrawPrimitive(&This->IDirect3DDevice7_iface,
03680             PrimitiveType, FVF, Vertices, VertexCount, Flags);
03681 }
03682 
03683 /*****************************************************************************
03684  * IDirect3DDevice7::DrawIndexedPrimitive
03685  *
03686  * Draws vertices from an application-provided pointer, based on the index
03687  * numbers in a WORD array.
03688  *
03689  * Version 2, 3 and 7. The version 7 thunk translates the vertex type into
03690  * an FVF format for D3D7
03691  *
03692  * Params:
03693  *  PrimitiveType: The primitive type to draw
03694  *  VertexType: The FVF vertex description
03695  *  Vertices: Pointer to the vertex array
03696  *  VertexCount: ?
03697  *  Indices: Pointer to the index array
03698  *  IndexCount: Number of indices = Number of vertices to draw
03699  *  Flags: As usual, some flags
03700  *
03701  * Returns:
03702  *  D3D_OK on success
03703  *  DDERR_INVALIDPARAMS if Vertices or Indices is NULL
03704  *  For details, see IWineD3DDevice::DrawIndexedPrimitiveUP
03705  *
03706  *****************************************************************************/
03707 static HRESULT
03708 IDirect3DDeviceImpl_7_DrawIndexedPrimitive(IDirect3DDevice7 *iface,
03709                                            D3DPRIMITIVETYPE PrimitiveType,
03710                                            DWORD VertexType,
03711                                            void *Vertices,
03712                                            DWORD VertexCount,
03713                                            WORD *Indices,
03714                                            DWORD IndexCount,
03715                                            DWORD Flags)
03716 {
03717     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
03718     HRESULT hr;
03719 
03720     TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
03721             iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
03722 
03723     /* Set the D3DDevice's FVF */
03724     wined3d_mutex_lock();
03725     hr = wined3d_device_set_vertex_declaration(This->wined3d_device, ddraw_find_decl(This->ddraw, VertexType));
03726     if(FAILED(hr))
03727     {
03728         ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
03729         wined3d_mutex_unlock();
03730         return hr;
03731     }
03732 
03733     wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
03734     hr = wined3d_device_draw_indexed_primitive_up(This->wined3d_device, IndexCount, Indices,
03735             WINED3DFMT_R16_UINT, Vertices, get_flexible_vertex_size(VertexType));
03736     wined3d_mutex_unlock();
03737 
03738     return hr;
03739 }
03740 
03741 static HRESULT WINAPI
03742 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup(IDirect3DDevice7 *iface,
03743                                            D3DPRIMITIVETYPE PrimitiveType,
03744                                            DWORD VertexType,
03745                                            void *Vertices,
03746                                            DWORD VertexCount,
03747                                            WORD *Indices,
03748                                            DWORD IndexCount,
03749                                            DWORD Flags)
03750 {
03751     return IDirect3DDeviceImpl_7_DrawIndexedPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
03752 }
03753 
03754 static HRESULT WINAPI
03755 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
03756                                            D3DPRIMITIVETYPE PrimitiveType,
03757                                            DWORD VertexType,
03758                                            void *Vertices,
03759                                            DWORD VertexCount,
03760                                            WORD *Indices,
03761                                            DWORD IndexCount,
03762                                            DWORD Flags)
03763 {
03764     HRESULT hr;
03765     WORD old_fpucw;
03766 
03767     old_fpucw = d3d_fpu_setup();
03768     hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
03769     set_fpu_control_word(old_fpucw);
03770 
03771     return hr;
03772 }
03773 
03774 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawIndexedPrimitive(IDirect3DDevice3 *iface,
03775         D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType, void *Vertices, DWORD VertexCount,
03776         WORD *Indices, DWORD IndexCount, DWORD Flags)
03777 {
03778     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
03779     TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
03780             iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
03781 
03782     return IDirect3DDevice7_DrawIndexedPrimitive(&This->IDirect3DDevice7_iface,
03783             PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
03784 }
03785 
03786 static HRESULT WINAPI IDirect3DDeviceImpl_2_DrawIndexedPrimitive(IDirect3DDevice2 *iface,
03787         D3DPRIMITIVETYPE PrimitiveType, D3DVERTEXTYPE VertexType, void *Vertices,
03788         DWORD VertexCount, WORD *Indices, DWORD IndexCount, DWORD Flags)
03789 {
03790     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
03791     DWORD FVF;
03792 
03793     TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
03794             iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
03795 
03796     switch(VertexType)
03797     {
03798         case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
03799         case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
03800         case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
03801         default:
03802             ERR("Unexpected vertex type %d\n", VertexType);
03803             return DDERR_INVALIDPARAMS;  /* Should never happen */
03804     }
03805 
03806     return IDirect3DDevice7_DrawIndexedPrimitive(&This->IDirect3DDevice7_iface,
03807             PrimitiveType, FVF, Vertices, VertexCount, Indices, IndexCount, Flags);
03808 }
03809 
03810 /*****************************************************************************
03811  * IDirect3DDevice7::SetClipStatus
03812  *
03813  * Sets the clip status. This defines things as clipping conditions and
03814  * the extents of the clipping region.
03815  *
03816  * Version 2, 3 and 7
03817  *
03818  * Params:
03819  *  ClipStatus:
03820  *
03821  * Returns:
03822  *  D3D_OK because it's a stub
03823  *  (DDERR_INVALIDPARAMS if ClipStatus == NULL)
03824  *
03825  *****************************************************************************/
03826 static HRESULT WINAPI
03827 IDirect3DDeviceImpl_7_SetClipStatus(IDirect3DDevice7 *iface,
03828                                     D3DCLIPSTATUS *ClipStatus)
03829 {
03830     FIXME("iface %p, clip_status %p stub!\n", iface, ClipStatus);
03831 
03832     /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them
03833      * Perhaps this needs a new data type and an additional IWineD3DDevice method
03834      */
03835     /* return IWineD3DDevice_SetClipStatus(This->wineD3DDevice, ClipStatus);*/
03836     return D3D_OK;
03837 }
03838 
03839 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetClipStatus(IDirect3DDevice3 *iface,
03840         D3DCLIPSTATUS *ClipStatus)
03841 {
03842     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
03843     TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
03844 
03845     return IDirect3DDevice7_SetClipStatus(&This->IDirect3DDevice7_iface, ClipStatus);
03846 }
03847 
03848 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetClipStatus(IDirect3DDevice2 *iface,
03849         D3DCLIPSTATUS *ClipStatus)
03850 {
03851     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
03852     TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
03853 
03854     return IDirect3DDevice7_SetClipStatus(&This->IDirect3DDevice7_iface, ClipStatus);
03855 }
03856 
03857 /*****************************************************************************
03858  * IDirect3DDevice7::GetClipStatus
03859  *
03860  * Returns the clip status
03861  *
03862  * Params:
03863  *  ClipStatus: Address to write the clip status to
03864  *
03865  * Returns:
03866  *  D3D_OK because it's a stub
03867  *
03868  *****************************************************************************/
03869 static HRESULT WINAPI
03870 IDirect3DDeviceImpl_7_GetClipStatus(IDirect3DDevice7 *iface,
03871                                     D3DCLIPSTATUS *ClipStatus)
03872 {
03873     FIXME("iface %p, clip_status %p stub!\n", iface, ClipStatus);
03874 
03875     /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them */
03876     /* return IWineD3DDevice_GetClipStatus(This->wineD3DDevice, ClipStatus);*/
03877     return D3D_OK;
03878 }
03879 
03880 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetClipStatus(IDirect3DDevice3 *iface,
03881         D3DCLIPSTATUS *ClipStatus)
03882 {
03883     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
03884     TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
03885 
03886     return IDirect3DDevice7_GetClipStatus(&This->IDirect3DDevice7_iface, ClipStatus);
03887 }
03888 
03889 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetClipStatus(IDirect3DDevice2 *iface,
03890         D3DCLIPSTATUS *ClipStatus)
03891 {
03892     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
03893     TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
03894 
03895     return IDirect3DDevice7_GetClipStatus(&This->IDirect3DDevice7_iface, ClipStatus);
03896 }
03897 
03898 /*****************************************************************************
03899  * IDirect3DDevice::DrawPrimitiveStrided
03900  *
03901  * Draws vertices described by a D3DDRAWPRIMITIVESTRIDEDDATA structure.
03902  *
03903  * Version 3 and 7
03904  *
03905  * Params:
03906  *  PrimitiveType: The primitive type to draw
03907  *  VertexType: The FVF description of the vertices to draw (for the stride??)
03908  *  D3DDrawPrimStrideData: A D3DDRAWPRIMITIVESTRIDEDDATA structure describing
03909  *                         the vertex data locations
03910  *  VertexCount: The number of vertices to draw
03911  *  Flags: Some flags
03912  *
03913  * Returns:
03914  *  D3D_OK, because it's a stub
03915  *  (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
03916  *  (For details, see IWineD3DDevice::DrawPrimitiveStrided)
03917  *
03918  *****************************************************************************/
03919 static HRESULT
03920 IDirect3DDeviceImpl_7_DrawPrimitiveStrided(IDirect3DDevice7 *iface,
03921                                            D3DPRIMITIVETYPE PrimitiveType,
03922                                            DWORD VertexType,
03923                                            D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
03924                                            DWORD VertexCount,
03925                                            DWORD Flags)
03926 {
03927     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
03928     struct wined3d_strided_data wined3d_strided;
03929     DWORD i;
03930     HRESULT hr;
03931 
03932     TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
03933             iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
03934 
03935     memset(&wined3d_strided, 0, sizeof(wined3d_strided));
03936     /* Get the strided data right. the wined3d structure is a bit bigger
03937      * Watch out: The contents of the strided data are determined by the fvf,
03938      * not by the members set in D3DDrawPrimStrideData. So it's valid
03939      * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
03940      * not set in the fvf.
03941      */
03942     if(VertexType & D3DFVF_POSITION_MASK)
03943     {
03944         wined3d_strided.position.format = WINED3DFMT_R32G32B32_FLOAT;
03945         wined3d_strided.position.data = D3DDrawPrimStrideData->position.lpvData;
03946         wined3d_strided.position.stride = D3DDrawPrimStrideData->position.dwStride;
03947         if (VertexType & D3DFVF_XYZRHW)
03948         {
03949             wined3d_strided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
03950             wined3d_strided.position_transformed = TRUE;
03951         }
03952         else
03953         {
03954             wined3d_strided.position_transformed = FALSE;
03955         }
03956     }
03957 
03958     if (VertexType & D3DFVF_NORMAL)
03959     {
03960         wined3d_strided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
03961         wined3d_strided.normal.data = D3DDrawPrimStrideData->normal.lpvData;
03962         wined3d_strided.normal.stride = D3DDrawPrimStrideData->normal.dwStride;
03963     }
03964 
03965     if (VertexType & D3DFVF_DIFFUSE)
03966     {
03967         wined3d_strided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
03968         wined3d_strided.diffuse.data = D3DDrawPrimStrideData->diffuse.lpvData;
03969         wined3d_strided.diffuse.stride = D3DDrawPrimStrideData->diffuse.dwStride;
03970     }
03971 
03972     if (VertexType & D3DFVF_SPECULAR)
03973     {
03974         wined3d_strided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
03975         wined3d_strided.specular.data = D3DDrawPrimStrideData->specular.lpvData;
03976         wined3d_strided.specular.stride = D3DDrawPrimStrideData->specular.dwStride;
03977     }
03978 
03979     for (i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); ++i)
03980     {
03981         switch (GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
03982         {
03983             case 1: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32_FLOAT; break;
03984             case 2: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32G32_FLOAT; break;
03985             case 3: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
03986             case 4: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
03987             default: ERR("Unexpected texture coordinate size %d\n",
03988                          GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
03989         }
03990         wined3d_strided.tex_coords[i].data = D3DDrawPrimStrideData->textureCoords[i].lpvData;
03991         wined3d_strided.tex_coords[i].stride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
03992     }
03993 
03994     /* WineD3D doesn't need the FVF here */
03995     wined3d_mutex_lock();
03996     wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
03997     hr = wined3d_device_draw_primitive_strided(This->wined3d_device, VertexCount, &wined3d_strided);
03998     wined3d_mutex_unlock();
03999 
04000     return hr;
04001 }
04002 
04003 static HRESULT WINAPI
04004 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
04005                                            D3DPRIMITIVETYPE PrimitiveType,
04006                                            DWORD VertexType,
04007                                            D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
04008                                            DWORD VertexCount,
04009                                            DWORD Flags)
04010 {
04011     return IDirect3DDeviceImpl_7_DrawPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
04012 }
04013 
04014 static HRESULT WINAPI
04015 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
04016                                            D3DPRIMITIVETYPE PrimitiveType,
04017                                            DWORD VertexType,
04018                                            D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
04019                                            DWORD VertexCount,
04020                                            DWORD Flags)
04021 {
04022     HRESULT hr;
04023     WORD old_fpucw;
04024 
04025     old_fpucw = d3d_fpu_setup();
04026     hr = IDirect3DDeviceImpl_7_DrawPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
04027     set_fpu_control_word(old_fpucw);
04028 
04029     return hr;
04030 }
04031 
04032 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawPrimitiveStrided(IDirect3DDevice3 *iface,
04033         D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
04034         D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
04035 {
04036     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
04037 
04038     TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
04039             iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
04040 
04041     return IDirect3DDevice7_DrawPrimitiveStrided(&This->IDirect3DDevice7_iface,
04042             PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
04043 }
04044 
04045 /*****************************************************************************
04046  * IDirect3DDevice7::DrawIndexedPrimitiveStrided
04047  *
04048  * Draws primitives specified by strided data locations based on indices
04049  *
04050  * Version 3 and 7
04051  *
04052  * Params:
04053  *  PrimitiveType:
04054  *
04055  * Returns:
04056  *  D3D_OK, because it's a stub
04057  *  (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
04058  *  (DDERR_INVALIDPARAMS if Indices is NULL)
04059  *  (For more details, see IWineD3DDevice::DrawIndexedPrimitiveStrided)
04060  *
04061  *****************************************************************************/
04062 static HRESULT
04063 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(IDirect3DDevice7 *iface,
04064                                                   D3DPRIMITIVETYPE PrimitiveType,
04065                                                   DWORD VertexType,
04066                                                   D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
04067                                                   DWORD VertexCount,
04068                                                   WORD *Indices,
04069                                                   DWORD IndexCount,
04070                                                   DWORD Flags)
04071 {
04072     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
04073     struct wined3d_strided_data wined3d_strided;
04074     DWORD i;
04075     HRESULT hr;
04076 
04077     TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
04078             iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
04079 
04080     memset(&wined3d_strided, 0, sizeof(wined3d_strided));
04081     /* Get the strided data right. the wined3d structure is a bit bigger
04082      * Watch out: The contents of the strided data are determined by the fvf,
04083      * not by the members set in D3DDrawPrimStrideData. So it's valid
04084      * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
04085      * not set in the fvf. */
04086     if (VertexType & D3DFVF_POSITION_MASK)
04087     {
04088         wined3d_strided.position.format = WINED3DFMT_R32G32B32_FLOAT;
04089         wined3d_strided.position.data = D3DDrawPrimStrideData->position.lpvData;
04090         wined3d_strided.position.stride = D3DDrawPrimStrideData->position.dwStride;
04091         if (VertexType & D3DFVF_XYZRHW)
04092         {
04093             wined3d_strided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
04094             wined3d_strided.position_transformed = TRUE;
04095         }
04096         else
04097         {
04098             wined3d_strided.position_transformed = FALSE;
04099         }
04100     }
04101 
04102     if (VertexType & D3DFVF_NORMAL)
04103     {
04104         wined3d_strided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
04105         wined3d_strided.normal.data = D3DDrawPrimStrideData->normal.lpvData;
04106         wined3d_strided.normal.stride = D3DDrawPrimStrideData->normal.dwStride;
04107     }
04108 
04109     if (VertexType & D3DFVF_DIFFUSE)
04110     {
04111         wined3d_strided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
04112         wined3d_strided.diffuse.data = D3DDrawPrimStrideData->diffuse.lpvData;
04113         wined3d_strided.diffuse.stride = D3DDrawPrimStrideData->diffuse.dwStride;
04114     }
04115 
04116     if (VertexType & D3DFVF_SPECULAR)
04117     {
04118         wined3d_strided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
04119         wined3d_strided.specular.data = D3DDrawPrimStrideData->specular.lpvData;
04120         wined3d_strided.specular.stride = D3DDrawPrimStrideData->specular.dwStride;
04121     }
04122 
04123     for (i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); ++i)
04124     {
04125         switch (GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
04126         {
04127             case 1: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32_FLOAT; break;
04128             case 2: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32G32_FLOAT; break;
04129             case 3: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
04130             case 4: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
04131             default: ERR("Unexpected texture coordinate size %d\n",
04132                          GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
04133         }
04134         wined3d_strided.tex_coords[i].data = D3DDrawPrimStrideData->textureCoords[i].lpvData;
04135         wined3d_strided.tex_coords[i].stride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
04136     }
04137 
04138     /* WineD3D doesn't need the FVF here */
04139     wined3d_mutex_lock();
04140     wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
04141     hr = wined3d_device_draw_indexed_primitive_strided(This->wined3d_device,
04142             IndexCount, &wined3d_strided, VertexCount, Indices, WINED3DFMT_R16_UINT);
04143     wined3d_mutex_unlock();
04144 
04145     return hr;
04146 }
04147 
04148 static HRESULT WINAPI
04149 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
04150                                                   D3DPRIMITIVETYPE PrimitiveType,
04151                                                   DWORD VertexType,
04152                                                   D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
04153                                                   DWORD VertexCount,
04154                                                   WORD *Indices,
04155                                                   DWORD IndexCount,
04156                                                   DWORD Flags)
04157 {
04158     return IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
04159 }
04160 
04161 static HRESULT WINAPI
04162 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
04163                                                   D3DPRIMITIVETYPE PrimitiveType,
04164                                                   DWORD VertexType,
04165                                                   D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
04166                                                   DWORD VertexCount,
04167                                                   WORD *Indices,
04168                                                   DWORD IndexCount,
04169                                                   DWORD Flags)
04170 {
04171     HRESULT hr;
04172     WORD old_fpucw;
04173 
04174     old_fpucw = d3d_fpu_setup();
04175     hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
04176     set_fpu_control_word(old_fpucw);
04177 
04178     return hr;
04179 }
04180 
04181 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided(IDirect3DDevice3 *iface,
04182         D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
04183         D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, WORD *Indices,
04184         DWORD IndexCount, DWORD Flags)
04185 {
04186     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
04187 
04188     TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
04189             iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
04190 
04191     return IDirect3DDevice7_DrawIndexedPrimitiveStrided(&This->IDirect3DDevice7_iface,
04192             PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
04193 }
04194 
04195 /*****************************************************************************
04196  * IDirect3DDevice7::DrawPrimitiveVB
04197  *
04198  * Draws primitives from a vertex buffer to the screen.
04199  *
04200  * Version 3 and 7
04201  *
04202  * Params:
04203  *  PrimitiveType: Type of primitive to be rendered.
04204  *  D3DVertexBuf: Source Vertex Buffer
04205  *  StartVertex: Index of the first vertex from the buffer to be rendered
04206  *  NumVertices: Number of vertices to be rendered
04207  *  Flags: Can be D3DDP_WAIT to wait until rendering has finished
04208  *
04209  * Return values
04210  *  D3D_OK on success
04211  *  DDERR_INVALIDPARAMS if D3DVertexBuf is NULL
04212  *
04213  *****************************************************************************/
04214 static HRESULT
04215 IDirect3DDeviceImpl_7_DrawPrimitiveVB(IDirect3DDevice7 *iface,
04216                                       D3DPRIMITIVETYPE PrimitiveType,
04217                                       IDirect3DVertexBuffer7 *D3DVertexBuf,
04218                                       DWORD StartVertex,
04219                                       DWORD NumVertices,
04220                                       DWORD Flags)
04221 {
04222     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
04223     IDirect3DVertexBufferImpl *vb = unsafe_impl_from_IDirect3DVertexBuffer7(D3DVertexBuf);
04224     HRESULT hr;
04225     DWORD stride;
04226 
04227     TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
04228             iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
04229 
04230     /* Sanity checks */
04231     if(!vb)
04232     {
04233         ERR("(%p) No Vertex buffer specified\n", This);
04234         return DDERR_INVALIDPARAMS;
04235     }
04236     stride = get_flexible_vertex_size(vb->fvf);
04237 
04238     wined3d_mutex_lock();
04239     hr = wined3d_device_set_vertex_declaration(This->wined3d_device, vb->wineD3DVertexDeclaration);
04240     if (FAILED(hr))
04241     {
04242         ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
04243         wined3d_mutex_unlock();
04244         return hr;
04245     }
04246 
04247     /* Set the vertex stream source */
04248     hr = wined3d_device_set_stream_source(This->wined3d_device, 0, vb->wineD3DVertexBuffer, 0, stride);
04249     if(hr != D3D_OK)
04250     {
04251         ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
04252         wined3d_mutex_unlock();
04253         return hr;
04254     }
04255 
04256     /* Now draw the primitives */
04257     wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
04258     hr = wined3d_device_draw_primitive(This->wined3d_device, StartVertex, NumVertices);
04259     wined3d_mutex_unlock();
04260 
04261     return hr;
04262 }
04263 
04264 static HRESULT WINAPI
04265 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
04266                                       D3DPRIMITIVETYPE PrimitiveType,
04267                                       IDirect3DVertexBuffer7 *D3DVertexBuf,
04268                                       DWORD StartVertex,
04269                                       DWORD NumVertices,
04270                                       DWORD Flags)
04271 {
04272     return IDirect3DDeviceImpl_7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
04273 }
04274 
04275 static HRESULT WINAPI
04276 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
04277                                       D3DPRIMITIVETYPE PrimitiveType,
04278                                       IDirect3DVertexBuffer7 *D3DVertexBuf,
04279                                       DWORD StartVertex,
04280                                       DWORD NumVertices,
04281                                       DWORD Flags)
04282 {
04283     HRESULT hr;
04284     WORD old_fpucw;
04285 
04286     old_fpucw = d3d_fpu_setup();
04287     hr = IDirect3DDeviceImpl_7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
04288     set_fpu_control_word(old_fpucw);
04289 
04290     return hr;
04291 }
04292 
04293 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawPrimitiveVB(IDirect3DDevice3 *iface,
04294         D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer *D3DVertexBuf, DWORD StartVertex,
04295         DWORD NumVertices, DWORD Flags)
04296 {
04297     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
04298     IDirect3DVertexBufferImpl *vb = unsafe_impl_from_IDirect3DVertexBuffer(D3DVertexBuf);
04299 
04300     TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
04301             iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
04302 
04303     return IDirect3DDevice7_DrawPrimitiveVB(&This->IDirect3DDevice7_iface,
04304             PrimitiveType, &vb->IDirect3DVertexBuffer7_iface, StartVertex, NumVertices, Flags);
04305 }
04306 
04307 
04308 /*****************************************************************************
04309  * IDirect3DDevice7::DrawIndexedPrimitiveVB
04310  *
04311  * Draws primitives from a vertex buffer to the screen
04312  *
04313  * Params:
04314  *  PrimitiveType: Type of primitive to be rendered.
04315  *  D3DVertexBuf: Source Vertex Buffer
04316  *  StartVertex: Index of the first vertex from the buffer to be rendered
04317  *  NumVertices: Number of vertices to be rendered
04318  *  Indices: Array of DWORDs used to index into the Vertices
04319  *  IndexCount: Number of indices in Indices
04320  *  Flags: Can be D3DDP_WAIT to wait until rendering has finished
04321  *
04322  * Return values
04323  *
04324  *****************************************************************************/
04325 static HRESULT
04326 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(IDirect3DDevice7 *iface,
04327                                              D3DPRIMITIVETYPE PrimitiveType,
04328                                              IDirect3DVertexBuffer7 *D3DVertexBuf,
04329                                              DWORD StartVertex,
04330                                              DWORD NumVertices,
04331                                              WORD *Indices,
04332                                              DWORD IndexCount,
04333                                              DWORD Flags)
04334 {
04335     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
04336     IDirect3DVertexBufferImpl *vb = unsafe_impl_from_IDirect3DVertexBuffer7(D3DVertexBuf);
04337     DWORD stride = get_flexible_vertex_size(vb->fvf);
04338     struct wined3d_resource *wined3d_resource;
04339     struct wined3d_resource_desc desc;
04340     WORD *LockedIndices;
04341     HRESULT hr;
04342 
04343     TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
04344             iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
04345 
04346     /* Steps:
04347      * 1) Upload the Indices to the index buffer
04348      * 2) Set the index source
04349      * 3) Set the Vertex Buffer as the Stream source
04350      * 4) Call IWineD3DDevice::DrawIndexedPrimitive
04351      */
04352 
04353     wined3d_mutex_lock();
04354 
04355     hr = wined3d_device_set_vertex_declaration(This->wined3d_device, vb->wineD3DVertexDeclaration);
04356     if (FAILED(hr))
04357     {
04358         ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
04359         wined3d_mutex_unlock();
04360         return hr;
04361     }
04362 
04363     /* check that the buffer is large enough to hold the indices,
04364      * reallocate if necessary. */
04365     wined3d_resource = wined3d_buffer_get_resource(This->indexbuffer);
04366     wined3d_resource_get_desc(wined3d_resource, &desc);
04367     if (desc.size < IndexCount * sizeof(WORD))
04368     {
04369         UINT size = max(desc.size * 2, IndexCount * sizeof(WORD));
04370         struct wined3d_buffer *buffer;
04371 
04372         TRACE("Growing index buffer to %u bytes\n", size);
04373 
04374         hr = wined3d_buffer_create_ib(This->wined3d_device, size, WINED3DUSAGE_DYNAMIC /* Usage */,
04375                 WINED3D_POOL_DEFAULT, NULL, &ddraw_null_wined3d_parent_ops, &buffer);
04376         if (FAILED(hr))
04377         {
04378             ERR("(%p) IWineD3DDevice::CreateIndexBuffer failed with hr = %08x\n", This, hr);
04379             wined3d_mutex_unlock();
04380             return hr;
04381         }
04382 
04383         wined3d_buffer_decref(This->indexbuffer);
04384         This->indexbuffer = buffer;
04385     }
04386 
04387     /* Copy the index stream into the index buffer. A new IWineD3DDevice
04388      * method could be created which takes an user pointer containing the
04389      * indices or a SetData-Method for the index buffer, which overrides the
04390      * index buffer data with our pointer. */
04391     hr = wined3d_buffer_map(This->indexbuffer, 0, IndexCount * sizeof(WORD),
04392             (BYTE **)&LockedIndices, 0);
04393     if (FAILED(hr))
04394     {
04395         ERR("Failed to map buffer, hr %#x.\n", hr);
04396         wined3d_mutex_unlock();
04397         return hr;
04398     }
04399     memcpy(LockedIndices, Indices, IndexCount * sizeof(WORD));
04400     wined3d_buffer_unmap(This->indexbuffer);
04401 
04402     /* Set the index stream */
04403     wined3d_device_set_base_vertex_index(This->wined3d_device, StartVertex);
04404     hr = wined3d_device_set_index_buffer(This->wined3d_device, This->indexbuffer, WINED3DFMT_R16_UINT);
04405 
04406     /* Set the vertex stream source */
04407     hr = wined3d_device_set_stream_source(This->wined3d_device, 0, vb->wineD3DVertexBuffer, 0, stride);
04408     if (FAILED(hr))
04409     {
04410         ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
04411         wined3d_mutex_unlock();
04412         return hr;
04413     }
04414 
04415 
04416     wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
04417     hr = wined3d_device_draw_indexed_primitive(This->wined3d_device, 0, IndexCount);
04418 
04419     wined3d_mutex_unlock();
04420 
04421     return hr;
04422 }
04423 
04424 static HRESULT WINAPI
04425 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
04426                                              D3DPRIMITIVETYPE PrimitiveType,
04427                                              IDirect3DVertexBuffer7 *D3DVertexBuf,
04428                                              DWORD StartVertex,
04429                                              DWORD NumVertices,
04430                                              WORD *Indices,
04431                                              DWORD IndexCount,
04432                                              DWORD Flags)
04433 {
04434     return IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
04435 }
04436 
04437 static HRESULT WINAPI
04438 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
04439                                              D3DPRIMITIVETYPE PrimitiveType,
04440                                              IDirect3DVertexBuffer7 *D3DVertexBuf,
04441                                              DWORD StartVertex,
04442                                              DWORD NumVertices,
04443                                              WORD *Indices,
04444                                              DWORD IndexCount,
04445                                              DWORD Flags)
04446 {
04447     HRESULT hr;
04448     WORD old_fpucw;
04449 
04450     old_fpucw = d3d_fpu_setup();
04451     hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
04452     set_fpu_control_word(old_fpucw);
04453 
04454     return hr;
04455 }
04456 
04457 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB(IDirect3DDevice3 *iface,
04458         D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer *D3DVertexBuf, WORD *Indices,
04459         DWORD IndexCount, DWORD Flags)
04460 {
04461     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
04462     IDirect3DVertexBufferImpl *vb = unsafe_impl_from_IDirect3DVertexBuffer(D3DVertexBuf);
04463 
04464     TRACE("iface %p, primitive_type %#x, vb %p, indices %p, index_count %u, flags %#x.\n",
04465             iface, PrimitiveType, D3DVertexBuf, Indices, IndexCount, Flags);
04466 
04467     return IDirect3DDevice7_DrawIndexedPrimitiveVB(&This->IDirect3DDevice7_iface,
04468             PrimitiveType, &vb->IDirect3DVertexBuffer7_iface, 0, IndexCount, Indices, IndexCount,
04469             Flags);
04470 }
04471 
04472 /*****************************************************************************
04473  * IDirect3DDevice7::ComputeSphereVisibility
04474  *
04475  * Calculates the visibility of spheres in the current viewport. The spheres
04476  * are passed in the Centers and Radii arrays, the results are passed back
04477  * in the ReturnValues array. Return values are either completely visible,
04478  * partially visible or completely invisible.
04479  * The return value consist of a combination of D3DCLIP_* flags, or it's
04480  * 0 if the sphere is completely visible(according to the SDK, not checked)
04481  *
04482  * Version 3 and 7
04483  *
04484  * Params:
04485  *  Centers: Array containing the sphere centers
04486  *  Radii: Array containing the sphere radii
04487  *  NumSpheres: The number of centers and radii in the arrays
04488  *  Flags: Some flags
04489  *  ReturnValues: Array to write the results to
04490  *
04491  * Returns:
04492  *  D3D_OK
04493  *  (DDERR_INVALIDPARAMS if Centers, Radii or ReturnValues are NULL)
04494  *  (D3DERR_INVALIDMATRIX if the combined world, view and proj matrix
04495  *  is singular)
04496  *
04497  *****************************************************************************/
04498 
04499 static DWORD in_plane(UINT plane, D3DVECTOR normal, D3DVALUE origin_plane, D3DVECTOR center, D3DVALUE radius)
04500 {
04501     float distance, norm;
04502 
04503     norm = sqrt( normal.u1.x * normal.u1.x + normal.u2.y * normal.u2.y + normal.u3.z * normal.u3.z );
04504     distance = ( origin_plane + normal.u1.x * center.u1.x + normal.u2.y * center.u2.y + normal.u3.z * center.u3.z ) / norm;
04505 
04506     if ( fabs( distance ) < radius ) return D3DSTATUS_CLIPUNIONLEFT << plane;
04507     if ( distance < -radius ) return (D3DSTATUS_CLIPUNIONLEFT  | D3DSTATUS_CLIPINTERSECTIONLEFT) << plane;
04508     return 0;
04509 }
04510 
04511 static HRESULT WINAPI
04512 IDirect3DDeviceImpl_7_ComputeSphereVisibility(IDirect3DDevice7 *iface,
04513                                               D3DVECTOR *Centers,
04514                                               D3DVALUE *Radii,
04515                                               DWORD NumSpheres,
04516                                               DWORD Flags,
04517                                               DWORD *ReturnValues)
04518 {
04519     D3DMATRIX m, temp;
04520     D3DVALUE origin_plane[6];
04521     D3DVECTOR vec[6];
04522     HRESULT hr;
04523     UINT i, j;
04524 
04525     TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
04526             iface, Centers, Radii, NumSpheres, Flags, ReturnValues);
04527 
04528     hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_WORLD, &m);
04529     if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
04530     hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_VIEW, &temp);
04531     if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
04532     multiply_matrix(&m, &temp, &m);
04533 
04534     hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_PROJECTION, &temp);
04535     if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
04536     multiply_matrix(&m, &temp, &m);
04537 
04538 /* Left plane */
04539     vec[0].u1.x = m._14 + m._11;
04540     vec[0].u2.y = m._24 + m._21;
04541     vec[0].u3.z = m._34 + m._31;
04542     origin_plane[0] = m._44 + m._41;
04543 
04544 /* Right plane */
04545     vec[1].u1.x = m._14 - m._11;
04546     vec[1].u2.y = m._24 - m._21;
04547     vec[1].u3.z = m._34 - m._31;
04548     origin_plane[1] = m._44 - m._41;
04549 
04550 /* Top plane */
04551     vec[2].u1.x = m._14 - m._12;
04552     vec[2].u2.y = m._24 - m._22;
04553     vec[2].u3.z = m._34 - m._32;
04554     origin_plane[2] = m._44 - m._42;
04555 
04556 /* Bottom plane */
04557     vec[3].u1.x = m._14 + m._12;
04558     vec[3].u2.y = m._24 + m._22;
04559     vec[3].u3.z = m._34 + m._32;
04560     origin_plane[3] = m._44 + m._42;
04561 
04562 /* Front plane */
04563     vec[4].u1.x = m._13;
04564     vec[4].u2.y = m._23;
04565     vec[4].u3.z = m._33;
04566     origin_plane[4] = m._43;
04567 
04568 /* Back plane*/
04569     vec[5].u1.x = m._14 - m._13;
04570     vec[5].u2.y = m._24 - m._23;
04571     vec[5].u3.z = m._34 - m._33;
04572     origin_plane[5] = m._44 - m._43;
04573 
04574     for(i=0; i<NumSpheres; i++)
04575     {
04576         ReturnValues[i] = 0;
04577         for(j=0; j<6; j++) ReturnValues[i] |= in_plane(j, vec[j], origin_plane[j], Centers[i], Radii[i]);
04578     }
04579 
04580     return D3D_OK;
04581 }
04582 
04583 static HRESULT WINAPI IDirect3DDeviceImpl_3_ComputeSphereVisibility(IDirect3DDevice3 *iface,
04584         D3DVECTOR *Centers, D3DVALUE *Radii, DWORD NumSpheres, DWORD Flags, DWORD *ReturnValues)
04585 {
04586     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
04587 
04588     TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
04589             iface, Centers, Radii, NumSpheres, Flags, ReturnValues);
04590 
04591     return IDirect3DDevice7_ComputeSphereVisibility(&This->IDirect3DDevice7_iface,
04592             Centers, Radii, NumSpheres, Flags, ReturnValues);
04593 }
04594 
04595 /*****************************************************************************
04596  * IDirect3DDevice7::GetTexture
04597  *
04598  * Returns the texture interface handle assigned to a texture stage.
04599  * The returned texture is AddRefed. This is taken from old ddraw,
04600  * not checked in Windows.
04601  *
04602  * Version 3 and 7
04603  *
04604  * Params:
04605  *  Stage: Texture stage to read the texture from
04606  *  Texture: Address to store the interface pointer at
04607  *
04608  * Returns:
04609  *  D3D_OK on success
04610  *  DDERR_INVALIDPARAMS if Texture is NULL
04611  *  For details, see IWineD3DDevice::GetTexture
04612  *
04613  *****************************************************************************/
04614 static HRESULT
04615 IDirect3DDeviceImpl_7_GetTexture(IDirect3DDevice7 *iface,
04616                                  DWORD Stage,
04617                                  IDirectDrawSurface7 **Texture)
04618 {
04619     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
04620     struct wined3d_texture *wined3d_texture;
04621     HRESULT hr;
04622 
04623     TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture);
04624 
04625     if(!Texture)
04626     {
04627         TRACE("Texture == NULL, failing with DDERR_INVALIDPARAMS\n");
04628         return DDERR_INVALIDPARAMS;
04629     }
04630 
04631     wined3d_mutex_lock();
04632     hr = wined3d_device_get_texture(This->wined3d_device, Stage, &wined3d_texture);
04633     if (FAILED(hr) || !wined3d_texture)
04634     {
04635         *Texture = NULL;
04636         wined3d_mutex_unlock();
04637         return hr;
04638     }
04639 
04640     *Texture = wined3d_texture_get_parent(wined3d_texture);
04641     IDirectDrawSurface7_AddRef(*Texture);
04642     wined3d_texture_decref(wined3d_texture);
04643     wined3d_mutex_unlock();
04644 
04645     return hr;
04646 }
04647 
04648 static HRESULT WINAPI
04649 IDirect3DDeviceImpl_7_GetTexture_FPUSetup(IDirect3DDevice7 *iface,
04650                                  DWORD Stage,
04651                                  IDirectDrawSurface7 **Texture)
04652 {
04653     return IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture);
04654 }
04655 
04656 static HRESULT WINAPI
04657 IDirect3DDeviceImpl_7_GetTexture_FPUPreserve(IDirect3DDevice7 *iface,
04658                                  DWORD Stage,
04659                                  IDirectDrawSurface7 **Texture)
04660 {
04661     HRESULT hr;
04662     WORD old_fpucw;
04663 
04664     old_fpucw = d3d_fpu_setup();
04665     hr = IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture);
04666     set_fpu_control_word(old_fpucw);
04667 
04668     return hr;
04669 }
04670 
04671 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetTexture(IDirect3DDevice3 *iface, DWORD Stage,
04672         IDirect3DTexture2 **Texture2)
04673 {
04674     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
04675     HRESULT ret;
04676     IDirectDrawSurface7 *ret_val;
04677     IDirectDrawSurfaceImpl *ret_val_impl;
04678 
04679     TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture2);
04680 
04681     ret = IDirect3DDevice7_GetTexture(&This->IDirect3DDevice7_iface, Stage, &ret_val);
04682 
04683     ret_val_impl = unsafe_impl_from_IDirectDrawSurface7(ret_val);
04684     *Texture2 = ret_val_impl ? &ret_val_impl->IDirect3DTexture2_iface : NULL;
04685 
04686     TRACE("Returning texture %p.\n", *Texture2);
04687 
04688     return ret;
04689 }
04690 
04691 /*****************************************************************************
04692  * IDirect3DDevice7::SetTexture
04693  *
04694  * Assigns a texture to a texture stage. Is the texture AddRef-ed?
04695  *
04696  * Version 3 and 7
04697  *
04698  * Params:
04699  *  Stage: The stage to assign the texture to
04700  *  Texture: Interface pointer to the texture surface
04701  *
04702  * Returns
04703  * D3D_OK on success
04704  * For details, see IWineD3DDevice::SetTexture
04705  *
04706  *****************************************************************************/
04707 static HRESULT
04708 IDirect3DDeviceImpl_7_SetTexture(IDirect3DDevice7 *iface,
04709                                  DWORD Stage,
04710                                  IDirectDrawSurface7 *Texture)
04711 {
04712     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
04713     IDirectDrawSurfaceImpl *surf = unsafe_impl_from_IDirectDrawSurface7(Texture);
04714     HRESULT hr;
04715 
04716     TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture);
04717 
04718     /* Texture may be NULL here */
04719     wined3d_mutex_lock();
04720     hr = wined3d_device_set_texture(This->wined3d_device,
04721             Stage, surf ? surf->wined3d_texture : NULL);
04722     wined3d_mutex_unlock();
04723 
04724     return hr;
04725 }
04726 
04727 static HRESULT WINAPI
04728 IDirect3DDeviceImpl_7_SetTexture_FPUSetup(IDirect3DDevice7 *iface,
04729                                  DWORD Stage,
04730                                  IDirectDrawSurface7 *Texture)
04731 {
04732     return IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture);
04733 }
04734 
04735 static HRESULT WINAPI
04736 IDirect3DDeviceImpl_7_SetTexture_FPUPreserve(IDirect3DDevice7 *iface,
04737                                  DWORD Stage,
04738                                  IDirectDrawSurface7 *Texture)
04739 {
04740     HRESULT hr;
04741     WORD old_fpucw;
04742 
04743     old_fpucw = d3d_fpu_setup();
04744     hr = IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture);
04745     set_fpu_control_word(old_fpucw);
04746 
04747     return hr;
04748 }
04749 
04750 static HRESULT WINAPI
04751 IDirect3DDeviceImpl_3_SetTexture(IDirect3DDevice3 *iface,
04752                                  DWORD Stage,
04753                                  IDirect3DTexture2 *Texture2)
04754 {
04755     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
04756     IDirectDrawSurfaceImpl *tex = unsafe_impl_from_IDirect3DTexture2(Texture2);
04757     DWORD texmapblend;
04758     HRESULT hr;
04759 
04760     TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture2);
04761 
04762     wined3d_mutex_lock();
04763 
04764     if (This->legacyTextureBlending)
04765         IDirect3DDevice3_GetRenderState(iface, D3DRENDERSTATE_TEXTUREMAPBLEND, &texmapblend);
04766 
04767     hr = IDirect3DDevice7_SetTexture(&This->IDirect3DDevice7_iface, Stage, &tex->IDirectDrawSurface7_iface);
04768 
04769     if (This->legacyTextureBlending && texmapblend == D3DTBLEND_MODULATE)
04770     {
04771         /* This fixup is required by the way D3DTBLEND_MODULATE maps to texture stage states.
04772            See IDirect3DDeviceImpl_3_SetRenderState for details. */
04773         struct wined3d_texture *tex = NULL;
04774         BOOL tex_alpha = FALSE;
04775         DDPIXELFORMAT ddfmt;
04776         HRESULT result;
04777 
04778         result = wined3d_device_get_texture(This->wined3d_device, 0, &tex);
04779         if (result == WINED3D_OK && tex)
04780         {
04781             struct wined3d_resource *sub_resource;
04782 
04783             if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
04784             {
04785                 struct wined3d_resource_desc desc;
04786 
04787                 wined3d_resource_get_desc(sub_resource, &desc);
04788                 ddfmt.dwSize = sizeof(ddfmt);
04789                 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
04790                 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
04791             }
04792 
04793             wined3d_texture_decref(tex);
04794         }
04795 
04796         /* Arg 1/2 are already set to WINED3DTA_TEXTURE/WINED3DTA_CURRENT in case of D3DTBLEND_MODULATE */
04797         if (tex_alpha)
04798             wined3d_device_set_texture_stage_state(This->wined3d_device,
04799                     0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG1);
04800         else
04801             wined3d_device_set_texture_stage_state(This->wined3d_device,
04802                     0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
04803     }
04804 
04805     wined3d_mutex_unlock();
04806 
04807     return hr;
04808 }
04809 
04810 static const struct tss_lookup
04811 {
04812     BOOL sampler_state;
04813     enum wined3d_texture_stage_state state;
04814 }
04815 tss_lookup[] =
04816 {
04817     {FALSE, WINED3D_TSS_INVALID},                   /*  0, unused */
04818     {FALSE, WINED3D_TSS_COLOR_OP},                  /*  1, D3DTSS_COLOROP */
04819     {FALSE, WINED3D_TSS_COLOR_ARG1},                /*  2, D3DTSS_COLORARG1 */
04820     {FALSE, WINED3D_TSS_COLOR_ARG2},                /*  3, D3DTSS_COLORARG2 */
04821     {FALSE, WINED3D_TSS_ALPHA_OP},                  /*  4, D3DTSS_ALPHAOP */
04822     {FALSE, WINED3D_TSS_ALPHA_ARG1},                /*  5, D3DTSS_ALPHAARG1 */
04823     {FALSE, WINED3D_TSS_ALPHA_ARG2},                /*  6, D3DTSS_ALPHAARG2 */
04824     {FALSE, WINED3D_TSS_BUMPENV_MAT00},             /*  7, D3DTSS_BUMPENVMAT00 */
04825     {FALSE, WINED3D_TSS_BUMPENV_MAT01},             /*  8, D3DTSS_BUMPENVMAT01 */
04826     {FALSE, WINED3D_TSS_BUMPENV_MAT10},             /*  9, D3DTSS_BUMPENVMAT10 */
04827     {FALSE, WINED3D_TSS_BUMPENV_MAT11},             /* 10, D3DTSS_BUMPENVMAT11 */
04828     {FALSE, WINED3D_TSS_TEXCOORD_INDEX},            /* 11, D3DTSS_TEXCOORDINDEX */
04829     {TRUE,  WINED3D_SAMP_ADDRESS_U},                /* 12, D3DTSS_ADDRESS */
04830     {TRUE,  WINED3D_SAMP_ADDRESS_U},                /* 13, D3DTSS_ADDRESSU */
04831     {TRUE,  WINED3D_SAMP_ADDRESS_V},                /* 14, D3DTSS_ADDRESSV */
04832     {TRUE,  WINED3D_SAMP_BORDER_COLOR},             /* 15, D3DTSS_BORDERCOLOR */
04833     {TRUE,  WINED3D_SAMP_MAG_FILTER},               /* 16, D3DTSS_MAGFILTER */
04834     {TRUE,  WINED3D_SAMP_MIN_FILTER},               /* 17, D3DTSS_MINFILTER */
04835     {TRUE,  WINED3D_SAMP_MIP_FILTER},               /* 18, D3DTSS_MIPFILTER */
04836     {TRUE,  WINED3D_SAMP_MIPMAP_LOD_BIAS},          /* 19, D3DTSS_MIPMAPLODBIAS */
04837     {TRUE,  WINED3D_SAMP_MAX_MIP_LEVEL},            /* 20, D3DTSS_MAXMIPLEVEL */
04838     {TRUE,  WINED3D_SAMP_MAX_ANISOTROPY},           /* 21, D3DTSS_MAXANISOTROPY */
04839     {FALSE, WINED3D_TSS_BUMPENV_LSCALE},            /* 22, D3DTSS_BUMPENVLSCALE */
04840     {FALSE, WINED3D_TSS_BUMPENV_LOFFSET},           /* 23, D3DTSS_BUMPENVLOFFSET */
04841     {FALSE, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS},   /* 24, D3DTSS_TEXTURETRANSFORMFLAGS */
04842 };
04843 
04844 /*****************************************************************************
04845  * IDirect3DDevice7::GetTextureStageState
04846  *
04847  * Retrieves a state from a texture stage.
04848  *
04849  * Version 3 and 7
04850  *
04851  * Params:
04852  *  Stage: The stage to retrieve the state from
04853  *  TexStageStateType: The state type to retrieve
04854  *  State: Address to store the state's value at
04855  *
04856  * Returns:
04857  *  D3D_OK on success
04858  *  DDERR_INVALIDPARAMS if State is NULL
04859  *  For details, see IWineD3DDevice::GetTextureStageState
04860  *
04861  *****************************************************************************/
04862 static HRESULT
04863 IDirect3DDeviceImpl_7_GetTextureStageState(IDirect3DDevice7 *iface,
04864                                            DWORD Stage,
04865                                            D3DTEXTURESTAGESTATETYPE TexStageStateType,
04866                                            DWORD *State)
04867 {
04868     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
04869     HRESULT hr;
04870     const struct tss_lookup *l;
04871 
04872     TRACE("iface %p, stage %u, state %#x, value %p.\n",
04873             iface, Stage, TexStageStateType, State);
04874 
04875     if(!State)
04876         return DDERR_INVALIDPARAMS;
04877 
04878     if (TexStageStateType > D3DTSS_TEXTURETRANSFORMFLAGS)
04879     {
04880         WARN("Invalid TexStageStateType %#x passed.\n", TexStageStateType);
04881         return DD_OK;
04882     }
04883 
04884     l = &tss_lookup[TexStageStateType];
04885 
04886     wined3d_mutex_lock();
04887 
04888     if (l->sampler_state)
04889     {
04890         hr = wined3d_device_get_sampler_state(This->wined3d_device, Stage, l->state, State);
04891 
04892         switch(TexStageStateType)
04893         {
04894             /* Mipfilter is a sampler state with different values */
04895             case D3DTSS_MIPFILTER:
04896             {
04897                 switch(*State)
04898                 {
04899                     case WINED3D_TEXF_NONE:
04900                         *State = D3DTFP_NONE;
04901                         break;
04902                     case WINED3D_TEXF_POINT:
04903                         *State = D3DTFP_POINT;
04904                         break;
04905                     case WINED3D_TEXF_LINEAR:
04906                         *State = D3DTFP_LINEAR;
04907                         break;
04908                     default:
04909                         ERR("Unexpected mipfilter value %#x\n", *State);
04910                         *State = D3DTFP_NONE;
04911                         break;
04912                 }
04913                 break;
04914             }
04915 
04916             /* Magfilter has slightly different values */
04917             case D3DTSS_MAGFILTER:
04918             {
04919                 switch(*State)
04920                 {
04921                     case WINED3D_TEXF_POINT:
04922                             *State = D3DTFG_POINT;
04923                             break;
04924                     case WINED3D_TEXF_LINEAR:
04925                             *State = D3DTFG_LINEAR;
04926                             break;
04927                     case WINED3D_TEXF_ANISOTROPIC:
04928                             *State = D3DTFG_ANISOTROPIC;
04929                             break;
04930                     case WINED3D_TEXF_FLAT_CUBIC:
04931                             *State = D3DTFG_FLATCUBIC;
04932                             break;
04933                     case WINED3D_TEXF_GAUSSIAN_CUBIC:
04934                             *State = D3DTFG_GAUSSIANCUBIC;
04935                             break;
04936                     default:
04937                         ERR("Unexpected wined3d mag filter value %#x\n", *State);
04938                         *State = D3DTFG_POINT;
04939                         break;
04940                 }
04941                 break;
04942             }
04943 
04944             default:
04945                 break;
04946         }
04947     }
04948     else
04949     {
04950         hr = wined3d_device_get_texture_stage_state(This->wined3d_device, Stage, l->state, State);
04951     }
04952 
04953     wined3d_mutex_unlock();
04954 
04955     return hr;
04956 }
04957 
04958 static HRESULT WINAPI
04959 IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
04960                                            DWORD Stage,
04961                                            D3DTEXTURESTAGESTATETYPE TexStageStateType,
04962                                            DWORD *State)
04963 {
04964     return IDirect3DDeviceImpl_7_GetTextureStageState(iface, Stage, TexStageStateType, State);
04965 }
04966 
04967 static HRESULT WINAPI
04968 IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
04969                                            DWORD Stage,
04970                                            D3DTEXTURESTAGESTATETYPE TexStageStateType,
04971                                            DWORD *State)
04972 {
04973     HRESULT hr;
04974     WORD old_fpucw;
04975 
04976     old_fpucw = d3d_fpu_setup();
04977     hr = IDirect3DDeviceImpl_7_GetTextureStageState(iface, Stage, TexStageStateType, State);
04978     set_fpu_control_word(old_fpucw);
04979 
04980     return hr;
04981 }
04982 
04983 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetTextureStageState(IDirect3DDevice3 *iface,
04984         DWORD Stage, D3DTEXTURESTAGESTATETYPE TexStageStateType, DWORD *State)
04985 {
04986     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
04987 
04988     TRACE("iface %p, stage %u, state %#x, value %p.\n",
04989             iface, Stage, TexStageStateType, State);
04990 
04991     return IDirect3DDevice7_GetTextureStageState(&This->IDirect3DDevice7_iface,
04992             Stage, TexStageStateType, State);
04993 }
04994 
04995 /*****************************************************************************
04996  * IDirect3DDevice7::SetTextureStageState
04997  *
04998  * Sets a texture stage state. Some stage types need to be handled specially,
04999  * because they do not exist in WineD3D and were moved to another place
05000  *
05001  * Version 3 and 7
05002  *
05003  * Params:
05004  *  Stage: The stage to modify
05005  *  TexStageStateType: The state to change
05006  *  State: The new value for the state
05007  *
05008  * Returns:
05009  *  D3D_OK on success
05010  *  For details, see IWineD3DDevice::SetTextureStageState
05011  *
05012  *****************************************************************************/
05013 static HRESULT
05014 IDirect3DDeviceImpl_7_SetTextureStageState(IDirect3DDevice7 *iface,
05015                                            DWORD Stage,
05016                                            D3DTEXTURESTAGESTATETYPE TexStageStateType,
05017                                            DWORD State)
05018 {
05019     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
05020     const struct tss_lookup *l;
05021     HRESULT hr;
05022 
05023     TRACE("iface %p, stage %u, state %#x, value %#x.\n",
05024             iface, Stage, TexStageStateType, State);
05025 
05026     if (TexStageStateType > D3DTSS_TEXTURETRANSFORMFLAGS)
05027     {
05028         WARN("Invalid TexStageStateType %#x passed.\n", TexStageStateType);
05029         return DD_OK;
05030     }
05031 
05032     l = &tss_lookup[TexStageStateType];
05033 
05034     wined3d_mutex_lock();
05035 
05036     if (l->sampler_state)
05037     {
05038         switch(TexStageStateType)
05039         {
05040             /* Mipfilter is a sampler state with different values */
05041             case D3DTSS_MIPFILTER:
05042             {
05043                 switch(State)
05044                 {
05045                     case D3DTFP_NONE:
05046                         State = WINED3D_TEXF_NONE;
05047                         break;
05048                     case D3DTFP_POINT:
05049                         State = WINED3D_TEXF_POINT;
05050                         break;
05051                     case 0: /* Unchecked */
05052                     case D3DTFP_LINEAR:
05053                         State = WINED3D_TEXF_LINEAR;
05054                         break;
05055                     default:
05056                         ERR("Unexpected mipfilter value %d\n", State);
05057                         State = WINED3D_TEXF_NONE;
05058                         break;
05059                 }
05060                 break;
05061             }
05062 
05063             /* Magfilter has slightly different values */
05064             case D3DTSS_MAGFILTER:
05065             {
05066                 switch(State)
05067                 {
05068                     case D3DTFG_POINT:
05069                         State = WINED3D_TEXF_POINT;
05070                         break;
05071                     case D3DTFG_LINEAR:
05072                         State = WINED3D_TEXF_LINEAR;
05073                         break;
05074                     case D3DTFG_FLATCUBIC:
05075                         State = WINED3D_TEXF_FLAT_CUBIC;
05076                         break;
05077                     case D3DTFG_GAUSSIANCUBIC:
05078                         State = WINED3D_TEXF_GAUSSIAN_CUBIC;
05079                         break;
05080                     case D3DTFG_ANISOTROPIC:
05081                         State = WINED3D_TEXF_ANISOTROPIC;
05082                         break;
05083                     default:
05084                         ERR("Unexpected d3d7 mag filter type %d\n", State);
05085                         State = WINED3D_TEXF_POINT;
05086                         break;
05087                 }
05088                 break;
05089             }
05090 
05091             case D3DTSS_ADDRESS:
05092                 wined3d_device_set_sampler_state(This->wined3d_device, Stage, WINED3D_SAMP_ADDRESS_V, State);
05093                 break;
05094 
05095             default:
05096                 break;
05097         }
05098 
05099         hr = wined3d_device_set_sampler_state(This->wined3d_device, Stage, l->state, State);
05100     }
05101     else
05102     {
05103         hr = wined3d_device_set_texture_stage_state(This->wined3d_device, Stage, l->state, State);
05104     }
05105 
05106     wined3d_mutex_unlock();
05107 
05108     return hr;
05109 }
05110 
05111 static HRESULT WINAPI
05112 IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
05113                                            DWORD Stage,
05114                                            D3DTEXTURESTAGESTATETYPE TexStageStateType,
05115                                            DWORD State)
05116 {
05117     return IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State);
05118 }
05119 
05120 static HRESULT WINAPI
05121 IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
05122                                            DWORD Stage,
05123                                            D3DTEXTURESTAGESTATETYPE TexStageStateType,
05124                                            DWORD State)
05125 {
05126     HRESULT hr;
05127     WORD old_fpucw;
05128 
05129     old_fpucw = d3d_fpu_setup();
05130     hr = IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State);
05131     set_fpu_control_word(old_fpucw);
05132 
05133     return hr;
05134 }
05135 
05136 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetTextureStageState(IDirect3DDevice3 *iface,
05137         DWORD Stage, D3DTEXTURESTAGESTATETYPE TexStageStateType, DWORD State)
05138 {
05139     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
05140 
05141     TRACE("iface %p, stage %u, state %#x, value %#x.\n",
05142             iface, Stage, TexStageStateType, State);
05143 
05144     return IDirect3DDevice7_SetTextureStageState(&This->IDirect3DDevice7_iface,
05145             Stage, TexStageStateType, State);
05146 }
05147 
05148 /*****************************************************************************
05149  * IDirect3DDevice7::ValidateDevice
05150  *
05151  * SDK: "Reports the device's ability to render the currently set
05152  * texture-blending operations in a single pass". Whatever that means
05153  * exactly...
05154  *
05155  * Version 3 and 7
05156  *
05157  * Params:
05158  *  NumPasses: Address to write the number of necessary passes for the
05159  *             desired effect to.
05160  *
05161  * Returns:
05162  *  D3D_OK on success
05163  *  See IWineD3DDevice::ValidateDevice for more details
05164  *
05165  *****************************************************************************/
05166 static HRESULT
05167 IDirect3DDeviceImpl_7_ValidateDevice(IDirect3DDevice7 *iface,
05168                                      DWORD *NumPasses)
05169 {
05170     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
05171     HRESULT hr;
05172 
05173     TRACE("iface %p, pass_count %p.\n", iface, NumPasses);
05174 
05175     wined3d_mutex_lock();
05176     hr = wined3d_device_validate_device(This->wined3d_device, NumPasses);
05177     wined3d_mutex_unlock();
05178 
05179     return hr;
05180 }
05181 
05182 static HRESULT WINAPI
05183 IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup(IDirect3DDevice7 *iface,
05184                                      DWORD *NumPasses)
05185 {
05186     return IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses);
05187 }
05188 
05189 static HRESULT WINAPI
05190 IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve(IDirect3DDevice7 *iface,
05191                                      DWORD *NumPasses)
05192 {
05193     HRESULT hr;
05194     WORD old_fpucw;
05195 
05196     old_fpucw = d3d_fpu_setup();
05197     hr = IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses);
05198     set_fpu_control_word(old_fpucw);
05199 
05200     return hr;
05201 }
05202 
05203 static HRESULT WINAPI IDirect3DDeviceImpl_3_ValidateDevice(IDirect3DDevice3 *iface, DWORD *Passes)
05204 {
05205     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
05206 
05207     TRACE("iface %p, pass_count %p.\n", iface, Passes);
05208 
05209     return IDirect3DDevice7_ValidateDevice(&This->IDirect3DDevice7_iface, Passes);
05210 }
05211 
05212 /*****************************************************************************
05213  * IDirect3DDevice7::Clear
05214  *
05215  * Fills the render target, the z buffer and the stencil buffer with a
05216  * clear color / value
05217  *
05218  * Version 7 only
05219  *
05220  * Params:
05221  *  Count: Number of rectangles in Rects must be 0 if Rects is NULL
05222  *  Rects: Rectangles to clear. If NULL, the whole surface is cleared
05223  *  Flags: Some flags, as usual
05224  *  Color: Clear color for the render target
05225  *  Z: Clear value for the Z buffer
05226  *  Stencil: Clear value to store in each stencil buffer entry
05227  *
05228  * Returns:
05229  *  D3D_OK on success
05230  *  For details, see IWineD3DDevice::Clear
05231  *
05232  *****************************************************************************/
05233 static HRESULT IDirect3DDeviceImpl_7_Clear(IDirect3DDevice7 *iface, DWORD count,
05234         D3DRECT *rects, DWORD flags, D3DCOLOR color, D3DVALUE z, DWORD stencil)
05235 {
05236     const struct wined3d_color c =
05237     {
05238         ((color >> 16) & 0xff) / 255.0f,
05239         ((color >>  8) & 0xff) / 255.0f,
05240         (color & 0xff) / 255.0f,
05241         ((color >> 24) & 0xff) / 255.0f,
05242     };
05243     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
05244     HRESULT hr;
05245 
05246     TRACE("iface %p, count %u, rects %p, flags %#x, color 0x%08x, z %.8e, stencil %#x.\n",
05247             iface, count, rects, flags, color, z, stencil);
05248 
05249     wined3d_mutex_lock();
05250     hr = wined3d_device_clear(This->wined3d_device, count, (RECT *)rects, flags, &c, z, stencil);
05251     wined3d_mutex_unlock();
05252 
05253     return hr;
05254 }
05255 
05256 static HRESULT WINAPI
05257 IDirect3DDeviceImpl_7_Clear_FPUSetup(IDirect3DDevice7 *iface,
05258                             DWORD Count,
05259                             D3DRECT *Rects,
05260                             DWORD Flags,
05261                             D3DCOLOR Color,
05262                             D3DVALUE Z,
05263                             DWORD Stencil)
05264 {
05265     return IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
05266 }
05267 
05268 static HRESULT WINAPI
05269 IDirect3DDeviceImpl_7_Clear_FPUPreserve(IDirect3DDevice7 *iface,
05270                             DWORD Count,
05271                             D3DRECT *Rects,
05272                             DWORD Flags,
05273                             D3DCOLOR Color,
05274                             D3DVALUE Z,
05275                             DWORD Stencil)
05276 {
05277     HRESULT hr;
05278     WORD old_fpucw;
05279 
05280     old_fpucw = d3d_fpu_setup();
05281     hr = IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
05282     set_fpu_control_word(old_fpucw);
05283 
05284     return hr;
05285 }
05286 
05287 /*****************************************************************************
05288  * IDirect3DDevice7::SetViewport
05289  *
05290  * Sets the current viewport.
05291  *
05292  * Version 7 only, but IDirect3DViewport uses this call for older
05293  * versions
05294  *
05295  * Params:
05296  *  Data: The new viewport to set
05297  *
05298  * Returns:
05299  *  D3D_OK on success
05300  *  DDERR_INVALIDPARAMS if Data is NULL
05301  *  For more details, see IWineDDDevice::SetViewport
05302  *
05303  *****************************************************************************/
05304 static HRESULT
05305 IDirect3DDeviceImpl_7_SetViewport(IDirect3DDevice7 *iface,
05306                                   D3DVIEWPORT7 *Data)
05307 {
05308     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
05309     HRESULT hr;
05310 
05311     TRACE("iface %p, viewport %p.\n", iface, Data);
05312 
05313     if(!Data)
05314         return DDERR_INVALIDPARAMS;
05315 
05316     /* Note: D3DVIEWPORT7 is compatible with struct wined3d_viewport. */
05317     wined3d_mutex_lock();
05318     hr = wined3d_device_set_viewport(This->wined3d_device, (struct wined3d_viewport *)Data);
05319     wined3d_mutex_unlock();
05320 
05321     return hr;
05322 }
05323 
05324 static HRESULT WINAPI
05325 IDirect3DDeviceImpl_7_SetViewport_FPUSetup(IDirect3DDevice7 *iface,
05326                                   D3DVIEWPORT7 *Data)
05327 {
05328     return IDirect3DDeviceImpl_7_SetViewport(iface, Data);
05329 }
05330 
05331 static HRESULT WINAPI
05332 IDirect3DDeviceImpl_7_SetViewport_FPUPreserve(IDirect3DDevice7 *iface,
05333                                   D3DVIEWPORT7 *Data)
05334 {
05335     HRESULT hr;
05336     WORD old_fpucw;
05337 
05338     old_fpucw = d3d_fpu_setup();
05339     hr = IDirect3DDeviceImpl_7_SetViewport(iface, Data);
05340     set_fpu_control_word(old_fpucw);
05341 
05342     return hr;
05343 }
05344 
05345 /*****************************************************************************
05346  * IDirect3DDevice::GetViewport
05347  *
05348  * Returns the current viewport
05349  *
05350  * Version 7
05351  *
05352  * Params:
05353  *  Data: D3D7Viewport structure to write the viewport information to
05354  *
05355  * Returns:
05356  *  D3D_OK on success
05357  *  DDERR_INVALIDPARAMS if Data is NULL
05358  *  For more details, see IWineD3DDevice::GetViewport
05359  *
05360  *****************************************************************************/
05361 static HRESULT
05362 IDirect3DDeviceImpl_7_GetViewport(IDirect3DDevice7 *iface,
05363                                   D3DVIEWPORT7 *Data)
05364 {
05365     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
05366     HRESULT hr;
05367 
05368     TRACE("iface %p, viewport %p.\n", iface, Data);
05369 
05370     if(!Data)
05371         return DDERR_INVALIDPARAMS;
05372 
05373     /* Note: D3DVIEWPORT7 is compatible with struct wined3d_viewport. */
05374     wined3d_mutex_lock();
05375     hr = wined3d_device_get_viewport(This->wined3d_device, (struct wined3d_viewport *)Data);
05376     wined3d_mutex_unlock();
05377 
05378     return hr_ddraw_from_wined3d(hr);
05379 }
05380 
05381 static HRESULT WINAPI
05382 IDirect3DDeviceImpl_7_GetViewport_FPUSetup(IDirect3DDevice7 *iface,
05383                                   D3DVIEWPORT7 *Data)
05384 {
05385     return IDirect3DDeviceImpl_7_GetViewport(iface, Data);
05386 }
05387 
05388 static HRESULT WINAPI
05389 IDirect3DDeviceImpl_7_GetViewport_FPUPreserve(IDirect3DDevice7 *iface,
05390                                   D3DVIEWPORT7 *Data)
05391 {
05392     HRESULT hr;
05393     WORD old_fpucw;
05394 
05395     old_fpucw = d3d_fpu_setup();
05396     hr = IDirect3DDeviceImpl_7_GetViewport(iface, Data);
05397     set_fpu_control_word(old_fpucw);
05398 
05399     return hr;
05400 }
05401 
05402 /*****************************************************************************
05403  * IDirect3DDevice7::SetMaterial
05404  *
05405  * Sets the Material
05406  *
05407  * Version 7
05408  *
05409  * Params:
05410  *  Mat: The material to set
05411  *
05412  * Returns:
05413  *  D3D_OK on success
05414  *  DDERR_INVALIDPARAMS if Mat is NULL.
05415  *  For more details, see IWineD3DDevice::SetMaterial
05416  *
05417  *****************************************************************************/
05418 static HRESULT
05419 IDirect3DDeviceImpl_7_SetMaterial(IDirect3DDevice7 *iface,
05420                                   D3DMATERIAL7 *Mat)
05421 {
05422     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
05423     HRESULT hr;
05424 
05425     TRACE("iface %p, material %p.\n", iface, Mat);
05426 
05427     if (!Mat) return DDERR_INVALIDPARAMS;
05428 
05429     wined3d_mutex_lock();
05430     /* Note: D3DMATERIAL7 is compatible with struct wined3d_material. */
05431     hr = wined3d_device_set_material(This->wined3d_device, (struct wined3d_material *)Mat);
05432     wined3d_mutex_unlock();
05433 
05434     return hr_ddraw_from_wined3d(hr);
05435 }
05436 
05437 static HRESULT WINAPI
05438 IDirect3DDeviceImpl_7_SetMaterial_FPUSetup(IDirect3DDevice7 *iface,
05439                                   D3DMATERIAL7 *Mat)
05440 {
05441     return IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
05442 }
05443 
05444 static HRESULT WINAPI
05445 IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
05446                                   D3DMATERIAL7 *Mat)
05447 {
05448     HRESULT hr;
05449     WORD old_fpucw;
05450 
05451     old_fpucw = d3d_fpu_setup();
05452     hr = IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
05453     set_fpu_control_word(old_fpucw);
05454 
05455     return hr;
05456 }
05457 
05458 /*****************************************************************************
05459  * IDirect3DDevice7::GetMaterial
05460  *
05461  * Returns the current material
05462  *
05463  * Version 7
05464  *
05465  * Params:
05466  *  Mat: D3DMATERIAL7 structure to write the material parameters to
05467  *
05468  * Returns:
05469  *  D3D_OK on success
05470  *  DDERR_INVALIDPARAMS if Mat is NULL
05471  *  For more details, see IWineD3DDevice::GetMaterial
05472  *
05473  *****************************************************************************/
05474 static HRESULT
05475 IDirect3DDeviceImpl_7_GetMaterial(IDirect3DDevice7 *iface,
05476                                   D3DMATERIAL7 *Mat)
05477 {
05478     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
05479     HRESULT hr;
05480 
05481     TRACE("iface %p, material %p.\n", iface, Mat);
05482 
05483     wined3d_mutex_lock();
05484     /* Note: D3DMATERIAL7 is compatible with struct wined3d_material. */
05485     hr = wined3d_device_get_material(This->wined3d_device, (struct wined3d_material *)Mat);
05486     wined3d_mutex_unlock();
05487 
05488     return hr_ddraw_from_wined3d(hr);
05489 }
05490 
05491 static HRESULT WINAPI
05492 IDirect3DDeviceImpl_7_GetMaterial_FPUSetup(IDirect3DDevice7 *iface,
05493                                   D3DMATERIAL7 *Mat)
05494 {
05495     return IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
05496 }
05497 
05498 static HRESULT WINAPI
05499 IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
05500                                   D3DMATERIAL7 *Mat)
05501 {
05502     HRESULT hr;
05503     WORD old_fpucw;
05504 
05505     old_fpucw = d3d_fpu_setup();
05506     hr = IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
05507     set_fpu_control_word(old_fpucw);
05508 
05509     return hr;
05510 }
05511 
05512 /*****************************************************************************
05513  * IDirect3DDevice7::SetLight
05514  *
05515  * Assigns a light to a light index, but doesn't activate it yet.
05516  *
05517  * Version 7, IDirect3DLight uses this method for older versions
05518  *
05519  * Params:
05520  *  LightIndex: The index of the new light
05521  *  Light: A D3DLIGHT7 structure describing the light
05522  *
05523  * Returns:
05524  *  D3D_OK on success
05525  *  For more details, see IWineD3DDevice::SetLight
05526  *
05527  *****************************************************************************/
05528 static HRESULT
05529 IDirect3DDeviceImpl_7_SetLight(IDirect3DDevice7 *iface,
05530                                DWORD LightIndex,
05531                                D3DLIGHT7 *Light)
05532 {
05533     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
05534     HRESULT hr;
05535 
05536     TRACE("iface %p, light_idx %u, light %p.\n", iface, LightIndex, Light);
05537 
05538     wined3d_mutex_lock();
05539     /* Note: D3DLIGHT7 is compatible with struct wined3d_light. */
05540     hr = wined3d_device_set_light(This->wined3d_device, LightIndex, (struct wined3d_light *)Light);
05541     wined3d_mutex_unlock();
05542 
05543     return hr_ddraw_from_wined3d(hr);
05544 }
05545 
05546 static HRESULT WINAPI
05547 IDirect3DDeviceImpl_7_SetLight_FPUSetup(IDirect3DDevice7 *iface,
05548                                DWORD LightIndex,
05549                                D3DLIGHT7 *Light)
05550 {
05551     return IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
05552 }
05553 
05554 static HRESULT WINAPI
05555 IDirect3DDeviceImpl_7_SetLight_FPUPreserve(IDirect3DDevice7 *iface,
05556                                DWORD LightIndex,
05557                                D3DLIGHT7 *Light)
05558 {
05559     HRESULT hr;
05560     WORD old_fpucw;
05561 
05562     old_fpucw = d3d_fpu_setup();
05563     hr = IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
05564     set_fpu_control_word(old_fpucw);
05565 
05566     return hr;
05567 }
05568 
05569 /*****************************************************************************
05570  * IDirect3DDevice7::GetLight
05571  *
05572  * Returns the light assigned to a light index
05573  *
05574  * Params:
05575  *  Light: Structure to write the light information to
05576  *
05577  * Returns:
05578  *  D3D_OK on success
05579  *  DDERR_INVALIDPARAMS if Light is NULL
05580  *  For details, see IWineD3DDevice::GetLight
05581  *
05582  *****************************************************************************/
05583 static HRESULT
05584 IDirect3DDeviceImpl_7_GetLight(IDirect3DDevice7 *iface,
05585                                DWORD LightIndex,
05586                                D3DLIGHT7 *Light)
05587 {
05588     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
05589     HRESULT rc;
05590 
05591     TRACE("iface %p, light_idx %u, light %p.\n", iface, LightIndex, Light);
05592 
05593     wined3d_mutex_lock();
05594     /* Note: D3DLIGHT7 is compatible with struct wined3d_light. */
05595     rc =  wined3d_device_get_light(This->wined3d_device, LightIndex, (struct wined3d_light *)Light);
05596     wined3d_mutex_unlock();
05597 
05598     /* Translate the result. WineD3D returns other values than D3D7 */
05599     return hr_ddraw_from_wined3d(rc);
05600 }
05601 
05602 static HRESULT WINAPI
05603 IDirect3DDeviceImpl_7_GetLight_FPUSetup(IDirect3DDevice7 *iface,
05604                                DWORD LightIndex,
05605                                D3DLIGHT7 *Light)
05606 {
05607     return IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
05608 }
05609 
05610 static HRESULT WINAPI
05611 IDirect3DDeviceImpl_7_GetLight_FPUPreserve(IDirect3DDevice7 *iface,
05612                                DWORD LightIndex,
05613                                D3DLIGHT7 *Light)
05614 {
05615     HRESULT hr;
05616     WORD old_fpucw;
05617 
05618     old_fpucw = d3d_fpu_setup();
05619     hr = IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
05620     set_fpu_control_word(old_fpucw);
05621 
05622     return hr;
05623 }
05624 
05625 /*****************************************************************************
05626  * IDirect3DDevice7::BeginStateBlock
05627  *
05628  * Begins recording to a stateblock
05629  *
05630  * Version 7
05631  *
05632  * Returns:
05633  *  D3D_OK on success
05634  *  For details see IWineD3DDevice::BeginStateBlock
05635  *
05636  *****************************************************************************/
05637 static HRESULT
05638 IDirect3DDeviceImpl_7_BeginStateBlock(IDirect3DDevice7 *iface)
05639 {
05640     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
05641     HRESULT hr;
05642 
05643     TRACE("iface %p.\n", iface);
05644 
05645     wined3d_mutex_lock();
05646     hr = wined3d_device_begin_stateblock(This->wined3d_device);
05647     wined3d_mutex_unlock();
05648 
05649     return hr_ddraw_from_wined3d(hr);
05650 }
05651 
05652 static HRESULT WINAPI
05653 IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup(IDirect3DDevice7 *iface)
05654 {
05655     return IDirect3DDeviceImpl_7_BeginStateBlock(iface);
05656 }
05657 
05658 static HRESULT WINAPI
05659 IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve(IDirect3DDevice7 *iface)
05660 {
05661     HRESULT hr;
05662     WORD old_fpucw;
05663 
05664     old_fpucw = d3d_fpu_setup();
05665     hr = IDirect3DDeviceImpl_7_BeginStateBlock(iface);
05666     set_fpu_control_word(old_fpucw);
05667 
05668     return hr;
05669 }
05670 
05671 /*****************************************************************************
05672  * IDirect3DDevice7::EndStateBlock
05673  *
05674  * Stops recording to a state block and returns the created stateblock
05675  * handle.
05676  *
05677  * Version 7
05678  *
05679  * Params:
05680  *  BlockHandle: Address to store the stateblock's handle to
05681  *
05682  * Returns:
05683  *  D3D_OK on success
05684  *  DDERR_INVALIDPARAMS if BlockHandle is NULL
05685  *  See IWineD3DDevice::EndStateBlock for more details
05686  *
05687  *****************************************************************************/
05688 static HRESULT
05689 IDirect3DDeviceImpl_7_EndStateBlock(IDirect3DDevice7 *iface,
05690                                     DWORD *BlockHandle)
05691 {
05692     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
05693     struct wined3d_stateblock *wined3d_sb;
05694     HRESULT hr;
05695     DWORD h;
05696 
05697     TRACE("iface %p, stateblock %p.\n", iface, BlockHandle);
05698 
05699     if(!BlockHandle)
05700     {
05701         WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
05702         return DDERR_INVALIDPARAMS;
05703     }
05704 
05705     wined3d_mutex_lock();
05706 
05707     hr = wined3d_device_end_stateblock(This->wined3d_device, &wined3d_sb);
05708     if (FAILED(hr))
05709     {
05710         WARN("Failed to end stateblock, hr %#x.\n", hr);
05711         wined3d_mutex_unlock();
05712         *BlockHandle = 0;
05713         return hr_ddraw_from_wined3d(hr);
05714     }
05715 
05716     h = ddraw_allocate_handle(&This->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
05717     if (h == DDRAW_INVALID_HANDLE)
05718     {
05719         ERR("Failed to allocate a stateblock handle.\n");
05720         wined3d_stateblock_decref(wined3d_sb);
05721         wined3d_mutex_unlock();
05722         *BlockHandle = 0;
05723         return DDERR_OUTOFMEMORY;
05724     }
05725 
05726     wined3d_mutex_unlock();
05727     *BlockHandle = h + 1;
05728 
05729     return hr_ddraw_from_wined3d(hr);
05730 }
05731 
05732 static HRESULT WINAPI
05733 IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup(IDirect3DDevice7 *iface,
05734                                     DWORD *BlockHandle)
05735 {
05736     return IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
05737 }
05738 
05739 static HRESULT WINAPI
05740 IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
05741                                     DWORD *BlockHandle)
05742 {
05743     HRESULT hr;
05744     WORD old_fpucw;
05745 
05746     old_fpucw = d3d_fpu_setup();
05747     hr = IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
05748     set_fpu_control_word(old_fpucw);
05749 
05750     return hr;
05751 }
05752 
05753 /*****************************************************************************
05754  * IDirect3DDevice7::PreLoad
05755  *
05756  * Allows the app to signal that a texture will be used soon, to allow
05757  * the Direct3DDevice to load it to the video card in the meantime.
05758  *
05759  * Version 7
05760  *
05761  * Params:
05762  *  Texture: The texture to preload
05763  *
05764  * Returns:
05765  *  D3D_OK on success
05766  *  DDERR_INVALIDPARAMS if Texture is NULL
05767  *  See IWineD3DSurface::PreLoad for details
05768  *
05769  *****************************************************************************/
05770 static HRESULT
05771 IDirect3DDeviceImpl_7_PreLoad(IDirect3DDevice7 *iface,
05772                               IDirectDrawSurface7 *Texture)
05773 {
05774     IDirectDrawSurfaceImpl *surf = unsafe_impl_from_IDirectDrawSurface7(Texture);
05775 
05776     TRACE("iface %p, texture %p.\n", iface, Texture);
05777 
05778     if(!Texture)
05779         return DDERR_INVALIDPARAMS;
05780 
05781     wined3d_mutex_lock();
05782     wined3d_surface_preload(surf->wined3d_surface);
05783     wined3d_mutex_unlock();
05784 
05785     return D3D_OK;
05786 }
05787 
05788 static HRESULT WINAPI
05789 IDirect3DDeviceImpl_7_PreLoad_FPUSetup(IDirect3DDevice7 *iface,
05790                               IDirectDrawSurface7 *Texture)
05791 {
05792     return IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
05793 }
05794 
05795 static HRESULT WINAPI
05796 IDirect3DDeviceImpl_7_PreLoad_FPUPreserve(IDirect3DDevice7 *iface,
05797                               IDirectDrawSurface7 *Texture)
05798 {
05799     HRESULT hr;
05800     WORD old_fpucw;
05801 
05802     old_fpucw = d3d_fpu_setup();
05803     hr = IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
05804     set_fpu_control_word(old_fpucw);
05805 
05806     return hr;
05807 }
05808 
05809 /*****************************************************************************
05810  * IDirect3DDevice7::ApplyStateBlock
05811  *
05812  * Activates the state stored in a state block handle.
05813  *
05814  * Params:
05815  *  BlockHandle: The stateblock handle to activate
05816  *
05817  * Returns:
05818  *  D3D_OK on success
05819  *  D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
05820  *
05821  *****************************************************************************/
05822 static HRESULT
05823 IDirect3DDeviceImpl_7_ApplyStateBlock(IDirect3DDevice7 *iface,
05824                                       DWORD BlockHandle)
05825 {
05826     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
05827     struct wined3d_stateblock *wined3d_sb;
05828     HRESULT hr;
05829 
05830     TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
05831 
05832     wined3d_mutex_lock();
05833     wined3d_sb = ddraw_get_object(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
05834     if (!wined3d_sb)
05835     {
05836         WARN("Invalid stateblock handle.\n");
05837         wined3d_mutex_unlock();
05838         return D3DERR_INVALIDSTATEBLOCK;
05839     }
05840 
05841     hr = wined3d_stateblock_apply(wined3d_sb);
05842     wined3d_mutex_unlock();
05843 
05844     return hr_ddraw_from_wined3d(hr);
05845 }
05846 
05847 static HRESULT WINAPI
05848 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup(IDirect3DDevice7 *iface,
05849                                       DWORD BlockHandle)
05850 {
05851     return IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
05852 }
05853 
05854 static HRESULT WINAPI
05855 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
05856                                       DWORD BlockHandle)
05857 {
05858     HRESULT hr;
05859     WORD old_fpucw;
05860 
05861     old_fpucw = d3d_fpu_setup();
05862     hr = IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
05863     set_fpu_control_word(old_fpucw);
05864 
05865     return hr;
05866 }
05867 
05868 /*****************************************************************************
05869  * IDirect3DDevice7::CaptureStateBlock
05870  *
05871  * Updates a stateblock's values to the values currently set for the device
05872  *
05873  * Version 7
05874  *
05875  * Params:
05876  *  BlockHandle: Stateblock to update
05877  *
05878  * Returns:
05879  *  D3D_OK on success
05880  *  D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
05881  *  See IWineD3DDevice::CaptureStateBlock for more details
05882  *
05883  *****************************************************************************/
05884 static HRESULT
05885 IDirect3DDeviceImpl_7_CaptureStateBlock(IDirect3DDevice7 *iface,
05886                                         DWORD BlockHandle)
05887 {
05888     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
05889     struct wined3d_stateblock *wined3d_sb;
05890     HRESULT hr;
05891 
05892     TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
05893 
05894     wined3d_mutex_lock();
05895     wined3d_sb = ddraw_get_object(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
05896     if (!wined3d_sb)
05897     {
05898         WARN("Invalid stateblock handle.\n");
05899         wined3d_mutex_unlock();
05900         return D3DERR_INVALIDSTATEBLOCK;
05901     }
05902 
05903     hr = wined3d_stateblock_capture(wined3d_sb);
05904     wined3d_mutex_unlock();
05905 
05906     return hr_ddraw_from_wined3d(hr);
05907 }
05908 
05909 static HRESULT WINAPI
05910 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup(IDirect3DDevice7 *iface,
05911                                         DWORD BlockHandle)
05912 {
05913     return IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
05914 }
05915 
05916 static HRESULT WINAPI
05917 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
05918                                         DWORD BlockHandle)
05919 {
05920     HRESULT hr;
05921     WORD old_fpucw;
05922 
05923     old_fpucw = d3d_fpu_setup();
05924     hr = IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
05925     set_fpu_control_word(old_fpucw);
05926 
05927     return hr;
05928 }
05929 
05930 /*****************************************************************************
05931  * IDirect3DDevice7::DeleteStateBlock
05932  *
05933  * Deletes a stateblock handle. This means releasing the WineD3DStateBlock
05934  *
05935  * Version 7
05936  *
05937  * Params:
05938  *  BlockHandle: Stateblock handle to delete
05939  *
05940  * Returns:
05941  *  D3D_OK on success
05942  *  D3DERR_INVALIDSTATEBLOCK if BlockHandle is 0
05943  *
05944  *****************************************************************************/
05945 static HRESULT
05946 IDirect3DDeviceImpl_7_DeleteStateBlock(IDirect3DDevice7 *iface,
05947                                        DWORD BlockHandle)
05948 {
05949     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
05950     struct wined3d_stateblock *wined3d_sb;
05951     ULONG ref;
05952 
05953     TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
05954 
05955     wined3d_mutex_lock();
05956 
05957     wined3d_sb = ddraw_free_handle(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
05958     if (!wined3d_sb)
05959     {
05960         WARN("Invalid stateblock handle.\n");
05961         wined3d_mutex_unlock();
05962         return D3DERR_INVALIDSTATEBLOCK;
05963     }
05964 
05965     if ((ref = wined3d_stateblock_decref(wined3d_sb)))
05966     {
05967         ERR("Something is still holding stateblock %p (refcount %u).\n", wined3d_sb, ref);
05968     }
05969 
05970     wined3d_mutex_unlock();
05971 
05972     return D3D_OK;
05973 }
05974 
05975 static HRESULT WINAPI
05976 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup(IDirect3DDevice7 *iface,
05977                                        DWORD BlockHandle)
05978 {
05979     return IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
05980 }
05981 
05982 static HRESULT WINAPI
05983 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
05984                                        DWORD BlockHandle)
05985 {
05986     HRESULT hr;
05987     WORD old_fpucw;
05988 
05989     old_fpucw = d3d_fpu_setup();
05990     hr = IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
05991     set_fpu_control_word(old_fpucw);
05992 
05993     return hr;
05994 }
05995 
05996 /*****************************************************************************
05997  * IDirect3DDevice7::CreateStateBlock
05998  *
05999  * Creates a new state block handle.
06000  *
06001  * Version 7
06002  *
06003  * Params:
06004  *  Type: The state block type
06005  *  BlockHandle: Address to write the created handle to
06006  *
06007  * Returns:
06008  *   D3D_OK on success
06009  *   DDERR_INVALIDPARAMS if BlockHandle is NULL
06010  *
06011  *****************************************************************************/
06012 static HRESULT
06013 IDirect3DDeviceImpl_7_CreateStateBlock(IDirect3DDevice7 *iface,
06014                                        D3DSTATEBLOCKTYPE Type,
06015                                        DWORD *BlockHandle)
06016 {
06017     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
06018     struct wined3d_stateblock *wined3d_sb;
06019     HRESULT hr;
06020     DWORD h;
06021 
06022     TRACE("iface %p, type %#x, stateblock %p.\n", iface, Type, BlockHandle);
06023 
06024     if(!BlockHandle)
06025     {
06026         WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
06027         return DDERR_INVALIDPARAMS;
06028     }
06029     if(Type != D3DSBT_ALL         && Type != D3DSBT_PIXELSTATE &&
06030        Type != D3DSBT_VERTEXSTATE                              ) {
06031         WARN("Unexpected stateblock type, returning DDERR_INVALIDPARAMS\n");
06032         return DDERR_INVALIDPARAMS;
06033     }
06034 
06035     wined3d_mutex_lock();
06036 
06037     /* The D3DSTATEBLOCKTYPE enum is fine here. */
06038     hr = wined3d_stateblock_create(This->wined3d_device, Type, &wined3d_sb);
06039     if (FAILED(hr))
06040     {
06041         WARN("Failed to create stateblock, hr %#x.\n", hr);
06042         wined3d_mutex_unlock();
06043         return hr_ddraw_from_wined3d(hr);
06044     }
06045 
06046     h = ddraw_allocate_handle(&This->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
06047     if (h == DDRAW_INVALID_HANDLE)
06048     {
06049         ERR("Failed to allocate stateblock handle.\n");
06050         wined3d_stateblock_decref(wined3d_sb);
06051         wined3d_mutex_unlock();
06052         return DDERR_OUTOFMEMORY;
06053     }
06054 
06055     *BlockHandle = h + 1;
06056     wined3d_mutex_unlock();
06057 
06058     return hr_ddraw_from_wined3d(hr);
06059 }
06060 
06061 static HRESULT WINAPI
06062 IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup(IDirect3DDevice7 *iface,
06063                                        D3DSTATEBLOCKTYPE Type,
06064                                        DWORD *BlockHandle)
06065 {
06066     return IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
06067 }
06068 
06069 static HRESULT WINAPI
06070 IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
06071                                        D3DSTATEBLOCKTYPE Type,
06072                                        DWORD *BlockHandle)
06073 {
06074     HRESULT hr;
06075     WORD old_fpucw;
06076 
06077     old_fpucw = d3d_fpu_setup();
06078     hr =IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
06079     set_fpu_control_word(old_fpucw);
06080 
06081     return hr;
06082 }
06083 
06084 /* Helper function for IDirect3DDeviceImpl_7_Load. */
06085 static BOOL is_mip_level_subset(IDirectDrawSurfaceImpl *dest,
06086                                 IDirectDrawSurfaceImpl *src)
06087 {
06088     IDirectDrawSurfaceImpl *src_level, *dest_level;
06089     IDirectDrawSurface7 *temp;
06090     DDSURFACEDESC2 ddsd;
06091     BOOL levelFound; /* at least one suitable sublevel in dest found */
06092 
06093     /* To satisfy "destination is mip level subset of source" criteria (regular texture counts as 1 level),
06094      * 1) there must be at least one mip level in destination that matched dimensions of some mip level in source and
06095      * 2) there must be no destination levels that don't match any levels in source. Otherwise it's INVALIDPARAMS.
06096      */
06097     levelFound = FALSE;
06098 
06099     src_level = src;
06100     dest_level = dest;
06101 
06102     for (;src_level && dest_level;)
06103     {
06104         if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
06105             src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
06106         {
06107             levelFound = TRUE;
06108 
06109             ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
06110             ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
06111             IDirectDrawSurface7_GetAttachedSurface(&dest_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
06112 
06113             if (dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
06114 
06115             dest_level = unsafe_impl_from_IDirectDrawSurface7(temp);
06116         }
06117 
06118         ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
06119         ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
06120         IDirectDrawSurface7_GetAttachedSurface(&src_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
06121 
06122         if (src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
06123 
06124         src_level = unsafe_impl_from_IDirectDrawSurface7(temp);
06125     }
06126 
06127     if (src_level && src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
06128     if (dest_level && dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
06129 
06130     return !dest_level && levelFound;
06131 }
06132 
06133 /* Helper function for IDirect3DDeviceImpl_7_Load. */
06134 static void copy_mipmap_chain(IDirect3DDeviceImpl *device,
06135                               IDirectDrawSurfaceImpl *dest,
06136                               IDirectDrawSurfaceImpl *src,
06137                               const POINT *DestPoint,
06138                               const RECT *SrcRect)
06139 {
06140     IDirectDrawSurfaceImpl *src_level, *dest_level;
06141     IDirectDrawSurface7 *temp;
06142     DDSURFACEDESC2 ddsd;
06143     POINT point;
06144     RECT src_rect;
06145     HRESULT hr;
06146     IDirectDrawPalette *pal = NULL, *pal_src = NULL;
06147     DWORD ckeyflag;
06148     DDCOLORKEY ddckey;
06149 
06150     /* Copy palette, if possible. */
06151     IDirectDrawSurface7_GetPalette(&src->IDirectDrawSurface7_iface, &pal_src);
06152     IDirectDrawSurface7_GetPalette(&dest->IDirectDrawSurface7_iface, &pal);
06153 
06154     if (pal_src != NULL && pal != NULL)
06155     {
06156         PALETTEENTRY palent[256];
06157 
06158         IDirectDrawPalette_GetEntries(pal_src, 0, 0, 256, palent);
06159         IDirectDrawPalette_SetEntries(pal, 0, 0, 256, palent);
06160     }
06161 
06162     if (pal) IDirectDrawPalette_Release(pal);
06163     if (pal_src) IDirectDrawPalette_Release(pal_src);
06164 
06165     /* Copy colorkeys, if present. */
06166     for (ckeyflag = DDCKEY_DESTBLT; ckeyflag <= DDCKEY_SRCOVERLAY; ckeyflag <<= 1)
06167     {
06168         hr = IDirectDrawSurface7_GetColorKey(&src->IDirectDrawSurface7_iface, ckeyflag, &ddckey);
06169 
06170         if (SUCCEEDED(hr))
06171         {
06172             IDirectDrawSurface7_SetColorKey(&dest->IDirectDrawSurface7_iface, ckeyflag, &ddckey);
06173         }
06174     }
06175 
06176     src_level = src;
06177     dest_level = dest;
06178 
06179     point = *DestPoint;
06180     src_rect = *SrcRect;
06181 
06182     for (;src_level && dest_level;)
06183     {
06184         if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
06185             src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
06186         {
06187             UINT src_w = src_rect.right - src_rect.left;
06188             UINT src_h = src_rect.bottom - src_rect.top;
06189             RECT dst_rect = {point.x, point.y, point.x + src_w, point.y + src_h};
06190 
06191             if (FAILED(hr = wined3d_surface_blt(dest_level->wined3d_surface, &dst_rect,
06192                     src_level->wined3d_surface, &src_rect, 0, NULL, WINED3D_TEXF_POINT)))
06193                 ERR("Blit failed, hr %#x.\n", hr);
06194 
06195             ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
06196             ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
06197             IDirectDrawSurface7_GetAttachedSurface(&dest_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
06198 
06199             if (dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
06200 
06201             dest_level = unsafe_impl_from_IDirectDrawSurface7(temp);
06202         }
06203 
06204         ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
06205         ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
06206         IDirectDrawSurface7_GetAttachedSurface(&src_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
06207 
06208         if (src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
06209 
06210         src_level = unsafe_impl_from_IDirectDrawSurface7(temp);
06211 
06212         point.x /= 2;
06213         point.y /= 2;
06214 
06215         src_rect.top /= 2;
06216         src_rect.left /= 2;
06217         src_rect.right = (src_rect.right + 1) / 2;
06218         src_rect.bottom = (src_rect.bottom + 1) / 2;
06219     }
06220 
06221     if (src_level && src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
06222     if (dest_level && dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
06223 }
06224 
06225 /*****************************************************************************
06226  * IDirect3DDevice7::Load
06227  *
06228  * Loads a rectangular area from the source into the destination texture.
06229  * It can also copy the source to the faces of a cubic environment map
06230  *
06231  * Version 7
06232  *
06233  * Params:
06234  *  DestTex: Destination texture
06235  *  DestPoint: Point in the destination where the source image should be
06236  *             written to
06237  *  SrcTex: Source texture
06238  *  SrcRect: Source rectangle
06239  *  Flags: Cubemap faces to load (DDSCAPS2_CUBEMAP_ALLFACES, DDSCAPS2_CUBEMAP_POSITIVEX,
06240  *          DDSCAPS2_CUBEMAP_NEGATIVEX, DDSCAPS2_CUBEMAP_POSITIVEY, DDSCAPS2_CUBEMAP_NEGATIVEY,
06241  *          DDSCAPS2_CUBEMAP_POSITIVEZ, DDSCAPS2_CUBEMAP_NEGATIVEZ)
06242  *
06243  * Returns:
06244  *  D3D_OK on success
06245  *  DDERR_INVALIDPARAMS if DestTex or SrcTex are NULL, broken coordinates or anything unexpected.
06246  *
06247  *
06248  *****************************************************************************/
06249 
06250 static HRESULT
06251 IDirect3DDeviceImpl_7_Load(IDirect3DDevice7 *iface,
06252                            IDirectDrawSurface7 *DestTex,
06253                            POINT *DestPoint,
06254                            IDirectDrawSurface7 *SrcTex,
06255                            RECT *SrcRect,
06256                            DWORD Flags)
06257 {
06258     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
06259     IDirectDrawSurfaceImpl *dest = unsafe_impl_from_IDirectDrawSurface7(DestTex);
06260     IDirectDrawSurfaceImpl *src = unsafe_impl_from_IDirectDrawSurface7(SrcTex);
06261     POINT destpoint;
06262     RECT srcrect;
06263 
06264     TRACE("iface %p, dst_texture %p, dst_pos %s, src_texture %p, src_rect %s, flags %#x.\n",
06265             iface, DestTex, wine_dbgstr_point(DestPoint), SrcTex, wine_dbgstr_rect(SrcRect), Flags);
06266 
06267     if( (!src) || (!dest) )
06268         return DDERR_INVALIDPARAMS;
06269 
06270     wined3d_mutex_lock();
06271 
06272     if (SrcRect) srcrect = *SrcRect;
06273     else
06274     {
06275         srcrect.left = srcrect.top = 0;
06276         srcrect.right = src->surface_desc.dwWidth;
06277         srcrect.bottom = src->surface_desc.dwHeight;
06278     }
06279 
06280     if (DestPoint) destpoint = *DestPoint;
06281     else
06282     {
06283         destpoint.x = destpoint.y = 0;
06284     }
06285     /* Check bad dimensions. DestPoint is validated against src, not dest, because
06286      * destination can be a subset of mip levels, in which case actual coordinates used
06287      * for it may be divided. If any dimension of dest is larger than source, it can't be
06288      * mip level subset, so an error can be returned early.
06289      */
06290     if (srcrect.left >= srcrect.right || srcrect.top >= srcrect.bottom ||
06291         srcrect.right > src->surface_desc.dwWidth ||
06292         srcrect.bottom > src->surface_desc.dwHeight ||
06293         destpoint.x + srcrect.right - srcrect.left > src->surface_desc.dwWidth ||
06294         destpoint.y + srcrect.bottom - srcrect.top > src->surface_desc.dwHeight ||
06295         dest->surface_desc.dwWidth > src->surface_desc.dwWidth ||
06296         dest->surface_desc.dwHeight > src->surface_desc.dwHeight)
06297     {
06298         wined3d_mutex_unlock();
06299         return DDERR_INVALIDPARAMS;
06300     }
06301 
06302     /* Must be top level surfaces. */
06303     if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL ||
06304         dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL)
06305     {
06306         wined3d_mutex_unlock();
06307         return DDERR_INVALIDPARAMS;
06308     }
06309 
06310     if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
06311     {
06312         DWORD src_face_flag, dest_face_flag;
06313         IDirectDrawSurfaceImpl *src_face, *dest_face;
06314         IDirectDrawSurface7 *temp;
06315         DDSURFACEDESC2 ddsd;
06316         int i;
06317 
06318         if (!(dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP))
06319         {
06320             wined3d_mutex_unlock();
06321             return DDERR_INVALIDPARAMS;
06322         }
06323 
06324         /* Iterate through cube faces 2 times. First time is just to check INVALIDPARAMS conditions, second
06325          * time it's actual surface loading. */
06326         for (i = 0; i < 2; i++)
06327         {
06328             dest_face = dest;
06329             src_face = src;
06330 
06331             for (;dest_face && src_face;)
06332             {
06333                 src_face_flag = src_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
06334                 dest_face_flag = dest_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
06335 
06336                 if (src_face_flag == dest_face_flag)
06337                 {
06338                     if (i == 0)
06339                     {
06340                         /* Destination mip levels must be subset of source mip levels. */
06341                         if (!is_mip_level_subset(dest_face, src_face))
06342                         {
06343                             wined3d_mutex_unlock();
06344                             return DDERR_INVALIDPARAMS;
06345                         }
06346                     }
06347                     else if (Flags & dest_face_flag)
06348                     {
06349                         copy_mipmap_chain(This, dest_face, src_face, &destpoint, &srcrect);
06350                     }
06351 
06352                     if (src_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
06353                     {
06354                         ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
06355                         ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (src_face_flag << 1);
06356                         IDirectDrawSurface7_GetAttachedSurface(&src->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
06357 
06358                         if (src_face != src) IDirectDrawSurface7_Release(&src_face->IDirectDrawSurface7_iface);
06359 
06360                         src_face = unsafe_impl_from_IDirectDrawSurface7(temp);
06361                     }
06362                     else
06363                     {
06364                         if (src_face != src) IDirectDrawSurface7_Release(&src_face->IDirectDrawSurface7_iface);
06365 
06366                         src_face = NULL;
06367                     }
06368                 }
06369 
06370                 if (dest_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
06371                 {
06372                     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
06373                     ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (dest_face_flag << 1);
06374                     IDirectDrawSurface7_GetAttachedSurface(&dest->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
06375 
06376                     if (dest_face != dest) IDirectDrawSurface7_Release(&dest_face->IDirectDrawSurface7_iface);
06377 
06378                     dest_face = unsafe_impl_from_IDirectDrawSurface7(temp);
06379                 }
06380                 else
06381                 {
06382                     if (dest_face != dest) IDirectDrawSurface7_Release(&dest_face->IDirectDrawSurface7_iface);
06383 
06384                     dest_face = NULL;
06385                 }
06386             }
06387 
06388             if (i == 0)
06389             {
06390                 /* Native returns error if src faces are not subset of dest faces. */
06391                 if (src_face)
06392                 {
06393                     wined3d_mutex_unlock();
06394                     return DDERR_INVALIDPARAMS;
06395                 }
06396             }
06397         }
06398 
06399         wined3d_mutex_unlock();
06400         return D3D_OK;
06401     }
06402     else if (dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
06403     {
06404         wined3d_mutex_unlock();
06405         return DDERR_INVALIDPARAMS;
06406     }
06407 
06408     /* Handle non cube map textures. */
06409 
06410     /* Destination mip levels must be subset of source mip levels. */
06411     if (!is_mip_level_subset(dest, src))
06412     {
06413         wined3d_mutex_unlock();
06414         return DDERR_INVALIDPARAMS;
06415     }
06416 
06417     copy_mipmap_chain(This, dest, src, &destpoint, &srcrect);
06418 
06419     wined3d_mutex_unlock();
06420 
06421     return D3D_OK;
06422 }
06423 
06424 static HRESULT WINAPI
06425 IDirect3DDeviceImpl_7_Load_FPUSetup(IDirect3DDevice7 *iface,
06426                            IDirectDrawSurface7 *DestTex,
06427                            POINT *DestPoint,
06428                            IDirectDrawSurface7 *SrcTex,
06429                            RECT *SrcRect,
06430                            DWORD Flags)
06431 {
06432     return IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
06433 }
06434 
06435 static HRESULT WINAPI
06436 IDirect3DDeviceImpl_7_Load_FPUPreserve(IDirect3DDevice7 *iface,
06437                            IDirectDrawSurface7 *DestTex,
06438                            POINT *DestPoint,
06439                            IDirectDrawSurface7 *SrcTex,
06440                            RECT *SrcRect,
06441                            DWORD Flags)
06442 {
06443     HRESULT hr;
06444     WORD old_fpucw;
06445 
06446     old_fpucw = d3d_fpu_setup();
06447     hr = IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
06448     set_fpu_control_word(old_fpucw);
06449 
06450     return hr;
06451 }
06452 
06453 /*****************************************************************************
06454  * IDirect3DDevice7::LightEnable
06455  *
06456  * Enables or disables a light
06457  *
06458  * Version 7, IDirect3DLight uses this method too.
06459  *
06460  * Params:
06461  *  LightIndex: The index of the light to enable / disable
06462  *  Enable: Enable or disable the light
06463  *
06464  * Returns:
06465  *  D3D_OK on success
06466  *  For more details, see IWineD3DDevice::SetLightEnable
06467  *
06468  *****************************************************************************/
06469 static HRESULT
06470 IDirect3DDeviceImpl_7_LightEnable(IDirect3DDevice7 *iface,
06471                                   DWORD LightIndex,
06472                                   BOOL Enable)
06473 {
06474     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
06475     HRESULT hr;
06476 
06477     TRACE("iface %p, light_idx %u, enabled %#x.\n", iface, LightIndex, Enable);
06478 
06479     wined3d_mutex_lock();
06480     hr = wined3d_device_set_light_enable(This->wined3d_device, LightIndex, Enable);
06481     wined3d_mutex_unlock();
06482 
06483     return hr_ddraw_from_wined3d(hr);
06484 }
06485 
06486 static HRESULT WINAPI
06487 IDirect3DDeviceImpl_7_LightEnable_FPUSetup(IDirect3DDevice7 *iface,
06488                                   DWORD LightIndex,
06489                                   BOOL Enable)
06490 {
06491     return IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
06492 }
06493 
06494 static HRESULT WINAPI
06495 IDirect3DDeviceImpl_7_LightEnable_FPUPreserve(IDirect3DDevice7 *iface,
06496                                   DWORD LightIndex,
06497                                   BOOL Enable)
06498 {
06499     HRESULT hr;
06500     WORD old_fpucw;
06501 
06502     old_fpucw = d3d_fpu_setup();
06503     hr = IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
06504     set_fpu_control_word(old_fpucw);
06505 
06506     return hr;
06507 }
06508 
06509 /*****************************************************************************
06510  * IDirect3DDevice7::GetLightEnable
06511  *
06512  * Retrieves if the light with the given index is enabled or not
06513  *
06514  * Version 7
06515  *
06516  * Params:
06517  *  LightIndex: Index of desired light
06518  *  Enable: Pointer to a BOOL which contains the result
06519  *
06520  * Returns:
06521  *  D3D_OK on success
06522  *  DDERR_INVALIDPARAMS if Enable is NULL
06523  *  See IWineD3DDevice::GetLightEnable for more details
06524  *
06525  *****************************************************************************/
06526 static HRESULT
06527 IDirect3DDeviceImpl_7_GetLightEnable(IDirect3DDevice7 *iface,
06528                                      DWORD LightIndex,
06529                                      BOOL* Enable)
06530 {
06531     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
06532     HRESULT hr;
06533 
06534     TRACE("iface %p, light_idx %u, enabled %p.\n", iface, LightIndex, Enable);
06535 
06536     if(!Enable)
06537         return DDERR_INVALIDPARAMS;
06538 
06539     wined3d_mutex_lock();
06540     hr = wined3d_device_get_light_enable(This->wined3d_device, LightIndex, Enable);
06541     wined3d_mutex_unlock();
06542 
06543     return hr_ddraw_from_wined3d(hr);
06544 }
06545 
06546 static HRESULT WINAPI
06547 IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup(IDirect3DDevice7 *iface,
06548                                      DWORD LightIndex,
06549                                      BOOL* Enable)
06550 {
06551     return IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
06552 }
06553 
06554 static HRESULT WINAPI
06555 IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve(IDirect3DDevice7 *iface,
06556                                      DWORD LightIndex,
06557                                      BOOL* Enable)
06558 {
06559     HRESULT hr;
06560     WORD old_fpucw;
06561 
06562     old_fpucw = d3d_fpu_setup();
06563     hr = IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
06564     set_fpu_control_word(old_fpucw);
06565 
06566     return hr;
06567 }
06568 
06569 /*****************************************************************************
06570  * IDirect3DDevice7::SetClipPlane
06571  *
06572  * Sets custom clipping plane
06573  *
06574  * Version 7
06575  *
06576  * Params:
06577  *  Index: The index of the clipping plane
06578  *  PlaneEquation: An equation defining the clipping plane
06579  *
06580  * Returns:
06581  *  D3D_OK on success
06582  *  DDERR_INVALIDPARAMS if PlaneEquation is NULL
06583  *  See IWineD3DDevice::SetClipPlane for more details
06584  *
06585  *****************************************************************************/
06586 static HRESULT
06587 IDirect3DDeviceImpl_7_SetClipPlane(IDirect3DDevice7 *iface,
06588                                    DWORD Index,
06589                                    D3DVALUE* PlaneEquation)
06590 {
06591     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
06592     HRESULT hr;
06593 
06594     TRACE("iface %p, idx %u, plane %p.\n", iface, Index, PlaneEquation);
06595 
06596     if(!PlaneEquation)
06597         return DDERR_INVALIDPARAMS;
06598 
06599     wined3d_mutex_lock();
06600     hr = wined3d_device_set_clip_plane(This->wined3d_device, Index, PlaneEquation);
06601     wined3d_mutex_unlock();
06602 
06603     return hr;
06604 }
06605 
06606 static HRESULT WINAPI
06607 IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
06608                                    DWORD Index,
06609                                    D3DVALUE* PlaneEquation)
06610 {
06611     return IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
06612 }
06613 
06614 static HRESULT WINAPI
06615 IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
06616                                    DWORD Index,
06617                                    D3DVALUE* PlaneEquation)
06618 {
06619     HRESULT hr;
06620     WORD old_fpucw;
06621 
06622     old_fpucw = d3d_fpu_setup();
06623     hr = IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
06624     set_fpu_control_word(old_fpucw);
06625 
06626     return hr;
06627 }
06628 
06629 /*****************************************************************************
06630  * IDirect3DDevice7::GetClipPlane
06631  *
06632  * Returns the clipping plane with a specific index
06633  *
06634  * Params:
06635  *  Index: The index of the desired plane
06636  *  PlaneEquation: Address to store the plane equation to
06637  *
06638  * Returns:
06639  *  D3D_OK on success
06640  *  DDERR_INVALIDPARAMS if PlaneEquation is NULL
06641  *  See IWineD3DDevice::GetClipPlane for more details
06642  *
06643  *****************************************************************************/
06644 static HRESULT
06645 IDirect3DDeviceImpl_7_GetClipPlane(IDirect3DDevice7 *iface,
06646                                    DWORD Index,
06647                                    D3DVALUE* PlaneEquation)
06648 {
06649     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
06650     HRESULT hr;
06651 
06652     TRACE("iface %p, idx %u, plane %p.\n", iface, Index, PlaneEquation);
06653 
06654     if(!PlaneEquation)
06655         return DDERR_INVALIDPARAMS;
06656 
06657     wined3d_mutex_lock();
06658     hr = wined3d_device_get_clip_plane(This->wined3d_device, Index, PlaneEquation);
06659     wined3d_mutex_unlock();
06660 
06661     return hr;
06662 }
06663 
06664 static HRESULT WINAPI
06665 IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
06666                                    DWORD Index,
06667                                    D3DVALUE* PlaneEquation)
06668 {
06669     return IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
06670 }
06671 
06672 static HRESULT WINAPI
06673 IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
06674                                    DWORD Index,
06675                                    D3DVALUE* PlaneEquation)
06676 {
06677     HRESULT hr;
06678     WORD old_fpucw;
06679 
06680     old_fpucw = d3d_fpu_setup();
06681     hr = IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
06682     set_fpu_control_word(old_fpucw);
06683 
06684     return hr;
06685 }
06686 
06687 /*****************************************************************************
06688  * IDirect3DDevice7::GetInfo
06689  *
06690  * Retrieves some information about the device. The DirectX sdk says that
06691  * this version returns S_FALSE for all retail builds of DirectX, that's what
06692  * this implementation does.
06693  *
06694  * Params:
06695  *  DevInfoID: Information type requested
06696  *  DevInfoStruct: Pointer to a structure to store the info to
06697  *  Size: Size of the structure
06698  *
06699  * Returns:
06700  *  S_FALSE, because it's a non-debug driver
06701  *
06702  *****************************************************************************/
06703 static HRESULT WINAPI
06704 IDirect3DDeviceImpl_7_GetInfo(IDirect3DDevice7 *iface,
06705                               DWORD DevInfoID,
06706                               void *DevInfoStruct,
06707                               DWORD Size)
06708 {
06709     TRACE("iface %p, info_id %#x, info %p, info_size %u.\n",
06710             iface, DevInfoID, DevInfoStruct, Size);
06711 
06712     if (TRACE_ON(ddraw))
06713     {
06714         TRACE(" info requested : ");
06715         switch (DevInfoID)
06716         {
06717             case D3DDEVINFOID_TEXTUREMANAGER: TRACE("D3DDEVINFOID_TEXTUREMANAGER\n"); break;
06718             case D3DDEVINFOID_D3DTEXTUREMANAGER: TRACE("D3DDEVINFOID_D3DTEXTUREMANAGER\n"); break;
06719             case D3DDEVINFOID_TEXTURING: TRACE("D3DDEVINFOID_TEXTURING\n"); break;
06720             default: ERR(" invalid flag !!!\n"); return DDERR_INVALIDPARAMS;
06721         }
06722     }
06723 
06724     return S_FALSE; /* According to MSDN, this is valid for a non-debug driver */
06725 }
06726 
06727 /* For performance optimization, devices created in FPUSETUP and FPUPRESERVE modes
06728  * have separate vtables. Simple functions where this doesn't matter like GetDirect3D
06729  * are not duplicated.
06730 
06731  * Device created with DDSCL_FPUSETUP (d3d7 default) - device methods assume that FPU
06732  * has already been setup for optimal d3d operation.
06733 
06734  * Device created with DDSCL_FPUPRESERVE - resets and restores FPU mode when necessary in
06735  * d3d calls (FPU may be in a mode non-suitable for d3d when the app calls d3d). Required
06736  * by Sacrifice (game). */
06737 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_setup_vtbl =
06738 {
06739     /*** IUnknown Methods ***/
06740     IDirect3DDeviceImpl_7_QueryInterface,
06741     IDirect3DDeviceImpl_7_AddRef,
06742     IDirect3DDeviceImpl_7_Release,
06743     /*** IDirect3DDevice7 ***/
06744     IDirect3DDeviceImpl_7_GetCaps_FPUSetup,
06745     IDirect3DDeviceImpl_7_EnumTextureFormats_FPUSetup,
06746     IDirect3DDeviceImpl_7_BeginScene_FPUSetup,
06747     IDirect3DDeviceImpl_7_EndScene_FPUSetup,
06748     IDirect3DDeviceImpl_7_GetDirect3D,
06749     IDirect3DDeviceImpl_7_SetRenderTarget_FPUSetup,
06750     IDirect3DDeviceImpl_7_GetRenderTarget,
06751     IDirect3DDeviceImpl_7_Clear_FPUSetup,
06752     IDirect3DDeviceImpl_7_SetTransform_FPUSetup,
06753     IDirect3DDeviceImpl_7_GetTransform_FPUSetup,
06754     IDirect3DDeviceImpl_7_SetViewport_FPUSetup,
06755     IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup,
06756     IDirect3DDeviceImpl_7_GetViewport_FPUSetup,
06757     IDirect3DDeviceImpl_7_SetMaterial_FPUSetup,
06758     IDirect3DDeviceImpl_7_GetMaterial_FPUSetup,
06759     IDirect3DDeviceImpl_7_SetLight_FPUSetup,
06760     IDirect3DDeviceImpl_7_GetLight_FPUSetup,
06761     IDirect3DDeviceImpl_7_SetRenderState_FPUSetup,
06762     IDirect3DDeviceImpl_7_GetRenderState_FPUSetup,
06763     IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup,
06764     IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup,
06765     IDirect3DDeviceImpl_7_PreLoad_FPUSetup,
06766     IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup,
06767     IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup,
06768     IDirect3DDeviceImpl_7_SetClipStatus,
06769     IDirect3DDeviceImpl_7_GetClipStatus,
06770     IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup,
06771     IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup,
06772     IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup,
06773     IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup,
06774     IDirect3DDeviceImpl_7_ComputeSphereVisibility,
06775     IDirect3DDeviceImpl_7_GetTexture_FPUSetup,
06776     IDirect3DDeviceImpl_7_SetTexture_FPUSetup,
06777     IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup,
06778     IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup,
06779     IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup,
06780     IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup,
06781     IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup,
06782     IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup,
06783     IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup,
06784     IDirect3DDeviceImpl_7_Load_FPUSetup,
06785     IDirect3DDeviceImpl_7_LightEnable_FPUSetup,
06786     IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup,
06787     IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup,
06788     IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup,
06789     IDirect3DDeviceImpl_7_GetInfo
06790 };
06791 
06792 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_preserve_vtbl =
06793 {
06794     /*** IUnknown Methods ***/
06795     IDirect3DDeviceImpl_7_QueryInterface,
06796     IDirect3DDeviceImpl_7_AddRef,
06797     IDirect3DDeviceImpl_7_Release,
06798     /*** IDirect3DDevice7 ***/
06799     IDirect3DDeviceImpl_7_GetCaps_FPUPreserve,
06800     IDirect3DDeviceImpl_7_EnumTextureFormats_FPUPreserve,
06801     IDirect3DDeviceImpl_7_BeginScene_FPUPreserve,
06802     IDirect3DDeviceImpl_7_EndScene_FPUPreserve,
06803     IDirect3DDeviceImpl_7_GetDirect3D,
06804     IDirect3DDeviceImpl_7_SetRenderTarget_FPUPreserve,
06805     IDirect3DDeviceImpl_7_GetRenderTarget,
06806     IDirect3DDeviceImpl_7_Clear_FPUPreserve,
06807     IDirect3DDeviceImpl_7_SetTransform_FPUPreserve,
06808     IDirect3DDeviceImpl_7_GetTransform_FPUPreserve,
06809     IDirect3DDeviceImpl_7_SetViewport_FPUPreserve,
06810     IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve,
06811     IDirect3DDeviceImpl_7_GetViewport_FPUPreserve,
06812     IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve,
06813     IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve,
06814     IDirect3DDeviceImpl_7_SetLight_FPUPreserve,
06815     IDirect3DDeviceImpl_7_GetLight_FPUPreserve,
06816     IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve,
06817     IDirect3DDeviceImpl_7_GetRenderState_FPUPreserve,
06818     IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve,
06819     IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve,
06820     IDirect3DDeviceImpl_7_PreLoad_FPUPreserve,
06821     IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve,
06822     IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve,
06823     IDirect3DDeviceImpl_7_SetClipStatus,
06824     IDirect3DDeviceImpl_7_GetClipStatus,
06825     IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve,
06826     IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve,
06827     IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve,
06828     IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve,
06829     IDirect3DDeviceImpl_7_ComputeSphereVisibility,
06830     IDirect3DDeviceImpl_7_GetTexture_FPUPreserve,
06831     IDirect3DDeviceImpl_7_SetTexture_FPUPreserve,
06832     IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve,
06833     IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve,
06834     IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve,
06835     IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve,
06836     IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve,
06837     IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve,
06838     IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve,
06839     IDirect3DDeviceImpl_7_Load_FPUPreserve,
06840     IDirect3DDeviceImpl_7_LightEnable_FPUPreserve,
06841     IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve,
06842     IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve,
06843     IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve,
06844     IDirect3DDeviceImpl_7_GetInfo
06845 };
06846 
06847 static const struct IDirect3DDevice3Vtbl d3d_device3_vtbl =
06848 {
06849     /*** IUnknown Methods ***/
06850     IDirect3DDeviceImpl_3_QueryInterface,
06851     IDirect3DDeviceImpl_3_AddRef,
06852     IDirect3DDeviceImpl_3_Release,
06853     /*** IDirect3DDevice3 ***/
06854     IDirect3DDeviceImpl_3_GetCaps,
06855     IDirect3DDeviceImpl_3_GetStats,
06856     IDirect3DDeviceImpl_3_AddViewport,
06857     IDirect3DDeviceImpl_3_DeleteViewport,
06858     IDirect3DDeviceImpl_3_NextViewport,
06859     IDirect3DDeviceImpl_3_EnumTextureFormats,
06860     IDirect3DDeviceImpl_3_BeginScene,
06861     IDirect3DDeviceImpl_3_EndScene,
06862     IDirect3DDeviceImpl_3_GetDirect3D,
06863     IDirect3DDeviceImpl_3_SetCurrentViewport,
06864     IDirect3DDeviceImpl_3_GetCurrentViewport,
06865     IDirect3DDeviceImpl_3_SetRenderTarget,
06866     IDirect3DDeviceImpl_3_GetRenderTarget,
06867     IDirect3DDeviceImpl_3_Begin,
06868     IDirect3DDeviceImpl_3_BeginIndexed,
06869     IDirect3DDeviceImpl_3_Vertex,
06870     IDirect3DDeviceImpl_3_Index,
06871     IDirect3DDeviceImpl_3_End,
06872     IDirect3DDeviceImpl_3_GetRenderState,
06873     IDirect3DDeviceImpl_3_SetRenderState,
06874     IDirect3DDeviceImpl_3_GetLightState,
06875     IDirect3DDeviceImpl_3_SetLightState,
06876     IDirect3DDeviceImpl_3_SetTransform,
06877     IDirect3DDeviceImpl_3_GetTransform,
06878     IDirect3DDeviceImpl_3_MultiplyTransform,
06879     IDirect3DDeviceImpl_3_DrawPrimitive,
06880     IDirect3DDeviceImpl_3_DrawIndexedPrimitive,
06881     IDirect3DDeviceImpl_3_SetClipStatus,
06882     IDirect3DDeviceImpl_3_GetClipStatus,
06883     IDirect3DDeviceImpl_3_DrawPrimitiveStrided,
06884     IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided,
06885     IDirect3DDeviceImpl_3_DrawPrimitiveVB,
06886     IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB,
06887     IDirect3DDeviceImpl_3_ComputeSphereVisibility,
06888     IDirect3DDeviceImpl_3_GetTexture,
06889     IDirect3DDeviceImpl_3_SetTexture,
06890     IDirect3DDeviceImpl_3_GetTextureStageState,
06891     IDirect3DDeviceImpl_3_SetTextureStageState,
06892     IDirect3DDeviceImpl_3_ValidateDevice
06893 };
06894 
06895 static const struct IDirect3DDevice2Vtbl d3d_device2_vtbl =
06896 {
06897     /*** IUnknown Methods ***/
06898     IDirect3DDeviceImpl_2_QueryInterface,
06899     IDirect3DDeviceImpl_2_AddRef,
06900     IDirect3DDeviceImpl_2_Release,
06901     /*** IDirect3DDevice2 ***/
06902     IDirect3DDeviceImpl_2_GetCaps,
06903     IDirect3DDeviceImpl_2_SwapTextureHandles,
06904     IDirect3DDeviceImpl_2_GetStats,
06905     IDirect3DDeviceImpl_2_AddViewport,
06906     IDirect3DDeviceImpl_2_DeleteViewport,
06907     IDirect3DDeviceImpl_2_NextViewport,
06908     IDirect3DDeviceImpl_2_EnumTextureFormats,
06909     IDirect3DDeviceImpl_2_BeginScene,
06910     IDirect3DDeviceImpl_2_EndScene,
06911     IDirect3DDeviceImpl_2_GetDirect3D,
06912     IDirect3DDeviceImpl_2_SetCurrentViewport,
06913     IDirect3DDeviceImpl_2_GetCurrentViewport,
06914     IDirect3DDeviceImpl_2_SetRenderTarget,
06915     IDirect3DDeviceImpl_2_GetRenderTarget,
06916     IDirect3DDeviceImpl_2_Begin,
06917     IDirect3DDeviceImpl_2_BeginIndexed,
06918     IDirect3DDeviceImpl_2_Vertex,
06919     IDirect3DDeviceImpl_2_Index,
06920     IDirect3DDeviceImpl_2_End,
06921     IDirect3DDeviceImpl_2_GetRenderState,
06922     IDirect3DDeviceImpl_2_SetRenderState,
06923     IDirect3DDeviceImpl_2_GetLightState,
06924     IDirect3DDeviceImpl_2_SetLightState,
06925     IDirect3DDeviceImpl_2_SetTransform,
06926     IDirect3DDeviceImpl_2_GetTransform,
06927     IDirect3DDeviceImpl_2_MultiplyTransform,
06928     IDirect3DDeviceImpl_2_DrawPrimitive,
06929     IDirect3DDeviceImpl_2_DrawIndexedPrimitive,
06930     IDirect3DDeviceImpl_2_SetClipStatus,
06931     IDirect3DDeviceImpl_2_GetClipStatus
06932 };
06933 
06934 static const struct IDirect3DDeviceVtbl d3d_device1_vtbl =
06935 {
06936     /*** IUnknown Methods ***/
06937     IDirect3DDeviceImpl_1_QueryInterface,
06938     IDirect3DDeviceImpl_1_AddRef,
06939     IDirect3DDeviceImpl_1_Release,
06940     /*** IDirect3DDevice1 ***/
06941     IDirect3DDeviceImpl_1_Initialize,
06942     IDirect3DDeviceImpl_1_GetCaps,
06943     IDirect3DDeviceImpl_1_SwapTextureHandles,
06944     IDirect3DDeviceImpl_1_CreateExecuteBuffer,
06945     IDirect3DDeviceImpl_1_GetStats,
06946     IDirect3DDeviceImpl_1_Execute,
06947     IDirect3DDeviceImpl_1_AddViewport,
06948     IDirect3DDeviceImpl_1_DeleteViewport,
06949     IDirect3DDeviceImpl_1_NextViewport,
06950     IDirect3DDeviceImpl_1_Pick,
06951     IDirect3DDeviceImpl_1_GetPickRecords,
06952     IDirect3DDeviceImpl_1_EnumTextureFormats,
06953     IDirect3DDeviceImpl_1_CreateMatrix,
06954     IDirect3DDeviceImpl_1_SetMatrix,
06955     IDirect3DDeviceImpl_1_GetMatrix,
06956     IDirect3DDeviceImpl_1_DeleteMatrix,
06957     IDirect3DDeviceImpl_1_BeginScene,
06958     IDirect3DDeviceImpl_1_EndScene,
06959     IDirect3DDeviceImpl_1_GetDirect3D
06960 };
06961 
06962 IDirect3DDeviceImpl *unsafe_impl_from_IDirect3DDevice7(IDirect3DDevice7 *iface)
06963 {
06964     if (!iface) return NULL;
06965     assert((iface->lpVtbl == &d3d_device7_fpu_preserve_vtbl) || (iface->lpVtbl == &d3d_device7_fpu_setup_vtbl));
06966     return CONTAINING_RECORD(iface, IDirect3DDeviceImpl, IDirect3DDevice7_iface);
06967 }
06968 
06969 IDirect3DDeviceImpl *unsafe_impl_from_IDirect3DDevice3(IDirect3DDevice3 *iface)
06970 {
06971     if (!iface) return NULL;
06972     assert(iface->lpVtbl == &d3d_device3_vtbl);
06973     return CONTAINING_RECORD(iface, IDirect3DDeviceImpl, IDirect3DDevice3_iface);
06974 }
06975 
06976 IDirect3DDeviceImpl *unsafe_impl_from_IDirect3DDevice2(IDirect3DDevice2 *iface)
06977 {
06978     if (!iface) return NULL;
06979     assert(iface->lpVtbl == &d3d_device2_vtbl);
06980     return CONTAINING_RECORD(iface, IDirect3DDeviceImpl, IDirect3DDevice2_iface);
06981 }
06982 
06983 IDirect3DDeviceImpl *unsafe_impl_from_IDirect3DDevice(IDirect3DDevice *iface)
06984 {
06985     if (!iface) return NULL;
06986     assert(iface->lpVtbl == &d3d_device1_vtbl);
06987     return CONTAINING_RECORD(iface, IDirect3DDeviceImpl, IDirect3DDevice_iface);
06988 }
06989 
06990 /*****************************************************************************
06991  * IDirect3DDeviceImpl_UpdateDepthStencil
06992  *
06993  * Checks the current render target for attached depth stencils and sets the
06994  * WineD3D depth stencil accordingly.
06995  *
06996  * Returns:
06997  *  The depth stencil state to set if creating the device
06998  *
06999  *****************************************************************************/
07000 enum wined3d_depth_buffer_type IDirect3DDeviceImpl_UpdateDepthStencil(IDirect3DDeviceImpl *This)
07001 {
07002     IDirectDrawSurface7 *depthStencil = NULL;
07003     IDirectDrawSurfaceImpl *dsi;
07004     static DDSCAPS2 depthcaps = { DDSCAPS_ZBUFFER, 0, 0, {0} };
07005 
07006     IDirectDrawSurface7_GetAttachedSurface(&This->target->IDirectDrawSurface7_iface, &depthcaps, &depthStencil);
07007     if(!depthStencil)
07008     {
07009         TRACE("Setting wined3d depth stencil to NULL\n");
07010         wined3d_device_set_depth_stencil(This->wined3d_device, NULL);
07011         return WINED3D_ZB_FALSE;
07012     }
07013 
07014     dsi = impl_from_IDirectDrawSurface7(depthStencil);
07015     TRACE("Setting wined3d depth stencil to %p (wined3d %p)\n", dsi, dsi->wined3d_surface);
07016     wined3d_device_set_depth_stencil(This->wined3d_device, dsi->wined3d_surface);
07017 
07018     IDirectDrawSurface7_Release(depthStencil);
07019     return WINED3D_ZB_TRUE;
07020 }
07021 
07022 HRESULT d3d_device_init(IDirect3DDeviceImpl *device, IDirectDrawImpl *ddraw, IDirectDrawSurfaceImpl *target)
07023 {
07024     static const D3DMATRIX ident =
07025     {
07026         1.0f, 0.0f, 0.0f, 0.0f,
07027         0.0f, 1.0f, 0.0f, 0.0f,
07028         0.0f, 0.0f, 1.0f, 0.0f,
07029         0.0f, 0.0f, 0.0f, 1.0f,
07030     };
07031     HRESULT hr;
07032 
07033     if (ddraw->cooperative_level & DDSCL_FPUPRESERVE)
07034         device->IDirect3DDevice7_iface.lpVtbl = &d3d_device7_fpu_preserve_vtbl;
07035     else
07036         device->IDirect3DDevice7_iface.lpVtbl = &d3d_device7_fpu_setup_vtbl;
07037 
07038     device->IDirect3DDevice3_iface.lpVtbl = &d3d_device3_vtbl;
07039     device->IDirect3DDevice2_iface.lpVtbl = &d3d_device2_vtbl;
07040     device->IDirect3DDevice_iface.lpVtbl = &d3d_device1_vtbl;
07041     device->ref = 1;
07042     device->ddraw = ddraw;
07043     device->target = target;
07044     list_init(&device->viewport_list);
07045 
07046     if (!ddraw_handle_table_init(&device->handle_table, 64))
07047     {
07048         ERR("Failed to initialize handle table.\n");
07049         return DDERR_OUTOFMEMORY;
07050     }
07051 
07052     device->legacyTextureBlending = FALSE;
07053     device->legacy_projection = ident;
07054     device->legacy_clipspace = ident;
07055 
07056     /* Create an index buffer, it's needed for indexed drawing */
07057     hr = wined3d_buffer_create_ib(ddraw->wined3d_device, 0x40000 /* Length. Don't know how long it should be */,
07058             WINED3DUSAGE_DYNAMIC /* Usage */, WINED3D_POOL_DEFAULT, NULL,
07059             &ddraw_null_wined3d_parent_ops, &device->indexbuffer);
07060     if (FAILED(hr))
07061     {
07062         ERR("Failed to create an index buffer, hr %#x.\n", hr);
07063         ddraw_handle_table_destroy(&device->handle_table);
07064         return hr;
07065     }
07066 
07067     /* This is for convenience. */
07068     device->wined3d_device = ddraw->wined3d_device;
07069     wined3d_device_incref(ddraw->wined3d_device);
07070 
07071     /* Render to the back buffer */
07072     hr = wined3d_device_set_render_target(ddraw->wined3d_device, 0, target->wined3d_surface, TRUE);
07073     if (FAILED(hr))
07074     {
07075         ERR("Failed to set render target, hr %#x.\n", hr);
07076         wined3d_buffer_decref(device->indexbuffer);
07077         ddraw_handle_table_destroy(&device->handle_table);
07078         return hr;
07079     }
07080 
07081     /* FIXME: This is broken. The target AddRef() makes some sense, because
07082      * we store a pointer during initialization, but then that's also where
07083      * the AddRef() should be. We don't store ddraw->d3d_target anywhere. */
07084     /* AddRef the render target. Also AddRef the render target from ddraw,
07085      * because if it is released before the app releases the D3D device, the
07086      * D3D capabilities of wined3d will be uninitialized, which has bad effects.
07087      *
07088      * In most cases, those surfaces are the same anyway, but this will simply
07089      * add another ref which is released when the device is destroyed. */
07090     IDirectDrawSurface7_AddRef(&target->IDirectDrawSurface7_iface);
07091 
07092     ddraw->d3ddevice = device;
07093 
07094     wined3d_device_set_render_state(ddraw->wined3d_device, WINED3D_RS_ZENABLE,
07095             IDirect3DDeviceImpl_UpdateDepthStencil(device));
07096 
07097     return D3D_OK;
07098 }

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