diff options
40 files changed, 1663 insertions, 45 deletions
diff --git a/content/common/gpu/gpu_channel.cc b/content/common/gpu/gpu_channel.cc index 9785ce7..a93c5b6 100644 --- a/content/common/gpu/gpu_channel.cc +++ b/content/common/gpu/gpu_channel.cc @@ -18,6 +18,7 @@ #include "content/common/gpu/gpu_messages.h" #include "content/public/common/content_client.h" #include "content/public/common/content_switches.h" +#include "gpu/command_buffer/service/mailbox_manager.h" #include "ui/gfx/gl/gl_context.h" #include "ui/gfx/gl/gl_surface.h" @@ -41,6 +42,7 @@ GpuChannel::GpuChannel(GpuChannelManager* gpu_channel_manager, : gpu_channel_manager_(gpu_channel_manager), client_id_(client_id), share_group_(share_group ? share_group : new gfx::GLShareGroup), + mailbox_manager_(new gpu::gles2::MailboxManager), watchdog_(watchdog), software_(software), handle_messages_scheduled_(false), @@ -192,6 +194,7 @@ void GpuChannel::CreateViewCommandBuffer( this, share_group, window, + mailbox_manager_, gfx::Size(), disallowed_features_, init_params.allowed_extensions, @@ -349,6 +352,7 @@ void GpuChannel::OnCreateOffscreenCommandBuffer( this, share_group, gfx::GLSurfaceHandle(), + mailbox_manager_.get(), size, disallowed_features_, init_params.allowed_extensions, diff --git a/content/common/gpu/gpu_channel.h b/content/common/gpu/gpu_channel.h index 42e4d8b..67d856e 100644 --- a/content/common/gpu/gpu_channel.h +++ b/content/common/gpu/gpu_channel.h @@ -156,6 +156,8 @@ class GpuChannel : public IPC::Channel::Listener, // process use. scoped_refptr<gfx::GLShareGroup> share_group_; + scoped_refptr<gpu::gles2::MailboxManager> mailbox_manager_; + #if defined(ENABLE_GPU) typedef IDMap<GpuCommandBufferStub, IDMapOwnPointer> StubMap; StubMap stubs_; diff --git a/content/common/gpu/gpu_command_buffer_stub.cc b/content/common/gpu/gpu_command_buffer_stub.cc index b6f6d28..aa5b331 100644 --- a/content/common/gpu/gpu_command_buffer_stub.cc +++ b/content/common/gpu/gpu_command_buffer_stub.cc @@ -39,6 +39,7 @@ GpuCommandBufferStub::GpuCommandBufferStub( GpuChannel* channel, GpuCommandBufferStub* share_group, const gfx::GLSurfaceHandle& handle, + gpu::gles2::MailboxManager* mailbox_manager, const gfx::Size& size, const gpu::gles2::DisallowedFeatures& disallowed_features, const std::string& allowed_extensions, @@ -65,7 +66,7 @@ GpuCommandBufferStub::GpuCommandBufferStub( if (share_group) { context_group_ = share_group->context_group_; } else { - context_group_ = new gpu::gles2::ContextGroup(true); + context_group_ = new gpu::gles2::ContextGroup(mailbox_manager, true); } if (surface_id != 0) surface_state_.reset(new GpuCommandBufferStubBase::SurfaceState( diff --git a/content/common/gpu/gpu_command_buffer_stub.h b/content/common/gpu/gpu_command_buffer_stub.h index 4f08818..5a99c56 100644 --- a/content/common/gpu/gpu_command_buffer_stub.h +++ b/content/common/gpu/gpu_command_buffer_stub.h @@ -39,6 +39,12 @@ class GpuChannel; struct GpuMemoryAllocation; class GpuWatchdog; +namespace gpu { +namespace gles2 { +class MailboxManager; +} +} + // This Base class is used to expose methods of GpuCommandBufferStub used for // testability. class CONTENT_EXPORT GpuCommandBufferStubBase { @@ -88,6 +94,7 @@ class GpuCommandBufferStub GpuChannel* channel, GpuCommandBufferStub* share_group, const gfx::GLSurfaceHandle& handle, + gpu::gles2::MailboxManager* mailbox_manager, const gfx::Size& size, const gpu::gles2::DisallowedFeatures& disallowed_features, const std::string& allowed_extensions, @@ -7,5 +7,6 @@ include_rules = [ "+../common", "+../GLES2", "+../service", + "+crypto", "+ui/gfx", ] diff --git a/gpu/command_buffer/build_gles2_cmd_buffer.py b/gpu/command_buffer/build_gles2_cmd_buffer.py index 39d2025..a279798 100755 --- a/gpu/command_buffer/build_gles2_cmd_buffer.py +++ b/gpu/command_buffer/build_gles2_cmd_buffer.py @@ -862,6 +862,15 @@ _FUNCTION_INFO = { 'gl_test_func': 'glClearDepth', }, 'ColorMask': {'decoder_func': 'DoColorMask', 'expectation': False}, + 'ConsumeTextureCHROMIUM': { + 'decoder_func': 'DoConsumeTextureCHROMIUM', + 'type': 'PUT', + 'data_type': 'GLbyte', + 'count': 64, + 'unit_test': False, + 'extension': True, + 'chromium': True, + }, 'ClearStencil': {'decoder_func': 'DoClearStencil'}, 'EnableFeatureCHROMIUM': { 'type': 'Custom', @@ -988,6 +997,15 @@ _FUNCTION_INFO = { 'resource_type': 'Buffer', 'resource_types': 'Buffers', }, + 'GenMailboxCHROMIUM': { + 'type': 'Manual', + 'cmd_args': 'GLuint bucket_id', + 'result': ['SizedResult<GLint>'], + 'client_test': False, + 'unit_test': False, + 'extension': True, + 'chromium': True, + }, 'GenFramebuffers': { 'type': 'GENn', 'gl_test_func': 'glGenFramebuffersEXT', @@ -1278,6 +1296,15 @@ _FUNCTION_INFO = { 'extension': True, 'chromium': True, }, + 'ProduceTextureCHROMIUM': { + 'decoder_func': 'DoProduceTextureCHROMIUM', + 'type': 'PUT', + 'data_type': 'GLbyte', + 'count': 64, + 'unit_test': False, + 'extension': True, + 'chromium': True, + }, 'RenderbufferStorage': { 'decoder_func': 'DoRenderbufferStorage', 'gl_test_func': 'glRenderbufferStorageEXT', diff --git a/gpu/command_buffer/client/gles2_c_lib_autogen.h b/gpu/command_buffer/client/gles2_c_lib_autogen.h index 263c868..fa75173 100644 --- a/gpu/command_buffer/client/gles2_c_lib_autogen.h +++ b/gpu/command_buffer/client/gles2_c_lib_autogen.h @@ -641,6 +641,15 @@ void GLES2DrawElementsInstancedANGLE( void GLES2VertexAttribDivisorANGLE(GLuint index, GLuint divisor) { gles2::GetGLContext()->VertexAttribDivisorANGLE(index, divisor); } +void GLES2GenMailboxCHROMIUM(GLbyte* mailbox) { + gles2::GetGLContext()->GenMailboxCHROMIUM(mailbox); +} +void GLES2ProduceTextureCHROMIUM(GLenum target, const GLbyte* mailbox) { + gles2::GetGLContext()->ProduceTextureCHROMIUM(target, mailbox); +} +void GLES2ConsumeTextureCHROMIUM(GLenum target, const GLbyte* mailbox) { + gles2::GetGLContext()->ConsumeTextureCHROMIUM(target, mailbox); +} #endif // GPU_COMMAND_BUFFER_CLIENT_GLES2_C_LIB_AUTOGEN_H_ diff --git a/gpu/command_buffer/client/gles2_cmd_helper_autogen.h b/gpu/command_buffer/client/gles2_cmd_helper_autogen.h index b520491..82b3b15 100644 --- a/gpu/command_buffer/client/gles2_cmd_helper_autogen.h +++ b/gpu/command_buffer/client/gles2_cmd_helper_autogen.h @@ -1752,5 +1752,50 @@ } } + void GenMailboxCHROMIUM(GLuint bucket_id) { + gles2::GenMailboxCHROMIUM* c = GetCmdSpace<gles2::GenMailboxCHROMIUM>(); + if (c) { + c->Init(bucket_id); + } + } + + void ProduceTextureCHROMIUM( + GLenum target, uint32 mailbox_shm_id, uint32 mailbox_shm_offset) { + gles2::ProduceTextureCHROMIUM* c = + GetCmdSpace<gles2::ProduceTextureCHROMIUM>(); + if (c) { + c->Init(target, mailbox_shm_id, mailbox_shm_offset); + } + } + + void ProduceTextureCHROMIUMImmediate(GLenum target, const GLbyte* mailbox) { + const uint32 size = gles2::ProduceTextureCHROMIUMImmediate::ComputeSize(); + gles2::ProduceTextureCHROMIUMImmediate* c = + GetImmediateCmdSpaceTotalSize<gles2::ProduceTextureCHROMIUMImmediate>( + size); + if (c) { + c->Init(target, mailbox); + } + } + + void ConsumeTextureCHROMIUM( + GLenum target, uint32 mailbox_shm_id, uint32 mailbox_shm_offset) { + gles2::ConsumeTextureCHROMIUM* c = + GetCmdSpace<gles2::ConsumeTextureCHROMIUM>(); + if (c) { + c->Init(target, mailbox_shm_id, mailbox_shm_offset); + } + } + + void ConsumeTextureCHROMIUMImmediate(GLenum target, const GLbyte* mailbox) { + const uint32 size = gles2::ConsumeTextureCHROMIUMImmediate::ComputeSize(); + gles2::ConsumeTextureCHROMIUMImmediate* c = + GetImmediateCmdSpaceTotalSize<gles2::ConsumeTextureCHROMIUMImmediate>( + size); + if (c) { + c->Init(target, mailbox); + } + } + #endif // GPU_COMMAND_BUFFER_CLIENT_GLES2_CMD_HELPER_AUTOGEN_H_ diff --git a/gpu/command_buffer/client/gles2_implementation.cc b/gpu/command_buffer/client/gles2_implementation.cc index d136753..1375fe8 100644 --- a/gpu/command_buffer/client/gles2_implementation.cc +++ b/gpu/command_buffer/client/gles2_implementation.cc @@ -3138,5 +3138,20 @@ void GLES2Implementation::DrawElementsInstancedANGLE( #endif } +void GLES2Implementation::GenMailboxCHROMIUM( + GLbyte* mailbox) { + GPU_CLIENT_SINGLE_THREAD_CHECK(); + GPU_CLIENT_LOG("[" << this << "] glGenMailboxCHROMIUM(" + << static_cast<const void*>(mailbox) << ")"); + TRACE_EVENT0("gpu", "GLES2::GenMailboxCHROMIUM"); + + helper_->GenMailboxCHROMIUM(kResultBucketId); + + std::vector<GLbyte> result; + GetBucketContents(kResultBucketId, &result); + + std::copy(result.begin(), result.end(), mailbox); +} + } // namespace gles2 } // namespace gpu diff --git a/gpu/command_buffer/client/gles2_implementation_autogen.h b/gpu/command_buffer/client/gles2_implementation_autogen.h index 9193535..d9ba14ca 100644 --- a/gpu/command_buffer/client/gles2_implementation_autogen.h +++ b/gpu/command_buffer/client/gles2_implementation_autogen.h @@ -1562,5 +1562,21 @@ void DrawElementsInstancedANGLE( void VertexAttribDivisorANGLE(GLuint index, GLuint divisor); +void GenMailboxCHROMIUM(GLbyte* mailbox); + +void ProduceTextureCHROMIUM(GLenum target, const GLbyte* mailbox) { + GPU_CLIENT_SINGLE_THREAD_CHECK(); + GPU_CLIENT_LOG("[" << this << "] glProduceTextureCHROMIUM(" << GLES2Util::GetStringTextureTarget(target) << ", " << static_cast<const void*>(mailbox) << ")"); // NOLINT + GPU_CLIENT_LOG("values: " << mailbox[0] << ", " << mailbox[1] << ", " << mailbox[2] << ", " << mailbox[3] << ", " << mailbox[4] << ", " << mailbox[5] << ", " << mailbox[6] << ", " << mailbox[7] << ", " << mailbox[8] << ", " << mailbox[9] << ", " << mailbox[10] << ", " << mailbox[11] << ", " << mailbox[12] << ", " << mailbox[13] << ", " << mailbox[14] << ", " << mailbox[15] << ", " << mailbox[16] << ", " << mailbox[17] << ", " << mailbox[18] << ", " << mailbox[19] << ", " << mailbox[20] << ", " << mailbox[21] << ", " << mailbox[22] << ", " << mailbox[23] << ", " << mailbox[24] << ", " << mailbox[25] << ", " << mailbox[26] << ", " << mailbox[27] << ", " << mailbox[28] << ", " << mailbox[29] << ", " << mailbox[30] << ", " << mailbox[31] << ", " << mailbox[32] << ", " << mailbox[33] << ", " << mailbox[34] << ", " << mailbox[35] << ", " << mailbox[36] << ", " << mailbox[37] << ", " << mailbox[38] << ", " << mailbox[39] << ", " << mailbox[40] << ", " << mailbox[41] << ", " << mailbox[42] << ", " << mailbox[43] << ", " << mailbox[44] << ", " << mailbox[45] << ", " << mailbox[46] << ", " << mailbox[47] << ", " << mailbox[48] << ", " << mailbox[49] << ", " << mailbox[50] << ", " << mailbox[51] << ", " << mailbox[52] << ", " << mailbox[53] << ", " << mailbox[54] << ", " << mailbox[55] << ", " << mailbox[56] << ", " << mailbox[57] << ", " << mailbox[58] << ", " << mailbox[59] << ", " << mailbox[60] << ", " << mailbox[61] << ", " << mailbox[62] << ", " << mailbox[63]); // NOLINT + helper_->ProduceTextureCHROMIUMImmediate(target, mailbox); +} + +void ConsumeTextureCHROMIUM(GLenum target, const GLbyte* mailbox) { + GPU_CLIENT_SINGLE_THREAD_CHECK(); + GPU_CLIENT_LOG("[" << this << "] glConsumeTextureCHROMIUM(" << GLES2Util::GetStringTextureTarget(target) << ", " << static_cast<const void*>(mailbox) << ")"); // NOLINT + GPU_CLIENT_LOG("values: " << mailbox[0] << ", " << mailbox[1] << ", " << mailbox[2] << ", " << mailbox[3] << ", " << mailbox[4] << ", " << mailbox[5] << ", " << mailbox[6] << ", " << mailbox[7] << ", " << mailbox[8] << ", " << mailbox[9] << ", " << mailbox[10] << ", " << mailbox[11] << ", " << mailbox[12] << ", " << mailbox[13] << ", " << mailbox[14] << ", " << mailbox[15] << ", " << mailbox[16] << ", " << mailbox[17] << ", " << mailbox[18] << ", " << mailbox[19] << ", " << mailbox[20] << ", " << mailbox[21] << ", " << mailbox[22] << ", " << mailbox[23] << ", " << mailbox[24] << ", " << mailbox[25] << ", " << mailbox[26] << ", " << mailbox[27] << ", " << mailbox[28] << ", " << mailbox[29] << ", " << mailbox[30] << ", " << mailbox[31] << ", " << mailbox[32] << ", " << mailbox[33] << ", " << mailbox[34] << ", " << mailbox[35] << ", " << mailbox[36] << ", " << mailbox[37] << ", " << mailbox[38] << ", " << mailbox[39] << ", " << mailbox[40] << ", " << mailbox[41] << ", " << mailbox[42] << ", " << mailbox[43] << ", " << mailbox[44] << ", " << mailbox[45] << ", " << mailbox[46] << ", " << mailbox[47] << ", " << mailbox[48] << ", " << mailbox[49] << ", " << mailbox[50] << ", " << mailbox[51] << ", " << mailbox[52] << ", " << mailbox[53] << ", " << mailbox[54] << ", " << mailbox[55] << ", " << mailbox[56] << ", " << mailbox[57] << ", " << mailbox[58] << ", " << mailbox[59] << ", " << mailbox[60] << ", " << mailbox[61] << ", " << mailbox[62] << ", " << mailbox[63]); // NOLINT + helper_->ConsumeTextureCHROMIUMImmediate(target, mailbox); +} + #endif // GPU_COMMAND_BUFFER_CLIENT_GLES2_IMPLEMENTATION_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 8128e9c..4545550 100644 --- a/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h +++ b/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h @@ -1666,5 +1666,35 @@ TEST_F(GLES2ImplementationTest, VertexAttribDivisorANGLE) { gl_->VertexAttribDivisorANGLE(1, 2); EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); } + +TEST_F(GLES2ImplementationTest, ProduceTextureCHROMIUM) { + struct Cmds { + ProduceTextureCHROMIUMImmediate cmd; + GLbyte data[64]; + }; + + Cmds expected; + for (int jj = 0; jj < 64; ++jj) { + expected.data[jj] = static_cast<GLbyte>(jj); + } + expected.cmd.Init(GL_TEXTURE_2D, &expected.data[0]); + gl_->ProduceTextureCHROMIUM(GL_TEXTURE_2D, &expected.data[0]); + EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); +} + +TEST_F(GLES2ImplementationTest, ConsumeTextureCHROMIUM) { + struct Cmds { + ConsumeTextureCHROMIUMImmediate cmd; + GLbyte data[64]; + }; + + Cmds expected; + for (int jj = 0; jj < 64; ++jj) { + expected.data[jj] = static_cast<GLbyte>(jj); + } + expected.cmd.Init(GL_TEXTURE_2D, &expected.data[0]); + gl_->ConsumeTextureCHROMIUM(GL_TEXTURE_2D, &expected.data[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/cmd_buffer_functions.txt b/gpu/command_buffer/cmd_buffer_functions.txt index 9676d02..b22d383 100644 --- a/gpu/command_buffer/cmd_buffer_functions.txt +++ b/gpu/command_buffer/cmd_buffer_functions.txt @@ -182,4 +182,6 @@ GL_APICALL void GL_APIENTRY glCopyTextureCHROMIUM (GLenum target, GLenum GL_APICALL void GL_APIENTRY glDrawArraysInstancedANGLE (GLenumDrawMode mode, GLint first, GLsizei count, GLsizei primcount); GL_APICALL void GL_APIENTRY glDrawElementsInstancedANGLE (GLenumDrawMode mode, GLsizei count, GLenumIndexType type, const void* indices, GLsizei primcount); GL_APICALL void GL_APIENTRY glVertexAttribDivisorANGLE (GLuint index, GLuint divisor); - +GL_APICALL void GL_APIENTRY glGenMailboxCHROMIUM (GLbyte* mailbox); +GL_APICALL void GL_APIENTRY glProduceTextureCHROMIUM (GLenumTextureTarget target, const GLbyte* mailbox); +GL_APICALL void GL_APIENTRY glConsumeTextureCHROMIUM (GLenumTextureTarget target, const GLbyte* mailbox); diff --git a/gpu/command_buffer/common/gles2_cmd_format_autogen.h b/gpu/command_buffer/common/gles2_cmd_format_autogen.h index 3e93516..0f01f5c 100644 --- a/gpu/command_buffer/common/gles2_cmd_format_autogen.h +++ b/gpu/command_buffer/common/gles2_cmd_format_autogen.h @@ -9713,6 +9713,220 @@ COMPILE_ASSERT(offsetof(VertexAttribDivisorANGLE, index) == 4, COMPILE_ASSERT(offsetof(VertexAttribDivisorANGLE, divisor) == 8, OffsetOf_VertexAttribDivisorANGLE_divisor_not_8); +struct GenMailboxCHROMIUM { + typedef GenMailboxCHROMIUM ValueType; + static const CommandId kCmdId = kGenMailboxCHROMIUM; + static const cmd::ArgFlags kArgFlags = cmd::kFixed; + + typedef SizedResult<GLint> Result; + + static uint32 ComputeSize() { + return static_cast<uint32>(sizeof(ValueType)); // NOLINT + } + + void SetHeader() { + header.SetCmd<ValueType>(); + } + + void Init(GLuint _bucket_id) { + SetHeader(); + bucket_id = _bucket_id; + } + + void* Set(void* cmd, GLuint _bucket_id) { + static_cast<ValueType*>(cmd)->Init(_bucket_id); + return NextCmdAddress<ValueType>(cmd); + } + + gpu::CommandHeader header; + uint32 bucket_id; +}; + +COMPILE_ASSERT(sizeof(GenMailboxCHROMIUM) == 8, + Sizeof_GenMailboxCHROMIUM_is_not_8); +COMPILE_ASSERT(offsetof(GenMailboxCHROMIUM, header) == 0, + OffsetOf_GenMailboxCHROMIUM_header_not_0); +COMPILE_ASSERT(offsetof(GenMailboxCHROMIUM, bucket_id) == 4, + OffsetOf_GenMailboxCHROMIUM_bucket_id_not_4); + +struct ProduceTextureCHROMIUM { + typedef ProduceTextureCHROMIUM ValueType; + static const CommandId kCmdId = kProduceTextureCHROMIUM; + static const cmd::ArgFlags kArgFlags = cmd::kFixed; + + static uint32 ComputeSize() { + return static_cast<uint32>(sizeof(ValueType)); // NOLINT + } + + void SetHeader() { + header.SetCmd<ValueType>(); + } + + void Init( + GLenum _target, uint32 _mailbox_shm_id, uint32 _mailbox_shm_offset) { + SetHeader(); + target = _target; + mailbox_shm_id = _mailbox_shm_id; + mailbox_shm_offset = _mailbox_shm_offset; + } + + void* Set( + void* cmd, GLenum _target, uint32 _mailbox_shm_id, + uint32 _mailbox_shm_offset) { + static_cast<ValueType*>( + cmd)->Init(_target, _mailbox_shm_id, _mailbox_shm_offset); + return NextCmdAddress<ValueType>(cmd); + } + + gpu::CommandHeader header; + uint32 target; + uint32 mailbox_shm_id; + uint32 mailbox_shm_offset; +}; + +COMPILE_ASSERT(sizeof(ProduceTextureCHROMIUM) == 16, + Sizeof_ProduceTextureCHROMIUM_is_not_16); +COMPILE_ASSERT(offsetof(ProduceTextureCHROMIUM, header) == 0, + OffsetOf_ProduceTextureCHROMIUM_header_not_0); +COMPILE_ASSERT(offsetof(ProduceTextureCHROMIUM, target) == 4, + OffsetOf_ProduceTextureCHROMIUM_target_not_4); +COMPILE_ASSERT(offsetof(ProduceTextureCHROMIUM, mailbox_shm_id) == 8, + OffsetOf_ProduceTextureCHROMIUM_mailbox_shm_id_not_8); +COMPILE_ASSERT(offsetof(ProduceTextureCHROMIUM, mailbox_shm_offset) == 12, + OffsetOf_ProduceTextureCHROMIUM_mailbox_shm_offset_not_12); + +struct ProduceTextureCHROMIUMImmediate { + typedef ProduceTextureCHROMIUMImmediate ValueType; + static const CommandId kCmdId = kProduceTextureCHROMIUMImmediate; + static const cmd::ArgFlags kArgFlags = cmd::kAtLeastN; + + static uint32 ComputeDataSize() { + return static_cast<uint32>( + sizeof(GLbyte) * 64); // NOLINT + } + + static uint32 ComputeSize() { + return static_cast<uint32>( + sizeof(ValueType) + ComputeDataSize()); // NOLINT + } + + void SetHeader() { + header.SetCmdByTotalSize<ValueType>(ComputeSize()); + } + + void Init(GLenum _target, const GLbyte* _mailbox) { + SetHeader(); + target = _target; + memcpy(ImmediateDataAddress(this), + _mailbox, ComputeDataSize()); + } + + void* Set(void* cmd, GLenum _target, const GLbyte* _mailbox) { + static_cast<ValueType*>(cmd)->Init(_target, _mailbox); + const uint32 size = ComputeSize(); + return NextImmediateCmdAddressTotalSize<ValueType>(cmd, size); + } + + gpu::CommandHeader header; + uint32 target; +}; + +COMPILE_ASSERT(sizeof(ProduceTextureCHROMIUMImmediate) == 8, + Sizeof_ProduceTextureCHROMIUMImmediate_is_not_8); +COMPILE_ASSERT(offsetof(ProduceTextureCHROMIUMImmediate, header) == 0, + OffsetOf_ProduceTextureCHROMIUMImmediate_header_not_0); +COMPILE_ASSERT(offsetof(ProduceTextureCHROMIUMImmediate, target) == 4, + OffsetOf_ProduceTextureCHROMIUMImmediate_target_not_4); + +struct ConsumeTextureCHROMIUM { + typedef ConsumeTextureCHROMIUM ValueType; + static const CommandId kCmdId = kConsumeTextureCHROMIUM; + static const cmd::ArgFlags kArgFlags = cmd::kFixed; + + static uint32 ComputeSize() { + return static_cast<uint32>(sizeof(ValueType)); // NOLINT + } + + void SetHeader() { + header.SetCmd<ValueType>(); + } + + void Init( + GLenum _target, uint32 _mailbox_shm_id, uint32 _mailbox_shm_offset) { + SetHeader(); + target = _target; + mailbox_shm_id = _mailbox_shm_id; + mailbox_shm_offset = _mailbox_shm_offset; + } + + void* Set( + void* cmd, GLenum _target, uint32 _mailbox_shm_id, + uint32 _mailbox_shm_offset) { + static_cast<ValueType*>( + cmd)->Init(_target, _mailbox_shm_id, _mailbox_shm_offset); + return NextCmdAddress<ValueType>(cmd); + } + + gpu::CommandHeader header; + uint32 target; + uint32 mailbox_shm_id; + uint32 mailbox_shm_offset; +}; + +COMPILE_ASSERT(sizeof(ConsumeTextureCHROMIUM) == 16, + Sizeof_ConsumeTextureCHROMIUM_is_not_16); +COMPILE_ASSERT(offsetof(ConsumeTextureCHROMIUM, header) == 0, + OffsetOf_ConsumeTextureCHROMIUM_header_not_0); +COMPILE_ASSERT(offsetof(ConsumeTextureCHROMIUM, target) == 4, + OffsetOf_ConsumeTextureCHROMIUM_target_not_4); +COMPILE_ASSERT(offsetof(ConsumeTextureCHROMIUM, mailbox_shm_id) == 8, + OffsetOf_ConsumeTextureCHROMIUM_mailbox_shm_id_not_8); +COMPILE_ASSERT(offsetof(ConsumeTextureCHROMIUM, mailbox_shm_offset) == 12, + OffsetOf_ConsumeTextureCHROMIUM_mailbox_shm_offset_not_12); + +struct ConsumeTextureCHROMIUMImmediate { + typedef ConsumeTextureCHROMIUMImmediate ValueType; + static const CommandId kCmdId = kConsumeTextureCHROMIUMImmediate; + static const cmd::ArgFlags kArgFlags = cmd::kAtLeastN; + + static uint32 ComputeDataSize() { + return static_cast<uint32>( + sizeof(GLbyte) * 64); // NOLINT + } + + static uint32 ComputeSize() { + return static_cast<uint32>( + sizeof(ValueType) + ComputeDataSize()); // NOLINT + } + + void SetHeader() { + header.SetCmdByTotalSize<ValueType>(ComputeSize()); + } + + void Init(GLenum _target, const GLbyte* _mailbox) { + SetHeader(); + target = _target; + memcpy(ImmediateDataAddress(this), + _mailbox, ComputeDataSize()); + } + + void* Set(void* cmd, GLenum _target, const GLbyte* _mailbox) { + static_cast<ValueType*>(cmd)->Init(_target, _mailbox); + const uint32 size = ComputeSize(); + return NextImmediateCmdAddressTotalSize<ValueType>(cmd, size); + } + + gpu::CommandHeader header; + uint32 target; +}; + +COMPILE_ASSERT(sizeof(ConsumeTextureCHROMIUMImmediate) == 8, + Sizeof_ConsumeTextureCHROMIUMImmediate_is_not_8); +COMPILE_ASSERT(offsetof(ConsumeTextureCHROMIUMImmediate, header) == 0, + OffsetOf_ConsumeTextureCHROMIUMImmediate_header_not_0); +COMPILE_ASSERT(offsetof(ConsumeTextureCHROMIUMImmediate, target) == 4, + OffsetOf_ConsumeTextureCHROMIUMImmediate_target_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 4a5d29d..f3c0661 100644 --- a/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h +++ b/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h @@ -3775,5 +3775,224 @@ TEST_F(GLES2FormatTest, VertexAttribDivisorANGLE) { next_cmd, sizeof(cmd)); } +TEST_F(GLES2FormatTest, GenMailboxCHROMIUM) { + GenMailboxCHROMIUM& cmd = *GetBufferAs<GenMailboxCHROMIUM>(); + void* next_cmd = cmd.Set( + &cmd, + static_cast<GLuint>(11)); + EXPECT_EQ(static_cast<uint32>(GenMailboxCHROMIUM::kCmdId), + cmd.header.command); + EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u); + EXPECT_EQ(static_cast<GLuint>(11), cmd.bucket_id); + CheckBytesWrittenMatchesExpectedSize( + next_cmd, sizeof(cmd)); +} + +TEST_F(GLES2FormatTest, ProduceTextureCHROMIUM) { + ProduceTextureCHROMIUM& cmd = *GetBufferAs<ProduceTextureCHROMIUM>(); + void* next_cmd = cmd.Set( + &cmd, + static_cast<GLenum>(11), + static_cast<uint32>(12), + static_cast<uint32>(13)); + EXPECT_EQ(static_cast<uint32>(ProduceTextureCHROMIUM::kCmdId), + cmd.header.command); + EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u); + EXPECT_EQ(static_cast<GLenum>(11), cmd.target); + EXPECT_EQ(static_cast<uint32>(12), cmd.mailbox_shm_id); + EXPECT_EQ(static_cast<uint32>(13), cmd.mailbox_shm_offset); + CheckBytesWrittenMatchesExpectedSize( + next_cmd, sizeof(cmd)); +} + +TEST_F(GLES2FormatTest, ProduceTextureCHROMIUMImmediate) { + const int kSomeBaseValueToTestWith = 51; + static GLbyte data[] = { + static_cast<GLbyte>(kSomeBaseValueToTestWith + 0), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 1), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 2), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 3), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 4), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 5), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 6), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 7), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 8), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 9), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 10), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 11), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 12), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 13), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 14), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 15), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 16), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 17), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 18), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 19), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 20), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 21), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 22), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 23), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 24), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 25), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 26), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 27), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 28), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 29), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 30), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 31), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 32), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 33), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 34), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 35), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 36), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 37), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 38), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 39), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 40), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 41), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 42), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 43), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 44), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 45), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 46), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 47), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 48), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 49), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 50), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 51), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 52), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 53), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 54), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 55), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 56), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 57), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 58), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 59), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 60), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 61), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 62), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 63), + }; + ProduceTextureCHROMIUMImmediate& cmd = + *GetBufferAs<ProduceTextureCHROMIUMImmediate>(); + void* next_cmd = cmd.Set( + &cmd, + static_cast<GLenum>(11), + data); + EXPECT_EQ(static_cast<uint32>(ProduceTextureCHROMIUMImmediate::kCmdId), + cmd.header.command); + EXPECT_EQ(sizeof(cmd) + + RoundSizeToMultipleOfEntries(sizeof(data)), + cmd.header.size * 4u); + EXPECT_EQ(static_cast<GLenum>(11), cmd.target); + CheckBytesWrittenMatchesExpectedSize( + next_cmd, sizeof(cmd) + + RoundSizeToMultipleOfEntries(sizeof(data))); + // TODO(gman): Check that data was inserted; +} + +TEST_F(GLES2FormatTest, ConsumeTextureCHROMIUM) { + ConsumeTextureCHROMIUM& cmd = *GetBufferAs<ConsumeTextureCHROMIUM>(); + void* next_cmd = cmd.Set( + &cmd, + static_cast<GLenum>(11), + static_cast<uint32>(12), + static_cast<uint32>(13)); + EXPECT_EQ(static_cast<uint32>(ConsumeTextureCHROMIUM::kCmdId), + cmd.header.command); + EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u); + EXPECT_EQ(static_cast<GLenum>(11), cmd.target); + EXPECT_EQ(static_cast<uint32>(12), cmd.mailbox_shm_id); + EXPECT_EQ(static_cast<uint32>(13), cmd.mailbox_shm_offset); + CheckBytesWrittenMatchesExpectedSize( + next_cmd, sizeof(cmd)); +} + +TEST_F(GLES2FormatTest, ConsumeTextureCHROMIUMImmediate) { + const int kSomeBaseValueToTestWith = 51; + static GLbyte data[] = { + static_cast<GLbyte>(kSomeBaseValueToTestWith + 0), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 1), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 2), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 3), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 4), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 5), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 6), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 7), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 8), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 9), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 10), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 11), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 12), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 13), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 14), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 15), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 16), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 17), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 18), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 19), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 20), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 21), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 22), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 23), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 24), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 25), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 26), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 27), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 28), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 29), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 30), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 31), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 32), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 33), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 34), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 35), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 36), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 37), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 38), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 39), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 40), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 41), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 42), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 43), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 44), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 45), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 46), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 47), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 48), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 49), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 50), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 51), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 52), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 53), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 54), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 55), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 56), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 57), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 58), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 59), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 60), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 61), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 62), + static_cast<GLbyte>(kSomeBaseValueToTestWith + 63), + }; + ConsumeTextureCHROMIUMImmediate& cmd = + *GetBufferAs<ConsumeTextureCHROMIUMImmediate>(); + void* next_cmd = cmd.Set( + &cmd, + static_cast<GLenum>(11), + data); + EXPECT_EQ(static_cast<uint32>(ConsumeTextureCHROMIUMImmediate::kCmdId), + cmd.header.command); + EXPECT_EQ(sizeof(cmd) + + RoundSizeToMultipleOfEntries(sizeof(data)), + cmd.header.size * 4u); + EXPECT_EQ(static_cast<GLenum>(11), cmd.target); + 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 ac95b0c..5102903 100644 --- a/gpu/command_buffer/common/gles2_cmd_ids_autogen.h +++ b/gpu/command_buffer/common/gles2_cmd_ids_autogen.h @@ -222,6 +222,11 @@ OP(DrawArraysInstancedANGLE) /* 465 */ \ OP(DrawElementsInstancedANGLE) /* 466 */ \ OP(VertexAttribDivisorANGLE) /* 467 */ \ + OP(GenMailboxCHROMIUM) /* 468 */ \ + OP(ProduceTextureCHROMIUM) /* 469 */ \ + OP(ProduceTextureCHROMIUMImmediate) /* 470 */ \ + OP(ConsumeTextureCHROMIUM) /* 471 */ \ + OP(ConsumeTextureCHROMIUMImmediate) /* 472 */ \ enum CommandId { kStartPoint = cmd::kLastCommonId, // All GLES2 commands start after this. diff --git a/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h b/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h index d99da6d..5fb03f7 100644 --- a/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h +++ b/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h @@ -224,7 +224,7 @@ static GLES2Util::EnumToString enum_to_string_table[] = { { 0x00000400, "GL_STENCIL_BUFFER_BIT", }, { 0x800A, "GL_FUNC_SUBTRACT", }, { 0x8E2C, "GL_DEPTH_COMPONENT16_NONLINEAR_NV", }, - { 0x889F, "GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING", }, + { 0x8508, "GL_DECR_WRAP", }, { 0x8006, "GL_FUNC_ADD", }, { 0x8007, "GL_MIN_EXT", }, { 0x8004, "GL_ONE_MINUS_CONSTANT_ALPHA", }, @@ -378,6 +378,7 @@ static GLES2Util::EnumToString enum_to_string_table[] = { { 0x0502, "GL_INVALID_OPERATION", }, { 0x0501, "GL_INVALID_VALUE", }, { 0x0500, "GL_INVALID_ENUM", }, + { 64, "GL_MAILBOX_SIZE_CHROMIUM", }, { 0x0506, "GL_INVALID_FRAMEBUFFER_OPERATION", }, { 0x0505, "GL_OUT_OF_MEMORY", }, { 0x8B5F, "GL_SAMPLER_3D_OES", }, @@ -499,7 +500,7 @@ static GLES2Util::EnumToString enum_to_string_table[] = { { 0x8CD6, "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT", }, { 0x8253, "GL_GUILTY_CONTEXT_RESET_EXT", }, { 0x8872, "GL_MAX_TEXTURE_IMAGE_UNITS", }, - { 0x8508, "GL_DECR_WRAP", }, + { 0x889F, "GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING", }, { 0x8507, "GL_INCR_WRAP", }, { 0x8895, "GL_ELEMENT_ARRAY_BUFFER_BINDING", }, { 0x8894, "GL_ARRAY_BUFFER_BINDING", }, diff --git a/gpu/command_buffer/service/context_group.cc b/gpu/command_buffer/service/context_group.cc index dd99d84..8916801 100644 --- a/gpu/command_buffer/service/context_group.cc +++ b/gpu/command_buffer/service/context_group.cc @@ -13,6 +13,7 @@ #include "gpu/command_buffer/service/framebuffer_manager.h" #include "gpu/command_buffer/service/gles2_cmd_decoder.h" #include "gpu/command_buffer/service/gpu_switches.h" +#include "gpu/command_buffer/service/mailbox_manager.h" #include "gpu/command_buffer/service/program_manager.h" #include "gpu/command_buffer/service/renderbuffer_manager.h" #include "gpu/command_buffer/service/shader_manager.h" @@ -22,8 +23,10 @@ namespace gpu { namespace gles2 { -ContextGroup::ContextGroup(bool bind_generates_resource) - : num_contexts_(0), +ContextGroup::ContextGroup(MailboxManager* mailbox_manager, + bool bind_generates_resource) + : mailbox_manager_(mailbox_manager ? mailbox_manager : new MailboxManager), + num_contexts_(0), enforce_gl_minimums_(CommandLine::ForCurrentProcess()->HasSwitch( switches::kEnforceGLMinimums)), bind_generates_resource_(bind_generates_resource), @@ -249,6 +252,8 @@ void ContextGroup::Destroy(bool have_context) { } if (texture_manager_ != NULL) { + mailbox_manager_->DestroyOwnedTextures(texture_manager_.get(), + have_context); texture_manager_->Destroy(have_context); texture_manager_.reset(); } diff --git a/gpu/command_buffer/service/context_group.h b/gpu/command_buffer/service/context_group.h index 5284c1c..8c5477e 100644 --- a/gpu/command_buffer/service/context_group.h +++ b/gpu/command_buffer/service/context_group.h @@ -22,9 +22,10 @@ class IdAllocatorInterface; namespace gles2 { -class GLES2Decoder; class BufferManager; +class GLES2Decoder; class FramebufferManager; +class MailboxManager; class RenderbufferManager; class ProgramManager; class ShaderManager; @@ -37,7 +38,8 @@ class GPU_EXPORT ContextGroup : public base::RefCounted<ContextGroup> { public: typedef scoped_refptr<ContextGroup> Ref; - explicit ContextGroup(bool bind_generates_resource); + explicit ContextGroup(MailboxManager* mailbox_manager, + bool bind_generates_resource); ~ContextGroup(); // This should only be called by GLES2Decoder. This must be paired with a @@ -49,6 +51,10 @@ class GPU_EXPORT ContextGroup : public base::RefCounted<ContextGroup> { // It should only be called by GLES2Decoder. void Destroy(bool have_context); + MailboxManager* mailbox_manager() const { + return mailbox_manager_.get(); + } + bool bind_generates_resource() { return bind_generates_resource_; } @@ -117,6 +123,8 @@ class GPU_EXPORT ContextGroup : public base::RefCounted<ContextGroup> { bool QueryGLFeature(GLenum pname, GLint min_required, GLint* v); bool QueryGLFeatureU(GLenum pname, GLint min_required, uint32* v); + scoped_refptr<MailboxManager> mailbox_manager_; + // Whether or not this context is initialized. int num_contexts_; bool enforce_gl_minimums_; diff --git a/gpu/command_buffer/service/context_group_unittest.cc b/gpu/command_buffer/service/context_group_unittest.cc index bb60af9..e0eb64a 100644 --- a/gpu/command_buffer/service/context_group_unittest.cc +++ b/gpu/command_buffer/service/context_group_unittest.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -36,7 +36,7 @@ class ContextGroupTest : public testing::Test { virtual void SetUp() { gl_.reset(new ::testing::StrictMock< ::gfx::MockGLInterface>()); ::gfx::GLInterface::SetGLInterface(gl_.get()); - group_ = ContextGroup::Ref(new ContextGroup(true)); + group_ = ContextGroup::Ref(new ContextGroup(NULL, true)); } virtual void TearDown() { diff --git a/gpu/command_buffer/service/feature_info.cc b/gpu/command_buffer/service/feature_info.cc index fff10fc..01c0ffd 100644 --- a/gpu/command_buffer/service/feature_info.cc +++ b/gpu/command_buffer/service/feature_info.cc @@ -121,6 +121,7 @@ void FeatureInfo::AddFeatures(const char* desired_features) { AddExtensionString("GL_CHROMIUM_discard_framebuffer"); AddExtensionString("GL_CHROMIUM_command_buffer_query"); AddExtensionString("GL_CHROMIUM_copy_texture"); + AddExtensionString("GL_CHROMIUM_texture_mailbox"); AddExtensionString("GL_ANGLE_translated_shader_source"); if (ext.Have("GL_ANGLE_translated_shader_source")) { diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc index cc864ab..18c799d 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc @@ -36,6 +36,7 @@ #include "gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h" #include "gpu/command_buffer/service/gles2_cmd_validation.h" #include "gpu/command_buffer/service/gpu_switches.h" +#include "gpu/command_buffer/service/mailbox_manager.h" #include "gpu/command_buffer/service/program_manager.h" #include "gpu/command_buffer/service/query_manager.h" #include "gpu/command_buffer/service/renderbuffer_manager.h" @@ -43,6 +44,7 @@ #include "gpu/command_buffer/service/shader_translator.h" #include "gpu/command_buffer/service/stream_texture.h" #include "gpu/command_buffer/service/stream_texture_manager.h" +#include "gpu/command_buffer/service/texture_definition.h" #include "gpu/command_buffer/service/texture_manager.h" #include "gpu/command_buffer/service/vertex_attrib_manager.h" #include "ui/gfx/gl/gl_context.h" @@ -509,6 +511,9 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>, // Sets DEPTH_TEST, STENCIL_TEST and color mask for the current framebuffer. void ApplyDirtyState(); + // Reapply the texture parameters to the given texture. + void BindAndApplyTextureParameters(TextureManager::TextureInfo* info); + // These check the state of the currently bound framebuffer or the // backbuffer if no framebuffer is bound. bool BoundFramebufferHasColorAttachmentWithAlpha(); @@ -619,6 +624,10 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>, return group_->texture_manager(); } + MailboxManager* mailbox_manager() { + return group_->mailbox_manager(); + } + bool IsOffscreenBufferMultisampled() const { return offscreen_target_samples_ > 1; } @@ -742,6 +751,9 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>, GLsizei width, GLsizei height); + void DoProduceTextureCHROMIUM(GLenum target, const GLbyte* key); + void DoConsumeTextureCHROMIUM(GLenum target, const GLbyte* key); + // Creates a ProgramInfo for the given program. ProgramManager::ProgramInfo* CreateProgramInfo( GLuint client_id, GLuint service_id) { @@ -3265,6 +3277,15 @@ void GLES2DecoderImpl::ApplyDirtyState() { } } +void GLES2DecoderImpl::BindAndApplyTextureParameters( + TextureManager::TextureInfo* info) { + glBindTexture(info->target(), info->service_id()); + glTexParameteri(info->target(), GL_TEXTURE_MIN_FILTER, info->min_filter()); + glTexParameteri(info->target(), GL_TEXTURE_MAG_FILTER, info->mag_filter()); + glTexParameteri(info->target(), GL_TEXTURE_WRAP_S, info->wrap_s()); + glTexParameteri(info->target(), GL_TEXTURE_WRAP_T, info->wrap_t()); +} + GLuint GLES2DecoderImpl::GetBackbufferServiceId() { return (offscreen_target_frame_buffer_.get()) ? offscreen_target_frame_buffer_->id() : @@ -8507,6 +8528,78 @@ void GLES2DecoderImpl::DoTexStorage2DEXT( } } +error::Error GLES2DecoderImpl::HandleGenMailboxCHROMIUM( + uint32 immediate_data_size, const gles2::GenMailboxCHROMIUM& c) { + MailboxName name; + mailbox_manager()->GenerateMailboxName(&name); + uint32 bucket_id = static_cast<uint32>(c.bucket_id); + Bucket* bucket = CreateBucket(bucket_id); + + bucket->SetSize(GL_MAILBOX_SIZE_CHROMIUM); + bucket->SetData(&name, 0, GL_MAILBOX_SIZE_CHROMIUM); + + return error::kNoError; +} + +void GLES2DecoderImpl::DoProduceTextureCHROMIUM(GLenum target, + const GLbyte* mailbox) { + TextureManager::TextureInfo* info = GetTextureInfoForTarget(target); + if (!info) { + SetGLError(GL_INVALID_OPERATION, + "glProduceTextureCHROMIUM: unknown texture for target"); + return; + } + + TextureDefinition* definition = texture_manager()->Save(info); + if (!definition) { + SetGLError(GL_INVALID_OPERATION, + "glProduceTextureCHROMIUM: invalid texture"); + return; + } + + if (!group_->mailbox_manager()->ProduceTexture( + target, + *reinterpret_cast<const MailboxName*>(mailbox), + definition, + texture_manager())) { + bool success = texture_manager()->Restore(info, definition); + DCHECK(success); + SetGLError(GL_INVALID_OPERATION, + "glProduceTextureCHROMIUM: invalid mailbox name"); + return; + } + + BindAndApplyTextureParameters(info); +} + +void GLES2DecoderImpl::DoConsumeTextureCHROMIUM(GLenum target, + const GLbyte* mailbox) { + TextureManager::TextureInfo* info = GetTextureInfoForTarget(target); + if (!info) { + SetGLError(GL_INVALID_OPERATION, + "glConsumeTextureCHROMIUM: unknown texture for target"); + return; + } + + scoped_ptr<TextureDefinition> definition( + group_->mailbox_manager()->ConsumeTexture( + target, + *reinterpret_cast<const MailboxName*>(mailbox))); + if (!definition.get()) { + SetGLError(GL_INVALID_OPERATION, + "glConsumeTextureCHROMIUM: invalid mailbox name"); + return; + } + + if (!texture_manager()->Restore(info, definition.release())) { + SetGLError(GL_INVALID_OPERATION, + "glConsumeTextureCHROMIUM: invalid texture"); + return; + } + + BindAndApplyTextureParameters(info); +} + // Include the auto-generated part of this file. We split this because it means // we can easily edit the non-auto generated parts right here in this file // instead of having to edit some template or the code generator. diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h index 01fc027..f2b9f26 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h @@ -2736,5 +2736,97 @@ error::Error GLES2DecoderImpl::HandleCopyTextureCHROMIUM( return error::kNoError; } +error::Error GLES2DecoderImpl::HandleProduceTextureCHROMIUM( + uint32 immediate_data_size, const gles2::ProduceTextureCHROMIUM& c) { + GLenum target = static_cast<GLenum>(c.target); + uint32 data_size; + if (!ComputeDataSize(1, sizeof(GLbyte), 64, &data_size)) { + return error::kOutOfBounds; + } + const GLbyte* mailbox = GetSharedMemoryAs<const GLbyte*>( + c.mailbox_shm_id, c.mailbox_shm_offset, data_size); + if (!validators_->texture_target.IsValid(target)) { + SetGLError( + GL_INVALID_ENUM, "glProduceTextureCHROMIUM: target GL_INVALID_ENUM"); + return error::kNoError; + } + if (mailbox == NULL) { + return error::kOutOfBounds; + } + DoProduceTextureCHROMIUM(target, mailbox); + return error::kNoError; +} + +error::Error GLES2DecoderImpl::HandleProduceTextureCHROMIUMImmediate( + uint32 immediate_data_size, + const gles2::ProduceTextureCHROMIUMImmediate& c) { + GLenum target = static_cast<GLenum>(c.target); + uint32 data_size; + if (!ComputeDataSize(1, sizeof(GLbyte), 64, &data_size)) { + return error::kOutOfBounds; + } + if (data_size > immediate_data_size) { + return error::kOutOfBounds; + } + const GLbyte* mailbox = GetImmediateDataAs<const GLbyte*>( + c, data_size, immediate_data_size); + if (!validators_->texture_target.IsValid(target)) { + SetGLError( + GL_INVALID_ENUM, "glProduceTextureCHROMIUM: target GL_INVALID_ENUM"); + return error::kNoError; + } + if (mailbox == NULL) { + return error::kOutOfBounds; + } + DoProduceTextureCHROMIUM(target, mailbox); + return error::kNoError; +} + +error::Error GLES2DecoderImpl::HandleConsumeTextureCHROMIUM( + uint32 immediate_data_size, const gles2::ConsumeTextureCHROMIUM& c) { + GLenum target = static_cast<GLenum>(c.target); + uint32 data_size; + if (!ComputeDataSize(1, sizeof(GLbyte), 64, &data_size)) { + return error::kOutOfBounds; + } + const GLbyte* mailbox = GetSharedMemoryAs<const GLbyte*>( + c.mailbox_shm_id, c.mailbox_shm_offset, data_size); + if (!validators_->texture_target.IsValid(target)) { + SetGLError( + GL_INVALID_ENUM, "glConsumeTextureCHROMIUM: target GL_INVALID_ENUM"); + return error::kNoError; + } + if (mailbox == NULL) { + return error::kOutOfBounds; + } + DoConsumeTextureCHROMIUM(target, mailbox); + return error::kNoError; +} + +error::Error GLES2DecoderImpl::HandleConsumeTextureCHROMIUMImmediate( + uint32 immediate_data_size, + const gles2::ConsumeTextureCHROMIUMImmediate& c) { + GLenum target = static_cast<GLenum>(c.target); + uint32 data_size; + if (!ComputeDataSize(1, sizeof(GLbyte), 64, &data_size)) { + return error::kOutOfBounds; + } + if (data_size > immediate_data_size) { + return error::kOutOfBounds; + } + const GLbyte* mailbox = GetImmediateDataAs<const GLbyte*>( + c, data_size, immediate_data_size); + if (!validators_->texture_target.IsValid(target)) { + SetGLError( + GL_INVALID_ENUM, "glConsumeTextureCHROMIUM: target GL_INVALID_ENUM"); + return error::kNoError; + } + if (mailbox == NULL) { + return error::kOutOfBounds; + } + DoConsumeTextureCHROMIUM(target, mailbox); + return error::kNoError; +} + #endif // GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_AUTOGEN_H_ diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc index 9f08a9e..08bd91c 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc @@ -12,6 +12,7 @@ #include "gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h" #include "gpu/command_buffer/service/cmd_buffer_engine.h" #include "gpu/command_buffer/service/context_group.h" +#include "gpu/command_buffer/service/mailbox_manager.h" #include "gpu/command_buffer/service/stream_texture_mock.h" #include "gpu/command_buffer/service/stream_texture_manager_mock.h" #include "gpu/command_buffer/service/program_manager.h" @@ -6787,6 +6788,132 @@ TEST_F(GLES2DecoderTest, BeingEndQueryEXTCommandsIssuedCHROMIUM) { EXPECT_FALSE(query->pending()); } +TEST_F(GLES2DecoderTest, GenMailboxCHROMIUM) { + const uint32 kBucketId = 123; + + GenMailboxCHROMIUM gen_mailbox_cmd; + gen_mailbox_cmd.Init(kBucketId); + EXPECT_EQ(error::kNoError, ExecuteCmd(gen_mailbox_cmd)); + + CommonDecoder::Bucket* bucket = decoder_->GetBucket(kBucketId); + ASSERT_TRUE(bucket != NULL); + ASSERT_EQ(static_cast<uint32>(GL_MAILBOX_SIZE_CHROMIUM), bucket->size()); + + static const GLbyte zero[GL_MAILBOX_SIZE_CHROMIUM] = { + 0 + }; + EXPECT_NE(0, memcmp(zero, + bucket->GetData(0, GL_MAILBOX_SIZE_CHROMIUM), + sizeof(zero))); +} + +TEST_F(GLES2DecoderTest, ProduceAndConsumeTextureCHROMIUM) { + GLbyte mailbox[GL_MAILBOX_SIZE_CHROMIUM]; + group().mailbox_manager()->GenerateMailboxName( + reinterpret_cast<MailboxName*>(mailbox)); + + memcpy(shared_memory_address_, mailbox, sizeof(mailbox)); + + DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); + DoTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 3, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, + 0, 0); + DoTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 2, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, + 0, 0); + TextureManager::TextureInfo* info = + group().texture_manager()->GetTextureInfo(client_texture_id_); + EXPECT_EQ(kServiceTextureId, info->service_id()); + + // Assigns and binds new service side texture ID and applies the texture + // objects' state to it. + EXPECT_CALL(*gl_, GenTextures(1, _)) + .WillOnce(SetArgumentPointee<1>(kNewServiceId)) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, BindTexture(GL_TEXTURE_2D, kNewServiceId)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, TexParameteri(GL_TEXTURE_2D, + GL_TEXTURE_MIN_FILTER, + GL_NEAREST_MIPMAP_LINEAR)); + EXPECT_CALL(*gl_, TexParameteri(GL_TEXTURE_2D, + GL_TEXTURE_MAG_FILTER, + GL_LINEAR)); + EXPECT_CALL(*gl_, TexParameteri(GL_TEXTURE_2D, + GL_TEXTURE_WRAP_S, + GL_REPEAT)); + EXPECT_CALL(*gl_, TexParameteri(GL_TEXTURE_2D, + GL_TEXTURE_WRAP_T, + GL_REPEAT)); + + ProduceTextureCHROMIUM produce_cmd; + produce_cmd.Init(GL_TEXTURE_2D, kSharedMemoryId, kSharedMemoryOffset); + EXPECT_EQ(error::kNoError, ExecuteCmd(produce_cmd)); + + // Texture is zero-by-zero. + GLsizei width; + GLsizei height; + GLenum type; + GLenum internal_format; + + EXPECT_TRUE(info->GetLevelSize(GL_TEXTURE_2D, 0, &width, &height)); + EXPECT_EQ(0, width); + EXPECT_EQ(0, height); + EXPECT_TRUE(info->GetLevelType(GL_TEXTURE_2D, 0, &type, &internal_format)); + EXPECT_EQ(static_cast<GLenum>(GL_RGBA), internal_format); + EXPECT_EQ(static_cast<GLenum>(GL_UNSIGNED_BYTE), type); + + EXPECT_TRUE(info->GetLevelSize(GL_TEXTURE_2D, 1, &width, &height)); + EXPECT_EQ(0, width); + EXPECT_EQ(0, height); + EXPECT_TRUE(info->GetLevelType(GL_TEXTURE_2D, 1, &type, &internal_format)); + EXPECT_EQ(static_cast<GLenum>(GL_RGBA), internal_format); + EXPECT_EQ(static_cast<GLenum>(GL_UNSIGNED_BYTE), type); + + // Service ID has changed. + EXPECT_EQ(kNewServiceId, info->service_id()); + + // Assigns and binds original service side texture ID and applies the texture + // objects' state to it. + EXPECT_CALL(*gl_, DeleteTextures(1, _)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, BindTexture(GL_TEXTURE_2D, kServiceTextureId)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, TexParameteri(GL_TEXTURE_2D, + GL_TEXTURE_MIN_FILTER, + GL_NEAREST_MIPMAP_LINEAR)); + EXPECT_CALL(*gl_, TexParameteri(GL_TEXTURE_2D, + GL_TEXTURE_MAG_FILTER, + GL_LINEAR)); + EXPECT_CALL(*gl_, TexParameteri(GL_TEXTURE_2D, + GL_TEXTURE_WRAP_S, + GL_REPEAT)); + EXPECT_CALL(*gl_, TexParameteri(GL_TEXTURE_2D, + GL_TEXTURE_WRAP_T, + GL_REPEAT)); + + ConsumeTextureCHROMIUM consume_cmd; + consume_cmd.Init(GL_TEXTURE_2D, kSharedMemoryId, kSharedMemoryOffset); + EXPECT_EQ(error::kNoError, ExecuteCmd(consume_cmd)); + + // Texture is redefined. + EXPECT_TRUE(info->GetLevelSize(GL_TEXTURE_2D, 0, &width, &height)); + EXPECT_EQ(3, width); + EXPECT_EQ(1, height); + EXPECT_TRUE(info->GetLevelType(GL_TEXTURE_2D, 0, &type, &internal_format)); + EXPECT_EQ(static_cast<GLenum>(GL_RGBA), internal_format); + EXPECT_EQ(static_cast<GLenum>(GL_UNSIGNED_BYTE), type); + + EXPECT_TRUE(info->GetLevelSize(GL_TEXTURE_2D, 1, &width, &height)); + EXPECT_EQ(2, width); + EXPECT_EQ(4, height); + EXPECT_TRUE(info->GetLevelType(GL_TEXTURE_2D, 1, &type, &internal_format)); + EXPECT_EQ(static_cast<GLenum>(GL_RGBA), internal_format); + EXPECT_EQ(static_cast<GLenum>(GL_UNSIGNED_BYTE), type); + + // Service ID is restored. + EXPECT_EQ(kServiceTextureId, info->service_id()); +} // 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 8e2df7a..ccdc475 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 @@ -34,5 +34,10 @@ // TODO(gman): DrawArraysInstancedANGLE // TODO(gman): DrawElementsInstancedANGLE // TODO(gman): VertexAttribDivisorANGLE +// TODO(gman): GenMailboxCHROMIUM +// TODO(gman): ProduceTextureCHROMIUM +// TODO(gman): ProduceTextureCHROMIUMImmediate +// TODO(gman): ConsumeTextureCHROMIUM +// TODO(gman): ConsumeTextureCHROMIUMImmediate #endif // GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_UNITTEST_3_AUTOGEN_H_ diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc index 40e98d4..2a43f99 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc @@ -194,7 +194,7 @@ void GLES2DecoderTestBase::InitDecoder( bool bind_generates_resource) { gl_.reset(new StrictMock<MockGLInterface>()); ::gfx::GLInterface::SetGLInterface(gl_.get()); - group_ = ContextGroup::Ref(new ContextGroup(bind_generates_resource)); + group_ = ContextGroup::Ref(new ContextGroup(NULL, bind_generates_resource)); InSequence sequence; diff --git a/gpu/command_buffer/service/mailbox_manager.cc b/gpu/command_buffer/service/mailbox_manager.cc new file mode 100644 index 0000000..e161fcb --- /dev/null +++ b/gpu/command_buffer/service/mailbox_manager.cc @@ -0,0 +1,125 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "gpu/command_buffer/service/mailbox_manager.h" + +#include "base/rand_util.h" +#include "crypto/hmac.h" +#include "gpu/command_buffer/service/gl_utils.h" +#include "gpu/command_buffer/service/texture_definition.h" + +namespace gpu { +namespace gles2 { + +MailboxManager::MailboxManager() + : hmac_(crypto::HMAC::SHA256), + textures_(std::ptr_fun(&MailboxManager::TargetNameLess)) { + unsigned char private_key[GL_MAILBOX_SIZE_CHROMIUM / 2]; + base::RandBytes(private_key, sizeof(private_key)); + bool success = hmac_.Init(private_key, sizeof(private_key)); + DCHECK(success); +} + +MailboxManager::~MailboxManager() { +} + +void MailboxManager::GenerateMailboxName(MailboxName* name) { + base::RandBytes(name->key, sizeof(name->key)); + SignMailboxName(name); +} + +TextureDefinition* MailboxManager::ConsumeTexture(unsigned target, + const MailboxName& name) { + if (!IsMailboxNameValid(name)) + return NULL; + + TextureDefinitionMap::iterator it = + textures_.find(TargetName(target, name)); + if (it == textures_.end()) { + NOTREACHED(); + return NULL; + } + + TextureDefinition* definition = it->second.definition.release(); + textures_.erase(it); + + return definition; +} + +bool MailboxManager::ProduceTexture(unsigned target, + const MailboxName& name, + TextureDefinition* definition, + TextureManager* owner) { + if (!IsMailboxNameValid(name)) + return false; + + TextureDefinitionMap::iterator it = + textures_.find(TargetName(target, name)); + if (it != textures_.end()) { + NOTREACHED(); + GLuint service_id = it->second.definition->ReleaseServiceId(); + glDeleteTextures(1, &service_id); + it->second = OwnedTextureDefinition(definition, owner); + } else { + textures_.insert(std::make_pair( + TargetName(target, name), + OwnedTextureDefinition(definition, owner))); + } + + return true; +} + +void MailboxManager::DestroyOwnedTextures(TextureManager* owner, + bool have_context) { + TextureDefinitionMap::iterator it = textures_.begin(); + while (it != textures_.end()) { + TextureDefinitionMap::iterator current_it = it; + ++it; + if (current_it->second.owner == owner) { + NOTREACHED(); + GLuint service_id = current_it->second.definition->ReleaseServiceId(); + if (have_context) + glDeleteTextures(1, &service_id); + textures_.erase(current_it); + } + } +} + +void MailboxManager::SignMailboxName(MailboxName* name) { + bool success = hmac_.Sign( + base::StringPiece(reinterpret_cast<char*>(name->key), sizeof(name->key)), + reinterpret_cast<unsigned char*>(name->signature), + sizeof(name->signature)); + DCHECK(success); +} + +bool MailboxManager::IsMailboxNameValid(const MailboxName& name) { + return hmac_.Verify( + base::StringPiece(reinterpret_cast<const char*>(name.key), + sizeof(name.key)), + base::StringPiece(reinterpret_cast<const char*>(name.signature), + sizeof(name.signature))); +} + +MailboxManager::TargetName::TargetName(unsigned target, const MailboxName& name) + : target(target), + name(name) { +} + +bool MailboxManager::TargetNameLess(MailboxManager::TargetName lhs, + MailboxManager::TargetName rhs) { + return memcmp(&lhs, &rhs, sizeof(lhs)) < 0; +} + +MailboxManager::OwnedTextureDefinition::OwnedTextureDefinition( + TextureDefinition* definition, + TextureManager* owner) + : definition(definition), + owner(owner) { +} + +MailboxManager::OwnedTextureDefinition::~OwnedTextureDefinition() { +} +} // namespace gles2 +} // namespace gpu diff --git a/gpu/command_buffer/service/mailbox_manager.h b/gpu/command_buffer/service/mailbox_manager.h new file mode 100644 index 0000000..e7af1c4 --- /dev/null +++ b/gpu/command_buffer/service/mailbox_manager.h @@ -0,0 +1,99 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef GPU_COMMAND_BUFFER_SERVICE_MAILBOX_MANAGER_H_ +#define GPU_COMMAND_BUFFER_SERVICE_MAILBOX_MANAGER_H_ + +#include <functional> +#include <map> + +#include "base/memory/linked_ptr.h" +#include "base/memory/ref_counted.h" +#include "crypto/hmac.h" +#include "gpu/command_buffer/common/constants.h" +#include "gpu/gpu_export.h" + +// From gl2/gl2ext.h. +#ifndef GL_MAILBOX_SIZE_CHROMIUM +#define GL_MAILBOX_SIZE_CHROMIUM 64 +#endif + +typedef signed char GLbyte; + +namespace gpu { +namespace gles2 { + +class TextureDefinition; +class TextureManager; + +// Identifies a mailbox where a texture definition can be stored for +// transferring textures between contexts that are not in the same context +// group. It is a random key signed with a hash of a private key. +struct MailboxName { + GLbyte key[GL_MAILBOX_SIZE_CHROMIUM / 2]; + GLbyte signature[GL_MAILBOX_SIZE_CHROMIUM / 2]; +}; + +// Manages resources scoped beyond the context or context group level. +class GPU_EXPORT MailboxManager : public base::RefCounted<MailboxManager> { + public: + MailboxManager(); + + // Generate a unique mailbox name signed with the manager's private key. + void GenerateMailboxName(MailboxName* name); + + // Remove the texture definition from the named mailbox and empty the mailbox. + TextureDefinition* ConsumeTexture(unsigned target, const MailboxName& name); + + // Put the texture definition in the named mailbox. + bool ProduceTexture(unsigned target, + const MailboxName& name, + TextureDefinition* definition, + TextureManager* owner); + + // Destroy any texture definitions and mailboxes owned by the given texture + // manager. + void DestroyOwnedTextures(TextureManager* owner, bool have_context); + + private: + friend class base::RefCounted<MailboxManager>; + + ~MailboxManager(); + + void SignMailboxName(MailboxName* name); + bool IsMailboxNameValid(const MailboxName& name); + + struct TargetName { + TargetName(unsigned target, const MailboxName& name); + unsigned target; + MailboxName name; + }; + + static bool TargetNameLess(TargetName lhs, TargetName rhs); + + struct OwnedTextureDefinition { + OwnedTextureDefinition(TextureDefinition* definition, + TextureManager* owner); + ~OwnedTextureDefinition(); + linked_ptr<TextureDefinition> definition; + TextureManager* owner; + }; + + typedef std::map< + TargetName, + OwnedTextureDefinition, + std::pointer_to_binary_function<TargetName, TargetName, bool> > + TextureDefinitionMap; + + crypto::HMAC hmac_; + TextureDefinitionMap textures_; + + DISALLOW_COPY_AND_ASSIGN(MailboxManager); +}; +} // namespage gles2 +} // namespace gpu + +#endif // GPU_COMMAND_BUFFER_SERVICE_MAILBOX_MANAGER_H_ + + diff --git a/gpu/command_buffer/service/texture_definition.cc b/gpu/command_buffer/service/texture_definition.cc new file mode 100644 index 0000000..731ff6f --- /dev/null +++ b/gpu/command_buffer/service/texture_definition.cc @@ -0,0 +1,49 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "gpu/command_buffer/service/texture_definition.h" + +namespace gpu { +namespace gles2 { + +TextureDefinition::LevelInfo::LevelInfo(GLenum target, + GLenum internal_format, + GLsizei width, + GLsizei height, + GLsizei depth, + GLint border, + GLenum format, + GLenum type, + bool cleared) + : target(target), + internal_format(internal_format), + width(width), + height(height), + depth(depth), + border(border), + format(format), + type(type), + cleared(cleared) { +} + +TextureDefinition::TextureDefinition(GLenum target, + GLuint service_id, + const LevelInfos& level_infos) + : target_(target), + service_id_(service_id), + level_infos_(level_infos) { +} + +TextureDefinition::~TextureDefinition() { + DCHECK_EQ(0U, service_id_) << "TextureDefinition leaked texture."; +} + +GLuint TextureDefinition::ReleaseServiceId() { + GLuint service_id = service_id_; + service_id_ = 0; + return service_id; +} + +} // namespace gles2 +} // namespace gpu diff --git a/gpu/command_buffer/service/texture_definition.h b/gpu/command_buffer/service/texture_definition.h new file mode 100644 index 0000000..520c6f8 --- /dev/null +++ b/gpu/command_buffer/service/texture_definition.h @@ -0,0 +1,75 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef GPU_COMMAND_BUFFER_SERVICE_TEXTURE_DEFINITION_H_ +#define GPU_COMMAND_BUFFER_SERVICE_TEXTURE_DEFINITION_H_ + +#include <vector> + +#include "base/callback.h" +#include "gpu/command_buffer/service/gl_utils.h" +#include "gpu/gpu_export.h" + +namespace gpu { +namespace gles2 { + +// A saved definition of a texture that still exists in the underlying +// GLShareGroup and can be used to redefine a client visible texture in any +// context using the same GLShareGroup with the corresponding service ID. +class GPU_EXPORT TextureDefinition { + public: + struct LevelInfo { + LevelInfo(GLenum target, + GLenum internal_format, + GLsizei width, + GLsizei height, + GLsizei depth, + GLint border, + GLenum format, + GLenum type, + bool cleared); + GLenum target; + GLenum internal_format; + GLsizei width; + GLsizei height; + GLsizei depth; + GLint border; + GLenum format; + GLenum type; + bool cleared; + }; + + typedef std::vector<std::vector<LevelInfo> > LevelInfos; + + typedef base::Callback<void(TextureDefinition*)> DestroyCallback; + + TextureDefinition(GLenum target, + GLuint service_id, + const LevelInfos& level_infos); + ~TextureDefinition(); + + GLenum target() const { + return target_; + } + + GLuint ReleaseServiceId(); + + const LevelInfos& level_infos() const { + return level_infos_; + } + + private: + GLenum target_; + GLuint service_id_; + std::vector<std::vector<LevelInfo> > level_infos_; + + DISALLOW_COPY_AND_ASSIGN(TextureDefinition); +}; + +} // namespage gles2 +} // namespace gpu + +#endif // GPU_COMMAND_BUFFER_SERVICE_TEXTURE_DEFINITION_H_ + + diff --git a/gpu/command_buffer/service/texture_manager.cc b/gpu/command_buffer/service/texture_manager.cc index 241fb3e..e97514d 100644 --- a/gpu/command_buffer/service/texture_manager.cc +++ b/gpu/command_buffer/service/texture_manager.cc @@ -8,6 +8,8 @@ #include "gpu/command_buffer/common/gles2_cmd_utils.h" #include "gpu/command_buffer/service/feature_info.h" #include "gpu/command_buffer/service/gles2_cmd_decoder.h" +#include "gpu/command_buffer/service/mailbox_manager.h" +#include "gpu/command_buffer/service/texture_definition.h" namespace gpu { namespace gles2 { @@ -87,6 +89,34 @@ void TextureManager::Destroy(bool have_context) { UpdateMemRepresented(); } +TextureManager::TextureInfo::TextureInfo(TextureManager* manager, + GLuint service_id) + : manager_(manager), + service_id_(service_id), + deleted_(false), + cleared_(true), + num_uncleared_mips_(0), + target_(0), + min_filter_(GL_NEAREST_MIPMAP_LINEAR), + mag_filter_(GL_LINEAR), + wrap_s_(GL_REPEAT), + wrap_t_(GL_REPEAT), + usage_(GL_NONE), + max_level_set_(-1), + texture_complete_(false), + cube_complete_(false), + npot_(false), + has_been_bound_(false), + framebuffer_attachment_count_(0), + owned_(true), + stream_texture_(false), + immutable_(false), + estimated_size_(0) { + if (manager_) { + manager_->StartTracking(this); + } +} + TextureManager::TextureInfo::~TextureInfo() { if (manager_) { if (owned_ && manager_->have_context_) { @@ -798,6 +828,106 @@ void TextureManager::SetLevelInfo( } } +TextureDefinition* TextureManager::Save(TextureInfo* info) { + DCHECK(info->owned_); + + if (info->IsAttachedToFramebuffer()) + return NULL; + + if (info->IsImmutable()) + return NULL; + + TextureDefinition::LevelInfos level_infos(info->level_infos_.size()); + for (size_t face = 0; face < level_infos.size(); ++face) { + GLenum target = info->target() == GL_TEXTURE_2D ? + GL_TEXTURE_2D : FaceIndexToGLTarget(face); + for (size_t level = 0; level < info->level_infos_[face].size(); ++level) { + const TextureInfo::LevelInfo& level_info = + info->level_infos_[face][level]; + level_infos[face].push_back( + TextureDefinition::LevelInfo(target, + level_info.internal_format, + level_info.width, + level_info.height, + level_info.depth, + level_info.border, + level_info.format, + level_info.type, + level_info.cleared)); + + SetLevelInfo(info, + target, + level, + GL_RGBA, + 0, + 0, + 0, + 0, + GL_RGBA, + GL_UNSIGNED_BYTE, + true); + } + } + + GLuint old_service_id = info->service_id(); + + GLuint new_service_id = 0; + glGenTextures(1, &new_service_id); + info->SetServiceId(new_service_id); + + return new TextureDefinition(info->target(), + old_service_id, + level_infos); +} + +bool TextureManager::Restore(TextureInfo* info, + TextureDefinition* definition) { + DCHECK(info->owned_); + + scoped_ptr<TextureDefinition> scoped_definition(definition); + + if (info->IsAttachedToFramebuffer()) + return false; + + if (info->IsImmutable()) + return false; + + if (info->target() != definition->target()) + return false; + + if (info->level_infos_.size() != definition->level_infos().size()) + return false; + + if (info->level_infos_[0].size() != definition->level_infos()[0].size()) + return false; + + for (size_t face = 0; face < info->level_infos_.size(); ++face) { + GLenum target = info->target() == GL_TEXTURE_2D ? + GL_TEXTURE_2D : FaceIndexToGLTarget(face); + for (size_t level = 0; level < info->level_infos_[face].size(); ++level) { + const TextureDefinition::LevelInfo& level_info = + definition->level_infos()[face][level]; + SetLevelInfo(info, + target, + level, + level_info.internal_format, + level_info.width, + level_info.height, + level_info.depth, + level_info.border, + level_info.format, + level_info.type, + level_info.cleared); + } + } + + GLuint old_service_id = info->service_id(); + glDeleteTextures(1, &old_service_id); + info->SetServiceId(definition->ReleaseServiceId()); + + return true; +} + bool TextureManager::SetParameter( TextureManager::TextureInfo* info, GLenum pname, GLint param) { DCHECK(info); @@ -915,7 +1045,6 @@ GLsizei TextureManager::ComputeMipMapCount( return 1 + base::bits::Log2Floor(std::max(std::max(width, height), depth)); } - } // namespace gles2 } // namespace gpu diff --git a/gpu/command_buffer/service/texture_manager.h b/gpu/command_buffer/service/texture_manager.h index 9cdc74a..927711c 100644 --- a/gpu/command_buffer/service/texture_manager.h +++ b/gpu/command_buffer/service/texture_manager.h @@ -18,6 +18,8 @@ namespace gpu { namespace gles2 { class GLES2Decoder; +class Display; +class TextureDefinition; // This class keeps track of the textures and their sizes so we can do NPOT and // texture complete checking. @@ -39,32 +41,7 @@ class GPU_EXPORT TextureManager { public: typedef scoped_refptr<TextureInfo> Ref; - TextureInfo(TextureManager* manager, GLuint service_id) - : manager_(manager), - service_id_(service_id), - deleted_(false), - cleared_(true), - num_uncleared_mips_(0), - target_(0), - min_filter_(GL_NEAREST_MIPMAP_LINEAR), - mag_filter_(GL_LINEAR), - wrap_s_(GL_REPEAT), - wrap_t_(GL_REPEAT), - usage_(GL_NONE), - max_level_set_(-1), - texture_complete_(false), - cube_complete_(false), - npot_(false), - has_been_bound_(false), - framebuffer_attachment_count_(0), - owned_(true), - stream_texture_(false), - immutable_(false), - estimated_size_(0) { - if (manager_) { - manager_->StartTracking(this); - } - } + TextureInfo(TextureManager* manager, GLuint service_id); GLenum min_filter() const { return min_filter_; @@ -223,6 +200,20 @@ class GPU_EXPORT TextureManager { estimated_size(0) { } + LevelInfo(const LevelInfo& rhs) + : cleared(rhs.cleared), + target(rhs.target), + level(rhs.level), + internal_format(rhs.internal_format), + width(rhs.width), + height(rhs.height), + depth(rhs.depth), + border(rhs.border), + format(rhs.format), + type(rhs.type), + estimated_size(rhs.estimated_size) { + } + bool cleared; GLenum target; GLint level; @@ -436,6 +427,13 @@ class GPU_EXPORT TextureManager { GLenum type, bool cleared); + // Save the texture definition and leave it undefined. + TextureDefinition* Save(TextureInfo* info); + + // Redefine all the levels from the texture definition. + bool Restore(TextureInfo* info, + TextureDefinition* definition); + // Sets a mip as cleared. void SetLevelCleared(TextureInfo* info, GLenum target, GLint level); diff --git a/gpu/command_buffer/tests/gl_manager.cc b/gpu/command_buffer/tests/gl_manager.cc index 7db4c10..48c15bf2 100644 --- a/gpu/command_buffer/tests/gl_manager.cc +++ b/gpu/command_buffer/tests/gl_manager.cc @@ -9,9 +9,10 @@ #include "gpu/command_buffer/client/gles2_implementation.h" #include "gpu/command_buffer/client/transfer_buffer.h" #include "gpu/command_buffer/common/constants.h" +#include "gpu/command_buffer/service/command_buffer_service.h" #include "gpu/command_buffer/service/context_group.h" #include "gpu/command_buffer/service/gpu_scheduler.h" -#include "gpu/command_buffer/service/command_buffer_service.h" +#include "gpu/command_buffer/service/mailbox_manager.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/gfx/gl/gl_context.h" #include "ui/gfx/gl/gl_share_group.h" @@ -19,7 +20,10 @@ namespace gpu { -GLManager::GLManager() { +GLManager::GLManager(gles2::MailboxManager* mailbox_manager, + gfx::GLShareGroup* share_group) + : mailbox_manager_(mailbox_manager), + share_group_(share_group) { } GLManager::~GLManager() { @@ -54,13 +58,12 @@ void GLManager::Initialize(const gfx::Size& size) { attribs.push_back(16); attribs.push_back(EGL_NONE); - share_group_ = new gfx::GLShareGroup; command_buffer_.reset(new CommandBufferService); ASSERT_TRUE(command_buffer_->Initialize()) << "could not create command buffer service"; decoder_.reset(::gpu::gles2::GLES2Decoder::Create( - new gles2::ContextGroup(false))); + new gles2::ContextGroup(mailbox_manager_.get(), false))); gpu_scheduler_.reset(new GpuScheduler(command_buffer_.get(), decoder_.get(), diff --git a/gpu/command_buffer/tests/gl_manager.h b/gpu/command_buffer/tests/gl_manager.h index cacf47a..b25bbfb 100644 --- a/gpu/command_buffer/tests/gl_manager.h +++ b/gpu/command_buffer/tests/gl_manager.h @@ -25,6 +25,7 @@ class GpuScheduler; namespace gles2 { +class MailboxManager; class GLES2Decoder; class GLES2CmdHelper; class GLES2Implementation; @@ -33,7 +34,8 @@ class GLES2Implementation; class GLManager { public: - GLManager(); + GLManager(gles2::MailboxManager* mailbox_manager, + gfx::GLShareGroup* share_group); ~GLManager(); void Initialize(const gfx::Size& size); @@ -45,6 +47,7 @@ class GLManager { void PumpCommands(); bool GetBufferChanged(int32 transfer_buffer_id); + scoped_refptr<gles2::MailboxManager> mailbox_manager_; scoped_refptr<gfx::GLShareGroup> share_group_; scoped_ptr<CommandBufferService> command_buffer_; scoped_ptr<gles2::GLES2Decoder> decoder_; diff --git a/gpu/command_buffer/tests/gl_texture_mailbox_unittests.cc b/gpu/command_buffer/tests/gl_texture_mailbox_unittests.cc new file mode 100644 index 0000000..9f13344 --- /dev/null +++ b/gpu/command_buffer/tests/gl_texture_mailbox_unittests.cc @@ -0,0 +1,172 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef GL_GLEXT_PROTOTYPES +#define GL_GLEXT_PROTOTYPES +#endif + +#include <GLES2/gl2.h> +#include <GLES2/gl2ext.h> + +#include "gpu/command_buffer/service/mailbox_manager.h" +#include "gpu/command_buffer/tests/gl_manager.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/gfx/gl/gl_share_group.h" + +namespace gpu { + +namespace { +uint32 ReadTexel(GLuint id, GLint x, GLint y) { + GLint old_fbo = 0; + glGetIntegerv(GL_FRAMEBUFFER_BINDING, &old_fbo); + + GLuint fbo; + glGenFramebuffers(1, &fbo); + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glFramebufferTexture2D(GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, + id, + 0); + EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE), + glCheckFramebufferStatus(GL_FRAMEBUFFER)); + + uint32 texel; + glReadPixels(x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &texel); + + glBindFramebuffer(GL_FRAMEBUFFER, old_fbo); + + glDeleteFramebuffers(1, &fbo); + + return texel; +} +} + +class GLTextureMailboxTest : public testing::Test { + protected: + GLTextureMailboxTest() { + gles2::MailboxManager* mailbox_manager = new gles2::MailboxManager; + gfx::GLShareGroup* share_group = new gfx::GLShareGroup; + gl1_.reset(new GLManager(mailbox_manager, share_group)); + gl2_.reset(new GLManager(mailbox_manager, share_group)); + } + + virtual void SetUp() { + gl1_->Initialize(gfx::Size(4, 4)); + gl2_->Initialize(gfx::Size(4, 4)); + } + + virtual void TearDown() { + gl1_->Destroy(); + gl2_->Destroy(); + } + + scoped_ptr<GLManager> gl1_; + scoped_ptr<GLManager> gl2_; +}; + +TEST_F(GLTextureMailboxTest, ProduceAndConsumeTexture) { + gl1_->MakeCurrent(); + + GLbyte mailbox1[GL_MAILBOX_SIZE_CHROMIUM]; + glGenMailboxCHROMIUM(mailbox1); + + GLbyte mailbox2[GL_MAILBOX_SIZE_CHROMIUM]; + glGenMailboxCHROMIUM(mailbox2); + + GLuint tex1; + glGenTextures(1, &tex1); + + glBindTexture(GL_TEXTURE_2D, tex1); + uint32 source_pixel = 0xFF0000FF; + glTexImage2D(GL_TEXTURE_2D, + 0, + GL_RGBA, + 1, 1, + 0, + GL_RGBA, + GL_UNSIGNED_BYTE, + &source_pixel); + + glProduceTextureCHROMIUM(GL_TEXTURE_2D, mailbox1); + glFlush(); + + gl2_->MakeCurrent(); + + GLuint tex2; + glGenTextures(1, &tex2); + + glBindTexture(GL_TEXTURE_2D, tex2); + glConsumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox1); + EXPECT_EQ(source_pixel, ReadTexel(tex2, 0, 0)); + glProduceTextureCHROMIUM(GL_TEXTURE_2D, mailbox2); + glFlush(); + + gl1_->MakeCurrent(); + + glBindTexture(GL_TEXTURE_2D, tex1); + glConsumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox2); + EXPECT_EQ(source_pixel, ReadTexel(tex1, 0, 0)); +} + +TEST_F(GLTextureMailboxTest, ProduceTextureValidatesKey) { + GLuint tex; + glGenTextures(1, &tex); + + glBindTexture(GL_TEXTURE_2D, tex); + uint32 source_pixel = 0xFF0000FF; + glTexImage2D(GL_TEXTURE_2D, + 0, + GL_RGBA, + 1, 1, + 0, + GL_RGBA, + GL_UNSIGNED_BYTE, + &source_pixel); + + GLbyte invalid_mailbox[GL_MAILBOX_SIZE_CHROMIUM]; + glGenMailboxCHROMIUM(invalid_mailbox); + ++invalid_mailbox[GL_MAILBOX_SIZE_CHROMIUM - 1]; + + EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); + glProduceTextureCHROMIUM(GL_TEXTURE_2D, invalid_mailbox); + EXPECT_EQ(static_cast<GLenum>(GL_INVALID_OPERATION), glGetError()); + + // Ensure level 0 is still intact after glProduceTextureCHROMIUM fails. + EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); + EXPECT_EQ(source_pixel, ReadTexel(tex, 0, 0)); + EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); +} + +TEST_F(GLTextureMailboxTest, ConsumeTextureValidatesKey) { + GLuint tex; + glGenTextures(1, &tex); + + glBindTexture(GL_TEXTURE_2D, tex); + uint32 source_pixel = 0xFF0000FF; + glTexImage2D(GL_TEXTURE_2D, + 0, + GL_RGBA, + 1, 1, + 0, + GL_RGBA, + GL_UNSIGNED_BYTE, + &source_pixel); + + GLbyte invalid_mailbox[GL_MAILBOX_SIZE_CHROMIUM]; + glGenMailboxCHROMIUM(invalid_mailbox); + ++invalid_mailbox[GL_MAILBOX_SIZE_CHROMIUM - 1]; + + EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); + glConsumeTextureCHROMIUM(GL_TEXTURE_2D, invalid_mailbox); + EXPECT_EQ(static_cast<GLenum>(GL_INVALID_OPERATION), glGetError()); + + // Ensure level 0 is still intact after glConsumeTextureCHROMIUM fails. + EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); + EXPECT_EQ(source_pixel, ReadTexel(tex, 0, 0)); + EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); +} +} // namespace gpu + diff --git a/gpu/command_buffer/tests/gl_unittests.cc b/gpu/command_buffer/tests/gl_unittests.cc index 1a45349..921f5f2f 100644 --- a/gpu/command_buffer/tests/gl_unittests.cc +++ b/gpu/command_buffer/tests/gl_unittests.cc @@ -2,16 +2,26 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#ifndef GL_GLEXT_PROTOTYPES +#define GL_GLEXT_PROTOTYPES +#endif + #include <GLES2/gl2.h> +#include <GLES2/gl2ext.h> +#include "gpu/command_buffer/service/mailbox_manager.h" #include "gpu/command_buffer/tests/gl_manager.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +#include "ui/gfx/gl/gl_share_group.h" namespace gpu { class GLTest : public testing::Test { protected: + GLTest() : gl_(new gles2::MailboxManager, new gfx::GLShareGroup) { + } + virtual void SetUp() { gl_.Initialize(gfx::Size(4, 4)); } diff --git a/gpu/command_buffer_service.gypi b/gpu/command_buffer_service.gypi index a1988ad..d9e0121 100644 --- a/gpu/command_buffer_service.gypi +++ b/gpu/command_buffer_service.gypi @@ -15,6 +15,7 @@ }, 'dependencies': [ '../base/base.gyp:base', + '../crypto/crypto.gyp:crypto', '../ui/gfx/gl/gl.gyp:gl', '../ui/gfx/surface/surface.gyp:surface', '../ui/ui.gyp:ui', @@ -53,6 +54,8 @@ 'command_buffer/service/gpu_switches.cc', 'command_buffer/service/id_manager.h', 'command_buffer/service/id_manager.cc', + 'command_buffer/service/mailbox_manager.cc', + 'command_buffer/service/mailbox_manager.h', 'command_buffer/service/mocks.h', 'command_buffer/service/program_manager.h', 'command_buffer/service/program_manager.cc', @@ -66,6 +69,8 @@ 'command_buffer/service/shader_translator.cc', 'command_buffer/service/stream_texture.h', 'command_buffer/service/stream_texture_manager.h', + 'command_buffer/service/texture_definition.cc', + 'command_buffer/service/texture_definition.h', 'command_buffer/service/texture_manager.h', 'command_buffer/service/texture_manager.cc', 'command_buffer/service/vertex_attrib_manager.h', diff --git a/gpu/gles2_conform_support/egl/display.cc b/gpu/gles2_conform_support/egl/display.cc index bc07fae..54912d2 100644 --- a/gpu/gles2_conform_support/egl/display.cc +++ b/gpu/gles2_conform_support/egl/display.cc @@ -87,7 +87,7 @@ EGLSurface Display::CreateWindowSurface(EGLConfig config, if (!command_buffer->Initialize()) return NULL; - gpu::gles2::ContextGroup::Ref group(new gpu::gles2::ContextGroup(true)); + gpu::gles2::ContextGroup::Ref group(new gpu::gles2::ContextGroup(NULL, true)); decoder_.reset(gpu::gles2::GLES2Decoder::Create(group.get())); if (!decoder_.get()) diff --git a/gpu/gpu_common.gypi b/gpu/gpu_common.gypi index 43646c8..0de1c3e 100644 --- a/gpu/gpu_common.gypi +++ b/gpu/gpu_common.gypi @@ -223,6 +223,7 @@ 'command_buffer/tests/gl_tests_main.cc', 'command_buffer/tests/gl_manager.cc', 'command_buffer/tests/gl_manager.h', + 'command_buffer/tests/gl_texture_mailbox_unittests.cc', 'command_buffer/tests/gl_unittests.cc', ], }, diff --git a/third_party/khronos/GLES2/gl2ext.h b/third_party/khronos/GLES2/gl2ext.h index 8effd30..45943a0 100644 --- a/third_party/khronos/GLES2/gl2ext.h +++ b/third_party/khronos/GLES2/gl2ext.h @@ -1982,6 +1982,26 @@ typedef void (GL_APIENTRYP PFNGLCOPYTEXTURECHROMIUM) (GLenum target, GLenum sour #define GL_COMMANDS_ISSUED_CHROMIUM 0x84F2 #endif +/* GL_CHROMIUM_texture_mailbox */ +#ifndef GL_CHROMIUM_texture_mailbox +#define GL_CHROMIUM_texture_mailbox 1 +#define GL_MAILBOX_SIZE_CHROMIUM 64 +#ifdef GL_GLEXT_PROTOTYPES +#define glGenMailboxCHROMIUM GLES2_GET_FUN(GenMailboxCHROMIUM) +#define glProduceTextureCHROMIUM GLES2_GET_FUN(ProduceTextureCHROMIUM) +#define glConsumeTextureCHROMIUM GLES2_GET_FUN(ConsumeTextureCHROMIUM) +#if !defined(GLES2_USE_CPP_BINDINGS) +GL_APICALL void GL_APIENTRY glGenMailboxCHROMIUM (GLbyte* mailbox); +GL_APICALL void GL_APIENTRY glProduceTextureCHROMIUM (GLenum target, const GLbyte* mailbox); +GL_APICALL void GL_APIENTRY glConsumeTextureCHROMIUM (GLenum target, const GLbyte* mailbox); +#endif +#else +typedef void (GL_APIENTRYP PFNGLGENMAILBOXCHROMIUM) (GLbyte* mailbox); +typedef void (GL_APIENTRYP PFNGLPRODUCETEXTURECHROMIUM) (GLenum target, const GLbyte* mailbox); +typedef void (GL_APIENTRYP PFNGLCONSUMETEXTURECHROMIUM) (GLenum target, const GLbyte* mailbox); +#endif +#endif + #ifdef __cplusplus } #endif diff --git a/webkit/gpu/webgraphicscontext3d_in_process_command_buffer_impl.cc b/webkit/gpu/webgraphicscontext3d_in_process_command_buffer_impl.cc index d9db876..36b7814 100644 --- a/webkit/gpu/webgraphicscontext3d_in_process_command_buffer_impl.cc +++ b/webkit/gpu/webgraphicscontext3d_in_process_command_buffer_impl.cc @@ -399,7 +399,7 @@ bool GLInProcessContext::Initialize(const gfx::Size& size, bool bind_generates_resource = false; decoder_.reset(::gpu::gles2::GLES2Decoder::Create(context_group ? context_group->decoder_->GetContextGroup() : - new ::gpu::gles2::ContextGroup(bind_generates_resource))); + new ::gpu::gles2::ContextGroup(NULL, bind_generates_resource))); gpu_scheduler_.reset(new GpuScheduler(command_buffer_.get(), decoder_.get(), |