Changeset 125838 in webkit


Ignore:
Timestamp:
Aug 16, 2012 6:16:42 PM (12 years ago)
Author:
piman@chromium.org
Message:

[chromium] Add resource transfer functions to CCResourceProvider
https://bugs.webkit.org/show_bug.cgi?id=93524

Reviewed by James Robinson.

This adds methods to CCResourceProvider to be able to transport
resources from a child to a parent.

Added test to CCResourceProviderTest.

Source/WebCore:

  • platform/graphics/chromium/cc/CCResourceProvider.cpp:

(WebCore::CCResourceProvider::inUseByConsumer):
(WebCore::CCResourceProvider::createResource):
(WebCore::CCResourceProvider::createResourceFromExternalTexture):
(WebCore::CCResourceProvider::CCResourceProvider):
(WebCore::CCResourceProvider::createChild):
(WebCore):
(WebCore::CCResourceProvider::destroyChild):
(WebCore::CCResourceProvider::getChildToParentMap):
(WebCore::CCResourceProvider::prepareSendToParent):
(WebCore::CCResourceProvider::prepareSendToChild):
(WebCore::CCResourceProvider::receiveFromChild):
(WebCore::CCResourceProvider::receiveFromParent):
(WebCore::CCResourceProvider::transferResource):

  • platform/graphics/chromium/cc/CCResourceProvider.h:

(Mailbox):
(TransferableResource):
(TransferableResourceList):
(CCResourceProvider):
(Resource):
(Child):

Source/WebKit/chromium:

  • tests/CCResourceProviderTest.cpp:

(WebKit::textureSize):
(WebKit):
(WebKit::Texture::Texture):
(Texture):
(ContextSharedData):
(WebKit::ContextSharedData::create):
(WebKit::ContextSharedData::insertSyncPoint):
(WebKit::ContextSharedData::genMailbox):
(WebKit::ContextSharedData::produceTexture):
(WebKit::ContextSharedData::consumeTexture):
(WebKit::ContextSharedData::ContextSharedData):
(WebKit::ResourceProviderContext::create):
(ResourceProviderContext):
(WebKit::ResourceProviderContext::insertSyncPoint):
(WebKit::ResourceProviderContext::waitSyncPoint):
(WebKit::ResourceProviderContext::genMailboxCHROMIUM):
(WebKit::ResourceProviderContext::produceTextureCHROMIUM):
(WebKit::ResourceProviderContext::consumeTextureCHROMIUM):
(WebKit::ResourceProviderContext::ResourceProviderContext):
(PendingProduceTexture):
(WebKit::CCResourceProviderTest::CCResourceProviderTest):
(CCResourceProviderTest):
(WebKit::TEST_F):

Location:
trunk/Source
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r125837 r125838  
     12012-08-16  Antoine Labour  <piman@chromium.org>
     2
     3        [chromium] Add resource transfer functions to CCResourceProvider
     4        https://bugs.webkit.org/show_bug.cgi?id=93524
     5
     6        Reviewed by James Robinson.
     7
     8        This adds methods to CCResourceProvider to be able to transport
     9        resources from a child to a parent.
     10
     11        Added test to CCResourceProviderTest.
     12
     13        * platform/graphics/chromium/cc/CCResourceProvider.cpp:
     14        (WebCore::CCResourceProvider::inUseByConsumer):
     15        (WebCore::CCResourceProvider::createResource):
     16        (WebCore::CCResourceProvider::createResourceFromExternalTexture):
     17        (WebCore::CCResourceProvider::CCResourceProvider):
     18        (WebCore::CCResourceProvider::createChild):
     19        (WebCore):
     20        (WebCore::CCResourceProvider::destroyChild):
     21        (WebCore::CCResourceProvider::getChildToParentMap):
     22        (WebCore::CCResourceProvider::prepareSendToParent):
     23        (WebCore::CCResourceProvider::prepareSendToChild):
     24        (WebCore::CCResourceProvider::receiveFromChild):
     25        (WebCore::CCResourceProvider::receiveFromParent):
     26        (WebCore::CCResourceProvider::transferResource):
     27        * platform/graphics/chromium/cc/CCResourceProvider.h:
     28        (Mailbox):
     29        (TransferableResource):
     30        (TransferableResourceList):
     31        (CCResourceProvider):
     32        (Resource):
     33        (Child):
     34
    1352012-08-16  Kent Tamura  <tkent@chromium.org>
    236
  • trunk/Source/WebCore/platform/graphics/chromium/cc/CCResourceProvider.cpp

    r125827 r125838  
    3333#include "cc/CCProxy.h"
    3434#include <public/WebGraphicsContext3D.h>
     35#include <wtf/HashSet.h>
    3536
    3637using WebKit::WebGraphicsContext3D;
     
    8384    ResourceMap::iterator it = m_resources.find(id);
    8485    ASSERT(it != m_resources.end());
    85     return !!it->second.lockForReadCount;
     86    return !!it->second.lockForReadCount || it->second.exported;
    8687}
    8788
     
    110111        GLC(context3d, context3d->texImage2D(GraphicsContext3D::TEXTURE_2D, 0, format, size.width(), size.height(), 0, format, GraphicsContext3D::UNSIGNED_BYTE, 0));
    111112    ResourceId id = m_nextId++;
    112     Resource resource = {textureId, pool, 0, false, false, size, format};
     113    Resource resource(textureId, pool, size, format);
    113114    m_resources.add(id, resource);
    114115    return id;
     
    119120    ASSERT(CCProxy::isImplThread());
    120121    ResourceId id = m_nextId++;
    121     Resource resource = {textureId, 0, 0, false, true, IntSize(), 0};
     122    Resource resource;
     123    resource.glId = textureId;
     124    resource.external = true;
    122125    m_resources.add(id, resource);
    123126    return id;
     
    142145{
    143146    ASSERT(CCProxy::isImplThread());
    144     Vector<ResourceId> toDelete;
     147    ResourceIdArray toDelete;
    145148    for (ResourceMap::iterator it = m_resources.begin(); it != m_resources.end(); ++it) {
    146149        if (it->second.pool == pool && !it->second.external)
    147150            toDelete.append(it->first);
    148151    }
    149     for (Vector<ResourceId>::iterator it = toDelete.begin(); it != toDelete.end(); ++it)
     152    for (ResourceIdArray::iterator it = toDelete.begin(); it != toDelete.end(); ++it)
    150153        deleteResource(*it);
    151154}
     
    229232    : m_context(context)
    230233    , m_nextId(1)
     234    , m_nextChild(1)
    231235    , m_useTextureStorageExt(false)
    232236    , m_useTextureUsageHint(false)
     
    265269}
    266270
    267 }
     271int CCResourceProvider::createChild(int pool)
     272{
     273    ASSERT(CCProxy::isImplThread());
     274    Child childInfo;
     275    childInfo.pool = pool;
     276    int child = m_nextChild++;
     277    m_children.add(child, childInfo);
     278    return child;
     279}
     280
     281void CCResourceProvider::destroyChild(int child)
     282{
     283    ASSERT(CCProxy::isImplThread());
     284    ChildMap::iterator it = m_children.find(child);
     285    ASSERT(it != m_children.end());
     286    deleteOwnedResources(it->second.pool);
     287    m_children.remove(it);
     288    trimMailboxDeque();
     289}
     290
     291const CCResourceProvider::ResourceIdMap& CCResourceProvider::getChildToParentMap(int child) const
     292{
     293    ASSERT(CCProxy::isImplThread());
     294    ChildMap::const_iterator it = m_children.find(child);
     295    ASSERT(it != m_children.end());
     296    return it->second.childToParentMap;
     297}
     298
     299CCResourceProvider::TransferableResourceList CCResourceProvider::prepareSendToParent(const ResourceIdArray& resources)
     300{
     301    ASSERT(CCProxy::isImplThread());
     302    TransferableResourceList list;
     303    list.syncPoint = 0;
     304    WebGraphicsContext3D* context3d = m_context->context3D();
     305    if (!context3d || !context3d->makeContextCurrent()) {
     306        // FIXME: Implement this path for software compositing.
     307        return list;
     308    }
     309    for (ResourceIdArray::const_iterator it = resources.begin(); it != resources.end(); ++it) {
     310        TransferableResource resource;
     311        if (transferResource(context3d, *it, &resource)) {
     312            m_resources.find(*it)->second.exported = true;
     313            list.resources.append(resource);
     314        }
     315    }
     316    if (list.resources.size())
     317        list.syncPoint = context3d->insertSyncPoint();
     318    return list;
     319}
     320
     321CCResourceProvider::TransferableResourceList CCResourceProvider::prepareSendToChild(int child, const ResourceIdArray& resources)
     322{
     323    ASSERT(CCProxy::isImplThread());
     324    TransferableResourceList list;
     325    list.syncPoint = 0;
     326    WebGraphicsContext3D* context3d = m_context->context3D();
     327    if (!context3d || !context3d->makeContextCurrent()) {
     328        // FIXME: Implement this path for software compositing.
     329        return list;
     330    }
     331    Child& childInfo = m_children.find(child)->second;
     332    for (ResourceIdArray::const_iterator it = resources.begin(); it != resources.end(); ++it) {
     333        TransferableResource resource;
     334        if (!transferResource(context3d, *it, &resource))
     335            ASSERT_NOT_REACHED();
     336        resource.id = childInfo.parentToChildMap.get(*it);
     337        childInfo.parentToChildMap.remove(*it);
     338        childInfo.childToParentMap.remove(resource.id);
     339        list.resources.append(resource);
     340        deleteResource(*it);
     341    }
     342    if (list.resources.size())
     343        list.syncPoint = context3d->insertSyncPoint();
     344    return list;
     345}
     346
     347void CCResourceProvider::receiveFromChild(int child, const TransferableResourceList& resources)
     348{
     349    ASSERT(CCProxy::isImplThread());
     350    WebGraphicsContext3D* context3d = m_context->context3D();
     351    if (!context3d || !context3d->makeContextCurrent()) {
     352        // FIXME: Implement this path for software compositing.
     353        return;
     354    }
     355    if (resources.syncPoint) {
     356        // NOTE: If the parent is a browser and the child a renderer, the parent
     357        // is not supposed to have its context wait, because that could induce
     358        // deadlocks and/or security issues. The caller is responsible for
     359        // waiting asynchronously, and resetting syncPoint before calling this.
     360        // However if the parent is a renderer (e.g. browser tag), it may be ok
     361        // (and is simpler) to wait.
     362        GLC(context3d, context3d->waitSyncPoint(resources.syncPoint));
     363    }
     364    Child& childInfo = m_children.find(child)->second;
     365    for (Vector<TransferableResource>::const_iterator it = resources.resources.begin(); it != resources.resources.end(); ++it) {
     366        unsigned textureId;
     367        GLC(context3d, textureId = context3d->createTexture());
     368        GLC(context3d, context3d->bindTexture(GraphicsContext3D::TEXTURE_2D, textureId));
     369        GLC(context3d, context3d->consumeTextureCHROMIUM(GraphicsContext3D::TEXTURE_2D, it->mailbox.name));
     370        ResourceId id = m_nextId++;
     371        Resource resource(textureId, childInfo.pool, it->size, it->format);
     372        m_resources.add(id, resource);
     373        m_mailboxes.append(it->mailbox);
     374        childInfo.parentToChildMap.add(id, it->id);
     375        childInfo.childToParentMap.add(it->id, id);
     376    }
     377}
     378
     379void CCResourceProvider::receiveFromParent(const TransferableResourceList& resources)
     380{
     381    ASSERT(CCProxy::isImplThread());
     382    WebGraphicsContext3D* context3d = m_context->context3D();
     383    if (!context3d || !context3d->makeContextCurrent()) {
     384        // FIXME: Implement this path for software compositing.
     385        return;
     386    }
     387    if (resources.syncPoint)
     388        GLC(context3d, context3d->waitSyncPoint(resources.syncPoint));
     389    for (Vector<TransferableResource>::const_iterator it = resources.resources.begin(); it != resources.resources.end(); ++it) {
     390        Resource& resource = m_resources.find(it->id)->second;
     391        ASSERT(resource.exported);
     392        resource.exported = false;
     393        GLC(context3d, context3d->bindTexture(GraphicsContext3D::TEXTURE_2D, resource.glId));
     394        GLC(context3d, context3d->consumeTextureCHROMIUM(GraphicsContext3D::TEXTURE_2D, it->mailbox.name));
     395        m_mailboxes.append(it->mailbox);
     396    }
     397}
     398
     399bool CCResourceProvider::transferResource(WebGraphicsContext3D* context, ResourceId id, TransferableResource* resource)
     400{
     401    ASSERT(CCProxy::isImplThread());
     402    ResourceMap::const_iterator it = m_resources.find(id);
     403    ASSERT(it != m_resources.end() && !it->second.lockedForWrite && !it->second.lockForReadCount && !it->second.external);
     404    if (it->second.exported)
     405        return false;
     406    resource->id = id;
     407    resource->format = it->second.format;
     408    resource->size = it->second.size;
     409    if (!m_mailboxes.isEmpty())
     410        resource->mailbox = m_mailboxes.takeFirst();
     411    else
     412        GLC(context, context->genMailboxCHROMIUM(resource->mailbox.name));
     413    GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, it->second.glId));
     414    GLC(context, context->produceTextureCHROMIUM(GraphicsContext3D::TEXTURE_2D, resource->mailbox.name));
     415    return true;
     416}
     417
     418void CCResourceProvider::trimMailboxDeque()
     419{
     420    // Trim the mailbox deque to the maximum number of resources we may need to
     421    // send.
     422    // If we have a parent, any non-external resource not already transfered is
     423    // eligible to be sent to the parent. Otherwise, all resources belonging to
     424    // a child might need to be sent back to the child.
     425    size_t maxMailboxCount = 0;
     426    if (m_context->capabilities().hasParentCompositor) {
     427        for (ResourceMap::iterator it = m_resources.begin(); it != m_resources.end(); ++it) {
     428            if (!it->second.exported && !it->second.external)
     429                ++maxMailboxCount;
     430        }
     431    } else {
     432        HashSet<int> childPoolSet;
     433        for (ChildMap::iterator it = m_children.begin(); it != m_children.end(); ++it)
     434            childPoolSet.add(it->second.pool);
     435        for (ResourceMap::iterator it = m_resources.begin(); it != m_resources.end(); ++it) {
     436            if (childPoolSet.contains(it->second.pool))
     437                ++maxMailboxCount;
     438        }
     439    }
     440    while (m_mailboxes.size() > maxMailboxCount)
     441        m_mailboxes.removeFirst();
     442}
     443
     444}
  • trunk/Source/WebCore/platform/graphics/chromium/cc/CCResourceProvider.h

    r125827 r125838  
    3131#include "IntSize.h"
    3232#include "cc/CCGraphicsContext.h"
     33#include <wtf/Deque.h>
    3334#include <wtf/HashMap.h>
    3435#include <wtf/OwnPtr.h>
     
    3637#include <wtf/PassRefPtr.h>
    3738#include <wtf/RefPtr.h>
     39#include <wtf/Vector.h>
    3840
    3941namespace WebKit {
     
    5456public:
    5557    typedef unsigned ResourceId;
     58    typedef Vector<ResourceId> ResourceIdArray;
     59    typedef HashMap<ResourceId, ResourceId> ResourceIdMap;
    5660    enum TextureUsageHint { TextureUsageAny, TextureUsageFramebuffer };
     61    struct Mailbox {
     62        GC3Dbyte name[64];
     63    };
     64    struct TransferableResource {
     65        unsigned id;
     66        GC3Denum format;
     67        IntSize size;
     68        Mailbox mailbox;
     69    };
     70    typedef Vector<TransferableResource> TransferableResourceArray;
     71    struct TransferableResourceList {
     72        TransferableResourceArray resources;
     73        unsigned syncPoint;
     74    };
    5775
    5876    static PassOwnPtr<CCResourceProvider> create(CCGraphicsContext*);
     
    91109    bool shallowFlushIfSupported();
    92110
     111    // Creates accounting for a child, and associate it with a pool. Resources
     112    // transfered from that child will go to that pool. Returns a child ID.
     113    int createChild(int pool);
     114
     115    // Destroys accounting for the child, deleting all resources from that pool.
     116    void destroyChild(int child);
     117
     118    // Gets the child->parent resource ID map.
     119    const ResourceIdMap& getChildToParentMap(int child) const;
     120
     121    // Prepares resources to be transfered to the parent, moving them to
     122    // mailboxes and serializing meta-data into TransferableResources.
     123    // Resources are not removed from the CCResourceProvider, but are markes as
     124    // "in use".
     125    TransferableResourceList prepareSendToParent(const ResourceIdArray&);
     126
     127    // Prepares resources to be transfered back to the child, moving them to
     128    // mailboxes and serializing meta-data into TransferableResources.
     129    // Resources are removed from the CCResourceProvider. Note: the resource IDs
     130    // passed are in the parent namespace and will be translated to the child
     131    // namespace when returned.
     132    TransferableResourceList prepareSendToChild(int child, const ResourceIdArray&);
     133
     134    // Receives resources from a child, moving them from mailboxes. Resource IDs
     135    // passed are in the child namespace, and will be translated to the parent
     136    // namespace, added to the child->parent map.
     137    // NOTE: if the syncPoint filed in TransferableResourceList is set, this
     138    // will wait on it.
     139    void receiveFromChild(int child, const TransferableResourceList&);
     140
     141    // Receives resources from the parent, moving them from mailboxes. Resource IDs
     142    // passed are in the child namespace.
     143    // NOTE: if the syncPoint filed in TransferableResourceList is set, this
     144    // will wait on it.
     145    void receiveFromParent(const TransferableResourceList&);
     146
     147    // Only for testing
     148    size_t mailboxCount() const { return m_mailboxes.size(); }
     149
    93150private:
    94151    friend class CCScopedLockResourceForRead;
     
    96153
    97154    struct Resource {
     155        Resource()
     156            : glId(0)
     157            , pool(0)
     158            , lockForReadCount(0)
     159            , lockedForWrite(false)
     160            , external(false)
     161            , exported(false)
     162            , size()
     163            , format(0)
     164        { }
     165        Resource(unsigned textureId, int pool, const IntSize& size, GC3Denum format)
     166            : glId(textureId)
     167            , pool(pool)
     168            , lockForReadCount(0)
     169            , lockedForWrite(false)
     170            , external(false)
     171            , exported(false)
     172            , size(size)
     173            , format(format)
     174        { }
    98175        unsigned glId;
    99176        int pool;
     
    101178        bool lockedForWrite;
    102179        bool external;
     180        bool exported;
    103181        IntSize size;
    104182        GC3Denum format;
    105183    };
    106184    typedef HashMap<ResourceId, Resource> ResourceMap;
     185    struct Child {
     186        int pool;
     187        ResourceIdMap childToParentMap;
     188        ResourceIdMap parentToChildMap;
     189    };
     190    typedef HashMap<int, Child> ChildMap;
    107191
    108192    explicit CCResourceProvider(CCGraphicsContext*);
     
    117201    void unlockForRead(ResourceId);
    118202
     203    bool transferResource(WebKit::WebGraphicsContext3D*, ResourceId, TransferableResource*);
     204    void trimMailboxDeque();
     205
    119206    CCGraphicsContext* m_context;
    120207    ResourceId m_nextId;
    121208    ResourceMap m_resources;
     209    int m_nextChild;
     210    ChildMap m_children;
     211
     212    Deque<Mailbox> m_mailboxes;
    122213
    123214    bool m_useTextureStorageExt;
  • trunk/Source/WebKit/chromium/ChangeLog

    r125827 r125838  
     12012-08-16  Antoine Labour  <piman@chromium.org>
     2
     3        [chromium] Add resource transfer functions to CCResourceProvider
     4        https://bugs.webkit.org/show_bug.cgi?id=93524
     5
     6        Reviewed by James Robinson.
     7
     8        This adds methods to CCResourceProvider to be able to transport
     9        resources from a child to a parent.
     10
     11        Added test to CCResourceProviderTest.
     12
     13        * tests/CCResourceProviderTest.cpp:
     14        (WebKit::textureSize):
     15        (WebKit):
     16        (WebKit::Texture::Texture):
     17        (Texture):
     18        (ContextSharedData):
     19        (WebKit::ContextSharedData::create):
     20        (WebKit::ContextSharedData::insertSyncPoint):
     21        (WebKit::ContextSharedData::genMailbox):
     22        (WebKit::ContextSharedData::produceTexture):
     23        (WebKit::ContextSharedData::consumeTexture):
     24        (WebKit::ContextSharedData::ContextSharedData):
     25        (WebKit::ResourceProviderContext::create):
     26        (ResourceProviderContext):
     27        (WebKit::ResourceProviderContext::insertSyncPoint):
     28        (WebKit::ResourceProviderContext::waitSyncPoint):
     29        (WebKit::ResourceProviderContext::genMailboxCHROMIUM):
     30        (WebKit::ResourceProviderContext::produceTextureCHROMIUM):
     31        (WebKit::ResourceProviderContext::consumeTextureCHROMIUM):
     32        (WebKit::ResourceProviderContext::ResourceProviderContext):
     33        (PendingProduceTexture):
     34        (WebKit::CCResourceProviderTest::CCResourceProviderTest):
     35        (CCResourceProviderTest):
     36        (WebKit::TEST_F):
     37
    1382012-08-16  Alexandre Elias  <aelias@google.com>
    239
  • trunk/Source/WebKit/chromium/tests/CCResourceProviderTest.cpp

    r125827 r125838  
    4343namespace {
    4444
     45size_t textureSize(const IntSize& size, WGC3Denum format)
     46{
     47    unsigned int componentsPerPixel = 4;
     48    unsigned int bytesPerComponent = 1;
     49    GraphicsContext3D::computeFormatAndTypeParameters(format, GraphicsContext3D::UNSIGNED_BYTE, &componentsPerPixel, &bytesPerComponent);
     50    return size.width() * size.height() * componentsPerPixel * bytesPerComponent;
     51}
     52
     53struct Texture {
     54    Texture(const IntSize& size, WGC3Denum format)
     55        : size(size)
     56        , format(format)
     57        , data(adoptArrayPtr(new uint8_t[textureSize(size, format)]))
     58    {
     59    }
     60
     61    IntSize size;
     62    WGC3Denum format;
     63    OwnArrayPtr<uint8_t> data;
     64};
     65
     66// Shared data between multiple ResourceProviderContext. This contains mailbox
     67// contents as well as information about sync points.
     68class ContextSharedData {
     69public:
     70    static PassOwnPtr<ContextSharedData> create() { return adoptPtr(new ContextSharedData()); }
     71
     72    unsigned insertSyncPoint() { return m_nextSyncPoint++; }
     73
     74    void genMailbox(WGC3Dbyte* mailbox)
     75    {
     76        memset(mailbox, 0, sizeof(WGC3Dbyte[64]));
     77        memcpy(mailbox, &m_nextMailBox, sizeof(m_nextMailBox));
     78        ++m_nextMailBox;
     79    }
     80
     81    void produceTexture(const WGC3Dbyte* mailboxName, unsigned syncPoint, PassOwnPtr<Texture> texture)
     82    {
     83        unsigned mailbox = 0;
     84        memcpy(&mailbox, mailboxName, sizeof(mailbox));
     85        ASSERT(mailbox && mailbox < m_nextMailBox);
     86        m_textures.set(mailbox, texture);
     87        ASSERT(m_syncPointForMailbox.get(mailbox) < syncPoint);
     88        m_syncPointForMailbox.set(mailbox, syncPoint);
     89    }
     90
     91    PassOwnPtr<Texture> consumeTexture(const WGC3Dbyte* mailboxName, unsigned syncPoint)
     92    {
     93        unsigned mailbox = 0;
     94        memcpy(&mailbox, mailboxName, sizeof(mailbox));
     95        ASSERT(mailbox && mailbox < m_nextMailBox);
     96
     97        // If the latest sync point the context has waited on is before the sync
     98        // point for when the mailbox was set, pretend we never saw that
     99        // produceTexture.
     100        if (m_syncPointForMailbox.get(mailbox) < syncPoint)
     101            return nullptr;
     102        return m_textures.take(mailbox);
     103    }
     104
     105private:
     106    ContextSharedData()
     107        : m_nextSyncPoint(1)
     108        , m_nextMailBox(1)
     109    { }
     110
     111    unsigned m_nextSyncPoint;
     112    unsigned m_nextMailBox;
     113    typedef HashMap<unsigned, OwnPtr<Texture> > TextureMap;
     114    TextureMap m_textures;
     115    HashMap<unsigned, unsigned> m_syncPointForMailbox;
     116};
     117
    45118class ResourceProviderContext : public CompositorFakeWebGraphicsContext3D {
    46119public:
    47     static PassOwnPtr<ResourceProviderContext> create() { return adoptPtr(new ResourceProviderContext(Attributes())); }
     120    static PassOwnPtr<ResourceProviderContext> create(ContextSharedData* sharedData) { return adoptPtr(new ResourceProviderContext(Attributes(), sharedData)); }
     121
     122    virtual unsigned insertSyncPoint()
     123    {
     124        unsigned syncPoint = m_sharedData->insertSyncPoint();
     125        // Commit the produceTextureCHROMIUM calls at this point, so that
     126        // they're associated with the sync point.
     127        for (PendingProduceTextureList::iterator it = m_pendingProduceTextures.begin(); it != m_pendingProduceTextures.end(); ++it)
     128            m_sharedData->produceTexture((*it)->mailbox, syncPoint, (*it)->texture.release());
     129        m_pendingProduceTextures.clear();
     130        return syncPoint;
     131    }
     132
     133    virtual void waitSyncPoint(unsigned syncPoint)
     134    {
     135        m_lastWaitedSyncPoint = std::max(syncPoint, m_lastWaitedSyncPoint);
     136    }
    48137
    49138    virtual void bindTexture(WGC3Denum target, WebGLId texture)
     
    114203    }
    115204
     205    virtual void genMailboxCHROMIUM(WGC3Dbyte* mailbox) { return m_sharedData->genMailbox(mailbox); }
     206    virtual void produceTextureCHROMIUM(WGC3Denum target, const WGC3Dbyte* mailbox)
     207    {
     208        ASSERT(m_currentTexture);
     209        ASSERT(target == GraphicsContext3D::TEXTURE_2D);
     210
     211        // Delay movind the texture into the mailbox until the next
     212        // insertSyncPoint, so that it is not visible to other contexts that
     213        // haven't waited on that sync point.
     214        OwnPtr<PendingProduceTexture> pending = adoptPtr(new PendingProduceTexture);
     215        memcpy(pending->mailbox, mailbox, sizeof(pending->mailbox));
     216        pending->texture = m_textures.take(m_currentTexture);
     217        m_textures.set(m_currentTexture, nullptr);
     218        m_pendingProduceTextures.append(pending.release());
     219    }
     220
     221    virtual void consumeTextureCHROMIUM(WGC3Denum target, const WGC3Dbyte* mailbox)
     222    {
     223        ASSERT(m_currentTexture);
     224        ASSERT(target == GraphicsContext3D::TEXTURE_2D);
     225        m_textures.set(m_currentTexture, m_sharedData->consumeTexture(mailbox, m_lastWaitedSyncPoint));
     226    }
     227
    116228    void getPixels(const IntSize& size, WGC3Denum format, uint8_t* pixels)
    117229    {
     
    129241    }
    130242
    131     static size_t textureSize(const IntSize& size, WGC3Denum format)
    132     {
    133         unsigned int componentsPerPixel = 4;
    134         unsigned int bytesPerComponent = 1;
    135         GraphicsContext3D::computeFormatAndTypeParameters(format, GraphicsContext3D::UNSIGNED_BYTE, &componentsPerPixel, &bytesPerComponent);
    136         return size.width() * size.height() * componentsPerPixel * bytesPerComponent;
    137     }
    138 
    139243protected:
    140     explicit ResourceProviderContext(const Attributes& attrs)
     244    ResourceProviderContext(const Attributes& attrs, ContextSharedData* sharedData)
    141245        : CompositorFakeWebGraphicsContext3D(attrs)
     246        , m_sharedData(sharedData)
    142247        , m_currentTexture(0)
     248        , m_lastWaitedSyncPoint(0)
    143249    { }
    144250
    145251private:
    146     struct Texture {
    147         Texture(const IntSize& size_, WGC3Denum format_)
    148             : size(size_)
    149             , format(format_)
    150             , data(adoptArrayPtr(new uint8_t[textureSize(size, format)]))
    151         {
    152         }
    153 
    154         IntSize size;
    155         WGC3Denum format;
    156         OwnArrayPtr<uint8_t> data;
    157     };
    158 
    159252    void allocateTexture(const IntSize& size, WGC3Denum format)
    160253    {
     
    183276
    184277    typedef HashMap<WebGLId, OwnPtr<Texture> > TextureMap;
     278    struct PendingProduceTexture {
     279        WGC3Dbyte mailbox[64];
     280        OwnPtr<Texture> texture;
     281    };
     282    typedef Deque<OwnPtr<PendingProduceTexture> > PendingProduceTextureList;
     283    ContextSharedData* m_sharedData;
    185284    WebGLId m_currentTexture;
    186285    TextureMap m_textures;
     286    unsigned m_lastWaitedSyncPoint;
     287    PendingProduceTextureList m_pendingProduceTextures;
    187288};
    188289
     
    190291public:
    191292    CCResourceProviderTest()
    192         : m_context(FakeWebCompositorOutputSurface::create(ResourceProviderContext::create()))
     293        : m_sharedData(ContextSharedData::create())
     294        , m_context(FakeWebCompositorOutputSurface::create(ResourceProviderContext::create(m_sharedData.get())))
    193295        , m_resourceProvider(CCResourceProvider::create(m_context.get()))
    194296    {
     
    207309protected:
    208310    DebugScopedSetImplThread implThread;
     311    OwnPtr<ContextSharedData> m_sharedData;
    209312    OwnPtr<CCGraphicsContext> m_context;
    210313    OwnPtr<CCResourceProvider> m_resourceProvider;
     
    216319    WGC3Denum format = GraphicsContext3D::RGBA;
    217320    int pool = 1;
    218     size_t pixelSize = ResourceProviderContext::textureSize(size, format);
     321    size_t pixelSize = textureSize(size, format);
    219322    ASSERT_EQ(4U, pixelSize);
    220323
     
    257360    WGC3Denum format = GraphicsContext3D::RGBA;
    258361    int pool = 1;
    259     size_t pixelSize = ResourceProviderContext::textureSize(size, format);
     362    size_t pixelSize = textureSize(size, format);
    260363    ASSERT_EQ(16U, pixelSize);
    261364
     
    304407}
    305408
     409TEST_F(CCResourceProviderTest, TransferResources)
     410{
     411    OwnPtr<CCGraphicsContext> childContext(FakeWebCompositorOutputSurface::create(ResourceProviderContext::create(m_sharedData.get())));
     412    OwnPtr<CCResourceProvider> childResourceProvider(CCResourceProvider::create(childContext.get()));
     413
     414    IntSize size(1, 1);
     415    WGC3Denum format = GraphicsContext3D::RGBA;
     416    int pool = 1;
     417    size_t pixelSize = textureSize(size, format);
     418    ASSERT_EQ(4U, pixelSize);
     419
     420    CCResourceProvider::ResourceId id1 = childResourceProvider->createResource(pool, size, format, CCResourceProvider::TextureUsageAny);
     421    uint8_t data1[4] = {1, 2, 3, 4};
     422    IntRect rect(IntPoint(), size);
     423    childResourceProvider->upload(id1, data1, rect, rect, IntSize());
     424
     425    CCResourceProvider::ResourceId id2 = childResourceProvider->createResource(pool, size, format, CCResourceProvider::TextureUsageAny);
     426    uint8_t data2[4] = {5, 5, 5, 5};
     427    childResourceProvider->upload(id2, data2, rect, rect, IntSize());
     428
     429    int childPool = 2;
     430    int childId = m_resourceProvider->createChild(childPool);
     431
     432    {
     433        // Transfer some resources to the parent.
     434        CCResourceProvider::ResourceIdArray resourceIdsToTransfer;
     435        resourceIdsToTransfer.append(id1);
     436        resourceIdsToTransfer.append(id2);
     437        CCResourceProvider::TransferableResourceList list = childResourceProvider->prepareSendToParent(resourceIdsToTransfer);
     438        EXPECT_NE(0u, list.syncPoint);
     439        EXPECT_EQ(2u, list.resources.size());
     440        EXPECT_TRUE(childResourceProvider->inUseByConsumer(id1));
     441        EXPECT_TRUE(childResourceProvider->inUseByConsumer(id2));
     442        m_resourceProvider->receiveFromChild(childId, list);
     443    }
     444
     445    EXPECT_EQ(2u, m_resourceProvider->numResources());
     446    EXPECT_EQ(2u, m_resourceProvider->mailboxCount());
     447    CCResourceProvider::ResourceIdMap resourceMap = m_resourceProvider->getChildToParentMap(childId);
     448    CCResourceProvider::ResourceId mappedId1 = resourceMap.get(id1);
     449    CCResourceProvider::ResourceId mappedId2 = resourceMap.get(id2);
     450    EXPECT_NE(0u, mappedId1);
     451    EXPECT_NE(0u, mappedId2);
     452    EXPECT_FALSE(m_resourceProvider->inUseByConsumer(id1));
     453    EXPECT_FALSE(m_resourceProvider->inUseByConsumer(id2));
     454
     455    uint8_t result[4] = {0};
     456    getResourcePixels(mappedId1, size, format, result);
     457    EXPECT_EQ(0, memcmp(data1, result, pixelSize));
     458
     459    getResourcePixels(mappedId2, size, format, result);
     460    EXPECT_EQ(0, memcmp(data2, result, pixelSize));
     461
     462    {
     463        // Check that transfering again the same resource from the child to the
     464        // parent is a noop.
     465        CCResourceProvider::ResourceIdArray resourceIdsToTransfer;
     466        resourceIdsToTransfer.append(id1);
     467        CCResourceProvider::TransferableResourceList list = childResourceProvider->prepareSendToParent(resourceIdsToTransfer);
     468        EXPECT_EQ(0u, list.syncPoint);
     469        EXPECT_EQ(0u, list.resources.size());
     470    }
     471
     472    {
     473        // Transfer resources back from the parent to the child.
     474        CCResourceProvider::ResourceIdArray resourceIdsToTransfer;
     475        resourceIdsToTransfer.append(mappedId1);
     476        resourceIdsToTransfer.append(mappedId2);
     477        CCResourceProvider::TransferableResourceList list = m_resourceProvider->prepareSendToChild(childId, resourceIdsToTransfer);
     478        EXPECT_NE(0u, list.syncPoint);
     479        EXPECT_EQ(2u, list.resources.size());
     480        childResourceProvider->receiveFromParent(list);
     481    }
     482    EXPECT_EQ(0u, m_resourceProvider->mailboxCount());
     483    EXPECT_EQ(2u, childResourceProvider->mailboxCount());
     484    EXPECT_FALSE(childResourceProvider->inUseByConsumer(id1));
     485    EXPECT_FALSE(childResourceProvider->inUseByConsumer(id2));
     486
     487    ResourceProviderContext* childContext3D = static_cast<ResourceProviderContext*>(childContext->context3D());
     488    {
     489        CCScopedLockResourceForRead lock(childResourceProvider.get(), id1);
     490        ASSERT_NE(0U, lock.textureId());
     491        childContext3D->bindTexture(GraphicsContext3D::TEXTURE_2D, lock.textureId());
     492        childContext3D->getPixels(size, format, result);
     493        EXPECT_EQ(0, memcmp(data1, result, pixelSize));
     494    }
     495    {
     496        CCScopedLockResourceForRead lock(childResourceProvider.get(), id2);
     497        ASSERT_NE(0U, lock.textureId());
     498        childContext3D->bindTexture(GraphicsContext3D::TEXTURE_2D, lock.textureId());
     499        childContext3D->getPixels(size, format, result);
     500        EXPECT_EQ(0, memcmp(data2, result, pixelSize));
     501    }
     502
     503    {
     504        // Transfer resources to the parent again.
     505        CCResourceProvider::ResourceIdArray resourceIdsToTransfer;
     506        resourceIdsToTransfer.append(id1);
     507        resourceIdsToTransfer.append(id2);
     508        CCResourceProvider::TransferableResourceList list = childResourceProvider->prepareSendToParent(resourceIdsToTransfer);
     509        EXPECT_NE(0u, list.syncPoint);
     510        EXPECT_EQ(2u, list.resources.size());
     511        EXPECT_TRUE(childResourceProvider->inUseByConsumer(id1));
     512        EXPECT_TRUE(childResourceProvider->inUseByConsumer(id2));
     513        m_resourceProvider->receiveFromChild(childId, list);
     514    }
     515
     516    EXPECT_EQ(2u, m_resourceProvider->numResources());
     517    m_resourceProvider->destroyChild(childId);
     518    EXPECT_EQ(0u, m_resourceProvider->numResources());
     519    EXPECT_EQ(0u, m_resourceProvider->mailboxCount());
     520}
     521
    306522} // namespace
Note: See TracChangeset for help on using the changeset viewer.