summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoroetuaho@nvidia.com <oetuaho@nvidia.com@0039d316-1c4b-4281-b951-d872f2087c98>2014-02-14 15:20:52 +0000
committeroetuaho@nvidia.com <oetuaho@nvidia.com@0039d316-1c4b-4281-b951-d872f2087c98>2014-02-14 15:20:52 +0000
commit17a96119afdf3e468e0174d14c12a4686295bab1 (patch)
tree4bccf2a3a3003d062be60dab33daf9fae6042e3f
parent768b8dc9a21c920a81e0c00c8aff3447c84130b2 (diff)
downloadchromium_src-17a96119afdf3e468e0174d14c12a4686295bab1.zip
chromium_src-17a96119afdf3e468e0174d14c12a4686295bab1.tar.gz
chromium_src-17a96119afdf3e468e0174d14c12a4686295bab1.tar.bz2
Implement support for rendering to 32-bit float textures on ES3
On ES2 with OES_texture_float/OES_texture_half_float support, it is only possible to render to 16-bit half float textures using EXT_color_buffer_half_float. There's no support for rendering to 32-bit float textures in ES2 extensions. On ES3, rendering to some 32-bit float texture formats is exposed with EXT_color_buffer_float, but one must use the sized internal formats specified in ES3 core to do that. To expose this, a new command buffer extension is added which enables clients to directly use the sized internal format GL_RGBA32F. A similar extension is also added to expose GL_RGB32F on desktop GL platforms for the sake of consistency. These extensions are available whenever rendering to float textures is available. To support the current version of ANGLE, format conversions back to unsized internal formats are added to ui/gl. Tests are added to cover this functionality. The new tests also add coverage for the handling of 32-bit float formats on ES2 and on desktop GL that existed before this patch. BUG=329605 TEST=gpu_unittests, WebGL conformance tests Review URL: https://codereview.chromium.org/139013008 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@251329 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--gpu/GLES2/extensions/CHROMIUM/CHROMIUM_color_buffer_float_rgb.txt64
-rw-r--r--gpu/GLES2/extensions/CHROMIUM/CHROMIUM_color_buffer_float_rgba.txt64
-rw-r--r--gpu/GLES2/gl2extchromium.h14
-rw-r--r--gpu/command_buffer/service/context_group_unittest.cc4
-rw-r--r--gpu/command_buffer/service/feature_info.cc90
-rw-r--r--gpu/command_buffer/service/feature_info.h2
-rw-r--r--gpu/command_buffer/service/feature_info_unittest.cc17
-rw-r--r--gpu/command_buffer/service/framebuffer_manager_unittest.cc153
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder.cc26
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc72
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc47
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h6
-rw-r--r--gpu/command_buffer/service/test_helper.cc82
-rw-r--r--gpu/command_buffer/service/test_helper.h3
-rw-r--r--gpu/command_buffer/service/texture_manager.cc78
-rw-r--r--gpu/command_buffer/service/texture_manager.h11
-rw-r--r--gpu/command_buffer/service/texture_manager_unittest.cc27
-rw-r--r--ui/gl/gl_context.cc10
-rw-r--r--ui/gl/gl_context.h9
-rw-r--r--ui/gl/gl_context_stub.cc4
-rw-r--r--ui/gl/gl_context_stub.h1
-rw-r--r--ui/gl/gl_gl_api_implementation.cc33
-rw-r--r--ui/gl/gl_version_info.cc8
-rw-r--r--ui/gl/gl_version_info.h4
24 files changed, 678 insertions, 151 deletions
diff --git a/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_color_buffer_float_rgb.txt b/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_color_buffer_float_rgb.txt
new file mode 100644
index 0000000..7f22008
--- /dev/null
+++ b/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_color_buffer_float_rgb.txt
@@ -0,0 +1,64 @@
+Name
+
+ CHROMIUM_color_buffer_float_rgb
+
+Name Strings
+
+ GL_CHROMIUM_color_buffer_float_rgb
+
+Version
+
+ Last Modifed Date: February 7, 2014
+
+Dependencies
+
+ This extension is written against the OpenGL ES 2.0 specification.
+
+ OpenGL ES 2.0 is required.
+
+ OES_texture_float is required.
+
+Overview
+
+ This extension implements a subset of ARB_color_buffer_float on top of
+ OpenGL ES 2.0.
+
+ This extension enables rendering to floating point RGB textures. When
+ this extension is enabled:
+
+ * The 32-bit floating point type GL_RGB32F becomes available as a
+ color-renderable internal format. Textures created with type = FLOAT,
+ and internal format GL_RGB32F, can be attached to framebuffer object
+ color attachments for rendering.
+
+ * GL_RGB / GL_RGB32F becomes an allowable format / internalformat parameter
+ pair for TexImage2D. The restriction in section 3.7.1 of the OpenGL ES
+ 2.0 spec that the internalformat parameter and format parameter of
+ TexImage2D must match is lifted for this case.
+
+ Floating point RGB textures may still be created also with the unsized
+ GL_RGB internal format, but whether such textures are renderable is not
+ guaranteed.
+
+New Tokens
+
+ Accepted by the <internalformat> parameter of TexImage2D:
+
+ GL_RGB32F 0x8815
+
+New Procedures and Functions
+
+ None.
+
+Errors
+
+ None.
+
+New State
+
+ None.
+
+Revision History
+
+ 2/7/2014 Documented the extension
+
diff --git a/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_color_buffer_float_rgba.txt b/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_color_buffer_float_rgba.txt
new file mode 100644
index 0000000..d52bab851
--- /dev/null
+++ b/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_color_buffer_float_rgba.txt
@@ -0,0 +1,64 @@
+Name
+
+ CHROMIUM_color_buffer_float_rgba
+
+Name Strings
+
+ GL_CHROMIUM_color_buffer_float_rgba
+
+Version
+
+ Last Modifed Date: February 7, 2014
+
+Dependencies
+
+ This extension is written against the OpenGL ES 2.0 specification.
+
+ OpenGL ES 2.0 is required.
+
+ OES_texture_float is required.
+
+Overview
+
+ This extension implements a subset of EXT_color_buffer_float on top of
+ OpenGL ES 2.0.
+
+ This extension enables rendering to floating point RGBA textures. When
+ this extension is enabled:
+
+ * The 32-bit floating point type GL_RGBA32F becomes available as a
+ color-renderable internal format. Textures created with type = FLOAT,
+ and internal format GL_RGBA32F, can be attached to framebuffer object
+ color attachments for rendering.
+
+ * GL_RGBA / GL_RGBA32F becomes an allowable format / internalformat
+ parameter pair for TexImage2D. The restriction in section 3.7.1 of the
+ OpenGL ES 2.0 spec that the internalformat parameter and format parameter
+ of TexImage2D must match is lifted for this case.
+
+ Floating point RGBA textures may still be created also with the unsized
+ GL_RGBA internal format, but whether such textures are renderable is not
+ guaranteed.
+
+New Tokens
+
+ Accepted by the <internalformat> parameter of TexImage2D:
+
+ GL_RGBA32F 0x8814
+
+New Procedures and Functions
+
+ None.
+
+Errors
+
+ None.
+
+New State
+
+ None.
+
+Revision History
+
+ 2/7/2014 Documented the extension
+
diff --git a/gpu/GLES2/gl2extchromium.h b/gpu/GLES2/gl2extchromium.h
index 11db4b7..50a6247 100644
--- a/gpu/GLES2/gl2extchromium.h
+++ b/gpu/GLES2/gl2extchromium.h
@@ -618,6 +618,20 @@ typedef GLuint (GL_APIENTRYP PFNGLINSERTSYNCPOINTCHROMIUMPROC) ();
typedef void (GL_APIENTRYP PFNGLWAITSYNCPOINTCHROMIUMPROC) (GLuint sync_point);
#endif /* GL_CHROMIUM_sync_point */
+#ifndef GL_CHROMIUM_color_buffer_float_rgba
+#define GL_CHROMIUM_color_buffer_float_rgba 1
+#ifndef GL_RGBA32F
+#define GL_RGBA32F 0x8814
+#endif
+#endif /* GL_CHROMIUM_color_buffer_float_rgba */
+
+#ifndef GL_CHROMIUM_color_buffer_float_rgb
+#define GL_CHROMIUM_color_buffer_float_rgb 1
+#ifndef GL_RGB32F
+#define GL_RGB32F 0x8815
+#endif
+#endif /* GL_CHROMIUM_color_buffer_float_rgb */
+
#ifdef __cplusplus
}
#endif
diff --git a/gpu/command_buffer/service/context_group_unittest.cc b/gpu/command_buffer/service/context_group_unittest.cc
index 3cce29c..23919bf 100644
--- a/gpu/command_buffer/service/context_group_unittest.cc
+++ b/gpu/command_buffer/service/context_group_unittest.cc
@@ -71,7 +71,7 @@ TEST_F(ContextGroupTest, Basic) {
TEST_F(ContextGroupTest, InitializeNoExtensions) {
TestHelper::SetupContextGroupInitExpectations(gl_.get(),
- DisallowedFeatures(), "");
+ DisallowedFeatures(), "", "");
group_->Initialize(decoder_.get(), DisallowedFeatures());
EXPECT_EQ(static_cast<uint32>(TestHelper::kNumVertexAttribs),
group_->max_vertex_attribs());
@@ -106,7 +106,7 @@ TEST_F(ContextGroupTest, InitializeNoExtensions) {
TEST_F(ContextGroupTest, MultipleContexts) {
scoped_ptr<MockGLES2Decoder> decoder2_(new MockGLES2Decoder());
TestHelper::SetupContextGroupInitExpectations(gl_.get(),
- DisallowedFeatures(), "");
+ DisallowedFeatures(), "", "");
group_->Initialize(decoder_.get(), DisallowedFeatures());
group_->Initialize(decoder2_.get(), DisallowedFeatures());
diff --git a/gpu/command_buffer/service/feature_info.cc b/gpu/command_buffer/service/feature_info.cc
index 573cec4..e3ed72b 100644
--- a/gpu/command_buffer/service/feature_info.cc
+++ b/gpu/command_buffer/service/feature_info.cc
@@ -7,6 +7,7 @@
#include <set>
#include "base/command_line.h"
+#include "base/macros.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
@@ -99,7 +100,9 @@ void StringToWorkarounds(
} // anonymous namespace.
FeatureInfo::FeatureFlags::FeatureFlags()
- : chromium_framebuffer_multisample(false),
+ : chromium_color_buffer_float_rgba(false),
+ chromium_color_buffer_float_rgb(false),
+ chromium_framebuffer_multisample(false),
use_core_framebuffer_multisample(false),
multisampled_render_to_texture(false),
use_img_for_multisampled_render_to_texture(false),
@@ -437,26 +440,28 @@ void FeatureInfo::InitializeFeatures() {
bool enable_texture_half_float = false;
bool enable_texture_half_float_linear = false;
- bool have_arb_texture_float = extensions.Contains("GL_ARB_texture_float");
+ bool may_enable_chromium_color_buffer_float = false;
- if (have_arb_texture_float) {
+ if (extensions.Contains("GL_ARB_texture_float")) {
enable_texture_float = true;
enable_texture_float_linear = true;
enable_texture_half_float = true;
enable_texture_half_float_linear = true;
+ may_enable_chromium_color_buffer_float = true;
} else {
- if (extensions.Contains("GL_OES_texture_float") || have_arb_texture_float) {
+ if (extensions.Contains("GL_OES_texture_float")) {
enable_texture_float = true;
- if (extensions.Contains("GL_OES_texture_float_linear") ||
- have_arb_texture_float) {
+ if (extensions.Contains("GL_OES_texture_float_linear")) {
enable_texture_float_linear = true;
}
+ if ((is_es3 && extensions.Contains("GL_EXT_color_buffer_float")) ||
+ feature_flags_.is_angle) {
+ may_enable_chromium_color_buffer_float = true;
+ }
}
- if (extensions.Contains("GL_OES_texture_half_float") ||
- have_arb_texture_float) {
+ if (extensions.Contains("GL_OES_texture_half_float")) {
enable_texture_half_float = true;
- if (extensions.Contains("GL_OES_texture_half_float_linear") ||
- have_arb_texture_float) {
+ if (extensions.Contains("GL_OES_texture_half_float_linear")) {
enable_texture_half_float_linear = true;
}
}
@@ -490,6 +495,62 @@ void FeatureInfo::InitializeFeatures() {
}
}
+ if (may_enable_chromium_color_buffer_float) {
+ COMPILE_ASSERT(GL_RGBA32F_ARB == GL_RGBA32F &&
+ GL_RGBA32F_EXT == GL_RGBA32F &&
+ GL_RGB32F_ARB == GL_RGB32F &&
+ GL_RGB32F_EXT == GL_RGB32F,
+ sized_float_internal_format_variations_must_match);
+ // We don't check extension support beyond ARB_texture_float on desktop GL,
+ // and format support varies between GL configurations. For example, spec
+ // prior to OpenGL 3.0 mandates framebuffer support only for one
+ // implementation-chosen format, and ES3.0 EXT_color_buffer_float does not
+ // support rendering to RGB32F. Check for framebuffer completeness with
+ // formats that the extensions expose, and only enable an extension when a
+ // framebuffer created with its texture format is reported as complete.
+ GLint fb_binding = 0;
+ GLint tex_binding = 0;
+ glGetIntegerv(GL_FRAMEBUFFER_BINDING, &fb_binding);
+ glGetIntegerv(GL_TEXTURE_BINDING_2D, &tex_binding);
+
+ GLuint tex_id = 0;
+ GLuint fb_id = 0;
+ GLsizei width = 16;
+
+ glGenTextures(1, &tex_id);
+ glGenFramebuffersEXT(1, &fb_id);
+ glBindTexture(GL_TEXTURE_2D, tex_id);
+ // Nearest filter needed for framebuffer completeness on some drivers.
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width, width, 0, GL_RGBA,
+ GL_FLOAT, NULL);
+ glBindFramebufferEXT(GL_FRAMEBUFFER, fb_id);
+ glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ GL_TEXTURE_2D, tex_id, 0);
+ GLenum statusRGBA = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, width, width, 0, GL_RGB,
+ GL_FLOAT, NULL);
+ GLenum statusRGB = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
+ glDeleteFramebuffersEXT(1, &fb_id);
+ glDeleteTextures(1, &tex_id);
+
+ glBindFramebufferEXT(GL_FRAMEBUFFER, static_cast<GLuint>(fb_binding));
+ glBindTexture(GL_TEXTURE_2D, static_cast<GLuint>(tex_binding));
+
+ DCHECK(glGetError() == GL_NO_ERROR);
+
+ if (statusRGBA == GL_FRAMEBUFFER_COMPLETE) {
+ validators_.texture_internal_format.AddValue(GL_RGBA32F);
+ feature_flags_.chromium_color_buffer_float_rgba = true;
+ AddExtensionString("GL_CHROMIUM_color_buffer_float_rgba");
+ }
+ if (statusRGB == GL_FRAMEBUFFER_COMPLETE) {
+ validators_.texture_internal_format.AddValue(GL_RGB32F);
+ feature_flags_.chromium_color_buffer_float_rgb = true;
+ AddExtensionString("GL_CHROMIUM_color_buffer_float_rgb");
+ }
+ }
+
// Check for multisample support
if (!disallowed_features_.multisampling &&
!workarounds_.disable_framebuffer_multisample) {
@@ -719,7 +780,14 @@ void FeatureInfo::InitializeFeatures() {
}
void FeatureInfo::AddExtensionString(const std::string& str) {
- if (extensions_.find(str) == std::string::npos) {
+ size_t pos = extensions_.find(str);
+ while (pos != std::string::npos &&
+ pos + str.length() < extensions_.length() &&
+ extensions_.substr(pos + str.length(), 1) != " ") {
+ // This extension name is a substring of another.
+ pos = extensions_.find(str, pos + str.length());
+ }
+ if (pos == std::string::npos) {
extensions_ += (extensions_.empty() ? "" : " ") + str;
}
}
diff --git a/gpu/command_buffer/service/feature_info.h b/gpu/command_buffer/service/feature_info.h
index 81a7f7c..a47a080 100644
--- a/gpu/command_buffer/service/feature_info.h
+++ b/gpu/command_buffer/service/feature_info.h
@@ -26,6 +26,8 @@ class GPU_EXPORT FeatureInfo : public base::RefCounted<FeatureInfo> {
struct FeatureFlags {
FeatureFlags();
+ bool chromium_color_buffer_float_rgba;
+ bool chromium_color_buffer_float_rgb;
bool chromium_framebuffer_multisample;
// Use glBlitFramebuffer() and glRenderbufferStorageMultisample() with
// GL_EXT_framebuffer_multisample-style semantics, since they are exposed
diff --git a/gpu/command_buffer/service/feature_info_unittest.cc b/gpu/command_buffer/service/feature_info_unittest.cc
index 53d1527..1a8cc12 100644
--- a/gpu/command_buffer/service/feature_info_unittest.cc
+++ b/gpu/command_buffer/service/feature_info_unittest.cc
@@ -280,6 +280,10 @@ TEST_F(FeatureInfoTest, InitializeNoExtensions) {
GL_DEPTH24_STENCIL8));
EXPECT_FALSE(info_->validators()->texture_internal_format.IsValid(
GL_DEPTH_STENCIL));
+ EXPECT_FALSE(info_->validators()->texture_internal_format.IsValid(
+ GL_RGBA32F));
+ EXPECT_FALSE(info_->validators()->texture_internal_format.IsValid(
+ GL_RGB32F));
EXPECT_FALSE(info_->validators()->texture_format.IsValid(
GL_DEPTH_STENCIL));
EXPECT_FALSE(info_->validators()->pixel_type.IsValid(
@@ -407,6 +411,19 @@ TEST_F(FeatureInfoTest, InitializeEXT_read_format_bgra) {
GL_BGRA8_EXT));
}
+TEST_F(FeatureInfoTest, InitializeARB_texture_float) {
+ SetupInitExpectations("GL_ARB_texture_float");
+ EXPECT_TRUE(info_->feature_flags().chromium_color_buffer_float_rgba);
+ EXPECT_TRUE(info_->feature_flags().chromium_color_buffer_float_rgb);
+ std::string extensions = info_->extensions() + " ";
+ EXPECT_THAT(extensions, HasSubstr("GL_CHROMIUM_color_buffer_float_rgb "));
+ EXPECT_THAT(extensions, HasSubstr("GL_CHROMIUM_color_buffer_float_rgba"));
+ EXPECT_TRUE(info_->validators()->texture_internal_format.IsValid(
+ GL_RGBA32F));
+ EXPECT_TRUE(info_->validators()->texture_internal_format.IsValid(
+ GL_RGB32F));
+}
+
TEST_F(FeatureInfoTest, InitializeOES_texture_floatGLES2) {
SetupInitExpectations("GL_OES_texture_float");
EXPECT_FALSE(info_->feature_flags().enable_texture_float_linear);
diff --git a/gpu/command_buffer/service/framebuffer_manager_unittest.cc b/gpu/command_buffer/service/framebuffer_manager_unittest.cc
index a9b4388..ba123dd 100644
--- a/gpu/command_buffer/service/framebuffer_manager_unittest.cc
+++ b/gpu/command_buffer/service/framebuffer_manager_unittest.cc
@@ -33,7 +33,6 @@ class FramebufferManagerTest : public testing::Test {
NULL, new FeatureInfo(), kMaxTextureSize, kMaxCubemapSize),
renderbuffer_manager_(NULL, kMaxRenderbufferSize, kMaxSamples,
kDepth24Supported) {
-
}
virtual ~FramebufferManagerTest() {
manager_.Destroy(false);
@@ -110,21 +109,29 @@ class FramebufferInfoTest : public testing::Test {
FramebufferInfoTest()
: manager_(1, 1),
- texture_manager_(
- NULL, new FeatureInfo(), kMaxTextureSize, kMaxCubemapSize),
+ feature_info_(new FeatureInfo()),
renderbuffer_manager_(NULL, kMaxRenderbufferSize, kMaxSamples,
kDepth24Supported) {
+ texture_manager_.reset(new TextureManager(NULL, feature_info_.get(),
+ kMaxTextureSize, kMaxCubemapSize));
}
virtual ~FramebufferInfoTest() {
manager_.Destroy(false);
- texture_manager_.Destroy(false);
+ texture_manager_->Destroy(false);
renderbuffer_manager_.Destroy(false);
}
protected:
virtual void SetUp() {
+ InitializeContext("", "");
+ }
+
+ void InitializeContext(const char* gl_version, const char* extensions) {
gl_.reset(new ::testing::StrictMock< ::gfx::MockGLInterface>());
::gfx::MockGLInterface::SetGLInterface(gl_.get());
+ TestHelper::SetupFeatureInfoInitExpectationsWithGLVersion(gl_.get(),
+ extensions, "", gl_version);
+ feature_info_->Initialize();
manager_.CreateFramebuffer(kClient1Id, kService1Id);
error_state_.reset(new ::testing::StrictMock<gles2::MockErrorState>());
framebuffer_ = manager_.GetFramebuffer(kClient1Id);
@@ -140,7 +147,8 @@ class FramebufferInfoTest : public testing::Test {
scoped_ptr< ::testing::StrictMock< ::gfx::MockGLInterface> > gl_;
FramebufferManager manager_;
Framebuffer* framebuffer_;
- TextureManager texture_manager_;
+ scoped_refptr<FeatureInfo> feature_info_;
+ scoped_ptr<TextureManager> texture_manager_;
RenderbufferManager renderbuffer_manager_;
scoped_ptr<MockErrorState> error_state_;
};
@@ -268,7 +276,7 @@ TEST_F(FramebufferInfoTest, AttachRenderbuffer) {
// check marking them as cleared.
manager_.MarkAttachmentsAsCleared(
- framebuffer_, &renderbuffer_manager_, &texture_manager_);
+ framebuffer_, &renderbuffer_manager_, texture_manager_.get());
EXPECT_FALSE(framebuffer_->HasUnclearedAttachment(GL_COLOR_ATTACHMENT0));
EXPECT_FALSE(framebuffer_->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT));
EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE),
@@ -319,7 +327,7 @@ TEST_F(FramebufferInfoTest, AttachRenderbuffer) {
// Clear it.
manager_.MarkAttachmentsAsCleared(
- framebuffer_, &renderbuffer_manager_, &texture_manager_);
+ framebuffer_, &renderbuffer_manager_, texture_manager_.get());
EXPECT_FALSE(framebuffer_->HasUnclearedAttachment(GL_COLOR_ATTACHMENT0));
EXPECT_TRUE(framebuffer_->IsCleared());
@@ -419,9 +427,9 @@ TEST_F(FramebufferInfoTest, AttachTexture) {
EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT),
framebuffer_->IsPossiblyComplete());
- texture_manager_.CreateTexture(kTextureClient1Id, kTextureService1Id);
+ texture_manager_->CreateTexture(kTextureClient1Id, kTextureService1Id);
scoped_refptr<TextureRef> texture1(
- texture_manager_.GetTexture(kTextureClient1Id));
+ texture_manager_->GetTexture(kTextureClient1Id));
ASSERT_TRUE(texture1.get() != NULL);
// check adding one attachment
@@ -434,8 +442,8 @@ TEST_F(FramebufferInfoTest, AttachTexture) {
EXPECT_EQ(static_cast<GLenum>(0), framebuffer_->GetColorAttachmentFormat());
// Try format that doesn't work with COLOR_ATTACHMENT0
- texture_manager_.SetTarget(texture1.get(), GL_TEXTURE_2D);
- texture_manager_.SetLevelInfo(texture1.get(),
+ texture_manager_->SetTarget(texture1.get(), GL_TEXTURE_2D);
+ texture_manager_->SetLevelInfo(texture1.get(),
GL_TEXTURE_2D,
kLevel1,
kBadFormat1,
@@ -450,7 +458,7 @@ TEST_F(FramebufferInfoTest, AttachTexture) {
framebuffer_->IsPossiblyComplete());
// Try a good format.
- texture_manager_.SetLevelInfo(texture1.get(),
+ texture_manager_->SetLevelInfo(texture1.get(),
GL_TEXTURE_2D,
kLevel1,
kFormat1,
@@ -464,7 +472,7 @@ TEST_F(FramebufferInfoTest, AttachTexture) {
EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE),
framebuffer_->IsPossiblyComplete());
EXPECT_FALSE(framebuffer_->IsCleared());
- texture_manager_.SetLevelInfo(texture1.get(),
+ texture_manager_->SetLevelInfo(texture1.get(),
GL_TEXTURE_2D,
kLevel1,
kFormat1,
@@ -491,12 +499,12 @@ TEST_F(FramebufferInfoTest, AttachTexture) {
EXPECT_TRUE(attachment->cleared());
// Check replacing an attachment
- texture_manager_.CreateTexture(kTextureClient2Id, kTextureService2Id);
+ texture_manager_->CreateTexture(kTextureClient2Id, kTextureService2Id);
scoped_refptr<TextureRef> texture2(
- texture_manager_.GetTexture(kTextureClient2Id));
+ texture_manager_->GetTexture(kTextureClient2Id));
ASSERT_TRUE(texture2.get() != NULL);
- texture_manager_.SetTarget(texture2.get(), GL_TEXTURE_2D);
- texture_manager_.SetLevelInfo(texture2.get(),
+ texture_manager_->SetTarget(texture2.get(), GL_TEXTURE_2D);
+ texture_manager_->SetLevelInfo(texture2.get(),
GL_TEXTURE_2D,
kLevel2,
kFormat2,
@@ -525,7 +533,7 @@ TEST_F(FramebufferInfoTest, AttachTexture) {
EXPECT_TRUE(attachment->cleared());
// Check changing attachment
- texture_manager_.SetLevelInfo(texture2.get(),
+ texture_manager_->SetLevelInfo(texture2.get(),
GL_TEXTURE_2D,
kLevel3,
kFormat3,
@@ -550,7 +558,7 @@ TEST_F(FramebufferInfoTest, AttachTexture) {
EXPECT_FALSE(framebuffer_->IsCleared());
// Set to size 0
- texture_manager_.SetLevelInfo(texture2.get(),
+ texture_manager_->SetLevelInfo(texture2.get(),
GL_TEXTURE_2D,
kLevel3,
kFormat3,
@@ -574,6 +582,65 @@ TEST_F(FramebufferInfoTest, AttachTexture) {
EXPECT_TRUE(framebuffer_->IsCleared());
}
+class FramebufferInfoFloatTest : public FramebufferInfoTest {
+ public:
+ FramebufferInfoFloatTest()
+ : FramebufferInfoTest() {
+ }
+ virtual ~FramebufferInfoFloatTest() {
+ }
+
+ protected:
+ virtual void SetUp() {
+ InitializeContext("OpenGL ES 3.0",
+ "GL_OES_texture_float GL_EXT_color_buffer_float");
+ }
+};
+
+TEST_F(FramebufferInfoFloatTest, AttachFloatTexture) {
+ const GLuint kTextureClientId = 33;
+ const GLuint kTextureServiceId = 333;
+ const GLint kDepth = 1;
+ const GLint kBorder = 0;
+ const GLenum kType = GL_FLOAT;
+ const GLsizei kWidth = 16;
+ const GLsizei kHeight = 32;
+ const GLint kLevel = 0;
+ const GLenum kFormat = GL_RGBA;
+ const GLenum kInternalFormat = GL_RGBA32F;
+ const GLenum kTarget = GL_TEXTURE_2D;
+ const GLsizei kSamples = 0;
+ EXPECT_FALSE(framebuffer_->HasUnclearedAttachment(GL_COLOR_ATTACHMENT0));
+ EXPECT_FALSE(framebuffer_->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT));
+ EXPECT_FALSE(framebuffer_->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT));
+
+ texture_manager_->CreateTexture(kTextureClientId, kTextureServiceId);
+ scoped_refptr<TextureRef> texture(
+ texture_manager_->GetTexture(kTextureClientId));
+ ASSERT_TRUE(texture.get() != NULL);
+
+ framebuffer_->AttachTexture(
+ GL_COLOR_ATTACHMENT0, texture.get(), kTarget, kLevel, kSamples);
+ EXPECT_EQ(static_cast<GLenum>(0), framebuffer_->GetColorAttachmentFormat());
+
+ texture_manager_->SetTarget(texture.get(), GL_TEXTURE_2D);
+ texture_manager_->SetLevelInfo(texture.get(),
+ GL_TEXTURE_2D,
+ kLevel,
+ kInternalFormat,
+ kWidth,
+ kHeight,
+ kDepth,
+ kBorder,
+ kFormat,
+ kType,
+ false);
+ // Texture with a sized float internalformat is allowed as an attachment
+ // since float color attachment extension is present.
+ EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE),
+ framebuffer_->IsPossiblyComplete());
+}
+
TEST_F(FramebufferInfoTest, UnbindRenderbuffer) {
const GLuint kRenderbufferClient1Id = 33;
const GLuint kRenderbufferService1Id = 333;
@@ -618,13 +685,13 @@ TEST_F(FramebufferInfoTest, UnbindTexture) {
const GLint kLevel1 = 0;
const GLint kSamples1 = 0;
- texture_manager_.CreateTexture(kTextureClient1Id, kTextureService1Id);
+ texture_manager_->CreateTexture(kTextureClient1Id, kTextureService1Id);
scoped_refptr<TextureRef> texture1(
- texture_manager_.GetTexture(kTextureClient1Id));
+ texture_manager_->GetTexture(kTextureClient1Id));
ASSERT_TRUE(texture1.get() != NULL);
- texture_manager_.CreateTexture(kTextureClient2Id, kTextureService2Id);
+ texture_manager_->CreateTexture(kTextureClient2Id, kTextureService2Id);
scoped_refptr<TextureRef> texture2(
- texture_manager_.GetTexture(kTextureClient2Id));
+ texture_manager_->GetTexture(kTextureClient2Id));
ASSERT_TRUE(texture2.get() != NULL);
// Attach to 2 attachment points.
@@ -661,9 +728,9 @@ TEST_F(FramebufferInfoTest, IsCompleteMarkAsComplete) {
Renderbuffer* renderbuffer1 =
renderbuffer_manager_.GetRenderbuffer(kRenderbufferClient1Id);
ASSERT_TRUE(renderbuffer1 != NULL);
- texture_manager_.CreateTexture(kTextureClient2Id, kTextureService2Id);
+ texture_manager_->CreateTexture(kTextureClient2Id, kTextureService2Id);
scoped_refptr<TextureRef> texture2(
- texture_manager_.GetTexture(kTextureClient2Id));
+ texture_manager_->GetTexture(kTextureClient2Id));
ASSERT_TRUE(texture2.get() != NULL);
// Check MarkAsComlete marks as complete.
@@ -681,7 +748,7 @@ TEST_F(FramebufferInfoTest, IsCompleteMarkAsComplete) {
// Check MarkAttachmentsAsCleared marks as complete.
manager_.MarkAttachmentsAsCleared(
- framebuffer_, &renderbuffer_manager_, &texture_manager_);
+ framebuffer_, &renderbuffer_manager_, texture_manager_.get());
EXPECT_TRUE(manager_.IsComplete(framebuffer_));
// Check Unbind marks as not complete.
@@ -707,16 +774,16 @@ TEST_F(FramebufferInfoTest, GetStatus) {
Renderbuffer* renderbuffer1 =
renderbuffer_manager_.GetRenderbuffer(kRenderbufferClient1Id);
ASSERT_TRUE(renderbuffer1 != NULL);
- texture_manager_.CreateTexture(kTextureClient2Id, kTextureService2Id);
+ texture_manager_->CreateTexture(kTextureClient2Id, kTextureService2Id);
scoped_refptr<TextureRef> texture2(
- texture_manager_.GetTexture(kTextureClient2Id));
+ texture_manager_->GetTexture(kTextureClient2Id));
ASSERT_TRUE(texture2.get() != NULL);
- texture_manager_.SetTarget(texture2.get(), GL_TEXTURE_2D);
+ texture_manager_->SetTarget(texture2.get(), GL_TEXTURE_2D);
EXPECT_CALL(*gl_, CheckFramebufferStatusEXT(GL_FRAMEBUFFER))
.WillOnce(Return(GL_FRAMEBUFFER_COMPLETE))
.RetiresOnSaturation();
- framebuffer_->GetStatus(&texture_manager_, GL_FRAMEBUFFER);
+ framebuffer_->GetStatus(texture_manager_.get(), GL_FRAMEBUFFER);
// Check a second call for the same type does not call anything
if (!framebuffer_->AllowFramebufferComboCompleteMapForTesting()) {
@@ -724,14 +791,14 @@ TEST_F(FramebufferInfoTest, GetStatus) {
.WillOnce(Return(GL_FRAMEBUFFER_COMPLETE))
.RetiresOnSaturation();
}
- framebuffer_->GetStatus(&texture_manager_, GL_FRAMEBUFFER);
+ framebuffer_->GetStatus(texture_manager_.get(), GL_FRAMEBUFFER);
// Check changing the attachments calls CheckFramebufferStatus.
framebuffer_->AttachTexture(
GL_COLOR_ATTACHMENT0, texture2.get(), kTarget1, kLevel1, kSamples1);
EXPECT_CALL(*gl_, CheckFramebufferStatusEXT(GL_FRAMEBUFFER))
.WillOnce(Return(GL_FRAMEBUFFER_COMPLETE)).RetiresOnSaturation();
- framebuffer_->GetStatus(&texture_manager_, GL_FRAMEBUFFER);
+ framebuffer_->GetStatus(texture_manager_.get(), GL_FRAMEBUFFER);
// Check a second call for the same type does not call anything.
if (!framebuffer_->AllowFramebufferComboCompleteMapForTesting()) {
@@ -739,13 +806,13 @@ TEST_F(FramebufferInfoTest, GetStatus) {
.WillOnce(Return(GL_FRAMEBUFFER_COMPLETE))
.RetiresOnSaturation();
}
- framebuffer_->GetStatus(&texture_manager_, GL_FRAMEBUFFER);
+ framebuffer_->GetStatus(texture_manager_.get(), GL_FRAMEBUFFER);
// Check a second call with a different target calls CheckFramebufferStatus.
EXPECT_CALL(*gl_, CheckFramebufferStatusEXT(GL_READ_FRAMEBUFFER))
.WillOnce(Return(GL_FRAMEBUFFER_COMPLETE))
.RetiresOnSaturation();
- framebuffer_->GetStatus(&texture_manager_, GL_READ_FRAMEBUFFER);
+ framebuffer_->GetStatus(texture_manager_.get(), GL_READ_FRAMEBUFFER);
// Check a second call for the same type does not call anything.
if (!framebuffer_->AllowFramebufferComboCompleteMapForTesting()) {
@@ -753,14 +820,14 @@ TEST_F(FramebufferInfoTest, GetStatus) {
.WillOnce(Return(GL_FRAMEBUFFER_COMPLETE))
.RetiresOnSaturation();
}
- framebuffer_->GetStatus(&texture_manager_, GL_READ_FRAMEBUFFER);
+ framebuffer_->GetStatus(texture_manager_.get(), GL_READ_FRAMEBUFFER);
// Check adding another attachment calls CheckFramebufferStatus.
framebuffer_->AttachRenderbuffer(GL_DEPTH_ATTACHMENT, renderbuffer1);
EXPECT_CALL(*gl_, CheckFramebufferStatusEXT(GL_READ_FRAMEBUFFER))
.WillOnce(Return(GL_FRAMEBUFFER_COMPLETE))
.RetiresOnSaturation();
- framebuffer_->GetStatus(&texture_manager_, GL_READ_FRAMEBUFFER);
+ framebuffer_->GetStatus(texture_manager_.get(), GL_READ_FRAMEBUFFER);
// Check a second call for the same type does not call anything.
if (!framebuffer_->AllowFramebufferComboCompleteMapForTesting()) {
@@ -768,12 +835,12 @@ TEST_F(FramebufferInfoTest, GetStatus) {
.WillOnce(Return(GL_FRAMEBUFFER_COMPLETE))
.RetiresOnSaturation();
}
- framebuffer_->GetStatus(&texture_manager_, GL_READ_FRAMEBUFFER);
+ framebuffer_->GetStatus(texture_manager_.get(), GL_READ_FRAMEBUFFER);
// Check changing the format calls CheckFramebuffferStatus.
TestHelper::SetTexParameterWithExpectations(gl_.get(),
error_state_.get(),
- &texture_manager_,
+ texture_manager_.get(),
texture2.get(),
GL_TEXTURE_WRAP_S,
GL_CLAMP_TO_EDGE,
@@ -783,11 +850,11 @@ TEST_F(FramebufferInfoTest, GetStatus) {
.WillOnce(Return(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT))
.WillOnce(Return(GL_FRAMEBUFFER_COMPLETE))
.RetiresOnSaturation();
- framebuffer_->GetStatus(&texture_manager_, GL_READ_FRAMEBUFFER);
+ framebuffer_->GetStatus(texture_manager_.get(), GL_READ_FRAMEBUFFER);
// Check since it did not return FRAMEBUFFER_COMPLETE that it calls
// CheckFramebufferStatus
- framebuffer_->GetStatus(&texture_manager_, GL_READ_FRAMEBUFFER);
+ framebuffer_->GetStatus(texture_manager_.get(), GL_READ_FRAMEBUFFER);
// Check putting it back does not call CheckFramebufferStatus.
if (!framebuffer_->AllowFramebufferComboCompleteMapForTesting()) {
@@ -797,12 +864,12 @@ TEST_F(FramebufferInfoTest, GetStatus) {
}
TestHelper::SetTexParameterWithExpectations(gl_.get(),
error_state_.get(),
- &texture_manager_,
+ texture_manager_.get(),
texture2.get(),
GL_TEXTURE_WRAP_S,
GL_REPEAT,
GL_NO_ERROR);
- framebuffer_->GetStatus(&texture_manager_, GL_READ_FRAMEBUFFER);
+ framebuffer_->GetStatus(texture_manager_.get(), GL_READ_FRAMEBUFFER);
// Check Unbinding does not call CheckFramebufferStatus
framebuffer_->UnbindRenderbuffer(GL_RENDERBUFFER, renderbuffer1);
@@ -811,7 +878,7 @@ TEST_F(FramebufferInfoTest, GetStatus) {
.WillOnce(Return(GL_FRAMEBUFFER_COMPLETE))
.RetiresOnSaturation();
}
- framebuffer_->GetStatus(&texture_manager_, GL_READ_FRAMEBUFFER);
+ framebuffer_->GetStatus(texture_manager_.get(), GL_READ_FRAMEBUFFER);
}
} // namespace gles2
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
index 99b9976..414ecc6 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -8159,7 +8159,7 @@ void GLES2DecoderImpl::DoCompressedTexSubImage2D(
return;
}
if (!texture->ValidForTexture(
- target, level, xoffset, yoffset, width, height, format, type)) {
+ target, level, xoffset, yoffset, width, height, type)) {
LOCAL_SET_GL_ERROR(
GL_INVALID_VALUE, "glCompressedTexSubImage2D", "bad dimensions.");
return;
@@ -8228,9 +8228,9 @@ void GLES2DecoderImpl::DoCopyTexImage2D(
GL_INVALID_VALUE, "glCopyTexImage2D", "dimensions out of range");
return;
}
- if (!texture_manager()->ValidateTextureParameters(
- state_.GetErrorState(), "glCopyTexImage2D", target, internal_format,
- GL_UNSIGNED_BYTE, level)) {
+ if (!texture_manager()->ValidateFormatAndTypeCombination(
+ state_.GetErrorState(), "glCopyTexImage2D", internal_format,
+ GL_UNSIGNED_BYTE)) {
return;
}
@@ -8343,7 +8343,7 @@ void GLES2DecoderImpl::DoCopyTexSubImage2D(
GLenum format = 0;
if (!texture->GetLevelType(target, level, &type, &format) ||
!texture->ValidForTexture(
- target, level, xoffset, yoffset, width, height, format, type)) {
+ target, level, xoffset, yoffset, width, height, type)) {
LOCAL_SET_GL_ERROR(
GL_INVALID_VALUE, "glCopyTexSubImage2D", "bad dimensions.");
return;
@@ -8449,14 +8449,6 @@ bool GLES2DecoderImpl::ValidateTexSubImage2D(
LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "height < 0");
return false;
}
- if (!validators_->texture_format.IsValid(format)) {
- LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, format, "format");
- return false;
- }
- if (!validators_->pixel_type.IsValid(type)) {
- LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, type, "type");
- return false;
- }
TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
&state_, target);
if (!texture_ref) {
@@ -8473,10 +8465,8 @@ bool GLES2DecoderImpl::ValidateTexSubImage2D(
GL_INVALID_OPERATION, function_name, "level does not exist.");
return false;
}
- if (format != internal_format) {
- LOCAL_SET_GL_ERROR(
- GL_INVALID_OPERATION,
- function_name, "format does not match internal format.");
+ if (!texture_manager()->ValidateTextureParameters(state_.GetErrorState(),
+ function_name, format, type, internal_format, level)) {
return false;
}
if (type != current_type) {
@@ -8492,7 +8482,7 @@ bool GLES2DecoderImpl::ValidateTexSubImage2D(
return false;
}
if (!texture->ValidForTexture(
- target, level, xoffset, yoffset, width, height, format, type)) {
+ target, level, xoffset, yoffset, width, height, type)) {
LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "bad dimensions.");
return false;
}
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc
index 2756257..4d1c77e 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc
@@ -8903,6 +8903,78 @@ TEST_F(GLES2DecoderManualInitTest, ClearUniformsBeforeFirstProgramUse) {
}
}
+TEST_F(GLES2DecoderManualInitTest, TexImage2DFloatOnGLES2) {
+ InitDecoder("GL_OES_texture_float", // extensions
+ "opengl es 2.0", // gl version
+ false, // has alpha
+ false, // has depth
+ false, // has stencil
+ false, // request alpha
+ false, // request depth
+ false, // request stencil
+ false); // bind generates resource
+ DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId);
+ DoTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 17, 0, GL_RGBA, GL_FLOAT, 0, 0);
+ DoTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 16, 17, 0, GL_RGB, GL_FLOAT, 0, 0);
+ DoTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, 16, 17, 0, GL_LUMINANCE,
+ GL_FLOAT, 0, 0);
+ DoTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, 16, 17, 0, GL_ALPHA, GL_FLOAT,
+ 0, 0);
+ DoTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, 16, 17, 0,
+ GL_LUMINANCE_ALPHA, GL_FLOAT, 0, 0);
+}
+
+TEST_F(GLES2DecoderManualInitTest, TexImage2DFloatOnGLES3) {
+ InitDecoder("GL_OES_texture_float GL_EXT_color_buffer_float", // extensions
+ "opengl es 3.0", // gl version
+ false, // has alpha
+ false, // has depth
+ false, // has stencil
+ false, // request alpha
+ false, // request depth
+ false, // request stencil
+ false); // bind generates resource
+ DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId);
+ DoTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 17, 0, GL_RGBA, GL_FLOAT, 0, 0);
+ DoTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 16, 17, 0, GL_RGB, GL_FLOAT, 0, 0);
+ DoTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 16, 17, 0, GL_RGBA, GL_FLOAT, 0,
+ 0);
+ DoTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, 16, 17, 0, GL_LUMINANCE,
+ GL_FLOAT, 0, 0);
+ DoTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, 16, 17, 0, GL_ALPHA, GL_FLOAT,
+ 0, 0);
+ DoTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, 16, 17, 0,
+ GL_LUMINANCE_ALPHA, GL_FLOAT, 0, 0);
+}
+
+TEST_F(GLES2DecoderManualInitTest, TexImage2DFloatConvertsFormatDesktop) {
+ InitDecoder("GL_ARB_texture_float", // extensions
+ "2.1", // gl version
+ false, // has alpha
+ false, // has depth
+ false, // has stencil
+ false, // request alpha
+ false, // request depth
+ false, // request stencil
+ false); // bind generates resource
+ DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId);
+ DoTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 16, 17, 0, GL_RGBA, GL_FLOAT, 0,
+ 0);
+ DoTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, 16, 17, 0, GL_RGB, GL_FLOAT, 0, 0);
+ DoTexImage2DConvertInternalFormat(GL_TEXTURE_2D, 0, GL_RGBA, 16, 17, 0,
+ GL_RGBA, GL_FLOAT, 0, 0, GL_RGBA32F_ARB);
+ DoTexImage2DConvertInternalFormat(GL_TEXTURE_2D, 0, GL_RGB, 16, 17, 0,
+ GL_RGB, GL_FLOAT, 0, 0, GL_RGB32F_ARB);
+ DoTexImage2DConvertInternalFormat(GL_TEXTURE_2D, 0, GL_LUMINANCE, 16, 17, 0,
+ GL_LUMINANCE, GL_FLOAT, 0, 0,
+ GL_LUMINANCE32F_ARB);
+ DoTexImage2DConvertInternalFormat(GL_TEXTURE_2D, 0, GL_ALPHA, 16, 17, 0,
+ GL_ALPHA, GL_FLOAT, 0, 0, GL_ALPHA32F_ARB);
+ DoTexImage2DConvertInternalFormat(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, 16,
+ 17, 0, GL_LUMINANCE_ALPHA, GL_FLOAT, 0, 0,
+ GL_LUMINANCE_ALPHA32F_ARB);
+}
+
// 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 6f74bde..0b35b39 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc
@@ -141,8 +141,21 @@ void GLES2DecoderTestBase::InitDecoderWithCommandLine(
InSequence sequence;
+ surface_ = new gfx::GLSurfaceStub;
+ surface_->SetSize(gfx::Size(kBackBufferWidth, kBackBufferHeight));
+
+ // Context needs to be created before initializing ContextGroup, which will
+ // in turn initialize FeatureInfo, which needs a context to determine
+ // extension support.
+ context_ = new gfx::GLContextStubWithExtensions;
+ context_->AddExtensionsString(extensions);
+ context_->SetGLVersionString(gl_version);
+
+ context_->MakeCurrent(surface_.get());
+ gfx::GLSurface::InitializeDynamicMockBindingsForTests(context_);
+
TestHelper::SetupContextGroupInitExpectations(gl_.get(),
- DisallowedFeatures(), extensions);
+ DisallowedFeatures(), extensions, gl_version);
// We initialize the ContextGroup with a MockGLES2Decoder so that
// we can use the ContextGroup to figure out how the real GLES2Decoder
@@ -281,16 +294,6 @@ void GLES2DecoderTestBase::InitDecoderWithCommandLine(
shared_memory_id_ = kSharedMemoryId;
shared_memory_base_ = buffer.ptr;
- surface_ = new gfx::GLSurfaceStub;
- surface_->SetSize(gfx::Size(kBackBufferWidth, kBackBufferHeight));
-
- context_ = new gfx::GLContextStubWithExtensions;
- context_->AddExtensionsString(extensions);
- context_->SetGLVersionString(gl_version);
-
- context_->MakeCurrent(surface_.get());
- gfx::GLSurface::InitializeDynamicMockBindingsForTests(context_);
-
int32 attributes[] = {
EGL_ALPHA_SIZE, request_alpha ? 8 : 0,
EGL_DEPTH_SIZE, request_depth ? 24 : 0,
@@ -834,6 +837,28 @@ void GLES2DecoderTestBase::DoTexImage2D(
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
}
+void GLES2DecoderTestBase::DoTexImage2DConvertInternalFormat(
+ GLenum target, GLint level, GLenum requested_internal_format,
+ GLsizei width, GLsizei height, GLint border,
+ GLenum format, GLenum type,
+ uint32 shared_memory_id, uint32 shared_memory_offset,
+ GLenum expected_internal_format) {
+ EXPECT_CALL(*gl_, GetError())
+ .WillOnce(Return(GL_NO_ERROR))
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, TexImage2D(target, level, expected_internal_format,
+ width, height, border, format, type, _))
+ .Times(1)
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, GetError())
+ .WillOnce(Return(GL_NO_ERROR))
+ .RetiresOnSaturation();
+ cmds::TexImage2D cmd;
+ cmd.Init(target, level, requested_internal_format, width, height, border,
+ format, type, shared_memory_id, shared_memory_offset);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+}
+
void GLES2DecoderTestBase::DoCompressedTexImage2D(
GLenum target, GLint level, GLenum format,
GLsizei width, GLsizei height, GLint border,
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 733724f..62ca07c 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h
@@ -244,6 +244,12 @@ class GLES2DecoderTestBase : public testing::Test {
GLsizei width, GLsizei height, GLint border,
GLenum format, GLenum type,
uint32 shared_memory_id, uint32 shared_memory_offset);
+ void DoTexImage2DConvertInternalFormat(
+ GLenum target, GLint level, GLenum requested_internal_format,
+ GLsizei width, GLsizei height, GLint border,
+ GLenum format, GLenum type,
+ uint32 shared_memory_id, uint32 shared_memory_offset,
+ GLenum expected_internal_format);
void DoRenderbufferStorage(
GLenum target, GLenum internal_format, GLenum actual_format,
GLsizei width, GLsizei height, GLenum error);
diff --git a/gpu/command_buffer/service/test_helper.cc b/gpu/command_buffer/service/test_helper.cc
index 92c5ec4..c164eea 100644
--- a/gpu/command_buffer/service/test_helper.cc
+++ b/gpu/command_buffer/service/test_helper.cc
@@ -227,16 +227,20 @@ void TestHelper::SetupTextureManagerDestructionExpectations(
void TestHelper::SetupContextGroupInitExpectations(
::gfx::MockGLInterface* gl,
const DisallowedFeatures& disallowed_features,
- const char* extensions) {
+ const char* extensions,
+ const char* gl_version) {
InSequence sequence;
- SetupFeatureInfoInitExpectations(gl, extensions);
+ SetupFeatureInfoInitExpectationsWithGLVersion(gl, extensions, "", gl_version);
+
+ std::string l_version(StringToLowerASCII(std::string(gl_version)));
+ bool is_es3 = (l_version.substr(0, 12) == "opengl es 3.");
EXPECT_CALL(*gl, GetIntegerv(GL_MAX_RENDERBUFFER_SIZE, _))
.WillOnce(SetArgumentPointee<1>(kMaxRenderbufferSize))
.RetiresOnSaturation();
if (strstr(extensions, "GL_EXT_framebuffer_multisample") ||
- strstr(extensions, "GL_EXT_multisampled_render_to_texture")) {
+ strstr(extensions, "GL_EXT_multisampled_render_to_texture") || is_es3) {
EXPECT_CALL(*gl, GetIntegerv(GL_MAX_SAMPLES, _))
.WillOnce(SetArgumentPointee<1>(kMaxSamples))
.RetiresOnSaturation();
@@ -297,6 +301,78 @@ void TestHelper::SetupFeatureInfoInitExpectationsWithGLVersion(
EXPECT_CALL(*gl, GetString(GL_VERSION))
.WillOnce(Return(reinterpret_cast<const uint8*>(gl_version)))
.RetiresOnSaturation();
+
+ std::string l_version(StringToLowerASCII(std::string(gl_version)));
+ bool is_es3 = (l_version.substr(0, 12) == "opengl es 3.");
+
+ if (strstr(extensions, "GL_ARB_texture_float") ||
+ (is_es3 && strstr(extensions, "GL_EXT_color_buffer_float"))) {
+ static const GLuint gl_ids[] = {101, 102};
+ const GLsizei width = 16;
+ EXPECT_CALL(*gl, GetIntegerv(GL_FRAMEBUFFER_BINDING, _))
+ .WillOnce(SetArgumentPointee<1>(gl_ids[0]))
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl, GetIntegerv(GL_TEXTURE_BINDING_2D, _))
+ .WillOnce(SetArgumentPointee<1>(gl_ids[0]))
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl, GenTextures(1, _))
+ .WillOnce(SetArrayArgument<1>(gl_ids + 1, gl_ids + 2))
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl, GenFramebuffersEXT(1, _))
+ .WillOnce(SetArrayArgument<1>(gl_ids + 1, gl_ids + 2))
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl, BindTexture(GL_TEXTURE_2D, gl_ids[1]))
+ .Times(1)
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl, TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
+ GL_NEAREST))
+ .Times(1)
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl, TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width, width, 0,
+ GL_RGBA, GL_FLOAT, _))
+ .Times(1)
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl, BindFramebufferEXT(GL_FRAMEBUFFER, gl_ids[1]))
+ .Times(1)
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl, FramebufferTexture2DEXT(GL_FRAMEBUFFER,
+ GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, gl_ids[1], 0))
+ .Times(1)
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl, CheckFramebufferStatusEXT(GL_FRAMEBUFFER))
+ .WillOnce(Return(GL_FRAMEBUFFER_COMPLETE))
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl, TexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, width, width, 0,
+ GL_RGB, GL_FLOAT, _))
+ .Times(1)
+ .RetiresOnSaturation();
+ if (is_es3) {
+ EXPECT_CALL(*gl, CheckFramebufferStatusEXT(GL_FRAMEBUFFER))
+ .WillOnce(Return(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT))
+ .RetiresOnSaturation();
+ } else {
+ EXPECT_CALL(*gl, CheckFramebufferStatusEXT(GL_FRAMEBUFFER))
+ .WillOnce(Return(GL_FRAMEBUFFER_COMPLETE))
+ .RetiresOnSaturation();
+ }
+ EXPECT_CALL(*gl, DeleteFramebuffersEXT(1, _))
+ .Times(1)
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl, DeleteTextures(1, _))
+ .Times(1)
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl, BindFramebufferEXT(GL_FRAMEBUFFER, gl_ids[0]))
+ .Times(1)
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl, BindTexture(GL_TEXTURE_2D, gl_ids[0]))
+ .Times(1)
+ .RetiresOnSaturation();
+ if (DCHECK_IS_ON()) {
+ EXPECT_CALL(*gl, GetError())
+ .WillOnce(Return(GL_NO_ERROR))
+ .RetiresOnSaturation();
+ }
+ }
}
void TestHelper::SetupExpectationsForClearingUniforms(
diff --git a/gpu/command_buffer/service/test_helper.h b/gpu/command_buffer/service/test_helper.h
index a619073..99041e7 100644
--- a/gpu/command_buffer/service/test_helper.h
+++ b/gpu/command_buffer/service/test_helper.h
@@ -65,7 +65,8 @@ class TestHelper {
static void SetupContextGroupInitExpectations(
::gfx::MockGLInterface* gl,
const DisallowedFeatures& disallowed_features,
- const char* extensions);
+ const char* extensions,
+ const char* gl_version);
static void SetupFeatureInfoInitExpectations(
::gfx::MockGLInterface* gl, const char* extensions);
static void SetupFeatureInfoInitExpectationsWithGLVersion(
diff --git a/gpu/command_buffer/service/texture_manager.cc b/gpu/command_buffer/service/texture_manager.cc
index 72d3b4c..a0a60c1 100644
--- a/gpu/command_buffer/service/texture_manager.cc
+++ b/gpu/command_buffer/service/texture_manager.cc
@@ -517,7 +517,6 @@ bool Texture::ValidForTexture(
GLint yoffset,
GLsizei width,
GLsizei height,
- GLenum format,
GLenum type) const {
size_t face_index = GLTargetToFaceIndex(target);
if (level >= 0 && face_index < level_infos_.size() &&
@@ -531,7 +530,6 @@ bool Texture::ValidForTexture(
yoffset >= 0 &&
right <= info.width &&
top <= info.height &&
- format == info.internal_format &&
type == info.type;
}
return false;
@@ -1259,20 +1257,10 @@ void TextureManager::IncFramebufferStateChangeCount() {
framebuffer_manager_->IncFramebufferStateChangeCount();
}
-bool TextureManager::ValidateTextureParameters(
- ErrorState* error_state, const char* function_name,
- GLenum target, GLenum format, GLenum type, GLint level) {
+bool TextureManager::ValidateFormatAndTypeCombination(
+ ErrorState* error_state, const char* function_name, GLenum format,
+ GLenum type) {
if (!feature_info_->GetTextureFormatValidator(format).IsValid(type)) {
- ERRORSTATE_SET_GL_ERROR(
- error_state, GL_INVALID_OPERATION, function_name,
- (std::string("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) {
ERRORSTATE_SET_GL_ERROR(
error_state, GL_INVALID_OPERATION, function_name,
(std::string("invalid type ") +
@@ -1283,6 +1271,40 @@ bool TextureManager::ValidateTextureParameters(
return true;
}
+bool TextureManager::ValidateTextureParameters(
+ ErrorState* error_state, const char* function_name,
+ GLenum format, GLenum type, GLenum internal_format, GLint level) {
+ const Validators* validators = feature_info_->validators();
+ if (!validators->texture_format.IsValid(format)) {
+ ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(
+ error_state, function_name, format, "format");
+ return false;
+ }
+ if (!validators->pixel_type.IsValid(type)) {
+ ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(
+ error_state, function_name, type, "type");
+ return false;
+ }
+ if (format != internal_format &&
+ !((internal_format == GL_RGBA32F && format == GL_RGBA) ||
+ (internal_format == GL_RGB32F && format == GL_RGB))) {
+ ERRORSTATE_SET_GL_ERROR(
+ error_state, GL_INVALID_OPERATION, function_name,
+ "format != internalformat");
+ return false;
+ }
+ uint32 channels = GLES2Util::GetChannelsForFormat(format);
+ if ((channels & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0 && level) {
+ ERRORSTATE_SET_GL_ERROR(
+ error_state, GL_INVALID_OPERATION, function_name,
+ (std::string("invalid format ") + GLES2Util::GetStringEnum(format) +
+ " for level != 0").c_str());
+ return false;
+ }
+ return ValidateFormatAndTypeCombination(error_state, function_name,
+ format, type);
+}
+
// Gets the texture id for a given target.
TextureRef* TextureManager::GetTextureInfoForTarget(
ContextState* state, GLenum target) {
@@ -1336,31 +1358,15 @@ bool TextureManager::ValidateTexImage2D(
error_state, function_name, args.target, "target");
return false;
}
- if (!validators->texture_format.IsValid(args.internal_format)) {
+ if (!validators->texture_internal_format.IsValid(args.internal_format)) {
ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(
error_state, function_name, args.internal_format,
- "internal_format");
- return false;
- }
- if (!validators->texture_format.IsValid(args.format)) {
- ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(
- error_state, function_name, args.format, "format");
- return false;
- }
- if (!validators->pixel_type.IsValid(args.type)) {
- ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(
- error_state, function_name, args.type, "type");
- return false;
- }
- if (args.format != args.internal_format) {
- ERRORSTATE_SET_GL_ERROR(
- error_state, GL_INVALID_OPERATION, function_name,
- "format != internalFormat");
+ "internalformat");
return false;
}
if (!ValidateTextureParameters(
- error_state, function_name, args.target, args.format, args.type,
- args.level)) {
+ error_state, function_name, args.format, args.type,
+ args.internal_format, args.level)) {
return false;
}
if (!ValidForTarget(args.target, args.level, args.width, args.height, 1) ||
@@ -1396,7 +1402,7 @@ bool TextureManager::ValidateTexImage2D(
// They both use the same MemoryTracker, and this call just re-routes
// to it.
if (!memory_tracker_managed_->EnsureGPUMemoryAvailable(args.pixels_size)) {
- ERRORSTATE_SET_GL_ERROR(error_state, GL_OUT_OF_MEMORY, "glTexImage2D",
+ ERRORSTATE_SET_GL_ERROR(error_state, GL_OUT_OF_MEMORY, function_name,
"out of memory");
return false;
}
diff --git a/gpu/command_buffer/service/texture_manager.h b/gpu/command_buffer/service/texture_manager.h
index b74ef91..c44bef3 100644
--- a/gpu/command_buffer/service/texture_manager.h
+++ b/gpu/command_buffer/service/texture_manager.h
@@ -116,7 +116,7 @@ class GPU_EXPORT Texture {
}
// Returns true of the given dimensions are inside the dimensions of the
- // level and if the format and type match the level.
+ // level and if the type matches the level.
bool ValidForTexture(
GLint target,
GLint level,
@@ -124,7 +124,6 @@ class GPU_EXPORT Texture {
GLint yoffset,
GLsizei width,
GLsizei height,
- GLenum format,
GLenum type) const;
bool IsValid() const {
@@ -707,9 +706,15 @@ class GPU_EXPORT TextureManager {
TextureRef* GetTextureInfoForTargetUnlessDefault(
ContextState* state, GLenum target);
+ bool ValidateFormatAndTypeCombination(
+ ErrorState* error_state, const char* function_name,
+ GLenum format, GLenum type);
+
+ // Note that internal_format is only checked in relation to the format
+ // parameter, so that this function may be used to validate texSubImage2D.
bool ValidateTextureParameters(
ErrorState* error_state, const char* function_name,
- GLenum target, GLenum format, GLenum type, GLint level);
+ GLenum format, GLenum type, GLenum internal_format, GLint level);
private:
friend class Texture;
diff --git a/gpu/command_buffer/service/texture_manager_unittest.cc b/gpu/command_buffer/service/texture_manager_unittest.cc
index 002f2f8..ada24a8 100644
--- a/gpu/command_buffer/service/texture_manager_unittest.cc
+++ b/gpu/command_buffer/service/texture_manager_unittest.cc
@@ -1042,43 +1042,40 @@ TEST_F(TextureTest, ValidForTexture) {
Texture* texture = texture_ref_->texture();
EXPECT_FALSE(texture->ValidForTexture(
GL_TEXTURE_CUBE_MAP_NEGATIVE_Z,
- 1, 0, 0, 4, 5, GL_RGBA, GL_UNSIGNED_BYTE));
+ 1, 0, 0, 4, 5, GL_UNSIGNED_BYTE));
// Check bad level.
EXPECT_FALSE(texture->ValidForTexture(
- GL_TEXTURE_2D, 0, 0, 0, 4, 5, GL_RGBA, GL_UNSIGNED_BYTE));
+ GL_TEXTURE_2D, 0, 0, 0, 4, 5, GL_UNSIGNED_BYTE));
// Check bad xoffset.
EXPECT_FALSE(texture->ValidForTexture(
- GL_TEXTURE_2D, 1, -1, 0, 4, 5, GL_RGBA, GL_UNSIGNED_BYTE));
+ GL_TEXTURE_2D, 1, -1, 0, 4, 5, GL_UNSIGNED_BYTE));
// Check bad xoffset + width > width.
EXPECT_FALSE(texture->ValidForTexture(
- GL_TEXTURE_2D, 1, 1, 0, 4, 5, GL_RGBA, GL_UNSIGNED_BYTE));
+ GL_TEXTURE_2D, 1, 1, 0, 4, 5, GL_UNSIGNED_BYTE));
// Check bad yoffset.
EXPECT_FALSE(texture->ValidForTexture(
- GL_TEXTURE_2D, 1, 0, -1, 4, 5, GL_RGBA, GL_UNSIGNED_BYTE));
+ GL_TEXTURE_2D, 1, 0, -1, 4, 5, GL_UNSIGNED_BYTE));
// Check bad yoffset + height > height.
EXPECT_FALSE(texture->ValidForTexture(
- GL_TEXTURE_2D, 1, 0, 1, 4, 5, GL_RGBA, GL_UNSIGNED_BYTE));
+ GL_TEXTURE_2D, 1, 0, 1, 4, 5, GL_UNSIGNED_BYTE));
// Check bad width.
EXPECT_FALSE(texture->ValidForTexture(
- GL_TEXTURE_2D, 1, 0, 0, 5, 5, GL_RGBA, GL_UNSIGNED_BYTE));
+ GL_TEXTURE_2D, 1, 0, 0, 5, 5, GL_UNSIGNED_BYTE));
// Check bad height.
EXPECT_FALSE(texture->ValidForTexture(
- GL_TEXTURE_2D, 1, 0, 0, 4, 6, GL_RGBA, GL_UNSIGNED_BYTE));
- // Check bad format.
- EXPECT_FALSE(texture->ValidForTexture(
- GL_TEXTURE_2D, 1, 0, 0, 4, 5, GL_RGB, GL_UNSIGNED_BYTE));
+ GL_TEXTURE_2D, 1, 0, 0, 4, 6, GL_UNSIGNED_BYTE));
// Check bad type.
EXPECT_FALSE(texture->ValidForTexture(
- GL_TEXTURE_2D, 1, 0, 0, 4, 5, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4));
+ GL_TEXTURE_2D, 1, 0, 0, 4, 5, GL_UNSIGNED_SHORT_4_4_4_4));
// Check valid full size
EXPECT_TRUE(texture->ValidForTexture(
- GL_TEXTURE_2D, 1, 0, 0, 4, 5, GL_RGBA, GL_UNSIGNED_BYTE));
+ GL_TEXTURE_2D, 1, 0, 0, 4, 5, GL_UNSIGNED_BYTE));
// Check valid particial size.
EXPECT_TRUE(texture->ValidForTexture(
- GL_TEXTURE_2D, 1, 1, 1, 2, 3, GL_RGBA, GL_UNSIGNED_BYTE));
+ GL_TEXTURE_2D, 1, 1, 1, 2, 3, GL_UNSIGNED_BYTE));
manager_->RemoveTexture(kClient1Id);
EXPECT_TRUE(texture->ValidForTexture(
- GL_TEXTURE_2D, 1, 0, 0, 4, 5, GL_RGBA, GL_UNSIGNED_BYTE));
+ GL_TEXTURE_2D, 1, 0, 0, 4, 5, GL_UNSIGNED_BYTE));
}
TEST_F(TextureTest, FloatNotLinear) {
diff --git a/ui/gl/gl_context.cc b/ui/gl/gl_context.cc
index dc3a3e8..cd9a28c 100644
--- a/ui/gl/gl_context.cc
+++ b/ui/gl/gl_context.cc
@@ -66,6 +66,13 @@ std::string GLContext::GetGLVersion() {
return std::string(version ? version : "");
}
+std::string GLContext::GetGLRenderer() {
+ DCHECK(IsCurrent(NULL));
+ const char *renderer =
+ reinterpret_cast<const char*>(glGetString(GL_RENDERER));
+ return std::string(renderer ? renderer : "");
+}
+
bool GLContext::HasExtension(const char* name) {
std::string extensions = GetExtensions();
extensions += " ";
@@ -79,8 +86,9 @@ bool GLContext::HasExtension(const char* name) {
const GLVersionInfo* GLContext::GetVersionInfo() {
if(!version_info_) {
std::string version = GetGLVersion();
+ std::string renderer = GetGLRenderer();
version_info_ = scoped_ptr<GLVersionInfo>(
- new GLVersionInfo(version.c_str()));
+ new GLVersionInfo(version.c_str(), renderer.c_str()));
}
return version_info_.get();
}
diff --git a/ui/gl/gl_context.h b/ui/gl/gl_context.h
index 66a7631..f40b1bb 100644
--- a/ui/gl/gl_context.h
+++ b/ui/gl/gl_context.h
@@ -108,6 +108,12 @@ class GL_EXPORT GLContext : public base::RefCounted<GLContext> {
// being released or destroyed.
void OnReleaseVirtuallyCurrent(GLContext* virtual_context);
+ // Returns the GL version string. The context must be current.
+ virtual std::string GetGLVersion();
+
+ // Returns the GL renderer string. The context must be current.
+ virtual std::string GetGLRenderer();
+
protected:
virtual ~GLContext();
@@ -123,9 +129,6 @@ class GL_EXPORT GLContext : public base::RefCounted<GLContext> {
// Returns the last real (non-virtual) GLContext made current.
static GLContext* GetRealCurrent();
- // Returns the GL version string. The context must be current.
- virtual std::string GetGLVersion();
-
private:
friend class base::RefCounted<GLContext>;
diff --git a/ui/gl/gl_context_stub.cc b/ui/gl/gl_context_stub.cc
index 56fb3c7..1d39d3e 100644
--- a/ui/gl/gl_context_stub.cc
+++ b/ui/gl/gl_context_stub.cc
@@ -39,6 +39,10 @@ std::string GLContextStub::GetExtensions() {
return std::string();
}
+std::string GLContextStub::GetGLRenderer() {
+ return std::string("CHROMIUM");
+}
+
GLContextStub::~GLContextStub() {}
} // namespace gfx
diff --git a/ui/gl/gl_context_stub.h b/ui/gl/gl_context_stub.h
index 8fca5b7..d57e02e 100644
--- a/ui/gl/gl_context_stub.h
+++ b/ui/gl/gl_context_stub.h
@@ -24,6 +24,7 @@ class GL_EXPORT GLContextStub : public GLContextReal {
virtual void* GetHandle() OVERRIDE;
virtual void SetSwapInterval(int interval) OVERRIDE;
virtual std::string GetExtensions() OVERRIDE;
+ virtual std::string GetGLRenderer() OVERRIDE;
protected:
virtual ~GLContextStub();
diff --git a/ui/gl/gl_gl_api_implementation.cc b/ui/gl/gl_gl_api_implementation.cc
index 9184fc3..fe98fba 100644
--- a/ui/gl/gl_gl_api_implementation.cc
+++ b/ui/gl/gl_gl_api_implementation.cc
@@ -14,6 +14,7 @@
#include "ui/gl/gl_state_restorer.h"
#include "ui/gl/gl_surface.h"
#include "ui/gl/gl_switches.h"
+#include "ui/gl/gl_version_info.h"
namespace gfx {
@@ -23,6 +24,8 @@ static GLApi* g_gl;
static RealGLApi* g_real_gl;
// A GL Api that calls TRACE and then calls another GL api.
static TraceGLApi* g_trace_gl;
+// GL version used when initializing dynamic bindings.
+static GLVersionInfo* g_version_info = NULL;
namespace {
@@ -40,7 +43,28 @@ static inline GLenum GetTexInternalFormat(GLenum internal_format,
GLenum type) {
GLenum gl_internal_format = GetInternalFormat(internal_format);
- if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
+ // g_version_info must be initialized when this function is bound.
+ DCHECK(gfx::g_version_info);
+ if (type == GL_FLOAT && gfx::g_version_info->is_angle &&
+ gfx::g_version_info->is_es2) {
+ // It's possible that the texture is using a sized internal format, and
+ // ANGLE exposing GLES2 API doesn't support those.
+ // TODO(oetuaho@nvidia.com): Remove these conversions once ANGLE has the
+ // support.
+ // http://code.google.com/p/angleproject/issues/detail?id=556
+ switch (format) {
+ case GL_RGBA:
+ gl_internal_format = GL_RGBA;
+ break;
+ case GL_RGB:
+ gl_internal_format = GL_RGB;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (gfx::g_version_info->is_es)
return gl_internal_format;
if (type == GL_FLOAT) {
@@ -208,6 +232,9 @@ void SetGLToRealGLApi() {
void InitializeDynamicGLBindingsGL(GLContext* context) {
g_driver_gl.InitializeCustomDynamicBindings(context);
+ DCHECK(context && context->IsCurrent(NULL) && !g_version_info);
+ g_version_info = new GLVersionInfo(context->GetGLVersion().c_str(),
+ context->GetGLRenderer().c_str());
}
void InitializeDebugGLBindingsGL() {
@@ -233,6 +260,10 @@ void ClearGLBindingsGL() {
delete g_current_gl_context_tls;
g_current_gl_context_tls = NULL;
}
+ if (g_version_info) {
+ delete g_version_info;
+ g_version_info = NULL;
+ }
}
GLApi::GLApi() {
diff --git a/ui/gl/gl_version_info.cc b/ui/gl/gl_version_info.cc
index a45219a..996c44f 100644
--- a/ui/gl/gl_version_info.cc
+++ b/ui/gl/gl_version_info.cc
@@ -8,7 +8,7 @@
namespace gfx {
-GLVersionInfo::GLVersionInfo(const char* version_str)
+GLVersionInfo::GLVersionInfo(const char* version_str, const char* renderer_str)
: is_es(false),
is_es1(false),
is_es2(false),
@@ -16,7 +16,8 @@ GLVersionInfo::GLVersionInfo(const char* version_str)
is_gl1(false),
is_gl2(false),
is_gl3(false),
- is_gl4(false) {
+ is_gl4(false),
+ is_angle(false) {
if (version_str) {
std::string lstr(StringToLowerASCII(std::string(version_str)));
is_es = (lstr.substr(0, 9) == "opengl es");
@@ -33,6 +34,9 @@ GLVersionInfo::GLVersionInfo(const char* version_str)
is_gl1 = !is_gl2 && !is_gl3 && !is_gl4;
}
}
+ if (renderer_str) {
+ is_angle = StartsWithASCII(renderer_str, "ANGLE", true);
+ }
}
} // namespace gfx
diff --git a/ui/gl/gl_version_info.h b/ui/gl/gl_version_info.h
index c8ecb07..13b323f 100644
--- a/ui/gl/gl_version_info.h
+++ b/ui/gl/gl_version_info.h
@@ -11,7 +11,7 @@
namespace gfx {
struct GLVersionInfo {
- explicit GLVersionInfo(const char* version_str);
+ GLVersionInfo(const char* version_str, const char* renderer_str);
// New flags, such as is_gl4_4 could be introduced as needed.
// For now, this level of granularity is enough.
@@ -25,6 +25,8 @@ struct GLVersionInfo {
bool is_gl3;
bool is_gl4;
+ bool is_angle;
+
private:
DISALLOW_COPY_AND_ASSIGN(GLVersionInfo);
};