Implemented eglSwapInterval
TRAC #12137
Signed-off-by: Andrew Lewycky
Signed-off-by: Daniel Koch

Author:    Nicolas Capens

git-svn-id: https://angleproject.googlecode.com/svn/trunk@235 736b8ea6-26fd-11df-bfd4-992fa37f6226
diff --git a/src/libEGL/Display.cpp b/src/libEGL/Display.cpp
index 6276452..175cb17 100644
--- a/src/libEGL/Display.cpp
+++ b/src/libEGL/Display.cpp
@@ -26,6 +26,7 @@
 
     mAdapter = D3DADAPTER_DEFAULT;
     mDeviceType = D3DDEVTYPE_HAL;
+    mSwapInterval = 1;
 }
 
 Display::~Display()
@@ -224,7 +225,7 @@
       case EGL_ALPHA_MASK_SIZE:           *value = configuration->mAlphaMaskSize;          break;
       case EGL_COLOR_BUFFER_TYPE:         *value = configuration->mColorBufferType;        break;
       case EGL_RENDERABLE_TYPE:           *value = configuration->mRenderableType;         break;
-      case EGL_MATCH_NATIVE_PIXMAP:       *value = false; UNIMPLEMENTED();                break;
+      case EGL_MATCH_NATIVE_PIXMAP:       *value = false; UNIMPLEMENTED();                 break;
       case EGL_CONFORMANT:                *value = configuration->mConformant;             break;
       default:
         return false;
@@ -233,9 +234,9 @@
     return true;
 }
 
-egl::Surface *Display::createWindowSurface(HWND window, EGLConfig config)
+Surface *Display::createWindowSurface(HWND window, EGLConfig config)
 {
-    const egl::Config *configuration = mConfigSet.get(config);
+    const Config *configuration = mConfigSet.get(config);
 
     D3DPRESENT_PARAMETERS presentParameters = {0};
 
@@ -249,7 +250,7 @@
     presentParameters.hDeviceWindow = window;
     presentParameters.MultiSampleQuality = 0;                  // FIXME: Unimplemented
     presentParameters.MultiSampleType = D3DMULTISAMPLE_NONE;   // FIXME: Unimplemented
-    presentParameters.PresentationInterval = configuration->mMinSwapInterval;
+    presentParameters.PresentationInterval = getPresentInterval(configuration, true);
     presentParameters.SwapEffect = D3DSWAPEFFECT_COPY;
     presentParameters.Windowed = TRUE;   // FIXME
 
@@ -345,7 +346,7 @@
 
     if (swapChain)
     {
-        surface = new Surface(this, swapChain, depthStencilSurface, configuration->mConfigID);
+        surface = new Surface(this, swapChain, depthStencilSurface, configuration);
         mSurfaceSet.insert(surface);
 
         swapChain->Release();
@@ -409,6 +410,30 @@
     return false;
 }
 
+void Display::setSwapInterval(GLint interval)
+{
+    mSwapInterval = interval;
+}
+
+DWORD Display::getPresentInterval(const egl::Config *config, bool maximumRate)
+{
+    GLint interval = maximumRate ? 0 : mSwapInterval;
+    interval = interval < config->mMinSwapInterval ? config->mMinSwapInterval : interval;
+    interval = interval > config->mMaxSwapInterval ? config->mMaxSwapInterval : 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;
+}
+
 IDirect3DDevice9 *Display::getDevice()
 {
     return mDevice;
diff --git a/src/libEGL/Display.h b/src/libEGL/Display.h
index 2876c4a..1c46e0c 100644
--- a/src/libEGL/Display.h
+++ b/src/libEGL/Display.h
@@ -54,6 +54,9 @@
     bool isValidSurface(egl::Surface *surface);
     bool hasExistingWindowSurface(HWND window);
 
+    void setSwapInterval(GLint interval);
+    DWORD getPresentInterval(const egl::Config *config, bool maximumRate);
+
     virtual IDirect3DDevice9 *getDevice();
 
   private:
@@ -66,6 +69,7 @@
     IDirect3DDevice9 *mDevice;
 
     bool mSceneStarted;
+    GLint mSwapInterval;
 
     typedef std::set<Surface*> SurfaceSet;
     SurfaceSet mSurfaceSet;
diff --git a/src/libEGL/Surface.cpp b/src/libEGL/Surface.cpp
index d1e7eec..1dd88a2 100644
--- a/src/libEGL/Surface.cpp
+++ b/src/libEGL/Surface.cpp
@@ -17,8 +17,8 @@
 
 namespace egl
 {
-Surface::Surface(Display *display, IDirect3DSwapChain9 *swapChain, IDirect3DSurface9 *depthStencil, EGLint configID) 
-    : mDisplay(display), mSwapChain(swapChain), mConfigID(configID), mDepthStencil(depthStencil)
+Surface::Surface(Display *display, IDirect3DSwapChain9 *swapChain, IDirect3DSurface9 *depthStencil, const Config *config) 
+    : mDisplay(display), mSwapChain(swapChain), mDepthStencil(depthStencil), mConfig(config)
 {
     mBackBuffer = NULL;
     mRenderTarget = NULL;
@@ -150,7 +150,7 @@
         texture->Release();
 
         mDisplay->endScene();
-        result = mSwapChain->Present(NULL, NULL, NULL, NULL, D3DPRESENT_INTERVAL_IMMEDIATE | D3DPRESENT_DONOTWAIT);   // FIXME: Get the swap interval from the associated Display
+        result = mSwapChain->Present(NULL, NULL, NULL, NULL, mDisplay->getPresentInterval(mConfig, false));
 
         if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_DRIVERINTERNALERROR)
         {
diff --git a/src/libEGL/Surface.h b/src/libEGL/Surface.h
index 8953834..0422843 100644
--- a/src/libEGL/Surface.h
+++ b/src/libEGL/Surface.h
@@ -20,11 +20,12 @@
 namespace egl
 {
 class Display;
+class Config;
 
 class Surface
 {
   public:
-    Surface(Display *display, IDirect3DSwapChain9 *swapChain, IDirect3DSurface9* depthStencil, EGLint configID);
+    Surface(Display *display, IDirect3DSwapChain9 *swapChain, IDirect3DSurface9* depthStencil, const egl::Config *config);
 
     ~Surface();
 
@@ -45,7 +46,7 @@
     IDirect3DSurface9 *mRenderTarget;
     IDirect3DSurface9 *mDepthStencil;
 
-    const EGLint mConfigID;        // ID of EGLConfig surface was created with
+    const egl::Config *mConfig;    // EGL config surface was created with
     EGLint mHeight;                // Height of surface
     EGLint mWidth;                 // Width of surface
 //  EGLint horizontalResolution;   // Horizontal dot pitch
diff --git a/src/libEGL/libEGL.cpp b/src/libEGL/libEGL.cpp
index 3c58f23..a98a34c 100644
--- a/src/libEGL/libEGL.cpp
+++ b/src/libEGL/libEGL.cpp
@@ -746,7 +746,7 @@
             return EGL_FALSE;
         }
 
-    //    UNIMPLEMENTED();   // FIXME
+        display->setSwapInterval(interval);
 
         return success(EGL_TRUE);
     }