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

Side by Side Diff: cc/resource_provider.cc

Issue 12471007: Part 8 of cc/ directory shuffles: resources (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 9 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
« no previous file with comments | « cc/resource_provider.h ('k') | cc/resource_provider_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "cc/resource_provider.h"
6
7 #include <limits.h>
8
9 #include "base/debug/alias.h"
10 #include "base/hash_tables.h"
11 #include "base/stl_util.h"
12 #include "base/string_util.h"
13 #include "base/strings/string_split.h"
14 #include "cc/output/gl_renderer.h" // For the GLC() macro.
15 #include "cc/platform_color.h"
16 #include "cc/texture_uploader.h"
17 #include "cc/transferable_resource.h"
18 #include "gpu/GLES2/gl2extchromium.h"
19 #include "third_party/WebKit/Source/Platform/chromium/public/WebGraphicsContext3 D.h"
20 #include "third_party/khronos/GLES2/gl2.h"
21 #include "third_party/khronos/GLES2/gl2ext.h"
22 #include "ui/gfx/rect.h"
23 #include "ui/gfx/vector2d.h"
24
25 using WebKit::WebGraphicsContext3D;
26
27 namespace cc {
28
29 static GLenum TextureToStorageFormat(GLenum texture_format) {
30 GLenum storage_format = GL_RGBA8_OES;
31 switch (texture_format) {
32 case GL_RGBA:
33 break;
34 case GL_BGRA_EXT:
35 storage_format = GL_BGRA8_EXT;
36 break;
37 default:
38 NOTREACHED();
39 break;
40 }
41
42 return storage_format;
43 }
44
45 static bool IsTextureFormatSupportedForStorage(GLenum format) {
46 return (format == GL_RGBA || format == GL_BGRA_EXT);
47 }
48
49 static unsigned CreateTextureId(WebGraphicsContext3D* context3d) {
50 unsigned texture_id = 0;
51 GLC(context3d, texture_id = context3d->createTexture());
52 GLC(context3d, context3d->bindTexture(GL_TEXTURE_2D, texture_id));
53 GLC(context3d, context3d->texParameteri(
54 GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
55 GLC(context3d, context3d->texParameteri(
56 GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
57 GLC(context3d, context3d->texParameteri(
58 GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
59 GLC(context3d, context3d->texParameteri(
60 GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
61 return texture_id;
62 }
63
64 ResourceProvider::Resource::Resource()
65 : gl_id(0),
66 gl_pixel_buffer_id(0),
67 gl_upload_query_id(0),
68 pixels(NULL),
69 pixel_buffer(NULL),
70 lock_for_read_count(0),
71 locked_for_write(false),
72 external(false),
73 exported(false),
74 marked_for_deletion(false),
75 pending_set_pixels(false),
76 set_pixels_completion_forced(false),
77 allocated(false),
78 enable_read_lock_fences(false),
79 read_lock_fence(NULL),
80 size(),
81 format(0),
82 filter(0),
83 type(static_cast<ResourceType>(0)) {}
84
85 ResourceProvider::Resource::~Resource() {}
86
87 ResourceProvider::Resource::Resource(
88 unsigned texture_id, gfx::Size size, GLenum format, GLenum filter)
89 : gl_id(texture_id),
90 gl_pixel_buffer_id(0),
91 gl_upload_query_id(0),
92 pixels(NULL),
93 pixel_buffer(NULL),
94 lock_for_read_count(0),
95 locked_for_write(false),
96 external(false),
97 exported(false),
98 marked_for_deletion(false),
99 pending_set_pixels(false),
100 set_pixels_completion_forced(false),
101 allocated(false),
102 enable_read_lock_fences(false),
103 read_lock_fence(NULL),
104 size(size),
105 format(format),
106 filter(filter),
107 type(GLTexture) {}
108
109 ResourceProvider::Resource::Resource(
110 uint8_t* pixels, gfx::Size size, GLenum format, GLenum filter)
111 : gl_id(0),
112 gl_pixel_buffer_id(0),
113 gl_upload_query_id(0),
114 pixels(pixels),
115 pixel_buffer(NULL),
116 lock_for_read_count(0),
117 locked_for_write(false),
118 external(false),
119 exported(false),
120 marked_for_deletion(false),
121 pending_set_pixels(false),
122 set_pixels_completion_forced(false),
123 allocated(false),
124 enable_read_lock_fences(false),
125 read_lock_fence(NULL),
126 size(size),
127 format(format),
128 filter(filter),
129 type(Bitmap) {}
130
131 ResourceProvider::Child::Child() {}
132
133 ResourceProvider::Child::~Child() {}
134
135 scoped_ptr<ResourceProvider> ResourceProvider::Create(
136 OutputSurface* output_surface) {
137 scoped_ptr<ResourceProvider> resource_provider(
138 new ResourceProvider(output_surface));
139 if (!resource_provider->Initialize())
140 return scoped_ptr<ResourceProvider>();
141 return resource_provider.Pass();
142 }
143
144 ResourceProvider::~ResourceProvider() {
145 WebGraphicsContext3D* context3d = output_surface_->context3d();
146 if (!context3d || !context3d->makeContextCurrent())
147 return;
148 texture_uploader_.reset();
149 texture_copier_.reset();
150 }
151
152 WebGraphicsContext3D* ResourceProvider::GraphicsContext3D() {
153 DCHECK(thread_checker_.CalledOnValidThread());
154 return output_surface_->context3d();
155 }
156
157 bool ResourceProvider::InUseByConsumer(ResourceId id) {
158 DCHECK(thread_checker_.CalledOnValidThread());
159 ResourceMap::iterator it = resources_.find(id);
160 CHECK(it != resources_.end());
161 Resource* resource = &it->second;
162 return !!resource->lock_for_read_count || resource->exported;
163 }
164
165 ResourceProvider::ResourceId ResourceProvider::CreateResource(
166 gfx::Size size, GLenum format, TextureUsageHint hint) {
167 switch (default_resource_type_) {
168 case GLTexture:
169 return CreateGLTexture(
170 size, format, GL_TEXTURE_POOL_UNMANAGED_CHROMIUM, hint);
171 case Bitmap:
172 DCHECK(format == GL_RGBA);
173 return CreateBitmap(size);
174 }
175
176 LOG(FATAL) << "Invalid default resource type.";
177 return 0;
178 }
179
180 ResourceProvider::ResourceId ResourceProvider::CreateManagedResource(
181 gfx::Size size, GLenum format, TextureUsageHint hint) {
182 switch (default_resource_type_) {
183 case GLTexture:
184 return CreateGLTexture(
185 size, format, GL_TEXTURE_POOL_MANAGED_CHROMIUM, hint);
186 case Bitmap:
187 DCHECK(format == GL_RGBA);
188 return CreateBitmap(size);
189 }
190
191 LOG(FATAL) << "Invalid default resource type.";
192 return 0;
193 }
194
195 ResourceProvider::ResourceId ResourceProvider::CreateGLTexture(
196 gfx::Size size, GLenum format, GLenum texture_pool, TextureUsageHint hint) {
197 DCHECK_LE(size.width(), max_texture_size_);
198 DCHECK_LE(size.height(), max_texture_size_);
199
200 DCHECK(thread_checker_.CalledOnValidThread());
201 WebGraphicsContext3D* context3d = output_surface_->context3d();
202 DCHECK(context3d);
203
204 // Create and set texture properties. Allocation is delayed until needed.
205 unsigned texture_id = CreateTextureId(context3d);
206 GLC(context3d, context3d->texParameteri(GL_TEXTURE_2D,
207 GL_TEXTURE_POOL_CHROMIUM,
208 texture_pool));
209 if (use_texture_usage_hint_ && hint == TextureUsageFramebuffer) {
210 GLC(context3d, context3d->texParameteri(GL_TEXTURE_2D,
211 GL_TEXTURE_USAGE_ANGLE,
212 GL_FRAMEBUFFER_ATTACHMENT_ANGLE));
213 }
214
215 ResourceId id = next_id_++;
216 Resource resource(texture_id, size, format, GL_LINEAR);
217 resource.allocated = false;
218 resources_[id] = resource;
219 return id;
220 }
221
222 ResourceProvider::ResourceId ResourceProvider::CreateBitmap(gfx::Size size) {
223 DCHECK(thread_checker_.CalledOnValidThread());
224
225 uint8_t* pixels = new uint8_t[size.width() * size.height() * 4];
226
227 ResourceId id = next_id_++;
228 Resource resource(pixels, size, GL_RGBA, GL_LINEAR);
229 resource.allocated = true;
230 resources_[id] = resource;
231 return id;
232 }
233
234 ResourceProvider::ResourceId ResourceProvider::
235 CreateResourceFromExternalTexture(unsigned texture_id) {
236 DCHECK(thread_checker_.CalledOnValidThread());
237
238 WebGraphicsContext3D* context3d = output_surface_->context3d();
239 DCHECK(context3d);
240 GLC(context3d, context3d->bindTexture(GL_TEXTURE_2D, texture_id));
241 GLC(context3d, context3d->texParameteri(
242 GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
243 GLC(context3d, context3d->texParameteri(
244 GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
245 GLC(context3d, context3d->texParameteri(
246 GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
247 GLC(context3d, context3d->texParameteri(
248 GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
249
250 ResourceId id = next_id_++;
251 Resource resource(texture_id, gfx::Size(), 0, GL_LINEAR);
252 resource.external = true;
253 resource.allocated = true;
254 resources_[id] = resource;
255 return id;
256 }
257
258 ResourceProvider::ResourceId ResourceProvider::CreateResourceFromTextureMailbox(
259 const TextureMailbox& mailbox) {
260 DCHECK(thread_checker_.CalledOnValidThread());
261 // Just store the information. Mailbox will be consumed in LockForRead().
262 ResourceId id = next_id_++;
263 unsigned texture_id = 0;
264 Resource resource(texture_id, gfx::Size(), 0, GL_LINEAR);
265 resource.external = true;
266 resource.allocated = true;
267 resource.mailbox = mailbox;
268 resources_[id] = resource;
269 return id;
270 }
271
272 void ResourceProvider::DeleteResource(ResourceId id) {
273 DCHECK(thread_checker_.CalledOnValidThread());
274 ResourceMap::iterator it = resources_.find(id);
275 CHECK(it != resources_.end());
276 Resource* resource = &it->second;
277 DCHECK(!resource->lock_for_read_count);
278 DCHECK(!resource->marked_for_deletion);
279 DCHECK(resource->pending_set_pixels || !resource->locked_for_write);
280
281 if (resource->exported) {
282 resource->marked_for_deletion = true;
283 return;
284 } else {
285 DeleteResourceInternal(it);
286 }
287 }
288
289 void ResourceProvider::DeleteResourceInternal(ResourceMap::iterator it) {
290 Resource* resource = &it->second;
291 if (resource->gl_id && !resource->external) {
292 WebGraphicsContext3D* context3d = output_surface_->context3d();
293 DCHECK(context3d);
294 GLC(context3d, context3d->deleteTexture(resource->gl_id));
295 }
296 if (resource->gl_upload_query_id) {
297 WebGraphicsContext3D* context3d = output_surface_->context3d();
298 DCHECK(context3d);
299 GLC(context3d, context3d->deleteQueryEXT(resource->gl_upload_query_id));
300 }
301 if (resource->gl_pixel_buffer_id) {
302 WebGraphicsContext3D* context3d = output_surface_->context3d();
303 DCHECK(context3d);
304 GLC(context3d, context3d->deleteBuffer(resource->gl_pixel_buffer_id));
305 }
306 if (!resource->mailbox.IsEmpty() && resource->external) {
307 WebGraphicsContext3D* context3d = output_surface_->context3d();
308 DCHECK(context3d);
309 unsigned sync_point = resource->mailbox.sync_point();
310 if (resource->gl_id) {
311 GLC(context3d, context3d->bindTexture(GL_TEXTURE_2D, resource->gl_id));
312 GLC(context3d, context3d->produceTextureCHROMIUM(
313 GL_TEXTURE_2D, resource->mailbox.data()));
314 GLC(context3d, context3d->deleteTexture(resource->gl_id));
315 sync_point = context3d->insertSyncPoint();
316 }
317 resource->mailbox.RunReleaseCallback(sync_point);
318 }
319 if (resource->pixels)
320 delete[] resource->pixels;
321 if (resource->pixel_buffer)
322 delete[] resource->pixel_buffer;
323
324 resources_.erase(it);
325 }
326
327 ResourceProvider::ResourceType ResourceProvider::GetResourceType(
328 ResourceId id) {
329 ResourceMap::iterator it = resources_.find(id);
330 CHECK(it != resources_.end());
331 Resource* resource = &it->second;
332 return resource->type;
333 }
334
335 void ResourceProvider::SetPixels(ResourceId id,
336 const uint8_t* image,
337 gfx::Rect image_rect,
338 gfx::Rect source_rect,
339 gfx::Vector2d dest_offset) {
340 DCHECK(thread_checker_.CalledOnValidThread());
341 ResourceMap::iterator it = resources_.find(id);
342 CHECK(it != resources_.end());
343 Resource* resource = &it->second;
344 DCHECK(!resource->locked_for_write);
345 DCHECK(!resource->lock_for_read_count);
346 DCHECK(!resource->external);
347 DCHECK(!resource->exported);
348 DCHECK(ReadLockFenceHasPassed(resource));
349 LazyAllocate(resource);
350
351 if (resource->gl_id) {
352 DCHECK(!resource->pending_set_pixels);
353 WebGraphicsContext3D* context3d = output_surface_->context3d();
354 DCHECK(context3d);
355 DCHECK(texture_uploader_.get());
356 context3d->bindTexture(GL_TEXTURE_2D, resource->gl_id);
357 texture_uploader_->Upload(image,
358 image_rect,
359 source_rect,
360 dest_offset,
361 resource->format,
362 resource->size);
363 }
364
365 if (resource->pixels) {
366 DCHECK(resource->allocated);
367 DCHECK(resource->format == GL_RGBA);
368 SkBitmap src_full;
369 src_full.setConfig(
370 SkBitmap::kARGB_8888_Config, image_rect.width(), image_rect.height());
371 src_full.setPixels(const_cast<uint8_t*>(image));
372 SkBitmap src_subset;
373 SkIRect sk_source_rect = SkIRect::MakeXYWH(source_rect.x(),
374 source_rect.y(),
375 source_rect.width(),
376 source_rect.height());
377 sk_source_rect.offset(-image_rect.x(), -image_rect.y());
378 src_full.extractSubset(&src_subset, sk_source_rect);
379
380 ScopedWriteLockSoftware lock(this, id);
381 SkCanvas* dest = lock.sk_canvas();
382 dest->writePixels(src_subset, dest_offset.x(), dest_offset.y());
383 }
384 }
385
386 size_t ResourceProvider::NumBlockingUploads() {
387 if (!texture_uploader_)
388 return 0;
389
390 return texture_uploader_->NumBlockingUploads();
391 }
392
393 void ResourceProvider::MarkPendingUploadsAsNonBlocking() {
394 if (!texture_uploader_)
395 return;
396
397 texture_uploader_->MarkPendingUploadsAsNonBlocking();
398 }
399
400 double ResourceProvider::EstimatedUploadsPerSecond() {
401 if (!texture_uploader_)
402 return 0.0;
403
404 return texture_uploader_->EstimatedTexturesPerSecond();
405 }
406
407 void ResourceProvider::FlushUploads() {
408 if (!texture_uploader_)
409 return;
410
411 texture_uploader_->Flush();
412 }
413
414 void ResourceProvider::ReleaseCachedData() {
415 if (!texture_uploader_)
416 return;
417
418 texture_uploader_->ReleaseCachedQueries();
419 }
420
421 void ResourceProvider::Flush() {
422 DCHECK(thread_checker_.CalledOnValidThread());
423 WebGraphicsContext3D* context3d = output_surface_->context3d();
424 if (context3d)
425 context3d->flush();
426 }
427
428 bool ResourceProvider::ShallowFlushIfSupported() {
429 DCHECK(thread_checker_.CalledOnValidThread());
430 WebGraphicsContext3D* context3d = output_surface_->context3d();
431 if (!context3d || !use_shallow_flush_)
432 return false;
433
434 context3d->shallowFlushCHROMIUM();
435 return true;
436 }
437
438 const ResourceProvider::Resource* ResourceProvider::LockForRead(ResourceId id) {
439 DCHECK(thread_checker_.CalledOnValidThread());
440 ResourceMap::iterator it = resources_.find(id);
441 CHECK(it != resources_.end());
442 Resource* resource = &it->second;
443 DCHECK(!resource->locked_for_write || resource->set_pixels_completion_forced);
444 DCHECK(!resource->exported);
445 // Uninitialized! Call SetPixels or LockForWrite first.
446 DCHECK(resource->allocated);
447
448 if (!resource->gl_id && resource->external && !resource->mailbox.IsEmpty()) {
449 WebGraphicsContext3D* context3d = output_surface_->context3d();
450 DCHECK(context3d);
451 if (resource->mailbox.sync_point()) {
452 GLC(context3d, context3d->waitSyncPoint(resource->mailbox.sync_point()));
453 resource->mailbox.ResetSyncPoint();
454 }
455 resource->gl_id = context3d->createTexture();
456 GLC(context3d, context3d->bindTexture(GL_TEXTURE_2D, resource->gl_id));
457 GLC(context3d, context3d->consumeTextureCHROMIUM(GL_TEXTURE_2D,
458 resource->mailbox.data()));
459 }
460
461 resource->lock_for_read_count++;
462 if (resource->enable_read_lock_fences)
463 resource->read_lock_fence = current_read_lock_fence_;
464
465 return resource;
466 }
467
468 void ResourceProvider::UnlockForRead(ResourceId id) {
469 DCHECK(thread_checker_.CalledOnValidThread());
470 ResourceMap::iterator it = resources_.find(id);
471 CHECK(it != resources_.end());
472 Resource* resource = &it->second;
473 DCHECK(resource->lock_for_read_count > 0);
474 DCHECK(!resource->exported);
475 resource->lock_for_read_count--;
476 }
477
478 const ResourceProvider::Resource* ResourceProvider::LockForWrite(
479 ResourceId id) {
480 DCHECK(thread_checker_.CalledOnValidThread());
481 ResourceMap::iterator it = resources_.find(id);
482 CHECK(it != resources_.end());
483 Resource* resource = &it->second;
484 DCHECK(!resource->locked_for_write);
485 DCHECK(!resource->lock_for_read_count);
486 DCHECK(!resource->exported);
487 DCHECK(!resource->external);
488 DCHECK(ReadLockFenceHasPassed(resource));
489 LazyAllocate(resource);
490
491 resource->locked_for_write = true;
492 return resource;
493 }
494
495 bool ResourceProvider::CanLockForWrite(ResourceId id) {
496 DCHECK(thread_checker_.CalledOnValidThread());
497 ResourceMap::iterator it = resources_.find(id);
498 CHECK(it != resources_.end());
499 Resource* resource = &it->second;
500 return !resource->locked_for_write &&
501 !resource->lock_for_read_count &&
502 !resource->exported &&
503 !resource->external &&
504 ReadLockFenceHasPassed(resource);
505 }
506
507 void ResourceProvider::UnlockForWrite(ResourceId id) {
508 DCHECK(thread_checker_.CalledOnValidThread());
509 ResourceMap::iterator it = resources_.find(id);
510 CHECK(it != resources_.end());
511 Resource* resource = &it->second;
512 DCHECK(resource->locked_for_write);
513 DCHECK(!resource->exported);
514 DCHECK(!resource->external);
515 resource->locked_for_write = false;
516 }
517
518 ResourceProvider::ScopedReadLockGL::ScopedReadLockGL(
519 ResourceProvider* resource_provider,
520 ResourceProvider::ResourceId resource_id)
521 : resource_provider_(resource_provider),
522 resource_id_(resource_id),
523 texture_id_(resource_provider->LockForRead(resource_id)->gl_id) {
524 DCHECK(texture_id_);
525 }
526
527 ResourceProvider::ScopedReadLockGL::~ScopedReadLockGL() {
528 resource_provider_->UnlockForRead(resource_id_);
529 }
530
531 ResourceProvider::ScopedSamplerGL::ScopedSamplerGL(
532 ResourceProvider* resource_provider,
533 ResourceProvider::ResourceId resource_id,
534 GLenum target,
535 GLenum filter)
536 : ScopedReadLockGL(resource_provider, resource_id) {
537 resource_provider->BindForSampling(resource_id, target, filter);
538 }
539
540 ResourceProvider::ScopedWriteLockGL::ScopedWriteLockGL(
541 ResourceProvider* resource_provider,
542 ResourceProvider::ResourceId resource_id)
543 : resource_provider_(resource_provider),
544 resource_id_(resource_id),
545 texture_id_(resource_provider->LockForWrite(resource_id)->gl_id) {
546 DCHECK(texture_id_);
547 }
548
549 ResourceProvider::ScopedWriteLockGL::~ScopedWriteLockGL() {
550 resource_provider_->UnlockForWrite(resource_id_);
551 }
552
553 void ResourceProvider::PopulateSkBitmapWithResource(
554 SkBitmap* sk_bitmap, const Resource* resource) {
555 DCHECK(resource->pixels);
556 DCHECK(resource->format == GL_RGBA);
557 sk_bitmap->setConfig(SkBitmap::kARGB_8888_Config,
558 resource->size.width(),
559 resource->size.height());
560 sk_bitmap->setPixels(resource->pixels);
561 }
562
563 ResourceProvider::ScopedReadLockSoftware::ScopedReadLockSoftware(
564 ResourceProvider* resource_provider,
565 ResourceProvider::ResourceId resource_id)
566 : resource_provider_(resource_provider),
567 resource_id_(resource_id) {
568 ResourceProvider::PopulateSkBitmapWithResource(
569 &sk_bitmap_, resource_provider->LockForRead(resource_id));
570 }
571
572 ResourceProvider::ScopedReadLockSoftware::~ScopedReadLockSoftware() {
573 resource_provider_->UnlockForRead(resource_id_);
574 }
575
576 ResourceProvider::ScopedWriteLockSoftware::ScopedWriteLockSoftware(
577 ResourceProvider* resource_provider,
578 ResourceProvider::ResourceId resource_id)
579 : resource_provider_(resource_provider),
580 resource_id_(resource_id) {
581 ResourceProvider::PopulateSkBitmapWithResource(
582 &sk_bitmap_, resource_provider->LockForWrite(resource_id));
583 sk_canvas_.reset(new SkCanvas(sk_bitmap_));
584 }
585
586 ResourceProvider::ScopedWriteLockSoftware::~ScopedWriteLockSoftware() {
587 resource_provider_->UnlockForWrite(resource_id_);
588 }
589
590 ResourceProvider::ResourceProvider(OutputSurface* output_surface)
591 : output_surface_(output_surface),
592 next_id_(1),
593 next_child_(1),
594 default_resource_type_(GLTexture),
595 use_texture_storage_ext_(false),
596 use_texture_usage_hint_(false),
597 use_shallow_flush_(false),
598 max_texture_size_(0),
599 best_texture_format_(0) {}
600
601 bool ResourceProvider::Initialize() {
602 DCHECK(thread_checker_.CalledOnValidThread());
603 WebGraphicsContext3D* context3d = output_surface_->context3d();
604 if (!context3d) {
605 max_texture_size_ = INT_MAX / 2;
606 best_texture_format_ = GL_RGBA;
607 return true;
608 }
609 if (!context3d->makeContextCurrent())
610 return false;
611
612 std::string extensions_string =
613 UTF16ToASCII(context3d->getString(GL_EXTENSIONS));
614 std::vector<std::string> extensions;
615 base::SplitString(extensions_string, ' ', &extensions);
616 bool use_map_sub = false;
617 bool use_bind_uniform = false;
618 bool use_bgra = false;
619 for (size_t i = 0; i < extensions.size(); ++i) {
620 if (extensions[i] == "GL_EXT_texture_storage")
621 use_texture_storage_ext_ = true;
622 else if (extensions[i] == "GL_ANGLE_texture_usage")
623 use_texture_usage_hint_ = true;
624 else if (extensions[i] == "GL_CHROMIUM_map_sub")
625 use_map_sub = true;
626 else if (extensions[i] == "GL_CHROMIUM_shallow_flush")
627 use_shallow_flush_ = true;
628 else if (extensions[i] == "GL_CHROMIUM_bind_uniform_location")
629 use_bind_uniform = true;
630 else if (extensions[i] == "GL_EXT_texture_format_BGRA8888")
631 use_bgra = true;
632 }
633
634 texture_copier_ =
635 AcceleratedTextureCopier::Create(context3d, use_bind_uniform);
636
637 texture_uploader_ =
638 TextureUploader::Create(context3d, use_map_sub, use_shallow_flush_);
639 GLC(context3d, context3d->getIntegerv(GL_MAX_TEXTURE_SIZE,
640 &max_texture_size_));
641 best_texture_format_ =
642 PlatformColor::BestTextureFormat(context3d, use_bgra);
643 return true;
644 }
645
646 int ResourceProvider::CreateChild() {
647 DCHECK(thread_checker_.CalledOnValidThread());
648 Child child_info;
649 int child = next_child_++;
650 children_[child] = child_info;
651 return child;
652 }
653
654 void ResourceProvider::DestroyChild(int child_id) {
655 DCHECK(thread_checker_.CalledOnValidThread());
656 ChildMap::iterator it = children_.find(child_id);
657 DCHECK(it != children_.end());
658 Child& child = it->second;
659 for (ResourceIdMap::iterator child_it = child.child_to_parent_map.begin();
660 child_it != child.child_to_parent_map.end();
661 ++child_it)
662 DeleteResource(child_it->second);
663 children_.erase(it);
664 }
665
666 const ResourceProvider::ResourceIdMap& ResourceProvider::GetChildToParentMap(
667 int child) const {
668 DCHECK(thread_checker_.CalledOnValidThread());
669 ChildMap::const_iterator it = children_.find(child);
670 DCHECK(it != children_.end());
671 return it->second.child_to_parent_map;
672 }
673
674 void ResourceProvider::PrepareSendToParent(const ResourceIdArray& resources,
675 TransferableResourceArray* list) {
676 DCHECK(thread_checker_.CalledOnValidThread());
677 list->clear();
678 WebGraphicsContext3D* context3d = output_surface_->context3d();
679 if (!context3d || !context3d->makeContextCurrent()) {
680 // FIXME: Implement this path for software compositing.
681 return;
682 }
683 bool need_sync_point = false;
684 for (ResourceIdArray::const_iterator it = resources.begin();
685 it != resources.end();
686 ++it) {
687 TransferableResource resource;
688 if (TransferResource(context3d, *it, &resource)) {
689 if (!resource.sync_point)
690 need_sync_point = true;
691 resources_.find(*it)->second.exported = true;
692 list->push_back(resource);
693 }
694 }
695 if (need_sync_point) {
696 unsigned int sync_point = context3d->insertSyncPoint();
697 for (TransferableResourceArray::iterator it = list->begin();
698 it != list->end();
699 ++it) {
700 if (!it->sync_point)
701 it->sync_point = sync_point;
702 }
703 }
704 }
705
706 void ResourceProvider::PrepareSendToChild(int child,
707 const ResourceIdArray& resources,
708 TransferableResourceArray* list) {
709 DCHECK(thread_checker_.CalledOnValidThread());
710 list->clear();
711 WebGraphicsContext3D* context3d = output_surface_->context3d();
712 if (!context3d || !context3d->makeContextCurrent()) {
713 // FIXME: Implement this path for software compositing.
714 return;
715 }
716 Child& child_info = children_.find(child)->second;
717 bool need_sync_point = false;
718 for (ResourceIdArray::const_iterator it = resources.begin();
719 it != resources.end();
720 ++it) {
721 TransferableResource resource;
722 if (!TransferResource(context3d, *it, &resource))
723 NOTREACHED();
724 if (!resource.sync_point)
725 need_sync_point = true;
726 DCHECK(child_info.parent_to_child_map.find(*it) !=
727 child_info.parent_to_child_map.end());
728 resource.id = child_info.parent_to_child_map[*it];
729 child_info.parent_to_child_map.erase(*it);
730 child_info.child_to_parent_map.erase(resource.id);
731 list->push_back(resource);
732 DeleteResource(*it);
733 }
734 if (need_sync_point) {
735 unsigned int sync_point = context3d->insertSyncPoint();
736 for (TransferableResourceArray::iterator it = list->begin();
737 it != list->end();
738 ++it) {
739 if (!it->sync_point)
740 it->sync_point = sync_point;
741 }
742 }
743 }
744
745 void ResourceProvider::ReceiveFromChild(
746 int child, const TransferableResourceArray& resources) {
747 DCHECK(thread_checker_.CalledOnValidThread());
748 WebGraphicsContext3D* context3d = output_surface_->context3d();
749 if (!context3d || !context3d->makeContextCurrent()) {
750 // FIXME: Implement this path for software compositing.
751 return;
752 }
753 Child& child_info = children_.find(child)->second;
754 for (TransferableResourceArray::const_iterator it = resources.begin();
755 it != resources.end();
756 ++it) {
757 unsigned texture_id;
758 // NOTE: If the parent is a browser and the child a renderer, the parent
759 // is not supposed to have its context wait, because that could induce
760 // deadlocks and/or security issues. The caller is responsible for
761 // waiting asynchronously, and resetting sync_point before calling this.
762 // However if the parent is a renderer (e.g. browser tag), it may be ok
763 // (and is simpler) to wait.
764 if (it->sync_point)
765 GLC(context3d, context3d->waitSyncPoint(it->sync_point));
766 GLC(context3d, texture_id = context3d->createTexture());
767 GLC(context3d, context3d->bindTexture(GL_TEXTURE_2D, texture_id));
768 GLC(context3d, context3d->consumeTextureCHROMIUM(GL_TEXTURE_2D,
769 it->mailbox.name));
770 ResourceId id = next_id_++;
771 Resource resource(texture_id, it->size, it->format, it->filter);
772 resource.mailbox.SetName(it->mailbox);
773 // Don't allocate a texture for a child.
774 resource.allocated = true;
775 resources_[id] = resource;
776 child_info.parent_to_child_map[id] = it->id;
777 child_info.child_to_parent_map[it->id] = id;
778 }
779 }
780
781 void ResourceProvider::ReceiveFromParent(
782 const TransferableResourceArray& resources) {
783 DCHECK(thread_checker_.CalledOnValidThread());
784 WebGraphicsContext3D* context3d = output_surface_->context3d();
785 if (!context3d || !context3d->makeContextCurrent()) {
786 // FIXME: Implement this path for software compositing.
787 return;
788 }
789 for (TransferableResourceArray::const_iterator it = resources.begin();
790 it != resources.end();
791 ++it) {
792 ResourceMap::iterator map_iterator = resources_.find(it->id);
793 DCHECK(map_iterator != resources_.end());
794 Resource* resource = &map_iterator->second;
795 DCHECK(resource->exported);
796 resource->exported = false;
797 resource->filter = it->filter;
798 DCHECK(resource->mailbox.Equals(it->mailbox));
799 if (resource->gl_id) {
800 if (it->sync_point)
801 GLC(context3d, context3d->waitSyncPoint(it->sync_point));
802 GLC(context3d, context3d->bindTexture(GL_TEXTURE_2D, resource->gl_id));
803 GLC(context3d, context3d->consumeTextureCHROMIUM(GL_TEXTURE_2D,
804 it->mailbox.name));
805 } else {
806 resource->mailbox = TextureMailbox(resource->mailbox.name(),
807 resource->mailbox.callback(),
808 it->sync_point);
809 }
810 if (resource->marked_for_deletion)
811 DeleteResourceInternal(map_iterator);
812 }
813 }
814
815 bool ResourceProvider::TransferResource(WebGraphicsContext3D* context,
816 ResourceId id,
817 TransferableResource* resource) {
818 DCHECK(thread_checker_.CalledOnValidThread());
819 WebGraphicsContext3D* context3d = output_surface_->context3d();
820 ResourceMap::iterator it = resources_.find(id);
821 CHECK(it != resources_.end());
822 Resource* source = &it->second;
823 DCHECK(!source->locked_for_write);
824 DCHECK(!source->lock_for_read_count);
825 DCHECK(!source->external || (source->external && !source->mailbox.IsEmpty()));
826 DCHECK(source->allocated);
827 if (source->exported)
828 return false;
829 resource->id = id;
830 resource->format = source->format;
831 resource->filter = source->filter;
832 resource->size = source->size;
833
834 if (source->mailbox.IsEmpty()) {
835 GLC(context3d, context3d->genMailboxCHROMIUM(resource->mailbox.name));
836 source->mailbox.SetName(resource->mailbox);
837 } else {
838 resource->mailbox = source->mailbox.name();
839 }
840
841 if (source->gl_id) {
842 GLC(context, context->bindTexture(GL_TEXTURE_2D, source->gl_id));
843 GLC(context, context->produceTextureCHROMIUM(GL_TEXTURE_2D,
844 resource->mailbox.name));
845 } else {
846 resource->sync_point = source->mailbox.sync_point();
847 source->mailbox.ResetSyncPoint();
848 }
849 return true;
850 }
851
852 void ResourceProvider::AcquirePixelBuffer(ResourceId id) {
853 DCHECK(thread_checker_.CalledOnValidThread());
854 ResourceMap::iterator it = resources_.find(id);
855 CHECK(it != resources_.end());
856 Resource* resource = &it->second;
857 DCHECK(!resource->external);
858 DCHECK(!resource->exported);
859
860 if (resource->gl_id) {
861 WebGraphicsContext3D* context3d = output_surface_->context3d();
862 DCHECK(context3d);
863 if (!resource->gl_pixel_buffer_id)
864 resource->gl_pixel_buffer_id = context3d->createBuffer();
865 context3d->bindBuffer(
866 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
867 resource->gl_pixel_buffer_id);
868 context3d->bufferData(
869 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
870 resource->size.width() * resource->size.height() * 4,
871 NULL,
872 GL_DYNAMIC_DRAW);
873 context3d->bindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0);
874 }
875
876 if (resource->pixels) {
877 if (resource->pixel_buffer)
878 return;
879
880 resource->pixel_buffer = new uint8_t[
881 resource->size.width() * resource->size.height() * 4];
882 }
883 }
884
885 void ResourceProvider::ReleasePixelBuffer(ResourceId id) {
886 DCHECK(thread_checker_.CalledOnValidThread());
887 ResourceMap::iterator it = resources_.find(id);
888 CHECK(it != resources_.end());
889 Resource* resource = &it->second;
890 DCHECK(!resource->external);
891 DCHECK(!resource->exported);
892
893 if (resource->gl_id) {
894 DCHECK(resource->gl_pixel_buffer_id);
895 WebGraphicsContext3D* context3d = output_surface_->context3d();
896 DCHECK(context3d);
897 context3d->bindBuffer(
898 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
899 resource->gl_pixel_buffer_id);
900 context3d->bufferData(
901 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
902 0,
903 NULL,
904 GL_DYNAMIC_DRAW);
905 context3d->bindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0);
906 }
907
908 if (resource->pixels) {
909 if (!resource->pixel_buffer)
910 return;
911 delete[] resource->pixel_buffer;
912 resource->pixel_buffer = NULL;
913 }
914 }
915
916 uint8_t* ResourceProvider::MapPixelBuffer(ResourceId id) {
917 DCHECK(thread_checker_.CalledOnValidThread());
918 ResourceMap::iterator it = resources_.find(id);
919 CHECK(it != resources_.end());
920 Resource* resource = &it->second;
921 DCHECK(!resource->external);
922 DCHECK(!resource->exported);
923
924 if (resource->gl_id) {
925 WebGraphicsContext3D* context3d = output_surface_->context3d();
926 DCHECK(context3d);
927 DCHECK(resource->gl_pixel_buffer_id);
928 context3d->bindBuffer(
929 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
930 resource->gl_pixel_buffer_id);
931 uint8_t* image = static_cast<uint8_t*>(
932 context3d->mapBufferCHROMIUM(
933 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, GL_WRITE_ONLY));
934 context3d->bindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0);
935 DCHECK(image);
936 return image;
937 }
938
939 if (resource->pixels)
940 return resource->pixel_buffer;
941
942 return NULL;
943 }
944
945 void ResourceProvider::UnmapPixelBuffer(ResourceId id) {
946 DCHECK(thread_checker_.CalledOnValidThread());
947 ResourceMap::iterator it = resources_.find(id);
948 CHECK(it != resources_.end());
949 Resource* resource = &it->second;
950 DCHECK(!resource->external);
951 DCHECK(!resource->exported);
952
953 if (resource->gl_id) {
954 WebGraphicsContext3D* context3d = output_surface_->context3d();
955 DCHECK(context3d);
956 DCHECK(resource->gl_pixel_buffer_id);
957 context3d->bindBuffer(
958 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
959 resource->gl_pixel_buffer_id);
960 context3d->unmapBufferCHROMIUM(
961 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM);
962 context3d->bindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0);
963 }
964 }
965
966 void ResourceProvider::SetPixelsFromBuffer(ResourceId id) {
967 DCHECK(thread_checker_.CalledOnValidThread());
968 ResourceMap::iterator it = resources_.find(id);
969 CHECK(it != resources_.end());
970 Resource* resource = &it->second;
971 DCHECK(!resource->locked_for_write);
972 DCHECK(!resource->lock_for_read_count);
973 DCHECK(!resource->external);
974 DCHECK(!resource->exported);
975 DCHECK(ReadLockFenceHasPassed(resource));
976 LazyAllocate(resource);
977
978 if (resource->gl_id) {
979 WebGraphicsContext3D* context3d = output_surface_->context3d();
980 DCHECK(context3d);
981 DCHECK(resource->gl_pixel_buffer_id);
982 context3d->bindTexture(GL_TEXTURE_2D, resource->gl_id);
983 context3d->bindBuffer(
984 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
985 resource->gl_pixel_buffer_id);
986 context3d->texSubImage2D(GL_TEXTURE_2D,
987 0, /* level */
988 0, /* x */
989 0, /* y */
990 resource->size.width(),
991 resource->size.height(),
992 resource->format,
993 GL_UNSIGNED_BYTE,
994 NULL);
995 context3d->bindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0);
996 }
997
998 if (resource->pixels) {
999 DCHECK(resource->pixel_buffer);
1000 DCHECK(resource->format == GL_RGBA);
1001 SkBitmap src;
1002 src.setConfig(SkBitmap::kARGB_8888_Config,
1003 resource->size.width(),
1004 resource->size.height());
1005 src.setPixels(resource->pixel_buffer);
1006
1007 ScopedWriteLockSoftware lock(this, id);
1008 SkCanvas* dest = lock.sk_canvas();
1009 dest->writePixels(src, 0, 0);
1010 }
1011 }
1012
1013 void ResourceProvider::BindForSampling(ResourceProvider::ResourceId resource_id,
1014 GLenum target, GLenum filter) {
1015 DCHECK(thread_checker_.CalledOnValidThread());
1016 WebGraphicsContext3D* context3d = output_surface_->context3d();
1017 ResourceMap::iterator it = resources_.find(resource_id);
1018 DCHECK(it != resources_.end());
1019 Resource* resource = &it->second;
1020 DCHECK(resource->lock_for_read_count);
1021 DCHECK(!resource->locked_for_write || resource->set_pixels_completion_forced);
1022
1023 GLC(context3d, context3d->bindTexture(target, resource->gl_id));
1024 if (filter != resource->filter) {
1025 GLC(context3d, context3d->texParameteri(target,
1026 GL_TEXTURE_MIN_FILTER,
1027 filter));
1028 GLC(context3d, context3d->texParameteri(target,
1029 GL_TEXTURE_MAG_FILTER,
1030 filter));
1031 resource->filter = filter;
1032 }
1033 }
1034
1035 void ResourceProvider::BeginSetPixels(ResourceId id) {
1036 DCHECK(thread_checker_.CalledOnValidThread());
1037 ResourceMap::iterator it = resources_.find(id);
1038 CHECK(it != resources_.end());
1039 Resource* resource = &it->second;
1040 DCHECK(!resource->pending_set_pixels);
1041 DCHECK(resource->gl_id || resource->allocated);
1042 DCHECK(ReadLockFenceHasPassed(resource));
1043
1044 bool allocate = !resource->allocated;
1045 resource->allocated = true;
1046 LockForWrite(id);
1047
1048 if (resource->gl_id) {
1049 WebGraphicsContext3D* context3d = output_surface_->context3d();
1050 DCHECK(context3d);
1051 DCHECK(resource->gl_pixel_buffer_id);
1052 context3d->bindTexture(GL_TEXTURE_2D, resource->gl_id);
1053 context3d->bindBuffer(
1054 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
1055 resource->gl_pixel_buffer_id);
1056 if (!resource->gl_upload_query_id)
1057 resource->gl_upload_query_id = context3d->createQueryEXT();
1058 context3d->beginQueryEXT(
1059 GL_ASYNC_PIXEL_TRANSFERS_COMPLETED_CHROMIUM,
1060 resource->gl_upload_query_id);
1061 if (allocate) {
1062 context3d->asyncTexImage2DCHROMIUM(GL_TEXTURE_2D,
1063 0, /* level */
1064 resource->format,
1065 resource->size.width(),
1066 resource->size.height(),
1067 0, /* border */
1068 resource->format,
1069 GL_UNSIGNED_BYTE,
1070 NULL);
1071 } else {
1072 context3d->asyncTexSubImage2DCHROMIUM(GL_TEXTURE_2D,
1073 0, /* level */
1074 0, /* x */
1075 0, /* y */
1076 resource->size.width(),
1077 resource->size.height(),
1078 resource->format,
1079 GL_UNSIGNED_BYTE,
1080 NULL);
1081 }
1082 context3d->endQueryEXT(GL_ASYNC_PIXEL_TRANSFERS_COMPLETED_CHROMIUM);
1083 context3d->bindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0);
1084 }
1085
1086 if (resource->pixels)
1087 SetPixelsFromBuffer(id);
1088
1089 resource->pending_set_pixels = true;
1090 resource->set_pixels_completion_forced = false;
1091 }
1092
1093 void ResourceProvider::ForceSetPixelsToComplete(ResourceId id) {
1094 DCHECK(thread_checker_.CalledOnValidThread());
1095 ResourceMap::iterator it = resources_.find(id);
1096 CHECK(it != resources_.end());
1097 Resource* resource = &it->second;
1098 DCHECK(resource->locked_for_write);
1099 DCHECK(resource->pending_set_pixels);
1100 DCHECK(!resource->set_pixels_completion_forced);
1101
1102 if (resource->gl_id) {
1103 WebGraphicsContext3D* context3d = output_surface_->context3d();
1104 GLC(context3d, context3d->bindTexture(GL_TEXTURE_2D, resource->gl_id));
1105 GLC(context3d, context3d->waitAsyncTexImage2DCHROMIUM(GL_TEXTURE_2D));
1106 GLC(context3d, context3d->bindTexture(GL_TEXTURE_2D, 0));
1107 }
1108
1109 resource->set_pixels_completion_forced = true;
1110 }
1111
1112 bool ResourceProvider::DidSetPixelsComplete(ResourceId id) {
1113 DCHECK(thread_checker_.CalledOnValidThread());
1114 ResourceMap::iterator it = resources_.find(id);
1115 CHECK(it != resources_.end());
1116 Resource* resource = &it->second;
1117 DCHECK(resource->locked_for_write);
1118 DCHECK(resource->pending_set_pixels);
1119
1120 if (resource->gl_id) {
1121 WebGraphicsContext3D* context3d = output_surface_->context3d();
1122 DCHECK(context3d);
1123 DCHECK(resource->gl_upload_query_id);
1124 unsigned complete = 1;
1125 context3d->getQueryObjectuivEXT(
1126 resource->gl_upload_query_id,
1127 GL_QUERY_RESULT_AVAILABLE_EXT,
1128 &complete);
1129 if (!complete)
1130 return false;
1131 }
1132
1133 resource->pending_set_pixels = false;
1134 UnlockForWrite(id);
1135
1136 return true;
1137 }
1138
1139 void ResourceProvider::AbortSetPixels(ResourceId id) {
1140 DCHECK(thread_checker_.CalledOnValidThread());
1141 ResourceMap::iterator it = resources_.find(id);
1142 CHECK(it != resources_.end());
1143 Resource* resource = &it->second;
1144 DCHECK(resource->locked_for_write);
1145 DCHECK(resource->pending_set_pixels);
1146
1147 if (resource->gl_id) {
1148 WebGraphicsContext3D* context3d = output_surface_->context3d();
1149 DCHECK(context3d);
1150 DCHECK(resource->gl_upload_query_id);
1151 // CHROMIUM_async_pixel_transfers currently doesn't have a way to
1152 // abort an upload. The best we can do is delete the query and
1153 // the texture.
1154 context3d->deleteQueryEXT(resource->gl_upload_query_id);
1155 resource->gl_upload_query_id = 0;
1156 context3d->deleteTexture(resource->gl_id);
1157 resource->gl_id = CreateTextureId(context3d);
1158 resource->allocated = false;
1159 }
1160
1161 resource->pending_set_pixels = false;
1162 UnlockForWrite(id);
1163 }
1164
1165 void ResourceProvider::AllocateForTesting(ResourceId id) {
1166 ResourceMap::iterator it = resources_.find(id);
1167 CHECK(it != resources_.end());
1168 Resource* resource = &it->second;
1169 LazyAllocate(resource);
1170 }
1171
1172 void ResourceProvider::LazyAllocate(Resource* resource) {
1173 DCHECK(resource);
1174 DCHECK(resource->gl_id || resource->allocated);
1175
1176 if (resource->allocated || !resource->gl_id)
1177 return;
1178 resource->allocated = true;
1179 WebGraphicsContext3D* context3d = output_surface_->context3d();
1180 gfx::Size& size = resource->size;
1181 GLenum format = resource->format;
1182 GLC(context3d, context3d->bindTexture(GL_TEXTURE_2D, resource->gl_id));
1183 if (use_texture_storage_ext_ && IsTextureFormatSupportedForStorage(format)) {
1184 GLenum storage_format = TextureToStorageFormat(format);
1185 GLC(context3d, context3d->texStorage2DEXT(GL_TEXTURE_2D,
1186 1,
1187 storage_format,
1188 size.width(),
1189 size.height()));
1190 } else
1191 GLC(context3d, context3d->texImage2D(GL_TEXTURE_2D,
1192 0,
1193 format,
1194 size.width(),
1195 size.height(),
1196 0,
1197 format,
1198 GL_UNSIGNED_BYTE,
1199 NULL));
1200 }
1201
1202 void ResourceProvider::EnableReadLockFences(ResourceProvider::ResourceId id,
1203 bool enable) {
1204 DCHECK(thread_checker_.CalledOnValidThread());
1205 ResourceMap::iterator it = resources_.find(id);
1206 CHECK(it != resources_.end());
1207 Resource* resource = &it->second;
1208 resource->enable_read_lock_fences = enable;
1209 }
1210
1211 } // namespace cc
OLDNEW
« no previous file with comments | « cc/resource_provider.h ('k') | cc/resource_provider_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698