Commit b13daa8f by Austin Kinross Committed by Jamie Madill

Implement EXT_discard_framebuffer in D3D11 renderer

Change-Id: I0e39a196796813203c841c46aa2a6b89957f6051 Reviewed-on: https://chromium-review.googlesource.com/261355Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Tested-by: 's avatarJamie Madill <jmadill@chromium.org>
parent ecbfc5c6
......@@ -133,6 +133,7 @@ Extensions::Extensions()
fragDepth(false),
textureUsage(false),
translatedShaderSource(false),
discardFramebuffer(false),
colorBufferFloat(false)
{
}
......@@ -182,6 +183,7 @@ std::vector<std::string> Extensions::getStrings() const
InsertExtensionString("GL_EXT_frag_depth", fragDepth, &extensionStrings);
InsertExtensionString("GL_ANGLE_texture_usage", textureUsage, &extensionStrings);
InsertExtensionString("GL_ANGLE_translated_shader_source", translatedShaderSource, &extensionStrings);
InsertExtensionString("GL_EXT_discard_framebuffer", discardFramebuffer, &extensionStrings);
InsertExtensionString("GL_EXT_color_buffer_float", colorBufferFloat, &extensionStrings);
return extensionStrings;
......
......@@ -209,6 +209,9 @@ struct Extensions
// GL_ANGLE_translated_shader_source
bool translatedShaderSource;
// GL_EXT_discard_framebuffer
bool discardFramebuffer;
// ES3 Extension support
// GL_EXT_color_buffer_float
......
......@@ -461,6 +461,11 @@ GLenum Framebuffer::checkStatus(const gl::Data &data) const
return mImpl->checkStatus();
}
Error Framebuffer::discard(size_t count, const GLenum *attachments)
{
return mImpl->discard(count, attachments);
}
Error Framebuffer::invalidate(size_t count, const GLenum *attachments)
{
return mImpl->invalidate(count, attachments);
......
......@@ -112,6 +112,7 @@ class Framebuffer
GLenum checkStatus(const gl::Data &data) const;
bool hasValidDepthStencil() const;
Error discard(size_t count, const GLenum *attachments);
Error invalidate(size_t count, const GLenum *attachments);
Error invalidateSub(size_t count, const GLenum *attachments, const gl::Rectangle &area);
......
......@@ -39,6 +39,7 @@ class FramebufferImpl
virtual void setDrawBuffers(size_t count, const GLenum *buffers) = 0;
virtual void setReadBuffer(GLenum buffer) = 0;
virtual gl::Error discard(size_t count, const GLenum *attachments) = 0;
virtual gl::Error invalidate(size_t count, const GLenum *attachments) = 0;
virtual gl::Error invalidateSub(size_t count, const GLenum *attachments, const gl::Rectangle &area) = 0;
......
......@@ -161,18 +161,6 @@ void FramebufferD3D::setReadBuffer(GLenum)
{
}
gl::Error FramebufferD3D::invalidate(size_t, const GLenum *)
{
// No-op in D3D
return gl::Error(GL_NO_ERROR);
}
gl::Error FramebufferD3D::invalidateSub(size_t, const GLenum *, const gl::Rectangle &)
{
// No-op in D3D
return gl::Error(GL_NO_ERROR);
}
gl::Error FramebufferD3D::clear(const gl::State &state, GLbitfield mask)
{
ClearParameters clearParams = GetClearParameters(state, mask);
......
......@@ -85,9 +85,6 @@ class FramebufferD3D : public FramebufferImpl
void setDrawBuffers(size_t count, const GLenum *buffers) override;
void setReadBuffer(GLenum buffer) override;
gl::Error invalidate(size_t count, const GLenum *attachments) override;
gl::Error invalidateSub(size_t count, const GLenum *attachments, const gl::Rectangle &area) override;
gl::Error clear(const gl::State &state, GLbitfield mask) override;
gl::Error clearBufferfv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLfloat *values) override;
gl::Error clearBufferuiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLuint *values) override;
......
......@@ -132,6 +132,159 @@ static gl::Error getRenderTargetResource(const gl::FramebufferAttachment *colorb
return gl::Error(GL_NO_ERROR);
}
gl::Error Framebuffer11::invalidate(size_t count, const GLenum *attachments)
{
return invalidateBase(count, attachments, false);
}
gl::Error Framebuffer11::discard(size_t count, const GLenum *attachments)
{
return invalidateBase(count, attachments, true);
}
gl::Error Framebuffer11::invalidateBase(size_t count, const GLenum *attachments, bool useEXTBehavior) const
{
ID3D11DeviceContext1 *deviceContext1 = mRenderer->getDeviceContext1IfSupported();
if (!deviceContext1)
{
// DiscardView() is only supported on ID3D11DeviceContext1
return gl::Error(GL_NO_ERROR);
}
bool foundDepth = false;
bool foundStencil = false;
for (size_t i = 0; i < count; ++i)
{
switch (attachments[i])
{
// Handle depth and stencil attachments. Defer discarding until later.
case GL_DEPTH_STENCIL_ATTACHMENT:
foundDepth = true;
foundStencil = true;
break;
case GL_DEPTH_EXT:
case GL_DEPTH_ATTACHMENT:
foundDepth = true;
break;
case GL_STENCIL_EXT:
case GL_STENCIL_ATTACHMENT:
foundStencil = true;
break;
default:
{
// Handle color attachments
ASSERT((attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT15) ||
(attachments[i] == GL_COLOR));
RenderTarget11 *renderTarget = nullptr;
ID3D11View *colorView = nullptr;
gl::Error error(GL_NO_ERROR);
size_t colorAttachmentID = 0;
if (attachments[i] == GL_COLOR)
{
colorAttachmentID = 0;
}
else
{
colorAttachmentID = attachments[i] - GL_COLOR_ATTACHMENT0;
}
if (mData.mColorAttachments[colorAttachmentID])
{
error = d3d11::GetAttachmentRenderTarget(mData.mColorAttachments[colorAttachmentID], &renderTarget);
if (error.isError())
{
return error;
}
colorView = renderTarget->getRenderTargetView();
if (colorView != nullptr)
{
deviceContext1->DiscardView(colorView);
}
}
break;
}
}
}
bool discardDepth = false;
bool discardStencil = false;
// The D3D11 renderer uses the same view for depth and stencil buffers, so we must be careful.
if (useEXTBehavior)
{
// In the extension, if the app discards only one of the depth and stencil attachments, but
// those are backed by the same packed_depth_stencil buffer, then both images become undefined.
discardDepth = foundDepth;
// Don't bother discarding the stencil buffer if the depth buffer will already do it
discardStencil = foundStencil && (!discardDepth || mData.mDepthAttachment == nullptr);
}
else
{
// In ES 3.0.4, if a specified attachment has base internal format DEPTH_STENCIL but the
// attachments list does not include DEPTH_STENCIL_ATTACHMENT or both DEPTH_ATTACHMENT and
// STENCIL_ATTACHMENT, then only the specified portion of every pixel in the subregion of pixels
// of the DEPTH_STENCIL buffer may be invalidated, and the other portion must be preserved.
discardDepth = (foundDepth && foundStencil) || (foundDepth && (mData.mStencilAttachment == nullptr));
discardStencil = (foundStencil && (mData.mDepthAttachment == nullptr));
}
if (discardDepth && mData.mDepthAttachment)
{
RenderTarget11 *renderTarget = nullptr;
ID3D11View *depthView = nullptr;
gl::Error error(GL_NO_ERROR);
error = d3d11::GetAttachmentRenderTarget(mData.mDepthAttachment, &renderTarget);
if (error.isError())
{
return error;
}
depthView = renderTarget->getDepthStencilView();
if (depthView != nullptr)
{
deviceContext1->DiscardView(depthView);
}
}
if (discardStencil && mData.mStencilAttachment)
{
RenderTarget11 *renderTarget = nullptr;
ID3D11View *stencilView = nullptr;
gl::Error error(GL_NO_ERROR);
error = d3d11::GetAttachmentRenderTarget(mData.mStencilAttachment, &renderTarget);
if (error.isError())
{
return error;
}
stencilView = renderTarget->getDepthStencilView();
if (stencilView != nullptr)
{
deviceContext1->DiscardView(stencilView);
}
}
return gl::Error(GL_NO_ERROR);
}
gl::Error Framebuffer11::invalidateSub(size_t, const GLenum *, const gl::Rectangle &)
{
// A no-op implementation conforms to the spec, so don't call UNIMPLEMENTED()
return gl::Error(GL_NO_ERROR);
}
gl::Error Framebuffer11::readPixels(const gl::Rectangle &area, GLenum format, GLenum type, size_t outputPitch, const gl::PixelPackState &pack, uint8_t *pixels) const
{
ID3D11Texture2D *colorBufferTexture = NULL;
......
......@@ -21,6 +21,10 @@ class Framebuffer11 : public FramebufferD3D
Framebuffer11(const gl::Framebuffer::Data &data, Renderer11 *renderer);
virtual ~Framebuffer11();
gl::Error discard(size_t count, const GLenum *attachments) override;
gl::Error invalidate(size_t count, const GLenum *attachments) override;
gl::Error invalidateSub(size_t count, const GLenum *attachments, const gl::Rectangle &area) override;
// Invalidate the cached swizzles of all bound texture attachments.
gl::Error invalidateSwizzles() const;
......@@ -34,6 +38,7 @@ class Framebuffer11 : public FramebufferD3D
bool blitRenderTarget, bool blitDepth, bool blitStencil, GLenum filter,
const gl::Framebuffer *sourceFramebuffer) override;
gl::Error invalidateBase(size_t count, const GLenum *attachments, bool useEXTBehavior) const;
GLenum getRenderTargetImplementationFormat(RenderTargetD3D *renderTarget) const override;
......
......@@ -1098,6 +1098,7 @@ void GenerateCaps(ID3D11Device *device, gl::Caps *caps, gl::TextureCapsMap *text
extensions->shaderTextureLOD = GetShaderTextureLODSupport(featureLevel);
extensions->fragDepth = true;
extensions->textureUsage = true; // This could be false since it has no effect in D3D11
extensions->discardFramebuffer = true;
extensions->translatedShaderSource = true;
}
......
......@@ -32,6 +32,24 @@ Framebuffer9::~Framebuffer9()
{
}
gl::Error Framebuffer9::discard(size_t, const GLenum *)
{
// No-op in D3D9
return gl::Error(GL_NO_ERROR);
}
gl::Error Framebuffer9::invalidate(size_t, const GLenum *)
{
// No-op in D3D9
return gl::Error(GL_NO_ERROR);
}
gl::Error Framebuffer9::invalidateSub(size_t, const GLenum *, const gl::Rectangle &)
{
// No-op in D3D9
return gl::Error(GL_NO_ERROR);
}
gl::Error Framebuffer9::clear(const gl::State &state, const ClearParameters &clearParams)
{
const gl::FramebufferAttachment *colorAttachment = mData.mColorAttachments[0];
......
......@@ -21,6 +21,10 @@ class Framebuffer9 : public FramebufferD3D
Framebuffer9(const gl::Framebuffer::Data &data, Renderer9 *renderer);
virtual ~Framebuffer9();
gl::Error discard(size_t count, const GLenum *attachments) override;
gl::Error invalidate(size_t count, const GLenum *attachments) override;
gl::Error invalidateSub(size_t count, const GLenum *attachments, const gl::Rectangle &area) override;
private:
gl::Error clear(const gl::State &state, const ClearParameters &clearParams) override;
......
......@@ -536,6 +536,7 @@ void GenerateCaps(IDirect3D9 *d3d9, IDirect3DDevice9 *device, D3DDEVTYPE deviceT
extensions->fragDepth = true;
extensions->textureUsage = true;
extensions->translatedShaderSource = true;
extensions->discardFramebuffer = false; // It would be valid to set this to true, since glDiscardFramebufferEXT is just a hint
extensions->colorBufferFloat = false;
}
......
......@@ -51,6 +51,12 @@ void FramebufferGL::setReadBuffer(GLenum buffer)
//UNIMPLEMENTED();
}
gl::Error FramebufferGL::discard(size_t count, const GLenum *attachments)
{
UNIMPLEMENTED();
return gl::Error(GL_INVALID_OPERATION);
}
gl::Error FramebufferGL::invalidate(size_t count, const GLenum *attachments)
{
UNIMPLEMENTED();
......
......@@ -28,6 +28,7 @@ class FramebufferGL : public FramebufferImpl
void setDrawBuffers(size_t count, const GLenum *buffers) override;
void setReadBuffer(GLenum buffer) override;
gl::Error discard(size_t count, const GLenum *attachments) override;
gl::Error invalidate(size_t count, const GLenum *attachments) override;
gl::Error invalidateSub(size_t count, const GLenum *attachments, const gl::Rectangle &area) override;
......
......@@ -1848,4 +1848,62 @@ bool ValidateGetnUniformivEXT(Context *context, GLuint program, GLint location,
return ValidateSizedGetUniform(context, program, location, bufSize);
}
bool ValidateDiscardFramebufferBase(Context *context, GLenum target, GLsizei numAttachments,
const GLenum *attachments, bool defaultFramebuffer)
{
if (numAttachments < 0)
{
context->recordError(Error(GL_INVALID_VALUE, "numAttachments must not be less than zero"));
return false;
}
for (GLsizei i = 0; i < numAttachments; ++i)
{
if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT15)
{
if (defaultFramebuffer)
{
context->recordError(Error(GL_INVALID_ENUM, "Invalid attachment when the default framebuffer is bound"));
return false;
}
if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
{
context->recordError(Error(GL_INVALID_OPERATION,
"Requested color attachment is greater than the maximum supported color attachments"));
return false;
}
}
else
{
switch (attachments[i])
{
case GL_DEPTH_ATTACHMENT:
case GL_STENCIL_ATTACHMENT:
case GL_DEPTH_STENCIL_ATTACHMENT:
if (defaultFramebuffer)
{
context->recordError(Error(GL_INVALID_ENUM, "Invalid attachment when the default framebuffer is bound"));
return false;
}
break;
case GL_COLOR:
case GL_DEPTH:
case GL_STENCIL:
if (!defaultFramebuffer)
{
context->recordError(Error(GL_INVALID_ENUM, "Invalid attachment when the default framebuffer is not bound"));
return false;
}
break;
default:
context->recordError(Error(GL_INVALID_ENUM, "Invalid attachment"));
return false;
}
}
}
return true;
}
}
......@@ -89,6 +89,9 @@ bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLin
bool ValidateGetnUniformfvEXT(Context *context, GLuint program, GLint location, GLsizei bufSize, GLfloat* params);
bool ValidateGetnUniformivEXT(Context *context, GLuint program, GLint location, GLsizei bufSize, GLint* params);
bool ValidateDiscardFramebufferBase(Context *context, GLenum target, GLsizei numAttachments,
const GLenum *attachments, bool defaultFramebuffer);
}
#endif // LIBANGLE_VALIDATION_ES_H_
......@@ -879,4 +879,22 @@ bool ValidES2ReadFormatType(Context *context, GLenum format, GLenum type)
return true;
}
bool ValidateDiscardFramebufferEXT(Context *context, GLenum target, GLsizei numAttachments,
const GLenum *attachments)
{
bool defaultFramebuffer = false;
switch (target)
{
case GL_FRAMEBUFFER:
defaultFramebuffer = (context->getState().getTargetFramebuffer(GL_FRAMEBUFFER)->id() == 0);
break;
default:
context->recordError(Error(GL_INVALID_ENUM, "Invalid framebuffer target"));
return false;
}
return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments, defaultFramebuffer);
}
}
......@@ -29,6 +29,9 @@ bool ValidateES2TexStorageParameters(Context *context, GLenum target, GLsizei le
bool ValidES2ReadFormatType(Context *context, GLenum format, GLenum type);
bool ValidateDiscardFramebufferEXT(Context *context, GLenum target, GLsizei numAttachments,
const GLenum *attachments);
}
#endif // LIBANGLE_VALIDATION_ES2_H_
......@@ -1132,9 +1132,15 @@ bool ValidateES3RenderbufferStorageParameters(gl::Context *context, GLenum targe
return true;
}
bool ValidateInvalidateFramebufferParameters(Context *context, GLenum target, GLsizei numAttachments,
const GLenum* attachments)
bool ValidateInvalidateFramebuffer(Context *context, GLenum target, GLsizei numAttachments,
const GLenum *attachments)
{
if (context->getClientVersion() < 3)
{
context->recordError(Error(GL_INVALID_OPERATION, "Operation only supported on ES 3.0 and above"));
return false;
}
bool defaultFramebuffer = false;
switch (target)
......@@ -1147,56 +1153,11 @@ bool ValidateInvalidateFramebufferParameters(Context *context, GLenum target, GL
defaultFramebuffer = context->getState().getReadFramebuffer()->id() == 0;
break;
default:
context->recordError(Error(GL_INVALID_ENUM));
return false;
}
for (int i = 0; i < numAttachments; ++i)
{
if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT15)
{
if (defaultFramebuffer)
{
context->recordError(Error(GL_INVALID_ENUM));
return false;
}
if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
{
context->recordError(Error(GL_INVALID_OPERATION));
return false;
}
}
else
{
switch (attachments[i])
{
case GL_DEPTH_ATTACHMENT:
case GL_STENCIL_ATTACHMENT:
case GL_DEPTH_STENCIL_ATTACHMENT:
if (defaultFramebuffer)
{
context->recordError(Error(GL_INVALID_ENUM));
return false;
}
break;
case GL_COLOR:
case GL_DEPTH:
case GL_STENCIL:
if (!defaultFramebuffer)
{
context->recordError(Error(GL_INVALID_ENUM));
return false;
}
break;
default:
context->recordError(Error(GL_INVALID_ENUM));
return false;
}
}
context->recordError(Error(GL_INVALID_ENUM, "Invalid framebuffer target"));
return false;
}
return true;
return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments, defaultFramebuffer);
}
bool ValidateClearBuffer(Context *context)
......
......@@ -35,8 +35,8 @@ bool ValidES3ReadFormatType(Context *context, GLenum internalFormat, GLenum form
bool ValidateES3RenderbufferStorageParameters(Context *context, GLenum target, GLsizei samples,
GLenum internalformat, GLsizei width, GLsizei height);
bool ValidateInvalidateFramebufferParameters(Context *context, GLenum target, GLsizei numAttachments,
const GLenum* attachments);
bool ValidateInvalidateFramebuffer(Context *context, GLenum target, GLsizei numAttachments,
const GLenum *attachments);
bool ValidateClearBuffer(Context *context);
......
......@@ -1107,6 +1107,7 @@ __eglMustCastToProperFunctionPointerType EGLAPIENTRY GetProcAddress(const char *
{ "glUnmapBufferOES", (__eglMustCastToProperFunctionPointerType)gl::UnmapBufferOES },
{ "glMapBufferRangeEXT", (__eglMustCastToProperFunctionPointerType)gl::MapBufferRangeEXT },
{ "glFlushMappedBufferRangeEXT", (__eglMustCastToProperFunctionPointerType)gl::FlushMappedBufferRangeEXT },
{ "glDiscardFramebufferEXT", (__eglMustCastToProperFunctionPointerType)gl::DiscardFramebufferEXT },
{ "", NULL },
};
......
......@@ -682,6 +682,38 @@ void GL_APIENTRY BlitFramebufferANGLE(GLint srcX0, GLint srcY0, GLint srcX1, GLi
}
}
void GL_APIENTRY DiscardFramebufferEXT(GLenum target, GLsizei numAttachments, const GLenum *attachments)
{
EVENT("(GLenum target = 0x%X, GLsizei numAttachments = %d, attachments = 0x%0.8p)", target, numAttachments, attachments);
Context *context = GetValidGlobalContext();
if (context)
{
if (!context->getExtensions().discardFramebuffer)
{
context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
return;
}
if (!ValidateDiscardFramebufferEXT(context, target, numAttachments, attachments))
{
return;
}
Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target);
ASSERT(framebuffer);
// The specification isn't clear what should be done when the framebuffer isn't complete.
// We leave it up to the framebuffer implementation to decide what to do.
Error error = framebuffer->discard(numAttachments, attachments);
if (error.isError())
{
context->recordError(error);
return;
}
}
}
void GL_APIENTRY TexImage3DOES(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth,
GLint border, GLenum format, GLenum type, const GLvoid* pixels)
{
......
......@@ -22,6 +22,9 @@ ANGLE_EXPORT void GL_APIENTRY BlitFramebufferANGLE(GLint srcX0, GLint srcY0, GLi
// GL_ANGLE_framebuffer_multisample
ANGLE_EXPORT void GL_APIENTRY RenderbufferStorageMultisampleANGLE(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
// GL_EXT_discard_framebuffer
ANGLE_EXPORT void GL_APIENTRY DiscardFramebufferEXT(GLenum target, GLsizei numAttachments, const GLenum *attachments);
// GL_NV_fence
ANGLE_EXPORT void GL_APIENTRY DeleteFencesNV(GLsizei n, const GLuint* fences);
ANGLE_EXPORT void GL_APIENTRY GenFencesNV(GLsizei n, GLuint* fences);
......
......@@ -3189,13 +3189,7 @@ void GL_APIENTRY InvalidateFramebuffer(GLenum target, GLsizei numAttachments, co
Context *context = GetValidGlobalContext();
if (context)
{
if (context->getClientVersion() < 3)
{
context->recordError(Error(GL_INVALID_OPERATION));
return;
}
if (!ValidateInvalidateFramebufferParameters(context, target, numAttachments, attachments))
if (!ValidateInvalidateFramebuffer(context, target, numAttachments, attachments))
{
return;
}
......@@ -3224,13 +3218,7 @@ void GL_APIENTRY InvalidateSubFramebuffer(GLenum target, GLsizei numAttachments,
Context *context = GetValidGlobalContext();
if (context)
{
if (context->getClientVersion() < 3)
{
context->recordError(Error(GL_INVALID_OPERATION));
return;
}
if (!ValidateInvalidateFramebufferParameters(context, target, numAttachments, attachments))
if (!ValidateInvalidateFramebuffer(context, target, numAttachments, attachments))
{
return;
}
......
......@@ -1256,6 +1256,11 @@ void GL_APIENTRY glRenderbufferStorageMultisampleANGLE(GLenum target, GLsizei sa
return gl::RenderbufferStorageMultisampleANGLE(target, samples, internalformat, width, height);
}
void GL_APIENTRY glDiscardFramebufferEXT(GLenum target, GLsizei numAttachments, const GLenum *attachments)
{
return gl::DiscardFramebufferEXT(target, numAttachments, attachments);
}
void GL_APIENTRY glDeleteFencesNV(GLsizei n, const GLuint* fences)
{
return gl::DeleteFencesNV(n, fences);
......
......@@ -177,6 +177,7 @@ EXPORTS
glGetBufferPointervOES @287
glMapBufferRangeEXT @288
glFlushMappedBufferRangeEXT @289
glDiscardFramebufferEXT @293
; GLES 3.0 Functions
glReadBuffer @180
......
......@@ -24,6 +24,7 @@
'<(angle_path)/src/tests/end2end_tests/CompressedTextureTest.cpp',
'<(angle_path)/src/tests/end2end_tests/CubeMapTextureTest.cpp',
'<(angle_path)/src/tests/end2end_tests/DepthStencilFormatsTest.cpp',
'<(angle_path)/src/tests/end2end_tests/DiscardFramebufferEXTTest.cpp',
'<(angle_path)/src/tests/end2end_tests/DrawBuffersTest.cpp',
'<(angle_path)/src/tests/end2end_tests/FramebufferFormatsTest.cpp',
'<(angle_path)/src/tests/end2end_tests/GLSLTest.cpp',
......
#include "ANGLETest.h"
// Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
ANGLE_TYPED_TEST_CASE(DiscardFramebufferEXTTest, ES2_D3D9, ES2_D3D11, ES2_D3D11_FL9_3);
template<typename T>
class DiscardFramebufferEXTTest : public ANGLETest
{
protected:
DiscardFramebufferEXTTest() : ANGLETest(T::GetGlesMajorVersion(), T::GetPlatform())
{
setWindowWidth(256);
setWindowHeight(256);
setConfigRedBits(8);
setConfigGreenBits(8);
setConfigBlueBits(8);
setConfigAlphaBits(8);
setConfigDepthBits(24);
setConfigStencilBits(8);
}
T fixtureType;
};
TYPED_TEST(DiscardFramebufferEXTTest, ExtensionEnabled)
{
EGLPlatformParameters platform = fixtureType.GetPlatform();
if (platform.renderer == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
{
EXPECT_TRUE(extensionEnabled("EXT_discard_framebuffer"));
}
else
{
// Other platforms don't currently implement this extension
EXPECT_FALSE(extensionEnabled("EXT_discard_framebuffer"));
}
}
TYPED_TEST(DiscardFramebufferEXTTest, DefaultFramebuffer)
{
if (!extensionEnabled("EXT_discard_framebuffer"))
{
return;
}
// These should succeed on the default framebuffer
const GLenum discards1[] = { GL_COLOR_EXT };
glDiscardFramebufferEXT(GL_FRAMEBUFFER, 1, discards1);
EXPECT_GL_NO_ERROR();
const GLenum discards2[] = { GL_DEPTH_EXT };
glDiscardFramebufferEXT(GL_FRAMEBUFFER, 1, discards2);
EXPECT_GL_NO_ERROR();
const GLenum discards3[] = { GL_STENCIL_EXT };
glDiscardFramebufferEXT(GL_FRAMEBUFFER, 1, discards3);
EXPECT_GL_NO_ERROR();
const GLenum discards4[] = { GL_STENCIL_EXT, GL_COLOR_EXT, GL_DEPTH_EXT };
glDiscardFramebufferEXT(GL_FRAMEBUFFER, 3, discards4);
EXPECT_GL_NO_ERROR();
// These should fail on the default framebuffer
const GLenum discards5[] = { GL_COLOR_ATTACHMENT0 };
glDiscardFramebufferEXT(GL_FRAMEBUFFER, 1, discards5);
EXPECT_GL_ERROR(GL_INVALID_ENUM);
const GLenum discards6[] = { GL_DEPTH_ATTACHMENT };
glDiscardFramebufferEXT(GL_FRAMEBUFFER, 1, discards6);
EXPECT_GL_ERROR(GL_INVALID_ENUM);
const GLenum discards7[] = { GL_STENCIL_ATTACHMENT };
glDiscardFramebufferEXT(GL_FRAMEBUFFER, 1, discards7);
EXPECT_GL_ERROR(GL_INVALID_ENUM);
}
TYPED_TEST(DiscardFramebufferEXTTest, NonDefaultFramebuffer)
{
if (!extensionEnabled("EXT_discard_framebuffer"))
{
return;
}
GLuint tex2D;
GLuint framebuffer;
// Create a basic off-screen framebuffer
// Don't create a depth/stencil texture, to ensure that also works correctly
glGenTextures(1, &tex2D);
glGenFramebuffers(1, &framebuffer);
glBindTexture(GL_TEXTURE_2D, tex2D);
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, getWindowWidth(), getWindowHeight(), 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex2D, 0);
ASSERT_EQ(glCheckFramebufferStatus(GL_FRAMEBUFFER), GL_FRAMEBUFFER_COMPLETE);
// These should fail on the non-default framebuffer
const GLenum discards1[] = { GL_COLOR_EXT };
glDiscardFramebufferEXT(GL_FRAMEBUFFER, 1, discards1);
EXPECT_GL_ERROR(GL_INVALID_ENUM);
const GLenum discards2[] = { GL_DEPTH_EXT };
glDiscardFramebufferEXT(GL_FRAMEBUFFER, 1, discards2);
EXPECT_GL_ERROR(GL_INVALID_ENUM);
const GLenum discards3[] = { GL_STENCIL_EXT };
glDiscardFramebufferEXT(GL_FRAMEBUFFER, 1, discards3);
EXPECT_GL_ERROR(GL_INVALID_ENUM);
const GLenum discards4[] = { GL_STENCIL_EXT, GL_COLOR_EXT, GL_DEPTH_EXT };
glDiscardFramebufferEXT(GL_FRAMEBUFFER, 3, discards4);
EXPECT_GL_ERROR(GL_INVALID_ENUM);
// These should succeed on the non-default framebuffer
const GLenum discards5[] = { GL_COLOR_ATTACHMENT0 };
glDiscardFramebufferEXT(GL_FRAMEBUFFER, 1, discards5);
EXPECT_GL_NO_ERROR();
const GLenum discards6[] = { GL_DEPTH_ATTACHMENT };
glDiscardFramebufferEXT(GL_FRAMEBUFFER, 1, discards6);
EXPECT_GL_NO_ERROR();
const GLenum discards7[] = { GL_STENCIL_ATTACHMENT };
glDiscardFramebufferEXT(GL_FRAMEBUFFER, 1, discards7);
EXPECT_GL_NO_ERROR();
}
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