Implement GL_RASTERIZER_DISCARD.
BUG=angle:498
Change-Id: Ib60c39e206003ae67c93769e35f7f9ef790ce9f4
Reviewed-on: https://chromium-review.googlesource.com/184396
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Tested-by: Geoff Lang <geofflang@chromium.org>
diff --git a/src/libGLESv2/Context.cpp b/src/libGLESv2/Context.cpp
index 379dc82..92227b5 100644
--- a/src/libGLESv2/Context.cpp
+++ b/src/libGLESv2/Context.cpp
@@ -59,6 +59,7 @@
mState.depthClearValue = 1.0f;
mState.stencilClearValue = 0;
+ mState.rasterizer.rasterizerDiscard = false;
mState.rasterizer.cullFace = false;
mState.rasterizer.cullMode = GL_BACK;
mState.rasterizer.frontFace = GL_CCW;
@@ -405,6 +406,44 @@
return mContextLost;
}
+void Context::setCap(GLenum cap, bool enabled)
+{
+ switch (cap)
+ {
+ case GL_CULL_FACE: setCullFace(enabled); break;
+ case GL_POLYGON_OFFSET_FILL: setPolygonOffsetFill(enabled); break;
+ case GL_SAMPLE_ALPHA_TO_COVERAGE: setSampleAlphaToCoverage(enabled); break;
+ case GL_SAMPLE_COVERAGE: setSampleCoverage(enabled); break;
+ case GL_SCISSOR_TEST: setScissorTest(enabled); break;
+ case GL_STENCIL_TEST: setStencilTest(enabled); break;
+ case GL_DEPTH_TEST: setDepthTest(enabled); break;
+ case GL_BLEND: setBlend(enabled); break;
+ case GL_DITHER: setDither(enabled); break;
+ case GL_PRIMITIVE_RESTART_FIXED_INDEX: UNIMPLEMENTED(); break;
+ case GL_RASTERIZER_DISCARD: setRasterizerDiscard(enabled); break;
+ default: UNREACHABLE();
+ }
+}
+
+bool Context::getCap(GLenum cap)
+{
+ switch (cap)
+ {
+ case GL_CULL_FACE: return isCullFaceEnabled();
+ case GL_POLYGON_OFFSET_FILL: return isPolygonOffsetFillEnabled();
+ case GL_SAMPLE_ALPHA_TO_COVERAGE: return isSampleAlphaToCoverageEnabled();
+ case GL_SAMPLE_COVERAGE: return isSampleCoverageEnabled();
+ case GL_SCISSOR_TEST: return isScissorTestEnabled();
+ case GL_STENCIL_TEST: return isStencilTestEnabled();
+ case GL_DEPTH_TEST: return isDepthTestEnabled();
+ case GL_BLEND: return isBlendEnabled();
+ case GL_DITHER: return isDitherEnabled();
+ case GL_PRIMITIVE_RESTART_FIXED_INDEX: UNIMPLEMENTED(); return false;
+ case GL_RASTERIZER_DISCARD: return isRasterizerDiscardEnabled();
+ default: UNREACHABLE(); return false;
+ }
+}
+
void Context::setClearColor(float red, float green, float blue, float alpha)
{
mState.colorClearValue.red = red;
@@ -423,6 +462,16 @@
mState.stencilClearValue = stencil;
}
+void Context::setRasterizerDiscard(bool enabled)
+{
+ mState.rasterizer.rasterizerDiscard = enabled;
+}
+
+bool Context::isRasterizerDiscardEnabled() const
+{
+ return mState.rasterizer.rasterizerDiscard;
+}
+
void Context::setCullFace(bool enabled)
{
mState.rasterizer.cullFace = enabled;
@@ -2400,10 +2449,10 @@
}
// Applies the shaders and shader constants to the Direct3D 9 device
-void Context::applyShaders(ProgramBinary *programBinary)
+void Context::applyShaders(ProgramBinary *programBinary, bool rasterizerDiscard)
{
- mRenderer->applyShaders(programBinary);
-
+ mRenderer->applyShaders(programBinary, rasterizerDiscard);
+
programBinary->applyUniforms();
}
@@ -2550,6 +2599,11 @@
void Context::clear(GLbitfield mask)
{
+ if (isRasterizerDiscardEnabled())
+ {
+ return;
+ }
+
ClearParameters clearParams = { 0 };
for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
{
@@ -2618,8 +2672,12 @@
void Context::clearBufferfv(GLenum buffer, int drawbuffer, const float *values)
{
- // glClearBufferfv can be called to clear the color buffer or depth buffer
+ if (isRasterizerDiscardEnabled())
+ {
+ return;
+ }
+ // glClearBufferfv can be called to clear the color buffer or depth buffer
ClearParameters clearParams = { 0 };
if (buffer == GL_COLOR)
@@ -2673,8 +2731,12 @@
void Context::clearBufferuiv(GLenum buffer, int drawbuffer, const unsigned int *values)
{
- // glClearBufferuv can only be called to clear a color buffer
+ if (isRasterizerDiscardEnabled())
+ {
+ return;
+ }
+ // glClearBufferuv can only be called to clear a color buffer
ClearParameters clearParams = { 0 };
for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
{
@@ -2704,8 +2766,12 @@
void Context::clearBufferiv(GLenum buffer, int drawbuffer, const int *values)
{
- // glClearBufferfv can be called to clear the color buffer or stencil buffer
+ if (isRasterizerDiscardEnabled())
+ {
+ return;
+ }
+ // glClearBufferfv can be called to clear the color buffer or stencil buffer
ClearParameters clearParams = { 0 };
if (buffer == GL_COLOR)
@@ -2760,8 +2826,12 @@
void Context::clearBufferfi(GLenum buffer, int drawbuffer, float depth, int stencil)
{
- // glClearBufferfi can only be called to clear a depth stencil buffer
+ if (isRasterizerDiscardEnabled())
+ {
+ return;
+ }
+ // glClearBufferfi can only be called to clear a depth stencil buffer
ClearParameters clearParams = { 0 };
for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
{
@@ -2851,7 +2921,7 @@
return gl::error(err);
}
- applyShaders(programBinary);
+ applyShaders(programBinary, mState.rasterizer.rasterizerDiscard);
applyTextures(programBinary);
if (!applyUniformBuffers())
@@ -2914,7 +2984,7 @@
return gl::error(err);
}
- applyShaders(programBinary);
+ applyShaders(programBinary, mState.rasterizer.rasterizerDiscard);
applyTextures(programBinary);
if (!applyUniformBuffers())
diff --git a/src/libGLESv2/Context.h b/src/libGLESv2/Context.h
index f5c4fc4..4ba106d 100644
--- a/src/libGLESv2/Context.h
+++ b/src/libGLESv2/Context.h
@@ -146,12 +146,18 @@
bool isContextLost();
// State manipulation
+ void setCap(GLenum cap, bool enabled);
+ bool getCap(GLenum cap);
+
void setClearColor(float red, float green, float blue, float alpha);
void setClearDepth(float depth);
void setClearStencil(int stencil);
+ void setRasterizerDiscard(bool enabled);
+ bool isRasterizerDiscardEnabled() const;
+
void setCullFace(bool enabled);
bool isCullFaceEnabled() const;
@@ -453,7 +459,7 @@
bool applyRenderTarget(GLenum drawMode, bool ignoreViewport);
void applyState(GLenum drawMode);
- void applyShaders(ProgramBinary *programBinary);
+ void applyShaders(ProgramBinary *programBinary, bool rasterizerDiscard);
void applyTextures(ProgramBinary *programBinary);
void applyTextures(ProgramBinary *programBinary, SamplerType type);
bool applyUniformBuffers();
diff --git a/src/libGLESv2/angletypes.h b/src/libGLESv2/angletypes.h
index 4f6df67..6ab68b8 100644
--- a/src/libGLESv2/angletypes.h
+++ b/src/libGLESv2/angletypes.h
@@ -100,6 +100,8 @@
bool pointDrawMode;
bool multiSample;
+
+ bool rasterizerDiscard;
};
struct BlendState
diff --git a/src/libGLESv2/libGLESv2.cpp b/src/libGLESv2/libGLESv2.cpp
index 15ffe45..0d19eb3 100644
--- a/src/libGLESv2/libGLESv2.cpp
+++ b/src/libGLESv2/libGLESv2.cpp
@@ -1632,30 +1632,12 @@
if (context)
{
- switch (cap)
+ if (!ValidCap(context, cap))
{
- case GL_CULL_FACE: context->setCullFace(false); break;
- case GL_POLYGON_OFFSET_FILL: context->setPolygonOffsetFill(false); break;
- case GL_SAMPLE_ALPHA_TO_COVERAGE: context->setSampleAlphaToCoverage(false); break;
- case GL_SAMPLE_COVERAGE: context->setSampleCoverage(false); break;
- case GL_SCISSOR_TEST: context->setScissorTest(false); break;
- case GL_STENCIL_TEST: context->setStencilTest(false); break;
- case GL_DEPTH_TEST: context->setDepthTest(false); break;
- case GL_BLEND: context->setBlend(false); break;
- case GL_DITHER: context->setDither(false); break;
-
- case GL_PRIMITIVE_RESTART_FIXED_INDEX:
- case GL_RASTERIZER_DISCARD:
- if (context->getClientVersion() < 3)
- {
- return gl::error(GL_INVALID_ENUM);
- }
- UNIMPLEMENTED();
- break;
-
- default:
return gl::error(GL_INVALID_ENUM);
}
+
+ context->setCap(cap, false);
}
}
catch(std::bad_alloc&)
@@ -1832,20 +1814,12 @@
if (context)
{
- switch (cap)
+ if (!ValidCap(context, cap))
{
- case GL_CULL_FACE: context->setCullFace(true); break;
- case GL_POLYGON_OFFSET_FILL: context->setPolygonOffsetFill(true); break;
- case GL_SAMPLE_ALPHA_TO_COVERAGE: context->setSampleAlphaToCoverage(true); break;
- case GL_SAMPLE_COVERAGE: context->setSampleCoverage(true); break;
- case GL_SCISSOR_TEST: context->setScissorTest(true); break;
- case GL_STENCIL_TEST: context->setStencilTest(true); break;
- case GL_DEPTH_TEST: context->setDepthTest(true); break;
- case GL_BLEND: context->setBlend(true); break;
- case GL_DITHER: context->setDither(true); break;
- default:
return gl::error(GL_INVALID_ENUM);
}
+
+ context->setCap(cap, true);
}
}
catch(std::bad_alloc&)
@@ -4105,20 +4079,12 @@
if (context)
{
- switch (cap)
+ if (!ValidCap(context, cap))
{
- case GL_CULL_FACE: return context->isCullFaceEnabled();
- case GL_POLYGON_OFFSET_FILL: return context->isPolygonOffsetFillEnabled();
- case GL_SAMPLE_ALPHA_TO_COVERAGE: return context->isSampleAlphaToCoverageEnabled();
- case GL_SAMPLE_COVERAGE: return context->isSampleCoverageEnabled();
- case GL_SCISSOR_TEST: return context->isScissorTestEnabled();
- case GL_STENCIL_TEST: return context->isStencilTestEnabled();
- case GL_DEPTH_TEST: return context->isDepthTestEnabled();
- case GL_BLEND: return context->isBlendEnabled();
- case GL_DITHER: return context->isDitherEnabled();
- default:
return gl::error(GL_INVALID_ENUM, false);
}
+
+ return context->getCap(cap);
}
}
catch(std::bad_alloc&)
diff --git a/src/libGLESv2/renderer/Renderer.h b/src/libGLESv2/renderer/Renderer.h
index fca70e1..8f1ab44 100644
--- a/src/libGLESv2/renderer/Renderer.h
+++ b/src/libGLESv2/renderer/Renderer.h
@@ -136,7 +136,7 @@
bool ignoreViewport) = 0;
virtual bool applyRenderTarget(gl::Framebuffer *frameBuffer) = 0;
- virtual void applyShaders(gl::ProgramBinary *programBinary) = 0;
+ virtual void applyShaders(gl::ProgramBinary *programBinary, bool rasterizerDiscard) = 0;
virtual void applyUniforms(const gl::ProgramBinary &programBinary) = 0;
virtual bool applyPrimitiveType(GLenum primitiveType, GLsizei elementCount) = 0;
virtual GLenum applyVertexBuffer(gl::ProgramBinary *programBinary, const gl::VertexAttribute vertexAttributes[], gl::VertexAttribCurrentValueData currentValues[],
diff --git a/src/libGLESv2/renderer/d3d11/Renderer11.cpp b/src/libGLESv2/renderer/d3d11/Renderer11.cpp
index ecc1887..0c80c03 100644
--- a/src/libGLESv2/renderer/d3d11/Renderer11.cpp
+++ b/src/libGLESv2/renderer/d3d11/Renderer11.cpp
@@ -1403,7 +1403,7 @@
}
}
-void Renderer11::applyShaders(gl::ProgramBinary *programBinary)
+void Renderer11::applyShaders(gl::ProgramBinary *programBinary, bool rasterizerDiscard)
{
ShaderExecutable *vertexExe = programBinary->getVertexExecutable();
ShaderExecutable *pixelExe = programBinary->getPixelExecutable();
@@ -1419,6 +1419,12 @@
geometryShader = NULL;
}
+ // Skip pixel shader if we're doing rasterizer discard.
+ if (rasterizerDiscard)
+ {
+ pixelShader = NULL;
+ }
+
bool dirtyUniforms = false;
if (vertexShader != mAppliedVertexShader)
diff --git a/src/libGLESv2/renderer/d3d11/Renderer11.h b/src/libGLESv2/renderer/d3d11/Renderer11.h
index 4f626a7..69e04ab 100644
--- a/src/libGLESv2/renderer/d3d11/Renderer11.h
+++ b/src/libGLESv2/renderer/d3d11/Renderer11.h
@@ -75,7 +75,7 @@
virtual bool applyPrimitiveType(GLenum mode, GLsizei count);
virtual bool applyRenderTarget(gl::Framebuffer *frameBuffer);
- virtual void applyShaders(gl::ProgramBinary *programBinary);
+ virtual void applyShaders(gl::ProgramBinary *programBinary, bool rasterizerDiscard);
virtual void applyUniforms(const gl::ProgramBinary &programBinary);
virtual GLenum applyVertexBuffer(gl::ProgramBinary *programBinary, const gl::VertexAttribute vertexAttributes[], gl::VertexAttribCurrentValueData currentValues[],
GLint first, GLsizei count, GLsizei instances);
diff --git a/src/libGLESv2/renderer/d3d9/Renderer9.cpp b/src/libGLESv2/renderer/d3d9/Renderer9.cpp
index ffb537b..eef5a12 100644
--- a/src/libGLESv2/renderer/d3d9/Renderer9.cpp
+++ b/src/libGLESv2/renderer/d3d9/Renderer9.cpp
@@ -1722,8 +1722,10 @@
}
}
-void Renderer9::applyShaders(gl::ProgramBinary *programBinary)
+void Renderer9::applyShaders(gl::ProgramBinary *programBinary, bool rasterizerDiscard)
{
+ ASSERT(!rasterizerDiscard);
+
ShaderExecutable *vertexExe = programBinary->getVertexExecutable();
ShaderExecutable *pixelExe = programBinary->getPixelExecutable();
diff --git a/src/libGLESv2/renderer/d3d9/Renderer9.h b/src/libGLESv2/renderer/d3d9/Renderer9.h
index baa69c2..e26928a 100644
--- a/src/libGLESv2/renderer/d3d9/Renderer9.h
+++ b/src/libGLESv2/renderer/d3d9/Renderer9.h
@@ -86,7 +86,7 @@
bool ignoreViewport);
virtual bool applyRenderTarget(gl::Framebuffer *frameBuffer);
- virtual void applyShaders(gl::ProgramBinary *programBinary);
+ virtual void applyShaders(gl::ProgramBinary *programBinary, bool rasterizerDiscard);
virtual void applyUniforms(const gl::ProgramBinary &programBinary);
virtual bool applyPrimitiveType(GLenum primitiveType, GLsizei elementCount);
virtual GLenum applyVertexBuffer(gl::ProgramBinary *programBinary, const gl::VertexAttribute vertexAttributes[], gl::VertexAttribCurrentValueData currentValues[],
diff --git a/src/libGLESv2/validationES.cpp b/src/libGLESv2/validationES.cpp
index ef759a5..3bc63f6 100644
--- a/src/libGLESv2/validationES.cpp
+++ b/src/libGLESv2/validationES.cpp
@@ -21,6 +21,28 @@
namespace gl
{
+bool ValidCap(const Context *context, GLenum cap)
+{
+ switch (cap)
+ {
+ case GL_CULL_FACE:
+ case GL_POLYGON_OFFSET_FILL:
+ case GL_SAMPLE_ALPHA_TO_COVERAGE:
+ case GL_SAMPLE_COVERAGE:
+ case GL_SCISSOR_TEST:
+ case GL_STENCIL_TEST:
+ case GL_DEPTH_TEST:
+ case GL_BLEND:
+ case GL_DITHER:
+ return true;
+ case GL_PRIMITIVE_RESTART_FIXED_INDEX:
+ case GL_RASTERIZER_DISCARD:
+ return (context->getClientVersion() >= 3);
+ default:
+ return false;
+ }
+}
+
bool ValidTextureTarget(const Context *context, GLenum target)
{
switch (target)
diff --git a/src/libGLESv2/validationES.h b/src/libGLESv2/validationES.h
index 2afd2dc..a22028f 100644
--- a/src/libGLESv2/validationES.h
+++ b/src/libGLESv2/validationES.h
@@ -14,6 +14,7 @@
class Context;
+bool ValidCap(const Context *context, GLenum cap);
bool ValidTextureTarget(const Context *context, GLenum target);
bool ValidFramebufferTarget(GLenum target);
bool ValidMipLevel(const Context *context, GLenum target, GLint level);