summaryrefslogtreecommitdiffstats
path: root/gpu/command_buffer
diff options
context:
space:
mode:
Diffstat (limited to 'gpu/command_buffer')
-rwxr-xr-xgpu/command_buffer/build_gles2_cmd_buffer.py28
-rw-r--r--gpu/command_buffer/client/gles2_c_lib_autogen.h5
-rw-r--r--gpu/command_buffer/client/gles2_cmd_helper_autogen.h20
-rw-r--r--gpu/command_buffer/client/gles2_implementation_autogen.h2
-rw-r--r--gpu/command_buffer/client/gles2_implementation_impl_autogen.h16
-rw-r--r--gpu/command_buffer/client/gles2_implementation_unittest_autogen.h17
-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.h6
-rw-r--r--gpu/command_buffer/cmd_buffer_functions.txt1
-rw-r--r--gpu/command_buffer/common/gles2_cmd_format_autogen.h87
-rw-r--r--gpu/command_buffer/common/gles2_cmd_format_test_autogen.h41
-rw-r--r--gpu/command_buffer/common/gles2_cmd_ids_autogen.h2
-rw-r--r--gpu/command_buffer/common/gles2_cmd_utils.cc10
-rw-r--r--gpu/command_buffer/common/gles2_cmd_utils.h3
-rw-r--r--gpu/command_buffer/service/context_group.cc18
-rw-r--r--gpu/command_buffer/service/context_group.h20
-rw-r--r--gpu/command_buffer/service/feature_info.cc26
-rw-r--r--gpu/command_buffer/service/feature_info.h1
-rw-r--r--gpu/command_buffer/service/framebuffer_manager.cc49
-rw-r--r--gpu/command_buffer/service/framebuffer_manager.h14
-rw-r--r--gpu/command_buffer/service/framebuffer_manager_unittest.cc5
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder.cc77
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_autogen.h44
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc55
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_unittest_3_autogen.h2
28 files changed, 522 insertions, 33 deletions
diff --git a/gpu/command_buffer/build_gles2_cmd_buffer.py b/gpu/command_buffer/build_gles2_cmd_buffer.py
index 213e62db..9f472a1 100755
--- a/gpu/command_buffer/build_gles2_cmd_buffer.py
+++ b/gpu/command_buffer/build_gles2_cmd_buffer.py
@@ -2152,6 +2152,15 @@ _FUNCTION_INFO = {
'pepper_interface': 'InstancedArrays',
'defer_draws': True,
},
+ 'DrawBuffersEXT': {
+ 'type': 'PUTn',
+ 'decoder_func': 'DoDrawBuffersEXT',
+ 'data_type': 'GLenum',
+ 'count': 1,
+ 'client_test': False,
+ 'unit_test': False,
+ 'extension': True,
+ },
'DrawElementsInstancedANGLE': {
'type': 'Manual',
'cmd_args': 'GLenumDrawMode mode, GLsizei count, '
@@ -4927,11 +4936,11 @@ TEST_F(%(test_name)s, %(name)sInvalidArgs%(arg_index)d_%(value_index)d) {
TEST_F(GLES2ImplementationTest, %(name)s) {
struct Cmds {
cmds::%(name)sImmediate cmd;
- %(type)s data[2][%(count)d];
+ %(type)s data[%(count_param)d][%(count)d];
};
Cmds expected;
- for (int ii = 0; ii < 2; ++ii) {
+ for (int ii = 0; ii < %(count_param)d; ++ii) {
for (int jj = 0; jj < %(count)d; ++jj) {
expected.data[ii][jj] = static_cast<%(type)s>(ii * %(count)d + jj);
}
@@ -4945,14 +4954,18 @@ TEST_F(GLES2ImplementationTest, %(name)s) {
for count, arg in enumerate(func.GetCmdArgs()[0:-2]):
cmd_arg_strings.append(arg.GetValidClientSideCmdArg(func, count, 0))
gl_arg_strings = []
+ count_param = 0
for count, arg in enumerate(func.GetOriginalArgs()[0:-1]):
gl_arg_strings.append(arg.GetValidClientSideArg(func, count, 0))
+ if arg.name == "count":
+ count_param = int(arg.GetValidClientSideArg(func, count, 0))
file.Write(code % {
'name': func.name,
'type': func.GetInfo('data_type'),
'count': func.GetInfo('count'),
'args': ", ".join(gl_arg_strings),
'cmd_args': ", ".join(cmd_arg_strings),
+ 'count_param': count_param,
})
def WriteImmediateCmdComputeSize(self, func, file):
@@ -5028,26 +5041,29 @@ TEST_F(GLES2ImplementationTest, %(name)s) {
def WriteImmediateFormatTest(self, func, file):
"""Overrriden from TypeHandler."""
+ args = func.GetCmdArgs()
+ count_param = 0
+ for value, arg in enumerate(args):
+ if arg.name == "count":
+ count_param = int(arg.GetValidClientSideArg(func, value, 0))
file.Write("TEST_F(GLES2FormatTest, %s) {\n" % func.name)
file.Write(" const int kSomeBaseValueToTestWith = 51;\n")
file.Write(" static %s data[] = {\n" % func.info.data_type)
- for v in range(0, func.info.count * 2):
+ for v in range(0, func.info.count * count_param):
file.Write(" static_cast<%s>(kSomeBaseValueToTestWith + %d),\n" %
(func.info.data_type, v))
file.Write(" };\n")
file.Write(" cmds::%s& cmd = *GetBufferAs<cmds::%s>();\n" %
(func.name, func.name))
- file.Write(" const GLsizei kNumElements = 2;\n")
+ file.Write(" const GLsizei kNumElements = %d;\n" % count_param)
file.Write(" const size_t kExpectedCmdSize =\n")
file.Write(" sizeof(cmd) + kNumElements * sizeof(%s) * %d;\n" %
(func.info.data_type, func.info.count))
file.Write(" void* next_cmd = cmd.Set(\n")
file.Write(" &cmd")
- args = func.GetCmdArgs()
for value, arg in enumerate(args):
file.Write(",\n static_cast<%s>(%d)" % (arg.type, value + 1))
file.Write(",\n data);\n")
- args = func.GetCmdArgs()
file.Write(" EXPECT_EQ(static_cast<uint32>(cmds::%s::kCmdId),\n" %
func.name)
file.Write(" cmd.header.command);\n")
diff --git a/gpu/command_buffer/client/gles2_c_lib_autogen.h b/gpu/command_buffer/client/gles2_c_lib_autogen.h
index 08c3e90..70a7c55 100644
--- a/gpu/command_buffer/client/gles2_c_lib_autogen.h
+++ b/gpu/command_buffer/client/gles2_c_lib_autogen.h
@@ -728,6 +728,9 @@ GLuint GLES2InsertSyncPointCHROMIUM() {
void GLES2WaitSyncPointCHROMIUM(GLuint sync_point) {
gles2::GetGLContext()->WaitSyncPointCHROMIUM(sync_point);
}
+void GLES2DrawBuffersEXT(GLsizei count, const GLenum* bufs) {
+ gles2::GetGLContext()->DrawBuffersEXT(count, bufs);
+}
namespace gles2 {
@@ -1069,6 +1072,8 @@ NameToFunc g_gles2_function_table[] = {
glInsertSyncPointCHROMIUM), },
{ "glWaitSyncPointCHROMIUM", reinterpret_cast<GLES2FunctionPointer>(
glWaitSyncPointCHROMIUM), },
+ { "glDrawBuffersEXT", reinterpret_cast<GLES2FunctionPointer>(
+ glDrawBuffersEXT), },
{ NULL, NULL, },
};
diff --git a/gpu/command_buffer/client/gles2_cmd_helper_autogen.h b/gpu/command_buffer/client/gles2_cmd_helper_autogen.h
index ec8b078..d55fe34 100644
--- a/gpu/command_buffer/client/gles2_cmd_helper_autogen.h
+++ b/gpu/command_buffer/client/gles2_cmd_helper_autogen.h
@@ -2080,5 +2080,25 @@
}
}
+ void DrawBuffersEXT(
+ GLsizei count, uint32 bufs_shm_id, uint32 bufs_shm_offset) {
+ gles2::cmds::DrawBuffersEXT* c =
+ GetCmdSpace<gles2::cmds::DrawBuffersEXT>();
+ if (c) {
+ c->Init(count, bufs_shm_id, bufs_shm_offset);
+ }
+ }
+
+ void DrawBuffersEXTImmediate(GLsizei count, const GLenum* bufs) {
+ const uint32 size =
+ gles2::cmds::DrawBuffersEXTImmediate::ComputeSize(count);
+ gles2::cmds::DrawBuffersEXTImmediate* c =
+ GetImmediateCmdSpaceTotalSize<gles2::cmds::DrawBuffersEXTImmediate>(
+ size);
+ if (c) {
+ c->Init(count, bufs);
+ }
+ }
+
#endif // GPU_COMMAND_BUFFER_CLIENT_GLES2_CMD_HELPER_AUTOGEN_H_
diff --git a/gpu/command_buffer/client/gles2_implementation_autogen.h b/gpu/command_buffer/client/gles2_implementation_autogen.h
index 30e7834..8e49da5 100644
--- a/gpu/command_buffer/client/gles2_implementation_autogen.h
+++ b/gpu/command_buffer/client/gles2_implementation_autogen.h
@@ -530,5 +530,7 @@ virtual GLuint InsertSyncPointCHROMIUM() OVERRIDE;
virtual void WaitSyncPointCHROMIUM(GLuint sync_point) OVERRIDE;
+virtual void DrawBuffersEXT(GLsizei count, const GLenum* bufs) OVERRIDE;
+
#endif // GPU_COMMAND_BUFFER_CLIENT_GLES2_IMPLEMENTATION_AUTOGEN_H_
diff --git a/gpu/command_buffer/client/gles2_implementation_impl_autogen.h b/gpu/command_buffer/client/gles2_implementation_impl_autogen.h
index 7de6ca4..980a514 100644
--- a/gpu/command_buffer/client/gles2_implementation_impl_autogen.h
+++ b/gpu/command_buffer/client/gles2_implementation_impl_autogen.h
@@ -1703,5 +1703,21 @@ void GLES2Implementation::WaitSyncPointCHROMIUM(GLuint sync_point) {
CheckGLError();
}
+void GLES2Implementation::DrawBuffersEXT(GLsizei count, const GLenum* bufs) {
+ GPU_CLIENT_SINGLE_THREAD_CHECK();
+ GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDrawBuffersEXT(" << count << ", " << static_cast<const void*>(bufs) << ")"); // NOLINT
+ GPU_CLIENT_LOG_CODE_BLOCK({
+ for (GLsizei i = 0; i < count; ++i) {
+ GPU_CLIENT_LOG(" " << i << ": " << bufs[0 + i * 1]);
+ }
+ });
+ if (count < 0) {
+ SetGLError(GL_INVALID_VALUE, "glDrawBuffersEXT", "count < 0");
+ return;
+ }
+ helper_->DrawBuffersEXTImmediate(count, bufs);
+ CheckGLError();
+}
+
#endif // GPU_COMMAND_BUFFER_CLIENT_GLES2_IMPLEMENTATION_IMPL_AUTOGEN_H_
diff --git a/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h b/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h
index b573574..b28a051 100644
--- a/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h
+++ b/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h
@@ -1798,5 +1798,22 @@ TEST_F(GLES2ImplementationTest, WaitSyncPointCHROMIUM) {
gl_->WaitSyncPointCHROMIUM(1);
EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
}
+
+TEST_F(GLES2ImplementationTest, DrawBuffersEXT) {
+ struct Cmds {
+ cmds::DrawBuffersEXTImmediate cmd;
+ GLenum data[1][1];
+ };
+
+ Cmds expected;
+ for (int ii = 0; ii < 1; ++ii) {
+ for (int jj = 0; jj < 1; ++jj) {
+ expected.data[ii][jj] = static_cast<GLenum>(ii * 1 + jj);
+ }
+ }
+ expected.cmd.Init(1, &expected.data[0][0]);
+ gl_->DrawBuffersEXT(1, &expected.data[0][0]);
+ EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
+}
#endif // GPU_COMMAND_BUFFER_CLIENT_GLES2_IMPLEMENTATION_UNITTEST_AUTOGEN_H_
diff --git a/gpu/command_buffer/client/gles2_interface_autogen.h b/gpu/command_buffer/client/gles2_interface_autogen.h
index ba55dce..5451db6 100644
--- a/gpu/command_buffer/client/gles2_interface_autogen.h
+++ b/gpu/command_buffer/client/gles2_interface_autogen.h
@@ -306,5 +306,6 @@ virtual void DiscardFramebufferEXT(
virtual void LoseContextCHROMIUM(GLenum current, GLenum other) = 0;
virtual GLuint InsertSyncPointCHROMIUM() = 0;
virtual void WaitSyncPointCHROMIUM(GLuint sync_point) = 0;
+virtual void DrawBuffersEXT(GLsizei count, const GLenum* bufs) = 0;
#endif // GPU_COMMAND_BUFFER_CLIENT_GLES2_INTERFACE_AUTOGEN_H_
diff --git a/gpu/command_buffer/client/gles2_interface_stub_autogen.h b/gpu/command_buffer/client/gles2_interface_stub_autogen.h
index f374aef..1ca2b4f 100644
--- a/gpu/command_buffer/client/gles2_interface_stub_autogen.h
+++ b/gpu/command_buffer/client/gles2_interface_stub_autogen.h
@@ -337,5 +337,6 @@ virtual void DiscardFramebufferEXT(
virtual void LoseContextCHROMIUM(GLenum current, GLenum other) OVERRIDE;
virtual GLuint InsertSyncPointCHROMIUM() OVERRIDE;
virtual void WaitSyncPointCHROMIUM(GLuint sync_point) OVERRIDE;
+virtual void DrawBuffersEXT(GLsizei count, const GLenum* bufs) OVERRIDE;
#endif // GPU_COMMAND_BUFFER_CLIENT_GLES2_INTERFACE_STUB_AUTOGEN_H_
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 5a202e2..4a430a1 100644
--- a/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h
+++ b/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h
@@ -637,5 +637,8 @@ GLuint GLES2InterfaceStub::InsertSyncPointCHROMIUM() {
}
void GLES2InterfaceStub::WaitSyncPointCHROMIUM(GLuint /* sync_point */) {
}
+void GLES2InterfaceStub::DrawBuffersEXT(
+ GLsizei /* count */, const GLenum* /* bufs */) {
+}
#endif // GPU_COMMAND_BUFFER_CLIENT_GLES2_INTERFACE_STUB_IMPL_AUTOGEN_H_
diff --git a/gpu/command_buffer/client/gles2_trace_implementation_autogen.h b/gpu/command_buffer/client/gles2_trace_implementation_autogen.h
index f90a95d..3c7617e 100644
--- a/gpu/command_buffer/client/gles2_trace_implementation_autogen.h
+++ b/gpu/command_buffer/client/gles2_trace_implementation_autogen.h
@@ -337,5 +337,6 @@ virtual void DiscardFramebufferEXT(
virtual void LoseContextCHROMIUM(GLenum current, GLenum other) OVERRIDE;
virtual GLuint InsertSyncPointCHROMIUM() OVERRIDE;
virtual void WaitSyncPointCHROMIUM(GLuint sync_point) OVERRIDE;
+virtual void DrawBuffersEXT(GLsizei count, const GLenum* bufs) OVERRIDE;
#endif // GPU_COMMAND_BUFFER_CLIENT_GLES2_TRACE_IMPLEMENTATION_AUTOGEN_H_
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 deca187..99fe9a4 100644
--- a/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h
+++ b/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h
@@ -1180,5 +1180,11 @@ void GLES2TraceImplementation::WaitSyncPointCHROMIUM(GLuint sync_point) {
gl_->WaitSyncPointCHROMIUM(sync_point);
}
+void GLES2TraceImplementation::DrawBuffersEXT(
+ GLsizei count, const GLenum* bufs) {
+ TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::DrawBuffersEXT");
+ gl_->DrawBuffersEXT(count, bufs);
+}
+
#endif // GPU_COMMAND_BUFFER_CLIENT_GLES2_TRACE_IMPLEMENTATION_IMPL_AUTOGEN_H_
diff --git a/gpu/command_buffer/cmd_buffer_functions.txt b/gpu/command_buffer/cmd_buffer_functions.txt
index 8728294..1af5b925 100644
--- a/gpu/command_buffer/cmd_buffer_functions.txt
+++ b/gpu/command_buffer/cmd_buffer_functions.txt
@@ -210,5 +210,6 @@ GL_APICALL void GL_APIENTRY glDiscardFramebufferEXT (GLenum target, GLsi
GL_APICALL void GL_APIENTRY glLoseContextCHROMIUM (GLenum current, GLenum other);
GL_APICALL GLuint GL_APIENTRY glInsertSyncPointCHROMIUM (void);
GL_APICALL void GL_APIENTRY glWaitSyncPointCHROMIUM (GLuint sync_point);
+GL_APICALL void GL_APIENTRY glDrawBuffersEXT (GLsizei count, const GLenum* bufs);
diff --git a/gpu/command_buffer/common/gles2_cmd_format_autogen.h b/gpu/command_buffer/common/gles2_cmd_format_autogen.h
index 7597a51..3557348 100644
--- a/gpu/command_buffer/common/gles2_cmd_format_autogen.h
+++ b/gpu/command_buffer/common/gles2_cmd_format_autogen.h
@@ -10936,6 +10936,93 @@ COMPILE_ASSERT(offsetof(WaitSyncPointCHROMIUM, header) == 0,
COMPILE_ASSERT(offsetof(WaitSyncPointCHROMIUM, sync_point) == 4,
OffsetOf_WaitSyncPointCHROMIUM_sync_point_not_4);
+struct DrawBuffersEXT {
+ typedef DrawBuffersEXT ValueType;
+ static const CommandId kCmdId = kDrawBuffersEXT;
+ static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+ static uint32 ComputeSize() {
+ return static_cast<uint32>(sizeof(ValueType)); // NOLINT
+ }
+
+ void SetHeader() {
+ header.SetCmd<ValueType>();
+ }
+
+ void Init(GLsizei _count, uint32 _bufs_shm_id, uint32 _bufs_shm_offset) {
+ SetHeader();
+ count = _count;
+ bufs_shm_id = _bufs_shm_id;
+ bufs_shm_offset = _bufs_shm_offset;
+ }
+
+ void* Set(
+ void* cmd, GLsizei _count, uint32 _bufs_shm_id,
+ uint32 _bufs_shm_offset) {
+ static_cast<ValueType*>(cmd)->Init(_count, _bufs_shm_id, _bufs_shm_offset);
+ return NextCmdAddress<ValueType>(cmd);
+ }
+
+ gpu::CommandHeader header;
+ int32 count;
+ uint32 bufs_shm_id;
+ uint32 bufs_shm_offset;
+};
+
+COMPILE_ASSERT(sizeof(DrawBuffersEXT) == 16,
+ Sizeof_DrawBuffersEXT_is_not_16);
+COMPILE_ASSERT(offsetof(DrawBuffersEXT, header) == 0,
+ OffsetOf_DrawBuffersEXT_header_not_0);
+COMPILE_ASSERT(offsetof(DrawBuffersEXT, count) == 4,
+ OffsetOf_DrawBuffersEXT_count_not_4);
+COMPILE_ASSERT(offsetof(DrawBuffersEXT, bufs_shm_id) == 8,
+ OffsetOf_DrawBuffersEXT_bufs_shm_id_not_8);
+COMPILE_ASSERT(offsetof(DrawBuffersEXT, bufs_shm_offset) == 12,
+ OffsetOf_DrawBuffersEXT_bufs_shm_offset_not_12);
+
+struct DrawBuffersEXTImmediate {
+ typedef DrawBuffersEXTImmediate ValueType;
+ static const CommandId kCmdId = kDrawBuffersEXTImmediate;
+ static const cmd::ArgFlags kArgFlags = cmd::kAtLeastN;
+
+ static uint32 ComputeDataSize(GLsizei count) {
+ return static_cast<uint32>(
+ sizeof(GLenum) * 1 * count); // NOLINT
+ }
+
+ static uint32 ComputeSize(GLsizei count) {
+ return static_cast<uint32>(
+ sizeof(ValueType) + ComputeDataSize(count)); // NOLINT
+ }
+
+ void SetHeader(GLsizei count) {
+ header.SetCmdByTotalSize<ValueType>(ComputeSize(count));
+ }
+
+ void Init(GLsizei _count, const GLenum* _bufs) {
+ SetHeader(_count);
+ count = _count;
+ memcpy(ImmediateDataAddress(this),
+ _bufs, ComputeDataSize(_count));
+ }
+
+ void* Set(void* cmd, GLsizei _count, const GLenum* _bufs) {
+ static_cast<ValueType*>(cmd)->Init(_count, _bufs);
+ const uint32 size = ComputeSize(_count);
+ return NextImmediateCmdAddressTotalSize<ValueType>(cmd, size);
+ }
+
+ gpu::CommandHeader header;
+ int32 count;
+};
+
+COMPILE_ASSERT(sizeof(DrawBuffersEXTImmediate) == 8,
+ Sizeof_DrawBuffersEXTImmediate_is_not_8);
+COMPILE_ASSERT(offsetof(DrawBuffersEXTImmediate, header) == 0,
+ OffsetOf_DrawBuffersEXTImmediate_header_not_0);
+COMPILE_ASSERT(offsetof(DrawBuffersEXTImmediate, count) == 4,
+ OffsetOf_DrawBuffersEXTImmediate_count_not_4);
+
#endif // GPU_COMMAND_BUFFER_COMMON_GLES2_CMD_FORMAT_AUTOGEN_H_
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 970215d..59e9f49 100644
--- a/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h
+++ b/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h
@@ -4457,5 +4457,46 @@ TEST_F(GLES2FormatTest, WaitSyncPointCHROMIUM) {
next_cmd, sizeof(cmd));
}
+TEST_F(GLES2FormatTest, DrawBuffersEXT) {
+ cmds::DrawBuffersEXT& cmd = *GetBufferAs<cmds::DrawBuffersEXT>();
+ void* next_cmd = cmd.Set(
+ &cmd,
+ static_cast<GLsizei>(11),
+ static_cast<uint32>(12),
+ static_cast<uint32>(13));
+ EXPECT_EQ(static_cast<uint32>(cmds::DrawBuffersEXT::kCmdId),
+ cmd.header.command);
+ EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u);
+ EXPECT_EQ(static_cast<GLsizei>(11), cmd.count);
+ EXPECT_EQ(static_cast<uint32>(12), cmd.bufs_shm_id);
+ EXPECT_EQ(static_cast<uint32>(13), cmd.bufs_shm_offset);
+ CheckBytesWrittenMatchesExpectedSize(
+ next_cmd, sizeof(cmd));
+}
+
+TEST_F(GLES2FormatTest, DrawBuffersEXTImmediate) {
+ const int kSomeBaseValueToTestWith = 51;
+ static GLenum data[] = {
+ static_cast<GLenum>(kSomeBaseValueToTestWith + 0),
+ };
+ cmds::DrawBuffersEXTImmediate& cmd =
+ *GetBufferAs<cmds::DrawBuffersEXTImmediate>();
+ const GLsizei kNumElements = 1;
+ const size_t kExpectedCmdSize =
+ sizeof(cmd) + kNumElements * sizeof(GLenum) * 1;
+ void* next_cmd = cmd.Set(
+ &cmd,
+ static_cast<GLsizei>(1),
+ data);
+ EXPECT_EQ(static_cast<uint32>(cmds::DrawBuffersEXTImmediate::kCmdId),
+ cmd.header.command);
+ EXPECT_EQ(kExpectedCmdSize, cmd.header.size * 4u);
+ EXPECT_EQ(static_cast<GLsizei>(1), cmd.count);
+ CheckBytesWrittenMatchesExpectedSize(
+ next_cmd, sizeof(cmd) +
+ RoundSizeToMultipleOfEntries(sizeof(data)));
+ // TODO(gman): Check that data was inserted;
+}
+
#endif // GPU_COMMAND_BUFFER_COMMON_GLES2_CMD_FORMAT_TEST_AUTOGEN_H_
diff --git a/gpu/command_buffer/common/gles2_cmd_ids_autogen.h b/gpu/command_buffer/common/gles2_cmd_ids_autogen.h
index 4a5efae..e998be6 100644
--- a/gpu/command_buffer/common/gles2_cmd_ids_autogen.h
+++ b/gpu/command_buffer/common/gles2_cmd_ids_autogen.h
@@ -251,6 +251,8 @@
OP(LoseContextCHROMIUM) /* 494 */ \
OP(InsertSyncPointCHROMIUM) /* 495 */ \
OP(WaitSyncPointCHROMIUM) /* 496 */ \
+ OP(DrawBuffersEXT) /* 497 */ \
+ OP(DrawBuffersEXTImmediate) /* 498 */ \
enum CommandId {
kStartPoint = cmd::kLastCommonId, // All GLES2 commands start after this.
diff --git a/gpu/command_buffer/common/gles2_cmd_utils.cc b/gpu/command_buffer/common/gles2_cmd_utils.cc
index f2513a9..7bbed41 100644
--- a/gpu/command_buffer/common/gles2_cmd_utils.cc
+++ b/gpu/command_buffer/common/gles2_cmd_utils.cc
@@ -622,15 +622,19 @@ uint32 GLES2Util::GetChannelsForFormat(int format) {
}
}
-uint32 GLES2Util::GetChannelsNeededForAttachmentType(int type) {
+uint32 GLES2Util::GetChannelsNeededForAttachmentType(
+ int type, uint32 max_color_attachments) {
switch (type) {
- case GL_COLOR_ATTACHMENT0:
- return kRGBA;
case GL_DEPTH_ATTACHMENT:
return kDepth;
case GL_STENCIL_ATTACHMENT:
return kStencil;
default:
+ if (type >= GL_COLOR_ATTACHMENT0 &&
+ type < static_cast<int>(
+ GL_COLOR_ATTACHMENT0 + max_color_attachments)) {
+ return kRGBA;
+ }
return 0x0000;
}
}
diff --git a/gpu/command_buffer/common/gles2_cmd_utils.h b/gpu/command_buffer/common/gles2_cmd_utils.h
index 014dfa7..525a560 100644
--- a/gpu/command_buffer/common/gles2_cmd_utils.h
+++ b/gpu/command_buffer/common/gles2_cmd_utils.h
@@ -137,7 +137,8 @@ class GLES2_UTILS_EXPORT GLES2Util {
static uint32 GetChannelsForFormat(int format);
// Returns a bitmask for the channels the given attachment type needs.
- static uint32 GetChannelsNeededForAttachmentType(int type);
+ static uint32 GetChannelsNeededForAttachmentType(
+ int type, uint32 max_color_attachments);
static bool IsNPOT(uint32 value) {
return value > 0 && (value & (value - 1)) != 0;
diff --git a/gpu/command_buffer/service/context_group.cc b/gpu/command_buffer/service/context_group.cc
index 9f893e4..d1821d7 100644
--- a/gpu/command_buffer/service/context_group.cc
+++ b/gpu/command_buffer/service/context_group.cc
@@ -46,8 +46,11 @@ ContextGroup::ContextGroup(
max_fragment_uniform_vectors_(0u),
max_varying_vectors_(0u),
max_vertex_uniform_vectors_(0u),
+ max_color_attachments_(1u),
+ max_draw_buffers_(1u),
program_cache_(NULL),
- feature_info_(new FeatureInfo()) {
+ feature_info_(new FeatureInfo()),
+ draw_buffer_(GL_BACK) {
{
TransferBufferManager* manager = new TransferBufferManager();
transfer_buffer_manager_.reset(manager);
@@ -100,9 +103,20 @@ bool ContextGroup::Initialize(
glGetIntegerv(GL_MAX_SAMPLES, &max_samples);
}
+ if (feature_info_->feature_flags().ext_draw_buffers) {
+ GetIntegerv(GL_MAX_COLOR_ATTACHMENTS_EXT, &max_color_attachments_);
+ if (max_color_attachments_ < 1)
+ max_color_attachments_ = 1;
+ GetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, &max_draw_buffers_);
+ if (max_draw_buffers_ < 1)
+ max_draw_buffers_ = 1;
+ draw_buffer_ = GL_BACK;
+ }
+
buffer_manager_.reset(new BufferManager(
memory_tracker_, feature_info_.get()));
- framebuffer_manager_.reset(new FramebufferManager());
+ framebuffer_manager_.reset(
+ new FramebufferManager(max_draw_buffers_, max_color_attachments_));
renderbuffer_manager_.reset(new RenderbufferManager(memory_tracker_,
max_renderbuffer_size,
max_samples));
diff --git a/gpu/command_buffer/service/context_group.h b/gpu/command_buffer/service/context_group.h
index 8819179..c77ce1f 100644
--- a/gpu/command_buffer/service/context_group.h
+++ b/gpu/command_buffer/service/context_group.h
@@ -103,6 +103,14 @@ class GPU_EXPORT ContextGroup : public base::RefCounted<ContextGroup> {
return max_vertex_uniform_vectors_;
}
+ uint32 max_color_attachments() const {
+ return max_color_attachments_;
+ }
+
+ uint32 max_draw_buffers() const {
+ return max_draw_buffers_;
+ }
+
FeatureInfo* feature_info() {
return feature_info_.get();
}
@@ -150,6 +158,14 @@ class GPU_EXPORT ContextGroup : public base::RefCounted<ContextGroup> {
// Loses all the context associated with this group.
void LoseContexts(GLenum reset_status);
+ // EXT_draw_buffer related states for backbuffer.
+ GLenum draw_buffer() const {
+ return draw_buffer_;
+ }
+ void set_draw_buffer(GLenum buf) {
+ draw_buffer_ = buf;
+ }
+
private:
friend class base::RefCounted<ContextGroup>;
~ContextGroup();
@@ -175,6 +191,8 @@ class GPU_EXPORT ContextGroup : public base::RefCounted<ContextGroup> {
uint32 max_fragment_uniform_vectors_;
uint32 max_varying_vectors_;
uint32 max_vertex_uniform_vectors_;
+ uint32 max_color_attachments_;
+ uint32 max_draw_buffers_;
ProgramCache* program_cache_;
@@ -197,6 +215,8 @@ class GPU_EXPORT ContextGroup : public base::RefCounted<ContextGroup> {
std::vector<base::WeakPtr<gles2::GLES2Decoder> > decoders_;
+ GLenum draw_buffer_;
+
DISALLOW_COPY_AND_ASSIGN(ContextGroup);
};
diff --git a/gpu/command_buffer/service/feature_info.cc b/gpu/command_buffer/service/feature_info.cc
index 9a17a57..cd49d08 100644
--- a/gpu/command_buffer/service/feature_info.cc
+++ b/gpu/command_buffer/service/feature_info.cc
@@ -82,7 +82,8 @@ FeatureInfo::FeatureFlags::FeatureFlags()
native_vertex_array_object(false),
disable_workarounds(false),
enable_shader_name_hashing(false),
- enable_samplers(false) {
+ enable_samplers(false),
+ ext_draw_buffers(false) {
}
FeatureInfo::Workarounds::Workarounds()
@@ -614,6 +615,29 @@ void FeatureInfo::AddFeatures() {
validators_.vertex_attribute.AddValue(GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE);
}
+ if (extensions.Contains("GL_ARB_draw_buffers")) {
+ AddExtensionString("GL_EXT_draw_buffers");
+ feature_flags_.ext_draw_buffers = true;
+
+ GLint max_color_attachments = 0;
+ glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS_EXT, &max_color_attachments);
+ for (GLenum i = GL_COLOR_ATTACHMENT1_EXT;
+ i < static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + max_color_attachments);
+ ++i) {
+ validators_.attachment.AddValue(i);
+ }
+
+ validators_.g_l_state.AddValue(GL_MAX_COLOR_ATTACHMENTS_EXT);
+ validators_.g_l_state.AddValue(GL_MAX_DRAW_BUFFERS_ARB);
+ GLint max_draw_buffers = 0;
+ glGetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, &max_draw_buffers);
+ for (GLenum i = GL_DRAW_BUFFER0_ARB;
+ i < static_cast<GLenum>(GL_DRAW_BUFFER0_ARB + max_draw_buffers);
+ ++i) {
+ validators_.g_l_state.AddValue(i);
+ }
+ }
+
if (!disallowed_features_.swap_buffer_complete_callback)
AddExtensionString("GL_CHROMIUM_swapbuffers_complete_callback");
diff --git a/gpu/command_buffer/service/feature_info.h b/gpu/command_buffer/service/feature_info.h
index 9188d98..4efff80 100644
--- a/gpu/command_buffer/service/feature_info.h
+++ b/gpu/command_buffer/service/feature_info.h
@@ -40,6 +40,7 @@ class GPU_EXPORT FeatureInfo : public base::RefCounted<FeatureInfo> {
bool disable_workarounds;
bool enable_shader_name_hashing;
bool enable_samplers;
+ bool ext_draw_buffers;
};
struct Workarounds {
diff --git a/gpu/command_buffer/service/framebuffer_manager.cc b/gpu/command_buffer/service/framebuffer_manager.cc
index d9206bc..e6396ed 100644
--- a/gpu/command_buffer/service/framebuffer_manager.cc
+++ b/gpu/command_buffer/service/framebuffer_manager.cc
@@ -75,9 +75,10 @@ class RenderbufferAttachment
// Nothing to do for renderbuffers.
}
- virtual bool ValidForAttachmentType(GLenum attachment_type) OVERRIDE {
+ virtual bool ValidForAttachmentType(
+ GLenum attachment_type, uint32 max_color_attachments) OVERRIDE {
uint32 need = GLES2Util::GetChannelsNeededForAttachmentType(
- attachment_type);
+ attachment_type, max_color_attachments);
uint32 have = GLES2Util::GetChannelsForFormat(internal_format());
return (need & have) != 0;
}
@@ -169,14 +170,15 @@ class TextureAttachment
texture_->DetachFromFramebuffer();
}
- virtual bool ValidForAttachmentType(GLenum attachment_type) OVERRIDE {
+ virtual bool ValidForAttachmentType(
+ GLenum attachment_type, uint32 max_color_attachments) OVERRIDE {
GLenum type = 0;
GLenum internal_format = 0;
if (!texture_->GetLevelType(target_, level_, &type, &internal_format)) {
return false;
}
uint32 need = GLES2Util::GetChannelsNeededForAttachmentType(
- attachment_type);
+ attachment_type, max_color_attachments);
uint32 have = GLES2Util::GetChannelsForFormat(internal_format);
return (need & have) != 0;
}
@@ -198,10 +200,15 @@ class TextureAttachment
DISALLOW_COPY_AND_ASSIGN(TextureAttachment);
};
-FramebufferManager::FramebufferManager()
+FramebufferManager::FramebufferManager(
+ uint32 max_draw_buffers, uint32 max_color_attachments)
: framebuffer_state_change_count_(1),
framebuffer_count_(0),
- have_context_(true) {
+ have_context_(true),
+ max_draw_buffers_(max_draw_buffers),
+ max_color_attachments_(max_color_attachments) {
+ DCHECK_GT(max_draw_buffers_, 0u);
+ DCHECK_GT(max_color_attachments_, 0u);
}
FramebufferManager::~FramebufferManager() {
@@ -254,6 +261,11 @@ Framebuffer::Framebuffer(
has_been_bound_(false),
framebuffer_complete_state_count_id_(0) {
manager->StartTracking(this);
+ DCHECK_GT(manager->max_draw_buffers_, 0u);
+ draw_buffers_.reset(new GLenum[manager->max_draw_buffers_]);
+ draw_buffers_[0] = GL_COLOR_ATTACHMENT0;
+ for (uint32 i = 1; i < manager->max_draw_buffers_; ++i)
+ draw_buffers_[i] = GL_NONE;
}
Framebuffer::~Framebuffer() {
@@ -337,7 +349,8 @@ GLenum Framebuffer::IsPossiblyComplete() const {
it != attachments_.end(); ++it) {
GLenum attachment_type = it->first;
Attachment* attachment = it->second;
- if (!attachment->ValidForAttachmentType(attachment_type)) {
+ if (!attachment->ValidForAttachmentType(
+ attachment_type, manager_->max_color_attachments_)) {
return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
}
if (width < 0) {
@@ -402,6 +415,20 @@ bool Framebuffer::IsCleared() const {
return true;
}
+GLenum Framebuffer::GetDrawBuffer(GLenum draw_buffer) const {
+ GLsizei index = static_cast<GLsizei>(
+ draw_buffer - GL_DRAW_BUFFER0_ARB);
+ CHECK(index >= 0 &&
+ index < static_cast<GLsizei>(manager_->max_draw_buffers_));
+ return draw_buffers_[index];
+}
+
+void Framebuffer::SetDrawBuffers(GLsizei n, const GLenum* bufs) {
+ DCHECK(n <= static_cast<GLsizei>(manager_->max_draw_buffers_));
+ for (GLsizei i = 0; i < n; ++i)
+ draw_buffers_[i] = bufs[i];
+}
+
void Framebuffer::UnbindRenderbuffer(
GLenum target, Renderbuffer* renderbuffer) {
bool done;
@@ -456,10 +483,6 @@ void FramebufferManager::RemoveFramebuffer(GLuint client_id) {
void Framebuffer::AttachRenderbuffer(
GLenum attachment, Renderbuffer* renderbuffer) {
- DCHECK(attachment == GL_COLOR_ATTACHMENT0 ||
- attachment == GL_DEPTH_ATTACHMENT ||
- attachment == GL_STENCIL_ATTACHMENT ||
- attachment == GL_DEPTH_STENCIL_ATTACHMENT);
const Attachment* a = GetAttachment(attachment);
if (a)
a->DetachFromFramebuffer();
@@ -475,10 +498,6 @@ void Framebuffer::AttachRenderbuffer(
void Framebuffer::AttachTexture(
GLenum attachment, Texture* texture, GLenum target,
GLint level) {
- DCHECK(attachment == GL_COLOR_ATTACHMENT0 ||
- attachment == GL_DEPTH_ATTACHMENT ||
- attachment == GL_STENCIL_ATTACHMENT ||
- attachment == GL_DEPTH_STENCIL_ATTACHMENT);
const Attachment* a = GetAttachment(attachment);
if (a)
a->DetachFromFramebuffer();
diff --git a/gpu/command_buffer/service/framebuffer_manager.h b/gpu/command_buffer/service/framebuffer_manager.h
index fb32f34..788d169 100644
--- a/gpu/command_buffer/service/framebuffer_manager.h
+++ b/gpu/command_buffer/service/framebuffer_manager.h
@@ -40,7 +40,8 @@ class GPU_EXPORT Framebuffer : public base::RefCounted<Framebuffer> {
Renderbuffer* renderbuffer) const = 0;
virtual bool CanRenderTo() const = 0;
virtual void DetachFromFramebuffer() const = 0;
- virtual bool ValidForAttachmentType(GLenum attachment_type) = 0;
+ virtual bool ValidForAttachmentType(
+ GLenum attachment_type, uint32 max_color_attachments) = 0;
virtual void AddToSignature(
TextureManager* texture_manager, std::string* signature) const = 0;
@@ -114,6 +115,10 @@ class GPU_EXPORT Framebuffer : public base::RefCounted<Framebuffer> {
// Check all attachments are cleared
bool IsCleared() const;
+ GLenum GetDrawBuffer(GLenum draw_buffer) const;
+
+ void SetDrawBuffers(GLsizei n, const GLenum* bufs);
+
static void ClearFramebufferCompleteComboMap();
private:
@@ -160,6 +165,8 @@ class GPU_EXPORT Framebuffer : public base::RefCounted<Framebuffer> {
typedef base::hash_map<std::string, bool> FramebufferComboCompleteMap;
static FramebufferComboCompleteMap* framebuffer_combo_complete_map_;
+ scoped_array<GLenum> draw_buffers_;
+
DISALLOW_COPY_AND_ASSIGN(Framebuffer);
};
@@ -167,7 +174,7 @@ class GPU_EXPORT Framebuffer : public base::RefCounted<Framebuffer> {
// so we can correctly clear them.
class GPU_EXPORT FramebufferManager {
public:
- FramebufferManager();
+ FramebufferManager(uint32 max_draw_buffers, uint32 max_color_attachments);
~FramebufferManager();
// Must call before destruction.
@@ -221,6 +228,9 @@ class GPU_EXPORT FramebufferManager {
bool have_context_;
+ uint32 max_draw_buffers_;
+ uint32 max_color_attachments_;
+
DISALLOW_COPY_AND_ASSIGN(FramebufferManager);
};
diff --git a/gpu/command_buffer/service/framebuffer_manager_unittest.cc b/gpu/command_buffer/service/framebuffer_manager_unittest.cc
index b2f2924..e1aedb2 100644
--- a/gpu/command_buffer/service/framebuffer_manager_unittest.cc
+++ b/gpu/command_buffer/service/framebuffer_manager_unittest.cc
@@ -24,7 +24,8 @@ class FramebufferManagerTest : public testing::Test {
public:
FramebufferManagerTest()
- : texture_manager_(
+ : manager_(1, 1),
+ texture_manager_(
NULL, new FeatureInfo(), kMaxTextureSize, kMaxCubemapSize),
renderbuffer_manager_(NULL, kMaxRenderbufferSize, kMaxSamples) {
@@ -115,7 +116,7 @@ class FramebufferInfoTest : public testing::Test {
static const GLint kMaxSamples = 4;
FramebufferInfoTest()
- : manager_(),
+ : manager_(1, 1),
texture_manager_(
NULL, new FeatureInfo(), kMaxTextureSize, kMaxCubemapSize),
renderbuffer_manager_(NULL, kMaxRenderbufferSize, kMaxSamples) {
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
index 1d642fd..c9fd9ff 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -925,6 +925,8 @@ class GLES2DecoderImpl : public GLES2Decoder {
void DoTraceEndCHROMIUM(void);
+ void DoDrawBuffersEXT(GLsizei count, const GLenum* bufs);
+
// Creates a Program for the given program.
Program* CreateProgram(
GLuint client_id, GLuint service_id) {
@@ -2597,7 +2599,7 @@ bool GLES2DecoderImpl::InitializeShaderTranslator() {
resources.MaxTextureImageUnits = group_->max_texture_image_units();
resources.MaxFragmentUniformVectors =
group_->max_fragment_uniform_vectors();
- resources.MaxDrawBuffers = 1;
+ resources.MaxDrawBuffers = group_->max_draw_buffers();
#if (ANGLE_SH_VERSION >= 110)
GLint range[2];
@@ -2618,6 +2620,8 @@ bool GLES2DecoderImpl::InitializeShaderTranslator() {
features().arb_texture_rectangle ? 1 : 0;
resources.OES_EGL_image_external =
features().oes_egl_image_external ? 1 : 0;
+ resources.EXT_draw_buffers =
+ features().ext_draw_buffers ? 1 : 0;
}
ShShaderSpec shader_spec = force_webgl_glsl_validation_ ||
@@ -4117,6 +4121,18 @@ bool GLES2DecoderImpl::GetHelper(
params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_CUBE_MAP);
}
return true;
+ case GL_MAX_COLOR_ATTACHMENTS_EXT:
+ *num_written = 1;
+ if (params) {
+ params[0] = group_->max_color_attachments();
+ }
+ return true;
+ case GL_MAX_DRAW_BUFFERS_ARB:
+ *num_written = 1;
+ if (params) {
+ params[0] = group_->max_draw_buffers();
+ }
+ return true;
case GL_ALPHA_BITS:
*num_written = 1;
if (params) {
@@ -4349,6 +4365,23 @@ bool GLES2DecoderImpl::GetHelper(
}
return true;
default:
+ if (pname >= GL_DRAW_BUFFER0_ARB &&
+ pname < GL_DRAW_BUFFER0_ARB + group_->max_draw_buffers()) {
+ *num_written = 1;
+ if (params) {
+ Framebuffer* framebuffer =
+ GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
+ if (framebuffer) {
+ params[0] = framebuffer->GetDrawBuffer(pname);
+ } else { // backbuffer
+ if (pname == GL_DRAW_BUFFER0_ARB)
+ params[0] = group_->draw_buffer();
+ else
+ params[0] = GL_NONE;
+ }
+ }
+ return true;
+ }
*num_written = util_.GLGetNumValuesReturned(pname);
return false;
}
@@ -10104,6 +10137,48 @@ void GLES2DecoderImpl::DoTraceEndCHROMIUM() {
gpu_tracer_->End();
}
+void GLES2DecoderImpl::DoDrawBuffersEXT(
+ GLsizei count, const GLenum* bufs) {
+ if (count > static_cast<GLsizei>(group_->max_draw_buffers())) {
+ LOCAL_SET_GL_ERROR(
+ GL_INVALID_VALUE,
+ "glDrawBuffersEXT", "greater than GL_MAX_DRAW_BUFFERS_EXT");
+ return;
+ }
+
+ Framebuffer* framebuffer = GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
+ if (framebuffer) {
+ for (GLsizei i = 0; i < count; ++i) {
+ if (bufs[i] != static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + i) &&
+ bufs[i] != GL_NONE) {
+ LOCAL_SET_GL_ERROR(
+ GL_INVALID_OPERATION,
+ "glDrawBuffersEXT",
+ "bufs[i] not GL_NONE or GL_COLOR_ATTACHMENTi_EXT");
+ return;
+ }
+ }
+ glDrawBuffersARB(count, bufs);
+ framebuffer->SetDrawBuffers(count, bufs);
+ } else { // backbuffer
+ if (count > 1 ||
+ (bufs[0] != GL_BACK && bufs[0] != GL_NONE)) {
+ LOCAL_SET_GL_ERROR(
+ GL_INVALID_OPERATION,
+ "glDrawBuffersEXT",
+ "more than one buffer or bufs not GL_NONE or GL_BACK");
+ return;
+ }
+ GLenum mapped_buf = bufs[0];
+ if (GetBackbufferServiceId() != 0 && // emulated backbuffer
+ bufs[0] == GL_BACK) {
+ mapped_buf = GL_COLOR_ATTACHMENT0;
+ }
+ glDrawBuffersARB(count, &mapped_buf);
+ group_->set_draw_buffer(bufs[0]);
+ }
+}
+
bool GLES2DecoderImpl::ValidateAsyncTransfer(
const char* function_name,
Texture* texture,
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h
index 630525d8..6ea12d8 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h
@@ -3210,6 +3210,50 @@ error::Error GLES2DecoderImpl::HandleDiscardFramebufferEXTImmediate(
return error::kNoError;
}
+error::Error GLES2DecoderImpl::HandleDrawBuffersEXT(
+ uint32 immediate_data_size, const gles2::cmds::DrawBuffersEXT& c) {
+ GLsizei count = static_cast<GLsizei>(c.count);
+ uint32 data_size;
+ if (!ComputeDataSize(count, sizeof(GLenum), 1, &data_size)) {
+ return error::kOutOfBounds;
+ }
+ const GLenum* bufs = GetSharedMemoryAs<const GLenum*>(
+ c.bufs_shm_id, c.bufs_shm_offset, data_size);
+ if (count < 0) {
+ LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glDrawBuffersEXT", "count < 0");
+ return error::kNoError;
+ }
+ if (bufs == NULL) {
+ return error::kOutOfBounds;
+ }
+ DoDrawBuffersEXT(count, bufs);
+ return error::kNoError;
+}
+
+error::Error GLES2DecoderImpl::HandleDrawBuffersEXTImmediate(
+ uint32 immediate_data_size,
+ const gles2::cmds::DrawBuffersEXTImmediate& c) {
+ GLsizei count = static_cast<GLsizei>(c.count);
+ uint32 data_size;
+ if (!ComputeDataSize(count, sizeof(GLenum), 1, &data_size)) {
+ return error::kOutOfBounds;
+ }
+ if (data_size > immediate_data_size) {
+ return error::kOutOfBounds;
+ }
+ const GLenum* bufs = GetImmediateDataAs<const GLenum*>(
+ c, data_size, immediate_data_size);
+ if (count < 0) {
+ LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glDrawBuffersEXT", "count < 0");
+ return error::kNoError;
+ }
+ if (bufs == NULL) {
+ return error::kOutOfBounds;
+ }
+ DoDrawBuffersEXT(count, bufs);
+ return error::kNoError;
+}
+
bool GLES2DecoderImpl::SetCapabilityState(GLenum cap, bool enabled) {
switch (cap) {
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc
index a385f81..0745c91 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc
@@ -8395,6 +8395,61 @@ TEST_F(GLES2DecoderManualInitTest, MemoryTrackerBufferData) {
EXPECT_EQ(128u, memory_tracker->GetPoolSize(MemoryTracker::kManaged));
}
+TEST_F(GLES2DecoderTest, DrawBuffersEXTImmediateSuccceeds) {
+ const GLsizei count = 1;
+ const GLenum bufs[] = { GL_COLOR_ATTACHMENT0 };
+ DrawBuffersEXTImmediate& cmd =
+ *GetImmediateAs<DrawBuffersEXTImmediate>();
+ cmd.Init(count, bufs);
+
+ DoBindFramebuffer(GL_FRAMEBUFFER, client_framebuffer_id_,
+ kServiceFramebufferId);
+ EXPECT_CALL(*gl_, DrawBuffersARB(count, _))
+ .Times(1)
+ .RetiresOnSaturation();
+ EXPECT_EQ(error::kNoError,
+ ExecuteImmediateCmd(cmd, sizeof(bufs)));
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+}
+
+TEST_F(GLES2DecoderTest, DrawBuffersEXTImmediateFails) {
+ const GLsizei count = 1;
+ const GLenum bufs[] = { GL_COLOR_ATTACHMENT1_EXT };
+ DrawBuffersEXTImmediate& cmd =
+ *GetImmediateAs<DrawBuffersEXTImmediate>();
+ cmd.Init(count, bufs);
+
+ DoBindFramebuffer(GL_FRAMEBUFFER, client_framebuffer_id_,
+ kServiceFramebufferId);
+ EXPECT_EQ(error::kNoError,
+ ExecuteImmediateCmd(cmd, sizeof(bufs)));
+ EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
+}
+
+TEST_F(GLES2DecoderTest, DrawBuffersEXTImmediateBackbuffer) {
+ const GLsizei count = 1;
+ const GLenum bufs[] = { GL_BACK };
+ DrawBuffersEXTImmediate& cmd =
+ *GetImmediateAs<DrawBuffersEXTImmediate>();
+ cmd.Init(count, bufs);
+
+ DoBindFramebuffer(GL_FRAMEBUFFER, client_framebuffer_id_,
+ kServiceFramebufferId);
+ EXPECT_EQ(error::kNoError,
+ ExecuteImmediateCmd(cmd, sizeof(bufs)));
+ EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
+
+ DoBindFramebuffer(GL_FRAMEBUFFER, 0, 0); // unbind
+
+ EXPECT_CALL(*gl_, DrawBuffersARB(count, _))
+ .Times(1)
+ .RetiresOnSaturation();
+
+ EXPECT_EQ(error::kNoError,
+ ExecuteImmediateCmd(cmd, sizeof(bufs)));
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+}
+
// TODO(gman): Complete this test.
// TEST_F(GLES2DecoderTest, CompressedTexImage2DGLError) {
// }
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 470dbcf..ff078ef 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
@@ -74,5 +74,7 @@
// TODO(gman): WaitSyncPointCHROMIUM
+// TODO(gman): DrawBuffersEXT
+// TODO(gman): DrawBuffersEXTImmediate
#endif // GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_UNITTEST_3_AUTOGEN_H_