Update function names in BrowserContextKeyedServiceFactory::GetServiceForBrowserConte...
[chromium-blink-merge.git] / content / renderer / gpu / mailbox_output_surface.cc
blob8af117d2aa453354bdc95244273de237cfc03254
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/renderer/gpu/mailbox_output_surface.h"
7 #include "base/logging.h"
8 #include "cc/output/compositor_frame.h"
9 #include "cc/output/compositor_frame_ack.h"
10 #include "cc/output/gl_frame_data.h"
11 #include "third_party/WebKit/public/platform/WebGraphicsContext3D.h"
12 #include "third_party/khronos/GLES2/gl2.h"
13 #include "third_party/khronos/GLES2/gl2ext.h"
15 using cc::CompositorFrame;
16 using cc::GLFrameData;
17 using gpu::Mailbox;
19 namespace content {
21 MailboxOutputSurface::MailboxOutputSurface(
22 int32 routing_id,
23 WebGraphicsContext3DCommandBufferImpl* context3D,
24 cc::SoftwareOutputDevice* software_device)
25 : CompositorOutputSurface(routing_id, context3D, software_device, true),
26 fbo_(0),
27 is_backbuffer_discarded_(false) {
28 pending_textures_.push_back(TransferableFrame());
29 capabilities_.max_frames_pending = 1;
32 MailboxOutputSurface::~MailboxOutputSurface() {
33 DiscardBackbuffer();
34 while (!pending_textures_.empty()) {
35 if (pending_textures_.front().texture_id)
36 context3d_->deleteTexture(pending_textures_.front().texture_id);
37 pending_textures_.pop_front();
41 void MailboxOutputSurface::EnsureBackbuffer() {
42 is_backbuffer_discarded_ = false;
44 if (!current_backing_.texture_id) {
45 // Find a texture of matching size to recycle.
46 while (!returned_textures_.empty()) {
47 TransferableFrame& texture = returned_textures_.front();
48 if (texture.size == surface_size_) {
49 current_backing_ = texture;
50 if (current_backing_.sync_point)
51 context3d_->waitSyncPoint(current_backing_.sync_point);
52 returned_textures_.pop();
53 break;
56 context3d_->deleteTexture(texture.texture_id);
57 returned_textures_.pop();
60 if (!current_backing_.texture_id) {
61 current_backing_.texture_id = context3d_->createTexture();
62 current_backing_.size = surface_size_;
63 context3d_->bindTexture(GL_TEXTURE_2D, current_backing_.texture_id);
64 context3d_->texParameteri(
65 GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
66 context3d_->texParameteri(
67 GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
68 context3d_->texParameteri(
69 GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
70 context3d_->texParameteri(
71 GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
72 context3d_->texImage2D(
73 GL_TEXTURE_2D, 0, GL_RGBA,
74 surface_size_.width(), surface_size_.height(), 0,
75 GL_RGBA, GL_UNSIGNED_BYTE, NULL);
76 context3d_->genMailboxCHROMIUM(current_backing_.mailbox.name);
77 context3d_->produceTextureCHROMIUM(
78 GL_TEXTURE_2D, current_backing_.mailbox.name);
83 void MailboxOutputSurface::DiscardBackbuffer() {
84 is_backbuffer_discarded_ = true;
86 if (current_backing_.texture_id) {
87 context3d_->deleteTexture(current_backing_.texture_id);
88 current_backing_ = TransferableFrame();
91 while (!returned_textures_.empty()) {
92 const TransferableFrame& frame = returned_textures_.front();
93 context3d_->deleteTexture(frame.texture_id);
94 returned_textures_.pop();
97 if (fbo_) {
98 context3d_->bindFramebuffer(GL_FRAMEBUFFER, fbo_);
99 context3d_->deleteFramebuffer(fbo_);
100 fbo_ = 0;
104 void MailboxOutputSurface::Reshape(gfx::Size size, float scale_factor) {
105 if (size == surface_size_)
106 return;
108 surface_size_ = size;
109 device_scale_factor_ = scale_factor;
110 DiscardBackbuffer();
111 EnsureBackbuffer();
114 void MailboxOutputSurface::BindFramebuffer() {
115 EnsureBackbuffer();
116 DCHECK(current_backing_.texture_id);
118 if (!fbo_)
119 fbo_ = context3d_->createFramebuffer();
120 context3d_->bindFramebuffer(GL_FRAMEBUFFER, fbo_);
121 context3d_->framebufferTexture2D(
122 GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
123 current_backing_.texture_id, 0);
126 void MailboxOutputSurface::OnSwapAck(const cc::CompositorFrameAck& ack) {
127 if (!ack.gl_frame_data->mailbox.IsZero()) {
128 DCHECK(!ack.gl_frame_data->size.IsEmpty());
129 // The browser could be returning the oldest or any other pending texture
130 // if it decided to skip a frame.
131 std::deque<TransferableFrame>::iterator it;
132 for (it = pending_textures_.begin(); it != pending_textures_.end(); it++) {
133 DCHECK(!it->mailbox.IsZero());
134 if (!memcmp(it->mailbox.name,
135 ack.gl_frame_data->mailbox.name,
136 sizeof(it->mailbox.name))) {
137 DCHECK(it->size == ack.gl_frame_data->size);
138 break;
141 DCHECK(it != pending_textures_.end());
142 it->sync_point = ack.gl_frame_data->sync_point;
144 if (!is_backbuffer_discarded_) {
145 returned_textures_.push(*it);
146 } else {
147 context3d_->deleteTexture(it->texture_id);
150 pending_textures_.erase(it);
151 } else {
152 DCHECK(!pending_textures_.empty());
153 // The browser always keeps one texture as the frontbuffer.
154 // If it does not return a mailbox, it discarded the frontbuffer which is
155 // the oldest texture we sent.
156 uint32 texture_id = pending_textures_.front().texture_id;
157 if (texture_id)
158 context3d_->deleteTexture(texture_id);
159 pending_textures_.pop_front();
161 CompositorOutputSurface::OnSwapAck(ack);
164 void MailboxOutputSurface::SwapBuffers(cc::CompositorFrame* frame) {
165 DCHECK(frame->gl_frame_data);
166 DCHECK(!surface_size_.IsEmpty());
167 DCHECK(surface_size_ == current_backing_.size);
168 DCHECK(frame->gl_frame_data->size == current_backing_.size);
169 DCHECK(!current_backing_.mailbox.IsZero());
171 frame->gl_frame_data->mailbox = current_backing_.mailbox;
172 context3d_->flush();
173 frame->gl_frame_data->sync_point = context3d_->insertSyncPoint();
174 CompositorOutputSurface::SwapBuffers(frame);
176 pending_textures_.push_back(current_backing_);
177 current_backing_ = TransferableFrame();
180 size_t MailboxOutputSurface::GetNumAcksPending() {
181 DCHECK(pending_textures_.size());
182 return pending_textures_.size() - 1;
185 } // namespace content