Home | History | Annotate | Download | only in chromium
      1 /*
      2  * Copyright (C) 2010 Google Inc. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions are
      6  * met:
      7  *
      8  *     * Redistributions of source code must retain the above copyright
      9  * notice, this list of conditions and the following disclaimer.
     10  *     * Redistributions in binary form must reproduce the above
     11  * copyright notice, this list of conditions and the following disclaimer
     12  * in the documentation and/or other materials provided with the
     13  * distribution.
     14  *     * Neither the name of Google Inc. nor the names of its
     15  * contributors may be used to endorse or promote products derived from
     16  * this software without specific prior written permission.
     17  *
     18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29  */
     30 
     31 #include "config.h"
     32 
     33 #if USE(ACCELERATED_COMPOSITING)
     34 
     35 #include "LayerChromium.h"
     36 
     37 #include "cc/CCLayerImpl.h"
     38 #include "GraphicsContext3D.h"
     39 #include "LayerRendererChromium.h"
     40 #if USE(SKIA)
     41 #include "NativeImageSkia.h"
     42 #include "PlatformContextSkia.h"
     43 #endif
     44 #include "RenderLayerBacking.h"
     45 #include "TextStream.h"
     46 #include "skia/ext/platform_canvas.h"
     47 
     48 namespace WebCore {
     49 
     50 using namespace std;
     51 
     52 #ifndef NDEBUG
     53 static int s_nextLayerDebugID = 1;
     54 #endif
     55 
     56 PassRefPtr<LayerChromium> LayerChromium::create(GraphicsLayerChromium* owner)
     57 {
     58     return adoptRef(new LayerChromium(owner));
     59 }
     60 
     61 LayerChromium::LayerChromium(GraphicsLayerChromium* owner)
     62     : m_owner(owner)
     63     , m_contentsDirty(false)
     64     , m_maskLayer(0)
     65     , m_ccLayerImpl(0)
     66     , m_superlayer(0)
     67 #ifndef NDEBUG
     68     , m_debugID(s_nextLayerDebugID++)
     69 #endif
     70     , m_anchorPoint(0.5, 0.5)
     71     , m_backgroundColor(0, 0, 0, 0)
     72     , m_opacity(1.0)
     73     , m_zPosition(0.0)
     74     , m_anchorPointZ(0)
     75     , m_clearsContext(false)
     76     , m_hidden(false)
     77     , m_masksToBounds(false)
     78     , m_opaque(true)
     79     , m_geometryFlipped(false)
     80     , m_needsDisplayOnBoundsChange(false)
     81     , m_doubleSided(true)
     82     , m_replicaLayer(0)
     83 {
     84 }
     85 
     86 LayerChromium::~LayerChromium()
     87 {
     88     // Our superlayer should be holding a reference to us so there should be no
     89     // way for us to be destroyed while we still have a superlayer.
     90     ASSERT(!superlayer());
     91 
     92     if (m_ccLayerImpl)
     93         m_ccLayerImpl->resetOwner();
     94 
     95     // Remove the superlayer reference from all sublayers.
     96     removeAllSublayers();
     97 }
     98 
     99 void LayerChromium::cleanupResources()
    100 {
    101     if (m_ccLayerImpl)
    102         m_ccLayerImpl->cleanupResources();
    103 }
    104 
    105 void LayerChromium::setLayerRenderer(LayerRendererChromium* renderer)
    106 {
    107     // If we're changing layer renderers then we need to free up any resources
    108     // allocated by the old renderer.
    109     if (layerRenderer() && layerRenderer() != renderer) {
    110         cleanupResources();
    111         setNeedsDisplay();
    112     }
    113     m_layerRenderer = renderer;
    114 }
    115 
    116 void LayerChromium::setNeedsCommit()
    117 {
    118     // Call notifySyncRequired(), which for non-root layers plumbs through to
    119     // call setRootLayerNeedsDisplay() on the WebView, which will cause LayerRendererChromium
    120     // to render a frame.
    121     // This function has no effect on root layers.
    122     if (m_owner)
    123         m_owner->notifySyncRequired();
    124 }
    125 
    126 void LayerChromium::addSublayer(PassRefPtr<LayerChromium> sublayer)
    127 {
    128     insertSublayer(sublayer, numSublayers());
    129 }
    130 
    131 void LayerChromium::insertSublayer(PassRefPtr<LayerChromium> sublayer, size_t index)
    132 {
    133     index = min(index, m_sublayers.size());
    134     sublayer->removeFromSuperlayer();
    135     sublayer->setSuperlayer(this);
    136     m_sublayers.insert(index, sublayer);
    137     setNeedsCommit();
    138 }
    139 
    140 void LayerChromium::removeFromSuperlayer()
    141 {
    142     if (m_superlayer)
    143         m_superlayer->removeSublayer(this);
    144 }
    145 
    146 void LayerChromium::removeSublayer(LayerChromium* sublayer)
    147 {
    148     int foundIndex = indexOfSublayer(sublayer);
    149     if (foundIndex == -1)
    150         return;
    151 
    152     sublayer->setSuperlayer(0);
    153     m_sublayers.remove(foundIndex);
    154     setNeedsCommit();
    155 }
    156 
    157 void LayerChromium::replaceSublayer(LayerChromium* reference, PassRefPtr<LayerChromium> newLayer)
    158 {
    159     ASSERT_ARG(reference, reference);
    160     ASSERT_ARG(reference, reference->superlayer() == this);
    161 
    162     if (reference == newLayer)
    163         return;
    164 
    165     int referenceIndex = indexOfSublayer(reference);
    166     if (referenceIndex == -1) {
    167         ASSERT_NOT_REACHED();
    168         return;
    169     }
    170 
    171     reference->removeFromSuperlayer();
    172 
    173     if (newLayer) {
    174         newLayer->removeFromSuperlayer();
    175         insertSublayer(newLayer, referenceIndex);
    176     }
    177 }
    178 
    179 int LayerChromium::indexOfSublayer(const LayerChromium* reference)
    180 {
    181     for (size_t i = 0; i < m_sublayers.size(); i++) {
    182         if (m_sublayers[i] == reference)
    183             return i;
    184     }
    185     return -1;
    186 }
    187 
    188 void LayerChromium::setBounds(const IntSize& size)
    189 {
    190     if (bounds() == size)
    191         return;
    192 
    193     bool firstResize = !bounds().width() && !bounds().height() && size.width() && size.height();
    194 
    195     m_bounds = size;
    196 
    197     if (firstResize)
    198         setNeedsDisplay(FloatRect(0, 0, bounds().width(), bounds().height()));
    199     else
    200         setNeedsCommit();
    201 }
    202 
    203 void LayerChromium::setFrame(const FloatRect& rect)
    204 {
    205     if (rect == m_frame)
    206       return;
    207 
    208     m_frame = rect;
    209     setNeedsDisplay(FloatRect(0, 0, bounds().width(), bounds().height()));
    210 }
    211 
    212 const LayerChromium* LayerChromium::rootLayer() const
    213 {
    214     const LayerChromium* layer = this;
    215     for (LayerChromium* superlayer = layer->superlayer(); superlayer; layer = superlayer, superlayer = superlayer->superlayer()) { }
    216     return layer;
    217 }
    218 
    219 void LayerChromium::removeAllSublayers()
    220 {
    221     while (m_sublayers.size()) {
    222         LayerChromium* layer = m_sublayers[0].get();
    223         ASSERT(layer->superlayer());
    224         layer->removeFromSuperlayer();
    225     }
    226 }
    227 
    228 void LayerChromium::setSublayers(const Vector<RefPtr<LayerChromium> >& sublayers)
    229 {
    230     if (sublayers == m_sublayers)
    231         return;
    232 
    233     removeAllSublayers();
    234     size_t listSize = sublayers.size();
    235     for (size_t i = 0; i < listSize; i++)
    236         addSublayer(sublayers[i]);
    237 }
    238 
    239 LayerChromium* LayerChromium::superlayer() const
    240 {
    241     return m_superlayer;
    242 }
    243 
    244 void LayerChromium::setName(const String& name)
    245 {
    246     m_name = name;
    247 }
    248 
    249 void LayerChromium::setNeedsDisplay(const FloatRect& dirtyRect)
    250 {
    251     // Simply mark the contents as dirty. For non-root layers, the call to
    252     // setNeedsCommit will schedule a fresh compositing pass.
    253     // For the root layer, setNeedsCommit has no effect.
    254     m_contentsDirty = true;
    255 
    256     m_dirtyRect.unite(dirtyRect);
    257     setNeedsCommit();
    258 }
    259 
    260 void LayerChromium::setNeedsDisplay()
    261 {
    262     m_dirtyRect.setLocation(FloatPoint());
    263     m_dirtyRect.setSize(bounds());
    264     m_contentsDirty = true;
    265     setNeedsCommit();
    266 }
    267 
    268 void LayerChromium::resetNeedsDisplay()
    269 {
    270     m_dirtyRect = FloatRect();
    271     m_contentsDirty = false;
    272 }
    273 
    274 void LayerChromium::toGLMatrix(float* flattened, const TransformationMatrix& m)
    275 {
    276     flattened[0] = m.m11();
    277     flattened[1] = m.m12();
    278     flattened[2] = m.m13();
    279     flattened[3] = m.m14();
    280     flattened[4] = m.m21();
    281     flattened[5] = m.m22();
    282     flattened[6] = m.m23();
    283     flattened[7] = m.m24();
    284     flattened[8] = m.m31();
    285     flattened[9] = m.m32();
    286     flattened[10] = m.m33();
    287     flattened[11] = m.m34();
    288     flattened[12] = m.m41();
    289     flattened[13] = m.m42();
    290     flattened[14] = m.m43();
    291     flattened[15] = m.m44();
    292 }
    293 
    294 void LayerChromium::pushPropertiesTo(CCLayerImpl* layer)
    295 {
    296     layer->setAnchorPoint(m_anchorPoint);
    297     layer->setAnchorPointZ(m_anchorPointZ);
    298     layer->setBounds(m_bounds);
    299     layer->setDebugBorderColor(m_debugBorderColor);
    300     layer->setDebugBorderWidth(m_debugBorderWidth);
    301     layer->setDoubleSided(m_doubleSided);
    302     layer->setLayerRenderer(m_layerRenderer.get());
    303     layer->setMasksToBounds(m_masksToBounds);
    304     layer->setName(m_name);
    305     layer->setOpacity(m_opacity);
    306     layer->setPosition(m_position);
    307     layer->setPreserves3D(preserves3D());
    308     layer->setSublayerTransform(m_sublayerTransform);
    309     layer->setTransform(m_transform);
    310 
    311     if (maskLayer())
    312         maskLayer()->pushPropertiesTo(layer->maskLayer());
    313     if (replicaLayer())
    314         replicaLayer()->pushPropertiesTo(layer->replicaLayer());
    315 }
    316 
    317 GraphicsContext3D* LayerChromium::layerRendererContext() const
    318 {
    319     ASSERT(layerRenderer());
    320     return layerRenderer()->context();
    321 }
    322 
    323 void LayerChromium::drawTexturedQuad(GraphicsContext3D* context, const TransformationMatrix& projectionMatrix, const TransformationMatrix& drawMatrix,
    324                                      float width, float height, float opacity,
    325                                      int matrixLocation, int alphaLocation)
    326 {
    327     static float glMatrix[16];
    328 
    329     TransformationMatrix renderMatrix = drawMatrix;
    330 
    331     // Apply a scaling factor to size the quad from 1x1 to its intended size.
    332     renderMatrix.scale3d(width, height, 1);
    333 
    334     // Apply the projection matrix before sending the transform over to the shader.
    335     toGLMatrix(&glMatrix[0], projectionMatrix * renderMatrix);
    336 
    337     GLC(context, context->uniformMatrix4fv(matrixLocation, false, &glMatrix[0], 1));
    338 
    339     if (alphaLocation != -1)
    340         GLC(context, context->uniform1f(alphaLocation, opacity));
    341 
    342     GLC(context, context->drawElements(GraphicsContext3D::TRIANGLES, 6, GraphicsContext3D::UNSIGNED_SHORT, 0));
    343 }
    344 
    345 String LayerChromium::layerTreeAsText() const
    346 {
    347     TextStream ts;
    348     dumpLayer(ts, 0);
    349     return ts.release();
    350 }
    351 
    352 static void writeIndent(TextStream& ts, int indent)
    353 {
    354     for (int i = 0; i != indent; ++i)
    355         ts << "  ";
    356 }
    357 
    358 void LayerChromium::dumpLayer(TextStream& ts, int indent) const
    359 {
    360     writeIndent(ts, indent);
    361     ts << layerTypeAsString() << "(" << m_name << ")\n";
    362     dumpLayerProperties(ts, indent+2);
    363     if (m_ccLayerImpl)
    364         m_ccLayerImpl->dumpLayerProperties(ts, indent+2);
    365     if (m_replicaLayer) {
    366         writeIndent(ts, indent+2);
    367         ts << "Replica:\n";
    368         m_replicaLayer->dumpLayer(ts, indent+3);
    369     }
    370     if (m_maskLayer) {
    371         writeIndent(ts, indent+2);
    372         ts << "Mask:\n";
    373         m_maskLayer->dumpLayer(ts, indent+3);
    374     }
    375     for (size_t i = 0; i < m_sublayers.size(); ++i)
    376         m_sublayers[i]->dumpLayer(ts, indent+1);
    377 }
    378 
    379 void LayerChromium::dumpLayerProperties(TextStream& ts, int indent) const
    380 {
    381     writeIndent(ts, indent);
    382 #ifndef NDEBUG
    383     ts << "debugID: " << debugID() << ", ";
    384 #else
    385 #endif
    386     ts << "drawsContent: " << drawsContent() << "\n";
    387 
    388 }
    389 
    390 PassRefPtr<CCLayerImpl> LayerChromium::createCCLayerImpl()
    391 {
    392     return CCLayerImpl::create(this);
    393 }
    394 
    395 void LayerChromium::createCCLayerImplIfNeeded()
    396 {
    397     if (!m_ccLayerImpl)
    398         m_ccLayerImpl = createCCLayerImpl();
    399 }
    400 
    401 CCLayerImpl* LayerChromium::ccLayerImpl()
    402 {
    403     return m_ccLayerImpl.get();
    404 }
    405 
    406 void LayerChromium::setBorderColor(const Color& color)
    407 {
    408     m_debugBorderColor = color;
    409     setNeedsCommit();
    410 }
    411 
    412 void LayerChromium::setBorderWidth(float width)
    413 {
    414     m_debugBorderWidth = width;
    415     setNeedsCommit();
    416 }
    417 
    418 LayerRendererChromium* LayerChromium::layerRenderer() const
    419 {
    420     return m_layerRenderer.get();
    421 }
    422 
    423 }
    424 #endif // USE(ACCELERATED_COMPOSITING)
    425