Support window resizing

TRAC #12660 Automatically resize the D3D swap chain when the eglSwapBuffers is called and the presentation window has changed size. Also change D3D device init to be performed once when the Display is created using a hidden 1x1 window. Signed-off-by: Nicolas Capens Signed-off-by: Daniel Koch Author: Andrew Lewycky git-svn-id: https://angleproject.googlecode.com/svn/trunk@365 736b8ea6-26fd-11df-bfd4-992fa37f6226
parent 9ecb9f9d
...@@ -25,6 +25,7 @@ Display::Display(HDC deviceContext) : mDc(deviceContext) ...@@ -25,6 +25,7 @@ Display::Display(HDC deviceContext) : mDc(deviceContext)
{ {
mD3d9 = NULL; mD3d9 = NULL;
mDevice = NULL; mDevice = NULL;
mDeviceWindow = NULL;
mAdapter = D3DADAPTER_DEFAULT; mAdapter = D3DADAPTER_DEFAULT;
...@@ -150,6 +151,13 @@ bool Display::initialize() ...@@ -150,6 +151,13 @@ bool Display::initialize()
mConfigSet.mSet.insert(configuration); mConfigSet.mSet.insert(configuration);
} }
} }
if (!createDevice())
{
terminate();
return false;
}
} }
if (!isInitialized()) if (!isInitialized())
...@@ -185,6 +193,12 @@ void Display::terminate() ...@@ -185,6 +193,12 @@ void Display::terminate()
mD3d9->Release(); mD3d9->Release();
mD3d9 = NULL; mD3d9 = NULL;
} }
if (mDeviceWindow)
{
DestroyWindow(mDeviceWindow);
mDeviceWindow = NULL;
}
} }
void Display::startScene() void Display::startScene()
...@@ -254,126 +268,65 @@ bool Display::getConfigAttrib(EGLConfig config, EGLint attribute, EGLint *value) ...@@ -254,126 +268,65 @@ bool Display::getConfigAttrib(EGLConfig config, EGLint attribute, EGLint *value)
return true; return true;
} }
bool Display::createDevice()
{
static const TCHAR windowName[] = TEXT("AngleHiddenWindow");
static const TCHAR className[] = TEXT("STATIC");
mDeviceWindow = CreateWindowEx(WS_EX_NOACTIVATE, className, windowName, WS_DISABLED | WS_POPUP, 0, 0, 1, 1, HWND_MESSAGE, NULL, GetModuleHandle(NULL), NULL);
D3DPRESENT_PARAMETERS presentParameters = {0};
// The default swap chain is never actually used. Surface will create a new swap chain with the proper parameters.
presentParameters.AutoDepthStencilFormat = D3DFMT_UNKNOWN;
presentParameters.BackBufferCount = 1;
presentParameters.BackBufferFormat = D3DFMT_UNKNOWN;
presentParameters.BackBufferWidth = 1;
presentParameters.BackBufferHeight = 1;
presentParameters.EnableAutoDepthStencil = FALSE;
presentParameters.Flags = 0;
presentParameters.hDeviceWindow = mDeviceWindow;
presentParameters.MultiSampleQuality = 0;
presentParameters.MultiSampleType = D3DMULTISAMPLE_NONE;
presentParameters.PresentationInterval = convertInterval(mMinSwapInterval);
presentParameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
presentParameters.Windowed = TRUE;
DWORD behaviorFlags = D3DCREATE_FPU_PRESERVE | D3DCREATE_NOWINDOWCHANGES;
HRESULT result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow, behaviorFlags | D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE, &presentParameters, &mDevice);
if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
{
return error(EGL_BAD_ALLOC, false);
}
if (FAILED(result))
{
result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow, behaviorFlags | D3DCREATE_SOFTWARE_VERTEXPROCESSING, &presentParameters, &mDevice);
if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
{
return error(EGL_BAD_ALLOC, false);
}
}
ASSERT(SUCCEEDED(result));
// Permanent non-default states
mDevice->SetRenderState(D3DRS_POINTSPRITEENABLE, TRUE);
mSceneStarted = false;
return true;
}
Surface *Display::createWindowSurface(HWND window, EGLConfig config) Surface *Display::createWindowSurface(HWND window, EGLConfig config)
{ {
const Config *configuration = mConfigSet.get(config); const Config *configuration = mConfigSet.get(config);
D3DPRESENT_PARAMETERS presentParameters = {0}; Surface *surface = new Surface(this, configuration, window);
mSurfaceSet.insert(surface);
presentParameters.AutoDepthStencilFormat = configuration->mDepthStencilFormat;
presentParameters.BackBufferCount = 1;
presentParameters.BackBufferFormat = configuration->mRenderTargetFormat;
presentParameters.BackBufferWidth = 0;
presentParameters.BackBufferHeight = 0;
presentParameters.EnableAutoDepthStencil = configuration->mDepthSize ? TRUE : FALSE;
presentParameters.Flags = 0;
presentParameters.hDeviceWindow = window;
presentParameters.MultiSampleQuality = 0; // FIXME: Unimplemented
presentParameters.MultiSampleType = D3DMULTISAMPLE_NONE; // FIXME: Unimplemented
presentParameters.PresentationInterval = convertInterval(mMinSwapInterval);
presentParameters.SwapEffect = D3DSWAPEFFECT_COPY;
presentParameters.Windowed = TRUE; // FIXME
IDirect3DSwapChain9 *swapChain = NULL;
IDirect3DSurface9 *depthStencilSurface = NULL;
if (!mDevice)
{
DWORD behaviorFlags = D3DCREATE_FPU_PRESERVE | D3DCREATE_NOWINDOWCHANGES;
HRESULT result = mD3d9->CreateDevice(mAdapter, mDeviceType, window, behaviorFlags | D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE, &presentParameters, &mDevice);
if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
{
return error(EGL_BAD_ALLOC, (egl::Surface*)NULL);
}
if (FAILED(result))
{
result = mD3d9->CreateDevice(mAdapter, mDeviceType, window, behaviorFlags | D3DCREATE_SOFTWARE_VERTEXPROCESSING, &presentParameters, &mDevice);
if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
{
return error(EGL_BAD_ALLOC, (egl::Surface*)NULL);
}
}
ASSERT(SUCCEEDED(result));
if (mDevice)
{
mSceneStarted = false;
mDevice->GetSwapChain(0, &swapChain);
mDevice->GetDepthStencilSurface(&depthStencilSurface);
}
}
else
{
if (!mSurfaceSet.empty())
{
// if the device already exists, and there are other surfaces/windows currently in use, we need to create
// a separate swap chain for the new draw surface.
HRESULT result = mDevice->CreateAdditionalSwapChain(&presentParameters, &swapChain);
if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
{
ERR("Could not create additional swap chains. Out of memory.");
return error(EGL_BAD_ALLOC, (egl::Surface*)NULL);
}
ASSERT(SUCCEEDED(result));
// CreateAdditionalSwapChain does not automatically generate a depthstencil surface, unlike
// CreateDevice, so we must do so explicitly.
result = mDevice->CreateDepthStencilSurface(presentParameters.BackBufferWidth, presentParameters.BackBufferHeight,
presentParameters.AutoDepthStencilFormat, presentParameters.MultiSampleType,
presentParameters.MultiSampleQuality, FALSE, &depthStencilSurface, NULL);
if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
{
swapChain->Release();
ERR("Could not create depthstencil surface for new swap chain. Out of memory.");
return error(EGL_BAD_ALLOC, (egl::Surface*)NULL);
}
ASSERT(SUCCEEDED(result));
}
else
{
// if the device already exists, but there are no surfaces in use, then all the surfaces/windows
// have been destroyed, and we should repurpose the originally created depthstencil surface for
// use with the new surface we are creating.
HRESULT result = mDevice->Reset(&presentParameters);
if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
{
ERR("Could not reset presentation parameters for device. Out of memory.");
return error(EGL_BAD_ALLOC, (egl::Surface*)NULL);
}
ASSERT(SUCCEEDED(result));
if (mDevice)
{
mSceneStarted = false;
mDevice->GetSwapChain(0, &swapChain);
mDevice->GetDepthStencilSurface(&depthStencilSurface);
}
}
}
// Permanent non-default states
mDevice->SetRenderState(D3DRS_POINTSPRITEENABLE, TRUE);
Surface *surface = NULL;
if (swapChain)
{
surface = new Surface(this, swapChain, depthStencilSurface, configuration);
mSurfaceSet.insert(surface);
swapChain->Release();
}
return surface; return surface;
} }
......
...@@ -70,6 +70,7 @@ class Display ...@@ -70,6 +70,7 @@ class Display
IDirect3D9 *mD3d9; IDirect3D9 *mD3d9;
IDirect3DDevice9 *mDevice; IDirect3DDevice9 *mDevice;
D3DCAPS9 mDeviceCaps; D3DCAPS9 mDeviceCaps;
HWND mDeviceWindow;
bool mSceneStarted; bool mSceneStarted;
GLint mSwapInterval; GLint mSwapInterval;
...@@ -84,6 +85,8 @@ class Display ...@@ -84,6 +85,8 @@ class Display
typedef std::set<gl::Context*> ContextSet; typedef std::set<gl::Context*> ContextSet;
ContextSet mContextSet; ContextSet mContextSet;
bool createDevice();
}; };
} }
......
...@@ -17,9 +17,11 @@ ...@@ -17,9 +17,11 @@
namespace egl namespace egl
{ {
Surface::Surface(Display *display, IDirect3DSwapChain9 *swapChain, IDirect3DSurface9 *depthStencil, const Config *config) Surface::Surface(Display *display, const Config *config, HWND window)
: mDisplay(display), mSwapChain(swapChain), mDepthStencil(depthStencil), mConfig(config) : mDisplay(display), mConfig(config), mWindow(window)
{ {
mSwapChain = NULL;
mDepthStencil = NULL;
mBackBuffer = NULL; mBackBuffer = NULL;
mRenderTarget = NULL; mRenderTarget = NULL;
mFlipTexture = NULL; mFlipTexture = NULL;
...@@ -30,42 +32,7 @@ Surface::Surface(Display *display, IDirect3DSwapChain9 *swapChain, IDirect3DSurf ...@@ -30,42 +32,7 @@ Surface::Surface(Display *display, IDirect3DSwapChain9 *swapChain, IDirect3DSurf
mRenderBuffer = EGL_BACK_BUFFER; mRenderBuffer = EGL_BACK_BUFFER;
mSwapBehavior = EGL_BUFFER_PRESERVED; mSwapBehavior = EGL_BUFFER_PRESERVED;
if (mSwapChain) resetSwapChain();
{
mSwapChain->AddRef();
mSwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &mBackBuffer);
D3DSURFACE_DESC description;
mBackBuffer->GetDesc(&description);
mWidth = description.Width;
mHeight = description.Height;
IDirect3DDevice9 *device = display->getDevice();
HRESULT result = device->CreateRenderTarget(mWidth, mHeight, description.Format, description.MultiSampleType, description.MultiSampleQuality, FALSE, &mRenderTarget, NULL);
if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
{
error(EGL_BAD_ALLOC);
return;
}
ASSERT(SUCCEEDED(result));
result = device->CreateTexture(mWidth, mHeight, 1, D3DUSAGE_RENDERTARGET, description.Format, D3DPOOL_DEFAULT, &mFlipTexture, NULL);
if (FAILED(result))
{
ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
error(EGL_BAD_ALLOC);
mRenderTarget->Release();
return;
}
}
} }
Surface::~Surface() Surface::~Surface()
...@@ -106,20 +73,116 @@ Surface::~Surface() ...@@ -106,20 +73,116 @@ Surface::~Surface()
} }
} }
HWND Surface::getWindowHandle() void Surface::resetSwapChain()
{ {
if (mSwapChain) IDirect3DDevice9 *device = mDisplay->getDevice();
D3DPRESENT_PARAMETERS presentParameters = {0};
presentParameters.AutoDepthStencilFormat = mConfig->mDepthStencilFormat;
presentParameters.BackBufferCount = 1;
presentParameters.BackBufferFormat = mConfig->mRenderTargetFormat;
presentParameters.EnableAutoDepthStencil = FALSE;
presentParameters.Flags = 0;
presentParameters.hDeviceWindow = getWindowHandle();
presentParameters.MultiSampleQuality = 0; // FIXME: Unimplemented
presentParameters.MultiSampleType = D3DMULTISAMPLE_NONE; // FIXME: Unimplemented
presentParameters.PresentationInterval = Display::convertInterval(mConfig->mMinSwapInterval);
presentParameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
presentParameters.Windowed = TRUE;
RECT windowRect;
GetClientRect(getWindowHandle(), &windowRect);
presentParameters.BackBufferWidth = windowRect.right - windowRect.left;
presentParameters.BackBufferHeight = windowRect.bottom - windowRect.top;
IDirect3DSwapChain9 *swapChain = NULL;
HRESULT result = device->CreateAdditionalSwapChain(&presentParameters, &swapChain);
if (FAILED(result))
{
ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
ERR("Could not create additional swap chains: %08lX", result);
return error(EGL_BAD_ALLOC);
}
IDirect3DSurface9 *depthStencilSurface = NULL;
result = device->CreateDepthStencilSurface(presentParameters.BackBufferWidth, presentParameters.BackBufferHeight,
presentParameters.AutoDepthStencilFormat, presentParameters.MultiSampleType,
presentParameters.MultiSampleQuality, FALSE, &depthStencilSurface, NULL);
if (FAILED(result))
{
ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
swapChain->Release();
ERR("Could not create depthstencil surface for new swap chain: %08lX", result);
return error(EGL_BAD_ALLOC);
}
IDirect3DSurface9 *renderTarget = NULL;
result = device->CreateRenderTarget(presentParameters.BackBufferWidth, presentParameters.BackBufferHeight, presentParameters.BackBufferFormat,
presentParameters.MultiSampleType, presentParameters.MultiSampleQuality, FALSE, &renderTarget, NULL);
if (FAILED(result))
{
ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
swapChain->Release();
depthStencilSurface->Release();
ERR("Could not create render target surface for new swap chain: %08lX", result);
return error(EGL_BAD_ALLOC);
}
ASSERT(SUCCEEDED(result));
IDirect3DTexture9 *flipTexture = NULL;
result = device->CreateTexture(presentParameters.BackBufferWidth, presentParameters.BackBufferHeight, 1, D3DUSAGE_RENDERTARGET,
presentParameters.BackBufferFormat, D3DPOOL_DEFAULT, &flipTexture, NULL);
if (FAILED(result))
{ {
D3DPRESENT_PARAMETERS presentParameters; ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
mSwapChain->GetPresentParameters(&presentParameters);
swapChain->Release();
depthStencilSurface->Release();
renderTarget->Release();
return presentParameters.hDeviceWindow; ERR("Could not create flip texture for new swap chain: %08lX", result);
return error(EGL_BAD_ALLOC);
} }
return NULL; IDirect3DSurface9 *backBuffer = NULL;
swapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &backBuffer);
if (mSwapChain) mSwapChain->Release();
if (mDepthStencil) mDepthStencil->Release();
if (mBackBuffer) mBackBuffer->Release();
if (mRenderTarget) mRenderTarget->Release();
if (mFlipTexture) mFlipTexture->Release();
mWidth = presentParameters.BackBufferWidth;
mHeight = presentParameters.BackBufferHeight;
mSwapChain = swapChain;
mDepthStencil = depthStencilSurface;
mBackBuffer = backBuffer;
mRenderTarget = renderTarget;
mFlipTexture = flipTexture;
// The flip state block recorded mFlipTexture so it is now invalid.
releaseRecordedState(device);
}
HWND Surface::getWindowHandle()
{
return mWindow;
} }
void Surface::writeRecordableFlipState(IDirect3DDevice9 *device, IDirect3DTexture9 *source) void Surface::writeRecordableFlipState(IDirect3DDevice9 *device)
{ {
// Disable all pipeline operations // Disable all pipeline operations
device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE); device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
...@@ -138,16 +201,18 @@ void Surface::writeRecordableFlipState(IDirect3DDevice9 *device, IDirect3DTextur ...@@ -138,16 +201,18 @@ void Surface::writeRecordableFlipState(IDirect3DDevice9 *device, IDirect3DTextur
device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
device->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); device->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
device->SetTexture(0, source); device->SetTexture(0, NULL); // The actual texture will change after resizing. But the pre-flip state block must save/restore the texture.
device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT); device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT); device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
device->SetSamplerState(0, D3DSAMP_SRGBTEXTURE, FALSE); device->SetSamplerState(0, D3DSAMP_SRGBTEXTURE, FALSE);
device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
device->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1); device->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1);
device->SetStreamSourceFreq(0, 1); // DrawPrimitiveUP only cares about stream 0, not the rest. device->SetStreamSourceFreq(0, 1); // DrawPrimitiveUP only cares about stream 0, not the rest.
} }
void Surface::applyFlipState(IDirect3DDevice9 *device, IDirect3DTexture9 *source) void Surface::applyFlipState(IDirect3DDevice9 *device)
{ {
HRESULT hr; HRESULT hr;
...@@ -158,7 +223,7 @@ void Surface::applyFlipState(IDirect3DDevice9 *device, IDirect3DTexture9 *source ...@@ -158,7 +223,7 @@ void Surface::applyFlipState(IDirect3DDevice9 *device, IDirect3DTexture9 *source
// mPreFlipState will record the original state each entry. // mPreFlipState will record the original state each entry.
hr = device->BeginStateBlock(); hr = device->BeginStateBlock();
ASSERT(SUCCEEDED(hr)); ASSERT(SUCCEEDED(hr));
writeRecordableFlipState(device, source); writeRecordableFlipState(device);
hr = device->EndStateBlock(&mPreFlipState); hr = device->EndStateBlock(&mPreFlipState);
ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY); ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
...@@ -171,7 +236,7 @@ void Surface::applyFlipState(IDirect3DDevice9 *device, IDirect3DTexture9 *source ...@@ -171,7 +236,7 @@ void Surface::applyFlipState(IDirect3DDevice9 *device, IDirect3DTexture9 *source
hr = device->BeginStateBlock(); hr = device->BeginStateBlock();
ASSERT(SUCCEEDED(hr)); ASSERT(SUCCEEDED(hr));
writeRecordableFlipState(device, source); writeRecordableFlipState(device);
hr = device->EndStateBlock(&mFlipState); hr = device->EndStateBlock(&mFlipState);
ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY); ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
...@@ -223,29 +288,83 @@ void Surface::restoreState(IDirect3DDevice9 *device) ...@@ -223,29 +288,83 @@ void Surface::restoreState(IDirect3DDevice9 *device)
} }
} }
// On the next flip, this will cause the state to be recorded from scratch.
// In particular we need to do this if the flip texture changes.
void Surface::releaseRecordedState(IDirect3DDevice9 *device)
{
if (mFlipState)
{
mFlipState->Release();
mFlipState = NULL;
}
if (mPreFlipState)
{
mPreFlipState->Release();
mPreFlipState = NULL;
}
}
bool Surface::checkForWindowResize()
{
RECT client;
GetClientRect(getWindowHandle(), &client);
if (getWidth() != client.right - client.left || getHeight() != client.bottom - client.top)
{
resetSwapChain();
if (static_cast<egl::Surface*>(getCurrentDrawSurface()) == this)
{
glMakeCurrent(glGetCurrentContext(), static_cast<egl::Display*>(getCurrentDisplay()), this);
}
return true;
}
return false;
}
bool Surface::swap() bool Surface::swap()
{ {
if (mSwapChain) if (mSwapChain)
{ {
IDirect3DTexture9 *flipTexture = mFlipTexture;
flipTexture->AddRef();
IDirect3DSurface9 *renderTarget = mRenderTarget;
renderTarget->AddRef();
EGLint oldWidth = mWidth;
EGLint oldHeight = mHeight;
checkForWindowResize();
IDirect3DDevice9 *device = mDisplay->getDevice(); IDirect3DDevice9 *device = mDisplay->getDevice();
IDirect3DSurface9 *textureSurface; IDirect3DSurface9 *textureSurface;
mFlipTexture->GetSurfaceLevel(0, &textureSurface); flipTexture->GetSurfaceLevel(0, &textureSurface);
mDisplay->endScene(); mDisplay->endScene();
device->StretchRect(mRenderTarget, NULL, textureSurface, NULL, D3DTEXF_NONE); device->StretchRect(renderTarget, NULL, textureSurface, NULL, D3DTEXF_NONE);
renderTarget->Release();
applyFlipState(device, mFlipTexture); applyFlipState(device);
device->SetTexture(0, flipTexture);
float xscale = (float)mWidth / oldWidth;
float yscale = (float)mHeight / oldHeight;
// Render the texture upside down into the back buffer // Render the texture upside down into the back buffer
float quad[4][6] = {{ 0 - 0.5f, 0 - 0.5f, 0.0f, 1.0f, 0.0f, 1.0f}, // Texcoords are chosen to pin a potentially resized image into the upper-left corner without scaling.
{mWidth - 0.5f, 0 - 0.5f, 0.0f, 1.0f, 1.0f, 1.0f}, float quad[4][6] = {{ 0 - 0.5f, 0 - 0.5f, 0.0f, 1.0f, 0.0f, 1.0f },
{mWidth - 0.5f, mHeight - 0.5f, 0.0f, 1.0f, 1.0f, 0.0f}, {mWidth - 0.5f, 0 - 0.5f, 0.0f, 1.0f, xscale, 1.0f },
{ 0 - 0.5f, mHeight - 0.5f, 0.0f, 1.0f, 0.0f, 0.0f}}; // x, y, z, rhw, u, v {mWidth - 0.5f, mHeight - 0.5f, 0.0f, 1.0f, xscale, 1.0f-yscale},
{ 0 - 0.5f, mHeight - 0.5f, 0.0f, 1.0f, 0.0f, 1.0f-yscale}}; // x, y, z, rhw, u, v
mDisplay->startScene(); mDisplay->startScene();
device->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, quad, 6 * sizeof(float)); device->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, quad, 6 * sizeof(float));
flipTexture->Release();
textureSurface->Release(); textureSurface->Release();
restoreState(device); restoreState(device);
...@@ -264,6 +383,7 @@ bool Surface::swap() ...@@ -264,6 +383,7 @@ bool Surface::swap()
} }
ASSERT(SUCCEEDED(result)); ASSERT(SUCCEEDED(result));
} }
return true; return true;
......
...@@ -25,7 +25,7 @@ class Config; ...@@ -25,7 +25,7 @@ class Config;
class Surface class Surface
{ {
public: public:
Surface(Display *display, IDirect3DSwapChain9 *swapChain, IDirect3DSurface9* depthStencil, const egl::Config *config); Surface(Display *display, const egl::Config *config, HWND window);
~Surface(); ~Surface();
...@@ -42,20 +42,25 @@ class Surface ...@@ -42,20 +42,25 @@ class Surface
DISALLOW_COPY_AND_ASSIGN(Surface); DISALLOW_COPY_AND_ASSIGN(Surface);
Display *const mDisplay; Display *const mDisplay;
IDirect3DSwapChain9 *const mSwapChain; IDirect3DSwapChain9 *mSwapChain;
IDirect3DSurface9 *mBackBuffer; IDirect3DSurface9 *mBackBuffer;
IDirect3DSurface9 *mRenderTarget; IDirect3DSurface9 *mRenderTarget;
IDirect3DSurface9 *mDepthStencil; IDirect3DSurface9 *mDepthStencil;
IDirect3DTexture9 *mFlipTexture; IDirect3DTexture9 *mFlipTexture;
void applyFlipState(IDirect3DDevice9 *device, IDirect3DTexture9 *source); void resetSwapChain();
bool checkForWindowResize();
void applyFlipState(IDirect3DDevice9 *device);
void restoreState(IDirect3DDevice9 *device); void restoreState(IDirect3DDevice9 *device);
void writeRecordableFlipState(IDirect3DDevice9 *device, IDirect3DTexture9 *source); void writeRecordableFlipState(IDirect3DDevice9 *device);
void releaseRecordedState(IDirect3DDevice9 *device);
IDirect3DStateBlock9 *mFlipState; IDirect3DStateBlock9 *mFlipState;
IDirect3DStateBlock9 *mPreFlipState; IDirect3DStateBlock9 *mPreFlipState;
IDirect3DSurface9 *mPreFlipBackBuffer; IDirect3DSurface9 *mPreFlipBackBuffer;
IDirect3DSurface9 *mPreFlipDepthStencil; IDirect3DSurface9 *mPreFlipDepthStencil;
const HWND mWindow; // Window that the surface is created for.
const egl::Config *mConfig; // EGL config surface was created with const egl::Config *mConfig; // EGL config surface was created with
EGLint mHeight; // Height of surface EGLint mHeight; // Height of surface
EGLint mWidth; // Width of surface EGLint mWidth; // Width of surface
......
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