summaryrefslogtreecommitdiffstats
path: root/gpu/command_buffer
diff options
context:
space:
mode:
authorgman@chromium.org <gman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-12-21 20:45:03 +0000
committergman@chromium.org <gman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-12-21 20:45:03 +0000
commit6e2886139e576ba8bb2407465938aacbfaa4c825 (patch)
treefe8c930ee2b1d81c477110f75d0921a945a8a3e4 /gpu/command_buffer
parent5b4607627527e29fca660106f8cc76c17ba46927 (diff)
downloadchromium_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')
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder.cc91
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc6
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h3
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(), &copyX, &copyWidth);
+ Clip(y, height, size.height(), &copyY, &copyHeight);
+
+ 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(), &copyX, &copyWidth);
+ Clip(y, height, size.height(), &copyY, &copyHeight);
+ 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) {