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

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

Powered by Google App Engine
This is Rietveld 408576698