diff options
author | jamesr@chromium.org <jamesr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-08-28 00:48:56 +0000 |
---|---|---|
committer | jamesr@chromium.org <jamesr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-08-28 00:48:56 +0000 |
commit | a3a93e7bbb8275069f319e0807c43f7395502abf (patch) | |
tree | f5424f889285ff09f930ffc30ed16c0203ad1827 /gpu | |
parent | 9117fb714da99c44319cc8e56909d0a48bf7da02 (diff) | |
download | chromium_src-a3a93e7bbb8275069f319e0807c43f7395502abf.zip chromium_src-a3a93e7bbb8275069f319e0807c43f7395502abf.tar.gz chromium_src-a3a93e7bbb8275069f319e0807c43f7395502abf.tar.bz2 |
Add way to create a texture in parent's context and copy into it
For canvas we need a way to create multiple offscreen render targets within
the same OpenGL context and expose them all to the compositor, which exists
as a parent context. ggl currently provides a single framebuffer and texture
pair per offscreen context and implements swapBuffers() to copy to the parent
texture. This generalizes that to let clients create as many parent textures
as necessary and do the equivalent of swapBuffers() for each without the
service side needing to keep track of the mapping.
We'll want to change this in the future when we start using glBlitFramebuffer
to support multisampling. I think in that world we'll need a way to bind a
texture in the parent's context to the DRAW_FRAMEBUFFER context. For now,
I think this is OK.
TEST=open a page with multiple accelerated canvases in a shared context
BUG=52684
Review URL: http://codereview.chromium.org/3211005
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@57761 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'gpu')
12 files changed, 145 insertions, 0 deletions
diff --git a/gpu/GLES2/gl2ext.h b/gpu/GLES2/gl2ext.h index cae6500..35ac011 100644 --- a/gpu/GLES2/gl2ext.h +++ b/gpu/GLES2/gl2ext.h @@ -896,6 +896,20 @@ typedef void* (GL_APIENTRYP PFNGLMAPTEXSUBIMAGE2D) (GLenum target, GLint level, typedef void (GL_APIENTRYP PFNGLUNMAPTEXSUBIMAGE2D) (const void* mem); #endif +/* GL_CHROMIUM_copy_texture_to_parent_texture */ +#ifndef GL_CHROMIUM_copy_texture_to_parent_texture +#define GL_CHROMIUM_copy_texture_to_parent_texture 1 +#ifdef GL_GLEXT_PROTOTYPES +#define glCopyTextureToParentTexture GLES2_GET_FUN(CopyTextureToParentTexture) +#if !defined(GLES2_USE_CPP_BINDINGS) +GL_APICALL void* GL_APIENTRY glCopyTextureToParentTexture (GLuint id, GLuint id2); +#endif +#else +typedef void* (GL_APIENTRYP PFNGLCOPYTEXTURETOPARENTTEXTURE) (GLuint id, GLuint id2); +#endif +#endif + + #ifdef __cplusplus } #endif diff --git a/gpu/command_buffer/build_gles2_cmd_buffer.py b/gpu/command_buffer/build_gles2_cmd_buffer.py index 59ed349..4381fdc 100755 --- a/gpu/command_buffer/build_gles2_cmd_buffer.py +++ b/gpu/command_buffer/build_gles2_cmd_buffer.py @@ -188,6 +188,7 @@ GL_APICALL void* GL_APIENTRY glMapBufferSubData (GLuint target, GLintptr GL_APICALL void GL_APIENTRY glUnmapBufferSubData (const void* mem); GL_APICALL void* GL_APIENTRY glMapTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLenum access); GL_APICALL void GL_APIENTRY glUnmapTexSubImage2D (const void* mem); +GL_APICALL void GL_APIENTRY glCopyTextureToParentTexture (GLidBindTexture client_child_id, GLidBindTexture client_parent_id); """ # This is the list of all commmands that will be generated and their Id. @@ -387,6 +388,7 @@ _CMD_ID_TABLE = { 'CompressedTexSubImage2DBucket': 444, 'RenderbufferStorageMultisampleEXT': 445, 'BlitFramebufferEXT': 446, + 'CopyTextureToParentTexture': 447, } # This is a list of enum names and their valid values. It is used to map @@ -1520,6 +1522,10 @@ _FUNCTION_INFO = { 'cmd_args': 'GLuint indx, GLint size, GLenum type, GLboolean normalized, ' 'GLsizei stride, GLuint offset', }, + 'CopyTextureToParentTexture': { + 'decoder_func': 'DoCopyTextureToParentTexture', + 'unit_test': False + }, } diff --git a/gpu/command_buffer/client/gles2_c_lib_autogen.h b/gpu/command_buffer/client/gles2_c_lib_autogen.h index 0aca957..fd11206 100644 --- a/gpu/command_buffer/client/gles2_c_lib_autogen.h +++ b/gpu/command_buffer/client/gles2_c_lib_autogen.h @@ -550,6 +550,11 @@ void* GLES2MapTexSubImage2D( void GLES2UnmapTexSubImage2D(const void* mem) { gles2::GetGLContext()->UnmapTexSubImage2D(mem); } +void GLES2CopyTextureToParentTexture( + GLuint client_child_id, GLuint client_parent_id) { + gles2::GetGLContext()->CopyTextureToParentTexture( + client_child_id, client_parent_id); +} #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 0815df3..dde9b69 100644 --- a/gpu/command_buffer/client/gles2_cmd_helper_autogen.h +++ b/gpu/command_buffer/client/gles2_cmd_helper_autogen.h @@ -1186,5 +1186,12 @@ c.Init(bucket_id, result_shm_id, result_shm_offset); } + void CopyTextureToParentTexture( + GLuint client_child_id, GLuint client_parent_id) { + gles2::CopyTextureToParentTexture& c = + GetCmdSpace<gles2::CopyTextureToParentTexture>(); + c.Init(client_child_id, client_parent_id); + } + #endif // GPU_COMMAND_BUFFER_CLIENT_GLES2_CMD_HELPER_AUTOGEN_H_ diff --git a/gpu/command_buffer/client/gles2_implementation_autogen.h b/gpu/command_buffer/client/gles2_implementation_autogen.h index 872bcf63..f3fad49 100644 --- a/gpu/command_buffer/client/gles2_implementation_autogen.h +++ b/gpu/command_buffer/client/gles2_implementation_autogen.h @@ -832,5 +832,10 @@ void* MapTexSubImage2D( void UnmapTexSubImage2D(const void* mem); +void CopyTextureToParentTexture( + GLuint client_child_id, GLuint client_parent_id) { + helper_->CopyTextureToParentTexture(client_child_id, client_parent_id); +} + #endif // GPU_COMMAND_BUFFER_CLIENT_GLES2_IMPLEMENTATION_AUTOGEN_H_ diff --git a/gpu/command_buffer/common/gles2_cmd_format_autogen.h b/gpu/command_buffer/common/gles2_cmd_format_autogen.h index badcffa..2b16bea 100644 --- a/gpu/command_buffer/common/gles2_cmd_format_autogen.h +++ b/gpu/command_buffer/common/gles2_cmd_format_autogen.h @@ -8755,6 +8755,44 @@ COMPILE_ASSERT(offsetof(CommandBufferEnable, result_shm_id) == 8, COMPILE_ASSERT(offsetof(CommandBufferEnable, result_shm_offset) == 12, OffsetOf_CommandBufferEnable_result_shm_offset_not_12); +struct CopyTextureToParentTexture { + typedef CopyTextureToParentTexture ValueType; + static const CommandId kCmdId = kCopyTextureToParentTexture; + static const cmd::ArgFlags kArgFlags = cmd::kFixed; + + static uint32 ComputeSize() { + return static_cast<uint32>(sizeof(ValueType)); // NOLINT + } + + void SetHeader() { + header.SetCmd<ValueType>(); + } + + void Init(GLuint _client_child_id, GLuint _client_parent_id) { + SetHeader(); + client_child_id = _client_child_id; + client_parent_id = _client_parent_id; + } + + void* Set(void* cmd, GLuint _client_child_id, GLuint _client_parent_id) { + static_cast<ValueType*>(cmd)->Init(_client_child_id, _client_parent_id); + return NextCmdAddress<ValueType>(cmd); + } + + gpu::CommandHeader header; + uint32 client_child_id; + uint32 client_parent_id; +}; + +COMPILE_ASSERT(sizeof(CopyTextureToParentTexture) == 12, + Sizeof_CopyTextureToParentTexture_is_not_12); +COMPILE_ASSERT(offsetof(CopyTextureToParentTexture, header) == 0, + OffsetOf_CopyTextureToParentTexture_header_not_0); +COMPILE_ASSERT(offsetof(CopyTextureToParentTexture, client_child_id) == 4, + OffsetOf_CopyTextureToParentTexture_client_child_id_not_4); +COMPILE_ASSERT(offsetof(CopyTextureToParentTexture, client_parent_id) == 8, + OffsetOf_CopyTextureToParentTexture_client_parent_id_not_8); + #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 177b084..06e701e 100644 --- a/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h +++ b/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h @@ -3450,5 +3450,20 @@ TEST(GLES2FormatTest, CommandBufferEnable) { EXPECT_EQ(static_cast<uint32>(13), cmd.result_shm_offset); } +TEST(GLES2FormatTest, CopyTextureToParentTexture) { + CopyTextureToParentTexture cmd = { { 0 } }; + void* next_cmd = cmd.Set( + &cmd, + static_cast<GLuint>(11), + static_cast<GLuint>(12)); + EXPECT_EQ(static_cast<uint32>(CopyTextureToParentTexture::kCmdId), + cmd.header.command); + EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u); + EXPECT_EQ(static_cast<char*>(next_cmd), + reinterpret_cast<char*>(&cmd) + sizeof(cmd)); + EXPECT_EQ(static_cast<GLuint>(11), cmd.client_child_id); + EXPECT_EQ(static_cast<GLuint>(12), cmd.client_parent_id); +} + #endif // GPU_COMMAND_BUFFER_COMMON_GLES2_CMD_FORMAT_TEST_AUTOGEN_H_ diff --git a/gpu/command_buffer/common/gles2_cmd_id_test_autogen.h b/gpu/command_buffer/common/gles2_cmd_id_test_autogen.h index 7fc268d..e0f1544 100644 --- a/gpu/command_buffer/common/gles2_cmd_id_test_autogen.h +++ b/gpu/command_buffer/common/gles2_cmd_id_test_autogen.h @@ -393,6 +393,8 @@ TEST(GLES2CommandIdTest, CommandIdsMatch) { GLES2_RegisterSharedIds_kCmdId_mismatch); COMPILE_ASSERT(CommandBufferEnable::kCmdId == 442, GLES2_CommandBufferEnable_kCmdId_mismatch); + COMPILE_ASSERT(CopyTextureToParentTexture::kCmdId == 447, + GLES2_CopyTextureToParentTexture_kCmdId_mismatch); } #endif // GPU_COMMAND_BUFFER_COMMON_GLES2_CMD_ID_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 f9ae357..466bf4a 100644 --- a/gpu/command_buffer/common/gles2_cmd_ids_autogen.h +++ b/gpu/command_buffer/common/gles2_cmd_ids_autogen.h @@ -199,6 +199,7 @@ OP(CompressedTexSubImage2DBucket) /* 444 */ \ OP(RenderbufferStorageMultisampleEXT) /* 445 */ \ OP(BlitFramebufferEXT) /* 446 */ \ + OP(CopyTextureToParentTexture) /* 447 */ \ enum CommandId { kStartPoint = cmd::kLastCommonId, // All GLES2 commands start after this. diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc index 7d7a364..092b5d1 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc @@ -1057,6 +1057,8 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>, // Wrapper for glValidateProgram. void DoValidateProgram(GLuint program_client_id); + void DoCopyTextureToParentTexture(GLuint client_texture_id, GLuint parent_client_texture_id); + // Gets the number of values that will be returned by glGetXXX. Returns // false if pname is unknown. bool GetNumValuesReturnedForGLGet(GLenum pname, GLsizei* num_values); @@ -1259,6 +1261,8 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>, scoped_ptr<RenderBuffer> offscreen_target_depth_render_buffer_; scoped_ptr<RenderBuffer> offscreen_target_stencil_render_buffer_; + GLuint copy_texture_to_parent_texture_fb_; + // The copy that is saved when SwapBuffers is called. scoped_ptr<Texture> offscreen_saved_color_texture_; @@ -1267,6 +1271,9 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>, // The last error message set. std::string last_error_; + // The current decoder error. + error::Error current_decoder_error_; + bool use_shader_translator_; ShHandle vertex_compiler_; ShHandle fragment_compiler_; @@ -1529,6 +1536,7 @@ GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group) mask_depth_(true), enable_scissor_test_(false), anti_aliased_(false), + current_decoder_error_(error::kNoError), use_shader_translator_(true), vertex_compiler_(NULL), fragment_compiler_(NULL), @@ -1656,6 +1664,8 @@ bool GLES2DecoderImpl::Initialize(gfx::GLContext* context, // Bind to the new default frame buffer (the offscreen target frame buffer). // This should now be associated with ID zero. DoBindFramebuffer(GL_FRAMEBUFFER, 0); + + glGenFramebuffersEXT(1, ©_texture_to_parent_texture_fb_); } // OpenGL ES 2.0 implicitly enables the desktop GL capability @@ -2108,6 +2118,8 @@ void GLES2DecoderImpl::Destroy() { if (parent_->texture_manager()->GetClientId(service_id, &client_id)) { parent_->texture_manager()->RemoveTextureInfo(client_id); } + + glDeleteFramebuffersEXT(1, ©_texture_to_parent_texture_fb_); } if (offscreen_target_frame_buffer_.get()) { @@ -2152,6 +2164,33 @@ void GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size& size) { pending_offscreen_size_ = size; } +void GLES2DecoderImpl::DoCopyTextureToParentTexture(GLuint client_texture_id, GLuint parent_client_texture_id) { + if (parent_) { + TextureManager::TextureInfo* texture = texture_manager()->GetTextureInfo(client_texture_id); + TextureManager::TextureInfo* parent_texture = parent_->texture_manager()->GetTextureInfo(parent_client_texture_id); + if (!texture || !parent_texture) { + current_decoder_error_ = error::kInvalidArguments; + return; + } + ScopedFrameBufferBinder fb_binder(this, copy_texture_to_parent_texture_fb_); + glFramebufferTexture2DEXT(GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, + texture->service_id(), + 0); + ScopedTexture2DBinder tex_binder(this, parent_texture->service_id()); + GLsizei width, height; + parent_texture->GetLevelSize(GL_TEXTURE_2D, 0, &width, &height); + glCopyTexImage2D(GL_TEXTURE_2D, + 0, // level + GL_RGBA, + 0, 0, // x, y + width, + height, + 0); // border + } +} + const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id) const { if (command_id > kStartPoint && command_id < kNumCommands) { return gles2::GetCommandName(static_cast<CommandId>(command_id)); @@ -2206,6 +2245,10 @@ error::Error GLES2DecoderImpl::DoCommand( } else { result = DoCommonCommand(command, arg_count, cmd_data); } + if (result == error::kNoError && current_decoder_error_ != error::kNoError) { + result = current_decoder_error_; + current_decoder_error_ = error::kNoError; + } return result; } diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h index 7e15253..474147e 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h @@ -2814,5 +2814,13 @@ error::Error GLES2DecoderImpl::HandleGetMaxValueInBuffer( return error::kNoError; } +error::Error GLES2DecoderImpl::HandleCopyTextureToParentTexture( + uint32 immediate_data_size, const gles2::CopyTextureToParentTexture& c) { + GLuint client_child_id = c.client_child_id; + GLuint client_parent_id = c.client_parent_id; + DoCopyTextureToParentTexture(client_child_id, client_parent_id); + return error::kNoError; +} + #endif // GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_AUTOGEN_H_ diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.h index 0b6aee3..d970703 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.h @@ -1611,5 +1611,6 @@ TEST_F(GLES2DecoderTest2, ViewportInvalidArgs3_0) { // TODO(gman): CommandBufferEnable +// TODO(gman): CopyTextureToParentTexture #endif // GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_UNITTEST_2_AUTOGEN_H_ |