diff options
author | gman@chromium.org <gman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-06-08 00:04:00 +0000 |
---|---|---|
committer | gman@chromium.org <gman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-06-08 00:04:00 +0000 |
commit | 81375743a18758e2d3e1401086c41fc6102d7404 (patch) | |
tree | 8934b84e05e419c1857139a547507c5704808c46 | |
parent | c1b2efa44d46f948b3820f02e169bd95db094625 (diff) | |
download | chromium_src-81375743a18758e2d3e1401086c41fc6102d7404.zip chromium_src-81375743a18758e2d3e1401086c41fc6102d7404.tar.gz chromium_src-81375743a18758e2d3e1401086c41fc6102d7404.tar.bz2 |
Plum through ANGLE_depth_texture
TEST=unit tests
BUG=none
Review URL: https://chromiumcodereview.appspot.com/10441087
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@141117 0039d316-1c4b-4281-b951-d872f2087c98
21 files changed, 951 insertions, 27 deletions
diff --git a/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_depth_texture.txt b/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_depth_texture.txt new file mode 100644 index 0000000..b7cc380 --- /dev/null +++ b/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_depth_texture.txt @@ -0,0 +1,38 @@ +Name + + CHROMIUM_depth_texture + +Name Strings + + GL_CHROMIUM_depth_texture + +Status + + DRAFT. + +Version + + Last Modifed Date: June 4, 2012 + Revision: #1 + +Number + + TBD + +Dependencies + + OpenGL ES 2.0 is required. + This extension is written against the OpenGL ES 2.0.25 specification + + ANGLE_depth_texture. + +Overview + + This extension is the same as ANGLE_depth_texture except it does + not add support for TexStorageEXT. + +New Procedures and Functions + + None + + diff --git a/gpu/command_buffer/build_gles2_cmd_buffer.py b/gpu/command_buffer/build_gles2_cmd_buffer.py index ccdbc4e..3a8a46c 100755 --- a/gpu/command_buffer/build_gles2_cmd_buffer.py +++ b/gpu/command_buffer/build_gles2_cmd_buffer.py @@ -629,6 +629,19 @@ _ENUM_LISTS = { 'GL_INT', ], }, + 'ReadPixelType': { + 'type': 'GLenum', + 'valid': [ + 'GL_UNSIGNED_BYTE', + 'GL_UNSIGNED_SHORT_5_6_5', + 'GL_UNSIGNED_SHORT_4_4_4_4', + 'GL_UNSIGNED_SHORT_5_5_5_1', + ], + 'invalid': [ + 'GL_SHORT', + 'GL_INT', + ], + }, 'RenderBufferFormat': { 'type': 'GLenum', 'valid': [ @@ -1335,7 +1348,7 @@ _FUNCTION_INFO = { 'client_test': False, 'cmd_args': 'GLint x, GLint y, GLsizei width, GLsizei height, ' - 'GLenumReadPixelFormat format, GLenumPixelType type, ' + 'GLenumReadPixelFormat format, GLenumReadPixelType type, ' 'uint32 pixels_shm_id, uint32 pixels_shm_offset, ' 'uint32 result_shm_id, uint32 result_shm_offset', 'result': ['uint32'], diff --git a/gpu/command_buffer/common/gles2_cmd_utils.cc b/gpu/command_buffer/common/gles2_cmd_utils.cc index 736e673..9c10bb4 100644 --- a/gpu/command_buffer/common/gles2_cmd_utils.cc +++ b/gpu/command_buffer/common/gles2_cmd_utils.cc @@ -346,6 +346,10 @@ int ElementsPerGroup(int format, int type) { case GL_ALPHA: case GL_LUMINANCE: case GL_DEPTH_COMPONENT: + case GL_DEPTH_COMPONENT24_OES: + case GL_DEPTH_COMPONENT32_OES: + case GL_DEPTH_COMPONENT16: + case GL_DEPTH24_STENCIL8_OES: case GL_DEPTH_STENCIL_OES: return 1; default: @@ -598,6 +602,8 @@ uint32 GLES2Util::GetChannelsForFormat(int format) { case GL_RGBA4: case GL_RGB5_A1: return kRGBA; + case GL_DEPTH_COMPONENT32_OES: + case GL_DEPTH_COMPONENT24_OES: case GL_DEPTH_COMPONENT16: case GL_DEPTH_COMPONENT: return kDepth; diff --git a/gpu/command_buffer/common/gles2_cmd_utils_autogen.h b/gpu/command_buffer/common/gles2_cmd_utils_autogen.h index 7a30e0c..bc004e8 100644 --- a/gpu/command_buffer/common/gles2_cmd_utils_autogen.h +++ b/gpu/command_buffer/common/gles2_cmd_utils_autogen.h @@ -37,6 +37,7 @@ static std::string GetStringQueryObjectParameter(uint32 value); static std::string GetStringQueryParameter(uint32 value); static std::string GetStringQueryTarget(uint32 value); static std::string GetStringReadPixelFormat(uint32 value); +static std::string GetStringReadPixelType(uint32 value); static std::string GetStringRenderBufferFormat(uint32 value); static std::string GetStringRenderBufferParameter(uint32 value); static std::string GetStringRenderBufferTarget(uint32 value); diff --git a/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h b/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h index dc2012d..b1f44ad 100644 --- a/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h +++ b/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h @@ -963,6 +963,17 @@ std::string GLES2Util::GetStringReadPixelFormat(uint32 value) { string_table, arraysize(string_table), value); } +std::string GLES2Util::GetStringReadPixelType(uint32 value) { + static EnumToString string_table[] = { + { GL_UNSIGNED_BYTE, "GL_UNSIGNED_BYTE" }, + { GL_UNSIGNED_SHORT_5_6_5, "GL_UNSIGNED_SHORT_5_6_5" }, + { GL_UNSIGNED_SHORT_4_4_4_4, "GL_UNSIGNED_SHORT_4_4_4_4" }, + { GL_UNSIGNED_SHORT_5_5_5_1, "GL_UNSIGNED_SHORT_5_5_5_1" }, + }; + return GLES2Util::GetQualifiedEnumString( + string_table, arraysize(string_table), value); +} + std::string GLES2Util::GetStringRenderBufferFormat(uint32 value) { static EnumToString string_table[] = { { GL_RGBA4, "GL_RGBA4" }, diff --git a/gpu/command_buffer/service/feature_info.cc b/gpu/command_buffer/service/feature_info.cc index 9e9cb6e..bbb0997 100644 --- a/gpu/command_buffer/service/feature_info.cc +++ b/gpu/command_buffer/service/feature_info.cc @@ -18,7 +18,50 @@ namespace gpu { namespace gles2 { +namespace { + +struct FormatInfo { + GLenum format; + const GLenum* types; + size_t count; +}; + +} // anonymous namespace. + FeatureInfo::FeatureInfo() { + static const GLenum kAlphaTypes[] = { + GL_UNSIGNED_BYTE, + }; + static const GLenum kRGBTypes[] = { + GL_UNSIGNED_BYTE, + GL_UNSIGNED_SHORT_5_6_5, + }; + static const GLenum kRGBATypes[] = { + GL_UNSIGNED_BYTE, + GL_UNSIGNED_SHORT_4_4_4_4, + GL_UNSIGNED_SHORT_5_5_5_1, + }; + static const GLenum kLuminanceTypes[] = { + GL_UNSIGNED_BYTE, + }; + static const GLenum kLuminanceAlphaTypes[] = { + GL_UNSIGNED_BYTE, + }; + static const FormatInfo kFormatTypes[] = { + { GL_ALPHA, kAlphaTypes, arraysize(kAlphaTypes), }, + { GL_RGB, kRGBTypes, arraysize(kRGBTypes), }, + { GL_RGBA, kRGBATypes, arraysize(kRGBATypes), }, + { GL_LUMINANCE, kLuminanceTypes, arraysize(kLuminanceTypes), }, + { GL_LUMINANCE_ALPHA, kLuminanceAlphaTypes, + arraysize(kLuminanceAlphaTypes), } , + }; + for (size_t ii = 0; ii < arraysize(kFormatTypes); ++ii) { + const FormatInfo& info = kFormatTypes[ii]; + ValueValidator<GLenum>& validator = texture_format_validators_[info.format]; + for (size_t jj = 0; jj < info.count; ++jj) { + validator.AddValue(info.types[jj]); + } + } } // Helps query for extensions. @@ -212,29 +255,44 @@ void FeatureInfo::AddFeatures(const char* desired_features) { } // Check if we should support GL_OES_packed_depth_stencil and/or - // GL_GOOGLE_depth_texture. - // NOTE: GL_OES_depth_texture requires support for depth - // cubemaps. GL_ARB_depth_texture requires other features that - // GL_OES_packed_depth_stencil does not provide. Therefore we made up - // GL_GOOGLE_depth_texture. + // GL_GOOGLE_depth_texture / GL_CHROMIUM_depth_texture. + // + // NOTE: GL_OES_depth_texture requires support for depth cubemaps. + // GL_ARB_depth_texture requires other features that + // GL_OES_packed_depth_stencil does not provide. + // + // Therefore we made up GL_GOOGLE_depth_texture / GL_CHROMIUM_depth_texture. + // + // GL_GOOGLE_depth_texture is legacy. As we exposed it into NaCl we can't + // get rid of it. + // bool enable_depth_texture = false; - if (ext.Desire("GL_GOOGLE_depth_texture") && + if ((ext.Desire("GL_GOOGLE_depth_texture") || + ext.Desire("GL_CHROMIUM_depth_texture")) && (ext.Have("GL_ARB_depth_texture") || - ext.Have("GL_OES_depth_texture"))) { + ext.Have("GL_OES_depth_texture") || + ext.Have("GL_ANGLE_depth_texture"))) { enable_depth_texture = true; + } + + if (enable_depth_texture) { + AddExtensionString("GL_CHROMIUM_depth_texture"); AddExtensionString("GL_GOOGLE_depth_texture"); + texture_format_validators_[GL_DEPTH_COMPONENT].AddValue(GL_UNSIGNED_SHORT); + texture_format_validators_[GL_DEPTH_COMPONENT].AddValue(GL_UNSIGNED_INT); validators_.texture_internal_format.AddValue(GL_DEPTH_COMPONENT); validators_.texture_format.AddValue(GL_DEPTH_COMPONENT); validators_.pixel_type.AddValue(GL_UNSIGNED_SHORT); validators_.pixel_type.AddValue(GL_UNSIGNED_INT); } - // TODO(gman): Add depth types fo ElementsPerGroup and BytesPerElement if (ext.Desire("GL_OES_packed_depth_stencil") && (ext.Have("GL_EXT_packed_depth_stencil") || ext.Have("GL_OES_packed_depth_stencil"))) { AddExtensionString("GL_OES_packed_depth_stencil"); if (enable_depth_texture) { + texture_format_validators_[GL_DEPTH_STENCIL].AddValue( + GL_UNSIGNED_INT_24_8); validators_.texture_internal_format.AddValue(GL_DEPTH_STENCIL); validators_.texture_format.AddValue(GL_DEPTH_STENCIL); validators_.pixel_type.AddValue(GL_UNSIGNED_INT_24_8); @@ -265,6 +323,7 @@ void FeatureInfo::AddFeatures(const char* desired_features) { if (enable_texture_format_bgra8888) { AddExtensionString("GL_EXT_texture_format_BGRA8888"); + texture_format_validators_[GL_BGRA_EXT].AddValue(GL_UNSIGNED_BYTE); validators_.texture_internal_format.AddValue(GL_BGRA_EXT); validators_.texture_format.AddValue(GL_BGRA_EXT); } @@ -328,7 +387,13 @@ void FeatureInfo::AddFeatures(const char* desired_features) { } if (enable_texture_float) { + texture_format_validators_[GL_ALPHA].AddValue(GL_FLOAT); + texture_format_validators_[GL_RGB].AddValue(GL_FLOAT); + texture_format_validators_[GL_RGBA].AddValue(GL_FLOAT); + texture_format_validators_[GL_LUMINANCE].AddValue(GL_FLOAT); + texture_format_validators_[GL_LUMINANCE_ALPHA].AddValue(GL_FLOAT); validators_.pixel_type.AddValue(GL_FLOAT); + validators_.read_pixel_type.AddValue(GL_FLOAT); AddExtensionString("GL_OES_texture_float"); if (enable_texture_float_linear) { AddExtensionString("GL_OES_texture_float_linear"); @@ -336,7 +401,13 @@ void FeatureInfo::AddFeatures(const char* desired_features) { } if (enable_texture_half_float) { + texture_format_validators_[GL_ALPHA].AddValue(GL_HALF_FLOAT_OES); + texture_format_validators_[GL_RGB].AddValue(GL_HALF_FLOAT_OES); + texture_format_validators_[GL_RGBA].AddValue(GL_HALF_FLOAT_OES); + texture_format_validators_[GL_LUMINANCE].AddValue(GL_HALF_FLOAT_OES); + texture_format_validators_[GL_LUMINANCE_ALPHA].AddValue(GL_HALF_FLOAT_OES); validators_.pixel_type.AddValue(GL_HALF_FLOAT_OES); + validators_.read_pixel_type.AddValue(GL_HALF_FLOAT_OES); AddExtensionString("GL_OES_texture_half_float"); if (enable_texture_half_float_linear) { AddExtensionString("GL_OES_texture_half_float_linear"); diff --git a/gpu/command_buffer/service/feature_info.h b/gpu/command_buffer/service/feature_info.h index b626441..4489ef3 100644 --- a/gpu/command_buffer/service/feature_info.h +++ b/gpu/command_buffer/service/feature_info.h @@ -6,6 +6,7 @@ #define GPU_COMMAND_BUFFER_SERVICE_FEATURE_INFO_H_ #include <string> +#include "base/hash_tables.h" #include "base/memory/ref_counted.h" #include "gpu/command_buffer/service/gles2_cmd_decoder.h" #include "gpu/command_buffer/service/gles2_cmd_validation.h" @@ -77,6 +78,10 @@ class GPU_EXPORT FeatureInfo : public base::RefCounted<FeatureInfo> { return &validators_; } + const ValueValidator<GLenum>& GetTextureFormatValidator(GLenum format) { + return texture_format_validators_[format]; + } + const std::string& extensions() const { return extensions_; } @@ -87,6 +92,10 @@ class GPU_EXPORT FeatureInfo : public base::RefCounted<FeatureInfo> { private: friend class base::RefCounted<FeatureInfo>; + + typedef base::hash_map<GLenum, ValueValidator<GLenum> > ValidatorMap; + ValidatorMap texture_format_validators_; + ~FeatureInfo(); void AddExtensionString(const std::string& str); diff --git a/gpu/command_buffer/service/feature_info_unittest.cc b/gpu/command_buffer/service/feature_info_unittest.cc index 14ed0fe..2724a12 100644 --- a/gpu/command_buffer/service/feature_info_unittest.cc +++ b/gpu/command_buffer/service/feature_info_unittest.cc @@ -59,6 +59,16 @@ class FeatureInfoTest : public testing::Test { FeatureInfo::Ref info_; }; +namespace { + +struct FormatInfo { + GLenum format; + const GLenum* types; + size_t count; +}; + +} // anonymous namespace. + TEST_F(FeatureInfoTest, Basic) { // Test it starts off uninitialized. EXPECT_FALSE(info_->feature_flags().chromium_framebuffer_multisample); @@ -81,6 +91,97 @@ TEST_F(FeatureInfoTest, Basic) { EXPECT_FALSE(info_->feature_flags().is_intel); EXPECT_FALSE(info_->feature_flags().is_nvidia); EXPECT_FALSE(info_->feature_flags().is_amd); + + // Test good types. + { + static const GLenum kAlphaTypes[] = { + GL_UNSIGNED_BYTE, + }; + static const GLenum kRGBTypes[] = { + GL_UNSIGNED_BYTE, + GL_UNSIGNED_SHORT_5_6_5, + }; + static const GLenum kRGBATypes[] = { + GL_UNSIGNED_BYTE, + GL_UNSIGNED_SHORT_4_4_4_4, + GL_UNSIGNED_SHORT_5_5_5_1, + }; + static const GLenum kLuminanceTypes[] = { + GL_UNSIGNED_BYTE, + }; + static const GLenum kLuminanceAlphaTypes[] = { + GL_UNSIGNED_BYTE, + }; + static const FormatInfo kFormatTypes[] = { + { GL_ALPHA, kAlphaTypes, arraysize(kAlphaTypes), }, + { GL_RGB, kRGBTypes, arraysize(kRGBTypes), }, + { GL_RGBA, kRGBATypes, arraysize(kRGBATypes), }, + { GL_LUMINANCE, kLuminanceTypes, arraysize(kLuminanceTypes), }, + { GL_LUMINANCE_ALPHA, kLuminanceAlphaTypes, + arraysize(kLuminanceAlphaTypes), } , + }; + for (size_t ii = 0; ii < arraysize(kFormatTypes); ++ii) { + const FormatInfo& info = kFormatTypes[ii]; + const ValueValidator<GLenum>& validator = + info_->GetTextureFormatValidator(info.format); + for (size_t jj = 0; jj < info.count; ++jj) { + EXPECT_TRUE(validator.IsValid(info.types[jj])); + } + } + } + + // Test some bad types + { + static const GLenum kAlphaTypes[] = { + GL_UNSIGNED_SHORT_5_5_5_1, + GL_FLOAT, + }; + static const GLenum kRGBTypes[] = { + GL_UNSIGNED_SHORT_4_4_4_4, + GL_FLOAT, + }; + static const GLenum kRGBATypes[] = { + GL_UNSIGNED_SHORT_5_6_5, + GL_FLOAT, + }; + static const GLenum kLuminanceTypes[] = { + GL_UNSIGNED_SHORT_4_4_4_4, + GL_FLOAT, + }; + static const GLenum kLuminanceAlphaTypes[] = { + GL_UNSIGNED_SHORT_5_5_5_1, + GL_FLOAT, + }; + static const GLenum kBGRATypes[] = { + GL_UNSIGNED_BYTE, + GL_UNSIGNED_SHORT_5_6_5, + GL_FLOAT, + }; + static const GLenum kDepthTypes[] = { + GL_UNSIGNED_BYTE, + GL_UNSIGNED_SHORT, + GL_UNSIGNED_INT, + GL_FLOAT, + }; + static const FormatInfo kFormatTypes[] = { + { GL_ALPHA, kAlphaTypes, arraysize(kAlphaTypes), }, + { GL_RGB, kRGBTypes, arraysize(kRGBTypes), }, + { GL_RGBA, kRGBATypes, arraysize(kRGBATypes), }, + { GL_LUMINANCE, kLuminanceTypes, arraysize(kLuminanceTypes), }, + { GL_LUMINANCE_ALPHA, kLuminanceAlphaTypes, + arraysize(kLuminanceAlphaTypes), } , + { GL_BGRA_EXT, kBGRATypes, arraysize(kBGRATypes), }, + { GL_DEPTH_COMPONENT, kDepthTypes, arraysize(kDepthTypes), }, + }; + for (size_t ii = 0; ii < arraysize(kFormatTypes); ++ii) { + const FormatInfo& info = kFormatTypes[ii]; + const ValueValidator<GLenum>& validator = + info_->GetTextureFormatValidator(info.format); + for (size_t jj = 0; jj < info.count; ++jj) { + EXPECT_FALSE(validator.IsValid(info.types[jj])); + } + } + } } TEST_F(FeatureInfoTest, InitializeNoExtensions) { @@ -146,6 +247,12 @@ TEST_F(FeatureInfoTest, InitializeNoExtensions) { GL_DEPTH_COMPONENT24)); EXPECT_FALSE(info_->validators()->texture_parameter.IsValid( GL_TEXTURE_USAGE_ANGLE)); + EXPECT_FALSE(info_->validators()->texture_internal_format_storage.IsValid( + GL_DEPTH_COMPONENT16)); + EXPECT_FALSE(info_->validators()->texture_internal_format_storage.IsValid( + GL_DEPTH_COMPONENT32_OES)); + EXPECT_FALSE(info_->validators()->texture_internal_format_storage.IsValid( + GL_DEPTH24_STENCIL8_OES)); } TEST_F(FeatureInfoTest, InitializeNPOTExtensionGLES) { @@ -205,6 +312,8 @@ TEST_F(FeatureInfoTest, InitializeEXT_texture_format_BGRA8888GLES2) { GL_BGRA_EXT)); EXPECT_TRUE(info_->validators()->texture_internal_format.IsValid( GL_BGRA_EXT)); + EXPECT_TRUE(info_->GetTextureFormatValidator(GL_BGRA_EXT).IsValid( + GL_UNSIGNED_BYTE)); } TEST_F(FeatureInfoTest, InitializeEXT_texture_format_BGRA8888GL) { @@ -220,6 +329,8 @@ TEST_F(FeatureInfoTest, InitializeEXT_texture_format_BGRA8888GL) { GL_BGRA_EXT)); EXPECT_TRUE(info_->validators()->read_pixel_format.IsValid( GL_BGRA_EXT)); + EXPECT_TRUE(info_->GetTextureFormatValidator(GL_BGRA_EXT).IsValid( + GL_UNSIGNED_BYTE)); } TEST_F(FeatureInfoTest, InitializeEXT_texture_format_BGRA8888Apple) { @@ -231,6 +342,8 @@ TEST_F(FeatureInfoTest, InitializeEXT_texture_format_BGRA8888Apple) { GL_BGRA_EXT)); EXPECT_TRUE(info_->validators()->texture_internal_format.IsValid( GL_BGRA_EXT)); + EXPECT_TRUE(info_->GetTextureFormatValidator(GL_BGRA_EXT).IsValid( + GL_UNSIGNED_BYTE)); } TEST_F(FeatureInfoTest, InitializeEXT_read_format_bgra) { @@ -259,6 +372,26 @@ TEST_F(FeatureInfoTest, InitializeOES_texture_floatGLES2) { Not(HasSubstr("GL_OES_texture_half_float_linear"))); EXPECT_TRUE(info_->validators()->pixel_type.IsValid(GL_FLOAT)); EXPECT_FALSE(info_->validators()->pixel_type.IsValid(GL_HALF_FLOAT_OES)); + EXPECT_TRUE(info_->GetTextureFormatValidator(GL_ALPHA).IsValid( + GL_FLOAT)); + EXPECT_TRUE(info_->GetTextureFormatValidator(GL_RGB).IsValid( + GL_FLOAT)); + EXPECT_TRUE(info_->GetTextureFormatValidator(GL_RGBA).IsValid( + GL_FLOAT)); + EXPECT_TRUE(info_->GetTextureFormatValidator(GL_LUMINANCE).IsValid( + GL_FLOAT)); + EXPECT_TRUE(info_->GetTextureFormatValidator(GL_LUMINANCE_ALPHA).IsValid( + GL_FLOAT)); + EXPECT_FALSE(info_->GetTextureFormatValidator(GL_ALPHA).IsValid( + GL_HALF_FLOAT_OES)); + EXPECT_FALSE(info_->GetTextureFormatValidator(GL_RGB).IsValid( + GL_HALF_FLOAT_OES)); + EXPECT_FALSE(info_->GetTextureFormatValidator(GL_RGBA).IsValid( + GL_HALF_FLOAT_OES)); + EXPECT_FALSE(info_->GetTextureFormatValidator(GL_LUMINANCE).IsValid( + GL_HALF_FLOAT_OES)); + EXPECT_FALSE(info_->GetTextureFormatValidator(GL_LUMINANCE_ALPHA).IsValid( + GL_HALF_FLOAT_OES)); } TEST_F(FeatureInfoTest, InitializeOES_texture_float_linearGLES2) { @@ -273,6 +406,26 @@ TEST_F(FeatureInfoTest, InitializeOES_texture_float_linearGLES2) { Not(HasSubstr("GL_OES_texture_half_float_linear"))); EXPECT_TRUE(info_->validators()->pixel_type.IsValid(GL_FLOAT)); EXPECT_FALSE(info_->validators()->pixel_type.IsValid(GL_HALF_FLOAT_OES)); + EXPECT_TRUE(info_->GetTextureFormatValidator(GL_ALPHA).IsValid( + GL_FLOAT)); + EXPECT_TRUE(info_->GetTextureFormatValidator(GL_RGB).IsValid( + GL_FLOAT)); + EXPECT_TRUE(info_->GetTextureFormatValidator(GL_RGBA).IsValid( + GL_FLOAT)); + EXPECT_TRUE(info_->GetTextureFormatValidator(GL_LUMINANCE).IsValid( + GL_FLOAT)); + EXPECT_TRUE(info_->GetTextureFormatValidator(GL_LUMINANCE_ALPHA).IsValid( + GL_FLOAT)); + EXPECT_FALSE(info_->GetTextureFormatValidator(GL_ALPHA).IsValid( + GL_HALF_FLOAT_OES)); + EXPECT_FALSE(info_->GetTextureFormatValidator(GL_RGB).IsValid( + GL_HALF_FLOAT_OES)); + EXPECT_FALSE(info_->GetTextureFormatValidator(GL_RGBA).IsValid( + GL_HALF_FLOAT_OES)); + EXPECT_FALSE(info_->GetTextureFormatValidator(GL_LUMINANCE).IsValid( + GL_HALF_FLOAT_OES)); + EXPECT_FALSE(info_->GetTextureFormatValidator(GL_LUMINANCE_ALPHA).IsValid( + GL_HALF_FLOAT_OES)); } TEST_F(FeatureInfoTest, InitializeOES_texture_half_floatGLES2) { @@ -288,6 +441,26 @@ TEST_F(FeatureInfoTest, InitializeOES_texture_half_floatGLES2) { Not(HasSubstr("GL_OES_texture_half_float_linear"))); EXPECT_FALSE(info_->validators()->pixel_type.IsValid(GL_FLOAT)); EXPECT_TRUE(info_->validators()->pixel_type.IsValid(GL_HALF_FLOAT_OES)); + EXPECT_FALSE(info_->GetTextureFormatValidator(GL_ALPHA).IsValid( + GL_FLOAT)); + EXPECT_FALSE(info_->GetTextureFormatValidator(GL_RGB).IsValid( + GL_FLOAT)); + EXPECT_FALSE(info_->GetTextureFormatValidator(GL_RGBA).IsValid( + GL_FLOAT)); + EXPECT_FALSE(info_->GetTextureFormatValidator(GL_LUMINANCE).IsValid( + GL_FLOAT)); + EXPECT_FALSE(info_->GetTextureFormatValidator(GL_LUMINANCE_ALPHA).IsValid( + GL_FLOAT)); + EXPECT_TRUE(info_->GetTextureFormatValidator(GL_ALPHA).IsValid( + GL_HALF_FLOAT_OES)); + EXPECT_TRUE(info_->GetTextureFormatValidator(GL_RGB).IsValid( + GL_HALF_FLOAT_OES)); + EXPECT_TRUE(info_->GetTextureFormatValidator(GL_RGBA).IsValid( + GL_HALF_FLOAT_OES)); + EXPECT_TRUE(info_->GetTextureFormatValidator(GL_LUMINANCE).IsValid( + GL_HALF_FLOAT_OES)); + EXPECT_TRUE(info_->GetTextureFormatValidator(GL_LUMINANCE_ALPHA).IsValid( + GL_HALF_FLOAT_OES)); } TEST_F(FeatureInfoTest, InitializeOES_texture_half_float_linearGLES2) { @@ -304,6 +477,26 @@ TEST_F(FeatureInfoTest, InitializeOES_texture_half_float_linearGLES2) { HasSubstr("GL_OES_texture_half_float_linear")); EXPECT_FALSE(info_->validators()->pixel_type.IsValid(GL_FLOAT)); EXPECT_TRUE(info_->validators()->pixel_type.IsValid(GL_HALF_FLOAT_OES)); + EXPECT_FALSE(info_->GetTextureFormatValidator(GL_ALPHA).IsValid( + GL_FLOAT)); + EXPECT_FALSE(info_->GetTextureFormatValidator(GL_RGB).IsValid( + GL_FLOAT)); + EXPECT_FALSE(info_->GetTextureFormatValidator(GL_RGBA).IsValid( + GL_FLOAT)); + EXPECT_FALSE(info_->GetTextureFormatValidator(GL_LUMINANCE).IsValid( + GL_FLOAT)); + EXPECT_FALSE(info_->GetTextureFormatValidator(GL_LUMINANCE_ALPHA).IsValid( + GL_FLOAT)); + EXPECT_TRUE(info_->GetTextureFormatValidator(GL_ALPHA).IsValid( + GL_HALF_FLOAT_OES)); + EXPECT_TRUE(info_->GetTextureFormatValidator(GL_RGB).IsValid( + GL_HALF_FLOAT_OES)); + EXPECT_TRUE(info_->GetTextureFormatValidator(GL_RGBA).IsValid( + GL_HALF_FLOAT_OES)); + EXPECT_TRUE(info_->GetTextureFormatValidator(GL_LUMINANCE).IsValid( + GL_HALF_FLOAT_OES)); + EXPECT_TRUE(info_->GetTextureFormatValidator(GL_LUMINANCE_ALPHA).IsValid( + GL_HALF_FLOAT_OES)); } TEST_F(FeatureInfoTest, InitializeEXT_framebuffer_multisample) { @@ -340,11 +533,20 @@ TEST_F(FeatureInfoTest, InitializeEXT_ARB_depth_texture) { info_->Initialize(NULL); EXPECT_THAT(info_->extensions(), HasSubstr("GL_GOOGLE_depth_texture")); + EXPECT_THAT(info_->extensions(), + HasSubstr("GL_CHROMIUM_depth_texture")); EXPECT_TRUE(info_->validators()->texture_internal_format.IsValid( GL_DEPTH_COMPONENT)); EXPECT_TRUE(info_->validators()->texture_format.IsValid(GL_DEPTH_COMPONENT)); + EXPECT_FALSE(info_->validators()->texture_format.IsValid(GL_DEPTH_STENCIL)); EXPECT_TRUE(info_->validators()->pixel_type.IsValid(GL_UNSIGNED_SHORT)); EXPECT_TRUE(info_->validators()->pixel_type.IsValid(GL_UNSIGNED_INT)); + EXPECT_TRUE(info_->GetTextureFormatValidator(GL_DEPTH_COMPONENT).IsValid( + GL_UNSIGNED_SHORT)); + EXPECT_TRUE(info_->GetTextureFormatValidator(GL_DEPTH_COMPONENT).IsValid( + GL_UNSIGNED_INT)); + EXPECT_FALSE(info_->GetTextureFormatValidator(GL_DEPTH_STENCIL).IsValid( + GL_UNSIGNED_INT_24_8)); } TEST_F(FeatureInfoTest, InitializeOES_ARB_depth_texture) { @@ -352,11 +554,49 @@ TEST_F(FeatureInfoTest, InitializeOES_ARB_depth_texture) { info_->Initialize(NULL); EXPECT_THAT(info_->extensions(), HasSubstr("GL_GOOGLE_depth_texture")); + EXPECT_THAT(info_->extensions(), + HasSubstr("GL_CHROMIUM_depth_texture")); + EXPECT_TRUE(info_->validators()->texture_internal_format.IsValid( + GL_DEPTH_COMPONENT)); + EXPECT_TRUE(info_->validators()->texture_format.IsValid(GL_DEPTH_COMPONENT)); + EXPECT_FALSE(info_->validators()->texture_format.IsValid(GL_DEPTH_STENCIL)); + EXPECT_TRUE(info_->validators()->pixel_type.IsValid(GL_UNSIGNED_SHORT)); + EXPECT_TRUE(info_->validators()->pixel_type.IsValid(GL_UNSIGNED_INT)); + EXPECT_TRUE(info_->GetTextureFormatValidator(GL_DEPTH_COMPONENT).IsValid( + GL_UNSIGNED_SHORT)); + EXPECT_TRUE(info_->GetTextureFormatValidator(GL_DEPTH_COMPONENT).IsValid( + GL_UNSIGNED_INT)); + EXPECT_FALSE(info_->GetTextureFormatValidator(GL_DEPTH_STENCIL).IsValid( + GL_UNSIGNED_INT_24_8)); +} + +TEST_F(FeatureInfoTest, InitializeANGLE_depth_texture) { + SetupInitExpectations("GL_ANGLE_depth_texture"); + info_->Initialize(NULL); + EXPECT_THAT(info_->extensions(), + HasSubstr("GL_GOOGLE_depth_texture")); + EXPECT_THAT(info_->extensions(), + HasSubstr("GL_CHROMIUM_depth_texture")); + EXPECT_THAT(info_->extensions(), + Not(HasSubstr("GL_ANGLE_depth_texture"))); EXPECT_TRUE(info_->validators()->texture_internal_format.IsValid( GL_DEPTH_COMPONENT)); EXPECT_TRUE(info_->validators()->texture_format.IsValid(GL_DEPTH_COMPONENT)); + EXPECT_FALSE(info_->validators()->texture_format.IsValid(GL_DEPTH_STENCIL)); EXPECT_TRUE(info_->validators()->pixel_type.IsValid(GL_UNSIGNED_SHORT)); EXPECT_TRUE(info_->validators()->pixel_type.IsValid(GL_UNSIGNED_INT)); + EXPECT_FALSE(info_->validators()->texture_internal_format_storage.IsValid( + GL_DEPTH_COMPONENT16)); + EXPECT_FALSE(info_->validators()->texture_internal_format_storage.IsValid( + GL_DEPTH_COMPONENT32_OES)); + EXPECT_FALSE(info_->validators()->texture_internal_format_storage.IsValid( + GL_DEPTH24_STENCIL8_OES)); + EXPECT_TRUE(info_->GetTextureFormatValidator(GL_DEPTH_COMPONENT).IsValid( + GL_UNSIGNED_SHORT)); + EXPECT_TRUE(info_->GetTextureFormatValidator(GL_DEPTH_COMPONENT).IsValid( + GL_UNSIGNED_INT)); + EXPECT_FALSE(info_->GetTextureFormatValidator(GL_DEPTH_STENCIL).IsValid( + GL_UNSIGNED_INT_24_8)); } TEST_F(FeatureInfoTest, InitializeEXT_packed_depth_stencil) { @@ -401,6 +641,12 @@ TEST_F(FeatureInfoTest, GL_DEPTH_STENCIL)); EXPECT_TRUE(info_->validators()->pixel_type.IsValid( GL_UNSIGNED_INT_24_8)); + EXPECT_TRUE(info_->GetTextureFormatValidator(GL_DEPTH_COMPONENT).IsValid( + GL_UNSIGNED_SHORT)); + EXPECT_TRUE(info_->GetTextureFormatValidator(GL_DEPTH_COMPONENT).IsValid( + GL_UNSIGNED_INT)); + EXPECT_TRUE(info_->GetTextureFormatValidator(GL_DEPTH_STENCIL).IsValid( + GL_UNSIGNED_INT_24_8)); } TEST_F(FeatureInfoTest, InitializeOES_depth24) { diff --git a/gpu/command_buffer/service/gl_utils.h b/gpu/command_buffer/service/gl_utils.h index 3f95b1c..f8f52ee 100644 --- a/gpu/command_buffer/service/gl_utils.h +++ b/gpu/command_buffer/service/gl_utils.h @@ -86,7 +86,16 @@ #define GL_COMMANDS_ISSUED_CHROMIUM 0x84F2 // GL_OES_texure_3D -#define GL_SAMPLER_3D_OES 0x8B5F +#define GL_SAMPLER_3D_OES 0x8B5F + +// GL_OES_depth24 +#define GL_DEPTH_COMPONENT24_OES 0x81A6 + +// GL_OES_depth32 +#define GL_DEPTH_COMPONENT32_OES 0x81A7 + +// GL_OES_packed_depth_stencil +#define GL_DEPTH24_STENCIL8_OES 0x88F0 #define GL_GLEXT_PROTOTYPES 1 diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc index 11bd915..e041c275 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc @@ -1324,6 +1324,13 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>, void ReleaseIOSurfaceForTexture(GLuint texture_id); #endif + // Validates the combination of texture parameters. For example validates that + // for a given format the specific type, level and targets are valid. + // Synthesizes the correct GL error if invalid. Returns true if valid. + bool ValidateTextureParameters( + const char* function_name, + GLenum target, GLenum format, GLenum type, GLint level); + void LogMessage(const std::string& msg); void RenderWarning(const std::string& msg); void PerformanceWarning(const std::string& msg); @@ -6667,6 +6674,43 @@ bool GLES2DecoderImpl::ClearLevel( int width, int height, bool is_texture_immutable) { + uint32 channels = GLES2Util::GetChannelsForFormat(format); + if (IsAngle() && (channels & GLES2Util::kDepth) != 0) { + // It's a depth format and ANGLE doesn't allow texImage2D or texSubImage2D + // on depth formats. + GLuint fb = 0; + glGenFramebuffersEXT(1, &fb); + glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fb); + + bool have_stencil = (channels & GLES2Util::kStencil) != 0; + GLenum attachment = have_stencil ? GL_DEPTH_STENCIL_ATTACHMENT : + GL_DEPTH_ATTACHMENT; + + glFramebufferTexture2DEXT( + GL_DRAW_FRAMEBUFFER_EXT, attachment, target, service_id, level); + // ANGLE promises a depth only attachment ok. + if (glCheckFramebufferStatusEXT(GL_DRAW_FRAMEBUFFER_EXT) != + GL_FRAMEBUFFER_COMPLETE) { + return false; + } + glClearStencil(0); + glStencilMask(-1); + glClearDepth(1.0f); + glDepthMask(true); + glDisable(GL_SCISSOR_TEST); + glClear(GL_DEPTH_BUFFER_BIT | (have_stencil ? GL_STENCIL_BUFFER_BIT : 0)); + + RestoreClearState(); + + glDeleteFramebuffersEXT(1, &fb); + FramebufferManager::FramebufferInfo* framebuffer = + GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT); + GLuint fb_service_id = + framebuffer ? framebuffer->service_id() : GetBackbufferServiceId(); + glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fb_service_id); + return true; + } + static const uint32 kMaxZeroSize = 1024 * 1024 * 4; uint32 size; @@ -6894,6 +6938,28 @@ error::Error GLES2DecoderImpl::HandleCompressedTexSubImage2DBucket( return error::kNoError; } +bool GLES2DecoderImpl::ValidateTextureParameters( + const char* function_name, + GLenum target, GLenum format, GLenum type, GLint level) { + if (!feature_info_->GetTextureFormatValidator(format).IsValid(type)) { + SetGLError(GL_INVALID_OPERATION, + (std::string(function_name) + ": invalid type " + + GLES2Util::GetStringEnum(type) + " for format " + + GLES2Util::GetStringEnum(format)).c_str()); + return false; + } + + uint32 channels = GLES2Util::GetChannelsForFormat(format); + if ((channels & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0 && level) { + SetGLError(GL_INVALID_OPERATION, + (std::string(function_name) + ": invalid type " + + GLES2Util::GetStringEnum(type) + " for format " + + GLES2Util::GetStringEnum(format)).c_str()); + return false; + } + return true; +} + error::Error GLES2DecoderImpl::DoTexImage2D( GLenum target, GLint level, @@ -6926,11 +6992,21 @@ error::Error GLES2DecoderImpl::DoTexImage2D( SetGLError(GL_INVALID_OPERATION, "glTexImage2D: format != internalFormat"); return error::kNoError; } + if (!ValidateTextureParameters("glTexImage2D", target, format, type, level)) { + return error::kNoError; + } if (!texture_manager()->ValidForTarget(target, level, width, height, 1) || border != 0) { SetGLError(GL_INVALID_VALUE, "glTexImage2D: dimensions out of range"); return error::kNoError; } + if ((GLES2Util::GetChannelsForFormat(format) & + (GLES2Util::kDepth | GLES2Util::kStencil)) != 0 && pixels) { + SetGLError( + GL_INVALID_OPERATION, + "glTexImage2D: can not supply data for depth or stencil textures"); + return error::kNoError; + } TextureManager::TextureInfo* info = GetTextureInfoForTarget(target); if (!info) { SetGLError(GL_INVALID_OPERATION, @@ -7137,6 +7213,10 @@ void GLES2DecoderImpl::DoCopyTexImage2D( SetGLError(GL_INVALID_VALUE, "glCopyTexImage2D: dimensions out of range"); return; } + if (!ValidateTextureParameters( + "glCopyTexImage2D", target, internal_format, GL_UNSIGNED_BYTE, level)) { + return; + } // Check we have compatible formats. GLenum read_format = GetBoundReadFrameBufferInternalFormat(); @@ -7148,6 +7228,13 @@ void GLES2DecoderImpl::DoCopyTexImage2D( return; } + if ((channels_needed & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) { + SetGLError( + GL_INVALID_OPERATION, + "glCopyImage2D: can not be used with depth or stencil textures"); + return; + } + if (!CheckBoundFramebuffersValid("glCopyTexImage2D")) { return; } @@ -7240,6 +7327,13 @@ void GLES2DecoderImpl::DoCopyTexSubImage2D( return; } + if ((channels_needed & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) { + SetGLError( + GL_INVALID_OPERATION, + "glCopySubImage2D: can not be used with depth or stencil textures"); + return; + } + if (!CheckBoundFramebuffersValid("glCopyTexSubImage2D")) { return; } @@ -7330,6 +7424,14 @@ void GLES2DecoderImpl::DoTexSubImage2D( return; } + if ((GLES2Util::GetChannelsForFormat(format) & + (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) { + SetGLError( + GL_INVALID_OPERATION, + "glTexSubImage2D: can not supply data for depth or stencil textures"); + return; + } + GLsizei tex_width = 0; GLsizei tex_height = 0; bool ok = info->GetLevelSize(target, level, &tex_width, &tex_height); diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc index e76cc96..5594c16 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc @@ -123,6 +123,13 @@ class GLES2DecoderManualInitTest : public GLES2DecoderWithShaderTest { } }; +class GLES2DecoderANGLEManualInitTest : public GLES2DecoderANGLETest { + public: + // Override default setup so nothing gets setup. + virtual void SetUp() { + } +}; + TEST_F(GLES2DecoderWithShaderTest, DrawArraysNoAttributesSucceeds) { SetupTexture(); AddExpectationsForSimulatedAttrib0(kNumVertices, 0); @@ -7050,6 +7057,155 @@ TEST_F(GLES2DecoderTest, IsEnabledReturnsCachedValue) { } } +TEST_F(GLES2DecoderManualInitTest, DepthTextureBadArgs) { + InitDecoder( + "GL_ANGLE_depth_texture", // extensions + false, // has alpha + true, // has depth + true, // has stencil + false, // request alpha + true, // request depth + true, // request stencil + true); // bind generates resource + + DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); + // Check trying to upload data fails. + TexImage2D tex_cmd; + tex_cmd.Init( + GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, + 1, 1, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, + kSharedMemoryId, kSharedMemoryOffset); + EXPECT_EQ(error::kNoError, ExecuteCmd(tex_cmd)); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); + // Try level > 0. + tex_cmd.Init( + GL_TEXTURE_2D, 1, GL_DEPTH_COMPONENT, + 1, 1, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, 0, 0); + EXPECT_EQ(error::kNoError, ExecuteCmd(tex_cmd)); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); + // Make a 1 pixel depth texture. + DoTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, + 1, 1, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, 0, 0); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + // Check that trying to update it fails. + TexSubImage2D tex_sub_cmd; + tex_sub_cmd.Init( + GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, + kSharedMemoryId, kSharedMemoryOffset, GL_FALSE); + EXPECT_EQ(error::kNoError, ExecuteCmd(tex_sub_cmd)); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); + + // Check that trying to CopyTexImage2D fails + CopyTexImage2D copy_tex_cmd; + copy_tex_cmd.Init(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, 0, 0, 1, 1, 0); + EXPECT_EQ(error::kNoError, ExecuteCmd(copy_tex_cmd)); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); + + // Check that trying to CopyTexSubImage2D fails + CopyTexSubImage2D copy_sub_cmd; + copy_sub_cmd.Init(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 1, 1); + EXPECT_EQ(error::kNoError, ExecuteCmd(copy_sub_cmd)); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); +} + +TEST_F(GLES2DecoderManualInitTest, GenerateMipmapDepthTexture) { + InitDecoder( + "GL_ANGLE_depth_texture", // extensions + false, // has alpha + true, // has depth + true, // has stencil + false, // request alpha + true, // request depth + true, // request stencil + true); // bind generates resource + DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); + DoTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, + 2, 2, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, + 0, 0); + GenerateMipmap cmd; + cmd.Init(GL_TEXTURE_2D); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); +} + +TEST_F(GLES2DecoderANGLEManualInitTest, DrawClearsDepthTexture) { + InitDecoder( + "GL_ANGLE_depth_texture", // extensions + true, // has alpha + true, // has depth + false, // has stencil + true, // request alpha + true, // request depth + false, // request stencil + true); // bind generates resource + + SetupDefaultProgram(); + SetupAllNeededVertexBuffers(); + const GLenum attachment = GL_DEPTH_ATTACHMENT; + const GLenum target = GL_TEXTURE_2D; + const GLint level = 0; + DoBindTexture(target, client_texture_id_, kServiceTextureId); + + // Create a depth texture. + DoTexImage2D(target, level, GL_DEPTH_COMPONENT, 1, 1, 0, + GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, 0, 0); + + EXPECT_CALL(*gl_, GenFramebuffersEXT(1, _)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, BindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, _)) + .Times(1) + .RetiresOnSaturation(); + + EXPECT_CALL(*gl_, FramebufferTexture2DEXT( + GL_DRAW_FRAMEBUFFER_EXT, attachment, target, kServiceTextureId, level)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, CheckFramebufferStatusEXT(GL_DRAW_FRAMEBUFFER_EXT)) + .WillOnce(Return(GL_FRAMEBUFFER_COMPLETE)) + .RetiresOnSaturation(); + + EXPECT_CALL(*gl_, ClearStencil(0)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, StencilMask(-1)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, ClearDepth(1.0f)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, DepthMask(true)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, Disable(GL_SCISSOR_TEST)) + .Times(1) + .RetiresOnSaturation(); + + EXPECT_CALL(*gl_, Clear(GL_DEPTH_BUFFER_BIT)) + .Times(1) + .RetiresOnSaturation(); + + SetupExpectationsForRestoreClearState( + 0.0f, 0.0f, 0.0f, 0.0f, 0, 1.0f, false); + + EXPECT_CALL(*gl_, DeleteFramebuffersEXT(1, _)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, BindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0)) + .Times(1) + .RetiresOnSaturation(); + + SetupExpectationsForApplyingDefaultDirtyState(); + EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices)) + .Times(1) + .RetiresOnSaturation(); + DrawArrays cmd; + cmd.Init(GL_TRIANGLES, 0, kNumVertices); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + // TODO(gman): Complete this test. // TEST_F(GLES2DecoderTest, CompressedTexImage2DGLError) { // } diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc index 2886ed1..8ff9770 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc @@ -388,6 +388,31 @@ void GLES2DecoderTestBase::SetupExpectationsForFramebufferClearing( restore_scissor_test); } +void GLES2DecoderTestBase::SetupExpectationsForRestoreClearState( + GLclampf restore_red, + GLclampf restore_green, + GLclampf restore_blue, + GLclampf restore_alpha, + GLuint restore_stencil, + GLclampf restore_depth, + bool restore_scissor_test) { + EXPECT_CALL(*gl_, ClearColor( + restore_red, restore_green, restore_blue, restore_alpha)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, ClearStencil(restore_stencil)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, ClearDepth(restore_depth)) + .Times(1) + .RetiresOnSaturation(); + if (restore_scissor_test) { + EXPECT_CALL(*gl_, Enable(GL_SCISSOR_TEST)) + .Times(1) + .RetiresOnSaturation(); + } +} + void GLES2DecoderTestBase::SetupExpectationsForFramebufferClearingMulti( GLuint read_framebuffer_service_id, GLuint draw_framebuffer_service_id, @@ -444,21 +469,9 @@ void GLES2DecoderTestBase::SetupExpectationsForFramebufferClearingMulti( EXPECT_CALL(*gl_, Clear(clear_bits)) .Times(1) .RetiresOnSaturation(); - EXPECT_CALL(*gl_, ClearColor( - restore_red, restore_green, restore_blue, restore_alpha)) - .Times(1) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, ClearStencil(restore_stencil)) - .Times(1) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, ClearDepth(restore_depth)) - .Times(1) - .RetiresOnSaturation(); - if (restore_scissor_test) { - EXPECT_CALL(*gl_, Enable(GL_SCISSOR_TEST)) - .Times(1) - .RetiresOnSaturation(); - } + SetupExpectationsForRestoreClearState( + restore_red, restore_green, restore_blue, restore_alpha, + restore_stencil, restore_depth, restore_scissor_test); if (target == GL_READ_FRAMEBUFFER_EXT) { EXPECT_CALL(*gl_, BindFramebufferEXT( GL_READ_FRAMEBUFFER_EXT, read_framebuffer_service_id)) diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h index f98f0fc..9f61aa3 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h @@ -262,6 +262,15 @@ class GLES2DecoderTestBase : public testing::Test { GLsizei width, GLsizei height); + void SetupExpectationsForRestoreClearState( + GLclampf restore_red, + GLclampf restore_green, + GLclampf restore_blue, + GLclampf restore_alpha, + GLuint restore_stencil, + GLclampf restore_depth, + bool restore_scissor_test); + void SetupExpectationsForFramebufferClearing( GLenum target, GLuint clear_bits, diff --git a/gpu/command_buffer/service/gles2_cmd_validation_autogen.h b/gpu/command_buffer/service/gles2_cmd_validation_autogen.h index 34ebb6f..d127f25 100644 --- a/gpu/command_buffer/service/gles2_cmd_validation_autogen.h +++ b/gpu/command_buffer/service/gles2_cmd_validation_autogen.h @@ -39,6 +39,7 @@ ValueValidator<GLenum> query_object_parameter; ValueValidator<GLenum> query_parameter; ValueValidator<GLenum> query_target; ValueValidator<GLenum> read_pixel_format; +ValueValidator<GLenum> read_pixel_type; ValueValidator<GLenum> render_buffer_format; ValueValidator<GLenum> render_buffer_parameter; ValueValidator<GLenum> render_buffer_target; diff --git a/gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h b/gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h index 18e5136..bc19e4f 100644 --- a/gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h +++ b/gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h @@ -290,6 +290,13 @@ static GLenum valid_read_pixel_format_table[] = { GL_RGBA, }; +static GLenum valid_read_pixel_type_table[] = { + GL_UNSIGNED_BYTE, + GL_UNSIGNED_SHORT_5_6_5, + GL_UNSIGNED_SHORT_4_4_4_4, + GL_UNSIGNED_SHORT_5_5_5_1, +}; + static GLenum valid_render_buffer_format_table[] = { GL_RGBA4, GL_RGB565, @@ -555,6 +562,8 @@ Validators::Validators() read_pixel_format( valid_read_pixel_format_table, arraysize( valid_read_pixel_format_table)), + read_pixel_type( + valid_read_pixel_type_table, arraysize(valid_read_pixel_type_table)), render_buffer_format( valid_render_buffer_format_table, arraysize( valid_render_buffer_format_table)), diff --git a/gpu/command_buffer/service/texture_manager.cc b/gpu/command_buffer/service/texture_manager.cc index e97514d..9666597 100644 --- a/gpu/command_buffer/service/texture_manager.cc +++ b/gpu/command_buffer/service/texture_manager.cc @@ -210,7 +210,13 @@ bool TextureManager::TextureInfo::CanGenerateMipmaps( return false; } + // Can't generate mips for depth or stencil textures. const TextureInfo::LevelInfo& first = level_infos_[0][0]; + uint32 channels = GLES2Util::GetChannelsForFormat(first.format); + if (channels & (GLES2Util::kDepth | GLES2Util::kStencil)) { + return false; + } + // TODO(gman): Check internal_format, format and type. for (size_t ii = 0; ii < level_infos_.size(); ++ii) { const LevelInfo& info = level_infos_[ii][0]; diff --git a/gpu/command_buffer/service/texture_manager_unittest.cc b/gpu/command_buffer/service/texture_manager_unittest.cc index 485808d..f077114 100644 --- a/gpu/command_buffer/service/texture_manager_unittest.cc +++ b/gpu/command_buffer/service/texture_manager_unittest.cc @@ -767,6 +767,24 @@ TEST_F(TextureInfoTest, EGLImageExternal) { manager.Destroy(false); } +TEST_F(TextureInfoTest, DepthTexture) { + TestHelper::SetupFeatureInfoInitExpectations( + gl_.get(), "GL_ANGLE_depth_texture"); + FeatureInfo::Ref feature_info(new FeatureInfo()); + feature_info->Initialize(NULL); + TextureManager manager( + feature_info.get(), kMaxTextureSize, kMaxCubeMapTextureSize); + manager.CreateTextureInfo(kClient1Id, kService1Id); + TextureManager::TextureInfo* info = manager.GetTextureInfo(kClient1Id); + ASSERT_TRUE(info != NULL); + manager.SetInfoTarget(info, GL_TEXTURE_2D); + manager.SetLevelInfo( + info, GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, 4, 4, 1, 0, + GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, false); + EXPECT_FALSE(manager.CanGenerateMipmaps(info)); + manager.Destroy(false); +} + TEST_F(TextureInfoTest, SafeUnsafe) { static const GLuint kClient2Id = 2; static const GLuint kService2Id = 12; diff --git a/gpu/command_buffer/tests/gl_depth_texture_unittest.cc b/gpu/command_buffer/tests/gl_depth_texture_unittest.cc new file mode 100644 index 0000000..9663340 --- /dev/null +++ b/gpu/command_buffer/tests/gl_depth_texture_unittest.cc @@ -0,0 +1,205 @@ +// Copyright (c) 2012 The Chromium 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 <GLES2/gl2.h> +#include <GLES2/gl2ext.h> + +#include "gpu/command_buffer/tests/gl_manager.h" +#include "gpu/command_buffer/tests/gl_test_utils.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +#define SHADER(Src) #Src + +namespace gpu { + +class DepthTextureTest : public testing::Test { + protected: + static const GLsizei kResolution = 64; + virtual void SetUp() { + gl_.Initialize(gfx::Size(kResolution, kResolution)); + } + + virtual void TearDown() { + gl_.Destroy(); + } + + GLuint SetupUnitQuad(GLint position_location); + + GLManager gl_; +}; + + + +GLuint DepthTextureTest::SetupUnitQuad(GLint position_location) { + GLuint vbo = 0; + glGenBuffers(1, &vbo); + glBindBuffer(GL_ARRAY_BUFFER, vbo); + static float vertices[] = { + 1.0f, 1.0f, 1.0f, + -1.0f, 1.0f, 0.0f, + -1.0f, -1.0f, -1.0f, + 1.0f, 1.0f, 1.0f, + -1.0f, -1.0f, -1.0f, + 1.0f, -1.0f, 0.0f, + }; + glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); + glEnableVertexAttribArray(position_location); + glVertexAttribPointer(position_location, 3, GL_FLOAT, GL_FALSE, 0, 0); + + return vbo; +} + +namespace { + +struct FormatType { + GLenum format; + GLenum type; +}; + +} // anonymous namespace + +TEST_F(DepthTextureTest, RenderTo) { + if (!GLTestHelper::HasExtension("GL_CHROMIUM_depth_texture")) { + return; + } + + bool have_depth_stencil = GLTestHelper::HasExtension( + "GL_OES_packed_depth_stencil"); + + static const char* v_shader_str = SHADER( + attribute vec4 v_position; + void main() + { + gl_Position = v_position; + } + ); + static const char* f_shader_str = SHADER( + precision mediump float; + uniform sampler2D u_texture; + uniform vec2 u_resolution; + void main() + { + vec2 texcoord = gl_FragCoord.xy / u_resolution; + gl_FragColor = texture2D(u_texture, texcoord); + } + ); + + GLuint program = GLTestHelper::LoadProgram(v_shader_str, f_shader_str); + + GLint position_loc = glGetAttribLocation(program, "v_position"); + GLint resolution_loc = glGetUniformLocation(program, "u_resolution"); + + SetupUnitQuad(position_loc); + + // Depth test needs to be on for the depth buffer to be updated. + glEnable(GL_DEPTH_TEST); + + // create an fbo + GLuint fbo = 0; + glGenFramebuffers(1, &fbo); + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + + // create a depth texture. + GLuint color_texture = 0; + GLuint depth_texture = 0; + + glGenTextures(1, &color_texture); + glBindTexture(GL_TEXTURE_2D, color_texture); + glTexImage2D( + GL_TEXTURE_2D, 0, GL_RGBA, kResolution, kResolution, + 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + glFramebufferTexture2D( + GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color_texture, 0); + + glGenTextures(1, &depth_texture); + glBindTexture(GL_TEXTURE_2D, depth_texture); + 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_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glFramebufferTexture2D( + GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depth_texture, 0); + + glUseProgram(program); + glUniform2f(resolution_loc, kResolution, kResolution); + + static const FormatType format_types[] = { + { GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, }, + { GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, }, + { GL_DEPTH_STENCIL_OES, GL_UNSIGNED_INT_24_8_OES, }, + }; + for (size_t ii = 0; ii < arraysize(format_types); ++ii) { + GLenum format = format_types[ii].format; + GLenum type = format_types[ii].type; + + if (format == GL_DEPTH_STENCIL_OES && !have_depth_stencil) { + continue; + } + + glBindTexture(GL_TEXTURE_2D, depth_texture); + glTexImage2D( + GL_TEXTURE_2D, 0, format, kResolution, kResolution, + 0, format, type, NULL); + + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + EXPECT_TRUE( + glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE); + + GLTestHelper::CheckGLError("no errors", __LINE__); + + glClearColor(1.0f, 1.0f, 1.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + // Disconnect the texture so we'll render with the default texture. + glBindTexture(GL_TEXTURE_2D, 0); + + // Render to the fbo. + glDrawArrays(GL_TRIANGLES, 0, 6); + + // Render with the depth texture. + glBindFramebuffer(GL_FRAMEBUFFER, 0); + glBindTexture(GL_TEXTURE_2D, depth_texture); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glDrawArrays(GL_TRIANGLES, 0, 6); + + uint8 actual_pixels[kResolution * kResolution * 4] = { 0, }; + glReadPixels( + 0, 0, kResolution, kResolution, GL_RGBA, GL_UNSIGNED_BYTE, + actual_pixels); + + // Check that each pixel's RGB are the same and that it's value is less + // than the previous pixel in either direction. Basically verify we have a + // gradient. + for (GLint yy = 0; yy < kResolution; ++yy) { + for (GLint xx = 0; xx < kResolution; ++xx) { + const uint8* actual = &actual_pixels[(yy * kResolution + xx) * 4]; + const uint8* left = actual - 4; + const uint8* down = actual - kResolution * 4; + + EXPECT_EQ(actual[0], actual[1]); + EXPECT_EQ(actual[1], actual[2]); + EXPECT_EQ(0xFF, actual[3]); + + if (xx > 0) { + EXPECT_GT(actual[0], left[0]); + } + if (yy > 0) { + EXPECT_GT(actual[0], down[0]); + } + } + } + + // Check that bottom left corner is vastly different thatn top right. + EXPECT_GT( + actual_pixels[(kResolution * kResolution - 1) * 4] - actual_pixels[0], + 0xC0); + GLTestHelper::CheckGLError("no errors", __LINE__); + } +} + +} // namespace gpu + + + diff --git a/gpu/command_buffer/tests/gl_test_utils.cc b/gpu/command_buffer/tests/gl_test_utils.cc index a666fff..437ffba 100644 --- a/gpu/command_buffer/tests/gl_test_utils.cc +++ b/gpu/command_buffer/tests/gl_test_utils.cc @@ -105,7 +105,7 @@ GLuint GLTestHelper::SetupUnitQuad(GLint position_location) { bool GLTestHelper::CheckPixels( GLint x, GLint y, GLsizei width, GLsizei height, GLint tolerance, - uint8* color) { + const uint8* color) { GLsizei size = width * height * 4; scoped_array<uint8> pixels(new uint8[size]); memset(pixels.get(), 123, size); diff --git a/gpu/command_buffer/tests/gl_test_utils.h b/gpu/command_buffer/tests/gl_test_utils.h index b5f9dc2..bd2d380 100644 --- a/gpu/command_buffer/tests/gl_test_utils.h +++ b/gpu/command_buffer/tests/gl_test_utils.h @@ -36,7 +36,7 @@ class GLTestHelper { // Checks an area of pixels for a color. static bool CheckPixels( GLint x, GLint y, GLsizei width, GLsizei height, GLint tolerance, - uint8* color); + const uint8* color); // Uses ReadPixels to save an area of the current FBO/Backbuffer. static bool SaveBackbufferAsBMP(const char* filename, int width, int height); diff --git a/gpu/gpu_common.gypi b/gpu/gpu_common.gypi index a28698e..93910b0 100644 --- a/gpu/gpu_common.gypi +++ b/gpu/gpu_common.gypi @@ -233,6 +233,7 @@ '<@(gles2_c_lib_source_files)', 'command_buffer/tests/occlusion_query_unittests.cc', 'command_buffer/tests/gl_copy_texture_CHROMIUM_unittest.cc', + 'command_buffer/tests/gl_depth_texture_unittest.cc', 'command_buffer/tests/gl_manager.cc', 'command_buffer/tests/gl_manager.h', 'command_buffer/tests/gl_tests_main.cc', |