Chromium Code Reviews| Index: gpu/command_buffer/service/gles2_cmd_decoder.cc |
| diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc |
| index c9e8470b6cca2e031b61a22bbd12e737b48a5c55..a929aa00cd22875858e0e116632b2f76919ba5fe 100644 |
| --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc |
| +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc |
| @@ -593,7 +593,10 @@ class GLES2DecoderImpl : public GLES2Decoder, public ErrorStateClient { |
| const std::vector<int32_t>& attribs) override; |
| void Destroy(bool have_context) override; |
| void SetSurface(const scoped_refptr<gfx::GLSurface>& surface) override; |
| - void ProduceFrontBuffer(const Mailbox& mailbox) override; |
| + void ReleaseSurface() override; |
| + void TakeFrontBuffer(const Mailbox& mailbox) override; |
| + void ReturnFrontBuffer(const Mailbox& mailbox, |
| + bool is_lost) override; |
| bool ResizeOffscreenFrameBuffer(const gfx::Size& size) override; |
| void UpdateParentTextureInfo(); |
| bool MakeCurrent() override; |
| @@ -1994,6 +1997,33 @@ class GLES2DecoderImpl : public GLES2Decoder, public ErrorStateClient { |
| scoped_refptr<TextureRef> |
| offscreen_saved_color_texture_info_; |
| + // When a client requests ownership of the swapped front buffer, all |
| + // information is saved in this structure, and |in_use| is set to true. When a |
| + // client releases ownership, |in_use| is set to false. |
| + // |
| + // An instance of this struct, with |in_use| = false may be reused instead of |
| + // making a new BackTexture. |
| + struct SavedBackTexture { |
| + std::unique_ptr<BackTexture> back_texture; |
| + scoped_refptr<TextureRef> texture_ref; |
| + bool in_use; |
| + }; |
| + std::vector<SavedBackTexture> saved_back_textures_; |
| + |
| + // If there's a SavedBackTexture that's not in use, takes that. Otherwise, |
| + // generates a new back texture. |
| + void CreateBackTexture(); |
| + size_t create_back_texture_count_for_test_ = 0; |
| + |
| + // Releases all saved BackTextures that are not in use by a client. |
| + void ReleaseNotInUseBackTextures(); |
| + |
| + // Releases all saved BackTextures. |
| + void ReleaseAllBackTextures(); |
| + |
| + size_t GetSavedBackTextureCountForTest() override; |
| + size_t GetCreatedBackTextureCountForTest() override; |
| + |
| // The copy that is used as the destination for multi-sample resolves. |
| std::unique_ptr<BackFramebuffer> offscreen_resolved_frame_buffer_; |
| std::unique_ptr<BackTexture> offscreen_resolved_color_texture_; |
| @@ -4067,6 +4097,7 @@ void GLES2DecoderImpl::Destroy(bool have_context) { |
| offscreen_saved_color_texture_->Invalidate(); |
| offscreen_saved_color_texture_info_ = NULL; |
| } |
| + ReleaseAllBackTextures(); |
| if (have_context) { |
| if (copy_texture_CHROMIUM_.get()) { |
| copy_texture_CHROMIUM_->Destroy(); |
| @@ -4205,11 +4236,23 @@ void GLES2DecoderImpl::SetSurface( |
| RestoreCurrentFramebufferBindings(); |
| } |
| -void GLES2DecoderImpl::ProduceFrontBuffer(const Mailbox& mailbox) { |
| +void GLES2DecoderImpl::ReleaseSurface() { |
| + if (!context_.get()) |
| + return; |
| + if (WasContextLost()) { |
| + DLOG(ERROR) << " GLES2DecoderImpl: Trying to release lost context."; |
| + return; |
| + } |
| + context_->ReleaseCurrent(surface_.get()); |
| + surface_ = nullptr; |
| +} |
| + |
| +void GLES2DecoderImpl::TakeFrontBuffer(const Mailbox& mailbox) { |
| if (!offscreen_saved_color_texture_.get()) { |
| - LOG(ERROR) << "Called ProduceFrontBuffer on a non-offscreen context"; |
| + LOG(ERROR) << "Called TakeFrontBuffer on a non-offscreen context"; |
|
piman
2016/04/26 01:54:01
nit: DLOG
erikchen
2016/04/27 16:31:23
Done.
|
| return; |
| } |
| + |
| if (!offscreen_saved_color_texture_info_.get()) { |
| GLuint service_id = offscreen_saved_color_texture_->id(); |
| offscreen_saved_color_texture_info_ = TextureRef::Create( |
| @@ -4218,8 +4261,93 @@ void GLES2DecoderImpl::ProduceFrontBuffer(const Mailbox& mailbox) { |
| GL_TEXTURE_2D); |
| UpdateParentTextureInfo(); |
| } |
| + |
| mailbox_manager()->ProduceTexture( |
| mailbox, offscreen_saved_color_texture_info_->texture()); |
| + |
| + // Save the BackTexture and TextureRef. |
| + SavedBackTexture save; |
| + save.back_texture.swap(offscreen_saved_color_texture_); |
| + save.texture_ref = offscreen_saved_color_texture_info_; |
| + offscreen_saved_color_texture_info_ = nullptr; |
| + save.in_use = true; |
| + saved_back_textures_.push_back(std::move(save)); |
| + |
| + CreateBackTexture(); |
| +} |
| + |
| +void GLES2DecoderImpl::ReturnFrontBuffer(const Mailbox& mailbox, |
| + bool is_lost) { |
| + Texture* texture = mailbox_manager()->ConsumeTexture(mailbox); |
| + for (auto it = saved_back_textures_.begin(); it != saved_back_textures_.end(); |
| + ++it) { |
| + if (texture != it->texture_ref->texture()) |
| + continue; |
| + |
| + if (is_lost || it->back_texture->size() != offscreen_size_) { |
| + it->back_texture->Invalidate(); |
| + saved_back_textures_.erase(it); |
| + return; |
| + } |
| + |
| + it->in_use = false; |
| + return; |
| + } |
| + |
| + NOTREACHED(); |
|
piman
2016/04/26 01:54:01
nit: Not NOTREACHED(), this could be reached from
erikchen
2016/04/27 16:31:23
This seems like the perfect place for NOTREACHED()
piman
2016/04/27 23:00:58
I insist :) This is consistent in GPU code.
DCHECK
erikchen
2016/04/27 23:59:24
Point taken. Thanks for the example. Switched to a
|
| +} |
| + |
| +void GLES2DecoderImpl::CreateBackTexture() { |
| + for (auto it = saved_back_textures_.begin(); it != saved_back_textures_.end(); |
| + ++it) { |
| + if (it->in_use) |
| + continue; |
| + |
| + if (it->back_texture->size() != offscreen_size_) |
| + continue; |
| + offscreen_saved_color_texture_ = std::move(it->back_texture); |
| + offscreen_saved_color_texture_info_ = it->texture_ref; |
| + saved_back_textures_.erase(it); |
| + return; |
| + } |
| + |
| + ++create_back_texture_count_for_test_; |
| + offscreen_saved_color_texture_.reset( |
| + new BackTexture(memory_tracker(), &state_)); |
| + offscreen_saved_color_texture_->Create(); |
| + offscreen_saved_color_texture_->AllocateStorage( |
| + offscreen_size_, offscreen_saved_color_format_, false); |
| + offscreen_saved_frame_buffer_->AttachRenderTexture( |
| + offscreen_saved_color_texture_.get()); |
| +} |
| + |
| +void GLES2DecoderImpl::ReleaseNotInUseBackTextures() { |
| + for (auto& saved_back_texture : saved_back_textures_) { |
| + if (!saved_back_texture.in_use) |
| + saved_back_texture.back_texture->Invalidate(); |
| + } |
| + |
| + std::remove_if(saved_back_textures_.begin(), saved_back_textures_.end(), |
| + [](const SavedBackTexture& saved_back_texture) { |
| + return !saved_back_texture.in_use; |
| + }); |
| +} |
| + |
| +void GLES2DecoderImpl::ReleaseAllBackTextures() { |
| + for (auto& saved_back_texture : saved_back_textures_) { |
| + // The texture will be destroyed by texture_ref's destructor. |
| + DCHECK(saved_back_texture.texture_ref); |
| + saved_back_texture.back_texture->Invalidate(); |
| + } |
| + saved_back_textures_.clear(); |
| +} |
| + |
| +size_t GLES2DecoderImpl::GetSavedBackTextureCountForTest() { |
| + return saved_back_textures_.size(); |
| +} |
| + |
| +size_t GLES2DecoderImpl::GetCreatedBackTextureCountForTest() { |
| + return create_back_texture_count_for_test_; |
| } |
| bool GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size& size) { |
| @@ -12715,6 +12843,10 @@ void GLES2DecoderImpl::DoSwapBuffers() { |
| glFinish(); |
| } |
| + // The size has changed, so none of the cached BackTextures are useful |
| + // anymore. |
| + ReleaseNotInUseBackTextures(); |
| + |
| // Allocate the offscreen saved color texture. |
| DCHECK(offscreen_saved_color_format_); |
| offscreen_saved_color_texture_->AllocateStorage( |