[chromium] Add software bitmap resources to CCResourceProvider
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 22 Aug 2012 21:26:45 +0000 (21:26 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 22 Aug 2012 21:26:45 +0000 (21:26 +0000)
https://bugs.webkit.org/show_bug.cgi?id=93677

Patch by Alexandre Elias <aelias@google.com> on 2012-08-22
Reviewed by Adrienne Walker.

Second commit after revert.

This adds the ability to CCResourceProvider to use software bitmaps.
They are allocated as plain-old-memory, and exposed as Skia objects.

We want the ResourceProvider to be able to handle different resource
types at the same time.  In practice, a default resource type is
desired for most uses within a single compositor instance, which is
specified by the default resource type.  Default resource types are
expected to be mostly 1-to-1 with CCRenderer types.

New tests added by parametrizing existing CCResourceProvider tests.

Source/WebCore:

* platform/graphics/chromium/FrameBufferSkPictureCanvasLayerTextureUpdater.cpp:
(WebCore::FrameBufferSkPictureCanvasLayerTextureUpdater::updateTextureRect):
* platform/graphics/chromium/LayerRendererChromium.cpp:
(WebCore::applyFilters):
(WebCore::LayerRendererChromium::drawRenderPassQuad):
(WebCore::LayerRendererChromium::drawTileQuad):
(WebCore::LayerRendererChromium::drawYUVVideoQuad):
(WebCore::LayerRendererChromium::drawTextureQuad):
(WebCore::LayerRendererChromium::getFramebufferTexture):
(WebCore::LayerRendererChromium::bindFramebufferToTexture):
* platform/graphics/chromium/LayerRendererChromium.h:
(DrawingFrame):
* platform/graphics/chromium/cc/CCResourceProvider.cpp:
(WebCore::CCResourceProvider::createResource):
(WebCore):
(WebCore::CCResourceProvider::createGLTexture):
(WebCore::CCResourceProvider::createBitmap):
(WebCore::CCResourceProvider::createResourceFromExternalTexture):
(WebCore::CCResourceProvider::deleteResource):
(WebCore::CCResourceProvider::upload):
(WebCore::CCResourceProvider::flush):
(WebCore::CCResourceProvider::shallowFlushIfSupported):
(WebCore::CCResourceProvider::lockForRead):
(WebCore::CCResourceProvider::unlockForRead):
(WebCore::CCResourceProvider::lockForWrite):
(WebCore::CCResourceProvider::unlockForWrite):
(WebCore::CCResourceProvider::ScopedReadLockGL::ScopedReadLockGL):
(WebCore::CCResourceProvider::ScopedReadLockGL::~ScopedReadLockGL):
(WebCore::CCResourceProvider::ScopedWriteLockGL::ScopedWriteLockGL):
(WebCore::CCResourceProvider::ScopedWriteLockGL::~ScopedWriteLockGL):
(WebCore::CCResourceProvider::populateSkBitmapWithResource):
(WebCore::CCResourceProvider::ScopedReadLockSoftware::ScopedReadLockSoftware):
(WebCore::CCResourceProvider::ScopedReadLockSoftware::~ScopedReadLockSoftware):
(WebCore::CCResourceProvider::ScopedWriteLockSoftware::ScopedWriteLockSoftware):
(WebCore::CCResourceProvider::ScopedWriteLockSoftware::~ScopedWriteLockSoftware):
(WebCore::CCResourceProvider::CCResourceProvider):
* platform/graphics/chromium/cc/CCResourceProvider.h:
(WebCore):
(WebCore::CCResourceProvider::setCreationPolicy):
(WebCore::CCResourceProvider::creationPolicy):
(CCResourceProvider):
(ScopedReadLockGL):
(WebCore::CCResourceProvider::ScopedReadLockGL::textureId):
(ScopedWriteLockGL):
(WebCore::CCResourceProvider::ScopedWriteLockGL::textureId):
(ScopedReadLockSoftware):
(WebCore::CCResourceProvider::ScopedReadLockSoftware::skBitmap):
(ScopedWriteLockSoftware):
(WebCore::CCResourceProvider::ScopedWriteLockSoftware::skCanvas):
(Resource):

Source/WebKit/chromium:

* tests/CCResourceProviderTest.cpp:
(WebKit::CCResourceProviderTest::getResourcePixels):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@126351 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/platform/graphics/chromium/FrameBufferSkPictureCanvasLayerTextureUpdater.cpp
Source/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp
Source/WebCore/platform/graphics/chromium/LayerRendererChromium.h
Source/WebCore/platform/graphics/chromium/cc/CCResourceProvider.cpp
Source/WebCore/platform/graphics/chromium/cc/CCResourceProvider.h
Source/WebKit/chromium/ChangeLog
Source/WebKit/chromium/tests/CCResourceProviderTest.cpp

index cf3c367..c95c042 100644 (file)
@@ -1,3 +1,74 @@
+2012-08-22  Alexandre Elias  <aelias@google.com>
+
+        [chromium] Add software bitmap resources to CCResourceProvider
+        https://bugs.webkit.org/show_bug.cgi?id=93677
+
+        Reviewed by Adrienne Walker.
+
+        Second commit after revert.
+
+        This adds the ability to CCResourceProvider to use software bitmaps.
+        They are allocated as plain-old-memory, and exposed as Skia objects.
+
+        We want the ResourceProvider to be able to handle different resource
+        types at the same time.  In practice, a default resource type is
+        desired for most uses within a single compositor instance, which is
+        specified by the default resource type.  Default resource types are
+        expected to be mostly 1-to-1 with CCRenderer types.
+
+        New tests added by parametrizing existing CCResourceProvider tests.
+
+        * platform/graphics/chromium/FrameBufferSkPictureCanvasLayerTextureUpdater.cpp:
+        (WebCore::FrameBufferSkPictureCanvasLayerTextureUpdater::updateTextureRect):
+        * platform/graphics/chromium/LayerRendererChromium.cpp:
+        (WebCore::applyFilters):
+        (WebCore::LayerRendererChromium::drawRenderPassQuad):
+        (WebCore::LayerRendererChromium::drawTileQuad):
+        (WebCore::LayerRendererChromium::drawYUVVideoQuad):
+        (WebCore::LayerRendererChromium::drawTextureQuad):
+        (WebCore::LayerRendererChromium::getFramebufferTexture):
+        (WebCore::LayerRendererChromium::bindFramebufferToTexture):
+        * platform/graphics/chromium/LayerRendererChromium.h:
+        (DrawingFrame):
+        * platform/graphics/chromium/cc/CCResourceProvider.cpp:
+        (WebCore::CCResourceProvider::createResource):
+        (WebCore):
+        (WebCore::CCResourceProvider::createGLTexture):
+        (WebCore::CCResourceProvider::createBitmap):
+        (WebCore::CCResourceProvider::createResourceFromExternalTexture):
+        (WebCore::CCResourceProvider::deleteResource):
+        (WebCore::CCResourceProvider::upload):
+        (WebCore::CCResourceProvider::flush):
+        (WebCore::CCResourceProvider::shallowFlushIfSupported):
+        (WebCore::CCResourceProvider::lockForRead):
+        (WebCore::CCResourceProvider::unlockForRead):
+        (WebCore::CCResourceProvider::lockForWrite):
+        (WebCore::CCResourceProvider::unlockForWrite):
+        (WebCore::CCResourceProvider::ScopedReadLockGL::ScopedReadLockGL):
+        (WebCore::CCResourceProvider::ScopedReadLockGL::~ScopedReadLockGL):
+        (WebCore::CCResourceProvider::ScopedWriteLockGL::ScopedWriteLockGL):
+        (WebCore::CCResourceProvider::ScopedWriteLockGL::~ScopedWriteLockGL):
+        (WebCore::CCResourceProvider::populateSkBitmapWithResource):
+        (WebCore::CCResourceProvider::ScopedReadLockSoftware::ScopedReadLockSoftware):
+        (WebCore::CCResourceProvider::ScopedReadLockSoftware::~ScopedReadLockSoftware):
+        (WebCore::CCResourceProvider::ScopedWriteLockSoftware::ScopedWriteLockSoftware):
+        (WebCore::CCResourceProvider::ScopedWriteLockSoftware::~ScopedWriteLockSoftware):
+        (WebCore::CCResourceProvider::CCResourceProvider):
+        * platform/graphics/chromium/cc/CCResourceProvider.h:
+        (WebCore):
+        (WebCore::CCResourceProvider::setCreationPolicy):
+        (WebCore::CCResourceProvider::creationPolicy):
+        (CCResourceProvider):
+        (ScopedReadLockGL):
+        (WebCore::CCResourceProvider::ScopedReadLockGL::textureId):
+        (ScopedWriteLockGL):
+        (WebCore::CCResourceProvider::ScopedWriteLockGL::textureId):
+        (ScopedReadLockSoftware):
+        (WebCore::CCResourceProvider::ScopedReadLockSoftware::skBitmap):
+        (ScopedWriteLockSoftware):
+        (WebCore::CCResourceProvider::ScopedWriteLockSoftware::skCanvas):
+        (Resource):
+
 2012-08-22  Anna Cavender  <annacc@chromium.org>
 
         Update the TextTrackCue Constructor
index da2ecc6..101ad4b 100644 (file)
@@ -107,7 +107,7 @@ void FrameBufferSkPictureCanvasLayerTextureUpdater::updateTextureRect(WebGraphic
     context->makeContextCurrent();
 
     texture->acquireBackingTexture(resourceProvider);
-    CCScopedLockResourceForWrite lock(resourceProvider, texture->resourceId());
+    CCResourceProvider::ScopedWriteLockGL lock(resourceProvider, texture->resourceId());
     // Create an accelerated canvas to draw on.
     OwnPtr<SkCanvas> canvas = createAcceleratedCanvas(grContext, texture->size(), lock.textureId());
 
index 36e47d1..84f00a1 100644 (file)
@@ -363,7 +363,7 @@ static inline SkBitmap applyFilters(LayerRendererChromium* layerRenderer, const
 
     layerRenderer->context()->flush();
 
-    CCScopedLockResourceForWrite lock(layerRenderer->resourceProvider(), sourceTexture->id());
+    CCResourceProvider::ScopedWriteLockGL lock(layerRenderer->resourceProvider(), sourceTexture->id());
     SkBitmap source = CCRenderSurfaceFilters::apply(filters, lock.textureId(), sourceTexture->size(), filterContext, filterGrContext);
     return source;
 }
@@ -465,20 +465,20 @@ void LayerRendererChromium::drawRenderPassQuad(DrawingFrame& frame, const CCRend
     // FIXME: Cache this value so that we don't have to do it for both the surface and its replica.
     // Apply filters to the contents texture.
     SkBitmap filterBitmap = applyFilters(this, renderPass->filters(), contentsTexture);
-    OwnPtr<CCScopedLockResourceForRead> contentsResourceLock;
+    OwnPtr<CCResourceProvider::ScopedReadLockGL> contentsResourceLock;
     unsigned contentsTextureId = 0;
     if (filterBitmap.getTexture()) {
         GrTexture* texture = reinterpret_cast<GrTexture*>(filterBitmap.getTexture());
         contentsTextureId = texture->getTextureHandle();
     } else {
-        contentsResourceLock = adoptPtr(new CCScopedLockResourceForRead(m_resourceProvider, contentsTexture->id()));
+        contentsResourceLock = adoptPtr(new CCResourceProvider::ScopedReadLockGL(m_resourceProvider, contentsTexture->id()));
         contentsTextureId = contentsResourceLock->textureId();
     }
 
     // Draw the background texture if there is one.
     if (backgroundTexture) {
         ASSERT(backgroundTexture->size() == quad->quadRect().size());
-        CCScopedLockResourceForRead lock(m_resourceProvider, backgroundTexture->id());
+        CCResourceProvider::ScopedReadLockGL lock(m_resourceProvider, backgroundTexture->id());
         copyTextureToFramebuffer(frame, lock.textureId(), quad->quadRect(), quad->quadTransform());
     }
 
@@ -495,10 +495,10 @@ void LayerRendererChromium::drawRenderPassQuad(DrawingFrame& frame, const CCRend
         deviceLayerEdges.inflateAntiAliasingDistance();
     }
 
-    OwnPtr<CCScopedLockResourceForRead> maskResourceLock;
+    OwnPtr<CCResourceProvider::ScopedReadLockGL> maskResourceLock;
     unsigned maskTextureId = 0;
     if (quad->maskResourceId()) {
-        maskResourceLock = adoptPtr(new CCScopedLockResourceForRead(m_resourceProvider, quad->maskResourceId()));
+        maskResourceLock = adoptPtr(new CCResourceProvider::ScopedReadLockGL(m_resourceProvider, quad->maskResourceId()));
         maskTextureId = maskResourceLock->textureId();
     }
 
@@ -689,7 +689,7 @@ void LayerRendererChromium::drawTileQuad(const DrawingFrame& frame, const CCTile
     GLC(context(), context()->useProgram(uniforms.program));
     GLC(context(), context()->uniform1i(uniforms.samplerLocation, 0));
     GLC(context(), context()->activeTexture(GraphicsContext3D::TEXTURE0));
-    CCScopedLockResourceForRead quadResourceLock(m_resourceProvider, quad->resourceId());
+    CCResourceProvider::ScopedReadLockGL quadResourceLock(m_resourceProvider, quad->resourceId());
     GLC(context(), context()->bindTexture(GraphicsContext3D::TEXTURE_2D, quadResourceLock.textureId()));
     GLC(context(), context()->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, quad->textureFilter()));
     GLC(context(), context()->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, quad->textureFilter()));
@@ -796,9 +796,9 @@ void LayerRendererChromium::drawYUVVideoQuad(const DrawingFrame& frame, const CC
     const CCVideoLayerImpl::FramePlane& uPlane = quad->uPlane();
     const CCVideoLayerImpl::FramePlane& vPlane = quad->vPlane();
 
-    CCScopedLockResourceForRead yPlaneLock(m_resourceProvider, yPlane.resourceId);
-    CCScopedLockResourceForRead uPlaneLock(m_resourceProvider, uPlane.resourceId);
-    CCScopedLockResourceForRead vPlaneLock(m_resourceProvider, vPlane.resourceId);
+    CCResourceProvider::ScopedReadLockGL yPlaneLock(m_resourceProvider, yPlane.resourceId);
+    CCResourceProvider::ScopedReadLockGL uPlaneLock(m_resourceProvider, uPlane.resourceId);
+    CCResourceProvider::ScopedReadLockGL vPlaneLock(m_resourceProvider, vPlane.resourceId);
     GLC(context(), context()->activeTexture(GraphicsContext3D::TEXTURE1));
     GLC(context(), context()->bindTexture(GraphicsContext3D::TEXTURE_2D, yPlaneLock.textureId()));
     GLC(context(), context()->activeTexture(GraphicsContext3D::TEXTURE2));
@@ -907,7 +907,7 @@ void LayerRendererChromium::drawTextureQuad(const DrawingFrame& frame, const CCT
     GLC(context(), context()->uniform4f(binding.texTransformLocation, uvRect.x(), uvRect.y(), uvRect.width(), uvRect.height()));
 
     GLC(context(), context()->activeTexture(GraphicsContext3D::TEXTURE0));
-    CCScopedLockResourceForRead quadResourceLock(m_resourceProvider, quad->resourceId());
+    CCResourceProvider::ScopedReadLockGL quadResourceLock(m_resourceProvider, quad->resourceId());
     GLC(context(), context()->bindTexture(GraphicsContext3D::TEXTURE_2D, quadResourceLock.textureId()));
 
     // FIXME: setting the texture parameters every time is redundant. Move this code somewhere
@@ -1199,7 +1199,7 @@ bool LayerRendererChromium::getFramebufferTexture(CCScopedTexture* texture, cons
     if (!texture->id() && !texture->allocate(CCRenderer::ImplPool, deviceRect.size(), GraphicsContext3D::RGB, CCResourceProvider::TextureUsageAny))
         return false;
 
-    CCScopedLockResourceForWrite lock(m_resourceProvider, texture->id());
+    CCResourceProvider::ScopedWriteLockGL lock(m_resourceProvider, texture->id());
     GLC(m_context, m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, lock.textureId()));
     GLC(m_context, m_context->copyTexImage2D(GraphicsContext3D::TEXTURE_2D, 0, texture->format(),
                                              deviceRect.x(), deviceRect.y(), deviceRect.width(), deviceRect.height(), 0));
@@ -1226,7 +1226,7 @@ bool LayerRendererChromium::bindFramebufferToTexture(DrawingFrame& frame, const
     ASSERT(texture->id());
 
     GLC(m_context, m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_offscreenFramebufferId));
-    m_currentFramebufferLock = adoptPtr(new CCScopedLockResourceForWrite(m_resourceProvider, texture->id()));
+    m_currentFramebufferLock = adoptPtr(new CCResourceProvider::ScopedWriteLockGL(m_resourceProvider, texture->id()));
     unsigned textureId = m_currentFramebufferLock->textureId();
     GLC(m_context, m_context->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE_2D, textureId, 0));
 
index 09cd0e2..3575c19 100644 (file)
@@ -248,7 +248,7 @@ private:
     bool m_visible;
     TextureUploaderOption m_textureUploaderSetting;
 
-    OwnPtr<CCScopedLockResourceForWrite> m_currentFramebufferLock;
+    OwnPtr<CCResourceProvider::ScopedWriteLockGL> m_currentFramebufferLock;
 };
 
 
index 8a5d6af..fb36b4c 100644 (file)
@@ -31,6 +31,7 @@
 #include "IntRect.h"
 #include "LayerRendererChromium.h" // For the GLC() macro
 #include "LayerTextureSubImage.h"
+#include <limits.h>
 #include <public/WebGraphicsContext3D.h>
 #include <wtf/HashSet.h>
 
@@ -88,13 +89,24 @@ bool CCResourceProvider::inUseByConsumer(ResourceId id)
 
 CCResourceProvider::ResourceId CCResourceProvider::createResource(int pool, const IntSize& size, GC3Denum format, TextureUsageHint hint)
 {
+    switch (m_defaultResourceType) {
+    case GLTexture:
+        return createGLTexture(pool, size, format, hint);
+    case Bitmap:
+        ASSERT(format == GraphicsContext3D::RGBA);
+        return createBitmap(pool, size);
+    }
+
+    CRASH();
+    return 0;
+}
+
+CCResourceProvider::ResourceId CCResourceProvider::createGLTexture(int pool, const IntSize& size, GC3Denum format, TextureUsageHint hint)
+{
     ASSERT(CCProxy::isImplThread());
     unsigned textureId = 0;
     WebGraphicsContext3D* context3d = m_context->context3D();
-    if (!context3d) {
-        // FIXME: Implement this path for software compositing.
-        return 0;
-    }
+    ASSERT(context3d);
     GLC(context3d, textureId = context3d->createTexture());
     GLC(context3d, context3d->bindTexture(GraphicsContext3D::TEXTURE_2D, textureId));
     GLC(context3d, context3d->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR));
@@ -115,12 +127,24 @@ CCResourceProvider::ResourceId CCResourceProvider::createResource(int pool, cons
     return id;
 }
 
+CCResourceProvider::ResourceId CCResourceProvider::createBitmap(int pool, const IntSize& size)
+{
+    ASSERT(CCProxy::isImplThread());
+
+    uint8_t* pixels = new uint8_t[size.width() * size.height() * 4];
+
+    ResourceId id = m_nextId++;
+    Resource resource(pixels, pool, size, GraphicsContext3D::RGBA);
+    m_resources.add(id, resource);
+    return id;
+}
+
 CCResourceProvider::ResourceId CCResourceProvider::createResourceFromExternalTexture(unsigned textureId)
 {
     ASSERT(CCProxy::isImplThread());
+    ASSERT(m_context->context3D());
     ResourceId id = m_nextId++;
-    Resource resource;
-    resource.glId = textureId;
+    Resource resource(textureId, 0, IntSize(), 0);
     resource.external = true;
     m_resources.add(id, resource);
     return id;
@@ -129,15 +153,17 @@ CCResourceProvider::ResourceId CCResourceProvider::createResourceFromExternalTex
 void CCResourceProvider::deleteResource(ResourceId id)
 {
     ASSERT(CCProxy::isImplThread());
-    WebGraphicsContext3D* context3d = m_context->context3D();
-    if (!context3d) {
-        // FIXME: Implement this path for software compositing.
-        return;
-    }
     ResourceMap::iterator it = m_resources.find(id);
     ASSERT(it != m_resources.end() && !it->second.lockedForWrite && !it->second.lockForReadCount);
-    if (!it->second.external)
+
+    if (it->second.glId && !it->second.external) {
+        WebGraphicsContext3D* context3d = m_context->context3D();
+        ASSERT(context3d);
         GLC(context3d, context3d->deleteTexture(it->second.glId));
+    }
+    if (it->second.pixels)
+        delete it->second.pixels;
+
     m_resources.remove(it);
 }
 
@@ -153,71 +179,68 @@ void CCResourceProvider::deleteOwnedResources(int pool)
         deleteResource(*it);
 }
 
-void CCResourceProvider::upload(ResourceId id, const uint8_t* image, const IntRect& imageRect, const IntRect& sourceRect, const IntSize& destOffset)
+CCResourceProvider::ResourceType CCResourceProvider::resourceType(ResourceId id)
 {
-    ASSERT(CCProxy::isImplThread());
-    ASSERT(m_texSubImage.get());
-    WebGraphicsContext3D* context3d = m_context->context3D();
-    if (!context3d) {
-        // FIXME: Implement this path for software compositing.
-        return;
-    }
     ResourceMap::iterator it = m_resources.find(id);
-    ASSERT(it != m_resources.end() && !it->second.lockedForWrite && !it->second.lockForReadCount && !it->second.external);
-
-    context3d->bindTexture(GraphicsContext3D::TEXTURE_2D, it->second.glId);
-    m_texSubImage->upload(image, imageRect, sourceRect, destOffset, it->second.format, context3d);
+    ASSERT(it != m_resources.end());
+    return it->second.type;
 }
 
-unsigned CCResourceProvider::lockForWrite(ResourceId id)
+void CCResourceProvider::upload(ResourceId id, const uint8_t* image, const IntRect& imageRect, const IntRect& sourceRect, const IntSize& destOffset)
 {
     ASSERT(CCProxy::isImplThread());
     ResourceMap::iterator it = m_resources.find(id);
     ASSERT(it != m_resources.end() && !it->second.lockedForWrite && !it->second.lockForReadCount && !it->second.external);
-    it->second.lockedForWrite = true;
-    return it->second.glId;
-}
 
-void CCResourceProvider::unlockForWrite(ResourceId id)
-{
-    ASSERT(CCProxy::isImplThread());
-    ResourceMap::iterator it = m_resources.find(id);
-    ASSERT(it != m_resources.end() && it->second.lockedForWrite && !it->second.external);
-    it->second.lockedForWrite = false;
+    if (it->second.glId) {
+        WebGraphicsContext3D* context3d = m_context->context3D();
+        ASSERT(context3d);
+        ASSERT(m_texSubImage.get());
+        context3d->bindTexture(GraphicsContext3D::TEXTURE_2D, it->second.glId);
+        m_texSubImage->upload(image, imageRect, sourceRect, destOffset, it->second.format, context3d);
+    }
+
+    if (it->second.pixels) {
+        SkBitmap srcFull;
+        srcFull.setConfig(SkBitmap::kARGB_8888_Config, imageRect.width(), imageRect.height());
+        srcFull.setPixels(const_cast<uint8_t*>(image));
+        SkBitmap srcSubset;
+        SkIRect skSourceRect = SkIRect::MakeXYWH(sourceRect.x(), sourceRect.y(), sourceRect.width(), sourceRect.height());
+        skSourceRect.offset(-imageRect.x(), -imageRect.y());
+        srcFull.extractSubset(&srcSubset, skSourceRect);
+
+        ScopedWriteLockSoftware lock(this, id);
+        SkCanvas* dest = lock.skCanvas();
+        dest->writePixels(srcSubset, destOffset.width(), destOffset.height());
+    }
 }
 
 void CCResourceProvider::flush()
 {
     ASSERT(CCProxy::isImplThread());
     WebGraphicsContext3D* context3d = m_context->context3D();
-    if (!context3d) {
-        // FIXME: Implement this path for software compositing.
-        return;
-    }
-    context3d->flush();
+    if (context3d)
+        context3d->flush();
 }
 
 bool CCResourceProvider::shallowFlushIfSupported()
 {
     ASSERT(CCProxy::isImplThread());
     WebGraphicsContext3D* context3d = m_context->context3D();
-    if (!context3d) {
-        // FIXME: Implement this path for software compositing.
+    if (!context3d || !m_useShallowFlush)
         return false;
-    }
 
-    if (m_useShallowFlush)
-        context3d->shallowFlushCHROMIUM();
-    return m_useShallowFlush;
+    context3d->shallowFlushCHROMIUM();
+    return true;
 }
 
-unsigned CCResourceProvider::lockForRead(ResourceId id)
+const CCResourceProvider::Resource* CCResourceProvider::lockForRead(ResourceId id)
 {
     ASSERT(CCProxy::isImplThread());
     ResourceMap::iterator it = m_resources.find(id);
     ASSERT(it != m_resources.end() && !it->second.lockedForWrite);
-    ++(it->second.lockForReadCount);
-    return it->second.glId;
+    it->second.lockForReadCount++;
+    return &it->second;
 }
 
 void CCResourceProvider::unlockForRead(ResourceId id)
@@ -225,13 +248,90 @@ void CCResourceProvider::unlockForRead(ResourceId id)
     ASSERT(CCProxy::isImplThread());
     ResourceMap::iterator it = m_resources.find(id);
     ASSERT(it != m_resources.end() && it->second.lockForReadCount > 0);
-    --(it->second.lockForReadCount);
+    it->second.lockForReadCount--;
+}
+
+const CCResourceProvider::Resource* CCResourceProvider::lockForWrite(ResourceId id)
+{
+    ASSERT(CCProxy::isImplThread());
+    ResourceMap::iterator it = m_resources.find(id);
+    ASSERT(it != m_resources.end() && !it->second.lockedForWrite && !it->second.lockForReadCount && !it->second.external);
+    it->second.lockedForWrite = true;
+    return &it->second;
+}
+
+void CCResourceProvider::unlockForWrite(ResourceId id)
+{
+    ASSERT(CCProxy::isImplThread());
+    ResourceMap::iterator it = m_resources.find(id);
+    ASSERT(it != m_resources.end() && it->second.lockedForWrite && !it->second.external);
+    it->second.lockedForWrite = false;
+}
+
+CCResourceProvider::ScopedReadLockGL::ScopedReadLockGL(CCResourceProvider* resourceProvider, CCResourceProvider::ResourceId resourceId)
+    : m_resourceProvider(resourceProvider)
+    , m_resourceId(resourceId)
+    , m_textureId(resourceProvider->lockForRead(resourceId)->glId)
+{
+    ASSERT(m_textureId);
+}
+
+CCResourceProvider::ScopedReadLockGL::~ScopedReadLockGL()
+{
+    m_resourceProvider->unlockForRead(m_resourceId);
+}
+
+CCResourceProvider::ScopedWriteLockGL::ScopedWriteLockGL(CCResourceProvider* resourceProvider, CCResourceProvider::ResourceId resourceId)
+    : m_resourceProvider(resourceProvider)
+    , m_resourceId(resourceId)
+    , m_textureId(resourceProvider->lockForWrite(resourceId)->glId)
+{
+    ASSERT(m_textureId);
+}
+
+CCResourceProvider::ScopedWriteLockGL::~ScopedWriteLockGL()
+{
+    m_resourceProvider->unlockForWrite(m_resourceId);
+}
+
+void CCResourceProvider::populateSkBitmapWithResource(SkBitmap* skBitmap, const Resource* resource)
+{
+    ASSERT(resource->pixels);
+    ASSERT(resource->format == GraphicsContext3D::RGBA);
+    skBitmap->setConfig(SkBitmap::kARGB_8888_Config, resource->size.width(), resource->size.height());
+    skBitmap->setPixels(resource->pixels);
+}
+
+CCResourceProvider::ScopedReadLockSoftware::ScopedReadLockSoftware(CCResourceProvider* resourceProvider, CCResourceProvider::ResourceId resourceId)
+    : m_resourceProvider(resourceProvider)
+    , m_resourceId(resourceId)
+{
+    CCResourceProvider::populateSkBitmapWithResource(&m_skBitmap, resourceProvider->lockForRead(resourceId));
+}
+
+CCResourceProvider::ScopedReadLockSoftware::~ScopedReadLockSoftware()
+{
+    m_resourceProvider->unlockForRead(m_resourceId);
+}
+
+CCResourceProvider::ScopedWriteLockSoftware::ScopedWriteLockSoftware(CCResourceProvider* resourceProvider, CCResourceProvider::ResourceId resourceId)
+    : m_resourceProvider(resourceProvider)
+    , m_resourceId(resourceId)
+{
+    CCResourceProvider::populateSkBitmapWithResource(&m_skBitmap, resourceProvider->lockForWrite(resourceId));
+    m_skCanvas.setBitmapDevice(m_skBitmap);
+}
+
+CCResourceProvider::ScopedWriteLockSoftware::~ScopedWriteLockSoftware()
+{
+    m_resourceProvider->unlockForWrite(m_resourceId);
 }
 
 CCResourceProvider::CCResourceProvider(CCGraphicsContext* context)
     : m_context(context)
     , m_nextId(1)
     , m_nextChild(1)
+    , m_defaultResourceType(GLTexture)
     , m_useTextureStorageExt(false)
     , m_useTextureUsageHint(false)
     , m_useShallowFlush(false)
@@ -243,10 +343,15 @@ bool CCResourceProvider::initialize()
 {
     ASSERT(CCProxy::isImplThread());
     WebGraphicsContext3D* context3d = m_context->context3D();
-    if (!context3d || !context3d->makeContextCurrent()) {
+    if (!context3d) {
+        m_maxTextureSize = INT_MAX;
+
         // FIXME: Implement this path for software compositing.
         return false;
     }
+    if (!context3d->makeContextCurrent())
+        return false;
+
     WebKit::WebString extensionsWebString = context3d->getString(GraphicsContext3D::EXTENSIONS);
     String extensionsString(extensionsWebString.data(), extensionsWebString.length());
     Vector<String> extensions;
index e927d29..ebad4b9 100644 (file)
@@ -30,6 +30,8 @@
 #include "CCGraphicsContext.h"
 #include "GraphicsContext3D.h"
 #include "IntSize.h"
+#include "SkBitmap.h"
+#include "SkCanvas.h"
 #include <wtf/Deque.h>
 #include <wtf/HashMap.h>
 #include <wtf/OwnPtr.h>
@@ -44,8 +46,6 @@ class WebGraphicsContext3D;
 
 namespace WebCore {
 
-class CCScopedLockResourceForRead;
-class CCScopedLockResourceForWrite;
 class IntRect;
 class LayerTextureSubImage;
 
@@ -58,6 +58,10 @@ public:
     typedef Vector<ResourceId> ResourceIdArray;
     typedef HashMap<ResourceId, ResourceId> ResourceIdMap;
     enum TextureUsageHint { TextureUsageAny, TextureUsageFramebuffer };
+    enum ResourceType {
+        GLTexture = 1,
+        Bitmap,
+    };
     struct Mailbox {
         GC3Dbyte name[64];
     };
@@ -87,11 +91,19 @@ public:
 
     // Producer interface.
 
-    // Creates a resource of the given size/format, into the given pool.
+    void setDefaultResourceType(ResourceType type) { m_defaultResourceType = type; }
+    ResourceType defaultResourceType() const { return m_defaultResourceType; }
+    ResourceType resourceType(ResourceId);
+
+    // Creates a resource of the default resource type.
     ResourceId createResource(int pool, const IntSize&, GC3Denum format, TextureUsageHint);
 
-    // Wraps an external texture into a resource.
+    // You can also explicitly create a specific resource type.
+    ResourceId createGLTexture(int pool, const IntSize&, GC3Denum format, TextureUsageHint);
+    ResourceId createBitmap(int pool, const IntSize&);
+    // Wraps an external texture into a GL resource.
     ResourceId createResourceFromExternalTexture(unsigned textureId);
+
     void deleteResource(ResourceId);
 
     // Deletes all resources owned by a given pool.
@@ -147,13 +159,72 @@ public:
     // Only for testing
     size_t mailboxCount() const { return m_mailboxes.size(); }
 
-private:
-    friend class CCScopedLockResourceForRead;
-    friend class CCScopedLockResourceForWrite;
+    // The following lock classes are part of the CCResourceProvider API and are
+    // needed to read and write the resource contents. The user must ensure
+    // that they only use GL locks on GL resources, etc, and this is enforced
+    // by assertions.
+    class ScopedReadLockGL {
+        WTF_MAKE_NONCOPYABLE(ScopedReadLockGL);
+    public:
+        ScopedReadLockGL(CCResourceProvider*, CCResourceProvider::ResourceId);
+        ~ScopedReadLockGL();
+
+        unsigned textureId() const { return m_textureId; }
+
+    private:
+        CCResourceProvider* m_resourceProvider;
+        CCResourceProvider::ResourceId m_resourceId;
+        unsigned m_textureId;
+    };
+
+    class ScopedWriteLockGL {
+        WTF_MAKE_NONCOPYABLE(ScopedWriteLockGL);
+    public:
+        ScopedWriteLockGL(CCResourceProvider*, CCResourceProvider::ResourceId);
+        ~ScopedWriteLockGL();
+
+        unsigned textureId() const { return m_textureId; }
+
+    private:
+        CCResourceProvider* m_resourceProvider;
+        CCResourceProvider::ResourceId m_resourceId;
+        unsigned m_textureId;
+    };
+
+    class ScopedReadLockSoftware {
+        WTF_MAKE_NONCOPYABLE(ScopedReadLockSoftware);
+    public:
+        ScopedReadLockSoftware(CCResourceProvider*, CCResourceProvider::ResourceId);
+        ~ScopedReadLockSoftware();
+
+        const SkBitmap* skBitmap() const { return &m_skBitmap; }
 
+    private:
+        CCResourceProvider* m_resourceProvider;
+        CCResourceProvider::ResourceId m_resourceId;
+        SkBitmap m_skBitmap;
+    };
+
+    class ScopedWriteLockSoftware {
+        WTF_MAKE_NONCOPYABLE(ScopedWriteLockSoftware);
+    public:
+        ScopedWriteLockSoftware(CCResourceProvider*, CCResourceProvider::ResourceId);
+        ~ScopedWriteLockSoftware();
+
+        SkCanvas* skCanvas() { return &m_skCanvas; }
+
+    private:
+        CCResourceProvider* m_resourceProvider;
+        CCResourceProvider::ResourceId m_resourceId;
+        SkBitmap m_skBitmap;
+        SkCanvas m_skCanvas;
+    };
+
+private:
     struct Resource {
         Resource()
             : glId(0)
+            , pixels(0)
             , pool(0)
             , lockForReadCount(0)
             , lockedForWrite(false)
@@ -161,9 +232,23 @@ private:
             , exported(false)
             , size()
             , format(0)
+            , type(static_cast<ResourceType>(0))
         { }
         Resource(unsigned textureId, int pool, const IntSize& size, GC3Denum format)
             : glId(textureId)
+            , pixels(0)
+            , pool(pool)
+            , lockForReadCount(0)
+            , lockedForWrite(false)
+            , external(false)
+            , exported(false)
+            , size(size)
+            , format(format)
+            , type(GLTexture)
+        { }
+        Resource(uint8_t* pixels, int pool, const IntSize& size, GC3Denum format)
+            : glId(0)
+            , pixels(pixels)
             , pool(pool)
             , lockForReadCount(0)
             , lockedForWrite(false)
@@ -171,8 +256,10 @@ private:
             , exported(false)
             , size(size)
             , format(format)
+            , type(Bitmap)
         { }
         unsigned glId;
+        uint8_t* pixels;
         int pool;
         int lockForReadCount;
         bool lockedForWrite;
@@ -180,6 +267,7 @@ private:
         bool exported;
         IntSize size;
         GC3Denum format;
+        ResourceType type;
     };
     typedef HashMap<ResourceId, Resource> ResourceMap;
     struct Child {
@@ -192,13 +280,11 @@ private:
     explicit CCResourceProvider(CCGraphicsContext*);
     bool initialize();
 
-    // Gets a GL texture id representing the resource, that can be rendered into.
-    unsigned lockForWrite(ResourceId);
-    void unlockForWrite(ResourceId);
-
-    // Gets a GL texture id representing the resource, that can be rendered with.
-    unsigned lockForRead(ResourceId);
+    const Resource* lockForRead(ResourceId);
     void unlockForRead(ResourceId);
+    const Resource* lockForWrite(ResourceId);
+    void unlockForWrite(ResourceId);
+    static void populateSkBitmapWithResource(SkBitmap*, const Resource*);
 
     bool transferResource(WebKit::WebGraphicsContext3D*, ResourceId, TransferableResource*);
     void trimMailboxDeque();
@@ -211,6 +297,7 @@ private:
 
     Deque<Mailbox> m_mailboxes;
 
+    ResourceType m_defaultResourceType;
     bool m_useTextureStorageExt;
     bool m_useTextureUsageHint;
     bool m_useShallowFlush;
@@ -218,51 +305,6 @@ private:
     int m_maxTextureSize;
 };
 
-class CCScopedLockResourceForRead {
-    WTF_MAKE_NONCOPYABLE(CCScopedLockResourceForRead);
-public:
-    CCScopedLockResourceForRead(CCResourceProvider* resourceProvider, CCResourceProvider::ResourceId resourceId)
-        : m_resourceProvider(resourceProvider)
-        , m_resourceId(resourceId)
-        , m_textureId(resourceProvider->lockForRead(resourceId))
-    {
-        ASSERT(m_textureId);
-    }
-
-    ~CCScopedLockResourceForRead()
-    {
-        m_resourceProvider->unlockForRead(m_resourceId);
-    }
-
-    unsigned textureId() const { return m_textureId; }
-
-private:
-    CCResourceProvider* m_resourceProvider;
-    CCResourceProvider::ResourceId m_resourceId;
-    unsigned m_textureId;
-};
-
-class CCScopedLockResourceForWrite {
-    WTF_MAKE_NONCOPYABLE(CCScopedLockResourceForWrite);
-public:
-    CCScopedLockResourceForWrite(CCResourceProvider* resourceProvider, CCResourceProvider::ResourceId resourceId)
-        : m_resourceProvider(resourceProvider)
-        , m_resourceId(resourceId)
-        , m_textureId(resourceProvider->lockForWrite(resourceId)) { }
-
-    ~CCScopedLockResourceForWrite()
-    {
-        m_resourceProvider->unlockForWrite(m_resourceId);
-    }
-
-    unsigned textureId() const { return m_textureId; }
-
-private:
-    CCResourceProvider* m_resourceProvider;
-    CCResourceProvider::ResourceId m_resourceId;
-    unsigned m_textureId;
-};
-
 }
 
 #endif
index 7d252bf..a9c0116 100644 (file)
@@ -1,3 +1,26 @@
+2012-08-22  Alexandre Elias  <aelias@google.com>
+
+        [chromium] Add software bitmap resources to CCResourceProvider
+        https://bugs.webkit.org/show_bug.cgi?id=93677
+
+        Reviewed by Adrienne Walker.
+
+        Second commit after revert.
+
+        This adds the ability to CCResourceProvider to use software bitmaps.
+        They are allocated as plain-old-memory, and exposed as Skia objects.
+
+        We want the ResourceProvider to be able to handle different resource
+        types at the same time.  In practice, a default resource type is
+        desired for most uses within a single compositor instance, which is
+        specified by the default resource type.  Default resource types are
+        expected to be mostly 1-to-1 with CCRenderer types.
+
+        New tests added by parametrizing existing CCResourceProvider tests.
+
+        * tests/CCResourceProviderTest.cpp:
+        (WebKit::CCResourceProviderTest::getResourcePixels):
+
 2012-08-22  W. James MacLean  <wjmaclean@chromium.org>
 
         [chromium] Add touch link highlight animation layers.
index 9e8599c..e55c3c5 100644 (file)
@@ -287,23 +287,36 @@ private:
     PendingProduceTextureList m_pendingProduceTextures;
 };
 
-class CCResourceProviderTest : public testing::Test {
+class CCResourceProviderTest : public testing::TestWithParam<CCResourceProvider::ResourceType> {
 public:
     CCResourceProviderTest()
         : m_sharedData(ContextSharedData::create())
         , m_context(FakeWebCompositorOutputSurface::create(ResourceProviderContext::create(m_sharedData.get())))
         , m_resourceProvider(CCResourceProvider::create(m_context.get()))
     {
+        m_resourceProvider->setDefaultResourceType(GetParam());
     }
 
     ResourceProviderContext* context() { return static_cast<ResourceProviderContext*>(m_context->context3D()); }
 
     void getResourcePixels(CCResourceProvider::ResourceId id, const IntSize& size, WGC3Denum format, uint8_t* pixels)
     {
-        CCScopedLockResourceForRead lock(m_resourceProvider.get(), id);
-        ASSERT_NE(0U, lock.textureId());
-        context()->bindTexture(GraphicsContext3D::TEXTURE_2D, lock.textureId());
-        context()->getPixels(size, format, pixels);
+        if (GetParam() == CCResourceProvider::GLTexture) {
+            CCResourceProvider::ScopedReadLockGL lockGL(m_resourceProvider.get(), id);
+            ASSERT_NE(0U, lockGL.textureId());
+            context()->bindTexture(GraphicsContext3D::TEXTURE_2D, lockGL.textureId());
+            context()->getPixels(size, format, pixels);
+        } else if (GetParam() == CCResourceProvider::Bitmap) {
+            CCResourceProvider::ScopedReadLockSoftware lockSoftware(m_resourceProvider.get(), id);
+            memcpy(pixels, lockSoftware.skBitmap()->getPixels(), lockSoftware.skBitmap()->getSize());
+        }
+    }
+
+    void expectNumResources(int count)
+    {
+        EXPECT_EQ(count, static_cast<int>(m_resourceProvider->numResources()));
+        if (GetParam() == CCResourceProvider::GLTexture)
+            EXPECT_EQ(count, context()->textureCount());
     }
 
 protected:
@@ -313,7 +326,7 @@ protected:
     OwnPtr<CCResourceProvider> m_resourceProvider;
 };
 
-TEST_F(CCResourceProviderTest, Basic)
+TEST_P(CCResourceProviderTest, Basic)
 {
     IntSize size(1, 1);
     WGC3Denum format = GraphicsContext3D::RGBA;
@@ -322,7 +335,7 @@ TEST_F(CCResourceProviderTest, Basic)
     ASSERT_EQ(4U, pixelSize);
 
     CCResourceProvider::ResourceId id = m_resourceProvider->createResource(pool, size, format, CCResourceProvider::TextureUsageAny);
-    EXPECT_EQ(1, context()->textureCount());
+    expectNumResources(1);
 
     uint8_t data[4] = {1, 2, 3, 4};
     IntRect rect(IntPoint(), size);
@@ -333,10 +346,10 @@ TEST_F(CCResourceProviderTest, Basic)
     EXPECT_EQ(0, memcmp(data, result, pixelSize));
 
     m_resourceProvider->deleteResource(id);
-    EXPECT_EQ(0, context()->textureCount());
+    expectNumResources(0);
 }
 
-TEST_F(CCResourceProviderTest, DeleteOwnedResources)
+TEST_P(CCResourceProviderTest, DeleteOwnedResources)
 {
     IntSize size(1, 1);
     WGC3Denum format = GraphicsContext3D::RGBA;
@@ -345,16 +358,16 @@ TEST_F(CCResourceProviderTest, DeleteOwnedResources)
     const int count = 3;
     for (int i = 0; i < count; ++i)
         m_resourceProvider->createResource(pool, size, format, CCResourceProvider::TextureUsageAny);
-    EXPECT_EQ(3, context()->textureCount());
+    expectNumResources(3);
 
     m_resourceProvider->deleteOwnedResources(pool+1);
-    EXPECT_EQ(3, context()->textureCount());
+    expectNumResources(3);
 
     m_resourceProvider->deleteOwnedResources(pool);
-    EXPECT_EQ(0, context()->textureCount());
+    expectNumResources(0);
 }
 
-TEST_F(CCResourceProviderTest, Upload)
+TEST_P(CCResourceProviderTest, Upload)
 {
     IntSize size(2, 2);
     WGC3Denum format = GraphicsContext3D::RGBA;
@@ -402,12 +415,28 @@ TEST_F(CCResourceProviderTest, Upload)
         getResourcePixels(id, size, format, result);
         EXPECT_EQ(0, memcmp(expected, result, pixelSize));
     }
+    {
+        IntRect offsetImageRect(IntPoint(100, 100), size);
+        IntRect sourceRect(100, 100, 1, 1);
+        IntSize destOffset(1, 0);
+        m_resourceProvider->upload(id, image, offsetImageRect, sourceRect, destOffset);
+
+        uint8_t expected[16] = {0, 1, 2, 3,   0, 1, 2, 3,
+                                4, 5, 6, 7,   0, 1, 2, 3};
+        getResourcePixels(id, size, format, result);
+        EXPECT_EQ(0, memcmp(expected, result, pixelSize));
+    }
+
 
     m_resourceProvider->deleteResource(id);
 }
 
-TEST_F(CCResourceProviderTest, TransferResources)
+TEST_P(CCResourceProviderTest, TransferResources)
 {
+    // Resource transfer is only supported with GL textures for now.
+    if (GetParam() != CCResourceProvider::GLTexture)
+        return;
+
     OwnPtr<CCGraphicsContext> childContext(FakeWebCompositorOutputSurface::create(ResourceProviderContext::create(m_sharedData.get())));
     OwnPtr<CCResourceProvider> childResourceProvider(CCResourceProvider::create(childContext.get()));
 
@@ -486,14 +515,14 @@ TEST_F(CCResourceProviderTest, TransferResources)
 
     ResourceProviderContext* childContext3D = static_cast<ResourceProviderContext*>(childContext->context3D());
     {
-        CCScopedLockResourceForRead lock(childResourceProvider.get(), id1);
+        CCResourceProvider::ScopedReadLockGL lock(childResourceProvider.get(), id1);
         ASSERT_NE(0U, lock.textureId());
         childContext3D->bindTexture(GraphicsContext3D::TEXTURE_2D, lock.textureId());
         childContext3D->getPixels(size, format, result);
         EXPECT_EQ(0, memcmp(data1, result, pixelSize));
     }
     {
-        CCScopedLockResourceForRead lock(childResourceProvider.get(), id2);
+        CCResourceProvider::ScopedReadLockGL lock(childResourceProvider.get(), id2);
         ASSERT_NE(0U, lock.textureId());
         childContext3D->bindTexture(GraphicsContext3D::TEXTURE_2D, lock.textureId());
         childContext3D->getPixels(size, format, result);
@@ -519,4 +548,9 @@ TEST_F(CCResourceProviderTest, TransferResources)
     EXPECT_EQ(0u, m_resourceProvider->mailboxCount());
 }
 
+INSTANTIATE_TEST_CASE_P(CCResourceProviderTests,
+                        CCResourceProviderTest,
+                        ::testing::Values(CCResourceProvider::GLTexture,
+                                          CCResourceProvider::Bitmap));
+
 } // namespace