swapchain.c revision a3133ef29cdf3656735d569fd64e54c9286effc0
/*
*IDirect3DSwapChain9 implementation
*
*Copyright 2002-2003 Jason Edmeades
*Copyright 2002-2003 Raphael Junqueira
*Copyright 2005 Oliver Stieber
*Copyright 2007-2008 Stefan Dösinger for CodeWeavers
*
*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
*/
/*
* Sun LGPL Disclaimer: For the avoidance of doubt, except that if any license choice
* other than GPL or LGPL is available it will apply instead, Sun elects to use only
* the Lesser General Public License version 2.1 (LGPLv2) at this time for any software where
* a choice of LGPL license versions is made available with the language indicating
* that LGPLv2 or any later version may be used, or where a choice of which version
* of the LGPL is applied is otherwise unspecified.
*/
#include "config.h"
#include "wined3d_private.h"
/*TODO: some of the additional parameters may be required to
set the gamma ramp (for some weird reason microsoft have left swap gammaramp in device
but it operates on a swapchain, it may be a good idea to move it to IWineD3DSwapChain for IWineD3D)*/
/*IWineD3DSwapChain parts follow: */
{
unsigned int i;
/* Release the swapchain's draw buffers. Make sure This->backBuffer[0] is
* the last buffer to be destroyed, FindContext() depends on that. */
if (This->frontBuffer)
{
{
WARN("(%p) Something's still holding the front buffer (%p).\n",
}
}
if (This->backBuffer)
{
while (i--)
{
WARN("(%p) Something's still holding back buffer %u (%p).\n",
}
}
for (i = 0; i < This->num_contexts; ++i)
{
}
/* Restore the screen resolution if we rendered in fullscreen
* This will restore the screen resolution to what it was before creating the swapchain. In case of d3d8 and d3d9
* this will be the original desktop resolution. In case of d3d7 this will be a NOP because ddraw sets the resolution
* before starting up Direct3D, thus orig_width and orig_height will be equal to the modes in the presentation params
*/
mode.RefreshRate = 0;
}
}
static HRESULT WINAPI IWineD3DSwapChainImpl_Present(IWineD3DSwapChain *iface, CONST RECT *pSourceRect, CONST RECT *pDestRect, HWND hDestWindowOverride, CONST RGNDATA *pDirtyRegion, DWORD dwFlags) {
unsigned int sync;
int retval;
/* Render the cursor onto the back buffer, using our nifty directdraw blitting code :-) */
This->wineD3DDevice->xScreenSpace + This->wineD3DDevice->cursorWidth - This->wineD3DDevice->xHotSpot,
This->wineD3DDevice->yScreenSpace + This->wineD3DDevice->cursorHeight - This->wineD3DDevice->yHotSpot};
/* Build a fake surface to call the Blitting code. It is not possible to use the interface passed by
* the application because we are only supposed to copy the information out. Using a fake surface
* allows to use the Blitting engine and avoid copying the whole texture -> render target blitting code.
*/
cursor.texture_level = 0;
/* The cursor must have pow2 sizes */
/* The surface is in the texture */
/* DDBLT_KEYSRC will cause BltOverride to enable the alpha test with GL_NOTEQUAL, 0.0,
* which is exactly what we want :-)
*/
}
}
/* Blit the logo into the upper left corner of the drawable */
IWineD3DSurface_BltFast(This->backBuffer[0], 0, 0, This->wineD3DDevice->logo_surface, NULL, WINEDDBLTFAST_SRCCOLORKEY);
}
if (pSourceRect || pDestRect) FIXME("Unhandled present rects %s/%s\n", wine_dbgstr_rect(pSourceRect), wine_dbgstr_rect(pDestRect));
/* TODO: If only source rect or dest rect are supplied then clip the window to match */
/* Don't call checkGLcall, as glGetError is not applicable here */
}
TRACE("SwapBuffers called, Starting new frame\n");
/* FPS support */
{
/* every 1.5 seconds */
}
}
#if defined(FRAME_DEBUGGING)
{
if (!isOn) {
FIXME("Enabling D3D Trace\n");
#if defined(SHOW_FRAME_MAKEUP)
FIXME("Singe Frame snapshots Starting\n");
ENTER_GL();
LEAVE_GL();
#endif
#if defined(SINGLE_FRAME_DEBUGGING)
} else {
#if defined(SHOW_FRAME_MAKEUP)
FIXME("Singe Frame snapshots Finishing\n");
#endif
FIXME("Singe Frame trace complete\n");
DeleteFileA("C:\\D3DTRACE");
#endif
}
} else {
if (isOn) {
#if defined(SHOW_FRAME_MAKEUP)
FIXME("Single Frame snapshots Finishing\n");
#endif
FIXME("Disabling D3D Trace\n");
}
}
}
#endif
/* This is disabled, but the code left in for debug purposes.
*
* Since we're allowed to modify the new back buffer on a D3DSWAPEFFECT_DISCARD flip,
* we can clear it with some ugly color to make bad drawing visible and ease debugging.
* The Debug runtime does the same on Windows. However, a few games do not redraw the
* screen properly, like Max Payne 2, which leaves a few pixels undefined.
*
* Tests show that the content of the back buffer after a discard flip is indeed not
* reliable, so no game can depend on the exact content. However, it resembles the
* old contents in some way, for example by showing fragments at other locations. In
* general, the color theme is still intact. So Max payne, which draws rather dark scenes
* gets a dark background image. If we clear it with a bright ugly color, the game's
* bug shows up much more than it does on Windows, and the players see single pixels
* with wrong colors.
* (The Max Payne bug has been confirmed on Windows with the debug runtime)
*/
TRACE("Clearing the color buffer with cyan color\n");
}
/* Both memory copies of the surfaces are ok, flip them around too instead of dirtifying */
/* Tell the front buffer surface that is has been modified. However,
* the other locations were preserved during that, so keep the flags.
* This serves to update the emulated overlay, if any
*/
} else {
}
} else {
/* If the swapeffect is DISCARD, the back buffer is undefined. That means the SYSMEM
* and INTEXTURE copies can keep their old content if they have any defined content.
* If the swapeffect is COPY, the content remains the same. If it is FLIP however,
* the texture / sysmem copy needs to be reloaded from the drawable
*/
}
}
}
}
if(This->presentParms.PresentationInterval != WINED3DPRESENT_INTERVAL_IMMEDIATE && GL_SUPPORT(SGI_VIDEO_SYNC)) {
if(retval != 0) {
}
} else {
}
break;
} else {
}
break;
} else {
}
break;
} else {
}
break;
default:
}
}
TRACE("returning\n");
return WINED3D_OK;
}
static HRESULT WINAPI IWineD3DSwapChainImpl_SetDestWindowOverride(IWineD3DSwapChain *iface, HWND window) {
TRACE("Performing dest override of swapchain %p from window %p to %p\n", This, This->win_handle, window);
/* The primary context 'owns' all the opengl resources. Destroying and recreating that context requires downloading
* all opengl resources, deleting the gl resources, destroying all other contexts, then recreating all other contexts
* and reload the resources
*/
} else {
/* The old back buffer has to be copied over to the new back buffer. A lockrect - switchcontext - unlockrect
* would suffice in theory, but it is rather nasty and may cause troubles with future changes of the locking code
* So lock read only, copy the surface out, then lock with the discard flag and write back
*/
mem = HeapAlloc(GetProcessHeap(), 0, r.Pitch * ((IWineD3DSurfaceImpl *) This->backBuffer[0])->currentDesc.Height);
This->context[0] = CreateContext(This->wineD3DDevice, (IWineD3DSurfaceImpl *) This->frontBuffer, This->win_handle, FALSE /* pbuffer */, &This->presentParms);
}
return WINED3D_OK;
}
{
/* IUnknown */
/* IWineD3DSwapChain */
};
{
struct wined3d_context **newArray;
struct wined3d_context *ctx;
if(!ctx) {
ERR("Failed to create a new context for the swapchain\n");
return NULL;
}
if(!newArray) {
ERR("Out of memory when trying to allocate a new context array\n");
return NULL;
}
This->num_contexts++;
return ctx;
}
{
/* The drawable size of an onscreen drawable is the surface size.
* (Actually: The window size, but the surface is created in window size) */
}