Commit 0db0d6c8 by apatrick@chromium.org

Replaces swap chain lazily when the swap interval is changed.

It does not appear to be possible to pass a presentation interval to Present() or change it after creating the swap chain, short of calling Reset(). I decided to try fixing it by replacing the swap chain under the same conditions as a window resize. I tested it with a modified version of the simple vertex shader sample, passing various values to eglSwapInterval. My reading of the EGL spec might be wrong but I believe the interval state should be associated with the surface bound to the current context, rather than the display. Review URL: http://codereview.appspot.com/2036044 git-svn-id: https://angleproject.googlecode.com/svn/trunk@408 736b8ea6-26fd-11df-bfd4-992fa37f6226
parent 6a20d108
......@@ -41,7 +41,6 @@ Display::Display(HDC deviceContext) : mDc(deviceContext)
mMinSwapInterval = 1;
mMaxSwapInterval = 1;
setSwapInterval(1);
}
Display::~Display()
......@@ -452,33 +451,14 @@ bool Display::hasExistingWindowSurface(HWND window)
return false;
}
void Display::setSwapInterval(GLint interval)
EGLint Display::getMinSwapInterval()
{
mSwapInterval = interval;
mSwapInterval = std::max(mSwapInterval, mMinSwapInterval);
mSwapInterval = std::min(mSwapInterval, mMaxSwapInterval);
mPresentInterval = convertInterval(mSwapInterval);
}
DWORD Display::getPresentInterval()
{
return mPresentInterval;
return mMinSwapInterval;
}
DWORD Display::convertInterval(GLint interval)
EGLint Display::getMaxSwapInterval()
{
switch(interval)
{
case 0: return D3DPRESENT_INTERVAL_IMMEDIATE;
case 1: return D3DPRESENT_INTERVAL_ONE;
case 2: return D3DPRESENT_INTERVAL_TWO;
case 3: return D3DPRESENT_INTERVAL_THREE;
case 4: return D3DPRESENT_INTERVAL_FOUR;
default: UNREACHABLE();
}
return D3DPRESENT_INTERVAL_DEFAULT;
return mMaxSwapInterval;
}
IDirect3DDevice9 *Display::getDevice()
......@@ -587,7 +567,7 @@ D3DPRESENT_PARAMETERS Display::getPresentParameters()
presentParameters.hDeviceWindow = mDeviceWindow;
presentParameters.MultiSampleQuality = 0;
presentParameters.MultiSampleType = D3DMULTISAMPLE_NONE;
presentParameters.PresentationInterval = convertInterval(mMinSwapInterval);
presentParameters.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
presentParameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
presentParameters.Windowed = TRUE;
......
......@@ -54,9 +54,8 @@ class Display
bool isValidSurface(egl::Surface *surface);
bool hasExistingWindowSurface(HWND window);
void setSwapInterval(GLint interval);
DWORD getPresentInterval();
static DWORD convertInterval(GLint interval);
EGLint getMinSwapInterval();
EGLint getMaxSwapInterval();
virtual IDirect3DDevice9 *getDevice();
virtual D3DCAPS9 getDeviceCaps();
......@@ -84,11 +83,9 @@ class Display
HWND mDeviceWindow;
bool mSceneStarted;
GLint mSwapInterval;
EGLint mMaxSwapInterval;
EGLint mMinSwapInterval;
DWORD mPresentInterval;
typedef std::set<Surface*> SurfaceSet;
SurfaceSet mSurfaceSet;
......
......@@ -31,6 +31,8 @@ Surface::Surface(Display *display, const Config *config, HWND window)
mPixelAspectRatio = (EGLint)(1.0 * EGL_DISPLAY_SCALING); // FIXME: Determine actual pixel aspect ratio
mRenderBuffer = EGL_BACK_BUFFER;
mSwapBehavior = EGL_BUFFER_PRESERVED;
mSwapInterval = -1;
setSwapInterval(1);
resetSwapChain();
}
......@@ -99,7 +101,7 @@ void Surface::resetSwapChain()
presentParameters.hDeviceWindow = getWindowHandle();
presentParameters.MultiSampleQuality = 0; // FIXME: Unimplemented
presentParameters.MultiSampleType = D3DMULTISAMPLE_NONE; // FIXME: Unimplemented
presentParameters.PresentationInterval = Display::convertInterval(mConfig->mMinSwapInterval);
presentParameters.PresentationInterval = mPresentInterval;
presentParameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
presentParameters.Windowed = TRUE;
......@@ -190,6 +192,8 @@ void Surface::resetSwapChain()
mRenderTarget = renderTarget;
mFlipTexture = flipTexture;
mPresentIntervalDirty = false;
// The flip state block recorded mFlipTexture so it is now invalid.
releaseRecordedState(device);
}
......@@ -322,7 +326,7 @@ void Surface::releaseRecordedState(IDirect3DDevice9 *device)
}
}
bool Surface::checkForWindowResize()
bool Surface::checkForOutOfDateSwapChain()
{
RECT client;
if (!GetClientRect(getWindowHandle(), &client))
......@@ -331,7 +335,7 @@ bool Surface::checkForWindowResize()
return false;
}
if (getWidth() != client.right - client.left || getHeight() != client.bottom - client.top)
if (getWidth() != client.right - client.left || getHeight() != client.bottom - client.top || mPresentIntervalDirty)
{
resetSwapChain();
......@@ -346,6 +350,22 @@ bool Surface::checkForWindowResize()
return false;
}
DWORD Surface::convertInterval(EGLint interval)
{
switch(interval)
{
case 0: return D3DPRESENT_INTERVAL_IMMEDIATE;
case 1: return D3DPRESENT_INTERVAL_ONE;
case 2: return D3DPRESENT_INTERVAL_TWO;
case 3: return D3DPRESENT_INTERVAL_THREE;
case 4: return D3DPRESENT_INTERVAL_FOUR;
default: UNREACHABLE();
}
return D3DPRESENT_INTERVAL_DEFAULT;
}
bool Surface::swap()
{
if (mSwapChain)
......@@ -359,7 +379,7 @@ bool Surface::swap()
EGLint oldWidth = mWidth;
EGLint oldHeight = mHeight;
checkForWindowResize();
checkForOutOfDateSwapChain();
IDirect3DDevice9 *device = mDisplay->getDevice();
......@@ -392,7 +412,7 @@ bool Surface::swap()
restoreState(device);
mDisplay->endScene();
HRESULT result = mSwapChain->Present(NULL, NULL, NULL, NULL, mDisplay->getPresentInterval());
HRESULT result = mSwapChain->Present(NULL, NULL, NULL, NULL, 0);
if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_DRIVERINTERNALERROR)
{
......@@ -440,4 +460,19 @@ IDirect3DSurface9 *Surface::getDepthStencil()
return mDepthStencil;
}
void Surface::setSwapInterval(EGLint interval)
{
if (mSwapInterval == interval)
{
return;
}
mSwapInterval = interval;
mSwapInterval = std::max(mSwapInterval, mDisplay->getMinSwapInterval());
mSwapInterval = std::min(mSwapInterval, mDisplay->getMaxSwapInterval());
mPresentInterval = convertInterval(mSwapInterval);
mPresentIntervalDirty = true;
}
}
......@@ -41,6 +41,8 @@ class Surface
virtual IDirect3DSurface9 *getRenderTarget();
virtual IDirect3DSurface9 *getDepthStencil();
void setSwapInterval(EGLint interval);
private:
DISALLOW_COPY_AND_ASSIGN(Surface);
......@@ -51,7 +53,9 @@ class Surface
IDirect3DSurface9 *mDepthStencil;
IDirect3DTexture9 *mFlipTexture;
bool checkForWindowResize();
bool checkForOutOfDateSwapChain();
static DWORD convertInterval(EGLint interval);
void applyFlipState(IDirect3DDevice9 *device);
void restoreState(IDirect3DDevice9 *device);
......@@ -79,6 +83,9 @@ class Surface
// EGLenum textureTarget; // Type of texture: 2D or no texture
// EGLenum vgAlphaFormat; // Alpha format for OpenVG
// EGLenum vgColorSpace; // Color space for OpenVG
EGLint mSwapInterval;
DWORD mPresentInterval;
bool mPresentIntervalDirty;
};
}
......
......@@ -746,7 +746,14 @@ EGLBoolean __stdcall eglSwapInterval(EGLDisplay dpy, EGLint interval)
return EGL_FALSE;
}
display->setSwapInterval(interval);
egl::Surface *draw_surface = static_cast<egl::Surface*>(egl::getCurrentDrawSurface());
if (draw_surface == NULL)
{
return error(EGL_BAD_SURFACE, EGL_FALSE);
}
draw_surface->setSwapInterval(interval);
return success(EGL_TRUE);
}
......
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