Commit a175e7b6 authored by Stefan Dösinger's avatar Stefan Dösinger Committed by Alexandre Julliard

wined3d: Move a part of LockRect to the base class.

parent 2a09716c
......@@ -690,41 +690,14 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_LockRect(IWineD3DSurface *iface, WINED
TRACE("(%p) : rect@%p flags(%08x), output lockedRect@%p, memory@%p\n", This, pRect, Flags, pLockedRect, This->resource.allocatedMemory);
/* This is also done in the base class, but we have to verify this before loading any data from
* gl into the sysmem copy. The PBO may be mapped, a different rectangle locked, the discard flag
* may interfere, and all other bad things may happen
*/
if (This->Flags & SFLAG_LOCKED) {
WARN("Surface is already locked, returning D3DERR_INVALIDCALL\n");
return WINED3DERR_INVALIDCALL;
}
if (!(This->Flags & SFLAG_LOCKABLE)) {
/* Note: UpdateTextures calls CopyRects which calls this routine to populate the
texture regions, and since the destination is an unlockable region we need
to tolerate this */
TRACE("Warning: trying to lock unlockable surf@%p\n", This);
/*return WINED3DERR_INVALIDCALL; */
}
pLockedRect->Pitch = IWineD3DSurface_GetPitch(iface);
/* Mark the surface locked */
This->Flags |= SFLAG_LOCKED;
/* Calculate the correct start address to report */
if (NULL == pRect) {
This->lockedRect.left = 0;
This->lockedRect.top = 0;
This->lockedRect.right = This->currentDesc.Width;
This->lockedRect.bottom = This->currentDesc.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 {
This->lockedRect.left = pRect->left;
This->lockedRect.top = pRect->top;
This->lockedRect.right = pRect->right;
This->lockedRect.bottom = pRect->bottom;
TRACE("Locked Rect (%p) = l %d, t %d, r %d, b %d\n", pRect, pRect->left, pRect->top, pRect->right, pRect->bottom);
}
if (This->Flags & SFLAG_NONPOW2) {
TRACE("Locking non-power 2 texture\n");
}
if (Flags & WINED3DLOCK_DISCARD) {
/* Set SFLAG_INSYSMEM, so we'll never try to download the data from the texture. */
......@@ -744,15 +717,17 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_LockRect(IWineD3DSurface *iface, WINED
*/
IWineD3DSurface_GetContainer(iface, &IID_IWineD3DSwapChain, (void **)&swapchain);
if(swapchain || iface == myDevice->render_targets[0]) {
RECT *read_rect;
const RECT *pass_rect = pRect;
if(This->lockedRect.left == 0 &&
This->lockedRect.top == 0 &&
This->lockedRect.right == This->currentDesc.Width &&
This->lockedRect.bottom == This->currentDesc.Height) {
read_rect = NULL;
} else {
read_rect = &This->lockedRect;
/* IWineD3DSurface_LoadLocation does not check if the rectangle specifies the full surfaces
* because most caller functions do not need that. So do that here
*/
if(pRect &&
pRect->top == 0 &&
pRect->left == 0 &&
pRect->right == This->currentDesc.Width &&
pRect->bottom == This->currentDesc.Height) {
pass_rect = NULL;
}
switch(wined3d_settings.rendertargetlock_mode) {
......@@ -771,7 +746,7 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_LockRect(IWineD3DSurface *iface, WINED
case RTL_AUTO:
case RTL_READDRAW:
case RTL_READTEX:
IWineD3DSurface_LoadLocation(iface, SFLAG_INSYSMEM, read_rect);
IWineD3DSurface_LoadLocation(iface, SFLAG_INSYSMEM, pRect);
break;
case RTL_DISABLE:
......@@ -828,27 +803,6 @@ lock_end:
LEAVE_GL();
}
/* Calculate the correct start address to report */
if (NULL == pRect) {
pLockedRect->pBits = This->resource.allocatedMemory;
} else {
/* DXTn textures are based on compressed blocks of 4x4 pixels, each
* 16 bytes large (8 bytes in case of DXT1). Because of that Pitch has
* slightly different meaning compared to regular textures. For DXTn
* textures Pitch is the size of a row of blocks, 4 high and "width"
* long. The x offset is calculated differently as well, since moving 4
* pixels to the right actually moves an entire 4x4 block to right, ie
* 16 bytes (8 in case of DXT1). */
if (This->resource.format == WINED3DFMT_DXT1) {
pLockedRect->pBits = This->resource.allocatedMemory + (pLockedRect->Pitch * pRect->top / 4) + (pRect->left * 2);
} else if (This->resource.format == WINED3DFMT_DXT2 || This->resource.format == WINED3DFMT_DXT3
|| This->resource.format == WINED3DFMT_DXT4 || This->resource.format == WINED3DFMT_DXT5) {
pLockedRect->pBits = This->resource.allocatedMemory + (pLockedRect->Pitch * pRect->top / 4) + (pRect->left * 4);
} else {
pLockedRect->pBits = This->resource.allocatedMemory + (pLockedRect->Pitch * pRect->top) + (pRect->left * This->bytesPerPixel);
}
}
if (Flags & (WINED3DLOCK_NO_DIRTY_UPDATE | WINED3DLOCK_READONLY)) {
/* Don't dirtify */
} else {
......@@ -869,9 +823,7 @@ lock_end:
}
}
TRACE("returning memory@%p, pitch(%d) dirtyfied(%d)\n", pLockedRect->pBits, pLockedRect->Pitch,
This->Flags & (SFLAG_INDRAWABLE | SFLAG_INTEXTURE) ? 0 : 1);
return WINED3D_OK;
return IWineD3DBaseSurfaceImpl_LockRect(iface, pLockedRect, pRect, Flags);
}
static void flush_to_framebuffer_drawpixels(IWineD3DSurfaceImpl *This) {
......
......@@ -1568,3 +1568,80 @@ error:
return ret;
}
HRESULT WINAPI IWineD3DBaseSurfaceImpl_LockRect(IWineD3DSurface *iface, WINED3DLOCKED_RECT* pLockedRect, CONST RECT* pRect, DWORD Flags)
{
IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
/* Already locked? */
if(This->Flags & SFLAG_LOCKED)
{
ERR("(%p) Surface already locked\n", This);
/* What should I return here? */
return WINED3DERR_INVALIDCALL;
}
if (!(This->Flags & SFLAG_LOCKABLE))
{
/* This is some GL specific thing, see the OpenGL version of
* this method, but check for the flag and write a trace
*/
TRACE("Warning: trying to lock unlockable surf@%p\n", This);
}
TRACE("(%p) : rect@%p flags(%08x), output lockedRect@%p, memory@%p\n",
This, pRect, Flags, pLockedRect, This->resource.allocatedMemory);
pLockedRect->Pitch = IWineD3DSurface_GetPitch(iface);
if (NULL == pRect)
{
pLockedRect->pBits = This->resource.allocatedMemory;
This->lockedRect.left = 0;
This->lockedRect.top = 0;
This->lockedRect.right = This->currentDesc.Width;
This->lockedRect.bottom = This->currentDesc.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
{
TRACE("Lock Rect (%p) = l %d, t %d, r %d, b %d\n",
pRect, pRect->left, pRect->top, pRect->right, pRect->bottom);
/* DXTn textures are based on compressed blocks of 4x4 pixels, each
* 16 bytes large (8 bytes in case of DXT1). Because of that Pitch has
* slightly different meaning compared to regular textures. For DXTn
* textures Pitch is the size of a row of blocks, 4 high and "width"
* long. The x offset is calculated differently as well, since moving 4
* pixels to the right actually moves an entire 4x4 block to right, ie
* 16 bytes (8 in case of DXT1). */
if (This->resource.format == WINED3DFMT_DXT1)
{
pLockedRect->pBits = This->resource.allocatedMemory + (pLockedRect->Pitch * pRect->top / 4) + (pRect->left * 2);
}
else if (This->resource.format == WINED3DFMT_DXT2 || This->resource.format == WINED3DFMT_DXT3 ||
This->resource.format == WINED3DFMT_DXT4 || This->resource.format == WINED3DFMT_DXT5)
{
pLockedRect->pBits = This->resource.allocatedMemory + (pLockedRect->Pitch * pRect->top / 4) + (pRect->left * 4);
}
else
{
pLockedRect->pBits = This->resource.allocatedMemory +
(pLockedRect->Pitch * pRect->top) +
(pRect->left * This->bytesPerPixel);
}
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);
This->Flags |= SFLAG_LOCKED;
return WINED3D_OK;
}
......@@ -205,80 +205,15 @@ IWineGDISurfaceImpl_LockRect(IWineD3DSurface *iface,
{
IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
/* Already locked? */
if(This->Flags & SFLAG_LOCKED)
{
ERR("(%p) Surface already locked\n", This);
/* What should I return here? */
return WINED3DERR_INVALIDCALL;
}
if (!(This->Flags & SFLAG_LOCKABLE))
{
/* This is some GL specific thing, see the OpenGL version of
* this method, but check for the flag and write a trace
*/
TRACE("Warning: trying to lock unlockable surf@%p\n", This);
}
TRACE("(%p) : rect@%p flags(%08x), output lockedRect@%p, memory@%p\n",
This, pRect, Flags, pLockedRect, This->resource.allocatedMemory);
if(!This->resource.allocatedMemory) {
HDC hdc;
HRESULT hr;
/* This happens on gdi surfaces if the application set a user pointer and resets it.
* Recreate the DIB section
*/
hr = IWineD3DSurface_GetDC(iface, &hdc); /* will recursively call lockrect, do not set the LOCKED flag to this line */
if(hr != WINED3D_OK) return hr;
hr = IWineD3DSurface_ReleaseDC(iface, hdc);
if(hr != WINED3D_OK) return hr;
IWineD3DBaseSurfaceImpl_CreateDIBSection(iface);
This->resource.allocatedMemory = This->dib.bitmap_data;
}
pLockedRect->Pitch = IWineD3DSurface_GetPitch(iface);
if (NULL == pRect)
{
pLockedRect->pBits = This->resource.allocatedMemory;
This->lockedRect.left = 0;
This->lockedRect.top = 0;
This->lockedRect.right = This->currentDesc.Width;
This->lockedRect.bottom = This->currentDesc.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
{
TRACE("Lock Rect (%p) = l %d, t %d, r %d, b %d\n",
pRect, pRect->left, pRect->top, pRect->right, pRect->bottom);
if (This->resource.format == WINED3DFMT_DXT1)
{
/* DXT1 is half byte per pixel */
pLockedRect->pBits = This->resource.allocatedMemory +
(pLockedRect->Pitch * pRect->top) +
((pRect->left * This->bytesPerPixel / 2));
}
else
{
pLockedRect->pBits = This->resource.allocatedMemory +
(pLockedRect->Pitch * pRect->top) +
(pRect->left * This->bytesPerPixel);
}
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);
This->Flags |= SFLAG_LOCKED;
return WINED3D_OK;
return IWineD3DBaseSurfaceImpl_LockRect(iface, pLockedRect, pRect, Flags);
}
/*****************************************************************************
......
......@@ -1163,10 +1163,10 @@ HRESULT WINAPI IWineD3DBaseSurfaceImpl_SetFormat(IWineD3DSurface *iface, WINED3D
HRESULT IWineD3DBaseSurfaceImpl_CreateDIBSection(IWineD3DSurface *iface);
HRESULT WINAPI IWineD3DBaseSurfaceImpl_Blt(IWineD3DSurface *iface, RECT *DestRect, IWineD3DSurface *SrcSurface, RECT *SrcRect, DWORD Flags, WINEDDBLTFX *DDBltFx, WINED3DTEXTUREFILTERTYPE Filter);
HRESULT WINAPI IWineD3DBaseSurfaceImpl_BltFast(IWineD3DSurface *iface, DWORD dstx, DWORD dsty, IWineD3DSurface *Source, RECT *rsrc, DWORD trans);
HRESULT WINAPI IWineD3DBaseSurfaceImpl_LockRect(IWineD3DSurface *iface, WINED3DLOCKED_RECT* pLockedRect, CONST RECT* pRect, DWORD Flags);
const void *WINAPI IWineD3DSurfaceImpl_GetData(IWineD3DSurface *iface);
/* Surface flags: */
#define SFLAG_OVERSIZE 0x00000001 /* Surface is bigger than gl size, blts only */
#define SFLAG_CONVERTED 0x00000002 /* Converted for color keying or Palettized */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment