зеркало из https://github.com/AvaloniaUI/angle.git
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:
Родитель
776a75b45c
Коммит
a797e066c1
|
@ -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"), ©TexSubImage3D);
|
||||
|
||||
// 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,
|
||||
¶m);
|
||||
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());
|
Загрузка…
Ссылка в новой задаче