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/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
;
28 static GLenum
textureToStorageFormat(GLenum textureFormat
)
30 GLenum storageFormat
= GL_RGBA8_OES
;
31 switch (textureFormat
) {
35 storageFormat
= GL_BGRA8_EXT
;
45 static bool isTextureFormatSupportedForStorage(GLenum format
)
47 return (format
== GL_RGBA
|| format
== GL_BGRA_EXT
);
50 ResourceProvider::Resource::Resource()
57 , lockedForWrite(false)
60 , markedForDeletion(false)
63 , type(static_cast<ResourceType
>(0))
67 ResourceProvider::Resource::Resource(unsigned textureId
, int pool
, const gfx::Size
& size
, GLenum format
)
74 , lockedForWrite(false)
77 , markedForDeletion(false)
84 ResourceProvider::Resource::Resource(uint8_t* pixels
, int pool
, const gfx::Size
& size
, GLenum format
)
91 , lockedForWrite(false)
94 , markedForDeletion(false)
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())
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
) {
145 return createGLTexture(pool
, size
, format
, hint
);
147 DCHECK(format
== GL_RGBA
);
148 return createBitmap(pool
, size
);
151 LOG(FATAL
) << "Invalid default resource type.";
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();
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()));
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
;
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
;
197 ResourceProvider::ResourceId
ResourceProvider::createResourceFromExternalTexture(unsigned textureId
)
199 DCHECK(m_threadChecker
.CalledOnValidThread());
201 WebGraphicsContext3D
* context3d
= m_context
->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
;
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;
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();
239 GLC(context3d
, context3d
->deleteTexture(resource
->glId
));
241 if (resource
->glPixelBufferId
) {
242 WebGraphicsContext3D
* context3d
= m_context
->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
)
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();
288 DCHECK(m_textureUploader
.get());
289 context3d
->bindTexture(GL_TEXTURE_2D
, resource
->glId
);
290 m_textureUploader
->upload(image
,
298 if (resource
->pixels
) {
299 DCHECK(resource
->format
== GL_RGBA
);
301 srcFull
.setConfig(SkBitmap::kARGB_8888_Config
, imageRect
.width(), imageRect
.height());
302 srcFull
.setPixels(const_cast<uint8_t*>(image
));
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
)
319 return m_textureUploader
->numBlockingUploads();
322 void ResourceProvider::markPendingUploadsAsNonBlocking()
324 if (!m_textureUploader
)
327 m_textureUploader
->markPendingUploadsAsNonBlocking();
330 double ResourceProvider::estimatedUploadsPerSecond()
332 if (!m_textureUploader
)
335 return m_textureUploader
->estimatedTexturesPerSecond();
338 void ResourceProvider::flushUploads()
340 if (!m_textureUploader
)
343 m_textureUploader
->flush();
346 void ResourceProvider::flush()
348 DCHECK(m_threadChecker
.CalledOnValidThread());
349 WebGraphicsContext3D
* context3d
= m_context
->context3D();
354 bool ResourceProvider::shallowFlushIfSupported()
356 DCHECK(m_threadChecker
.CalledOnValidThread());
357 WebGraphicsContext3D
* context3d
= m_context
->context3D();
358 if (!context3d
|| !m_useShallowFlush
)
361 context3d
->shallowFlushCHROMIUM();
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
++;
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;
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
)
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
)
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
)
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();
490 m_maxTextureSize
= INT_MAX
/ 2;
493 if (!context3d
->makeContextCurrent())
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")
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
));
521 int ResourceProvider::createChild(int pool
)
523 DCHECK(m_threadChecker
.CalledOnValidThread());
525 childInfo
.pool
= pool
;
526 int child
= m_nextChild
++;
527 m_children
[child
] = childInfo
;
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.
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.
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
))
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
);
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.
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
) {
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.
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
)
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
));
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
)
691 WebGraphicsContext3D
* context3d
= m_context
->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,
702 context3d
->bindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
, 0);
705 if (resource
->pixels
) {
706 if (resource
->pixelBuffer
)
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
)
726 WebGraphicsContext3D
* context3d
= m_context
->context3D();
728 context3d
->deleteBuffer(resource
->glPixelBufferId
);
729 resource
->glPixelBufferId
= 0;
732 if (resource
->pixels
) {
733 if (!resource
->pixelBuffer
)
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();
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);
764 if (resource
->pixels
)
765 return resource
->pixelBuffer
;
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();
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();
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
,
815 resource
->size
.width(),
816 resource
->size
.height(),
820 context3d
->bindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
, 0);
823 if (resource
->pixels
) {
824 DCHECK(resource
->pixelBuffer
);
825 DCHECK(resource
->format
== GL_RGBA
);
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);