diff options
author | apatrick@chromium.org <apatrick@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-07-29 20:02:01 +0000 |
---|---|---|
committer | apatrick@chromium.org <apatrick@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-07-29 20:02:01 +0000 |
commit | de472286527828640709fe3dfcfb48d074e63098 (patch) | |
tree | 4873318953ce9b06f7e3742430f865df70893267 /gpu/command_buffer/service | |
parent | cf0a77e1e18f547316c8da0a55c3ddeedae18263 (diff) | |
download | chromium_src-de472286527828640709fe3dfcfb48d074e63098.zip chromium_src-de472286527828640709fe3dfcfb48d074e63098.tar.gz chromium_src-de472286527828640709fe3dfcfb48d074e63098.tar.bz2 |
Allow the renderer process to map textures from one context into another.
This is on an individual resource basis rather than general share groups in order to hide be able to hide the full namespace from untrusted plugins.
Accelerated 2D canvas now no longer needs to copy its backing store on every page composite and the redundant backing texture is not needed, saving video memory.
Unit tests for the GPU service to follow.
Patch to delete copyTextureToParentTexture extensions from gpu/ to follow.
BUG=90714
Review URL: http://codereview.chromium.org/7529015
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@94743 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'gpu/command_buffer/service')
-rw-r--r-- | gpu/command_buffer/service/gles2_cmd_decoder.cc | 50 | ||||
-rw-r--r-- | gpu/command_buffer/service/gles2_cmd_decoder.h | 21 | ||||
-rw-r--r-- | gpu/command_buffer/service/gles2_cmd_decoder_mock.h | 5 | ||||
-rw-r--r-- | gpu/command_buffer/service/gpu_scheduler.cc | 12 | ||||
-rw-r--r-- | gpu/command_buffer/service/gpu_scheduler.h | 6 | ||||
-rw-r--r-- | gpu/command_buffer/service/texture_manager.cc | 31 | ||||
-rw-r--r-- | gpu/command_buffer/service/texture_manager.h | 26 | ||||
-rw-r--r-- | gpu/command_buffer/service/texture_manager_unittest.cc | 22 |
8 files changed, 125 insertions, 48 deletions
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc index ed6e000..f0162d6 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc @@ -465,6 +465,10 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>, const char* allowed_extensions, const std::vector<int32>& attribs); virtual void Destroy(); + virtual bool MapExternalResource(resource_type::ResourceType resource_type, + uint32 resource_source_id, + GLES2Decoder* source_decoder, + uint32 resource_dest_id); virtual bool SetParent(GLES2Decoder* parent_decoder, uint32 parent_texture_id); virtual void ResizeOffscreenFrameBuffer(const gfx::Size& size); @@ -588,6 +592,11 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>, return (info && !info->IsDeleted()) ? info : NULL; } + // Adds the texture info for the given texture. + void AddTextureInfo(GLuint client_id, TextureManager::TextureInfo* info) { + texture_manager()->AddTextureInfo(feature_info_, client_id, info); + } + // Deletes the texture info for the given texture. void RemoveTextureInfo(GLuint client_id) { texture_manager()->RemoveTextureInfo(feature_info_, client_id); @@ -2089,8 +2098,10 @@ void GLES2DecoderImpl::DeleteTexturesHelper( if (info->IsAttachedToFramebuffer()) { state_dirty_ = true; } - GLuint service_id = info->service_id(); - glDeleteTextures(1, &service_id); + if (info->owner() == group_->texture_manager()) { + GLuint service_id = info->service_id(); + glDeleteTextures(1, &service_id); + } RemoveTextureInfo(client_ids[ii]); } } @@ -2470,6 +2481,37 @@ void GLES2DecoderImpl::Destroy() { offscreen_saved_color_texture_.reset(); } +bool GLES2DecoderImpl::MapExternalResource( + resource_type::ResourceType resource_type, + uint32 resource_source_id, + GLES2Decoder* source_decoder, + uint32 resource_dest_id) { + GLES2DecoderImpl* source_decoder_impl = static_cast<GLES2DecoderImpl*>( + source_decoder); + + if (resource_type != resource_type::kTexture) + return false; + + if (!source_decoder) + return false; + + // The client should already have created the texture in the source context + // group and flushed. + TextureManager::TextureInfo* source_info = + source_decoder_impl->GetTextureInfo(resource_source_id); + if (!source_info) + return false; + + // Delete or unmap any existing texture with this ID. + DeleteTexturesHelper(1, &resource_dest_id); + + // Add the source texture info to this group's manager with the + // requested id. + AddTextureInfo(resource_dest_id, source_info); + + return true; +} + bool GLES2DecoderImpl::SetParent(GLES2Decoder* new_parent, uint32 new_parent_texture_id) { if (!offscreen_saved_color_texture_.get()) @@ -2502,8 +2544,8 @@ bool GLES2DecoderImpl::SetParent(GLES2Decoder* new_parent, feature_info_, new_parent_texture_id); TextureManager::TextureInfo* info = - new_parent_impl->CreateTextureInfo(new_parent_texture_id, service_id); - info->SetNotOwned(); + new TextureManager::TextureInfo(service_id); + new_parent_impl->AddTextureInfo(new_parent_texture_id, info); new_parent_impl->texture_manager()->SetInfoTarget(info, GL_TEXTURE_2D); parent_ = new_parent_impl->AsWeakPtr(); diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.h b/gpu/command_buffer/service/gles2_cmd_decoder.h index 23c5e3a..76cd15b 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder.h @@ -12,6 +12,7 @@ #include "base/callback.h" #include "base/callback_old.h" #include "build/build_config.h" +#include "gpu/command_buffer/common/constants.h" #include "gpu/command_buffer/service/common_decoder.h" #include "ui/gfx/size.h" @@ -77,6 +78,26 @@ class GLES2Decoder : public CommonDecoder { // Destroys the graphics context. virtual void Destroy() = 0; + // Map a resource from an external context into this context. The source + // context need not be in the same share group from the client's point of + // view, allowing safe sharing between an "untrusted" context, like Pepper + // and a compositor context. + // + // Currently only texture resources are supported. TODO(apatrick): generalize + // this as appropriate. + // + // To unmap a previously mapped external resource, delete it in the + // destination context group. This will not delete the underlying texture + // object, just disassociate it with the id in the destination context group. + // + // The lifetime of the external resource is managed by the context group it + // was originally created in. When the last context in that group is destroyed + // the resource becomes invalid in all other context groups it is mapped into. + virtual bool MapExternalResource(resource_type::ResourceType resource_type, + uint32 resource_source_id, + GLES2Decoder* source_decoder, + uint32 resource_dest_id) = 0; + virtual bool SetParent(GLES2Decoder* parent_decoder, uint32 parent_texture_id) = 0; diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_mock.h b/gpu/command_buffer/service/gles2_cmd_decoder_mock.h index 13e60bb..fe1d6cf 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_mock.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_mock.h @@ -37,6 +37,11 @@ class MockGLES2Decoder : public GLES2Decoder { const char* allowed_extensions, const std::vector<int32>& attribs)); MOCK_METHOD0(Destroy, void()); + MOCK_METHOD4(MapExternalResource, + bool(resource_type::ResourceType resource_type, + uint32 resource_source_id, + GLES2Decoder* source_decoder, + uint32 resource_dest_id)); MOCK_METHOD2(SetParent, bool(GLES2Decoder* parent, uint32 parent_texture_id)); MOCK_METHOD1(ResizeOffscreenFrameBuffer, void(const gfx::Size& size)); MOCK_METHOD0(UpdateOffscreenFrameBufferSize, bool()); diff --git a/gpu/command_buffer/service/gpu_scheduler.cc b/gpu/command_buffer/service/gpu_scheduler.cc index 15316ea..35cefa1 100644 --- a/gpu/command_buffer/service/gpu_scheduler.cc +++ b/gpu/command_buffer/service/gpu_scheduler.cc @@ -129,6 +129,18 @@ bool GpuScheduler::SetParent(GpuScheduler* parent_scheduler, return decoder_->SetParent(NULL, 0); } +bool GpuScheduler::MapExternalResource( + resource_type::ResourceType resource_type, + uint32 resource_source_id, + GpuScheduler* source_scheduler, + uint32 resource_dest_id) { + return decoder_->MapExternalResource( + resource_type, + resource_source_id, + source_scheduler ? source_scheduler->decoder_.get() : NULL, + resource_dest_id); +} + #if defined(OS_MACOSX) namespace { const unsigned int kMaxOutstandingSwapBuffersCallsPerOnscreenContext = 1; diff --git a/gpu/command_buffer/service/gpu_scheduler.h b/gpu/command_buffer/service/gpu_scheduler.h index 75ccc63..04b6f3b 100644 --- a/gpu/command_buffer/service/gpu_scheduler.h +++ b/gpu/command_buffer/service/gpu_scheduler.h @@ -15,6 +15,7 @@ #include "base/shared_memory.h" #include "base/task.h" #include "gpu/command_buffer/common/command_buffer.h" +#include "gpu/command_buffer/common/constants.h" #include "gpu/command_buffer/service/cmd_buffer_engine.h" #include "gpu/command_buffer/service/cmd_parser.h" #include "gpu/command_buffer/service/gles2_cmd_decoder.h" @@ -75,6 +76,11 @@ class GpuScheduler : public CommandBufferEngine { void Destroy(); void DestroyCommon(); + bool MapExternalResource(resource_type::ResourceType resource_type, + uint32 resource_source_id, + GpuScheduler* source_scheduler, + uint32 resource_dest_id); + bool SetParent(GpuScheduler* parent_scheduler, uint32 parent_texture_id); void PutChanged(); diff --git a/gpu/command_buffer/service/texture_manager.cc b/gpu/command_buffer/service/texture_manager.cc index c37f375..4406b48 100644 --- a/gpu/command_buffer/service/texture_manager.cc +++ b/gpu/command_buffer/service/texture_manager.cc @@ -68,7 +68,7 @@ void TextureManager::Destroy(bool have_context) { while (!texture_infos_.empty()) { if (have_context) { TextureInfo* info = texture_infos_.begin()->second; - if (!info->IsDeleted() && info->owned_) { + if (!info->IsDeleted() && info->owner_.get() == this) { GLuint service_id = info->service_id(); glDeleteTextures(1, &service_id); info->MarkAsDeleted(); @@ -556,14 +556,10 @@ bool TextureManager::MarkMipmapsGenerated( TextureManager::TextureInfo* TextureManager::CreateTextureInfo( const FeatureInfo* feature_info, GLuint client_id, GLuint service_id) { - TextureInfo::Ref info(new TextureInfo(service_id)); - std::pair<TextureInfoMap::iterator, bool> result = - texture_infos_.insert(std::make_pair(client_id, info)); - DCHECK(result.second); - if (!info->CanRender(feature_info)) { - ++num_unrenderable_textures_; - } - return info.get(); + TextureInfo* texture_info = new TextureInfo(service_id); + texture_info->owner_ = AsWeakPtr(); + AddTextureInfo(feature_info, client_id, texture_info); + return texture_info; } TextureManager::TextureInfo* TextureManager::GetTextureInfo( @@ -572,15 +568,26 @@ TextureManager::TextureInfo* TextureManager::GetTextureInfo( return it != texture_infos_.end() ? it->second : NULL; } +void TextureManager::AddTextureInfo( + const FeatureInfo* feature_info, + GLuint client_id, TextureInfo* texture_info) { + std::pair<TextureInfoMap::iterator, bool> result = + texture_infos_.insert(std::make_pair(client_id, texture_info)); + DCHECK(result.second); + if (!texture_info->CanRender(feature_info)) { + ++num_unrenderable_textures_; + } +} + void TextureManager::RemoveTextureInfo( const FeatureInfo* feature_info, GLuint client_id) { TextureInfoMap::iterator it = texture_infos_.find(client_id); if (it != texture_infos_.end()) { TextureInfo* info = it->second; - if (!info->CanRender(feature_info)) { + if (!info->CanRender(feature_info)) --num_unrenderable_textures_; - } - info->MarkAsDeleted(); + if (info->owner_.get() == this) + info->MarkAsDeleted(); texture_infos_.erase(it); } } diff --git a/gpu/command_buffer/service/texture_manager.h b/gpu/command_buffer/service/texture_manager.h index b4e9626..94b4937 100644 --- a/gpu/command_buffer/service/texture_manager.h +++ b/gpu/command_buffer/service/texture_manager.h @@ -10,6 +10,7 @@ #include "base/hash_tables.h" #include "base/logging.h" #include "base/memory/ref_counted.h" +#include "base/memory/weak_ptr.h" #include "gpu/command_buffer/service/gl_utils.h" namespace gpu { @@ -22,7 +23,7 @@ class FeatureInfo; // // NOTE: To support shared resources an instance of this class will need to be // shared by multiple GLES2Decoders. -class TextureManager { +class TextureManager : public base::SupportsWeakPtr<TextureManager> { public: // Info about Textures currently in the system. class TextureInfo : public base::RefCounted<TextureInfo> { @@ -42,8 +43,7 @@ class TextureManager { cube_complete_(false), npot_(false), has_been_bound_(false), - framebuffer_attachment_count_(0), - owned_(true) { + framebuffer_attachment_count_(0) { } GLenum min_filter() const { @@ -96,6 +96,10 @@ class TextureManager { return npot_; } + TextureManager* owner() const { + return owner_.get(); + } + // Returns true if mipmaps can be generated by GL. bool CanGenerateMipmaps(const FeatureInfo* feature_info) const; @@ -128,10 +132,6 @@ class TextureManager { return target() && !IsDeleted(); } - void SetNotOwned() { - owned_ = false; - } - bool IsAttachedToFramebuffer() const { return framebuffer_attachment_count_ != 0; } @@ -250,9 +250,9 @@ class TextureManager { // The number of framebuffers this texture is attached to. int framebuffer_attachment_count_; - // Whether the associated context group owns this texture and should delete - // it. - bool owned_; + // The framebuffer manager that controls the lifetime of this framebuffer + // or NULL if it has been deleted. + base::WeakPtr<TextureManager> owner_; DISALLOW_COPY_AND_ASSIGN(TextureInfo); }; @@ -338,6 +338,12 @@ class TextureManager { // Gets the texture info for the given texture. TextureInfo* GetTextureInfo(GLuint client_id); + // Adds a texture info for a texture owned by another texture + // manager. + void AddTextureInfo(const FeatureInfo* feature_info, + GLuint client_id, + TextureInfo* info); + // Removes a texture info. void RemoveTextureInfo(const FeatureInfo* feature_info, GLuint client_id); diff --git a/gpu/command_buffer/service/texture_manager_unittest.cc b/gpu/command_buffer/service/texture_manager_unittest.cc index 356453d..6757e9d 100644 --- a/gpu/command_buffer/service/texture_manager_unittest.cc +++ b/gpu/command_buffer/service/texture_manager_unittest.cc @@ -153,28 +153,6 @@ TEST_F(TextureManagerTest, Destroy) { ASSERT_TRUE(info1 == NULL); } -TEST_F(TextureManagerTest, DestroyUnowned) { - const GLuint kClient1Id = 1; - const GLuint kService1Id = 11; - EXPECT_FALSE(manager_.HaveUnrenderableTextures()); - // Check we can create texture. - TextureManager::TextureInfo* created_info = - manager_.CreateTextureInfo(&feature_info_, kClient1Id, kService1Id); - created_info->SetNotOwned(); - - // Check texture got created. - TextureManager::TextureInfo* info1 = manager_.GetTextureInfo(kClient1Id); - ASSERT_TRUE(info1 != NULL); - EXPECT_CALL(*gl_, DeleteTextures(4, _)) - .Times(1) - .RetiresOnSaturation(); - - // Check that it is not freed if it is not owned. - manager_.Destroy(true); - info1 = manager_.GetTextureInfo(kClient1Id); - ASSERT_TRUE(info1 == NULL); -} - TEST_F(TextureManagerTest, MaxValues) { // Check we get the right values for the max sizes. EXPECT_EQ(kMax2dLevels, manager_.MaxLevelsForTarget(GL_TEXTURE_2D)); |