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