Use SCHEME_HTTP for HTTPS proxies on Android.
[chromium-blink-merge.git] / cc / resource_provider.cc
blob2cd7b4ce7f65bea623d8d2a067c5ddc2e159cadc
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/platform_color.h"
16 #include "cc/texture_uploader.h"
17 #include "cc/transferable_resource.h"
18 #include "third_party/khronos/GLES2/gl2.h"
19 #include "third_party/khronos/GLES2/gl2ext.h"
20 #include "ui/gfx/rect.h"
21 #include "ui/gfx/vector2d.h"
23 #include <public/WebGraphicsContext3D.h>
25 using WebKit::WebGraphicsContext3D;
27 namespace cc {
29 static GLenum textureToStorageFormat(GLenum textureFormat)
31 GLenum storageFormat = GL_RGBA8_OES;
32 switch (textureFormat) {
33 case GL_RGBA:
34 break;
35 case GL_BGRA_EXT:
36 storageFormat = GL_BGRA8_EXT;
37 break;
38 default:
39 NOTREACHED();
40 break;
43 return storageFormat;
46 static bool isTextureFormatSupportedForStorage(GLenum format)
48 return (format == GL_RGBA || format == GL_BGRA_EXT);
51 ResourceProvider::Resource::Resource()
52 : glId(0)
53 , glPixelBufferId(0)
54 , glUploadQueryId(0)
55 , pixels(0)
56 , pixelBuffer(0)
57 , pool(0)
58 , lockForReadCount(0)
59 , lockedForWrite(false)
60 , external(false)
61 , exported(false)
62 , markedForDeletion(false)
63 , pendingSetPixels(false)
64 , size()
65 , format(0)
66 , filter(0)
67 , type(static_cast<ResourceType>(0))
71 ResourceProvider::Resource::Resource(unsigned textureId, int pool, const gfx::Size& size, GLenum format, GLenum filter)
72 : glId(textureId)
73 , glPixelBufferId(0)
74 , glUploadQueryId(0)
75 , pixels(0)
76 , pixelBuffer(0)
77 , pool(pool)
78 , lockForReadCount(0)
79 , lockedForWrite(false)
80 , external(false)
81 , exported(false)
82 , markedForDeletion(false)
83 , pendingSetPixels(false)
84 , size(size)
85 , format(format)
86 , filter(filter)
87 , type(GLTexture)
91 ResourceProvider::Resource::Resource(uint8_t* pixels, int pool, const gfx::Size& size, GLenum format, GLenum filter)
92 : glId(0)
93 , glPixelBufferId(0)
94 , glUploadQueryId(0)
95 , pixels(pixels)
96 , pixelBuffer(0)
97 , pool(pool)
98 , lockForReadCount(0)
99 , lockedForWrite(false)
100 , external(false)
101 , exported(false)
102 , markedForDeletion(false)
103 , pendingSetPixels(false)
104 , size(size)
105 , format(format)
106 , filter(filter)
107 , type(Bitmap)
111 ResourceProvider::Child::Child()
115 ResourceProvider::Child::~Child()
119 scoped_ptr<ResourceProvider> ResourceProvider::create(OutputSurface* context)
121 scoped_ptr<ResourceProvider> resourceProvider(new ResourceProvider(context));
122 if (!resourceProvider->initialize())
123 return scoped_ptr<ResourceProvider>();
124 return resourceProvider.Pass();
127 ResourceProvider::~ResourceProvider()
129 WebGraphicsContext3D* context3d = m_outputSurface->Context3D();
130 if (!context3d || !context3d->makeContextCurrent())
131 return;
132 m_textureUploader.reset();
133 m_textureCopier.reset();
136 WebGraphicsContext3D* ResourceProvider::graphicsContext3D()
138 DCHECK(m_threadChecker.CalledOnValidThread());
139 return m_outputSurface->Context3D();
142 bool ResourceProvider::inUseByConsumer(ResourceId id)
144 DCHECK(m_threadChecker.CalledOnValidThread());
145 ResourceMap::iterator it = m_resources.find(id);
146 CHECK(it != m_resources.end());
147 Resource* resource = &it->second;
148 return !!resource->lockForReadCount || resource->exported;
151 ResourceProvider::ResourceId ResourceProvider::createResource(int pool, const gfx::Size& size, GLenum format, TextureUsageHint hint)
153 switch (m_defaultResourceType) {
154 case GLTexture:
155 return createGLTexture(pool, size, format, hint);
156 case Bitmap:
157 DCHECK(format == GL_RGBA);
158 return createBitmap(pool, size);
161 LOG(FATAL) << "Invalid default resource type.";
162 return 0;
165 ResourceProvider::ResourceId ResourceProvider::createGLTexture(int pool, const gfx::Size& size, GLenum format, TextureUsageHint hint)
167 DCHECK_LE(size.width(), m_maxTextureSize);
168 DCHECK_LE(size.height(), m_maxTextureSize);
170 DCHECK(m_threadChecker.CalledOnValidThread());
171 unsigned textureId = 0;
172 WebGraphicsContext3D* context3d = m_outputSurface->Context3D();
173 DCHECK(context3d);
174 GLC(context3d, textureId = context3d->createTexture());
175 GLC(context3d, context3d->bindTexture(GL_TEXTURE_2D, textureId));
176 GLC(context3d, context3d->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
177 GLC(context3d, context3d->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
178 GLC(context3d, context3d->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
179 GLC(context3d, context3d->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
181 if (m_useTextureUsageHint && hint == TextureUsageFramebuffer)
182 GLC(context3d, context3d->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_USAGE_ANGLE, GL_FRAMEBUFFER_ATTACHMENT_ANGLE));
183 if (m_useTextureStorageExt && isTextureFormatSupportedForStorage(format)) {
184 GLenum storageFormat = textureToStorageFormat(format);
185 GLC(context3d, context3d->texStorage2DEXT(GL_TEXTURE_2D, 1, storageFormat, size.width(), size.height()));
186 } else
187 GLC(context3d, context3d->texImage2D(GL_TEXTURE_2D, 0, format, size.width(), size.height(), 0, format, GL_UNSIGNED_BYTE, 0));
189 ResourceId id = m_nextId++;
190 Resource resource(textureId, pool, size, format, GL_LINEAR);
191 m_resources[id] = resource;
192 return id;
195 ResourceProvider::ResourceId ResourceProvider::createBitmap(int pool, const gfx::Size& size)
197 DCHECK(m_threadChecker.CalledOnValidThread());
199 uint8_t* pixels = new uint8_t[size.width() * size.height() * 4];
201 ResourceId id = m_nextId++;
202 Resource resource(pixels, pool, size, GL_RGBA, GL_LINEAR);
203 m_resources[id] = resource;
204 return id;
207 ResourceProvider::ResourceId ResourceProvider::createResourceFromExternalTexture(unsigned textureId)
209 DCHECK(m_threadChecker.CalledOnValidThread());
211 WebGraphicsContext3D* context3d = m_outputSurface->Context3D();
212 DCHECK(context3d);
213 GLC(context3d, context3d->bindTexture(GL_TEXTURE_2D, textureId));
214 GLC(context3d, context3d->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
215 GLC(context3d, context3d->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
216 GLC(context3d, context3d->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
217 GLC(context3d, context3d->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
219 ResourceId id = m_nextId++;
220 Resource resource(textureId, 0, gfx::Size(), 0, GL_LINEAR);
221 resource.external = true;
222 m_resources[id] = resource;
223 return id;
226 void ResourceProvider::deleteResource(ResourceId id)
228 DCHECK(m_threadChecker.CalledOnValidThread());
229 ResourceMap::iterator it = m_resources.find(id);
230 CHECK(it != m_resources.end());
231 Resource* resource = &it->second;
232 DCHECK(!resource->lockedForWrite);
233 DCHECK(!resource->lockForReadCount);
234 DCHECK(!resource->markedForDeletion);
236 if (resource->exported) {
237 resource->markedForDeletion = true;
238 return;
239 } else
240 deleteResourceInternal(it);
243 void ResourceProvider::deleteResourceInternal(ResourceMap::iterator it)
245 Resource* resource = &it->second;
246 if (resource->glId && !resource->external) {
247 WebGraphicsContext3D* context3d = m_outputSurface->Context3D();
248 DCHECK(context3d);
249 GLC(context3d, context3d->deleteTexture(resource->glId));
251 if (resource->glUploadQueryId) {
252 WebGraphicsContext3D* context3d = m_outputSurface->Context3D();
253 DCHECK(context3d);
254 GLC(context3d, context3d->deleteQueryEXT(resource->glUploadQueryId));
256 if (resource->glPixelBufferId) {
257 WebGraphicsContext3D* context3d = m_outputSurface->Context3D();
258 DCHECK(context3d);
259 GLC(context3d, context3d->deleteBuffer(resource->glPixelBufferId));
261 if (resource->pixels)
262 delete[] resource->pixels;
263 if (resource->pixelBuffer)
264 delete[] resource->pixelBuffer;
266 m_resources.erase(it);
269 void ResourceProvider::deleteOwnedResources(int pool)
271 DCHECK(m_threadChecker.CalledOnValidThread());
272 ResourceIdArray toDelete;
273 for (ResourceMap::iterator it = m_resources.begin(); it != m_resources.end(); ++it) {
274 if (it->second.pool == pool && !it->second.external && !it->second.markedForDeletion)
275 toDelete.push_back(it->first);
277 for (ResourceIdArray::iterator it = toDelete.begin(); it != toDelete.end(); ++it)
278 deleteResource(*it);
281 ResourceProvider::ResourceType ResourceProvider::resourceType(ResourceId id)
283 ResourceMap::iterator it = m_resources.find(id);
284 CHECK(it != m_resources.end());
285 Resource* resource = &it->second;
286 return resource->type;
289 void ResourceProvider::setPixels(ResourceId id, const uint8_t* image, const gfx::Rect& imageRect, const gfx::Rect& sourceRect, const gfx::Vector2d& destOffset)
291 DCHECK(m_threadChecker.CalledOnValidThread());
292 ResourceMap::iterator it = m_resources.find(id);
293 CHECK(it != m_resources.end());
294 Resource* resource = &it->second;
295 DCHECK(!resource->lockedForWrite);
296 DCHECK(!resource->lockForReadCount);
297 DCHECK(!resource->external);
298 DCHECK(!resource->exported);
300 if (resource->glId) {
301 WebGraphicsContext3D* context3d = m_outputSurface->Context3D();
302 DCHECK(context3d);
303 DCHECK(m_textureUploader.get());
304 context3d->bindTexture(GL_TEXTURE_2D, resource->glId);
305 m_textureUploader->upload(image,
306 imageRect,
307 sourceRect,
308 destOffset,
309 resource->format,
310 resource->size);
313 if (resource->pixels) {
314 DCHECK(resource->format == GL_RGBA);
315 SkBitmap srcFull;
316 srcFull.setConfig(SkBitmap::kARGB_8888_Config, imageRect.width(), imageRect.height());
317 srcFull.setPixels(const_cast<uint8_t*>(image));
318 SkBitmap srcSubset;
319 SkIRect skSourceRect = SkIRect::MakeXYWH(sourceRect.x(), sourceRect.y(), sourceRect.width(), sourceRect.height());
320 skSourceRect.offset(-imageRect.x(), -imageRect.y());
321 srcFull.extractSubset(&srcSubset, skSourceRect);
323 ScopedWriteLockSoftware lock(this, id);
324 SkCanvas* dest = lock.skCanvas();
325 dest->writePixels(srcSubset, destOffset.x(), destOffset.y());
329 size_t ResourceProvider::numBlockingUploads()
331 if (!m_textureUploader)
332 return 0;
334 return m_textureUploader->numBlockingUploads();
337 void ResourceProvider::markPendingUploadsAsNonBlocking()
339 if (!m_textureUploader)
340 return;
342 m_textureUploader->markPendingUploadsAsNonBlocking();
345 double ResourceProvider::estimatedUploadsPerSecond()
347 if (!m_textureUploader)
348 return 0.0;
350 return m_textureUploader->estimatedTexturesPerSecond();
353 void ResourceProvider::flushUploads()
355 if (!m_textureUploader)
356 return;
358 m_textureUploader->flush();
361 void ResourceProvider::flush()
363 DCHECK(m_threadChecker.CalledOnValidThread());
364 WebGraphicsContext3D* context3d = m_outputSurface->Context3D();
365 if (context3d)
366 context3d->flush();
369 bool ResourceProvider::shallowFlushIfSupported()
371 DCHECK(m_threadChecker.CalledOnValidThread());
372 WebGraphicsContext3D* context3d = m_outputSurface->Context3D();
373 if (!context3d || !m_useShallowFlush)
374 return false;
376 context3d->shallowFlushCHROMIUM();
377 return true;
380 const ResourceProvider::Resource* ResourceProvider::lockForRead(ResourceId id)
382 DCHECK(m_threadChecker.CalledOnValidThread());
383 ResourceMap::iterator it = m_resources.find(id);
384 CHECK(it != m_resources.end());
385 Resource* resource = &it->second;
386 DCHECK(!resource->lockedForWrite);
387 DCHECK(!resource->exported);
388 resource->lockForReadCount++;
389 return resource;
392 void ResourceProvider::unlockForRead(ResourceId id)
394 DCHECK(m_threadChecker.CalledOnValidThread());
395 ResourceMap::iterator it = m_resources.find(id);
396 CHECK(it != m_resources.end());
397 Resource* resource = &it->second;
398 DCHECK(resource->lockForReadCount > 0);
399 DCHECK(!resource->exported);
400 resource->lockForReadCount--;
403 const ResourceProvider::Resource* ResourceProvider::lockForWrite(ResourceId id)
405 DCHECK(m_threadChecker.CalledOnValidThread());
406 ResourceMap::iterator it = m_resources.find(id);
407 CHECK(it != m_resources.end());
408 Resource* resource = &it->second;
409 DCHECK(!resource->lockedForWrite);
410 DCHECK(!resource->lockForReadCount);
411 DCHECK(!resource->exported);
412 DCHECK(!resource->external);
413 resource->lockedForWrite = true;
414 return resource;
417 void ResourceProvider::unlockForWrite(ResourceId id)
419 DCHECK(m_threadChecker.CalledOnValidThread());
420 ResourceMap::iterator it = m_resources.find(id);
421 CHECK(it != m_resources.end());
422 Resource* resource = &it->second;
423 DCHECK(resource->lockedForWrite);
424 DCHECK(!resource->exported);
425 DCHECK(!resource->external);
426 resource->lockedForWrite = false;
429 ResourceProvider::ScopedReadLockGL::ScopedReadLockGL(ResourceProvider* resourceProvider, ResourceProvider::ResourceId resourceId)
430 : m_resourceProvider(resourceProvider)
431 , m_resourceId(resourceId)
432 , m_textureId(resourceProvider->lockForRead(resourceId)->glId)
434 DCHECK(m_textureId);
437 ResourceProvider::ScopedReadLockGL::~ScopedReadLockGL()
439 m_resourceProvider->unlockForRead(m_resourceId);
442 ResourceProvider::ScopedSamplerGL::ScopedSamplerGL(ResourceProvider* resourceProvider, ResourceProvider::ResourceId resourceId, GLenum target, GLenum filter)
443 : ScopedReadLockGL(resourceProvider, resourceId)
445 resourceProvider->bindForSampling(resourceId, target, filter);
448 ResourceProvider::ScopedWriteLockGL::ScopedWriteLockGL(ResourceProvider* resourceProvider, ResourceProvider::ResourceId resourceId)
449 : m_resourceProvider(resourceProvider)
450 , m_resourceId(resourceId)
451 , m_textureId(resourceProvider->lockForWrite(resourceId)->glId)
453 DCHECK(m_textureId);
456 ResourceProvider::ScopedWriteLockGL::~ScopedWriteLockGL()
458 m_resourceProvider->unlockForWrite(m_resourceId);
461 void ResourceProvider::populateSkBitmapWithResource(SkBitmap* skBitmap, const Resource* resource)
463 DCHECK(resource->pixels);
464 DCHECK(resource->format == GL_RGBA);
465 skBitmap->setConfig(SkBitmap::kARGB_8888_Config, resource->size.width(), resource->size.height());
466 skBitmap->setPixels(resource->pixels);
469 ResourceProvider::ScopedReadLockSoftware::ScopedReadLockSoftware(ResourceProvider* resourceProvider, ResourceProvider::ResourceId resourceId)
470 : m_resourceProvider(resourceProvider)
471 , m_resourceId(resourceId)
473 ResourceProvider::populateSkBitmapWithResource(&m_skBitmap, resourceProvider->lockForRead(resourceId));
476 ResourceProvider::ScopedReadLockSoftware::~ScopedReadLockSoftware()
478 m_resourceProvider->unlockForRead(m_resourceId);
481 ResourceProvider::ScopedWriteLockSoftware::ScopedWriteLockSoftware(ResourceProvider* resourceProvider, ResourceProvider::ResourceId resourceId)
482 : m_resourceProvider(resourceProvider)
483 , m_resourceId(resourceId)
485 ResourceProvider::populateSkBitmapWithResource(&m_skBitmap, resourceProvider->lockForWrite(resourceId));
486 m_skCanvas.reset(new SkCanvas(m_skBitmap));
489 ResourceProvider::ScopedWriteLockSoftware::~ScopedWriteLockSoftware()
491 m_resourceProvider->unlockForWrite(m_resourceId);
494 ResourceProvider::ResourceProvider(OutputSurface* context)
495 : m_outputSurface(context)
496 , m_nextId(1)
497 , m_nextChild(1)
498 , m_defaultResourceType(GLTexture)
499 , m_useTextureStorageExt(false)
500 , m_useTextureUsageHint(false)
501 , m_useShallowFlush(false)
502 , m_maxTextureSize(0)
503 , m_bestTextureFormat(0)
507 bool ResourceProvider::initialize()
509 DCHECK(m_threadChecker.CalledOnValidThread());
510 WebGraphicsContext3D* context3d = m_outputSurface->Context3D();
511 if (!context3d) {
512 m_maxTextureSize = INT_MAX / 2;
513 m_bestTextureFormat = GL_RGBA;
514 return true;
516 if (!context3d->makeContextCurrent())
517 return false;
519 std::string extensionsString = UTF16ToASCII(context3d->getString(GL_EXTENSIONS));
520 std::vector<std::string> extensions;
521 base::SplitString(extensionsString, ' ', &extensions);
522 bool useMapSub = false;
523 bool useBindUniform = false;
524 bool useBGRA = false;
525 for (size_t i = 0; i < extensions.size(); ++i) {
526 if (extensions[i] == "GL_EXT_texture_storage")
527 m_useTextureStorageExt = true;
528 else if (extensions[i] == "GL_ANGLE_texture_usage")
529 m_useTextureUsageHint = true;
530 else if (extensions[i] == "GL_CHROMIUM_map_sub")
531 useMapSub = true;
532 else if (extensions[i] == "GL_CHROMIUM_shallow_flush")
533 m_useShallowFlush = true;
534 else if (extensions[i] == "GL_CHROMIUM_bind_uniform_location")
535 useBindUniform = true;
536 else if (extensions[i] == "GL_EXT_texture_format_BGRA8888")
537 useBGRA = true;
540 m_textureCopier = AcceleratedTextureCopier::create(context3d, useBindUniform);
542 m_textureUploader = TextureUploader::create(context3d, useMapSub, m_useShallowFlush);
543 GLC(context3d, context3d->getIntegerv(GL_MAX_TEXTURE_SIZE, &m_maxTextureSize));
544 m_bestTextureFormat = PlatformColor::bestTextureFormat(context3d, useBGRA);
545 return true;
548 int ResourceProvider::createChild(int pool)
550 DCHECK(m_threadChecker.CalledOnValidThread());
551 Child childInfo;
552 childInfo.pool = pool;
553 int child = m_nextChild++;
554 m_children[child] = childInfo;
555 return child;
558 void ResourceProvider::destroyChild(int child)
560 DCHECK(m_threadChecker.CalledOnValidThread());
561 ChildMap::iterator it = m_children.find(child);
562 DCHECK(it != m_children.end());
563 deleteOwnedResources(it->second.pool);
564 m_children.erase(it);
567 const ResourceProvider::ResourceIdMap& ResourceProvider::getChildToParentMap(int child) const
569 DCHECK(m_threadChecker.CalledOnValidThread());
570 ChildMap::const_iterator it = m_children.find(child);
571 DCHECK(it != m_children.end());
572 return it->second.childToParentMap;
575 void ResourceProvider::prepareSendToParent(const ResourceIdArray& resources, TransferableResourceList* list)
577 DCHECK(m_threadChecker.CalledOnValidThread());
578 list->sync_point = 0;
579 list->resources.clear();
580 WebGraphicsContext3D* context3d = m_outputSurface->Context3D();
581 if (!context3d || !context3d->makeContextCurrent()) {
582 // FIXME: Implement this path for software compositing.
583 return;
585 for (ResourceIdArray::const_iterator it = resources.begin(); it != resources.end(); ++it) {
586 TransferableResource resource;
587 if (transferResource(context3d, *it, &resource)) {
588 m_resources.find(*it)->second.exported = true;
589 list->resources.push_back(resource);
592 if (list->resources.size())
593 list->sync_point = context3d->insertSyncPoint();
596 void ResourceProvider::prepareSendToChild(int child, const ResourceIdArray& resources, TransferableResourceList* list)
598 DCHECK(m_threadChecker.CalledOnValidThread());
599 list->sync_point = 0;
600 list->resources.clear();
601 WebGraphicsContext3D* context3d = m_outputSurface->Context3D();
602 if (!context3d || !context3d->makeContextCurrent()) {
603 // FIXME: Implement this path for software compositing.
604 return;
606 Child& childInfo = m_children.find(child)->second;
607 for (ResourceIdArray::const_iterator it = resources.begin(); it != resources.end(); ++it) {
608 TransferableResource resource;
609 if (!transferResource(context3d, *it, &resource))
610 NOTREACHED();
611 DCHECK(childInfo.parentToChildMap.find(*it) != childInfo.parentToChildMap.end());
612 resource.id = childInfo.parentToChildMap[*it];
613 childInfo.parentToChildMap.erase(*it);
614 childInfo.childToParentMap.erase(resource.id);
615 list->resources.push_back(resource);
616 deleteResource(*it);
618 if (list->resources.size())
619 list->sync_point = context3d->insertSyncPoint();
622 void ResourceProvider::receiveFromChild(int child, const TransferableResourceList& resources)
624 DCHECK(m_threadChecker.CalledOnValidThread());
625 WebGraphicsContext3D* context3d = m_outputSurface->Context3D();
626 if (!context3d || !context3d->makeContextCurrent()) {
627 // FIXME: Implement this path for software compositing.
628 return;
630 if (resources.sync_point) {
631 // NOTE: If the parent is a browser and the child a renderer, the parent
632 // is not supposed to have its context wait, because that could induce
633 // deadlocks and/or security issues. The caller is responsible for
634 // waiting asynchronously, and resetting sync_point before calling this.
635 // However if the parent is a renderer (e.g. browser tag), it may be ok
636 // (and is simpler) to wait.
637 GLC(context3d, context3d->waitSyncPoint(resources.sync_point));
639 Child& childInfo = m_children.find(child)->second;
640 for (TransferableResourceArray::const_iterator it = resources.resources.begin(); it != resources.resources.end(); ++it) {
641 unsigned textureId;
642 GLC(context3d, textureId = context3d->createTexture());
643 GLC(context3d, context3d->bindTexture(GL_TEXTURE_2D, textureId));
644 GLC(context3d, context3d->consumeTextureCHROMIUM(GL_TEXTURE_2D, it->mailbox.name));
645 ResourceId id = m_nextId++;
646 Resource resource(textureId, childInfo.pool, it->size, it->format, it->filter);
647 resource.mailbox.setName(it->mailbox.name);
648 m_resources[id] = resource;
649 childInfo.parentToChildMap[id] = it->id;
650 childInfo.childToParentMap[it->id] = id;
654 void ResourceProvider::receiveFromParent(const TransferableResourceList& resources)
656 DCHECK(m_threadChecker.CalledOnValidThread());
657 WebGraphicsContext3D* context3d = m_outputSurface->Context3D();
658 if (!context3d || !context3d->makeContextCurrent()) {
659 // FIXME: Implement this path for software compositing.
660 return;
662 if (resources.sync_point)
663 GLC(context3d, context3d->waitSyncPoint(resources.sync_point));
664 for (TransferableResourceArray::const_iterator it = resources.resources.begin(); it != resources.resources.end(); ++it) {
665 ResourceMap::iterator mapIterator = m_resources.find(it->id);
666 DCHECK(mapIterator != m_resources.end());
667 Resource* resource = &mapIterator->second;
668 DCHECK(resource->exported);
669 resource->exported = false;
670 resource->mailbox.setName(it->mailbox.name);
671 GLC(context3d, context3d->bindTexture(GL_TEXTURE_2D, resource->glId));
672 GLC(context3d, context3d->consumeTextureCHROMIUM(GL_TEXTURE_2D, it->mailbox.name));
673 if (resource->markedForDeletion)
674 deleteResourceInternal(mapIterator);
678 bool ResourceProvider::transferResource(WebGraphicsContext3D* context, ResourceId id, TransferableResource* resource)
680 DCHECK(m_threadChecker.CalledOnValidThread());
681 WebGraphicsContext3D* context3d = m_outputSurface->Context3D();
682 ResourceMap::iterator it = m_resources.find(id);
683 CHECK(it != m_resources.end());
684 Resource* source = &it->second;
685 DCHECK(!source->lockedForWrite);
686 DCHECK(!source->lockForReadCount);
687 DCHECK(!source->external);
688 if (source->exported)
689 return false;
690 resource->id = id;
691 resource->format = source->format;
692 resource->filter = source->filter;
693 resource->size = source->size;
695 if (source->mailbox.isZero()) {
696 GLbyte name[GL_MAILBOX_SIZE_CHROMIUM];
697 GLC(context3d, context3d->genMailboxCHROMIUM(name));
698 source->mailbox.setName(name);
701 resource->mailbox = source->mailbox;
702 GLC(context, context->bindTexture(GL_TEXTURE_2D, source->glId));
703 GLC(context, context->produceTextureCHROMIUM(GL_TEXTURE_2D, resource->mailbox.name));
704 return true;
707 void ResourceProvider::acquirePixelBuffer(ResourceId id)
709 DCHECK(m_threadChecker.CalledOnValidThread());
710 ResourceMap::iterator it = m_resources.find(id);
711 CHECK(it != m_resources.end());
712 Resource* resource = &it->second;
713 DCHECK(!resource->external);
714 DCHECK(!resource->exported);
716 if (resource->glId) {
717 WebGraphicsContext3D* context3d = m_outputSurface->Context3D();
718 DCHECK(context3d);
719 if (!resource->glPixelBufferId)
720 resource->glPixelBufferId = context3d->createBuffer();
721 context3d->bindBuffer(
722 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
723 resource->glPixelBufferId);
724 context3d->bufferData(
725 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
726 resource->size.width() * resource->size.height() * 4,
727 NULL,
728 GL_DYNAMIC_DRAW);
729 context3d->bindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0);
732 if (resource->pixels) {
733 if (resource->pixelBuffer)
734 return;
736 resource->pixelBuffer = new uint8_t[
737 resource->size.width() * resource->size.height() * 4];
741 void ResourceProvider::releasePixelBuffer(ResourceId id)
743 DCHECK(m_threadChecker.CalledOnValidThread());
744 ResourceMap::iterator it = m_resources.find(id);
745 CHECK(it != m_resources.end());
746 Resource* resource = &it->second;
747 DCHECK(!resource->external);
748 DCHECK(!resource->exported);
750 if (resource->glId) {
751 DCHECK(resource->glPixelBufferId);
752 WebGraphicsContext3D* context3d = m_outputSurface->Context3D();
753 DCHECK(context3d);
754 context3d->bindBuffer(
755 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
756 resource->glPixelBufferId);
757 context3d->bufferData(
758 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
760 NULL,
761 GL_DYNAMIC_DRAW);
762 context3d->bindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0);
765 if (resource->pixels) {
766 if (!resource->pixelBuffer)
767 return;
768 delete[] resource->pixelBuffer;
769 resource->pixelBuffer = 0;
773 uint8_t* ResourceProvider::mapPixelBuffer(ResourceId id)
775 DCHECK(m_threadChecker.CalledOnValidThread());
776 ResourceMap::iterator it = m_resources.find(id);
777 CHECK(it != m_resources.end());
778 Resource* resource = &it->second;
779 DCHECK(!resource->external);
780 DCHECK(!resource->exported);
782 if (resource->glId) {
783 WebGraphicsContext3D* context3d = m_outputSurface->Context3D();
784 DCHECK(context3d);
785 DCHECK(resource->glPixelBufferId);
786 context3d->bindBuffer(
787 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
788 resource->glPixelBufferId);
789 uint8_t* image = static_cast<uint8_t*>(
790 context3d->mapBufferCHROMIUM(
791 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, GL_WRITE_ONLY));
792 context3d->bindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0);
793 DCHECK(image);
794 return image;
797 if (resource->pixels)
798 return resource->pixelBuffer;
800 return NULL;
803 void ResourceProvider::unmapPixelBuffer(ResourceId id)
805 DCHECK(m_threadChecker.CalledOnValidThread());
806 ResourceMap::iterator it = m_resources.find(id);
807 CHECK(it != m_resources.end());
808 Resource* resource = &it->second;
809 DCHECK(!resource->external);
810 DCHECK(!resource->exported);
812 if (resource->glId) {
813 WebGraphicsContext3D* context3d = m_outputSurface->Context3D();
814 DCHECK(context3d);
815 DCHECK(resource->glPixelBufferId);
816 context3d->bindBuffer(
817 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
818 resource->glPixelBufferId);
819 context3d->unmapBufferCHROMIUM(
820 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM);
821 context3d->bindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0);
825 void ResourceProvider::setPixelsFromBuffer(ResourceId id)
827 DCHECK(m_threadChecker.CalledOnValidThread());
828 ResourceMap::iterator it = m_resources.find(id);
829 CHECK(it != m_resources.end());
830 Resource* resource = &it->second;
831 DCHECK(!resource->lockedForWrite);
832 DCHECK(!resource->lockForReadCount);
833 DCHECK(!resource->external);
834 DCHECK(!resource->exported);
836 if (resource->glId) {
837 WebGraphicsContext3D* context3d = m_outputSurface->Context3D();
838 DCHECK(context3d);
839 DCHECK(resource->glPixelBufferId);
840 context3d->bindTexture(GL_TEXTURE_2D, resource->glId);
841 context3d->bindBuffer(
842 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
843 resource->glPixelBufferId);
844 context3d->texSubImage2D(GL_TEXTURE_2D,
845 0, /* level */
846 0, /* x */
847 0, /* y */
848 resource->size.width(),
849 resource->size.height(),
850 resource->format,
851 GL_UNSIGNED_BYTE,
852 NULL);
853 context3d->bindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0);
856 if (resource->pixels) {
857 DCHECK(resource->pixelBuffer);
858 DCHECK(resource->format == GL_RGBA);
859 SkBitmap src;
860 src.setConfig(SkBitmap::kARGB_8888_Config,
861 resource->size.width(),
862 resource->size.height());
863 src.setPixels(resource->pixelBuffer);
865 ScopedWriteLockSoftware lock(this, id);
866 SkCanvas* dest = lock.skCanvas();
867 dest->writePixels(src, 0, 0);
871 void ResourceProvider::bindForSampling(ResourceProvider::ResourceId resourceId, GLenum target, GLenum filter)
873 DCHECK(m_threadChecker.CalledOnValidThread());
874 WebGraphicsContext3D* context3d = m_outputSurface->Context3D();
875 ResourceMap::iterator it = m_resources.find(resourceId);
876 DCHECK(it != m_resources.end());
877 Resource* resource = &it->second;
878 DCHECK(resource->lockForReadCount);
879 DCHECK(!resource->lockedForWrite);
881 GLC(context3d, context3d->bindTexture(target, resource->glId));
882 if (filter != resource->filter) {
883 GLC(context3d, context3d->texParameteri(target, GL_TEXTURE_MIN_FILTER, filter));
884 GLC(context3d, context3d->texParameteri(target, GL_TEXTURE_MAG_FILTER, filter));
885 resource->filter = filter;
889 void ResourceProvider::beginSetPixels(ResourceId id)
891 DCHECK(m_threadChecker.CalledOnValidThread());
892 ResourceMap::iterator it = m_resources.find(id);
893 CHECK(it != m_resources.end());
894 Resource* resource = &it->second;
895 DCHECK(!resource->pendingSetPixels);
897 lockForWrite(id);
899 if (resource->glId) {
900 WebGraphicsContext3D* context3d = m_outputSurface->Context3D();
901 DCHECK(context3d);
902 DCHECK(resource->glPixelBufferId);
903 context3d->bindTexture(GL_TEXTURE_2D, resource->glId);
904 context3d->bindBuffer(
905 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
906 resource->glPixelBufferId);
907 if (!resource->glUploadQueryId)
908 resource->glUploadQueryId = context3d->createQueryEXT();
909 context3d->beginQueryEXT(
910 GL_ASYNC_PIXEL_TRANSFERS_COMPLETED_CHROMIUM,
911 resource->glUploadQueryId);
912 context3d->asyncTexSubImage2DCHROMIUM(GL_TEXTURE_2D,
913 0, /* level */
914 0, /* x */
915 0, /* y */
916 resource->size.width(),
917 resource->size.height(),
918 resource->format,
919 GL_UNSIGNED_BYTE,
920 NULL);
921 context3d->endQueryEXT(GL_ASYNC_PIXEL_TRANSFERS_COMPLETED_CHROMIUM);
922 context3d->bindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0);
925 if (resource->pixels)
926 setPixelsFromBuffer(id);
928 resource->pendingSetPixels = true;
931 bool ResourceProvider::didSetPixelsComplete(ResourceId id) {
932 DCHECK(m_threadChecker.CalledOnValidThread());
933 ResourceMap::iterator it = m_resources.find(id);
934 CHECK(it != m_resources.end());
935 Resource* resource = &it->second;
936 DCHECK(resource->lockedForWrite);
937 DCHECK(resource->pendingSetPixels);
939 if (resource->glId) {
940 WebGraphicsContext3D* context3d = m_outputSurface->Context3D();
941 DCHECK(context3d);
942 DCHECK(resource->glUploadQueryId);
943 unsigned complete = 1;
944 context3d->getQueryObjectuivEXT(
945 resource->glUploadQueryId,
946 GL_QUERY_RESULT_AVAILABLE_EXT,
947 &complete);
948 if (!complete)
949 return false;
952 resource->pendingSetPixels = false;
953 unlockForWrite(id);
955 return true;
958 } // namespace cc