Add intro to any Chrome app API with no overview docs.
[chromium-blink-merge.git] / cc / resource_provider.cc
blob9f208af335811554168e1213c6c903810362df6a
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 , glPixelBufferId(0)
53 , pixels(0)
54 , pixelBuffer(0)
55 , pool(0)
56 , lockForReadCount(0)
57 , lockedForWrite(false)
58 , external(false)
59 , exported(false)
60 , markedForDeletion(false)
61 , size()
62 , format(0)
63 , type(static_cast<ResourceType>(0))
67 ResourceProvider::Resource::Resource(unsigned textureId, int pool, const gfx::Size& size, GLenum format)
68 : glId(textureId)
69 , glPixelBufferId(0)
70 , pixels(0)
71 , pixelBuffer(0)
72 , pool(pool)
73 , lockForReadCount(0)
74 , lockedForWrite(false)
75 , external(false)
76 , exported(false)
77 , markedForDeletion(false)
78 , size(size)
79 , format(format)
80 , type(GLTexture)
84 ResourceProvider::Resource::Resource(uint8_t* pixels, int pool, const gfx::Size& size, GLenum format)
85 : glId(0)
86 , glPixelBufferId(0)
87 , pixels(pixels)
88 , pixelBuffer(0)
89 , pool(pool)
90 , lockForReadCount(0)
91 , lockedForWrite(false)
92 , external(false)
93 , exported(false)
94 , markedForDeletion(false)
95 , size(size)
96 , format(format)
97 , type(Bitmap)
101 ResourceProvider::Child::Child()
105 ResourceProvider::Child::~Child()
109 scoped_ptr<ResourceProvider> ResourceProvider::create(GraphicsContext* context)
111 scoped_ptr<ResourceProvider> resourceProvider(new ResourceProvider(context));
112 if (!resourceProvider->initialize())
113 return scoped_ptr<ResourceProvider>();
114 return resourceProvider.Pass();
117 ResourceProvider::~ResourceProvider()
119 WebGraphicsContext3D* context3d = m_context->context3D();
120 if (!context3d || !context3d->makeContextCurrent())
121 return;
122 m_textureUploader.reset();
123 m_textureCopier.reset();
126 WebGraphicsContext3D* ResourceProvider::graphicsContext3D()
128 DCHECK(m_threadChecker.CalledOnValidThread());
129 return m_context->context3D();
132 bool ResourceProvider::inUseByConsumer(ResourceId id)
134 DCHECK(m_threadChecker.CalledOnValidThread());
135 ResourceMap::iterator it = m_resources.find(id);
136 CHECK(it != m_resources.end());
137 Resource* resource = &it->second;
138 return !!resource->lockForReadCount || resource->exported;
141 ResourceProvider::ResourceId ResourceProvider::createResource(int pool, const gfx::Size& size, GLenum format, TextureUsageHint hint)
143 switch (m_defaultResourceType) {
144 case GLTexture:
145 return createGLTexture(pool, size, format, hint);
146 case Bitmap:
147 DCHECK(format == GL_RGBA);
148 return createBitmap(pool, size);
151 LOG(FATAL) << "Invalid default resource type.";
152 return 0;
155 ResourceProvider::ResourceId ResourceProvider::createGLTexture(int pool, const gfx::Size& size, GLenum format, TextureUsageHint hint)
157 DCHECK_LE(size.width(), m_maxTextureSize);
158 DCHECK_LE(size.height(), m_maxTextureSize);
160 DCHECK(m_threadChecker.CalledOnValidThread());
161 unsigned textureId = 0;
162 WebGraphicsContext3D* context3d = m_context->context3D();
163 DCHECK(context3d);
164 GLC(context3d, textureId = context3d->createTexture());
165 GLC(context3d, context3d->bindTexture(GL_TEXTURE_2D, textureId));
166 GLC(context3d, context3d->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
167 GLC(context3d, context3d->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
168 GLC(context3d, context3d->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
169 GLC(context3d, context3d->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
171 if (m_useTextureUsageHint && hint == TextureUsageFramebuffer)
172 GLC(context3d, context3d->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_USAGE_ANGLE, GL_FRAMEBUFFER_ATTACHMENT_ANGLE));
173 if (m_useTextureStorageExt && isTextureFormatSupportedForStorage(format)) {
174 GLenum storageFormat = textureToStorageFormat(format);
175 GLC(context3d, context3d->texStorage2DEXT(GL_TEXTURE_2D, 1, storageFormat, size.width(), size.height()));
176 } else
177 GLC(context3d, context3d->texImage2D(GL_TEXTURE_2D, 0, format, size.width(), size.height(), 0, format, GL_UNSIGNED_BYTE, 0));
179 ResourceId id = m_nextId++;
180 Resource resource(textureId, pool, size, format);
181 m_resources[id] = resource;
182 return id;
185 ResourceProvider::ResourceId ResourceProvider::createBitmap(int pool, const gfx::Size& size)
187 DCHECK(m_threadChecker.CalledOnValidThread());
189 uint8_t* pixels = new uint8_t[size.width() * size.height() * 4];
191 ResourceId id = m_nextId++;
192 Resource resource(pixels, pool, size, GL_RGBA);
193 m_resources[id] = resource;
194 return id;
197 ResourceProvider::ResourceId ResourceProvider::createResourceFromExternalTexture(unsigned textureId)
199 DCHECK(m_threadChecker.CalledOnValidThread());
201 WebGraphicsContext3D* context3d = m_context->context3D();
202 DCHECK(context3d);
203 GLC(context3d, context3d->bindTexture(GL_TEXTURE_2D, textureId));
204 GLC(context3d, context3d->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
205 GLC(context3d, context3d->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
206 GLC(context3d, context3d->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
207 GLC(context3d, context3d->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
209 ResourceId id = m_nextId++;
210 Resource resource(textureId, 0, gfx::Size(), 0);
211 resource.external = true;
212 m_resources[id] = resource;
213 return id;
216 void ResourceProvider::deleteResource(ResourceId id)
218 DCHECK(m_threadChecker.CalledOnValidThread());
219 ResourceMap::iterator it = m_resources.find(id);
220 CHECK(it != m_resources.end());
221 Resource* resource = &it->second;
222 DCHECK(!resource->lockedForWrite);
223 DCHECK(!resource->lockForReadCount);
224 DCHECK(!resource->markedForDeletion);
226 if (resource->exported) {
227 resource->markedForDeletion = true;
228 return;
229 } else
230 deleteResourceInternal(it);
233 void ResourceProvider::deleteResourceInternal(ResourceMap::iterator it)
235 Resource* resource = &it->second;
236 if (resource->glId && !resource->external) {
237 WebGraphicsContext3D* context3d = m_context->context3D();
238 DCHECK(context3d);
239 GLC(context3d, context3d->deleteTexture(resource->glId));
241 if (resource->glPixelBufferId) {
242 WebGraphicsContext3D* context3d = m_context->context3D();
243 DCHECK(context3d);
244 GLC(context3d, context3d->deleteBuffer(resource->glPixelBufferId));
246 if (resource->pixels)
247 delete[] resource->pixels;
248 if (resource->pixelBuffer)
249 delete[] resource->pixelBuffer;
251 m_resources.erase(it);
254 void ResourceProvider::deleteOwnedResources(int pool)
256 DCHECK(m_threadChecker.CalledOnValidThread());
257 ResourceIdArray toDelete;
258 for (ResourceMap::iterator it = m_resources.begin(); it != m_resources.end(); ++it) {
259 if (it->second.pool == pool && !it->second.external && !it->second.markedForDeletion)
260 toDelete.push_back(it->first);
262 for (ResourceIdArray::iterator it = toDelete.begin(); it != toDelete.end(); ++it)
263 deleteResource(*it);
266 ResourceProvider::ResourceType ResourceProvider::resourceType(ResourceId id)
268 ResourceMap::iterator it = m_resources.find(id);
269 CHECK(it != m_resources.end());
270 Resource* resource = &it->second;
271 return resource->type;
274 void ResourceProvider::setPixels(ResourceId id, const uint8_t* image, const gfx::Rect& imageRect, const gfx::Rect& sourceRect, const gfx::Vector2d& destOffset)
276 DCHECK(m_threadChecker.CalledOnValidThread());
277 ResourceMap::iterator it = m_resources.find(id);
278 CHECK(it != m_resources.end());
279 Resource* resource = &it->second;
280 DCHECK(!resource->lockedForWrite);
281 DCHECK(!resource->lockForReadCount);
282 DCHECK(!resource->external);
283 DCHECK(!resource->exported);
285 if (resource->glId) {
286 WebGraphicsContext3D* context3d = m_context->context3D();
287 DCHECK(context3d);
288 DCHECK(m_textureUploader.get());
289 context3d->bindTexture(GL_TEXTURE_2D, resource->glId);
290 m_textureUploader->upload(image,
291 imageRect,
292 sourceRect,
293 destOffset,
294 resource->format,
295 resource->size);
298 if (resource->pixels) {
299 DCHECK(resource->format == GL_RGBA);
300 SkBitmap srcFull;
301 srcFull.setConfig(SkBitmap::kARGB_8888_Config, imageRect.width(), imageRect.height());
302 srcFull.setPixels(const_cast<uint8_t*>(image));
303 SkBitmap srcSubset;
304 SkIRect skSourceRect = SkIRect::MakeXYWH(sourceRect.x(), sourceRect.y(), sourceRect.width(), sourceRect.height());
305 skSourceRect.offset(-imageRect.x(), -imageRect.y());
306 srcFull.extractSubset(&srcSubset, skSourceRect);
308 ScopedWriteLockSoftware lock(this, id);
309 SkCanvas* dest = lock.skCanvas();
310 dest->writePixels(srcSubset, destOffset.x(), destOffset.y());
314 size_t ResourceProvider::numBlockingUploads()
316 if (!m_textureUploader)
317 return 0;
319 return m_textureUploader->numBlockingUploads();
322 void ResourceProvider::markPendingUploadsAsNonBlocking()
324 if (!m_textureUploader)
325 return;
327 m_textureUploader->markPendingUploadsAsNonBlocking();
330 double ResourceProvider::estimatedUploadsPerSecond()
332 if (!m_textureUploader)
333 return 0.0;
335 return m_textureUploader->estimatedTexturesPerSecond();
338 void ResourceProvider::flushUploads()
340 if (!m_textureUploader)
341 return;
343 m_textureUploader->flush();
346 void ResourceProvider::flush()
348 DCHECK(m_threadChecker.CalledOnValidThread());
349 WebGraphicsContext3D* context3d = m_context->context3D();
350 if (context3d)
351 context3d->flush();
354 bool ResourceProvider::shallowFlushIfSupported()
356 DCHECK(m_threadChecker.CalledOnValidThread());
357 WebGraphicsContext3D* context3d = m_context->context3D();
358 if (!context3d || !m_useShallowFlush)
359 return false;
361 context3d->shallowFlushCHROMIUM();
362 return true;
365 const ResourceProvider::Resource* ResourceProvider::lockForRead(ResourceId id)
367 DCHECK(m_threadChecker.CalledOnValidThread());
368 ResourceMap::iterator it = m_resources.find(id);
369 CHECK(it != m_resources.end());
370 Resource* resource = &it->second;
371 DCHECK(!resource->lockedForWrite);
372 DCHECK(!resource->exported);
373 resource->lockForReadCount++;
374 return resource;
377 void ResourceProvider::unlockForRead(ResourceId id)
379 DCHECK(m_threadChecker.CalledOnValidThread());
380 ResourceMap::iterator it = m_resources.find(id);
381 CHECK(it != m_resources.end());
382 Resource* resource = &it->second;
383 DCHECK(resource->lockForReadCount > 0);
384 DCHECK(!resource->exported);
385 resource->lockForReadCount--;
388 const ResourceProvider::Resource* ResourceProvider::lockForWrite(ResourceId id)
390 DCHECK(m_threadChecker.CalledOnValidThread());
391 ResourceMap::iterator it = m_resources.find(id);
392 CHECK(it != m_resources.end());
393 Resource* resource = &it->second;
394 DCHECK(!resource->lockedForWrite);
395 DCHECK(!resource->lockForReadCount);
396 DCHECK(!resource->exported);
397 DCHECK(!resource->external);
398 resource->lockedForWrite = true;
399 return resource;
402 void ResourceProvider::unlockForWrite(ResourceId id)
404 DCHECK(m_threadChecker.CalledOnValidThread());
405 ResourceMap::iterator it = m_resources.find(id);
406 CHECK(it != m_resources.end());
407 Resource* resource = &it->second;
408 DCHECK(resource->lockedForWrite);
409 DCHECK(!resource->exported);
410 DCHECK(!resource->external);
411 resource->lockedForWrite = false;
414 ResourceProvider::ScopedReadLockGL::ScopedReadLockGL(ResourceProvider* resourceProvider, ResourceProvider::ResourceId resourceId)
415 : m_resourceProvider(resourceProvider)
416 , m_resourceId(resourceId)
417 , m_textureId(resourceProvider->lockForRead(resourceId)->glId)
419 DCHECK(m_textureId);
422 ResourceProvider::ScopedReadLockGL::~ScopedReadLockGL()
424 m_resourceProvider->unlockForRead(m_resourceId);
427 ResourceProvider::ScopedWriteLockGL::ScopedWriteLockGL(ResourceProvider* resourceProvider, ResourceProvider::ResourceId resourceId)
428 : m_resourceProvider(resourceProvider)
429 , m_resourceId(resourceId)
430 , m_textureId(resourceProvider->lockForWrite(resourceId)->glId)
432 DCHECK(m_textureId);
435 ResourceProvider::ScopedWriteLockGL::~ScopedWriteLockGL()
437 m_resourceProvider->unlockForWrite(m_resourceId);
440 void ResourceProvider::populateSkBitmapWithResource(SkBitmap* skBitmap, const Resource* resource)
442 DCHECK(resource->pixels);
443 DCHECK(resource->format == GL_RGBA);
444 skBitmap->setConfig(SkBitmap::kARGB_8888_Config, resource->size.width(), resource->size.height());
445 skBitmap->setPixels(resource->pixels);
448 ResourceProvider::ScopedReadLockSoftware::ScopedReadLockSoftware(ResourceProvider* resourceProvider, ResourceProvider::ResourceId resourceId)
449 : m_resourceProvider(resourceProvider)
450 , m_resourceId(resourceId)
452 ResourceProvider::populateSkBitmapWithResource(&m_skBitmap, resourceProvider->lockForRead(resourceId));
455 ResourceProvider::ScopedReadLockSoftware::~ScopedReadLockSoftware()
457 m_resourceProvider->unlockForRead(m_resourceId);
460 ResourceProvider::ScopedWriteLockSoftware::ScopedWriteLockSoftware(ResourceProvider* resourceProvider, ResourceProvider::ResourceId resourceId)
461 : m_resourceProvider(resourceProvider)
462 , m_resourceId(resourceId)
464 ResourceProvider::populateSkBitmapWithResource(&m_skBitmap, resourceProvider->lockForWrite(resourceId));
465 m_skCanvas.reset(new SkCanvas(m_skBitmap));
468 ResourceProvider::ScopedWriteLockSoftware::~ScopedWriteLockSoftware()
470 m_resourceProvider->unlockForWrite(m_resourceId);
473 ResourceProvider::ResourceProvider(GraphicsContext* context)
474 : m_context(context)
475 , m_nextId(1)
476 , m_nextChild(1)
477 , m_defaultResourceType(GLTexture)
478 , m_useTextureStorageExt(false)
479 , m_useTextureUsageHint(false)
480 , m_useShallowFlush(false)
481 , m_maxTextureSize(0)
485 bool ResourceProvider::initialize()
487 DCHECK(m_threadChecker.CalledOnValidThread());
488 WebGraphicsContext3D* context3d = m_context->context3D();
489 if (!context3d) {
490 m_maxTextureSize = INT_MAX / 2;
491 return true;
493 if (!context3d->makeContextCurrent())
494 return false;
496 std::string extensionsString = UTF16ToASCII(context3d->getString(GL_EXTENSIONS));
497 std::vector<std::string> extensions;
498 base::SplitString(extensionsString, ' ', &extensions);
499 bool useMapSub = false;
500 bool useBindUniform = false;
501 for (size_t i = 0; i < extensions.size(); ++i) {
502 if (extensions[i] == "GL_EXT_texture_storage")
503 m_useTextureStorageExt = true;
504 else if (extensions[i] == "GL_ANGLE_texture_usage")
505 m_useTextureUsageHint = true;
506 else if (extensions[i] == "GL_CHROMIUM_map_sub")
507 useMapSub = true;
508 else if (extensions[i] == "GL_CHROMIUM_shallow_flush")
509 m_useShallowFlush = true;
510 else if (extensions[i] == "GL_CHROMIUM_bind_uniform_location")
511 useBindUniform = true;
514 m_textureCopier = AcceleratedTextureCopier::create(context3d, useBindUniform);
516 m_textureUploader = TextureUploader::create(context3d, useMapSub, m_useShallowFlush);
517 GLC(context3d, context3d->getIntegerv(GL_MAX_TEXTURE_SIZE, &m_maxTextureSize));
518 return true;
521 int ResourceProvider::createChild(int pool)
523 DCHECK(m_threadChecker.CalledOnValidThread());
524 Child childInfo;
525 childInfo.pool = pool;
526 int child = m_nextChild++;
527 m_children[child] = childInfo;
528 return child;
531 void ResourceProvider::destroyChild(int child)
533 DCHECK(m_threadChecker.CalledOnValidThread());
534 ChildMap::iterator it = m_children.find(child);
535 DCHECK(it != m_children.end());
536 deleteOwnedResources(it->second.pool);
537 m_children.erase(it);
540 const ResourceProvider::ResourceIdMap& ResourceProvider::getChildToParentMap(int child) const
542 DCHECK(m_threadChecker.CalledOnValidThread());
543 ChildMap::const_iterator it = m_children.find(child);
544 DCHECK(it != m_children.end());
545 return it->second.childToParentMap;
548 void ResourceProvider::prepareSendToParent(const ResourceIdArray& resources, TransferableResourceList* list)
550 DCHECK(m_threadChecker.CalledOnValidThread());
551 list->sync_point = 0;
552 list->resources.clear();
553 WebGraphicsContext3D* context3d = m_context->context3D();
554 if (!context3d || !context3d->makeContextCurrent()) {
555 // FIXME: Implement this path for software compositing.
556 return;
558 for (ResourceIdArray::const_iterator it = resources.begin(); it != resources.end(); ++it) {
559 TransferableResource resource;
560 if (transferResource(context3d, *it, &resource)) {
561 m_resources.find(*it)->second.exported = true;
562 list->resources.push_back(resource);
565 if (list->resources.size())
566 list->sync_point = context3d->insertSyncPoint();
569 void ResourceProvider::prepareSendToChild(int child, const ResourceIdArray& resources, TransferableResourceList* list)
571 DCHECK(m_threadChecker.CalledOnValidThread());
572 list->sync_point = 0;
573 list->resources.clear();
574 WebGraphicsContext3D* context3d = m_context->context3D();
575 if (!context3d || !context3d->makeContextCurrent()) {
576 // FIXME: Implement this path for software compositing.
577 return;
579 Child& childInfo = m_children.find(child)->second;
580 for (ResourceIdArray::const_iterator it = resources.begin(); it != resources.end(); ++it) {
581 TransferableResource resource;
582 if (!transferResource(context3d, *it, &resource))
583 NOTREACHED();
584 DCHECK(childInfo.parentToChildMap.find(*it) != childInfo.parentToChildMap.end());
585 resource.id = childInfo.parentToChildMap[*it];
586 childInfo.parentToChildMap.erase(*it);
587 childInfo.childToParentMap.erase(resource.id);
588 list->resources.push_back(resource);
589 deleteResource(*it);
591 if (list->resources.size())
592 list->sync_point = context3d->insertSyncPoint();
595 void ResourceProvider::receiveFromChild(int child, const TransferableResourceList& resources)
597 DCHECK(m_threadChecker.CalledOnValidThread());
598 WebGraphicsContext3D* context3d = m_context->context3D();
599 if (!context3d || !context3d->makeContextCurrent()) {
600 // FIXME: Implement this path for software compositing.
601 return;
603 if (resources.sync_point) {
604 // NOTE: If the parent is a browser and the child a renderer, the parent
605 // is not supposed to have its context wait, because that could induce
606 // deadlocks and/or security issues. The caller is responsible for
607 // waiting asynchronously, and resetting sync_point before calling this.
608 // However if the parent is a renderer (e.g. browser tag), it may be ok
609 // (and is simpler) to wait.
610 GLC(context3d, context3d->waitSyncPoint(resources.sync_point));
612 Child& childInfo = m_children.find(child)->second;
613 for (TransferableResourceArray::const_iterator it = resources.resources.begin(); it != resources.resources.end(); ++it) {
614 unsigned textureId;
615 GLC(context3d, textureId = context3d->createTexture());
616 GLC(context3d, context3d->bindTexture(GL_TEXTURE_2D, textureId));
617 GLC(context3d, context3d->consumeTextureCHROMIUM(GL_TEXTURE_2D, it->mailbox.name));
618 ResourceId id = m_nextId++;
619 Resource resource(textureId, childInfo.pool, it->size, it->format);
620 resource.mailbox.setName(it->mailbox.name);
621 m_resources[id] = resource;
622 childInfo.parentToChildMap[id] = it->id;
623 childInfo.childToParentMap[it->id] = id;
627 void ResourceProvider::receiveFromParent(const TransferableResourceList& resources)
629 DCHECK(m_threadChecker.CalledOnValidThread());
630 WebGraphicsContext3D* context3d = m_context->context3D();
631 if (!context3d || !context3d->makeContextCurrent()) {
632 // FIXME: Implement this path for software compositing.
633 return;
635 if (resources.sync_point)
636 GLC(context3d, context3d->waitSyncPoint(resources.sync_point));
637 for (TransferableResourceArray::const_iterator it = resources.resources.begin(); it != resources.resources.end(); ++it) {
638 ResourceMap::iterator mapIterator = m_resources.find(it->id);
639 DCHECK(mapIterator != m_resources.end());
640 Resource* resource = &mapIterator->second;
641 DCHECK(resource->exported);
642 resource->exported = false;
643 resource->mailbox.setName(it->mailbox.name);
644 GLC(context3d, context3d->bindTexture(GL_TEXTURE_2D, resource->glId));
645 GLC(context3d, context3d->consumeTextureCHROMIUM(GL_TEXTURE_2D, it->mailbox.name));
646 if (resource->markedForDeletion)
647 deleteResourceInternal(mapIterator);
651 bool ResourceProvider::transferResource(WebGraphicsContext3D* context, ResourceId id, TransferableResource* resource)
653 DCHECK(m_threadChecker.CalledOnValidThread());
654 WebGraphicsContext3D* context3d = m_context->context3D();
655 ResourceMap::iterator it = m_resources.find(id);
656 CHECK(it != m_resources.end());
657 Resource* source = &it->second;
658 DCHECK(!source->lockedForWrite);
659 DCHECK(!source->lockForReadCount);
660 DCHECK(!source->external);
661 if (source->exported)
662 return false;
663 resource->id = id;
664 resource->format = source->format;
665 resource->size = source->size;
667 if (source->mailbox.isZero()) {
668 GLbyte name[GL_MAILBOX_SIZE_CHROMIUM];
669 GLC(context3d, context3d->genMailboxCHROMIUM(name));
670 source->mailbox.setName(name);
673 resource->mailbox = source->mailbox;
674 GLC(context, context->bindTexture(GL_TEXTURE_2D, source->glId));
675 GLC(context, context->produceTextureCHROMIUM(GL_TEXTURE_2D, resource->mailbox.name));
676 return true;
679 void ResourceProvider::acquirePixelBuffer(ResourceId id)
681 DCHECK(m_threadChecker.CalledOnValidThread());
682 ResourceMap::iterator it = m_resources.find(id);
683 CHECK(it != m_resources.end());
684 Resource* resource = &it->second;
685 DCHECK(!resource->external);
686 DCHECK(!resource->exported);
688 if (resource->glId) {
689 if (resource->glPixelBufferId)
690 return;
691 WebGraphicsContext3D* context3d = m_context->context3D();
692 DCHECK(context3d);
693 resource->glPixelBufferId = context3d->createBuffer();
694 context3d->bindBuffer(
695 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
696 resource->glPixelBufferId);
697 context3d->bufferData(
698 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
699 resource->size.width() * resource->size.height() * 4,
700 NULL,
701 GL_DYNAMIC_DRAW);
702 context3d->bindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0);
705 if (resource->pixels) {
706 if (resource->pixelBuffer)
707 return;
709 resource->pixelBuffer = new uint8_t[
710 resource->size.width() * resource->size.height() * 4];
714 void ResourceProvider::releasePixelBuffer(ResourceId id)
716 DCHECK(m_threadChecker.CalledOnValidThread());
717 ResourceMap::iterator it = m_resources.find(id);
718 CHECK(it != m_resources.end());
719 Resource* resource = &it->second;
720 DCHECK(!resource->external);
721 DCHECK(!resource->exported);
723 if (resource->glId) {
724 if (!resource->glPixelBufferId)
725 return;
726 WebGraphicsContext3D* context3d = m_context->context3D();
727 DCHECK(context3d);
728 context3d->deleteBuffer(resource->glPixelBufferId);
729 resource->glPixelBufferId = 0;
732 if (resource->pixels) {
733 if (!resource->pixelBuffer)
734 return;
735 delete[] resource->pixelBuffer;
736 resource->pixelBuffer = 0;
740 uint8_t* ResourceProvider::mapPixelBuffer(ResourceId id)
742 DCHECK(m_threadChecker.CalledOnValidThread());
743 ResourceMap::iterator it = m_resources.find(id);
744 CHECK(it != m_resources.end());
745 Resource* resource = &it->second;
746 DCHECK(!resource->external);
747 DCHECK(!resource->exported);
749 if (resource->glId) {
750 WebGraphicsContext3D* context3d = m_context->context3D();
751 DCHECK(context3d);
752 DCHECK(resource->glPixelBufferId);
753 context3d->bindBuffer(
754 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
755 resource->glPixelBufferId);
756 uint8_t* image = static_cast<uint8_t*>(
757 context3d->mapBufferCHROMIUM(
758 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, GL_WRITE_ONLY));
759 context3d->bindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0);
760 DCHECK(image);
761 return image;
764 if (resource->pixels)
765 return resource->pixelBuffer;
767 return NULL;
770 void ResourceProvider::unmapPixelBuffer(ResourceId id)
772 DCHECK(m_threadChecker.CalledOnValidThread());
773 ResourceMap::iterator it = m_resources.find(id);
774 CHECK(it != m_resources.end());
775 Resource* resource = &it->second;
776 DCHECK(!resource->external);
777 DCHECK(!resource->exported);
779 if (resource->glId) {
780 WebGraphicsContext3D* context3d = m_context->context3D();
781 DCHECK(context3d);
782 DCHECK(resource->glPixelBufferId);
783 context3d->bindBuffer(
784 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
785 resource->glPixelBufferId);
786 context3d->unmapBufferCHROMIUM(
787 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM);
788 context3d->bindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0);
792 void ResourceProvider::setPixelsFromBuffer(ResourceId id)
794 DCHECK(m_threadChecker.CalledOnValidThread());
795 ResourceMap::iterator it = m_resources.find(id);
796 CHECK(it != m_resources.end());
797 Resource* resource = &it->second;
798 DCHECK(!resource->lockedForWrite);
799 DCHECK(!resource->lockForReadCount);
800 DCHECK(!resource->external);
801 DCHECK(!resource->exported);
803 if (resource->glId) {
804 WebGraphicsContext3D* context3d = m_context->context3D();
805 DCHECK(context3d);
806 DCHECK(resource->glPixelBufferId);
807 context3d->bindTexture(GL_TEXTURE_2D, resource->glId);
808 context3d->bindBuffer(
809 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
810 resource->glPixelBufferId);
811 context3d->texSubImage2D(GL_TEXTURE_2D,
812 0, /* level */
813 0, /* x */
814 0, /* y */
815 resource->size.width(),
816 resource->size.height(),
817 resource->format,
818 GL_UNSIGNED_BYTE,
819 NULL);
820 context3d->bindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0);
823 if (resource->pixels) {
824 DCHECK(resource->pixelBuffer);
825 DCHECK(resource->format == GL_RGBA);
826 SkBitmap src;
827 src.setConfig(SkBitmap::kARGB_8888_Config,
828 resource->size.width(),
829 resource->size.height());
830 src.setPixels(resource->pixelBuffer);
832 ScopedWriteLockSoftware lock(this, id);
833 SkCanvas* dest = lock.skCanvas();
834 dest->writePixels(src, 0, 0);
838 } // namespace cc