summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorgman@chromium.org <gman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-06-07 01:33:30 +0000
committergman@chromium.org <gman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-06-07 01:33:30 +0000
commit473c01ccb10d0e459a6f06784c38ed8e2bc7215b (patch)
tree9ddc6e7fb736d2c20764f90f259a1e3613a98fca
parent0b407aea9852913d5a3825de8e9a9db017b49982 (diff)
downloadchromium_src-473c01ccb10d0e459a6f06784c38ed8e2bc7215b.zip
chromium_src-473c01ccb10d0e459a6f06784c38ed8e2bc7215b.tar.gz
chromium_src-473c01ccb10d0e459a6f06784c38ed8e2bc7215b.tar.bz2
Optimize TexSubImage2D and BufferSubData
They now call TexImage2D and BufferData if possible. TEST=some unit test, ran conformance tests BUG=84977 R=apatrick@chromium.org Review URL: http://codereview.chromium.org/6993049 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@88078 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--gpu/command_buffer/service/buffer_manager.cc13
-rw-r--r--gpu/command_buffer/service/buffer_manager.h13
-rw-r--r--gpu/command_buffer/service/buffer_manager_unittest.cc16
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder.cc110
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc7
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc3
6 files changed, 123 insertions, 39 deletions
diff --git a/gpu/command_buffer/service/buffer_manager.cc b/gpu/command_buffer/service/buffer_manager.cc
index fadbbad..e5f1fbd 100644
--- a/gpu/command_buffer/service/buffer_manager.cc
+++ b/gpu/command_buffer/service/buffer_manager.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 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.
@@ -58,13 +58,16 @@ BufferManager::BufferInfo::BufferInfo(GLuint service_id)
: service_id_(service_id),
target_(0),
size_(0),
+ usage_(GL_STATIC_DRAW),
shadowed_(false) {
}
BufferManager::BufferInfo::~BufferInfo() { }
-void BufferManager::BufferInfo::SetSize(GLsizeiptr size, bool shadow) {
+void BufferManager::BufferInfo::SetInfo(
+ GLsizeiptr size, GLenum usage, bool shadow) {
DCHECK(!IsDeleted());
+ usage_ = usage;
if (size != size_ || shadow != shadowed_) {
shadowed_ = shadow;
size_ = size;
@@ -188,9 +191,11 @@ bool BufferManager::GetClientId(GLuint service_id, GLuint* client_id) const {
return false;
}
-void BufferManager::SetSize(BufferManager::BufferInfo* info, GLsizeiptr size) {
+void BufferManager::SetInfo(
+ BufferManager::BufferInfo* info, GLsizeiptr size, GLenum usage) {
DCHECK(info);
- info->SetSize(size,
+ info->SetInfo(size,
+ usage,
info->target() == GL_ELEMENT_ARRAY_BUFFER ||
allow_buffers_on_multiple_targets_);
}
diff --git a/gpu/command_buffer/service/buffer_manager.h b/gpu/command_buffer/service/buffer_manager.h
index 6569116..6f67e53 100644
--- a/gpu/command_buffer/service/buffer_manager.h
+++ b/gpu/command_buffer/service/buffer_manager.h
@@ -38,6 +38,10 @@ class BufferManager {
return size_;
}
+ GLenum usage() const {
+ return usage_;
+ }
+
// Sets a range of data for this buffer. Returns false if the offset or size
// is out of range.
bool SetRange(
@@ -115,7 +119,7 @@ class BufferManager {
ClearCache();
}
- void SetSize(GLsizeiptr size, bool shadow);
+ void SetInfo(GLsizeiptr size, GLenum usage, bool shadow);
// Clears any cache of index ranges.
void ClearCache();
@@ -131,6 +135,9 @@ class BufferManager {
// Size of buffer.
GLsizeiptr size_;
+ // Usage of buffer.
+ GLenum usage_;
+
// Whether or not the data is shadowed.
bool shadowed_;
@@ -161,8 +168,8 @@ class BufferManager {
// Gets a client id for a given service id.
bool GetClientId(GLuint service_id, GLuint* client_id) const;
- // Sets the size of a buffer.
- void SetSize(BufferInfo* info, GLsizeiptr size);
+ // Sets the size and usage of a buffer.
+ void SetInfo(BufferInfo* info, GLsizeiptr size, GLenum usage);
// Sets the target of a buffer. Returns false if the target can not be set.
bool SetTarget(BufferInfo* info, GLenum target);
diff --git a/gpu/command_buffer/service/buffer_manager_unittest.cc b/gpu/command_buffer/service/buffer_manager_unittest.cc
index af09788..1e4258b 100644
--- a/gpu/command_buffer/service/buffer_manager_unittest.cc
+++ b/gpu/command_buffer/service/buffer_manager_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 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.
@@ -49,6 +49,7 @@ TEST_F(BufferManagerTest, Basic) {
ASSERT_TRUE(info1 != NULL);
EXPECT_EQ(0u, GetTarget(info1));
EXPECT_EQ(0, info1->size());
+ EXPECT_EQ(static_cast<GLenum>(GL_STATIC_DRAW), info1->usage());
EXPECT_FALSE(info1->IsDeleted());
EXPECT_EQ(kServiceBuffer1Id, info1->service_id());
GLuint client_id = 0;
@@ -57,8 +58,9 @@ TEST_F(BufferManagerTest, Basic) {
manager_.SetTarget(info1, GL_ELEMENT_ARRAY_BUFFER);
EXPECT_EQ(static_cast<GLenum>(GL_ELEMENT_ARRAY_BUFFER), GetTarget(info1));
// Check we and set its size.
- manager_.SetSize(info1, kBuffer1Size);
+ manager_.SetInfo(info1, kBuffer1Size, GL_DYNAMIC_DRAW);
EXPECT_EQ(kBuffer1Size, info1->size());
+ EXPECT_EQ(static_cast<GLenum>(GL_DYNAMIC_DRAW), info1->usage());
// Check we get nothing for a non-existent buffer.
EXPECT_TRUE(manager_.GetBufferInfo(kClientBuffer2Id) == NULL);
// Check trying to a remove non-existent buffers does not crash.
@@ -94,7 +96,7 @@ TEST_F(BufferManagerTest, SetRange) {
BufferManager::BufferInfo* info = manager_.GetBufferInfo(kClientBufferId);
ASSERT_TRUE(info != NULL);
manager_.SetTarget(info, GL_ELEMENT_ARRAY_BUFFER);
- manager_.SetSize(info, sizeof(data));
+ manager_.SetInfo(info, sizeof(data), GL_STATIC_DRAW);
EXPECT_TRUE(info->SetRange(0, sizeof(data), data));
EXPECT_TRUE(info->SetRange(sizeof(data), 0, data));
EXPECT_FALSE(info->SetRange(sizeof(data), 1, data));
@@ -111,7 +113,7 @@ TEST_F(BufferManagerTest, GetRange) {
BufferManager::BufferInfo* info = manager_.GetBufferInfo(kClientBufferId);
ASSERT_TRUE(info != NULL);
manager_.SetTarget(info, GL_ELEMENT_ARRAY_BUFFER);
- manager_.SetSize(info, sizeof(data));
+ manager_.SetInfo(info, sizeof(data), GL_STATIC_DRAW);
const char* buf = static_cast<const char*>(info->GetRange(0, sizeof(data)));
ASSERT_TRUE(buf != NULL);
const char* buf1 =
@@ -132,7 +134,7 @@ TEST_F(BufferManagerTest, GetMaxValueForRangeUint8) {
BufferManager::BufferInfo* info = manager_.GetBufferInfo(kClientBufferId);
ASSERT_TRUE(info != NULL);
manager_.SetTarget(info, GL_ELEMENT_ARRAY_BUFFER);
- manager_.SetSize(info, sizeof(data));
+ manager_.SetInfo(info, sizeof(data), GL_STATIC_DRAW);
EXPECT_TRUE(info->SetRange(0, sizeof(data), data));
GLuint max_value;
// Check entire range succeeds.
@@ -162,7 +164,7 @@ TEST_F(BufferManagerTest, GetMaxValueForRangeUint16) {
BufferManager::BufferInfo* info = manager_.GetBufferInfo(kClientBufferId);
ASSERT_TRUE(info != NULL);
manager_.SetTarget(info, GL_ELEMENT_ARRAY_BUFFER);
- manager_.SetSize(info, sizeof(data));
+ manager_.SetInfo(info, sizeof(data), GL_STATIC_DRAW);
EXPECT_TRUE(info->SetRange(0, sizeof(data), data));
GLuint max_value;
// Check entire range succeeds.
@@ -194,7 +196,7 @@ TEST_F(BufferManagerTest, GetMaxValueForRangeUint32) {
BufferManager::BufferInfo* info = manager_.GetBufferInfo(kClientBufferId);
ASSERT_TRUE(info != NULL);
manager_.SetTarget(info, GL_ELEMENT_ARRAY_BUFFER);
- manager_.SetSize(info, sizeof(data));
+ manager_.SetInfo(info, sizeof(data), GL_STATIC_DRAW);
EXPECT_TRUE(info->SetRange(0, sizeof(data), data));
GLuint max_value;
// Check entire range succeeds.
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
index 5f29545..3e0e02a 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -126,6 +126,39 @@ static bool IsAngle() {
#endif
}
+void WrappedTexImage2D(
+ GLenum target,
+ GLint level,
+ GLenum internal_format,
+ GLsizei width,
+ GLsizei height,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ const void* pixels) {
+ GLenum gl_internal_format = internal_format;
+ if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
+ if (format == GL_BGRA_EXT && internal_format == GL_BGRA_EXT) {
+ gl_internal_format = GL_RGBA;
+ } else if (type == GL_FLOAT) {
+ if (format == GL_RGBA) {
+ gl_internal_format = GL_RGBA32F_ARB;
+ } else if (format == GL_RGB) {
+ gl_internal_format = GL_RGB32F_ARB;
+ }
+ } else if (type == GL_HALF_FLOAT_OES) {
+ if (format == GL_RGBA) {
+ gl_internal_format = GL_RGBA16F_ARB;
+ } else if (format == GL_RGB) {
+ gl_internal_format = GL_RGB16F_ARB;
+ }
+ }
+ }
+ glTexImage2D(
+ target, level, gl_internal_format, width, height, border, format, type,
+ pixels);
+}
+
// This class prevents any GL errors that occur when it is in scope from
// being reported to the client.
class ScopedGLErrorSuppressor {
@@ -1469,6 +1502,9 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>,
// The format of the back buffer_
GLenum back_buffer_color_format_;
+ bool teximage2d_faster_than_texsubimage2d_;
+ bool bufferdata_faster_than_buffersubdata_;
+
// The last error message set.
std::string last_error_;
@@ -1815,6 +1851,8 @@ GLES2DecoderImpl::GLES2DecoderImpl(SurfaceManager* surface_manager,
copy_texture_to_parent_texture_fb_(0),
offscreen_saved_color_format_(0),
back_buffer_color_format_(0),
+ teximage2d_faster_than_texsubimage2d_(true),
+ bufferdata_faster_than_buffersubdata_(true),
current_decoder_error_(error::kNoError),
use_shader_translator_(true),
validators_(group_->feature_info()->validators()),
@@ -1838,6 +1876,12 @@ GLES2DecoderImpl::GLES2DecoderImpl(SurfaceManager* surface_manager,
gfx::GetGLImplementation() == gfx::kGLImplementationMockGL) {
use_shader_translator_ = false;
}
+
+ // TODO(gman): Consider setting these based on GPU and/or driver.
+ if (IsAngle()) {
+ teximage2d_faster_than_texsubimage2d_ = false;
+ bufferdata_faster_than_buffersubdata_ = false;
+ }
}
bool GLES2DecoderImpl::Initialize(
@@ -5335,13 +5379,21 @@ void GLES2DecoderImpl::DoBufferData(
memset(zero.get(), 0, size);
data = zero.get();
}
+
+ if (!bufferdata_faster_than_buffersubdata_ &&
+ size == info->size() && usage == info->usage()) {
+ glBufferSubData(target, 0, size, data);
+ info->SetRange(0, size, data);
+ return;
+ }
+
CopyRealGLErrorsToWrapper();
glBufferData(target, size, data, usage);
GLenum error = glGetError();
if (error != GL_NO_ERROR) {
SetGLError(error, NULL);
} else {
- buffer_manager()->SetSize(info, size);
+ buffer_manager()->SetInfo(info, size, usage);
info->SetRange(0, size, data);
}
}
@@ -5387,9 +5439,14 @@ void GLES2DecoderImpl::DoBufferSubData(
}
if (!info->SetRange(offset, size, data)) {
SetGLError(GL_INVALID_VALUE, "glBufferSubData: out of range");
- } else {
- glBufferSubData(target, offset, size, data);
+ return;
}
+ if (bufferdata_faster_than_buffersubdata_ &&
+ offset == 0 && size == info->size()) {
+ glBufferData(target, size, data, info->usage());
+ return;
+ }
+ glBufferSubData(target, offset, size, data);
}
error::Error GLES2DecoderImpl::DoCompressedTexImage2D(
@@ -5591,28 +5648,24 @@ error::Error GLES2DecoderImpl::DoTexImage2D(
pixels = zero.get();
}
- GLenum gl_internal_format = internal_format;
- if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
- if (format == GL_BGRA_EXT && internal_format == GL_BGRA_EXT) {
- gl_internal_format = GL_RGBA;
- } else if (type == GL_FLOAT) {
- if (format == GL_RGBA) {
- gl_internal_format = GL_RGBA32F_ARB;
- } else if (format == GL_RGB) {
- gl_internal_format = GL_RGB32F_ARB;
- }
- } else if (type == GL_HALF_FLOAT_OES) {
- if (format == GL_RGBA) {
- gl_internal_format = GL_RGBA16F_ARB;
- } else if (format == GL_RGB) {
- gl_internal_format = GL_RGB16F_ARB;
- }
+ if (!teximage2d_faster_than_texsubimage2d_) {
+ GLsizei tex_width = 0;
+ GLsizei tex_height = 0;
+ GLenum tex_type = 0;
+ GLenum tex_format = 0;
+ if (info->GetLevelSize(target, level, &tex_width, &tex_height) &&
+ info->GetLevelType(target, level, &tex_type, &tex_format) &&
+ width == tex_width && height == tex_height &&
+ type == tex_type && format == tex_format) {
+ glTexSubImage2D(target, level, 0, 0, width, height, format, type, pixels);
+ tex_image_2d_failed_ = false;
+ return error::kNoError;
}
}
CopyRealGLErrorsToWrapper();
- glTexImage2D(
- target, level, gl_internal_format, width, height, border, format, type,
+ WrappedTexImage2D(
+ target, level, internal_format, width, height, border, format, type,
pixels);
GLenum error = glGetError();
if (error == GL_NO_ERROR) {
@@ -5933,6 +5986,21 @@ void GLES2DecoderImpl::DoTexSubImage2D(
"glTexSubImage2D: bad dimensions.");
return;
}
+
+ // See if we can call glTexImage2D instead since it appears to be faster.
+ if (teximage2d_faster_than_texsubimage2d_ && xoffset == 0 && yoffset == 0) {
+ GLsizei tex_width = 0;
+ GLsizei tex_height = 0;
+ bool ok = info->GetLevelSize(target, level, &tex_width, &tex_height);
+ DCHECK(ok);
+ if (width == tex_width && height == tex_height) {
+ // NOTE: In OpenGL ES 2.0 border is always zero and format is always the
+ // same as internal_foramt. If that changes we'll need to look them up.
+ WrappedTexImage2D(
+ target, level, format, width, height, 0, format, type, data);
+ return;
+ }
+ }
glTexSubImage2D(
target, level, xoffset, yoffset, width, height, format, type, data);
}
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc
index 274d495..d50bb6d 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc
@@ -2389,13 +2389,14 @@ TEST_F(GLES2DecoderTest, TexSubImage2DValidArgs) {
GL_TEXTURE_2D, 1, GL_RGBA, kWidth, kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE,
0, 0);
EXPECT_CALL(*gl_, TexSubImage2D(
- GL_TEXTURE_2D, 1, 0, 0, kWidth, kHeight, GL_RGBA, GL_UNSIGNED_BYTE,
+ GL_TEXTURE_2D, 1, 1, 0, kWidth - 1, kHeight, GL_RGBA, GL_UNSIGNED_BYTE,
shared_memory_address_))
.Times(1)
.RetiresOnSaturation();
TexSubImage2D cmd;
- cmd.Init(GL_TEXTURE_2D, 1, 0, 0, kWidth, kHeight, GL_RGBA, GL_UNSIGNED_BYTE,
- kSharedMemoryId, kSharedMemoryOffset, GL_FALSE);
+ cmd.Init(
+ GL_TEXTURE_2D, 1, 1, 0, kWidth - 1, kHeight, GL_RGBA, GL_UNSIGNED_BYTE,
+ kSharedMemoryId, kSharedMemoryOffset, GL_FALSE);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(GL_NO_ERROR, GetGLError());
}
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 7dbc98c..9470d08 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc
@@ -745,7 +745,8 @@ void GLES2DecoderWithShaderTestBase::SetupIndexBuffer() {
static const GLshort indices[] = {100, 1, 2, 3, 4, 5, 6, 7, 100, 9};
COMPILE_ASSERT(arraysize(indices) == kNumIndices, Indices_is_not_10);
DoBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices));
- DoBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, sizeof(indices), indices);
+ DoBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, 2, indices);
+ DoBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 2, sizeof(indices) - 2, &indices[1]);
}
void GLES2DecoderWithShaderTestBase::SetupTexture() {