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"
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
;
29 static GLenum
textureToStorageFormat(GLenum textureFormat
)
31 GLenum storageFormat
= GL_RGBA8_OES
;
32 switch (textureFormat
) {
36 storageFormat
= GL_BGRA8_EXT
;
46 static bool isTextureFormatSupportedForStorage(GLenum format
)
48 return (format
== GL_RGBA
|| format
== GL_BGRA_EXT
);
51 ResourceProvider::Resource::Resource()
59 , lockedForWrite(false)
62 , markedForDeletion(false)
63 , pendingSetPixels(false)
67 , type(static_cast<ResourceType
>(0))
71 ResourceProvider::Resource::Resource(unsigned textureId
, int pool
, const gfx::Size
& size
, GLenum format
, GLenum filter
)
79 , lockedForWrite(false)
82 , markedForDeletion(false)
83 , pendingSetPixels(false)
91 ResourceProvider::Resource::Resource(uint8_t* pixels
, int pool
, const gfx::Size
& size
, GLenum format
, GLenum filter
)
99 , lockedForWrite(false)
102 , markedForDeletion(false)
103 , pendingSetPixels(false)
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())
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
) {
155 return createGLTexture(pool
, size
, format
, hint
);
157 DCHECK(format
== GL_RGBA
);
158 return createBitmap(pool
, size
);
161 LOG(FATAL
) << "Invalid default resource type.";
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();
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()));
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
;
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
;
207 ResourceProvider::ResourceId
ResourceProvider::createResourceFromExternalTexture(unsigned textureId
)
209 DCHECK(m_threadChecker
.CalledOnValidThread());
211 WebGraphicsContext3D
* context3d
= m_outputSurface
->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
;
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;
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();
249 GLC(context3d
, context3d
->deleteTexture(resource
->glId
));
251 if (resource
->glUploadQueryId
) {
252 WebGraphicsContext3D
* context3d
= m_outputSurface
->Context3D();
254 GLC(context3d
, context3d
->deleteQueryEXT(resource
->glUploadQueryId
));
256 if (resource
->glPixelBufferId
) {
257 WebGraphicsContext3D
* context3d
= m_outputSurface
->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
)
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();
303 DCHECK(m_textureUploader
.get());
304 context3d
->bindTexture(GL_TEXTURE_2D
, resource
->glId
);
305 m_textureUploader
->upload(image
,
313 if (resource
->pixels
) {
314 DCHECK(resource
->format
== GL_RGBA
);
316 srcFull
.setConfig(SkBitmap::kARGB_8888_Config
, imageRect
.width(), imageRect
.height());
317 srcFull
.setPixels(const_cast<uint8_t*>(image
));
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
)
334 return m_textureUploader
->numBlockingUploads();
337 void ResourceProvider::markPendingUploadsAsNonBlocking()
339 if (!m_textureUploader
)
342 m_textureUploader
->markPendingUploadsAsNonBlocking();
345 double ResourceProvider::estimatedUploadsPerSecond()
347 if (!m_textureUploader
)
350 return m_textureUploader
->estimatedTexturesPerSecond();
353 void ResourceProvider::flushUploads()
355 if (!m_textureUploader
)
358 m_textureUploader
->flush();
361 void ResourceProvider::flush()
363 DCHECK(m_threadChecker
.CalledOnValidThread());
364 WebGraphicsContext3D
* context3d
= m_outputSurface
->Context3D();
369 bool ResourceProvider::shallowFlushIfSupported()
371 DCHECK(m_threadChecker
.CalledOnValidThread());
372 WebGraphicsContext3D
* context3d
= m_outputSurface
->Context3D();
373 if (!context3d
|| !m_useShallowFlush
)
376 context3d
->shallowFlushCHROMIUM();
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
++;
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;
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
)
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
)
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
)
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();
512 m_maxTextureSize
= INT_MAX
/ 2;
513 m_bestTextureFormat
= GL_RGBA
;
516 if (!context3d
->makeContextCurrent())
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")
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")
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
);
548 int ResourceProvider::createChild(int pool
)
550 DCHECK(m_threadChecker
.CalledOnValidThread());
552 childInfo
.pool
= pool
;
553 int child
= m_nextChild
++;
554 m_children
[child
] = childInfo
;
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.
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.
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
))
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
);
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.
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
) {
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.
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
)
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
));
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();
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,
729 context3d
->bindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
, 0);
732 if (resource
->pixels
) {
733 if (resource
->pixelBuffer
)
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();
754 context3d
->bindBuffer(
755 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
,
756 resource
->glPixelBufferId
);
757 context3d
->bufferData(
758 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
,
762 context3d
->bindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
, 0);
765 if (resource
->pixels
) {
766 if (!resource
->pixelBuffer
)
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();
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);
797 if (resource
->pixels
)
798 return resource
->pixelBuffer
;
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();
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();
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
,
848 resource
->size
.width(),
849 resource
->size
.height(),
853 context3d
->bindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
, 0);
856 if (resource
->pixels
) {
857 DCHECK(resource
->pixelBuffer
);
858 DCHECK(resource
->format
== GL_RGBA
);
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
);
899 if (resource
->glId
) {
900 WebGraphicsContext3D
* context3d
= m_outputSurface
->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
,
916 resource
->size
.width(),
917 resource
->size
.height(),
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();
942 DCHECK(resource
->glUploadQueryId
);
943 unsigned complete
= 1;
944 context3d
->getQueryObjectuivEXT(
945 resource
->glUploadQueryId
,
946 GL_QUERY_RESULT_AVAILABLE_EXT
,
952 resource
->pendingSetPixels
= false;