https://bugs.webkit.org/show_bug.cgi?id=83424
Source/WebCore:
Modify BitmapTexture::updateContents to include a source offset.
This allows us to update a texture from a sub-image.
Reviewed by Kenneth Rohde Christiansen.
Tested by existing API tests.
* platform/graphics/texmap/TextureMapper.h:
(BitmapTexture):
* platform/graphics/texmap/TextureMapperGL.cpp:
(WebCore::BitmapTextureGL::didReset):
(WebCore::driverSupportsBGRASwizzling):
(WebCore::BitmapTextureGL::updateContents):
* platform/graphics/texmap/TextureMapperGL.h:
(WebCore::BitmapTextureGL::textureTarget):
(BitmapTextureGL):
* platform/graphics/texmap/TextureMapperImageBuffer.cpp:
(WebCore::BitmapTextureImageBuffer::updateContents):
* platform/graphics/texmap/TextureMapperImageBuffer.h:
(BitmapTextureImageBuffer):
Source/WebKit2:
Reviewed by Kenneth Rohde Christiansen.
Enabled creating a GraphicsContext that references a rect inside ShareableBitmap.
Added bitmapOffset to UpdateInfo, to allow updates to reference an offset inside the bitmap.
Added UpdateAtlas, a class that manages available rects in a larger ShareableBitmap.
In this iteration, UpdateAtlas has a simple behavior where a rect inside the bitmap is
either available or used. When the buffers are swapped, all used buffers become available
again. A future enhancement might allow triple-buffering, where available rects can be
updated while other rects from the same atlas are in use.
Added the necessary plumbing to allow Qt's UI-side compositing to take advantage of
UpdateAtlas. LayerTreeHostQt creates an atlas per type of bitmap (i.e. one opaque and one
alpha-enabled atlas). When a tile wants to update and there's no available scratch-buffer,
the update would be postponed to the next frame, creating a tiling-artifact in low memory
situations.
* Shared/UpdateInfo.cpp:
(WebKit::UpdateInfo::encode):
(WebKit::UpdateInfo::decode):
* Shared/UpdateInfo.h:
(UpdateInfo):
* Target.pri:
* UIProcess/LayerTreeHostProxy.cpp:
(WebKit::LayerTreeHostProxy::updateTileForLayer):
* UIProcess/WebLayerTreeRenderer.cpp:
(WebKit::WebLayerTreeRenderer::syncLayerParameters):
(WebKit::WebLayerTreeRenderer::updateTile):
(WebKit::WebLayerTreeRenderer::createImage):
* UIProcess/WebLayerTreeRenderer.h:
(TileUpdate):
(WebKit::WebLayerTreeRenderer::TileUpdate::TileUpdate):
(WebLayerTreeRenderer):
* UIProcess/qt/LayerBackingStore.cpp:
(WebKit::LayerBackingStoreTile::swapBuffers):
(WebKit::LayerBackingStoreTile::setBackBuffer):
(WebKit::LayerBackingStore::createTile):
* UIProcess/qt/LayerBackingStore.h:
(LayerBackingStoreTile):
(LayerBackingStore):
* WebProcess/WebCoreSupport/WebGraphicsLayer.cpp:
(WebCore::WebGraphicsLayer::tiledBackingStoreBackgroundColor):
(WebCore::WebGraphicsLayer::beginContentUpdate):
(WebCore):
* WebProcess/WebCoreSupport/WebGraphicsLayer.h:
(WebGraphicsLayerClient):
(WebGraphicsLayer):
* WebProcess/WebPage/TiledBackingStoreRemoteTile.cpp:
(WebKit::TiledBackingStoreRemoteTile::updateBackBuffer):
* WebProcess/WebPage/TiledBackingStoreRemoteTile.h:
(TiledBackingStoreRemoteTileClient):
* WebProcess/WebPage/UpdateAtlas.cpp: Added.
(WebKit):
(WebKit::UpdateAtlas::UpdateAtlas):
(WebKit::nextPowerOfTwo):
(WebKit::UpdateAtlas::buildLayoutIfNeeded):
(WebKit::UpdateAtlas::findAvailableIndex):
(WebKit::UpdateAtlas::didSwapBuffers):
(WebKit::UpdateAtlas::acquireScratchBuffer):
(WebKit::UpdateAtlas::offsetForIndex):
* WebProcess/WebPage/UpdateAtlas.h: Added.
(WebCore):
(WebKit):
(UpdateAtlas):
(WebKit::UpdateAtlas::bitmap):
(WebKit::UpdateAtlas::size):
(WebKit::UpdateAtlas::flags):
* WebProcess/WebPage/qt/LayerTreeHostQt.cpp:
(WebKit::LayerTreeHostQt::adoptImageBackingStore):
(WebKit::LayerTreeHostQt::renderNextFrame):
(WebKit::LayerTreeHostQt::purgeBackingStores):
(WebKit):
(WebKit::LayerTreeHostQt::getAtlas):
(WebKit::LayerTreeHostQt::beginContentUpdate):
* WebProcess/WebPage/qt/LayerTreeHostQt.h:
(LayerTreeHostQt):
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@113678
268f45cc-cd09-0410-ab3c-
d52691b4dbfc
+2012-04-09 No'am Rosenthal <noam.rosenthal@nokia.com>
+
+ [WK2] Enable using a single ShareableBitmap for multiple updates
+ https://bugs.webkit.org/show_bug.cgi?id=83424
+
+ Modify BitmapTexture::updateContents to include a source offset.
+ This allows us to update a texture from a sub-image.
+
+ Reviewed by Kenneth Rohde Christiansen.
+
+ Tested by existing API tests.
+
+ * platform/graphics/texmap/TextureMapper.h:
+ (BitmapTexture):
+ * platform/graphics/texmap/TextureMapperGL.cpp:
+ (WebCore::BitmapTextureGL::didReset):
+ (WebCore::driverSupportsBGRASwizzling):
+ (WebCore::BitmapTextureGL::updateContents):
+ * platform/graphics/texmap/TextureMapperGL.h:
+ (WebCore::BitmapTextureGL::textureTarget):
+ (BitmapTextureGL):
+ * platform/graphics/texmap/TextureMapperImageBuffer.cpp:
+ (WebCore::BitmapTextureImageBuffer::updateContents):
+ * platform/graphics/texmap/TextureMapperImageBuffer.h:
+ (BitmapTextureImageBuffer):
+
2012-04-09 Dana Jansens <danakj@chromium.org>
[chromium] Viewport is not filled when out of texture memory on mac
// A 2D texture that can be the target of software or GL rendering.
class BitmapTexture : public RefCounted<BitmapTexture> {
public:
- enum PixelFormat { BGRAFormat, RGBAFormat, BGRFormat, RGBFormat };
enum Flag {
SupportsAlpha = 0x01
};
virtual ~BitmapTexture() { }
virtual IntSize size() const = 0;
- virtual void updateContents(Image*, const IntRect&, const IntRect&, BitmapTexture::PixelFormat) = 0;
- virtual void updateContents(const void*, const IntRect&) = 0;
+ virtual void updateContents(Image*, const IntRect&, const IntPoint& offset) = 0;
+ virtual void updateContents(const void*, const IntRect& target, const IntPoint& offset, int bytesPerLine) = 0;
virtual bool isValid() const = 0;
inline Flags flags() const { return m_flags; }
namespace WebCore {
-void TextureMapperTile::updateContents(TextureMapper* textureMapper, Image* image, const IntRect& dirtyRect, BitmapTexture::PixelFormat format)
+void TextureMapperTile::updateContents(TextureMapper* textureMapper, Image* image, const IntRect& dirtyRect)
{
IntRect targetRect = enclosingIntRect(m_rect);
targetRect.intersect(dirtyRect);
if (targetRect.isEmpty())
return;
- IntRect sourceRect = targetRect;
+ IntPoint sourceOffset = targetRect.location();
// Normalize sourceRect to the buffer's coordinates.
- sourceRect.move(-dirtyRect.x(), -dirtyRect.y());
+ sourceOffset.move(-dirtyRect.x(), -dirtyRect.y());
// Normalize targetRect to the texture's coordinates.
targetRect.move(-m_rect.x(), -m_rect.y());
m_texture->reset(targetRect.size(), image->currentFrameHasAlpha() ? BitmapTexture::SupportsAlpha : 0);
}
- m_texture->updateContents(image, targetRect, sourceRect, format);
+ m_texture->updateContents(image, targetRect, sourceOffset);
}
void TextureMapperTile::paint(TextureMapper* textureMapper, const TransformationMatrix& transform, float opacity, BitmapTexture* mask)
if (!m_image)
return;
- updateContents(textureMapper, m_image.get(), m_image->currentFrameHasAlpha() ? BitmapTexture::BGRAFormat : BitmapTexture::BGRFormat);
+ updateContents(textureMapper, m_image.get());
m_image.clear();
}
m_tiles.remove(tileIndicesToRemove[i]);
}
-void TextureMapperTiledBackingStore::updateContents(TextureMapper* textureMapper, Image* image, const FloatSize& totalSize, const IntRect& dirtyRect, BitmapTexture::PixelFormat format)
+void TextureMapperTiledBackingStore::updateContents(TextureMapper* textureMapper, Image* image, const FloatSize& totalSize, const IntRect& dirtyRect)
{
createOrDestroyTilesIfNeeded(totalSize, textureMapper->maxTextureSize(), image->currentFrameHasAlpha());
for (size_t i = 0; i < m_tiles.size(); ++i)
- m_tiles[i].updateContents(textureMapper, image, dirtyRect, format);
+ m_tiles[i].updateContents(textureMapper, image, dirtyRect);
}
PassRefPtr<BitmapTexture> TextureMapperTiledBackingStore::texture() const
inline void setTexture(BitmapTexture* texture) { m_texture = texture; }
inline void setRect(const FloatRect& rect) { m_rect = rect; }
- void updateContents(TextureMapper*, Image*, const IntRect&, BitmapTexture::PixelFormat);
+ void updateContents(TextureMapper*, Image*, const IntRect&);
virtual void paint(TextureMapper*, const TransformationMatrix&, float, BitmapTexture*);
virtual ~TextureMapperTile() { }
virtual ~TextureMapperTiledBackingStore() { }
virtual void paintToTextureMapper(TextureMapper*, const FloatRect&, const TransformationMatrix&, float, BitmapTexture*);
virtual PassRefPtr<BitmapTexture> texture() const;
- void updateContents(TextureMapper*, Image*, const FloatSize&, const IntRect&, BitmapTexture::PixelFormat);
- void updateContents(TextureMapper* textureMapper, Image* image, BitmapTexture::PixelFormat format) { updateContents(textureMapper, image, image->size(), image->rect(), format); }
+ void updateContents(TextureMapper*, Image*, const FloatSize&, const IntRect&);
+ void updateContents(TextureMapper* textureMapper, Image* image) { updateContents(textureMapper, image, image->size(), image->rect()); }
inline FloatRect rect() const { return FloatRect(FloatPoint::zero(), m_size); }
static PassRefPtr<TextureMapperTiledBackingStore> create() { return adoptRef(new TextureMapperTiledBackingStore); }
void setContentsToImage(Image* image) { m_image = image; }
m_surfaceNeedsReset = true;
}
-static void swizzleBGRAToRGBA(uint32_t* data, const IntSize& size)
+static void swizzleBGRAToRGBA(uint32_t* data, const IntSize& size, int stride = 0)
{
int width = size.width();
int height = size.height();
+ stride = stride | width;
for (int y = 0; y < height; ++y) {
- uint32_t* p = data + y * width;
+ uint32_t* p = data + y * stride;
for (int x = 0; x < width; ++x)
p[x] = ((p[x] << 16) & 0xff0000) | ((p[x] >> 16) & 0xff) | (p[x] & 0xff00ff00);
}
#endif
}
-void BitmapTextureGL::updateContents(const void* data, const IntRect& targetRect)
+static bool driverSupportsSubImage()
+{
+#if defined(TEXMAP_OPENGL_ES_2)
+ // FIXME: Implement reliable detection.
+ return false;
+#else
+ return true;
+#endif
+}
+
+void BitmapTextureGL::updateContents(const void* data, const IntRect& targetRect, const IntPoint& sourceOffset, int bytesPerLine)
{
GLuint glFormat = GL_RGBA;
GL_CMD(glBindTexture(GL_TEXTURE_2D, m_id))
+
if (driverSupportsBGRASwizzling())
glFormat = GL_BGRA;
- else {
- swizzleBGRAToRGBA(static_cast<uint32_t*>(const_cast<void*>(data)), targetRect.size());
- glFormat = GL_RGBA;
+ else
+ swizzleBGRAToRGBA(static_cast<uint32_t*>(const_cast<void*>(data)), targetRect.size(), bytesPerLine / 4);
+
+ if (bytesPerLine == targetRect.width() / 4 && sourceOffset == IntPoint::zero()) {
+ GL_CMD(glTexSubImage2D(GL_TEXTURE_2D, 0, targetRect.x(), targetRect.y(), targetRect.width(), targetRect.height(), glFormat, GL_UNSIGNED_BYTE, (const char*)data))
+ return;
+ }
+
+ // For ES drivers that don't support sub-images, transfer the pixels row-by-row.
+ if (!driverSupportsSubImage()) {
+ const char* bits = static_cast<const char*>(data);
+ for (int y = 0; y < targetRect.height(); ++y) {
+ const char *row = bits + ((sourceOffset.y() + y) * bytesPerLine + sourceOffset.x() * 4);
+ GL_CMD(glTexSubImage2D(GL_TEXTURE_2D, 0, targetRect.x(), targetRect.y() + y, targetRect.width(), 1, glFormat, GL_UNSIGNED_BYTE, row))
+ }
+ return;
}
- GL_CMD(glTexSubImage2D(GL_TEXTURE_2D, 0, targetRect.x(), targetRect.y(), targetRect.width(), targetRect.height(), glFormat, GL_UNSIGNED_BYTE, data))
+ // Use the OpenGL sub-image extension, now that we know it's available.
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, bytesPerLine / 4);
+ glPixelStorei(GL_UNPACK_SKIP_ROWS, sourceOffset.y());
+ glPixelStorei(GL_UNPACK_SKIP_PIXELS, sourceOffset.x());
+ GL_CMD(glTexSubImage2D(GL_TEXTURE_2D, 0, targetRect.x(), targetRect.y(), targetRect.width(), targetRect.height(), glFormat, GL_UNSIGNED_BYTE, (const char*)data))
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
+ glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
+ glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
}
-void BitmapTextureGL::updateContents(Image* image, const IntRect& targetRect, const IntRect& sourceRect, BitmapTexture::PixelFormat format)
+void BitmapTextureGL::updateContents(Image* image, const IntRect& targetRect, const IntPoint& offset)
{
if (!image)
return;
- GL_CMD(glBindTexture(GL_TEXTURE_2D, m_id))
- GLuint glFormat = isOpaque() ? GL_RGB : GL_RGBA;
NativeImagePtr frameImage = image->nativeImageForCurrentFrame();
if (!frameImage)
return;
+ int bytesPerLine;
+ const char* imageData;
+
#if PLATFORM(QT)
QImage qtImage;
-
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
// With QPA, we can avoid a deep copy.
qtImage = *frameImage->handle()->buffer();
// This might be a deep copy, depending on other references to the pixmap.
qtImage = frameImage->toImage();
#endif
-
- if (IntSize(qtImage.size()) != sourceRect.size())
- qtImage = qtImage.copy(sourceRect);
- if (format == BGRAFormat || format == BGRFormat) {
- if (driverSupportsBGRASwizzling())
- glFormat = isOpaque() ? GL_BGR : GL_BGRA;
- else
- swizzleBGRAToRGBA(reinterpret_cast<uint32_t*>(qtImage.bits()), qtImage.size());
- }
- GL_CMD(glTexSubImage2D(GL_TEXTURE_2D, 0, targetRect.x(), targetRect.y(), targetRect.width(), targetRect.height(), glFormat, GL_UNSIGNED_BYTE, qtImage.constBits()))
-
+ imageData = reinterpret_cast<const char*>(qtImage.constBits());
+ bytesPerLine = qtImage.bytesPerLine();
#elif USE(CAIRO)
-
-#if !CPU(BIG_ENDIAN)
-#if defined(TEXMAP_OPENGL_ES_2)
- swizzleBGRAToRGBA(reinterpret_cast<uint32_t*>(cairo_image_surface_get_data(frameImage)),
- cairo_image_surface_get_stride(frameImage) * cairo_image_surface_get_height(frameImage));
-#else
- glFormat = isOpaque() ? GL_BGR : GL_BGRA;
-#endif
+ imageData = cairo_image_surface_get_data(frameImage);
+ bytesPerLine = cairo_image_surface_get_stride(frameImage);
#endif
- glPixelStorei(GL_UNPACK_ROW_LENGTH, cairo_image_surface_get_stride(frameImage) / 4);
- glPixelStorei(GL_UNPACK_SKIP_ROWS, sourceRect.y());
- glPixelStorei(GL_UNPACK_SKIP_PIXELS, sourceRect.x());
- GL_CMD(glTexSubImage2D(GL_TEXTURE_2D, 0,
- targetRect.x(), targetRect.y(),
- targetRect.width(), targetRect.height(),
- glFormat, GL_UNSIGNED_BYTE,
- cairo_image_surface_get_data(frameImage)));
- glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
- glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
- glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
-#endif
+ updateContents(imageData, targetRect, offset, bytesPerLine);
+
}
static inline TransformationMatrix createProjectionMatrix(const IntSize& size, bool flip)
void setGraphicsContext(GraphicsContext* context) { m_context = context; }
GraphicsContext* graphicsContext() { return m_context; }
virtual bool isOpenGLBacked() const { return true; }
- void platformUpdateContents(NativeImagePtr, const IntRect&, const IntRect&, BitmapTexture::PixelFormat);
+ void platformUpdateContents(NativeImagePtr, const IntRect&, const IntRect&);
virtual AccelerationMode accelerationMode() const { return OpenGLMode; }
private:
void initializeStencil();
~BitmapTextureGL();
virtual uint32_t id() const { return m_id; }
+ uint32_t textureTarget() const { return GL_TEXTURE_2D; }
IntSize textureSize() const { return m_textureSize; }
void setTextureMapper(TextureMapperGL* texmap) { m_textureMapper = texmap; }
- void updateContents(Image*, const IntRect&, const IntRect&, PixelFormat);
- void updateContents(const void*, const IntRect&);
+ void updateContents(Image*, const IntRect&, const IntPoint&);
+ virtual void updateContents(const void*, const IntRect& target, const IntPoint& sourceOffset, int bytesPerLine);
private:
GLuint m_id;
#if USE(TEXTURE_MAPPER)
namespace WebCore {
-void BitmapTextureImageBuffer::updateContents(const void* data, const IntRect& targetRect)
+void BitmapTextureImageBuffer::updateContents(const void* data, const IntRect& targetRect, const IntPoint& sourceOffset, int bytesPerLine)
{
#if PLATFORM(QT)
- QImage image(reinterpret_cast<const uchar*>(data), targetRect.width(), targetRect.height(), targetRect.width() * 4, QImage::Format_ARGB32_Premultiplied);
+ QImage image(reinterpret_cast<const uchar*>(data), targetRect.width(), targetRect.height(), bytesPerLine, QImage::Format_ARGB32_Premultiplied);
+
QPainter* painter = m_image->context()->platformContext();
painter->save();
painter->setCompositionMode(QPainter::CompositionMode_Source);
- painter->drawImage(targetRect, image);
+ painter->drawImage(targetRect, image, IntRect(sourceOffset, targetRect.size()));
painter->restore();
#endif
}
m_image = ImageBuffer::create(contentSize());
}
-void BitmapTextureImageBuffer::updateContents(Image* image, const IntRect& targetRect, const IntRect& sourceRect, PixelFormat)
+void BitmapTextureImageBuffer::updateContents(Image* image, const IntRect& targetRect, const IntPoint& offset)
{
- m_image->context()->drawImage(image, ColorSpaceDeviceRGB, targetRect, sourceRect, CompositeCopy);
+ m_image->context()->drawImage(image, ColorSpaceDeviceRGB, targetRect, IntRect(offset, targetRect.size()), CompositeCopy);
}
void TextureMapperImageBuffer::beginClip(const TransformationMatrix& matrix, const FloatRect& rect)
virtual void didReset();
virtual bool isValid() const { return m_image; }
inline GraphicsContext* graphicsContext() { return m_image ? m_image->context() : 0; }
- virtual void updateContents(Image*, const IntRect&, const IntRect&, PixelFormat);
- void updateContents(const void* data, const IntRect& targetRect);
+ virtual void updateContents(Image*, const IntRect&, const IntPoint&);
+ virtual void updateContents(const void*, const IntRect& target, const IntPoint& sourceOffset, int bytesPerLine);
#if ENABLE(CSS_FILTERS)
void applyFilters(const BitmapTexture&, const FilterOperations&);
#endif
image = imageBuffer->copyImage(CopyBackingStore);
#endif
- static_cast<TextureMapperTiledBackingStore*>(m_backingStore.get())->updateContents(textureMapper, image.get(), m_size, dirtyRect, BitmapTexture::BGRAFormat);
+ static_cast<TextureMapperTiledBackingStore*>(m_backingStore.get())->updateContents(textureMapper, image.get(), m_size, dirtyRect);
}
void TextureMapperLayer::paint()
2012-04-09 No'am Rosenthal <noam.rosenthal@nokia.com>
+ [WK2] Enable using a single ShareableBitmap for multiple updates
+ https://bugs.webkit.org/show_bug.cgi?id=83424
+
+ Reviewed by Kenneth Rohde Christiansen.
+
+ Enabled creating a GraphicsContext that references a rect inside ShareableBitmap.
+ Added bitmapOffset to UpdateInfo, to allow updates to reference an offset inside the bitmap.
+ Added UpdateAtlas, a class that manages available rects in a larger ShareableBitmap.
+
+ In this iteration, UpdateAtlas has a simple behavior where a rect inside the bitmap is
+ either available or used. When the buffers are swapped, all used buffers become available
+ again. A future enhancement might allow triple-buffering, where available rects can be
+ updated while other rects from the same atlas are in use.
+
+ Added the necessary plumbing to allow Qt's UI-side compositing to take advantage of
+ UpdateAtlas. LayerTreeHostQt creates an atlas per type of bitmap (i.e. one opaque and one
+ alpha-enabled atlas). When a tile wants to update and there's no available scratch-buffer,
+ the update would be postponed to the next frame, creating a tiling-artifact in low memory
+ situations.
+
+ * Shared/UpdateInfo.cpp:
+ (WebKit::UpdateInfo::encode):
+ (WebKit::UpdateInfo::decode):
+ * Shared/UpdateInfo.h:
+ (UpdateInfo):
+ * Target.pri:
+ * UIProcess/LayerTreeHostProxy.cpp:
+ (WebKit::LayerTreeHostProxy::updateTileForLayer):
+ * UIProcess/WebLayerTreeRenderer.cpp:
+ (WebKit::WebLayerTreeRenderer::syncLayerParameters):
+ (WebKit::WebLayerTreeRenderer::updateTile):
+ (WebKit::WebLayerTreeRenderer::createImage):
+ * UIProcess/WebLayerTreeRenderer.h:
+ (TileUpdate):
+ (WebKit::WebLayerTreeRenderer::TileUpdate::TileUpdate):
+ (WebLayerTreeRenderer):
+ * UIProcess/qt/LayerBackingStore.cpp:
+ (WebKit::LayerBackingStoreTile::swapBuffers):
+ (WebKit::LayerBackingStoreTile::setBackBuffer):
+ (WebKit::LayerBackingStore::createTile):
+ * UIProcess/qt/LayerBackingStore.h:
+ (LayerBackingStoreTile):
+ (LayerBackingStore):
+ * WebProcess/WebCoreSupport/WebGraphicsLayer.cpp:
+ (WebCore::WebGraphicsLayer::tiledBackingStoreBackgroundColor):
+ (WebCore::WebGraphicsLayer::beginContentUpdate):
+ (WebCore):
+ * WebProcess/WebCoreSupport/WebGraphicsLayer.h:
+ (WebGraphicsLayerClient):
+ (WebGraphicsLayer):
+ * WebProcess/WebPage/TiledBackingStoreRemoteTile.cpp:
+ (WebKit::TiledBackingStoreRemoteTile::updateBackBuffer):
+ * WebProcess/WebPage/TiledBackingStoreRemoteTile.h:
+ (TiledBackingStoreRemoteTileClient):
+ * WebProcess/WebPage/UpdateAtlas.cpp: Added.
+ (WebKit):
+ (WebKit::UpdateAtlas::UpdateAtlas):
+ (WebKit::nextPowerOfTwo):
+ (WebKit::UpdateAtlas::buildLayoutIfNeeded):
+ (WebKit::UpdateAtlas::findAvailableIndex):
+ (WebKit::UpdateAtlas::didSwapBuffers):
+ (WebKit::UpdateAtlas::acquireScratchBuffer):
+ (WebKit::UpdateAtlas::offsetForIndex):
+ * WebProcess/WebPage/UpdateAtlas.h: Added.
+ (WebCore):
+ (WebKit):
+ (UpdateAtlas):
+ (WebKit::UpdateAtlas::bitmap):
+ (WebKit::UpdateAtlas::size):
+ (WebKit::UpdateAtlas::flags):
+ * WebProcess/WebPage/qt/LayerTreeHostQt.cpp:
+ (WebKit::LayerTreeHostQt::adoptImageBackingStore):
+ (WebKit::LayerTreeHostQt::renderNextFrame):
+ (WebKit::LayerTreeHostQt::purgeBackingStores):
+ (WebKit):
+ (WebKit::LayerTreeHostQt::getAtlas):
+ (WebKit::LayerTreeHostQt::beginContentUpdate):
+ * WebProcess/WebPage/qt/LayerTreeHostQt.h:
+ (LayerTreeHostQt):
+
+2012-04-09 No'am Rosenthal <noam.rosenthal@nokia.com>
+
[Qt][WK2] Sync the layer's state and the layer's children separately
https://bugs.webkit.org/show_bug.cgi?id=82534
encoder->encode(updateRects);
encoder->encode(updateScaleFactor);
encoder->encode(bitmapHandle);
+ encoder->encode(bitmapOffset);
}
bool UpdateInfo::decode(CoreIPC::ArgumentDecoder* decoder, UpdateInfo& result)
return false;
if (!decoder->decode(result.bitmapHandle))
return false;
+ if (!decoder->decode(result.bitmapOffset))
+ return false;
return true;
}
// The handle of the shareable bitmap containing the updates. Will be null if there are no updates.
ShareableBitmap::Handle bitmapHandle;
+
+ // The offset in the bitmap where the rendered contents are.
+ WebCore::IntPoint bitmapOffset;
};
} // namespace WebKit
WebProcess/WebPage/FindController.h \
WebProcess/WebPage/TapHighlightController.h \
WebProcess/WebPage/PageOverlay.h \
+ WebProcess/WebPage/UpdateAtlas.h \
WebProcess/WebPage/WebContextMenu.h \
WebProcess/WebPage/WebFrame.h \
WebProcess/WebPage/WebInspector.h \
WebProcess/WebPage/WebPage.h \
WebProcess/WebPage/WebPageGroupProxy.h \
WebProcess/WebPage/WebUndoStep.h \
+ WebProcess/WebPage/qt/LayerTreeHostQt.h \
WebProcess/WebConnectionToUIProcess.h \
WebProcess/WebProcess.h \
WebProcess/qt/QtBuiltinBundle.h \
WebProcess/WebPage/LayerTreeHost.cpp \
WebProcess/WebPage/PageOverlay.cpp \
WebProcess/WebPage/TiledBackingStoreRemoteTile.cpp \
+ WebProcess/WebPage/UpdateAtlas.cpp \
WebProcess/WebPage/WebBackForwardListProxy.cpp \
WebProcess/WebPage/WebContextMenu.cpp \
WebProcess/WebPage/WebFrame.cpp \
IntRect sourceRect = updateInfo.updateRects.first();
IntRect targetRect = updateInfo.updateRectBounds;
RefPtr<ShareableBitmap> bitmap = ShareableBitmap::create(updateInfo.bitmapHandle);
- dispatchUpdate(bind(&WebLayerTreeRenderer::updateTile, m_renderer.get(), layerID, tileID, sourceRect, targetRect, bitmap));
+ dispatchUpdate(bind(&WebLayerTreeRenderer::updateTile, m_renderer.get(), layerID, tileID, WebLayerTreeRenderer::TileUpdate(sourceRect, targetRect, bitmap, updateInfo.bitmapOffset)));
}
void LayerTreeHostProxy::removeTileForLayer(int layerID, int tileID)
getBackingStore(layerID)->removeTile(tileID);
}
-void WebLayerTreeRenderer::updateTile(WebLayerID layerID, int tileID, const IntRect& sourceRect, const IntRect& targetRect, PassRefPtr<ShareableBitmap> weakBitmap)
+void WebLayerTreeRenderer::updateTile(WebLayerID layerID, int tileID, const TileUpdate& update)
{
- RefPtr<ShareableBitmap> bitmap = weakBitmap;
RefPtr<LayerBackingStore> backingStore = getBackingStore(layerID);
- backingStore->updateTile(tileID, sourceRect, targetRect, bitmap.get());
+ backingStore->updateTile(tileID, update.sourceRect, update.targetRect, update.bitmap, update.offset);
m_backingStoresWithPendingBuffers.add(backingStore);
}
{
RefPtr<ShareableBitmap> bitmap = weakBitmap;
RefPtr<TextureMapperTiledBackingStore> backingStore = TextureMapperTiledBackingStore::create();
- backingStore->updateContents(m_textureMapper.get(), bitmap->createImage().get(), BitmapTexture::BGRAFormat);
m_directlyCompositedImages.set(imageID, backingStore);
+ backingStore->updateContents(m_textureMapper.get(), bitmap->createImage().get());
}
void WebLayerTreeRenderer::destroyImage(int64_t imageID)
class WebLayerTreeRenderer : public ThreadSafeRefCounted<WebLayerTreeRenderer>, public WebCore::GraphicsLayerClient {
public:
+ struct TileUpdate {
+ WebCore::IntRect sourceRect;
+ WebCore::IntRect targetRect;
+ RefPtr<ShareableBitmap> bitmap;
+ WebCore::IntPoint offset;
+ TileUpdate(const WebCore::IntRect& source, const WebCore::IntRect& target, PassRefPtr<ShareableBitmap> newBitmap, const WebCore::IntPoint& newOffset)
+ : sourceRect(source)
+ , targetRect(target)
+ , bitmap(newBitmap)
+ , offset(newOffset)
+ {
+ }
+ };
WebLayerTreeRenderer(LayerTreeHostProxy*);
virtual ~WebLayerTreeRenderer();
void purgeGLResources();
void setLayerState(WebLayerID, const WebLayerInfo&);
void createTile(WebLayerID, int, float scale);
void removeTile(WebLayerID, int);
- void updateTile(WebLayerID, int, const WebCore::IntRect&, const WebCore::IntRect&, PassRefPtr<ShareableBitmap>);
+ void updateTile(WebLayerID, int, const TileUpdate&);
void flushLayerChanges();
void createImage(int64_t, PassRefPtr<ShareableBitmap>);
void destroyImage(int64_t);
#if USE(UI_SIDE_COMPOSITING)
#include "GraphicsLayer.h"
#include "TextureMapper.h"
-
-#include "stdio.h"
+#include "TextureMapperGL.h"
using namespace WebCore;
}
QImage qImage = m_backBuffer->createQImage();
-
if (shouldReset)
texture->reset(m_sourceRect.size(), qImage.hasAlphaChannel() ? BitmapTexture::SupportsAlpha : 0);
-
- texture->updateContents(qImage.constBits(), m_sourceRect);
+ texture->updateContents(qImage.constBits(), m_sourceRect, m_bitmapOffset, qImage.bytesPerLine());
m_backBuffer.clear();
}
-void LayerBackingStoreTile::setBackBuffer(const WebCore::IntRect& targetRect, const WebCore::IntRect& sourceRect, ShareableBitmap* buffer)
+void LayerBackingStoreTile::setBackBuffer(const IntRect& targetRect, const IntRect& sourceRect, PassRefPtr<ShareableBitmap> buffer, const IntPoint& offset)
{
m_sourceRect = sourceRect;
m_targetRect = targetRect;
+ m_bitmapOffset = offset;
m_backBuffer = buffer;
}
m_tilesToRemove.append(id);
}
-void LayerBackingStore::updateTile(int id, const IntRect& sourceRect, const IntRect& targetRect, ShareableBitmap* backBuffer)
+
+void LayerBackingStore::updateTile(int id, const IntRect& sourceRect, const IntRect& targetRect, PassRefPtr<ShareableBitmap> backBuffer, const IntPoint& offset)
{
HashMap<int, LayerBackingStoreTile>::iterator it = m_tiles.find(id);
ASSERT(it != m_tiles.end());
- it->second.setBackBuffer(targetRect, sourceRect, backBuffer);
+ it->second.setBackBuffer(targetRect, sourceRect, backBuffer, offset);
}
PassRefPtr<BitmapTexture> LayerBackingStore::texture() const
inline float scale() const { return m_scale; }
void swapBuffers(WebCore::TextureMapper*);
- void setBackBuffer(const WebCore::IntRect&, const WebCore::IntRect&, ShareableBitmap* buffer);
+ void setBackBuffer(const WebCore::IntRect&, const WebCore::IntRect&, PassRefPtr<ShareableBitmap> buffer, const WebCore::IntPoint&);
private:
RefPtr<ShareableBitmap> m_backBuffer;
WebCore::IntRect m_sourceRect;
WebCore::IntRect m_targetRect;
+ WebCore::IntPoint m_bitmapOffset;
float m_scale;
};
public:
void createTile(int, float);
void removeTile(int);
- void updateTile(int, const WebCore::IntRect&, const WebCore::IntRect&, ShareableBitmap*);
+ void updateTile(int, const WebCore::IntRect&, const WebCore::IntRect&, PassRefPtr<ShareableBitmap>, const WebCore::IntPoint&);
static PassRefPtr<LayerBackingStore> create() { return adoptRef(new LayerBackingStore); }
void commitTileOperations(WebCore::TextureMapper*);
PassRefPtr<WebCore::BitmapTexture> texture() const;
return contentsOpaque() ? Color::white : Color::transparent;
}
+PassOwnPtr<WebCore::GraphicsContext> WebGraphicsLayer::beginContentUpdate(const WebCore::IntSize& size, ShareableBitmap::Handle& handle, WebCore::IntPoint& offset)
+{
+ return m_webGraphicsLayerClient->beginContentUpdate(size, contentsOpaque() ? 0 : ShareableBitmap::SupportsAlpha, handle, offset);
+}
+
void WebGraphicsLayer::createTile(int tileID, const UpdateInfo& updateInfo)
{
m_webGraphicsLayerClient->createTile(id(), tileID, updateInfo);
virtual void syncLayerChildren(WebLayerID, const Vector<WebLayerID>&) = 0;
virtual void attachLayer(WebCore::WebGraphicsLayer*) = 0;
virtual void detachLayer(WebCore::WebGraphicsLayer*) = 0;
+ virtual PassOwnPtr<WebCore::GraphicsContext> beginContentUpdate(const WebCore::IntSize&, ShareableBitmap::Flags, ShareableBitmap::Handle&, WebCore::IntPoint&) = 0;
};
}
virtual void createTile(int tileID, const WebKit::UpdateInfo&);
virtual void updateTile(int tileID, const WebKit::UpdateInfo&);
virtual void removeTile(int tileID);
+ virtual PassOwnPtr<WebCore::GraphicsContext> beginContentUpdate(const WebCore::IntSize&, WebKit::ShareableBitmap::Handle&, WebCore::IntPoint&);
void setWebGraphicsLayerClient(WebKit::WebGraphicsLayerClient*);
void syncChildren();
if (!isDirty())
return Vector<IntRect>();
- RefPtr<ShareableBitmap> bitmap = ShareableBitmap::createShareable(m_dirtyRect.size(), m_tiledBackingStore->supportsAlpha() ? ShareableBitmap::SupportsAlpha : 0);
- OwnPtr<GraphicsContext> graphicsContext(bitmap->createGraphicsContext());
+ UpdateInfo updateInfo;
+ OwnPtr<GraphicsContext> graphicsContext = m_client->beginContentUpdate(m_dirtyRect.size(), updateInfo.bitmapHandle, updateInfo.bitmapOffset);
+ if (!graphicsContext)
+ return Vector<IntRect>();
graphicsContext->translate(-m_dirtyRect.x(), -m_dirtyRect.y());
graphicsContext->scale(FloatSize(m_tiledBackingStore->contentsScale(), m_tiledBackingStore->contentsScale()));
m_tiledBackingStore->client()->tiledBackingStorePaint(graphicsContext.get(), m_tiledBackingStore->mapToContents(m_dirtyRect));
- UpdateInfo updateInfo;
updateInfo.updateRectBounds = m_rect;
IntRect updateRect = m_dirtyRect;
updateRect.move(-m_rect.x(), -m_rect.y());
updateInfo.updateRects.append(updateRect);
updateInfo.updateScaleFactor = m_tiledBackingStore->contentsScale();
- bitmap->createHandle(updateInfo.bitmapHandle);
+ graphicsContext.release();
static int id = 0;
if (!m_ID) {
#if USE(TILED_BACKING_STORE)
+#include "ShareableBitmap.h"
#include "Tile.h"
#include "TiledBackingStore.h"
#include "WebCore/IntRect.h"
virtual void createTile(int tileID, const UpdateInfo&) = 0;
virtual void updateTile(int tileID, const UpdateInfo&) = 0;
virtual void removeTile(int tileID) = 0;
+ virtual PassOwnPtr<WebCore::GraphicsContext> beginContentUpdate(const WebCore::IntSize&, ShareableBitmap::Handle&, WebCore::IntPoint&) = 0;
};
class TiledBackingStoreRemoteTileBackend : public WebCore::TiledBackingStoreBackend {
--- /dev/null
+/*
+ Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "UpdateAtlas.h"
+
+#if USE(UI_SIDE_COMPOSITING)
+
+#include "GraphicsContext.h"
+#include "IntRect.h"
+#include "MathExtras.h"
+using namespace WebCore;
+
+namespace WebKit {
+
+UpdateAtlas::UpdateAtlas(int dimension, ShareableBitmap::Flags flags)
+ : m_flags(flags)
+{
+ m_bitmap = ShareableBitmap::createShareable(IntSize(dimension, dimension), flags);
+}
+
+static int nextPowerOfTwo(int number)
+{
+ // This is a fast trick to get nextPowerOfTwo for an integer.
+ --number;
+ number |= number >> 1;
+ number |= number >> 2;
+ number |= number >> 4;
+ number |= number >> 8;
+ number |= number >> 16;
+ number++;
+ return number;
+}
+
+void UpdateAtlas::buildLayoutIfNeeded()
+{
+ if (!m_layout.isEmpty())
+ return;
+
+ static const int MinTileSize = 32;
+ static const int MaxTileSize = 512;
+
+ // Divide our square to square power-of-two boxes.
+ for (int cursor = 0; cursor < size().width(); ) {
+ int remainder = size().width() - cursor;
+ int dimension = std::min(remainder, std::min(MaxTileSize, std::max(MinTileSize, nextPowerOfTwo(remainder / 2))));
+ cursor += dimension;
+ m_layout.append(dimension);
+ }
+
+ m_bufferStates.resize(m_layout.size() * m_layout.size());
+ for (int i = 0; i < m_bufferStates.size(); ++i)
+ m_bufferStates[i] = Available;
+}
+
+int UpdateAtlas::findAvailableIndex(const WebCore::IntSize& size)
+{
+ int dimension = m_layout.size();
+ int stride = dimension;
+ int requiredDimension = std::max(size.width(), size.height());
+
+ // Begin from the smallest buffer, until we reach the smallest available buffer that's big enough to contain our rect.
+ for (int i = m_bufferStates.size() - 1; i >= 0; i -= (dimension + 1), --stride) {
+ // Need a bigger buffer.
+ if (m_layout[i / dimension] < requiredDimension)
+ continue;
+
+ // Check all buffers of current size, to find an available one.
+ for (int offset = 0; offset < stride; ++offset) {
+ int index = i - offset;
+ if (m_bufferStates[index] == Available)
+ return index;
+ }
+ }
+
+ return -1;
+}
+
+void UpdateAtlas::didSwapBuffers()
+{
+ buildLayoutIfNeeded();
+ for (int i = 0; i < m_bufferStates.size(); ++i)
+ m_bufferStates[i] = Available;
+}
+
+PassOwnPtr<GraphicsContext> UpdateAtlas::beginPaintingOnAvailableBuffer(const WebCore::IntSize& size, IntPoint& offset)
+{
+ buildLayoutIfNeeded();
+ int index = findAvailableIndex(size);
+
+ // No available buffer was found, returning null.
+ if (index < 0)
+ return PassOwnPtr<GraphicsContext>();
+
+ // FIXME: Use tri-state buffers, to allow faster updates.
+ m_bufferStates[index] = Taken;
+ offset = offsetForIndex(index);
+ IntRect rect(IntPoint::zero(), size);
+ OwnPtr<GraphicsContext> graphicsContext = m_bitmap->createGraphicsContext();
+ graphicsContext->translate(offset.x(), offset.y());
+ graphicsContext->clip(rect);
+ graphicsContext->setCompositeOperation(CompositeCopy);
+ graphicsContext->fillRect(rect, (flags() & ShareableBitmap::SupportsAlpha) ? Color::transparent : Color::white, ColorSpaceDeviceRGB);
+ graphicsContext->setCompositeOperation(CompositeSourceOver);
+ return graphicsContext.release();
+}
+
+IntPoint UpdateAtlas::offsetForIndex(int index) const
+{
+ IntPoint coord(index % m_layout.size(), index / m_layout.size());
+ int x = 0;
+ int y = 0;
+ for (int i = 0; i < coord.x(); ++i)
+ x += m_layout[i];
+ for (int i = 0; i < coord.y(); ++i)
+ y += m_layout[i];
+
+ return IntPoint(x, y);
+}
+
+}
+#endif
--- /dev/null
+/*
+ Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ */
+
+#ifndef UpdateAtlas_h
+#define UpdateAtlas_h
+
+#include "ShareableBitmap.h"
+
+#if USE(UI_SIDE_COMPOSITING)
+namespace WebCore {
+class GraphicsContext;
+class IntRect;
+}
+
+namespace WebKit {
+
+class UpdateAtlas {
+public:
+ UpdateAtlas(int dimension, ShareableBitmap::Flags);
+
+ PassRefPtr<ShareableBitmap> bitmap() { return m_bitmap; }
+ inline WebCore::IntSize size() const { return m_bitmap->size(); }
+
+ // Returns a null pointer of there is no available buffer.
+ PassOwnPtr<WebCore::GraphicsContext> beginPaintingOnAvailableBuffer(const WebCore::IntSize&, WebCore::IntPoint& offset);
+ void didSwapBuffers();
+ ShareableBitmap::Flags flags() const { return m_flags; }
+
+private:
+ void buildLayoutIfNeeded();
+ WebCore::IntPoint offsetForIndex(int) const;
+ int findAvailableIndex(const WebCore::IntSize&);
+
+private:
+ enum State {
+ Available,
+ Taken
+ };
+
+ Vector<State> m_bufferStates;
+ Vector<int> m_layout;
+ ShareableBitmap::Flags m_flags;
+ RefPtr<ShareableBitmap> m_bitmap;
+};
+
+}
+#endif
+#endif // UpdateAtlas_h
#include "GraphicsContext.h"
#include "LayerTreeHostProxyMessages.h"
#include "MessageID.h"
+#include "WebCoreArgumentCoders.h"
#include "WebGraphicsLayer.h"
#include "WebPage.h"
#include <WebCore/Frame.h>
return key;
}
- RefPtr<ShareableBitmap> bitmap = ShareableBitmap::createShareable(image->size(), image->currentFrameHasAlpha() ? ShareableBitmap::SupportsAlpha : 0);
+ RefPtr<ShareableBitmap> bitmap = ShareableBitmap::createShareable(image->size(), (image->currentFrameHasAlpha() ? ShareableBitmap::SupportsAlpha : 0));
{
OwnPtr<WebCore::GraphicsContext> graphicsContext = bitmap->createGraphicsContext();
graphicsContext->drawImage(image, ColorSpaceDeviceRGB, IntPoint::zero());
{
m_waitingForUIProcess = false;
scheduleLayerFlush();
+ for (int i = 0; i < m_updateAtlases.size(); ++i)
+ m_updateAtlases[i].didSwapBuffers();
}
bool LayerTreeHostQt::layerTreeTileUpdatesAllowed() const
(*it)->purgeBackingStores();
ASSERT(!m_directlyCompositedImageRefCounts.size());
+ m_updateAtlases.clear();
+}
+
+UpdateAtlas& LayerTreeHostQt::getAtlas(ShareableBitmap::Flags flags)
+{
+ for (int i = 0; i < m_updateAtlases.size(); ++i) {
+ if (m_updateAtlases[i].flags() == flags)
+ return m_updateAtlases[i];
+ }
+ static const int ScratchBufferDimension = 2000;
+ m_updateAtlases.append(UpdateAtlas(ScratchBufferDimension, flags));
+ return m_updateAtlases.last();
+}
+
+PassOwnPtr<WebCore::GraphicsContext> LayerTreeHostQt::beginContentUpdate(const WebCore::IntSize& size, ShareableBitmap::Flags flags, ShareableBitmap::Handle& handle, WebCore::IntPoint& offset)
+{
+ UpdateAtlas& atlas = getAtlas(flags);
+ if (!atlas.bitmap()->createHandle(handle))
+ return PassOwnPtr<WebCore::GraphicsContext>();
+
+ // This will return null if there is no available buffer.
+ OwnPtr<WebCore::GraphicsContext> graphicsContext = atlas.beginPaintingOnAvailableBuffer(size, offset);
+ if (!graphicsContext)
+ return PassOwnPtr<WebCore::GraphicsContext>();
+
+ return graphicsContext.release();
}
} // namespace WebKit
#include "LayerTreeContext.h"
#include "LayerTreeHost.h"
#include "Timer.h"
+#include "UpdateAtlas.h"
#include "WebGraphicsLayer.h"
#include <WebCore/GraphicsLayerClient.h>
#include <wtf/OwnPtr.h>
virtual void attachLayer(WebCore::WebGraphicsLayer*);
virtual void detachLayer(WebCore::WebGraphicsLayer*);
+ virtual PassOwnPtr<WebCore::GraphicsContext> beginContentUpdate(const WebCore::IntSize&, ShareableBitmap::Flags, ShareableBitmap::Handle&, WebCore::IntPoint&);
+
protected:
explicit LayerTreeHostQt(WebPage*);
void performScheduledLayerFlush();
void sendLayersToUI();
+ UpdateAtlas& getAtlas(ShareableBitmap::Flags);
+
OwnPtr<WebCore::GraphicsLayer> m_rootLayer;
// The layer which contains all non-composited content.
HashSet<WebCore::WebGraphicsLayer*> m_registeredLayers;
HashMap<int64_t, int> m_directlyCompositedImageRefCounts;
+ Vector<UpdateAtlas> m_updateAtlases;
bool m_notifyAfterScheduledLayerFlush;
bool m_isValid;