diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index cefabea2a55..6ac60f1458a 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -6514,7 +6514,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice* return WINED3D_OK; } -static void updateSurfaceDesc(IWineD3DSurfaceImpl *surface, const WINED3DPRESENT_PARAMETERS* pPresentationParameters) +static HRESULT updateSurfaceDesc(IWineD3DSurfaceImpl *surface, const WINED3DPRESENT_PARAMETERS* pPresentationParameters) { IWineD3DDeviceImpl *device = surface->resource.wineD3DDevice; const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; @@ -6567,12 +6567,14 @@ static void updateSurfaceDesc(IWineD3DSurfaceImpl *surface, const WINED3DPRESENT surface->resource.allocatedMemory = NULL; surface->resource.heapMemory = NULL; surface->resource.size = IWineD3DSurface_GetPitch((IWineD3DSurface *) surface) * surface->pow2Width; - /* INDRAWABLE is a sane place for implicit targets after the reset, INSYSMEM is more appropriate for depth stencils. */ - if (surface->resource.usage & WINED3DUSAGE_DEPTHSTENCIL) { - IWineD3DSurface_ModifyLocation((IWineD3DSurface *) surface, SFLAG_INSYSMEM, TRUE); - } else { - IWineD3DSurface_ModifyLocation((IWineD3DSurface *) surface, SFLAG_INDRAWABLE, TRUE); + + /* Put all surfaces into sysmem - the drawable might disappear if the backbuffer was rendered + * to a FBO */ + if(!surface_init_sysmem((IWineD3DSurface *) surface)) + { + return E_OUTOFMEMORY; } + return WINED3D_OK; } static HRESULT WINAPI reset_unload_resources(IWineD3DResource *resource, void *data) { @@ -6830,12 +6832,28 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRE swapchain->presentParms.BackBufferWidth = pPresentationParameters->BackBufferWidth; swapchain->presentParms.BackBufferHeight = pPresentationParameters->BackBufferHeight; - updateSurfaceDesc((IWineD3DSurfaceImpl *)swapchain->frontBuffer, pPresentationParameters); + hr = updateSurfaceDesc((IWineD3DSurfaceImpl *)swapchain->frontBuffer, pPresentationParameters); + if(FAILED(hr)) + { + IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain); + return hr; + } + for(i = 0; i < swapchain->presentParms.BackBufferCount; i++) { - updateSurfaceDesc((IWineD3DSurfaceImpl *)swapchain->backBuffer[i], pPresentationParameters); + hr = updateSurfaceDesc((IWineD3DSurfaceImpl *)swapchain->backBuffer[i], pPresentationParameters); + if(FAILED(hr)) + { + IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain); + return hr; + } } if(This->auto_depth_stencil_buffer) { - updateSurfaceDesc((IWineD3DSurfaceImpl *)This->auto_depth_stencil_buffer, pPresentationParameters); + hr = updateSurfaceDesc((IWineD3DSurfaceImpl *)This->auto_depth_stencil_buffer, pPresentationParameters); + if(FAILED(hr)) + { + IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain); + return hr; + } } } diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c index d75c5e900e9..1463dd4a016 100644 --- a/dlls/wined3d/surface.c +++ b/dlls/wined3d/surface.c @@ -820,6 +820,30 @@ static void surface_remove_pbo(IWineD3DSurfaceImpl *This) { This->Flags &= ~SFLAG_PBO; } +BOOL surface_init_sysmem(IWineD3DSurface *iface) +{ + IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface; + + if(!This->resource.allocatedMemory) + { + This->resource.heapMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->resource.size + RESOURCE_ALIGNMENT); + if(!This->resource.heapMemory) + { + ERR("Out of memory\n"); + return FALSE; + } + This->resource.allocatedMemory = + (BYTE *)(((ULONG_PTR) This->resource.heapMemory + (RESOURCE_ALIGNMENT - 1)) & ~(RESOURCE_ALIGNMENT - 1)); + } + else + { + memset(This->resource.allocatedMemory, 0, This->resource.size); + } + + IWineD3DSurface_ModifyLocation(iface, SFLAG_INSYSMEM, TRUE); + return TRUE; +} + static void WINAPI IWineD3DSurfaceImpl_UnLoad(IWineD3DSurface *iface) { IWineD3DBaseTexture *texture = NULL; IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface; @@ -836,18 +860,12 @@ static void WINAPI IWineD3DSurfaceImpl_UnLoad(IWineD3DSurface *iface) { * or depth stencil. The content may be destroyed, but we still have to tear down * opengl resources, so we cannot leave early. * - * Put the most up to date surface location into the drawable. D3D-wise this content - * is undefined, so it would be nowhere, but that would make the location management - * more complicated. The drawable is a sane location, because if we mark sysmem or - * texture up to date, drawPrim will copy the uninitialized texture or sysmem to the - * uninitialized drawable. That's pointless and we'd have to allocate the texture / - * sysmem copy here. + * Put the surfaces into sysmem, and reset the content. The D3D content is undefined, + * but we can't set the sysmem INDRAWABLE because when we're rendering the swapchain + * or the depth stencil into an FBO the texture or render buffer will be removed + * and all flags get lost */ - if (This->resource.usage & WINED3DUSAGE_DEPTHSTENCIL) { - IWineD3DSurface_ModifyLocation(iface, SFLAG_INSYSMEM, TRUE); - } else { - IWineD3DSurface_ModifyLocation(iface, SFLAG_INDRAWABLE, TRUE); - } + surface_init_sysmem(iface); } else { /* Load the surface into system memory */ IWineD3DSurface_LoadLocation(iface, SFLAG_INSYSMEM, NULL); diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 39519a10788..bd8e58f0c8e 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -1726,6 +1726,7 @@ typedef struct IWineD3DBaseTextureClass } IWineD3DBaseTextureClass; void surface_internal_preload(IWineD3DSurface *iface, enum WINED3DSRGB srgb) DECLSPEC_HIDDEN; +BOOL surface_init_sysmem(IWineD3DSurface *iface) DECLSPEC_HIDDEN; typedef struct IWineD3DBaseTextureImpl {