Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(792)

Side by Side Diff: content/common/gpu/texture_image_transport_surface.cc

Issue 14188053: gpu: Change Produce/ConsumeTexture to allow texture sharing (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase Created 7 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698