diff options
author | gman@chromium.org <gman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-12-21 20:45:03 +0000 |
---|---|---|
committer | gman@chromium.org <gman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-12-21 20:45:03 +0000 |
commit | 6e2886139e576ba8bb2407465938aacbfaa4c825 (patch) | |
tree | fe8c930ee2b1d81c477110f75d0921a945a8a3e4 /gpu/command_buffer | |
parent | 5b4607627527e29fca660106f8cc76c17ba46927 (diff) | |
download | chromium_src-6e2886139e576ba8bb2407465938aacbfaa4c825.zip chromium_src-6e2886139e576ba8bb2407465938aacbfaa4c825.tar.gz chromium_src-6e2886139e576ba8bb2407465938aacbfaa4c825.tar.bz2 |
Fix glCopyTexImage2D and glCopyTexSubImage2D to handle
offscreen source areas like glReadPixels does.
TEST=webgl conformance tests pass
BUG=none
Review URL: http://codereview.chromium.org/6035003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@69869 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'gpu/command_buffer')
3 files changed, 97 insertions, 3 deletions
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc index 315731b..e93624c 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc @@ -5445,6 +5445,24 @@ void GLES2DecoderImpl::DoCompressedTexSubImage2D( target, level, xoffset, yoffset, width, height, format, image_size, data); } +static void Clip( + GLint start, GLint range, GLint sourceRange, + GLint* out_start, GLint* out_range) { + DCHECK(out_start); + DCHECK(out_range); + if (start < 0) { + range += start; + start = 0; + } + GLint end = start + range; + if (end > sourceRange) { + range -= end - sourceRange; + } + *out_start = start; + *out_range = range; +} + + void GLES2DecoderImpl::DoCopyTexImage2D( GLenum target, GLint level, @@ -5472,7 +5490,44 @@ void GLES2DecoderImpl::DoCopyTexImage2D( // TODO(gman): Type needs to match format for FBO. CopyRealGLErrorsToWrapper(); ScopedResolvedFrameBufferBinder binder(this); - glCopyTexImage2D(target, level, internal_format, x, y, width, height, border); + // Clip to size to source dimensions + gfx::Size size = GetBoundReadFrameBufferSize(); + GLint copyX = 0; + GLint copyY = 0; + GLint copyWidth = 0; + GLint copyHeight = 0; + Clip(x, width, size.width(), ©X, ©Width); + Clip(y, height, size.height(), ©Y, ©Height); + + if (copyX != x || + copyY != y || + copyWidth != width || + copyHeight != height) { + // some part was clipped so clear the texture. + uint32 pixels_size = 0; + if (!GLES2Util::ComputeImageDataSize( + width, height, internal_format, GL_UNSIGNED_BYTE, + unpack_alignment_, &pixels_size)) { + SetGLError(GL_INVALID_VALUE, "glCopyTexImage2D: dimensions too large"); + return; + } + scoped_array<char> zero(new char[pixels_size]); + memset(zero.get(), 0, pixels_size); + glTexImage2D(target, level, internal_format, width, height, 0, + internal_format, GL_UNSIGNED_BYTE, zero.get()); + if (copyHeight > 0 && copyWidth > 0) { + GLint dx = copyX - x; + GLint dy = copyY - y; + GLint destX = dx; + GLint destY = dy; + glCopyTexSubImage2D(target, level, + destX, destY, copyX, copyY, + copyWidth, copyHeight); + } + } else { + glCopyTexImage2D(target, level, internal_format, + copyX, copyY, copyWidth, copyHeight, border); + } GLenum error = glGetError(); if (error == GL_NO_ERROR) { texture_manager()->SetLevelInfo( @@ -5508,7 +5563,39 @@ void GLES2DecoderImpl::DoCopyTexSubImage2D( // TODO(gman): Should we check that x, y, width, and height are in range // for current FBO? ScopedResolvedFrameBufferBinder binder(this); - glCopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height); + gfx::Size size = GetBoundReadFrameBufferSize(); + GLint copyX = 0; + GLint copyY = 0; + GLint copyWidth = 0; + GLint copyHeight = 0; + Clip(x, width, size.width(), ©X, ©Width); + Clip(y, height, size.height(), ©Y, ©Height); + if (copyX != x || + copyY != y || + copyWidth != width || + copyHeight != height) { + // some part was clipped so clear the texture. + uint32 pixels_size = 0; + if (!GLES2Util::ComputeImageDataSize( + width, height, format, type, unpack_alignment_, &pixels_size)) { + SetGLError(GL_INVALID_VALUE, "glCopyTexSubImage2D: dimensions too large"); + return; + } + scoped_array<char> zero(new char[pixels_size]); + memset(zero.get(), 0, pixels_size); + glTexSubImage2D( + target, level, xoffset, yoffset, width, height, + format, type, zero.get()); + } + if (copyHeight > 0 && copyWidth > 0) { + GLint dx = copyX - x; + GLint dy = copyY - y; + GLint destX = xoffset + dx; + GLint destY = yoffset + dy; + glCopyTexSubImage2D(target, level, + destX, destY, copyX, copyY, + copyWidth, copyHeight); + } } void GLES2DecoderImpl::DoTexSubImage2D( 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 1b082dd..db175ce 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc @@ -108,10 +108,11 @@ void GLES2DecoderTestBase::InitDecoder(const char* extensions) { shared_memory_id_ = kSharedMemoryId; context_ = new gfx::StubGLContext; + context_->SetSize(gfx::Size(kBackBufferWidth, kBackBufferHeight)); decoder_.reset(GLES2Decoder::Create(group_.get())); decoder_->Initialize( - context_, gfx::Size(), NULL, std::vector<int32>(), NULL, 0); + context_, context_->GetSize(), NULL, std::vector<int32>(), NULL, 0); decoder_->set_engine(engine_.get()); EXPECT_CALL(*gl_, GenBuffersARB(_, _)) @@ -423,6 +424,9 @@ const uint8 GLES2DecoderTestBase::kInitialMemoryValue; const uint32 GLES2DecoderTestBase::kNewClientId; const uint32 GLES2DecoderTestBase::kNewServiceId; const uint32 GLES2DecoderTestBase::kInvalidClientId; + +const int GLES2DecoderTestBase::kBackBufferWidth; +const int GLES2DecoderTestBase::kBackBufferHeight; #endif void GLES2DecoderWithShaderTestBase::SetUp() { 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 a6c8cad..78b8fb5 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h @@ -71,6 +71,9 @@ class GLES2DecoderTestBase : public testing::Test { static const uint32 kNewServiceId = 502; static const uint32 kInvalidClientId = 601; + static const int kBackBufferWidth = 128; + static const int kBackBufferHeight = 64; + // Template to call glGenXXX functions. template <typename T> void GenHelper(GLuint client_id) { |