wined3d: Implement texture DC creation on top of D3DKMTCreateDCFromMemory().

Signed-off-by: Henri Verbeet <hverbeet@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Henri Verbeet 2016-04-14 19:32:46 +02:00 committed by Alexandre Julliard
parent b08c430c51
commit 82a7f1ebf2
13 changed files with 180 additions and 270 deletions

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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;
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 (!surface->dc)
{
ERR("Surface %p has no DC.\n", surface);
return;
}
TRACE("dc %p, bitmap %p.\n", surface->dc, surface->bitmap);
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;
if (device->d3d_initialized)
{
context = context_acquire(device, NULL);
gl_info = context->gl_info;
}
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);
if (context)
context_release(context);
}
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;
unsigned int format_flags = texture->resource.format_flags;
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;
BITMAPINFO *b_info;
DWORD *masks;
struct wined3d_bo_address data;
D3DKMT_CREATEDCFROMMEMORY desc;
NTSTATUS status;
TRACE("surface %p.\n", surface);
if (!(format_flags & WINED3DFMT_FLAG_GETDC))
if (!format->ddi_format)
{
WARN("Cannot use GetDC on a %s surface.\n", debug_d3dformat(format->id));
WARN("Cannot create a DC for format %s.\n", debug_d3dformat(format->id));
return WINED3DERR_INVALIDCALL;
}
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;
case 3:
b_info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, FIELD_OFFSET(BITMAPINFO, bmiColors[0]));
break;
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 (!b_info)
return E_OUTOFMEMORY;
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)
if (device->d3d_initialized)
{
case WINED3DFMT_B8G8R8_UNORM:
b_info->bmiHeader.biCompression = BI_RGB;
break;
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;
default:
/* Don't know palette */
b_info->bmiHeader.biCompression = BI_RGB;
break;
context = context_acquire(device, NULL);
gl_info = context->gl_info;
}
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_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);
if (!surface->dib.DIBsection)
if (context)
context_release(context);
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;
status = D3DKMTCreateDCFromMemory(&desc);
DeleteDC(desc.hDeviceDc);
if (status)
{
ERR("Failed to create DIB section.\n");
HeapFree(GetProcessHeap(), 0, b_info);
return HRESULT_FROM_WIN32(GetLastError());
WARN("Failed to create DC, status %#x.\n", status);
return WINED3DERR_INVALIDCALL;
}
TRACE("DIBSection at %p.\n", surface->dib.bitmap_data);
surface->dib.bitmap_size = b_info->bmiHeader.biSizeImage;
surface->dc = desc.hDc;
surface->bitmap = desc.hBitmap;
HeapFree(GetProcessHeap(), 0, b_info);
/* Now allocate a DC. */
surface->hDC = CreateCompatibleDC(0);
SelectObject(surface->hDC, surface->dib.DIBsection);
surface->flags |= SFLAG_DIBSECTION;
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_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);

View File

@ -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))

View File

@ -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)
if (surface->dc)
{
DeleteDC(surface->hDC);
surface->hDC = NULL;
DeleteObject(surface->dib.DIBsection);
surface->dib.DIBsection = NULL;
surface->dib.bitmap_data = NULL;
surface->flags &= ~SFLAG_DIBSECTION;
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)))
{
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 (!(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);
if (context)
context_release(context);
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;
}

View File

@ -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);

View File

@ -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;