Home | History | Annotate | Download | only in qt
      1 /*
      2  * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions
      6  * are met:
      7  * 1. Redistributions of source code must retain the above copyright
      8  *    notice, this list of conditions and the following disclaimer.
      9  * 2. Redistributions in binary form must reproduce the above copyright
     10  *    notice, this list of conditions and the following disclaimer in the
     11  *    documentation and/or other materials provided with the distribution.
     12  *
     13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
     14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
     17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
     23  * THE POSSIBILITY OF SUCH DAMAGE.
     24  */
     25 
     26 #include "config.h"
     27 #include "TiledDrawingAreaTile.h"
     28 
     29 #if ENABLE(TILED_BACKING_STORE)
     30 
     31 #include "GraphicsContext.h"
     32 #include "TiledDrawingAreaProxy.h"
     33 #include "WebPageProxy.h"
     34 #include "WebProcessProxy.h"
     35 #include "UpdateChunk.h"
     36 #include <QApplication>
     37 #include <QObject>
     38 #include <QPainter>
     39 
     40 using namespace WebCore;
     41 
     42 namespace WebKit {
     43 
     44 TiledDrawingAreaTile::TiledDrawingAreaTile(TiledDrawingAreaProxy* proxy, const Coordinate& tileCoordinate)
     45     : m_proxy(proxy)
     46     , m_coordinate(tileCoordinate)
     47     , m_rect(proxy->tileRectForCoordinate(tileCoordinate))
     48     , m_hasUpdatePending(false)
     49     , m_dirtyRegion(m_rect)
     50 {
     51     static int id = 0;
     52     m_ID = ++id;
     53 #ifdef TILE_DEBUG_LOG
     54     qDebug() << "deleting tile id=" << m_ID;
     55 #endif
     56 }
     57 
     58 TiledDrawingAreaTile::~TiledDrawingAreaTile()
     59 {
     60 #ifdef TILE_DEBUG_LOG
     61     qDebug() << "deleting tile id=" << m_ID;
     62 #endif
     63 }
     64 
     65 bool TiledDrawingAreaTile::isDirty() const
     66 {
     67     return !m_dirtyRegion.isEmpty();
     68 }
     69 
     70 bool TiledDrawingAreaTile::isReadyToPaint() const
     71 {
     72     return !m_buffer.isNull();
     73 }
     74 
     75 bool TiledDrawingAreaTile::hasReadyBackBuffer() const
     76 {
     77     return !m_backBuffer.isNull() && !m_hasUpdatePending;
     78 }
     79 
     80 void TiledDrawingAreaTile::invalidate(const IntRect& dirtyRect)
     81 {
     82     IntRect tileDirtyRect = intersection(dirtyRect, m_rect);
     83     if (tileDirtyRect.isEmpty())
     84         return;
     85 
     86     m_dirtyRegion += tileDirtyRect;
     87 }
     88 
     89 void TiledDrawingAreaTile::resize(const IntSize& newSize)
     90 {
     91     IntRect oldRect = m_rect;
     92     m_rect = IntRect(m_rect.location(), newSize);
     93     if (m_rect.maxX() > oldRect.maxX())
     94         invalidate(IntRect(oldRect.maxX(), oldRect.y(), m_rect.maxX() - oldRect.maxX(), m_rect.height()));
     95     if (m_rect.maxY() > oldRect.maxY())
     96         invalidate(IntRect(oldRect.x(), oldRect.maxY(), m_rect.width(), m_rect.maxY() - oldRect.maxY()));
     97 }
     98 
     99 void TiledDrawingAreaTile::swapBackBufferToFront()
    100 {
    101     ASSERT(!m_backBuffer.isNull());
    102 
    103     m_buffer = m_backBuffer;
    104     m_backBuffer = QPixmap();
    105 }
    106 
    107 void TiledDrawingAreaTile::paint(GraphicsContext* context, const IntRect& rect)
    108 {
    109     ASSERT(!m_buffer.isNull());
    110 
    111     IntRect target = intersection(rect, m_rect);
    112     IntRect source((target.x() - m_rect.x()),
    113                    (target.y() - m_rect.y()),
    114                    target.width(),
    115                    target.height());
    116 
    117     context->platformContext()->drawPixmap(target, m_buffer, source);
    118 }
    119 
    120 void TiledDrawingAreaTile::updateFromChunk(UpdateChunk* updateChunk, float)
    121 {
    122     QImage image(updateChunk->createImage());
    123     const IntRect& updateChunkRect = updateChunk->rect();
    124 
    125 #ifdef TILE_DEBUG_LOG
    126     qDebug() << "tile updated id=" << ID() << " rect=" << QRect(updateChunkRect);
    127 #endif
    128     if (updateChunkRect.size() == m_proxy->tileSize()) {
    129         // Make a deep copy of the image since it's in shared memory.
    130         m_backBuffer = QPixmap::fromImage(image.copy());
    131     } else {
    132         if (m_backBuffer.isNull())
    133             m_backBuffer = m_buffer.isNull() ? QPixmap(m_proxy->tileSize()) : m_buffer;
    134         QPainter painter(&m_backBuffer);
    135         IntSize drawPoint = updateChunkRect.location() - m_rect.location();
    136         painter.drawImage(QPoint(drawPoint.width(), drawPoint.height()), image);
    137     }
    138     m_hasUpdatePending = false;
    139 }
    140 
    141 void TiledDrawingAreaTile::updateBackBuffer()
    142 {
    143     if (isReadyToPaint() && !isDirty())
    144         return;
    145 
    146     // FIXME: individual rects
    147     IntRect dirtyRect = m_dirtyRegion.boundingRect();
    148     m_dirtyRegion = QRegion();
    149 
    150 #ifdef TILE_DEBUG_LOG
    151     qDebug() << "requesting tile update id=" << m_ID << " rect=" << QRect(dirtyRect) << " scale=" << m_proxy->contentsScale();
    152 #endif
    153     if (!m_proxy->page()->process()->isValid())
    154         return;
    155     m_proxy->requestTileUpdate(m_ID, dirtyRect);
    156 
    157     m_hasUpdatePending = true;
    158 }
    159 
    160 }
    161 #endif
    162