Chromium Code Reviews| Index: content/browser/compositor/buffered_output_surface.cc |
| diff --git a/content/browser/compositor/buffered_output_surface.cc b/content/browser/compositor/buffered_output_surface.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..3a1749d919ccbe11832790adb8f7140cc585f26b |
| --- /dev/null |
| +++ b/content/browser/compositor/buffered_output_surface.cc |
| @@ -0,0 +1,131 @@ |
| +// Copyright 2014 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 "content/browser/compositor/buffered_output_surface.h" |
| + |
| +#include "content/common/gpu/client/context_provider_command_buffer.h" |
| +#include "gpu/GLES2/gl2extchromium.h" |
| +#include "gpu/command_buffer/client/gles2_interface.h" |
| + |
| +namespace content { |
| + |
| +BufferedOutputSurface::BufferedOutputSurface( |
| + scoped_refptr<cc::ContextProvider> context_provider, |
| + unsigned int internalformat) |
| + : context_provider_(context_provider), |
| + fbo_(0), |
| + depth_rb_(0), |
| + tex_id_(0), |
| + internalformat_(internalformat), |
| + current_surface_(0), |
| + last_surface_(0), |
| + in_flight_surface_(0) { |
| + Initialize(); |
| +} |
| + |
| +BufferedOutputSurface::~BufferedOutputSurface() { |
| + gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); |
| + if (fbo_) |
| + gl->DeleteFramebuffers(1, &fbo_); |
| + if (depth_rb_) |
| + gl->DeleteRenderbuffers(1, &depth_rb_); |
| + if (tex_id_) |
| + gl->DeleteTextures(1, &tex_id_); |
| + FreeAllSurfaces(); |
| +} |
| + |
| +void BufferedOutputSurface::Initialize() { |
| + gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); |
| + gl->GenFramebuffers(1, &fbo_); |
| + gl->GenRenderbuffers(1, &depth_rb_); |
| + gl->GenTextures(1, &tex_id_); |
| + DCHECK(fbo_); |
| + DCHECK(depth_rb_); |
| + DCHECK(tex_id_); |
| +} |
| + |
| +void BufferedOutputSurface::BindFramebuffer() { |
| + if (!current_surface_) |
| + current_surface_ = GetNextSurface(); |
| + |
| + gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); |
| + gl->BindFramebuffer(GL_FRAMEBUFFER, fbo_); |
| + gl->BindTexture(GL_TEXTURE_2D, tex_id_); |
| + gl->BindTexImage2DCHROMIUM(GL_TEXTURE_2D, current_surface_); |
| + gl->FramebufferTexture2D( |
| + GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex_id_, 0); |
| +} |
| + |
| +void BufferedOutputSurface::SwapBuffers() { |
| + if (last_surface_) { |
| + if (in_flight_surface_) |
| + context_provider_->ContextGL()->DestroyImageCHROMIUM(in_flight_surface_); |
| + else |
| + in_flight_surface_ = last_surface_; |
| + } |
| + last_surface_ = current_surface_; |
| + current_surface_ = 0; |
| +} |
| + |
| +void BufferedOutputSurface::Reshape(const gfx::Size& size, float scale_factor) { |
| + if (size == size_) |
| + return; |
| + size_ = size; |
| + FreeAllSurfaces(); |
| + |
| + if (size_.width() == 0 || size_.height() == 0) |
| + return; // Nothing to do. |
| + gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); |
| + gl->BindFramebuffer(GL_FRAMEBUFFER, fbo_); |
| + gl->BindRenderbuffer(GL_RENDERBUFFER, depth_rb_); |
| + gl->RenderbufferStorage( |
| + GL_RENDERBUFFER, GL_DEPTH_COMPONENT24_OES, size_.width(), size_.height()); |
| + gl->FramebufferRenderbuffer( |
| + GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depth_rb_); |
| +} |
| + |
| +void BufferedOutputSurface::PageFlipComplete() { |
| + if (in_flight_surface_) { |
| + if (available_surfaces_.size() < 2) |
|
alexst (slow to review)
2014/09/10 15:39:07
Let's not try to limit things to 2 buffers here, w
achaulk
2014/09/10 16:47:55
Actually thinking about it the check is redundant
|
| + available_surfaces_.push_back(in_flight_surface_); |
| + else |
| + context_provider_->ContextGL()->DestroyImageCHROMIUM(in_flight_surface_); |
| + } |
| + in_flight_surface_ = 0; |
| +} |
| + |
| +void BufferedOutputSurface::FreeAllSurfaces() { |
| + FreeSurface(&in_flight_surface_); |
| + FreeSurface(&last_surface_); |
| + FreeSurface(¤t_surface_); |
| + for (size_t i = 0; i < available_surfaces_.size(); i++) |
| + context_provider_->ContextGL()->DestroyImageCHROMIUM( |
|
alexst (slow to review)
2014/09/10 15:39:07
You are calling FreeSurface above, but Destroy dir
achaulk
2014/09/10 16:47:54
The free function is just a shortcut for release-a
|
| + available_surfaces_[i]); |
| + available_surfaces_.clear(); |
| +} |
| + |
| +void BufferedOutputSurface::FreeSurface(unsigned int* surface) { |
| + if (*surface) { |
| + context_provider_->ContextGL()->DestroyImageCHROMIUM(*surface); |
| + *surface = 0; |
| + } |
| +} |
| + |
| +unsigned int BufferedOutputSurface::GetNextSurface() { |
| + if (!available_surfaces_.empty()) { |
| + unsigned int id = available_surfaces_.back(); |
| + available_surfaces_.pop_back(); |
| + return id; |
| + } |
| + |
| + unsigned int id = context_provider_->ContextGL()->CreateImageCHROMIUM( |
|
alexst (slow to review)
2014/09/10 15:39:07
Maybe we can associate an image with a unique text
achaulk
2014/09/10 16:47:55
We could, but then we would just have more things
|
| + size_.width(), |
| + size_.height(), |
| + internalformat_, |
| + GL_IMAGE_SCANOUT_CHROMIUM); |
| + DCHECK(id); |
| + return id; |
| +} |
| + |
| +} // namespace content |