[DDRAW] Sync with Wine 3.0. CORE-14225
[reactos.git] / dll / directx / wine / ddraw / surface.c
index 74f2d15..abae18b 100644 (file)
@@ -37,7 +37,6 @@ static inline struct ddraw_surface *impl_from_IDirectDrawGammaControl(IDirectDra
  * to support windowless rendering first. */
 HRESULT ddraw_surface_update_frontbuffer(struct ddraw_surface *surface, const RECT *rect, BOOL read)
 {
-    struct ddraw *ddraw = surface->ddraw;
     HDC surface_dc, screen_dc;
     int x, y, w, h;
     HRESULT hr;
@@ -58,14 +57,14 @@ HRESULT ddraw_surface_update_frontbuffer(struct ddraw_surface *surface, const RE
     if (w <= 0 || h <= 0)
         return DD_OK;
 
-    if (ddraw->swapchain_window && !(ddraw->flags & DDRAW_GDI_FLIP))
+    if (surface->ddraw->swapchain_window)
     {
         /* Nothing to do, we control the frontbuffer, or at least the parts we
          * care about. */
         if (read)
             return DD_OK;
 
-        return wined3d_texture_blt(ddraw->wined3d_frontbuffer, 0, rect,
+        return wined3d_texture_blt(surface->ddraw->wined3d_frontbuffer, 0, rect,
                 surface->wined3d_texture, surface->sub_resource_idx, rect, 0, NULL, WINED3D_TEXF_POINT);
     }
 
@@ -204,7 +203,7 @@ static HRESULT WINAPI ddraw_surface7_QueryInterface(IDirectDrawSurface7 *iface,
             {
                 HRESULT hr;
 
-                if (FAILED(hr = d3d_device_create(This->ddraw, riid, This, (IUnknown *)&This->IDirectDrawSurface_iface,
+                if (FAILED(hr = d3d_device_create(This->ddraw, This, (IUnknown *)&This->IDirectDrawSurface_iface,
                         1, &This->device1, (IUnknown *)&This->IDirectDrawSurface_iface)))
                 {
                     This->device1 = NULL;
@@ -5181,46 +5180,6 @@ static struct ddraw_surface *get_sub_mimaplevel(struct ddraw_surface *surface)
     return impl_from_IDirectDrawSurface7(next_level);
 }
 
-static BOOL compare_format(DDPIXELFORMAT *format1, DDPIXELFORMAT *format2)
-{
-    if ((format1->dwFlags & (DDPF_RGB|DDPF_YUV|DDPF_FOURCC)) !=
-        (format2->dwFlags & (DDPF_RGB|DDPF_YUV|DDPF_FOURCC)))
-        return FALSE;
-
-    if (format1->dwFlags & (DDPF_RGB|DDPF_YUV))
-    {
-        if (!(format1->dwFlags & DDPF_ALPHA))
-        {
-            /* The RGB and YUV bits are stored in the same fields */
-            if (format1->u1.dwRGBBitCount != format2->u1.dwRGBBitCount)
-                return FALSE;
-
-            if (format1->u2.dwRBitMask != format2->u2.dwRBitMask)
-                return FALSE;
-
-            if (format1->u3.dwGBitMask != format2->u3.dwGBitMask)
-                return FALSE;
-
-            if (format1->u4.dwBBitMask != format2->u4.dwBBitMask)
-                return FALSE;
-        }
-
-        if (format1->dwFlags & (DDPF_ALPHAPIXELS | DDPF_ALPHA))
-        {
-            if (format1->u5.dwRGBAlphaBitMask != format2->u5.dwRGBAlphaBitMask)
-                return FALSE;
-        }
-    }
-
-    if (format1->dwFlags & DDPF_FOURCC)
-    {
-        if (format1->dwFourCC != format2->dwFourCC)
-            return FALSE;
-    }
-
-    return TRUE;
-}
-
 /*****************************************************************************
  * IDirect3DTexture2::Load
  *
@@ -5242,7 +5201,7 @@ static HRESULT WINAPI d3d_texture2_Load(IDirect3DTexture2 *iface, IDirect3DTextu
 {
     struct ddraw_surface *dst_surface = impl_from_IDirect3DTexture2(iface);
     struct ddraw_surface *src_surface = unsafe_impl_from_IDirect3DTexture2(src_texture);
-    RECT src_rect, dst_rect;
+    struct wined3d_resource *dst_resource, *src_resource;
     HRESULT hr;
 
     TRACE("iface %p, src_texture %p.\n", iface, src_texture);
@@ -5255,60 +5214,90 @@ static HRESULT WINAPI d3d_texture2_Load(IDirect3DTexture2 *iface, IDirect3DTextu
 
     wined3d_mutex_lock();
 
+    dst_resource = wined3d_texture_get_resource(dst_surface->wined3d_texture);
+    src_resource = wined3d_texture_get_resource(src_surface->wined3d_texture);
+
+    if (((src_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP)
+            != (dst_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP))
+            || (src_surface->surface_desc.u2.dwMipMapCount != dst_surface->surface_desc.u2.dwMipMapCount))
+    {
+        ERR("Trying to load surfaces with different mip-map counts.\n");
+    }
+
     for (;;)
     {
-        DDSURFACEDESC *src_desc = (DDSURFACEDESC *)&src_surface->surface_desc;
+        struct ddraw_palette *dst_pal, *src_pal;
+        DDSURFACEDESC *src_desc, *dst_desc;
 
         TRACE("Copying surface %p to surface %p.\n", src_surface, dst_surface);
 
-        if (compare_format(&src_surface->surface_desc.u4.ddpfPixelFormat,
-                           &dst_surface->surface_desc.u4.ddpfPixelFormat))
-        {
-            struct ddraw_palette *dst_pal, *src_pal;
+        /* Suppress the ALLOCONLOAD flag */
+        dst_surface->surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_ALLOCONLOAD;
 
-            /* Get the palettes */
-            dst_pal = dst_surface->palette;
-            src_pal = src_surface->palette;
+        /* Get the palettes */
+        dst_pal = dst_surface->palette;
+        src_pal = src_surface->palette;
 
-            if (src_pal)
-            {
-                PALETTEENTRY palent[256];
+        if (src_pal)
+        {
+            PALETTEENTRY palent[256];
 
-                if (!dst_pal)
-                {
-                    wined3d_mutex_unlock();
-                    return DDERR_NOPALETTEATTACHED;
-                }
-                IDirectDrawPalette_GetEntries(&src_pal->IDirectDrawPalette_iface, 0, 0, 256, palent);
-                IDirectDrawPalette_SetEntries(&dst_pal->IDirectDrawPalette_iface, 0, 0, 256, palent);
+            if (!dst_pal)
+            {
+                wined3d_mutex_unlock();
+                return DDERR_NOPALETTEATTACHED;
             }
+            IDirectDrawPalette_GetEntries(&src_pal->IDirectDrawPalette_iface, 0, 0, 256, palent);
+            IDirectDrawPalette_SetEntries(&dst_pal->IDirectDrawPalette_iface, 0, 0, 256, palent);
+        }
 
+        /* Copy one surface on the other */
+        dst_desc = (DDSURFACEDESC *)&(dst_surface->surface_desc);
+        src_desc = (DDSURFACEDESC *)&(src_surface->surface_desc);
+
+        if ((src_desc->dwWidth != dst_desc->dwWidth) || (src_desc->dwHeight != dst_desc->dwHeight))
+        {
+            /* Should also check for same pixel format, u1.lPitch, ... */
+            ERR("Error in surface sizes.\n");
+            wined3d_mutex_unlock();
+            return D3DERR_TEXTURE_LOAD_FAILED;
+        }
+        else
+        {
+            struct wined3d_map_desc src_map_desc, dst_map_desc;
+
+            /* Copy the src blit color key if the source has one, don't erase
+             * the destination's ckey if the source has none */
             if (src_desc->dwFlags & DDSD_CKSRCBLT)
             {
                 IDirectDrawSurface7_SetColorKey(&dst_surface->IDirectDrawSurface7_iface,
                         DDCKEY_SRCBLT, &src_desc->ddckCKSrcBlt);
             }
-        }
-        else
-        {
-            if (src_desc->dwFlags & DDSD_CKSRCBLT)
-                return E_FAIL;
-        }
 
-        /* Suppress the ALLOCONLOAD flag */
-        dst_surface->surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_ALLOCONLOAD;
+            if (FAILED(hr = wined3d_resource_map(src_resource,
+                    src_surface->sub_resource_idx, &src_map_desc, NULL, 0)))
+            {
+                ERR("Failed to lock source surface, hr %#x.\n", hr);
+                wined3d_mutex_unlock();
+                return D3DERR_TEXTURE_LOAD_FAILED;
+            }
 
-        SetRect(&src_rect, 0, 0, src_surface->surface_desc.dwWidth, src_surface->surface_desc.dwHeight);
-        SetRect(&dst_rect, 0, 0, dst_surface->surface_desc.dwWidth, dst_surface->surface_desc.dwHeight);
+            if (FAILED(hr = wined3d_resource_map(dst_resource,
+                    dst_surface->sub_resource_idx, &dst_map_desc, NULL, 0)))
+            {
+                ERR("Failed to lock destination surface, hr %#x.\n", hr);
+                wined3d_resource_unmap(src_resource, src_surface->sub_resource_idx);
+                wined3d_mutex_unlock();
+                return D3DERR_TEXTURE_LOAD_FAILED;
+            }
 
-        hr = wined3d_texture_blt(dst_surface->wined3d_texture, dst_surface->sub_resource_idx, &dst_rect,
-                                 src_surface->wined3d_texture, src_surface->sub_resource_idx, &src_rect,
-                                 0, NULL, WINED3D_TEXF_LINEAR);
-        if (FAILED(hr))
-        {
-            ERR("Failed to blit surface, hr %#x.\n", hr);
-            wined3d_mutex_unlock();
-            return hr;
+            if (dst_surface->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_FOURCC)
+                memcpy(dst_map_desc.data, src_map_desc.data, src_surface->surface_desc.u1.dwLinearSize);
+            else
+                memcpy(dst_map_desc.data, src_map_desc.data, src_map_desc.row_pitch * src_desc->dwHeight);
+
+            wined3d_resource_unmap(dst_resource, dst_surface->sub_resource_idx);
+            wined3d_resource_unmap(src_resource, src_surface->sub_resource_idx);
         }
 
         if (src_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP)
@@ -5321,11 +5310,12 @@ static HRESULT WINAPI d3d_texture2_Load(IDirect3DTexture2 *iface, IDirect3DTextu
         else
             dst_surface = NULL;
 
-        if (src_surface && !dst_surface)
-            return DDERR_NOTFOUND;
-
         if (!src_surface || !dst_surface)
+        {
+            if (src_surface != dst_surface)
+                ERR("Loading surface with different mipmap structure.\n");
             break;
+        }
     }
 
     wined3d_mutex_unlock();
@@ -5555,7 +5545,7 @@ static const struct IDirectDrawSurface2Vtbl ddraw_surface2_vtbl =
     ddraw_surface2_PageUnlock,
 };
 
-static struct IDirectDrawSurfaceVtbl ddraw_surface1_vtbl =
+static const struct IDirectDrawSurfaceVtbl ddraw_surface1_vtbl =
 {
     /* IUnknown */
     ddraw_surface1_QueryInterface,
@@ -6007,6 +5997,9 @@ HRESULT ddraw_surface_create(struct ddraw *ddraw, const DDSURFACEDESC2 *surface_
                 HeapFree(GetProcessHeap(), 0, texture);
                 return hr_ddraw_from_wined3d(hr);
             }
+
+            wined3d_device_set_render_state(ddraw->wined3d_device, WINED3D_RS_ZENABLE,
+                    !!swapchain_desc.enable_auto_depth_stencil);
         }
     }
 
@@ -6102,24 +6095,7 @@ HRESULT ddraw_surface_create(struct ddraw *ddraw, const DDSURFACEDESC2 *surface_
 
     if (desc->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
     {
-        /*
-         * The ddraw RGB device allows to use system memory surfaces as rendering target.
-         * This does not cause problems because the RGB device does software rasterization
-         * though it will fail with hardware accelerated ddraw. In order to be partially
-         * compatible with games requesting explicitly the RGB device, we ignore the
-         * specified location and try to create rendering targets in video memory if
-         * possible.
-         */
-        if ((desc->ddsCaps.dwCaps & DDSCAPS_3DDEVICE) &&
-            SUCCEEDED(hr = wined3d_check_device_format(ddraw->wined3d, WINED3DADAPTER_DEFAULT,
-                        WINED3D_DEVICE_TYPE_HAL, mode.format_id, WINED3DUSAGE_RENDERTARGET,
-                        WINED3D_RTYPE_TEXTURE_2D, wined3d_desc.format)))
-        {
-            FIXME("Application wants to create rendering target in system memory, using video memory instead\n");
-            wined3d_desc.usage |= WINED3DUSAGE_RENDERTARGET;
-        }
-        else
-            wined3d_desc.pool = WINED3D_POOL_SYSTEM_MEM;
+        wined3d_desc.pool = WINED3D_POOL_SYSTEM_MEM;
     }
     else
     {