| 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 d4d0fab085fbfcc7d9713bf5b20bb2eb8a8152c1..88c2ee623bc951ad7a22dfe8360babb71c1cc853 100644
|
| --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
|
| +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
|
| @@ -593,7 +593,8 @@ 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 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;
|
| @@ -2007,6 +2008,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_;
|
| @@ -4081,6 +4109,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();
|
| @@ -4219,11 +4248,12 @@ void GLES2DecoderImpl::SetSurface(
|
| RestoreCurrentFramebufferBindings();
|
| }
|
|
|
| -void GLES2DecoderImpl::ProduceFrontBuffer(const Mailbox& mailbox) {
|
| +void GLES2DecoderImpl::TakeFrontBuffer(const Mailbox& mailbox) {
|
| if (!offscreen_saved_color_texture_.get()) {
|
| - LOG(ERROR) << "Called ProduceFrontBuffer on a non-offscreen context";
|
| + DLOG(ERROR) << "Called TakeFrontBuffer on a non-offscreen context";
|
| return;
|
| }
|
| +
|
| if (!offscreen_saved_color_texture_info_.get()) {
|
| GLuint service_id = offscreen_saved_color_texture_->id();
|
| offscreen_saved_color_texture_info_ = TextureRef::Create(
|
| @@ -4232,8 +4262,94 @@ 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;
|
| + }
|
| +
|
| + DLOG(ERROR) << "Attempting to return a frontbuffer that was not saved.";
|
| +}
|
| +
|
| +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();
|
| + }
|
| +
|
| + auto to_remove =
|
| + std::remove_if(saved_back_textures_.begin(), saved_back_textures_.end(),
|
| + [](const SavedBackTexture& saved_back_texture) {
|
| + return !saved_back_texture.in_use;
|
| + });
|
| + saved_back_textures_.erase(to_remove, saved_back_textures_.end());
|
| +}
|
| +
|
| +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) {
|
| @@ -12786,6 +12902,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(
|
|
|