Support CHROMIUM_framebuffer_mixed_samples in the GL backend

BUG=angleproject:1378

Change-Id: I634c41f3507dbdeaa56234c4de1b498f81c848ed
Reviewed-on: https://chromium-review.googlesource.com/344520
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Geoff Lang <geofflang@chromium.org>
Commit-Queue: Sami Väisänen <svaisanen@nvidia.com>
This commit is contained in:
Sami Väisänen 2016-05-12 15:23:40 +03:00 коммит произвёл Commit Bot
Родитель 776a75b45c
Коммит a797e066c1
22 изменённых файлов: 516 добавлений и 66 удалений

Просмотреть файл

@ -821,6 +821,15 @@ GL_APICALL void GL_APIENTRY glBlitFramebufferANGLE (GLint srcX0, GLint srcY0, GL
#endif
#endif /* GL_ANGLE_framebuffer_blit */
#ifndef GL_CHROMIUM_framebuffer_mixed_samples
#define GL_CHROMIUM_frambuffer_mixed_samples 1
#define GL_COVERAGE_MODULATION_CHROMIUM 0x9332
typedef void (GL_APIENTRYP PFNGLCOVERAGEMODULATIONCHROMIUMPROC) (GLenum components);
#ifdef GL_GLEXT_PROTOTYPES
GL_APICALL void GL_APIENTRY glCoverageModulationCHROMIUM(GLenum components);
#endif
#endif /* GL_CHROMIUM_framebuffer_mixed_samples */
#ifndef GL_ANGLE_framebuffer_multisample
#define GL_ANGLE_framebuffer_multisample 1
#define GL_RENDERBUFFER_SAMPLES_ANGLE 0x8CAB

Просмотреть файл

@ -161,7 +161,8 @@ Extensions::Extensions()
bindUniformLocation(false),
syncQuery(false),
colorBufferFloat(false),
multisampleCompatibility(false)
multisampleCompatibility(false),
framebufferMixedSamples(false)
{
}
@ -170,72 +171,73 @@ std::vector<std::string> Extensions::getStrings() const
std::vector<std::string> extensionStrings;
// clang-format off
// | Extension name | Supported flag | Output vector |
InsertExtensionString("GL_OES_element_index_uint", elementIndexUint, &extensionStrings);
InsertExtensionString("GL_OES_packed_depth_stencil", packedDepthStencil, &extensionStrings);
InsertExtensionString("GL_OES_get_program_binary", getProgramBinary, &extensionStrings);
InsertExtensionString("GL_OES_rgb8_rgba8", rgb8rgba8, &extensionStrings);
InsertExtensionString("GL_EXT_texture_format_BGRA8888", textureFormatBGRA8888, &extensionStrings);
InsertExtensionString("GL_EXT_read_format_bgra", readFormatBGRA, &extensionStrings);
InsertExtensionString("GL_NV_pixel_buffer_object", pixelBufferObject, &extensionStrings);
InsertExtensionString("GL_OES_mapbuffer", mapBuffer, &extensionStrings);
InsertExtensionString("GL_EXT_map_buffer_range", mapBufferRange, &extensionStrings);
InsertExtensionString("GL_EXT_color_buffer_half_float", colorBufferHalfFloat, &extensionStrings);
InsertExtensionString("GL_OES_texture_half_float", textureHalfFloat, &extensionStrings);
InsertExtensionString("GL_OES_texture_half_float_linear", textureHalfFloatLinear, &extensionStrings);
InsertExtensionString("GL_OES_texture_float", textureFloat, &extensionStrings);
InsertExtensionString("GL_OES_texture_float_linear", textureFloatLinear, &extensionStrings);
InsertExtensionString("GL_EXT_texture_rg", textureRG, &extensionStrings);
InsertExtensionString("GL_EXT_texture_compression_dxt1", textureCompressionDXT1, &extensionStrings);
InsertExtensionString("GL_ANGLE_texture_compression_dxt3", textureCompressionDXT3, &extensionStrings);
InsertExtensionString("GL_ANGLE_texture_compression_dxt5", textureCompressionDXT5, &extensionStrings);
InsertExtensionString("GL_KHR_texture_compression_astc_hdr", textureCompressionASTCHDR, &extensionStrings);
InsertExtensionString("GL_KHR_texture_compression_astc_ldr", textureCompressionASTCLDR, &extensionStrings);
InsertExtensionString("GL_OES_compressed_ETC1_RGB8_texture", compressedETC1RGB8Texture, &extensionStrings);
InsertExtensionString("GL_EXT_sRGB", sRGB, &extensionStrings);
InsertExtensionString("GL_ANGLE_depth_texture", depthTextures, &extensionStrings);
InsertExtensionString("GL_OES_depth32", depth32, &extensionStrings);
InsertExtensionString("GL_EXT_texture_storage", textureStorage, &extensionStrings);
InsertExtensionString("GL_OES_texture_npot", textureNPOT, &extensionStrings);
InsertExtensionString("GL_EXT_draw_buffers", drawBuffers, &extensionStrings);
InsertExtensionString("GL_EXT_texture_filter_anisotropic", textureFilterAnisotropic, &extensionStrings);
InsertExtensionString("GL_EXT_occlusion_query_boolean", occlusionQueryBoolean, &extensionStrings);
InsertExtensionString("GL_NV_fence", fence, &extensionStrings);
InsertExtensionString("GL_ANGLE_timer_query", timerQuery, &extensionStrings);
InsertExtensionString("GL_EXT_disjoint_timer_query", disjointTimerQuery, &extensionStrings);
InsertExtensionString("GL_EXT_robustness", robustness, &extensionStrings);
InsertExtensionString("GL_EXT_blend_minmax", blendMinMax, &extensionStrings);
InsertExtensionString("GL_ANGLE_framebuffer_blit", framebufferBlit, &extensionStrings);
InsertExtensionString("GL_ANGLE_framebuffer_multisample", framebufferMultisample, &extensionStrings);
InsertExtensionString("GL_ANGLE_instanced_arrays", instancedArrays, &extensionStrings);
InsertExtensionString("GL_ANGLE_pack_reverse_row_order", packReverseRowOrder, &extensionStrings);
InsertExtensionString("GL_OES_standard_derivatives", standardDerivatives, &extensionStrings);
InsertExtensionString("GL_EXT_shader_texture_lod", shaderTextureLOD, &extensionStrings);
InsertExtensionString("GL_NV_shader_framebuffer_fetch", NVshaderFramebufferFetch, &extensionStrings);
InsertExtensionString("GL_ARM_shader_framebuffer_fetch", ARMshaderFramebufferFetch, &extensionStrings);
InsertExtensionString("GL_EXT_shader_framebuffer_fetch", shaderFramebufferFetch, &extensionStrings);
InsertExtensionString("GL_EXT_frag_depth", fragDepth, &extensionStrings);
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_debug_marker", debugMarker, &extensionStrings);
InsertExtensionString("GL_OES_EGL_image", eglImage, &extensionStrings);
InsertExtensionString("GL_OES_EGL_image_external", eglImageExternal, &extensionStrings);
InsertExtensionString("GL_OES_EGL_image_external_essl3", eglImageExternalEssl3, &extensionStrings);
InsertExtensionString("GL_NV_EGL_stream_consumer_external", eglStreamConsumerExternal, &extensionStrings);
InsertExtensionString("GL_EXT_unpack_subimage", unpackSubimage, &extensionStrings);
InsertExtensionString("GL_NV_pack_subimage", packSubimage, &extensionStrings);
InsertExtensionString("GL_EXT_color_buffer_float", colorBufferFloat, &extensionStrings);
InsertExtensionString("GL_OES_vertex_array_object", vertexArrayObject, &extensionStrings);
InsertExtensionString("GL_KHR_debug", debug, &extensionStrings);
// | Extension name | Supported flag | Output vector |
InsertExtensionString("GL_OES_element_index_uint", elementIndexUint, &extensionStrings);
InsertExtensionString("GL_OES_packed_depth_stencil", packedDepthStencil, &extensionStrings);
InsertExtensionString("GL_OES_get_program_binary", getProgramBinary, &extensionStrings);
InsertExtensionString("GL_OES_rgb8_rgba8", rgb8rgba8, &extensionStrings);
InsertExtensionString("GL_EXT_texture_format_BGRA8888", textureFormatBGRA8888, &extensionStrings);
InsertExtensionString("GL_EXT_read_format_bgra", readFormatBGRA, &extensionStrings);
InsertExtensionString("GL_NV_pixel_buffer_object", pixelBufferObject, &extensionStrings);
InsertExtensionString("GL_OES_mapbuffer", mapBuffer, &extensionStrings);
InsertExtensionString("GL_EXT_map_buffer_range", mapBufferRange, &extensionStrings);
InsertExtensionString("GL_EXT_color_buffer_half_float", colorBufferHalfFloat, &extensionStrings);
InsertExtensionString("GL_OES_texture_half_float", textureHalfFloat, &extensionStrings);
InsertExtensionString("GL_OES_texture_half_float_linear", textureHalfFloatLinear, &extensionStrings);
InsertExtensionString("GL_OES_texture_float", textureFloat, &extensionStrings);
InsertExtensionString("GL_OES_texture_float_linear", textureFloatLinear, &extensionStrings);
InsertExtensionString("GL_EXT_texture_rg", textureRG, &extensionStrings);
InsertExtensionString("GL_EXT_texture_compression_dxt1", textureCompressionDXT1, &extensionStrings);
InsertExtensionString("GL_ANGLE_texture_compression_dxt3", textureCompressionDXT3, &extensionStrings);
InsertExtensionString("GL_ANGLE_texture_compression_dxt5", textureCompressionDXT5, &extensionStrings);
InsertExtensionString("GL_KHR_texture_compression_astc_hdr", textureCompressionASTCHDR, &extensionStrings);
InsertExtensionString("GL_KHR_texture_compression_astc_ldr", textureCompressionASTCLDR, &extensionStrings);
InsertExtensionString("GL_OES_compressed_ETC1_RGB8_texture", compressedETC1RGB8Texture, &extensionStrings);
InsertExtensionString("GL_EXT_sRGB", sRGB, &extensionStrings);
InsertExtensionString("GL_ANGLE_depth_texture", depthTextures, &extensionStrings);
InsertExtensionString("GL_OES_depth32", depth32, &extensionStrings);
InsertExtensionString("GL_EXT_texture_storage", textureStorage, &extensionStrings);
InsertExtensionString("GL_OES_texture_npot", textureNPOT, &extensionStrings);
InsertExtensionString("GL_EXT_draw_buffers", drawBuffers, &extensionStrings);
InsertExtensionString("GL_EXT_texture_filter_anisotropic", textureFilterAnisotropic, &extensionStrings);
InsertExtensionString("GL_EXT_occlusion_query_boolean", occlusionQueryBoolean, &extensionStrings);
InsertExtensionString("GL_NV_fence", fence, &extensionStrings);
InsertExtensionString("GL_ANGLE_timer_query", timerQuery, &extensionStrings);
InsertExtensionString("GL_EXT_disjoint_timer_query", disjointTimerQuery, &extensionStrings);
InsertExtensionString("GL_EXT_robustness", robustness, &extensionStrings);
InsertExtensionString("GL_EXT_blend_minmax", blendMinMax, &extensionStrings);
InsertExtensionString("GL_ANGLE_framebuffer_blit", framebufferBlit, &extensionStrings);
InsertExtensionString("GL_ANGLE_framebuffer_multisample", framebufferMultisample, &extensionStrings);
InsertExtensionString("GL_ANGLE_instanced_arrays", instancedArrays, &extensionStrings);
InsertExtensionString("GL_ANGLE_pack_reverse_row_order", packReverseRowOrder, &extensionStrings);
InsertExtensionString("GL_OES_standard_derivatives", standardDerivatives, &extensionStrings);
InsertExtensionString("GL_EXT_shader_texture_lod", shaderTextureLOD, &extensionStrings);
InsertExtensionString("GL_NV_shader_framebuffer_fetch", NVshaderFramebufferFetch, &extensionStrings);
InsertExtensionString("GL_ARM_shader_framebuffer_fetch", ARMshaderFramebufferFetch, &extensionStrings);
InsertExtensionString("GL_EXT_shader_framebuffer_fetch", shaderFramebufferFetch, &extensionStrings);
InsertExtensionString("GL_EXT_frag_depth", fragDepth, &extensionStrings);
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_debug_marker", debugMarker, &extensionStrings);
InsertExtensionString("GL_OES_EGL_image", eglImage, &extensionStrings);
InsertExtensionString("GL_OES_EGL_image_external", eglImageExternal, &extensionStrings);
InsertExtensionString("GL_OES_EGL_image_external_essl3", eglImageExternalEssl3, &extensionStrings);
InsertExtensionString("GL_NV_EGL_stream_consumer_external", eglStreamConsumerExternal, &extensionStrings);
InsertExtensionString("GL_EXT_unpack_subimage", unpackSubimage, &extensionStrings);
InsertExtensionString("GL_NV_pack_subimage", packSubimage, &extensionStrings);
InsertExtensionString("GL_EXT_color_buffer_float", colorBufferFloat, &extensionStrings);
InsertExtensionString("GL_OES_vertex_array_object", vertexArrayObject, &extensionStrings);
InsertExtensionString("GL_KHR_debug", debug, &extensionStrings);
// TODO(jmadill): Enable this when complete.
//InsertExtensionString("GL_KHR_no_error", noError, &extensionStrings);
InsertExtensionString("GL_ANGLE_lossy_etc_decode", lossyETCDecode, &extensionStrings);
InsertExtensionString("GL_CHROMIUM_bind_uniform_location", bindUniformLocation, &extensionStrings);
InsertExtensionString("GL_CHROMIUM_sync_query", syncQuery, &extensionStrings);
InsertExtensionString("GL_EXT_multisample_compatibility", multisampleCompatibility, &extensionStrings);
InsertExtensionString("GL_ANGLE_lossy_etc_decode", lossyETCDecode, &extensionStrings);
InsertExtensionString("GL_CHROMIUM_bind_uniform_location", bindUniformLocation, &extensionStrings);
InsertExtensionString("GL_CHROMIUM_sync_query", syncQuery, &extensionStrings);
InsertExtensionString("GL_EXT_multisample_compatibility", multisampleCompatibility, &extensionStrings);
InsertExtensionString("GL_CHROMIUM_framebuffer_mixed_samples", framebufferMixedSamples, &extensionStrings);
// clang-format on
return extensionStrings;

Просмотреть файл

@ -295,6 +295,9 @@ struct Extensions
// GL_EXT_multisample_compatibility.
// written against ES 3.1 but can apply to earlier versions.
bool multisampleCompatibility;
// GL_CHROMIUM_framebuffer_mixed_samples
bool framebufferMixedSamples;
};
struct Limitations

Просмотреть файл

@ -1380,6 +1380,14 @@ bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *nu
*type = GL_INT;
*numParams = 1;
return true;
case GL_COVERAGE_MODULATION_CHROMIUM:
if (!mExtensions.framebufferMixedSamples)
{
return false;
}
*type = GL_INT;
*numParams = 1;
return true;
}
if (mExtensions.debug)
@ -1655,6 +1663,12 @@ void Context::bindUniformLocation(GLuint program, GLint location, const GLchar *
programObject->bindUniformLocation(location, name);
}
void Context::setCoverageModulation(GLenum components)
{
mState.setCoverageModulation(components);
}
void Context::handleError(const Error &error)
{
if (error.isError())

Просмотреть файл

@ -389,6 +389,9 @@ class Context final : public ValidationContext
void bindUniformLocation(GLuint program, GLint location, const GLchar *name);
// CHROMIUM_framebuffer_mixed_samples
void setCoverageModulation(GLenum components);
void handleError(const Error &error) override;
GLenum getError();

Просмотреть файл

@ -523,7 +523,17 @@ GLenum Framebuffer::checkStatus(const ContextState &data) const
}
else if (samples != depthAttachment.getSamples())
{
return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
// CHROMIUM_framebuffer_mixed_samples allows a framebuffer to be
// considered complete when its depth or stencil samples are a
// multiple of the number of color samples.
const bool mixedSamples = data.extensions->framebufferMixedSamples;
if (!mixedSamples)
return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
const int colorSamples = samples ? samples : 1;
const int depthSamples = depthAttachment.getSamples();
if ((depthSamples % colorSamples) != 0)
return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
}
}
@ -573,7 +583,15 @@ GLenum Framebuffer::checkStatus(const ContextState &data) const
}
else if (samples != stencilAttachment.getSamples())
{
return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
// see the comments in depth attachment check.
const bool mixedSamples = data.extensions->framebufferMixedSamples;
if (!mixedSamples)
return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
const int colorSamples = samples ? samples : 1;
const int stencilSamples = stencilAttachment.getSamples();
if ((stencilSamples % colorSamples) != 0)
return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
}
// Starting from ES 3.0 stencil and depth, if present, should be the same image

Просмотреть файл

@ -178,6 +178,8 @@ void State::initialize(const Caps &caps,
mMultiSampling = true;
mSampleAlphaToOne = false;
}
mCoverageModulation = GL_NONE;
}
void State::reset()
@ -1359,6 +1361,17 @@ Debug &State::getDebug()
return mDebug;
}
void State::setCoverageModulation(GLenum components)
{
mCoverageModulation = components;
mDirtyBits.set(DIRTY_BIT_COVERAGE_MODULATION);
}
GLenum State::getCoverageModulation() const
{
return mCoverageModulation;
}
void State::getBooleanv(GLenum pname, GLboolean *params)
{
switch (pname)
@ -1440,6 +1453,8 @@ void State::getFloatv(GLenum pname, GLfloat *params)
break;
case GL_SAMPLE_ALPHA_TO_ONE_EXT:
*params = static_cast<GLfloat>(mSampleAlphaToOne);
case GL_COVERAGE_MODULATION_CHROMIUM:
params[0] = mCoverageModulation;
break;
default:
UNREACHABLE();
@ -1684,6 +1699,8 @@ void State::getIntegerv(const ContextState &data, GLenum pname, GLint *params)
break;
case GL_SAMPLE_ALPHA_TO_ONE_EXT:
*params = static_cast<GLint>(mSampleAlphaToOne);
case GL_COVERAGE_MODULATION_CHROMIUM:
*params = static_cast<GLint>(mCoverageModulation);
break;
default:
UNREACHABLE();

Просмотреть файл

@ -274,6 +274,10 @@ class State : angle::NonCopyable
const Debug &getDebug() const;
Debug &getDebug();
// CHROMIUM_framebuffer_mixed_samples coverage modulation
void setCoverageModulation(GLenum components);
GLenum getCoverageModulation() const;
// State query functions
void getBooleanv(GLenum pname, GLboolean *params);
void getFloatv(GLenum pname, GLfloat *params);
@ -342,6 +346,7 @@ class State : angle::NonCopyable
DIRTY_BIT_PROGRAM_BINDING,
DIRTY_BIT_MULTISAMPLING,
DIRTY_BIT_SAMPLE_ALPHA_TO_ONE,
DIRTY_BIT_COVERAGE_MODULATION, // CHROMIUM_framebuffer_mixed_samples
DIRTY_BIT_CURRENT_VALUE_0,
DIRTY_BIT_CURRENT_VALUE_MAX = DIRTY_BIT_CURRENT_VALUE_0 + MAX_VERTEX_ATTRIBS,
DIRTY_BIT_INVALID = DIRTY_BIT_CURRENT_VALUE_MAX,
@ -447,6 +452,8 @@ class State : angle::NonCopyable
bool mMultiSampling;
bool mSampleAlphaToOne;
GLenum mCoverageModulation;
DirtyBits mDirtyBits;
DirtyObjects mDirtyObjects;
};

Просмотреть файл

@ -640,6 +640,7 @@ FunctionsGL::FunctionsGL()
vertexAttribIFormat(nullptr),
vertexAttribLFormat(nullptr),
vertexBindingDivisor(nullptr),
coverageModulationNV(nullptr),
bindBuffersBase(nullptr),
bindBuffersRange(nullptr),
@ -823,6 +824,9 @@ void FunctionsGL::initializeProcsDesktopGL()
// Even though extensions are written against specific versions of GL, many drivers expose the extensions
// in even older versions. Always try loading the extensions regardless of GL version.
// GL_NV_framebuffer_mixed_samples
AssignGLExtensionEntryPoint(extensions, "GL_NV_framebuffer_mixed_samples", loadProcAddress("glCoverageModulationNV"), &coverageModulationNV);
// GL_NV_fence
AssignGLExtensionEntryPoint(extensions, "GL_NV_fence", loadProcAddress("glDeleteFencesNV"), &deleteFencesNV);
AssignGLExtensionEntryPoint(extensions, "GL_NV_fence", loadProcAddress("glGenFencesNV"), &genFencesNV);
@ -1724,6 +1728,9 @@ void FunctionsGL::initializeProcsGLES()
AssignGLExtensionEntryPoint(extensions, "GL_OES_texture_3D", loadProcAddress("glTexSubImage3DOES"), &texSubImage3D);
AssignGLExtensionEntryPoint(extensions, "GL_OES_texture_3D", loadProcAddress("glCopyTexSubImage3DOES"), &copyTexSubImage3D);
// GL_NV_framebuffer_mixed_samples
AssignGLExtensionEntryPoint(extensions, "GL_NV_framebuffer_mixed_samples", loadProcAddress("glCoverageModulationNV"), &coverageModulationNV);
// GL_NV_fence
AssignGLExtensionEntryPoint(extensions, "GL_NV_fence", loadProcAddress("glDeleteFencesNV"), &deleteFencesNV);
AssignGLExtensionEntryPoint(extensions, "GL_NV_fence", loadProcAddress("glGenFencesNV"), &genFencesNV);

Просмотреть файл

@ -619,6 +619,7 @@ class FunctionsGL
PFNGLVERTEXATTRIBIFORMATPROC vertexAttribIFormat;
PFNGLVERTEXATTRIBLFORMATPROC vertexAttribLFormat;
PFNGLVERTEXBINDINGDIVISORPROC vertexBindingDivisor;
PFNGLCOVERAGEMODULATIONNVPROC coverageModulationNV;
// 4.4
PFNGLBINDBUFFERSBASEPROC bindBuffersBase;

Просмотреть файл

@ -115,6 +115,7 @@ StateManagerGL::StateManagerGL(const FunctionsGL *functions, const gl::Caps &ren
mTextureCubemapSeamlessEnabled(false),
mMultisamplingEnabled(true),
mSampleAlphaToOneEnabled(false),
mCoverageModulation(GL_NONE),
mLocalDirtyBits()
{
ASSERT(mFunctions);
@ -1520,6 +1521,8 @@ void StateManagerGL::syncState(const gl::State &state, const gl::State::DirtyBit
break;
case gl::State::DIRTY_BIT_SAMPLE_ALPHA_TO_ONE:
setSampleAlphaToOneStateEnabled(state.isSampleAlphaToOneEnabled());
case gl::State::DIRTY_BIT_COVERAGE_MODULATION:
setCoverageModulation(state.getCoverageModulation());
break;
default:
{
@ -1587,6 +1590,17 @@ void StateManagerGL::setSampleAlphaToOneStateEnabled(bool enabled)
}
}
void StateManagerGL::setCoverageModulation(GLenum components)
{
if (mCoverageModulation != components)
{
mCoverageModulation = components;
mFunctions->coverageModulationNV(components);
mLocalDirtyBits.set(gl::State::DIRTY_BIT_COVERAGE_MODULATION);
}
}
void StateManagerGL::setTextureCubemapSeamlessEnabled(bool enabled)
{
if (mTextureCubemapSeamlessEnabled != enabled)

Просмотреть файл

@ -127,6 +127,8 @@ class StateManagerGL final : angle::NonCopyable
void setMultisamplingStateEnabled(bool enabled);
void setSampleAlphaToOneStateEnabled(bool enabled);
void setCoverageModulation(GLenum components);
void onDeleteQueryObject(QueryGL *query);
gl::Error setDrawArraysState(const gl::ContextState &data,
@ -260,6 +262,8 @@ class StateManagerGL final : angle::NonCopyable
bool mMultisamplingEnabled;
bool mSampleAlphaToOneEnabled;
GLenum mCoverageModulation;
gl::State::DirtyBits mLocalDirtyBits;
};

Просмотреть файл

@ -627,6 +627,9 @@ typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBIFORMATPROC)(GLuint, GLint,
typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBLFORMATPROC)(GLuint, GLint, GLenum, GLuint);
typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXBINDINGDIVISORPROC)(GLuint, GLuint);
// NV_framebuffer_mixed_samples
typedef void (INTERNAL_GL_APIENTRY *PFNGLCOVERAGEMODULATIONNVPROC)(GLenum);
// 4.4
typedef void (INTERNAL_GL_APIENTRY *PFNGLBINDBUFFERSBASEPROC)(GLenum, GLuint, GLsizei, const GLuint *);
typedef void (INTERNAL_GL_APIENTRY *PFNGLBINDBUFFERSRANGEPROC)(GLenum, GLuint, GLsizei, const GLuint *, const GLintptr *, const GLsizeiptr *);

Просмотреть файл

@ -663,6 +663,9 @@ void GenerateCaps(const FunctionsGL *functions, gl::Caps *caps, gl::TextureCapsM
extensions->multisampleCompatibility = functions->isAtLeastGL(gl::Version(1, 3)) ||
functions->hasGLESExtension("GL_EXT_multisample_compatibility");
extensions->framebufferMixedSamples = functions->hasGLExtension("GL_NV_framebuffer_mixed_samples") ||
functions->hasGLESExtension("GL_NV_framebuffer_mixed_samples");
// ANGLE emulates vertex array objects in its GL layer
extensions->vertexArrayObject = true;

Просмотреть файл

@ -2056,4 +2056,28 @@ bool ValidateBindUniformLocationCHROMIUM(Context *context,
return true;
}
bool ValidateCoverageModulationCHROMIUM(Context* context, GLenum components)
{
if (!context->getExtensions().framebufferMixedSamples)
{
context->handleError(
Error(GL_INVALID_OPERATION, "GL_CHROMIUM_framebuffer_mixed_samples is not available."));
return false;
}
switch (components)
{
case GL_RGB:
case GL_RGBA:
case GL_ALPHA:
case GL_NONE:
break;
default:
context->handleError(
Error(GL_INVALID_ENUM, "GLenum components is not one of GL_RGB, GL_RGBA, GL_ALPHA or GL_NONE."));
return false;
}
return true;
}
} // namespace gl

Просмотреть файл

@ -188,6 +188,8 @@ bool ValidateBindUniformLocationCHROMIUM(Context *context,
GLint location,
const GLchar *name);
bool ValidateCoverageModulationCHROMIUM(Context* context, GLenum components);
} // namespace gl
#endif // LIBANGLE_VALIDATION_ES2_H_

Просмотреть файл

@ -1388,4 +1388,20 @@ ANGLE_EXPORT void GL_APIENTRY BindUniformLocationCHROMIUM(GLuint program,
context->bindUniformLocation(program, location, name);
}
}
ANGLE_EXPORT void GL_APIENTRY CoverageModulationCHROMIUM(GLenum components)
{
EVENT("(GLenum components = %u)", components);
Context* context = GetValidGlobalContext();
if (context)
{
if (!ValidateCoverageModulationCHROMIUM(context, components))
{
return;
}
context->setCoverageModulation(components);
}
}
}

Просмотреть файл

@ -145,6 +145,9 @@ ANGLE_EXPORT void GL_APIENTRY GetPointervKHR(GLenum pname, void **params);
ANGLE_EXPORT void GL_APIENTRY BindUniformLocationCHROMIUM(GLuint program,
GLint location,
const GLchar *name);
// GL_CHROMIUM_framebuffer_mixed_samples
ANGLE_EXPORT void GL_APIENTRY CoverageModulationCHROMIUM(GLenum components);
}
#endif // LIBGLESV2_ENTRYPOINTGLES20EXT_H_

Просмотреть файл

@ -1567,4 +1567,10 @@ void GL_APIENTRY glBindUniformLocationCHROMIUM(GLuint program, GLint location, c
{
return gl::BindUniformLocationCHROMIUM(program, location, name);
}
void GL_APIENTRY glCoverageModulationCHROMIUM(GLenum components)
{
return gl::CoverageModulationCHROMIUM(components);
}
}

Просмотреть файл

@ -203,6 +203,7 @@ EXPORTS
glGetQueryObjecti64vEXT @316
glGetQueryObjectui64vEXT @317
glBindUniformLocationCHROMIUM @318
glCoverageModulationCHROMIUM @319
; GLES 3.0 Functions
glReadBuffer @180

Просмотреть файл

@ -16,6 +16,7 @@
'angle_end2end_tests_sources':
[
'<(angle_path)/src/tests/gl_tests/MultisampleCompatibilityTest.cpp',
'<(angle_path)/src/tests/gl_tests/FramebufferMixedSamplesTest.cpp',
'<(angle_path)/src/tests/gl_tests/BindUniformLocationTest.cpp',
'<(angle_path)/src/tests/gl_tests/BlendMinMaxTest.cpp',
'<(angle_path)/src/tests/gl_tests/BlitFramebufferANGLETest.cpp',

Просмотреть файл

@ -0,0 +1,292 @@
//
// Copyright 2016 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.
//
// CHROMIUMFramebufferMixedSamplesTest
// Test CHROMIUM subset of NV_framebuffer_mixed_samples.
// This extension allows rendering to a framebuffer that has different
// sample counts for different render buffers (stencil, depth, color)
#include "test_utils/ANGLETest.h"
#include "shader_utils.h"
using namespace angle;
namespace
{
const GLuint kWidth = 100;
const GLuint kHeight = 100;
class CHROMIUMFramebufferMixedSamplesTest : public ANGLETest
{
protected:
enum SetupFBOType
{
MixedSampleFBO, // 1 color sample, N stencil samples.
SingleSampleFBO, // 1 color sample, 1 stencil sample.
};
bool isApplicable() const
{
return extensionEnabled("GL_CHROMIUM_framebuffer_mixed_samples") &&
extensionEnabled("GL_OES_rgb8_rgba8");
}
void SetUp() override
{
ANGLETest::SetUp();
// clang-format off
static const char* kVertexShaderSource =
"attribute mediump vec4 position;\n"
"void main() {\n"
" gl_Position = position;\n"
"}\n";
static const char* kFragmentShaderSource =
"uniform mediump vec4 color;\n"
"void main() {\n"
" gl_FragColor = color;\n"
"}\n";
// clang-format on
mProgram = CompileProgram(kVertexShaderSource, kFragmentShaderSource);
GLuint position_loc = glGetAttribLocation(mProgram, "position");
mColorLoc = glGetUniformLocation(mProgram, "color");
glGenBuffers(1, &mVBO);
glBindBuffer(GL_ARRAY_BUFFER, mVBO);
static float vertices[] = {
1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f,
-1.0f, 1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f,
};
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(position_loc);
glVertexAttribPointer(position_loc, 2, GL_FLOAT, GL_FALSE, 0, 0);
ASSERT_GL_NO_ERROR();
}
void TearDown() override
{
glDeleteBuffers(1, &mVBO);
glDeleteProgram(mProgram);
ASSERT_GL_NO_ERROR();
ANGLETest::TearDown();
}
void prepareForDraw(SetupFBOType fbo_type)
{
glActiveTexture(GL_TEXTURE0);
glGenTextures(1, &mTexture);
glBindTexture(GL_TEXTURE_2D, mTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kWidth, kHeight, 0, GL_RGBA,
GL_UNSIGNED_BYTE, NULL);
glBindTexture(GL_TEXTURE_2D, 0);
glGenRenderbuffers(1, &mStencilRB);
glBindRenderbuffer(GL_RENDERBUFFER, mStencilRB);
if (fbo_type == MixedSampleFBO)
{
// Create a sample buffer.
GLsizei num_samples = 8, max_samples = 0;
glGetIntegerv(GL_MAX_SAMPLES, &max_samples);
num_samples = std::min(num_samples, max_samples);
glRenderbufferStorageMultisampleANGLE(
GL_RENDERBUFFER, num_samples, GL_STENCIL_INDEX8, kWidth, kHeight);
GLint param = 0;
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_SAMPLES,
&param);
EXPECT_GT(param, 1);
}
else
{
glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, kWidth, kHeight);
}
glBindRenderbuffer(GL_RENDERBUFFER, 0);
glGenFramebuffers(1, &mSampleFBO);
glBindFramebuffer(GL_FRAMEBUFFER, mSampleFBO);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTexture, 0);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
GL_RENDERBUFFER, mStencilRB);
EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE),
glCheckFramebufferStatus(GL_FRAMEBUFFER));
glUseProgram(mProgram);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glViewport(0, 0, kWidth, kHeight);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClearStencil(1);
glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glEnable(GL_STENCIL_TEST);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glStencilMask(0xffffffff);
glStencilFunc(GL_EQUAL, 1, 0xffffffff);
glStencilOp(GL_KEEP, GL_KEEP, GL_ZERO);
ASSERT_GL_NO_ERROR();
}
void cleanup()
{
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glDeleteFramebuffers(1, &mSampleFBO);
glDeleteTextures(1, &mTexture);
glDeleteRenderbuffers(1, &mStencilRB);
ASSERT_GL_NO_ERROR();
}
GLuint mSampleFBO;
GLuint mStencilRB;
GLuint mTexture;
GLuint mProgram;
GLuint mVBO;
GLint mColorLoc;
};
} //
TEST_P(CHROMIUMFramebufferMixedSamplesTest, StateSettingTest)
{
if (!isApplicable())
{
return;
}
GLint value = -1;
glGetIntegerv(GL_COVERAGE_MODULATION_CHROMIUM, &value);
EXPECT_EQ(GL_NONE, value);
GLenum kValues[] = {GL_NONE, GL_RGB, GL_RGBA, GL_ALPHA};
for (auto expect : kValues)
{
glCoverageModulationCHROMIUM(expect);
value = -1;
glGetIntegerv(GL_COVERAGE_MODULATION_CHROMIUM, &value);
EXPECT_EQ(expect, static_cast<GLenum>(value));
EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
}
glCoverageModulationCHROMIUM(GL_BYTE);
EXPECT_EQ(static_cast<GLenum>(GL_INVALID_ENUM), glGetError());
value = -1;
glGetIntegerv(GL_COVERAGE_MODULATION_CHROMIUM, &value);
EXPECT_EQ(static_cast<GLenum>(GL_ALPHA), static_cast<GLenum>(value));
EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
}
// The test pattern is as follows:
// A green triangle (bottom left, top right, top left).
// A blue triangle (top left, bottom right, bottom left).
// The triangles will overlap but overlap only contains green pixels,
// due to each draw erasing its area from stencil.
// The blue triangle will fill only the area (bottom left, center,
// bottom right).
// The test tests that CoverageModulation call works.
// The fractional pixels of both triangles end up being modulated
// by the coverage of the fragment. Test that drawing with and without
// CoverageModulation causes the result to be different.
TEST_P(CHROMIUMFramebufferMixedSamplesTest, CoverageModulation)
{
if (!isApplicable())
{
return;
}
static const float kBlue[] = {0.0f, 0.0f, 1.0f, 1.0f};
static const float kGreen[] = {0.0f, 1.0f, 0.0f, 1.0f};
std::unique_ptr<uint8_t[]> results[3];
const GLint kResultSize = kWidth * kHeight * 4;
for (int pass = 0; pass < 3; ++pass)
{
prepareForDraw(MixedSampleFBO);
if (pass == 1)
{
glCoverageModulationCHROMIUM(GL_RGBA);
}
glUniform4fv(mColorLoc, 1, kGreen);
glDrawArrays(GL_TRIANGLES, 0, 3);
glUniform4fv(mColorLoc, 1, kBlue);
glDrawArrays(GL_TRIANGLES, 3, 3);
if (pass == 1)
{
glCoverageModulationCHROMIUM(GL_NONE);
}
results[pass].reset(new uint8_t[kResultSize]);
memset(results[pass].get(), 123u, kResultSize);
glReadPixels(0, 0, kWidth, kHeight, GL_RGBA, GL_UNSIGNED_BYTE,
results[pass].get());
cleanup();
}
EXPECT_NE(0, memcmp(results[0].get(), results[1].get(), kResultSize));
// Verify that rendering is deterministic, so that the pass above does not
// come from non-deterministic rendering.
EXPECT_EQ(0, memcmp(results[0].get(), results[2].get(), kResultSize));
}
// The test tests that the stencil buffer can be multisampled, even though the
// color buffer is single-sampled. Draws the same pattern with single-sample
// stencil buffer and with multisample stencil buffer. The images should differ.
TEST_P(CHROMIUMFramebufferMixedSamplesTest, MultisampleStencilEffective)
{
if (!isApplicable())
{
return;
}
static const float kBlue[] = {0.0f, 0.0f, 1.0f, 1.0f};
static const float kGreen[] = {0.0f, 1.0f, 0.0f, 1.0f};
std::unique_ptr<uint8_t[]> results[3];
const GLint kResultSize = kWidth * kHeight * 4;
for (int pass = 0; pass < 3; ++pass)
{
if (pass == 1)
{
prepareForDraw(MixedSampleFBO);
}
else
{
prepareForDraw(SingleSampleFBO);
}
glUniform4fv(mColorLoc, 1, kGreen);
glDrawArrays(GL_TRIANGLES, 0, 3);
glUniform4fv(mColorLoc, 1, kBlue);
glDrawArrays(GL_TRIANGLES, 3, 3);
results[pass].reset(new uint8_t[kResultSize]);
memset(results[pass].get(), 12u, kResultSize);
glReadPixels(0, 0, kWidth, kHeight, GL_RGBA, GL_UNSIGNED_BYTE,
results[pass].get());
cleanup();
}
EXPECT_NE(0, memcmp(results[0].get(), results[1].get(), kResultSize));
// Verify that rendering is deterministic, so that the pass above does not
// come from non-deterministic rendering.
EXPECT_EQ(0, memcmp(results[0].get(), results[2].get(), kResultSize));
}
ANGLE_INSTANTIATE_TEST(CHROMIUMFramebufferMixedSamplesTest, ES2_OPENGL(), ES2_OPENGLES(), ES3_OPENGL());