* Copyright 1998-2000 Lionel Ulmer
* Copyright 2000-2001 TransGaming Technologies Inc.
* Copyright 2006 Stefan Dösinger
+ * Copyright 2008 Denver Gingerich
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
#include "windef.h"
#include "winbase.h"
-#include "winnls.h"
#include "winerror.h"
#include "wingdi.h"
#include "wine/exception.h"
-#include "excpt.h"
#include "ddraw.h"
#include "d3d.h"
* method.
* The returned interface is AddRef()-ed before it's returned
*
- * Rules for QueryInterface:
- * http://msdn.microsoft.com/library/default.asp? \
- * url=/library/en-us/com/html/6db17ed8-06e4-4bae-bc26-113176cc7e0e.asp
- *
* Used for version 1, 2, 4 and 7
*
* Params:
TRACE("(%p)->(%s,%p)\n", This, debugstr_guid(refiid), obj);
+ /* Can change surface impl type */
+ EnterCriticalSection(&ddraw_cs);
+
/* According to COM docs, if the QueryInterface fails, obj should be set to NULL */
*obj = NULL;
if(!refiid)
+ {
+ LeaveCriticalSection(&ddraw_cs);
return DDERR_INVALIDPARAMS;
+ }
/* Check DirectDraw Interfaces */
if ( IsEqualGUID( &IID_IUnknown, refiid ) ||
else
{
ERR("(%p)->(%s, %p): No interface found\n", This, debugstr_guid(refiid), obj);
+ LeaveCriticalSection(&ddraw_cs);
return E_NOINTERFACE;
}
IUnknown_AddRef( (IUnknown *) *obj );
+ LeaveCriticalSection(&ddraw_cs);
return S_OK;
}
void
IDirectDrawImpl_Destroy(IDirectDrawImpl *This)
{
- int i;
-
- for(i = 0; i < This->numConvertedDecls; i++)
- {
- IWineD3DVertexDeclaration_Release(This->decls[i].decl);
- }
- HeapFree(GetProcessHeap(), 0, This->decls);
-
/* Clear the cooplevel to restore window and display mode */
IDirectDraw7_SetCooperativeLevel(ICOM_INTERFACE(This, IDirectDraw7),
NULL,
/* Unregister the window class */
UnregisterClassA(This->classname, 0);
- remove_ddraw_object(This);
+ EnterCriticalSection(&ddraw_cs);
+ list_remove(&This->ddraw_list_entry);
+ LeaveCriticalSection(&ddraw_cs);
/* Release the attached WineD3D stuff */
IWineD3DDevice_Release(This->wineD3DDevice);
*
* Unsure about these: DDSCL_FPUSETUP DDSCL_FPURESERVE
*
- * These seem not really imporant for wine
+ * These don't seem very important for wine:
* DDSCL_ALLOWREBOOT, DDSCL_NOWINDOWCHANGES, DDSCL_ALLOWMODEX
*
* Returns:
HWND window;
HRESULT hr;
- FIXME("(%p)->(%p,%08x)\n",This,hwnd,cooplevel);
+ TRACE("(%p)->(%p,%08x)\n",This,hwnd,cooplevel);
DDRAW_dump_cooperativelevel(cooplevel);
+ EnterCriticalSection(&ddraw_cs);
+
/* Get the old window */
hr = IWineD3DDevice_GetHWND(This->wineD3DDevice, &window);
if(hr != D3D_OK)
{
ERR("IWineD3DDevice::GetHWND failed, hr = %08x\n", hr);
+ LeaveCriticalSection(&ddraw_cs);
return hr;
}
DDSCL_EXCLUSIVE )))
{
TRACE("Incorrect cooplevel flags, returning DDERR_INVALIDPARAMS\n");
+ LeaveCriticalSection(&ddraw_cs);
return DDERR_INVALIDPARAMS;
}
DDSCL_FULLSCREEN ) )
{
TRACE("Called with incompatible flags, returning DDERR_INVALIDPARAMS\n");
+ LeaveCriticalSection(&ddraw_cs);
return DDERR_INVALIDPARAMS;
}
else if( (This->cooperative_level & DDSCL_FULLSCREEN) && window)
{
TRACE("Setting DDSCL_SETFOCUSWINDOW with an already set window, returning DDERR_HWNDALREADYSET\n");
+ LeaveCriticalSection(&ddraw_cs);
return DDERR_HWNDALREADYSET;
}
if(cooplevel & (DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE) )
{
TRACE("(%p) DDSCL_NORMAL is not compative with DDSCL_FULLSCREEN or DDSCL_EXCLUSIVE\n", This);
+ LeaveCriticalSection(&ddraw_cs);
return DDERR_INVALIDPARAMS;
}
if(!(cooplevel & DDSCL_EXCLUSIVE) )
{
TRACE("(%p) DDSCL_FULLSCREEN needs DDSCL_EXCLUSIVE\n", This);
+ LeaveCriticalSection(&ddraw_cs);
return DDERR_INVALIDPARAMS;
}
/* Need a HWND
}
*/
- /* Switch from normal to full screen mode? */
- if(This->cooperative_level & DDSCL_NORMAL)
- {
- This->cooperative_level &= ~DDSCL_NORMAL;
- IWineD3DDevice_SetFullscreen(This->wineD3DDevice,
- TRUE);
- }
+ This->cooperative_level &= ~DDSCL_NORMAL;
+ IWineD3DDevice_SetFullscreen(This->wineD3DDevice,
+ TRUE);
/* Don't override focus windows or private device windows */
if( hwnd &&
else if(cooplevel & DDSCL_EXCLUSIVE)
{
TRACE("(%p) DDSCL_EXCLUSIVE needs DDSCL_FULLSCREEN\n", This);
+ LeaveCriticalSection(&ddraw_cs);
return DDERR_INVALIDPARAMS;
}
if(cooplevel & DDSCL_MULTITHREADED && !(This->cooperative_level & DDSCL_MULTITHREADED))
{
- FIXME("DirectDraw is not thread safe yet\n");
-
/* Enable thread safety in wined3d */
IWineD3DDevice_SetMultithreaded(This->wineD3DDevice);
}
/* Store the cooperative_level */
This->cooperative_level |= cooplevel;
TRACE("SetCooperativeLevel retuning DD_OK\n");
+ LeaveCriticalSection(&ddraw_cs);
return DD_OK;
}
/*****************************************************************************
- * IDirectDraw7::SetDisplayMode
*
- * Sets the display screen resolution, color depth and refresh frequency
- * when in fullscreen mode (in theory).
- * Possible return values listed in the SDK suggest that this method fails
- * when not in fullscreen mode, but this is wrong. Windows 2000 happily sets
- * the display mode in DDSCL_NORMAL mode without an hwnd specified.
- * It seems to be valid to pass 0 for With and Height, this has to be tested
- * It could mean that the current video mode should be left as-is. (But why
- * call it then?)
+ * Helper function for SetDisplayMode and RestoreDisplayMode
*
- * Params:
- * Height, Width: Screen dimension
- * BPP: Color depth in Bits per pixel
- * Refreshrate: Screen refresh rate
- * Flags: Other stuff
- *
- * Returns
- * DD_OK on success
+ * Implements DirectDraw's SetDisplayMode, but ignores the value of
+ * ForceRefreshRate, since it is already handled by
+ * IDirectDrawImpl_SetDisplayMode. RestoreDisplayMode can use this function
+ * without worrying that ForceRefreshRate will override the refresh rate. For
+ * argument and return value documentation, see
+ * IDirectDrawImpl_SetDisplayMode.
*
*****************************************************************************/
-static HRESULT WINAPI
-IDirectDrawImpl_SetDisplayMode(IDirectDraw7 *iface,
- DWORD Width,
- DWORD Height,
- DWORD BPP,
- DWORD RefreshRate,
- DWORD Flags)
+static HRESULT
+IDirectDrawImpl_SetDisplayModeNoOverride(IDirectDraw7 *iface,
+ DWORD Width,
+ DWORD Height,
+ DWORD BPP,
+ DWORD RefreshRate,
+ DWORD Flags)
{
ICOM_THIS_FROM(IDirectDrawImpl, IDirectDraw7, iface);
WINED3DDISPLAYMODE Mode;
HRESULT hr;
TRACE("(%p)->(%d,%d,%d,%d,%x: Relay!\n", This, Width, Height, BPP, RefreshRate, Flags);
+ EnterCriticalSection(&ddraw_cs);
if( !Width || !Height )
{
ERR("Width=%d, Height=%d, what to do?\n", Width, Height);
/* It looks like Need for Speed Porsche Unleashed expects DD_OK here */
+ LeaveCriticalSection(&ddraw_cs);
return DD_OK;
}
case 15: Mode.Format = WINED3DFMT_X1R5G5B5; break;
case 16: Mode.Format = WINED3DFMT_R5G6B5; break;
case 24: Mode.Format = WINED3DFMT_R8G8B8; break;
- case 32: Mode.Format = WINED3DFMT_A8R8G8B8; break;
+ case 32: Mode.Format = WINED3DFMT_X8R8G8B8; break;
}
/* TODO: The possible return values from msdn suggest that
hr = IWineD3DDevice_SetDisplayMode(This->wineD3DDevice,
0, /* First swapchain */
&Mode);
+ LeaveCriticalSection(&ddraw_cs);
switch(hr)
{
- case WINED3DERR_NOTAVAILABLE: return DDERR_INVALIDMODE;
+ case WINED3DERR_NOTAVAILABLE: return DDERR_UNSUPPORTED;
default: return hr;
};
}
+/*****************************************************************************
+ * IDirectDraw7::SetDisplayMode
+ *
+ * Sets the display screen resolution, color depth and refresh frequency
+ * when in fullscreen mode (in theory).
+ * Possible return values listed in the SDK suggest that this method fails
+ * when not in fullscreen mode, but this is wrong. Windows 2000 happily sets
+ * the display mode in DDSCL_NORMAL mode without an hwnd specified.
+ * It seems to be valid to pass 0 for With and Height, this has to be tested
+ * It could mean that the current video mode should be left as-is. (But why
+ * call it then?)
+ *
+ * Params:
+ * Height, Width: Screen dimension
+ * BPP: Color depth in Bits per pixel
+ * Refreshrate: Screen refresh rate
+ * Flags: Other stuff
+ *
+ * Returns
+ * DD_OK on success
+ *
+ *****************************************************************************/
+static HRESULT WINAPI
+IDirectDrawImpl_SetDisplayMode(IDirectDraw7 *iface,
+ DWORD Width,
+ DWORD Height,
+ DWORD BPP,
+ DWORD RefreshRate,
+ DWORD Flags)
+{
+ if (force_refresh_rate != 0)
+ {
+ TRACE("ForceRefreshRate overriding passed-in refresh rate (%d Hz) to %d Hz\n", RefreshRate, force_refresh_rate);
+ RefreshRate = force_refresh_rate;
+ }
+
+ return IDirectDrawImpl_SetDisplayModeNoOverride(iface, Width, Height, BPP,
+ RefreshRate, Flags);
+}
+
/*****************************************************************************
* IDirectDraw7::RestoreDisplayMode
*
ICOM_THIS_FROM(IDirectDrawImpl, IDirectDraw7, iface);
TRACE("(%p)\n", This);
- return IDirectDraw7_SetDisplayMode(ICOM_INTERFACE(This, IDirectDraw7),
- This->orig_width,
- This->orig_height,
- This->orig_bpp,
- 0,
- 0);
+ return IDirectDrawImpl_SetDisplayModeNoOverride(ICOM_INTERFACE(This, IDirectDraw7),
+ This->orig_width,
+ This->orig_height,
+ This->orig_bpp,
+ 0,
+ 0);
}
/*****************************************************************************
DWORD Size;
TRACE("(%p)->(%p): Relay\n", This, DDSD);
+ EnterCriticalSection(&ddraw_cs);
/* This seems sane */
if(!DDSD)
{
+ LeaveCriticalSection(&ddraw_cs);
return DDERR_INVALIDPARAMS;
}
if( hr != D3D_OK )
{
ERR(" (%p) IWineD3DDevice::GetDisplayMode returned %08x\n", This, hr);
+ LeaveCriticalSection(&ddraw_cs);
return hr;
}
DDRAW_dump_surface_desc(DDSD);
}
+ LeaveCriticalSection(&ddraw_cs);
return DD_OK;
}
TRACE("(%p)->(%p)\n", This, status);
/* This looks sane, the MSDN suggests it too */
- if(!status) return DDERR_INVALIDPARAMS;
+ EnterCriticalSection(&ddraw_cs);
+ if(!status)
+ {
+ LeaveCriticalSection(&ddraw_cs);
+ return DDERR_INVALIDPARAMS;
+ }
*status = This->fake_vblank;
This->fake_vblank = !This->fake_vblank;
+ LeaveCriticalSection(&ddraw_cs);
return DD_OK;
}
{
TRACE("(%p) Asked for memory with description: ", This);
DDRAW_dump_DDSCAPS2(Caps);
- TRACE("\n");
}
+ EnterCriticalSection(&ddraw_cs);
/* Todo: System memory vs local video memory vs non-local video memory
* The MSDN also mentions differences between texture memory and other
* resources, but that's not important
*/
- if( (!total) && (!free) ) return DDERR_INVALIDPARAMS;
+ if( (!total) && (!free) )
+ {
+ LeaveCriticalSection(&ddraw_cs);
+ return DDERR_INVALIDPARAMS;
+ }
if(total) *total = This->total_vidmem;
if(free) *free = IWineD3DDevice_GetAvailableTextureMem(This->wineD3DDevice);
+ LeaveCriticalSection(&ddraw_cs);
return DD_OK;
}
WINED3DDISPLAYMODE Mode;
/* This function is called often, so print the fixme only once */
+ EnterCriticalSection(&ddraw_cs);
if(!hide)
{
FIXME("(%p)->(%p): Semi-Stub\n", This, Scanline);
if (This->cur_scanline >= Mode.Height + 20)
This->cur_scanline = 0;
+ LeaveCriticalSection(&ddraw_cs);
return DD_OK;
}
HRESULT hr;
TRACE("(%p)\n", This);
+ EnterCriticalSection(&ddraw_cs);
/* Description from MSDN:
* For fullscreen apps return DDERR_NOEXCLUSIVEMODE if the user switched
* away from the app with e.g. alt-tab. Windowed apps receive
case WINED3DERR_DEVICELOST:
if(This->cooperative_level & DDSCL_EXCLUSIVE)
{
+ LeaveCriticalSection(&ddraw_cs);
return DDERR_NOEXCLUSIVEMODE;
}
else
{
+ LeaveCriticalSection(&ddraw_cs);
return DDERR_EXCLUSIVEMODEALREADYSET;
}
case WINED3DERR_DEVICENOTRESET:
+ LeaveCriticalSection(&ddraw_cs);
return DD_OK;
case WINED3D_OK:
+ LeaveCriticalSection(&ddraw_cs);
return DD_OK;
case WINED3DERR_DRIVERINTERNALERROR:
" returning DD_OK\n", This, hr);
}
+ LeaveCriticalSection(&ddraw_cs);
return DD_OK;
}
/* Get the back buffer from the wineD3DDevice and search its
* attached surfaces for the front buffer
*/
+ EnterCriticalSection(&ddraw_cs);
hr = IWineD3DDevice_GetBackBuffer(This->wineD3DDevice,
0, /* SwapChain */
0, /* first back buffer*/
(!Surf) )
{
ERR("IWineD3DDevice::GetBackBuffer failed\n");
+ LeaveCriticalSection(&ddraw_cs);
return DDERR_NOTFOUND;
}
}
/* The AddRef is OK this time */
+ LeaveCriticalSection(&ddraw_cs);
return hr;
}
TRACE("(%p)->(%p,%p,%p): Relay\n", This, DDSD, Context, cb);
+ EnterCriticalSection(&ddraw_cs);
/* This looks sane */
- if(!cb) return DDERR_INVALIDPARAMS;
+ if(!cb)
+ {
+ LeaveCriticalSection(&ddraw_cs);
+ return DDERR_INVALIDPARAMS;
+ }
if(DDSD)
{
PixelFormat_WineD3DtoDD(&callback_sd.u4.ddpfPixelFormat, mode.Format);
- TRACE("Enumerating %dx%d@%d\n", callback_sd.dwWidth, callback_sd.dwHeight, callback_sd.u4.ddpfPixelFormat.u1.dwRGBBitCount);
+ /* Calc pitch and DWORD align like MSDN says */
+ callback_sd.u1.lPitch = (callback_sd.u4.ddpfPixelFormat.u1.dwRGBBitCount / 8) * mode.Width;
+ callback_sd.u1.lPitch = (callback_sd.u1.lPitch + 3) & ~3;
+
+ TRACE("Enumerating %dx%dx%d @%d\n", callback_sd.dwWidth, callback_sd.dwHeight, callback_sd.u4.ddpfPixelFormat.u1.dwRGBBitCount,
+ callback_sd.u2.dwRefreshRate);
if(cb(&callback_sd, Context) == DDENUMRET_CANCEL)
{
TRACE("Application asked to terminate the enumeration\n");
+ LeaveCriticalSection(&ddraw_cs);
return DD_OK;
}
}
}
TRACE("End of enumeration\n");
+ LeaveCriticalSection(&ddraw_cs);
return DD_OK;
}
IWineD3DSurface *wineD3DSurface;
HRESULT hr;
void *tmp;
+ IWineD3DClipper *clipper = NULL;
WINED3DSURFACE_DESC Desc;
WINED3DFORMAT Format;
IWineD3DSurface_Release(wineD3DSurface);
}
+ /* get the clipper */
+ IWineD3DSurface_GetClipper(wineD3DSurface, &clipper);
/* Get the surface properties */
Desc.Format = &Format;
if(hr != D3D_OK)
return hr;
+ IWineD3DSurface_SetClipper(surfImpl->WineD3DSurface, clipper);
+
/* Update the IParent if it exists */
if(parImpl)
{
surfImpl->ImplType = This->ImplType;
+ if(clipper)
+ {
+ IWineD3DClipper_Release(clipper);
+ }
return DDENUMRET_OK;
}
* Format: The requested format
* Usage, Pool: D3DUSAGE and D3DPOOL of the surface
* level: The mipmap level
+ * Face: The cube map face type
* Surface: Pointer to pass the created surface back at
* SharedHandle: NULL
*
UINT Width, UINT Height,
WINED3DFORMAT Format,
DWORD Usage, WINED3DPOOL Pool, UINT level,
+ WINED3DCUBEMAP_FACES Face,
IWineD3DSurface **Surface,
HANDLE *SharedHandle)
{
ICOM_THIS_FROM(IDirectDrawImpl, IDirectDraw7, device);
- IDirectDrawSurfaceImpl *surf = This->tex_root;
- int i;
- TRACE("(%p) call back. surf=%p\n", device, surf);
+ IDirectDrawSurfaceImpl *surf = NULL;
+ int i = 0;
+ DDSCAPS2 searchcaps = This->tex_root->surface_desc.ddsCaps;
+ TRACE("(%p) call back. surf=%p. Face %d level %d\n", device, This->tex_root, Face, level);
+
+ searchcaps.dwCaps2 &= ~DDSCAPS2_CUBEMAP_ALLFACES;
+ switch(Face)
+ {
+ case WINED3DCUBEMAP_FACE_POSITIVE_X:
+ TRACE("Asked for positive x\n");
+ if(searchcaps.dwCaps2 & DDSCAPS2_CUBEMAP) {
+ searchcaps.dwCaps2 |= DDSCAPS2_CUBEMAP_POSITIVEX;
+ }
+ surf = This->tex_root; break;
+ case WINED3DCUBEMAP_FACE_NEGATIVE_X:
+ TRACE("Asked for negative x\n");
+ searchcaps.dwCaps2 |= DDSCAPS2_CUBEMAP_NEGATIVEX; break;
+ case WINED3DCUBEMAP_FACE_POSITIVE_Y:
+ TRACE("Asked for positive y\n");
+ searchcaps.dwCaps2 |= DDSCAPS2_CUBEMAP_POSITIVEY; break;
+ case WINED3DCUBEMAP_FACE_NEGATIVE_Y:
+ TRACE("Asked for negative y\n");
+ searchcaps.dwCaps2 |= DDSCAPS2_CUBEMAP_NEGATIVEY; break;
+ case WINED3DCUBEMAP_FACE_POSITIVE_Z:
+ TRACE("Asked for positive z\n");
+ searchcaps.dwCaps2 |= DDSCAPS2_CUBEMAP_POSITIVEZ; break;
+ case WINED3DCUBEMAP_FACE_NEGATIVE_Z:
+ TRACE("Asked for negative z\n");
+ searchcaps.dwCaps2 |= DDSCAPS2_CUBEMAP_NEGATIVEZ; break;
+ default: {ERR("Unexpected cube face\n");} /* Stupid compiler */
+ }
+
+ if(!surf)
+ {
+ IDirectDrawSurface7 *attached;
+ IDirectDrawSurface7_GetAttachedSurface(ICOM_INTERFACE(This->tex_root, IDirectDrawSurface7),
+ &searchcaps,
+ &attached);
+ surf = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, attached);
+ IDirectDrawSurface7_Release(attached);
+ }
+ if(!surf) ERR("root search surface not found\n");
/* Find the wanted mipmap. There are enough mipmaps in the chain */
- for(i = 0; i < level; i++)
- surf = surf->next_complex;
+ while(i < level)
+ {
+ IDirectDrawSurface7 *attached;
+ IDirectDrawSurface7_GetAttachedSurface(ICOM_INTERFACE(surf, IDirectDrawSurface7),
+ &searchcaps,
+ &attached);
+ if(!attached) ERR("Surface not found\n");
+ surf = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, attached);
+ IDirectDrawSurface7_Release(attached);
+ i++;
+ }
/* Return the surface */
*Surface = surf->WineD3DSurface;
IUnknown* surfaceParent;
TRACE("(%p) call back\n", pSurface);
- IWineD3DSurface_GetParent(pSurface, (IUnknown **) &surfaceParent);
+ IWineD3DSurface_GetParent(pSurface, &surfaceParent);
IUnknown_Release(surfaceParent);
return IUnknown_Release(surfaceParent);
}
IDirectDrawImpl_RecreateAllSurfaces(This);
TRACE("(%p) Done recreating all surfaces\n", This);
}
- else if(This->ImplType != SURFACE_OPENGL)
+ else if(This->ImplType != SURFACE_OPENGL && pDDSD->ddsCaps.dwCaps & DDSCAPS_3DDEVICE)
{
WARN("The application requests a 3D capable surface, but a non-opengl surface was set in the registry\n");
/* Do not fail surface creation, only fail 3D device creation */
Usage |= WINED3DUSAGE_RENDERTARGET;
pDDSD->ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY |
- DDSCAPS_VISIBLE |
- DDSCAPS_LOCALVIDMEM;
+ DDSCAPS_VISIBLE;
}
if (pDDSD->ddsCaps.dwCaps & (DDSCAPS_OVERLAY))
{
Usage |= WINED3DUSAGE_OVERLAY;
}
- if(This->depthstencil)
+ if(This->depthstencil || (pDDSD->ddsCaps.dwCaps & DDSCAPS_ZBUFFER) )
{
/* The depth stencil creation callback sets this flag.
* Set the WineD3D usage to let it know that it's a depth
else if(pDDSD->ddsCaps.dwCaps2 & DDSCAPS2_TEXTUREMANAGE)
{
Pool = WINED3DPOOL_MANAGED;
+ /* Managed textures have the system memory flag set */
+ pDDSD->ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
+ }
+ else if(pDDSD->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)
+ {
+ /* Videomemory adds localvidmem, this is mutually exclusive with systemmemory
+ * and texturemanage
+ */
+ pDDSD->ddsCaps.dwCaps |= DDSCAPS_LOCALVIDMEM;
}
Format = PixelFormat_DD2WineD3D(&pDDSD->u4.ddpfPixelFormat);
(*ppSurf)->next_attached = NULL;
(*ppSurf)->first_attached = *ppSurf;
- (*ppSurf)->next_complex = NULL;
- (*ppSurf)->first_complex = *ppSurf;
-
/* Needed to re-create the surface on an implementation change */
(*ppSurf)->ImplType = ImplType;
/* Anno 1602 stores the pitch right after surface creation, so make sure it's there.
* I can't LockRect() the surface here because if OpenGL surfaces are in use, the
- * WineD3DDevice might not be useable for 3D yet, so an extra method was created
+ * WineD3DDevice might not be usable for 3D yet, so an extra method was created.
+ * TODO: Test other fourcc formats
*/
- (*ppSurf)->surface_desc.dwFlags |= DDSD_PITCH;
- (*ppSurf)->surface_desc.u1.lPitch = IWineD3DSurface_GetPitch((*ppSurf)->WineD3DSurface);
+ if(Format == WINED3DFMT_DXT1 || Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3 ||
+ Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5)
+ {
+ (*ppSurf)->surface_desc.dwFlags |= DDSD_LINEARSIZE;
+ if(Format == WINED3DFMT_DXT1)
+ {
+ (*ppSurf)->surface_desc.u1.dwLinearSize = max(4, Width) * max(4, Height) / 2;
+ }
+ else
+ {
+ (*ppSurf)->surface_desc.u1.dwLinearSize = max(4, Width) * max(4, Height);
+ }
+ }
+ else
+ {
+ (*ppSurf)->surface_desc.dwFlags |= DDSD_PITCH;
+ (*ppSurf)->surface_desc.u1.lPitch = IWineD3DSurface_GetPitch((*ppSurf)->WineD3DSurface);
+ }
/* Application passed a color key? Set it! */
if(pDDSD->dwFlags & DDSD_CKDESTOVERLAY)
return DD_OK;
}
+/*****************************************************************************
+ * CreateAdditionalSurfaces
+ *
+ * Creates a new mipmap chain.
+ *
+ * Params:
+ * root: Root surface to attach the newly created chain to
+ * count: number of surfaces to create
+ * DDSD: Description of the surface. Intentionally not a pointer to avoid side
+ * effects on the caller
+ * CubeFaceRoot: Whether the new surface is a root of a cube map face. This
+ * creates an additional surface without the mipmapping flags
+ *
+ *****************************************************************************/
+static HRESULT
+CreateAdditionalSurfaces(IDirectDrawImpl *This,
+ IDirectDrawSurfaceImpl *root,
+ UINT count,
+ DDSURFACEDESC2 DDSD,
+ BOOL CubeFaceRoot)
+{
+ UINT i, j, level = 0;
+ HRESULT hr;
+ IDirectDrawSurfaceImpl *last = root;
+
+ for(i = 0; i < count; i++)
+ {
+ IDirectDrawSurfaceImpl *object2 = NULL;
+
+ /* increase the mipmap level, but only if a mipmap is created
+ * In this case, also halve the size
+ */
+ if(DDSD.ddsCaps.dwCaps & DDSCAPS_MIPMAP && !CubeFaceRoot)
+ {
+ level++;
+ if(DDSD.dwWidth > 1) DDSD.dwWidth /= 2;
+ if(DDSD.dwHeight > 1) DDSD.dwHeight /= 2;
+ /* Set the mipmap sublevel flag according to msdn */
+ DDSD.ddsCaps.dwCaps2 |= DDSCAPS2_MIPMAPSUBLEVEL;
+ }
+ else
+ {
+ DDSD.ddsCaps.dwCaps2 &= ~DDSCAPS2_MIPMAPSUBLEVEL;
+ }
+ CubeFaceRoot = FALSE;
+
+ hr = IDirectDrawImpl_CreateNewSurface(This,
+ &DDSD,
+ &object2,
+ level);
+ if(hr != DD_OK)
+ {
+ return hr;
+ }
+
+ /* Add the new surface to the complex attachment array */
+ for(j = 0; j < MAX_COMPLEX_ATTACHED; j++)
+ {
+ if(last->complex_array[j]) continue;
+ last->complex_array[j] = object2;
+ break;
+ }
+ last = object2;
+
+ /* Remove the (possible) back buffer cap from the new surface description,
+ * because only one surface in the flipping chain is a back buffer, one
+ * is a front buffer, the others are just primary surfaces.
+ */
+ DDSD.ddsCaps.dwCaps &= ~DDSCAPS_BACKBUFFER;
+ }
+ return DD_OK;
+}
/*****************************************************************************
* IDirectDraw7::CreateSurface
* the WineD3DSurface when the ddraw surface is destroyed.
*
* However, for all surfaces which can be in a container in WineD3D,
- * we have to do this. These surfaces are ususally complex surfaces,
+ * we have to do this. These surfaces are usually complex surfaces,
* so this concerns primary surfaces with a front and a back buffer,
* and textures.
*
* |------------------------| |-----------------|
- * | DDraw surface | | Containter |
+ * | DDraw surface | | Container |
* | | | |
* | Child |<------------->| Parent |
* | Texture |<------------->| |
ICOM_THIS_FROM(IDirectDrawImpl, IDirectDraw7, iface);
IDirectDrawSurfaceImpl *object = NULL;
HRESULT hr;
- LONG extra_surfaces = 0, i;
+ LONG extra_surfaces = 0;
DDSURFACEDESC2 desc2;
- UINT level = 0;
WINED3DDISPLAYMODE Mode;
TRACE("(%p)->(%p,%p,%p)\n", This, DDSD, Surf, UnkOuter);
TRACE(" (%p) Requesting surface desc :\n", This);
DDRAW_dump_surface_desc(DDSD);
}
+ EnterCriticalSection(&ddraw_cs);
if (UnkOuter != NULL)
{
FIXME("(%p) : outer != NULL?\n", This);
+ LeaveCriticalSection(&ddraw_cs);
return CLASS_E_NOAGGREGATION; /* unchecked */
}
+ if (Surf == NULL)
+ {
+ FIXME("(%p) You want to get back a surface? Don't give NULL ptrs!\n", This);
+ LeaveCriticalSection(&ddraw_cs);
+ return E_POINTER; /* unchecked */
+ }
+
if (!(DDSD->dwFlags & DDSD_CAPS))
{
/* DVIDEO.DLL does forget the DDSD_CAPS flag ... *sigh* */
{
TRACE("(%p): Attempt to create a flipable primary surface without DDSCL_EXCLUSIVE set\n", This);
*Surf = NULL;
+ LeaveCriticalSection(&ddraw_cs);
return DDERR_NOEXCLUSIVEMODE;
}
- if (Surf == NULL)
+ if(DDSD->ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER | DDSCAPS_BACKBUFFER)) {
+ WARN("Application tried to create an explicit front or back buffer\n");
+ LeaveCriticalSection(&ddraw_cs);
+ return DDERR_INVALIDCAPS;
+ }
+ /* Check cube maps but only if the size includes them */
+ if (DDSD->dwSize >= sizeof(DDSURFACEDESC2))
{
- FIXME("(%p) You want to get back a surface? Don't give NULL ptrs!\n", This);
- return E_POINTER; /* unchecked */
+ if(DDSD->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES &&
+ !(DDSD->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP))
+ {
+ WARN("Cube map faces requested without cube map flag\n");
+ LeaveCriticalSection(&ddraw_cs);
+ return DDERR_INVALIDCAPS;
+ }
+ if(DDSD->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP &&
+ (DDSD->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES) == 0)
+ {
+ WARN("Cube map without faces requested\n");
+ LeaveCriticalSection(&ddraw_cs);
+ return DDERR_INVALIDPARAMS;
+ }
+
+ /* Quick tests confirm those can be created, but we don't do that yet */
+ if(DDSD->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP &&
+ (DDSD->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES) != DDSCAPS2_CUBEMAP_ALLFACES)
+ {
+ FIXME("Partial cube maps not supported yet\n");
+ }
}
/* According to the msdn this flag is ignored by CreateSurface */
}
}
- /* No Width or no Height? Use the current window size or
- * the original screen size
+ /* No Width or no Height? Use the original screen size
*/
if(!(desc2.dwFlags & DDSD_WIDTH) ||
!(desc2.dwFlags & DDSD_HEIGHT) )
{
- HWND window;
+ /* Invalid for non-render targets */
+ if(!(desc2.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE))
+ {
+ WARN("Creating a non-Primary surface without Width or Height info, returning DDERR_INVALIDPARAMS\n");
+ *Surf = NULL;
+ LeaveCriticalSection(&ddraw_cs);
+ return DDERR_INVALIDPARAMS;
+ }
- /* Fallback: From WineD3D / original mode */
desc2.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT;
desc2.dwWidth = Mode.Width;
desc2.dwHeight = Mode.Height;
-
- hr = IWineD3DDevice_GetHWND(This->wineD3DDevice,
- &window);
- if( (hr == D3D_OK) && (window != 0) )
- {
- RECT rect;
- if(GetWindowRect(window, &rect) )
- {
- /* This is a hack until I find a better solution */
- if( (rect.right - rect.left) <= 1 ||
- (rect.bottom - rect.top) <= 1 )
- {
- FIXME("Wanted to get surface dimensions from window %p, but it has only "
- "a size of %dx%d. Using full screen dimensions\n",
- window, rect.right - rect.left, rect.bottom - rect.top);
- }
- else
- {
- /* Not sure if this is correct */
- desc2.dwWidth = rect.right - rect.left;
- desc2.dwHeight = rect.bottom - rect.top;
- TRACE("Using window %p's dimensions: %dx%d\n", window, desc2.dwWidth, desc2.dwHeight);
- }
- }
- }
}
/* Mipmap count fixes */
{
if(desc2.dwFlags & DDSD_MIPMAPCOUNT)
{
- /* Mipmap count is given, nothing to do */
+ /* Mipmap count is given, should not be 0 */
+ if( desc2.u2.dwMipMapCount == 0 )
+ {
+ LeaveCriticalSection(&ddraw_cs);
+ return DDERR_INVALIDPARAMS;
+ }
}
else
{
desc2.ddsCaps.dwCaps |= DDSCAPS_FRONTBUFFER;
}
+ /* The root surface in a cube map is positive x */
+ if(desc2.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
+ {
+ desc2.ddsCaps.dwCaps2 &= ~DDSCAPS2_CUBEMAP_ALLFACES;
+ desc2.ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP_POSITIVEX;
+ }
+
/* Create the first surface */
hr = IDirectDrawImpl_CreateNewSurface(This, &desc2, &object, 0);
if( hr != DD_OK)
{
ERR("IDirectDrawImpl_CreateNewSurface failed with %08x\n", hr);
+ LeaveCriticalSection(&ddraw_cs);
return hr;
}
+ object->is_complex_root = TRUE;
*Surf = ICOM_INTERFACE(object, IDirectDrawSurface7);
desc2.ddsCaps.dwCaps &= ~DDSCAPS_FRONTBUFFER; /* It's not a front buffer */
desc2.ddsCaps.dwCaps |= DDSCAPS_BACKBUFFER;
}
- /* Set the DDSCAPS2_MIPMAPSUBLEVEL flag on mipmap sublevels according to the msdn */
- if(DDSD->ddsCaps.dwCaps & DDSCAPS_MIPMAP)
- {
- desc2.ddsCaps.dwCaps2 |= DDSCAPS2_MIPMAPSUBLEVEL;
- }
- for(i = 0; i < extra_surfaces; i++)
+ hr = DD_OK;
+ if(desc2.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
+ {
+ desc2.ddsCaps.dwCaps2 &= ~DDSCAPS2_CUBEMAP_ALLFACES;
+ desc2.ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP_NEGATIVEZ;
+ hr |= CreateAdditionalSurfaces(This, object, extra_surfaces + 1, desc2, TRUE);
+ desc2.ddsCaps.dwCaps2 &= ~DDSCAPS2_CUBEMAP_NEGATIVEZ;
+ desc2.ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP_POSITIVEZ;
+ hr |= CreateAdditionalSurfaces(This, object, extra_surfaces + 1, desc2, TRUE);
+ desc2.ddsCaps.dwCaps2 &= ~DDSCAPS2_CUBEMAP_POSITIVEZ;
+ desc2.ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP_NEGATIVEY;
+ hr |= CreateAdditionalSurfaces(This, object, extra_surfaces + 1, desc2, TRUE);
+ desc2.ddsCaps.dwCaps2 &= ~DDSCAPS2_CUBEMAP_NEGATIVEY;
+ desc2.ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP_POSITIVEY;
+ hr |= CreateAdditionalSurfaces(This, object, extra_surfaces + 1, desc2, TRUE);
+ desc2.ddsCaps.dwCaps2 &= ~DDSCAPS2_CUBEMAP_POSITIVEY;
+ desc2.ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP_NEGATIVEX;
+ hr |= CreateAdditionalSurfaces(This, object, extra_surfaces + 1, desc2, TRUE);
+ desc2.ddsCaps.dwCaps2 &= ~DDSCAPS2_CUBEMAP_NEGATIVEX;
+ desc2.ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP_POSITIVEX;
+ }
+
+ hr |= CreateAdditionalSurfaces(This, object, extra_surfaces, desc2, FALSE);
+ if(hr != DD_OK)
{
- IDirectDrawSurfaceImpl *object2 = NULL;
- IDirectDrawSurfaceImpl *iterator;
-
- /* increase the mipmap level, but only if a mipmap is created
- * In this case, also halve the size
- */
- if(DDSD->ddsCaps.dwCaps & DDSCAPS_MIPMAP)
- {
- level++;
- if(desc2.dwWidth > 1) desc2.dwWidth /= 2;
- if(desc2.dwHeight > 1) desc2.dwHeight /= 2;
- }
-
- hr = IDirectDrawImpl_CreateNewSurface(This,
- &desc2,
- &object2,
- level);
- if(hr != DD_OK)
- {
- /* This destroys and possibly created surfaces too */
- IDirectDrawSurface_Release( ICOM_INTERFACE(object, IDirectDrawSurface7) );
- return hr;
- }
-
- /* Add the new surface to the complex attachment list */
- object2->first_complex = object;
- object2->next_complex = NULL;
- iterator = object;
- while(iterator->next_complex) iterator = iterator->next_complex;
- iterator->next_complex = object2;
-
- /* Remove the (possible) back buffer cap from the new surface description,
- * because only one surface in the flipping chain is a back buffer, one
- * is a front buffer, the others are just primary surfaces.
- */
- desc2.ddsCaps.dwCaps &= ~DDSCAPS_BACKBUFFER;
+ /* This destroys and possibly created surfaces too */
+ IDirectDrawSurface_Release( ICOM_INTERFACE(object, IDirectDrawSurface7) );
+ LeaveCriticalSection(&ddraw_cs);
+ return hr;
}
- /* Addref the ddraw interface to keep an reference for each surface */
- IDirectDraw7_AddRef(iface);
- object->ifaceToRelease = (IUnknown *) iface;
-
/* If the implementation is OpenGL and there's no d3ddevice, attach a d3ddevice
* But attach the d3ddevice only if the currently created surface was
* a primary surface (2D app in 3D mode) or a 3DDEVICE surface (3D app)
LIST_FOR_EACH(entry, &This->surface_list)
{
surface = LIST_ENTRY(entry, IDirectDrawSurfaceImpl, surface_list_entry);
- if(surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
+ if((surface->surface_desc.ddsCaps.dwCaps & (DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER)) ==
+ (DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER))
{
/* found */
target = surface;
}
TRACE("(%p) Attaching a D3DDevice, rendertarget = %p\n", This, target);
- hr = IDirectDrawImpl_AttachD3DDevice(This, target->first_complex);
+ hr = IDirectDrawImpl_AttachD3DDevice(This, target);
if(hr != D3D_OK)
{
+ IDirectDrawSurfaceImpl *release_surf;
ERR("IDirectDrawImpl_AttachD3DDevice failed, hr = %x\n", hr);
+ *Surf = NULL;
+
+ /* The before created surface structures are in an incomplete state here.
+ * WineD3D holds the reference on the IParents, and it released them on the failure
+ * already. So the regular release method implementation would fail on the attempt
+ * to destroy either the IParents or the swapchain. So free the surface here.
+ * The surface structure here is a list, not a tree, because onscreen targets
+ * cannot be cube textures
+ */
+ while(object)
+ {
+ release_surf = object;
+ object = object->complex_array[0];
+ IDirectDrawSurfaceImpl_Destroy(release_surf);
+ }
+ LeaveCriticalSection(&ddraw_cs);
+ return hr;
}
}
+ /* Addref the ddraw interface to keep an reference for each surface */
+ IDirectDraw7_AddRef(iface);
+ object->ifaceToRelease = (IUnknown *) iface;
+
/* Create a WineD3DTexture if a texture was requested */
- if(DDSD->ddsCaps.dwCaps & DDSCAPS_TEXTURE)
+ if(desc2.ddsCaps.dwCaps & DDSCAPS_TEXTURE)
{
UINT levels;
WINED3DFORMAT Format;
{
Pool = WINED3DPOOL_SYSTEMMEM;
}
- /* Should I forward the MANEGED cap to the managed pool ? */
+ /* Should I forward the MANAGED cap to the managed pool ? */
/* Get the format. It's set already by CreateNewSurface */
Format = PixelFormat_DD2WineD3D(&object->surface_desc.u4.ddpfPixelFormat);
/* The surfaces are already created, the callback only
* passes the IWineD3DSurface to WineD3D
*/
- hr = IWineD3DDevice_CreateTexture( This->wineD3DDevice,
- DDSD->dwWidth, DDSD->dwHeight,
- levels, /* MipMapCount = Levels */
- 0, /* usage */
- Format,
- Pool,
- &object->wineD3DTexture,
- 0, /* SharedHandle */
- (IUnknown *) ICOM_INTERFACE(object, IDirectDrawSurface7),
- D3D7CB_CreateSurface );
+ if(desc2.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
+ {
+ hr = IWineD3DDevice_CreateCubeTexture(This->wineD3DDevice,
+ DDSD->dwWidth, /* Edgelength */
+ levels,
+ 0, /* usage */
+ Format,
+ Pool,
+ (IWineD3DCubeTexture **) &object->wineD3DTexture,
+ 0, /* SharedHandle */
+ (IUnknown *) ICOM_INTERFACE(object, IDirectDrawSurface7),
+ D3D7CB_CreateSurface);
+ }
+ else
+ {
+ hr = IWineD3DDevice_CreateTexture(This->wineD3DDevice,
+ DDSD->dwWidth, DDSD->dwHeight,
+ levels, /* MipMapCount = Levels */
+ 0, /* usage */
+ Format,
+ Pool,
+ (IWineD3DTexture **) &object->wineD3DTexture,
+ 0, /* SharedHandle */
+ (IUnknown *) ICOM_INTERFACE(object, IDirectDrawSurface7),
+ D3D7CB_CreateSurface );
+ }
This->tex_root = NULL;
}
+ LeaveCriticalSection(&ddraw_cs);
return hr;
}
nomatch = Flags & DDENUMSURFACES_NOMATCH;
TRACE("(%p)->(%x,%p,%p,%p)\n", This, Flags, DDSD, Context, Callback);
+ EnterCriticalSection(&ddraw_cs);
if(!Callback)
+ {
+ LeaveCriticalSection(&ddraw_cs);
return DDERR_INVALIDPARAMS;
+ }
/* Use the _SAFE enumeration, the app may destroy enumerated surfaces */
LIST_FOR_EACH_SAFE(entry, entry2, &This->surface_list)
desc = surf->surface_desc;
IDirectDrawSurface7_AddRef(ICOM_INTERFACE(surf, IDirectDrawSurface7));
if(Callback( ICOM_INTERFACE(surf, IDirectDrawSurface7), &desc, Context) != DDENUMRET_OK)
+ {
+ LeaveCriticalSection(&ddraw_cs);
return DD_OK;
+ }
}
}
+ LeaveCriticalSection(&ddraw_cs);
return DD_OK;
}
HANDLE* pSharedHandle)
{
ICOM_THIS_FROM(IDirectDrawImpl, IDirectDraw7, device);
- IDirectDrawSurfaceImpl *d3dSurface = This->d3d_target->first_complex, *target = NULL;
+ IDirectDrawSurfaceImpl *d3dSurface = This->d3d_target, *target = NULL;
TRACE("(%p) call back\n", device);
if(d3dSurface->isRenderTarget)
localParameters.SwapEffect = WINED3DSWAPEFFECT_COPY;
localParameters.hDeviceWindow = window;
localParameters.Windowed = !(This->cooperative_level & DDSCL_FULLSCREEN);
- localParameters.EnableAutoDepthStencil = FALSE;
+ localParameters.EnableAutoDepthStencil = TRUE;
localParameters.AutoDepthStencilFormat = WINED3DFMT_D16;
localParameters.Flags = 0;
localParameters.FullScreen_RefreshRateInHz = WINED3DPRESENT_RATE_DEFAULT; /* Default rate: It's already set */
D3D7CB_CreateAdditionalSwapChain);
if(FAILED(hr))
{
- This->wineD3DDevice = NULL;
+ This->d3d_target = NULL;
+ This->d3d_initialized = FALSE;
return hr;
}
+ This->declArraySize = 2;
+ This->decls = HeapAlloc(GetProcessHeap(),
+ HEAP_ZERO_MEMORY,
+ sizeof(*This->decls) * This->declArraySize);
+ if(!This->decls)
+ {
+ ERR("Error allocating an array for the converted vertex decls\n");
+ This->declArraySize = 0;
+ hr = IWineD3DDevice_Uninit3D(This->wineD3DDevice,
+ D3D7CB_DestroyDepthStencilSurface,
+ D3D7CB_DestroySwapChain);
+ return E_OUTOFMEMORY;
+ }
+
/* Create an Index Buffer parent */
TRACE("(%p) Successfully initialized 3D\n", This);
return DD_OK;
*****************************************************************************/
HRESULT WINAPI
DirectDrawCreateClipper(DWORD Flags,
- IDirectDrawClipper **Clipper,
+ LPDIRECTDRAWCLIPPER *Clipper,
IUnknown *UnkOuter)
{
IDirectDrawClipperImpl* object;
TRACE("(%08x,%p,%p)\n", Flags, Clipper, UnkOuter);
- if (UnkOuter != NULL) return CLASS_E_NOAGGREGATION;
+ EnterCriticalSection(&ddraw_cs);
+ if (UnkOuter != NULL)
+ {
+ LeaveCriticalSection(&ddraw_cs);
+ return CLASS_E_NOAGGREGATION;
+ }
object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
sizeof(IDirectDrawClipperImpl));
- if (object == NULL) return E_OUTOFMEMORY;
+ if (object == NULL)
+ {
+ LeaveCriticalSection(&ddraw_cs);
+ return E_OUTOFMEMORY;
+ }
ICOM_INIT_INTERFACE(object, IDirectDrawClipper, IDirectDrawClipper_Vtbl);
object->ref = 1;
- object->hWnd = 0;
- object->ddraw_owner = NULL;
+ object->wineD3DClipper = pWineDirect3DCreateClipper((IUnknown *) object);
+ if(!object->wineD3DClipper)
+ {
+ HeapFree(GetProcessHeap(), 0, object);
+ LeaveCriticalSection(&ddraw_cs);
+ return E_OUTOFMEMORY;
+ }
*Clipper = (IDirectDrawClipper *) object;
+ LeaveCriticalSection(&ddraw_cs);
return DD_OK;
}
HRESULT hr = DDERR_GENERIC;
TRACE("(%p)->(%x,%p,%p,%p)\n", This, Flags, ColorTable, Palette, pUnkOuter);
+ EnterCriticalSection(&ddraw_cs);
if(pUnkOuter != NULL)
{
WARN("pUnkOuter is %p, returning CLASS_E_NOAGGREGATION\n", pUnkOuter);
+ LeaveCriticalSection(&ddraw_cs);
return CLASS_E_NOAGGREGATION;
}
if(!This->cooperative_level)
{
WARN("No cooperative level set, returning DDERR_NOCOOPERATIVELEVELSET\n");
+ LeaveCriticalSection(&ddraw_cs);
return DDERR_NOCOOPERATIVELEVELSET;
}
if(!object)
{
ERR("Out of memory when allocating memory for a palette implementation\n");
+ LeaveCriticalSection(&ddraw_cs);
return E_OUTOFMEMORY;
}
if(hr != DD_OK)
{
HeapFree(GetProcessHeap(), 0, object);
+ LeaveCriticalSection(&ddraw_cs);
return hr;
}
IDirectDraw7_AddRef(iface);
object->ifaceToRelease = (IUnknown *) iface;
*Palette = ICOM_INTERFACE(object, IDirectDrawPalette);
+ LeaveCriticalSection(&ddraw_cs);
return DD_OK;
}
*
* This function is in ddraw.c and the DDraw object space because D3D7
* vertex buffers are created using the IDirect3D interface to the ddraw
- * object, so they can be valid accross D3D devices(theoretically. The ddraw
+ * object, so they can be valid across D3D devices(theoretically. The ddraw
* object also owns the wined3d device
*
* Parameters: