Index: cc/resource_provider.cc |
diff --git a/cc/resource_provider.cc b/cc/resource_provider.cc |
index 4269b8123185b5400c66356bc9c4b9ce30697cb6..3f083ce21e3b9b64df321744da9448957574e311 100644 |
--- a/cc/resource_provider.cc |
+++ b/cc/resource_provider.cc |
@@ -47,9 +47,34 @@ static bool isTextureFormatSupportedForStorage(GLenum format) |
return (format == GL_RGBA || format == GL_BGRA_EXT); |
} |
+static void texImage2D(WebGraphicsContext3D* context3d, |
+ const gfx::Size& size, |
+ GLenum format, |
+ bool useTextureStorageExt) |
+{ |
+ if (useTextureStorageExt && isTextureFormatSupportedForStorage(format)) { |
+ GLenum storageFormat = textureToStorageFormat(format); |
+ context3d->texStorage2DEXT( |
+ GL_TEXTURE_2D, 1, storageFormat, size.width(), size.height()); |
+ } else { |
+ context3d->texImage2D(GL_TEXTURE_2D, |
+ 0, |
+ format, |
+ size.width(), |
+ size.height(), |
+ 0, |
+ format, |
+ GL_UNSIGNED_BYTE, |
+ 0); |
+ } |
+} |
+ |
ResourceProvider::Resource::Resource() |
: glId(0) |
+ , glPixelBufferId(0) |
+ , glUploadQueryId(0) |
, pixels(0) |
+ , pixelBuffer(0) |
, pool(0) |
, lockForReadCount(0) |
, lockedForWrite(false) |
@@ -64,7 +89,10 @@ ResourceProvider::Resource::Resource() |
ResourceProvider::Resource::Resource(unsigned textureId, int pool, const gfx::Size& size, GLenum format) |
: glId(textureId) |
+ , glPixelBufferId(0) |
+ , glUploadQueryId(0) |
, pixels(0) |
+ , pixelBuffer(0) |
, pool(pool) |
, lockForReadCount(0) |
, lockedForWrite(false) |
@@ -79,7 +107,10 @@ ResourceProvider::Resource::Resource(unsigned textureId, int pool, const gfx::Si |
ResourceProvider::Resource::Resource(uint8_t* pixels, int pool, const gfx::Size& size, GLenum format) |
: glId(0) |
+ , glPixelBufferId(0) |
+ , glUploadQueryId(0) |
, pixels(pixels) |
+ , pixelBuffer(0) |
, pool(pool) |
, lockForReadCount(0) |
, lockedForWrite(false) |
@@ -161,11 +192,8 @@ ResourceProvider::ResourceId ResourceProvider::createGLTexture(int pool, const g |
if (m_useTextureUsageHint && hint == TextureUsageFramebuffer) |
GLC(context3d, context3d->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_USAGE_ANGLE, GL_FRAMEBUFFER_ATTACHMENT_ANGLE)); |
- if (m_useTextureStorageExt && isTextureFormatSupportedForStorage(format)) { |
- GLenum storageFormat = textureToStorageFormat(format); |
- GLC(context3d, context3d->texStorage2DEXT(GL_TEXTURE_2D, 1, storageFormat, size.width(), size.height())); |
- } else |
- GLC(context3d, context3d->texImage2D(GL_TEXTURE_2D, 0, format, size.width(), size.height(), 0, format, GL_UNSIGNED_BYTE, 0)); |
+ |
+ texImage2D(context3d, size, format, m_useTextureStorageExt); |
ResourceId id = m_nextId++; |
Resource resource(textureId, pool, size, format); |
@@ -229,8 +257,20 @@ void ResourceProvider::deleteResourceInternal(ResourceMap::iterator it) |
DCHECK(context3d); |
GLC(context3d, context3d->deleteTexture(resource->glId)); |
} |
+ if (resource->glUploadQueryId) { |
+ WebGraphicsContext3D* context3d = m_context->context3D(); |
+ DCHECK(context3d); |
+ GLC(context3d, context3d->deleteQueryEXT(resource->glUploadQueryId)); |
+ } |
+ if (resource->glPixelBufferId) { |
+ WebGraphicsContext3D* context3d = m_context->context3D(); |
+ DCHECK(context3d); |
+ GLC(context3d, context3d->deleteBuffer(resource->glPixelBufferId)); |
+ } |
if (resource->pixels) |
delete[] resource->pixels; |
+ if (resource->pixelBuffer) |
+ delete[] resource->pixelBuffer; |
m_resources.erase(it); |
} |
@@ -660,4 +700,215 @@ bool ResourceProvider::transferResource(WebGraphicsContext3D* context, ResourceI |
return true; |
} |
+void ResourceProvider::acquirePixelBuffer(ResourceId id) |
+{ |
+ DCHECK(m_threadChecker.CalledOnValidThread()); |
+ ResourceMap::iterator it = m_resources.find(id); |
+ CHECK(it != m_resources.end()); |
+ Resource* resource = &it->second; |
+ DCHECK(!resource->external); |
+ DCHECK(!resource->exported); |
+ |
+ if (resource->glId) { |
+ if (resource->glPixelBufferId) |
+ return; |
+ WebGraphicsContext3D* context3d = m_context->context3D(); |
+ DCHECK(context3d); |
+ resource->glPixelBufferId = context3d->createBuffer(); |
+ context3d->bindBuffer( |
+ GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, |
+ resource->glPixelBufferId); |
+ context3d->bufferData( |
+ GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, |
+ resource->size.width() * resource->size.height() * 4, |
+ NULL, |
+ GL_DYNAMIC_DRAW); |
+ context3d->bindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0); |
+ } |
+ |
+ if (resource->pixels) { |
+ if (resource->pixelBuffer) |
+ return; |
+ |
+ resource->pixelBuffer = new uint8_t[ |
+ resource->size.width() * resource->size.height() * 4]; |
+ } |
+} |
+ |
+void ResourceProvider::releasePixelBuffer(ResourceId id) |
+{ |
+ DCHECK(m_threadChecker.CalledOnValidThread()); |
+ ResourceMap::iterator it = m_resources.find(id); |
+ CHECK(it != m_resources.end()); |
+ Resource* resource = &it->second; |
+ DCHECK(!resource->external); |
+ DCHECK(!resource->exported); |
+ |
+ if (resource->glId) { |
+ if (!resource->glPixelBufferId) |
+ return; |
+ WebGraphicsContext3D* context3d = m_context->context3D(); |
+ DCHECK(context3d); |
+ context3d->deleteBuffer(resource->glPixelBufferId); |
+ resource->glPixelBufferId = 0; |
+ } |
+ |
+ if (resource->pixels) { |
+ if (!resource->pixelBuffer) |
+ return; |
+ delete[] resource->pixelBuffer; |
+ resource->pixelBuffer = 0; |
+ } |
+} |
+ |
+uint8_t* ResourceProvider::mapPixelBuffer(ResourceId id) |
+{ |
+ DCHECK(m_threadChecker.CalledOnValidThread()); |
+ ResourceMap::iterator it = m_resources.find(id); |
+ CHECK(it != m_resources.end()); |
+ Resource* resource = &it->second; |
+ DCHECK(!resource->external); |
+ DCHECK(!resource->exported); |
+ |
+ if (resource->glId) { |
+ WebGraphicsContext3D* context3d = m_context->context3D(); |
+ DCHECK(context3d); |
+ DCHECK(resource->glPixelBufferId); |
+ context3d->bindBuffer( |
+ GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, |
+ resource->glPixelBufferId); |
+ uint8_t* image = static_cast<uint8_t*>( |
+ context3d->mapBufferCHROMIUM( |
+ GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, GL_WRITE_ONLY)); |
+ context3d->bindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0); |
+ DCHECK(image); |
+ return image; |
+ } |
+ |
+ if (resource->pixels) |
+ return resource->pixelBuffer; |
+ |
+ return NULL; |
+} |
+ |
+void ResourceProvider::unmapPixelBuffer(ResourceId id) |
+{ |
+ DCHECK(m_threadChecker.CalledOnValidThread()); |
+ ResourceMap::iterator it = m_resources.find(id); |
+ CHECK(it != m_resources.end()); |
+ Resource* resource = &it->second; |
+ DCHECK(!resource->external); |
+ DCHECK(!resource->exported); |
+ |
+ if (resource->glId) { |
+ WebGraphicsContext3D* context3d = m_context->context3D(); |
+ DCHECK(context3d); |
+ DCHECK(resource->glPixelBufferId); |
+ context3d->bindBuffer( |
+ GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, |
+ resource->glPixelBufferId); |
+ context3d->unmapBufferCHROMIUM( |
+ GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM); |
+ context3d->bindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0); |
+ } |
+} |
+ |
+void ResourceProvider::beginSetPixels(ResourceId id) |
+{ |
+ DCHECK(m_threadChecker.CalledOnValidThread()); |
+ ResourceMap::iterator it = m_resources.find(id); |
+ CHECK(it != m_resources.end()); |
+ Resource* resource = &it->second; |
+ DCHECK(!resource->lockedForWrite); |
+ DCHECK(!resource->lockForReadCount); |
+ DCHECK(!resource->external); |
+ DCHECK(!resource->exported); |
+ |
+ if (resource->glId) { |
+ WebGraphicsContext3D* context3d = m_context->context3D(); |
+ DCHECK(context3d); |
+ DCHECK(m_textureUploader.get()); |
+ lockForWrite(id); |
+ DCHECK(resource->glPixelBufferId); |
+ context3d->bindTexture(GL_TEXTURE_2D, resource->glId); |
+ context3d->bindBuffer( |
+ GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, |
+ resource->glPixelBufferId); |
+ if (!resource->glUploadQueryId) |
+ resource->glUploadQueryId = context3d->createQueryEXT(); |
+ context3d->beginQueryEXT( |
+ GL_ASYNC_TEXTURES_UPLOADED_CHROMIUM, resource->glUploadQueryId); |
+ context3d->asyncTexSubImage2DCHROMIUM(GL_TEXTURE_2D, |
+ 0, /* level */ |
+ 0, /* x */ |
+ 0, /* y */ |
+ resource->size.width(), |
+ resource->size.height(), |
+ resource->format, |
+ GL_UNSIGNED_BYTE, |
+ NULL); |
+ context3d->endQueryEXT(GL_ASYNC_TEXTURES_UPLOADED_CHROMIUM); |
+ } |
+ |
+ if (resource->pixels) { |
+ DCHECK(resource->pixelBuffer); |
+ DCHECK(resource->format == GL_RGBA); |
+ SkBitmap src; |
+ src.setConfig(SkBitmap::kARGB_8888_Config, |
+ resource->size.width(), |
+ resource->size.height()); |
+ src.setPixels(resource->pixelBuffer); |
+ |
+ ScopedWriteLockSoftware lock(this, id); |
+ SkCanvas* dest = lock.skCanvas(); |
+ dest->writePixels(src, 0, 0); |
+ } |
+} |
+ |
+bool ResourceProvider::didSetPixelsComplete(ResourceId id) { |
+ DCHECK(m_threadChecker.CalledOnValidThread()); |
+ ResourceMap::iterator it = m_resources.find(id); |
+ CHECK(it != m_resources.end()); |
+ Resource* resource = &it->second; |
+ |
+ if (resource->glId) { |
+ WebGraphicsContext3D* context3d = m_context->context3D(); |
+ DCHECK(context3d); |
+ DCHECK(resource->glUploadQueryId); |
+ DCHECK(resource->lockedForWrite); |
+ unsigned complete = 1; |
+ context3d->getQueryObjectuivEXT( |
+ resource->glUploadQueryId, |
+ GL_QUERY_RESULT_AVAILABLE_EXT, |
+ &complete); |
+ if (!complete) |
+ return false; |
+ |
+ unlockForWrite(id); |
+ } |
+ |
+ return true; |
+} |
+ |
+void ResourceProvider::abortSetPixels(ResourceId id) { |
+ DCHECK(m_threadChecker.CalledOnValidThread()); |
+ ResourceMap::iterator it = m_resources.find(id); |
+ CHECK(it != m_resources.end()); |
+ Resource* resource = &it->second; |
+ |
+ if (resource->glId) { |
+ WebGraphicsContext3D* context3d = m_context->context3D(); |
+ DCHECK(context3d); |
+ DCHECK(resource->glUploadQueryId); |
+ DCHECK(resource->lockedForWrite); |
+ context3d->bindTexture(GL_TEXTURE_2D, resource->glId); |
+ texImage2D(context3d, |
+ resource->size, |
nduca
2012/11/23 22:16:42
if we land this, should we file a followup bug tha
reveman
2012/11/23 22:52:28
I don't have any intentions to land this until we
|
+ resource->format, |
+ m_useTextureStorageExt); |
+ |
+ unlockForWrite(id); |
+ } |
+} |
+ |
} // namespace cc |