Commit 08332634 by Austin Kinross Committed by Geoff Lang

Implement EXT_discard_framebuffer in D3D11 renderer

Change-Id: I52bcf0cfb1aa123e085a35730fdefb006b617c3c Reviewed-on: https://chromium-review.googlesource.com/269232Tested-by: 's avatarAustin Kinross <aukinros@microsoft.com> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent 450a80a2
......@@ -134,6 +134,7 @@ Extensions::Extensions()
textureUsage(false),
translatedShaderSource(false),
fboRenderMipmap(false),
discardFramebuffer(false),
colorBufferFloat(false)
{
}
......@@ -184,6 +185,7 @@ std::vector<std::string> Extensions::getStrings() const
InsertExtensionString("GL_ANGLE_texture_usage", textureUsage, &extensionStrings);
InsertExtensionString("GL_ANGLE_translated_shader_source", translatedShaderSource, &extensionStrings);
InsertExtensionString("GL_OES_fbo_render_mipmap", fboRenderMipmap, &extensionStrings);
InsertExtensionString("GL_EXT_discard_framebuffer", discardFramebuffer, &extensionStrings);
InsertExtensionString("GL_EXT_color_buffer_float", colorBufferFloat, &extensionStrings);
return extensionStrings;
......
......@@ -213,6 +213,9 @@ struct Extensions
// GL_OES_fbo_render_mipmap
bool fboRenderMipmap;
// GL_EXT_discard_framebuffer
bool discardFramebuffer;
// ES3 Extension support
// GL_EXT_color_buffer_float
......
......@@ -497,6 +497,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);
......
......@@ -118,6 +118,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 : angle::NonCopyable
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;
......
......@@ -123,18 +123,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::Data &data, GLbitfield mask)
{
const gl::State &state = *data.state;
......
......@@ -66,9 +66,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::Data &data, 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;
......
......@@ -135,6 +135,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.getColorAttachment(colorAttachmentID))
{
error = mData.getColorAttachment(colorAttachmentID)->getRenderTarget(&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.getDepthAttachment() == 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.getStencilAttachment() == nullptr));
discardStencil = (foundStencil && (mData.getDepthAttachment() == nullptr));
}
if (discardDepth && mData.getDepthAttachment())
{
RenderTarget11 *renderTarget = nullptr;
ID3D11View *depthView = nullptr;
gl::Error error(GL_NO_ERROR);
error = mData.getDepthAttachment()->getRenderTarget(&renderTarget);
if (error.isError())
{
return error;
}
depthView = renderTarget->getDepthStencilView();
if (depthView != nullptr)
{
deviceContext1->DiscardView(depthView);
}
}
if (discardStencil && mData.getStencilAttachment())
{
RenderTarget11 *renderTarget = nullptr;
ID3D11View *stencilView = nullptr;
gl::Error error(GL_NO_ERROR);
error = mData.getStencilAttachment()->getRenderTarget(&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 = nullptr;
......
......@@ -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;
......
......@@ -1102,6 +1102,7 @@ void GenerateCaps(ID3D11Device *device, ID3D11DeviceContext *deviceContext, cons
extensions->shaderTextureLOD = GetShaderTextureLODSupport(featureLevel);
extensions->fragDepth = true;
extensions->textureUsage = true; // This could be false since it has no effect in D3D11
extensions->discardFramebuffer = false; // TODO: enable this once BUG:497445 is fixed (Chrome WebGL video tests fail with this extension active)
extensions->translatedShaderSource = true;
extensions->fboRenderMipmap = false;
}
......
......@@ -32,6 +32,27 @@ Framebuffer9::~Framebuffer9()
{
}
gl::Error Framebuffer9::discard(size_t, const GLenum *)
{
// Extension not implemented in D3D9 renderer
UNREACHABLE();
return gl::Error(GL_NO_ERROR);
}
gl::Error Framebuffer9::invalidate(size_t, const GLenum *)
{
// Shouldn't ever reach here in D3D9
UNREACHABLE();
return gl::Error(GL_NO_ERROR);
}
gl::Error Framebuffer9::invalidateSub(size_t, const GLenum *, const gl::Rectangle &)
{
// Shouldn't ever reach here in D3D9
UNREACHABLE();
return gl::Error(GL_NO_ERROR);
}
gl::Error Framebuffer9::clear(const gl::State &state, const ClearParameters &clearParams)
{
const gl::FramebufferAttachment *colorAttachment = mData.getColorAttachment(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;
......
......@@ -538,6 +538,7 @@ void GenerateCaps(IDirect3D9 *d3d9, IDirect3DDevice9 *device, D3DDEVTYPE deviceT
extensions->textureUsage = true;
extensions->translatedShaderSource = true;
extensions->fboRenderMipmap = false;
extensions->discardFramebuffer = false; // It would be valid to set this to true, since glDiscardFramebufferEXT is just a hint
extensions->colorBufferFloat = false;
}
......
......@@ -152,6 +152,12 @@ void FramebufferGL::setReadBuffer(GLenum buffer)
}
}
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)
{
// Since this function is just a hint and not available until OpenGL 4.3, only call it if it is available.
......
......@@ -31,6 +31,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;
......
......@@ -1884,4 +1884,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);
......
......@@ -1162,6 +1162,7 @@ __eglMustCastToProperFunctionPointerType EGLAPIENTRY GetProcAddress(const char *
{ "glUnmapBufferOES", (__eglMustCastToProperFunctionPointerType)gl::UnmapBufferOES },
{ "glMapBufferRangeEXT", (__eglMustCastToProperFunctionPointerType)gl::MapBufferRangeEXT },
{ "glFlushMappedBufferRangeEXT", (__eglMustCastToProperFunctionPointerType)gl::FlushMappedBufferRangeEXT },
{ "glDiscardFramebufferEXT", (__eglMustCastToProperFunctionPointerType)gl::DiscardFramebufferEXT },
{ "", NULL },
};
......
......@@ -684,6 +684,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);
......
......@@ -3207,13 +3207,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;
}
......@@ -3242,13 +3236,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
......
......@@ -21,6 +21,7 @@
'<(angle_path)/src/tests/gl_tests/CompressedTextureTest.cpp',
'<(angle_path)/src/tests/gl_tests/CubeMapTextureTest.cpp',
'<(angle_path)/src/tests/gl_tests/DepthStencilFormatsTest.cpp',
'<(angle_path)/src/tests/gl_tests/DiscardFramebufferEXTTest.cpp',
'<(angle_path)/src/tests/gl_tests/DrawBuffersTest.cpp',
'<(angle_path)/src/tests/gl_tests/FenceSyncTests.cpp',
'<(angle_path)/src/tests/gl_tests/FramebufferFormatsTest.cpp',
......
//
// Copyright 2015 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
#include "test_utils/ANGLETest.h"
using namespace angle;
class DiscardFramebufferEXTTest : public ANGLETest
{
protected:
DiscardFramebufferEXTTest()
{
setWindowWidth(256);
setWindowHeight(256);
setConfigRedBits(8);
setConfigGreenBits(8);
setConfigBlueBits(8);
setConfigAlphaBits(8);
setConfigDepthBits(24);
setConfigStencilBits(8);
}
};
TEST_P(DiscardFramebufferEXTTest, ExtensionEnabled)
{
EGLPlatformParameters platform = GetParam().mEGLPlatformParameters;
if (platform.renderer == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
{
// EXPECT_TRUE(extensionEnabled("EXT_discard_framebuffer"));
// EXT_discard_framebuffer is disabled in D3D11 ANGLE due to Chromium BUG:497445
// Enabling this extension (even as a no-op) causes WebGL video failures in Chromium
// Once this bug is fixed, we can reenable the extension.
EXPECT_FALSE(extensionEnabled("EXT_discard_framebuffer"));
}
else
{
// Other platforms don't currently implement this extension
EXPECT_FALSE(extensionEnabled("EXT_discard_framebuffer"));
}
}
TEST_P(DiscardFramebufferEXTTest, DefaultFramebuffer)
{
if (!extensionEnabled("EXT_discard_framebuffer"))
{
std::cout << "Test skipped because EXT_discard_framebuffer is not available." << std::endl;
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);
}
TEST_P(DiscardFramebufferEXTTest, NonDefaultFramebuffer)
{
if (!extensionEnabled("EXT_discard_framebuffer"))
{
std::cout << "Test skipped because EXT_discard_framebuffer is not available." << std::endl;
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();
}
// Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
ANGLE_INSTANTIATE_TEST(DiscardFramebufferEXTTest, ES2_D3D9(), ES2_D3D11(), ES2_D3D11_FL9_3(), ES2_OPENGL(), ES3_OPENGL());
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