summaryrefslogtreecommitdiffstats
path: root/gpu
diff options
context:
space:
mode:
authorgman@chromium.org <gman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-07-22 03:25:07 +0000
committergman@chromium.org <gman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-07-22 03:25:07 +0000
commit0226c11e6cfd7510d97aaf4499aa2c10aad8c7e6 (patch)
tree2ad5eae3d1915932745b4b99a872aebc79f4fe12 /gpu
parent212a96285521d213cd7fe720f26a721cdae70d90 (diff)
downloadchromium_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.h17
-rw-r--r--gpu/command_buffer/client/gles2_implementation.cc114
-rw-r--r--gpu/command_buffer/client/gles2_implementation.h6
-rw-r--r--gpu/command_buffer/client/gles2_implementation_unittest.cc372
-rw-r--r--gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h1
-rw-r--r--gpu/command_buffer/service/feature_info.cc1
-rw-r--r--gpu/command_buffer/service/feature_info_unittest.cc1
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder.cc32
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();