Chromium Code Reviews| Index: content/renderer/gpu/mailbox_output_surface.cc |
| diff --git a/content/renderer/gpu/mailbox_output_surface.cc b/content/renderer/gpu/mailbox_output_surface.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..cf18fbf8d8e90b4212af8308100a6c0cc9c241fc |
| --- /dev/null |
| +++ b/content/renderer/gpu/mailbox_output_surface.cc |
| @@ -0,0 +1,158 @@ |
| +// Copyright (c) 2012 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/renderer/gpu/mailbox_output_surface.h" |
| + |
| +#include "base/logging.h" |
| +#include "cc/compositor_frame.h" |
| +#include "cc/compositor_frame_ack.h" |
| +#include "cc/gl_frame_data.h" |
| +#include "third_party/WebKit/Source/Platform/chromium/public/WebGraphicsContext3D.h" |
| +#include "third_party/khronos/GLES2/gl2.h" |
| +#include "third_party/khronos/GLES2/gl2ext.h" |
| + |
| +using cc::CompositorFrame; |
| +using cc::GLFrameData; |
| +using cc::Mailbox; |
| +using WebKit::WebGraphicsContext3D; |
| + |
| +namespace content { |
| + |
| +MailboxOutputSurface::MailboxOutputSurface( |
| + int32 routing_id, |
| + WebGraphicsContext3D* context3D, |
| + cc::SoftwareOutputDevice* software_device) |
| + : CompositorOutputSurface(routing_id, |
| + context3D, |
| + software_device), |
| + fbo_(0) { |
| +} |
| + |
| +MailboxOutputSurface::~MailboxOutputSurface() { |
| + DiscardBackbuffer(); |
| +} |
| + |
| +void MailboxOutputSurface::EnsureBackbuffer() { |
| + if (!current_backing_.texture_id) { |
| + // Find a texture of matching size to recycle. |
| + while (returned_textures_.size()) { |
|
piman
2013/02/27 23:51:04
!returned_textures_.empty()
no sievers
2013/02/28 18:43:40
Done.
|
| + TransferableFrame& texture = returned_textures_.front(); |
| + if (texture.size == size_) { |
| + current_backing_ = texture; |
| + returned_textures_.pop(); |
| + break; |
| + } |
| + |
| + context3d_->deleteTexture(texture.texture_id); |
| + returned_textures_.pop(); |
| + } |
| + |
| + if (!current_backing_.texture_id) { |
| + current_backing_.texture_id = context3d_->createTexture(); |
| + current_backing_.size = size_; |
| + context3d_->genMailboxCHROMIUM(current_backing_.mailbox.name); |
| + context3d_->bindTexture(GL_TEXTURE_2D, current_backing_.texture_id); |
| + context3d_->texParameteri( |
| + GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
| + context3d_->texParameteri( |
| + GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); |
| + context3d_->texParameteri( |
| + GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
| + context3d_->texParameteri( |
| + GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
| + context3d_->texImage2D( |
| + GL_TEXTURE_2D, 0, GL_RGBA, size_.width(), size_.height(), 0, |
| + GL_RGBA, GL_UNSIGNED_BYTE, NULL); |
| + } |
| + } |
| +} |
| + |
| +void MailboxOutputSurface::DiscardBackbuffer() { |
| + if (current_backing_.texture_id) { |
| + context3d_->deleteTexture(current_backing_.texture_id); |
| + current_backing_ = TransferableFrame(); |
| + } |
| + |
| + while (returned_textures_.size()) { |
|
piman
2013/02/27 23:51:04
!returned_textures_.empty()
no sievers
2013/02/28 18:43:40
Done.
|
| + context3d_->deleteTexture(returned_textures_.front().texture_id); |
| + returned_textures_.pop(); |
| + } |
| + |
| + if (fbo_) { |
| + context3d_->bindFramebuffer(GL_FRAMEBUFFER, fbo_); |
| + context3d_->deleteFramebuffer(fbo_); |
| + fbo_ = 0; |
| + } |
| +} |
| + |
| +void MailboxOutputSurface::Reshape(const gfx::Size& size) { |
| + size_ = size; |
|
Sami
2013/02/28 12:46:58
Should we DCHECK here that size_ != size? Hopefull
no sievers
2013/02/28 18:43:40
I added an early-return.
|
| + DiscardBackbuffer(); |
| + EnsureBackbuffer(); |
| +} |
| + |
| +void MailboxOutputSurface::BindFramebuffer() { |
| + EnsureBackbuffer(); |
| + DCHECK(current_backing_.texture_id); |
| + |
| + if (!fbo_) |
| + fbo_ = context3d_->createFramebuffer(); |
|
Sami
2013/02/28 12:46:58
Nit: indent by 2.
no sievers
2013/02/28 18:43:40
Done.
|
| + context3d_->bindFramebuffer(GL_FRAMEBUFFER, fbo_); |
| + context3d_->framebufferTexture2D( |
| + GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, |
| + current_backing_.texture_id, 0); |
| +} |
| + |
| +void MailboxOutputSurface::SendFrameToParentCompositor( |
| + cc::CompositorFrame* frame) { |
| + frame->gl_frame_data.reset(new GLFrameData()); |
| + |
| + DCHECK(!size_.IsEmpty()); |
| + DCHECK(size_ == current_backing_.size); |
| + DCHECK(!current_backing_.mailbox.isZero()); |
| + |
| + context3d_->framebufferTexture2D( |
| + GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); |
| + context3d_->bindTexture(GL_TEXTURE_2D, current_backing_.texture_id); |
| + context3d_->produceTextureCHROMIUM( |
| + GL_TEXTURE_2D, current_backing_.mailbox.name); |
| + frame->gl_frame_data->mailbox = current_backing_.mailbox; |
| + frame->gl_frame_data->size = current_backing_.size; |
| + context3d_->flush(); |
| + frame->gl_frame_data->sync_point = context3d_->insertSyncPoint(); |
| + context3d_->deleteTexture(current_backing_.texture_id); |
|
piman
2013/02/27 23:51:04
note: for a follow-up probably, but you may want t
no sievers
2013/02/28 18:43:40
TODO added.
|
| + current_backing_ = TransferableFrame(); |
| + CompositorOutputSurface::SendFrameToParentCompositor(frame); |
|
piman
2013/02/27 23:51:04
nit: can you move this above the deleteTexture? It
no sievers
2013/02/28 18:43:40
Done.
|
| +} |
| + |
| +void MailboxOutputSurface::OnSwapAck(const cc::CompositorFrameAck& ack) { |
| + if (!ack.gl_frame_data->mailbox.isZero()) { |
| + DCHECK(!ack.gl_frame_data->size.IsEmpty()); |
| + uint32 texture_id = context3d_->createTexture(); |
| + TransferableFrame texture( |
| + texture_id, ack.gl_frame_data->mailbox, ack.gl_frame_data->size); |
| + |
| + context3d_->bindTexture(GL_TEXTURE_2D, texture_id); |
| + |
| + // If the consumer is bouncing back the same texture (i.e. skipping the |
| + // frame), we don't have to synchronize here (sync_point == 0). |
| + if (ack.gl_frame_data->sync_point) |
| + context3d_->waitSyncPoint(ack.gl_frame_data->sync_point); |
|
piman
2013/02/27 23:51:04
note: a potential optimization (for a follow-up to
no sievers
2013/02/28 18:43:40
TODO added.
|
| + |
| + context3d_->consumeTextureCHROMIUM( |
| + GL_TEXTURE_2D, ack.gl_frame_data->mailbox.name); |
| + returned_textures_.push(texture); |
| + } |
| + CompositorOutputSurface::OnSwapAck(ack); |
| +} |
| + |
| +void MailboxOutputSurface::SwapBuffers() { |
| +} |
| + |
| +void MailboxOutputSurface::PostSubBuffer(const gfx::Rect& rect) { |
| + NOTIMPLEMENTED() |
| + << "Partial swap not supported with composite-to-mailbox yet."; |
| +} |
| + |
| +} // namespace content |