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/common/gpu/texture_image_transport_surface.h" | 5 #include "content/common/gpu/texture_image_transport_surface.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
11 #include "content/common/gpu/gpu_channel.h" | 11 #include "content/common/gpu/gpu_channel.h" |
12 #include "content/common/gpu/gpu_channel_manager.h" | 12 #include "content/common/gpu/gpu_channel_manager.h" |
13 #include "content/common/gpu/gpu_messages.h" | 13 #include "content/common/gpu/gpu_messages.h" |
14 #include "content/common/gpu/sync_point_manager.h" | 14 #include "content/common/gpu/sync_point_manager.h" |
15 #include "content/public/common/content_switches.h" | 15 #include "content/public/common/content_switches.h" |
16 #include "gpu/command_buffer/service/context_group.h" | 16 #include "gpu/command_buffer/service/context_group.h" |
17 #include "gpu/command_buffer/service/gpu_scheduler.h" | 17 #include "gpu/command_buffer/service/gpu_scheduler.h" |
18 #include "ui/gl/scoped_binders.h" | 18 #include "ui/gl/scoped_binders.h" |
19 | 19 |
20 using gpu::gles2::ContextGroup; | 20 using gpu::gles2::ContextGroup; |
| 21 using gpu::gles2::GLES2Decoder; |
21 using gpu::gles2::MailboxManager; | 22 using gpu::gles2::MailboxManager; |
22 using gpu::gles2::MailboxName; | 23 using gpu::gles2::MailboxName; |
23 using gpu::gles2::TextureDefinition; | 24 using gpu::gles2::Texture; |
24 using gpu::gles2::TextureManager; | 25 using gpu::gles2::TextureManager; |
| 26 using gpu::gles2::TextureRef; |
25 | 27 |
26 namespace content { | 28 namespace content { |
27 | 29 |
28 TextureImageTransportSurface::TextureImageTransportSurface( | 30 TextureImageTransportSurface::TextureImageTransportSurface( |
29 GpuChannelManager* manager, | 31 GpuChannelManager* manager, |
30 GpuCommandBufferStub* stub, | 32 GpuCommandBufferStub* stub, |
31 const gfx::GLSurfaceHandle& handle) | 33 const gfx::GLSurfaceHandle& handle) |
32 : fbo_id_(0), | 34 : fbo_id_(0), |
33 backbuffer_(CreateTextureDefinition(gfx::Size(), 0)), | 35 current_size_(1, 1), |
34 stub_destroyed_(false), | 36 stub_destroyed_(false), |
35 backbuffer_suggested_allocation_(true), | 37 backbuffer_suggested_allocation_(true), |
36 frontbuffer_suggested_allocation_(true), | 38 frontbuffer_suggested_allocation_(true), |
37 handle_(handle), | 39 handle_(handle), |
38 is_swap_buffers_pending_(false), | 40 is_swap_buffers_pending_(false), |
39 did_unschedule_(false) { | 41 did_unschedule_(false) { |
40 helper_.reset(new ImageTransportHelper(this, | 42 helper_.reset(new ImageTransportHelper(this, |
41 manager, | 43 manager, |
42 stub, | 44 stub, |
43 gfx::kNullPluginWindow)); | 45 gfx::kNullPluginWindow)); |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
84 // Ack arrives. | 86 // Ack arrives. |
85 DCHECK(!did_unschedule_); | 87 DCHECK(!did_unschedule_); |
86 if (is_swap_buffers_pending_) { | 88 if (is_swap_buffers_pending_) { |
87 did_unschedule_ = true; | 89 did_unschedule_ = true; |
88 helper_->SetScheduled(false); | 90 helper_->SetScheduled(false); |
89 return true; | 91 return true; |
90 } | 92 } |
91 return false; | 93 return false; |
92 } | 94 } |
93 | 95 |
94 bool TextureImageTransportSurface::Resize(const gfx::Size&) { | |
95 return true; | |
96 } | |
97 | |
98 bool TextureImageTransportSurface::IsOffscreen() { | 96 bool TextureImageTransportSurface::IsOffscreen() { |
99 return true; | 97 return true; |
100 } | 98 } |
101 | 99 |
102 bool TextureImageTransportSurface::OnMakeCurrent(gfx::GLContext* context) { | 100 unsigned int TextureImageTransportSurface::GetBackingFrameBufferObject() { |
103 if (stub_destroyed_) { | 101 DCHECK(helper_->stub()->decoder()->GetGLContext()->IsCurrent(NULL)); |
104 // Early-exit so that we don't recreate the fbo. We still want to return | |
105 // true, so that the context is made current and the GLES2DecoderImpl can | |
106 // release its own resources. | |
107 return true; | |
108 } | |
109 | |
110 context_ = context; | |
111 | |
112 if (!fbo_id_) { | 102 if (!fbo_id_) { |
113 glGenFramebuffersEXT(1, &fbo_id_); | 103 glGenFramebuffersEXT(1, &fbo_id_); |
114 glBindFramebufferEXT(GL_FRAMEBUFFER, fbo_id_); | 104 glBindFramebufferEXT(GL_FRAMEBUFFER, fbo_id_); |
115 current_size_ = gfx::Size(1, 1); | |
116 helper_->stub()->AddDestructionObserver(this); | 105 helper_->stub()->AddDestructionObserver(this); |
| 106 CreateBackTexture(); |
117 } | 107 } |
118 | 108 |
119 // We could be receiving non-deferred GL commands, that is anything that does | |
120 // not need a framebuffer. | |
121 if (!backbuffer_->service_id() && !is_swap_buffers_pending_ && | |
122 backbuffer_suggested_allocation_) { | |
123 CreateBackTexture(); | |
124 } | |
125 return true; | |
126 } | |
127 | |
128 unsigned int TextureImageTransportSurface::GetBackingFrameBufferObject() { | |
129 return fbo_id_; | 109 return fbo_id_; |
130 } | 110 } |
131 | 111 |
132 bool TextureImageTransportSurface::SetBackbufferAllocation(bool allocation) { | 112 bool TextureImageTransportSurface::SetBackbufferAllocation(bool allocation) { |
133 DCHECK(!is_swap_buffers_pending_); | 113 DCHECK(!is_swap_buffers_pending_); |
134 if (backbuffer_suggested_allocation_ == allocation) | 114 if (backbuffer_suggested_allocation_ == allocation) |
135 return true; | 115 return true; |
136 backbuffer_suggested_allocation_ = allocation; | 116 backbuffer_suggested_allocation_ = allocation; |
137 | 117 |
138 if (backbuffer_suggested_allocation_) { | 118 if (backbuffer_suggested_allocation_) { |
139 DCHECK(!backbuffer_->service_id()); | 119 DCHECK(!backbuffer_); |
140 CreateBackTexture(); | 120 CreateBackTexture(); |
141 } else { | 121 } else { |
142 ReleaseBackTexture(); | 122 ReleaseBackTexture(); |
143 } | 123 } |
144 | 124 |
145 return true; | 125 return true; |
146 } | 126 } |
147 | 127 |
148 void TextureImageTransportSurface::SetFrontbufferAllocation(bool allocation) { | 128 void TextureImageTransportSurface::SetFrontbufferAllocation(bool allocation) { |
149 if (frontbuffer_suggested_allocation_ == allocation) | 129 if (frontbuffer_suggested_allocation_ == allocation) |
150 return; | 130 return; |
151 frontbuffer_suggested_allocation_ = allocation; | 131 frontbuffer_suggested_allocation_ = allocation; |
152 | 132 |
153 if (!frontbuffer_suggested_allocation_) { | 133 // If a swapbuffers is in flight, wait for the ack before releasing the front |
154 GpuHostMsg_AcceleratedSurfaceRelease_Params params; | 134 // buffer: |
155 helper_->SendAcceleratedSurfaceRelease(params); | 135 // - we don't know yet which texture the browser will want to keep |
| 136 // - we want to ensure we don't destroy a texture that is in flight before the |
| 137 // browser got a reference on it. |
| 138 if (!frontbuffer_suggested_allocation_ && |
| 139 !is_swap_buffers_pending_ && |
| 140 helper_->MakeCurrent()) { |
| 141 ReleaseFrontTexture(); |
156 } | 142 } |
157 } | 143 } |
158 | 144 |
159 void* TextureImageTransportSurface::GetShareHandle() { | 145 void* TextureImageTransportSurface::GetShareHandle() { |
160 return GetHandle(); | 146 return GetHandle(); |
161 } | 147 } |
162 | 148 |
163 void* TextureImageTransportSurface::GetDisplay() { | 149 void* TextureImageTransportSurface::GetDisplay() { |
164 return surface_.get() ? surface_->GetDisplay() : NULL; | 150 return surface_.get() ? surface_->GetDisplay() : NULL; |
165 } | 151 } |
166 | 152 |
167 void* TextureImageTransportSurface::GetConfig() { | 153 void* TextureImageTransportSurface::GetConfig() { |
168 return surface_.get() ? surface_->GetConfig() : NULL; | 154 return surface_.get() ? surface_->GetConfig() : NULL; |
169 } | 155 } |
170 | 156 |
171 void TextureImageTransportSurface::OnResize(gfx::Size size) { | 157 void TextureImageTransportSurface::OnResize(gfx::Size size) { |
| 158 DCHECK_GE(size.width(), 1); |
| 159 DCHECK_GE(size.height(), 1); |
172 current_size_ = size; | 160 current_size_ = size; |
173 CreateBackTexture(); | 161 CreateBackTexture(); |
174 } | 162 } |
175 | 163 |
176 void TextureImageTransportSurface::OnWillDestroyStub() { | 164 void TextureImageTransportSurface::OnWillDestroyStub() { |
| 165 DCHECK(helper_->stub()->decoder()->GetGLContext()->IsCurrent(NULL)); |
177 helper_->stub()->RemoveDestructionObserver(this); | 166 helper_->stub()->RemoveDestructionObserver(this); |
178 | 167 |
179 GpuHostMsg_AcceleratedSurfaceRelease_Params params; | |
180 helper_->SendAcceleratedSurfaceRelease(params); | |
181 | |
182 ReleaseBackTexture(); | |
183 | |
184 // We are losing the stub owning us, this is our last chance to clean up the | 168 // We are losing the stub owning us, this is our last chance to clean up the |
185 // resources we allocated in the stub's context. | 169 // resources we allocated in the stub's context. |
| 170 ReleaseBackTexture(); |
| 171 ReleaseFrontTexture(); |
| 172 |
186 if (fbo_id_) { | 173 if (fbo_id_) { |
187 glDeleteFramebuffersEXT(1, &fbo_id_); | 174 glDeleteFramebuffersEXT(1, &fbo_id_); |
188 CHECK_GL_ERROR(); | 175 CHECK_GL_ERROR(); |
189 fbo_id_ = 0; | 176 fbo_id_ = 0; |
190 } | 177 } |
191 | 178 |
192 stub_destroyed_ = true; | 179 stub_destroyed_ = true; |
193 } | 180 } |
194 | 181 |
195 void TextureImageTransportSurface::SetLatencyInfo( | 182 void TextureImageTransportSurface::SetLatencyInfo( |
196 const cc::LatencyInfo& latency_info) { | 183 const cc::LatencyInfo& latency_info) { |
197 latency_info_ = latency_info; | 184 latency_info_ = latency_info; |
198 } | 185 } |
199 | 186 |
200 bool TextureImageTransportSurface::SwapBuffers() { | 187 bool TextureImageTransportSurface::SwapBuffers() { |
| 188 DCHECK(helper_->stub()->decoder()->GetGLContext()->IsCurrent(NULL)); |
201 DCHECK(backbuffer_suggested_allocation_); | 189 DCHECK(backbuffer_suggested_allocation_); |
202 | 190 |
203 if (!frontbuffer_suggested_allocation_) | 191 if (!frontbuffer_suggested_allocation_) |
204 return true; | 192 return true; |
205 | 193 |
206 if (!backbuffer_->service_id()) { | 194 if (!backbuffer_) { |
207 LOG(ERROR) << "Swap without valid backing."; | 195 LOG(ERROR) << "Swap without valid backing."; |
208 return true; | 196 return true; |
209 } | 197 } |
210 | 198 |
211 DCHECK(backbuffer_size() == current_size_); | 199 DCHECK(backbuffer_size() == current_size_); |
212 GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params; | 200 GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params; |
213 params.size = backbuffer_size(); | 201 params.size = backbuffer_size(); |
214 params.mailbox_name.assign( | 202 params.mailbox_name.assign( |
215 reinterpret_cast<const char*>(&mailbox_name_), sizeof(mailbox_name_)); | 203 reinterpret_cast<const char*>(&back_mailbox_name_), |
| 204 sizeof(back_mailbox_name_)); |
216 | 205 |
217 glFlush(); | 206 glFlush(); |
218 ProduceTexture(); | |
219 | |
220 // Do not allow destruction while we are still waiting for a swap ACK, | |
221 // so we do not leak a texture in the mailbox. | |
222 AddRef(); | |
223 | 207 |
224 params.latency_info = latency_info_; | 208 params.latency_info = latency_info_; |
225 helper_->SendAcceleratedSurfaceBuffersSwapped(params); | 209 helper_->SendAcceleratedSurfaceBuffersSwapped(params); |
226 | 210 |
227 DCHECK(!is_swap_buffers_pending_); | 211 DCHECK(!is_swap_buffers_pending_); |
228 is_swap_buffers_pending_ = true; | 212 is_swap_buffers_pending_ = true; |
229 return true; | 213 return true; |
230 } | 214 } |
231 | 215 |
232 bool TextureImageTransportSurface::PostSubBuffer( | 216 bool TextureImageTransportSurface::PostSubBuffer( |
233 int x, int y, int width, int height) { | 217 int x, int y, int width, int height) { |
| 218 DCHECK(helper_->stub()->decoder()->GetGLContext()->IsCurrent(NULL)); |
234 DCHECK(backbuffer_suggested_allocation_); | 219 DCHECK(backbuffer_suggested_allocation_); |
235 if (!frontbuffer_suggested_allocation_) | 220 if (!frontbuffer_suggested_allocation_) |
236 return true; | 221 return true; |
237 const gfx::Rect new_damage_rect(x, y, width, height); | 222 const gfx::Rect new_damage_rect(x, y, width, height); |
238 DCHECK(gfx::Rect(gfx::Point(), current_size_).Contains(new_damage_rect)); | 223 DCHECK(gfx::Rect(gfx::Point(), current_size_).Contains(new_damage_rect)); |
239 | 224 |
240 // An empty damage rect is a successful no-op. | 225 // An empty damage rect is a successful no-op. |
241 if (new_damage_rect.IsEmpty()) | 226 if (new_damage_rect.IsEmpty()) |
242 return true; | 227 return true; |
243 | 228 |
244 if (!backbuffer_->service_id()) { | 229 if (!backbuffer_) { |
245 LOG(ERROR) << "Swap without valid backing."; | 230 LOG(ERROR) << "Swap without valid backing."; |
246 return true; | 231 return true; |
247 } | 232 } |
248 | 233 |
249 DCHECK(current_size_ == backbuffer_size()); | 234 DCHECK(current_size_ == backbuffer_size()); |
250 GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params params; | 235 GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params params; |
251 params.surface_size = backbuffer_size(); | 236 params.surface_size = backbuffer_size(); |
252 params.x = x; | 237 params.x = x; |
253 params.y = y; | 238 params.y = y; |
254 params.width = width; | 239 params.width = width; |
255 params.height = height; | 240 params.height = height; |
256 params.mailbox_name.assign( | 241 params.mailbox_name.assign( |
257 reinterpret_cast<const char*>(&mailbox_name_), sizeof(mailbox_name_)); | 242 reinterpret_cast<const char*>(&back_mailbox_name_), |
| 243 sizeof(back_mailbox_name_)); |
258 | 244 |
259 glFlush(); | 245 glFlush(); |
260 ProduceTexture(); | |
261 | |
262 // Do not allow destruction while we are still waiting for a swap ACK, | |
263 // so we do not leak a texture in the mailbox. | |
264 AddRef(); | |
265 | 246 |
266 params.latency_info = latency_info_; | 247 params.latency_info = latency_info_; |
267 helper_->SendAcceleratedSurfacePostSubBuffer(params); | 248 helper_->SendAcceleratedSurfacePostSubBuffer(params); |
268 | 249 |
269 DCHECK(!is_swap_buffers_pending_); | 250 DCHECK(!is_swap_buffers_pending_); |
270 is_swap_buffers_pending_ = true; | 251 is_swap_buffers_pending_ = true; |
271 return true; | 252 return true; |
272 } | 253 } |
273 | 254 |
274 std::string TextureImageTransportSurface::GetExtensions() { | 255 std::string TextureImageTransportSurface::GetExtensions() { |
275 std::string extensions = gfx::GLSurface::GetExtensions(); | 256 std::string extensions = gfx::GLSurface::GetExtensions(); |
276 extensions += extensions.empty() ? "" : " "; | 257 extensions += extensions.empty() ? "" : " "; |
277 extensions += "GL_CHROMIUM_front_buffer_cached "; | 258 extensions += "GL_CHROMIUM_front_buffer_cached "; |
278 extensions += "GL_CHROMIUM_post_sub_buffer"; | 259 extensions += "GL_CHROMIUM_post_sub_buffer"; |
279 return extensions; | 260 return extensions; |
280 } | 261 } |
281 | 262 |
282 gfx::Size TextureImageTransportSurface::GetSize() { | 263 gfx::Size TextureImageTransportSurface::GetSize() { |
283 gfx::Size size = current_size_; | 264 return current_size_; |
284 | |
285 // OSMesa expects a non-zero size. | |
286 return gfx::Size(size.width() == 0 ? 1 : size.width(), | |
287 size.height() == 0 ? 1 : size.height()); | |
288 } | 265 } |
289 | 266 |
290 void* TextureImageTransportSurface::GetHandle() { | 267 void* TextureImageTransportSurface::GetHandle() { |
291 return surface_.get() ? surface_->GetHandle() : NULL; | 268 return surface_.get() ? surface_->GetHandle() : NULL; |
292 } | 269 } |
293 | 270 |
294 unsigned TextureImageTransportSurface::GetFormat() { | 271 unsigned TextureImageTransportSurface::GetFormat() { |
295 return surface_.get() ? surface_->GetFormat() : 0; | 272 return surface_.get() ? surface_->GetFormat() : 0; |
296 } | 273 } |
297 | 274 |
298 void TextureImageTransportSurface::OnBufferPresented( | 275 void TextureImageTransportSurface::OnBufferPresented( |
299 const AcceleratedSurfaceMsg_BufferPresented_Params& params) { | 276 const AcceleratedSurfaceMsg_BufferPresented_Params& params) { |
300 if (params.sync_point == 0) { | 277 if (params.sync_point == 0) { |
301 BufferPresentedImpl(params.mailbox_name); | 278 BufferPresentedImpl(params.mailbox_name); |
302 } else { | 279 } else { |
303 helper_->manager()->sync_point_manager()->AddSyncPointCallback( | 280 helper_->manager()->sync_point_manager()->AddSyncPointCallback( |
304 params.sync_point, | 281 params.sync_point, |
305 base::Bind(&TextureImageTransportSurface::BufferPresentedImpl, | 282 base::Bind(&TextureImageTransportSurface::BufferPresentedImpl, |
306 this, | 283 this, |
307 params.mailbox_name)); | 284 params.mailbox_name)); |
308 } | 285 } |
309 | |
310 // Careful, we might get deleted now if we were only waiting for | |
311 // a final swap ACK. | |
312 Release(); | |
313 } | 286 } |
314 | 287 |
315 void TextureImageTransportSurface::BufferPresentedImpl( | 288 void TextureImageTransportSurface::BufferPresentedImpl( |
316 const std::string& mailbox_name) { | 289 const std::string& mailbox_name) { |
317 DCHECK(!backbuffer_->service_id()); | |
318 if (!mailbox_name.empty()) { | |
319 DCHECK(mailbox_name.length() == GL_MAILBOX_SIZE_CHROMIUM); | |
320 mailbox_name.copy(reinterpret_cast<char *>(&mailbox_name_), | |
321 sizeof(MailboxName)); | |
322 ConsumeTexture(); | |
323 } | |
324 | |
325 if (stub_destroyed_ && backbuffer_->service_id()) { | |
326 // TODO(sievers): Remove this after changes to the mailbox to take ownership | |
327 // of the service ids. | |
328 DCHECK(context_.get() && surface_.get()); | |
329 uint32 service_id = backbuffer_->ReleaseServiceId(); | |
330 if (context_->MakeCurrent(surface_)) | |
331 glDeleteTextures(1, &service_id); | |
332 | |
333 return; | |
334 } | |
335 | |
336 DCHECK(is_swap_buffers_pending_); | 290 DCHECK(is_swap_buffers_pending_); |
337 is_swap_buffers_pending_ = false; | 291 is_swap_buffers_pending_ = false; |
338 | |
339 // We should not have allowed the backbuffer to be discarded while the ack | 292 // We should not have allowed the backbuffer to be discarded while the ack |
340 // was pending. | 293 // was pending. |
341 DCHECK(backbuffer_suggested_allocation_); | 294 DCHECK(backbuffer_suggested_allocation_); |
| 295 DCHECK(backbuffer_); |
| 296 |
| 297 bool swap = true; |
| 298 if (!mailbox_name.empty()) { |
| 299 DCHECK(mailbox_name.length() == GL_MAILBOX_SIZE_CHROMIUM); |
| 300 if (!memcmp(mailbox_name.data(), |
| 301 &back_mailbox_name_, |
| 302 mailbox_name.length())) { |
| 303 // The browser has skipped the frame to unblock the GPU process, waiting |
| 304 // for one of the right size, and returned the back buffer, so don't swap. |
| 305 swap = false; |
| 306 } |
| 307 } |
| 308 if (swap) { |
| 309 std::swap(backbuffer_, frontbuffer_); |
| 310 std::swap(back_mailbox_name_, front_mailbox_name_); |
| 311 } |
342 | 312 |
343 // We're relying on the fact that the parent context is | 313 // We're relying on the fact that the parent context is |
344 // finished with it's context when it inserts the sync point that | 314 // finished with its context when it inserts the sync point that |
345 // triggers this callback. | 315 // triggers this callback. |
346 if (helper_->MakeCurrent()) { | 316 if (helper_->MakeCurrent()) { |
347 if (backbuffer_size() != current_size_ || !backbuffer_->service_id()) | 317 if (frontbuffer_ && !frontbuffer_suggested_allocation_) |
| 318 ReleaseFrontTexture(); |
| 319 if (!backbuffer_ || backbuffer_size() != current_size_) |
348 CreateBackTexture(); | 320 CreateBackTexture(); |
349 else | 321 else |
350 AttachBackTextureToFBO(); | 322 AttachBackTextureToFBO(); |
351 } | 323 } |
352 | 324 |
353 // Even if MakeCurrent fails, schedule anyway, to trigger the lost context | 325 // Even if MakeCurrent fails, schedule anyway, to trigger the lost context |
354 // logic. | 326 // logic. |
355 if (did_unschedule_) { | 327 if (did_unschedule_) { |
356 did_unschedule_ = false; | 328 did_unschedule_ = false; |
357 helper_->SetScheduled(true); | 329 helper_->SetScheduled(true); |
358 } | 330 } |
359 } | 331 } |
360 | 332 |
361 void TextureImageTransportSurface::OnResizeViewACK() { | 333 void TextureImageTransportSurface::OnResizeViewACK() { |
362 NOTREACHED(); | 334 NOTREACHED(); |
363 } | 335 } |
364 | 336 |
365 void TextureImageTransportSurface::ReleaseBackTexture() { | 337 void TextureImageTransportSurface::ReleaseBackTexture() { |
366 if (!backbuffer_->service_id()) | 338 DCHECK(helper_->stub()->decoder()->GetGLContext()->IsCurrent(NULL)); |
367 return; | 339 backbuffer_ = NULL; |
368 | 340 back_mailbox_name_ = MailboxName(); |
369 uint32 service_id = backbuffer_->ReleaseServiceId(); | |
370 glDeleteTextures(1, &service_id); | |
371 backbuffer_.reset(CreateTextureDefinition(gfx::Size(), 0)); | |
372 mailbox_name_ = MailboxName(); | |
373 glFlush(); | 341 glFlush(); |
374 CHECK_GL_ERROR(); | 342 CHECK_GL_ERROR(); |
375 } | 343 } |
376 | 344 |
| 345 void TextureImageTransportSurface::ReleaseFrontTexture() { |
| 346 DCHECK(helper_->stub()->decoder()->GetGLContext()->IsCurrent(NULL)); |
| 347 frontbuffer_ = NULL; |
| 348 front_mailbox_name_ = MailboxName(); |
| 349 glFlush(); |
| 350 CHECK_GL_ERROR(); |
| 351 GpuHostMsg_AcceleratedSurfaceRelease_Params params; |
| 352 helper_->SendAcceleratedSurfaceRelease(params); |
| 353 } |
| 354 |
377 void TextureImageTransportSurface::CreateBackTexture() { | 355 void TextureImageTransportSurface::CreateBackTexture() { |
| 356 DCHECK(helper_->stub()->decoder()->GetGLContext()->IsCurrent(NULL)); |
378 // If |is_swap_buffers_pending| we are waiting for our backbuffer | 357 // If |is_swap_buffers_pending| we are waiting for our backbuffer |
379 // in the mailbox, so we shouldn't be reallocating it now. | 358 // in the mailbox, so we shouldn't be reallocating it now. |
380 DCHECK(!is_swap_buffers_pending_); | 359 DCHECK(!is_swap_buffers_pending_); |
381 | 360 |
382 if (backbuffer_->service_id() && backbuffer_size() == current_size_) | 361 if (backbuffer_ && backbuffer_size() == current_size_) |
383 return; | 362 return; |
384 | 363 |
385 uint32 service_id = backbuffer_->ReleaseServiceId(); | |
386 | |
387 VLOG(1) << "Allocating new backbuffer texture"; | 364 VLOG(1) << "Allocating new backbuffer texture"; |
388 | 365 |
389 // On Qualcomm we couldn't resize an FBO texture past a certain | 366 // On Qualcomm we couldn't resize an FBO texture past a certain |
390 // size, after we allocated it as 1x1. So here we simply delete | 367 // size, after we allocated it as 1x1. So here we simply delete |
391 // the previous texture on resize, to insure we don't 'run out of | 368 // the previous texture on resize, to insure we don't 'run out of |
392 // memory'. | 369 // memory'. |
393 if (service_id && | 370 if (backbuffer_ && |
394 helper_->stub() | 371 helper_->stub() |
395 ->decoder() | 372 ->decoder() |
396 ->GetContextGroup() | 373 ->GetContextGroup() |
397 ->feature_info() | 374 ->feature_info() |
398 ->workarounds() | 375 ->workarounds() |
399 .delete_instead_of_resize_fbo) { | 376 .delete_instead_of_resize_fbo) { |
400 glDeleteTextures(1, &service_id); | 377 ReleaseBackTexture(); |
401 service_id = 0; | 378 } |
402 mailbox_name_ = MailboxName(); | 379 GLES2Decoder* decoder = helper_->stub()->decoder(); |
| 380 TextureManager* texture_manager = |
| 381 decoder->GetContextGroup()->texture_manager(); |
| 382 if (!backbuffer_) { |
| 383 mailbox_manager_->GenerateMailboxName(&back_mailbox_name_); |
| 384 GLuint service_id; |
| 385 glGenTextures(1, &service_id); |
| 386 backbuffer_ = TextureRef::Create(texture_manager, 0, service_id); |
| 387 texture_manager->SetTarget(backbuffer_, GL_TEXTURE_2D); |
| 388 Texture* texture = texture_manager->Produce(backbuffer_); |
| 389 bool success = mailbox_manager_->ProduceTexture( |
| 390 GL_TEXTURE_2D, back_mailbox_name_, texture); |
| 391 DCHECK(success); |
403 } | 392 } |
404 | 393 |
405 if (!service_id) { | |
406 MailboxName new_mailbox_name; | |
407 MailboxName& name = mailbox_name_; | |
408 // This slot should be uninitialized. | |
409 DCHECK(!memcmp(&name, &new_mailbox_name, sizeof(MailboxName))); | |
410 mailbox_manager_->GenerateMailboxName(&new_mailbox_name); | |
411 name = new_mailbox_name; | |
412 glGenTextures(1, &service_id); | |
413 } | |
414 | |
415 backbuffer_.reset( | |
416 CreateTextureDefinition(current_size_, service_id)); | |
417 | |
418 { | 394 { |
419 gfx::ScopedTextureBinder texture_binder(GL_TEXTURE_2D, service_id); | 395 gfx::ScopedTextureBinder texture_binder(GL_TEXTURE_2D, |
420 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | 396 backbuffer_->service_id()); |
421 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | |
422 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | |
423 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | |
424 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, | 397 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, |
425 current_size_.width(), current_size_.height(), 0, | 398 current_size_.width(), current_size_.height(), 0, |
426 GL_RGBA, GL_UNSIGNED_BYTE, NULL); | 399 GL_RGBA, GL_UNSIGNED_BYTE, NULL); |
| 400 gpu::gles2::ErrorState* error_state = decoder->GetErrorState(); |
| 401 texture_manager->SetParameter("Backbuffer", error_state, backbuffer_, |
| 402 GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
| 403 texture_manager->SetParameter("Backbuffer", error_state, backbuffer_, |
| 404 GL_TEXTURE_MAG_FILTER, GL_LINEAR); |
| 405 texture_manager->SetParameter("Backbuffer", error_state, backbuffer_, |
| 406 GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
| 407 texture_manager->SetParameter("Backbuffer", error_state, backbuffer_, |
| 408 GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
| 409 texture_manager->SetLevelInfo( |
| 410 backbuffer_, |
| 411 GL_TEXTURE_2D, |
| 412 0, |
| 413 GL_RGBA, |
| 414 current_size_.width(), |
| 415 current_size_.height(), |
| 416 1, |
| 417 0, |
| 418 GL_RGBA, |
| 419 GL_UNSIGNED_BYTE, |
| 420 true); |
| 421 DCHECK(texture_manager->CanRender(backbuffer_)); |
427 CHECK_GL_ERROR(); | 422 CHECK_GL_ERROR(); |
428 } | 423 } |
429 | 424 |
430 AttachBackTextureToFBO(); | 425 AttachBackTextureToFBO(); |
431 } | 426 } |
432 | 427 |
433 void TextureImageTransportSurface::AttachBackTextureToFBO() { | 428 void TextureImageTransportSurface::AttachBackTextureToFBO() { |
434 DCHECK(backbuffer_->service_id()); | 429 DCHECK(helper_->stub()->decoder()->GetGLContext()->IsCurrent(NULL)); |
| 430 DCHECK(backbuffer_); |
435 gfx::ScopedFrameBufferBinder fbo_binder(fbo_id_); | 431 gfx::ScopedFrameBufferBinder fbo_binder(fbo_id_); |
436 glFramebufferTexture2DEXT(GL_FRAMEBUFFER, | 432 glFramebufferTexture2DEXT(GL_FRAMEBUFFER, |
437 GL_COLOR_ATTACHMENT0, | 433 GL_COLOR_ATTACHMENT0, |
438 GL_TEXTURE_2D, | 434 GL_TEXTURE_2D, |
439 backbuffer_->service_id(), | 435 backbuffer_->service_id(), |
440 0); | 436 0); |
441 CHECK_GL_ERROR(); | 437 CHECK_GL_ERROR(); |
442 | 438 |
443 #ifndef NDEBUG | 439 #ifndef NDEBUG |
444 GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER); | 440 GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER); |
445 if (status != GL_FRAMEBUFFER_COMPLETE) { | 441 if (status != GL_FRAMEBUFFER_COMPLETE) { |
446 DLOG(FATAL) << "Framebuffer incomplete: " << status; | 442 DLOG(FATAL) << "Framebuffer incomplete: " << status; |
447 } | 443 } |
448 #endif | 444 #endif |
449 } | 445 } |
450 | 446 |
451 TextureDefinition* TextureImageTransportSurface::CreateTextureDefinition( | |
452 gfx::Size size, int service_id) { | |
453 TextureDefinition::LevelInfo info( | |
454 GL_TEXTURE_2D, GL_RGBA, size.width(), size.height(), 1, | |
455 0, GL_RGBA, GL_UNSIGNED_BYTE, true); | |
456 | |
457 TextureDefinition::LevelInfos level_infos; | |
458 level_infos.resize(1); | |
459 level_infos[0].resize(1); | |
460 level_infos[0][0] = info; | |
461 return new TextureDefinition( | |
462 GL_TEXTURE_2D, | |
463 service_id, | |
464 GL_LINEAR, | |
465 GL_LINEAR, | |
466 GL_CLAMP_TO_EDGE, | |
467 GL_CLAMP_TO_EDGE, | |
468 GL_NONE, | |
469 true, | |
470 false, | |
471 level_infos); | |
472 } | |
473 | |
474 void TextureImageTransportSurface::ConsumeTexture() { | |
475 DCHECK(!backbuffer_->service_id()); | |
476 | |
477 backbuffer_.reset(mailbox_manager_->ConsumeTexture( | |
478 GL_TEXTURE_2D, mailbox_name_)); | |
479 if (!backbuffer_) { | |
480 mailbox_name_ = MailboxName(); | |
481 backbuffer_.reset(CreateTextureDefinition(gfx::Size(), 0)); | |
482 } | |
483 } | |
484 | |
485 void TextureImageTransportSurface::ProduceTexture() { | |
486 DCHECK(backbuffer_->service_id()); | |
487 DCHECK(!backbuffer_size().IsEmpty()); | |
488 | |
489 // Pass NULL as |owner| here to avoid errors from glConsumeTextureCHROMIUM() | |
490 // when the renderer context group goes away before the RWHV handles a pending | |
491 // ACK. We avoid leaking a texture in the mailbox by waiting for the final ACK | |
492 // at which point we consume the correct texture back. | |
493 bool success = mailbox_manager_->ProduceTexture( | |
494 GL_TEXTURE_2D, | |
495 mailbox_name_, | |
496 backbuffer_.release(), | |
497 NULL); | |
498 DCHECK(success); | |
499 mailbox_name_ = MailboxName(); | |
500 backbuffer_.reset(CreateTextureDefinition(gfx::Size(), 0)); | |
501 } | |
502 | |
503 } // namespace content | 447 } // namespace content |
OLD | NEW |