summaryrefslogtreecommitdiffstats
path: root/gpu
diff options
context:
space:
mode:
authorzmo <zmo@chromium.org>2015-03-11 17:48:25 -0700
committerCommit bot <commit-bot@chromium.org>2015-03-12 00:49:13 +0000
commit2a09dc05582a7cb4664e9f18cb2c4ba1e39e0c98 (patch)
tree826bac9a2b8e9dd92b59e427742142de57e33ddb /gpu
parent33886ae4a9d84cee3effc75f86feb22b27bde49d (diff)
downloadchromium_src-2a09dc05582a7cb4664e9f18cb2c4ba1e39e0c98.zip
chromium_src-2a09dc05582a7cb4664e9f18cb2c4ba1e39e0c98.tar.gz
chromium_src-2a09dc05582a7cb4664e9f18cb2c4ba1e39e0c98.tar.bz2
Add ES3 command glUnmapBuffer to GPU command buffer.
BUG=429053 TEST=gpu_unittests R=piman@chromium.org Review URL: https://codereview.chromium.org/996913002 Cr-Commit-Position: refs/heads/master@{#320194}
Diffstat (limited to 'gpu')
-rw-r--r--gpu/GLES2/gl2chromium_autogen.h1
-rwxr-xr-xgpu/command_buffer/build_gles2_cmd_buffer.py4
-rw-r--r--gpu/command_buffer/client/gles2_c_lib_autogen.h7
-rw-r--r--gpu/command_buffer/client/gles2_cmd_helper_autogen.h7
-rw-r--r--gpu/command_buffer/client/gles2_implementation.cc39
-rw-r--r--gpu/command_buffer/client/gles2_implementation_autogen.h2
-rw-r--r--gpu/command_buffer/client/gles2_implementation_unittest.cc65
-rw-r--r--gpu/command_buffer/client/gles2_implementation_unittest_autogen.h1
-rw-r--r--gpu/command_buffer/client/gles2_interface_autogen.h1
-rw-r--r--gpu/command_buffer/client/gles2_interface_stub_autogen.h1
-rw-r--r--gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h3
-rw-r--r--gpu/command_buffer/client/gles2_trace_implementation_autogen.h1
-rw-r--r--gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h5
-rw-r--r--gpu/command_buffer/cmd_buffer_functions.txt1
-rw-r--r--gpu/command_buffer/common/gles2_cmd_format_autogen.h32
-rw-r--r--gpu/command_buffer/common/gles2_cmd_format_test_autogen.h10
-rw-r--r--gpu/command_buffer/common/gles2_cmd_ids_autogen.h95
-rw-r--r--gpu/command_buffer/service/buffer_manager.cc26
-rw-r--r--gpu/command_buffer/service/buffer_manager.h31
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder.cc56
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_unittest_3_autogen.h2
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_unittest_buffers.cc256
22 files changed, 536 insertions, 110 deletions
diff --git a/gpu/GLES2/gl2chromium_autogen.h b/gpu/GLES2/gl2chromium_autogen.h
index 0f3ebf3..d04bf11 100644
--- a/gpu/GLES2/gl2chromium_autogen.h
+++ b/gpu/GLES2/gl2chromium_autogen.h
@@ -257,6 +257,7 @@
#define glMapBufferSubDataCHROMIUM GLES2_GET_FUN(MapBufferSubDataCHROMIUM)
#define glUnmapBufferSubDataCHROMIUM GLES2_GET_FUN(UnmapBufferSubDataCHROMIUM)
#define glMapBufferRange GLES2_GET_FUN(MapBufferRange)
+#define glUnmapBuffer GLES2_GET_FUN(UnmapBuffer)
#define glMapTexSubImage2DCHROMIUM GLES2_GET_FUN(MapTexSubImage2DCHROMIUM)
#define glUnmapTexSubImage2DCHROMIUM GLES2_GET_FUN(UnmapTexSubImage2DCHROMIUM)
#define glResizeCHROMIUM GLES2_GET_FUN(ResizeCHROMIUM)
diff --git a/gpu/command_buffer/build_gles2_cmd_buffer.py b/gpu/command_buffer/build_gles2_cmd_buffer.py
index 4207305..3e86540 100755
--- a/gpu/command_buffer/build_gles2_cmd_buffer.py
+++ b/gpu/command_buffer/build_gles2_cmd_buffer.py
@@ -2912,6 +2912,10 @@ _FUNCTION_INFO = {
'client_test': False,
'pepper_interface': 'ChromiumMapSub',
},
+ 'UnmapBuffer': {
+ 'type': 'Custom',
+ 'unsafe': True,
+ },
'UnmapTexSubImage2DCHROMIUM': {
'gen_cmd': False,
'extension': True,
diff --git a/gpu/command_buffer/client/gles2_c_lib_autogen.h b/gpu/command_buffer/client/gles2_c_lib_autogen.h
index 84a5708..ff604c6 100644
--- a/gpu/command_buffer/client/gles2_c_lib_autogen.h
+++ b/gpu/command_buffer/client/gles2_c_lib_autogen.h
@@ -1071,6 +1071,9 @@ void* GLES2MapBufferRange(GLenum target,
GLbitfield access) {
return gles2::GetGLContext()->MapBufferRange(target, offset, size, access);
}
+GLboolean GLES2UnmapBuffer(GLenum target) {
+ return gles2::GetGLContext()->UnmapBuffer(target);
+}
void* GLES2MapTexSubImage2DCHROMIUM(GLenum target,
GLint level,
GLint xoffset,
@@ -2303,6 +2306,10 @@ extern const NameToFunc g_gles2_function_table[] = {
reinterpret_cast<GLES2FunctionPointer>(glMapBufferRange),
},
{
+ "glUnmapBuffer",
+ reinterpret_cast<GLES2FunctionPointer>(glUnmapBuffer),
+ },
+ {
"glMapTexSubImage2DCHROMIUM",
reinterpret_cast<GLES2FunctionPointer>(glMapTexSubImage2DCHROMIUM),
},
diff --git a/gpu/command_buffer/client/gles2_cmd_helper_autogen.h b/gpu/command_buffer/client/gles2_cmd_helper_autogen.h
index e9abfc7..bd40e41 100644
--- a/gpu/command_buffer/client/gles2_cmd_helper_autogen.h
+++ b/gpu/command_buffer/client/gles2_cmd_helper_autogen.h
@@ -2241,6 +2241,13 @@ void MapBufferRange(GLenum target,
}
}
+void UnmapBuffer(GLenum target) {
+ gles2::cmds::UnmapBuffer* c = GetCmdSpace<gles2::cmds::UnmapBuffer>();
+ if (c) {
+ c->Init(target);
+ }
+}
+
void ResizeCHROMIUM(GLuint width, GLuint height, GLfloat scale_factor) {
gles2::cmds::ResizeCHROMIUM* c = GetCmdSpace<gles2::cmds::ResizeCHROMIUM>();
if (c) {
diff --git a/gpu/command_buffer/client/gles2_implementation.cc b/gpu/command_buffer/client/gles2_implementation.cc
index 74e79ef..c31ee5e 100644
--- a/gpu/command_buffer/client/gles2_implementation.cc
+++ b/gpu/command_buffer/client/gles2_implementation.cc
@@ -3748,6 +3748,45 @@ void* GLES2Implementation::MapBufferRange(
return mem;
}
+GLboolean GLES2Implementation::UnmapBuffer(GLenum target) {
+ GPU_CLIENT_SINGLE_THREAD_CHECK();
+ GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glUnmapBuffer("
+ << GLES2Util::GetStringEnum(target) << ")");
+ switch (target) {
+ case GL_ARRAY_BUFFER:
+ case GL_ELEMENT_ARRAY_BUFFER:
+ case GL_COPY_READ_BUFFER:
+ case GL_COPY_WRITE_BUFFER:
+ case GL_PIXEL_PACK_BUFFER:
+ case GL_PIXEL_UNPACK_BUFFER:
+ case GL_TRANSFORM_FEEDBACK_BUFFER:
+ case GL_UNIFORM_BUFFER:
+ break;
+ default:
+ SetGLError(GL_INVALID_ENUM, "glUnmapBuffer", "invalid target");
+ return GL_FALSE;
+ }
+ GLuint buffer = GetBoundBufferHelper(target);
+ if (buffer == 0) {
+ SetGLError(GL_INVALID_OPERATION, "glUnmapBuffer", "no buffer bound");
+ return GL_FALSE;
+ }
+ auto iter = mapped_buffer_range_map_.find(buffer);
+ if (iter == mapped_buffer_range_map_.end()) {
+ SetGLError(GL_INVALID_OPERATION, "glUnmapBuffer", "buffer is unmapped");
+ return GL_FALSE;
+ }
+
+ helper_->UnmapBuffer(target);
+ RemoveMappedBufferRangeById(buffer);
+ // TODO(zmo): There is a rare situation that data might be corrupted and
+ // GL_FALSE should be returned. We lose context on that sitatuon, so we
+ // don't have to WaitForCmd().
+ GPU_CLIENT_LOG(" returned " << GL_TRUE);
+ CheckGLError();
+ return GL_TRUE;
+}
+
void* GLES2Implementation::MapTexSubImage2DCHROMIUM(
GLenum target,
GLint level,
diff --git a/gpu/command_buffer/client/gles2_implementation_autogen.h b/gpu/command_buffer/client/gles2_implementation_autogen.h
index 5111a6a..a452193 100644
--- a/gpu/command_buffer/client/gles2_implementation_autogen.h
+++ b/gpu/command_buffer/client/gles2_implementation_autogen.h
@@ -805,6 +805,8 @@ void* MapBufferRange(GLenum target,
GLsizeiptr size,
GLbitfield access) override;
+GLboolean UnmapBuffer(GLenum target) override;
+
void* MapTexSubImage2DCHROMIUM(GLenum target,
GLint level,
GLint xoffset,
diff --git a/gpu/command_buffer/client/gles2_implementation_unittest.cc b/gpu/command_buffer/client/gles2_implementation_unittest.cc
index 16908ca..4fecbbc 100644
--- a/gpu/command_buffer/client/gles2_implementation_unittest.cc
+++ b/gpu/command_buffer/client/gles2_implementation_unittest.cc
@@ -3600,7 +3600,7 @@ TEST_F(GLES2ImplementationTest, WaitSync) {
EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
}
-TEST_F(GLES2ImplementationTest, MapBufferRangeWrite) {
+TEST_F(GLES2ImplementationTest, MapBufferRangeUnmapBufferWrite) {
ExpectedMemoryInfo result =
GetExpectedResultMemory(sizeof(cmds::MapBufferRange::Result));
@@ -3613,6 +3613,8 @@ TEST_F(GLES2ImplementationTest, MapBufferRangeWrite) {
void* mem = gl_->MapBufferRange(GL_ARRAY_BUFFER, 10, 64, GL_MAP_WRITE_BIT);
EXPECT_TRUE(mem != nullptr);
+
+ EXPECT_TRUE(gl_->UnmapBuffer(GL_ARRAY_BUFFER));
}
TEST_F(GLES2ImplementationTest, MapBufferRangeWriteWithInvalidateBit) {
@@ -3652,7 +3654,7 @@ TEST_F(GLES2ImplementationTest, MapBufferRangeWriteWithGLError) {
EXPECT_TRUE(mem == nullptr);
}
-TEST_F(GLES2ImplementationTest, MapBufferRangeRead) {
+TEST_F(GLES2ImplementationTest, MapBufferRangeUnmapBufferRead) {
ExpectedMemoryInfo result =
GetExpectedResultMemory(sizeof(cmds::MapBufferRange::Result));
@@ -3665,6 +3667,8 @@ TEST_F(GLES2ImplementationTest, MapBufferRangeRead) {
void* mem = gl_->MapBufferRange(GL_ARRAY_BUFFER, 10, 64, GL_MAP_READ_BIT);
EXPECT_TRUE(mem != nullptr);
+
+ EXPECT_TRUE(gl_->UnmapBuffer(GL_ARRAY_BUFFER));
}
TEST_F(GLES2ImplementationTest, MapBufferRangeReadWithGLError) {
@@ -3683,6 +3687,63 @@ TEST_F(GLES2ImplementationTest, MapBufferRangeReadWithGLError) {
EXPECT_TRUE(mem == nullptr);
}
+TEST_F(GLES2ImplementationTest, UnmapBufferFails) {
+ // No bound buffer.
+ EXPECT_FALSE(gl_->UnmapBuffer(GL_ARRAY_BUFFER));
+ EXPECT_EQ(GL_INVALID_OPERATION, CheckError());
+
+ const GLuint kBufferId = 123;
+ gl_->BindBuffer(GL_ARRAY_BUFFER, kBufferId);
+
+ // Buffer is unmapped.
+ EXPECT_FALSE(gl_->UnmapBuffer(GL_ARRAY_BUFFER));
+ EXPECT_EQ(GL_INVALID_OPERATION, CheckError());
+}
+
+TEST_F(GLES2ImplementationTest, BufferDataUnmapsDataStore) {
+ ExpectedMemoryInfo result =
+ GetExpectedResultMemory(sizeof(cmds::MapBufferRange::Result));
+
+ EXPECT_CALL(*command_buffer(), OnFlush())
+ .WillOnce(SetMemory(result.ptr, uint32_t(1)))
+ .RetiresOnSaturation();
+
+ const GLuint kBufferId = 123;
+ gl_->BindBuffer(GL_ARRAY_BUFFER, kBufferId);
+
+ void* mem = gl_->MapBufferRange(GL_ARRAY_BUFFER, 10, 64, GL_MAP_WRITE_BIT);
+ EXPECT_TRUE(mem != nullptr);
+
+ std::vector<uint8_t> data(16);
+ // BufferData unmaps the data store.
+ gl_->BufferData(GL_ARRAY_BUFFER, 16, &data[0], GL_STREAM_DRAW);
+
+ EXPECT_FALSE(gl_->UnmapBuffer(GL_ARRAY_BUFFER));
+ EXPECT_EQ(GL_INVALID_OPERATION, CheckError());
+}
+
+TEST_F(GLES2ImplementationTest, DeleteBuffersUnmapsDataStore) {
+ ExpectedMemoryInfo result =
+ GetExpectedResultMemory(sizeof(cmds::MapBufferRange::Result));
+
+ EXPECT_CALL(*command_buffer(), OnFlush())
+ .WillOnce(SetMemory(result.ptr, uint32_t(1)))
+ .RetiresOnSaturation();
+
+ const GLuint kBufferId = 123;
+ gl_->BindBuffer(GL_ARRAY_BUFFER, kBufferId);
+
+ void* mem = gl_->MapBufferRange(GL_ARRAY_BUFFER, 10, 64, GL_MAP_WRITE_BIT);
+ EXPECT_TRUE(mem != nullptr);
+
+ std::vector<uint8_t> data(16);
+ // DeleteBuffers unmaps the data store.
+ gl_->DeleteBuffers(1, &kBufferId);
+
+ EXPECT_FALSE(gl_->UnmapBuffer(GL_ARRAY_BUFFER));
+ EXPECT_EQ(GL_INVALID_OPERATION, CheckError());
+}
+
TEST_F(GLES2ImplementationManualInitTest, LoseContextOnOOM) {
ContextInitOptions init_options;
init_options.lose_context_when_out_of_memory = true;
diff --git a/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h b/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h
index 4785ff0..ad794d2 100644
--- a/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h
+++ b/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h
@@ -2719,6 +2719,7 @@ TEST_F(GLES2ImplementationTest, IsVertexArrayOES) {
}
// TODO(zmo): Implement unit test for EnableFeatureCHROMIUM
// TODO(zmo): Implement unit test for MapBufferRange
+// TODO(zmo): Implement unit test for UnmapBuffer
TEST_F(GLES2ImplementationTest, ResizeCHROMIUM) {
struct Cmds {
diff --git a/gpu/command_buffer/client/gles2_interface_autogen.h b/gpu/command_buffer/client/gles2_interface_autogen.h
index a181c43..0a3c12bf 100644
--- a/gpu/command_buffer/client/gles2_interface_autogen.h
+++ b/gpu/command_buffer/client/gles2_interface_autogen.h
@@ -587,6 +587,7 @@ virtual void* MapBufferRange(GLenum target,
GLintptr offset,
GLsizeiptr size,
GLbitfield access) = 0;
+virtual GLboolean UnmapBuffer(GLenum target) = 0;
virtual void* MapTexSubImage2DCHROMIUM(GLenum target,
GLint level,
GLint xoffset,
diff --git a/gpu/command_buffer/client/gles2_interface_stub_autogen.h b/gpu/command_buffer/client/gles2_interface_stub_autogen.h
index 48697d5..fd933f2 100644
--- a/gpu/command_buffer/client/gles2_interface_stub_autogen.h
+++ b/gpu/command_buffer/client/gles2_interface_stub_autogen.h
@@ -572,6 +572,7 @@ void* MapBufferRange(GLenum target,
GLintptr offset,
GLsizeiptr size,
GLbitfield access) override;
+GLboolean UnmapBuffer(GLenum target) override;
void* MapTexSubImage2DCHROMIUM(GLenum target,
GLint level,
GLint xoffset,
diff --git a/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h b/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h
index dfbb319..e350029 100644
--- a/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h
+++ b/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h
@@ -993,6 +993,9 @@ void* GLES2InterfaceStub::MapBufferRange(GLenum /* target */,
GLbitfield /* access */) {
return 0;
}
+GLboolean GLES2InterfaceStub::UnmapBuffer(GLenum /* target */) {
+ return 0;
+}
void* GLES2InterfaceStub::MapTexSubImage2DCHROMIUM(GLenum /* target */,
GLint /* level */,
GLint /* xoffset */,
diff --git a/gpu/command_buffer/client/gles2_trace_implementation_autogen.h b/gpu/command_buffer/client/gles2_trace_implementation_autogen.h
index 32ccdab..9d148ce 100644
--- a/gpu/command_buffer/client/gles2_trace_implementation_autogen.h
+++ b/gpu/command_buffer/client/gles2_trace_implementation_autogen.h
@@ -572,6 +572,7 @@ void* MapBufferRange(GLenum target,
GLintptr offset,
GLsizeiptr size,
GLbitfield access) override;
+GLboolean UnmapBuffer(GLenum target) override;
void* MapTexSubImage2DCHROMIUM(GLenum target,
GLint level,
GLint xoffset,
diff --git a/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h b/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h
index 327becc..699f99b 100644
--- a/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h
+++ b/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h
@@ -1691,6 +1691,11 @@ void* GLES2TraceImplementation::MapBufferRange(GLenum target,
return gl_->MapBufferRange(target, offset, size, access);
}
+GLboolean GLES2TraceImplementation::UnmapBuffer(GLenum target) {
+ TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::UnmapBuffer");
+ return gl_->UnmapBuffer(target);
+}
+
void* GLES2TraceImplementation::MapTexSubImage2DCHROMIUM(GLenum target,
GLint level,
GLint xoffset,
diff --git a/gpu/command_buffer/cmd_buffer_functions.txt b/gpu/command_buffer/cmd_buffer_functions.txt
index 153aca4..8d32d99 100644
--- a/gpu/command_buffer/cmd_buffer_functions.txt
+++ b/gpu/command_buffer/cmd_buffer_functions.txt
@@ -247,6 +247,7 @@ GL_APICALL GLboolean GL_APIENTRY glUnmapBufferCHROMIUM (GLuint target);
GL_APICALL void* GL_APIENTRY glMapBufferSubDataCHROMIUM (GLuint target, GLintptrNotNegative offset, GLsizeiptr size, GLenum access);
GL_APICALL void GL_APIENTRY glUnmapBufferSubDataCHROMIUM (const void* mem);
GL_APICALL void* GL_APIENTRY glMapBufferRange (GLenumBufferTarget target, GLintptrNotNegative offset, GLsizeiptr size, GLbitfieldMapBufferAccess access);
+GL_APICALL GLboolean GL_APIENTRY glUnmapBuffer (GLenumBufferTarget target);
GL_APICALL void* GL_APIENTRY glMapTexSubImage2DCHROMIUM (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLenum access);
GL_APICALL void GL_APIENTRY glUnmapTexSubImage2DCHROMIUM (const void* mem);
GL_APICALL void GL_APIENTRY glResizeCHROMIUM (GLuint width, GLuint height, GLfloat scale_factor);
diff --git a/gpu/command_buffer/common/gles2_cmd_format_autogen.h b/gpu/command_buffer/common/gles2_cmd_format_autogen.h
index 251bfff..a829dcb 100644
--- a/gpu/command_buffer/common/gles2_cmd_format_autogen.h
+++ b/gpu/command_buffer/common/gles2_cmd_format_autogen.h
@@ -11019,6 +11019,38 @@ static_assert(offsetof(MapBufferRange, result_shm_id) == 28,
static_assert(offsetof(MapBufferRange, result_shm_offset) == 32,
"offset of MapBufferRange result_shm_offset should be 32");
+struct UnmapBuffer {
+ typedef UnmapBuffer ValueType;
+ static const CommandId kCmdId = kUnmapBuffer;
+ static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+ static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3);
+
+ static uint32_t ComputeSize() {
+ return static_cast<uint32_t>(sizeof(ValueType)); // NOLINT
+ }
+
+ void SetHeader() { header.SetCmd<ValueType>(); }
+
+ void Init(GLenum _target) {
+ SetHeader();
+ target = _target;
+ }
+
+ void* Set(void* cmd, GLenum _target) {
+ static_cast<ValueType*>(cmd)->Init(_target);
+ return NextCmdAddress<ValueType>(cmd);
+ }
+
+ gpu::CommandHeader header;
+ uint32_t target;
+};
+
+static_assert(sizeof(UnmapBuffer) == 8, "size of UnmapBuffer should be 8");
+static_assert(offsetof(UnmapBuffer, header) == 0,
+ "offset of UnmapBuffer header should be 0");
+static_assert(offsetof(UnmapBuffer, target) == 4,
+ "offset of UnmapBuffer target should be 4");
+
struct ResizeCHROMIUM {
typedef ResizeCHROMIUM ValueType;
static const CommandId kCmdId = kResizeCHROMIUM;
diff --git a/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h b/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h
index 55485bf..d14f48df 100644
--- a/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h
+++ b/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h
@@ -3799,6 +3799,16 @@ TEST_F(GLES2FormatTest, MapBufferRange) {
CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd));
}
+TEST_F(GLES2FormatTest, UnmapBuffer) {
+ cmds::UnmapBuffer& cmd = *GetBufferAs<cmds::UnmapBuffer>();
+ void* next_cmd = cmd.Set(&cmd, static_cast<GLenum>(11));
+ EXPECT_EQ(static_cast<uint32_t>(cmds::UnmapBuffer::kCmdId),
+ cmd.header.command);
+ EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u);
+ EXPECT_EQ(static_cast<GLenum>(11), cmd.target);
+ CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd));
+}
+
TEST_F(GLES2FormatTest, ResizeCHROMIUM) {
cmds::ResizeCHROMIUM& cmd = *GetBufferAs<cmds::ResizeCHROMIUM>();
void* next_cmd = cmd.Set(&cmd, static_cast<GLuint>(11),
diff --git a/gpu/command_buffer/common/gles2_cmd_ids_autogen.h b/gpu/command_buffer/common/gles2_cmd_ids_autogen.h
index 997268c2..ea62be1 100644
--- a/gpu/command_buffer/common/gles2_cmd_ids_autogen.h
+++ b/gpu/command_buffer/common/gles2_cmd_ids_autogen.h
@@ -244,53 +244,54 @@
OP(GetMaxValueInBufferCHROMIUM) /* 485 */ \
OP(EnableFeatureCHROMIUM) /* 486 */ \
OP(MapBufferRange) /* 487 */ \
- OP(ResizeCHROMIUM) /* 488 */ \
- OP(GetRequestableExtensionsCHROMIUM) /* 489 */ \
- OP(RequestExtensionCHROMIUM) /* 490 */ \
- OP(GetProgramInfoCHROMIUM) /* 491 */ \
- OP(GetUniformBlocksCHROMIUM) /* 492 */ \
- OP(GetTransformFeedbackVaryingsCHROMIUM) /* 493 */ \
- OP(GetUniformsES3CHROMIUM) /* 494 */ \
- OP(GetTranslatedShaderSourceANGLE) /* 495 */ \
- OP(PostSubBufferCHROMIUM) /* 496 */ \
- OP(TexImageIOSurface2DCHROMIUM) /* 497 */ \
- OP(CopyTextureCHROMIUM) /* 498 */ \
- OP(CopySubTextureCHROMIUM) /* 499 */ \
- OP(DrawArraysInstancedANGLE) /* 500 */ \
- OP(DrawElementsInstancedANGLE) /* 501 */ \
- OP(VertexAttribDivisorANGLE) /* 502 */ \
- OP(GenMailboxCHROMIUM) /* 503 */ \
- OP(ProduceTextureCHROMIUMImmediate) /* 504 */ \
- OP(ProduceTextureDirectCHROMIUMImmediate) /* 505 */ \
- OP(ConsumeTextureCHROMIUMImmediate) /* 506 */ \
- OP(CreateAndConsumeTextureCHROMIUMImmediate) /* 507 */ \
- OP(BindUniformLocationCHROMIUMBucket) /* 508 */ \
- OP(GenValuebuffersCHROMIUMImmediate) /* 509 */ \
- OP(DeleteValuebuffersCHROMIUMImmediate) /* 510 */ \
- OP(IsValuebufferCHROMIUM) /* 511 */ \
- OP(BindValuebufferCHROMIUM) /* 512 */ \
- OP(SubscribeValueCHROMIUM) /* 513 */ \
- OP(PopulateSubscribedValuesCHROMIUM) /* 514 */ \
- OP(UniformValuebufferCHROMIUM) /* 515 */ \
- OP(BindTexImage2DCHROMIUM) /* 516 */ \
- OP(ReleaseTexImage2DCHROMIUM) /* 517 */ \
- OP(TraceBeginCHROMIUM) /* 518 */ \
- OP(TraceEndCHROMIUM) /* 519 */ \
- OP(AsyncTexSubImage2DCHROMIUM) /* 520 */ \
- OP(AsyncTexImage2DCHROMIUM) /* 521 */ \
- OP(WaitAsyncTexImage2DCHROMIUM) /* 522 */ \
- OP(WaitAllAsyncTexImage2DCHROMIUM) /* 523 */ \
- OP(DiscardFramebufferEXTImmediate) /* 524 */ \
- OP(LoseContextCHROMIUM) /* 525 */ \
- OP(InsertSyncPointCHROMIUM) /* 526 */ \
- OP(WaitSyncPointCHROMIUM) /* 527 */ \
- OP(DrawBuffersEXTImmediate) /* 528 */ \
- OP(DiscardBackbufferCHROMIUM) /* 529 */ \
- OP(ScheduleOverlayPlaneCHROMIUM) /* 530 */ \
- OP(SwapInterval) /* 531 */ \
- OP(MatrixLoadfCHROMIUMImmediate) /* 532 */ \
- OP(MatrixLoadIdentityCHROMIUM) /* 533 */ \
- OP(BlendBarrierKHR) /* 534 */
+ OP(UnmapBuffer) /* 488 */ \
+ OP(ResizeCHROMIUM) /* 489 */ \
+ OP(GetRequestableExtensionsCHROMIUM) /* 490 */ \
+ OP(RequestExtensionCHROMIUM) /* 491 */ \
+ OP(GetProgramInfoCHROMIUM) /* 492 */ \
+ OP(GetUniformBlocksCHROMIUM) /* 493 */ \
+ OP(GetTransformFeedbackVaryingsCHROMIUM) /* 494 */ \
+ OP(GetUniformsES3CHROMIUM) /* 495 */ \
+ OP(GetTranslatedShaderSourceANGLE) /* 496 */ \
+ OP(PostSubBufferCHROMIUM) /* 497 */ \
+ OP(TexImageIOSurface2DCHROMIUM) /* 498 */ \
+ OP(CopyTextureCHROMIUM) /* 499 */ \
+ OP(CopySubTextureCHROMIUM) /* 500 */ \
+ OP(DrawArraysInstancedANGLE) /* 501 */ \
+ OP(DrawElementsInstancedANGLE) /* 502 */ \
+ OP(VertexAttribDivisorANGLE) /* 503 */ \
+ OP(GenMailboxCHROMIUM) /* 504 */ \
+ OP(ProduceTextureCHROMIUMImmediate) /* 505 */ \
+ OP(ProduceTextureDirectCHROMIUMImmediate) /* 506 */ \
+ OP(ConsumeTextureCHROMIUMImmediate) /* 507 */ \
+ OP(CreateAndConsumeTextureCHROMIUMImmediate) /* 508 */ \
+ OP(BindUniformLocationCHROMIUMBucket) /* 509 */ \
+ OP(GenValuebuffersCHROMIUMImmediate) /* 510 */ \
+ OP(DeleteValuebuffersCHROMIUMImmediate) /* 511 */ \
+ OP(IsValuebufferCHROMIUM) /* 512 */ \
+ OP(BindValuebufferCHROMIUM) /* 513 */ \
+ OP(SubscribeValueCHROMIUM) /* 514 */ \
+ OP(PopulateSubscribedValuesCHROMIUM) /* 515 */ \
+ OP(UniformValuebufferCHROMIUM) /* 516 */ \
+ OP(BindTexImage2DCHROMIUM) /* 517 */ \
+ OP(ReleaseTexImage2DCHROMIUM) /* 518 */ \
+ OP(TraceBeginCHROMIUM) /* 519 */ \
+ OP(TraceEndCHROMIUM) /* 520 */ \
+ OP(AsyncTexSubImage2DCHROMIUM) /* 521 */ \
+ OP(AsyncTexImage2DCHROMIUM) /* 522 */ \
+ OP(WaitAsyncTexImage2DCHROMIUM) /* 523 */ \
+ OP(WaitAllAsyncTexImage2DCHROMIUM) /* 524 */ \
+ OP(DiscardFramebufferEXTImmediate) /* 525 */ \
+ OP(LoseContextCHROMIUM) /* 526 */ \
+ OP(InsertSyncPointCHROMIUM) /* 527 */ \
+ OP(WaitSyncPointCHROMIUM) /* 528 */ \
+ OP(DrawBuffersEXTImmediate) /* 529 */ \
+ OP(DiscardBackbufferCHROMIUM) /* 530 */ \
+ OP(ScheduleOverlayPlaneCHROMIUM) /* 531 */ \
+ OP(SwapInterval) /* 532 */ \
+ OP(MatrixLoadfCHROMIUMImmediate) /* 533 */ \
+ OP(MatrixLoadIdentityCHROMIUM) /* 534 */ \
+ OP(BlendBarrierKHR) /* 535 */
enum CommandId {
kStartPoint = cmd::kLastCommonId, // All GLES2 commands start after this.
diff --git a/gpu/command_buffer/service/buffer_manager.cc b/gpu/command_buffer/service/buffer_manager.cc
index d151a65..c2a0ba5 100644
--- a/gpu/command_buffer/service/buffer_manager.cc
+++ b/gpu/command_buffer/service/buffer_manager.cc
@@ -74,6 +74,27 @@ void BufferManager::StopTracking(Buffer* buffer) {
--buffer_count_;
}
+Buffer::MappedRange::MappedRange(
+ GLintptr offset, GLsizeiptr size, GLenum access, void* pointer,
+ scoped_refptr<gpu::Buffer> shm)
+ : offset(offset),
+ size(size),
+ access(access),
+ pointer(pointer),
+ shm(shm) {
+ DCHECK(pointer);
+ DCHECK(shm.get() && GetShmPointer());
+}
+
+Buffer::MappedRange::~MappedRange() {
+}
+
+void* Buffer::MappedRange::GetShmPointer() const {
+ DCHECK(shm.get());
+ return shm->GetDataAddress(static_cast<unsigned int>(offset),
+ static_cast<unsigned int>(size));
+}
+
Buffer::Buffer(BufferManager* manager, GLuint service_id)
: manager_(manager),
size_(0),
@@ -82,8 +103,7 @@ Buffer::Buffer(BufferManager* manager, GLuint service_id)
is_client_side_array_(false),
service_id_(service_id),
target_(0),
- usage_(GL_STATIC_DRAW),
- buffer_range_pointer_(nullptr) {
+ usage_(GL_STATIC_DRAW) {
manager_->StartTracking(this);
}
@@ -120,7 +140,7 @@ void Buffer::SetInfo(
memset(shadow_.get(), 0, size);
}
}
- buffer_range_pointer_ = nullptr;
+ mapped_range_.reset(nullptr);
}
bool Buffer::CheckRange(
diff --git a/gpu/command_buffer/service/buffer_manager.h b/gpu/command_buffer/service/buffer_manager.h
index fb6261d..29bfaf4 100644
--- a/gpu/command_buffer/service/buffer_manager.h
+++ b/gpu/command_buffer/service/buffer_manager.h
@@ -11,6 +11,7 @@
#include "base/logging.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
+#include "gpu/command_buffer/common/buffer.h"
#include "gpu/command_buffer/service/gl_utils.h"
#include "gpu/command_buffer/service/memory_tracking.h"
#include "gpu/gpu_export.h"
@@ -27,6 +28,19 @@ class TestHelper;
// Info about Buffers currently in the system.
class GPU_EXPORT Buffer : public base::RefCounted<Buffer> {
public:
+ struct MappedRange {
+ GLintptr offset;
+ GLsizeiptr size;
+ GLenum access;
+ void* pointer; // Pointer returned by driver.
+ scoped_refptr<gpu::Buffer> shm; // Client side mem.
+
+ MappedRange(GLintptr offset, GLsizeiptr size, GLenum access,
+ void* pointer, scoped_refptr<gpu::Buffer> shm);
+ ~MappedRange();
+ void* GetShmPointer() const;
+ };
+
Buffer(BufferManager* manager, GLuint service_id);
GLuint service_id() const {
@@ -67,12 +81,17 @@ class GPU_EXPORT Buffer : public base::RefCounted<Buffer> {
return is_client_side_array_;
}
- void set_buffer_range_pointer(void* mem) {
- buffer_range_pointer_ = mem;
+ void SetMappedRange(GLintptr offset, GLsizeiptr size, GLenum access,
+ void* pointer, scoped_refptr<gpu::Buffer> shm) {
+ mapped_range_.reset(new MappedRange(offset, size, access, pointer, shm));
+ }
+
+ void RemoveMappedRange() {
+ mapped_range_.reset(nullptr);
}
- void* buffer_range_pointer() const {
- return buffer_range_pointer_;
+ const MappedRange* GetMappedRange() const {
+ return mapped_range_.get();
}
private:
@@ -171,8 +190,8 @@ class GPU_EXPORT Buffer : public base::RefCounted<Buffer> {
// Usage of buffer.
GLenum usage_;
- // Returned value from last glMapBufferRange call.
- void* buffer_range_pointer_;
+ // Data cached from last glMapBufferRange call.
+ scoped_ptr<MappedRange> mapped_range_;
// A map of ranges to the highest value in that range of a certain type.
typedef std::map<Range, GLuint, Range::Less> RangeToMaxValueMap;
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
index 3cf4dda..3e568e3 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -3113,7 +3113,7 @@ void GLES2DecoderImpl::DeleteBuffersHelper(
for (GLsizei ii = 0; ii < n; ++ii) {
Buffer* buffer = GetBuffer(client_ids[ii]);
if (buffer && !buffer->IsDeleted()) {
- buffer->set_buffer_range_pointer(nullptr);
+ buffer->RemoveMappedRange();
state_.vertex_attrib_manager->Unbind(buffer);
if (state_.bound_array_buffer.get() == buffer) {
state_.bound_array_buffer = NULL;
@@ -12343,9 +12343,8 @@ error::Error GLES2DecoderImpl::HandleMapBufferRange(
}
Buffer* buffer = buffer_manager()->GetBufferInfoForTarget(&state_, target);
DCHECK(buffer);
- if ((access & GL_MAP_WRITE_BIT) == GL_MAP_WRITE_BIT) {
- buffer->set_buffer_range_pointer(ptr);
- }
+ buffer->SetMappedRange(offset, size, access, ptr,
+ GetSharedMemoryBuffer(c.data_shm_id));
if ((access & GL_MAP_INVALIDATE_RANGE_BIT) == 0) {
memcpy(mem, ptr, size);
}
@@ -12353,6 +12352,55 @@ error::Error GLES2DecoderImpl::HandleMapBufferRange(
return error::kNoError;
}
+error::Error GLES2DecoderImpl::HandleUnmapBuffer(
+ uint32_t immediate_data_size, const void* cmd_data) {
+ if (!unsafe_es3_apis_enabled()) {
+ return error::kUnknownCommand;
+ }
+ const gles2::cmds::UnmapBuffer& c =
+ *static_cast<const gles2::cmds::UnmapBuffer*>(cmd_data);
+ GLenum target = static_cast<GLenum>(c.target);
+
+ Buffer* buffer = buffer_manager()->GetBufferInfoForTarget(&state_, target);
+ if (!buffer) {
+ LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "UnmapBuffer", "no buffer bound");
+ return error::kNoError;
+ }
+ const Buffer::MappedRange* mapped_range = buffer->GetMappedRange();
+ if (!mapped_range) {
+ LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "UnmapBuffer",
+ "buffer is unmapped");
+ return error::kNoError;
+ }
+ if ((mapped_range->access & GL_MAP_WRITE_BIT) == 0 ||
+ (mapped_range->access & GL_MAP_FLUSH_EXPLICIT_BIT) ==
+ GL_MAP_FLUSH_EXPLICIT_BIT) {
+ // If we don't need to write back, or explict flush is required, no copying
+ // back is needed.
+ } else {
+ void* mem = mapped_range->GetShmPointer();
+ if (!mem) {
+ return error::kOutOfBounds;
+ }
+ DCHECK(mapped_range->pointer);
+ memcpy(mapped_range->pointer, mem, mapped_range->size);
+ }
+ buffer->RemoveMappedRange();
+ GLboolean rt = glUnmapBuffer(target);
+ if (rt == GL_FALSE) {
+ // At this point, we have already done the necessary validation, so
+ // GL_FALSE indicates data corruption.
+ // TODO(zmo): We could redo the map / copy data / unmap to recover, but
+ // the second unmap could still return GL_FALSE. For now, we simply lose
+ // the contexts in the share group.
+ LOG(ERROR) << "glUnmapBuffer unexpectedly returned GL_FALSE";
+ group_->LoseContexts(GL_INNOCENT_CONTEXT_RESET_ARB);
+ reset_status_ = GL_GUILTY_CONTEXT_RESET_ARB;
+ return error::kLostContext;
+ }
+ return error::kNoError;
+}
+
void GLES2DecoderImpl::OnTextureRefDetachedFromFramebuffer(
TextureRef* texture_ref) {
Texture* texture = texture_ref->texture();
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_3_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_3_autogen.h
index fe5975e..2e153b4 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_3_autogen.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_3_autogen.h
@@ -220,6 +220,8 @@ TEST_P(GLES2DecoderTest3, PopGroupMarkerEXTValidArgs) {
// TODO(gman): MapBufferRange
+// TODO(gman): UnmapBuffer
+
// TODO(gman): ResizeCHROMIUM
// TODO(gman): GetRequestableExtensionsCHROMIUM
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_buffers.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_buffers.cc
index 1c934dd..389c78f 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_buffers.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_buffers.cc
@@ -19,83 +19,123 @@ namespace {
} // namespace anonymous
-TEST_P(GLES2DecoderTest, MapBufferRangeReadSucceeds) {
+TEST_P(GLES2DecoderTest, MapBufferRangeUnmapBufferReadSucceeds) {
const GLenum kTarget = GL_ARRAY_BUFFER;
const GLintptr kOffset = 10;
const GLsizeiptr kSize = 64;
const GLbitfield kAccess = GL_MAP_READ_BIT;
+ uint32_t result_shm_id = kSharedMemoryId;
+ uint32_t result_shm_offset = kSharedMemoryOffset;
+ uint32_t data_shm_id = kSharedMemoryId;
+ // uint32_t is Result for both MapBufferRange and UnmapBuffer commands.
+ uint32_t data_shm_offset = kSharedMemoryOffset + sizeof(uint32_t);
+
DoBindBuffer(kTarget, client_buffer_id_, kServiceBufferId);
std::vector<int8_t> data(kSize);
for (GLsizeiptr ii = 0; ii < kSize; ++ii) {
data[ii] = static_cast<int8_t>(ii % 255);
}
- EXPECT_CALL(*gl_,
- MapBufferRange(kTarget, kOffset, kSize, kAccess))
- .WillOnce(Return(&data[0]))
- .RetiresOnSaturation();
- typedef MapBufferRange::Result Result;
- Result* result = GetSharedMemoryAs<Result*>();
- *result = 0;
- uint32_t result_shm_id = kSharedMemoryId;
- uint32_t result_shm_offset = kSharedMemoryOffset;
- uint32_t data_shm_id = kSharedMemoryId;
- uint32_t data_shm_offset = kSharedMemoryOffset + sizeof(*result);
+ { // MapBufferRange
+ EXPECT_CALL(*gl_,
+ MapBufferRange(kTarget, kOffset, kSize, kAccess))
+ .WillOnce(Return(&data[0]))
+ .RetiresOnSaturation();
+
+ typedef MapBufferRange::Result Result;
+ Result* result = GetSharedMemoryAs<Result*>();
+
+ MapBufferRange cmd;
+ cmd.Init(kTarget, kOffset, kSize, kAccess, data_shm_id, data_shm_offset,
+ result_shm_id, result_shm_offset);
+ decoder_->set_unsafe_es3_apis_enabled(false);
+ *result = 0;
+ EXPECT_EQ(error::kUnknownCommand, ExecuteCmd(cmd));
+ EXPECT_EQ(0u, *result);
+ decoder_->set_unsafe_es3_apis_enabled(true);
+ *result = 0;
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ int8_t* mem = reinterpret_cast<int8_t*>(&result[1]);
+ EXPECT_EQ(0, memcmp(&data[0], mem, kSize));
+ EXPECT_EQ(1u, *result);
+ }
- MapBufferRange cmd;
- cmd.Init(kTarget, kOffset, kSize, kAccess, data_shm_id, data_shm_offset,
- result_shm_id, result_shm_offset);
- decoder_->set_unsafe_es3_apis_enabled(true);
- EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
- int8_t* mem = reinterpret_cast<int8_t*>(&result[1]);
- EXPECT_EQ(0, memcmp(&data[0], mem, kSize));
- EXPECT_EQ(1u, *result);
- decoder_->set_unsafe_es3_apis_enabled(false);
- *result = 0;
- EXPECT_EQ(error::kUnknownCommand, ExecuteCmd(cmd));
- EXPECT_EQ(0u, *result);
+ { // UnmapBuffer
+ EXPECT_CALL(*gl_, UnmapBuffer(kTarget))
+ .WillOnce(Return(GL_TRUE))
+ .RetiresOnSaturation();
+
+ UnmapBuffer cmd;
+ cmd.Init(kTarget);
+ decoder_->set_unsafe_es3_apis_enabled(false);
+ EXPECT_EQ(error::kUnknownCommand, ExecuteCmd(cmd));
+ decoder_->set_unsafe_es3_apis_enabled(true);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ }
+
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
}
-TEST_P(GLES2DecoderTest, MapBufferRangeWriteSucceeds) {
+TEST_P(GLES2DecoderTest, MapBufferRangeUnmapBufferWriteSucceeds) {
const GLenum kTarget = GL_ARRAY_BUFFER;
const GLintptr kOffset = 10;
const GLsizeiptr kSize = 64;
const GLbitfield kAccess = GL_MAP_WRITE_BIT;
const GLbitfield kMappedAccess = GL_MAP_WRITE_BIT | GL_MAP_READ_BIT;
+ uint32_t result_shm_id = kSharedMemoryId;
+ uint32_t result_shm_offset = kSharedMemoryOffset;
+ uint32_t data_shm_id = kSharedMemoryId;
+ // uint32_t is Result for both MapBufferRange and UnmapBuffer commands.
+ uint32_t data_shm_offset = kSharedMemoryOffset + sizeof(uint32_t);
+
DoBindBuffer(kTarget, client_buffer_id_, kServiceBufferId);
std::vector<int8_t> data(kSize);
for (GLsizeiptr ii = 0; ii < kSize; ++ii) {
data[ii] = static_cast<int8_t>(ii % 255);
}
- EXPECT_CALL(*gl_,
- MapBufferRange(kTarget, kOffset, kSize, kMappedAccess))
- .WillOnce(Return(&data[0]))
- .RetiresOnSaturation();
- typedef MapBufferRange::Result Result;
- Result* result = GetSharedMemoryAs<Result*>();
- *result = 0;
- uint32_t result_shm_id = kSharedMemoryId;
- uint32_t result_shm_offset = kSharedMemoryOffset;
- uint32_t data_shm_id = kSharedMemoryId;
- uint32_t data_shm_offset = kSharedMemoryOffset + sizeof(*result);
+ { // MapBufferRange succeeds
+ EXPECT_CALL(*gl_,
+ MapBufferRange(kTarget, kOffset, kSize, kMappedAccess))
+ .WillOnce(Return(&data[0]))
+ .RetiresOnSaturation();
+
+ typedef MapBufferRange::Result Result;
+ Result* result = GetSharedMemoryAs<Result*>();
+
+ MapBufferRange cmd;
+ cmd.Init(kTarget, kOffset, kSize, kAccess, data_shm_id, data_shm_offset,
+ result_shm_id, result_shm_offset);
+ decoder_->set_unsafe_es3_apis_enabled(false);
+ *result = 0;
+ EXPECT_EQ(error::kUnknownCommand, ExecuteCmd(cmd));
+ EXPECT_EQ(0u, *result);
+ decoder_->set_unsafe_es3_apis_enabled(true);
+ *result = 0;
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ int8_t* mem = reinterpret_cast<int8_t*>(&result[1]);
+ EXPECT_EQ(0, memcmp(&data[0], mem, kSize));
+ EXPECT_EQ(1u, *result);
+ }
- MapBufferRange cmd;
- cmd.Init(kTarget, kOffset, kSize, kAccess, data_shm_id, data_shm_offset,
- result_shm_id, result_shm_offset);
- decoder_->set_unsafe_es3_apis_enabled(true);
- EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
- int8_t* mem = reinterpret_cast<int8_t*>(&result[1]);
- EXPECT_EQ(0, memcmp(&data[0], mem, kSize));
- EXPECT_EQ(1u, *result);
- decoder_->set_unsafe_es3_apis_enabled(false);
- *result = 0;
- EXPECT_EQ(error::kUnknownCommand, ExecuteCmd(cmd));
- EXPECT_EQ(0u, *result);
+ { // UnmapBuffer succeeds
+ EXPECT_CALL(*gl_, UnmapBuffer(kTarget))
+ .WillOnce(Return(GL_TRUE))
+ .RetiresOnSaturation();
+
+ UnmapBuffer cmd;
+ cmd.Init(kTarget);
+ decoder_->set_unsafe_es3_apis_enabled(false);
+ EXPECT_EQ(error::kUnknownCommand, ExecuteCmd(cmd));
+ decoder_->set_unsafe_es3_apis_enabled(true);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ }
+
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
}
TEST_P(GLES2DecoderTest, MapBufferRangeNotInitFails) {
@@ -307,5 +347,125 @@ TEST_P(GLES2DecoderTest, MapBufferRangeBadSharedMemoryFails) {
EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
}
+TEST_P(GLES2DecoderTest, UnmapBufferWriteNotMappedFails) {
+ const GLenum kTarget = GL_ARRAY_BUFFER;
+
+ DoBindBuffer(kTarget, client_buffer_id_, kServiceBufferId);
+
+ UnmapBuffer cmd;
+ cmd.Init(kTarget);
+ decoder_->set_unsafe_es3_apis_enabled(true);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
+}
+
+TEST_P(GLES2DecoderTest, UnmapBufferWriteNoBoundBufferFails) {
+ const GLenum kTarget = GL_ARRAY_BUFFER;
+
+ UnmapBuffer cmd;
+ cmd.Init(kTarget);
+ decoder_->set_unsafe_es3_apis_enabled(true);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
+}
+
+TEST_P(GLES2DecoderTest, BufferDataDestroysDataStore) {
+ const GLenum kTarget = GL_ARRAY_BUFFER;
+ const GLintptr kOffset = 10;
+ const GLsizeiptr kSize = 64;
+ const GLbitfield kAccess = GL_MAP_WRITE_BIT;
+ const GLbitfield kFilteredAccess = GL_MAP_WRITE_BIT | GL_MAP_READ_BIT;
+
+ uint32_t result_shm_id = kSharedMemoryId;
+ uint32_t result_shm_offset = kSharedMemoryOffset;
+ uint32_t data_shm_id = kSharedMemoryId;
+ // uint32_t is Result for both MapBufferRange and UnmapBuffer commands.
+ uint32_t data_shm_offset = kSharedMemoryOffset + sizeof(uint32_t);
+
+ DoBindBuffer(kTarget, client_buffer_id_, kServiceBufferId);
+
+ std::vector<int8_t> data(kSize);
+
+ decoder_->set_unsafe_es3_apis_enabled(true);
+
+ { // MapBufferRange succeeds
+ EXPECT_CALL(*gl_,
+ MapBufferRange(kTarget, kOffset, kSize, kFilteredAccess))
+ .WillOnce(Return(&data[0]))
+ .RetiresOnSaturation();
+
+ typedef MapBufferRange::Result Result;
+ Result* result = GetSharedMemoryAs<Result*>();
+
+ MapBufferRange cmd;
+ cmd.Init(kTarget, kOffset, kSize, kAccess, data_shm_id, data_shm_offset,
+ result_shm_id, result_shm_offset);
+ *result = 0;
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(1u, *result);
+ }
+
+ { // BufferData unmaps the data store.
+ DoBufferData(kTarget, kSize * 2);
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+ }
+
+ { // UnmapBuffer fails.
+ UnmapBuffer cmd;
+ cmd.Init(kTarget);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
+ }
+}
+
+TEST_P(GLES2DecoderTest, DeleteBuffersDestroysDataStore) {
+ const GLenum kTarget = GL_ARRAY_BUFFER;
+ const GLintptr kOffset = 10;
+ const GLsizeiptr kSize = 64;
+ const GLbitfield kAccess = GL_MAP_WRITE_BIT;
+ const GLbitfield kFilteredAccess = GL_MAP_WRITE_BIT | GL_MAP_READ_BIT;
+
+ uint32_t result_shm_id = kSharedMemoryId;
+ uint32_t result_shm_offset = kSharedMemoryOffset;
+ uint32_t data_shm_id = kSharedMemoryId;
+ // uint32_t is Result for both MapBufferRange and UnmapBuffer commands.
+ uint32_t data_shm_offset = kSharedMemoryOffset + sizeof(uint32_t);
+
+ DoBindBuffer(kTarget, client_buffer_id_, kServiceBufferId);
+
+ std::vector<int8_t> data(kSize);
+
+ decoder_->set_unsafe_es3_apis_enabled(true);
+
+ { // MapBufferRange succeeds
+ EXPECT_CALL(*gl_,
+ MapBufferRange(kTarget, kOffset, kSize, kFilteredAccess))
+ .WillOnce(Return(&data[0]))
+ .RetiresOnSaturation();
+
+ typedef MapBufferRange::Result Result;
+ Result* result = GetSharedMemoryAs<Result*>();
+
+ MapBufferRange cmd;
+ cmd.Init(kTarget, kOffset, kSize, kAccess, data_shm_id, data_shm_offset,
+ result_shm_id, result_shm_offset);
+ *result = 0;
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(1u, *result);
+ }
+
+ { // DeleteBuffers unmaps the data store.
+ DoDeleteBuffer(client_buffer_id_, kServiceBufferId);
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+ }
+
+ { // UnmapBuffer fails.
+ UnmapBuffer cmd;
+ cmd.Init(kTarget);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
+ }
+}
+
} // namespace gles2
} // namespace gpu