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_) { | |
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_) { | 101 if (!fbo_id_) { |
113 glGenFramebuffersEXT(1, &fbo_id_); | 102 glGenFramebuffersEXT(1, &fbo_id_); |
114 glBindFramebufferEXT(GL_FRAMEBUFFER, fbo_id_); | 103 glBindFramebufferEXT(GL_FRAMEBUFFER, fbo_id_); |
115 current_size_ = gfx::Size(1, 1); | |
116 helper_->stub()->AddDestructionObserver(this); | 104 helper_->stub()->AddDestructionObserver(this); |
105 CreateBackTexture(); | |
117 } | 106 } |
118 | 107 |
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(); | |
piman
2013/05/23 02:33:01
note: Construction moved to GetBackingFrameBufferO
| |
124 } | |
125 return true; | |
126 } | |
127 | |
128 unsigned int TextureImageTransportSurface::GetBackingFrameBufferObject() { | |
129 return fbo_id_; | 108 return fbo_id_; |
130 } | 109 } |
131 | 110 |
132 bool TextureImageTransportSurface::SetBackbufferAllocation(bool allocation) { | 111 bool TextureImageTransportSurface::SetBackbufferAllocation(bool allocation) { |
133 DCHECK(!is_swap_buffers_pending_); | 112 DCHECK(!is_swap_buffers_pending_); |
134 if (backbuffer_suggested_allocation_ == allocation) | 113 if (backbuffer_suggested_allocation_ == allocation) |
135 return true; | 114 return true; |
136 backbuffer_suggested_allocation_ = allocation; | 115 backbuffer_suggested_allocation_ = allocation; |
137 | 116 |
138 if (backbuffer_suggested_allocation_) { | 117 if (backbuffer_suggested_allocation_) { |
139 DCHECK(!backbuffer_->service_id()); | 118 DCHECK(!backbuffer_); |
140 CreateBackTexture(); | 119 CreateBackTexture(); |
141 } else { | 120 } else { |
142 ReleaseBackTexture(); | 121 ReleaseBackTexture(); |
143 } | 122 } |
144 | 123 |
145 return true; | 124 return true; |
146 } | 125 } |
147 | 126 |
148 void TextureImageTransportSurface::SetFrontbufferAllocation(bool allocation) { | 127 void TextureImageTransportSurface::SetFrontbufferAllocation(bool allocation) { |
149 if (frontbuffer_suggested_allocation_ == allocation) | 128 if (frontbuffer_suggested_allocation_ == allocation) |
150 return; | 129 return; |
151 frontbuffer_suggested_allocation_ = allocation; | 130 frontbuffer_suggested_allocation_ = allocation; |
152 | 131 |
153 if (!frontbuffer_suggested_allocation_) { | 132 // If a swapbuffers is in flight, wait for the ack before releasing the front |
154 GpuHostMsg_AcceleratedSurfaceRelease_Params params; | 133 // buffer: |
155 helper_->SendAcceleratedSurfaceRelease(params); | 134 // - we don't know yet which texture the browser will want to keep |
135 // - we want to ensure we don't destroy a texture that is in flight before the | |
136 // browser got a reference on it. | |
137 if (!frontbuffer_suggested_allocation_ && | |
138 !is_swap_buffers_pending_ && | |
139 helper_->MakeCurrent()) { | |
140 ReleaseFrontTexture(); | |
156 } | 141 } |
157 } | 142 } |
158 | 143 |
159 void* TextureImageTransportSurface::GetShareHandle() { | 144 void* TextureImageTransportSurface::GetShareHandle() { |
160 return GetHandle(); | 145 return GetHandle(); |
161 } | 146 } |
162 | 147 |
163 void* TextureImageTransportSurface::GetDisplay() { | 148 void* TextureImageTransportSurface::GetDisplay() { |
164 return surface_.get() ? surface_->GetDisplay() : NULL; | 149 return surface_.get() ? surface_->GetDisplay() : NULL; |
165 } | 150 } |
166 | 151 |
167 void* TextureImageTransportSurface::GetConfig() { | 152 void* TextureImageTransportSurface::GetConfig() { |
168 return surface_.get() ? surface_->GetConfig() : NULL; | 153 return surface_.get() ? surface_->GetConfig() : NULL; |
169 } | 154 } |
170 | 155 |
171 void TextureImageTransportSurface::OnResize(gfx::Size size) { | 156 void TextureImageTransportSurface::OnResize(gfx::Size size) { |
157 DCHECK_GE(size.width(), 1); | |
158 DCHECK_GE(size.height(), 1); | |
172 current_size_ = size; | 159 current_size_ = size; |
173 CreateBackTexture(); | 160 CreateBackTexture(); |
174 } | 161 } |
175 | 162 |
176 void TextureImageTransportSurface::OnWillDestroyStub() { | 163 void TextureImageTransportSurface::OnWillDestroyStub() { |
177 helper_->stub()->RemoveDestructionObserver(this); | 164 helper_->stub()->RemoveDestructionObserver(this); |
178 | 165 |
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 | 166 // 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. | 167 // resources we allocated in the stub's context. |
168 ReleaseBackTexture(); | |
169 ReleaseFrontTexture(); | |
170 | |
186 if (fbo_id_) { | 171 if (fbo_id_) { |
187 glDeleteFramebuffersEXT(1, &fbo_id_); | 172 glDeleteFramebuffersEXT(1, &fbo_id_); |
188 CHECK_GL_ERROR(); | 173 CHECK_GL_ERROR(); |
189 fbo_id_ = 0; | 174 fbo_id_ = 0; |
190 } | 175 } |
191 | 176 |
192 stub_destroyed_ = true; | 177 stub_destroyed_ = true; |
193 } | 178 } |
194 | 179 |
195 void TextureImageTransportSurface::SetLatencyInfo( | 180 void TextureImageTransportSurface::SetLatencyInfo( |
196 const cc::LatencyInfo& latency_info) { | 181 const cc::LatencyInfo& latency_info) { |
197 latency_info_ = latency_info; | 182 latency_info_ = latency_info; |
198 } | 183 } |
199 | 184 |
200 bool TextureImageTransportSurface::SwapBuffers() { | 185 bool TextureImageTransportSurface::SwapBuffers() { |
201 DCHECK(backbuffer_suggested_allocation_); | 186 DCHECK(backbuffer_suggested_allocation_); |
202 | 187 |
203 if (!frontbuffer_suggested_allocation_) | 188 if (!frontbuffer_suggested_allocation_) |
204 return true; | 189 return true; |
205 | 190 |
206 if (!backbuffer_->service_id()) { | 191 if (!backbuffer_) { |
207 LOG(ERROR) << "Swap without valid backing."; | 192 LOG(ERROR) << "Swap without valid backing."; |
208 return true; | 193 return true; |
209 } | 194 } |
210 | 195 |
211 DCHECK(backbuffer_size() == current_size_); | 196 DCHECK(backbuffer_size() == current_size_); |
212 GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params; | 197 GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params; |
213 params.size = backbuffer_size(); | 198 params.size = backbuffer_size(); |
214 params.mailbox_name.assign( | 199 params.mailbox_name.assign( |
215 reinterpret_cast<const char*>(&mailbox_name_), sizeof(mailbox_name_)); | 200 reinterpret_cast<const char*>(&back_mailbox_name_), |
201 sizeof(back_mailbox_name_)); | |
216 | 202 |
217 glFlush(); | 203 glFlush(); |
greggman
2013/05/23 17:36:19
This is probably a dumb question since I'm not cle
piman
2013/05/23 18:02:38
SwapBuffers and SetBackbufferAllocation are called
piman
2013/05/24 02:32:22
Added a bunch of DCHECKs in functions that call GL
| |
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 | 204 |
224 params.latency_info = latency_info_; | 205 params.latency_info = latency_info_; |
225 helper_->SendAcceleratedSurfaceBuffersSwapped(params); | 206 helper_->SendAcceleratedSurfaceBuffersSwapped(params); |
226 | 207 |
227 DCHECK(!is_swap_buffers_pending_); | 208 DCHECK(!is_swap_buffers_pending_); |
228 is_swap_buffers_pending_ = true; | 209 is_swap_buffers_pending_ = true; |
229 return true; | 210 return true; |
230 } | 211 } |
231 | 212 |
232 bool TextureImageTransportSurface::PostSubBuffer( | 213 bool TextureImageTransportSurface::PostSubBuffer( |
233 int x, int y, int width, int height) { | 214 int x, int y, int width, int height) { |
234 DCHECK(backbuffer_suggested_allocation_); | 215 DCHECK(backbuffer_suggested_allocation_); |
235 if (!frontbuffer_suggested_allocation_) | 216 if (!frontbuffer_suggested_allocation_) |
236 return true; | 217 return true; |
237 const gfx::Rect new_damage_rect(x, y, width, height); | 218 const gfx::Rect new_damage_rect(x, y, width, height); |
238 DCHECK(gfx::Rect(gfx::Point(), current_size_).Contains(new_damage_rect)); | 219 DCHECK(gfx::Rect(gfx::Point(), current_size_).Contains(new_damage_rect)); |
239 | 220 |
240 // An empty damage rect is a successful no-op. | 221 // An empty damage rect is a successful no-op. |
241 if (new_damage_rect.IsEmpty()) | 222 if (new_damage_rect.IsEmpty()) |
242 return true; | 223 return true; |
243 | 224 |
244 if (!backbuffer_->service_id()) { | 225 if (!backbuffer_) { |
245 LOG(ERROR) << "Swap without valid backing."; | 226 LOG(ERROR) << "Swap without valid backing."; |
246 return true; | 227 return true; |
247 } | 228 } |
248 | 229 |
249 DCHECK(current_size_ == backbuffer_size()); | 230 DCHECK(current_size_ == backbuffer_size()); |
250 GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params params; | 231 GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params params; |
251 params.surface_size = backbuffer_size(); | 232 params.surface_size = backbuffer_size(); |
252 params.x = x; | 233 params.x = x; |
253 params.y = y; | 234 params.y = y; |
254 params.width = width; | 235 params.width = width; |
255 params.height = height; | 236 params.height = height; |
256 params.mailbox_name.assign( | 237 params.mailbox_name.assign( |
257 reinterpret_cast<const char*>(&mailbox_name_), sizeof(mailbox_name_)); | 238 reinterpret_cast<const char*>(&back_mailbox_name_), |
239 sizeof(back_mailbox_name_)); | |
258 | 240 |
259 glFlush(); | 241 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 | 242 |
266 params.latency_info = latency_info_; | 243 params.latency_info = latency_info_; |
267 helper_->SendAcceleratedSurfacePostSubBuffer(params); | 244 helper_->SendAcceleratedSurfacePostSubBuffer(params); |
268 | 245 |
269 DCHECK(!is_swap_buffers_pending_); | 246 DCHECK(!is_swap_buffers_pending_); |
270 is_swap_buffers_pending_ = true; | 247 is_swap_buffers_pending_ = true; |
271 return true; | 248 return true; |
272 } | 249 } |
273 | 250 |
274 std::string TextureImageTransportSurface::GetExtensions() { | 251 std::string TextureImageTransportSurface::GetExtensions() { |
275 std::string extensions = gfx::GLSurface::GetExtensions(); | 252 std::string extensions = gfx::GLSurface::GetExtensions(); |
276 extensions += extensions.empty() ? "" : " "; | 253 extensions += extensions.empty() ? "" : " "; |
277 extensions += "GL_CHROMIUM_front_buffer_cached "; | 254 extensions += "GL_CHROMIUM_front_buffer_cached "; |
278 extensions += "GL_CHROMIUM_post_sub_buffer"; | 255 extensions += "GL_CHROMIUM_post_sub_buffer"; |
279 return extensions; | 256 return extensions; |
280 } | 257 } |
281 | 258 |
282 gfx::Size TextureImageTransportSurface::GetSize() { | 259 gfx::Size TextureImageTransportSurface::GetSize() { |
283 gfx::Size size = current_size_; | 260 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 } | 261 } |
289 | 262 |
290 void* TextureImageTransportSurface::GetHandle() { | 263 void* TextureImageTransportSurface::GetHandle() { |
291 return surface_.get() ? surface_->GetHandle() : NULL; | 264 return surface_.get() ? surface_->GetHandle() : NULL; |
292 } | 265 } |
293 | 266 |
294 unsigned TextureImageTransportSurface::GetFormat() { | 267 unsigned TextureImageTransportSurface::GetFormat() { |
295 return surface_.get() ? surface_->GetFormat() : 0; | 268 return surface_.get() ? surface_->GetFormat() : 0; |
296 } | 269 } |
297 | 270 |
298 void TextureImageTransportSurface::OnBufferPresented( | 271 void TextureImageTransportSurface::OnBufferPresented( |
299 const AcceleratedSurfaceMsg_BufferPresented_Params& params) { | 272 const AcceleratedSurfaceMsg_BufferPresented_Params& params) { |
300 if (params.sync_point == 0) { | 273 if (params.sync_point == 0) { |
301 BufferPresentedImpl(params.mailbox_name); | 274 BufferPresentedImpl(params.mailbox_name); |
302 } else { | 275 } else { |
303 helper_->manager()->sync_point_manager()->AddSyncPointCallback( | 276 helper_->manager()->sync_point_manager()->AddSyncPointCallback( |
304 params.sync_point, | 277 params.sync_point, |
305 base::Bind(&TextureImageTransportSurface::BufferPresentedImpl, | 278 base::Bind(&TextureImageTransportSurface::BufferPresentedImpl, |
306 this, | 279 this, |
307 params.mailbox_name)); | 280 params.mailbox_name)); |
308 } | 281 } |
309 | |
310 // Careful, we might get deleted now if we were only waiting for | |
311 // a final swap ACK. | |
312 Release(); | |
313 } | 282 } |
314 | 283 |
315 void TextureImageTransportSurface::BufferPresentedImpl( | 284 void TextureImageTransportSurface::BufferPresentedImpl( |
316 const std::string& mailbox_name) { | 285 const std::string& mailbox_name) { |
317 DCHECK(!backbuffer_->service_id()); | 286 bool swap = true; |
318 if (!mailbox_name.empty()) { | 287 if (backbuffer_ && !mailbox_name.empty()) { |
no sievers
2013/05/24 01:31:38
When would backbuffer_ ever be invalid here?
We ca
piman
2013/05/24 02:32:22
I can't remember why I did this originally (I had
| |
319 DCHECK(mailbox_name.length() == GL_MAILBOX_SIZE_CHROMIUM); | 288 DCHECK(mailbox_name.length() == GL_MAILBOX_SIZE_CHROMIUM); |
320 mailbox_name.copy(reinterpret_cast<char *>(&mailbox_name_), | 289 |
321 sizeof(MailboxName)); | 290 MailboxName name; |
322 ConsumeTexture(); | 291 mailbox_name.copy(reinterpret_cast<char *>(&name), sizeof(MailboxName)); |
292 if (!memcmp(&name, &back_mailbox_name_, sizeof(name))) | |
no sievers
2013/05/24 01:31:38
nit: maybe comment that the browser skipped/return
piman
2013/05/24 02:32:22
Done. (also simplified a bit, I don't need to copy
| |
293 swap = false; | |
323 } | 294 } |
324 | 295 if (swap) { |
325 if (stub_destroyed_ && backbuffer_->service_id()) { | 296 std::swap(backbuffer_, frontbuffer_); |
326 // TODO(sievers): Remove this after changes to the mailbox to take ownership | 297 std::swap(back_mailbox_name_, front_mailbox_name_); |
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 } | 298 } |
335 | 299 |
336 DCHECK(is_swap_buffers_pending_); | 300 DCHECK(is_swap_buffers_pending_); |
337 is_swap_buffers_pending_ = false; | 301 is_swap_buffers_pending_ = false; |
338 | 302 |
339 // We should not have allowed the backbuffer to be discarded while the ack | 303 // We should not have allowed the backbuffer to be discarded while the ack |
340 // was pending. | 304 // was pending. |
341 DCHECK(backbuffer_suggested_allocation_); | 305 DCHECK(backbuffer_suggested_allocation_); |
342 | 306 |
343 // We're relying on the fact that the parent context is | 307 // We're relying on the fact that the parent context is |
344 // finished with it's context when it inserts the sync point that | 308 // finished with its context when it inserts the sync point that |
345 // triggers this callback. | 309 // triggers this callback. |
346 if (helper_->MakeCurrent()) { | 310 if (helper_->MakeCurrent()) { |
347 if (backbuffer_size() != current_size_ || !backbuffer_->service_id()) | 311 if (frontbuffer_ && !frontbuffer_suggested_allocation_) |
312 ReleaseFrontTexture(); | |
313 if (!backbuffer_ || backbuffer_size() != current_size_) | |
348 CreateBackTexture(); | 314 CreateBackTexture(); |
349 else | 315 else |
350 AttachBackTextureToFBO(); | 316 AttachBackTextureToFBO(); |
351 } | 317 } |
352 | 318 |
353 // Even if MakeCurrent fails, schedule anyway, to trigger the lost context | 319 // Even if MakeCurrent fails, schedule anyway, to trigger the lost context |
354 // logic. | 320 // logic. |
355 if (did_unschedule_) { | 321 if (did_unschedule_) { |
356 did_unschedule_ = false; | 322 did_unschedule_ = false; |
357 helper_->SetScheduled(true); | 323 helper_->SetScheduled(true); |
358 } | 324 } |
359 } | 325 } |
360 | 326 |
361 void TextureImageTransportSurface::OnResizeViewACK() { | 327 void TextureImageTransportSurface::OnResizeViewACK() { |
362 NOTREACHED(); | 328 NOTREACHED(); |
363 } | 329 } |
364 | 330 |
365 void TextureImageTransportSurface::ReleaseBackTexture() { | 331 void TextureImageTransportSurface::ReleaseBackTexture() { |
366 if (!backbuffer_->service_id()) | 332 backbuffer_ = NULL; |
367 return; | 333 back_mailbox_name_ = MailboxName(); |
368 | |
369 uint32 service_id = backbuffer_->ReleaseServiceId(); | |
370 glDeleteTextures(1, &service_id); | |
371 backbuffer_.reset(CreateTextureDefinition(gfx::Size(), 0)); | |
372 mailbox_name_ = MailboxName(); | |
373 glFlush(); | 334 glFlush(); |
374 CHECK_GL_ERROR(); | 335 CHECK_GL_ERROR(); |
375 } | 336 } |
376 | 337 |
338 void TextureImageTransportSurface::ReleaseFrontTexture() { | |
339 frontbuffer_ = NULL; | |
340 front_mailbox_name_ = MailboxName(); | |
341 glFlush(); | |
342 CHECK_GL_ERROR(); | |
343 GpuHostMsg_AcceleratedSurfaceRelease_Params params; | |
344 helper_->SendAcceleratedSurfaceRelease(params); | |
345 } | |
346 | |
377 void TextureImageTransportSurface::CreateBackTexture() { | 347 void TextureImageTransportSurface::CreateBackTexture() { |
378 // If |is_swap_buffers_pending| we are waiting for our backbuffer | 348 // If |is_swap_buffers_pending| we are waiting for our backbuffer |
379 // in the mailbox, so we shouldn't be reallocating it now. | 349 // in the mailbox, so we shouldn't be reallocating it now. |
380 DCHECK(!is_swap_buffers_pending_); | 350 DCHECK(!is_swap_buffers_pending_); |
381 | 351 |
382 if (backbuffer_->service_id() && backbuffer_size() == current_size_) | 352 if (backbuffer_ && backbuffer_size() == current_size_) |
383 return; | 353 return; |
384 | 354 |
385 uint32 service_id = backbuffer_->ReleaseServiceId(); | |
386 | |
387 VLOG(1) << "Allocating new backbuffer texture"; | 355 VLOG(1) << "Allocating new backbuffer texture"; |
388 | 356 |
389 // On Qualcomm we couldn't resize an FBO texture past a certain | 357 // 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 | 358 // 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 | 359 // the previous texture on resize, to insure we don't 'run out of |
392 // memory'. | 360 // memory'. |
393 if (service_id && | 361 if (backbuffer_ && |
394 helper_->stub() | 362 helper_->stub() |
395 ->decoder() | 363 ->decoder() |
396 ->GetContextGroup() | 364 ->GetContextGroup() |
397 ->feature_info() | 365 ->feature_info() |
398 ->workarounds() | 366 ->workarounds() |
399 .delete_instead_of_resize_fbo) { | 367 .delete_instead_of_resize_fbo) { |
400 glDeleteTextures(1, &service_id); | 368 ReleaseBackTexture(); |
401 service_id = 0; | 369 } |
402 mailbox_name_ = MailboxName(); | 370 GLES2Decoder* decoder = helper_->stub()->decoder(); |
371 TextureManager* texture_manager = | |
372 decoder->GetContextGroup()->texture_manager(); | |
373 if (!backbuffer_) { | |
374 mailbox_manager_->GenerateMailboxName(&back_mailbox_name_); | |
375 GLuint service_id; | |
376 glGenTextures(1, &service_id); | |
377 backbuffer_ = TextureRef::Create(texture_manager, 0, service_id); | |
378 texture_manager->SetTarget(backbuffer_, GL_TEXTURE_2D); | |
379 Texture* texture = texture_manager->Produce(backbuffer_); | |
380 bool success = mailbox_manager_->ProduceTexture( | |
381 GL_TEXTURE_2D, back_mailbox_name_, texture); | |
382 DCHECK(success); | |
403 } | 383 } |
404 | 384 |
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 { | 385 { |
419 gfx::ScopedTextureBinder texture_binder(GL_TEXTURE_2D, service_id); | 386 gfx::ScopedTextureBinder texture_binder(GL_TEXTURE_2D, |
420 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | 387 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, | 388 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, |
425 current_size_.width(), current_size_.height(), 0, | 389 current_size_.width(), current_size_.height(), 0, |
426 GL_RGBA, GL_UNSIGNED_BYTE, NULL); | 390 GL_RGBA, GL_UNSIGNED_BYTE, NULL); |
391 gpu::gles2::ErrorState* error_state = decoder->GetErrorState(); | |
392 texture_manager->SetParameter("Backbuffer", error_state, backbuffer_, | |
393 GL_TEXTURE_MIN_FILTER, GL_LINEAR); | |
394 texture_manager->SetParameter("Backbuffer", error_state, backbuffer_, | |
395 GL_TEXTURE_MAG_FILTER, GL_LINEAR); | |
396 texture_manager->SetParameter("Backbuffer", error_state, backbuffer_, | |
397 GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | |
398 texture_manager->SetParameter("Backbuffer", error_state, backbuffer_, | |
399 GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | |
400 texture_manager->SetLevelInfo( | |
401 backbuffer_, | |
402 GL_TEXTURE_2D, | |
403 0, | |
404 GL_RGBA, | |
405 current_size_.width(), | |
406 current_size_.height(), | |
407 1, | |
408 0, | |
409 GL_RGBA, | |
410 GL_UNSIGNED_BYTE, | |
411 true); | |
412 DCHECK(texture_manager->CanRender(backbuffer_)); | |
427 CHECK_GL_ERROR(); | 413 CHECK_GL_ERROR(); |
428 } | 414 } |
429 | 415 |
430 AttachBackTextureToFBO(); | 416 AttachBackTextureToFBO(); |
431 } | 417 } |
432 | 418 |
433 void TextureImageTransportSurface::AttachBackTextureToFBO() { | 419 void TextureImageTransportSurface::AttachBackTextureToFBO() { |
434 DCHECK(backbuffer_->service_id()); | 420 DCHECK(backbuffer_->service_id()); |
435 gfx::ScopedFrameBufferBinder fbo_binder(fbo_id_); | 421 gfx::ScopedFrameBufferBinder fbo_binder(fbo_id_); |
436 glFramebufferTexture2DEXT(GL_FRAMEBUFFER, | 422 glFramebufferTexture2DEXT(GL_FRAMEBUFFER, |
437 GL_COLOR_ATTACHMENT0, | 423 GL_COLOR_ATTACHMENT0, |
438 GL_TEXTURE_2D, | 424 GL_TEXTURE_2D, |
439 backbuffer_->service_id(), | 425 backbuffer_->service_id(), |
440 0); | 426 0); |
441 CHECK_GL_ERROR(); | 427 CHECK_GL_ERROR(); |
442 | 428 |
443 #ifndef NDEBUG | 429 #ifndef NDEBUG |
444 GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER); | 430 GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER); |
445 if (status != GL_FRAMEBUFFER_COMPLETE) { | 431 if (status != GL_FRAMEBUFFER_COMPLETE) { |
446 DLOG(FATAL) << "Framebuffer incomplete: " << status; | 432 DLOG(FATAL) << "Framebuffer incomplete: " << status; |
447 } | 433 } |
448 #endif | 434 #endif |
449 } | 435 } |
450 | 436 |
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 | 437 } // namespace content |
OLD | NEW |