OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/renderer/gpu/mailbox_output_surface.h" | 5 #include "content/renderer/gpu/mailbox_output_surface.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 #include "cc/output/compositor_frame.h" | 8 #include "cc/output/compositor_frame.h" |
9 #include "cc/output/compositor_frame_ack.h" | 9 #include "cc/output/compositor_frame_ack.h" |
10 #include "cc/output/gl_frame_data.h" | 10 #include "cc/output/gl_frame_data.h" |
11 #include "cc/resources/resource_provider.h" | 11 #include "cc/resources/resource_provider.h" |
12 #include "third_party/WebKit/public/platform/WebGraphicsContext3D.h" | 12 #include "gpu/command_buffer/client/gles2_interface.h" |
13 #include "third_party/khronos/GLES2/gl2.h" | 13 #include "third_party/khronos/GLES2/gl2.h" |
14 #include "third_party/khronos/GLES2/gl2ext.h" | 14 #include "third_party/khronos/GLES2/gl2ext.h" |
15 | 15 |
16 using cc::CompositorFrame; | 16 using cc::CompositorFrame; |
17 using cc::GLFrameData; | 17 using cc::GLFrameData; |
18 using cc::ResourceProvider; | 18 using cc::ResourceProvider; |
19 using gpu::Mailbox; | 19 using gpu::Mailbox; |
| 20 using gpu::gles2::GLES2Interface; |
20 | 21 |
21 namespace content { | 22 namespace content { |
22 | 23 |
23 MailboxOutputSurface::MailboxOutputSurface( | 24 MailboxOutputSurface::MailboxOutputSurface( |
24 int32 routing_id, | 25 int32 routing_id, |
25 uint32 output_surface_id, | 26 uint32 output_surface_id, |
26 const scoped_refptr<ContextProviderCommandBuffer>& context_provider, | 27 const scoped_refptr<ContextProviderCommandBuffer>& context_provider, |
27 scoped_ptr<cc::SoftwareOutputDevice> software_device, | 28 scoped_ptr<cc::SoftwareOutputDevice> software_device, |
28 cc::ResourceFormat format) | 29 cc::ResourceFormat format) |
29 : CompositorOutputSurface(routing_id, | 30 : CompositorOutputSurface(routing_id, |
30 output_surface_id, | 31 output_surface_id, |
31 context_provider, | 32 context_provider, |
32 software_device.Pass(), | 33 software_device.Pass(), |
33 true), | 34 true), |
34 fbo_(0), | 35 fbo_(0), |
35 is_backbuffer_discarded_(false), | 36 is_backbuffer_discarded_(false), |
36 format_(format) { | 37 format_(format) { |
37 pending_textures_.push_back(TransferableFrame()); | 38 pending_textures_.push_back(TransferableFrame()); |
38 capabilities_.max_frames_pending = 1; | 39 capabilities_.max_frames_pending = 1; |
39 capabilities_.uses_default_gl_framebuffer = false; | 40 capabilities_.uses_default_gl_framebuffer = false; |
40 } | 41 } |
41 | 42 |
42 MailboxOutputSurface::~MailboxOutputSurface() { | 43 MailboxOutputSurface::~MailboxOutputSurface() { |
43 DiscardBackbuffer(); | 44 DiscardBackbuffer(); |
44 while (!pending_textures_.empty()) { | 45 while (!pending_textures_.empty()) { |
45 if (pending_textures_.front().texture_id) { | 46 if (pending_textures_.front().texture_id) { |
46 context_provider_->Context3d()->deleteTexture( | 47 context_provider_->ContextGL()->DeleteTextures( |
47 pending_textures_.front().texture_id); | 48 1, &pending_textures_.front().texture_id); |
48 } | 49 } |
49 pending_textures_.pop_front(); | 50 pending_textures_.pop_front(); |
50 } | 51 } |
51 } | 52 } |
52 | 53 |
53 void MailboxOutputSurface::EnsureBackbuffer() { | 54 void MailboxOutputSurface::EnsureBackbuffer() { |
54 is_backbuffer_discarded_ = false; | 55 is_backbuffer_discarded_ = false; |
55 | 56 |
56 blink::WebGraphicsContext3D* context3d = context_provider_->Context3d(); | 57 GLES2Interface* gl = context_provider_->ContextGL(); |
57 | 58 |
58 if (!current_backing_.texture_id) { | 59 if (!current_backing_.texture_id) { |
59 // Find a texture of matching size to recycle. | 60 // Find a texture of matching size to recycle. |
60 while (!returned_textures_.empty()) { | 61 while (!returned_textures_.empty()) { |
61 TransferableFrame& texture = returned_textures_.front(); | 62 TransferableFrame& texture = returned_textures_.front(); |
62 if (texture.size == surface_size_) { | 63 if (texture.size == surface_size_) { |
63 current_backing_ = texture; | 64 current_backing_ = texture; |
64 if (current_backing_.sync_point) | 65 if (current_backing_.sync_point) |
65 context3d->waitSyncPoint(current_backing_.sync_point); | 66 gl->WaitSyncPointCHROMIUM(current_backing_.sync_point); |
66 returned_textures_.pop(); | 67 returned_textures_.pop(); |
67 break; | 68 break; |
68 } | 69 } |
69 | 70 |
70 context3d->deleteTexture(texture.texture_id); | 71 gl->DeleteTextures(1, &texture.texture_id); |
71 returned_textures_.pop(); | 72 returned_textures_.pop(); |
72 } | 73 } |
73 | 74 |
74 if (!current_backing_.texture_id) { | 75 if (!current_backing_.texture_id) { |
75 current_backing_.texture_id = context3d->createTexture(); | 76 gl->GenTextures(1, ¤t_backing_.texture_id); |
76 current_backing_.size = surface_size_; | 77 current_backing_.size = surface_size_; |
77 context3d->bindTexture(GL_TEXTURE_2D, current_backing_.texture_id); | 78 gl->BindTexture(GL_TEXTURE_2D, current_backing_.texture_id); |
78 context3d->texParameteri( | 79 gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
79 GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | 80 gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); |
80 context3d->texParameteri( | 81 gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
81 GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | 82 gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
82 context3d->texParameteri( | 83 gl->TexImage2D(GL_TEXTURE_2D, |
83 GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | 84 0, |
84 context3d->texParameteri( | 85 GLInternalFormat(format_), |
85 GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | 86 surface_size_.width(), |
86 context3d->texImage2D( | 87 surface_size_.height(), |
87 GL_TEXTURE_2D, | 88 0, |
88 0, | 89 GLDataFormat(format_), |
89 GLInternalFormat(format_), | 90 GLDataType(format_), |
90 surface_size_.width(), | 91 NULL); |
91 surface_size_.height(), | 92 gl->GenMailboxCHROMIUM(current_backing_.mailbox.name); |
92 0, | 93 gl->ProduceTextureCHROMIUM(GL_TEXTURE_2D, current_backing_.mailbox.name); |
93 GLDataFormat(format_), | |
94 GLDataType(format_), | |
95 NULL); | |
96 context3d->genMailboxCHROMIUM(current_backing_.mailbox.name); | |
97 context3d->produceTextureCHROMIUM( | |
98 GL_TEXTURE_2D, current_backing_.mailbox.name); | |
99 } | 94 } |
100 } | 95 } |
101 } | 96 } |
102 | 97 |
103 void MailboxOutputSurface::DiscardBackbuffer() { | 98 void MailboxOutputSurface::DiscardBackbuffer() { |
104 is_backbuffer_discarded_ = true; | 99 is_backbuffer_discarded_ = true; |
105 | 100 |
106 blink::WebGraphicsContext3D* context3d = context_provider_->Context3d(); | 101 GLES2Interface* gl = context_provider_->ContextGL(); |
107 | 102 |
108 if (current_backing_.texture_id) { | 103 if (current_backing_.texture_id) { |
109 context3d->deleteTexture(current_backing_.texture_id); | 104 gl->DeleteTextures(1, ¤t_backing_.texture_id); |
110 current_backing_ = TransferableFrame(); | 105 current_backing_ = TransferableFrame(); |
111 } | 106 } |
112 | 107 |
113 while (!returned_textures_.empty()) { | 108 while (!returned_textures_.empty()) { |
114 const TransferableFrame& frame = returned_textures_.front(); | 109 const TransferableFrame& frame = returned_textures_.front(); |
115 context3d->deleteTexture(frame.texture_id); | 110 gl->DeleteTextures(1, &frame.texture_id); |
116 returned_textures_.pop(); | 111 returned_textures_.pop(); |
117 } | 112 } |
118 | 113 |
119 if (fbo_) { | 114 if (fbo_) { |
120 context3d->bindFramebuffer(GL_FRAMEBUFFER, fbo_); | 115 gl->BindFramebuffer(GL_FRAMEBUFFER, fbo_); |
121 context3d->deleteFramebuffer(fbo_); | 116 gl->DeleteFramebuffers(1, &fbo_); |
122 fbo_ = 0; | 117 fbo_ = 0; |
123 } | 118 } |
124 } | 119 } |
125 | 120 |
126 void MailboxOutputSurface::Reshape(gfx::Size size, float scale_factor) { | 121 void MailboxOutputSurface::Reshape(gfx::Size size, float scale_factor) { |
127 if (size == surface_size_) | 122 if (size == surface_size_) |
128 return; | 123 return; |
129 | 124 |
130 surface_size_ = size; | 125 surface_size_ = size; |
131 device_scale_factor_ = scale_factor; | 126 device_scale_factor_ = scale_factor; |
132 DiscardBackbuffer(); | 127 DiscardBackbuffer(); |
133 EnsureBackbuffer(); | 128 EnsureBackbuffer(); |
134 } | 129 } |
135 | 130 |
136 void MailboxOutputSurface::BindFramebuffer() { | 131 void MailboxOutputSurface::BindFramebuffer() { |
137 EnsureBackbuffer(); | 132 EnsureBackbuffer(); |
138 DCHECK(current_backing_.texture_id); | 133 DCHECK(current_backing_.texture_id); |
139 | 134 |
140 blink::WebGraphicsContext3D* context3d = context_provider_->Context3d(); | 135 GLES2Interface* gl = context_provider_->ContextGL(); |
141 | 136 |
142 if (!fbo_) | 137 if (!fbo_) |
143 fbo_ = context3d->createFramebuffer(); | 138 gl->GenFramebuffers(1, &fbo_); |
144 context3d->bindFramebuffer(GL_FRAMEBUFFER, fbo_); | 139 gl->BindFramebuffer(GL_FRAMEBUFFER, fbo_); |
145 context3d->framebufferTexture2D( | 140 gl->FramebufferTexture2D(GL_FRAMEBUFFER, |
146 GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, | 141 GL_COLOR_ATTACHMENT0, |
147 current_backing_.texture_id, 0); | 142 GL_TEXTURE_2D, |
| 143 current_backing_.texture_id, |
| 144 0); |
148 } | 145 } |
149 | 146 |
150 void MailboxOutputSurface::OnSwapAck(uint32 output_surface_id, | 147 void MailboxOutputSurface::OnSwapAck(uint32 output_surface_id, |
151 const cc::CompositorFrameAck& ack) { | 148 const cc::CompositorFrameAck& ack) { |
152 // Ignore message if it's a stale one coming from a different output surface | 149 // Ignore message if it's a stale one coming from a different output surface |
153 // (e.g. after a lost context). | 150 // (e.g. after a lost context). |
154 if (output_surface_id != output_surface_id_) { | 151 if (output_surface_id != output_surface_id_) { |
155 CompositorOutputSurface::OnSwapAck(output_surface_id, ack); | 152 CompositorOutputSurface::OnSwapAck(output_surface_id, ack); |
156 return; | 153 return; |
157 } | 154 } |
(...skipping 10 matching lines...) Expand all Loading... |
168 DCHECK(it->size == ack.gl_frame_data->size); | 165 DCHECK(it->size == ack.gl_frame_data->size); |
169 break; | 166 break; |
170 } | 167 } |
171 } | 168 } |
172 DCHECK(it != pending_textures_.end()); | 169 DCHECK(it != pending_textures_.end()); |
173 it->sync_point = ack.gl_frame_data->sync_point; | 170 it->sync_point = ack.gl_frame_data->sync_point; |
174 | 171 |
175 if (!is_backbuffer_discarded_) { | 172 if (!is_backbuffer_discarded_) { |
176 returned_textures_.push(*it); | 173 returned_textures_.push(*it); |
177 } else { | 174 } else { |
178 context_provider_->Context3d()->deleteTexture(it->texture_id); | 175 context_provider_->ContextGL()->DeleteTextures(1, &it->texture_id); |
179 } | 176 } |
180 | 177 |
181 pending_textures_.erase(it); | 178 pending_textures_.erase(it); |
182 } else { | 179 } else { |
183 DCHECK(!pending_textures_.empty()); | 180 DCHECK(!pending_textures_.empty()); |
184 // The browser always keeps one texture as the frontbuffer. | 181 // The browser always keeps one texture as the frontbuffer. |
185 // If it does not return a mailbox, it discarded the frontbuffer which is | 182 // If it does not return a mailbox, it discarded the frontbuffer which is |
186 // the oldest texture we sent. | 183 // the oldest texture we sent. |
187 uint32 texture_id = pending_textures_.front().texture_id; | 184 uint32 texture_id = pending_textures_.front().texture_id; |
188 if (texture_id) | 185 if (texture_id) |
189 context_provider_->Context3d()->deleteTexture(texture_id); | 186 context_provider_->ContextGL()->DeleteTextures(1, &texture_id); |
190 pending_textures_.pop_front(); | 187 pending_textures_.pop_front(); |
191 } | 188 } |
192 CompositorOutputSurface::OnSwapAck(output_surface_id, ack); | 189 CompositorOutputSurface::OnSwapAck(output_surface_id, ack); |
193 } | 190 } |
194 | 191 |
195 void MailboxOutputSurface::SwapBuffers(cc::CompositorFrame* frame) { | 192 void MailboxOutputSurface::SwapBuffers(cc::CompositorFrame* frame) { |
196 DCHECK(frame->gl_frame_data); | 193 DCHECK(frame->gl_frame_data); |
197 DCHECK(!surface_size_.IsEmpty()); | 194 DCHECK(!surface_size_.IsEmpty()); |
198 DCHECK(surface_size_ == current_backing_.size); | 195 DCHECK(surface_size_ == current_backing_.size); |
199 DCHECK(frame->gl_frame_data->size == current_backing_.size); | 196 DCHECK(frame->gl_frame_data->size == current_backing_.size); |
200 DCHECK(!current_backing_.mailbox.IsZero() || | 197 DCHECK(!current_backing_.mailbox.IsZero() || |
201 context_provider_->Context3d()->isContextLost()); | 198 context_provider_->IsContextLost()); |
202 | 199 |
203 frame->gl_frame_data->mailbox = current_backing_.mailbox; | 200 frame->gl_frame_data->mailbox = current_backing_.mailbox; |
204 context_provider_->Context3d()->flush(); | 201 context_provider_->ContextGL()->Flush(); |
205 frame->gl_frame_data->sync_point = | 202 frame->gl_frame_data->sync_point = |
206 context_provider_->Context3d()->insertSyncPoint(); | 203 context_provider_->ContextGL()->InsertSyncPointCHROMIUM(); |
207 CompositorOutputSurface::SwapBuffers(frame); | 204 CompositorOutputSurface::SwapBuffers(frame); |
208 | 205 |
209 pending_textures_.push_back(current_backing_); | 206 pending_textures_.push_back(current_backing_); |
210 current_backing_ = TransferableFrame(); | 207 current_backing_ = TransferableFrame(); |
211 } | 208 } |
212 | 209 |
213 size_t MailboxOutputSurface::GetNumAcksPending() { | 210 size_t MailboxOutputSurface::GetNumAcksPending() { |
214 DCHECK(pending_textures_.size()); | 211 DCHECK(pending_textures_.size()); |
215 return pending_textures_.size() - 1; | 212 return pending_textures_.size() - 1; |
216 } | 213 } |
217 | 214 |
218 } // namespace content | 215 } // namespace content |
OLD | NEW |