[PATCH 2/6] wined3d: Implement texture DC creation on top of D3DKMTCreateDCFromMemory().

Henri Verbeet hverbeet at codeweavers.com
Thu Apr 14 12:32:46 CDT 2016


Signed-off-by: Henri Verbeet <hverbeet at codeweavers.com>
---
 dlls/d3d9/tests/d3d9ex.c       |   2 +-
 dlls/d3d9/tests/device.c       |   2 +-
 dlls/ddraw/surface.c           |   2 +-
 dlls/ddraw/tests/ddraw1.c      |   2 +-
 dlls/ddraw/tests/ddraw2.c      |   4 +-
 dlls/ddraw/tests/ddraw4.c      |   4 +-
 dlls/ddraw/tests/ddraw7.c      |   4 +-
 dlls/wined3d/palette.c         |   5 --
 dlls/wined3d/surface.c         | 200 ++++++++++++++++-------------------------
 dlls/wined3d/swapchain.c       |  45 +++-------
 dlls/wined3d/texture.c         | 101 +++++++--------------
 dlls/wined3d/utils.c           |  42 ++++++---
 dlls/wined3d/wined3d_private.h |  37 ++++----
 13 files changed, 180 insertions(+), 270 deletions(-)

diff --git a/dlls/d3d9/tests/d3d9ex.c b/dlls/d3d9/tests/d3d9ex.c
index e9548de..8506f2d 100644
--- a/dlls/d3d9/tests/d3d9ex.c
+++ b/dlls/d3d9/tests/d3d9ex.c
@@ -1471,7 +1471,7 @@ static void test_user_memory_getdc(void)
     ok(!!bitmap, "Failed to get bitmap.\n");
     size = GetObjectA(bitmap, sizeof(dib), &dib);
     ok(size == sizeof(dib), "Got unexpected size %d.\n", size);
-    todo_wine ok(dib.dsBm.bmBits == data, "Got unexpected bits %p, expected %p.\n", dib.dsBm.bmBits, data);
+    ok(dib.dsBm.bmBits == data, "Got unexpected bits %p, expected %p.\n", dib.dsBm.bmBits, data);
     BitBlt(dc, 0, 0, 16, 8, NULL, 0, 0, WHITENESS);
     BitBlt(dc, 0, 8, 16, 8, NULL, 0, 0, BLACKNESS);
     hr = IDirect3DSurface9_ReleaseDC(surface, dc);
diff --git a/dlls/d3d9/tests/device.c b/dlls/d3d9/tests/device.c
index a14e3d4..237fcc3 100644
--- a/dlls/d3d9/tests/device.c
+++ b/dlls/d3d9/tests/device.c
@@ -7689,7 +7689,7 @@ static void test_getdc(void)
             ok(dib.dsBmih.biCompression == (testdata[i].bit_count == 16 ? BI_BITFIELDS : BI_RGB),
                     "Got unexpected compression %#x for format %s.\n",
                     dib.dsBmih.biCompression, testdata[i].name);
-            todo_wine ok(!dib.dsBmih.biSizeImage, "Got unexpected image size %u for format %s.\n",
+            ok(!dib.dsBmih.biSizeImage, "Got unexpected image size %u for format %s.\n",
                     dib.dsBmih.biSizeImage, testdata[i].name);
             ok(!dib.dsBmih.biXPelsPerMeter, "Got unexpected horizontal resolution %d for format %s.\n",
                     dib.dsBmih.biXPelsPerMeter, testdata[i].name);
diff --git a/dlls/ddraw/surface.c b/dlls/ddraw/surface.c
index c47c546..8f627d8 100644
--- a/dlls/ddraw/surface.c
+++ b/dlls/ddraw/surface.c
@@ -2172,7 +2172,7 @@ static HRESULT WINAPI ddraw_surface7_GetDC(IDirectDrawSurface7 *iface, HDC *dc)
          * does not touch *dc. */
         case WINED3DERR_INVALIDCALL:
             *dc = NULL;
-            return DDERR_INVALIDPARAMS;
+            return DDERR_CANTCREATEDC;
 
         default:
             return hr;
diff --git a/dlls/ddraw/tests/ddraw1.c b/dlls/ddraw/tests/ddraw1.c
index 9b9db30..0bb601b 100644
--- a/dlls/ddraw/tests/ddraw1.c
+++ b/dlls/ddraw/tests/ddraw1.c
@@ -8720,7 +8720,7 @@ static void test_getdc(void)
                     || broken(U2(test_data[i].format).dwRGBBitCount == 32 && dib.dsBmih.biCompression == BI_BITFIELDS),
                     "Got unexpected compression %#x for format %s.\n",
                     dib.dsBmih.biCompression, test_data[i].name);
-            todo_wine ok(!dib.dsBmih.biSizeImage, "Got unexpected image size %u for format %s.\n",
+            ok(!dib.dsBmih.biSizeImage, "Got unexpected image size %u for format %s.\n",
                     dib.dsBmih.biSizeImage, test_data[i].name);
             ok(!dib.dsBmih.biXPelsPerMeter, "Got unexpected horizontal resolution %d for format %s.\n",
                     dib.dsBmih.biXPelsPerMeter, test_data[i].name);
diff --git a/dlls/ddraw/tests/ddraw2.c b/dlls/ddraw/tests/ddraw2.c
index 43e2c48..f1a5ff3 100644
--- a/dlls/ddraw/tests/ddraw2.c
+++ b/dlls/ddraw/tests/ddraw2.c
@@ -5346,7 +5346,7 @@ static void test_user_memory_getdc(void)
     ok(!!bitmap, "Failed to get bitmap.\n");
     size = GetObjectA(bitmap, sizeof(dib), &dib);
     ok(size == sizeof(dib), "Got unexpected size %d.\n", size);
-    todo_wine ok(dib.dsBm.bmBits == data, "Got unexpected bits %p, expected %p.\n", dib.dsBm.bmBits, data);
+    ok(dib.dsBm.bmBits == data, "Got unexpected bits %p, expected %p.\n", dib.dsBm.bmBits, data);
     BitBlt(dc, 0, 0, 16, 8, NULL, 0, 0, WHITENESS);
     BitBlt(dc, 0, 8, 16, 8, NULL, 0, 0, BLACKNESS);
     hr = IDirectDrawSurface3_ReleaseDC(surface3, dc);
@@ -9835,7 +9835,7 @@ static void test_getdc(void)
                     || broken(U2(test_data[i].format).dwRGBBitCount == 32 && dib.dsBmih.biCompression == BI_BITFIELDS),
                     "Got unexpected compression %#x for format %s.\n",
                     dib.dsBmih.biCompression, test_data[i].name);
-            todo_wine ok(!dib.dsBmih.biSizeImage, "Got unexpected image size %u for format %s.\n",
+            ok(!dib.dsBmih.biSizeImage, "Got unexpected image size %u for format %s.\n",
                     dib.dsBmih.biSizeImage, test_data[i].name);
             ok(!dib.dsBmih.biXPelsPerMeter, "Got unexpected horizontal resolution %d for format %s.\n",
                     dib.dsBmih.biXPelsPerMeter, test_data[i].name);
diff --git a/dlls/ddraw/tests/ddraw4.c b/dlls/ddraw/tests/ddraw4.c
index fdf9e58..775b9d6 100644
--- a/dlls/ddraw/tests/ddraw4.c
+++ b/dlls/ddraw/tests/ddraw4.c
@@ -6659,7 +6659,7 @@ static void test_user_memory_getdc(void)
     ok(!!bitmap, "Failed to get bitmap.\n");
     size = GetObjectA(bitmap, sizeof(dib), &dib);
     ok(size == sizeof(dib), "Got unexpected size %d.\n", size);
-    todo_wine ok(dib.dsBm.bmBits == data, "Got unexpected bits %p, expected %p.\n", dib.dsBm.bmBits, data);
+    ok(dib.dsBm.bmBits == data, "Got unexpected bits %p, expected %p.\n", dib.dsBm.bmBits, data);
     BitBlt(dc, 0, 0, 16, 8, NULL, 0, 0, WHITENESS);
     BitBlt(dc, 0, 8, 16, 8, NULL, 0, 0, BLACKNESS);
     hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
@@ -11112,7 +11112,7 @@ static void test_getdc(void)
                     || broken(U2(test_data[i].format).dwRGBBitCount == 32 && dib.dsBmih.biCompression == BI_BITFIELDS),
                     "Got unexpected compression %#x for format %s.\n",
                     dib.dsBmih.biCompression, test_data[i].name);
-            todo_wine ok(!dib.dsBmih.biSizeImage, "Got unexpected image size %u for format %s.\n",
+            ok(!dib.dsBmih.biSizeImage, "Got unexpected image size %u for format %s.\n",
                     dib.dsBmih.biSizeImage, test_data[i].name);
             ok(!dib.dsBmih.biXPelsPerMeter, "Got unexpected horizontal resolution %d for format %s.\n",
                     dib.dsBmih.biXPelsPerMeter, test_data[i].name);
diff --git a/dlls/ddraw/tests/ddraw7.c b/dlls/ddraw/tests/ddraw7.c
index 2fc2796..f4388ca 100644
--- a/dlls/ddraw/tests/ddraw7.c
+++ b/dlls/ddraw/tests/ddraw7.c
@@ -6525,7 +6525,7 @@ static void test_user_memory_getdc(void)
     ok(!!bitmap, "Failed to get bitmap.\n");
     size = GetObjectA(bitmap, sizeof(dib), &dib);
     ok(size == sizeof(dib), "Got unexpected size %d.\n", size);
-    todo_wine ok(dib.dsBm.bmBits == data, "Got unexpected bits %p, expected %p.\n", dib.dsBm.bmBits, data);
+    ok(dib.dsBm.bmBits == data, "Got unexpected bits %p, expected %p.\n", dib.dsBm.bmBits, data);
     BitBlt(dc, 0, 0, 16, 8, NULL, 0, 0, WHITENESS);
     BitBlt(dc, 0, 8, 16, 8, NULL, 0, 0, BLACKNESS);
     hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
@@ -11378,7 +11378,7 @@ static void test_getdc(void)
                     || broken(U2(test_data[i].format).dwRGBBitCount == 32 && dib.dsBmih.biCompression == BI_BITFIELDS),
                     "Got unexpected compression %#x for format %s.\n",
                     dib.dsBmih.biCompression, test_data[i].name);
-            todo_wine ok(!dib.dsBmih.biSizeImage, "Got unexpected image size %u for format %s.\n",
+            ok(!dib.dsBmih.biSizeImage, "Got unexpected image size %u for format %s.\n",
                     dib.dsBmih.biSizeImage, test_data[i].name);
             ok(!dib.dsBmih.biXPelsPerMeter, "Got unexpected horizontal resolution %d for format %s.\n",
                     dib.dsBmih.biXPelsPerMeter, test_data[i].name);
diff --git a/dlls/wined3d/palette.c b/dlls/wined3d/palette.c
index 0d7bfa4..fadcc43 100644
--- a/dlls/wined3d/palette.c
+++ b/dlls/wined3d/palette.c
@@ -20,11 +20,6 @@
  */
 #include "config.h"
 #include "wine/port.h"
-#include "winerror.h"
-#include "wine/debug.h"
-
-#include <string.h>
-
 #include "wined3d_private.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c
index de82dda..9dfefe0 100644
--- a/dlls/wined3d/surface.c
+++ b/dlls/wined3d/surface.c
@@ -35,9 +35,8 @@ WINE_DECLARE_DEBUG_CHANNEL(d3d_perf);
 
 #define MAXLOCKCOUNT 50 /* After this amount of locks do not free the sysmem copy. */
 
-static const DWORD surface_simple_locations =
-        WINED3D_LOCATION_SYSMEM | WINED3D_LOCATION_USER_MEMORY
-        | WINED3D_LOCATION_DIB | WINED3D_LOCATION_BUFFER;
+static const DWORD surface_simple_locations = WINED3D_LOCATION_SYSMEM
+        | WINED3D_LOCATION_USER_MEMORY | WINED3D_LOCATION_BUFFER;
 
 void wined3d_surface_cleanup(struct wined3d_surface *surface)
 {
@@ -80,12 +79,8 @@ void wined3d_surface_cleanup(struct wined3d_surface *surface)
         context_release(context);
     }
 
-    if (surface->flags & SFLAG_DIBSECTION)
-    {
-        DeleteDC(surface->hDC);
-        DeleteObject(surface->dib.DIBsection);
-        surface->dib.bitmap_data = NULL;
-    }
+    if (surface->dc)
+        wined3d_surface_destroy_dc(surface);
 
     if (surface->overlay_dest)
         list_remove(&surface->overlay_entry);
@@ -348,110 +343,100 @@ static void get_color_masks(const struct wined3d_format *format, DWORD *masks)
     masks[2] = ((1u << format->blue_size) - 1) << format->blue_offset;
 }
 
-HRESULT surface_create_dib_section(struct wined3d_surface *surface)
+void wined3d_surface_destroy_dc(struct wined3d_surface *surface)
 {
+    unsigned int sub_resource_idx = surface_get_sub_resource_idx(surface);
     struct wined3d_texture *texture = surface->container;
-    const struct wined3d_format *format = texture->resource.format;
-    unsigned int format_flags = texture->resource.format_flags;
-    unsigned int row_pitch, slice_pitch;
-    BITMAPINFO *b_info;
-    DWORD *masks;
-
-    TRACE("surface %p.\n", surface);
+    struct wined3d_device *device = texture->resource.device;
+    const struct wined3d_gl_info *gl_info = NULL;
+    D3DKMT_DESTROYDCFROMMEMORY destroy_desc;
+    struct wined3d_context *context = NULL;
+    struct wined3d_bo_address data;
+    NTSTATUS status;
 
-    if (!(format_flags & WINED3DFMT_FLAG_GETDC))
+    if (!surface->dc)
     {
-        WARN("Cannot use GetDC on a %s surface.\n", debug_d3dformat(format->id));
-        return WINED3DERR_INVALIDCALL;
+        ERR("Surface %p has no DC.\n", surface);
+        return;
     }
 
-    switch (format->byte_count)
-    {
-        case 2:
-        case 4:
-            /* Allocate extra space to store the RGB bit masks. */
-            b_info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, FIELD_OFFSET(BITMAPINFO, bmiColors[3]));
-            break;
+    TRACE("dc %p, bitmap %p.\n", surface->dc, surface->bitmap);
 
-        case 3:
-            b_info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, FIELD_OFFSET(BITMAPINFO, bmiColors[0]));
-            break;
+    destroy_desc.hDc = surface->dc;
+    destroy_desc.hBitmap = surface->bitmap;
+    if ((status = D3DKMTDestroyDCFromMemory(&destroy_desc)))
+        ERR("Failed to destroy dc, status %#x.\n", status);
+    surface->dc = NULL;
+    surface->bitmap = NULL;
 
-        default:
-            /* Allocate extra space for a palette. */
-            b_info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
-                    FIELD_OFFSET(BITMAPINFO, bmiColors[1u << (format->byte_count * 8)]));
-            break;
+    if (device->d3d_initialized)
+    {
+        context = context_acquire(device, NULL);
+        gl_info = context->gl_info;
     }
 
-    if (!b_info)
-        return E_OUTOFMEMORY;
+    wined3d_texture_get_memory(texture, sub_resource_idx, &data, surface->resource.map_binding);
+    wined3d_texture_unmap_bo_address(&data, gl_info, GL_PIXEL_UNPACK_BUFFER);
 
-    b_info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
-    wined3d_texture_get_pitch(texture, surface->texture_level, &row_pitch, &slice_pitch);
-    b_info->bmiHeader.biWidth = row_pitch / format->byte_count;
-    b_info->bmiHeader.biHeight = 0 - wined3d_texture_get_level_height(texture, surface->texture_level);
-    b_info->bmiHeader.biSizeImage = slice_pitch;
-    b_info->bmiHeader.biPlanes = 1;
-    b_info->bmiHeader.biBitCount = format->byte_count * 8;
-
-    b_info->bmiHeader.biXPelsPerMeter = 0;
-    b_info->bmiHeader.biYPelsPerMeter = 0;
-    b_info->bmiHeader.biClrUsed = 0;
-    b_info->bmiHeader.biClrImportant = 0;
-
-    /* Get the bit masks */
-    masks = (DWORD *)b_info->bmiColors;
-    switch (format->id)
-    {
-        case WINED3DFMT_B8G8R8_UNORM:
-            b_info->bmiHeader.biCompression = BI_RGB;
-            break;
+    if (context)
+        context_release(context);
+}
 
-        case WINED3DFMT_B5G5R5X1_UNORM:
-        case WINED3DFMT_B5G5R5A1_UNORM:
-        case WINED3DFMT_B4G4R4A4_UNORM:
-        case WINED3DFMT_B4G4R4X4_UNORM:
-        case WINED3DFMT_B2G3R3_UNORM:
-        case WINED3DFMT_B2G3R3A8_UNORM:
-        case WINED3DFMT_R10G10B10A2_UNORM:
-        case WINED3DFMT_R8G8B8A8_UNORM:
-        case WINED3DFMT_R8G8B8X8_UNORM:
-        case WINED3DFMT_B10G10R10A2_UNORM:
-        case WINED3DFMT_B5G6R5_UNORM:
-        case WINED3DFMT_R16G16B16A16_UNORM:
-            b_info->bmiHeader.biCompression = BI_BITFIELDS;
-            get_color_masks(format, masks);
-            break;
+HRESULT wined3d_surface_create_dc(struct wined3d_surface *surface)
+{
+    unsigned int sub_resource_idx = surface_get_sub_resource_idx(surface);
+    struct wined3d_texture *texture = surface->container;
+    const struct wined3d_format *format = texture->resource.format;
+    struct wined3d_device *device = texture->resource.device;
+    const struct wined3d_gl_info *gl_info = NULL;
+    struct wined3d_context *context = NULL;
+    unsigned int row_pitch, slice_pitch;
+    struct wined3d_bo_address data;
+    D3DKMT_CREATEDCFROMMEMORY desc;
+    NTSTATUS status;
 
-        default:
-            /* Don't know palette */
-            b_info->bmiHeader.biCompression = BI_RGB;
-            break;
+    TRACE("surface %p.\n", surface);
+
+    if (!format->ddi_format)
+    {
+        WARN("Cannot create a DC for format %s.\n", debug_d3dformat(format->id));
+        return WINED3DERR_INVALIDCALL;
     }
 
-    TRACE("Creating a DIB section with size %dx%dx%d, size=%d.\n",
-            b_info->bmiHeader.biWidth, b_info->bmiHeader.biHeight,
-            b_info->bmiHeader.biBitCount, b_info->bmiHeader.biSizeImage);
-    surface->dib.DIBsection = CreateDIBSection(0, b_info, DIB_RGB_COLORS, &surface->dib.bitmap_data, 0, 0);
+    wined3d_texture_get_pitch(texture, surface->texture_level, &row_pitch, &slice_pitch);
 
-    if (!surface->dib.DIBsection)
+    if (device->d3d_initialized)
     {
-        ERR("Failed to create DIB section.\n");
-        HeapFree(GetProcessHeap(), 0, b_info);
-        return HRESULT_FROM_WIN32(GetLastError());
+        context = context_acquire(device, NULL);
+        gl_info = context->gl_info;
     }
 
-    TRACE("DIBSection at %p.\n", surface->dib.bitmap_data);
-    surface->dib.bitmap_size = b_info->bmiHeader.biSizeImage;
+    wined3d_texture_get_memory(texture, sub_resource_idx, &data, surface->resource.map_binding);
+    desc.pMemory = wined3d_texture_map_bo_address(&data, surface->resource.size,
+            gl_info, GL_PIXEL_UNPACK_BUFFER, 0);
 
-    HeapFree(GetProcessHeap(), 0, b_info);
+    if (context)
+        context_release(context);
 
-    /* Now allocate a DC. */
-    surface->hDC = CreateCompatibleDC(0);
-    SelectObject(surface->hDC, surface->dib.DIBsection);
+    desc.Format = format->ddi_format;
+    desc.Width = wined3d_texture_get_level_width(texture, surface->texture_level);
+    desc.Height = wined3d_texture_get_level_height(texture, surface->texture_level);
+    desc.Pitch = row_pitch;
+    desc.hDeviceDc = CreateCompatibleDC(NULL);
+    desc.pColorTable = NULL;
 
-    surface->flags |= SFLAG_DIBSECTION;
+    status = D3DKMTCreateDCFromMemory(&desc);
+    DeleteDC(desc.hDeviceDc);
+    if (status)
+    {
+        WARN("Failed to create DC, status %#x.\n", status);
+        return WINED3DERR_INVALIDCALL;
+    }
+
+    surface->dc = desc.hDc;
+    surface->bitmap = desc.hBitmap;
+
+    TRACE("Created DC %p, bitmap %p for surface %p.\n", surface->dc, surface->bitmap, surface);
 
     return WINED3D_OK;
 }
@@ -2905,7 +2890,6 @@ static DWORD resource_access_from_location(DWORD location)
     {
         case WINED3D_LOCATION_SYSMEM:
         case WINED3D_LOCATION_USER_MEMORY:
-        case WINED3D_LOCATION_DIB:
         case WINED3D_LOCATION_BUFFER:
             return WINED3D_RESOURCE_ACCESS_CPU;
 
@@ -3132,11 +3116,7 @@ static HRESULT surface_load_texture(struct wined3d_surface *surface,
     {
         TRACE("Removing the pbo attached to surface %p.\n", surface);
 
-        if (surface->flags & SFLAG_DIBSECTION)
-            surface->resource.map_binding = WINED3D_LOCATION_DIB;
-        else
-            surface->resource.map_binding = WINED3D_LOCATION_SYSMEM;
-
+        surface->resource.map_binding = WINED3D_LOCATION_SYSMEM;
         surface_load_location(surface, context, surface->resource.map_binding);
         wined3d_texture_remove_buffer_object(texture, sub_resource_idx, gl_info);
     }
@@ -3275,7 +3255,6 @@ HRESULT surface_load_location(struct wined3d_surface *surface, struct wined3d_co
 
     switch (location)
     {
-        case WINED3D_LOCATION_DIB:
         case WINED3D_LOCATION_USER_MEMORY:
         case WINED3D_LOCATION_SYSMEM:
         case WINED3D_LOCATION_BUFFER:
@@ -4567,26 +4546,6 @@ HRESULT wined3d_surface_init(struct wined3d_surface *surface, struct wined3d_tex
     if (wined3d_texture_use_pbo(container, gl_info))
         surface->resource.map_binding = WINED3D_LOCATION_BUFFER;
 
-    /* Similar to lockable rendertargets above, creating the DIB section
-     * during surface initialization prevents the sysmem pointer from changing
-     * after a wined3d_texture_get_dc() call. */
-    if ((desc->usage & WINED3DUSAGE_OWNDC) || (device->wined3d->flags & WINED3D_NO3D))
-    {
-        if (FAILED(hr = surface_create_dib_section(surface)))
-        {
-            wined3d_surface_cleanup(surface);
-            return hr;
-        }
-        surface->resource.map_binding = WINED3D_LOCATION_DIB;
-    }
-
-    if (surface->resource.map_binding == WINED3D_LOCATION_DIB)
-    {
-        wined3d_resource_free_sysmem(&surface->resource);
-        wined3d_texture_validate_location(container, sub_resource_idx, WINED3D_LOCATION_DIB);
-        wined3d_texture_invalidate_location(container, sub_resource_idx, WINED3D_LOCATION_SYSMEM);
-    }
-
     return hr;
 }
 
@@ -4607,11 +4566,6 @@ void wined3d_surface_prepare(struct wined3d_surface *surface, struct wined3d_con
                 ERR("Map binding is set to WINED3D_LOCATION_USER_MEMORY but surface->user_memory is NULL.\n");
             break;
 
-        case WINED3D_LOCATION_DIB:
-            if (!surface->dib.bitmap_data)
-                ERR("Map binding is set to WINED3D_LOCATION_DIB but surface->dib.bitmap_data is NULL.\n");
-            break;
-
         case WINED3D_LOCATION_BUFFER:
             wined3d_texture_prepare_buffer_object(texture,
                     surface_get_sub_resource_idx(surface), context->gl_info);
diff --git a/dlls/wined3d/swapchain.c b/dlls/wined3d/swapchain.c
index e5c7da6..e9e6bfa 100644
--- a/dlls/wined3d/swapchain.c
+++ b/dlls/wined3d/swapchain.c
@@ -661,16 +661,14 @@ static void swapchain_gdi_frontbuffer_updated(struct wined3d_swapchain *swapchai
 
     front = swapchain->front_buffer->sub_resources[0].u.surface;
     if (swapchain->palette)
-        wined3d_palette_apply_to_dc(swapchain->palette, front->hDC);
+        wined3d_palette_apply_to_dc(swapchain->palette, front->dc);
 
     if (front->container->resource.map_count)
         ERR("Trying to blit a mapped surface.\n");
 
     TRACE("Copying surface %p to screen.\n", front);
 
-    surface_load_location(front, NULL, WINED3D_LOCATION_DIB);
-
-    src_dc = front->hDC;
+    src_dc = front->dc;
     window = swapchain->win_handle;
     dst_dc = GetDCEx(window, 0, DCX_CLIPSIBLINGS | DCX_CACHE);
 
@@ -699,40 +697,25 @@ static void swapchain_gdi_present(struct wined3d_swapchain *swapchain,
         const RECT *src_rect, const RECT *dst_rect, DWORD flags)
 {
     struct wined3d_surface *front, *back;
+    HBITMAP bitmap;
+    void *data;
+    HDC dc;
 
     front = swapchain->front_buffer->sub_resources[0].u.surface;
     back = swapchain->back_buffers[0]->sub_resources[0].u.surface;
 
-    /* Flip the DC. */
-    {
-        HDC tmp;
-        tmp = front->hDC;
-        front->hDC = back->hDC;
-        back->hDC = tmp;
-    }
-
-    /* Flip the DIBsection. */
-    {
-        HBITMAP tmp;
-        tmp = front->dib.DIBsection;
-        front->dib.DIBsection = back->dib.DIBsection;
-        back->dib.DIBsection = tmp;
-    }
-
     /* Flip the surface data. */
-    {
-        void *tmp;
+    dc = front->dc;
+    bitmap = front->bitmap;
+    data = front->resource.heap_memory;
 
-        tmp = front->dib.bitmap_data;
-        front->dib.bitmap_data = back->dib.bitmap_data;
-        back->dib.bitmap_data = tmp;
+    front->dc = back->dc;
+    front->bitmap = back->bitmap;
+    front->resource.heap_memory = back->resource.heap_memory;
 
-        if (front->resource.heap_memory)
-            ERR("GDI Surface %p has heap memory allocated.\n", front);
-
-        if (back->resource.heap_memory)
-            ERR("GDI Surface %p has heap memory allocated.\n", back);
-    }
+    back->dc = dc;
+    back->bitmap = bitmap;
+    back->resource.heap_memory = data;
 
     /* FPS support */
     if (TRACE_ON(fps))
diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c
index 50c5b2c..55d2a8e 100644
--- a/dlls/wined3d/texture.c
+++ b/dlls/wined3d/texture.c
@@ -105,7 +105,7 @@ void wined3d_texture_invalidate_location(struct wined3d_texture *texture,
 }
 
 /* Context activation is done by the caller. */
-static void *wined3d_texture_map_bo_address(const struct wined3d_bo_address *data, size_t size,
+void *wined3d_texture_map_bo_address(const struct wined3d_bo_address *data, size_t size,
         const struct wined3d_gl_info *gl_info, GLenum binding, DWORD flags)
 {
     BYTE *memory;
@@ -133,7 +133,7 @@ static void *wined3d_texture_map_bo_address(const struct wined3d_bo_address *dat
 }
 
 /* Context activation is done by the caller. */
-static void wined3d_texture_unmap_bo_address(const struct wined3d_bo_address *data,
+void wined3d_texture_unmap_bo_address(const struct wined3d_bo_address *data,
         const struct wined3d_gl_info *gl_info, GLenum binding)
 {
     if (!data->buffer_object)
@@ -166,17 +166,6 @@ void wined3d_texture_get_memory(struct wined3d_texture *texture, unsigned int su
         data->buffer_object = 0;
         return;
     }
-    if (locations & WINED3D_LOCATION_DIB)
-    {
-        if (texture->resource.type == WINED3D_RTYPE_TEXTURE_2D)
-        {
-            data->addr = sub_resource->u.surface->dib.bitmap_data;
-            data->buffer_object = 0;
-            return;
-        }
-        ERR("Invalid location WINED3D_LOCATION_DIB for resource type %s.\n",
-                debug_d3dresourcetype(texture->resource.type));
-    }
     if (locations & WINED3D_LOCATION_SYSMEM)
     {
         data->addr = sub_resource->resource->heap_memory;
@@ -903,14 +892,9 @@ HRESULT CDECL wined3d_texture_update_desc(struct wined3d_texture *texture, UINT
 
     sub_resource = &texture->sub_resources[0];
     surface = sub_resource->u.surface;
-    if (surface->flags & SFLAG_DIBSECTION)
-    {
-        DeleteDC(surface->hDC);
-        surface->hDC = NULL;
-        DeleteObject(surface->dib.DIBsection);
-        surface->dib.DIBsection = NULL;
-        surface->dib.bitmap_data = NULL;
-        surface->flags &= ~SFLAG_DIBSECTION;
+    if (surface->dc)
+    {
+        wined3d_surface_destroy_dc(surface);
         create_dib = TRUE;
     }
 
@@ -962,10 +946,6 @@ HRESULT CDECL wined3d_texture_update_desc(struct wined3d_texture *texture, UINT
         sub_resource->resource->map_binding = WINED3D_LOCATION_USER_MEMORY;
         valid_location = WINED3D_LOCATION_USER_MEMORY;
     }
-    else if (create_dib && SUCCEEDED(surface_create_dib_section(surface)))
-    {
-        valid_location = WINED3D_LOCATION_DIB;
-    }
     else
     {
         wined3d_surface_prepare(surface, NULL, WINED3D_LOCATION_SYSMEM);
@@ -977,10 +957,13 @@ HRESULT CDECL wined3d_texture_update_desc(struct wined3d_texture *texture, UINT
      * change it - whatever made us not use PBOs might come back, e.g.
      * color keys. */
     if (sub_resource->resource->map_binding == WINED3D_LOCATION_BUFFER && !wined3d_texture_use_pbo(texture, gl_info))
-        sub_resource->resource->map_binding = surface->dib.DIBsection ? WINED3D_LOCATION_DIB : WINED3D_LOCATION_SYSMEM;
+        sub_resource->resource->map_binding = WINED3D_LOCATION_SYSMEM;
 
     wined3d_texture_validate_location(texture, 0, valid_location);
 
+    if (create_dib)
+        wined3d_surface_create_dc(surface);
+
     return WINED3D_OK;
 }
 
@@ -1693,6 +1676,13 @@ static HRESULT texture_init(struct wined3d_texture *texture, const struct wined3
             texture->sub_resources[idx].resource = &surface->resource;
             texture->sub_resources[idx].u.surface = surface;
             TRACE("Created surface level %u, layer %u @ %p.\n", i, j, surface);
+
+            if (((desc->usage & WINED3DUSAGE_OWNDC) || (device->wined3d->flags & WINED3D_NO3D))
+                    && FAILED(hr = wined3d_surface_create_dc(surface)))
+            {
+                wined3d_texture_cleanup(texture);
+                return hr;
+            }
         }
         /* Calculate the next mipmap level. */
         surface_desc.width = max(1, surface_desc.width >> 1);
@@ -2239,7 +2229,7 @@ HRESULT CDECL wined3d_texture_get_dc(struct wined3d_texture *texture, unsigned i
     struct wined3d_texture_sub_resource *sub_resource;
     struct wined3d_context *context = NULL;
     struct wined3d_surface *surface;
-    HRESULT hr;
+    HRESULT hr = WINED3D_OK;
 
     TRACE("texture %p, sub_resource_idx %u, dc %p.\n", texture, sub_resource_idx, dc);
 
@@ -2260,43 +2250,31 @@ HRESULT CDECL wined3d_texture_get_dc(struct wined3d_texture *texture, unsigned i
     if (device->d3d_initialized)
         context = context_acquire(device, NULL);
 
-    /* Create a DIB section if there isn't a dc yet. */
-    if (!surface->hDC)
-    {
-        if (FAILED(hr = surface_create_dib_section(surface)))
-        {
-            if (context)
-                context_release(context);
-             return WINED3DERR_INVALIDCALL;
-        }
-        if (!(surface->resource.map_binding == WINED3D_LOCATION_USER_MEMORY
-                || texture->flags & WINED3D_TEXTURE_PIN_SYSMEM
-                || texture->sub_resources[sub_resource_idx].buffer_object))
-            surface->resource.map_binding = WINED3D_LOCATION_DIB;
-    }
-
-    surface_load_location(surface, context, WINED3D_LOCATION_DIB);
-    wined3d_texture_invalidate_location(texture, sub_resource_idx, ~WINED3D_LOCATION_DIB);
+    surface_load_location(surface, context, surface->resource.map_binding);
+    wined3d_texture_invalidate_location(texture, sub_resource_idx, ~surface->resource.map_binding);
 
+    if (!surface->dc)
+        hr = wined3d_surface_create_dc(surface);
     if (context)
         context_release(context);
+    if (FAILED(hr))
+        return WINED3DERR_INVALIDCALL;
 
     if (!(texture->flags & WINED3D_TEXTURE_GET_DC_LENIENT))
         texture->flags |= WINED3D_TEXTURE_DC_IN_USE;
     ++texture->resource.map_count;
     ++sub_resource->map_count;
 
-    *dc = surface->hDC;
+    *dc = surface->dc;
     TRACE("Returning dc %p.\n", *dc);
 
-    return WINED3D_OK;
+    return hr;
 }
 
 HRESULT CDECL wined3d_texture_release_dc(struct wined3d_texture *texture, unsigned int sub_resource_idx, HDC dc)
 {
     struct wined3d_device *device = texture->resource.device;
     struct wined3d_texture_sub_resource *sub_resource;
-    struct wined3d_context *context = NULL;
     struct wined3d_surface *surface;
 
     TRACE("texture %p, sub_resource_idx %u, dc %p.\n", texture, sub_resource_idx, dc);
@@ -2315,38 +2293,19 @@ HRESULT CDECL wined3d_texture_release_dc(struct wined3d_texture *texture, unsign
     if (!(texture->flags & (WINED3D_TEXTURE_GET_DC_LENIENT | WINED3D_TEXTURE_DC_IN_USE)))
         return WINED3DERR_INVALIDCALL;
 
-    if (surface->hDC != dc)
+    if (surface->dc != dc)
     {
-        WARN("Application tries to release invalid DC %p, surface DC is %p.\n",
-                dc, surface->hDC);
+        WARN("Application tries to release invalid DC %p, surface DC is %p.\n", dc, surface->dc);
         return WINED3DERR_INVALIDCALL;
     }
 
+    if (!(texture->resource.usage & WINED3DUSAGE_OWNDC) && !(device->wined3d->flags & WINED3D_NO3D))
+        wined3d_surface_destroy_dc(surface);
+
     --sub_resource->map_count;
     --texture->resource.map_count;
     if (!(texture->flags & WINED3D_TEXTURE_GET_DC_LENIENT))
         texture->flags &= ~WINED3D_TEXTURE_DC_IN_USE;
 
-    if (surface->resource.map_binding == WINED3D_LOCATION_USER_MEMORY
-            || (surface->container->flags & WINED3D_TEXTURE_PIN_SYSMEM
-            && surface->resource.map_binding != WINED3D_LOCATION_DIB))
-    {
-        /* The game Salammbo modifies the surface contents without mapping the surface between
-         * a GetDC/ReleaseDC operation and flipping the surface. If the DIB remains the active
-         * copy and is copied to the screen, this update, which draws the mouse pointer, is lost.
-         * Do not only copy the DIB to the map location, but also make sure the map location is
-         * copied back to the DIB in the next getdc call.
-         *
-         * The same consideration applies to user memory surfaces. */
-
-        if (device->d3d_initialized)
-            context = context_acquire(device, NULL);
-
-        surface_load_location(surface, context, surface->resource.map_binding);
-        wined3d_texture_invalidate_location(texture, sub_resource_idx, WINED3D_LOCATION_DIB);
-        if (context)
-            context_release(context);
-    }
-
     return WINED3D_OK;
 }
diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c
index 34df7ff..c0688b5 100644
--- a/dlls/wined3d/utils.c
+++ b/dlls/wined3d/utils.c
@@ -250,6 +250,23 @@ static const struct wined3d_typed_format_info typed_formats[] =
     {WINED3DFMT_B8G8R8X8_UNORM,         WINED3DFMT_B8G8R8X8_TYPELESS,     "uuu"},
 };
 
+struct wined3d_format_ddi_info
+{
+    enum wined3d_format_id id;
+    D3DDDIFORMAT ddi_format;
+};
+
+static const struct wined3d_format_ddi_info ddi_formats[] =
+{
+    {WINED3DFMT_B8G8R8_UNORM,       D3DDDIFMT_R8G8B8},
+    {WINED3DFMT_B8G8R8A8_UNORM,     D3DDDIFMT_A8R8G8B8},
+    {WINED3DFMT_B8G8R8X8_UNORM,     D3DDDIFMT_X8R8G8B8},
+    {WINED3DFMT_B5G6R5_UNORM,       D3DDDIFMT_R5G6B5},
+    {WINED3DFMT_B5G5R5X1_UNORM,     D3DDDIFMT_X1R5G5B5},
+    {WINED3DFMT_B5G5R5A1_UNORM,     D3DDDIFMT_A1R5G5B5},
+    {WINED3DFMT_P8_UINT,            D3DDDIFMT_P8},
+};
+
 struct wined3d_format_base_flags
 {
     enum wined3d_format_id id;
@@ -261,17 +278,6 @@ struct wined3d_format_base_flags
  * resource size. */
 static const struct wined3d_format_base_flags format_base_flags[] =
 {
-    {WINED3DFMT_P8_UINT,            WINED3DFMT_FLAG_GETDC},
-    {WINED3DFMT_B8G8R8_UNORM,       WINED3DFMT_FLAG_GETDC},
-    {WINED3DFMT_B8G8R8A8_UNORM,     WINED3DFMT_FLAG_GETDC},
-    {WINED3DFMT_B8G8R8X8_UNORM,     WINED3DFMT_FLAG_GETDC},
-    {WINED3DFMT_B5G6R5_UNORM,       WINED3DFMT_FLAG_GETDC},
-    {WINED3DFMT_B5G5R5X1_UNORM,     WINED3DFMT_FLAG_GETDC},
-    {WINED3DFMT_B5G5R5A1_UNORM,     WINED3DFMT_FLAG_GETDC},
-    {WINED3DFMT_B4G4R4A4_UNORM,     WINED3DFMT_FLAG_GETDC},
-    {WINED3DFMT_B4G4R4X4_UNORM,     WINED3DFMT_FLAG_GETDC},
-    {WINED3DFMT_R8G8B8A8_UNORM,     WINED3DFMT_FLAG_GETDC},
-    {WINED3DFMT_R8G8B8X8_UNORM,     WINED3DFMT_FLAG_GETDC},
     {WINED3DFMT_ATI1N,              WINED3DFMT_FLAG_BROKEN_PITCH},
     {WINED3DFMT_ATI2N,              WINED3DFMT_FLAG_BROKEN_PITCH},
     {WINED3DFMT_R11G11B10_FLOAT,    WINED3DFMT_FLAG_FLOAT},
@@ -1663,6 +1669,19 @@ static BOOL init_format_base_info(struct wined3d_gl_info *gl_info)
         format_set_flag(format, flags);
     }
 
+    for (i = 0; i < ARRAY_SIZE(ddi_formats); ++i)
+    {
+        int fmt_idx = get_format_idx(ddi_formats[i].id);
+
+        if (fmt_idx == -1)
+        {
+            ERR("Format %s (%#x) not found.\n", debug_d3dformat(ddi_formats[i].id), ddi_formats[i].id);
+            goto fail;
+        }
+
+        gl_info->formats[fmt_idx].ddi_format = ddi_formats[i].ddi_format;
+    }
+
     for (i = 0; i < ARRAY_SIZE(format_base_flags); ++i)
     {
         int fmt_idx = get_format_idx(format_base_flags[i].id);
@@ -5444,7 +5463,6 @@ const char *wined3d_debug_location(DWORD location)
     LOCATION_TO_STR(WINED3D_LOCATION_DISCARDED);
     LOCATION_TO_STR(WINED3D_LOCATION_SYSMEM);
     LOCATION_TO_STR(WINED3D_LOCATION_USER_MEMORY);
-    LOCATION_TO_STR(WINED3D_LOCATION_DIB);
     LOCATION_TO_STR(WINED3D_LOCATION_BUFFER);
     LOCATION_TO_STR(WINED3D_LOCATION_TEXTURE_RGB);
     LOCATION_TO_STR(WINED3D_LOCATION_TEXTURE_SRGB);
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 4f0a9f3..6fd93e9 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -34,6 +34,8 @@
 #include <stdarg.h>
 #include <math.h>
 #include <limits.h>
+#include "ntstatus.h"
+#define WIN32_NO_STATUS
 #define NONAMELESSUNION
 #define NONAMELESSSTRUCT
 #define COBJMACROS
@@ -42,6 +44,8 @@
 #include "winreg.h"
 #include "wingdi.h"
 #include "winuser.h"
+#include "winternl.h"
+#include "ddk/d3dkmthk.h"
 #include "wine/debug.h"
 #include "wine/unicode.h"
 
@@ -2553,6 +2557,8 @@ void wined3d_texture_invalidate_location(struct wined3d_texture *texture,
         unsigned int sub_resource_idx, DWORD location) DECLSPEC_HIDDEN;
 void wined3d_texture_load(struct wined3d_texture *texture,
         struct wined3d_context *context, BOOL srgb) DECLSPEC_HIDDEN;
+void *wined3d_texture_map_bo_address(const struct wined3d_bo_address *data, size_t size,
+        const struct wined3d_gl_info *gl_info, GLenum binding, DWORD flags) DECLSPEC_HIDDEN;
 void wined3d_texture_prepare_buffer_object(struct wined3d_texture *texture,
         unsigned int sub_resource_idx, const struct wined3d_gl_info *gl_info) DECLSPEC_HIDDEN;
 void wined3d_texture_prepare_texture(struct wined3d_texture *texture,
@@ -2562,6 +2568,8 @@ void wined3d_texture_remove_buffer_object(struct wined3d_texture *texture,
 void wined3d_texture_set_dirty(struct wined3d_texture *texture) DECLSPEC_HIDDEN;
 void wined3d_texture_set_swapchain(struct wined3d_texture *texture,
         struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN;
+void wined3d_texture_unmap_bo_address(const struct wined3d_bo_address *data,
+        const struct wined3d_gl_info *gl_info, GLenum binding) DECLSPEC_HIDDEN;
 BOOL wined3d_texture_use_pbo(const struct wined3d_texture *texture,
         const struct wined3d_gl_info *gl_info) DECLSPEC_HIDDEN;
 void wined3d_texture_validate_location(struct wined3d_texture *texture,
@@ -2570,13 +2578,12 @@ void wined3d_texture_validate_location(struct wined3d_texture *texture,
 #define WINED3D_LOCATION_DISCARDED      0x00000001
 #define WINED3D_LOCATION_SYSMEM         0x00000002
 #define WINED3D_LOCATION_USER_MEMORY    0x00000004
-#define WINED3D_LOCATION_DIB            0x00000008
-#define WINED3D_LOCATION_BUFFER         0x00000010
-#define WINED3D_LOCATION_TEXTURE_RGB    0x00000020
-#define WINED3D_LOCATION_TEXTURE_SRGB   0x00000040
-#define WINED3D_LOCATION_DRAWABLE       0x00000080
-#define WINED3D_LOCATION_RB_MULTISAMPLE 0x00000100
-#define WINED3D_LOCATION_RB_RESOLVED    0x00000200
+#define WINED3D_LOCATION_BUFFER         0x00000008
+#define WINED3D_LOCATION_TEXTURE_RGB    0x00000010
+#define WINED3D_LOCATION_TEXTURE_SRGB   0x00000020
+#define WINED3D_LOCATION_DRAWABLE       0x00000040
+#define WINED3D_LOCATION_RB_MULTISAMPLE 0x00000080
+#define WINED3D_LOCATION_RB_RESOLVED    0x00000100
 
 const char *wined3d_debug_location(DWORD location) DECLSPEC_HIDDEN;
 
@@ -2603,13 +2610,6 @@ BOOL wined3d_volume_prepare_location(struct wined3d_volume *volume,
 void wined3d_volume_upload_data(struct wined3d_volume *volume, const struct wined3d_context *context,
         const struct wined3d_const_bo_address *data) DECLSPEC_HIDDEN;
 
-struct wined3d_surface_dib
-{
-    HBITMAP DIBsection;
-    void *bitmap_data;
-    UINT bitmap_size;
-};
-
 struct wined3d_renderbuffer_entry
 {
     struct list entry;
@@ -2657,8 +2657,8 @@ struct wined3d_surface
     unsigned int texture_layer;
 
     /* For GetDC */
-    struct wined3d_surface_dib dib;
-    HDC                       hDC;
+    HBITMAP bitmap;
+    HDC dc;
 
     struct list               renderbuffers;
     const struct wined3d_renderbuffer_entry *current_renderbuffer;
@@ -2706,7 +2706,8 @@ HRESULT wined3d_surface_blt(struct wined3d_surface *dst_surface, const RECT *dst
 void wined3d_surface_cleanup(struct wined3d_surface *surface) DECLSPEC_HIDDEN;
 HRESULT surface_color_fill(struct wined3d_surface *s,
         const RECT *rect, const struct wined3d_color *color) DECLSPEC_HIDDEN;
-HRESULT surface_create_dib_section(struct wined3d_surface *surface) DECLSPEC_HIDDEN;
+HRESULT wined3d_surface_create_dc(struct wined3d_surface *surface) DECLSPEC_HIDDEN;
+void wined3d_surface_destroy_dc(struct wined3d_surface *surface) DECLSPEC_HIDDEN;
 void surface_get_drawable_size(const struct wined3d_surface *surface, const struct wined3d_context *context,
         unsigned int *width, unsigned int *height) DECLSPEC_HIDDEN;
 HRESULT wined3d_surface_init(struct wined3d_surface *surface,
@@ -2734,7 +2735,6 @@ void draw_textured_quad(const struct wined3d_surface *src_surface, struct wined3
         const RECT *src_rect, const RECT *dst_rect, enum wined3d_texture_filter_type filter) DECLSPEC_HIDDEN;
 
 /* Surface flags: */
-#define SFLAG_DIBSECTION        0x00000001 /* Has a DIB section attached for GetDC. */
 #define SFLAG_DISCARD           0x00000002 /* ??? */
 
 struct wined3d_sampler
@@ -3451,6 +3451,7 @@ struct wined3d_format
 {
     enum wined3d_format_id id;
 
+    D3DDDIFORMAT ddi_format;
     DWORD red_size;
     DWORD green_size;
     DWORD blue_size;
-- 
2.1.4




More information about the wine-patches mailing list