diff options
Diffstat (limited to 'gpu')
30 files changed, 642 insertions, 33 deletions
diff --git a/gpu/GLES2/gl2chromium_autogen.h b/gpu/GLES2/gl2chromium_autogen.h index c53d1ce..fa099e6 100644 --- a/gpu/GLES2/gl2chromium_autogen.h +++ b/gpu/GLES2/gl2chromium_autogen.h @@ -225,6 +225,7 @@ #define glLoseContextCHROMIUM GLES2_GET_FUN(LoseContextCHROMIUM) #define glInsertSyncPointCHROMIUM GLES2_GET_FUN(InsertSyncPointCHROMIUM) #define glWaitSyncPointCHROMIUM GLES2_GET_FUN(WaitSyncPointCHROMIUM) +#define glDrawBuffersEXT GLES2_GET_FUN(DrawBuffersEXT) #endif // GPU_GLES2_GL2CHROMIUM_AUTOGEN_H_ diff --git a/gpu/GLES2/gl2extchromium.h b/gpu/GLES2/gl2extchromium.h index 6609fd4..b8dbc30 100644 --- a/gpu/GLES2/gl2extchromium.h +++ b/gpu/GLES2/gl2extchromium.h @@ -413,6 +413,125 @@ typedef void (GL_APIENTRYP PFNGLBLITFRAMEBUFFEREXTPROC) ( GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); #endif /* GL_EXT_framebuffer_blit */ +/* GL_EXT_draw_buffers */ +#ifndef GL_EXT_draw_buffers +#define GL_EXT_draw_buffers 1 + +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glDrawBuffersEXT( + GLsizei n, const GLenum* bufs); +#endif +typedef void (GL_APIENTRYP PFNGLDRAWBUFFERSEXTPROC) ( + GLsizei n, const GLenum* bufs); + +#ifndef GL_COLOR_ATTACHMENT0_EXT +#define GL_COLOR_ATTACHMENT0_EXT 0x8CE0 +#endif +#ifndef GL_COLOR_ATTACHMENT1_EXT +#define GL_COLOR_ATTACHMENT1_EXT 0x8CE1 +#endif +#ifndef GL_COLOR_ATTACHMENT2_EXT +#define GL_COLOR_ATTACHMENT2_EXT 0x8CE2 +#endif +#ifndef GL_COLOR_ATTACHMENT3_EXT +#define GL_COLOR_ATTACHMENT3_EXT 0x8CE3 +#endif +#ifndef GL_COLOR_ATTACHMENT4_EXT +#define GL_COLOR_ATTACHMENT4_EXT 0x8CE4 +#endif +#ifndef GL_COLOR_ATTACHMENT5_EXT +#define GL_COLOR_ATTACHMENT5_EXT 0x8CE5 +#endif +#ifndef GL_COLOR_ATTACHMENT6_EXT +#define GL_COLOR_ATTACHMENT6_EXT 0x8CE6 +#endif +#ifndef GL_COLOR_ATTACHMENT7_EXT +#define GL_COLOR_ATTACHMENT7_EXT 0x8CE7 +#endif +#ifndef GL_COLOR_ATTACHMENT8_EXT +#define GL_COLOR_ATTACHMENT8_EXT 0x8CE8 +#endif +#ifndef GL_COLOR_ATTACHMENT9_EXT +#define GL_COLOR_ATTACHMENT9_EXT 0x8CE9 +#endif +#ifndef GL_COLOR_ATTACHMENT10_EXT +#define GL_COLOR_ATTACHMENT10_EXT 0x8CEA +#endif +#ifndef GL_COLOR_ATTACHMENT11_EXT +#define GL_COLOR_ATTACHMENT11_EXT 0x8CEB +#endif +#ifndef GL_COLOR_ATTACHMENT12_EXT +#define GL_COLOR_ATTACHMENT12_EXT 0x8CEC +#endif +#ifndef GL_COLOR_ATTACHMENT13_EXT +#define GL_COLOR_ATTACHMENT13_EXT 0x8CED +#endif +#ifndef GL_COLOR_ATTACHMENT14_EXT +#define GL_COLOR_ATTACHMENT14_EXT 0x8CEE +#endif +#ifndef GL_COLOR_ATTACHMENT15_EXT +#define GL_COLOR_ATTACHMENT15_EXT 0x8CEF +#endif + +#ifndef GL_DRAW_BUFFER0_EXT +#define GL_DRAW_BUFFER0_EXT 0x8825 +#endif +#ifndef GL_DRAW_BUFFER1_EXT +#define GL_DRAW_BUFFER1_EXT 0x8826 +#endif +#ifndef GL_DRAW_BUFFER2_EXT +#define GL_DRAW_BUFFER2_EXT 0x8827 +#endif +#ifndef GL_DRAW_BUFFER3_EXT +#define GL_DRAW_BUFFER3_EXT 0x8828 +#endif +#ifndef GL_DRAW_BUFFER4_EXT +#define GL_DRAW_BUFFER4_EXT 0x8829 +#endif +#ifndef GL_DRAW_BUFFER5_EXT +#define GL_DRAW_BUFFER5_EXT 0x882A +#endif +#ifndef GL_DRAW_BUFFER6_EXT +#define GL_DRAW_BUFFER6_EXT 0x882B +#endif +#ifndef GL_DRAW_BUFFER7_EXT +#define GL_DRAW_BUFFER7_EXT 0x882C +#endif +#ifndef GL_DRAW_BUFFER8_EXT +#define GL_DRAW_BUFFER8_EXT 0x882D +#endif +#ifndef GL_DRAW_BUFFER9_EXT +#define GL_DRAW_BUFFER9_EXT 0x882E +#endif +#ifndef GL_DRAW_BUFFER10_EXT +#define GL_DRAW_BUFFER10_EXT 0x882F +#endif +#ifndef GL_DRAW_BUFFER11_EXT +#define GL_DRAW_BUFFER11_EXT 0x8830 +#endif +#ifndef GL_DRAW_BUFFER12_EXT +#define GL_DRAW_BUFFER12_EXT 0x8831 +#endif +#ifndef GL_DRAW_BUFFER13_EXT +#define GL_DRAW_BUFFER13_EXT 0x8832 +#endif +#ifndef GL_DRAW_BUFFER14_EXT +#define GL_DRAW_BUFFER14_EXT 0x8833 +#endif +#ifndef GL_DRAW_BUFFER15_EXT +#define GL_DRAW_BUFFER15_EXT 0x8834 +#endif + +#ifndef GL_MAX_COLOR_ATTACHMENTS_EXT +#define GL_MAX_COLOR_ATTACHMENTS_EXT 0x8CDF +#endif + +#ifndef GL_MAX_DRAW_BUFFERS_EXT +#define GL_MAX_DRAW_BUFFERS_EXT 0x8824 +#endif + +#endif /* GL_EXT_draw_buffers */ + /* GL_CHROMIUM_resize */ #ifndef GL_CHROMIUM_resize #define GL_CHROMIUM_resize 1 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_ |