Commit ba90a740 authored by Roderick Colenbrander's avatar Roderick Colenbrander Committed by Alexandre Julliard

wined3d: Add read_from_framebuffer_texture which combines code from…

wined3d: Add read_from_framebuffer_texture which combines code from read_from_framebuffer (drawpixels) and LoadLocation. This makes the code easier to read and the pieces borrowed from read_from_framebuffer are more correct than the code in LoadLocation.
parent 61ca7a57
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
* Copyright 2005 Oliver Stieber * Copyright 2005 Oliver Stieber
* Copyright 2006-2007 Stefan Dsinger for CodeWeavers * Copyright 2006-2007 Stefan Dsinger for CodeWeavers
* Copyright 2007 Henri Verbeet * Copyright 2007 Henri Verbeet
* Copyright 2006-2007 Roderick Colenbrander * Copyright 2006-2008 Roderick Colenbrander
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
...@@ -35,6 +35,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3d_surface); ...@@ -35,6 +35,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3d_surface);
HRESULT d3dfmt_convert_surface(BYTE *src, BYTE *dst, UINT pitch, UINT width, UINT height, UINT outpitch, CONVERT_TYPES convert, IWineD3DSurfaceImpl *surf); HRESULT d3dfmt_convert_surface(BYTE *src, BYTE *dst, UINT pitch, UINT width, UINT height, UINT outpitch, CONVERT_TYPES convert, IWineD3DSurfaceImpl *surf);
static void d3dfmt_p8_init_palette(IWineD3DSurfaceImpl *This, BYTE table[256][4], BOOL colorkey); static void d3dfmt_p8_init_palette(IWineD3DSurfaceImpl *This, BYTE table[256][4], BOOL colorkey);
static inline void clear_unused_channels(IWineD3DSurfaceImpl *This);
static void surface_bind_and_dirtify(IWineD3DSurfaceImpl *This) { static void surface_bind_and_dirtify(IWineD3DSurfaceImpl *This) {
/* Make sure that a proper texture unit is selected, bind the texture /* Make sure that a proper texture unit is selected, bind the texture
...@@ -603,6 +604,7 @@ const void *WINAPI IWineD3DSurfaceImpl_GetData(IWineD3DSurface *iface) { ...@@ -603,6 +604,7 @@ const void *WINAPI IWineD3DSurfaceImpl_GetData(IWineD3DSurface *iface) {
return (CONST void*)(This->resource.allocatedMemory); return (CONST void*)(This->resource.allocatedMemory);
} }
/* Read the framebuffer back into the surface */
static void read_from_framebuffer(IWineD3DSurfaceImpl *This, CONST RECT *rect, void *dest, UINT pitch) { static void read_from_framebuffer(IWineD3DSurfaceImpl *This, CONST RECT *rect, void *dest, UINT pitch) {
IWineD3DSwapChainImpl *swapchain; IWineD3DSwapChainImpl *swapchain;
IWineD3DDeviceImpl *myDevice = This->resource.wineD3DDevice; IWineD3DDeviceImpl *myDevice = This->resource.wineD3DDevice;
...@@ -806,6 +808,79 @@ static void read_from_framebuffer(IWineD3DSurfaceImpl *This, CONST RECT *rect, v ...@@ -806,6 +808,79 @@ static void read_from_framebuffer(IWineD3DSurfaceImpl *This, CONST RECT *rect, v
LEAVE_GL(); LEAVE_GL();
} }
/* Read the framebuffer contents into a texture */
static void read_from_framebuffer_texture(IWineD3DSurfaceImpl *This)
{
IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;
IWineD3DSwapChainImpl *swapchain;
int bpp;
GLenum format, internal, type;
CONVERT_TYPES convert;
BOOL srcIsUpsideDown;
GLint prevRead;
d3dfmt_get_conv(This, TRUE /* We need color keying */, TRUE /* We will use textures */, &format, &internal, &type, &convert, &bpp, This->srgb);
IWineD3DSurface_GetContainer((IWineD3DSurface *) This, &IID_IWineD3DSwapChain, (void **)&swapchain);
/* Activate the surface. Set it up for blitting now, although not necessarily needed for LockRect.
* Certain graphics drivers seem to dislike some enabled states when reading from opengl, the blitting usage
* should help here. Furthermore unlockrect will need the context set up for blitting. The context manager will find
* context->last_was_blit set on the unlock.
*/
ActivateContext(device, (IWineD3DSurface *) This, CTXUSAGE_BLIT);
surface_bind_and_dirtify(This);
ENTER_GL();
glGetIntegerv(GL_READ_BUFFER, &prevRead);
/* Select the correct read buffer, and give some debug output.
* There is no need to keep track of the current read buffer or reset it, every part of the code
* that reads sets the read buffer as desired.
*/
if(!swapchain) {
/* Locking the primary render target which is not on a swapchain(=offscreen render target).
* Read from the back buffer
*/
TRACE("Locking offscreen render target\n");
glReadBuffer(device->offscreenBuffer);
srcIsUpsideDown = TRUE;
} else {
GLenum buffer = surface_get_gl_buffer((IWineD3DSurface *) This, (IWineD3DSwapChain *)swapchain);
TRACE("Locking %#x buffer\n", buffer);
glReadBuffer(buffer);
checkGLcall("glReadBuffer");
IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain);
srcIsUpsideDown = FALSE;
}
if(!(This->Flags & SFLAG_ALLOCATED)) {
surface_allocate_surface(This, internal, This->pow2Width,
This->pow2Height, format, type);
}
clear_unused_channels(This);
/* If !SrcIsUpsideDown we should flip the surface.
* This can be done using glCopyTexSubImage2D but this
* is VERY slow, so don't do that. We should prevent
* this code from getting called in such cases or perhaps
* we can use FBOs */
glCopyTexSubImage2D(This->glDescription.target,
This->glDescription.level,
0, 0, 0, 0,
This->currentDesc.Width,
This->currentDesc.Height);
checkGLcall("glCopyTexSubImage2D");
glReadBuffer(prevRead);
vcheckGLcall("glReadBuffer");
LEAVE_GL();
TRACE("Updated target %d\n", This->glDescription.target);
}
static void surface_prepare_system_memory(IWineD3DSurfaceImpl *This) { static void surface_prepare_system_memory(IWineD3DSurfaceImpl *This) {
/* Performance optimization: Count how often a surface is locked, if it is locked regularly do not throw away the system memory copy. /* Performance optimization: Count how often a surface is locked, if it is locked regularly do not throw away the system memory copy.
* This avoids the need to download the surface from opengl all the time. The surface is still downloaded if the opengl texture is * This avoids the need to download the surface from opengl all the time. The surface is still downloaded if the opengl texture is
...@@ -3865,41 +3940,15 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_LoadLocation(IWineD3DSurface *iface, D ...@@ -3865,41 +3940,15 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_LoadLocation(IWineD3DSurface *iface, D
HeapFree(GetProcessHeap(), 0, mem); HeapFree(GetProcessHeap(), 0, mem);
} }
} else /* if(flag == SFLAG_INTEXTURE) */ { } else /* if(flag == SFLAG_INTEXTURE) */ {
d3dfmt_get_conv(This, TRUE /* We need color keying */, TRUE /* We will use textures */, &format, &internal, &type, &convert, &bpp, This->srgb);
ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
surface_bind_and_dirtify(This);
if (This->Flags & SFLAG_INDRAWABLE) { if (This->Flags & SFLAG_INDRAWABLE) {
GLint prevRead; read_from_framebuffer_texture(This);
} else { /* Upload from system memory */
d3dfmt_get_conv(This, TRUE /* We need color keying */, TRUE /* We will use textures */, &format, &internal, &type, &convert, &bpp, This->srgb);
ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
surface_bind_and_dirtify(This);
ENTER_GL(); ENTER_GL();
glGetIntegerv(GL_READ_BUFFER, &prevRead);
vcheckGLcall("glGetIntegerv");
glReadBuffer(This->resource.wineD3DDevice->offscreenBuffer);
vcheckGLcall("glReadBuffer");
if(!(This->Flags & SFLAG_ALLOCATED)) {
surface_allocate_surface(This, internal, This->pow2Width,
This->pow2Height, format, type);
}
clear_unused_channels(This);
glCopyTexSubImage2D(This->glDescription.target,
This->glDescription.level,
0, 0, 0, 0,
This->currentDesc.Width,
This->currentDesc.Height);
checkGLcall("glCopyTexSubImage2D");
glReadBuffer(prevRead);
vcheckGLcall("glReadBuffer");
LEAVE_GL();
TRACE("Updated target %d\n", This->glDescription.target);
} else {
/* The only place where LoadTexture() might get called when isInDraw=1 /* The only place where LoadTexture() might get called when isInDraw=1
* is ActivateContext where lastActiveRenderTarget is preloaded. * is ActivateContext where lastActiveRenderTarget is preloaded.
*/ */
...@@ -3967,6 +4016,7 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_LoadLocation(IWineD3DSurface *iface, D ...@@ -3967,6 +4016,7 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_LoadLocation(IWineD3DSurface *iface, D
/* Restore the default pitch */ /* Restore the default pitch */
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
LEAVE_GL();
/* Don't delete PBO memory */ /* Don't delete PBO memory */
if((mem != This->resource.allocatedMemory) && !(This->Flags & SFLAG_PBO)) if((mem != This->resource.allocatedMemory) && !(This->Flags & SFLAG_PBO))
......
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