diff options
author | gman@chromium.org <gman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-07-22 03:25:07 +0000 |
---|---|---|
committer | gman@chromium.org <gman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-07-22 03:25:07 +0000 |
commit | 0226c11e6cfd7510d97aaf4499aa2c10aad8c7e6 (patch) | |
tree | 2ad5eae3d1915932745b4b99a872aebc79f4fe12 /gpu | |
parent | 212a96285521d213cd7fe720f26a721cdae70d90 (diff) | |
download | chromium_src-0226c11e6cfd7510d97aaf4499aa2c10aad8c7e6.zip chromium_src-0226c11e6cfd7510d97aaf4499aa2c10aad8c7e6.tar.gz chromium_src-0226c11e6cfd7510d97aaf4499aa2c10aad8c7e6.tar.bz2 |
Add support for GL_CHROMIUM_flipy
Also fixed a couple of other related things
TEST=unit tests
BUG=89593
Review URL: http://codereview.chromium.org/7471032
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@93541 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'gpu')
-rw-r--r-- | gpu/GLES2/gl2ext.h | 17 | ||||
-rw-r--r-- | gpu/command_buffer/client/gles2_implementation.cc | 114 | ||||
-rw-r--r-- | gpu/command_buffer/client/gles2_implementation.h | 6 | ||||
-rw-r--r-- | gpu/command_buffer/client/gles2_implementation_unittest.cc | 372 | ||||
-rw-r--r-- | gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h | 1 | ||||
-rw-r--r-- | gpu/command_buffer/service/feature_info.cc | 1 | ||||
-rw-r--r-- | gpu/command_buffer/service/feature_info_unittest.cc | 1 | ||||
-rw-r--r-- | gpu/command_buffer/service/gles2_cmd_decoder.cc | 32 |
8 files changed, 504 insertions, 40 deletions
diff --git a/gpu/GLES2/gl2ext.h b/gpu/GLES2/gl2ext.h index 1afb408..6fef647 100644 --- a/gpu/GLES2/gl2ext.h +++ b/gpu/GLES2/gl2ext.h @@ -902,10 +902,10 @@ typedef void (GL_APIENTRYP PFNGLUNMAPTEXSUBIMAGE2DCHROMIUM) (const void* mem); #ifdef GL_GLEXT_PROTOTYPES #define glCopyTextureToParentTextureCHROMIUM GLES2_GET_FUN(CopyTextureToParentTextureCHROMIUM) #if !defined(GLES2_USE_CPP_BINDINGS) -GL_APICALL void* GL_APIENTRY glCopyTextureToParentTextureCHROMIUM (GLuint id, GLuint id2); +GL_APICALL void GL_APIENTRY glCopyTextureToParentTextureCHROMIUM (GLuint id, GLuint id2); #endif #else -typedef void* (GL_APIENTRYP PFNGLCOPYTEXTURETOPARENTTEXTURECHROMIUM) (GLuint id, GLuint id2); +typedef void (GL_APIENTRYP PFNGLCOPYTEXTURETOPARENTTEXTURECHROMIUM) (GLuint id, GLuint id2); #endif #endif @@ -1001,7 +1001,7 @@ typedef void (GL_APIENTRYP PFNGLRATELIMITOFFSCREENCONTEXTCHROMIUM) (); #define glGetMultipleIntegervCHROMIUM GLES2_GET_FUN(GetMultipleIntegervCHROMIUM) #define glGetProgramInfoCHROMIUM GLES2_GET_FUN(GetProgramInfovCHROMIUM) #if !defined(GLES2_USE_CPP_BINDINGS) -GL_APICALL void GL_APIENTRY glGetMultipleIntegervCHROMIUM (void); +GL_APICALL void GL_APIENTRY glGetMultipleIntegervCHROMIUM (const GLenum* pnames, GLuint count, GLint* results, GLsizeiptr size); GL_APICALL void GL_APIENTRY glGetProgrmaInfoCHROMIUM (GLuint program, GLsizei bufsize, GLsizei* size, void* info); #endif #else @@ -1010,6 +1010,17 @@ typedef void (GL_APIENTRYP PFNGLGETPROGRAMINFOCHROMIUM) (); #endif #endif +/* GL_CHROMIUM_flipy */ +/* + * This extension provides GL_UNPACK_FLIP_Y_CHROMIUM as a parameter to + * glPixelStorei. When true images submitted to glTexImage2D and glTexSubImage2D + * are flipped vertically. + */ +#ifndef GL_CHROMIUM_flipy +#define GL_CHROMIUM_flipy 1 +#define GL_UNPACK_FLIP_Y_CHROMIUM 0x9240 +#endif + /* GL_ARB_robustness */ /* This extension is subsetted for the moment, incorporating only the * enums necessary to describe the reasons that we might encounter for diff --git a/gpu/command_buffer/client/gles2_implementation.cc b/gpu/command_buffer/client/gles2_implementation.cc index 52abdf1..3f04ec3 100644 --- a/gpu/command_buffer/client/gles2_implementation.cc +++ b/gpu/command_buffer/client/gles2_implementation.cc @@ -5,6 +5,8 @@ // A class to emulate GLES2 over command buffers. #include "../client/gles2_implementation.h" + +#include <GLES2/gl2ext.h> #include <GLES2/gles2_command_buffer.h> #include "../client/mapped_memory.h" #include "../common/gles2_cmd_utils.h" @@ -443,6 +445,7 @@ GLES2Implementation::GLES2Implementation( transfer_buffer_id_(transfer_buffer_id), pack_alignment_(4), unpack_alignment_(4), + unpack_flip_y_(false), active_texture_unit_(0), bound_framebuffer_(0), bound_renderbuffer_(0), @@ -1017,14 +1020,17 @@ void GLES2Implementation::PixelStorei(GLenum pname, GLint param) { << GLES2Util::GetStringPixelStore(pname) << ", " << param << ")"); switch (pname) { - case GL_PACK_ALIGNMENT: - pack_alignment_ = param; - break; - case GL_UNPACK_ALIGNMENT: - unpack_alignment_ = param; - break; - default: - break; + case GL_PACK_ALIGNMENT: + pack_alignment_ = param; + break; + case GL_UNPACK_ALIGNMENT: + unpack_alignment_ = param; + break; + case GL_UNPACK_FLIP_Y_CHROMIUM: + unpack_flip_y_ = (param != 0); + return; + default: + break; } helper_->PixelStorei(pname, param); } @@ -1231,6 +1237,45 @@ void GLES2Implementation::CompressedTexSubImage2D( helper_->SetBucketSize(kResultBucketId, 0); } +bool GLES2Implementation::CopyRectToBufferFlipped( + const void* pixels, + GLsizei width, + GLsizei height, + GLenum format, + GLenum type, + void* buffer) { + if (width == 0 || height == 0) { + return true; + } + + uint32 temp_size; + if (!GLES2Util::ComputeImageDataSize( + width, 1, format, type, unpack_alignment_, &temp_size)) { + SetGLError(GL_INVALID_VALUE, "glTexSubImage2D: size to large"); + return false; + } + GLsizeiptr unpadded_row_size = temp_size; + if (!GLES2Util::ComputeImageDataSize( + width, 2, format, type, unpack_alignment_, &temp_size)) { + SetGLError(GL_INVALID_VALUE, "glTexSubImage2D: size to large"); + return false; + } + GLsizeiptr padded_row_size = temp_size - unpadded_row_size; + if (padded_row_size < 0 || unpadded_row_size < 0) { + SetGLError(GL_INVALID_VALUE, "glTexSubImage2D: size to large"); + return false; + } + + const int8* source = static_cast<const int8*>(pixels); + int8* dest = static_cast<int8*>(buffer) + padded_row_size * (height - 1); + for (; height; --height) { + memcpy(dest, source, unpadded_row_size); + dest -= padded_row_size; + source += padded_row_size; + } + return true; +} + void GLES2Implementation::TexImage2D( GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, @@ -1269,10 +1314,19 @@ void GLES2Implementation::TexImage2D( } void* buffer = transfer_buffer_.Alloc(size); - memcpy(buffer, pixels, size); - helper_->TexImage2D( - target, level, internalformat, width, height, border, format, type, - transfer_buffer_id_, transfer_buffer_.GetOffset(buffer)); + bool copy_success = true; + if (unpack_flip_y_) { + copy_success = CopyRectToBufferFlipped( + pixels, width, height, format, type, buffer); + } else { + memcpy(buffer, pixels, size); + } + + if (copy_success) { + helper_->TexImage2D( + target, level, internalformat, width, height, border, format, type, + transfer_buffer_id_, transfer_buffer_.GetOffset(buffer)); + } transfer_buffer_.FreePendingToken(buffer, helper_->InsertToken()); } @@ -1323,6 +1377,7 @@ void GLES2Implementation::TexSubImage2DImpl( return; } + GLsizei original_height = height; if (padded_row_size <= max_size) { // Transfer by rows. GLint max_rows = max_size / std::max(padded_row_size, @@ -1331,9 +1386,18 @@ void GLES2Implementation::TexSubImage2DImpl( GLint num_rows = std::min(height, max_rows); GLsizeiptr part_size = num_rows * padded_row_size; void* buffer = transfer_buffer_.Alloc(part_size); - memcpy(buffer, source, part_size); + GLint y; + if (unpack_flip_y_) { + bool copy_success = CopyRectToBufferFlipped( + source, width, num_rows, format, type, buffer); + GPU_DCHECK(copy_success); + y = original_height - yoffset - num_rows; + } else { + memcpy(buffer, source, part_size); + y = yoffset; + } helper_->TexSubImage2D( - target, level, xoffset, yoffset, width, num_rows, format, type, + target, level, xoffset, y, width, num_rows, format, type, transfer_buffer_id_, transfer_buffer_.GetOffset(buffer), internal); transfer_buffer_.FreePendingToken(buffer, helper_->InsertToken()); yoffset += num_rows; @@ -1357,8 +1421,9 @@ void GLES2Implementation::TexSubImage2DImpl( GLsizeiptr part_size = num_pixels * element_size; void* buffer = transfer_buffer_.Alloc(part_size); memcpy(buffer, row_source, part_size); + GLint y = unpack_flip_y_ ? (original_height - yoffset - 1) : yoffset; helper_->TexSubImage2D( - target, level, temp_xoffset, yoffset, temp_width, 1, format, type, + target, level, temp_xoffset, y, num_pixels, 1, format, type, transfer_buffer_id_, transfer_buffer_.GetOffset(buffer), internal); transfer_buffer_.FreePendingToken(buffer, helper_->InsertToken()); row_source += part_size; @@ -1537,14 +1602,25 @@ const GLubyte* GLES2Implementation::GetString(GLenum name) { GPU_CLIENT_LOG("[" << this << "] glGetString(" << GLES2Util::GetStringStringType(name) << ")"); const char* result = NULL; - // Clear the bucket so if the command fails nothing will be in it. + // Clears the bucket so if the command fails nothing will be in it. helper_->SetBucketSize(kResultBucketId, 0); helper_->GetString(name, kResultBucketId); std::string str; if (GetBucketAsString(kResultBucketId, &str)) { - // Because of WebGL the extensions can change. We have to cache each - // unique result since we don't know when the client will stop referring to - // a previous one it queries. + // Adds extensions implemented on client side only. + switch (name) { + case GL_EXTENSIONS: + str += std::string(str.empty() ? "" : " ") + + "GL_CHROMIUM_map_sub " + "GL_CHROMIUM_flipy"; + break; + default: + break; + } + + // Because of WebGL the extensions can change. We have to cache each unique + // result since we don't know when the client will stop referring to a + // previous one it queries. GLStringMap::iterator it = gl_strings_.find(name); if (it == gl_strings_.end()) { std::set<std::string> strings; diff --git a/gpu/command_buffer/client/gles2_implementation.h b/gpu/command_buffer/client/gles2_implementation.h index d7b955e..562910c 100644 --- a/gpu/command_buffer/client/gles2_implementation.h +++ b/gpu/command_buffer/client/gles2_implementation.h @@ -379,6 +379,9 @@ class GLES2Implementation { GLsizei GetMaxIndexInElementArrayBuffer( GLuint buffer_id, GLsizei count, GLenum type, GLuint offset); + bool CopyRectToBufferFlipped( + const void* pixels, GLsizei width, GLsizei height, GLenum format, + GLenum type, void* buffer); void TexSubImage2DImpl( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* pixels, @@ -423,6 +426,9 @@ class GLES2Implementation { // unpack alignment as last set by glPixelStorei GLint unpack_alignment_; + // unpack yflip as last set by glPixelstorei + bool unpack_flip_y_; + scoped_array<TextureUnit> texture_units_; // 0 to gl_state_.max_combined_texture_image_units. diff --git a/gpu/command_buffer/client/gles2_implementation_unittest.cc b/gpu/command_buffer/client/gles2_implementation_unittest.cc index a37f4b2..9120c64 100644 --- a/gpu/command_buffer/client/gles2_implementation_unittest.cc +++ b/gpu/command_buffer/client/gles2_implementation_unittest.cc @@ -5,6 +5,8 @@ // Tests for the Command Buffer Helper. #include "gpu/command_buffer/client/gles2_implementation.h" + +#include <GLES2/gl2ext.h> #include "gpu/command_buffer/common/command_buffer.h" #include "gpu/GLES2/gles2_command_buffer.h" #include "testing/gtest/include/gtest/gtest.h" @@ -58,7 +60,6 @@ class GLES2MockCommandBufferHelper : public CommandBuffer { state_.put_offset = put_offset; state_.get_offset = put_offset; OnFlush(transfer_buffer_buffer_.ptr); - return state_; } @@ -189,7 +190,7 @@ struct Str7 { // Test fixture for CommandBufferHelper test. class GLES2ImplementationTest : public testing::Test { protected: - static const int32 kNumCommandEntries = 100; + static const int32 kNumCommandEntries = 400; static const int32 kCommandBufferSizeBytes = kNumCommandEntries * sizeof(CommandBufferEntry); static const size_t kTransferBufferSize = 256; @@ -261,7 +262,9 @@ class GLES2ImplementationTest : public testing::Test { kTransferBufferId, false)); - EXPECT_CALL(*command_buffer_, OnFlush(_)).Times(1).RetiresOnSaturation(); + EXPECT_CALL(*command_buffer_, OnFlush(_)) + .Times(1) + .RetiresOnSaturation(); helper_->CommandBufferHelper::Finish(); Buffer ring_buffer = command_buffer_->GetRingBuffer(); commands_ = static_cast<CommandBufferEntry*>(ring_buffer.ptr) + @@ -272,6 +275,14 @@ class GLES2ImplementationTest : public testing::Test { virtual void TearDown() { } + const void* GetPut() { + return helper_->GetSpace(0); + } + + size_t MaxTransferBufferSize() { + return kTransferBufferSize - GLES2Implementation::kStartingOffset; + } + void ClearCommands() { Buffer ring_buffer = command_buffer_->GetRingBuffer(); memset(ring_buffer.ptr, kInitialValue, ring_buffer.size); @@ -304,6 +315,16 @@ class GLES2ImplementationTest : public testing::Test { return offset; } + void* GetTransferAddressFromOffset(uint32 offset, size_t size) { + EXPECT_LE(offset + size, transfer_buffer_.size); + return static_cast<int8*>(transfer_buffer_.ptr) + offset; + } + + template <typename T> + T* GetTransferAddressFromOffsetAs(uint32 offset, size_t size) { + return static_cast<T*>(GetTransferAddressFromOffset(offset, size)); + } + Buffer transfer_buffer_; CommandBufferEntry* commands_; scoped_ptr<MockGLES2CommandBuffer> command_buffer_; @@ -1319,6 +1340,351 @@ TEST_F(GLES2ImplementationTest, GetIntegerCacheWrite) { EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), gl_->GetError()); } +static bool ComputeImageDataSizes( + int width, int height, int format, int type, int unpack_alignment, + uint32* size, uint32* unpadded_row_size, uint32* padded_row_size) { + uint32 temp_size; + if (!GLES2Util::ComputeImageDataSize( + width, 1, format, type, unpack_alignment, &temp_size)) { + return false; + } + *unpadded_row_size = temp_size; + if (!GLES2Util::ComputeImageDataSize( + width, 2, format, type, unpack_alignment, &temp_size)) { + return false; + } + *padded_row_size = temp_size - *unpadded_row_size; + return GLES2Util::ComputeImageDataSize( + width, height, format, type, unpack_alignment, size); +} + +static bool CheckRect( + int width, int height, GLenum format, GLenum type, int alignment, + bool flip_y, const uint8* r1, const uint8* r2) { + uint32 size = 0; + uint32 unpadded_row_size = 0; + uint32 padded_row_size = 0; + if (!ComputeImageDataSizes( + width, height, format, type, alignment, &size, &unpadded_row_size, + &padded_row_size)) { + return false; + } + + int r2_stride = flip_y ? -static_cast<int>(padded_row_size) : padded_row_size; + r2 = flip_y ? (r2 + (height - 1) * padded_row_size) : r2; + + for (int y = 0; y < height; ++y) { + if (memcmp(r1, r2, unpadded_row_size) != 0) { + return false; + } + r1 += padded_row_size; + r2 += r2_stride; + } + return true; +} + +ACTION_P8(CheckRectAction, width, height, format, type, alignment, flip_y, + r1, r2) { + EXPECT_TRUE(CheckRect( + width, height, format, type, alignment, flip_y, r1, r2)); +} + +// Test TexImage2D with and without flip_y +TEST_F(GLES2ImplementationTest, TexImage2D) { + struct Cmds { + TexImage2D tex_image_2d; + cmd::SetToken set_token; + }; + struct Cmds2 { + TexImage2D tex_image_2d; + cmd::SetToken set_token; + }; + const GLenum kTarget = GL_TEXTURE_2D; + const GLint kLevel = 0; + const GLenum kFormat = GL_RGB; + const GLsizei kWidth = 3; + const GLsizei kHeight = 4; + const GLint kBorder = 0; + const GLenum kType = GL_UNSIGNED_BYTE; + const GLint kPixelStoreUnpackAlignment = 4; + static uint8 pixels[] = { + 11, 12, 13, 13, 14, 15, 15, 16, 17, 101, 102, 103, + 21, 22, 23, 23, 24, 25, 25, 26, 27, 201, 202, 203, + 31, 32, 33, 33, 34, 35, 35, 36, 37, 123, 124, 125, + 41, 42, 43, 43, 44, 45, 45, 46, 47, + }; + uint32 offset = AllocateTransferBuffer(sizeof(pixels)); + Cmds expected; + expected.tex_image_2d.Init( + kTarget, kLevel, kFormat, kWidth, kHeight, kBorder, kFormat, kType, + kTransferBufferId, offset); + expected.set_token.Init(GetNextToken()); + gl_->TexImage2D( + kTarget, kLevel, kFormat, kWidth, kHeight, kBorder, kFormat, kType, + pixels); + EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); + EXPECT_TRUE(CheckRect( + kWidth, kHeight, kFormat, kType, kPixelStoreUnpackAlignment, false, + pixels, GetTransferAddressFromOffsetAs<uint8>(offset, sizeof(pixels)))); + + ClearCommands(); + uint32 offset2 = AllocateTransferBuffer(sizeof(pixels)); + Cmds2 expected2; + expected2.tex_image_2d.Init( + kTarget, kLevel, kFormat, kWidth, kHeight, kBorder, kFormat, kType, + kTransferBufferId, offset2); + expected2.set_token.Init(GetNextToken()); + const void* commands2 = GetPut(); + gl_->PixelStorei(GL_UNPACK_FLIP_Y_CHROMIUM, GL_TRUE); + gl_->TexImage2D( + kTarget, kLevel, kFormat, kWidth, kHeight, kBorder, kFormat, kType, + pixels); + EXPECT_EQ(0, memcmp(&expected2, commands2, sizeof(expected2))); + EXPECT_TRUE(CheckRect( + kWidth, kHeight, kFormat, kType, kPixelStoreUnpackAlignment, true, + pixels, GetTransferAddressFromOffsetAs<uint8>(offset2, sizeof(pixels)))); +} + +// Test TexImage2D with 2 writes +TEST_F(GLES2ImplementationTest, TexImage2D2Writes) { + struct Cmds { + TexImage2D tex_image_2d; + TexSubImage2D tex_sub_image_2d1; + cmd::SetToken set_token1; + TexSubImage2D tex_sub_image_2d2; + cmd::SetToken set_token2; + }; + const GLenum kTarget = GL_TEXTURE_2D; + const GLint kLevel = 0; + const GLenum kFormat = GL_RGB; + const GLint kBorder = 0; + const GLenum kType = GL_UNSIGNED_BYTE; + const GLint kPixelStoreUnpackAlignment = 4; + const GLsizei kWidth = 3; + + uint32 size = 0; + uint32 unpadded_row_size = 0; + uint32 padded_row_size = 0; + ASSERT_TRUE(ComputeImageDataSizes( + kWidth, 2, kFormat, kType, kPixelStoreUnpackAlignment, + &size, &unpadded_row_size, &padded_row_size)); + const GLsizei kHeight = (MaxTransferBufferSize() / padded_row_size) * 2; + ASSERT_TRUE(GLES2Util::ComputeImageDataSize( + kWidth, kHeight, kFormat, kType, kPixelStoreUnpackAlignment, + &size)); + uint32 half_size = 0; + ASSERT_TRUE(GLES2Util::ComputeImageDataSize( + kWidth, kHeight / 2, kFormat, kType, kPixelStoreUnpackAlignment, + &half_size)); + + scoped_array<uint8> pixels(new uint8[size]); + for (uint32 ii = 0; ii < size; ++ii) { + pixels[ii] = static_cast<uint8>(ii); + } + uint32 offset1 = AllocateTransferBuffer(half_size); + uint32 offset2 = AllocateTransferBuffer(half_size); + Cmds expected; + expected.tex_image_2d.Init( + kTarget, kLevel, kFormat, kWidth, kHeight, kBorder, kFormat, kType, + 0, 0); + expected.tex_sub_image_2d1.Init( + kTarget, kLevel, 0, 0, kWidth, kHeight / 2, kFormat, kType, + kTransferBufferId, offset1, true); + expected.set_token1.Init(GetNextToken()); + expected.tex_sub_image_2d2.Init( + kTarget, kLevel, 0, kHeight / 2, kWidth, kHeight / 2, kFormat, kType, + kTransferBufferId, offset2, true); + expected.set_token2.Init(GetNextToken()); + + // TODO(gman): Make it possible to run this test + // EXPECT_CALL(*command_buffer_, OnFlush(_)) + // .WillOnce(CheckRectAction( + // kWidth, kHeight / 2, kFormat, kType, kPixelStoreUnpackAlignment, + // false, pixels.get(), + // GetTransferAddressFromOffsetAs<uint8>(offset1, half_size))) + // .RetiresOnSaturation(); + + gl_->TexImage2D( + kTarget, kLevel, kFormat, kWidth, kHeight, kBorder, kFormat, kType, + pixels.get()); + EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); + EXPECT_TRUE(CheckRect( + kWidth, kHeight / 2, kFormat, kType, kPixelStoreUnpackAlignment, false, + pixels.get() + kHeight / 2 * padded_row_size, + GetTransferAddressFromOffsetAs<uint8>(offset2, half_size))); + + ClearCommands(); + const void* commands2 = GetPut(); + uint32 offset3 = AllocateTransferBuffer(half_size); + uint32 offset4 = AllocateTransferBuffer(half_size); + expected.tex_image_2d.Init( + kTarget, kLevel, kFormat, kWidth, kHeight, kBorder, kFormat, kType, + 0, 0); + expected.tex_sub_image_2d1.Init( + kTarget, kLevel, 0, kHeight / 2, kWidth, kHeight / 2, kFormat, kType, + kTransferBufferId, offset3, true); + expected.set_token1.Init(GetNextToken()); + expected.tex_sub_image_2d2.Init( + kTarget, kLevel, 0, 0, kWidth, kHeight / 2, kFormat, kType, + kTransferBufferId, offset4, true); + expected.set_token2.Init(GetNextToken()); + + // TODO(gman): Make it possible to run this test + // EXPECT_CALL(*command_buffer_, OnFlush(_)) + // .WillOnce(CheckRectAction( + // kWidth, kHeight / 2, kFormat, kType, kPixelStoreUnpackAlignment, + // true, pixels.get(), + // GetTransferAddressFromOffsetAs<uint8>(offset3, half_size))) + // .RetiresOnSaturation(); + + gl_->PixelStorei(GL_UNPACK_FLIP_Y_CHROMIUM, GL_TRUE); + gl_->TexImage2D( + kTarget, kLevel, kFormat, kWidth, kHeight, kBorder, kFormat, kType, + pixels.get()); + EXPECT_EQ(0, memcmp(&expected, commands2, sizeof(expected))); + EXPECT_TRUE(CheckRect( + kWidth, kHeight / 2, kFormat, kType, kPixelStoreUnpackAlignment, true, + pixels.get() + kHeight / 2 * padded_row_size, + GetTransferAddressFromOffsetAs<uint8>(offset4, half_size))); +} + +// Test TexImage2D with sub rows +TEST_F(GLES2ImplementationTest, TexImage2DSubRows) { + struct Cmds { + TexImage2D tex_image_2d; + TexSubImage2D tex_sub_image_2d1; + cmd::SetToken set_token1; + TexSubImage2D tex_sub_image_2d2; + cmd::SetToken set_token2; + TexSubImage2D tex_sub_image_2d3; + cmd::SetToken set_token3; + TexSubImage2D tex_sub_image_2d4; + cmd::SetToken set_token4; + }; + const GLenum kTarget = GL_TEXTURE_2D; + const GLint kLevel = 0; + const GLenum kFormat = GL_RGB; + const GLint kBorder = 0; + const GLenum kType = GL_UNSIGNED_BYTE; + const GLint kPixelStoreUnpackAlignment = 4; + const GLsizei kHeight = 2; + const GLsizei kWidth = (MaxTransferBufferSize() / 3) * 2; + + uint32 size = 0; + uint32 unpadded_row_size = 0; + uint32 padded_row_size = 0; + ASSERT_TRUE(ComputeImageDataSizes( + kWidth, kHeight, kFormat, kType, kPixelStoreUnpackAlignment, + &size, &unpadded_row_size, &padded_row_size)); + uint32 part_size = kWidth * 3 / 2; + + scoped_array<uint8> pixels(new uint8[size]); + for (uint32 ii = 0; ii < size; ++ii) { + pixels[ii] = static_cast<uint8>(ii); + } + uint32 offset1 = AllocateTransferBuffer(part_size); + uint32 offset2 = AllocateTransferBuffer(part_size); + uint32 offset3 = AllocateTransferBuffer(part_size); + uint32 offset4 = AllocateTransferBuffer(part_size); + Cmds expected; + expected.tex_image_2d.Init( + kTarget, kLevel, kFormat, kWidth, kHeight, kBorder, kFormat, kType, + 0, 0); + expected.tex_sub_image_2d1.Init( + kTarget, kLevel, 0, 0, kWidth / 2, 1, kFormat, kType, + kTransferBufferId, offset1, true); + expected.set_token1.Init(GetNextToken()); + expected.tex_sub_image_2d2.Init( + kTarget, kLevel, kWidth / 2, 0, kWidth / 2, 1, kFormat, kType, + kTransferBufferId, offset2, true); + expected.set_token2.Init(GetNextToken()); + expected.tex_sub_image_2d3.Init( + kTarget, kLevel, 0, 1, kWidth / 2, 1, kFormat, kType, + kTransferBufferId, offset3, true); + expected.set_token3.Init(GetNextToken()); + expected.tex_sub_image_2d4.Init( + kTarget, kLevel, kWidth / 2, 1, kWidth / 2, 1, kFormat, kType, + kTransferBufferId, offset4, true); + expected.set_token4.Init(GetNextToken()); + + // TODO(gman): Make it possible to run this test + // EXPECT_CALL(*command_buffer_, OnFlush(_)) + // .WillOnce(CheckRectAction( + // kWidth / 2, 1, kFormat, kType, kPixelStoreUnpackAlignment, false, + // pixels.get(), + // GetTransferAddressFromOffsetAs<uint8>(offset1, part_size))) + // .WillOnce(CheckRectAction( + // kWidth / 2, 1, kFormat, kType, kPixelStoreUnpackAlignment, false, + // pixels.get() + part_size, + // GetTransferAddressFromOffsetAs<uint8>(offset2, part_size))) + // .WillOnce(CheckRectAction( + // kWidth / 2, 1, kFormat, kType, kPixelStoreUnpackAlignment, false, + // pixels.get() + padded_row_size, + // GetTransferAddressFromOffsetAs<uint8>(offset3, part_size))) + // .RetiresOnSaturation(); + + gl_->TexImage2D( + kTarget, kLevel, kFormat, kWidth, kHeight, kBorder, kFormat, kType, + pixels.get()); + EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); + EXPECT_TRUE(CheckRect( + kWidth / 2, 1, kFormat, kType, kPixelStoreUnpackAlignment, false, + pixels.get() + padded_row_size + part_size, + GetTransferAddressFromOffsetAs<uint8>(offset4, part_size))); + + ClearCommands(); + const void* commands2 = GetPut(); + offset1 = AllocateTransferBuffer(part_size); + offset2 = AllocateTransferBuffer(part_size); + offset3 = AllocateTransferBuffer(part_size); + offset4 = AllocateTransferBuffer(part_size); + expected.tex_image_2d.Init( + kTarget, kLevel, kFormat, kWidth, kHeight, kBorder, kFormat, kType, + 0, 0); + expected.tex_sub_image_2d1.Init( + kTarget, kLevel, 0, 1, kWidth / 2, 1, kFormat, kType, + kTransferBufferId, offset1, true); + expected.set_token1.Init(GetNextToken()); + expected.tex_sub_image_2d2.Init( + kTarget, kLevel, kWidth / 2, 1, kWidth / 2, 1, kFormat, kType, + kTransferBufferId, offset2, true); + expected.set_token2.Init(GetNextToken()); + expected.tex_sub_image_2d3.Init( + kTarget, kLevel, 0, 0, kWidth / 2, 1, kFormat, kType, + kTransferBufferId, offset3, true); + expected.set_token3.Init(GetNextToken()); + expected.tex_sub_image_2d4.Init( + kTarget, kLevel, kWidth / 2, 0, kWidth / 2, 1, kFormat, kType, + kTransferBufferId, offset4, true); + expected.set_token4.Init(GetNextToken()); + + // TODO(gman): Make it possible to run this test + // EXPECT_CALL(*command_buffer_, OnFlush(_)) + // .WillOnce(CheckRectAction( + // kWidth / 2, 1, kFormat, kType, kPixelStoreUnpackAlignment, false, + // pixels.get(), + // GetTransferAddressFromOffsetAs<uint8>(offset1, part_size))) + // .WillOnce(CheckRectAction( + // kWidth / 2, 1, kFormat, kType, kPixelStoreUnpackAlignment, false, + // pixels.get() + part_size, + // GetTransferAddressFromOffsetAs<uint8>(offset2, part_size))) + // .WillOnce(CheckRectAction( + // kWidth / 2, 1, kFormat, kType, kPixelStoreUnpackAlignment, false, + // pixels.get() + padded_row_size, + // GetTransferAddressFromOffsetAs<uint8>(offset3, part_size))) + // .RetiresOnSaturation(); + + gl_->PixelStorei(GL_UNPACK_FLIP_Y_CHROMIUM, GL_TRUE); + gl_->TexImage2D( + kTarget, kLevel, kFormat, kWidth, kHeight, kBorder, kFormat, kType, + pixels.get()); + EXPECT_EQ(0, memcmp(&expected, commands2, sizeof(expected))); + EXPECT_TRUE(CheckRect( + kWidth / 2, 1, kFormat, kType, kPixelStoreUnpackAlignment, false, + pixels.get() + padded_row_size + part_size, + GetTransferAddressFromOffsetAs<uint8>(offset4, part_size))); +} + } // namespace gles2 } // namespace gpu 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 d83c3c1..30bb80f 100644 --- a/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h +++ b/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h @@ -240,6 +240,7 @@ static GLES2Util::EnumToString enum_to_string_table[] = { { 0x8DF3, "GL_LOW_INT", }, { 0x8B53, "GL_INT_VEC2", }, { 0x8B52, "GL_FLOAT_VEC4", }, + { 0x9240, "GL_UNPACK_FLIP_Y_CHROMIUM", }, { 0x8B51, "GL_FLOAT_VEC3", }, { 0x8B50, "GL_FLOAT_VEC2", }, { 0x812F, "GL_CLAMP_TO_EDGE", }, diff --git a/gpu/command_buffer/service/feature_info.cc b/gpu/command_buffer/service/feature_info.cc index f6bf440..b4e71b9 100644 --- a/gpu/command_buffer/service/feature_info.cc +++ b/gpu/command_buffer/service/feature_info.cc @@ -102,7 +102,6 @@ void FeatureInfo::AddFeatures(const char* desired_features) { bool npot_ok = false; - AddExtensionString("GL_CHROMIUM_map_sub"); AddExtensionString("GL_CHROMIUM_copy_texture_to_parent_texture"); AddExtensionString("GL_CHROMIUM_resource_safe"); AddExtensionString("GL_CHROMIUM_resize"); diff --git a/gpu/command_buffer/service/feature_info_unittest.cc b/gpu/command_buffer/service/feature_info_unittest.cc index b2863dc..f3c4797 100644 --- a/gpu/command_buffer/service/feature_info_unittest.cc +++ b/gpu/command_buffer/service/feature_info_unittest.cc @@ -66,7 +66,6 @@ TEST_F(FeatureInfoTest, InitializeNoExtensions) { SetupInitExpectations(""); info_.Initialize(NULL); // Check default extensions are there - EXPECT_THAT(info_.extensions(), HasSubstr("GL_CHROMIUM_map_sub")); EXPECT_THAT(info_.extensions(), HasSubstr("GL_CHROMIUM_copy_texture_to_parent_texture")); EXPECT_THAT(info_.extensions(), HasSubstr("GL_CHROMIUM_resource_safe")); diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc index d5bd745..4d32625 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc @@ -5657,6 +5657,21 @@ error::Error GLES2DecoderImpl::DoTexImage2D( "glTexImage2D: unknown texture for target"); return error::kNoError; } + + GLsizei tex_width = 0; + GLsizei tex_height = 0; + GLenum tex_type = 0; + GLenum tex_format = 0; + bool level_is_same = + 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; + + if (level_is_same && !pixels) { + return error::kNoError; + } + scoped_array<int8> zero; if (!pixels) { zero.reset(new int8[pixels_size]); @@ -5668,19 +5683,10 @@ error::Error GLES2DecoderImpl::DoTexImage2D( state_dirty_ = true; } - 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; - } + if (!teximage2d_faster_than_texsubimage2d_ && level_is_same) { + glTexSubImage2D(target, level, 0, 0, width, height, format, type, pixels); + tex_image_2d_failed_ = false; + return error::kNoError; } CopyRealGLErrorsToWrapper(); |