diff options
author | apatrick@chromium.org <apatrick@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-05-01 21:50:59 +0000 |
---|---|---|
committer | apatrick@chromium.org <apatrick@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-05-01 21:50:59 +0000 |
commit | 78b514be30c67dad84bb8e2b6dfac3cfb15c79ff (patch) | |
tree | dd7d62dafa82bd6fbe087fb6f4de8148939c34ee | |
parent | 107d6e00cece1fb1545f5403193576f822e93a09 (diff) | |
download | chromium_src-78b514be30c67dad84bb8e2b6dfac3cfb15c79ff.zip chromium_src-78b514be30c67dad84bb8e2b6dfac3cfb15c79ff.tar.gz chromium_src-78b514be30c67dad84bb8e2b6dfac3cfb15c79ff.tar.bz2 |
Allow textures to be moved from one GL context group to another.
The function glProduceTexture(target, mailbox) removes a texture from a context group and puts it in a "mailbox" that is accessible to all context groups on the same channel.
Then glConsumeTexture(target, mailbox) adds the texture to a context group, possibly a different one, if the caller knows the name of the mailbox.
From the point of view of the caller, the texture objects themselves do not move, just the texels. In terms of the underlying GL, the TextureInfo service IDs are reassigned as necessary.
A texture in a mailbox is destroyed when the context group that put it there is destroyed.
Expected usage is:
// Context 1
glBindTexture(GL_TEXTURE_2D, foo);
glProduceTexture(GL_TEXTURE_2D, secret_name);
glFlush();
// Context 2
glBindTexture(GL_TEXTURE_2D, bar);
glConsumeTexture(GL_TEXTURE_2D, secret_name);
Review URL: http://codereview.chromium.org/10106015
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@134791 0039d316-1c4b-4281-b951-d872f2087c98
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(), |