From f63a84be61f4ef2958c6e0417f982627403b46e0 Mon Sep 17 00:00:00 2001 From: Henri Verbeet Date: Mon, 25 Apr 2011 22:54:13 +0200 Subject: [PATCH] wined3d: Merge surface_base.c into surface.c. --- dlls/wined3d/Makefile.in | 1 - dlls/wined3d/surface.c | 1959 +++++++++++++++++++++++++++++++++++++++- dlls/wined3d/surface_base.c | 1953 --------------------------------------- dlls/wined3d/wined3d_private.h | 46 - 4 files changed, 1956 insertions(+), 2003 deletions(-) delete mode 100644 dlls/wined3d/surface_base.c diff --git a/dlls/wined3d/Makefile.in b/dlls/wined3d/Makefile.in index c0817bbb2c5..63f7b69083e 100644 --- a/dlls/wined3d/Makefile.in +++ b/dlls/wined3d/Makefile.in @@ -23,7 +23,6 @@ C_SRCS = \ state.c \ stateblock.c \ surface.c \ - surface_base.c \ swapchain.c \ texture.c \ utils.c \ diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c index b74cc8b5805..8d03a728f99 100644 --- a/dlls/wined3d/surface.c +++ b/dlls/wined3d/surface.c @@ -334,6 +334,157 @@ void draw_textured_quad(IWineD3DSurfaceImpl *src_surface, const RECT *src_rect, } } +static HRESULT surface_create_dib_section(IWineD3DSurfaceImpl *surface) +{ + const struct wined3d_format *format = surface->resource.format; + SYSTEM_INFO sysInfo; + BITMAPINFO *b_info; + int extraline = 0; + DWORD *masks; + UINT usage; + HDC dc; + + TRACE("surface %p.\n", surface); + + if (!(format->flags & WINED3DFMT_FLAG_GETDC)) + { + WARN("Cannot use GetDC on a %s surface.\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, sizeof(BITMAPINFOHEADER) + 3 * sizeof(DWORD)); + break; + + case 3: + b_info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER)); + break; + + default: + /* Allocate extra space for a palette. */ + b_info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * (1 << (format->byte_count * 8))); + break; + } + + if (!b_info) + return E_OUTOFMEMORY; + + /* Some applications access the surface in via DWORDs, and do not take + * the necessary care at the end of the surface. So we need at least + * 4 extra bytes at the end of the surface. Check against the page size, + * if the last page used for the surface has at least 4 spare bytes we're + * safe, otherwise add an extra line to the DIB section. */ + GetSystemInfo(&sysInfo); + if( ((surface->resource.size + 3) % sysInfo.dwPageSize) < 4) + { + extraline = 1; + TRACE("Adding an extra line to the DIB section.\n"); + } + + b_info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + /* TODO: Is there a nicer way to force a specific alignment? (8 byte for ddraw) */ + b_info->bmiHeader.biWidth = IWineD3DSurface_GetPitch((IWineD3DSurface *)surface) / format->byte_count; + b_info->bmiHeader.biHeight = -surface->resource.height - extraline; + b_info->bmiHeader.biSizeImage = (surface->resource.height + extraline) + * IWineD3DSurface_GetPitch((IWineD3DSurface *)surface); + 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 (surface->resource.format->id) + { + case WINED3DFMT_B8G8R8_UNORM: + usage = DIB_RGB_COLORS; + 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: + usage = 0; + b_info->bmiHeader.biCompression = BI_BITFIELDS; + masks[0] = format->red_mask; + masks[1] = format->green_mask; + masks[2] = format->blue_mask; + break; + + default: + /* Don't know palette */ + b_info->bmiHeader.biCompression = BI_RGB; + usage = 0; + break; + } + + if (!(dc = GetDC(0))) + { + HeapFree(GetProcessHeap(), 0, b_info); + return HRESULT_FROM_WIN32(GetLastError()); + } + + 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(dc, b_info, usage, &surface->dib.bitmap_data, 0, 0); + ReleaseDC(0, dc); + + if (!surface->dib.DIBsection) + { + ERR("Failed to create DIB section.\n"); + HeapFree(GetProcessHeap(), 0, b_info); + return HRESULT_FROM_WIN32(GetLastError()); + } + + TRACE("DIBSection at %p.\n", surface->dib.bitmap_data); + /* Copy the existing surface to the dib section. */ + if (surface->resource.allocatedMemory) + { + memcpy(surface->dib.bitmap_data, surface->resource.allocatedMemory, + surface->resource.height * IWineD3DSurface_GetPitch((IWineD3DSurface *)surface)); + } + else + { + /* This is to make maps read the GL texture although memory is allocated. */ + surface->flags &= ~SFLAG_INSYSMEM; + } + surface->dib.bitmap_size = b_info->bmiHeader.biSizeImage; + + HeapFree(GetProcessHeap(), 0, b_info); + + /* Now allocate a DC. */ + surface->hDC = CreateCompatibleDC(0); + surface->dib.holdbitmap = SelectObject(surface->hDC, surface->dib.DIBsection); + TRACE("Using wined3d palette %p.\n", surface->palette); + SelectPalette(surface->hDC, surface->palette ? surface->palette->hpal : 0, FALSE); + + surface->flags |= SFLAG_DIBSECTION; + + HeapFree(GetProcessHeap(), 0, surface->resource.heapMemory); + surface->resource.heapMemory = NULL; + + return WINED3D_OK; +} + + static HRESULT surface_private_setup(struct IWineD3DSurfaceImpl *surface) { /* TODO: Check against the maximum texture sizes supported by the video card. */ @@ -656,7 +807,7 @@ static HRESULT gdi_surface_private_setup(IWineD3DSurfaceImpl *surface) /* Sysmem textures have memory already allocated - release it, * this avoids an unnecessary memcpy. */ - hr = IWineD3DBaseSurfaceImpl_CreateDIBSection((IWineD3DSurface *)surface); + hr = surface_create_dib_section(surface); if (SUCCEEDED(hr)) { HeapFree(GetProcessHeap(), 0, surface->resource.heapMemory); @@ -1485,6 +1636,1808 @@ HRESULT surface_load(IWineD3DSurfaceImpl *surface, BOOL srgb) return WINED3D_OK; } +/* See also float_16_to_32() in wined3d_private.h */ +static inline unsigned short float_32_to_16(const float *in) +{ + int exp = 0; + float tmp = fabs(*in); + unsigned int mantissa; + unsigned short ret; + + /* Deal with special numbers */ + if (*in == 0.0f) + return 0x0000; + if (isnan(*in)) + return 0x7c01; + if (isinf(*in)) + return (*in < 0.0f ? 0xfc00 : 0x7c00); + + if (tmp < powf(2, 10)) + { + do + { + tmp = tmp * 2.0f; + exp--; + } while (tmp < powf(2, 10)); + } + else if (tmp >= powf(2, 11)) + { + do + { + tmp /= 2.0f; + exp++; + } while (tmp >= powf(2, 11)); + } + + mantissa = (unsigned int)tmp; + if (tmp - mantissa >= 0.5f) + ++mantissa; /* Round to nearest, away from zero. */ + + exp += 10; /* Normalize the mantissa. */ + exp += 15; /* Exponent is encoded with excess 15. */ + + if (exp > 30) /* too big */ + { + ret = 0x7c00; /* INF */ + } + else if (exp <= 0) + { + /* exp == 0: Non-normalized mantissa. Returns 0x0000 (=0.0) for too small numbers. */ + while (exp <= 0) + { + mantissa = mantissa >> 1; + ++exp; + } + ret = mantissa & 0x3ff; + } + else + { + ret = (exp << 10) | (mantissa & 0x3ff); + } + + ret |= ((*in < 0.0f ? 1 : 0) << 15); /* Add the sign */ + return ret; +} + +static HRESULT WINAPI IWineD3DBaseSurfaceImpl_QueryInterface(IWineD3DSurface *iface, + REFIID riid, void **object) +{ + TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object); + + if (IsEqualGUID(riid, &IID_IWineD3DSurface) + || IsEqualGUID(riid, &IID_IUnknown)) + { + IUnknown_AddRef(iface); + *object = iface; + return S_OK; + } + + WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid)); + + *object = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI IWineD3DBaseSurfaceImpl_AddRef(IWineD3DSurface *iface) +{ + IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *)iface; + ULONG refcount; + + TRACE("Surface %p, container %p of type %#x.\n", + surface, surface->container.u.base, surface->container.type); + + switch (surface->container.type) + { + case WINED3D_CONTAINER_TEXTURE: + return wined3d_texture_incref(surface->container.u.texture); + + case WINED3D_CONTAINER_SWAPCHAIN: + return wined3d_swapchain_incref(surface->container.u.swapchain); + + default: + ERR("Unhandled container type %#x.\n", surface->container.type); + case WINED3D_CONTAINER_NONE: + break; + } + + refcount = InterlockedIncrement(&surface->resource.ref); + TRACE("%p increasing refcount to %u.\n", surface, refcount); + + return refcount; +} + +static HRESULT WINAPI IWineD3DBaseSurfaceImpl_SetPrivateData(IWineD3DSurface *iface, + REFGUID riid, const void *data, DWORD data_size, DWORD flags) +{ + return resource_set_private_data(&((IWineD3DSurfaceImpl *)iface)->resource, riid, data, data_size, flags); +} + +static HRESULT WINAPI IWineD3DBaseSurfaceImpl_GetPrivateData(IWineD3DSurface *iface, + REFGUID guid, void *data, DWORD *data_size) +{ + return resource_get_private_data(&((IWineD3DSurfaceImpl *)iface)->resource, guid, data, data_size); +} + +static HRESULT WINAPI IWineD3DBaseSurfaceImpl_FreePrivateData(IWineD3DSurface *iface, REFGUID refguid) +{ + return resource_free_private_data(&((IWineD3DSurfaceImpl *)iface)->resource, refguid); +} + +static DWORD WINAPI IWineD3DBaseSurfaceImpl_SetPriority(IWineD3DSurface *iface, DWORD priority) +{ + return resource_set_priority(&((IWineD3DSurfaceImpl *)iface)->resource, priority); +} + +static DWORD WINAPI IWineD3DBaseSurfaceImpl_GetPriority(IWineD3DSurface *iface) +{ + return resource_get_priority(&((IWineD3DSurfaceImpl *)iface)->resource); +} + +static void * WINAPI IWineD3DBaseSurfaceImpl_GetParent(IWineD3DSurface *iface) +{ + TRACE("iface %p.\n", iface); + + return ((IWineD3DSurfaceImpl *)iface)->resource.parent; +} + +static struct wined3d_resource * WINAPI IWineD3DBaseSurfaceImpl_GetResource(IWineD3DSurface *iface) +{ + TRACE("iface %p.\n", iface); + + return &((IWineD3DSurfaceImpl *)iface)->resource; +} + +static HRESULT WINAPI IWineD3DBaseSurfaceImpl_GetBltStatus(IWineD3DSurface *iface, DWORD flags) +{ + TRACE("iface %p, flags %#x.\n", iface, flags); + + switch (flags) + { + case WINEDDGBS_CANBLT: + case WINEDDGBS_ISBLTDONE: + return WINED3D_OK; + + default: + return WINED3DERR_INVALIDCALL; + } +} + +static HRESULT WINAPI IWineD3DBaseSurfaceImpl_GetFlipStatus(IWineD3DSurface *iface, DWORD flags) +{ + /* XXX: DDERR_INVALIDSURFACETYPE */ + + TRACE("iface %p, flags %#x.\n", iface, flags); + + switch (flags) + { + case WINEDDGFS_CANFLIP: + case WINEDDGFS_ISFLIPDONE: + return WINED3D_OK; + + default: + return WINED3DERR_INVALIDCALL; + } +} + +static HRESULT WINAPI IWineD3DBaseSurfaceImpl_IsLost(IWineD3DSurface *iface) +{ + IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *)iface; + + TRACE("iface %p.\n", iface); + + /* D3D8 and 9 loose full devices, ddraw only surfaces. */ + return surface->flags & SFLAG_LOST ? WINED3DERR_DEVICELOST : WINED3D_OK; +} + +static HRESULT WINAPI IWineD3DBaseSurfaceImpl_Restore(IWineD3DSurface *iface) +{ + IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *)iface; + + TRACE("iface %p.\n", iface); + + /* So far we don't lose anything :) */ + surface->flags &= ~SFLAG_LOST; + return WINED3D_OK; +} + +static HRESULT WINAPI IWineD3DBaseSurfaceImpl_SetPalette(IWineD3DSurface *iface, struct wined3d_palette *palette) +{ + IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *)iface; + + TRACE("iface %p, palette %p.\n", iface, palette); + + if (surface->palette == palette) + { + TRACE("Nop palette change.\n"); + return WINED3D_OK; + } + + if (surface->palette && (surface->resource.usage & WINED3DUSAGE_RENDERTARGET)) + surface->palette->flags &= ~WINEDDPCAPS_PRIMARYSURFACE; + + surface->palette = palette; + + if (palette) + { + if (surface->resource.usage & WINED3DUSAGE_RENDERTARGET) + palette->flags |= WINEDDPCAPS_PRIMARYSURFACE; + + surface->surface_ops->surface_realize_palette(surface); + } + + return WINED3D_OK; +} + +static HRESULT WINAPI IWineD3DBaseSurfaceImpl_SetColorKey(IWineD3DSurface *iface, + DWORD flags, const WINEDDCOLORKEY *color_key) +{ + IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *)iface; + + TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key); + + if (flags & WINEDDCKEY_COLORSPACE) + { + FIXME(" colorkey value not supported (%08x) !\n", flags); + return WINED3DERR_INVALIDCALL; + } + + /* Dirtify the surface, but only if a key was changed. */ + if (color_key) + { + switch (flags & ~WINEDDCKEY_COLORSPACE) + { + case WINEDDCKEY_DESTBLT: + surface->DestBltCKey = *color_key; + surface->CKeyFlags |= WINEDDSD_CKDESTBLT; + break; + + case WINEDDCKEY_DESTOVERLAY: + surface->DestOverlayCKey = *color_key; + surface->CKeyFlags |= WINEDDSD_CKDESTOVERLAY; + break; + + case WINEDDCKEY_SRCOVERLAY: + surface->SrcOverlayCKey = *color_key; + surface->CKeyFlags |= WINEDDSD_CKSRCOVERLAY; + break; + + case WINEDDCKEY_SRCBLT: + surface->SrcBltCKey = *color_key; + surface->CKeyFlags |= WINEDDSD_CKSRCBLT; + break; + } + } + else + { + switch (flags & ~WINEDDCKEY_COLORSPACE) + { + case WINEDDCKEY_DESTBLT: + surface->CKeyFlags &= ~WINEDDSD_CKDESTBLT; + break; + + case WINEDDCKEY_DESTOVERLAY: + surface->CKeyFlags &= ~WINEDDSD_CKDESTOVERLAY; + break; + + case WINEDDCKEY_SRCOVERLAY: + surface->CKeyFlags &= ~WINEDDSD_CKSRCOVERLAY; + break; + + case WINEDDCKEY_SRCBLT: + surface->CKeyFlags &= ~WINEDDSD_CKSRCBLT; + break; + } + } + + return WINED3D_OK; +} + +static HRESULT WINAPI IWineD3DBaseSurfaceImpl_GetPalette(IWineD3DSurface *iface, struct wined3d_palette **palette) +{ + IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *) iface; + + TRACE("iface %p, palette %p.\n", iface, palette); + + *palette = surface->palette; + + return WINED3D_OK; +} + +static DWORD WINAPI IWineD3DBaseSurfaceImpl_GetPitch(IWineD3DSurface *iface) +{ + IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *)iface; + const struct wined3d_format *format = surface->resource.format; + DWORD pitch; + + TRACE("iface %p.\n", iface); + + if ((format->flags & (WINED3DFMT_FLAG_COMPRESSED | WINED3DFMT_FLAG_BROKEN_PITCH)) == WINED3DFMT_FLAG_COMPRESSED) + { + /* Since compressed formats are block based, pitch means the amount of + * bytes to the next row of block rather than the next row of pixels. */ + UINT row_block_count = (surface->resource.width + format->block_width - 1) / format->block_width; + pitch = row_block_count * format->block_byte_count; + } + else + { + unsigned char alignment = surface->resource.device->surface_alignment; + pitch = surface->resource.format->byte_count * surface->resource.width; /* Bytes / row */ + pitch = (pitch + alignment - 1) & ~(alignment - 1); + } + + TRACE("Returning %u.\n", pitch); + + return pitch; +} + +static HRESULT WINAPI IWineD3DBaseSurfaceImpl_SetOverlayPosition(IWineD3DSurface *iface, LONG x, LONG y) +{ + IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *)iface; + LONG w, h; + + TRACE("iface %p, x %d, y %d.\n", iface, x, y); + + if (!(surface->resource.usage & WINED3DUSAGE_OVERLAY)) + { + WARN("Not an overlay surface.\n"); + return WINEDDERR_NOTAOVERLAYSURFACE; + } + + w = surface->overlay_destrect.right - surface->overlay_destrect.left; + h = surface->overlay_destrect.bottom - surface->overlay_destrect.top; + surface->overlay_destrect.left = x; + surface->overlay_destrect.top = y; + surface->overlay_destrect.right = x + w; + surface->overlay_destrect.bottom = y + h; + + surface->surface_ops->surface_draw_overlay(surface); + + return WINED3D_OK; +} + +static HRESULT WINAPI IWineD3DBaseSurfaceImpl_GetOverlayPosition(IWineD3DSurface *iface, LONG *x, LONG *y) +{ + IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *)iface; + + TRACE("iface %p, x %p, y %p.\n", iface, x, y); + + if (!(surface->resource.usage & WINED3DUSAGE_OVERLAY)) + { + TRACE("Not an overlay surface.\n"); + return WINEDDERR_NOTAOVERLAYSURFACE; + } + + if (!surface->overlay_dest) + { + TRACE("Overlay not visible.\n"); + *x = 0; + *y = 0; + return WINEDDERR_OVERLAYNOTVISIBLE; + } + + *x = surface->overlay_destrect.left; + *y = surface->overlay_destrect.top; + + TRACE("Returning position %d, %d.\n", *x, *y); + + return WINED3D_OK; +} + +static HRESULT WINAPI IWineD3DBaseSurfaceImpl_UpdateOverlayZOrder(IWineD3DSurface *iface, + DWORD flags, IWineD3DSurface *ref) +{ + IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *)iface; + + FIXME("iface %p, flags %#x, ref %p stub!\n", iface, flags, ref); + + if (!(surface->resource.usage & WINED3DUSAGE_OVERLAY)) + { + TRACE("Not an overlay surface.\n"); + return WINEDDERR_NOTAOVERLAYSURFACE; + } + + return WINED3D_OK; +} + +static HRESULT WINAPI IWineD3DBaseSurfaceImpl_UpdateOverlay(IWineD3DSurface *iface, const RECT *src_rect, + IWineD3DSurface *dst_surface, const RECT *dst_rect, DWORD flags, const WINEDDOVERLAYFX *fx) +{ + IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *)iface; + IWineD3DSurfaceImpl *Dst = (IWineD3DSurfaceImpl *)dst_surface; + + TRACE("iface %p, src_rect %s, dst_surface %p, dst_rect %s, flags %#x, fx %p.\n", + iface, wine_dbgstr_rect(src_rect), dst_surface, wine_dbgstr_rect(dst_rect), flags, fx); + + if (!(surface->resource.usage & WINED3DUSAGE_OVERLAY)) + { + WARN("Not an overlay surface.\n"); + return WINEDDERR_NOTAOVERLAYSURFACE; + } + else if (!dst_surface) + { + WARN("Dest surface is NULL.\n"); + return WINED3DERR_INVALIDCALL; + } + + if (src_rect) + { + surface->overlay_srcrect = *src_rect; + } + else + { + surface->overlay_srcrect.left = 0; + surface->overlay_srcrect.top = 0; + surface->overlay_srcrect.right = surface->resource.width; + surface->overlay_srcrect.bottom = surface->resource.height; + } + + if (dst_rect) + { + surface->overlay_destrect = *dst_rect; + } + else + { + surface->overlay_destrect.left = 0; + surface->overlay_destrect.top = 0; + surface->overlay_destrect.right = Dst ? Dst->resource.width : 0; + surface->overlay_destrect.bottom = Dst ? Dst->resource.height : 0; + } + + if (surface->overlay_dest && (surface->overlay_dest != Dst || flags & WINEDDOVER_HIDE)) + { + list_remove(&surface->overlay_entry); + } + + if (flags & WINEDDOVER_SHOW) + { + if (surface->overlay_dest != Dst) + { + surface->overlay_dest = Dst; + list_add_tail(&Dst->overlays, &surface->overlay_entry); + } + } + else if (flags & WINEDDOVER_HIDE) + { + /* tests show that the rectangles are erased on hide */ + surface->overlay_srcrect.left = 0; surface->overlay_srcrect.top = 0; + surface->overlay_srcrect.right = 0; surface->overlay_srcrect.bottom = 0; + surface->overlay_destrect.left = 0; surface->overlay_destrect.top = 0; + surface->overlay_destrect.right = 0; surface->overlay_destrect.bottom = 0; + surface->overlay_dest = NULL; + } + + surface->surface_ops->surface_draw_overlay(surface); + + return WINED3D_OK; +} + +static HRESULT WINAPI IWineD3DBaseSurfaceImpl_SetClipper(IWineD3DSurface *iface, struct wined3d_clipper *clipper) +{ + IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *)iface; + + TRACE("iface %p, clipper %p.\n", iface, clipper); + + surface->clipper = clipper; + + return WINED3D_OK; +} + +static HRESULT WINAPI IWineD3DBaseSurfaceImpl_GetClipper(IWineD3DSurface *iface, struct wined3d_clipper **clipper) +{ + IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *)iface; + + TRACE("iface %p, clipper %p.\n", iface, clipper); + + *clipper = surface->clipper; + if (*clipper) + wined3d_clipper_incref(*clipper); + + return WINED3D_OK; +} + +static HRESULT WINAPI IWineD3DBaseSurfaceImpl_SetFormat(IWineD3DSurface *iface, enum wined3d_format_id format_id) +{ + IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *)iface; + const struct wined3d_format *format = wined3d_get_format(&surface->resource.device->adapter->gl_info, format_id); + + TRACE("iface %p, format %s.\n", iface, debug_d3dformat(format_id)); + + if (surface->resource.format->id != WINED3DFMT_UNKNOWN) + { + FIXME("The format of the surface must be WINED3DFORMAT_UNKNOWN.\n"); + return WINED3DERR_INVALIDCALL; + } + + surface->resource.size = wined3d_format_calculate_size(format, surface->resource.device->surface_alignment, + surface->pow2Width, surface->pow2Height); + surface->flags |= (WINED3DFMT_D16_LOCKABLE == format_id) ? SFLAG_LOCKABLE : 0; + surface->resource.format = format; + + TRACE("size %u, byte_count %u\n", surface->resource.size, format->byte_count); + + return WINED3D_OK; +} + +static void convert_r32_float_r16_float(const BYTE *src, BYTE *dst, + DWORD pitch_in, DWORD pitch_out, unsigned int w, unsigned int h) +{ + unsigned short *dst_s; + const float *src_f; + unsigned int x, y; + + TRACE("Converting %ux%u pixels, pitches %u %u.\n", w, h, pitch_in, pitch_out); + + for (y = 0; y < h; ++y) + { + src_f = (const float *)(src + y * pitch_in); + dst_s = (unsigned short *) (dst + y * pitch_out); + for (x = 0; x < w; ++x) + { + dst_s[x] = float_32_to_16(src_f + x); + } + } +} + +static void convert_r5g6b5_x8r8g8b8(const BYTE *src, BYTE *dst, + DWORD pitch_in, DWORD pitch_out, unsigned int w, unsigned int h) +{ + static const unsigned char convert_5to8[] = + { + 0x00, 0x08, 0x10, 0x19, 0x21, 0x29, 0x31, 0x3a, + 0x42, 0x4a, 0x52, 0x5a, 0x63, 0x6b, 0x73, 0x7b, + 0x84, 0x8c, 0x94, 0x9c, 0xa5, 0xad, 0xb5, 0xbd, + 0xc5, 0xce, 0xd6, 0xde, 0xe6, 0xef, 0xf7, 0xff, + }; + static const unsigned char convert_6to8[] = + { + 0x00, 0x04, 0x08, 0x0c, 0x10, 0x14, 0x18, 0x1c, + 0x20, 0x24, 0x28, 0x2d, 0x31, 0x35, 0x39, 0x3d, + 0x41, 0x45, 0x49, 0x4d, 0x51, 0x55, 0x59, 0x5d, + 0x61, 0x65, 0x69, 0x6d, 0x71, 0x75, 0x79, 0x7d, + 0x82, 0x86, 0x8a, 0x8e, 0x92, 0x96, 0x9a, 0x9e, + 0xa2, 0xa6, 0xaa, 0xae, 0xb2, 0xb6, 0xba, 0xbe, + 0xc2, 0xc6, 0xca, 0xce, 0xd2, 0xd7, 0xdb, 0xdf, + 0xe3, 0xe7, 0xeb, 0xef, 0xf3, 0xf7, 0xfb, 0xff, + }; + unsigned int x, y; + + TRACE("Converting %ux%u pixels, pitches %u %u.\n", w, h, pitch_in, pitch_out); + + for (y = 0; y < h; ++y) + { + const WORD *src_line = (const WORD *)(src + y * pitch_in); + DWORD *dst_line = (DWORD *)(dst + y * pitch_out); + for (x = 0; x < w; ++x) + { + WORD pixel = src_line[x]; + dst_line[x] = 0xff000000 + | convert_5to8[(pixel & 0xf800) >> 11] << 16 + | convert_6to8[(pixel & 0x07e0) >> 5] << 8 + | convert_5to8[(pixel & 0x001f)]; + } + } +} + +static void convert_a8r8g8b8_x8r8g8b8(const BYTE *src, BYTE *dst, + DWORD pitch_in, DWORD pitch_out, unsigned int w, unsigned int h) +{ + unsigned int x, y; + + TRACE("Converting %ux%u pixels, pitches %u %u.\n", w, h, pitch_in, pitch_out); + + for (y = 0; y < h; ++y) + { + const DWORD *src_line = (const DWORD *)(src + y * pitch_in); + DWORD *dst_line = (DWORD *)(dst + y * pitch_out); + + for (x = 0; x < w; ++x) + { + dst_line[x] = 0xff000000 | (src_line[x] & 0xffffff); + } + } +} + +static inline BYTE cliptobyte(int x) +{ + return (BYTE)((x < 0) ? 0 : ((x > 255) ? 255 : x)); +} + +static void convert_yuy2_x8r8g8b8(const BYTE *src, BYTE *dst, + DWORD pitch_in, DWORD pitch_out, unsigned int w, unsigned int h) +{ + int c2, d, e, r2 = 0, g2 = 0, b2 = 0; + unsigned int x, y; + + TRACE("Converting %ux%u pixels, pitches %u %u.\n", w, h, pitch_in, pitch_out); + + for (y = 0; y < h; ++y) + { + const BYTE *src_line = src + y * pitch_in; + DWORD *dst_line = (DWORD *)(dst + y * pitch_out); + for (x = 0; x < w; ++x) + { + /* YUV to RGB conversion formulas from http://en.wikipedia.org/wiki/YUV: + * C = Y - 16; D = U - 128; E = V - 128; + * R = cliptobyte((298 * C + 409 * E + 128) >> 8); + * G = cliptobyte((298 * C - 100 * D - 208 * E + 128) >> 8); + * B = cliptobyte((298 * C + 516 * D + 128) >> 8); + * Two adjacent YUY2 pixels are stored as four bytes: Y0 U Y1 V . + * U and V are shared between the pixels. */ + if (!(x & 1)) /* For every even pixel, read new U and V. */ + { + d = (int) src_line[1] - 128; + e = (int) src_line[3] - 128; + r2 = 409 * e + 128; + g2 = - 100 * d - 208 * e + 128; + b2 = 516 * d + 128; + } + c2 = 298 * ((int) src_line[0] - 16); + dst_line[x] = 0xff000000 + | cliptobyte((c2 + r2) >> 8) << 16 /* red */ + | cliptobyte((c2 + g2) >> 8) << 8 /* green */ + | cliptobyte((c2 + b2) >> 8); /* blue */ + /* Scale RGB values to 0..255 range, + * then clip them if still not in range (may be negative), + * then shift them within DWORD if necessary. */ + src_line += 2; + } + } +} + +static void convert_yuy2_r5g6b5(const BYTE *src, BYTE *dst, + DWORD pitch_in, DWORD pitch_out, unsigned int w, unsigned int h) +{ + unsigned int x, y; + int c2, d, e, r2 = 0, g2 = 0, b2 = 0; + + TRACE("Converting %ux%u pixels, pitches %u %u\n", w, h, pitch_in, pitch_out); + + for (y = 0; y < h; ++y) + { + const BYTE *src_line = src + y * pitch_in; + WORD *dst_line = (WORD *)(dst + y * pitch_out); + for (x = 0; x < w; ++x) + { + /* YUV to RGB conversion formulas from http://en.wikipedia.org/wiki/YUV: + * C = Y - 16; D = U - 128; E = V - 128; + * R = cliptobyte((298 * C + 409 * E + 128) >> 8); + * G = cliptobyte((298 * C - 100 * D - 208 * E + 128) >> 8); + * B = cliptobyte((298 * C + 516 * D + 128) >> 8); + * Two adjacent YUY2 pixels are stored as four bytes: Y0 U Y1 V . + * U and V are shared between the pixels. */ + if (!(x & 1)) /* For every even pixel, read new U and V. */ + { + d = (int) src_line[1] - 128; + e = (int) src_line[3] - 128; + r2 = 409 * e + 128; + g2 = - 100 * d - 208 * e + 128; + b2 = 516 * d + 128; + } + c2 = 298 * ((int) src_line[0] - 16); + dst_line[x] = (cliptobyte((c2 + r2) >> 8) >> 3) << 11 /* red */ + | (cliptobyte((c2 + g2) >> 8) >> 2) << 5 /* green */ + | (cliptobyte((c2 + b2) >> 8) >> 3); /* blue */ + /* Scale RGB values to 0..255 range, + * then clip them if still not in range (may be negative), + * then shift them within DWORD if necessary. */ + src_line += 2; + } + } +} + +struct d3dfmt_convertor_desc +{ + enum wined3d_format_id from, to; + void (*convert)(const BYTE *src, BYTE *dst, DWORD pitch_in, DWORD pitch_out, unsigned int w, unsigned int h); +}; + +static const struct d3dfmt_convertor_desc convertors[] = +{ + {WINED3DFMT_R32_FLOAT, WINED3DFMT_R16_FLOAT, convert_r32_float_r16_float}, + {WINED3DFMT_B5G6R5_UNORM, WINED3DFMT_B8G8R8X8_UNORM, convert_r5g6b5_x8r8g8b8}, + {WINED3DFMT_B8G8R8A8_UNORM, WINED3DFMT_B8G8R8X8_UNORM, convert_a8r8g8b8_x8r8g8b8}, + {WINED3DFMT_YUY2, WINED3DFMT_B8G8R8X8_UNORM, convert_yuy2_x8r8g8b8}, + {WINED3DFMT_YUY2, WINED3DFMT_B5G6R5_UNORM, convert_yuy2_r5g6b5}, +}; + +static inline const struct d3dfmt_convertor_desc *find_convertor(enum wined3d_format_id from, + enum wined3d_format_id to) +{ + unsigned int i; + + for (i = 0; i < (sizeof(convertors) / sizeof(*convertors)); ++i) + { + if (convertors[i].from == from && convertors[i].to == to) + return &convertors[i]; + } + + return NULL; +} + +/***************************************************************************** + * surface_convert_format + * + * Creates a duplicate of a surface in a different format. Is used by Blt to + * blit between surfaces with different formats. + * + * Parameters + * source: Source surface + * fmt: Requested destination format + * + *****************************************************************************/ +static IWineD3DSurfaceImpl *surface_convert_format(IWineD3DSurfaceImpl *source, enum wined3d_format_id to_fmt) +{ + const struct d3dfmt_convertor_desc *conv; + WINED3DLOCKED_RECT lock_src, lock_dst; + IWineD3DSurface *ret = NULL; + HRESULT hr; + + conv = find_convertor(source->resource.format->id, to_fmt); + if (!conv) + { + FIXME("Cannot find a conversion function from format %s to %s.\n", + debug_d3dformat(source->resource.format->id), debug_d3dformat(to_fmt)); + return NULL; + } + + IWineD3DDevice_CreateSurface((IWineD3DDevice *)source->resource.device, source->resource.width, + source->resource.height, to_fmt, TRUE /* lockable */, TRUE /* discard */, 0 /* level */, + 0 /* usage */, WINED3DPOOL_SCRATCH, WINED3DMULTISAMPLE_NONE /* TODO: Multisampled conversion */, + 0 /* MultiSampleQuality */, source->surface_type, NULL /* parent */, &wined3d_null_parent_ops, &ret); + if (!ret) + { + ERR("Failed to create a destination surface for conversion.\n"); + return NULL; + } + + memset(&lock_src, 0, sizeof(lock_src)); + memset(&lock_dst, 0, sizeof(lock_dst)); + + hr = IWineD3DSurface_Map((IWineD3DSurface *)source, &lock_src, NULL, WINED3DLOCK_READONLY); + if (FAILED(hr)) + { + ERR("Failed to lock the source surface.\n"); + IWineD3DSurface_Release(ret); + return NULL; + } + hr = IWineD3DSurface_Map(ret, &lock_dst, NULL, WINED3DLOCK_READONLY); + if (FAILED(hr)) + { + ERR("Failed to lock the destination surface.\n"); + IWineD3DSurface_Unmap((IWineD3DSurface *)source); + IWineD3DSurface_Release(ret); + return NULL; + } + + conv->convert(lock_src.pBits, lock_dst.pBits, lock_src.Pitch, lock_dst.Pitch, + source->resource.width, source->resource.height); + + IWineD3DSurface_Unmap(ret); + IWineD3DSurface_Unmap((IWineD3DSurface *)source); + + return (IWineD3DSurfaceImpl *)ret; +} + +static HRESULT _Blt_ColorFill(BYTE *buf, unsigned int width, unsigned int height, + unsigned int bpp, UINT pitch, DWORD color) +{ + BYTE *first; + int x, y; + + /* Do first row */ + +#define COLORFILL_ROW(type) \ +do { \ + type *d = (type *)buf; \ + for (x = 0; x < width; ++x) \ + d[x] = (type)color; \ +} while(0) + + switch (bpp) + { + case 1: + COLORFILL_ROW(BYTE); + break; + + case 2: + COLORFILL_ROW(WORD); + break; + + case 3: + { + BYTE *d = buf; + for (x = 0; x < width; ++x, d += 3) + { + d[0] = (color ) & 0xFF; + d[1] = (color >> 8) & 0xFF; + d[2] = (color >> 16) & 0xFF; + } + break; + } + case 4: + COLORFILL_ROW(DWORD); + break; + + default: + FIXME("Color fill not implemented for bpp %u!\n", bpp * 8); + return WINED3DERR_NOTAVAILABLE; + } + +#undef COLORFILL_ROW + + /* Now copy first row. */ + first = buf; + for (y = 1; y < height; ++y) + { + buf += pitch; + memcpy(buf, first, width * bpp); + } + + return WINED3D_OK; +} + +/***************************************************************************** + * IWineD3DSurface::Blt, SW emulation version + * + * Performs a blit to a surface, with or without a source surface. + * This is the main functionality of DirectDraw + *****************************************************************************/ +static HRESULT WINAPI IWineD3DBaseSurfaceImpl_Blt(IWineD3DSurface *iface, + const RECT *dst_rect, IWineD3DSurface *src_surface, const RECT *src_rect, + DWORD flags, const WINEDDBLTFX *fx, WINED3DTEXTUREFILTERTYPE filter) +{ + IWineD3DSurfaceImpl *dst_surface = (IWineD3DSurfaceImpl *)iface; + IWineD3DSurfaceImpl *src = (IWineD3DSurfaceImpl *)src_surface; + int bpp, srcheight, srcwidth, dstheight, dstwidth, width; + const struct wined3d_format *src_format, *dst_format; + WINED3DLOCKED_RECT dlock, slock; + HRESULT ret = WINED3D_OK; + const BYTE *sbuf; + RECT xdst,xsrc; + BYTE *dbuf; + int x, y; + + TRACE("iface %p, dst_rect %s, src_surface %p, src_rect %s, flags %#x, fx %p, filter %s.\n", + iface, wine_dbgstr_rect(dst_rect), src_surface, wine_dbgstr_rect(src_rect), + flags, fx, debug_d3dtexturefiltertype(filter)); + + if ((dst_surface->flags & SFLAG_LOCKED) || (src && (src->flags & SFLAG_LOCKED))) + { + WARN(" Surface is busy, returning DDERR_SURFACEBUSY\n"); + return WINEDDERR_SURFACEBUSY; + } + + /* First check for the validity of source / destination rectangles. + * This was verified using a test application and by MSDN. */ + if (src_rect) + { + if (src) + { + if (src_rect->right < src_rect->left || src_rect->bottom < src_rect->top + || src_rect->left > src->resource.width || src_rect->left < 0 + || src_rect->top > src->resource.height || src_rect->top < 0 + || src_rect->right > src->resource.width || src_rect->right < 0 + || src_rect->bottom > src->resource.height || src_rect->bottom < 0) + { + WARN("Application gave us bad source rectangle for Blt.\n"); + return WINEDDERR_INVALIDRECT; + } + + if (!src_rect->right || !src_rect->bottom + || src_rect->left == (int)src->resource.width + || src_rect->top == (int)src->resource.height) + { + TRACE("Nothing to be done.\n"); + return WINED3D_OK; + } + } + + xsrc = *src_rect; + } + else if (src) + { + xsrc.left = 0; + xsrc.top = 0; + xsrc.right = src->resource.width; + xsrc.bottom = src->resource.height; + } + else + { + memset(&xsrc, 0, sizeof(xsrc)); + } + + if (dst_rect) + { + /* For the Destination rect, it can be out of bounds on the condition + * that a clipper is set for the given surface. */ + if (!dst_surface->clipper && (dst_rect->right < dst_rect->left || dst_rect->bottom < dst_rect->top + || dst_rect->left > dst_surface->resource.width || dst_rect->left < 0 + || dst_rect->top > dst_surface->resource.height || dst_rect->top < 0 + || dst_rect->right > dst_surface->resource.width || dst_rect->right < 0 + || dst_rect->bottom > dst_surface->resource.height || dst_rect->bottom < 0)) + { + WARN("Application gave us bad destination rectangle for Blt without a clipper set.\n"); + return WINEDDERR_INVALIDRECT; + } + + if (dst_rect->right <= 0 || dst_rect->bottom <= 0 + || dst_rect->left >= (int)dst_surface->resource.width + || dst_rect->top >= (int)dst_surface->resource.height) + { + TRACE("Nothing to be done.\n"); + return WINED3D_OK; + } + + if (!src) + { + RECT full_rect; + + full_rect.left = 0; + full_rect.top = 0; + full_rect.right = dst_surface->resource.width; + full_rect.bottom = dst_surface->resource.height; + IntersectRect(&xdst, &full_rect, dst_rect); + } + else + { + BOOL clip_horiz, clip_vert; + + xdst = *dst_rect; + clip_horiz = xdst.left < 0 || xdst.right > (int)dst_surface->resource.width; + clip_vert = xdst.top < 0 || xdst.bottom > (int)dst_surface->resource.height; + + if (clip_vert || clip_horiz) + { + /* Now check if this is a special case or not... */ + if ((flags & WINEDDBLT_DDFX) + || (clip_horiz && xdst.right - xdst.left != xsrc.right - xsrc.left) + || (clip_vert && xdst.bottom - xdst.top != xsrc.bottom - xsrc.top)) + { + WARN("Out of screen rectangle in special case. Not handled right now.\n"); + return WINED3D_OK; + } + + if (clip_horiz) + { + if (xdst.left < 0) + { + xsrc.left -= xdst.left; + xdst.left = 0; + } + if (xdst.right > dst_surface->resource.width) + { + xsrc.right -= (xdst.right - (int)dst_surface->resource.width); + xdst.right = (int)dst_surface->resource.width; + } + } + + if (clip_vert) + { + if (xdst.top < 0) + { + xsrc.top -= xdst.top; + xdst.top = 0; + } + if (xdst.bottom > dst_surface->resource.height) + { + xsrc.bottom -= (xdst.bottom - (int)dst_surface->resource.height); + xdst.bottom = (int)dst_surface->resource.height; + } + } + + /* And check if after clipping something is still to be done... */ + if ((xdst.right <= 0) || (xdst.bottom <= 0) + || (xdst.left >= (int)dst_surface->resource.width) + || (xdst.top >= (int)dst_surface->resource.height) + || (xsrc.right <= 0) || (xsrc.bottom <= 0) + || (xsrc.left >= (int)src->resource.width) + || (xsrc.top >= (int)src->resource.height)) + { + TRACE("Nothing to be done after clipping.\n"); + return WINED3D_OK; + } + } + } + } + else + { + xdst.left = 0; + xdst.top = 0; + xdst.right = dst_surface->resource.width; + xdst.bottom = dst_surface->resource.height; + } + + if (src == dst_surface) + { + IWineD3DSurface_Map(iface, &dlock, NULL, 0); + slock = dlock; + src_format = dst_surface->resource.format; + dst_format = src_format; + } + else + { + dst_format = dst_surface->resource.format; + if (src) + { + if (dst_surface->resource.format->id != src->resource.format->id) + { + src = surface_convert_format(src, dst_format->id); + if (!src) + { + /* The conv function writes a FIXME */ + WARN("Cannot convert source surface format to dest format\n"); + goto release; + } + } + IWineD3DSurface_Map((IWineD3DSurface *)src, &slock, NULL, WINED3DLOCK_READONLY); + src_format = src->resource.format; + } + else + { + src_format = dst_format; + } + if (dst_rect) + IWineD3DSurface_Map(iface, &dlock, &xdst, 0); + else + IWineD3DSurface_Map(iface, &dlock, NULL, 0); + } + + if (!fx || !(fx->dwDDFX)) flags &= ~WINEDDBLT_DDFX; + + if (src_format->flags & dst_format->flags & WINED3DFMT_FLAG_FOURCC) + { + if (!dst_rect || src == dst_surface) + { + memcpy(dlock.pBits, slock.pBits, dst_surface->resource.size); + goto release; + } + } + + bpp = dst_surface->resource.format->byte_count; + srcheight = xsrc.bottom - xsrc.top; + srcwidth = xsrc.right - xsrc.left; + dstheight = xdst.bottom - xdst.top; + dstwidth = xdst.right - xdst.left; + width = (xdst.right - xdst.left) * bpp; + + if (dst_rect && src != dst_surface) + dbuf = dlock.pBits; + else + dbuf = (BYTE*)dlock.pBits+(xdst.top*dlock.Pitch)+(xdst.left*bpp); + + if (flags & WINEDDBLT_WAIT) + { + flags &= ~WINEDDBLT_WAIT; + } + if (flags & WINEDDBLT_ASYNC) + { + static BOOL displayed = FALSE; + if (!displayed) + FIXME("Can't handle WINEDDBLT_ASYNC flag right now.\n"); + displayed = TRUE; + flags &= ~WINEDDBLT_ASYNC; + } + if (flags & WINEDDBLT_DONOTWAIT) + { + /* WINEDDBLT_DONOTWAIT appeared in DX7 */ + static BOOL displayed = FALSE; + if (!displayed) + FIXME("Can't handle WINEDDBLT_DONOTWAIT flag right now.\n"); + displayed = TRUE; + flags &= ~WINEDDBLT_DONOTWAIT; + } + + /* First, all the 'source-less' blits */ + if (flags & WINEDDBLT_COLORFILL) + { + ret = _Blt_ColorFill(dbuf, dstwidth, dstheight, bpp, dlock.Pitch, fx->u5.dwFillColor); + flags &= ~WINEDDBLT_COLORFILL; + } + + if (flags & WINEDDBLT_DEPTHFILL) + { + FIXME("DDBLT_DEPTHFILL needs to be implemented!\n"); + } + if (flags & WINEDDBLT_ROP) + { + /* Catch some degenerate cases here. */ + switch (fx->dwROP) + { + case BLACKNESS: + ret = _Blt_ColorFill(dbuf,dstwidth,dstheight,bpp,dlock.Pitch,0); + break; + case 0xAA0029: /* No-op */ + break; + case WHITENESS: + ret = _Blt_ColorFill(dbuf,dstwidth,dstheight,bpp,dlock.Pitch,~0); + break; + case SRCCOPY: /* Well, we do that below? */ + break; + default: + FIXME("Unsupported raster op: %08x Pattern: %p\n", fx->dwROP, fx->u5.lpDDSPattern); + goto error; + } + flags &= ~WINEDDBLT_ROP; + } + if (flags & WINEDDBLT_DDROPS) + { + FIXME("\tDdraw Raster Ops: %08x Pattern: %p\n", fx->dwDDROP, fx->u5.lpDDSPattern); + } + /* Now the 'with source' blits. */ + if (src) + { + const BYTE *sbase; + int sx, xinc, sy, yinc; + + if (!dstwidth || !dstheight) /* Hmm... stupid program? */ + goto release; + + if (filter != WINED3DTEXF_NONE && filter != WINED3DTEXF_POINT + && (srcwidth != dstwidth || srcheight != dstheight)) + { + /* Can happen when d3d9 apps do a StretchRect() call which isn't handled in GL. */ + FIXME("Filter %s not supported in software blit.\n", debug_d3dtexturefiltertype(filter)); + } + + sbase = (BYTE*)slock.pBits+(xsrc.top*slock.Pitch)+xsrc.left*bpp; + xinc = (srcwidth << 16) / dstwidth; + yinc = (srcheight << 16) / dstheight; + + if (!flags) + { + /* No effects, we can cheat here. */ + if (dstwidth == srcwidth) + { + if (dstheight == srcheight) + { + /* No stretching in either direction. This needs to be as + * fast as possible. */ + sbuf = sbase; + + /* Check for overlapping surfaces. */ + if (src != dst_surface || xdst.top < xsrc.top + || xdst.right <= xsrc.left || xsrc.right <= xdst.left) + { + /* No overlap, or dst above src, so copy from top downwards. */ + for (y = 0; y < dstheight; ++y) + { + memcpy(dbuf, sbuf, width); + sbuf += slock.Pitch; + dbuf += dlock.Pitch; + } + } + else if (xdst.top > xsrc.top) + { + /* Copy from bottom upwards. */ + sbuf += (slock.Pitch*dstheight); + dbuf += (dlock.Pitch*dstheight); + for (y = 0; y < dstheight; ++y) + { + sbuf -= slock.Pitch; + dbuf -= dlock.Pitch; + memcpy(dbuf, sbuf, width); + } + } + else + { + /* Src and dst overlapping on the same line, use memmove. */ + for (y = 0; y < dstheight; ++y) + { + memmove(dbuf, sbuf, width); + sbuf += slock.Pitch; + dbuf += dlock.Pitch; + } + } + } + else + { + /* Stretching in y direction only. */ + for (y = sy = 0; y < dstheight; ++y, sy += yinc) + { + sbuf = sbase + (sy >> 16) * slock.Pitch; + memcpy(dbuf, sbuf, width); + dbuf += dlock.Pitch; + } + } + } + else + { + /* Stretching in X direction. */ + int last_sy = -1; + for (y = sy = 0; y < dstheight; ++y, sy += yinc) + { + sbuf = sbase + (sy >> 16) * slock.Pitch; + + if ((sy >> 16) == (last_sy >> 16)) + { + /* This source row is the same as last source row - + * Copy the already stretched row. */ + memcpy(dbuf, dbuf - dlock.Pitch, width); + } + else + { +#define STRETCH_ROW(type) \ +do { \ + const type *s = (const type *)sbuf; \ + type *d = (type *)dbuf; \ + for (x = sx = 0; x < dstwidth; ++x, sx += xinc) \ + d[x] = s[sx >> 16]; \ +} while(0) + + switch(bpp) + { + case 1: + STRETCH_ROW(BYTE); + break; + case 2: + STRETCH_ROW(WORD); + break; + case 4: + STRETCH_ROW(DWORD); + break; + case 3: + { + const BYTE *s; + BYTE *d = dbuf; + for (x = sx = 0; x < dstwidth; x++, sx+= xinc) + { + DWORD pixel; + + s = sbuf + 3 * (sx >> 16); + pixel = s[0] | (s[1] << 8) | (s[2] << 16); + d[0] = (pixel ) & 0xff; + d[1] = (pixel >> 8) & 0xff; + d[2] = (pixel >> 16) & 0xff; + d += 3; + } + break; + } + default: + FIXME("Stretched blit not implemented for bpp %u!\n", bpp * 8); + ret = WINED3DERR_NOTAVAILABLE; + goto error; + } +#undef STRETCH_ROW + } + dbuf += dlock.Pitch; + last_sy = sy; + } + } + } + else + { + LONG dstyinc = dlock.Pitch, dstxinc = bpp; + DWORD keylow = 0xFFFFFFFF, keyhigh = 0, keymask = 0xFFFFFFFF; + DWORD destkeylow = 0x0, destkeyhigh = 0xFFFFFFFF, destkeymask = 0xFFFFFFFF; + if (flags & (WINEDDBLT_KEYSRC | WINEDDBLT_KEYDEST | WINEDDBLT_KEYSRCOVERRIDE | WINEDDBLT_KEYDESTOVERRIDE)) + { + /* The color keying flags are checked for correctness in ddraw */ + if (flags & WINEDDBLT_KEYSRC) + { + keylow = src->SrcBltCKey.dwColorSpaceLowValue; + keyhigh = src->SrcBltCKey.dwColorSpaceHighValue; + } + else if (flags & WINEDDBLT_KEYSRCOVERRIDE) + { + keylow = fx->ddckSrcColorkey.dwColorSpaceLowValue; + keyhigh = fx->ddckSrcColorkey.dwColorSpaceHighValue; + } + + if (flags & WINEDDBLT_KEYDEST) + { + /* Destination color keys are taken from the source surface! */ + destkeylow = src->DestBltCKey.dwColorSpaceLowValue; + destkeyhigh = src->DestBltCKey.dwColorSpaceHighValue; + } + else if (flags & WINEDDBLT_KEYDESTOVERRIDE) + { + destkeylow = fx->ddckDestColorkey.dwColorSpaceLowValue; + destkeyhigh = fx->ddckDestColorkey.dwColorSpaceHighValue; + } + + if (bpp == 1) + { + keymask = 0xff; + } + else + { + keymask = src_format->red_mask + | src_format->green_mask + | src_format->blue_mask; + } + flags &= ~(WINEDDBLT_KEYSRC | WINEDDBLT_KEYDEST | WINEDDBLT_KEYSRCOVERRIDE | WINEDDBLT_KEYDESTOVERRIDE); + } + + if (flags & WINEDDBLT_DDFX) + { + BYTE *dTopLeft, *dTopRight, *dBottomLeft, *dBottomRight, *tmp; + LONG tmpxy; + dTopLeft = dbuf; + dTopRight = dbuf + ((dstwidth - 1) * bpp); + dBottomLeft = dTopLeft + ((dstheight - 1) * dlock.Pitch); + dBottomRight = dBottomLeft + ((dstwidth - 1) * bpp); + + if (fx->dwDDFX & WINEDDBLTFX_ARITHSTRETCHY) + { + /* I don't think we need to do anything about this flag */ + WARN("flags=DDBLT_DDFX nothing done for WINEDDBLTFX_ARITHSTRETCHY\n"); + } + if (fx->dwDDFX & WINEDDBLTFX_MIRRORLEFTRIGHT) + { + tmp = dTopRight; + dTopRight = dTopLeft; + dTopLeft = tmp; + tmp = dBottomRight; + dBottomRight = dBottomLeft; + dBottomLeft = tmp; + dstxinc = dstxinc * -1; + } + if (fx->dwDDFX & WINEDDBLTFX_MIRRORUPDOWN) + { + tmp = dTopLeft; + dTopLeft = dBottomLeft; + dBottomLeft = tmp; + tmp = dTopRight; + dTopRight = dBottomRight; + dBottomRight = tmp; + dstyinc = dstyinc * -1; + } + if (fx->dwDDFX & WINEDDBLTFX_NOTEARING) + { + /* I don't think we need to do anything about this flag */ + WARN("flags=DDBLT_DDFX nothing done for WINEDDBLTFX_NOTEARING\n"); + } + if (fx->dwDDFX & WINEDDBLTFX_ROTATE180) + { + tmp = dBottomRight; + dBottomRight = dTopLeft; + dTopLeft = tmp; + tmp = dBottomLeft; + dBottomLeft = dTopRight; + dTopRight = tmp; + dstxinc = dstxinc * -1; + dstyinc = dstyinc * -1; + } + if (fx->dwDDFX & WINEDDBLTFX_ROTATE270) + { + tmp = dTopLeft; + dTopLeft = dBottomLeft; + dBottomLeft = dBottomRight; + dBottomRight = dTopRight; + dTopRight = tmp; + tmpxy = dstxinc; + dstxinc = dstyinc; + dstyinc = tmpxy; + dstxinc = dstxinc * -1; + } + if (fx->dwDDFX & WINEDDBLTFX_ROTATE90) + { + tmp = dTopLeft; + dTopLeft = dTopRight; + dTopRight = dBottomRight; + dBottomRight = dBottomLeft; + dBottomLeft = tmp; + tmpxy = dstxinc; + dstxinc = dstyinc; + dstyinc = tmpxy; + dstyinc = dstyinc * -1; + } + if (fx->dwDDFX & WINEDDBLTFX_ZBUFFERBASEDEST) + { + /* I don't think we need to do anything about this flag */ + WARN("flags=WINEDDBLT_DDFX nothing done for WINEDDBLTFX_ZBUFFERBASEDEST\n"); + } + dbuf = dTopLeft; + flags &= ~(WINEDDBLT_DDFX); + } + +#define COPY_COLORKEY_FX(type) \ +do { \ + const type *s; \ + type *d = (type *)dbuf, *dx, tmp; \ + for (y = sy = 0; y < dstheight; ++y, sy += yinc) \ + { \ + s = (const type *)(sbase + (sy >> 16) * slock.Pitch); \ + dx = d; \ + for (x = sx = 0; x < dstwidth; ++x, sx += xinc) \ + { \ + tmp = s[sx >> 16]; \ + if (((tmp & keymask) < keylow || (tmp & keymask) > keyhigh) \ + && ((dx[0] & destkeymask) >= destkeylow && (dx[0] & destkeymask) <= destkeyhigh)) \ + { \ + dx[0] = tmp; \ + } \ + dx = (type *)(((BYTE *)dx) + dstxinc); \ + } \ + d = (type *)(((BYTE *)d) + dstyinc); \ + } \ +} while(0) + + switch (bpp) + { + case 1: + COPY_COLORKEY_FX(BYTE); + break; + case 2: + COPY_COLORKEY_FX(WORD); + break; + case 4: + COPY_COLORKEY_FX(DWORD); + break; + case 3: + { + const BYTE *s; + BYTE *d = dbuf, *dx; + for (y = sy = 0; y < dstheight; ++y, sy += yinc) + { + sbuf = sbase + (sy >> 16) * slock.Pitch; + dx = d; + for (x = sx = 0; x < dstwidth; ++x, sx+= xinc) + { + DWORD pixel, dpixel = 0; + s = sbuf + 3 * (sx>>16); + pixel = s[0] | (s[1] << 8) | (s[2] << 16); + dpixel = dx[0] | (dx[1] << 8 ) | (dx[2] << 16); + if (((pixel & keymask) < keylow || (pixel & keymask) > keyhigh) + && ((dpixel & keymask) >= destkeylow || (dpixel & keymask) <= keyhigh)) + { + dx[0] = (pixel ) & 0xff; + dx[1] = (pixel >> 8) & 0xff; + dx[2] = (pixel >> 16) & 0xff; + } + dx += dstxinc; + } + d += dstyinc; + } + break; + } + default: + FIXME("%s color-keyed blit not implemented for bpp %u!\n", + (flags & WINEDDBLT_KEYSRC) ? "Source" : "Destination", bpp * 8); + ret = WINED3DERR_NOTAVAILABLE; + goto error; +#undef COPY_COLORKEY_FX + } + } + } + +error: + if (flags && FIXME_ON(d3d_surface)) + { + FIXME("\tUnsupported flags: %#x.\n", flags); + } + +release: + IWineD3DSurface_Unmap(iface); + if (src && src != dst_surface) + IWineD3DSurface_Unmap((IWineD3DSurface *)src); + /* Release the converted surface, if any. */ + if (src && src_surface != (IWineD3DSurface *)src) + IWineD3DSurface_Release((IWineD3DSurface *)src); + return ret; +} + +static HRESULT WINAPI IWineD3DBaseSurfaceImpl_BltFast(IWineD3DSurface *iface, + DWORD dstx, DWORD dsty, IWineD3DSurface *src_surface, const RECT *rsrc, DWORD trans) +{ + IWineD3DSurfaceImpl *dst_surface = (IWineD3DSurfaceImpl *)iface; + IWineD3DSurfaceImpl *src = (IWineD3DSurfaceImpl *)src_surface; + const struct wined3d_format *src_format, *dst_format; + RECT lock_src, lock_dst, lock_union; + WINED3DLOCKED_RECT dlock, slock; + HRESULT ret = WINED3D_OK; + int bpp, w, h, x, y; + const BYTE *sbuf; + BYTE *dbuf; + RECT rsrc2; + + TRACE("iface %p, dst_x %u, dst_y %u, src_surface %p, src_rect %s, flags %#x.\n", + iface, dstx, dsty, src_surface, wine_dbgstr_rect(rsrc), trans); + + if ((dst_surface->flags & SFLAG_LOCKED) || (src->flags & SFLAG_LOCKED)) + { + WARN(" Surface is busy, returning DDERR_SURFACEBUSY\n"); + return WINEDDERR_SURFACEBUSY; + } + + if (!rsrc) + { + WARN("rsrc is NULL!\n"); + rsrc2.left = 0; + rsrc2.top = 0; + rsrc2.right = src->resource.width; + rsrc2.bottom = src->resource.height; + rsrc = &rsrc2; + } + + /* Check source rect for validity. Copied from normal Blt. Fixes Baldur's Gate. */ + if ((rsrc->bottom > src->resource.height) || (rsrc->bottom < 0) + || (rsrc->top > src->resource.height) || (rsrc->top < 0) + || (rsrc->left > src->resource.width) || (rsrc->left < 0) + || (rsrc->right > src->resource.width) || (rsrc->right < 0) + || (rsrc->right < rsrc->left) || (rsrc->bottom < rsrc->top)) + { + WARN("Application gave us bad source rectangle for BltFast.\n"); + return WINEDDERR_INVALIDRECT; + } + + h = rsrc->bottom - rsrc->top; + if (h > dst_surface->resource.height-dsty) + h = dst_surface->resource.height-dsty; + if (h > src->resource.height-rsrc->top) + h = src->resource.height-rsrc->top; + if (h <= 0) + return WINEDDERR_INVALIDRECT; + + w = rsrc->right - rsrc->left; + if (w > dst_surface->resource.width-dstx) + w = dst_surface->resource.width-dstx; + if (w > src->resource.width-rsrc->left) + w = src->resource.width-rsrc->left; + if (w <= 0) + return WINEDDERR_INVALIDRECT; + + /* Now compute the locking rectangle... */ + lock_src.left = rsrc->left; + lock_src.top = rsrc->top; + lock_src.right = lock_src.left + w; + lock_src.bottom = lock_src.top + h; + + lock_dst.left = dstx; + lock_dst.top = dsty; + lock_dst.right = dstx + w; + lock_dst.bottom = dsty + h; + + bpp = dst_surface->resource.format->byte_count; + + /* We need to lock the surfaces, or we won't get refreshes when done. */ + if (src == dst_surface) + { + int pitch; + + UnionRect(&lock_union, &lock_src, &lock_dst); + + /* Lock the union of the two rectangles */ + ret = IWineD3DSurface_Map(iface, &dlock, &lock_union, 0); + if (FAILED(ret)) + goto error; + + pitch = dlock.Pitch; + slock.Pitch = dlock.Pitch; + + /* Since slock was originally copied from this surface's description, we can just reuse it. */ + sbuf = dst_surface->resource.allocatedMemory + lock_src.top * pitch + lock_src.left * bpp; + dbuf = dst_surface->resource.allocatedMemory + lock_dst.top * pitch + lock_dst.left * bpp; + src_format = src->resource.format; + dst_format = src_format; + } + else + { + ret = IWineD3DSurface_Map(src_surface, &slock, &lock_src, WINED3DLOCK_READONLY); + if (FAILED(ret)) + goto error; + ret = IWineD3DSurface_Map(iface, &dlock, &lock_dst, 0); + if (FAILED(ret)) + goto error; + + sbuf = slock.pBits; + dbuf = dlock.pBits; + TRACE("Dst is at %p, Src is at %p.\n", dbuf, sbuf); + + src_format = src->resource.format; + dst_format = dst_surface->resource.format; + } + + /* Handle compressed surfaces first... */ + if (src_format->flags & dst_format->flags & WINED3DFMT_FLAG_COMPRESSED) + { + UINT row_block_count; + + TRACE("compressed -> compressed copy\n"); + if (trans) + FIXME("trans arg not supported when a compressed surface is involved\n"); + if (dstx || dsty) + FIXME("offset for destination surface is not supported\n"); + if (src->resource.format->id != dst_surface->resource.format->id) + { + FIXME("compressed -> compressed copy only supported for the same type of surface\n"); + ret = WINED3DERR_WRONGTEXTUREFORMAT; + goto error; + } + + row_block_count = (w + dst_format->block_width - 1) / dst_format->block_width; + for (y = 0; y < h; y += dst_format->block_height) + { + memcpy(dbuf, sbuf, row_block_count * dst_format->block_byte_count); + dbuf += dlock.Pitch; + sbuf += slock.Pitch; + } + + goto error; + } + if ((src_format->flags & WINED3DFMT_FLAG_COMPRESSED) && !(dst_format->flags & WINED3DFMT_FLAG_COMPRESSED)) + { + /* TODO: Use the libtxc_dxtn.so shared library to do software + * decompression. */ + ERR("Software decompression not supported.\n"); + goto error; + } + + if (trans & (WINEDDBLTFAST_SRCCOLORKEY | WINEDDBLTFAST_DESTCOLORKEY)) + { + DWORD keylow, keyhigh; + DWORD mask = src->resource.format->red_mask + | src->resource.format->green_mask + | src->resource.format->blue_mask; + + /* For some 8-bit formats like L8 and P8 color masks don't make sense */ + if (!mask && bpp == 1) + mask = 0xff; + + TRACE("Color keyed copy.\n"); + if (trans & WINEDDBLTFAST_SRCCOLORKEY) + { + keylow = src->SrcBltCKey.dwColorSpaceLowValue; + keyhigh = src->SrcBltCKey.dwColorSpaceHighValue; + } + else + { + /* I'm not sure if this is correct. */ + FIXME("WINEDDBLTFAST_DESTCOLORKEY not fully supported yet.\n"); + keylow = dst_surface->DestBltCKey.dwColorSpaceLowValue; + keyhigh = dst_surface->DestBltCKey.dwColorSpaceHighValue; + } + +#define COPYBOX_COLORKEY(type) \ +do { \ + const type *s = (const type *)sbuf; \ + type *d = (type *)dbuf; \ + type tmp; \ + for (y = 0; y < h; y++) \ + { \ + for (x = 0; x < w; x++) \ + { \ + tmp = s[x]; \ + if ((tmp & mask) < keylow || (tmp & mask) > keyhigh) d[x] = tmp; \ + } \ + s = (const type *)((const BYTE *)s + slock.Pitch); \ + d = (type *)((BYTE *)d + dlock.Pitch); \ + } \ +} while(0) + + switch (bpp) + { + case 1: + COPYBOX_COLORKEY(BYTE); + break; + case 2: + COPYBOX_COLORKEY(WORD); + break; + case 4: + COPYBOX_COLORKEY(DWORD); + break; + case 3: + { + const BYTE *s; + DWORD tmp; + BYTE *d; + s = sbuf; + d = dbuf; + for (y = 0; y < h; ++y) + { + for (x = 0; x < w * 3; x += 3) + { + tmp = (DWORD)s[x] + ((DWORD)s[x + 1] << 8) + ((DWORD)s[x + 2] << 16); + if (tmp < keylow || tmp > keyhigh) + { + d[x + 0] = s[x + 0]; + d[x + 1] = s[x + 1]; + d[x + 2] = s[x + 2]; + } + } + s += slock.Pitch; + d += dlock.Pitch; + } + break; + } + default: + FIXME("Source color key blitting not supported for bpp %u.\n", bpp * 8); + ret = WINED3DERR_NOTAVAILABLE; + goto error; + } +#undef COPYBOX_COLORKEY + TRACE("Copy done.\n"); + } + else + { + int width = w * bpp; + INT sbufpitch, dbufpitch; + + TRACE("No color key copy.\n"); + /* Handle overlapping surfaces. */ + if (sbuf < dbuf) + { + sbuf += (h - 1) * slock.Pitch; + dbuf += (h - 1) * dlock.Pitch; + sbufpitch = -slock.Pitch; + dbufpitch = -dlock.Pitch; + } + else + { + sbufpitch = slock.Pitch; + dbufpitch = dlock.Pitch; + } + for (y = 0; y < h; ++y) + { + /* This is pretty easy, a line for line memcpy. */ + memmove(dbuf, sbuf, width); + sbuf += sbufpitch; + dbuf += dbufpitch; + } + TRACE("Copy done.\n"); + } + +error: + if (src == dst_surface) + { + IWineD3DSurface_Unmap(iface); + } + else + { + IWineD3DSurface_Unmap(iface); + IWineD3DSurface_Unmap(src_surface); + } + + return ret; +} + +static HRESULT WINAPI IWineD3DBaseSurfaceImpl_Map(IWineD3DSurface *iface, + WINED3DLOCKED_RECT *locked_rect, const RECT *rect, DWORD flags) +{ + IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *)iface; + + TRACE("iface %p, locked_rect %p, rect %s, flags %#x.\n", + iface, locked_rect, wine_dbgstr_rect(rect), flags); + + locked_rect->Pitch = IWineD3DSurface_GetPitch(iface); + + if (!rect) + { + locked_rect->pBits = surface->resource.allocatedMemory; + surface->lockedRect.left = 0; + surface->lockedRect.top = 0; + surface->lockedRect.right = surface->resource.width; + surface->lockedRect.bottom = surface->resource.height; + } + else + { + const struct wined3d_format *format = surface->resource.format; + + if ((format->flags & (WINED3DFMT_FLAG_COMPRESSED | WINED3DFMT_FLAG_BROKEN_PITCH)) == WINED3DFMT_FLAG_COMPRESSED) + { + /* Compressed textures are block based, so calculate the offset of + * the block that contains the top-left pixel of the locked rectangle. */ + locked_rect->pBits = surface->resource.allocatedMemory + + ((rect->top / format->block_height) * locked_rect->Pitch) + + ((rect->left / format->block_width) * format->block_byte_count); + } + else + { + locked_rect->pBits = surface->resource.allocatedMemory + + (locked_rect->Pitch * rect->top) + + (rect->left * format->byte_count); + } + surface->lockedRect.left = rect->left; + surface->lockedRect.top = rect->top; + surface->lockedRect.right = rect->right; + surface->lockedRect.bottom = rect->bottom; + } + + TRACE("Locked rect %s.\n", wine_dbgstr_rect(&surface->lockedRect)); + TRACE("Returning memory %p, pitch %u.\n", locked_rect->pBits, locked_rect->Pitch); + + return WINED3D_OK; +} /* Do not call while under the GL lock. */ static ULONG WINAPI IWineD3DSurfaceImpl_Release(IWineD3DSurface *iface) { @@ -2356,7 +4309,7 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_GetDC(IWineD3DSurface *iface, HDC *pHD surface_load_location(This, SFLAG_INSYSMEM, NULL); surface_release_client_storage(This); } - hr = IWineD3DBaseSurfaceImpl_CreateDIBSection(iface); + hr = surface_create_dib_section(This); if(FAILED(hr)) return WINED3DERR_INVALIDCALL; /* Use the dib section from now on if we are not using a PBO */ @@ -5313,7 +7266,7 @@ static HRESULT WINAPI IWineGDISurfaceImpl_Map(IWineD3DSurface *iface, { /* This happens on gdi surfaces if the application set a user pointer * and resets it. Recreate the DIB section. */ - IWineD3DBaseSurfaceImpl_CreateDIBSection(iface); + surface_create_dib_section(surface); surface->resource.allocatedMemory = surface->dib.bitmap_data; } diff --git a/dlls/wined3d/surface_base.c b/dlls/wined3d/surface_base.c deleted file mode 100644 index d764ff4184f..00000000000 --- a/dlls/wined3d/surface_base.c +++ /dev/null @@ -1,1953 +0,0 @@ -/* - * IWineD3DSurface Implementation of management(non-rendering) functions - * - * Copyright 1998 Lionel Ulmer - * Copyright 2000-2001 TransGaming Technologies Inc. - * Copyright 2002-2005 Jason Edmeades - * Copyright 2002-2003 Raphael Junqueira - * Copyright 2004 Christian Costa - * Copyright 2005 Oliver Stieber - * Copyright 2006-2008 Stefan Dösinger for CodeWeavers - * Copyright 2007 Henri Verbeet - * Copyright 2006-2007 Roderick Colenbrander - * Copyright 2009-2010 Henri Verbeet for CodeWeavers - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA - */ - -#include "config.h" -#include "wine/port.h" -#include "wined3d_private.h" - -WINE_DEFAULT_DEBUG_CHANNEL(d3d_surface); - -/* See also float_16_to_32() in wined3d_private.h */ -static inline unsigned short float_32_to_16(const float *in) -{ - int exp = 0; - float tmp = fabs(*in); - unsigned int mantissa; - unsigned short ret; - - /* Deal with special numbers */ - if (*in == 0.0f) return 0x0000; - if(isnan(*in)) return 0x7C01; - if (isinf(*in)) return (*in < 0.0f ? 0xFC00 : 0x7c00); - - if(tmp < powf(2, 10)) { - do - { - tmp = tmp * 2.0f; - exp--; - }while(tmp < powf(2, 10)); - } else if(tmp >= powf(2, 11)) { - do - { - tmp /= 2.0f; - exp++; - }while(tmp >= powf(2, 11)); - } - - mantissa = (unsigned int) tmp; - if(tmp - mantissa >= 0.5f) mantissa++; /* round to nearest, away from zero */ - - exp += 10; /* Normalize the mantissa */ - exp += 15; /* Exponent is encoded with excess 15 */ - - if(exp > 30) { /* too big */ - ret = 0x7c00; /* INF */ - } else if(exp <= 0) { - /* exp == 0: Non-normalized mantissa. Returns 0x0000 (=0.0) for too small numbers */ - while(exp <= 0) { - mantissa = mantissa >> 1; - exp++; - } - ret = mantissa & 0x3ff; - } else { - ret = (exp << 10) | (mantissa & 0x3ff); - } - - ret |= ((*in < 0.0f ? 1 : 0) << 15); /* Add the sign */ - return ret; -} - -/* ******************************************* - IWineD3DSurface IUnknown parts follow - ******************************************* */ -HRESULT WINAPI IWineD3DBaseSurfaceImpl_QueryInterface(IWineD3DSurface *iface, REFIID riid, LPVOID *ppobj) -{ - IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface; - /* Warn ,but be nice about things */ - TRACE("(%p)->(%s,%p)\n", This,debugstr_guid(riid),ppobj); - - if (IsEqualGUID(riid, &IID_IUnknown) - || IsEqualGUID(riid, &IID_IWineD3DSurface)) { - IUnknown_AddRef((IUnknown*)iface); - *ppobj = This; - return S_OK; - } - *ppobj = NULL; - return E_NOINTERFACE; -} - -ULONG WINAPI IWineD3DBaseSurfaceImpl_AddRef(IWineD3DSurface *iface) -{ - IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *)iface; - ULONG refcount; - - TRACE("Surface %p, container %p of type %#x.\n", - surface, surface->container.u.base, surface->container.type); - - switch (surface->container.type) - { - case WINED3D_CONTAINER_TEXTURE: - return wined3d_texture_incref(surface->container.u.texture); - - case WINED3D_CONTAINER_SWAPCHAIN: - return wined3d_swapchain_incref(surface->container.u.swapchain); - - default: - ERR("Unhandled container type %#x.\n", surface->container.type); - case WINED3D_CONTAINER_NONE: - break; - } - - refcount = InterlockedIncrement(&surface->resource.ref); - TRACE("%p increasing refcount to %u.\n", surface, refcount); - - return refcount; -} - -HRESULT WINAPI IWineD3DBaseSurfaceImpl_SetPrivateData(IWineD3DSurface *iface, - REFGUID riid, const void *data, DWORD data_size, DWORD flags) -{ - return resource_set_private_data(&((IWineD3DSurfaceImpl *)iface)->resource, riid, data, data_size, flags); -} - -HRESULT WINAPI IWineD3DBaseSurfaceImpl_GetPrivateData(IWineD3DSurface *iface, - REFGUID guid, void *data, DWORD *data_size) -{ - return resource_get_private_data(&((IWineD3DSurfaceImpl *)iface)->resource, guid, data, data_size); -} - -HRESULT WINAPI IWineD3DBaseSurfaceImpl_FreePrivateData(IWineD3DSurface *iface, REFGUID refguid) -{ - return resource_free_private_data(&((IWineD3DSurfaceImpl *)iface)->resource, refguid); -} - -DWORD WINAPI IWineD3DBaseSurfaceImpl_SetPriority(IWineD3DSurface *iface, DWORD priority) -{ - return resource_set_priority(&((IWineD3DSurfaceImpl *)iface)->resource, priority); -} - -DWORD WINAPI IWineD3DBaseSurfaceImpl_GetPriority(IWineD3DSurface *iface) -{ - return resource_get_priority(&((IWineD3DSurfaceImpl *)iface)->resource); -} - -void * WINAPI IWineD3DBaseSurfaceImpl_GetParent(IWineD3DSurface *iface) -{ - TRACE("iface %p.\n", iface); - - return ((IWineD3DSurfaceImpl *)iface)->resource.parent; -} - -struct wined3d_resource * WINAPI IWineD3DBaseSurfaceImpl_GetResource(IWineD3DSurface *iface) -{ - TRACE("iface %p.\n", iface); - - return &((IWineD3DSurfaceImpl *)iface)->resource; -} - -HRESULT WINAPI IWineD3DBaseSurfaceImpl_GetBltStatus(IWineD3DSurface *iface, DWORD flags) -{ - TRACE("iface %p, flags %#x.\n", iface, flags); - - switch (flags) - { - case WINEDDGBS_CANBLT: - case WINEDDGBS_ISBLTDONE: - return WINED3D_OK; - - default: - return WINED3DERR_INVALIDCALL; - } -} - -HRESULT WINAPI IWineD3DBaseSurfaceImpl_GetFlipStatus(IWineD3DSurface *iface, DWORD flags) -{ - /* XXX: DDERR_INVALIDSURFACETYPE */ - - TRACE("iface %p, flags %#x.\n", iface, flags); - - switch (flags) - { - case WINEDDGFS_CANFLIP: - case WINEDDGFS_ISFLIPDONE: - return WINED3D_OK; - - default: - return WINED3DERR_INVALIDCALL; - } -} - -HRESULT WINAPI IWineD3DBaseSurfaceImpl_IsLost(IWineD3DSurface *iface) { - IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface; - TRACE("(%p)\n", This); - - /* D3D8 and 9 loose full devices, ddraw only surfaces */ - return This->flags & SFLAG_LOST ? WINED3DERR_DEVICELOST : WINED3D_OK; -} - -HRESULT WINAPI IWineD3DBaseSurfaceImpl_Restore(IWineD3DSurface *iface) { - IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface; - TRACE("(%p)\n", This); - - /* So far we don't lose anything :) */ - This->flags &= ~SFLAG_LOST; - return WINED3D_OK; -} - -HRESULT WINAPI IWineD3DBaseSurfaceImpl_SetPalette(IWineD3DSurface *iface, struct wined3d_palette *palette) -{ - IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface; - - TRACE("iface %p, palette %p.\n", iface, palette); - - if (This->palette == palette) - { - TRACE("Nop palette change\n"); - return WINED3D_OK; - } - - if (This->palette) - if (This->resource.usage & WINED3DUSAGE_RENDERTARGET) - This->palette->flags &= ~WINEDDPCAPS_PRIMARYSURFACE; - - This->palette = palette; - - if (palette) - { - if (This->resource.usage & WINED3DUSAGE_RENDERTARGET) - palette->flags |= WINEDDPCAPS_PRIMARYSURFACE; - - This->surface_ops->surface_realize_palette(This); - } - - return WINED3D_OK; -} - -HRESULT WINAPI IWineD3DBaseSurfaceImpl_SetColorKey(IWineD3DSurface *iface, DWORD flags, const WINEDDCOLORKEY *CKey) -{ - IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface; - - TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, CKey); - - if (flags & WINEDDCKEY_COLORSPACE) - { - FIXME(" colorkey value not supported (%08x) !\n", flags); - return WINED3DERR_INVALIDCALL; - } - - /* Dirtify the surface, but only if a key was changed */ - if (CKey) - { - switch (flags & ~WINEDDCKEY_COLORSPACE) - { - case WINEDDCKEY_DESTBLT: - This->DestBltCKey = *CKey; - This->CKeyFlags |= WINEDDSD_CKDESTBLT; - break; - - case WINEDDCKEY_DESTOVERLAY: - This->DestOverlayCKey = *CKey; - This->CKeyFlags |= WINEDDSD_CKDESTOVERLAY; - break; - - case WINEDDCKEY_SRCOVERLAY: - This->SrcOverlayCKey = *CKey; - This->CKeyFlags |= WINEDDSD_CKSRCOVERLAY; - break; - - case WINEDDCKEY_SRCBLT: - This->SrcBltCKey = *CKey; - This->CKeyFlags |= WINEDDSD_CKSRCBLT; - break; - } - } - else - { - switch (flags & ~WINEDDCKEY_COLORSPACE) - { - case WINEDDCKEY_DESTBLT: - This->CKeyFlags &= ~WINEDDSD_CKDESTBLT; - break; - - case WINEDDCKEY_DESTOVERLAY: - This->CKeyFlags &= ~WINEDDSD_CKDESTOVERLAY; - break; - - case WINEDDCKEY_SRCOVERLAY: - This->CKeyFlags &= ~WINEDDSD_CKSRCOVERLAY; - break; - - case WINEDDCKEY_SRCBLT: - This->CKeyFlags &= ~WINEDDSD_CKSRCBLT; - break; - } - } - - return WINED3D_OK; -} - -HRESULT WINAPI IWineD3DBaseSurfaceImpl_GetPalette(IWineD3DSurface *iface, struct wined3d_palette **palette) -{ - IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface; - - TRACE("iface %p, palette %p.\n", iface, palette); - - *palette = This->palette; - - return WINED3D_OK; -} - -DWORD WINAPI IWineD3DBaseSurfaceImpl_GetPitch(IWineD3DSurface *iface) -{ - IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface; - const struct wined3d_format *format = This->resource.format; - DWORD ret; - TRACE("(%p)\n", This); - - if ((format->flags & (WINED3DFMT_FLAG_COMPRESSED | WINED3DFMT_FLAG_BROKEN_PITCH)) == WINED3DFMT_FLAG_COMPRESSED) - { - /* Since compressed formats are block based, pitch means the amount of - * bytes to the next row of block rather than the next row of pixels. */ - UINT row_block_count = (This->resource.width + format->block_width - 1) / format->block_width; - ret = row_block_count * format->block_byte_count; - } - else - { - unsigned char alignment = This->resource.device->surface_alignment; - ret = This->resource.format->byte_count * This->resource.width; /* Bytes / row */ - ret = (ret + alignment - 1) & ~(alignment - 1); - } - TRACE("(%p) Returning %d\n", This, ret); - return ret; -} - -HRESULT WINAPI IWineD3DBaseSurfaceImpl_SetOverlayPosition(IWineD3DSurface *iface, LONG X, LONG Y) { - IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface; - LONG w, h; - - TRACE("(%p)->(%d,%d) Stub!\n", This, X, Y); - - if(!(This->resource.usage & WINED3DUSAGE_OVERLAY)) - { - TRACE("(%p): Not an overlay surface\n", This); - return WINEDDERR_NOTAOVERLAYSURFACE; - } - - w = This->overlay_destrect.right - This->overlay_destrect.left; - h = This->overlay_destrect.bottom - This->overlay_destrect.top; - This->overlay_destrect.left = X; - This->overlay_destrect.top = Y; - This->overlay_destrect.right = X + w; - This->overlay_destrect.bottom = Y + h; - - This->surface_ops->surface_draw_overlay(This); - - return WINED3D_OK; -} - -HRESULT WINAPI IWineD3DBaseSurfaceImpl_GetOverlayPosition(IWineD3DSurface *iface, LONG *X, LONG *Y) { - IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface; - HRESULT hr; - - TRACE("(%p)->(%p,%p)\n", This, X, Y); - - if(!(This->resource.usage & WINED3DUSAGE_OVERLAY)) - { - TRACE("(%p): Not an overlay surface\n", This); - return WINEDDERR_NOTAOVERLAYSURFACE; - } - - if (!This->overlay_dest) - { - *X = 0; *Y = 0; - hr = WINEDDERR_OVERLAYNOTVISIBLE; - } else { - *X = This->overlay_destrect.left; - *Y = This->overlay_destrect.top; - hr = WINED3D_OK; - } - - TRACE("Returning 0x%08x, position %d, %d\n", hr, *X, *Y); - return hr; -} - -HRESULT WINAPI IWineD3DBaseSurfaceImpl_UpdateOverlayZOrder(IWineD3DSurface *iface, DWORD flags, IWineD3DSurface *Ref) -{ - IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface; - - FIXME("iface %p, flags %#x, ref %p stub!\n", iface, flags, Ref); - - if(!(This->resource.usage & WINED3DUSAGE_OVERLAY)) - { - TRACE("(%p): Not an overlay surface\n", This); - return WINEDDERR_NOTAOVERLAYSURFACE; - } - - return WINED3D_OK; -} - -HRESULT WINAPI IWineD3DBaseSurfaceImpl_UpdateOverlay(IWineD3DSurface *iface, const RECT *SrcRect, - IWineD3DSurface *DstSurface, const RECT *DstRect, DWORD flags, const WINEDDOVERLAYFX *FX) -{ - IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface; - IWineD3DSurfaceImpl *Dst = (IWineD3DSurfaceImpl *) DstSurface; - - TRACE("iface %p, src_rect %s, dst_surface %p, dst_rect %s, flags %#x, fx %p.\n", - iface, wine_dbgstr_rect(SrcRect), DstSurface, wine_dbgstr_rect(DstRect), flags, FX); - - if(!(This->resource.usage & WINED3DUSAGE_OVERLAY)) - { - WARN("(%p): Not an overlay surface\n", This); - return WINEDDERR_NOTAOVERLAYSURFACE; - } else if(!DstSurface) { - WARN("(%p): Dest surface is NULL\n", This); - return WINED3DERR_INVALIDCALL; - } - - if(SrcRect) { - This->overlay_srcrect = *SrcRect; - } else { - This->overlay_srcrect.left = 0; - This->overlay_srcrect.top = 0; - This->overlay_srcrect.right = This->resource.width; - This->overlay_srcrect.bottom = This->resource.height; - } - - if(DstRect) { - This->overlay_destrect = *DstRect; - } else { - This->overlay_destrect.left = 0; - This->overlay_destrect.top = 0; - This->overlay_destrect.right = Dst ? Dst->resource.width : 0; - This->overlay_destrect.bottom = Dst ? Dst->resource.height : 0; - } - - if (This->overlay_dest && (This->overlay_dest != Dst || flags & WINEDDOVER_HIDE)) - { - list_remove(&This->overlay_entry); - } - - if (flags & WINEDDOVER_SHOW) - { - if (This->overlay_dest != Dst) - { - This->overlay_dest = Dst; - list_add_tail(&Dst->overlays, &This->overlay_entry); - } - } - else if (flags & WINEDDOVER_HIDE) - { - /* tests show that the rectangles are erased on hide */ - This->overlay_srcrect.left = 0; This->overlay_srcrect.top = 0; - This->overlay_srcrect.right = 0; This->overlay_srcrect.bottom = 0; - This->overlay_destrect.left = 0; This->overlay_destrect.top = 0; - This->overlay_destrect.right = 0; This->overlay_destrect.bottom = 0; - This->overlay_dest = NULL; - } - - This->surface_ops->surface_draw_overlay(This); - - return WINED3D_OK; -} - -HRESULT WINAPI IWineD3DBaseSurfaceImpl_SetClipper(IWineD3DSurface *iface, struct wined3d_clipper *clipper) -{ - IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface; - - TRACE("iface %p, clipper %p.\n", iface, clipper); - - This->clipper = clipper; - - return WINED3D_OK; -} - -HRESULT WINAPI IWineD3DBaseSurfaceImpl_GetClipper(IWineD3DSurface *iface, struct wined3d_clipper **clipper) -{ - IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface; - - TRACE("iface %p, clipper %p.\n", iface, clipper); - - *clipper = This->clipper; - if (*clipper) - wined3d_clipper_incref(*clipper); - - return WINED3D_OK; -} - -HRESULT WINAPI IWineD3DBaseSurfaceImpl_SetFormat(IWineD3DSurface *iface, enum wined3d_format_id format_id) -{ - IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface; - const struct wined3d_format *format = wined3d_get_format(&This->resource.device->adapter->gl_info, format_id); - - if (This->resource.format->id != WINED3DFMT_UNKNOWN) - { - FIXME("(%p) : The format of the surface must be WINED3DFORMAT_UNKNOWN\n", This); - return WINED3DERR_INVALIDCALL; - } - - TRACE("(%p) : Setting texture format to %s (%#x).\n", This, debug_d3dformat(format_id), format_id); - - This->resource.size = wined3d_format_calculate_size(format, This->resource.device->surface_alignment, - This->pow2Width, This->pow2Height); - - This->flags |= (WINED3DFMT_D16_LOCKABLE == format_id) ? SFLAG_LOCKABLE : 0; - - This->resource.format = format; - - TRACE("(%p) : Size %d, bytesPerPixel %d\n", This, This->resource.size, format->byte_count); - - return WINED3D_OK; -} - -HRESULT IWineD3DBaseSurfaceImpl_CreateDIBSection(IWineD3DSurface *iface) -{ - IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface; - const struct wined3d_format *format = This->resource.format; - int extraline = 0; - SYSTEM_INFO sysInfo; - BITMAPINFO* b_info; - HDC ddc; - DWORD *masks; - UINT usage; - - if (!(format->flags & WINED3DFMT_FLAG_GETDC)) - { - WARN("Cannot use GetDC on a %s surface\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, sizeof(BITMAPINFOHEADER) + 3 * sizeof(DWORD)); - break; - - case 3: - b_info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER)); - break; - - default: - /* Allocate extra space for a palette. */ - b_info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, - sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * (1 << (format->byte_count * 8))); - break; - } - - if (!b_info) - return E_OUTOFMEMORY; - - /* Some apps access the surface in via DWORDs, and do not take the necessary care at the end of the - * surface. So we need at least extra 4 bytes at the end of the surface. Check against the page size, - * if the last page used for the surface has at least 4 spare bytes we're safe, otherwise - * add an extra line to the dib section - */ - GetSystemInfo(&sysInfo); - if( ((This->resource.size + 3) % sysInfo.dwPageSize) < 4) { - extraline = 1; - TRACE("Adding an extra line to the dib section\n"); - } - - b_info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); - /* TODO: Is there a nicer way to force a specific alignment? (8 byte for ddraw) */ - b_info->bmiHeader.biWidth = IWineD3DSurface_GetPitch(iface) / format->byte_count; - b_info->bmiHeader.biHeight = -This->resource.height - extraline; - b_info->bmiHeader.biSizeImage = (This->resource.height + extraline) * IWineD3DSurface_GetPitch(iface); - 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 (This->resource.format->id) - { - case WINED3DFMT_B8G8R8_UNORM: - usage = DIB_RGB_COLORS; - 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: - usage = 0; - b_info->bmiHeader.biCompression = BI_BITFIELDS; - masks[0] = format->red_mask; - masks[1] = format->green_mask; - masks[2] = format->blue_mask; - break; - - default: - /* Don't know palette */ - b_info->bmiHeader.biCompression = BI_RGB; - usage = 0; - break; - } - - if (!(ddc = GetDC(0))) - { - HeapFree(GetProcessHeap(), 0, b_info); - return HRESULT_FROM_WIN32(GetLastError()); - } - - 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); - This->dib.DIBsection = CreateDIBSection(ddc, b_info, usage, &This->dib.bitmap_data, 0 /* Handle */, 0 /* Offset */); - ReleaseDC(0, ddc); - - if (!This->dib.DIBsection) { - ERR("CreateDIBSection failed!\n"); - HeapFree(GetProcessHeap(), 0, b_info); - return HRESULT_FROM_WIN32(GetLastError()); - } - - TRACE("DIBSection at : %p\n", This->dib.bitmap_data); - /* copy the existing surface to the dib section */ - if (This->resource.allocatedMemory) - { - memcpy(This->dib.bitmap_data, This->resource.allocatedMemory, - This->resource.height * IWineD3DSurface_GetPitch(iface)); - } - else - { - /* This is to make LockRect read the gl Texture although memory is allocated */ - This->flags &= ~SFLAG_INSYSMEM; - } - This->dib.bitmap_size = b_info->bmiHeader.biSizeImage; - - HeapFree(GetProcessHeap(), 0, b_info); - - /* Now allocate a HDC */ - This->hDC = CreateCompatibleDC(0); - This->dib.holdbitmap = SelectObject(This->hDC, This->dib.DIBsection); - TRACE("using wined3d palette %p\n", This->palette); - SelectPalette(This->hDC, - This->palette ? This->palette->hpal : 0, - FALSE); - - This->flags |= SFLAG_DIBSECTION; - - HeapFree(GetProcessHeap(), 0, This->resource.heapMemory); - This->resource.heapMemory = NULL; - - return WINED3D_OK; -} - -static void convert_r32_float_r16_float(const BYTE *src, BYTE *dst, DWORD pitch_in, DWORD pitch_out, - unsigned int w, unsigned int h) -{ - unsigned int x, y; - const float *src_f; - unsigned short *dst_s; - - TRACE("Converting %dx%d pixels, pitches %d %d\n", w, h, pitch_in, pitch_out); - for(y = 0; y < h; y++) { - src_f = (const float *)(src + y * pitch_in); - dst_s = (unsigned short *) (dst + y * pitch_out); - for(x = 0; x < w; x++) { - dst_s[x] = float_32_to_16(src_f + x); - } - } -} - -static void convert_r5g6b5_x8r8g8b8(const BYTE *src, BYTE *dst, - DWORD pitch_in, DWORD pitch_out, unsigned int w, unsigned int h) -{ - static const unsigned char convert_5to8[] = - { - 0x00, 0x08, 0x10, 0x19, 0x21, 0x29, 0x31, 0x3a, - 0x42, 0x4a, 0x52, 0x5a, 0x63, 0x6b, 0x73, 0x7b, - 0x84, 0x8c, 0x94, 0x9c, 0xa5, 0xad, 0xb5, 0xbd, - 0xc5, 0xce, 0xd6, 0xde, 0xe6, 0xef, 0xf7, 0xff, - }; - static const unsigned char convert_6to8[] = - { - 0x00, 0x04, 0x08, 0x0c, 0x10, 0x14, 0x18, 0x1c, - 0x20, 0x24, 0x28, 0x2d, 0x31, 0x35, 0x39, 0x3d, - 0x41, 0x45, 0x49, 0x4d, 0x51, 0x55, 0x59, 0x5d, - 0x61, 0x65, 0x69, 0x6d, 0x71, 0x75, 0x79, 0x7d, - 0x82, 0x86, 0x8a, 0x8e, 0x92, 0x96, 0x9a, 0x9e, - 0xa2, 0xa6, 0xaa, 0xae, 0xb2, 0xb6, 0xba, 0xbe, - 0xc2, 0xc6, 0xca, 0xce, 0xd2, 0xd7, 0xdb, 0xdf, - 0xe3, 0xe7, 0xeb, 0xef, 0xf3, 0xf7, 0xfb, 0xff, - }; - unsigned int x, y; - - TRACE("Converting %ux%u pixels, pitches %u %u\n", w, h, pitch_in, pitch_out); - - for (y = 0; y < h; ++y) - { - const WORD *src_line = (const WORD *)(src + y * pitch_in); - DWORD *dst_line = (DWORD *)(dst + y * pitch_out); - for (x = 0; x < w; ++x) - { - WORD pixel = src_line[x]; - dst_line[x] = 0xff000000 - | convert_5to8[(pixel & 0xf800) >> 11] << 16 - | convert_6to8[(pixel & 0x07e0) >> 5] << 8 - | convert_5to8[(pixel & 0x001f)]; - } - } -} - -static void convert_a8r8g8b8_x8r8g8b8(const BYTE *src, BYTE *dst, - DWORD pitch_in, DWORD pitch_out, unsigned int w, unsigned int h) -{ - unsigned int x, y; - - TRACE("Converting %ux%u pixels, pitches %u %u\n", w, h, pitch_in, pitch_out); - - for (y = 0; y < h; ++y) - { - const DWORD *src_line = (const DWORD *)(src + y * pitch_in); - DWORD *dst_line = (DWORD *)(dst + y * pitch_out); - - for (x = 0; x < w; ++x) - { - dst_line[x] = 0xff000000 | (src_line[x] & 0xffffff); - } - } -} - -static inline BYTE cliptobyte(int x) -{ - return (BYTE) ((x < 0) ? 0 : ((x > 255) ? 255 : x)); -} - -static void convert_yuy2_x8r8g8b8(const BYTE *src, BYTE *dst, - DWORD pitch_in, DWORD pitch_out, unsigned int w, unsigned int h) -{ - unsigned int x, y; - int c2, d, e, r2 = 0, g2 = 0, b2 = 0; - - TRACE("Converting %ux%u pixels, pitches %u %u\n", w, h, pitch_in, pitch_out); - - for (y = 0; y < h; ++y) - { - const BYTE *src_line = src + y * pitch_in; - DWORD *dst_line = (DWORD *)(dst + y * pitch_out); - for (x = 0; x < w; ++x) - { - /* YUV to RGB conversion formulas from http://en.wikipedia.org/wiki/YUV: - * C = Y - 16; D = U - 128; E = V - 128; - * R = cliptobyte((298 * C + 409 * E + 128) >> 8); - * G = cliptobyte((298 * C - 100 * D - 208 * E + 128) >> 8); - * B = cliptobyte((298 * C + 516 * D + 128) >> 8); - * Two adjacent YUY2 pixels are stored as four bytes: Y0 U Y1 V . - * U and V are shared between the pixels. - */ - if (!(x & 1)) /* for every even pixel, read new U and V */ - { - d = (int) src_line[1] - 128; - e = (int) src_line[3] - 128; - r2 = 409 * e + 128; - g2 = - 100 * d - 208 * e + 128; - b2 = 516 * d + 128; - } - c2 = 298 * ((int) src_line[0] - 16); - dst_line[x] = 0xff000000 - | cliptobyte((c2 + r2) >> 8) << 16 /* red */ - | cliptobyte((c2 + g2) >> 8) << 8 /* green */ - | cliptobyte((c2 + b2) >> 8); /* blue */ - /* Scale RGB values to 0..255 range, - * then clip them if still not in range (may be negative), - * then shift them within DWORD if necessary. - */ - src_line += 2; - } - } -} - -static void convert_yuy2_r5g6b5(const BYTE *src, BYTE *dst, - DWORD pitch_in, DWORD pitch_out, unsigned int w, unsigned int h) -{ - unsigned int x, y; - int c2, d, e, r2 = 0, g2 = 0, b2 = 0; - - TRACE("Converting %ux%u pixels, pitches %u %u\n", w, h, pitch_in, pitch_out); - - for (y = 0; y < h; ++y) - { - const BYTE *src_line = src + y * pitch_in; - WORD *dst_line = (WORD *)(dst + y * pitch_out); - for (x = 0; x < w; ++x) - { - /* YUV to RGB conversion formulas from http://en.wikipedia.org/wiki/YUV: - * C = Y - 16; D = U - 128; E = V - 128; - * R = cliptobyte((298 * C + 409 * E + 128) >> 8); - * G = cliptobyte((298 * C - 100 * D - 208 * E + 128) >> 8); - * B = cliptobyte((298 * C + 516 * D + 128) >> 8); - * Two adjacent YUY2 pixels are stored as four bytes: Y0 U Y1 V . - * U and V are shared between the pixels. - */ - if (!(x & 1)) /* for every even pixel, read new U and V */ - { - d = (int) src_line[1] - 128; - e = (int) src_line[3] - 128; - r2 = 409 * e + 128; - g2 = - 100 * d - 208 * e + 128; - b2 = 516 * d + 128; - } - c2 = 298 * ((int) src_line[0] - 16); - dst_line[x] = (cliptobyte((c2 + r2) >> 8) >> 3) << 11 /* red */ - | (cliptobyte((c2 + g2) >> 8) >> 2) << 5 /* green */ - | (cliptobyte((c2 + b2) >> 8) >> 3); /* blue */ - /* Scale RGB values to 0..255 range, - * then clip them if still not in range (may be negative), - * then shift them within DWORD if necessary. - */ - src_line += 2; - } - } -} - -struct d3dfmt_convertor_desc -{ - enum wined3d_format_id from, to; - void (*convert)(const BYTE *src, BYTE *dst, DWORD pitch_in, DWORD pitch_out, unsigned int w, unsigned int h); -}; - -static const struct d3dfmt_convertor_desc convertors[] = -{ - {WINED3DFMT_R32_FLOAT, WINED3DFMT_R16_FLOAT, convert_r32_float_r16_float}, - {WINED3DFMT_B5G6R5_UNORM, WINED3DFMT_B8G8R8X8_UNORM, convert_r5g6b5_x8r8g8b8}, - {WINED3DFMT_B8G8R8A8_UNORM, WINED3DFMT_B8G8R8X8_UNORM, convert_a8r8g8b8_x8r8g8b8}, - {WINED3DFMT_YUY2, WINED3DFMT_B8G8R8X8_UNORM, convert_yuy2_x8r8g8b8}, - {WINED3DFMT_YUY2, WINED3DFMT_B5G6R5_UNORM, convert_yuy2_r5g6b5}, -}; - -static inline const struct d3dfmt_convertor_desc *find_convertor(enum wined3d_format_id from, enum wined3d_format_id to) -{ - unsigned int i; - for(i = 0; i < (sizeof(convertors) / sizeof(convertors[0])); i++) { - if(convertors[i].from == from && convertors[i].to == to) { - return &convertors[i]; - } - } - return NULL; -} - -/***************************************************************************** - * surface_convert_format - * - * Creates a duplicate of a surface in a different format. Is used by Blt to - * blit between surfaces with different formats - * - * Parameters - * source: Source surface - * fmt: Requested destination format - * - *****************************************************************************/ -static IWineD3DSurfaceImpl *surface_convert_format(IWineD3DSurfaceImpl *source, enum wined3d_format_id to_fmt) -{ - IWineD3DSurface *ret = NULL; - const struct d3dfmt_convertor_desc *conv; - WINED3DLOCKED_RECT lock_src, lock_dst; - HRESULT hr; - - conv = find_convertor(source->resource.format->id, to_fmt); - if (!conv) - { - FIXME("Cannot find a conversion function from format %s to %s.\n", - debug_d3dformat(source->resource.format->id), debug_d3dformat(to_fmt)); - return NULL; - } - - IWineD3DDevice_CreateSurface((IWineD3DDevice *)source->resource.device, source->resource.width, - source->resource.height, to_fmt, TRUE /* lockable */, TRUE /* discard */, 0 /* level */, - 0 /* usage */, WINED3DPOOL_SCRATCH, WINED3DMULTISAMPLE_NONE /* TODO: Multisampled conversion */, - 0 /* MultiSampleQuality */, source->surface_type, NULL /* parent */, &wined3d_null_parent_ops, &ret); - if(!ret) { - ERR("Failed to create a destination surface for conversion\n"); - return NULL; - } - - memset(&lock_src, 0, sizeof(lock_src)); - memset(&lock_dst, 0, sizeof(lock_dst)); - - hr = IWineD3DSurface_Map((IWineD3DSurface *)source, &lock_src, NULL, WINED3DLOCK_READONLY); - if (FAILED(hr)) - { - ERR("Failed to lock the source surface.\n"); - IWineD3DSurface_Release(ret); - return NULL; - } - hr = IWineD3DSurface_Map(ret, &lock_dst, NULL, WINED3DLOCK_READONLY); - if (FAILED(hr)) - { - ERR("Failed to lock the dest surface\n"); - IWineD3DSurface_Unmap((IWineD3DSurface *)source); - IWineD3DSurface_Release(ret); - return NULL; - } - - conv->convert(lock_src.pBits, lock_dst.pBits, lock_src.Pitch, lock_dst.Pitch, - source->resource.width, source->resource.height); - - IWineD3DSurface_Unmap(ret); - IWineD3DSurface_Unmap((IWineD3DSurface *)source); - - return (IWineD3DSurfaceImpl *) ret; -} - -/***************************************************************************** - * _Blt_ColorFill - * - * Helper function that fills a memory area with a specific color - * - * Params: - * buf: memory address to start filling at - * width, height: Dimensions of the area to fill - * bpp: Bit depth of the surface - * lPitch: pitch of the surface - * color: Color to fill with - * - *****************************************************************************/ -static HRESULT - _Blt_ColorFill(BYTE *buf, - int width, int height, - int bpp, LONG lPitch, - DWORD color) -{ - int x, y; - LPBYTE first; - - /* Do first row */ - -#define COLORFILL_ROW(type) \ - { \ - type *d = (type *) buf; \ - for (x = 0; x < width; x++) \ - d[x] = (type) color; \ - break; \ -} - switch(bpp) - { - case 1: COLORFILL_ROW(BYTE) - case 2: COLORFILL_ROW(WORD) - case 3: - { - BYTE *d = buf; - for (x = 0; x < width; x++,d+=3) - { - d[0] = (color ) & 0xFF; - d[1] = (color>> 8) & 0xFF; - d[2] = (color>>16) & 0xFF; - } - break; - } - case 4: COLORFILL_ROW(DWORD) - default: - FIXME("Color fill not implemented for bpp %d!\n", bpp*8); - return WINED3DERR_NOTAVAILABLE; - } - -#undef COLORFILL_ROW - - /* Now copy first row */ - first = buf; - for (y = 1; y < height; y++) - { - buf += lPitch; - memcpy(buf, first, width * bpp); - } - return WINED3D_OK; -} - -/***************************************************************************** - * IWineD3DSurface::Blt, SW emulation version - * - * Performs a blit to a surface, with or without a source surface. - * This is the main functionality of DirectDraw - * - * Params: - * DestRect: Destination rectangle to write to - * src_surface: Source surface, can be NULL - * SrcRect: Source rectangle - *****************************************************************************/ -HRESULT WINAPI IWineD3DBaseSurfaceImpl_Blt(IWineD3DSurface *iface, const RECT *DestRect, IWineD3DSurface *src_surface, - const RECT *SrcRect, DWORD flags, const WINEDDBLTFX *DDBltFx, WINED3DTEXTUREFILTERTYPE Filter) -{ - IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface; - IWineD3DSurfaceImpl *src = (IWineD3DSurfaceImpl *)src_surface; - RECT xdst,xsrc; - HRESULT ret = WINED3D_OK; - WINED3DLOCKED_RECT dlock, slock; - int bpp, srcheight, srcwidth, dstheight, dstwidth, width; - const struct wined3d_format *sEntry, *dEntry; - int x, y; - const BYTE *sbuf; - BYTE *dbuf; - - TRACE("iface %p, dst_rect %s, src_surface %p, src_rect %s, flags %#x, fx %p, filter %s.\n", - iface, wine_dbgstr_rect(DestRect), src_surface, wine_dbgstr_rect(SrcRect), - flags, DDBltFx, debug_d3dtexturefiltertype(Filter)); - - if ((This->flags & SFLAG_LOCKED) || (src && (src->flags & SFLAG_LOCKED))) - { - WARN(" Surface is busy, returning DDERR_SURFACEBUSY\n"); - return WINEDDERR_SURFACEBUSY; - } - - /* First check for the validity of source / destination rectangles. - * This was verified using a test application + by MSDN. */ - - if (SrcRect) - { - if (src) - { - if (SrcRect->right < SrcRect->left || SrcRect->bottom < SrcRect->top - || SrcRect->left > src->resource.width || SrcRect->left < 0 - || SrcRect->top > src->resource.height || SrcRect->top < 0 - || SrcRect->right > src->resource.width || SrcRect->right < 0 - || SrcRect->bottom > src->resource.height || SrcRect->bottom < 0) - { - WARN("Application gave us bad source rectangle for Blt.\n"); - return WINEDDERR_INVALIDRECT; - } - - if (!SrcRect->right || !SrcRect->bottom - || SrcRect->left == (int)src->resource.width - || SrcRect->top == (int)src->resource.height) - { - TRACE("Nothing to be done.\n"); - return WINED3D_OK; - } - } - - xsrc = *SrcRect; - } - else if (src) - { - xsrc.left = 0; - xsrc.top = 0; - xsrc.right = src->resource.width; - xsrc.bottom = src->resource.height; - } - else - { - memset(&xsrc, 0, sizeof(xsrc)); - } - - if (DestRect) - { - /* For the Destination rect, it can be out of bounds on the condition - * that a clipper is set for the given surface. */ - if (!This->clipper && (DestRect->right < DestRect->left || DestRect->bottom < DestRect->top - || DestRect->left > This->resource.width || DestRect->left < 0 - || DestRect->top > This->resource.height || DestRect->top < 0 - || DestRect->right > This->resource.width || DestRect->right < 0 - || DestRect->bottom > This->resource.height || DestRect->bottom < 0)) - { - WARN("Application gave us bad destination rectangle for Blt without a clipper set.\n"); - return WINEDDERR_INVALIDRECT; - } - - if (DestRect->right <= 0 || DestRect->bottom <= 0 - || DestRect->left >= (int)This->resource.width - || DestRect->top >= (int)This->resource.height) - { - TRACE("Nothing to be done.\n"); - return WINED3D_OK; - } - - if (!src) - { - RECT full_rect; - - full_rect.left = 0; - full_rect.top = 0; - full_rect.right = This->resource.width; - full_rect.bottom = This->resource.height; - IntersectRect(&xdst, &full_rect, DestRect); - } - else - { - BOOL clip_horiz, clip_vert; - - xdst = *DestRect; - clip_horiz = xdst.left < 0 || xdst.right > (int)This->resource.width; - clip_vert = xdst.top < 0 || xdst.bottom > (int)This->resource.height; - - if (clip_vert || clip_horiz) - { - /* Now check if this is a special case or not... */ - if ((flags & WINEDDBLT_DDFX) - || (clip_horiz && xdst.right - xdst.left != xsrc.right - xsrc.left) - || (clip_vert && xdst.bottom - xdst.top != xsrc.bottom - xsrc.top)) - { - WARN("Out of screen rectangle in special case. Not handled right now.\n"); - return WINED3D_OK; - } - - if (clip_horiz) - { - if (xdst.left < 0) - { - xsrc.left -= xdst.left; - xdst.left = 0; - } - if (xdst.right > This->resource.width) - { - xsrc.right -= (xdst.right - (int)This->resource.width); - xdst.right = (int)This->resource.width; - } - } - - if (clip_vert) - { - if (xdst.top < 0) - { - xsrc.top -= xdst.top; - xdst.top = 0; - } - if (xdst.bottom > This->resource.height) - { - xsrc.bottom -= (xdst.bottom - (int)This->resource.height); - xdst.bottom = (int)This->resource.height; - } - } - - /* And check if after clipping something is still to be done... */ - if ((xdst.right <= 0) || (xdst.bottom <= 0) - || (xdst.left >= (int)This->resource.width) - || (xdst.top >= (int)This->resource.height) - || (xsrc.right <= 0) || (xsrc.bottom <= 0) - || (xsrc.left >= (int)src->resource.width) - || (xsrc.top >= (int)src->resource.height)) - { - TRACE("Nothing to be done after clipping.\n"); - return WINED3D_OK; - } - } - } - } - else - { - xdst.left = 0; - xdst.top = 0; - xdst.right = This->resource.width; - xdst.bottom = This->resource.height; - } - - if (src == This) - { - IWineD3DSurface_Map(iface, &dlock, NULL, 0); - slock = dlock; - sEntry = This->resource.format; - dEntry = sEntry; - } - else - { - dEntry = This->resource.format; - if (src) - { - if (This->resource.format->id != src->resource.format->id) - { - src = surface_convert_format(src, dEntry->id); - if (!src) - { - /* The conv function writes a FIXME */ - WARN("Cannot convert source surface format to dest format\n"); - goto release; - } - } - IWineD3DSurface_Map((IWineD3DSurface *)src, &slock, NULL, WINED3DLOCK_READONLY); - sEntry = src->resource.format; - } - else - { - sEntry = dEntry; - } - if (DestRect) - IWineD3DSurface_Map(iface, &dlock, &xdst, 0); - else - IWineD3DSurface_Map(iface, &dlock, NULL, 0); - } - - if (!DDBltFx || !(DDBltFx->dwDDFX)) flags &= ~WINEDDBLT_DDFX; - - if (sEntry->flags & dEntry->flags & WINED3DFMT_FLAG_FOURCC) - { - if (!DestRect || src == This) - { - memcpy(dlock.pBits, slock.pBits, This->resource.size); - goto release; - } - } - - bpp = This->resource.format->byte_count; - srcheight = xsrc.bottom - xsrc.top; - srcwidth = xsrc.right - xsrc.left; - dstheight = xdst.bottom - xdst.top; - dstwidth = xdst.right - xdst.left; - width = (xdst.right - xdst.left) * bpp; - - if (DestRect && src != This) - dbuf = dlock.pBits; - else - dbuf = (BYTE*)dlock.pBits+(xdst.top*dlock.Pitch)+(xdst.left*bpp); - - if (flags & WINEDDBLT_WAIT) - { - flags &= ~WINEDDBLT_WAIT; - } - if (flags & WINEDDBLT_ASYNC) - { - static BOOL displayed = FALSE; - if (!displayed) - FIXME("Can't handle WINEDDBLT_ASYNC flag right now.\n"); - displayed = TRUE; - flags &= ~WINEDDBLT_ASYNC; - } - if (flags & WINEDDBLT_DONOTWAIT) - { - /* WINEDDBLT_DONOTWAIT appeared in DX7 */ - static BOOL displayed = FALSE; - if (!displayed) - FIXME("Can't handle WINEDDBLT_DONOTWAIT flag right now.\n"); - displayed = TRUE; - flags &= ~WINEDDBLT_DONOTWAIT; - } - - /* First, all the 'source-less' blits */ - if (flags & WINEDDBLT_COLORFILL) - { - ret = _Blt_ColorFill(dbuf, dstwidth, dstheight, bpp, - dlock.Pitch, DDBltFx->u5.dwFillColor); - flags &= ~WINEDDBLT_COLORFILL; - } - - if (flags & WINEDDBLT_DEPTHFILL) - { - FIXME("DDBLT_DEPTHFILL needs to be implemented!\n"); - } - if (flags & WINEDDBLT_ROP) - { - /* Catch some degenerate cases here */ - switch(DDBltFx->dwROP) - { - case BLACKNESS: - ret = _Blt_ColorFill(dbuf,dstwidth,dstheight,bpp,dlock.Pitch,0); - break; - case 0xAA0029: /* No-op */ - break; - case WHITENESS: - ret = _Blt_ColorFill(dbuf,dstwidth,dstheight,bpp,dlock.Pitch,~0); - break; - case SRCCOPY: /* well, we do that below ? */ - break; - default: - FIXME("Unsupported raster op: %08x Pattern: %p\n", DDBltFx->dwROP, DDBltFx->u5.lpDDSPattern); - goto error; - } - flags &= ~WINEDDBLT_ROP; - } - if (flags & WINEDDBLT_DDROPS) - { - FIXME("\tDdraw Raster Ops: %08x Pattern: %p\n", DDBltFx->dwDDROP, DDBltFx->u5.lpDDSPattern); - } - /* Now the 'with source' blits */ - if (src) - { - const BYTE *sbase; - int sx, xinc, sy, yinc; - - if (!dstwidth || !dstheight) /* hmm... stupid program ? */ - goto release; - - if (Filter != WINED3DTEXF_NONE && Filter != WINED3DTEXF_POINT - && (srcwidth != dstwidth || srcheight != dstheight)) - { - /* Can happen when d3d9 apps do a StretchRect call which isn't handled in gl */ - FIXME("Filter %s not supported in software blit.\n", debug_d3dtexturefiltertype(Filter)); - } - - sbase = (BYTE*)slock.pBits+(xsrc.top*slock.Pitch)+xsrc.left*bpp; - xinc = (srcwidth << 16) / dstwidth; - yinc = (srcheight << 16) / dstheight; - - if (!flags) - { - /* No effects, we can cheat here */ - if (dstwidth == srcwidth) - { - if (dstheight == srcheight) - { - /* No stretching in either direction. This needs to be as - * fast as possible */ - sbuf = sbase; - - /* check for overlapping surfaces */ - if (src != This || xdst.top < xsrc.top || - xdst.right <= xsrc.left || xsrc.right <= xdst.left) - { - /* no overlap, or dst above src, so copy from top downwards */ - for (y = 0; y < dstheight; y++) - { - memcpy(dbuf, sbuf, width); - sbuf += slock.Pitch; - dbuf += dlock.Pitch; - } - } - else if (xdst.top > xsrc.top) /* copy from bottom upwards */ - { - sbuf += (slock.Pitch*dstheight); - dbuf += (dlock.Pitch*dstheight); - for (y = 0; y < dstheight; y++) - { - sbuf -= slock.Pitch; - dbuf -= dlock.Pitch; - memcpy(dbuf, sbuf, width); - } - } - else /* src and dst overlapping on the same line, use memmove */ - { - for (y = 0; y < dstheight; y++) - { - memmove(dbuf, sbuf, width); - sbuf += slock.Pitch; - dbuf += dlock.Pitch; - } - } - } else { - /* Stretching in Y direction only */ - for (y = sy = 0; y < dstheight; y++, sy += yinc) { - sbuf = sbase + (sy >> 16) * slock.Pitch; - memcpy(dbuf, sbuf, width); - dbuf += dlock.Pitch; - } - } - } - else - { - /* Stretching in X direction */ - int last_sy = -1; - for (y = sy = 0; y < dstheight; y++, sy += yinc) - { - sbuf = sbase + (sy >> 16) * slock.Pitch; - - if ((sy >> 16) == (last_sy >> 16)) - { - /* this sourcerow is the same as last sourcerow - - * copy already stretched row - */ - memcpy(dbuf, dbuf - dlock.Pitch, width); - } - else - { -#define STRETCH_ROW(type) { \ - const type *s = (const type *)sbuf; \ - type *d = (type *)dbuf; \ - for (x = sx = 0; x < dstwidth; x++, sx += xinc) \ - d[x] = s[sx >> 16]; \ - break; } - - switch(bpp) - { - case 1: STRETCH_ROW(BYTE) - case 2: STRETCH_ROW(WORD) - case 4: STRETCH_ROW(DWORD) - case 3: - { - const BYTE *s; - BYTE *d = dbuf; - for (x = sx = 0; x < dstwidth; x++, sx+= xinc) - { - DWORD pixel; - - s = sbuf+3*(sx>>16); - pixel = s[0]|(s[1]<<8)|(s[2]<<16); - d[0] = (pixel )&0xff; - d[1] = (pixel>> 8)&0xff; - d[2] = (pixel>>16)&0xff; - d+=3; - } - break; - } - default: - FIXME("Stretched blit not implemented for bpp %d!\n", bpp*8); - ret = WINED3DERR_NOTAVAILABLE; - goto error; - } -#undef STRETCH_ROW - } - dbuf += dlock.Pitch; - last_sy = sy; - } - } - } - else - { - LONG dstyinc = dlock.Pitch, dstxinc = bpp; - DWORD keylow = 0xFFFFFFFF, keyhigh = 0, keymask = 0xFFFFFFFF; - DWORD destkeylow = 0x0, destkeyhigh = 0xFFFFFFFF, destkeymask = 0xFFFFFFFF; - if (flags & (WINEDDBLT_KEYSRC | WINEDDBLT_KEYDEST | WINEDDBLT_KEYSRCOVERRIDE | WINEDDBLT_KEYDESTOVERRIDE)) - { - /* The color keying flags are checked for correctness in ddraw */ - if (flags & WINEDDBLT_KEYSRC) - { - keylow = src->SrcBltCKey.dwColorSpaceLowValue; - keyhigh = src->SrcBltCKey.dwColorSpaceHighValue; - } - else if (flags & WINEDDBLT_KEYSRCOVERRIDE) - { - keylow = DDBltFx->ddckSrcColorkey.dwColorSpaceLowValue; - keyhigh = DDBltFx->ddckSrcColorkey.dwColorSpaceHighValue; - } - - if (flags & WINEDDBLT_KEYDEST) - { - /* Destination color keys are taken from the source surface ! */ - destkeylow = src->DestBltCKey.dwColorSpaceLowValue; - destkeyhigh = src->DestBltCKey.dwColorSpaceHighValue; - } - else if (flags & WINEDDBLT_KEYDESTOVERRIDE) - { - destkeylow = DDBltFx->ddckDestColorkey.dwColorSpaceLowValue; - destkeyhigh = DDBltFx->ddckDestColorkey.dwColorSpaceHighValue; - } - - if(bpp == 1) - { - keymask = 0xff; - } - else - { - keymask = sEntry->red_mask - | sEntry->green_mask - | sEntry->blue_mask; - } - flags &= ~(WINEDDBLT_KEYSRC | WINEDDBLT_KEYDEST | WINEDDBLT_KEYSRCOVERRIDE | WINEDDBLT_KEYDESTOVERRIDE); - } - - if (flags & WINEDDBLT_DDFX) - { - LPBYTE dTopLeft, dTopRight, dBottomLeft, dBottomRight, tmp; - LONG tmpxy; - dTopLeft = dbuf; - dTopRight = dbuf+((dstwidth-1)*bpp); - dBottomLeft = dTopLeft+((dstheight-1)*dlock.Pitch); - dBottomRight = dBottomLeft+((dstwidth-1)*bpp); - - if (DDBltFx->dwDDFX & WINEDDBLTFX_ARITHSTRETCHY) - { - /* I don't think we need to do anything about this flag */ - WARN("flags=DDBLT_DDFX nothing done for WINEDDBLTFX_ARITHSTRETCHY\n"); - } - if (DDBltFx->dwDDFX & WINEDDBLTFX_MIRRORLEFTRIGHT) - { - tmp = dTopRight; - dTopRight = dTopLeft; - dTopLeft = tmp; - tmp = dBottomRight; - dBottomRight = dBottomLeft; - dBottomLeft = tmp; - dstxinc = dstxinc *-1; - } - if (DDBltFx->dwDDFX & WINEDDBLTFX_MIRRORUPDOWN) - { - tmp = dTopLeft; - dTopLeft = dBottomLeft; - dBottomLeft = tmp; - tmp = dTopRight; - dTopRight = dBottomRight; - dBottomRight = tmp; - dstyinc = dstyinc *-1; - } - if (DDBltFx->dwDDFX & WINEDDBLTFX_NOTEARING) - { - /* I don't think we need to do anything about this flag */ - WARN("flags=DDBLT_DDFX nothing done for WINEDDBLTFX_NOTEARING\n"); - } - if (DDBltFx->dwDDFX & WINEDDBLTFX_ROTATE180) - { - tmp = dBottomRight; - dBottomRight = dTopLeft; - dTopLeft = tmp; - tmp = dBottomLeft; - dBottomLeft = dTopRight; - dTopRight = tmp; - dstxinc = dstxinc * -1; - dstyinc = dstyinc * -1; - } - if (DDBltFx->dwDDFX & WINEDDBLTFX_ROTATE270) - { - tmp = dTopLeft; - dTopLeft = dBottomLeft; - dBottomLeft = dBottomRight; - dBottomRight = dTopRight; - dTopRight = tmp; - tmpxy = dstxinc; - dstxinc = dstyinc; - dstyinc = tmpxy; - dstxinc = dstxinc * -1; - } - if (DDBltFx->dwDDFX & WINEDDBLTFX_ROTATE90) - { - tmp = dTopLeft; - dTopLeft = dTopRight; - dTopRight = dBottomRight; - dBottomRight = dBottomLeft; - dBottomLeft = tmp; - tmpxy = dstxinc; - dstxinc = dstyinc; - dstyinc = tmpxy; - dstyinc = dstyinc * -1; - } - if (DDBltFx->dwDDFX & WINEDDBLTFX_ZBUFFERBASEDEST) - { - /* I don't think we need to do anything about this flag */ - WARN("flags=WINEDDBLT_DDFX nothing done for WINEDDBLTFX_ZBUFFERBASEDEST\n"); - } - dbuf = dTopLeft; - flags &= ~(WINEDDBLT_DDFX); - } - -#define COPY_COLORKEY_FX(type) { \ - const type *s; \ - type *d = (type *)dbuf, *dx, tmp; \ - for (y = sy = 0; y < dstheight; y++, sy += yinc) { \ - s = (const type*)(sbase + (sy >> 16) * slock.Pitch); \ - dx = d; \ - for (x = sx = 0; x < dstwidth; x++, sx += xinc) { \ - tmp = s[sx >> 16]; \ - if (((tmp & keymask) < keylow || (tmp & keymask) > keyhigh) && \ - ((dx[0] & destkeymask) >= destkeylow && (dx[0] & destkeymask) <= destkeyhigh)) { \ - dx[0] = tmp; \ - } \ - dx = (type*)(((LPBYTE)dx)+dstxinc); \ - } \ - d = (type*)(((LPBYTE)d)+dstyinc); \ - } \ - break; } - - switch (bpp) { - case 1: COPY_COLORKEY_FX(BYTE) - case 2: COPY_COLORKEY_FX(WORD) - case 4: COPY_COLORKEY_FX(DWORD) - case 3: - { - const BYTE *s; - BYTE *d = dbuf, *dx; - for (y = sy = 0; y < dstheight; y++, sy += yinc) - { - sbuf = sbase + (sy >> 16) * slock.Pitch; - dx = d; - for (x = sx = 0; x < dstwidth; x++, sx+= xinc) - { - DWORD pixel, dpixel = 0; - s = sbuf+3*(sx>>16); - pixel = s[0]|(s[1]<<8)|(s[2]<<16); - dpixel = dx[0]|(dx[1]<<8)|(dx[2]<<16); - if (((pixel & keymask) < keylow || (pixel & keymask) > keyhigh) && - ((dpixel & keymask) >= destkeylow || (dpixel & keymask) <= keyhigh)) - { - dx[0] = (pixel )&0xff; - dx[1] = (pixel>> 8)&0xff; - dx[2] = (pixel>>16)&0xff; - } - dx+= dstxinc; - } - d += dstyinc; - } - break; - } - default: - FIXME("%s color-keyed blit not implemented for bpp %d!\n", - (flags & WINEDDBLT_KEYSRC) ? "Source" : "Destination", bpp*8); - ret = WINED3DERR_NOTAVAILABLE; - goto error; -#undef COPY_COLORKEY_FX - } - } - } - -error: - if (flags && FIXME_ON(d3d_surface)) - { - FIXME("\tUnsupported flags: %#x.\n", flags); - } - -release: - IWineD3DSurface_Unmap(iface); - if (src && src != This) IWineD3DSurface_Unmap((IWineD3DSurface *)src); - /* Release the converted surface if any */ - if (src && src_surface != (IWineD3DSurface *)src) IWineD3DSurface_Release((IWineD3DSurface *)src); - return ret; -} - -/***************************************************************************** - * IWineD3DSurface::BltFast, SW emulation version - * - * This is the software implementation of BltFast, as used by GDI surfaces - * and as a fallback for OpenGL surfaces. This code is taken from the old - * DirectDraw code, and was originally written by TransGaming. - * - * Params: - * dstx: - * dsty: - * src_surface: Source surface to copy from - * rsrc: Source rectangle - * trans: Some flags - * - * Returns: - * WINED3D_OK on success - * - *****************************************************************************/ -HRESULT WINAPI IWineD3DBaseSurfaceImpl_BltFast(IWineD3DSurface *iface, DWORD dstx, DWORD dsty, - IWineD3DSurface *src_surface, const RECT *rsrc, DWORD trans) -{ - IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface; - IWineD3DSurfaceImpl *src = (IWineD3DSurfaceImpl *)src_surface; - - int bpp, w, h, x, y; - WINED3DLOCKED_RECT dlock,slock; - HRESULT ret = WINED3D_OK; - RECT rsrc2; - RECT lock_src, lock_dst, lock_union; - const BYTE *sbuf; - BYTE *dbuf; - const struct wined3d_format *sEntry, *dEntry; - - TRACE("iface %p, dst_x %u, dst_y %u, src_surface %p, src_rect %s, flags %#x.\n", - iface, dstx, dsty, src_surface, wine_dbgstr_rect(rsrc), trans); - - if ((This->flags & SFLAG_LOCKED) || (src->flags & SFLAG_LOCKED)) - { - WARN(" Surface is busy, returning DDERR_SURFACEBUSY\n"); - return WINEDDERR_SURFACEBUSY; - } - - if (!rsrc) - { - WARN("rsrc is NULL!\n"); - rsrc2.left = 0; - rsrc2.top = 0; - rsrc2.right = src->resource.width; - rsrc2.bottom = src->resource.height; - rsrc = &rsrc2; - } - - /* Check source rect for validity. Copied from normal Blt. Fixes Baldur's Gate.*/ - if ((rsrc->bottom > src->resource.height) || (rsrc->bottom < 0) - || (rsrc->top > src->resource.height) || (rsrc->top < 0) - || (rsrc->left > src->resource.width) || (rsrc->left < 0) - || (rsrc->right > src->resource.width) || (rsrc->right < 0) - || (rsrc->right < rsrc->left) || (rsrc->bottom < rsrc->top)) - { - WARN("Application gave us bad source rectangle for BltFast.\n"); - return WINEDDERR_INVALIDRECT; - } - - h = rsrc->bottom - rsrc->top; - if (h > This->resource.height-dsty) - h = This->resource.height-dsty; - if (h > src->resource.height-rsrc->top) - h = src->resource.height-rsrc->top; - if (h <= 0) - return WINEDDERR_INVALIDRECT; - - w = rsrc->right - rsrc->left; - if (w > This->resource.width-dstx) - w = This->resource.width-dstx; - if (w > src->resource.width-rsrc->left) - w = src->resource.width-rsrc->left; - if (w <= 0) - return WINEDDERR_INVALIDRECT; - - /* Now compute the locking rectangle... */ - lock_src.left = rsrc->left; - lock_src.top = rsrc->top; - lock_src.right = lock_src.left + w; - lock_src.bottom = lock_src.top + h; - - lock_dst.left = dstx; - lock_dst.top = dsty; - lock_dst.right = dstx + w; - lock_dst.bottom = dsty + h; - - bpp = This->resource.format->byte_count; - - /* We need to lock the surfaces, or we won't get refreshes when done. */ - if (src == This) - { - int pitch; - - UnionRect(&lock_union, &lock_src, &lock_dst); - - /* Lock the union of the two rectangles */ - ret = IWineD3DSurface_Map(iface, &dlock, &lock_union, 0); - if (FAILED(ret)) goto error; - - pitch = dlock.Pitch; - slock.Pitch = dlock.Pitch; - - /* Since slock was originally copied from this surface's description, we can just reuse it */ - sbuf = This->resource.allocatedMemory + lock_src.top * pitch + lock_src.left * bpp; - dbuf = This->resource.allocatedMemory + lock_dst.top * pitch + lock_dst.left * bpp; - sEntry = src->resource.format; - dEntry = sEntry; - } - else - { - ret = IWineD3DSurface_Map(src_surface, &slock, &lock_src, WINED3DLOCK_READONLY); - if (FAILED(ret)) goto error; - ret = IWineD3DSurface_Map(iface, &dlock, &lock_dst, 0); - if (FAILED(ret)) goto error; - - sbuf = slock.pBits; - dbuf = dlock.pBits; - TRACE("Dst is at %p, Src is at %p\n", dbuf, sbuf); - - sEntry = src->resource.format; - dEntry = This->resource.format; - } - - /* Handle compressed surfaces first... */ - if (sEntry->flags & dEntry->flags & WINED3DFMT_FLAG_COMPRESSED) - { - UINT row_block_count; - - TRACE("compressed -> compressed copy\n"); - if (trans) - FIXME("trans arg not supported when a compressed surface is involved\n"); - if (dstx || dsty) - FIXME("offset for destination surface is not supported\n"); - if (src->resource.format->id != This->resource.format->id) - { - FIXME("compressed -> compressed copy only supported for the same type of surface\n"); - ret = WINED3DERR_WRONGTEXTUREFORMAT; - goto error; - } - - row_block_count = (w + dEntry->block_width - 1) / dEntry->block_width; - for (y = 0; y < h; y += dEntry->block_height) - { - memcpy(dbuf, sbuf, row_block_count * dEntry->block_byte_count); - dbuf += dlock.Pitch; - sbuf += slock.Pitch; - } - - goto error; - } - if ((sEntry->flags & WINED3DFMT_FLAG_COMPRESSED) && !(dEntry->flags & WINED3DFMT_FLAG_COMPRESSED)) - { - /* TODO: Use the libtxc_dxtn.so shared library to do - * software decompression - */ - ERR("Software decompression not supported.\n"); - goto error; - } - - if (trans & (WINEDDBLTFAST_SRCCOLORKEY | WINEDDBLTFAST_DESTCOLORKEY)) - { - DWORD keylow, keyhigh; - DWORD mask = src->resource.format->red_mask - | src->resource.format->green_mask - | src->resource.format->blue_mask; - - /* For some 8-bit formats like L8 and P8 color masks don't make sense */ - if(!mask && bpp==1) - mask = 0xff; - - TRACE("Color keyed copy\n"); - if (trans & WINEDDBLTFAST_SRCCOLORKEY) - { - keylow = src->SrcBltCKey.dwColorSpaceLowValue; - keyhigh = src->SrcBltCKey.dwColorSpaceHighValue; - } - else - { - /* I'm not sure if this is correct */ - FIXME("WINEDDBLTFAST_DESTCOLORKEY not fully supported yet.\n"); - keylow = This->DestBltCKey.dwColorSpaceLowValue; - keyhigh = This->DestBltCKey.dwColorSpaceHighValue; - } - -#define COPYBOX_COLORKEY(type) { \ - const type *s = (const type *)sbuf; \ - type *d = (type *)dbuf; \ - type tmp; \ - for (y = 0; y < h; y++) { \ - for (x = 0; x < w; x++) { \ - tmp = s[x]; \ - if ((tmp & mask) < keylow || (tmp & mask) > keyhigh) d[x] = tmp; \ - } \ - s = (const type *)((const BYTE *)s + slock.Pitch); \ - d = (type *)((BYTE *)d + dlock.Pitch); \ - } \ - break; \ - } - - switch (bpp) { - case 1: COPYBOX_COLORKEY(BYTE) - case 2: COPYBOX_COLORKEY(WORD) - case 4: COPYBOX_COLORKEY(DWORD) - case 3: - { - const BYTE *s; - BYTE *d; - DWORD tmp; - s = sbuf; - d = dbuf; - for (y = 0; y < h; y++) - { - for (x = 0; x < w * 3; x += 3) - { - tmp = (DWORD)s[x] + ((DWORD)s[x + 1] << 8) + ((DWORD)s[x + 2] << 16); - if (tmp < keylow || tmp > keyhigh) - { - d[x + 0] = s[x + 0]; - d[x + 1] = s[x + 1]; - d[x + 2] = s[x + 2]; - } - } - s += slock.Pitch; - d += dlock.Pitch; - } - break; - } - default: - FIXME("Source color key blitting not supported for bpp %d\n",bpp*8); - ret = WINED3DERR_NOTAVAILABLE; - goto error; - } -#undef COPYBOX_COLORKEY - TRACE("Copy Done\n"); - } - else - { - int width = w * bpp; - INT sbufpitch, dbufpitch; - - TRACE("NO color key copy\n"); - /* Handle overlapping surfaces */ - if (sbuf < dbuf) - { - sbuf += (h - 1) * slock.Pitch; - dbuf += (h - 1) * dlock.Pitch; - sbufpitch = -slock.Pitch; - dbufpitch = -dlock.Pitch; - } - else - { - sbufpitch = slock.Pitch; - dbufpitch = dlock.Pitch; - } - for (y = 0; y < h; y++) - { - /* This is pretty easy, a line for line memcpy */ - memmove(dbuf, sbuf, width); - sbuf += sbufpitch; - dbuf += dbufpitch; - } - TRACE("Copy done\n"); - } - -error: - if (src == This) - { - IWineD3DSurface_Unmap(iface); - } - else - { - IWineD3DSurface_Unmap(iface); - IWineD3DSurface_Unmap(src_surface); - } - - return ret; -} - -HRESULT WINAPI IWineD3DBaseSurfaceImpl_Map(IWineD3DSurface *iface, - WINED3DLOCKED_RECT *pLockedRect, const RECT *pRect, DWORD flags) -{ - IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface; - - TRACE("iface %p, locked_rect %p, rect %s, flags %#x.\n", - iface, pLockedRect, wine_dbgstr_rect(pRect), flags); - - pLockedRect->Pitch = IWineD3DSurface_GetPitch(iface); - - if (!pRect) - { - pLockedRect->pBits = This->resource.allocatedMemory; - This->lockedRect.left = 0; - This->lockedRect.top = 0; - This->lockedRect.right = This->resource.width; - This->lockedRect.bottom = This->resource.height; - - TRACE("Locked Rect (%p) = l %d, t %d, r %d, b %d\n", - &This->lockedRect, This->lockedRect.left, This->lockedRect.top, - This->lockedRect.right, This->lockedRect.bottom); - } - else - { - const struct wined3d_format *format = This->resource.format; - - TRACE("Lock Rect (%p) = l %d, t %d, r %d, b %d\n", - pRect, pRect->left, pRect->top, pRect->right, pRect->bottom); - - if ((format->flags & (WINED3DFMT_FLAG_COMPRESSED | WINED3DFMT_FLAG_BROKEN_PITCH)) == WINED3DFMT_FLAG_COMPRESSED) - { - /* Compressed textures are block based, so calculate the offset of - * the block that contains the top-left pixel of the locked rectangle. */ - pLockedRect->pBits = This->resource.allocatedMemory - + ((pRect->top / format->block_height) * pLockedRect->Pitch) - + ((pRect->left / format->block_width) * format->block_byte_count); - } - else - { - pLockedRect->pBits = This->resource.allocatedMemory + - (pLockedRect->Pitch * pRect->top) + - (pRect->left * format->byte_count); - } - This->lockedRect.left = pRect->left; - This->lockedRect.top = pRect->top; - This->lockedRect.right = pRect->right; - This->lockedRect.bottom = pRect->bottom; - } - - /* No dirtifying is needed for this surface implementation */ - TRACE("returning memory@%p, pitch(%d)\n", pLockedRect->pBits, pLockedRect->Pitch); - - return WINED3D_OK; -} diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 3648ddf010b..0a9b36a0caf 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -2129,52 +2129,6 @@ void surface_set_texture_name(IWineD3DSurfaceImpl *surface, GLuint name, BOOL sr void surface_set_texture_target(IWineD3DSurfaceImpl *surface, GLenum target) DECLSPEC_HIDDEN; void surface_translate_drawable_coords(IWineD3DSurfaceImpl *surface, HWND window, RECT *rect) DECLSPEC_HIDDEN; -/* Predeclare the shared Surface functions */ -HRESULT WINAPI IWineD3DBaseSurfaceImpl_QueryInterface(IWineD3DSurface *iface, - REFIID riid, LPVOID *ppobj) DECLSPEC_HIDDEN; -ULONG WINAPI IWineD3DBaseSurfaceImpl_AddRef(IWineD3DSurface *iface) DECLSPEC_HIDDEN; -void * WINAPI IWineD3DBaseSurfaceImpl_GetParent(IWineD3DSurface *iface) DECLSPEC_HIDDEN; -HRESULT WINAPI IWineD3DBaseSurfaceImpl_SetPrivateData(IWineD3DSurface *iface, - REFGUID refguid, const void *pData, DWORD SizeOfData, DWORD flags) DECLSPEC_HIDDEN; -HRESULT WINAPI IWineD3DBaseSurfaceImpl_GetPrivateData(IWineD3DSurface *iface, - REFGUID refguid, void *pData, DWORD *pSizeOfData) DECLSPEC_HIDDEN; -HRESULT WINAPI IWineD3DBaseSurfaceImpl_FreePrivateData(IWineD3DSurface *iface, REFGUID refguid) DECLSPEC_HIDDEN; -DWORD WINAPI IWineD3DBaseSurfaceImpl_SetPriority(IWineD3DSurface *iface, DWORD PriorityNew) DECLSPEC_HIDDEN; -DWORD WINAPI IWineD3DBaseSurfaceImpl_GetPriority(IWineD3DSurface *iface) DECLSPEC_HIDDEN; -WINED3DRESOURCETYPE WINAPI IWineD3DBaseSurfaceImpl_GetType(IWineD3DSurface *iface) DECLSPEC_HIDDEN; -struct wined3d_resource * WINAPI IWineD3DBaseSurfaceImpl_GetResource(IWineD3DSurface *iface) DECLSPEC_HIDDEN; -HRESULT WINAPI IWineD3DBaseSurfaceImpl_GetBltStatus(IWineD3DSurface *iface, DWORD flags) DECLSPEC_HIDDEN; -HRESULT WINAPI IWineD3DBaseSurfaceImpl_GetFlipStatus(IWineD3DSurface *iface, DWORD flags) DECLSPEC_HIDDEN; -HRESULT WINAPI IWineD3DBaseSurfaceImpl_IsLost(IWineD3DSurface *iface) DECLSPEC_HIDDEN; -HRESULT WINAPI IWineD3DBaseSurfaceImpl_Restore(IWineD3DSurface *iface) DECLSPEC_HIDDEN; -HRESULT WINAPI IWineD3DBaseSurfaceImpl_GetPalette(IWineD3DSurface *iface, - struct wined3d_palette **Pal) DECLSPEC_HIDDEN; -HRESULT WINAPI IWineD3DBaseSurfaceImpl_SetPalette(IWineD3DSurface *iface, - struct wined3d_palette *Pal) DECLSPEC_HIDDEN; -HRESULT WINAPI IWineD3DBaseSurfaceImpl_SetColorKey(IWineD3DSurface *iface, - DWORD flags, const WINEDDCOLORKEY *CKey) DECLSPEC_HIDDEN; -DWORD WINAPI IWineD3DBaseSurfaceImpl_GetPitch(IWineD3DSurface *iface) DECLSPEC_HIDDEN; -HRESULT WINAPI IWineD3DBaseSurfaceImpl_SetOverlayPosition(IWineD3DSurface *iface, LONG X, LONG Y) DECLSPEC_HIDDEN; -HRESULT WINAPI IWineD3DBaseSurfaceImpl_GetOverlayPosition(IWineD3DSurface *iface, LONG *X, LONG *Y) DECLSPEC_HIDDEN; -HRESULT WINAPI IWineD3DBaseSurfaceImpl_UpdateOverlayZOrder(IWineD3DSurface *iface, - DWORD flags, IWineD3DSurface *Ref) DECLSPEC_HIDDEN; -HRESULT WINAPI IWineD3DBaseSurfaceImpl_UpdateOverlay(IWineD3DSurface *iface, const RECT *SrcRect, - IWineD3DSurface *DstSurface, const RECT *DstRect, DWORD flags, const WINEDDOVERLAYFX *FX) DECLSPEC_HIDDEN; -HRESULT WINAPI IWineD3DBaseSurfaceImpl_SetClipper(IWineD3DSurface *iface, - struct wined3d_clipper *clipper) DECLSPEC_HIDDEN; -HRESULT WINAPI IWineD3DBaseSurfaceImpl_GetClipper(IWineD3DSurface *iface, - struct wined3d_clipper **clipper) DECLSPEC_HIDDEN; -HRESULT WINAPI IWineD3DBaseSurfaceImpl_SetFormat(IWineD3DSurface *iface, - enum wined3d_format_id format_id) DECLSPEC_HIDDEN; -HRESULT IWineD3DBaseSurfaceImpl_CreateDIBSection(IWineD3DSurface *iface) DECLSPEC_HIDDEN; -HRESULT WINAPI IWineD3DBaseSurfaceImpl_Blt(IWineD3DSurface *iface, const RECT *dst_rect, IWineD3DSurface *src_surface, - const RECT *src_rect, DWORD flags, const WINEDDBLTFX *fx, WINED3DTEXTUREFILTERTYPE filter) DECLSPEC_HIDDEN; -HRESULT WINAPI IWineD3DBaseSurfaceImpl_BltFast(IWineD3DSurface *iface, DWORD dstx, DWORD dsty, - IWineD3DSurface *Source, const RECT *rsrc, DWORD trans) DECLSPEC_HIDDEN; -HRESULT WINAPI IWineD3DBaseSurfaceImpl_Map(IWineD3DSurface *iface, WINED3DLOCKED_RECT *pLockedRect, - const RECT *pRect, DWORD flags) DECLSPEC_HIDDEN; -const void *WINAPI IWineD3DBaseSurfaceImpl_GetData(IWineD3DSurface *iface) DECLSPEC_HIDDEN; - void get_drawable_size_swapchain(struct wined3d_context *context, UINT *width, UINT *height) DECLSPEC_HIDDEN; void get_drawable_size_backbuffer(struct wined3d_context *context, UINT *width, UINT *height) DECLSPEC_HIDDEN; void get_drawable_size_fbo(struct wined3d_context *context, UINT *width, UINT *height) DECLSPEC_HIDDEN; -- 2.11.4.GIT