Reenable NullOpenerRedirectForksProcess, as the offending patch has been reverted
[chromium-blink-merge.git] / cc / resource_provider.cc
blob4269b8123185b5400c66356bc9c4b9ce30697cb6
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.
5 #include "cc/resource_provider.h"
7 #include <limits.h>
9 #include "base/debug/alias.h"
10 #include "base/hash_tables.h"
11 #include "base/stl_util.h"
12 #include "base/string_split.h"
13 #include "base/string_util.h"
14 #include "cc/gl_renderer.h" // For the GLC() macro.
15 #include "cc/texture_uploader.h"
16 #include "cc/transferable_resource.h"
17 #include "third_party/khronos/GLES2/gl2.h"
18 #include "third_party/khronos/GLES2/gl2ext.h"
19 #include "ui/gfx/rect.h"
20 #include "ui/gfx/vector2d.h"
22 #include <public/WebGraphicsContext3D.h>
24 using WebKit::WebGraphicsContext3D;
26 namespace cc {
28 static GLenum textureToStorageFormat(GLenum textureFormat)
30 GLenum storageFormat = GL_RGBA8_OES;
31 switch (textureFormat) {
32 case GL_RGBA:
33 break;
34 case GL_BGRA_EXT:
35 storageFormat = GL_BGRA8_EXT;
36 break;
37 default:
38 NOTREACHED();
39 break;
42 return storageFormat;
45 static bool isTextureFormatSupportedForStorage(GLenum format)
47 return (format == GL_RGBA || format == GL_BGRA_EXT);
50 ResourceProvider::Resource::Resource()
51 : glId(0)
52 , pixels(0)
53 , pool(0)
54 , lockForReadCount(0)
55 , lockedForWrite(false)
56 , external(false)
57 , exported(false)
58 , markedForDeletion(false)
59 , size()
60 , format(0)
61 , type(static_cast<ResourceType>(0))
65 ResourceProvider::Resource::Resource(unsigned textureId, int pool, const gfx::Size& size, GLenum format)
66 : glId(textureId)
67 , pixels(0)
68 , pool(pool)
69 , lockForReadCount(0)
70 , lockedForWrite(false)
71 , external(false)
72 , exported(false)
73 , markedForDeletion(false)
74 , size(size)
75 , format(format)
76 , type(GLTexture)
80 ResourceProvider::Resource::Resource(uint8_t* pixels, int pool, const gfx::Size& size, GLenum format)
81 : glId(0)
82 , pixels(pixels)
83 , pool(pool)
84 , lockForReadCount(0)
85 , lockedForWrite(false)
86 , external(false)
87 , exported(false)
88 , markedForDeletion(false)
89 , size(size)
90 , format(format)
91 , type(Bitmap)
95 ResourceProvider::Child::Child()
99 ResourceProvider::Child::~Child()
103 scoped_ptr<ResourceProvider> ResourceProvider::create(GraphicsContext* context)
105 scoped_ptr<ResourceProvider> resourceProvider(new ResourceProvider(context));
106 if (!resourceProvider->initialize())
107 return scoped_ptr<ResourceProvider>();
108 return resourceProvider.Pass();
111 ResourceProvider::~ResourceProvider()
113 WebGraphicsContext3D* context3d = m_context->context3D();
114 if (!context3d || !context3d->makeContextCurrent())
115 return;
116 m_textureUploader.reset();
117 m_textureCopier.reset();
120 WebGraphicsContext3D* ResourceProvider::graphicsContext3D()
122 DCHECK(m_threadChecker.CalledOnValidThread());
123 return m_context->context3D();
126 bool ResourceProvider::inUseByConsumer(ResourceId id)
128 DCHECK(m_threadChecker.CalledOnValidThread());
129 ResourceMap::iterator it = m_resources.find(id);
130 CHECK(it != m_resources.end());
131 Resource* resource = &it->second;
132 return !!resource->lockForReadCount || resource->exported;
135 ResourceProvider::ResourceId ResourceProvider::createResource(int pool, const gfx::Size& size, GLenum format, TextureUsageHint hint)
137 switch (m_defaultResourceType) {
138 case GLTexture:
139 return createGLTexture(pool, size, format, hint);
140 case Bitmap:
141 DCHECK(format == GL_RGBA);
142 return createBitmap(pool, size);
145 LOG(FATAL) << "Invalid default resource type.";
146 return 0;
149 ResourceProvider::ResourceId ResourceProvider::createGLTexture(int pool, const gfx::Size& size, GLenum format, TextureUsageHint hint)
151 DCHECK(m_threadChecker.CalledOnValidThread());
152 unsigned textureId = 0;
153 WebGraphicsContext3D* context3d = m_context->context3D();
154 DCHECK(context3d);
155 GLC(context3d, textureId = context3d->createTexture());
156 GLC(context3d, context3d->bindTexture(GL_TEXTURE_2D, textureId));
157 GLC(context3d, context3d->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
158 GLC(context3d, context3d->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
159 GLC(context3d, context3d->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
160 GLC(context3d, context3d->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
162 if (m_useTextureUsageHint && hint == TextureUsageFramebuffer)
163 GLC(context3d, context3d->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_USAGE_ANGLE, GL_FRAMEBUFFER_ATTACHMENT_ANGLE));
164 if (m_useTextureStorageExt && isTextureFormatSupportedForStorage(format)) {
165 GLenum storageFormat = textureToStorageFormat(format);
166 GLC(context3d, context3d->texStorage2DEXT(GL_TEXTURE_2D, 1, storageFormat, size.width(), size.height()));
167 } else
168 GLC(context3d, context3d->texImage2D(GL_TEXTURE_2D, 0, format, size.width(), size.height(), 0, format, GL_UNSIGNED_BYTE, 0));
170 ResourceId id = m_nextId++;
171 Resource resource(textureId, pool, size, format);
172 m_resources[id] = resource;
173 return id;
176 ResourceProvider::ResourceId ResourceProvider::createBitmap(int pool, const gfx::Size& size)
178 DCHECK(m_threadChecker.CalledOnValidThread());
180 uint8_t* pixels = new uint8_t[size.width() * size.height() * 4];
182 ResourceId id = m_nextId++;
183 Resource resource(pixels, pool, size, GL_RGBA);
184 m_resources[id] = resource;
185 return id;
188 ResourceProvider::ResourceId ResourceProvider::createResourceFromExternalTexture(unsigned textureId)
190 DCHECK(m_threadChecker.CalledOnValidThread());
192 WebGraphicsContext3D* context3d = m_context->context3D();
193 DCHECK(context3d);
194 GLC(context3d, context3d->bindTexture(GL_TEXTURE_2D, textureId));
195 GLC(context3d, context3d->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
196 GLC(context3d, context3d->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
197 GLC(context3d, context3d->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
198 GLC(context3d, context3d->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
200 ResourceId id = m_nextId++;
201 Resource resource(textureId, 0, gfx::Size(), 0);
202 resource.external = true;
203 m_resources[id] = resource;
204 return id;
207 void ResourceProvider::deleteResource(ResourceId id)
209 DCHECK(m_threadChecker.CalledOnValidThread());
210 ResourceMap::iterator it = m_resources.find(id);
211 CHECK(it != m_resources.end());
212 Resource* resource = &it->second;
213 DCHECK(!resource->lockedForWrite);
214 DCHECK(!resource->lockForReadCount);
215 DCHECK(!resource->markedForDeletion);
217 if (resource->exported) {
218 resource->markedForDeletion = true;
219 return;
220 } else
221 deleteResourceInternal(it);
224 void ResourceProvider::deleteResourceInternal(ResourceMap::iterator it)
226 Resource* resource = &it->second;
227 if (resource->glId && !resource->external) {
228 WebGraphicsContext3D* context3d = m_context->context3D();
229 DCHECK(context3d);
230 GLC(context3d, context3d->deleteTexture(resource->glId));
232 if (resource->pixels)
233 delete[] resource->pixels;
235 m_resources.erase(it);
238 void ResourceProvider::deleteOwnedResources(int pool)
240 DCHECK(m_threadChecker.CalledOnValidThread());
241 ResourceIdArray toDelete;
242 for (ResourceMap::iterator it = m_resources.begin(); it != m_resources.end(); ++it) {
243 if (it->second.pool == pool && !it->second.external && !it->second.markedForDeletion)
244 toDelete.push_back(it->first);
246 for (ResourceIdArray::iterator it = toDelete.begin(); it != toDelete.end(); ++it)
247 deleteResource(*it);
250 ResourceProvider::ResourceType ResourceProvider::resourceType(ResourceId id)
252 ResourceMap::iterator it = m_resources.find(id);
253 CHECK(it != m_resources.end());
254 Resource* resource = &it->second;
255 return resource->type;
258 void ResourceProvider::setPixels(ResourceId id, const uint8_t* image, const gfx::Rect& imageRect, const gfx::Rect& sourceRect, const gfx::Vector2d& destOffset)
260 DCHECK(m_threadChecker.CalledOnValidThread());
261 ResourceMap::iterator it = m_resources.find(id);
262 CHECK(it != m_resources.end());
263 Resource* resource = &it->second;
264 DCHECK(!resource->lockedForWrite);
265 DCHECK(!resource->lockForReadCount);
266 DCHECK(!resource->external);
267 DCHECK(!resource->exported);
269 if (resource->glId) {
270 WebGraphicsContext3D* context3d = m_context->context3D();
271 DCHECK(context3d);
272 DCHECK(m_textureUploader.get());
273 context3d->bindTexture(GL_TEXTURE_2D, resource->glId);
274 m_textureUploader->upload(image,
275 imageRect,
276 sourceRect,
277 destOffset,
278 resource->format,
279 resource->size);
282 if (resource->pixels) {
283 DCHECK(resource->format == GL_RGBA);
284 SkBitmap srcFull;
285 srcFull.setConfig(SkBitmap::kARGB_8888_Config, imageRect.width(), imageRect.height());
286 srcFull.setPixels(const_cast<uint8_t*>(image));
287 SkBitmap srcSubset;
288 SkIRect skSourceRect = SkIRect::MakeXYWH(sourceRect.x(), sourceRect.y(), sourceRect.width(), sourceRect.height());
289 skSourceRect.offset(-imageRect.x(), -imageRect.y());
290 srcFull.extractSubset(&srcSubset, skSourceRect);
292 ScopedWriteLockSoftware lock(this, id);
293 SkCanvas* dest = lock.skCanvas();
294 dest->writePixels(srcSubset, destOffset.x(), destOffset.y());
298 size_t ResourceProvider::numBlockingUploads()
300 if (!m_textureUploader)
301 return 0;
303 return m_textureUploader->numBlockingUploads();
306 void ResourceProvider::markPendingUploadsAsNonBlocking()
308 if (!m_textureUploader)
309 return;
311 m_textureUploader->markPendingUploadsAsNonBlocking();
314 double ResourceProvider::estimatedUploadsPerSecond()
316 if (!m_textureUploader)
317 return 0.0;
319 return m_textureUploader->estimatedTexturesPerSecond();
322 void ResourceProvider::flushUploads()
324 if (!m_textureUploader)
325 return;
327 m_textureUploader->flush();
330 void ResourceProvider::flush()
332 DCHECK(m_threadChecker.CalledOnValidThread());
333 WebGraphicsContext3D* context3d = m_context->context3D();
334 if (context3d)
335 context3d->flush();
338 bool ResourceProvider::shallowFlushIfSupported()
340 DCHECK(m_threadChecker.CalledOnValidThread());
341 WebGraphicsContext3D* context3d = m_context->context3D();
342 if (!context3d || !m_useShallowFlush)
343 return false;
345 context3d->shallowFlushCHROMIUM();
346 return true;
349 const ResourceProvider::Resource* ResourceProvider::lockForRead(ResourceId id)
351 DCHECK(m_threadChecker.CalledOnValidThread());
352 ResourceMap::iterator it = m_resources.find(id);
353 CHECK(it != m_resources.end());
354 Resource* resource = &it->second;
355 DCHECK(!resource->lockedForWrite);
356 DCHECK(!resource->exported);
357 resource->lockForReadCount++;
358 return resource;
361 void ResourceProvider::unlockForRead(ResourceId id)
363 DCHECK(m_threadChecker.CalledOnValidThread());
364 ResourceMap::iterator it = m_resources.find(id);
365 CHECK(it != m_resources.end());
366 Resource* resource = &it->second;
367 DCHECK(resource->lockForReadCount > 0);
368 DCHECK(!resource->exported);
369 resource->lockForReadCount--;
372 const ResourceProvider::Resource* ResourceProvider::lockForWrite(ResourceId id)
374 DCHECK(m_threadChecker.CalledOnValidThread());
375 ResourceMap::iterator it = m_resources.find(id);
376 CHECK(it != m_resources.end());
377 Resource* resource = &it->second;
378 DCHECK(!resource->lockedForWrite);
379 DCHECK(!resource->lockForReadCount);
380 DCHECK(!resource->exported);
381 DCHECK(!resource->external);
382 resource->lockedForWrite = true;
383 return resource;
386 void ResourceProvider::unlockForWrite(ResourceId id)
388 DCHECK(m_threadChecker.CalledOnValidThread());
389 ResourceMap::iterator it = m_resources.find(id);
390 CHECK(it != m_resources.end());
391 Resource* resource = &it->second;
392 DCHECK(resource->lockedForWrite);
393 DCHECK(!resource->exported);
394 DCHECK(!resource->external);
395 resource->lockedForWrite = false;
398 ResourceProvider::ScopedReadLockGL::ScopedReadLockGL(ResourceProvider* resourceProvider, ResourceProvider::ResourceId resourceId)
399 : m_resourceProvider(resourceProvider)
400 , m_resourceId(resourceId)
401 , m_textureId(resourceProvider->lockForRead(resourceId)->glId)
403 DCHECK(m_textureId);
406 ResourceProvider::ScopedReadLockGL::~ScopedReadLockGL()
408 m_resourceProvider->unlockForRead(m_resourceId);
411 ResourceProvider::ScopedWriteLockGL::ScopedWriteLockGL(ResourceProvider* resourceProvider, ResourceProvider::ResourceId resourceId)
412 : m_resourceProvider(resourceProvider)
413 , m_resourceId(resourceId)
414 , m_textureId(resourceProvider->lockForWrite(resourceId)->glId)
416 DCHECK(m_textureId);
419 ResourceProvider::ScopedWriteLockGL::~ScopedWriteLockGL()
421 m_resourceProvider->unlockForWrite(m_resourceId);
424 void ResourceProvider::populateSkBitmapWithResource(SkBitmap* skBitmap, const Resource* resource)
426 DCHECK(resource->pixels);
427 DCHECK(resource->format == GL_RGBA);
428 skBitmap->setConfig(SkBitmap::kARGB_8888_Config, resource->size.width(), resource->size.height());
429 skBitmap->setPixels(resource->pixels);
432 ResourceProvider::ScopedReadLockSoftware::ScopedReadLockSoftware(ResourceProvider* resourceProvider, ResourceProvider::ResourceId resourceId)
433 : m_resourceProvider(resourceProvider)
434 , m_resourceId(resourceId)
436 ResourceProvider::populateSkBitmapWithResource(&m_skBitmap, resourceProvider->lockForRead(resourceId));
439 ResourceProvider::ScopedReadLockSoftware::~ScopedReadLockSoftware()
441 m_resourceProvider->unlockForRead(m_resourceId);
444 ResourceProvider::ScopedWriteLockSoftware::ScopedWriteLockSoftware(ResourceProvider* resourceProvider, ResourceProvider::ResourceId resourceId)
445 : m_resourceProvider(resourceProvider)
446 , m_resourceId(resourceId)
448 ResourceProvider::populateSkBitmapWithResource(&m_skBitmap, resourceProvider->lockForWrite(resourceId));
449 m_skCanvas.reset(new SkCanvas(m_skBitmap));
452 ResourceProvider::ScopedWriteLockSoftware::~ScopedWriteLockSoftware()
454 m_resourceProvider->unlockForWrite(m_resourceId);
457 ResourceProvider::ResourceProvider(GraphicsContext* context)
458 : m_context(context)
459 , m_nextId(1)
460 , m_nextChild(1)
461 , m_defaultResourceType(GLTexture)
462 , m_useTextureStorageExt(false)
463 , m_useTextureUsageHint(false)
464 , m_useShallowFlush(false)
465 , m_maxTextureSize(0)
469 bool ResourceProvider::initialize()
471 DCHECK(m_threadChecker.CalledOnValidThread());
472 WebGraphicsContext3D* context3d = m_context->context3D();
473 if (!context3d) {
474 m_maxTextureSize = INT_MAX / 2;
475 return true;
477 if (!context3d->makeContextCurrent())
478 return false;
480 std::string extensionsString = UTF16ToASCII(context3d->getString(GL_EXTENSIONS));
481 std::vector<std::string> extensions;
482 base::SplitString(extensionsString, ' ', &extensions);
483 bool useMapSub = false;
484 bool useBindUniform = false;
485 for (size_t i = 0; i < extensions.size(); ++i) {
486 if (extensions[i] == "GL_EXT_texture_storage")
487 m_useTextureStorageExt = true;
488 else if (extensions[i] == "GL_ANGLE_texture_usage")
489 m_useTextureUsageHint = true;
490 else if (extensions[i] == "GL_CHROMIUM_map_sub")
491 useMapSub = true;
492 else if (extensions[i] == "GL_CHROMIUM_shallow_flush")
493 m_useShallowFlush = true;
494 else if (extensions[i] == "GL_CHROMIUM_bind_uniform_location")
495 useBindUniform = true;
498 m_textureCopier = AcceleratedTextureCopier::create(context3d, useBindUniform);
500 m_textureUploader = TextureUploader::create(context3d, useMapSub, m_useShallowFlush);
501 GLC(context3d, context3d->getIntegerv(GL_MAX_TEXTURE_SIZE, &m_maxTextureSize));
502 return true;
505 int ResourceProvider::createChild(int pool)
507 DCHECK(m_threadChecker.CalledOnValidThread());
508 Child childInfo;
509 childInfo.pool = pool;
510 int child = m_nextChild++;
511 m_children[child] = childInfo;
512 return child;
515 void ResourceProvider::destroyChild(int child)
517 DCHECK(m_threadChecker.CalledOnValidThread());
518 ChildMap::iterator it = m_children.find(child);
519 DCHECK(it != m_children.end());
520 deleteOwnedResources(it->second.pool);
521 m_children.erase(it);
524 const ResourceProvider::ResourceIdMap& ResourceProvider::getChildToParentMap(int child) const
526 DCHECK(m_threadChecker.CalledOnValidThread());
527 ChildMap::const_iterator it = m_children.find(child);
528 DCHECK(it != m_children.end());
529 return it->second.childToParentMap;
532 void ResourceProvider::prepareSendToParent(const ResourceIdArray& resources, TransferableResourceList* list)
534 DCHECK(m_threadChecker.CalledOnValidThread());
535 list->sync_point = 0;
536 list->resources.clear();
537 WebGraphicsContext3D* context3d = m_context->context3D();
538 if (!context3d || !context3d->makeContextCurrent()) {
539 // FIXME: Implement this path for software compositing.
540 return;
542 for (ResourceIdArray::const_iterator it = resources.begin(); it != resources.end(); ++it) {
543 TransferableResource resource;
544 if (transferResource(context3d, *it, &resource)) {
545 m_resources.find(*it)->second.exported = true;
546 list->resources.push_back(resource);
549 if (list->resources.size())
550 list->sync_point = context3d->insertSyncPoint();
553 void ResourceProvider::prepareSendToChild(int child, const ResourceIdArray& resources, TransferableResourceList* list)
555 DCHECK(m_threadChecker.CalledOnValidThread());
556 list->sync_point = 0;
557 list->resources.clear();
558 WebGraphicsContext3D* context3d = m_context->context3D();
559 if (!context3d || !context3d->makeContextCurrent()) {
560 // FIXME: Implement this path for software compositing.
561 return;
563 Child& childInfo = m_children.find(child)->second;
564 for (ResourceIdArray::const_iterator it = resources.begin(); it != resources.end(); ++it) {
565 TransferableResource resource;
566 if (!transferResource(context3d, *it, &resource))
567 NOTREACHED();
568 DCHECK(childInfo.parentToChildMap.find(*it) != childInfo.parentToChildMap.end());
569 resource.id = childInfo.parentToChildMap[*it];
570 childInfo.parentToChildMap.erase(*it);
571 childInfo.childToParentMap.erase(resource.id);
572 list->resources.push_back(resource);
573 deleteResource(*it);
575 if (list->resources.size())
576 list->sync_point = context3d->insertSyncPoint();
579 void ResourceProvider::receiveFromChild(int child, const TransferableResourceList& resources)
581 DCHECK(m_threadChecker.CalledOnValidThread());
582 WebGraphicsContext3D* context3d = m_context->context3D();
583 if (!context3d || !context3d->makeContextCurrent()) {
584 // FIXME: Implement this path for software compositing.
585 return;
587 if (resources.sync_point) {
588 // NOTE: If the parent is a browser and the child a renderer, the parent
589 // is not supposed to have its context wait, because that could induce
590 // deadlocks and/or security issues. The caller is responsible for
591 // waiting asynchronously, and resetting sync_point before calling this.
592 // However if the parent is a renderer (e.g. browser tag), it may be ok
593 // (and is simpler) to wait.
594 GLC(context3d, context3d->waitSyncPoint(resources.sync_point));
596 Child& childInfo = m_children.find(child)->second;
597 for (TransferableResourceArray::const_iterator it = resources.resources.begin(); it != resources.resources.end(); ++it) {
598 unsigned textureId;
599 GLC(context3d, textureId = context3d->createTexture());
600 GLC(context3d, context3d->bindTexture(GL_TEXTURE_2D, textureId));
601 GLC(context3d, context3d->consumeTextureCHROMIUM(GL_TEXTURE_2D, it->mailbox.name));
602 ResourceId id = m_nextId++;
603 Resource resource(textureId, childInfo.pool, it->size, it->format);
604 resource.mailbox.setName(it->mailbox.name);
605 m_resources[id] = resource;
606 childInfo.parentToChildMap[id] = it->id;
607 childInfo.childToParentMap[it->id] = id;
611 void ResourceProvider::receiveFromParent(const TransferableResourceList& resources)
613 DCHECK(m_threadChecker.CalledOnValidThread());
614 WebGraphicsContext3D* context3d = m_context->context3D();
615 if (!context3d || !context3d->makeContextCurrent()) {
616 // FIXME: Implement this path for software compositing.
617 return;
619 if (resources.sync_point)
620 GLC(context3d, context3d->waitSyncPoint(resources.sync_point));
621 for (TransferableResourceArray::const_iterator it = resources.resources.begin(); it != resources.resources.end(); ++it) {
622 ResourceMap::iterator mapIterator = m_resources.find(it->id);
623 DCHECK(mapIterator != m_resources.end());
624 Resource* resource = &mapIterator->second;
625 DCHECK(resource->exported);
626 resource->exported = false;
627 resource->mailbox.setName(it->mailbox.name);
628 GLC(context3d, context3d->bindTexture(GL_TEXTURE_2D, resource->glId));
629 GLC(context3d, context3d->consumeTextureCHROMIUM(GL_TEXTURE_2D, it->mailbox.name));
630 if (resource->markedForDeletion)
631 deleteResourceInternal(mapIterator);
635 bool ResourceProvider::transferResource(WebGraphicsContext3D* context, ResourceId id, TransferableResource* resource)
637 DCHECK(m_threadChecker.CalledOnValidThread());
638 WebGraphicsContext3D* context3d = m_context->context3D();
639 ResourceMap::iterator it = m_resources.find(id);
640 CHECK(it != m_resources.end());
641 Resource* source = &it->second;
642 DCHECK(!source->lockedForWrite);
643 DCHECK(!source->lockForReadCount);
644 DCHECK(!source->external);
645 if (source->exported)
646 return false;
647 resource->id = id;
648 resource->format = source->format;
649 resource->size = source->size;
651 if (source->mailbox.isZero()) {
652 GLbyte name[GL_MAILBOX_SIZE_CHROMIUM];
653 GLC(context3d, context3d->genMailboxCHROMIUM(name));
654 source->mailbox.setName(name);
657 resource->mailbox = source->mailbox;
658 GLC(context, context->bindTexture(GL_TEXTURE_2D, source->glId));
659 GLC(context, context->produceTextureCHROMIUM(GL_TEXTURE_2D, resource->mailbox.name));
660 return true;
663 } // namespace cc