Scissor test state is set as part of the Renderer::setScissor method.

TRAC #22206

Moved scissorTest out of RasterizerState.
Fixes buffer-offscreen-test and buffer-preserve-test CTS regressions.

Signed-off-by: Nicolas Capens
Signed-off-by: Daniel Koch

git-svn-id: https://angleproject.googlecode.com/svn/branches/dx11proto@1549 736b8ea6-26fd-11df-bfd4-992fa37f6226
diff --git a/src/libGLESv2/Context.cpp b/src/libGLESv2/Context.cpp
index 2250b80..911a3ed 100644
--- a/src/libGLESv2/Context.cpp
+++ b/src/libGLESv2/Context.cpp
@@ -50,7 +50,7 @@
     mState.rasterizer.polygonOffsetFill = false;
     mState.rasterizer.polygonOffsetFactor = 0.0f;
     mState.rasterizer.polygonOffsetUnits = 0.0f;
-    mState.rasterizer.scissorTest = false;
+    mState.scissorTest = false;
     mState.scissor.x = 0;
     mState.scissor.y = 0;
     mState.scissor.width = 0;
@@ -523,12 +523,12 @@
 
 void Context::setScissorTest(bool enabled)
 {
-    mState.rasterizer.scissorTest = enabled;
+    mState.scissorTest = enabled;
 }
 
 bool Context::isScissorTestEnabled() const
 {
-    return mState.rasterizer.scissorTest;
+    return mState.scissorTest;
 }
 
 void Context::setDither(bool enabled)
@@ -1211,7 +1211,7 @@
       case GL_POLYGON_OFFSET_FILL:       *params = mState.rasterizer.polygonOffsetFill; break;
       case GL_SAMPLE_ALPHA_TO_COVERAGE:  *params = mState.blend.sampleAlphaToCoverage;  break;
       case GL_SAMPLE_COVERAGE:           *params = mState.sampleCoverage;               break;
-      case GL_SCISSOR_TEST:              *params = mState.rasterizer.scissorTest;       break;
+      case GL_SCISSOR_TEST:              *params = mState.scissorTest;                  break;
       case GL_STENCIL_TEST:              *params = mState.depthStencil.stencilTest;     break;
       case GL_DEPTH_TEST:                *params = mState.depthStencil.depthTest;       break;
       case GL_BLEND:                     *params = mState.blend.blend;                  break;
@@ -1723,7 +1723,7 @@
     }
     mDxUniformsDirty = false;
 
-    mRenderer->setScissorRectangle(mState.scissor);
+    mRenderer->setScissorRectangle(mState.scissor, mState.scissorTest);
 
     return true;
 }
@@ -2738,7 +2738,7 @@
     Rectangle sourceScissoredRect = sourceRect;
     Rectangle destScissoredRect = destRect;
 
-    if (mState.rasterizer.scissorTest)
+    if (mState.scissorTest)
     {
         // Only write to parts of the destination framebuffer which pass the scissor test.
         if (destRect.x < mState.scissor.x)
diff --git a/src/libGLESv2/Context.h b/src/libGLESv2/Context.h
index f6fbac2..16c4afc 100644
--- a/src/libGLESv2/Context.h
+++ b/src/libGLESv2/Context.h
@@ -145,6 +145,7 @@
     int stencilClearValue;
 
     RasterizerState rasterizer;
+    bool scissorTest;
     Rectangle scissor;
 
     BlendState blend;
diff --git a/src/libGLESv2/angletypes.h b/src/libGLESv2/angletypes.h
index 31ce78a..33a4ae5 100644
--- a/src/libGLESv2/angletypes.h
+++ b/src/libGLESv2/angletypes.h
@@ -55,8 +55,6 @@
     bool polygonOffsetFill;
     GLfloat polygonOffsetFactor;
     GLfloat polygonOffsetUnits;
-
-    bool scissorTest;
 };
 
 struct BlendState
diff --git a/src/libGLESv2/renderer/RenderStateCache.cpp b/src/libGLESv2/renderer/RenderStateCache.cpp
index 88add36..5c36fb8 100644
--- a/src/libGLESv2/renderer/RenderStateCache.cpp
+++ b/src/libGLESv2/renderer/RenderStateCache.cpp
@@ -168,7 +168,7 @@
 }
 
 ID3D11RasterizerState *RenderStateCache::getRasterizerState(const gl::RasterizerState &rasterState,
-                                                            unsigned int depthSize)
+                                                            bool scissorEnabled, unsigned int depthSize)
 {
     if (!mDevice)
     {
@@ -178,6 +178,7 @@
 
     RasterizerStateKey key;
     key.rasterizerState = rasterState;
+    key.scissorEnabled = scissorEnabled;
     key.depthSize = depthSize;
 
     RasterizerStateMap::iterator i = mRasterizerStateCache.find(key);
@@ -215,7 +216,7 @@
         rasterDesc.DepthBiasClamp = 0.0f; // MSDN documentation of DepthBiasClamp implies a value of zero will preform no clamping, must be tested though.
         rasterDesc.SlopeScaledDepthBias = rasterState.polygonOffsetUnits;
         rasterDesc.DepthClipEnable = TRUE;
-        rasterDesc.ScissorEnable = rasterState.scissorTest ? TRUE : FALSE;
+        rasterDesc.ScissorEnable = scissorEnabled ? TRUE : FALSE;
         rasterDesc.MultisampleEnable = TRUE;
         rasterDesc.AntialiasedLineEnable = FALSE;
 
diff --git a/src/libGLESv2/renderer/RenderStateCache.h b/src/libGLESv2/renderer/RenderStateCache.h
index 6c9e039..0fde432 100644
--- a/src/libGLESv2/renderer/RenderStateCache.h
+++ b/src/libGLESv2/renderer/RenderStateCache.h
@@ -31,7 +31,7 @@
     // Increments refcount on the returned blend state, Release() must be called.
     ID3D11BlendState *getBlendState(const gl::BlendState &blendState);
     ID3D11RasterizerState *getRasterizerState(const gl::RasterizerState &rasterState,
-                                              unsigned int depthSize);
+                                              bool scissorEnabled, unsigned int depthSize);
     ID3D11DepthStencilState* getDepthStencilState(const gl::DepthStencilState &dsState);
 
   private:
@@ -54,6 +54,7 @@
     struct RasterizerStateKey
     {
         gl::RasterizerState rasterizerState;
+        bool scissorEnabled;
         unsigned int depthSize;
     };
     static std::size_t hashRasterizerState(const RasterizerStateKey &rasterState);
diff --git a/src/libGLESv2/renderer/Renderer.h b/src/libGLESv2/renderer/Renderer.h
index 08254f2..7e1b043 100644
--- a/src/libGLESv2/renderer/Renderer.h
+++ b/src/libGLESv2/renderer/Renderer.h
@@ -89,7 +89,7 @@
     virtual void setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef,
                                       int stencilBackRef, bool frontFaceCCW) = 0;
 
-    virtual void setScissorRectangle(const gl::Rectangle &scissor) = 0;
+    virtual void setScissorRectangle(const gl::Rectangle &scissor, bool enabled) = 0;
     virtual bool setViewport(const gl::Rectangle &viewport, float zNear, float zFar, bool ignoreViewport,
                              gl::ProgramBinary *currentProgram, bool forceSetUniforms) = 0;
 
diff --git a/src/libGLESv2/renderer/Renderer11.cpp b/src/libGLESv2/renderer/Renderer11.cpp
index d1845b2..aa373ca 100644
--- a/src/libGLESv2/renderer/Renderer11.cpp
+++ b/src/libGLESv2/renderer/Renderer11.cpp
@@ -269,10 +269,11 @@
 {
     if (mForceSetRasterState || memcmp(&rasterState, &mCurRasterState, sizeof(gl::RasterizerState)) != 0)
     {
-        ID3D11RasterizerState *dxRasterState = mStateCache.getRasterizerState(rasterState, mCurDepthSize);
+        ID3D11RasterizerState *dxRasterState = mStateCache.getRasterizerState(rasterState, mScissorEnabled,
+                                                                              mCurDepthSize);
         if (!dxRasterState)
         {
-            ERR("NULL blend state returned by RenderStateCache::getRasterizerState, setting the "
+            ERR("NULL blend state returned by RenderStateCache::getRasterizerState, setting the default"
                 "rasterizer state.");
         }
 
@@ -355,19 +356,29 @@
     mForceSetDepthStencilState = false;
 }
 
-void Renderer11::setScissorRectangle(const gl::Rectangle &scissor)
+void Renderer11::setScissorRectangle(const gl::Rectangle &scissor, bool enabled)
 {
-    if (mForceSetScissor || memcmp(&scissor, &mCurScissor, sizeof(gl::Rectangle)) != 0)
+    if (mForceSetScissor || memcmp(&scissor, &mCurScissor, sizeof(gl::Rectangle)) != 0 ||
+        enabled != mScissorEnabled)
     {
-        D3D11_RECT rect;
-        rect.left = gl::clamp(scissor.x, 0, static_cast<int>(mRenderTargetDesc.width));
-        rect.top = gl::clamp(scissor.y, 0, static_cast<int>(mRenderTargetDesc.height));
-        rect.right = gl::clamp(scissor.x + scissor.width, 0, static_cast<int>(mRenderTargetDesc.width));
-        rect.bottom = gl::clamp(scissor.y + scissor.height, 0, static_cast<int>(mRenderTargetDesc.height));
+        if (enabled)
+        {
+            D3D11_RECT rect;
+            rect.left = gl::clamp(scissor.x, 0, static_cast<int>(mRenderTargetDesc.width));
+            rect.top = gl::clamp(scissor.y, 0, static_cast<int>(mRenderTargetDesc.height));
+            rect.right = gl::clamp(scissor.x + scissor.width, 0, static_cast<int>(mRenderTargetDesc.width));
+            rect.bottom = gl::clamp(scissor.y + scissor.height, 0, static_cast<int>(mRenderTargetDesc.height));
 
-        mDeviceContext->RSSetScissorRects(1, &rect);
+            mDeviceContext->RSSetScissorRects(1, &rect);
+        }
+
+        if (enabled != mScissorEnabled)
+        {
+            mForceSetRasterState = true;
+        }
 
         mCurScissor = scissor;
+        mScissorEnabled = enabled;
     }
 
     mForceSetScissor = false;
@@ -720,9 +731,9 @@
                 return;
             }
 
-            if (mCurScissor.x > 0 || mCurScissor.y > 0 ||
-                mCurScissor.x + mCurScissor.width < renderTarget->getWidth() ||
-                mCurScissor.y + mCurScissor.height < renderTarget->getHeight())
+            if (mScissorEnabled && (mCurScissor.x > 0 || mCurScissor.y > 0 ||
+                                    mCurScissor.x + mCurScissor.width < renderTarget->getWidth() ||
+                                    mCurScissor.y + mCurScissor.height < renderTarget->getHeight()))
             {
                 // TODO: clearing of subregion of render target
                 UNIMPLEMENTED();
@@ -769,9 +780,9 @@
                 return;
             }
 
-            if (mCurScissor.x > 0 || mCurScissor.y > 0 ||
-                mCurScissor.x + mCurScissor.width < renderTarget->getWidth() ||
-                mCurScissor.y + mCurScissor.height < renderTarget->getHeight())
+            if (mScissorEnabled && (mCurScissor.x > 0 || mCurScissor.y > 0 ||
+                                    mCurScissor.x + mCurScissor.width < renderTarget->getWidth() ||
+                                    mCurScissor.y + mCurScissor.height < renderTarget->getHeight()))
             {
                 // TODO: clearing of subregion of depth stencil view
                 UNIMPLEMENTED();
diff --git a/src/libGLESv2/renderer/Renderer11.h b/src/libGLESv2/renderer/Renderer11.h
index 357bef2..877210f 100644
--- a/src/libGLESv2/renderer/Renderer11.h
+++ b/src/libGLESv2/renderer/Renderer11.h
@@ -55,7 +55,7 @@
     virtual void setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef,
                                       int stencilBackRef, bool frontFaceCCW);
 
-    virtual void setScissorRectangle(const gl::Rectangle &scissor);
+    virtual void setScissorRectangle(const gl::Rectangle &scissor, bool enabled);
     virtual bool setViewport(const gl::Rectangle &viewport, float zNear, float zFar, bool ignoreViewport,
                              gl::ProgramBinary *currentProgram, bool forceSetUniforms);
 
@@ -179,6 +179,7 @@
 
     // Currently applied scissor rectangle
     bool mForceSetScissor;
+    bool mScissorEnabled;
     gl::Rectangle mCurScissor;
 
     // Currently applied viewport
diff --git a/src/libGLESv2/renderer/Renderer9.cpp b/src/libGLESv2/renderer/Renderer9.cpp
index f4b9d4c..d2eac1c 100644
--- a/src/libGLESv2/renderer/Renderer9.cpp
+++ b/src/libGLESv2/renderer/Renderer9.cpp
@@ -644,8 +644,6 @@
             mDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
         }
 
-        mDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, rasterState.scissorTest ? TRUE : FALSE);
-
         if (rasterState.polygonOffsetFill)
         {
             if (mCurDepthSize > 0)
@@ -860,19 +858,27 @@
     mForceSetDepthStencilState = false;
 }
 
-void Renderer9::setScissorRectangle(const gl::Rectangle &scissor)
+void Renderer9::setScissorRectangle(const gl::Rectangle &scissor, bool enabled)
 {
-    bool scissorChanged = mForceSetScissor || memcmp(&scissor, &mCurScissor, sizeof(gl::Rectangle)) != 0;
+    bool scissorChanged = mForceSetScissor ||
+                          memcmp(&scissor, &mCurScissor, sizeof(gl::Rectangle)) != 0 ||
+                          enabled != mScissorEnabled;
 
     if (scissorChanged)
     {
-        RECT rect;
-        rect.left = gl::clamp(scissor.x, 0, static_cast<int>(mRenderTargetDesc.width));
-        rect.top = gl::clamp(scissor.y, 0, static_cast<int>(mRenderTargetDesc.height));
-        rect.right = gl::clamp(scissor.x + scissor.width, 0, static_cast<int>(mRenderTargetDesc.width));
-        rect.bottom = gl::clamp(scissor.y + scissor.height, 0, static_cast<int>(mRenderTargetDesc.height));
-        mDevice->SetScissorRect(&rect);
+        if (enabled)
+        {
+            RECT rect;
+            rect.left = gl::clamp(scissor.x, 0, static_cast<int>(mRenderTargetDesc.width));
+            rect.top = gl::clamp(scissor.y, 0, static_cast<int>(mRenderTargetDesc.height));
+            rect.right = gl::clamp(scissor.x + scissor.width, 0, static_cast<int>(mRenderTargetDesc.width));
+            rect.bottom = gl::clamp(scissor.y + scissor.height, 0, static_cast<int>(mRenderTargetDesc.height));
+            mDevice->SetScissorRect(&rect);
+        }
 
+        mDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, enabled ? TRUE : FALSE);
+
+        mScissorEnabled = enabled;
         mCurScissor = scissor;
     }
 
diff --git a/src/libGLESv2/renderer/Renderer9.h b/src/libGLESv2/renderer/Renderer9.h
index eb79252..6420f0e 100644
--- a/src/libGLESv2/renderer/Renderer9.h
+++ b/src/libGLESv2/renderer/Renderer9.h
@@ -84,7 +84,7 @@
     virtual void setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef,
                                       int stencilBackRef, bool frontFaceCCW);
 
-    virtual void setScissorRectangle(const gl::Rectangle &scissor);
+    virtual void setScissorRectangle(const gl::Rectangle &scissor, bool enabled);
     virtual bool setViewport(const gl::Rectangle &viewport, float zNear, float zFar, bool ignoreViewport,
                              gl::ProgramBinary *currentProgram, bool forceSetUniforms);
 
@@ -241,6 +241,7 @@
 
     bool mForceSetScissor;
     gl::Rectangle mCurScissor;
+    bool mScissorEnabled;
     unsigned int mCurRenderTargetWidth;
     unsigned int mCurRenderTargetHeight;