From 2e510fd5b5a30f1315c272d44ae3aa4cba355498 Mon Sep 17 00:00:00 2001 From: Nicolas Roard Date: Fri, 6 Apr 2012 11:35:50 -0700 Subject: Reorganize platform/graphics/android Change-Id: Idc67155cfa99784dcd931e705336bfa063ecae46 --- Android.mk | 4 + CleanSpec.mk | 1 + Source/WebCore/Android.mk | 106 +- .../WebCore/platform/graphics/FontPlatformData.h | 2 +- .../platform/graphics/android/AndroidAnimation.cpp | 333 ------ .../platform/graphics/android/AndroidAnimation.h | 105 -- .../platform/graphics/android/BaseLayerAndroid.cpp | 56 - .../platform/graphics/android/BaseLayerAndroid.h | 59 - .../platform/graphics/android/BaseRenderer.cpp | 165 --- .../platform/graphics/android/BaseRenderer.h | 107 -- .../platform/graphics/android/CanvasLayer.cpp | 220 ---- .../platform/graphics/android/CanvasLayer.h | 81 -- .../platform/graphics/android/CanvasTexture.cpp | 225 ---- .../platform/graphics/android/CanvasTexture.h | 95 -- .../platform/graphics/android/ClassTracker.cpp | 121 -- .../platform/graphics/android/ClassTracker.h | 58 - .../platform/graphics/android/DrawQuadData.h | 172 --- .../platform/graphics/android/DumpLayer.cpp | 83 -- .../WebCore/platform/graphics/android/DumpLayer.h | 67 -- .../platform/graphics/android/FixedPositioning.cpp | 106 -- .../platform/graphics/android/FixedPositioning.h | 128 --- .../platform/graphics/android/FontAndroid.cpp | 1192 -------------------- .../platform/graphics/android/FontCacheAndroid.cpp | 195 ---- .../graphics/android/FontCustomPlatformData.cpp | 89 -- .../graphics/android/FontCustomPlatformData.h | 62 - .../platform/graphics/android/FontDataAndroid.cpp | 146 --- .../platform/graphics/android/FontPlatformData.h | 131 --- .../graphics/android/FontPlatformDataAndroid.cpp | 273 ----- .../WebCore/platform/graphics/android/GLExtras.cpp | 139 --- .../WebCore/platform/graphics/android/GLExtras.h | 60 - .../WebCore/platform/graphics/android/GLUtils.cpp | 669 ----------- Source/WebCore/platform/graphics/android/GLUtils.h | 98 -- .../platform/graphics/android/GaneshContext.cpp | 184 --- .../platform/graphics/android/GaneshContext.h | 63 -- .../platform/graphics/android/GaneshRenderer.cpp | 113 -- .../platform/graphics/android/GaneshRenderer.h | 61 - .../platform/graphics/android/GlyphMapAndroid.cpp | 146 --- .../platform/graphics/android/HarfbuzzSkia.cpp | 221 ---- .../platform/graphics/android/HarfbuzzSkia.h | 40 - .../graphics/android/IFrameContentLayerAndroid.cpp | 42 - .../graphics/android/IFrameContentLayerAndroid.h | 78 -- .../graphics/android/IFrameLayerAndroid.cpp | 40 - .../platform/graphics/android/IFrameLayerAndroid.h | 68 -- .../platform/graphics/android/ImageTexture.cpp | 256 ----- .../platform/graphics/android/ImageTexture.h | 110 -- .../platform/graphics/android/ImagesManager.cpp | 134 --- .../platform/graphics/android/ImagesManager.h | 64 -- .../platform/graphics/android/InspectorCanvas.cpp | 133 --- .../platform/graphics/android/InspectorCanvas.h | 102 -- Source/WebCore/platform/graphics/android/Layer.cpp | 237 ---- Source/WebCore/platform/graphics/android/Layer.h | 184 --- .../platform/graphics/android/LayerAndroid.cpp | 1034 ----------------- .../platform/graphics/android/LayerAndroid.h | 394 ------- .../platform/graphics/android/LayerContent.h | 56 - .../platform/graphics/android/MediaLayer.cpp | 115 -- .../WebCore/platform/graphics/android/MediaLayer.h | 70 -- .../platform/graphics/android/MediaListener.h | 89 -- .../graphics/android/MediaPlayerPrivateAndroid.h | 143 --- .../platform/graphics/android/MediaTexture.cpp | 316 ------ .../platform/graphics/android/MediaTexture.h | 97 -- .../graphics/android/PaintTileOperation.cpp | 117 -- .../platform/graphics/android/PaintTileOperation.h | 88 -- .../graphics/android/PictureLayerContent.cpp | 106 -- .../graphics/android/PictureLayerContent.h | 55 - .../graphics/android/PictureSetLayerContent.cpp | 41 - .../graphics/android/PictureSetLayerContent.h | 53 - .../platform/graphics/android/QueuedOperation.h | 47 - .../platform/graphics/android/RasterRenderer.cpp | 115 -- .../platform/graphics/android/RasterRenderer.h | 62 - .../graphics/android/ScrollableLayerAndroid.cpp | 80 -- .../graphics/android/ScrollableLayerAndroid.h | 88 -- .../platform/graphics/android/ShaderProgram.cpp | 730 ------------ .../platform/graphics/android/ShaderProgram.h | 234 ---- .../WebCore/platform/graphics/android/Surface.cpp | 346 ------ Source/WebCore/platform/graphics/android/Surface.h | 115 -- .../platform/graphics/android/SurfaceBacking.cpp | 171 --- .../platform/graphics/android/SurfaceBacking.h | 86 -- .../graphics/android/SurfaceCollection.cpp | 218 ---- .../platform/graphics/android/SurfaceCollection.h | 76 -- .../graphics/android/SurfaceCollectionManager.cpp | 258 ----- .../graphics/android/SurfaceCollectionManager.h | 74 -- .../WebCore/platform/graphics/android/TestExport.h | 32 - .../platform/graphics/android/TextureInfo.cpp | 65 -- .../platform/graphics/android/TextureInfo.h | 65 -- .../platform/graphics/android/TextureOwner.h | 47 - .../graphics/android/TexturesGenerator.cpp | 182 --- .../platform/graphics/android/TexturesGenerator.h | 70 -- Source/WebCore/platform/graphics/android/Tile.cpp | 528 --------- Source/WebCore/platform/graphics/android/Tile.h | 191 ---- .../WebCore/platform/graphics/android/TileGrid.cpp | 376 ------ .../WebCore/platform/graphics/android/TileGrid.h | 87 -- .../platform/graphics/android/TilePainter.h | 58 - .../platform/graphics/android/TileTexture.cpp | 147 --- .../platform/graphics/android/TileTexture.h | 99 -- .../platform/graphics/android/TilesManager.cpp | 449 -------- .../platform/graphics/android/TilesManager.h | 209 ---- .../platform/graphics/android/TilesProfiler.cpp | 133 --- .../platform/graphics/android/TilesProfiler.h | 90 -- .../platform/graphics/android/TransferQueue.cpp | 644 ----------- .../platform/graphics/android/TransferQueue.h | 234 ---- .../platform/graphics/android/VerticalTextMap.cpp | 106 -- .../platform/graphics/android/VerticalTextMap.h | 44 - .../graphics/android/VideoLayerAndroid.cpp | 220 ---- .../platform/graphics/android/VideoLayerAndroid.h | 82 -- .../graphics/android/VideoLayerManager.cpp | 385 ------- .../platform/graphics/android/VideoLayerManager.h | 141 --- .../platform/graphics/android/android_graphics.h | 42 - .../graphics/android/context/android_graphics.h | 42 + .../graphics/android/fonts/FontAndroid.cpp | 1192 ++++++++++++++++++++ .../graphics/android/fonts/FontCacheAndroid.cpp | 195 ++++ .../android/fonts/FontCustomPlatformData.cpp | 89 ++ .../android/fonts/FontCustomPlatformData.h | 62 + .../graphics/android/fonts/FontDataAndroid.cpp | 146 +++ .../graphics/android/fonts/FontPlatformData.h | 131 +++ .../android/fonts/FontPlatformDataAndroid.cpp | 273 +++++ .../graphics/android/fonts/GlyphMapAndroid.cpp | 146 +++ .../graphics/android/fonts/HarfbuzzSkia.cpp | 221 ++++ .../platform/graphics/android/fonts/HarfbuzzSkia.h | 40 + .../graphics/android/fonts/VerticalTextMap.cpp | 106 ++ .../graphics/android/fonts/VerticalTextMap.h | 44 + .../graphics/android/layers/AndroidAnimation.cpp | 333 ++++++ .../graphics/android/layers/AndroidAnimation.h | 105 ++ .../graphics/android/layers/BaseLayerAndroid.cpp | 56 + .../graphics/android/layers/BaseLayerAndroid.h | 59 + .../graphics/android/layers/CanvasLayer.cpp | 220 ++++ .../platform/graphics/android/layers/CanvasLayer.h | 81 ++ .../graphics/android/layers/CanvasTexture.cpp | 225 ++++ .../graphics/android/layers/CanvasTexture.h | 95 ++ .../platform/graphics/android/layers/DumpLayer.cpp | 83 ++ .../platform/graphics/android/layers/DumpLayer.h | 67 ++ .../graphics/android/layers/FixedPositioning.cpp | 106 ++ .../graphics/android/layers/FixedPositioning.h | 128 +++ .../android/layers/IFrameContentLayerAndroid.cpp | 42 + .../android/layers/IFrameContentLayerAndroid.h | 78 ++ .../graphics/android/layers/IFrameLayerAndroid.cpp | 40 + .../graphics/android/layers/IFrameLayerAndroid.h | 68 ++ .../platform/graphics/android/layers/Layer.cpp | 237 ++++ .../platform/graphics/android/layers/Layer.h | 184 +++ .../graphics/android/layers/LayerAndroid.cpp | 1034 +++++++++++++++++ .../graphics/android/layers/LayerAndroid.h | 394 +++++++ .../graphics/android/layers/LayerContent.h | 56 + .../graphics/android/layers/MediaLayer.cpp | 115 ++ .../platform/graphics/android/layers/MediaLayer.h | 70 ++ .../graphics/android/layers/MediaListener.h | 89 ++ .../android/layers/MediaPlayerPrivateAndroid.h | 143 +++ .../graphics/android/layers/MediaTexture.cpp | 316 ++++++ .../graphics/android/layers/MediaTexture.h | 97 ++ .../android/layers/PictureLayerContent.cpp | 106 ++ .../graphics/android/layers/PictureLayerContent.h | 55 + .../android/layers/PictureSetLayerContent.cpp | 41 + .../android/layers/PictureSetLayerContent.h | 53 + .../android/layers/ScrollableLayerAndroid.cpp | 80 ++ .../android/layers/ScrollableLayerAndroid.h | 88 ++ .../graphics/android/layers/VideoLayerAndroid.cpp | 220 ++++ .../graphics/android/layers/VideoLayerAndroid.h | 82 ++ .../graphics/android/layers/VideoLayerManager.cpp | 385 +++++++ .../graphics/android/layers/VideoLayerManager.h | 141 +++ .../graphics/android/rendering/BaseRenderer.cpp | 165 +++ .../graphics/android/rendering/BaseRenderer.h | 107 ++ .../graphics/android/rendering/DrawQuadData.h | 172 +++ .../graphics/android/rendering/GLExtras.cpp | 139 +++ .../platform/graphics/android/rendering/GLExtras.h | 60 + .../graphics/android/rendering/GLUtils.cpp | 669 +++++++++++ .../platform/graphics/android/rendering/GLUtils.h | 98 ++ .../graphics/android/rendering/GaneshContext.cpp | 184 +++ .../graphics/android/rendering/GaneshContext.h | 63 ++ .../graphics/android/rendering/GaneshRenderer.cpp | 113 ++ .../graphics/android/rendering/GaneshRenderer.h | 61 + .../graphics/android/rendering/ImageTexture.cpp | 256 +++++ .../graphics/android/rendering/ImageTexture.h | 110 ++ .../graphics/android/rendering/ImagesManager.cpp | 134 +++ .../graphics/android/rendering/ImagesManager.h | 64 ++ .../graphics/android/rendering/InspectorCanvas.cpp | 133 +++ .../graphics/android/rendering/InspectorCanvas.h | 102 ++ .../android/rendering/PaintTileOperation.cpp | 117 ++ .../android/rendering/PaintTileOperation.h | 88 ++ .../graphics/android/rendering/QueuedOperation.h | 47 + .../graphics/android/rendering/RasterRenderer.cpp | 115 ++ .../graphics/android/rendering/RasterRenderer.h | 62 + .../graphics/android/rendering/ShaderProgram.cpp | 730 ++++++++++++ .../graphics/android/rendering/ShaderProgram.h | 234 ++++ .../graphics/android/rendering/Surface.cpp | 346 ++++++ .../platform/graphics/android/rendering/Surface.h | 115 ++ .../graphics/android/rendering/SurfaceBacking.cpp | 171 +++ .../graphics/android/rendering/SurfaceBacking.h | 86 ++ .../android/rendering/SurfaceCollection.cpp | 218 ++++ .../graphics/android/rendering/SurfaceCollection.h | 76 ++ .../android/rendering/SurfaceCollectionManager.cpp | 258 +++++ .../android/rendering/SurfaceCollectionManager.h | 74 ++ .../graphics/android/rendering/TextureInfo.cpp | 65 ++ .../graphics/android/rendering/TextureInfo.h | 65 ++ .../graphics/android/rendering/TextureOwner.h | 47 + .../android/rendering/TexturesGenerator.cpp | 182 +++ .../graphics/android/rendering/TexturesGenerator.h | 70 ++ .../platform/graphics/android/rendering/Tile.cpp | 528 +++++++++ .../platform/graphics/android/rendering/Tile.h | 191 ++++ .../graphics/android/rendering/TileGrid.cpp | 376 ++++++ .../platform/graphics/android/rendering/TileGrid.h | 87 ++ .../graphics/android/rendering/TilePainter.h | 58 + .../graphics/android/rendering/TileTexture.cpp | 147 +++ .../graphics/android/rendering/TileTexture.h | 99 ++ .../graphics/android/rendering/TilesManager.cpp | 449 ++++++++ .../graphics/android/rendering/TilesManager.h | 209 ++++ .../graphics/android/rendering/TilesProfiler.cpp | 133 +++ .../graphics/android/rendering/TilesProfiler.h | 90 ++ .../graphics/android/rendering/TransferQueue.cpp | 644 +++++++++++ .../graphics/android/rendering/TransferQueue.h | 234 ++++ .../graphics/android/utils/ClassTracker.cpp | 121 ++ .../platform/graphics/android/utils/ClassTracker.h | 58 + .../platform/graphics/android/utils/TestExport.h | 32 + 210 files changed, 17772 insertions(+), 17763 deletions(-) delete mode 100644 Source/WebCore/platform/graphics/android/AndroidAnimation.cpp delete mode 100644 Source/WebCore/platform/graphics/android/AndroidAnimation.h delete mode 100644 Source/WebCore/platform/graphics/android/BaseLayerAndroid.cpp delete mode 100644 Source/WebCore/platform/graphics/android/BaseLayerAndroid.h delete mode 100644 Source/WebCore/platform/graphics/android/BaseRenderer.cpp delete mode 100644 Source/WebCore/platform/graphics/android/BaseRenderer.h delete mode 100644 Source/WebCore/platform/graphics/android/CanvasLayer.cpp delete mode 100644 Source/WebCore/platform/graphics/android/CanvasLayer.h delete mode 100644 Source/WebCore/platform/graphics/android/CanvasTexture.cpp delete mode 100644 Source/WebCore/platform/graphics/android/CanvasTexture.h delete mode 100644 Source/WebCore/platform/graphics/android/ClassTracker.cpp delete mode 100644 Source/WebCore/platform/graphics/android/ClassTracker.h delete mode 100644 Source/WebCore/platform/graphics/android/DrawQuadData.h delete mode 100644 Source/WebCore/platform/graphics/android/DumpLayer.cpp delete mode 100644 Source/WebCore/platform/graphics/android/DumpLayer.h delete mode 100644 Source/WebCore/platform/graphics/android/FixedPositioning.cpp delete mode 100644 Source/WebCore/platform/graphics/android/FixedPositioning.h delete mode 100644 Source/WebCore/platform/graphics/android/FontAndroid.cpp delete mode 100644 Source/WebCore/platform/graphics/android/FontCacheAndroid.cpp delete mode 100644 Source/WebCore/platform/graphics/android/FontCustomPlatformData.cpp delete mode 100644 Source/WebCore/platform/graphics/android/FontCustomPlatformData.h delete mode 100644 Source/WebCore/platform/graphics/android/FontDataAndroid.cpp delete mode 100644 Source/WebCore/platform/graphics/android/FontPlatformData.h delete mode 100644 Source/WebCore/platform/graphics/android/FontPlatformDataAndroid.cpp delete mode 100644 Source/WebCore/platform/graphics/android/GLExtras.cpp delete mode 100644 Source/WebCore/platform/graphics/android/GLExtras.h delete mode 100644 Source/WebCore/platform/graphics/android/GLUtils.cpp delete mode 100644 Source/WebCore/platform/graphics/android/GLUtils.h delete mode 100644 Source/WebCore/platform/graphics/android/GaneshContext.cpp delete mode 100644 Source/WebCore/platform/graphics/android/GaneshContext.h delete mode 100644 Source/WebCore/platform/graphics/android/GaneshRenderer.cpp delete mode 100644 Source/WebCore/platform/graphics/android/GaneshRenderer.h delete mode 100644 Source/WebCore/platform/graphics/android/GlyphMapAndroid.cpp delete mode 100644 Source/WebCore/platform/graphics/android/HarfbuzzSkia.cpp delete mode 100644 Source/WebCore/platform/graphics/android/HarfbuzzSkia.h delete mode 100644 Source/WebCore/platform/graphics/android/IFrameContentLayerAndroid.cpp delete mode 100644 Source/WebCore/platform/graphics/android/IFrameContentLayerAndroid.h delete mode 100644 Source/WebCore/platform/graphics/android/IFrameLayerAndroid.cpp delete mode 100644 Source/WebCore/platform/graphics/android/IFrameLayerAndroid.h delete mode 100644 Source/WebCore/platform/graphics/android/ImageTexture.cpp delete mode 100644 Source/WebCore/platform/graphics/android/ImageTexture.h delete mode 100644 Source/WebCore/platform/graphics/android/ImagesManager.cpp delete mode 100644 Source/WebCore/platform/graphics/android/ImagesManager.h delete mode 100644 Source/WebCore/platform/graphics/android/InspectorCanvas.cpp delete mode 100644 Source/WebCore/platform/graphics/android/InspectorCanvas.h delete mode 100644 Source/WebCore/platform/graphics/android/Layer.cpp delete mode 100644 Source/WebCore/platform/graphics/android/Layer.h delete mode 100644 Source/WebCore/platform/graphics/android/LayerAndroid.cpp delete mode 100644 Source/WebCore/platform/graphics/android/LayerAndroid.h delete mode 100644 Source/WebCore/platform/graphics/android/LayerContent.h delete mode 100644 Source/WebCore/platform/graphics/android/MediaLayer.cpp delete mode 100644 Source/WebCore/platform/graphics/android/MediaLayer.h delete mode 100644 Source/WebCore/platform/graphics/android/MediaListener.h delete mode 100644 Source/WebCore/platform/graphics/android/MediaPlayerPrivateAndroid.h delete mode 100644 Source/WebCore/platform/graphics/android/MediaTexture.cpp delete mode 100644 Source/WebCore/platform/graphics/android/MediaTexture.h delete mode 100644 Source/WebCore/platform/graphics/android/PaintTileOperation.cpp delete mode 100644 Source/WebCore/platform/graphics/android/PaintTileOperation.h delete mode 100644 Source/WebCore/platform/graphics/android/PictureLayerContent.cpp delete mode 100644 Source/WebCore/platform/graphics/android/PictureLayerContent.h delete mode 100644 Source/WebCore/platform/graphics/android/PictureSetLayerContent.cpp delete mode 100644 Source/WebCore/platform/graphics/android/PictureSetLayerContent.h delete mode 100644 Source/WebCore/platform/graphics/android/QueuedOperation.h delete mode 100644 Source/WebCore/platform/graphics/android/RasterRenderer.cpp delete mode 100644 Source/WebCore/platform/graphics/android/RasterRenderer.h delete mode 100644 Source/WebCore/platform/graphics/android/ScrollableLayerAndroid.cpp delete mode 100644 Source/WebCore/platform/graphics/android/ScrollableLayerAndroid.h delete mode 100644 Source/WebCore/platform/graphics/android/ShaderProgram.cpp delete mode 100644 Source/WebCore/platform/graphics/android/ShaderProgram.h delete mode 100644 Source/WebCore/platform/graphics/android/Surface.cpp delete mode 100644 Source/WebCore/platform/graphics/android/Surface.h delete mode 100644 Source/WebCore/platform/graphics/android/SurfaceBacking.cpp delete mode 100644 Source/WebCore/platform/graphics/android/SurfaceBacking.h delete mode 100644 Source/WebCore/platform/graphics/android/SurfaceCollection.cpp delete mode 100644 Source/WebCore/platform/graphics/android/SurfaceCollection.h delete mode 100644 Source/WebCore/platform/graphics/android/SurfaceCollectionManager.cpp delete mode 100644 Source/WebCore/platform/graphics/android/SurfaceCollectionManager.h delete mode 100644 Source/WebCore/platform/graphics/android/TestExport.h delete mode 100644 Source/WebCore/platform/graphics/android/TextureInfo.cpp delete mode 100644 Source/WebCore/platform/graphics/android/TextureInfo.h delete mode 100644 Source/WebCore/platform/graphics/android/TextureOwner.h delete mode 100644 Source/WebCore/platform/graphics/android/TexturesGenerator.cpp delete mode 100644 Source/WebCore/platform/graphics/android/TexturesGenerator.h delete mode 100644 Source/WebCore/platform/graphics/android/Tile.cpp delete mode 100644 Source/WebCore/platform/graphics/android/Tile.h delete mode 100644 Source/WebCore/platform/graphics/android/TileGrid.cpp delete mode 100644 Source/WebCore/platform/graphics/android/TileGrid.h delete mode 100644 Source/WebCore/platform/graphics/android/TilePainter.h delete mode 100644 Source/WebCore/platform/graphics/android/TileTexture.cpp delete mode 100644 Source/WebCore/platform/graphics/android/TileTexture.h delete mode 100644 Source/WebCore/platform/graphics/android/TilesManager.cpp delete mode 100644 Source/WebCore/platform/graphics/android/TilesManager.h delete mode 100644 Source/WebCore/platform/graphics/android/TilesProfiler.cpp delete mode 100644 Source/WebCore/platform/graphics/android/TilesProfiler.h delete mode 100644 Source/WebCore/platform/graphics/android/TransferQueue.cpp delete mode 100644 Source/WebCore/platform/graphics/android/TransferQueue.h delete mode 100644 Source/WebCore/platform/graphics/android/VerticalTextMap.cpp delete mode 100644 Source/WebCore/platform/graphics/android/VerticalTextMap.h delete mode 100644 Source/WebCore/platform/graphics/android/VideoLayerAndroid.cpp delete mode 100644 Source/WebCore/platform/graphics/android/VideoLayerAndroid.h delete mode 100644 Source/WebCore/platform/graphics/android/VideoLayerManager.cpp delete mode 100644 Source/WebCore/platform/graphics/android/VideoLayerManager.h delete mode 100644 Source/WebCore/platform/graphics/android/android_graphics.h create mode 100644 Source/WebCore/platform/graphics/android/context/android_graphics.h create mode 100644 Source/WebCore/platform/graphics/android/fonts/FontAndroid.cpp create mode 100644 Source/WebCore/platform/graphics/android/fonts/FontCacheAndroid.cpp create mode 100644 Source/WebCore/platform/graphics/android/fonts/FontCustomPlatformData.cpp create mode 100644 Source/WebCore/platform/graphics/android/fonts/FontCustomPlatformData.h create mode 100644 Source/WebCore/platform/graphics/android/fonts/FontDataAndroid.cpp create mode 100644 Source/WebCore/platform/graphics/android/fonts/FontPlatformData.h create mode 100644 Source/WebCore/platform/graphics/android/fonts/FontPlatformDataAndroid.cpp create mode 100644 Source/WebCore/platform/graphics/android/fonts/GlyphMapAndroid.cpp create mode 100644 Source/WebCore/platform/graphics/android/fonts/HarfbuzzSkia.cpp create mode 100644 Source/WebCore/platform/graphics/android/fonts/HarfbuzzSkia.h create mode 100644 Source/WebCore/platform/graphics/android/fonts/VerticalTextMap.cpp create mode 100644 Source/WebCore/platform/graphics/android/fonts/VerticalTextMap.h create mode 100644 Source/WebCore/platform/graphics/android/layers/AndroidAnimation.cpp create mode 100644 Source/WebCore/platform/graphics/android/layers/AndroidAnimation.h create mode 100644 Source/WebCore/platform/graphics/android/layers/BaseLayerAndroid.cpp create mode 100644 Source/WebCore/platform/graphics/android/layers/BaseLayerAndroid.h create mode 100644 Source/WebCore/platform/graphics/android/layers/CanvasLayer.cpp create mode 100644 Source/WebCore/platform/graphics/android/layers/CanvasLayer.h create mode 100644 Source/WebCore/platform/graphics/android/layers/CanvasTexture.cpp create mode 100644 Source/WebCore/platform/graphics/android/layers/CanvasTexture.h create mode 100644 Source/WebCore/platform/graphics/android/layers/DumpLayer.cpp create mode 100644 Source/WebCore/platform/graphics/android/layers/DumpLayer.h create mode 100644 Source/WebCore/platform/graphics/android/layers/FixedPositioning.cpp create mode 100644 Source/WebCore/platform/graphics/android/layers/FixedPositioning.h create mode 100644 Source/WebCore/platform/graphics/android/layers/IFrameContentLayerAndroid.cpp create mode 100644 Source/WebCore/platform/graphics/android/layers/IFrameContentLayerAndroid.h create mode 100644 Source/WebCore/platform/graphics/android/layers/IFrameLayerAndroid.cpp create mode 100644 Source/WebCore/platform/graphics/android/layers/IFrameLayerAndroid.h create mode 100644 Source/WebCore/platform/graphics/android/layers/Layer.cpp create mode 100644 Source/WebCore/platform/graphics/android/layers/Layer.h create mode 100644 Source/WebCore/platform/graphics/android/layers/LayerAndroid.cpp create mode 100644 Source/WebCore/platform/graphics/android/layers/LayerAndroid.h create mode 100644 Source/WebCore/platform/graphics/android/layers/LayerContent.h create mode 100644 Source/WebCore/platform/graphics/android/layers/MediaLayer.cpp create mode 100644 Source/WebCore/platform/graphics/android/layers/MediaLayer.h create mode 100644 Source/WebCore/platform/graphics/android/layers/MediaListener.h create mode 100644 Source/WebCore/platform/graphics/android/layers/MediaPlayerPrivateAndroid.h create mode 100644 Source/WebCore/platform/graphics/android/layers/MediaTexture.cpp create mode 100644 Source/WebCore/platform/graphics/android/layers/MediaTexture.h create mode 100644 Source/WebCore/platform/graphics/android/layers/PictureLayerContent.cpp create mode 100644 Source/WebCore/platform/graphics/android/layers/PictureLayerContent.h create mode 100644 Source/WebCore/platform/graphics/android/layers/PictureSetLayerContent.cpp create mode 100644 Source/WebCore/platform/graphics/android/layers/PictureSetLayerContent.h create mode 100644 Source/WebCore/platform/graphics/android/layers/ScrollableLayerAndroid.cpp create mode 100644 Source/WebCore/platform/graphics/android/layers/ScrollableLayerAndroid.h create mode 100644 Source/WebCore/platform/graphics/android/layers/VideoLayerAndroid.cpp create mode 100644 Source/WebCore/platform/graphics/android/layers/VideoLayerAndroid.h create mode 100644 Source/WebCore/platform/graphics/android/layers/VideoLayerManager.cpp create mode 100644 Source/WebCore/platform/graphics/android/layers/VideoLayerManager.h create mode 100644 Source/WebCore/platform/graphics/android/rendering/BaseRenderer.cpp create mode 100644 Source/WebCore/platform/graphics/android/rendering/BaseRenderer.h create mode 100644 Source/WebCore/platform/graphics/android/rendering/DrawQuadData.h create mode 100644 Source/WebCore/platform/graphics/android/rendering/GLExtras.cpp create mode 100644 Source/WebCore/platform/graphics/android/rendering/GLExtras.h create mode 100644 Source/WebCore/platform/graphics/android/rendering/GLUtils.cpp create mode 100644 Source/WebCore/platform/graphics/android/rendering/GLUtils.h create mode 100644 Source/WebCore/platform/graphics/android/rendering/GaneshContext.cpp create mode 100644 Source/WebCore/platform/graphics/android/rendering/GaneshContext.h create mode 100644 Source/WebCore/platform/graphics/android/rendering/GaneshRenderer.cpp create mode 100644 Source/WebCore/platform/graphics/android/rendering/GaneshRenderer.h create mode 100644 Source/WebCore/platform/graphics/android/rendering/ImageTexture.cpp create mode 100644 Source/WebCore/platform/graphics/android/rendering/ImageTexture.h create mode 100644 Source/WebCore/platform/graphics/android/rendering/ImagesManager.cpp create mode 100644 Source/WebCore/platform/graphics/android/rendering/ImagesManager.h create mode 100644 Source/WebCore/platform/graphics/android/rendering/InspectorCanvas.cpp create mode 100644 Source/WebCore/platform/graphics/android/rendering/InspectorCanvas.h create mode 100644 Source/WebCore/platform/graphics/android/rendering/PaintTileOperation.cpp create mode 100644 Source/WebCore/platform/graphics/android/rendering/PaintTileOperation.h create mode 100644 Source/WebCore/platform/graphics/android/rendering/QueuedOperation.h create mode 100644 Source/WebCore/platform/graphics/android/rendering/RasterRenderer.cpp create mode 100644 Source/WebCore/platform/graphics/android/rendering/RasterRenderer.h create mode 100644 Source/WebCore/platform/graphics/android/rendering/ShaderProgram.cpp create mode 100644 Source/WebCore/platform/graphics/android/rendering/ShaderProgram.h create mode 100644 Source/WebCore/platform/graphics/android/rendering/Surface.cpp create mode 100644 Source/WebCore/platform/graphics/android/rendering/Surface.h create mode 100644 Source/WebCore/platform/graphics/android/rendering/SurfaceBacking.cpp create mode 100644 Source/WebCore/platform/graphics/android/rendering/SurfaceBacking.h create mode 100644 Source/WebCore/platform/graphics/android/rendering/SurfaceCollection.cpp create mode 100644 Source/WebCore/platform/graphics/android/rendering/SurfaceCollection.h create mode 100644 Source/WebCore/platform/graphics/android/rendering/SurfaceCollectionManager.cpp create mode 100644 Source/WebCore/platform/graphics/android/rendering/SurfaceCollectionManager.h create mode 100644 Source/WebCore/platform/graphics/android/rendering/TextureInfo.cpp create mode 100644 Source/WebCore/platform/graphics/android/rendering/TextureInfo.h create mode 100644 Source/WebCore/platform/graphics/android/rendering/TextureOwner.h create mode 100644 Source/WebCore/platform/graphics/android/rendering/TexturesGenerator.cpp create mode 100644 Source/WebCore/platform/graphics/android/rendering/TexturesGenerator.h create mode 100644 Source/WebCore/platform/graphics/android/rendering/Tile.cpp create mode 100644 Source/WebCore/platform/graphics/android/rendering/Tile.h create mode 100644 Source/WebCore/platform/graphics/android/rendering/TileGrid.cpp create mode 100644 Source/WebCore/platform/graphics/android/rendering/TileGrid.h create mode 100644 Source/WebCore/platform/graphics/android/rendering/TilePainter.h create mode 100644 Source/WebCore/platform/graphics/android/rendering/TileTexture.cpp create mode 100644 Source/WebCore/platform/graphics/android/rendering/TileTexture.h create mode 100644 Source/WebCore/platform/graphics/android/rendering/TilesManager.cpp create mode 100644 Source/WebCore/platform/graphics/android/rendering/TilesManager.h create mode 100644 Source/WebCore/platform/graphics/android/rendering/TilesProfiler.cpp create mode 100644 Source/WebCore/platform/graphics/android/rendering/TilesProfiler.h create mode 100644 Source/WebCore/platform/graphics/android/rendering/TransferQueue.cpp create mode 100644 Source/WebCore/platform/graphics/android/rendering/TransferQueue.h create mode 100644 Source/WebCore/platform/graphics/android/utils/ClassTracker.cpp create mode 100644 Source/WebCore/platform/graphics/android/utils/ClassTracker.h create mode 100644 Source/WebCore/platform/graphics/android/utils/TestExport.h diff --git a/Android.mk b/Android.mk index 6041506..61bd467 100644 --- a/Android.mk +++ b/Android.mk @@ -128,6 +128,10 @@ LOCAL_C_INCLUDES := $(LOCAL_C_INCLUDES) \ $(WEBCORE_PATH)/platform/graphics \ $(WEBCORE_PATH)/platform/graphics/android \ $(WEBCORE_PATH)/platform/graphics/android/context \ + $(WEBCORE_PATH)/platform/graphics/android/fonts \ + $(WEBCORE_PATH)/platform/graphics/android/layers \ + $(WEBCORE_PATH)/platform/graphics/android/rendering \ + $(WEBCORE_PATH)/platform/graphics/android/utils \ $(WEBCORE_PATH)/platform/graphics/filters \ $(WEBCORE_PATH)/platform/graphics/gpu \ $(WEBCORE_PATH)/platform/graphics/network \ diff --git a/CleanSpec.mk b/CleanSpec.mk index fda2cf9..d2841a3 100644 --- a/CleanSpec.mk +++ b/CleanSpec.mk @@ -81,6 +81,7 @@ $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libwebcore_int $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libwebcore_intermediates) $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libwebcore_intermediates) $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libwebcore_intermediates) +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libwebcore_intermediates) # ************************************************ # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST diff --git a/Source/WebCore/Android.mk b/Source/WebCore/Android.mk index 54c7e01..3cf8d54 100644 --- a/Source/WebCore/Android.mk +++ b/Source/WebCore/Android.mk @@ -633,70 +633,74 @@ LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \ platform/graphics/StringTruncator.cpp \ platform/graphics/WidthIterator.cpp \ \ - platform/graphics/android/AndroidAnimation.cpp \ - platform/graphics/android/BaseLayerAndroid.cpp \ - platform/graphics/android/BaseRenderer.cpp \ platform/graphics/android/BitmapAllocatorAndroid.cpp \ - platform/graphics/android/CanvasLayer.cpp \ - platform/graphics/android/CanvasTexture.cpp \ - platform/graphics/android/ClassTracker.cpp \ - platform/graphics/android/DumpLayer.cpp \ - platform/graphics/android/FixedPositioning.cpp \ - platform/graphics/android/FontAndroid.cpp \ - platform/graphics/android/FontCacheAndroid.cpp \ - platform/graphics/android/FontCustomPlatformData.cpp \ - platform/graphics/android/FontDataAndroid.cpp \ - platform/graphics/android/FontPlatformDataAndroid.cpp \ - platform/graphics/android/GaneshContext.cpp \ - platform/graphics/android/GaneshRenderer.cpp \ - platform/graphics/android/GLExtras.cpp \ - platform/graphics/android/GLUtils.cpp \ - platform/graphics/android/GLWebViewState.cpp \ - platform/graphics/android/GlyphMapAndroid.cpp \ platform/graphics/android/GradientAndroid.cpp \ platform/graphics/android/GraphicsLayerAndroid.cpp \ - platform/graphics/android/IFrameContentLayerAndroid.cpp \ - platform/graphics/android/IFrameLayerAndroid.cpp \ + platform/graphics/android/GLWebViewState.cpp \ platform/graphics/android/ImageAndroid.cpp \ platform/graphics/android/ImageBufferAndroid.cpp \ platform/graphics/android/ImageSourceAndroid.cpp \ - platform/graphics/android/ImagesManager.cpp \ - platform/graphics/android/ImageTexture.cpp \ - platform/graphics/android/InspectorCanvas.cpp \ - platform/graphics/android/Layer.cpp \ - platform/graphics/android/LayerAndroid.cpp \ - platform/graphics/android/MediaLayer.cpp \ - platform/graphics/android/MediaTexture.cpp \ - platform/graphics/android/PaintTileOperation.cpp \ platform/graphics/android/PathAndroid.cpp \ platform/graphics/android/PatternAndroid.cpp \ - platform/graphics/android/PictureLayerContent.cpp \ - platform/graphics/android/PictureSetLayerContent.cpp \ - platform/graphics/android/RasterRenderer.cpp \ - platform/graphics/android/ScrollableLayerAndroid.cpp \ platform/graphics/android/SharedBufferStream.cpp \ - platform/graphics/android/ShaderProgram.cpp \ - platform/graphics/android/Surface.cpp \ - platform/graphics/android/SurfaceBacking.cpp \ - platform/graphics/android/TextureInfo.cpp \ - platform/graphics/android/TexturesGenerator.cpp \ - platform/graphics/android/Tile.cpp \ - platform/graphics/android/TileGrid.cpp \ - platform/graphics/android/TileTexture.cpp \ - platform/graphics/android/TilesManager.cpp \ - platform/graphics/android/TilesProfiler.cpp \ - platform/graphics/android/TransferQueue.cpp \ - platform/graphics/android/SurfaceCollection.cpp \ - platform/graphics/android/SurfaceCollectionManager.cpp \ - platform/graphics/android/VerticalTextMap.cpp \ - platform/graphics/android/VideoLayerAndroid.cpp \ - platform/graphics/android/VideoLayerManager.cpp \ \ platform/graphics/android/context/GraphicsContextAndroid.cpp \ platform/graphics/android/context/GraphicsOperationCollection.cpp \ platform/graphics/android/context/PlatformGraphicsContext.cpp \ platform/graphics/android/context/PlatformGraphicsContextRecording.cpp \ - platform/graphics/android/context/PlatformGraphicsContextSkia.cpp + platform/graphics/android/context/PlatformGraphicsContextSkia.cpp \ + \ + platform/graphics/android/fonts/FontAndroid.cpp \ + platform/graphics/android/fonts/FontCacheAndroid.cpp \ + platform/graphics/android/fonts/FontCustomPlatformData.cpp \ + platform/graphics/android/fonts/FontDataAndroid.cpp \ + platform/graphics/android/fonts/FontPlatformDataAndroid.cpp \ + platform/graphics/android/fonts/GlyphMapAndroid.cpp \ + platform/graphics/android/fonts/VerticalTextMap.cpp \ + \ + platform/graphics/android/layers/AndroidAnimation.cpp \ + platform/graphics/android/layers/BaseLayerAndroid.cpp \ + platform/graphics/android/layers/CanvasLayer.cpp \ + platform/graphics/android/layers/CanvasTexture.cpp \ + platform/graphics/android/layers/DumpLayer.cpp \ + platform/graphics/android/layers/FixedPositioning.cpp \ + platform/graphics/android/layers/IFrameContentLayerAndroid.cpp \ + platform/graphics/android/layers/IFrameLayerAndroid.cpp \ + platform/graphics/android/layers/Layer.cpp \ + platform/graphics/android/layers/LayerAndroid.cpp \ + platform/graphics/android/layers/MediaLayer.cpp \ + platform/graphics/android/layers/MediaTexture.cpp \ + platform/graphics/android/layers/PictureLayerContent.cpp \ + platform/graphics/android/layers/PictureSetLayerContent.cpp \ + platform/graphics/android/layers/ScrollableLayerAndroid.cpp \ + platform/graphics/android/layers/VideoLayerAndroid.cpp \ + platform/graphics/android/layers/VideoLayerManager.cpp \ + \ + platform/graphics/android/rendering/BaseRenderer.cpp \ + platform/graphics/android/rendering/GaneshContext.cpp \ + platform/graphics/android/rendering/GaneshRenderer.cpp \ + platform/graphics/android/rendering/GLExtras.cpp \ + platform/graphics/android/rendering/GLUtils.cpp \ + platform/graphics/android/rendering/ImagesManager.cpp \ + platform/graphics/android/rendering/ImageTexture.cpp \ + platform/graphics/android/rendering/InspectorCanvas.cpp \ + platform/graphics/android/rendering/PaintTileOperation.cpp \ + platform/graphics/android/rendering/RasterRenderer.cpp \ + platform/graphics/android/rendering/ShaderProgram.cpp \ + platform/graphics/android/rendering/Surface.cpp \ + platform/graphics/android/rendering/SurfaceBacking.cpp \ + platform/graphics/android/rendering/SurfaceCollection.cpp \ + platform/graphics/android/rendering/SurfaceCollectionManager.cpp \ + platform/graphics/android/rendering/TextureInfo.cpp \ + platform/graphics/android/rendering/TexturesGenerator.cpp \ + platform/graphics/android/rendering/Tile.cpp \ + platform/graphics/android/rendering/TileGrid.cpp \ + platform/graphics/android/rendering/TileTexture.cpp \ + platform/graphics/android/rendering/TilesManager.cpp \ + platform/graphics/android/rendering/TilesProfiler.cpp \ + platform/graphics/android/rendering/TransferQueue.cpp \ + \ + platform/graphics/android/utils/ClassTracker.cpp ifeq ($(ENABLE_SVG), true) LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \ @@ -1268,5 +1272,5 @@ LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \ # For complex scripts(Arabic, Thai, Hindi...). ifeq ($(SUPPORT_COMPLEX_SCRIPTS),true) LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \ - platform/graphics/android/HarfbuzzSkia.cpp + platform/graphics/android/fonts/HarfbuzzSkia.cpp endif diff --git a/Source/WebCore/platform/graphics/FontPlatformData.h b/Source/WebCore/platform/graphics/FontPlatformData.h index a32215d..36ccbb0 100644 --- a/Source/WebCore/platform/graphics/FontPlatformData.h +++ b/Source/WebCore/platform/graphics/FontPlatformData.h @@ -36,7 +36,7 @@ #elif (PLATFORM(EFL) || PLATFORM(GTK)) && USE(PANGO) #include "pango/FontPlatformData.h" #elif PLATFORM(ANDROID) -#include "android/FontPlatformData.h" +#include "android/fonts/FontPlatformData.h" #else #ifndef FontPlatformData_h diff --git a/Source/WebCore/platform/graphics/android/AndroidAnimation.cpp b/Source/WebCore/platform/graphics/android/AndroidAnimation.cpp deleted file mode 100644 index 0ef84b9..0000000 --- a/Source/WebCore/platform/graphics/android/AndroidAnimation.cpp +++ /dev/null @@ -1,333 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "AndroidAnimation" -#define LOG_NDEBUG 1 - -#include "config.h" -#include "AndroidAnimation.h" - -#if USE(ACCELERATED_COMPOSITING) - -#include "AndroidLog.h" -#include "Animation.h" -#include "GraphicsLayerAndroid.h" -#include "Timer.h" -#include "TimingFunction.h" -#include "TranslateTransformOperation.h" -#include "UnitBezier.h" - -namespace WebCore { - -static int gUniqueId; - -static long gDebugAndroidAnimationInstances; - -long AndroidAnimation::instancesCount() -{ - return gDebugAndroidAnimationInstances; -} - -AndroidAnimation::AndroidAnimation(AnimatedPropertyID type, - const Animation* animation, - KeyframeValueList* operations, - double beginTime) - : m_beginTime(beginTime) - , m_duration(animation->duration()) - , m_fillsBackwards(animation->fillsBackwards()) - , m_fillsForwards(animation->fillsForwards()) - , m_iterationCount(animation->iterationCount()) - , m_direction(animation->direction()) - , m_timingFunction(animation->timingFunction()) - , m_type(type) - , m_operations(operations) - , m_uniqueId(++gUniqueId) - , m_hasFinished(false) -{ - ASSERT(m_timingFunction); - - gDebugAndroidAnimationInstances++; -} - -AndroidAnimation::~AndroidAnimation() -{ - gDebugAndroidAnimationInstances--; -} - -void AndroidAnimation::suggestBeginTime(double time) -{ - if (m_beginTime <= 0.000001) // overflow or not yet set - m_beginTime = time; -} - -double AndroidAnimation::elapsedTime(double time) -{ - double elapsedTime = (m_beginTime < 0.000001) ? 0 : time - m_beginTime; - - if (m_duration <= 0) - m_duration = 0.000001; - - if (elapsedTime < 0) // animation not yet started. - return 0; - - return elapsedTime; -} - -bool AndroidAnimation::checkIterationsAndProgress(double time, float* finalProgress) -{ - double progress = elapsedTime(time); - double dur = m_duration; - if (m_iterationCount > 0) - dur *= m_iterationCount; - - if (m_duration <= 0) - return false; - - // If not infinite, return false if we are done - if (m_iterationCount > 0 && progress > dur) { - *finalProgress = 1.0; - if (!m_hasFinished) { - // first time past duration, continue with progress 1.0 so the - // element's final position lines up with it's last keyframe - m_hasFinished = true; - return true; - } - - return false; - } - - double fractionalTime = progress / m_duration; - int integralTime = static_cast(fractionalTime); - - fractionalTime -= integralTime; - - if ((m_direction == Animation::AnimationDirectionAlternate) && (integralTime & 1)) - fractionalTime = 1 - fractionalTime; - - *finalProgress = fractionalTime; - return true; -} - -double AndroidAnimation::applyTimingFunction(float from, float to, double progress, - const TimingFunction* tf) -{ - double fractionalTime = progress; - double offset = from; - double scale = 1.0 / (to - from); - - if (scale != 1 || offset) - fractionalTime = (fractionalTime - offset) * scale; - - const TimingFunction* timingFunction = tf; - - if (!timingFunction) - timingFunction = m_timingFunction.get(); - - if (timingFunction && timingFunction->isCubicBezierTimingFunction()) { - const CubicBezierTimingFunction* bezierFunction = static_cast(timingFunction); - UnitBezier bezier(bezierFunction->x1(), - bezierFunction->y1(), - bezierFunction->x2(), - bezierFunction->y2()); - if (m_duration > 0) - fractionalTime = bezier.solve(fractionalTime, 1.0f / (200.0f * m_duration)); - } else if (timingFunction && timingFunction->isStepsTimingFunction()) { - const StepsTimingFunction* stepFunction = static_cast(timingFunction); - if (stepFunction->stepAtStart()) { - fractionalTime = (floor(stepFunction->numberOfSteps() * fractionalTime) + 1) / stepFunction->numberOfSteps(); - if (fractionalTime > 1.0) - fractionalTime = 1.0; - } else { - fractionalTime = floor(stepFunction->numberOfSteps() * fractionalTime) / stepFunction->numberOfSteps(); - } - } - return fractionalTime; -} - -bool AndroidAnimation::evaluate(LayerAndroid* layer, double time) -{ - float progress; - if (!checkIterationsAndProgress(time, &progress) - && !(m_fillsBackwards || m_fillsForwards)) - return false; - - if (progress < 0) { - // The animation hasn't started yet - if (m_fillsBackwards || m_beginTime <= 0.000001) { - // in this case we want to apply the initial keyframe to the layer - applyForProgress(layer, 0); - } - // we still want to be evaluated until we get progress > 0 - return true; - } - - if (progress > 1) { - if (!m_fillsForwards) - return false; - progress = 1; - } - - if (!m_operations->size()) - return false; - - applyForProgress(layer, progress); - - return true; -} - -PassRefPtr AndroidOpacityAnimation::create( - const Animation* animation, - KeyframeValueList* operations, - double beginTime) -{ - return adoptRef(new AndroidOpacityAnimation(animation, operations, - beginTime)); -} - -AndroidOpacityAnimation::AndroidOpacityAnimation(const Animation* animation, - KeyframeValueList* operations, - double beginTime) - : AndroidAnimation(AnimatedPropertyOpacity, animation, operations, beginTime) -{ -} - -void AndroidAnimation::pickValues(double progress, int* start, int* end) -{ - float distance = -1; - unsigned int foundAt = 0; - for (unsigned int i = 0; i < m_operations->size(); i++) { - const AnimationValue* value = m_operations->at(i); - float key = value->keyTime(); - float d = progress - key; - if (distance == -1 || (d >= 0 && d < distance && i + 1 < m_operations->size())) { - distance = d; - foundAt = i; - } - } - - *start = foundAt; - - if (foundAt + 1 < m_operations->size()) - *end = foundAt + 1; - else - *end = foundAt; -} - -void AndroidOpacityAnimation::applyForProgress(LayerAndroid* layer, float progress) -{ - // First, we need to get the from and to values - int from, to; - pickValues(progress, &from, &to); - FloatAnimationValue* fromValue = (FloatAnimationValue*) m_operations->at(from); - FloatAnimationValue* toValue = (FloatAnimationValue*) m_operations->at(to); - - ALOGV("[layer %d] opacity fromValue %x, key %.2f, toValue %x, key %.2f for progress %.2f", - layer->uniqueId(), - fromValue, fromValue->keyTime(), - toValue, toValue->keyTime(), progress); - - // We now have the correct two values to work with, let's compute the - // progress value - - const TimingFunction* timingFunction = fromValue->timingFunction(); - progress = applyTimingFunction(fromValue->keyTime(), toValue->keyTime(), - progress, timingFunction); - - - float value = fromValue->value() + ((toValue->value() - fromValue->value()) * progress); - - layer->setOpacity(value); -} - -PassRefPtr AndroidTransformAnimation::create( - const Animation* animation, - KeyframeValueList* operations, - double beginTime) -{ - return adoptRef(new AndroidTransformAnimation(animation, operations, beginTime)); -} - -AndroidTransformAnimation::AndroidTransformAnimation(const Animation* animation, - KeyframeValueList* operations, - double beginTime) - : AndroidAnimation(AnimatedPropertyWebkitTransform, animation, operations, beginTime) -{ -} - -void AndroidTransformAnimation::applyForProgress(LayerAndroid* layer, float progress) -{ - // First, we need to get the from and to values - int from, to; - pickValues(progress, &from, &to); - - TransformAnimationValue* fromValue = (TransformAnimationValue*) m_operations->at(from); - TransformAnimationValue* toValue = (TransformAnimationValue*) m_operations->at(to); - - ALOGV("[layer %d] fromValue %x, key %.2f, toValue %x, key %.2f for progress %.2f", - layer->uniqueId(), - fromValue, fromValue->keyTime(), - toValue, toValue->keyTime(), progress); - - // We now have the correct two values to work with, let's compute the - // progress value - - const TimingFunction* timingFunction = fromValue->timingFunction(); - float p = applyTimingFunction(fromValue->keyTime(), toValue->keyTime(), - progress, timingFunction); - ALOGV("progress %.2f => %.2f from: %.2f to: %.2f", progress, p, fromValue->keyTime(), - toValue->keyTime()); - progress = p; - - // With both values and the progress, we also need to check out that - // the operations are compatible (i.e. we are animating the same number - // of values; if not we do a matrix blend) - - TransformationMatrix transformMatrix; - bool valid = true; - unsigned int fromSize = fromValue->value()->size(); - if (fromSize) { - if (toValue->value()->size() != fromSize) - valid = false; - else { - for (unsigned int j = 0; j < fromSize && valid; j++) { - if (!fromValue->value()->operations()[j]->isSameType( - *toValue->value()->operations()[j])) - valid = false; - } - } - } - - IntSize size(layer->getSize().width(), layer->getSize().height()); - if (valid) { - for (size_t i = 0; i < toValue->value()->size(); ++i) - toValue->value()->operations()[i]->blend(fromValue->value()->at(i), - progress)->apply(transformMatrix, size); - } else { - TransformationMatrix source; - - fromValue->value()->apply(size, source); - toValue->value()->apply(size, transformMatrix); - - transformMatrix.blend(source, progress); - } - - // Set the final transform on the layer - layer->setTransform(transformMatrix); -} - -} // namespace WebCore - -#endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/android/AndroidAnimation.h b/Source/WebCore/platform/graphics/android/AndroidAnimation.h deleted file mode 100644 index dca769f..0000000 --- a/Source/WebCore/platform/graphics/android/AndroidAnimation.h +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef AndroidAnimation_h -#define AndroidAnimation_h - -#if USE(ACCELERATED_COMPOSITING) - -#include "FloatPoint.h" -#include "FloatPoint3D.h" -#include "GraphicsLayer.h" -#include "HashMap.h" -#include "LayerAndroid.h" -#include "RefPtr.h" -#include "Timer.h" -#include "TransformOperation.h" -#include "Vector.h" - -namespace WebCore { - -class TimingFunction; - -class AndroidAnimation : public ThreadSafeRefCounted { -public: - AndroidAnimation(AnimatedPropertyID type, - const Animation* animation, - KeyframeValueList* operations, - double beginTime); - - virtual ~AndroidAnimation(); - void suggestBeginTime(double time); - double elapsedTime(double time); - void pickValues(double progress, int* start, int* end); - bool checkIterationsAndProgress(double time, float* finalProgress); - double applyTimingFunction(float from, float to, double progress, - const TimingFunction* timingFunction); - bool evaluate(LayerAndroid* layer, double time); - virtual void applyForProgress(LayerAndroid* layer, float progress) = 0; - static long instancesCount(); - void setName(const String& name) { m_name = name; } - String name() { return m_name; } - AnimatedPropertyID type() { return m_type; } - bool fillsBackwards() { return m_fillsBackwards; } - bool fillsForwards() { return m_fillsForwards; } - int uniqueId() { return m_uniqueId; } - -protected: - double m_beginTime; - double m_duration; - bool m_fillsBackwards; - bool m_fillsForwards; - int m_iterationCount; - int m_direction; - RefPtr m_timingFunction; - String m_name; - AnimatedPropertyID m_type; - KeyframeValueList* m_operations; - int m_uniqueId; - bool m_hasFinished; -}; - -class AndroidOpacityAnimation : public AndroidAnimation { -public: - static PassRefPtr create(const Animation* animation, - KeyframeValueList* operations, - double beginTime); - AndroidOpacityAnimation(const Animation* animation, - KeyframeValueList* operations, - double beginTime); - - virtual void applyForProgress(LayerAndroid* layer, float progress); -}; - -class AndroidTransformAnimation : public AndroidAnimation { -public: - static PassRefPtr create( - const Animation* animation, - KeyframeValueList* operations, - double beginTime); - AndroidTransformAnimation(const Animation* animation, - KeyframeValueList* operations, - double beginTime); - - virtual void applyForProgress(LayerAndroid* layer, float progress); -}; - -} // namespace WebCore - - -#endif // USE(ACCELERATED_COMPOSITING) - -#endif // AndroidAnimation_h diff --git a/Source/WebCore/platform/graphics/android/BaseLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/BaseLayerAndroid.cpp deleted file mode 100644 index 1de5ae7..0000000 --- a/Source/WebCore/platform/graphics/android/BaseLayerAndroid.cpp +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2012, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#define LOG_TAG "BaseLayerAndroid" -#define LOG_NDEBUG 1 - -#include "config.h" -#include "BaseLayerAndroid.h" - -#include "AndroidLog.h" -#include "GLWebViewState.h" -#include "LayerContent.h" - -namespace WebCore { - -// Note: this must match the use of ID 0 specifying the base layer in DrawExtra -#define BASE_UNIQUE_ID 0 - -BaseLayerAndroid::BaseLayerAndroid(LayerContent* content) - : LayerAndroid((RenderLayer*)0) - , m_color(Color::white) -{ - setContent(content); - setSize(content->width(), content->height()); - m_uniqueId = BASE_UNIQUE_ID; -} - -void BaseLayerAndroid::getLocalTransform(SkMatrix* matrix) const -{ - // base layer doesn't use size in transform calculation - matrix->preConcat(getMatrix()); -} - -} // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/BaseLayerAndroid.h b/Source/WebCore/platform/graphics/android/BaseLayerAndroid.h deleted file mode 100644 index 0ef39c8..0000000 --- a/Source/WebCore/platform/graphics/android/BaseLayerAndroid.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2012, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef BaseLayerAndroid_h -#define BaseLayerAndroid_h - -#include "Color.h" -#include "LayerAndroid.h" - -namespace WebCore { - -class RenderLayerCompositor; - -class BaseLayerAndroid : public LayerAndroid { - -public: - BaseLayerAndroid(LayerContent* content); - - virtual ~BaseLayerAndroid() {}; - - virtual SubclassType subclassType() { return LayerAndroid::BaseLayer; } - virtual bool needsTexture() { return true; } - - void setBackgroundColor(Color& color) { m_color = color; } - Color getBackgroundColor() { return m_color; } - - virtual void getLocalTransform(SkMatrix* matrix) const; - virtual const TransformationMatrix* drawTransform() const { return 0; } - -private: - // TODO: move to SurfaceCollection. - Color m_color; -}; - -} // namespace WebCore - -#endif //BaseLayerAndroid_h diff --git a/Source/WebCore/platform/graphics/android/BaseRenderer.cpp b/Source/WebCore/platform/graphics/android/BaseRenderer.cpp deleted file mode 100644 index 833aea9..0000000 --- a/Source/WebCore/platform/graphics/android/BaseRenderer.cpp +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright 2011, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#define LOG_TAG "BaseRenderer" -#define LOG_NDEBUG 1 - -#include "config.h" -#include "BaseRenderer.h" - -#if USE(ACCELERATED_COMPOSITING) - -#include "AndroidLog.h" -#include "GaneshRenderer.h" -#include "GLUtils.h" -#include "RasterRenderer.h" -#include "SkBitmap.h" -#include "SkBitmapRef.h" -#include "SkCanvas.h" -#include "SkDevice.h" -#include "SkPicture.h" -#include "SkTypeface.h" -#include "Tile.h" -#include "TilesManager.h" - -#include - -#define UPDATE_COUNT_MASK 0xFF // displayed count wraps at 256 -#define UPDATE_COUNT_ALPHA_MASK 0x1F // alpha wraps at 32 - -namespace WebCore { - -BaseRenderer::RendererType BaseRenderer::g_currentType = BaseRenderer::Raster; - -BaseRenderer* BaseRenderer::createRenderer() -{ - if (g_currentType == Raster) - return new RasterRenderer(); - else if (g_currentType == Ganesh) - return new GaneshRenderer(); - return NULL; -} - -void BaseRenderer::swapRendererIfNeeded(BaseRenderer*& renderer) -{ - if (renderer->getType() == g_currentType) - return; - - delete renderer; - renderer = createRenderer(); -} - -void BaseRenderer::drawTileInfo(SkCanvas* canvas, - const TileRenderInfo& renderInfo, int updateCount, double renderDuration) -{ - static SkTypeface* s_typeface = 0; - if (!s_typeface) - s_typeface = SkTypeface::CreateFromName("", SkTypeface::kBold); - SkPaint paint; - paint.setTextSize(17); - char str[256]; - snprintf(str, 256, " (%d,%d) %.2fx %d %.1fms", renderInfo.x, renderInfo.y, - renderInfo.scale, updateCount, renderDuration); - paint.setARGB(128, 255, 255, 255); - canvas->drawRectCoords(0, 0, renderInfo.tileSize.fWidth, 17, paint); - paint.setARGB(255, 255, 0, 0); - paint.setTypeface(s_typeface); - canvas->drawText(str, strlen(str), 20, 15, paint); -} - -void BaseRenderer::renderTiledContent(TileRenderInfo& renderInfo) -{ - const bool visualIndicator = TilesManager::instance()->getShowVisualIndicator(); - const SkSize& tileSize = renderInfo.tileSize; - - SkCanvas canvas; - setupCanvas(renderInfo, &canvas); - - if (!canvas.getDevice()) { - // TODO: consider ALOGE - ALOGV("Error: No Device"); - return; - } - - double before; - if (visualIndicator) { - canvas.save(); - before = currentTimeMS(); - } - - setupPartialInval(renderInfo, &canvas); - canvas.translate(-renderInfo.x * tileSize.width(), -renderInfo.y * tileSize.height()); - canvas.scale(renderInfo.scale, renderInfo.scale); - renderInfo.tilePainter->paint(renderInfo.baseTile, &canvas); - if (renderInfo.baseTile && renderInfo.baseTile->backTexture()) - checkForPureColor(renderInfo, &canvas); - else - renderInfo.isPureColor = false; - - if (visualIndicator) { - double after = currentTimeMS(); - canvas.restore(); - unsigned int updateCount = renderInfo.tilePainter->getUpdateCount() & UPDATE_COUNT_MASK; - const int color = updateCount & UPDATE_COUNT_ALPHA_MASK; - - // only color the invalidated area - SkPaint paint; - paint.setARGB(color, 0, 255, 0); - if (renderInfo.invalRect) - canvas.drawIRect(*renderInfo.invalRect, paint); - else { - SkIRect rect; - rect.set(0, 0, tileSize.width(), tileSize.height()); - canvas.drawIRect(rect, paint); - } - - if (renderInfo.invalRect) { - // if partial inval... - int x = renderInfo.invalRect->fLeft; - int y = renderInfo.invalRect->fTop; - int w = renderInfo.invalRect->width(); - int h = renderInfo.invalRect->height(); - - paint.setARGB(128, 255, 255, 0); - canvas.drawLine(x, y, x + w, y + h, paint); - canvas.drawLine(x, y + h, x + w, y, paint); - } - drawTileInfo(&canvas, renderInfo, updateCount, after - before); - - // paint the tile boundaries - paint.setARGB(64, 255, 0, 0); - paint.setStrokeWidth(3); - canvas.drawLine(0, 0, tileSize.width(), tileSize.height(), paint); - paint.setARGB(64, 0, 255, 0); - canvas.drawLine(0, tileSize.height(), tileSize.width(), 0, paint); - paint.setARGB(128, 0, 0, 255); - canvas.drawLine(tileSize.width(), 0, tileSize.width(), tileSize.height(), paint); - } - renderingComplete(renderInfo, &canvas); -} - -} // namespace WebCore - -#endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/android/BaseRenderer.h b/Source/WebCore/platform/graphics/android/BaseRenderer.h deleted file mode 100644 index f225871..0000000 --- a/Source/WebCore/platform/graphics/android/BaseRenderer.h +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright 2011, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef BaseRenderer_h -#define BaseRenderer_h - -#if USE(ACCELERATED_COMPOSITING) - -#include "Color.h" -#include "SkRect.h" -#include - -class SkCanvas; -class SkDevice; - -namespace WebCore { - -class TextureInfo; -class TilePainter; -class Tile; - -struct TileRenderInfo { - // coordinates of the tile - int x; - int y; - - // current scale factor - float scale; - - // inval rectangle with coordinates in the tile's coordinate space - SkIRect* invalRect; - - // the expected size of the tile - SkSize tileSize; - - // the painter object in charge of drawing our content - TilePainter* tilePainter; - - // the base tile calling us - Tile* baseTile; - - // info about the texture that we are to render into - TextureInfo* textureInfo; - - bool isPureColor; - Color pureColor; -}; - -/** - * - */ -class BaseRenderer { -public: - enum RendererType { Raster, Ganesh }; - BaseRenderer(RendererType type) : m_type(type) {} - virtual ~BaseRenderer() {} - - void renderTiledContent(TileRenderInfo& renderInfo); - - RendererType getType() { return m_type; } - - static BaseRenderer* createRenderer(); - static void swapRendererIfNeeded(BaseRenderer*& renderer); - static RendererType getCurrentRendererType() { return g_currentType; } - static void setCurrentRendererType(RendererType type) { g_currentType = type; } - -protected: - - virtual void setupCanvas(const TileRenderInfo& renderInfo, SkCanvas* canvas) = 0; - virtual void setupPartialInval(const TileRenderInfo& renderInfo, SkCanvas* canvas) {} - virtual void renderingComplete(const TileRenderInfo& renderInfo, SkCanvas* canvas) = 0; - virtual void checkForPureColor(TileRenderInfo& renderInfo, SkCanvas* canvas) = 0; - - void drawTileInfo(SkCanvas* canvas, const TileRenderInfo& renderInfo, - int updateCount, double renderDuration); - -private: - RendererType m_type; - static RendererType g_currentType; -}; - -} // namespace WebCore - -#endif // USE(ACCELERATED_COMPOSITING) -#endif // BaseRenderer_h diff --git a/Source/WebCore/platform/graphics/android/CanvasLayer.cpp b/Source/WebCore/platform/graphics/android/CanvasLayer.cpp deleted file mode 100644 index 1813903..0000000 --- a/Source/WebCore/platform/graphics/android/CanvasLayer.cpp +++ /dev/null @@ -1,220 +0,0 @@ -/* - * Copyright 2012, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#define LOG_TAG "CanvasLayer" -#define LOG_NDEBUG 1 - -#include "config.h" -#include "CanvasLayer.h" - -#if USE(ACCELERATED_COMPOSITING) - -#include "AndroidLog.h" -#include "CanvasTexture.h" -#include "DrawQuadData.h" -#include "Image.h" -#include "ImageBuffer.h" -#include "RenderLayerCompositor.h" -#include "SkBitmap.h" -#include "SkBitmapRef.h" -#include "SkCanvas.h" -#include "TilesManager.h" - -namespace WebCore { - -CanvasLayer::CanvasLayer(RenderLayer* owner, HTMLCanvasElement* canvas) - : LayerAndroid(owner) - , m_canvas(canvas) - , m_dirtyCanvas() - , m_bitmap(0) -{ - init(); - m_canvas->addObserver(this); -} - -CanvasLayer::CanvasLayer(const CanvasLayer& layer) - : LayerAndroid(layer) - , m_canvas(0) - , m_bitmap(0) -{ - init(); - if (!layer.m_canvas) { - // The canvas has already been destroyed - this shouldn't happen - ALOGW("Creating a CanvasLayer for a destroyed canvas!"); - m_contentRect = IntRect(); - m_offsetFromRenderer = IntSize(); - m_texture->setHwAccelerated(false); - return; - } - // We are making a copy for the UI, sync the interesting bits - m_contentRect = layer.contentRect(); - m_offsetFromRenderer = layer.offsetFromRenderer(); - bool previousState = m_texture->hasValidTexture(); - if (!previousState && layer.m_dirtyCanvas.isEmpty()) { - // We were previously in software and don't have anything new to draw, - // so stay in software - m_bitmap = layer.bitmap(); - SkSafeRef(m_bitmap); - } else { - // Attempt to upload to a surface texture - if (!m_texture->uploadImageBuffer(layer.m_canvas->buffer())) { - // Blargh, no surface texture or ImageBuffer - fall back to software - m_bitmap = layer.bitmap(); - SkSafeRef(m_bitmap); - // Merge the canvas invals with the layer's invals to repaint the needed - // tiles. - SkRegion::Iterator iter(layer.m_dirtyCanvas); - const IntPoint& offset = m_contentRect.location(); - for (; !iter.done(); iter.next()) { - SkIRect diff = iter.rect(); - diff.fLeft += offset.x(); - diff.fRight += offset.x(); - diff.fTop += offset.y(); - diff.fBottom += offset.y(); - m_dirtyRegion.op(diff, SkRegion::kUnion_Op); - } - } - if (previousState != m_texture->hasValidTexture()) { - // Need to do a full inval of the canvas content as we are mode switching - m_dirtyRegion.op(m_contentRect.x(), m_contentRect.y(), - m_contentRect.maxX(), m_contentRect.maxY(), SkRegion::kUnion_Op); - } - } -} - -CanvasLayer::~CanvasLayer() -{ - if (m_canvas) - m_canvas->removeObserver(this); - SkSafeUnref(m_bitmap); -} - -void CanvasLayer::init() -{ - m_texture = CanvasTexture::getCanvasTexture(this); -} - -void CanvasLayer::canvasChanged(HTMLCanvasElement*, const FloatRect& changedRect) -{ - if (!m_texture->hasValidTexture()) { - // We only need to track invals if we aren't using a SurfaceTexture. - // If we drop out of hwa, we will do a full inval anyway - SkIRect irect = SkIRect::MakeXYWH(changedRect.x(), changedRect.y(), - changedRect.width(), changedRect.height()); - m_dirtyCanvas.op(irect, SkRegion::kUnion_Op); - } - owningLayer()->compositor()->scheduleLayerFlush(); -} - -void CanvasLayer::canvasResized(HTMLCanvasElement*) -{ - const IntSize& size = m_canvas->size(); - m_dirtyCanvas.setRect(0, 0, size.width(), size.height()); - // If we are smaller than one tile, don't bother using a surface texture - if (size.width() <= TilesManager::tileWidth() - && size.height() <= TilesManager::tileHeight()) - m_texture->setSize(IntSize()); - else - m_texture->setSize(size); -} - -void CanvasLayer::canvasDestroyed(HTMLCanvasElement*) -{ - m_canvas = 0; -} - -void CanvasLayer::clearDirtyRegion() -{ - LayerAndroid::clearDirtyRegion(); - m_dirtyCanvas.setEmpty(); - if (m_canvas) - m_canvas->clearDirtyRect(); -} - -SkBitmapRef* CanvasLayer::bitmap() const -{ - if (!m_canvas || !m_canvas->buffer()) - return 0; - return m_canvas->copiedImage()->nativeImageForCurrentFrame(); -} - -IntRect CanvasLayer::contentRect() const -{ - if (!m_canvas - || !m_canvas->renderer() - || !m_canvas->renderer()->style() - || !m_canvas->inDocument() - || m_canvas->renderer()->style()->visibility() != VISIBLE) - return IntRect(); - return m_canvas->renderBox()->contentBoxRect(); -} - -IntSize CanvasLayer::offsetFromRenderer() const -{ - return m_canvas->renderBox()->layer()->backing()->graphicsLayer()->offsetFromRenderer(); -} - -bool CanvasLayer::needsTexture() -{ - return m_bitmap || LayerAndroid::needsTexture(); -} - -void CanvasLayer::contentDraw(SkCanvas* canvas, PaintStyle style) -{ - LayerAndroid::contentDraw(canvas, style); - if (!m_bitmap) - return; - SkBitmap& bitmap = m_bitmap->bitmap(); - SkRect dst = SkRect::MakeXYWH(m_contentRect.x() - m_offsetFromRenderer.width(), - m_contentRect.y() - m_offsetFromRenderer.height(), - m_contentRect.width(), m_contentRect.height()); - canvas->drawBitmapRect(bitmap, 0, dst, 0); -} - -bool CanvasLayer::drawGL(bool layerTilesDisabled) -{ - bool ret = LayerAndroid::drawGL(layerTilesDisabled); - m_texture->requireTexture(); - if (!m_bitmap && m_texture->updateTexImage()) { - SkRect rect = SkRect::MakeXYWH(m_contentRect.x() - m_offsetFromRenderer.width(), - m_contentRect.y() - m_offsetFromRenderer.height(), - m_contentRect.width(), m_contentRect.height()); - TextureQuadData data(m_texture->texture(), GL_TEXTURE_EXTERNAL_OES, - GL_LINEAR, LayerQuad, &m_drawTransform, &rect); - TilesManager::instance()->shader()->drawQuad(&data); - } - return ret; -} - -LayerAndroid::InvalidateFlags CanvasLayer::onSetHwAccelerated(bool hwAccelerated) -{ - if (m_texture->setHwAccelerated(hwAccelerated)) - return LayerAndroid::InvalidateLayers; - return LayerAndroid::InvalidateNone; -} - -} // namespace WebCore - -#endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/android/CanvasLayer.h b/Source/WebCore/platform/graphics/android/CanvasLayer.h deleted file mode 100644 index 532dbf2..0000000 --- a/Source/WebCore/platform/graphics/android/CanvasLayer.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright 2012, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef CanvasLayer_h -#define CanvasLayer_h - -#if USE(ACCELERATED_COMPOSITING) - -#include "HTMLCanvasElement.h" -#include "ImageData.h" -#include "LayerAndroid.h" -#include "RenderLayer.h" - -#include - -namespace WebCore { - -class CanvasTexture; - -class CanvasLayer : public LayerAndroid, private CanvasObserver { -public: - CanvasLayer(RenderLayer* owner, HTMLCanvasElement* canvas); - CanvasLayer(const CanvasLayer& layer); - virtual ~CanvasLayer(); - - virtual LayerAndroid* copy() const { return new CanvasLayer(*this); } - virtual SubclassType subclassType() { return LayerAndroid::CanvasLayer; } - virtual void clearDirtyRegion(); - - virtual bool drawGL(bool layerTilesDisabled); - virtual void contentDraw(SkCanvas* canvas, PaintStyle style); - virtual bool needsTexture(); - -protected: - virtual InvalidateFlags onSetHwAccelerated(bool hwAccelerated); - -private: - virtual void canvasChanged(HTMLCanvasElement*, const FloatRect& changedRect); - virtual void canvasResized(HTMLCanvasElement*); - virtual void canvasDestroyed(HTMLCanvasElement*); - - void init(); - SkBitmapRef* bitmap() const; - IntRect contentRect() const; - IntSize offsetFromRenderer() const; - - HTMLCanvasElement* m_canvas; - IntRect m_contentRect; - IntSize m_offsetFromRenderer; - SkRegion m_dirtyCanvas; - SkBitmapRef* m_bitmap; - RefPtr m_texture; -}; - -} // namespace WebCore - -#endif // USE(ACCELERATED_COMPOSITING) - -#endif // CanvasLayer_h diff --git a/Source/WebCore/platform/graphics/android/CanvasTexture.cpp b/Source/WebCore/platform/graphics/android/CanvasTexture.cpp deleted file mode 100644 index e4b2bc6..0000000 --- a/Source/WebCore/platform/graphics/android/CanvasTexture.cpp +++ /dev/null @@ -1,225 +0,0 @@ -/* - * Copyright 2012, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#define LOG_TAG "CanvasTexture" -#define LOG_NDEBUG 1 - -#include "config.h" -#include "CanvasTexture.h" - -#if USE(ACCELERATED_COMPOSITING) - -#include "android_graphics.h" -#include "AndroidLog.h" -#include "GLUtils.h" -#include "Image.h" -#include "ImageBuffer.h" -#include "SkBitmap.h" -#include "SkBitmapRef.h" -#include "SkDevice.h" -#include "SkPixelRef.h" - -#include -#include -#include - -namespace WebCore { - -static int s_maxTextureSize = 0; -static HashMap s_textures; -static android::Mutex s_texturesLock; - -/******************************************** - * Called by both threads - ********************************************/ - -PassRefPtr CanvasTexture::getCanvasTexture(CanvasLayer* layer) -{ - android::Mutex::Autolock lock(s_texturesLock); - RefPtr texture = s_textures.get(layer->uniqueId()); - if (texture.get()) - return texture.release(); - return adoptRef(new CanvasTexture(layer->uniqueId())); -} - -bool CanvasTexture::setHwAccelerated(bool hwAccelerated) -{ - android::Mutex::Autolock lock(m_surfaceLock); - if (m_useHwAcceleration == hwAccelerated) - return false; - m_useHwAcceleration = hwAccelerated; - if (!m_ANW.get()) - return false; - destroySurfaceTextureLocked(); - return true; -} - -/******************************************** - * Called by WebKit thread - ********************************************/ - -void CanvasTexture::setSize(const IntSize& size) -{ - android::Mutex::Autolock lock(m_surfaceLock); - if (m_size == size) - return; - m_size = size; - if (m_ANW.get()) { - if (useSurfaceTexture()) { - int result = native_window_set_buffers_dimensions(m_ANW.get(), - m_size.width(), m_size.height()); - GLUtils::checkSurfaceTextureError("native_window_set_buffers_dimensions", result); - if (result != NO_ERROR) - m_useHwAcceleration = false; // On error, drop out of HWA - } - if (!useSurfaceTexture()) - destroySurfaceTextureLocked(); - } -} - -SurfaceTextureClient* CanvasTexture::nativeWindow() -{ - android::Mutex::Autolock lock(m_surfaceLock); - if (m_ANW.get()) - return m_ANW.get(); - if (!m_texture) - return 0; - if (!useSurfaceTexture()) - return 0; - m_surfaceTexture = new android::SurfaceTexture(m_texture, false); - m_ANW = new android::SurfaceTextureClient(m_surfaceTexture); - int result = native_window_set_buffers_format(m_ANW.get(), HAL_PIXEL_FORMAT_RGBA_8888); - GLUtils::checkSurfaceTextureError("native_window_set_buffers_format", result); - if (result == NO_ERROR) { - result = native_window_set_buffers_dimensions(m_ANW.get(), - m_size.width(), m_size.height()); - GLUtils::checkSurfaceTextureError("native_window_set_buffers_dimensions", result); - } - if (result != NO_ERROR) { - m_useHwAcceleration = false; - destroySurfaceTextureLocked(); - return 0; - } - return m_ANW.get(); -} - -bool CanvasTexture::uploadImageBuffer(ImageBuffer* imageBuffer) -{ - m_hasValidTexture = false; - SurfaceTextureClient* anw = nativeWindow(); - if (!anw) - return false; - // Size mismatch, early abort (will fall back to software) - if (imageBuffer->size() != m_size) - return false; - GraphicsContext* gc = imageBuffer ? imageBuffer->context() : 0; - if (!gc) - return false; - const SkBitmap& bitmap = android_gc2canvas(gc)->getDevice()->accessBitmap(false); - if (!GLUtils::updateSharedSurfaceTextureWithBitmap(anw, bitmap)) - return false; - m_hasValidTexture = true; - return true; -} - -/******************************************** - * Called by UI thread WITH GL context - ********************************************/ - -CanvasTexture::~CanvasTexture() -{ - if (m_layerId) { - s_texturesLock.lock(); - s_textures.remove(m_layerId); - s_texturesLock.unlock(); - } - if (m_texture) - GLUtils::deleteTexture(&m_texture); -} - -void CanvasTexture::requireTexture() -{ - android::Mutex::Autolock lock(m_surfaceLock); - if (!m_texture) - glGenTextures(1, &m_texture); - if (!s_maxTextureSize) - glGetIntegerv(GL_MAX_TEXTURE_SIZE, &s_maxTextureSize); -} - -bool CanvasTexture::updateTexImage() -{ - android::Mutex::Autolock lock(m_surfaceLock); - if (!m_surfaceTexture.get()) - return false; - status_t result = m_surfaceTexture->updateTexImage(); - if (result != OK) { - ALOGE("unexpected error: updateTexImage return %d", result); - return false; - } - return true; -} - -/******************************************** - * Called by both threads - ********************************************/ - -void CanvasTexture::destroySurfaceTextureLocked() -{ - if (m_ANW.get()) { - m_ANW.clear(); - m_surfaceTexture->abandon(); - m_surfaceTexture.clear(); - } -} - -/******************************************** - * Called by WebKit thread - ********************************************/ - -CanvasTexture::CanvasTexture(int layerId) - : m_size() - , m_layerId(layerId) - , m_texture(0) - , m_surfaceTexture(0) - , m_ANW(0) - , m_hasValidTexture(false) - , m_useHwAcceleration(true) -{ - s_textures.add(m_layerId, this); -} - -// TODO: Have a global limit as well as a way to react to low memory situations -bool CanvasTexture::useSurfaceTexture() -{ - if (!m_useHwAcceleration) - return false; - if (m_size.isEmpty()) - return false; - return (m_size.width() < s_maxTextureSize) && (m_size.height() < s_maxTextureSize); -} - -} // namespace WebCore - -#endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/android/CanvasTexture.h b/Source/WebCore/platform/graphics/android/CanvasTexture.h deleted file mode 100644 index 98962a0..0000000 --- a/Source/WebCore/platform/graphics/android/CanvasTexture.h +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright 2012, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef CanvasTexture_h -#define CanvasTexture_h - -#if USE(ACCELERATED_COMPOSITING) - -#include "CanvasLayer.h" - -#include -#include - -namespace android { -class SurfaceTexture; -class SurfaceTextureClient; -} - -namespace WebCore { - -class CanvasTexture : public ThreadSafeRefCounted { - -public: - /******************************************** - * Called by both threads - ********************************************/ - static PassRefPtr getCanvasTexture(CanvasLayer* layer); - bool setHwAccelerated(bool hwAccelerated); - - /******************************************** - * Called by WebKit thread - ********************************************/ - void setSize(const IntSize& size); - SurfaceTextureClient* nativeWindow(); - bool uploadImageBuffer(ImageBuffer* imageBuffer); - bool hasValidTexture() { return m_hasValidTexture; } - - /******************************************** - * Called by UI thread WITH GL context - ********************************************/ - virtual ~CanvasTexture(); - void requireTexture(); - GLuint texture() { requireTexture(); return m_texture; } - bool updateTexImage(); - -private: - /******************************************** - * Called by both threads - ********************************************/ - void destroySurfaceTextureLocked(); - - /******************************************** - * Called by WebKit thread - ********************************************/ - CanvasTexture(int layerId); - bool useSurfaceTexture(); - - IntSize m_size; - int m_layerId; - GLuint m_texture; - android::Mutex m_surfaceLock; - sp m_surfaceTexture; - sp m_ANW; - bool m_hasValidTexture; - bool m_useHwAcceleration; - -}; - -} // namespace WebCore - -#endif // USE(ACCELERATED_COMPOSITING) - -#endif // CanvasTexture_h diff --git a/Source/WebCore/platform/graphics/android/ClassTracker.cpp b/Source/WebCore/platform/graphics/android/ClassTracker.cpp deleted file mode 100644 index 98e33d9..0000000 --- a/Source/WebCore/platform/graphics/android/ClassTracker.cpp +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright 2010, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#define LOG_TAG "ClassTracker" -#define LOG_NDEBUG 1 - -#include "config.h" -#include "ClassTracker.h" - -#include "AndroidLog.h" -#include "LayerAndroid.h" -#include "TilesManager.h" - -#include - -#define DEBUG_LAYERS -#undef DEBUG_LAYERS - -namespace WebCore { - -ClassTracker* ClassTracker::instance() -{ - if (!gInstance) - gInstance = new ClassTracker(); - return gInstance; -} - -ClassTracker* ClassTracker::gInstance = 0; - -void ClassTracker::increment(String name) -{ - android::Mutex::Autolock lock(m_lock); - int value = 0; - if (m_classes.contains(name)) - value = m_classes.get(name); - - m_classes.set(name, value + 1); -} - -void ClassTracker::decrement(String name) -{ - android::Mutex::Autolock lock(m_lock); - int value = 0; - if (m_classes.contains(name)) - value = m_classes.get(name); - - m_classes.set(name, value - 1); -} - -void ClassTracker::add(LayerAndroid* layer) -{ - android::Mutex::Autolock lock(m_lock); - m_layers.append(layer); -} - -void ClassTracker::remove(LayerAndroid* layer) -{ - android::Mutex::Autolock lock(m_lock); - m_layers.remove(m_layers.find(layer)); -} - -void ClassTracker::show() -{ - android::Mutex::Autolock lock(m_lock); - ALOGD("*** Tracking %d classes ***", m_classes.size()); - for (HashMap::iterator iter = m_classes.begin(); iter != m_classes.end(); ++iter) { - ALOGD("class %s has %d instances", - iter->first.latin1().data(), iter->second); - } - ALOGD("*** %d Layers ***", m_layers.size()); - int nbTextures = 0; - int nbAllocatedTextures = 0; - int nbLayerTextures = 0; - int nbAllocatedLayerTextures = 0; - float textureSize = 256 * 256 * 4 / 1024.0 / 1024.0; - TilesManager::instance()->gatherTexturesNumbers(&nbTextures, &nbAllocatedTextures, - &nbLayerTextures, &nbAllocatedLayerTextures); - ALOGD("*** textures: %d/%d (%.2f Mb), layer textures: %d/%d (%.2f Mb) : total used %.2f Mb", - nbAllocatedTextures, nbTextures, - nbAllocatedTextures * textureSize, - nbAllocatedLayerTextures, nbLayerTextures, - nbAllocatedLayerTextures * textureSize, - (nbAllocatedTextures + nbAllocatedLayerTextures) * textureSize); - -#ifdef DEBUG_LAYERS - for (unsigned int i = 0; i < m_layers.size(); i++) { - LayerAndroid* layer = m_layers[i]; - ALOGD("[%d/%d] layer %x (%.2f, %.2f) of type %d, refcount(%d) has texture %x has image ref %x (%x) root: %x parent: %x", - i, m_layers.size(), layer, - layer->getWidth(), layer->getHeight(), - layer->type(), layer->getRefCnt(), - layer->texture(), layer->imageRef(), - layer->imageTexture(), (LayerAndroid*) layer->getRootLayer(), - (LayerAndroid*) layer->getParent()); - } -#endif -} - -} // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/ClassTracker.h b/Source/WebCore/platform/graphics/android/ClassTracker.h deleted file mode 100644 index d169883..0000000 --- a/Source/WebCore/platform/graphics/android/ClassTracker.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2010, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef ClassTracker_h -#define ClassTracker_h - -#include -#include -#include - -#define DEBUG_COUNT // Add instances tracking -#undef DEBUG_COUNT - -namespace WebCore { - -class LayerAndroid; - -class ClassTracker { -public: - static ClassTracker* instance(); - void show(); - void increment(String name); - void decrement(String name); - void add(LayerAndroid*); - void remove(LayerAndroid*); -private: - ClassTracker() {}; - HashMap m_classes; - Vector m_layers; - static ClassTracker* gInstance; - android::Mutex m_lock; -}; - -} - -#endif // ClassTracker_h diff --git a/Source/WebCore/platform/graphics/android/DrawQuadData.h b/Source/WebCore/platform/graphics/android/DrawQuadData.h deleted file mode 100644 index 687808d..0000000 --- a/Source/WebCore/platform/graphics/android/DrawQuadData.h +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Copyright 2012, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef DrawQuadData_h -#define DrawQuadData_h - -#if USE(ACCELERATED_COMPOSITING) - -#include "Color.h" -#include "SkRect.h" -#include - -namespace WebCore { - -class TransformationMatrix; - -enum DrawQuadType { - BaseQuad, - LayerQuad, - Blit // 1:1 straight pixel blit -}; - -// Both PureColorQuadData and TextureQuadData share the data from DrawQuadData. -class DrawQuadData { -public: - DrawQuadData(DrawQuadType type = BaseQuad, - const TransformationMatrix* drawMatrix = 0, - const SkRect* geometry = 0, - float opacity = 1.0f, - bool forceBlending = true) - : m_type(type) - , m_drawMatrix(drawMatrix) - , m_geometry(geometry) - , m_opacity(opacity) - , m_forceBlending(forceBlending) - { - } - - DrawQuadData(const DrawQuadData& data) - : m_type(data.m_type) - , m_drawMatrix(data.m_drawMatrix) - , m_geometry(data.m_geometry) - , m_opacity(data.m_opacity) - , m_forceBlending(data.m_forceBlending) - { - } - - virtual ~DrawQuadData() {}; - - DrawQuadType type() const { return m_type; } - const TransformationMatrix* drawMatrix() const { return m_drawMatrix; } - const SkRect* geometry() const { return m_geometry; } - float opacity() const { return m_opacity; } - bool forceBlending() const { return m_forceBlending; } - - void updateDrawMatrix(TransformationMatrix* matrix) { m_drawMatrix = matrix; } - void updateGeometry(SkRect* rect) { m_geometry = rect; } - void updateOpacity(float opacity) { m_opacity = opacity; } - - virtual bool pureColor() const { return false; } - - virtual Color quadColor() const { return Color(); } - - virtual int textureId() const { return 0; } - virtual GLint textureFilter() const { return 0; } - virtual GLenum textureTarget() const { return 0; } - -private: - DrawQuadType m_type; - const TransformationMatrix* m_drawMatrix; - const SkRect* m_geometry; - float m_opacity; - bool m_forceBlending; -}; - -class PureColorQuadData : public DrawQuadData { -public: - PureColorQuadData(Color color, - DrawQuadType type = BaseQuad, - const TransformationMatrix* drawMatrix = 0, - const SkRect* geometry = 0, - float opacity = 1.0f, - bool forceBlending = true) - : DrawQuadData(type, drawMatrix, geometry, opacity, forceBlending) - { - m_quadColor = color; - } - - PureColorQuadData(const DrawQuadData& data, Color color) - : DrawQuadData(data) - { - m_quadColor = color; - } - - virtual ~PureColorQuadData() {}; - virtual bool pureColor() const { return true; } - virtual Color quadColor() const { return m_quadColor; } - void updateColor(const Color& color) { m_quadColor = color; } - -private: - Color m_quadColor; -}; - -class TextureQuadData : public DrawQuadData { -public: - TextureQuadData(int textureId, - GLenum textureTarget = GL_TEXTURE_2D, - GLint textureFilter = GL_LINEAR, - DrawQuadType type = BaseQuad, - const TransformationMatrix* drawMatrix = 0, - const SkRect* geometry = 0, - float opacity = 1.0f, - bool forceBlending = true) - : DrawQuadData(type, drawMatrix, geometry, opacity, forceBlending) - { - m_textureId = textureId; - m_textureTarget = textureTarget; - m_textureFilter = textureFilter; - } - - TextureQuadData(const DrawQuadData& data, - int textureId, - GLenum textureTarget = GL_TEXTURE_2D, - GLint textureFilter = GL_LINEAR) - : DrawQuadData(data) - { - m_textureId = textureId; - m_textureTarget = textureTarget; - m_textureFilter = textureFilter; - } - - virtual ~TextureQuadData() {}; - virtual bool pureColor() const { return false; } - - virtual int textureId() const { return m_textureId; } - virtual GLint textureFilter() const { return m_textureFilter; } - virtual GLenum textureTarget() const { return m_textureTarget; } - - void updateTextureId(int newId) { m_textureId = newId; } - -private: - int m_textureId; - GLint m_textureFilter; - GLenum m_textureTarget; -}; - -} // namespace WebCore - -#endif // USE(ACCELERATED_COMPOSITING) -#endif // DrawQuadData_h diff --git a/Source/WebCore/platform/graphics/android/DumpLayer.cpp b/Source/WebCore/platform/graphics/android/DumpLayer.cpp deleted file mode 100644 index 5551965..0000000 --- a/Source/WebCore/platform/graphics/android/DumpLayer.cpp +++ /dev/null @@ -1,83 +0,0 @@ -#include "config.h" -#include "DumpLayer.h" - -#if USE(ACCELERATED_COMPOSITING) - -namespace WebCore { - -void lwrite(FILE* file, const char* str) -{ - fwrite(str, sizeof(char), strlen(str), file); -} - -void writeIndent(FILE* file, int indentLevel) -{ - if (indentLevel) - fprintf(file, "%*s", indentLevel*2, " "); -} - -void writeln(FILE* file, int indentLevel, const char* str) -{ - writeIndent(file, indentLevel); - lwrite(file, str); - lwrite(file, "\n"); -} - -void writeIntVal(FILE* file, int indentLevel, const char* str, int value) -{ - writeIndent(file, indentLevel); - fprintf(file, "%s = %d;\n", str, value); -} - -void writeHexVal(FILE* file, int indentLevel, const char* str, int value) -{ - writeIndent(file, indentLevel); - fprintf(file, "%s = %x;\n", str, value); -} - -void writeFloatVal(FILE* file, int indentLevel, const char* str, float value) -{ - writeIndent(file, indentLevel); - fprintf(file, "%s = %.3f;\n", str, value); -} - -void writePoint(FILE* file, int indentLevel, const char* str, SkPoint point) -{ - writeIndent(file, indentLevel); - fprintf(file, "%s = { x = %.3f; y = %.3f; };\n", str, point.fX, point.fY); -} - -void writeIntPoint(FILE* file, int indentLevel, const char* str, IntPoint point) -{ - writeIndent(file, indentLevel); - fprintf(file, "%s = { x = %d; y = %d; };\n", str, point.x(), point.y()); -} - -void writeSize(FILE* file, int indentLevel, const char* str, SkSize size) -{ - writeIndent(file, indentLevel); - fprintf(file, "%s = { w = %.3f; h = %.3f; };\n", str, size.width(), size.height()); -} - -void writeRect(FILE* file, int indentLevel, const char* str, SkRect rect) -{ - writeIndent(file, indentLevel); - fprintf(file, "%s = { x = %.3f; y = %.3f; w = %.3f; h = %.3f; };\n", - str, rect.fLeft, rect.fTop, rect.width(), rect.height()); -} - -void writeMatrix(FILE* file, int indentLevel, const char* str, const TransformationMatrix& matrix) -{ - writeIndent(file, indentLevel); - fprintf(file, "%s = { (%.2f,%.2f,%.2f,%.2f),(%.2f,%.2f,%.2f,%.2f)," - "(%.2f,%.2f,%.2f,%.2f),(%.2f,%.2f,%.2f,%.2f) };\n", - str, - matrix.m11(), matrix.m12(), matrix.m13(), matrix.m14(), - matrix.m21(), matrix.m22(), matrix.m23(), matrix.m24(), - matrix.m31(), matrix.m32(), matrix.m33(), matrix.m34(), - matrix.m41(), matrix.m42(), matrix.m43(), matrix.m44()); -} - -} // namespace WebCore - -#endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/android/DumpLayer.h b/Source/WebCore/platform/graphics/android/DumpLayer.h deleted file mode 100644 index 5b30952..0000000 --- a/Source/WebCore/platform/graphics/android/DumpLayer.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef DumpLayer_h -#define DumpLayer_h - -#include "IntPoint.h" -#include "SkPoint.h" -#include "SkRect.h" -#include "SkSize.h" -#include "TransformationMatrix.h" - -// Debug tools : dump the layers tree in a file. -// The format is simple: -// properties have the form: key = value; -// all statements are finished with a semi-colon. -// value can be: -// - int -// - float -// - array of elements -// - composed type -// a composed type enclose properties in { and } -// an array enclose composed types in { }, separated with a comma. -// exemple: -// { -// x = 3; -// y = 4; -// value = { -// x = 3; -// y = 4; -// }; -// anarray = [ -// { x = 3; }, -// { y = 4; } -// ]; -// } - -namespace WebCore { - -void lwrite(FILE* file, const char* str); -void writeIndent(FILE* file, int indentLevel); -void writeln(FILE* file, int indentLevel, const char* str); -void writeIntVal(FILE* file, int indentLevel, const char* str, int value); -void writeHexVal(FILE* file, int indentLevel, const char* str, int value); -void writeFloatVal(FILE* file, int indentLevel, const char* str, float value); -void writePoint(FILE* file, int indentLevel, const char* str, SkPoint point); -void writeIntPoint(FILE* file, int indentLevel, const char* str, IntPoint point); -void writeSize(FILE* file, int indentLevel, const char* str, SkSize size); -void writeRect(FILE* file, int indentLevel, const char* str, SkRect rect); -void writeMatrix(FILE* file, int indentLevel, const char* str, const TransformationMatrix& matrix); - -} - -#endif // DumpLayer_h diff --git a/Source/WebCore/platform/graphics/android/FixedPositioning.cpp b/Source/WebCore/platform/graphics/android/FixedPositioning.cpp deleted file mode 100644 index c7909c4..0000000 --- a/Source/WebCore/platform/graphics/android/FixedPositioning.cpp +++ /dev/null @@ -1,106 +0,0 @@ -#define LOG_TAG "FixedPositioning" -#define LOG_NDEBUG 1 - -#include "config.h" -#include "FixedPositioning.h" - -#include "AndroidLog.h" -#include "DumpLayer.h" -#include "IFrameLayerAndroid.h" -#include "TilesManager.h" -#include "SkCanvas.h" - -#if USE(ACCELERATED_COMPOSITING) - -namespace WebCore { - -// Called when copying the layer tree to the UI -FixedPositioning::FixedPositioning(LayerAndroid* layer, const FixedPositioning& position) - : m_layer(layer) - , m_fixedLeft(position.m_fixedLeft) - , m_fixedTop(position.m_fixedTop) - , m_fixedRight(position.m_fixedRight) - , m_fixedBottom(position.m_fixedBottom) - , m_fixedMarginLeft(position.m_fixedMarginLeft) - , m_fixedMarginTop(position.m_fixedMarginTop) - , m_fixedMarginRight(position.m_fixedMarginRight) - , m_fixedMarginBottom(position.m_fixedMarginBottom) - , m_fixedRect(position.m_fixedRect) - , m_renderLayerPos(position.m_renderLayerPos) -{ -} - -// Executed on the UI -IFrameLayerAndroid* FixedPositioning::updatePosition(SkRect viewport, - IFrameLayerAndroid* parentIframeLayer) -{ - // So if this is a fixed layer inside a iframe, use the iframe offset - // and the iframe's size as the viewport and pass to the children - if (parentIframeLayer) { - viewport = SkRect::MakeXYWH(parentIframeLayer->iframeOffset().x(), - parentIframeLayer->iframeOffset().y(), - parentIframeLayer->getSize().width(), - parentIframeLayer->getSize().height()); - } - float w = viewport.width(); - float h = viewport.height(); - float dx = viewport.fLeft; - float dy = viewport.fTop; - float x = dx; - float y = dy; - - // It turns out that when it is 'auto', we should use the webkit value - // from the original render layer's X,Y, that will take care of alignment - // with the parent's layer and fix Margin etc. - if (!(m_fixedLeft.defined() || m_fixedRight.defined())) - x += m_renderLayerPos.x(); - else if (m_fixedLeft.defined() || !m_fixedRight.defined()) - x += m_fixedMarginLeft.calcFloatValue(w) + m_fixedLeft.calcFloatValue(w) - m_fixedRect.fLeft; - else - x += w - m_fixedMarginRight.calcFloatValue(w) - m_fixedRight.calcFloatValue(w) - m_fixedRect.fRight; - - if (!(m_fixedTop.defined() || m_fixedBottom.defined())) - y += m_renderLayerPos.y(); - else if (m_fixedTop.defined() || !m_fixedBottom.defined()) - y += m_fixedMarginTop.calcFloatValue(h) + m_fixedTop.calcFloatValue(h) - m_fixedRect.fTop; - else - y += h - m_fixedMarginBottom.calcFloatValue(h) - m_fixedBottom.calcFloatValue(h) - m_fixedRect.fBottom; - - m_layer->setPosition(x, y); - - return parentIframeLayer; -} - -void FixedPositioning::contentDraw(SkCanvas* canvas, Layer::PaintStyle style) -{ - if (TilesManager::instance()->getShowVisualIndicator()) { - SkPaint paint; - paint.setARGB(80, 255, 0, 0); - canvas->drawRect(m_fixedRect, paint); - } -} - -void writeLength(FILE* file, int indentLevel, const char* str, SkLength length) -{ - if (!length.defined()) - return; - writeIndent(file, indentLevel); - fprintf(file, "%s = { type = %d; value = %.2f; };\n", str, length.type, length.value); -} - -void FixedPositioning::dumpLayer(FILE* file, int indentLevel) const -{ - writeLength(file, indentLevel + 1, "fixedLeft", m_fixedLeft); - writeLength(file, indentLevel + 1, "fixedTop", m_fixedTop); - writeLength(file, indentLevel + 1, "fixedRight", m_fixedRight); - writeLength(file, indentLevel + 1, "fixedBottom", m_fixedBottom); - writeLength(file, indentLevel + 1, "fixedMarginLeft", m_fixedMarginLeft); - writeLength(file, indentLevel + 1, "fixedMarginTop", m_fixedMarginTop); - writeLength(file, indentLevel + 1, "fixedMarginRight", m_fixedMarginRight); - writeLength(file, indentLevel + 1, "fixedMarginBottom", m_fixedMarginBottom); - writeRect(file, indentLevel + 1, "fixedRect", m_fixedRect); -} - -} // namespace WebCore - -#endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/android/FixedPositioning.h b/Source/WebCore/platform/graphics/android/FixedPositioning.h deleted file mode 100644 index 973113b..0000000 --- a/Source/WebCore/platform/graphics/android/FixedPositioning.h +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright 2012, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef FixedPositioning_h -#define FixedPositioning_h - -#if USE(ACCELERATED_COMPOSITING) - -#include "LayerAndroid.h" - -namespace WebCore { - -class IFrameLayerAndroid; - -struct SkLength { - enum SkLengthType { Undefined, Auto, Relative, - Percent, Fixed, Static, Intrinsic, MinIntrinsic }; - SkLengthType type; - SkScalar value; - SkLength() - { - type = Undefined; - value = 0; - } - bool defined() const - { - if (type == Undefined) - return false; - return true; - } - float calcFloatValue(float max) const - { - switch (type) { - case Percent: - return (max * value) / 100.0f; - case Fixed: - return value; - default: - return value; - } - } -}; - -class FixedPositioning { - -public: - FixedPositioning(LayerAndroid* layer = 0) : m_layer(layer) {} - FixedPositioning(LayerAndroid* layer, const FixedPositioning& position); - virtual ~FixedPositioning() {}; - - void setFixedPosition(SkLength left, // CSS left property - SkLength top, // CSS top property - SkLength right, // CSS right property - SkLength bottom, // CSS bottom property - SkLength marginLeft, // CSS margin-left property - SkLength marginTop, // CSS margin-top property - SkLength marginRight, // CSS margin-right property - SkLength marginBottom, // CSS margin-bottom property - const IntPoint& renderLayerPos, // For undefined fixed position - SkRect viewRect) { // view rect, can be smaller than the layer's - m_fixedLeft = left; - m_fixedTop = top; - m_fixedRight = right; - m_fixedBottom = bottom; - m_fixedMarginLeft = marginLeft; - m_fixedMarginTop = marginTop; - m_fixedMarginRight = marginRight; - m_fixedMarginBottom = marginBottom; - m_fixedRect = viewRect; - m_renderLayerPos = renderLayerPos; - } - - IFrameLayerAndroid* updatePosition(SkRect viewPort, - IFrameLayerAndroid* parentIframeLayer); - - void contentDraw(SkCanvas* canvas, Layer::PaintStyle style); - - void dumpLayer(FILE*, int indentLevel) const; - - // ViewStateSerializer friends - friend void android::serializeLayer(LayerAndroid* layer, SkWStream* stream); - friend LayerAndroid* android::deserializeLayer(int version, SkStream* stream); - -private: - LayerAndroid* m_layer; - - SkLength m_fixedLeft; - SkLength m_fixedTop; - SkLength m_fixedRight; - SkLength m_fixedBottom; - SkLength m_fixedMarginLeft; - SkLength m_fixedMarginTop; - SkLength m_fixedMarginRight; - SkLength m_fixedMarginBottom; - SkRect m_fixedRect; - - // When fixed element is undefined or auto, the render layer's position - // is needed for offset computation - IntPoint m_renderLayerPos; -}; - -} - -#endif // USE(ACCELERATED_COMPOSITING) - -#endif // FixedPositioning_h diff --git a/Source/WebCore/platform/graphics/android/FontAndroid.cpp b/Source/WebCore/platform/graphics/android/FontAndroid.cpp deleted file mode 100644 index 3146612..0000000 --- a/Source/WebCore/platform/graphics/android/FontAndroid.cpp +++ /dev/null @@ -1,1192 +0,0 @@ -/* - * Copyright 2009, The Android Open Source Project - * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" - -#include "EmojiFont.h" -#include "GraphicsOperationCollection.h" -#include "GraphicsOperation.h" -#include "Font.h" -#include "FontData.h" -#include "FontFallbackList.h" -#include "GraphicsContext.h" -#include "GlyphBuffer.h" -#include "IntRect.h" -#include "NotImplemented.h" -#include "PlatformGraphicsContext.h" -#include "SkCanvas.h" -#include "SkColorFilter.h" -#include "SkLayerDrawLooper.h" -#include "SkPaint.h" -#include "SkTemplates.h" -#include "SkTypeface.h" -#include "SkUtils.h" -#include "TextRun.h" - -#ifdef SUPPORT_COMPLEX_SCRIPTS -#include "HarfbuzzSkia.h" -#include -#include -#include -#include -#include -#include -#include -#include -#endif - -using namespace android; - -namespace WebCore { - -typedef std::pair FallbackFontKey; -typedef HashMap FallbackHash; - -static void updateForFont(SkPaint* paint, const SimpleFontData* font) { - font->platformData().setupPaint(paint); - paint->setTextEncoding(SkPaint::kGlyphID_TextEncoding); -} - -static SkPaint* setupFill(SkPaint* paint, GraphicsContext* gc, - const SimpleFontData* font) { - gc->setupFillPaint(paint); - updateForFont(paint, font); - return paint; -} - -static SkPaint* setupStroke(SkPaint* paint, GraphicsContext* gc, - const SimpleFontData* font) { - gc->setupStrokePaint(paint); - updateForFont(paint, font); - return paint; -} - -static bool setupForText(SkPaint* paint, GraphicsContext* gc, - const SimpleFontData* font) { - int mode = gc->textDrawingMode() & (TextModeFill | TextModeStroke); - if (!mode) - return false; - - paint->setVerticalText(font->platformData().orientation() == Vertical); - - FloatSize shadowOffset; - float shadowBlur; - Color shadowColor; - ColorSpace shadowColorSpace; - bool hasShadow = gc->getShadow(shadowOffset, shadowBlur, shadowColor, shadowColorSpace); - bool hasBothStrokeAndFill = - (mode & (TextModeStroke | TextModeFill)) == (TextModeStroke | TextModeFill); - if (hasShadow || hasBothStrokeAndFill) { - SkLayerDrawLooper* looper = new SkLayerDrawLooper; - paint->setLooper(looper)->unref(); - - // The layerDrawLooper uses at the root paint to determine the text - // encoding so we need to make sure it is properly configured. - updateForFont(paint, font); - - // Specify the behavior of the looper - SkLayerDrawLooper::LayerInfo info; - info.fPaintBits = SkLayerDrawLooper::kEntirePaint_Bits; - info.fColorMode = SkXfermode::kSrc_Mode; - info.fFlagsMask = SkPaint::kAllFlags; - - // The paint is only valid until the looper receives another call to - // addLayer(). Therefore, we must cache certain state for later use. - bool hasFillPaint = false; - bool hasStrokePaint = false; - SkScalar strokeWidth; - - if ((mode & TextModeStroke) && gc->willStroke()) { - strokeWidth = setupStroke(looper->addLayer(info), gc, font)->getStrokeWidth(); - hasStrokePaint = true; - } - if ((mode & TextModeFill) && gc->willFill()) { - setupFill(looper->addLayer(info), gc, font); - hasFillPaint = true; - } - - if (hasShadow) { - SkPaint shadowPaint; - SkPoint offset; - if (gc->setupShadowPaint(&shadowPaint, &offset)) { - - // add an offset to the looper when creating a shadow layer - info.fOffset.set(offset.fX, offset.fY); - - SkPaint* p = looper->addLayer(info); - *p = shadowPaint; - - // Currently, only GraphicsContexts associated with the - // HTMLCanvasElement have shadows ignore transforms set. This - // allows us to distinguish between CSS and Canvas shadows which - // have different rendering specifications. - if (gc->shadowsIgnoreTransforms()) { - SkColorFilter* cf = SkColorFilter::CreateModeFilter(p->getColor(), - SkXfermode::kSrcIn_Mode); - p->setColorFilter(cf)->unref(); - } else { // in CSS - p->setShader(NULL); - } - - if (hasStrokePaint && !hasFillPaint) { - // stroke the shadow if we have stroke but no fill - p->setStyle(SkPaint::kStroke_Style); - p->setStrokeWidth(strokeWidth); - } - updateForFont(p, font); - } - } - } else if (mode & TextModeFill) { - (void)setupFill(paint, gc, font); - } else if (mode & TextModeStroke) { - (void)setupStroke(paint, gc, font); - } else { - return false; - } - return true; -} - -bool Font::canReturnFallbackFontsForComplexText() -{ - return false; -} - -bool Font::canExpandAroundIdeographsInComplexText() -{ - return false; -} - -void Font::drawGlyphs(GraphicsContext* gc, const SimpleFontData* font, - const GlyphBuffer& glyphBuffer, int from, int numGlyphs, - const FloatPoint& point) const -{ - // compile-time assert - SkASSERT(sizeof(GlyphBufferGlyph) == sizeof(uint16_t)); - - SkPaint paint; - if (!setupForText(&paint, gc, font)) { - return; - } - - SkScalar x = SkFloatToScalar(point.x()); - SkScalar y = SkFloatToScalar(point.y()); - const GlyphBufferGlyph* glyphs = glyphBuffer.glyphs(from); - const GlyphBufferAdvance* adv = glyphBuffer.advances(from); - SkAutoSTMalloc<32, SkPoint> storage(numGlyphs), storage2(numGlyphs), storage3(numGlyphs); - SkPoint* pos = storage.get(); - - SkCanvas* canvas = gc->platformContext()->recordingCanvas(); - - /* We need an array of [x,y,x,y,x,y,...], but webkit is giving us - point.xy + [width, height, width, height, ...], so we have to convert - */ - - if (font->platformData().orientation() == Vertical) - y += SkFloatToScalar(font->fontMetrics().floatAscent(IdeographicBaseline) - font->fontMetrics().floatAscent()); - - if (EmojiFont::IsAvailable()) { - // set filtering, to make scaled images look nice(r) - paint.setFilterBitmap(true); - - int localIndex = 0; - int localCount = 0; - for (int i = 0; i < numGlyphs; i++) { - if (EmojiFont::IsEmojiGlyph(glyphs[i])) { - if (localCount) - canvas->drawPosText(&glyphs[localIndex], - localCount * sizeof(uint16_t), - &pos[localIndex], paint); - EmojiFont::Draw(canvas, glyphs[i], x, y, paint); - // reset local index/count track for "real" glyphs - localCount = 0; - localIndex = i + 1; - } else { - pos[i].set(x, y); - localCount += 1; - } - x += SkFloatToScalar(adv[i].width()); - y += SkFloatToScalar(adv[i].height()); - } - // draw the last run of glyphs (if any) - if (localCount) - canvas->drawPosText(&glyphs[localIndex], - localCount * sizeof(uint16_t), - &pos[localIndex], paint); - } else { - for (int i = 0; i < numGlyphs; i++) { - pos[i].set(x, y); - y += SkFloatToScalar(adv[i].height()); - x += SkFloatToScalar(adv[i].width()); - } - - if (font->platformData().orientation() == Vertical) { - canvas->save(); - canvas->rotate(-90); - SkMatrix rotator; - rotator.reset(); - rotator.setRotate(90); - rotator.mapPoints(pos, numGlyphs); - } - - canvas->drawPosText(glyphs, numGlyphs * sizeof(uint16_t), pos, paint); - - if (font->platformData().orientation() == Vertical) - canvas->restore(); - } - gc->platformContext()->endRecording(); -} - -void Font::drawEmphasisMarksForComplexText(WebCore::GraphicsContext*, WebCore::TextRun const&, WTF::AtomicString const&, WebCore::FloatPoint const&, int, int) const -{ - notImplemented(); -} - -#ifndef SUPPORT_COMPLEX_SCRIPTS - -FloatRect Font::selectionRectForComplexText(const TextRun& run, - const FloatPoint& point, int h, int, int) const -{ - SkPaint paint; - SkScalar width, left; - SkPaint::FontMetrics metrics; - - primaryFont()->platformData().setupPaint(&paint); - - width = paint.measureText(run.characters(), run.length() << 1); - SkScalar spacing = paint.getFontMetrics(&metrics); - - return FloatRect(point.x(), - point.y(), - roundf(SkScalarToFloat(width)), - roundf(SkScalarToFloat(spacing))); -} - -void Font::drawComplexText(GraphicsContext* gc, TextRun const& run, - FloatPoint const& point, int, int) const -{ - SkCanvas* canvas = gc->platformContext()->mCanvas; - SkPaint paint; - - if (!setupForText(&paint, gc, primaryFont())) { - return; - } - - // go to chars, instead of glyphs, which was set by setupForText() - paint.setTextEncoding(SkPaint::kUTF16_TextEncoding); - - canvas->drawText(run.characters(), run.length() << 1, - SkFloatToScalar(point.x()), SkFloatToScalar(point.y()), - paint); -} - -float Font::floatWidthForComplexText(const TextRun& run, HashSet*, GlyphOverflow*) const -{ - SkPaint paint; - - primaryFont()->platformData().setupPaint(&paint); - -//printf("--------- complext measure %d chars\n", run.to() - run.from()); - - SkScalar width = paint.measureText(run.characters(), run.length() << 1); - return SkScalarToFloat(width); -} - -int Font::offsetForPositionForComplexText(const TextRun& run, float x, - bool includePartialGlyphs) const -{ - SkPaint paint; - int count = run.length(); - SkAutoSTMalloc<64, SkScalar> storage(count); - SkScalar* widths = storage.get(); - - primaryFont()->platformData().setupPaint(&paint); - - count = paint.getTextWidths(run.characters(), count << 1, widths); - - if (count > 0) - { - SkScalar pos = 0; - for (int i = 0; i < count; i++) - { - if (x < SkScalarRound(pos + SkScalarHalf(widths[i]))) - return i; - pos += widths[i]; - } - } - return count; -} - -#else - -// TODO Should we remove the multilayer support? -// If yes. remove isCanvasMultiLayered() and adjustTextRenderMode(). -static bool isCanvasMultiLayered(SkCanvas* canvas) -{ - SkCanvas::LayerIter layerIterator(canvas, false); - layerIterator.next(); - return !layerIterator.done(); -} - -static void adjustTextRenderMode(SkPaint* paint, bool isCanvasMultiLayered) -{ - // Our layers only have a single alpha channel. This means that subpixel - // rendered text cannot be compositied correctly when the layer is - // collapsed. Therefore, subpixel text is disabled when we are drawing - // onto a layer. - if (isCanvasMultiLayered) - paint->setLCDRenderText(false); -} - -// Harfbuzz uses 26.6 fixed point values for pixel offsets. However, we don't -// handle subpixel positioning so this function is used to truncate Harfbuzz -// values to a number of pixels. -static int truncateFixedPointToInteger(HB_Fixed value) -{ - return value >> 6; -} - -// TextRunWalker walks a TextRun and presents each script run in sequence. A -// TextRun is a sequence of code-points with the same embedding level (i.e. they -// are all left-to-right or right-to-left). A script run is a subsequence where -// all the characters have the same script (e.g. Arabic, Thai etc). Shaping is -// only ever done with script runs since the shapers only know how to deal with -// a single script. -// -// After creating it, the script runs are either iterated backwards or forwards. -// It defaults to backwards for RTL and forwards otherwise (which matches the -// presentation order), however you can set it with |setBackwardsIteration|. -// -// Once you have setup the object, call |nextScriptRun| to get the first script -// run. This will return false when the iteration is complete. At any time you -// can call |reset| to start over again. -class TextRunWalker { -public: - TextRunWalker(const TextRun&, int, int, const Font*); - ~TextRunWalker(); - - bool isWordBreak(unsigned, bool); - // setPadding sets a number of pixels to be distributed across the TextRun. - // WebKit uses this to justify text. - void setPadding(int); - void reset(); - void setBackwardsIteration(bool); - // Advance to the next script run, returning false when the end of the - // TextRun has been reached. - bool nextScriptRun(); - float widthOfFullRun(); - - // setWordSpacingAdjustment sets a delta (in pixels) which is applied at - // each word break in the TextRun. - void setWordSpacingAdjustment(int wordSpacingAdjustment) - { - m_wordSpacingAdjustment = wordSpacingAdjustment; - } - - // setLetterSpacingAdjustment sets an additional number of pixels that is - // added to the advance after each output cluster. This matches the behaviour - // of WidthIterator::advance. - // - // (NOTE: currently does nothing because I don't know how to get the - // cluster information from Harfbuzz.) - void setLetterSpacingAdjustment(int letterSpacingAdjustment) - { - m_letterSpacing = letterSpacingAdjustment; - } - - // setWordAndLetterSpacing calls setWordSpacingAdjustment() and - // setLetterSpacingAdjustment() to override m_wordSpacingAdjustment - // and m_letterSpacing. - void setWordAndLetterSpacing(int wordSpacingAdjustment, int letterSpacingAdjustment); - - // Set the x offset for the next script run. This affects the values in - // |xPositions| - void setXOffsetToZero() { m_offsetX = 0; } - bool rtl() const { return m_run.rtl(); } - const uint16_t* glyphs() const { return m_glyphs16; } - - // Return the length of the array returned by |glyphs| - unsigned length() const { return m_item.num_glyphs; } - - // Return the offset for each of the glyphs. Note that this is translated - // by the current x offset and that the x offset is updated for each script - // run. - const SkPoint* positions() const { return m_positions; } - - // Get the advances (widths) for each glyph. - const HB_Fixed* advances() const { return m_item.advances; } - - // Return the width (in px) of the current script run. - unsigned width() const { return m_pixelWidth; } - - // Return the cluster log for the current script run. For example: - // script run: f i a n c é (fi gets ligatured) - // log clutrs: 0 0 1 2 3 4 - // So, for each input code point, the log tells you which output glyph was - // generated for it. - const unsigned short* logClusters() const { return m_item.log_clusters; } - - // return the number of code points in the current script run - unsigned numCodePoints() const { return m_numCodePoints; } - - const FontPlatformData* fontPlatformDataForScriptRun() { - return reinterpret_cast(m_item.font->userData); - } - -private: - enum CustomScript { - Bengali, - Devanagari, - Hebrew, - HebrewBold, - Naskh, - Tamil, - Thai, - NUM_SCRIPTS - }; - - static const char* paths[NUM_SCRIPTS]; - - void setupFontForScriptRun(); - const FontPlatformData* setupComplexFont(CustomScript script, - const FontPlatformData& platformData); - HB_FontRec* allocHarfbuzzFont(); - void deleteGlyphArrays(); - void createGlyphArrays(int); - void resetGlyphArrays(); - void shapeGlyphs(); - void setGlyphPositions(bool); - - static void normalizeSpacesAndMirrorChars(const UChar* source, bool rtl, - UChar* destination, int length); - static const TextRun& getNormalizedTextRun(const TextRun& originalRun, - OwnPtr& normalizedRun, OwnArrayPtr& normalizedBuffer); - - // This matches the logic in RenderBlock::findNextLineBreak - static bool isCodepointSpace(HB_UChar16 c) { return c == ' ' || c == '\t'; } - - const Font* const m_font; - HB_ShaperItem m_item; - uint16_t* m_glyphs16; // A vector of 16-bit glyph ids. - SkPoint* m_positions; // A vector of positions for each glyph. - ssize_t m_indexOfNextScriptRun; // Indexes the script run in |m_run|. - const int m_startingX; // Offset in pixels of the first script run. - const int m_startingY; // Offset in pixels of the first script run. - int m_offsetX; // Offset in pixels to the start of the next script run. - unsigned m_pixelWidth; // Width (in px) of the current script run. - unsigned m_numCodePoints; // Code points in current script run. - unsigned m_glyphsArrayCapacity; // Current size of all the Harfbuzz arrays. - - OwnPtr m_normalizedRun; - OwnArrayPtr m_normalizedBuffer; // A buffer for normalized run. - const TextRun& m_run; - bool m_iterateBackwards; - int m_wordSpacingAdjustment; // delta adjustment (pixels) for each word break. - float m_padding; // pixels to be distributed over the line at word breaks. - float m_padPerWordBreak; // pixels to be added to each word break. - float m_padError; // |m_padPerWordBreak| might have a fractional component. - // Since we only add a whole number of padding pixels at - // each word break we accumulate error. This is the - // number of pixels that we are behind so far. - unsigned m_letterSpacing; // pixels to be added after each glyph. -}; - - -// Indexed using enum CustomScript -const char* TextRunWalker::paths[] = { - "/system/fonts/Lohit-Bengali.ttf", - "/system/fonts/Lohit-Devanagari.ttf", - "/system/fonts/DroidSansHebrew-Regular.ttf", - "/system/fonts/DroidSansHebrew-Bold.ttf", - "/system/fonts/DroidNaskh-Regular.ttf", - "/system/fonts/Lohit-Tamil.ttf", - "/system/fonts/DroidSansThai.ttf" -}; - -TextRunWalker::TextRunWalker(const TextRun& run, int startingX, int startingY, const Font* font) - : m_font(font) - , m_startingX(startingX) - , m_startingY(startingY) - , m_offsetX(m_startingX) - , m_run(getNormalizedTextRun(run, m_normalizedRun, m_normalizedBuffer)) - , m_iterateBackwards(m_run.rtl()) - , m_wordSpacingAdjustment(0) - , m_padding(0) - , m_padPerWordBreak(0) - , m_padError(0) - , m_letterSpacing(0) -{ - // Do not use |run| inside this constructor. Use |m_run| instead. - - memset(&m_item, 0, sizeof(m_item)); - // We cannot know, ahead of time, how many glyphs a given script run - // will produce. We take a guess that script runs will not produce more - // than twice as many glyphs as there are code points plus a bit of - // padding and fallback if we find that we are wrong. - createGlyphArrays((m_run.length() + 2) * 2); - - m_item.log_clusters = new unsigned short[m_run.length()]; - - m_item.face = 0; - m_item.font = allocHarfbuzzFont(); - - m_item.item.bidiLevel = m_run.rtl(); - - m_item.string = m_run.characters(); - m_item.stringLength = m_run.length(); - - reset(); -} - -TextRunWalker::~TextRunWalker() -{ - fastFree(m_item.font); - deleteGlyphArrays(); - delete[] m_item.log_clusters; -} - -bool TextRunWalker::isWordBreak(unsigned index, bool isRTL) -{ - if (!isRTL) - return index && isCodepointSpace(m_item.string[index]) - && !isCodepointSpace(m_item.string[index - 1]); - return index != m_item.stringLength - 1 && isCodepointSpace(m_item.string[index]) - && !isCodepointSpace(m_item.string[index + 1]); -} - -// setPadding sets a number of pixels to be distributed across the TextRun. -// WebKit uses this to justify text. -void TextRunWalker::setPadding(int padding) -{ - m_padding = padding; - if (!m_padding) - return; - - // If we have padding to distribute, then we try to give an equal - // amount to each space. The last space gets the smaller amount, if - // any. - unsigned numWordBreaks = 0; - bool isRTL = m_iterateBackwards; - - for (unsigned i = 0; i < m_item.stringLength; i++) { - if (isWordBreak(i, isRTL)) - numWordBreaks++; - } - - if (numWordBreaks) - m_padPerWordBreak = m_padding / numWordBreaks; - else - m_padPerWordBreak = 0; -} - -void TextRunWalker::reset() -{ - if (m_iterateBackwards) - m_indexOfNextScriptRun = m_run.length() - 1; - else - m_indexOfNextScriptRun = 0; - m_offsetX = m_startingX; -} - -void TextRunWalker::setBackwardsIteration(bool isBackwards) -{ - m_iterateBackwards = isBackwards; - reset(); -} - -// Advance to the next script run, returning false when the end of the -// TextRun has been reached. -bool TextRunWalker::nextScriptRun() -{ - if (m_iterateBackwards) { - // In right-to-left mode we need to render the shaped glyph backwards and - // also render the script runs themselves backwards. So given a TextRun: - // AAAAAAACTTTTTTT (A = Arabic, C = Common, T = Thai) - // we render: - // TTTTTTCAAAAAAA - // (and the glyphs in each A, C and T section are backwards too) - if (!hb_utf16_script_run_prev(&m_numCodePoints, &m_item.item, m_run.characters(), - m_run.length(), &m_indexOfNextScriptRun)) - return false; - } else { - if (!hb_utf16_script_run_next(&m_numCodePoints, &m_item.item, m_run.characters(), - m_run.length(), &m_indexOfNextScriptRun)) - return false; - - // It is actually wrong to consider script runs at all in this code. - // Other WebKit code (e.g. Mac) segments complex text just by finding - // the longest span of text covered by a single font. - // But we currently need to call hb_utf16_script_run_next anyway to fill - // in the harfbuzz data structures to e.g. pick the correct script's shaper. - // So we allow that to run first, then do a second pass over the range it - // found and take the largest subregion that stays within a single font. - const FontData* glyphData = m_font->glyphDataForCharacter( - m_item.string[m_item.item.pos], false).fontData; - unsigned endOfRun; - for (endOfRun = 1; endOfRun < m_item.item.length; ++endOfRun) { - const FontData* nextGlyphData = m_font->glyphDataForCharacter( - m_item.string[m_item.item.pos + endOfRun], false).fontData; - if (nextGlyphData != glyphData) - break; - } - m_item.item.length = endOfRun; - m_indexOfNextScriptRun = m_item.item.pos + endOfRun; - } - - setupFontForScriptRun(); - shapeGlyphs(); - setGlyphPositions(rtl()); - - return true; -} - -float TextRunWalker::widthOfFullRun() -{ - float widthSum = 0; - while (nextScriptRun()) - widthSum += width(); - - return widthSum; -} - -void TextRunWalker::setWordAndLetterSpacing(int wordSpacingAdjustment, - int letterSpacingAdjustment) -{ - setWordSpacingAdjustment(wordSpacingAdjustment); - setLetterSpacingAdjustment(letterSpacingAdjustment); -} - -const FontPlatformData* TextRunWalker::setupComplexFont( - CustomScript script, - const FontPlatformData& platformData) -{ - static FallbackHash fallbackPlatformData; - - FallbackFontKey key(script, platformData.size()); - FontPlatformData* newPlatformData = 0; - - if (!fallbackPlatformData.contains(key)) { - SkTypeface* typeface = SkTypeface::CreateFromFile(paths[script]); - newPlatformData = new FontPlatformData(platformData, typeface); - SkSafeUnref(typeface); - fallbackPlatformData.set(key, newPlatformData); - } - - if (!newPlatformData) - newPlatformData = fallbackPlatformData.get(key); - - // If we couldn't allocate a new FontPlatformData, revert to the one passed - return newPlatformData ? newPlatformData : &platformData; -} - -void TextRunWalker::setupFontForScriptRun() -{ - const FontData* fontData = m_font->glyphDataForCharacter(m_run[0], false).fontData; - const FontPlatformData& platformData = - fontData->fontDataForCharacter(' ')->platformData(); - const FontPlatformData* complexPlatformData = &platformData; - - switch (m_item.item.script) { - case HB_Script_Bengali: - complexPlatformData = setupComplexFont(Bengali, platformData); - break; - case HB_Script_Devanagari: - complexPlatformData = setupComplexFont(Devanagari, platformData); - break; - case HB_Script_Hebrew: - switch (platformData.typeface()->style()) { - case SkTypeface::kBold: - case SkTypeface::kBoldItalic: - complexPlatformData = setupComplexFont(HebrewBold, platformData); - break; - case SkTypeface::kNormal: - case SkTypeface::kItalic: - default: - complexPlatformData = setupComplexFont(Hebrew, platformData); - break; - } - break; - case HB_Script_Arabic: - complexPlatformData = setupComplexFont(Naskh, platformData); - break; - case HB_Script_Tamil: - complexPlatformData = setupComplexFont(Tamil, platformData); - break; - case HB_Script_Thai: - complexPlatformData = setupComplexFont(Thai, platformData); - break; - default: - // HB_Script_Common; includes Ethiopic - complexPlatformData = &platformData; - break; - } - m_item.face = complexPlatformData->harfbuzzFace(); - m_item.font->userData = const_cast(complexPlatformData); - - int size = complexPlatformData->size(); - m_item.font->x_ppem = size; - m_item.font->y_ppem = size; - // x_ and y_scale are the conversion factors from font design space (fEmSize) to 1/64th of device pixels in 16.16 format. - const int devicePixelFraction = 64; - const int multiplyFor16Dot16 = 1 << 16; - int scale = devicePixelFraction * size * multiplyFor16Dot16 / complexPlatformData->emSizeInFontUnits(); - m_item.font->x_scale = scale; - m_item.font->y_scale = scale; -} - -HB_FontRec* TextRunWalker::allocHarfbuzzFont() -{ - HB_FontRec* font = reinterpret_cast(fastMalloc(sizeof(HB_FontRec))); - memset(font, 0, sizeof(HB_FontRec)); - font->klass = &harfbuzzSkiaClass; - font->userData = 0; - - return font; -} - -void TextRunWalker::deleteGlyphArrays() -{ - delete[] m_item.glyphs; - delete[] m_item.attributes; - delete[] m_item.advances; - delete[] m_item.offsets; - delete[] m_glyphs16; - delete[] m_positions; -} - -void TextRunWalker::createGlyphArrays(int size) -{ - m_item.glyphs = new HB_Glyph[size]; - m_item.attributes = new HB_GlyphAttributes[size]; - m_item.advances = new HB_Fixed[size]; - m_item.offsets = new HB_FixedPoint[size]; - - m_glyphs16 = new uint16_t[size]; - m_positions = new SkPoint[size]; - - m_item.num_glyphs = size; - m_glyphsArrayCapacity = size; // Save the GlyphArrays size. -} - -void TextRunWalker::resetGlyphArrays() -{ - int size = m_item.num_glyphs; - // All the types here don't have pointers. It is safe to reset to - // zero unless Harfbuzz breaks the compatibility in the future. - memset(m_item.glyphs, 0, size * sizeof(m_item.glyphs[0])); - memset(m_item.attributes, 0, size * sizeof(m_item.attributes[0])); - memset(m_item.advances, 0, size * sizeof(m_item.advances[0])); - memset(m_item.offsets, 0, size * sizeof(m_item.offsets[0])); - memset(m_glyphs16, 0, size * sizeof(m_glyphs16[0])); - memset(m_positions, 0, size * sizeof(m_positions[0])); -} - -void TextRunWalker::shapeGlyphs() -{ - // HB_ShapeItem() resets m_item.num_glyphs. If the previous call to - // HB_ShapeItem() used less space than was available, the capacity of - // the array may be larger than the current value of m_item.num_glyphs. - // So, we need to reset the num_glyphs to the capacity of the array. - m_item.num_glyphs = m_glyphsArrayCapacity; - resetGlyphArrays(); - while (!HB_ShapeItem(&m_item)) { - // We overflowed our arrays. Resize and retry. - // HB_ShapeItem fills in m_item.num_glyphs with the needed size. - deleteGlyphArrays(); - createGlyphArrays(m_item.num_glyphs << 1); - resetGlyphArrays(); - } -} - -void TextRunWalker::setGlyphPositions(bool isRTL) -{ - int position = 0; - // logClustersIndex indexes logClusters for the first (or last when - // RTL) codepoint of the current glyph. Each time we advance a glyph, - // we skip over all the codepoints that contributed to the current - // glyph. - unsigned logClustersIndex = isRTL && m_item.num_glyphs ? m_item.num_glyphs - 1 : 0; - - for (unsigned iter = 0; iter < m_item.num_glyphs; ++iter) { - // Glyphs are stored in logical order, but for layout purposes we - // always go left to right. - int i = isRTL ? m_item.num_glyphs - iter - 1 : iter; - - m_glyphs16[i] = m_item.glyphs[i]; - int offsetX = truncateFixedPointToInteger(m_item.offsets[i].x); - int offsetY = truncateFixedPointToInteger(m_item.offsets[i].y); - m_positions[i].set(SkIntToScalar(m_offsetX + position) + offsetX, m_startingY + offsetY); - - int advance = truncateFixedPointToInteger(m_item.advances[i]); - // The first half of the conjunction works around the case where - // output glyphs aren't associated with any codepoints by the - // clusters log. - if (logClustersIndex < m_item.item.length - && isWordBreak(m_item.item.pos + logClustersIndex, isRTL)) { - advance += m_wordSpacingAdjustment; - - if (m_padding > 0) { - int toPad = roundf(m_padPerWordBreak + m_padError); - m_padError += m_padPerWordBreak - toPad; - - if (m_padding < toPad) - toPad = m_padding; - m_padding -= toPad; - advance += toPad; - } - } - - // ZeroWidthJoiners and ZeroWidthNonJoiners should be stripped by - // Harfbuzz, but aren't. Check for zwj and zwnj and replace with a - // zero width space. We get the glyph data for space instead of - // zeroWidthSpace because the latter was seen to render with an - // unexpected code point (the symbol for a cloud). Since the standard - // space is in page zero and since we've also confirmed that there is - // no advance on this glyph, that should be ok. - if (0 == m_item.advances[i]) { - const HB_UChar16 c = m_item.string[m_item.item.pos + logClustersIndex]; - if ((c == zeroWidthJoiner) || (c == zeroWidthNonJoiner)) { - static Glyph spaceGlyph = m_font->glyphDataForCharacter(space, false).glyph; - m_glyphs16[i] = spaceGlyph; - } - } - - // TODO We would like to add m_letterSpacing after each cluster, but I - // don't know where the cluster information is. This is typically - // fine for Roman languages, but breaks more complex languages - // terribly. - // advance += m_letterSpacing; - - if (isRTL) { - while (logClustersIndex > 0 && logClusters()[logClustersIndex] == i) - logClustersIndex--; - } else { - while (logClustersIndex < m_item.item.length - && logClusters()[logClustersIndex] == i) - logClustersIndex++; - } - - position += advance; - } - - m_pixelWidth = position; - m_offsetX += m_pixelWidth; -} - -void TextRunWalker::normalizeSpacesAndMirrorChars(const UChar* source, bool rtl, - UChar* destination, int length) -{ - int position = 0; - bool error = false; - // Iterate characters in source and mirror character if needed. - while (position < length) { - UChar32 character; - int nextPosition = position; - U16_NEXT(source, nextPosition, length, character); - - if (Font::treatAsSpace(character)) - character = space; - else if (Font::treatAsZeroWidthSpaceInComplexScript(character)) - character = zeroWidthSpace; - else if (rtl) - character = u_charMirror(character); - - U16_APPEND(destination, position, length, character, error); - ASSERT(!error); - position = nextPosition; - } -} - -const TextRun& TextRunWalker::getNormalizedTextRun(const TextRun& originalRun, - OwnPtr& normalizedRun, OwnArrayPtr& normalizedBuffer) -{ - // Normalize the text run in three ways: - // 1) Convert the |originalRun| to NFC normalized form if combining diacritical marks - // (U+0300..) are used in the run. This conversion is necessary since most OpenType - // fonts (e.g., Arial) don't have substitution rules for the diacritical marks in - // their GSUB tables. - // - // Note that we don't use the icu::Normalizer::isNormalized(UNORM_NFC) API here since - // the API returns FALSE (= not normalized) for complex runs that don't require NFC - // normalization (e.g., Arabic text). Unless the run contains the diacritical marks, - // Harfbuzz will do the same thing for us using the GSUB table. - // 2) Convert spacing characters into plain spaces, as some fonts will provide glyphs - // for characters like '\n' otherwise. - // 3) Convert mirrored characters such as parenthesis for rtl text. - - // Convert to NFC form if the text has diacritical marks. - icu::UnicodeString normalizedString; - UErrorCode error = U_ZERO_ERROR; - - for (int16_t i = 0; i < originalRun.length(); ++i) { - UChar ch = originalRun[i]; - if (::ublock_getCode(ch) == UBLOCK_COMBINING_DIACRITICAL_MARKS) { - icu::Normalizer::normalize(icu::UnicodeString(originalRun.characters(), - originalRun.length()), UNORM_NFC, 0 /* no options */, - normalizedString, error); - if (U_FAILURE(error)) - return originalRun; - break; - } - } - - // Normalize space and mirror parenthesis for rtl text. - int normalizedBufferLength; - const UChar* sourceText; - if (normalizedString.isEmpty()) { - normalizedBufferLength = originalRun.length(); - sourceText = originalRun.characters(); - } else { - normalizedBufferLength = normalizedString.length(); - sourceText = normalizedString.getBuffer(); - } - - normalizedBuffer = adoptArrayPtr(new UChar[normalizedBufferLength + 1]); - - normalizeSpacesAndMirrorChars(sourceText, originalRun.rtl(), normalizedBuffer.get(), - normalizedBufferLength); - - normalizedRun = adoptPtr(new TextRun(originalRun)); - normalizedRun->setText(normalizedBuffer.get(), normalizedBufferLength); - return *normalizedRun; -} - -FloatRect Font::selectionRectForComplexText(const TextRun& run, - const FloatPoint& point, int height, int from, int to) const -{ - - int fromX = -1, toX = -1, fromAdvance = -1, toAdvance = -1; - TextRunWalker walker(run, 0, 0, this); - walker.setWordAndLetterSpacing(wordSpacing(), letterSpacing()); - - // Base will point to the x offset for the current script run. Note that, in - // the LTR case, width will be 0. - int base = walker.rtl() ? walker.widthOfFullRun() : 0; - const int leftEdge = base; - - // We want to enumerate the script runs in code point order in the following - // code. This call also resets |walker|. - walker.setBackwardsIteration(false); - - while (walker.nextScriptRun() && (fromX == -1 || toX == -1)) { - // TextRunWalker will helpfully accumulate the x offsets for different - // script runs for us. For this code, however, we always want the x - // offsets to start from zero so we call this before each script run. - walker.setXOffsetToZero(); - - if (walker.rtl()) - base -= walker.width(); - - int numCodePoints = static_cast(walker.numCodePoints()); - if (fromX == -1 && from < numCodePoints) { - // |from| is within this script run. So we index the clusters log to - // find which glyph this code-point contributed to and find its x - // position. - int glyph = walker.logClusters()[from]; - fromX = base + walker.positions()[glyph].x(); - fromAdvance = walker.advances()[glyph]; - } else if (!walker.rtl()) - from -= numCodePoints; - - if (toX == -1 && to < numCodePoints) { - int glyph = walker.logClusters()[to]; - toX = base + walker.positions()[glyph].x(); - toAdvance = walker.advances()[glyph]; - } else if (!walker.rtl()) - to -= numCodePoints; - - if (!walker.rtl()) - base += walker.width(); - } - - // The position in question might be just after the text. - const int rightEdge = base; - if (fromX == -1 && !from) - fromX = leftEdge; - else if (walker.rtl()) - fromX += truncateFixedPointToInteger(fromAdvance); - - if (toX == -1 && !to) - toX = rightEdge; - - ASSERT(fromX != -1 && toX != -1); - - if (fromX < toX) - return FloatRect(point.x() + fromX, point.y(), toX - fromX, height); - - return FloatRect(point.x() + toX, point.y(), fromX - toX, height); -} - -void Font::drawComplexText(GraphicsContext* gc, TextRun const& run, - FloatPoint const& point, int, int) const -{ - if (!run.length()) - return; - - int mode = gc->textDrawingMode(); - bool fill = mode & TextModeFill; - bool stroke = mode & TextModeStroke; - if (!fill && !stroke) - return; - - SkPaint fillPaint, strokePaint; - if (fill) - setupFill(&fillPaint, gc, primaryFont()); - if (stroke) - setupStroke(&strokePaint, gc, primaryFont()); - - SkCanvas* canvas = gc->platformContext()->recordingCanvas(); - - bool haveMultipleLayers = isCanvasMultiLayered(canvas); - TextRunWalker walker(run, point.x(), point.y(), this); - walker.setWordAndLetterSpacing(wordSpacing(), letterSpacing()); - walker.setPadding(run.expansion()); - - while (walker.nextScriptRun()) { - if (fill) { - walker.fontPlatformDataForScriptRun()->setupPaint(&fillPaint); - adjustTextRenderMode(&fillPaint, haveMultipleLayers); - canvas->drawPosText(walker.glyphs(), walker.length() << 1, - walker.positions(), fillPaint); - } - if (stroke) { - walker.fontPlatformDataForScriptRun()->setupPaint(&strokePaint); - adjustTextRenderMode(&strokePaint, haveMultipleLayers); - canvas->drawPosText(walker.glyphs(), walker.length() << 1, - walker.positions(), strokePaint); - } - } - - gc->platformContext()->endRecording(); -} - -float Font::floatWidthForComplexText(const TextRun& run, - HashSet*, GlyphOverflow*) const -{ - TextRunWalker walker(run, 0, 0, this); - walker.setWordAndLetterSpacing(wordSpacing(), letterSpacing()); - return walker.widthOfFullRun(); -} - -static int glyphIndexForXPositionInScriptRun(const TextRunWalker& walker, int x) -{ - const HB_Fixed* advances = walker.advances(); - int glyphIndex; - if (walker.rtl()) { - for (glyphIndex = walker.length() - 1; glyphIndex >= 0; --glyphIndex) { - if (x < truncateFixedPointToInteger(advances[glyphIndex])) - break; - x -= truncateFixedPointToInteger(advances[glyphIndex]); - } - } else { - for (glyphIndex = 0; glyphIndex < static_cast(walker.length()); - ++glyphIndex) { - if (x < truncateFixedPointToInteger(advances[glyphIndex])) - break; - x -= truncateFixedPointToInteger(advances[glyphIndex]); - } - } - - return glyphIndex; -} - -int Font::offsetForPositionForComplexText(const TextRun& run, float x, - bool includePartialGlyphs) const -{ - // (Mac code ignores includePartialGlyphs, and they don't know what it's - // supposed to do, so we just ignore it as well.) - TextRunWalker walker(run, 0, 0, this); - walker.setWordAndLetterSpacing(wordSpacing(), letterSpacing()); - - // If this is RTL text, the first glyph from the left is actually the last - // code point. So we need to know how many code points there are total in - // order to subtract. This is different from the length of the TextRun - // because UTF-16 surrogate pairs are a single code point, but 32-bits long. - // In LTR we leave this as 0 so that we get the correct value for - // |basePosition|, below. - unsigned totalCodePoints = 0; - if (walker.rtl()) { - ssize_t offset = 0; - while (offset < run.length()) { - utf16_to_code_point(run.characters(), run.length(), &offset); - totalCodePoints++; - } - } - - unsigned basePosition = totalCodePoints; - - // For RTL: - // code-point order: abcd efg hijkl - // on screen: lkjih gfe dcba - // ^ ^ - // | | - // basePosition--| | - // totalCodePoints----| - // Since basePosition is currently the total number of code-points, the - // first thing we do is decrement it so that it's pointing to the start of - // the current script-run. - // - // For LTR, basePosition is zero so it already points to the start of the - // first script run. - while (walker.nextScriptRun()) { - if (walker.rtl()) - basePosition -= walker.numCodePoints(); - - if (x >= 0 && x < static_cast(walker.width())) { - // The x value in question is within this script run. We consider - // each glyph in presentation order and stop when we find the one - // covering this position. - const int glyphIndex = glyphIndexForXPositionInScriptRun(walker, x); - - // Now that we have a glyph index, we have to turn that into a - // code-point index. Because of ligatures, several code-points may - // have gone into a single glyph. We iterate over the clusters log - // and find the first code-point which contributed to the glyph. - - // Some shapers (i.e. Khmer) will produce cluster logs which report - // that /no/ code points contributed to certain glyphs. Because of - // this, we take any code point which contributed to the glyph in - // question, or any subsequent glyph. If we run off the end, then - // we take the last code point. - const unsigned short* log = walker.logClusters(); - for (unsigned j = 0; j < walker.numCodePoints(); ++j) { - if (log[j] >= glyphIndex) - return basePosition + j; - } - - return basePosition + walker.numCodePoints() - 1; - } - - x -= walker.width(); - - if (!walker.rtl()) - basePosition += walker.numCodePoints(); - } - - return basePosition; -} -#endif - -} diff --git a/Source/WebCore/platform/graphics/android/FontCacheAndroid.cpp b/Source/WebCore/platform/graphics/android/FontCacheAndroid.cpp deleted file mode 100644 index 5696a46..0000000 --- a/Source/WebCore/platform/graphics/android/FontCacheAndroid.cpp +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Copyright 2009, The Android Open Source Project - * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "FontCache.h" - -#include "Font.h" -#include "FontPlatformData.h" -#include "NotImplemented.h" -#include "SimpleFontData.h" -#include "SkPaint.h" -#include "SkTypeface.h" -#include "SkUtils.h" - -namespace WebCore { - -static const char* getFallbackFontName(const FontDescription& fontDescription) -{ - switch (fontDescription.genericFamily()) { - case FontDescription::StandardFamily: - case FontDescription::SerifFamily: - return "serif"; - case FontDescription::SansSerifFamily: - return "sans-serif"; - case FontDescription::MonospaceFamily: - return "monospace"; - case FontDescription::CursiveFamily: - return "cursive"; - case FontDescription::FantasyFamily: - return "fantasy"; - case FontDescription::NoFamily: - default: - return ""; - } -} - -static bool isFallbackFamily(String family) -{ - return family.startsWith("-webkit-") - || equalIgnoringCase(family, "serif") - || equalIgnoringCase(family, "sans-serif") - || equalIgnoringCase(family, "sans") - || equalIgnoringCase(family, "monospace") - || equalIgnoringCase(family, "times") // skia aliases for serif - || equalIgnoringCase(family, "times new roman") - || equalIgnoringCase(family, "palatino") - || equalIgnoringCase(family, "georgia") - || equalIgnoringCase(family, "baskerville") - || equalIgnoringCase(family, "goudy") - || equalIgnoringCase(family, "cursive") - || equalIgnoringCase(family, "fantasy") - || equalIgnoringCase(family, "ITC Stone Serif") - || equalIgnoringCase(family, "arial") // skia aliases for sans-serif - || equalIgnoringCase(family, "helvetica") - || equalIgnoringCase(family, "tahoma") - || equalIgnoringCase(family, "verdana") - || equalIgnoringCase(family, "courier") // skia aliases for monospace - || equalIgnoringCase(family, "courier new") - || equalIgnoringCase(family, "monaco"); -} - -static char* AtomicStringToUTF8String(const AtomicString& utf16) -{ - SkASSERT(sizeof(uint16_t) == sizeof(utf16.characters()[0])); - const uint16_t* uni = (uint16_t*)utf16.characters(); - - size_t bytes = SkUTF16_ToUTF8(uni, utf16.length(), 0); - char* utf8 = (char*)sk_malloc_throw(bytes + 1); - - (void)SkUTF16_ToUTF8(uni, utf16.length(), utf8); - utf8[bytes] = 0; - return utf8; -} - - -void FontCache::platformInit() -{ -} - -const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, const UChar* characters, int length) -{ - // since all of our fonts logically map to the fallback, we can always claim - // that each font supports all characters. - return font.primaryFont(); -} - -SimpleFontData* FontCache::getSimilarFontPlatformData(const Font& font) -{ - return 0; -} - -SimpleFontData* FontCache::getLastResortFallbackFont(const FontDescription& description) -{ - static const AtomicString sansStr("sans-serif"); - static const AtomicString serifStr("serif"); - static const AtomicString monospaceStr("monospace"); - - FontPlatformData* fontPlatformData = 0; - switch (description.genericFamily()) { - case FontDescription::SerifFamily: - fontPlatformData = getCachedFontPlatformData(description, serifStr); - break; - case FontDescription::MonospaceFamily: - fontPlatformData = getCachedFontPlatformData(description, monospaceStr); - break; - case FontDescription::SansSerifFamily: - default: - fontPlatformData = getCachedFontPlatformData(description, sansStr); - break; - } - - ASSERT(fontPlatformData); - return getCachedFontData(fontPlatformData); -} - -FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontDescription, const AtomicString& family) -{ - char* storage = 0; - const char* name = 0; - FontPlatformData* result = 0; - - if (family.length()) { - storage = AtomicStringToUTF8String(family); - name = storage; - } else - name = getFallbackFontName(fontDescription); - - int style = SkTypeface::kNormal; - if (fontDescription.weight() >= FontWeightBold) - style |= SkTypeface::kBold; - if (fontDescription.italic()) - style |= SkTypeface::kItalic; - - // CreateFromName always returns a typeface, falling back to a default font - // if the one requested is not found. Calling Equal() with a null pointer - // serves to compare the returned font against the default, with the caveat - // that the default is always of normal style. If we detect the default, we - // ignore it and allow WebCore to give us the next font on the CSS fallback - // list. The only exception is if the family name is a commonly used generic - // family, as when called by getSimilarFontPlatformData() and - // getLastResortFallbackFont(). In this case, the default font is an - // acceptable result. - - SkTypeface* tf = SkTypeface::CreateFromName(name, SkTypeface::kNormal); - - if (!SkTypeface::Equal(tf, 0) || isFallbackFamily(family.string())) { - // We had to use normal styling to see if this was a default font. If - // we need bold or italic, replace with the corrected typeface. - if (style != SkTypeface::kNormal) { - tf->unref(); - tf = SkTypeface::CreateFromName(name, (SkTypeface::Style)style); - } - - result = new FontPlatformData(tf, fontDescription.computedSize(), - (style & SkTypeface::kBold) && !tf->isBold(), - (style & SkTypeface::kItalic) && !tf->isItalic(), - fontDescription.orientation(), - fontDescription.textOrientation()); - } - - tf->unref(); - sk_free(storage); - return result; -} - - // new as of SVN change 36269, Sept 8, 2008 -void FontCache::getTraitsInFamily(const AtomicString& familyName, Vector& traitsMasks) -{ - // Don't understand this yet, but it seems safe to leave unimplemented -} - -} diff --git a/Source/WebCore/platform/graphics/android/FontCustomPlatformData.cpp b/Source/WebCore/platform/graphics/android/FontCustomPlatformData.cpp deleted file mode 100644 index 693386e..0000000 --- a/Source/WebCore/platform/graphics/android/FontCustomPlatformData.cpp +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright 2008, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "FontCustomPlatformData.h" - -#include "SkTypeface.h" -#include "SkStream.h" -#include "SharedBuffer.h" -#include "FontPlatformData.h" - -namespace WebCore { - -FontCustomPlatformData::FontCustomPlatformData(SkTypeface* face) -{ - SkSafeRef(face); - m_typeface = face; -} - -FontCustomPlatformData::~FontCustomPlatformData() -{ - SkSafeUnref(m_typeface); - // the unref is enough to release the font data... -} - -FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, - FontOrientation fontOrientation, TextOrientation textOrientation, FontWidthVariant, FontRenderingMode) -{ - // turn bold/italic into fakeBold/fakeItalic - if (m_typeface != NULL) { - if (m_typeface->isBold() == bold) - bold = false; - if (m_typeface->isItalic() == italic) - italic = false; - } - return FontPlatformData(m_typeface, size, bold, italic, fontOrientation, textOrientation); -} - -FontCustomPlatformData* createFontCustomPlatformData(SharedBuffer* buffer) -{ - // pass true until we know how we can share the data, and not have to - // make a copy of it. - SkStream* stream = new SkMemoryStream(buffer->data(), buffer->size(), true); - SkTypeface* face = SkTypeface::CreateFromStream(stream); - // Release the stream. - stream->unref(); - if (0 == face) { - SkDebugf("--------- SkTypeface::CreateFromBuffer failed %d\n", - buffer->size()); - return NULL; - } - - SkAutoUnref aur(face); - - return new FontCustomPlatformData(face); -} - -bool FontCustomPlatformData::supportsFormat(const String& format) -{ - return equalIgnoringCase(format, "truetype") || equalIgnoringCase(format, "opentype") -#if ENABLE(OPENTYPE_SANITIZER) - || equalIgnoringCase(format, "woff") -#endif - ; -} - -} diff --git a/Source/WebCore/platform/graphics/android/FontCustomPlatformData.h b/Source/WebCore/platform/graphics/android/FontCustomPlatformData.h deleted file mode 100644 index 47e5e71..0000000 --- a/Source/WebCore/platform/graphics/android/FontCustomPlatformData.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2008, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef FontCustomPlatformData_h -#define FontCustomPlatformData_h - -#include "FontOrientation.h" -#include "FontRenderingMode.h" -#include "FontWidthVariant.h" -#include "TextOrientation.h" -#include -#include - -class SkTypeface; - -namespace WebCore { - -class FontPlatformData; -class SharedBuffer; - -class FontCustomPlatformData { - WTF_MAKE_NONCOPYABLE(FontCustomPlatformData); -public: - FontCustomPlatformData(SkTypeface* face); - ~FontCustomPlatformData(); - - SkTypeface* typeface() const { return m_typeface; } - - FontPlatformData fontPlatformData(int size, bool bold, bool italic, FontOrientation, TextOrientation, FontWidthVariant, FontRenderingMode); - - static bool supportsFormat(const String&); -private: - SkTypeface* m_typeface; -}; - -FontCustomPlatformData* createFontCustomPlatformData(SharedBuffer* buffer); - -} // namespace WebCore - -#endif // FontCustomPlatformData_h diff --git a/Source/WebCore/platform/graphics/android/FontDataAndroid.cpp b/Source/WebCore/platform/graphics/android/FontDataAndroid.cpp deleted file mode 100644 index 88822df..0000000 --- a/Source/WebCore/platform/graphics/android/FontDataAndroid.cpp +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright 2009, The Android Open Source Project - * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" - -#include "EmojiFont.h" -#include "Font.h" -#include "FontCache.h" -#include "SimpleFontData.h" -#include "FloatRect.h" -#include "FontDescription.h" -#include "SkFontHost.h" -#include "SkPaint.h" -#include "SkTypeface.h" -#include "SkTime.h" - -using namespace android; - -namespace WebCore { - -void SimpleFontData::platformInit() -{ - SkPaint paint; - SkPaint::FontMetrics skiaFontMetrics; - - m_platformData.setupPaint(&paint); - paint.getFontMetrics(&skiaFontMetrics); - - float d = SkScalarToFloat(skiaFontMetrics.fDescent); - float s = SkScalarToFloat(skiaFontMetrics.fDescent - skiaFontMetrics.fAscent); - float a = s - d; - - m_fontMetrics.setAscent(a); - m_fontMetrics.setDescent(d); - m_fontMetrics.setXHeight(SkScalarToFloat(-skiaFontMetrics.fAscent) * 0.56f); // hack I stole from the window's port - float lineGap = SkScalarToFloat(skiaFontMetrics.fLeading); - if (platformData().orientation() == Vertical && lineGap == 0) { - lineGap = skiaFontMetrics.fAvgCharWidth * 0.56f; - } - m_fontMetrics.setLineGap(lineGap); - m_fontMetrics.setLineSpacing(a + d + lineGap); - - if (platformData().orientation() == Vertical && !isTextOrientationFallback()) { - static const uint32_t vheaTag = SkSetFourByteTag('v', 'h', 'e', 'a'); - static const uint32_t vorgTag = SkSetFourByteTag('V', 'O', 'R', 'G'); - const SkFontID fontID = m_platformData.uniqueID(); - size_t vheaSize = SkFontHost::GetTableSize(fontID, vheaTag); - size_t vorgSize = SkFontHost::GetTableSize(fontID, vorgTag); - if ((vheaSize > 0) || (vorgSize > 0)) - m_hasVerticalGlyphs = true; - } -} - -void SimpleFontData::platformCharWidthInit() -{ - m_avgCharWidth = 0.f; - m_maxCharWidth = 0.f; - initCharWidths(); -} - -void SimpleFontData::platformDestroy() -{ -} - -SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const -{ - if (!m_derivedFontData) - m_derivedFontData = DerivedFontData::create(isCustomFont()); - if (!m_derivedFontData->smallCaps) - m_derivedFontData->smallCaps = new SimpleFontData(FontPlatformData(m_platformData, fontDescription.computedSize() * 0.7f)); - - return m_derivedFontData->smallCaps.get(); -} - -SimpleFontData* SimpleFontData::emphasisMarkFontData(const FontDescription& fontDescription) const -{ - if (!m_derivedFontData) - m_derivedFontData = DerivedFontData::create(isCustomFont()); - if (!m_derivedFontData->emphasisMark) - m_derivedFontData->emphasisMark = new SimpleFontData(FontPlatformData(m_platformData, fontDescription.computedSize() * 0.5f)); - - return m_derivedFontData->emphasisMark.get(); -} - -bool SimpleFontData::containsCharacters(const UChar* characters, int length) const -{ - SkPaint paint; - - m_platformData.setupPaint(&paint); - paint.setTextEncoding(SkPaint::kUTF16_TextEncoding); - return paint.containsText(characters, length << 1); -} - -void SimpleFontData::determinePitch() -{ - m_treatAsFixedPitch = m_platformData.isFixedPitch(); -} - -FloatRect SimpleFontData::platformBoundsForGlyph(Glyph) const -{ - return FloatRect(); -} - -float SimpleFontData::platformWidthForGlyph(Glyph glyph) const -{ - SkASSERT(sizeof(glyph) == 2); // compile-time assert - - SkPaint paint; - - m_platformData.setupPaint(&paint); - - float advanceWidth; - if (EmojiFont::IsEmojiGlyph(glyph)) - advanceWidth = EmojiFont::GetAdvanceWidth(glyph, paint); - else { - paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); - advanceWidth = SkScalarToFloat(paint.measureText(&glyph, 2)); - } - return advanceWidth; -} - - -} diff --git a/Source/WebCore/platform/graphics/android/FontPlatformData.h b/Source/WebCore/platform/graphics/android/FontPlatformData.h deleted file mode 100644 index 1e46971..0000000 --- a/Source/WebCore/platform/graphics/android/FontPlatformData.h +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright 2009, The Android Open Source Project - * Copyright (C) 2006 Apple Computer, Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -// This file is part of the internal font implementation. It should not be included by anyone other than -// FontMac.cpp, FontWin.cpp and Font.cpp. - -#ifndef FontPlatformData_h -#define FontPlatformData_h - -#include "FontOrientation.h" -#include "TextOrientation.h" -#include - -#ifndef NDEBUG -#include "PlatformString.h" -#endif - -class SkPaint; -class SkTypeface; - -struct HB_FaceRec_; - -namespace WebCore { - -class FontPlatformData { -public: - static FontPlatformData Deleted() { - return FontPlatformData(NULL, -1, false, false); - } - - FontPlatformData(); - FontPlatformData(const FontPlatformData&); - FontPlatformData(SkTypeface*, float textSize, bool fakeBold, bool fakeItalic, - FontOrientation = Horizontal, TextOrientation = TextOrientationVerticalRight); - FontPlatformData(const FontPlatformData& src, float textSize); - FontPlatformData(float size, bool syntheticBold, bool syntheticOblique); - FontPlatformData(const FontPlatformData& src, SkTypeface* typeface); - - ~FontPlatformData(); - - FontPlatformData(WTF::HashTableDeletedValueType) - : mTypeface(hashTableDeletedFontValue()) { } - bool isHashTableDeletedValue() const { - return mTypeface == hashTableDeletedFontValue(); - } - - FontOrientation orientation() const { return mOrientation; } - void setOrientation(FontOrientation orientation) { mOrientation = orientation; } - FontPlatformData& operator=(const FontPlatformData&); - bool operator==(const FontPlatformData& a) const; - - void setupPaint(SkPaint*) const; - - // ------------------------------------------------------------------------- - // Return Skia's unique id for this font. This encodes both the style and - // the font's file name so refers to a single face. - // ------------------------------------------------------------------------- - uint32_t uniqueID() const; - - float size() const { return mTextSize; } - unsigned hash() const; - int emSizeInFontUnits() const; - bool isFixedPitch() const; - -#ifndef NDEBUG - String description() const { return ""; } -#endif - - HB_FaceRec_* harfbuzzFace() const; - SkTypeface* typeface() const { return mTypeface; } - -private: - class RefCountedHarfbuzzFace : public RefCounted { - public: - static PassRefPtr create(HB_FaceRec_* harfbuzzFace) - { - return adoptRef(new RefCountedHarfbuzzFace(harfbuzzFace)); - } - - ~RefCountedHarfbuzzFace(); - - HB_FaceRec_* face() const { return m_harfbuzzFace; } - - private: - RefCountedHarfbuzzFace(HB_FaceRec_* harfbuzzFace) : m_harfbuzzFace(harfbuzzFace) - { - } - - HB_FaceRec_* m_harfbuzzFace; - }; - - SkTypeface* mTypeface; - float mTextSize; - mutable int mEmSizeInFontUnits; - bool mFakeBold; - bool mFakeItalic; - FontOrientation mOrientation; - TextOrientation mTextOrientation; - mutable RefPtr m_harfbuzzFace; - - static SkTypeface* hashTableDeletedFontValue() { - return reinterpret_cast(-1); - } -}; - -} /* namespace */ - -#endif diff --git a/Source/WebCore/platform/graphics/android/FontPlatformDataAndroid.cpp b/Source/WebCore/platform/graphics/android/FontPlatformDataAndroid.cpp deleted file mode 100644 index fc254c0..0000000 --- a/Source/WebCore/platform/graphics/android/FontPlatformDataAndroid.cpp +++ /dev/null @@ -1,273 +0,0 @@ -/* - * Copyright 2009, The Android Open Source Project - * Copyright (C) 2006 Apple Computer, Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -//This file is part of the internal font implementation. It should not be included by anyone other than -// FontMac.cpp, FontWin.cpp and Font.cpp. - -#include "config.h" -#include "FontPlatformData.h" - -#ifdef SUPPORT_COMPLEX_SCRIPTS -#include "HarfbuzzSkia.h" -#endif -#include "SkAdvancedTypefaceMetrics.h" -#include "SkPaint.h" -#include "SkTypeface.h" - -//#define TRACE_FONTPLATFORMDATA_LIFE -//#define COUNT_FONTPLATFORMDATA_LIFE - -#ifdef COUNT_FONTPLATFORMDATA_LIFE -static int gCount; -static int gMaxCount; - -static void inc_count() -{ - if (++gCount > gMaxCount) - { - gMaxCount = gCount; - SkDebugf("---------- FontPlatformData %d\n", gMaxCount); - } -} - -static void dec_count() { --gCount; } -#else - #define inc_count() - #define dec_count() -#endif - -#ifdef TRACE_FONTPLATFORMDATA_LIFE - #define trace(num) SkDebugf("FontPlatformData%d %p %g %d %d\n", num, mTypeface, mTextSize, mFakeBold, mFakeItalic) -#else - #define trace(num) -#endif - -namespace WebCore { - -FontPlatformData::RefCountedHarfbuzzFace::~RefCountedHarfbuzzFace() -{ -#ifdef SUPPORT_COMPLEX_SCRIPTS - HB_FreeFace(m_harfbuzzFace); -#endif -} - -FontPlatformData::FontPlatformData() - : mTypeface(NULL), mTextSize(0), mEmSizeInFontUnits(0), mFakeBold(false), mFakeItalic(false), - mOrientation(Horizontal), mTextOrientation(TextOrientationVerticalRight) -{ - inc_count(); - trace(1); -} - -FontPlatformData::FontPlatformData(const FontPlatformData& src) -{ - if (hashTableDeletedFontValue() != src.mTypeface) { - SkSafeRef(src.mTypeface); - } - - mTypeface = src.mTypeface; - mTextSize = src.mTextSize; - mEmSizeInFontUnits = src.mEmSizeInFontUnits; - mFakeBold = src.mFakeBold; - mFakeItalic = src.mFakeItalic; - m_harfbuzzFace = src.m_harfbuzzFace; - mOrientation = src.mOrientation; - mTextOrientation = src.mTextOrientation; - - inc_count(); - trace(2); -} - -FontPlatformData::FontPlatformData(SkTypeface* tf, float textSize, bool fakeBold, bool fakeItalic, - FontOrientation orientation, TextOrientation textOrientation) - : mTypeface(tf), mTextSize(textSize), mEmSizeInFontUnits(0), mFakeBold(fakeBold), mFakeItalic(fakeItalic), - mOrientation(orientation), mTextOrientation(textOrientation) -{ - if (hashTableDeletedFontValue() != mTypeface) { - SkSafeRef(mTypeface); - } - - inc_count(); - trace(3); -} - -FontPlatformData::FontPlatformData(const FontPlatformData& src, float textSize) - : mTypeface(src.mTypeface), mTextSize(textSize), mEmSizeInFontUnits(src.mEmSizeInFontUnits), mFakeBold(src.mFakeBold), mFakeItalic(src.mFakeItalic), - mOrientation(src.mOrientation), mTextOrientation(src.mTextOrientation), m_harfbuzzFace(src.m_harfbuzzFace) -{ - if (hashTableDeletedFontValue() != mTypeface) { - SkSafeRef(mTypeface); - } - - inc_count(); - trace(4); -} - -FontPlatformData::FontPlatformData(float size, bool bold, bool oblique) - : mTypeface(NULL), mTextSize(size), mEmSizeInFontUnits(0), mFakeBold(bold), mFakeItalic(oblique), - mOrientation(Horizontal), mTextOrientation(TextOrientationVerticalRight) -{ - inc_count(); - trace(5); -} - -FontPlatformData::FontPlatformData(const FontPlatformData& src, SkTypeface* tf) - : mTypeface(tf), mTextSize(src.mTextSize), mEmSizeInFontUnits(0), mFakeBold(src.mFakeBold), - mFakeItalic(src.mFakeItalic), mOrientation(src.mOrientation), - mTextOrientation(src.mTextOrientation) -{ - if (hashTableDeletedFontValue() != mTypeface) { - SkSafeRef(mTypeface); - } - - inc_count(); - trace(6); -} - -FontPlatformData::~FontPlatformData() -{ - dec_count(); -#ifdef TRACE_FONTPLATFORMDATA_LIFE - SkDebugf("----------- ~FontPlatformData\n"); -#endif - - if (hashTableDeletedFontValue() != mTypeface) { - SkSafeUnref(mTypeface); - } -} - -int FontPlatformData::emSizeInFontUnits() const -{ - if (mEmSizeInFontUnits) - return mEmSizeInFontUnits; - - SkAdvancedTypefaceMetrics* metrics = 0; - if (mTypeface) - metrics = mTypeface->getAdvancedTypefaceMetrics(SkAdvancedTypefaceMetrics::kNo_PerGlyphInfo); - if (metrics) { - mEmSizeInFontUnits = metrics->fEmSize; - metrics->unref(); - } else - mEmSizeInFontUnits = 1000; // default value copied from Skia. - return mEmSizeInFontUnits; -} - -FontPlatformData& FontPlatformData::operator=(const FontPlatformData& src) -{ - if (hashTableDeletedFontValue() != src.mTypeface) { - SkSafeRef(src.mTypeface); - } - if (hashTableDeletedFontValue() != mTypeface) { - SkSafeUnref(mTypeface); - } - - mTypeface = src.mTypeface; - mEmSizeInFontUnits = src.mEmSizeInFontUnits; - mTextSize = src.mTextSize; - mFakeBold = src.mFakeBold; - mFakeItalic = src.mFakeItalic; - m_harfbuzzFace = src.m_harfbuzzFace; - mOrientation = src.mOrientation; - mTextOrientation = src.mTextOrientation; - - return *this; -} - -void FontPlatformData::setupPaint(SkPaint* paint) const -{ - if (hashTableDeletedFontValue() == mTypeface) - paint->setTypeface(0); - else - paint->setTypeface(mTypeface); - - paint->setAntiAlias(true); - paint->setSubpixelText(true); - paint->setHinting(SkPaint::kSlight_Hinting); - paint->setTextSize(SkFloatToScalar(mTextSize)); - paint->setFakeBoldText(mFakeBold); - paint->setTextSkewX(mFakeItalic ? -SK_Scalar1/4 : 0); -#ifndef SUPPORT_COMPLEX_SCRIPTS - paint->setTextEncoding(SkPaint::kUTF16_TextEncoding); -#endif -} - -uint32_t FontPlatformData::uniqueID() const -{ - if (hashTableDeletedFontValue() == mTypeface) - return SkTypeface::UniqueID(0); - else - return SkTypeface::UniqueID(mTypeface); -} - -bool FontPlatformData::operator==(const FontPlatformData& a) const -{ - return mTypeface == a.mTypeface && - mTextSize == a.mTextSize && - mFakeBold == a.mFakeBold && - mFakeItalic == a.mFakeItalic && - mOrientation == a.mOrientation && - mTextOrientation == a.mTextOrientation; -} - -unsigned FontPlatformData::hash() const -{ - unsigned h; - - if (hashTableDeletedFontValue() == mTypeface) { - h = reinterpret_cast(mTypeface); - } else { - h = SkTypeface::UniqueID(mTypeface); - } - - uint32_t sizeAsInt = *reinterpret_cast(&mTextSize); - - h ^= 0x01010101 * ((static_cast(mTextOrientation) << 3) | (static_cast(mOrientation) << 2) | - ((int)mFakeBold << 1) | (int)mFakeItalic); - h ^= sizeAsInt; - return h; -} - -bool FontPlatformData::isFixedPitch() const -{ - if (mTypeface && (mTypeface != hashTableDeletedFontValue())) - return mTypeface->isFixedWidth(); - else - return false; -} - -HB_FaceRec_* FontPlatformData::harfbuzzFace() const -{ -#ifdef SUPPORT_COMPLEX_SCRIPTS - if (!m_harfbuzzFace) - m_harfbuzzFace = RefCountedHarfbuzzFace::create( - HB_NewFace(const_cast(this), harfbuzzSkiaGetTable)); - - return m_harfbuzzFace->face(); -#else - return NULL; -#endif -} -} diff --git a/Source/WebCore/platform/graphics/android/GLExtras.cpp b/Source/WebCore/platform/graphics/android/GLExtras.cpp deleted file mode 100644 index 6498ecf..0000000 --- a/Source/WebCore/platform/graphics/android/GLExtras.cpp +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright 2011, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#define LOG_TAG "GLExtras" -#define LOG_NDEBUG 1 - -#include "config.h" - -#include "AndroidLog.h" -#include "DrawExtra.h" -#include "DrawQuadData.h" -#include "GLExtras.h" -#include "IntRect.h" -#include "SkPath.h" -#include "TilesManager.h" -#include "android_graphics.h" - -// Touch ring border width. This is doubled if the ring is not pressed -#define RING_BORDER_WIDTH 1 - -GLExtras::GLExtras() - : m_drawExtra(0) - , m_viewport() -{ -} - -GLExtras::~GLExtras() -{ -} - -void GLExtras::drawRing(SkRect& srcRect, Color color, const TransformationMatrix* drawMat) -{ - if (srcRect.fRight <= srcRect.fLeft || srcRect.fBottom <= srcRect.fTop) { - // Invalid rect, reject it - return; - } - ALOGV("drawQuad [%fx%f, %f, %f]", srcRect.fLeft, srcRect.fTop, - srcRect.width(), srcRect.height()); - // Pull the alpha out of the color so that the shader applies it correctly. - // Otherwise we either don't have blending enabled, or the alpha will get - // double applied - Color colorWithoutAlpha(0xFF000000 | color.rgb()); - float alpha = color.alpha() / (float) 255; - - PureColorQuadData data(colorWithoutAlpha, drawMat ? LayerQuad : BaseQuad, - drawMat, &srcRect, alpha, false); - TilesManager::instance()->shader()->drawQuad(&data); -} - -void GLExtras::drawRegion(const SkRegion& region, bool fill, bool drawBorder, - const TransformationMatrix* drawMat, Color color) -{ - if (region.isEmpty()) - return; - if (fill) { - SkRegion::Iterator rgnIter(region); - while (!rgnIter.done()) { - const SkIRect& ir = rgnIter.rect(); - SkRect r; - r.set(ir.fLeft, ir.fTop, ir.fRight, ir.fBottom); - drawRing(r, color, drawMat); - rgnIter.next(); - } - } - if (fill && !drawBorder) - return; - SkPath path; - if (!region.getBoundaryPath(&path)) - return; - SkPath::Iter iter(path, true); - SkPath::Verb verb; - SkPoint pts[4]; - SkRegion clip; - SkIRect startRect; - while ((verb = iter.next(pts)) != SkPath::kDone_Verb) { - if (verb == SkPath::kLine_Verb) { - SkRect r; - r.set(pts, 2); - SkIRect line; - int borderWidth = RING_BORDER_WIDTH; - if (!fill) - borderWidth *= 2; - line.fLeft = r.fLeft - borderWidth; - line.fRight = r.fRight + borderWidth; - line.fTop = r.fTop - borderWidth; - line.fBottom = r.fBottom + borderWidth; - if (clip.intersects(line)) { - clip.op(line, SkRegion::kReverseDifference_Op); - if (clip.isEmpty()) - continue; // Nothing to draw, continue - line = clip.getBounds(); - if (SkIRect::Intersects(startRect, line)) { - clip.op(startRect, SkRegion::kDifference_Op); - if (clip.isEmpty()) - continue; // Nothing to draw, continue - line = clip.getBounds(); - } - } else { - clip.setRect(line); - } - r.set(line.fLeft, line.fTop, line.fRight, line.fBottom); - drawRing(r, color, drawMat); - if (startRect.isEmpty()) { - startRect.set(line.fLeft, line.fTop, line.fRight, line.fBottom); - } - } - if (verb == SkPath::kMove_Verb) { - startRect.setEmpty(); - } - } -} - -void GLExtras::drawGL(const LayerAndroid* layer) -{ - if (m_drawExtra) - m_drawExtra->drawGL(this, layer); -} diff --git a/Source/WebCore/platform/graphics/android/GLExtras.h b/Source/WebCore/platform/graphics/android/GLExtras.h deleted file mode 100644 index 59a7c3c..0000000 --- a/Source/WebCore/platform/graphics/android/GLExtras.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 2011, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef GLExtras_h -#define GLExtras_h - -#include "Color.h" -#include "DrawExtra.h" -#include "SkRect.h" -#include "SkRegion.h" - -namespace WebCore { - -class LayerAndroid; -class TransformationMatrix; - -class GLExtras { -public: - GLExtras(); - virtual ~GLExtras(); - - void drawGL(const LayerAndroid* layer); - void setDrawExtra(android::DrawExtra* extra) { m_drawExtra = extra; } - void setViewport(const SkRect & viewport) { m_viewport = viewport; } - - void drawRegion(const SkRegion& region, bool fill, bool drawBorder, - const TransformationMatrix* drawMat, Color color = COLOR_HOLO_LIGHT); - -private: - void drawRing(SkRect& srcRect, Color color, const TransformationMatrix* drawMat); - - android::DrawExtra* m_drawExtra; - SkRect m_viewport; -}; - -} // namespace WebCore - -#endif // GLExtras_h diff --git a/Source/WebCore/platform/graphics/android/GLUtils.cpp b/Source/WebCore/platform/graphics/android/GLUtils.cpp deleted file mode 100644 index 26bd55d..0000000 --- a/Source/WebCore/platform/graphics/android/GLUtils.cpp +++ /dev/null @@ -1,669 +0,0 @@ -/* - * Copyright 2010, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#define LOG_TAG "GLUtils" -#define LOG_NDEBUG 1 - -#include "config.h" -#include "GLUtils.h" - -#if USE(ACCELERATED_COMPOSITING) - -#include "AndroidLog.h" -#include "BaseRenderer.h" -#include "TextureInfo.h" -#include "Tile.h" -#include "TilesManager.h" -#include "TransferQueue.h" - -#include -#include -#include - -// We will limit GL error logging for LOG_VOLUME_PER_CYCLE times every -// LOG_VOLUME_PER_CYCLE seconds. -#define LOG_CYCLE 30.0 -#define LOG_VOLUME_PER_CYCLE 20 - -struct ANativeWindowBuffer; - -namespace WebCore { - -using namespace android; - -///////////////////////////////////////////////////////////////////////////////////////// -// Matrix utilities -///////////////////////////////////////////////////////////////////////////////////////// - -void GLUtils::toGLMatrix(GLfloat* flattened, const TransformationMatrix& m) -{ - flattened[0] = m.m11(); // scaleX - flattened[1] = m.m12(); // skewY - flattened[2] = m.m13(); - flattened[3] = m.m14(); // persp0 - flattened[4] = m.m21(); // skewX - flattened[5] = m.m22(); // scaleY - flattened[6] = m.m23(); - flattened[7] = m.m24(); // persp1 - flattened[8] = m.m31(); - flattened[9] = m.m32(); - flattened[10] = m.m33(); - flattened[11] = m.m34(); - flattened[12] = m.m41(); // transX - flattened[13] = m.m42(); // transY - flattened[14] = m.m43(); - flattened[15] = m.m44(); // persp2 -} - -void GLUtils::toSkMatrix(SkMatrix& matrix, const TransformationMatrix& m) -{ - matrix[0] = m.m11(); // scaleX - matrix[1] = m.m21(); // skewX - matrix[2] = m.m41(); // transX - matrix[3] = m.m12(); // skewY - matrix[4] = m.m22(); // scaleY - matrix[5] = m.m42(); // transY - matrix[6] = m.m14(); // persp0 - matrix[7] = m.m24(); // persp1 - matrix[8] = m.m44(); // persp2 -} - -void GLUtils::setOrthographicMatrix(TransformationMatrix& ortho, float left, float top, - float right, float bottom, float nearZ, float farZ) -{ - float deltaX = right - left; - float deltaY = top - bottom; - float deltaZ = farZ - nearZ; - if (!deltaX || !deltaY || !deltaZ) - return; - - ortho.setM11(2.0f / deltaX); - ortho.setM41(-(right + left) / deltaX); - ortho.setM22(2.0f / deltaY); - ortho.setM42(-(top + bottom) / deltaY); - ortho.setM33(-2.0f / deltaZ); - ortho.setM43(-(nearZ + farZ) / deltaZ); -} - -///////////////////////////////////////////////////////////////////////////////////////// -// GL & EGL error checks -///////////////////////////////////////////////////////////////////////////////////////// - -double GLUtils::m_previousLogTime = 0; -int GLUtils::m_currentLogCounter = 0; - -bool GLUtils::allowGLLog() -{ - if (m_currentLogCounter < LOG_VOLUME_PER_CYCLE) { - m_currentLogCounter++; - return true; - } - - // when we are in Log cycle and over the log limit, just return false - double currentTime = WTF::currentTime(); - double delta = currentTime - m_previousLogTime; - bool inLogCycle = (delta <= LOG_CYCLE) && (delta > 0); - if (inLogCycle) - return false; - - // When we are out of Log Cycle and over the log limit, we need to reset - // the counter and timer. - m_previousLogTime = currentTime; - m_currentLogCounter = 0; - return false; -} - -static void crashIfOOM(GLint errorCode) -{ - const GLint OOM_ERROR_CODE = 0x505; - if (errorCode == OOM_ERROR_CODE) { - ALOGE("ERROR: Fatal OOM detected."); - CRASH(); - } -} - -void GLUtils::checkEglError(const char* op, EGLBoolean returnVal) -{ - if (returnVal != EGL_TRUE) { -#ifndef DEBUG - if (allowGLLog()) -#endif - ALOGE("EGL ERROR - %s() returned %d\n", op, returnVal); - } - - for (EGLint error = eglGetError(); error != EGL_SUCCESS; error = eglGetError()) { -#ifndef DEBUG - if (allowGLLog()) -#endif - ALOGE("after %s() eglError (0x%x)\n", op, error); - crashIfOOM(error); - } -} - -bool GLUtils::checkGlError(const char* op) -{ - bool ret = false; - for (GLint error = glGetError(); error; error = glGetError()) { -#ifndef DEBUG - if (allowGLLog()) -#endif - ALOGE("GL ERROR - after %s() glError (0x%x)\n", op, error); - crashIfOOM(error); - ret = true; - } - return ret; -} - -bool GLUtils::checkGlErrorOn(void* p, const char* op) -{ - bool ret = false; - for (GLint error = glGetError(); error; error = glGetError()) { -#ifndef DEBUG - if (allowGLLog()) -#endif - ALOGE("GL ERROR on %x - after %s() glError (0x%x)\n", p, op, error); - crashIfOOM(error); - ret = true; - } - return ret; -} - -void GLUtils::checkSurfaceTextureError(const char* functionName, int status) -{ - if (status != NO_ERROR) { -#ifndef DEBUG - if (allowGLLog()) -#endif - ALOGE("ERROR at calling %s status is (%d)", functionName, status); - } -} -///////////////////////////////////////////////////////////////////////////////////////// -// GL & EGL extension checks -///////////////////////////////////////////////////////////////////////////////////////// - -bool GLUtils::isEGLImageSupported() -{ - const char* eglExtensions = eglQueryString(eglGetCurrentDisplay(), EGL_EXTENSIONS); - const char* glExtensions = reinterpret_cast(glGetString(GL_EXTENSIONS)); - - return eglExtensions && glExtensions - && strstr(eglExtensions, "EGL_KHR_image_base") - && strstr(eglExtensions, "EGL_KHR_gl_texture_2D_image") - && strstr(glExtensions, "GL_OES_EGL_image"); -} - -bool GLUtils::isEGLFenceSyncSupported() -{ - const char* eglExtensions = eglQueryString(eglGetCurrentDisplay(), EGL_EXTENSIONS); - return eglExtensions && strstr(eglExtensions, "EGL_KHR_fence_sync"); -} - -///////////////////////////////////////////////////////////////////////////////////////// -// Textures utilities -///////////////////////////////////////////////////////////////////////////////////////// - -static GLenum getInternalFormat(SkBitmap::Config config) -{ - switch (config) { - case SkBitmap::kA8_Config: - return GL_ALPHA; - case SkBitmap::kARGB_4444_Config: - return GL_RGBA; - case SkBitmap::kARGB_8888_Config: - return GL_RGBA; - case SkBitmap::kRGB_565_Config: - return GL_RGB; - default: - return -1; - } -} - -static GLenum getType(SkBitmap::Config config) -{ - switch (config) { - case SkBitmap::kA8_Config: - return GL_UNSIGNED_BYTE; - case SkBitmap::kARGB_4444_Config: - return GL_UNSIGNED_SHORT_4_4_4_4; - case SkBitmap::kARGB_8888_Config: - return GL_UNSIGNED_BYTE; - case SkBitmap::kIndex8_Config: - return -1; // No type for compressed data. - case SkBitmap::kRGB_565_Config: - return GL_UNSIGNED_SHORT_5_6_5; - default: - return -1; - } -} - -static EGLConfig defaultPbufferConfig(EGLDisplay display) -{ - EGLConfig config; - EGLint numConfigs; - - static const EGLint configAttribs[] = { - EGL_SURFACE_TYPE, EGL_PBUFFER_BIT, - EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, - EGL_NONE - }; - - eglChooseConfig(display, configAttribs, &config, 1, &numConfigs); - GLUtils::checkEglError("eglPbufferConfig"); - if (numConfigs != 1) - ALOGI("eglPbufferConfig failed (%d)\n", numConfigs); - - return config; -} - -static EGLSurface createPbufferSurface(EGLDisplay display, const EGLConfig& config, - EGLint* errorCode) -{ - const EGLint attribList[] = { - EGL_WIDTH, 1, - EGL_HEIGHT, 1, - EGL_NONE - }; - EGLSurface surface = eglCreatePbufferSurface(display, config, attribList); - - if (errorCode) - *errorCode = eglGetError(); - else - GLUtils::checkEglError("eglCreatePbufferSurface"); - - if (surface == EGL_NO_SURFACE) - return EGL_NO_SURFACE; - - return surface; -} - -EGLContext GLUtils::createBackgroundContext(EGLContext sharedContext) -{ - checkEglError(""); - EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); - checkEglError("eglGetDisplay"); - if (display == EGL_NO_DISPLAY) { - ALOGE("eglGetDisplay returned EGL_NO_DISPLAY"); - return EGL_NO_CONTEXT; - } - - EGLint majorVersion; - EGLint minorVersion; - EGLBoolean returnValue = eglInitialize(display, &majorVersion, &minorVersion); - checkEglError("eglInitialize", returnValue); - if (returnValue != EGL_TRUE) { - ALOGE("eglInitialize failed\n"); - return EGL_NO_CONTEXT; - } - - EGLConfig config = defaultPbufferConfig(display); - EGLSurface surface = createPbufferSurface(display, config, 0); - - EGLint surfaceConfigId; - EGLBoolean success = eglGetConfigAttrib(display, config, EGL_CONFIG_ID, &surfaceConfigId); - - EGLint contextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; - EGLContext context = eglCreateContext(display, config, sharedContext, contextAttribs); - checkEglError("eglCreateContext"); - if (context == EGL_NO_CONTEXT) { - ALOGE("eglCreateContext failed\n"); - return EGL_NO_CONTEXT; - } - - returnValue = eglMakeCurrent(display, surface, surface, context); - checkEglError("eglMakeCurrent", returnValue); - if (returnValue != EGL_TRUE) { - ALOGE("eglMakeCurrent failed\n"); - return EGL_NO_CONTEXT; - } - - return context; -} - -void GLUtils::deleteTexture(GLuint* texture) -{ - glDeleteTextures(1, texture); - GLUtils::checkGlError("glDeleteTexture"); - *texture = 0; -} - -GLuint GLUtils::createSampleColorTexture(int r, int g, int b) -{ - GLuint texture; - glGenTextures(1, &texture); - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - GLubyte pixels[4 *3] = { - r, g, b, - r, g, b, - r, g, b, - r, g, b - }; - glBindTexture(GL_TEXTURE_2D, texture); - GLUtils::checkGlError("glBindTexture"); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 2, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, pixels); - GLUtils::checkGlError("glTexImage2D"); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - return texture; -} - -GLuint GLUtils::createSampleTexture() -{ - GLuint texture; - glGenTextures(1, &texture); - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - GLubyte pixels[4 *3] = { - 255, 0, 0, - 0, 255, 0, - 0, 0, 255, - 255, 255, 0 - }; - glBindTexture(GL_TEXTURE_2D, texture); - GLUtils::checkGlError("glBindTexture"); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 2, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, pixels); - GLUtils::checkGlError("glTexImage2D"); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - return texture; -} - -GLuint GLUtils::createTileGLTexture(int width, int height) -{ - GLuint texture; - glGenTextures(1, &texture); - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - GLubyte* pixels = 0; -#ifdef DEBUG - int length = width * height * 4; - pixels = new GLubyte[length]; - for (int i = 0; i < length; i++) - pixels[i] = i % 256; -#endif - glBindTexture(GL_TEXTURE_2D, texture); - GLUtils::checkGlError("glBindTexture"); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); - GLUtils::checkGlError("glTexImage2D"); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); -#ifdef DEBUG - delete pixels; -#endif - return texture; -} - -bool GLUtils::isPureColorBitmap(const SkBitmap& bitmap, Color& pureColor) -{ - // If the bitmap is the pure color, skip the transfer step, and update the Tile Info. - // This check is taking < 1ms if we do full bitmap check per tile. - // TODO: use the SkPicture to determine whether or not a tile is single color. - pureColor = Color(Color::transparent); - bitmap.lockPixels(); - bool sameColor = true; - int bitmapWidth = bitmap.width(); - - // Create a row of pure color using the first pixel. - // TODO: improve the perf here, by either picking a random pixel, or - // creating an array of rows with pre-defined commonly used color, add - // smart LUT to speed things up if possible. - int* firstPixelPtr = static_cast (bitmap.getPixels()); - int* pixelsRow = new int[bitmapWidth]; - for (int i = 0; i < bitmapWidth; i++) - pixelsRow[i] = (*firstPixelPtr); - - // Then compare the pure color row with each row of the bitmap. - for (int j = 0; j < bitmap.height(); j++) { - if (memcmp(pixelsRow, &firstPixelPtr[bitmapWidth * j], 4 * bitmapWidth)) { - sameColor = false; - break; - } - } - delete pixelsRow; - pixelsRow = 0; - - if (sameColor) { - char* rgbaPtr = static_cast(bitmap.getPixels()); - pureColor = Color(rgbaPtr[0], rgbaPtr[1], rgbaPtr[2], rgbaPtr[3]); - ALOGV("sameColor tile found , %x at (%d, %d, %d, %d)", - *firstPixelPtr, rgbaPtr[0], rgbaPtr[1], rgbaPtr[2], rgbaPtr[3]); - } - bitmap.unlockPixels(); - - return sameColor; -} - -// Return true when the tile is pure color. -bool GLUtils::skipTransferForPureColor(const TileRenderInfo* renderInfo, - const SkBitmap& bitmap) -{ - bool skipTransfer = false; - Tile* tilePtr = renderInfo->baseTile; - - // TODO: use pure color for partial invals as well - if (renderInfo->invalRect) - return false; - - if (tilePtr) { - TileTexture* tileTexture = tilePtr->backTexture(); - // Check the bitmap, and make everything ready here. - if (tileTexture && renderInfo->isPureColor) { - // update basetile's info - // Note that we are skipping the whole TransferQueue. - renderInfo->textureInfo->m_width = bitmap.width(); - renderInfo->textureInfo->m_height = bitmap.height(); - renderInfo->textureInfo->m_internalFormat = GL_RGBA; - - TilesManager::instance()->transferQueue()->addItemInPureColorQueue(renderInfo); - - skipTransfer = true; - } - } - return skipTransfer; -} - -void GLUtils::paintTextureWithBitmap(const TileRenderInfo* renderInfo, - const SkBitmap& bitmap) -{ - if (!renderInfo) - return; - const SkSize& requiredSize = renderInfo->tileSize; - TextureInfo* textureInfo = renderInfo->textureInfo; - - if (skipTransferForPureColor(renderInfo, bitmap)) - return; - - if (requiredSize.equals(textureInfo->m_width, textureInfo->m_height)) - GLUtils::updateQueueWithBitmap(renderInfo, bitmap); - else { - if (!requiredSize.equals(bitmap.width(), bitmap.height())) { - ALOGV("The bitmap size (%d,%d) does not equal the texture size (%d,%d)", - bitmap.width(), bitmap.height(), - requiredSize.width(), requiredSize.height()); - } - GLUtils::updateQueueWithBitmap(renderInfo, bitmap); - - textureInfo->m_width = bitmap.width(); - textureInfo->m_height = bitmap.height(); - textureInfo->m_internalFormat = GL_RGBA; - } -} - -void GLUtils::updateQueueWithBitmap(const TileRenderInfo* renderInfo, const SkBitmap& bitmap) -{ - if (!renderInfo - || !renderInfo->textureInfo - || !renderInfo->baseTile) - return; - - TilesManager::instance()->transferQueue()->updateQueueWithBitmap(renderInfo, bitmap); -} - -bool GLUtils::updateSharedSurfaceTextureWithBitmap(ANativeWindow* anw, const SkBitmap& bitmap) -{ - SkAutoLockPixels alp(bitmap); - if (!bitmap.getPixels()) - return false; - ANativeWindow_Buffer buffer; - if (ANativeWindow_lock(anw, &buffer, 0)) - return false; - if (buffer.width < bitmap.width() || buffer.height < bitmap.height()) { - ALOGW("bitmap (%dx%d) too large for buffer (%dx%d)!", - bitmap.width(), bitmap.height(), - buffer.width, buffer.height); - ANativeWindow_unlockAndPost(anw); - return false; - } - uint8_t* img = (uint8_t*)buffer.bits; - int row; - int bpp = 4; // Now we only deal with RGBA8888 format. - bitmap.lockPixels(); - uint8_t* bitmapOrigin = static_cast(bitmap.getPixels()); - - if (buffer.stride != bitmap.width()) - // Copied line by line since we need to handle the offsets and stride. - for (row = 0 ; row < bitmap.height(); row ++) { - uint8_t* dst = &(img[buffer.stride * row * bpp]); - uint8_t* src = &(bitmapOrigin[bitmap.width() * row * bpp]); - memcpy(dst, src, bpp * bitmap.width()); - } - else - memcpy(img, bitmapOrigin, bpp * bitmap.width() * bitmap.height()); - - bitmap.unlockPixels(); - ANativeWindow_unlockAndPost(anw); - return true; -} - -void GLUtils::createTextureWithBitmap(GLuint texture, const SkBitmap& bitmap, GLint filter) -{ - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - glBindTexture(GL_TEXTURE_2D, texture); - GLUtils::checkGlError("glBindTexture"); - SkBitmap::Config config = bitmap.getConfig(); - int internalformat = getInternalFormat(config); - int type = getType(config); - bitmap.lockPixels(); - glTexImage2D(GL_TEXTURE_2D, 0, internalformat, bitmap.width(), bitmap.height(), - 0, internalformat, type, bitmap.getPixels()); - bitmap.unlockPixels(); - if (GLUtils::checkGlError("glTexImage2D")) { -#ifndef DEBUG - if (allowGLLog()) -#endif - ALOGE("GL ERROR: glTexImage2D parameters are : bitmap.width() %d, bitmap.height() %d," - " internalformat 0x%x, type 0x%x, bitmap.getPixels() %p", - bitmap.width(), bitmap.height(), internalformat, type, bitmap.getPixels()); - } - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter); - - // The following is a workaround -- remove when EGLImage texture upload is fixed. - GLuint fboID; - glGenFramebuffers(1, &fboID); - glBindFramebuffer(GL_FRAMEBUFFER, fboID); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0); - glCheckFramebufferStatus(GL_FRAMEBUFFER); // should return GL_FRAMEBUFFER_COMPLETE - - glBindFramebuffer(GL_FRAMEBUFFER, 0); // rebind the standard FBO - glDeleteFramebuffers(1, &fboID); -} - -void GLUtils::updateTextureWithBitmap(GLuint texture, const SkBitmap& bitmap, - const IntRect& inval, GLint filter) -{ - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - glBindTexture(GL_TEXTURE_2D, texture); - GLUtils::checkGlError("glBindTexture"); - SkBitmap::Config config = bitmap.getConfig(); - int internalformat = getInternalFormat(config); - int type = getType(config); - bitmap.lockPixels(); - if (inval.isEmpty()) { - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, bitmap.width(), bitmap.height(), - internalformat, type, bitmap.getPixels()); - } else { - glTexSubImage2D(GL_TEXTURE_2D, 0, inval.x(), inval.y(), inval.width(), inval.height(), - internalformat, type, bitmap.getPixels()); - } - bitmap.unlockPixels(); - if (GLUtils::checkGlError("glTexSubImage2D")) { -#ifndef DEBUG - if (allowGLLog()) -#endif - ALOGE("GL ERROR: glTexSubImage2D parameters are : bitmap.width() %d, bitmap.height() %d," - " internalformat 0x%x, type 0x%x, bitmap.getPixels() %p", - bitmap.width(), bitmap.height(), internalformat, type, bitmap.getPixels()); - } - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter); -} - -void GLUtils::createEGLImageFromTexture(GLuint texture, EGLImageKHR* image) -{ - EGLClientBuffer buffer = reinterpret_cast(texture); - static const EGLint attr[] = { EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE }; - *image = eglCreateImageKHR(eglGetCurrentDisplay(), eglGetCurrentContext(), - EGL_GL_TEXTURE_2D_KHR, buffer, attr); - GLUtils::checkEglError("eglCreateImage", (*image != EGL_NO_IMAGE_KHR)); -} - -void GLUtils::createTextureFromEGLImage(GLuint texture, EGLImageKHR image, GLint filter) -{ - glBindTexture(GL_TEXTURE_2D, texture); - GLUtils::checkGlError("glBindTexture"); - glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)image); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter); -} - -void GLUtils::convertToTransformationMatrix(const float* matrix, TransformationMatrix& transformMatrix) -{ - transformMatrix.setMatrix( - matrix[0], matrix[1], matrix[2], matrix[3], - matrix[4], matrix[5], matrix[6], matrix[7], - matrix[8], matrix[9], matrix[10], matrix[11], - matrix[12], matrix[13], matrix[14], matrix[15]); -} - -void GLUtils::clearBackgroundIfOpaque(const Color* backgroundColor) -{ - if (!backgroundColor->hasAlpha()) { - if (TilesManager::instance()->invertedScreen()) { - float color = 1.0 - ((((float) backgroundColor->red() / 255.0) + - ((float) backgroundColor->green() / 255.0) + - ((float) backgroundColor->blue() / 255.0)) / 3.0); - glClearColor(color, color, color, 1); - } else { - glClearColor((float)backgroundColor->red() / 255.0, - (float)backgroundColor->green() / 255.0, - (float)backgroundColor->blue() / 255.0, 1); - } - glClear(GL_COLOR_BUFFER_BIT); - } -} - -} // namespace WebCore - -#endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/android/GLUtils.h b/Source/WebCore/platform/graphics/android/GLUtils.h deleted file mode 100644 index d4a2e84..0000000 --- a/Source/WebCore/platform/graphics/android/GLUtils.h +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright 2010, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef GLUtils_h -#define GLUtils_h - -#if USE(ACCELERATED_COMPOSITING) - -#include "Color.h" -#include "SkBitmap.h" -#include "SkMatrix.h" -#include "TransformationMatrix.h" -#include -#include -#include -#include - -namespace android { - -class SurfaceTexture; - -} // namespace android - -namespace WebCore { - -class TileRenderInfo; - -class GLUtils { - -public: - // Matrix utilities - static void toGLMatrix(GLfloat* flattened, const TransformationMatrix& matrix); - static void toSkMatrix(SkMatrix& skmatrix, const TransformationMatrix& matrix); - static void setOrthographicMatrix(TransformationMatrix& ortho, float left, float top, - float right, float bottom, float nearZ, float farZ); - - // GL & EGL error checks - static void checkEglError(const char* op, EGLBoolean returnVal = EGL_TRUE); - static bool checkGlErrorOn(void* p, const char* op); - static bool checkGlError(const char* op); - static void checkSurfaceTextureError(const char* functionName, int status); - - // GL & EGL extension checks - static bool isEGLImageSupported(); - static bool isEGLFenceSyncSupported(); - - // Texture utilities - static EGLContext createBackgroundContext(EGLContext sharedContext); - static void deleteTexture(GLuint* texture); - static GLuint createSampleColorTexture(int r, int g, int b); - static GLuint createSampleTexture(); - static GLuint createTileGLTexture(int width, int height); - - static void createTextureWithBitmap(GLuint texture, const SkBitmap& bitmap, GLint filter = GL_LINEAR); - static void updateTextureWithBitmap(GLuint texture, const SkBitmap& bitmap, const IntRect&, GLint filter = GL_LINEAR); - static void createEGLImageFromTexture(GLuint texture, EGLImageKHR* image); - static void createTextureFromEGLImage(GLuint texture, EGLImageKHR image, GLint filter = GL_LINEAR); - - static void paintTextureWithBitmap(const TileRenderInfo* renderInfo, const SkBitmap& bitmap); - static void updateQueueWithBitmap(const TileRenderInfo* , const SkBitmap& bitmap); - static bool updateSharedSurfaceTextureWithBitmap(ANativeWindow* anw, const SkBitmap& bitmap); - static void convertToTransformationMatrix(const float* matrix, TransformationMatrix& transformMatrix); - - static bool isPureColorBitmap(const SkBitmap& bitmap, Color& pureColor); - static bool skipTransferForPureColor(const TileRenderInfo* renderInfo, - const SkBitmap& bitmap); - static void clearBackgroundIfOpaque(const Color* backgroundColor); - static bool allowGLLog(); - static double m_previousLogTime; - static int m_currentLogCounter; -}; - -} // namespace WebCore - -#endif // USE(ACCELERATED_COMPOSITING) -#endif // GLUtils_h diff --git a/Source/WebCore/platform/graphics/android/GaneshContext.cpp b/Source/WebCore/platform/graphics/android/GaneshContext.cpp deleted file mode 100644 index bf43652..0000000 --- a/Source/WebCore/platform/graphics/android/GaneshContext.cpp +++ /dev/null @@ -1,184 +0,0 @@ -/* - * Copyright 2011, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#define LOG_TAG "GaneshContext" -#define LOG_NDEBUG 1 - -#include "config.h" -#include "GaneshContext.h" - -#include "AndroidLog.h" -#include "GLUtils.h" -#include "TextureInfo.h" -#include "TilesManager.h" -#include "TransferQueue.h" - -#include "android/native_window.h" - -#if USE(ACCELERATED_COMPOSITING) - -namespace WebCore { - -GaneshContext::GaneshContext() - : m_grContext(0) - , m_tileDeviceSurface(0) - , m_surfaceConfig(0) - , m_surfaceContext(EGL_NO_CONTEXT) -{ -} - -GaneshContext* GaneshContext::gInstance = 0; - -GaneshContext* GaneshContext::instance() -{ - if (!gInstance) - gInstance = new GaneshContext(); - return gInstance; -} - -GrContext* GaneshContext::getGrContext() -{ - if (!m_grContext) { - m_grContext = GrContext::Create(kOpenGL_Shaders_GrEngine, NULL); - } - return m_grContext; -} - -void GaneshContext::flush() -{ - if (m_grContext) - m_grContext->flush(); -} - -SkDevice* GaneshContext::getDeviceForTile(const TileRenderInfo& renderInfo) -{ - // Ganesh should be the only code in the rendering thread that is using GL - // and setting the EGLContext. If this is not the case then we need to - // reset the Ganesh context to prevent rendering issues. - bool contextNeedsReset = false; - if (eglGetCurrentContext() != m_surfaceContext) { - ALOGV("Warning: EGLContext has Changed! %p, %p", - m_surfaceContext, eglGetCurrentContext()); - contextNeedsReset = true; - } - - EGLDisplay display; - - if (!m_surfaceContext) { - - if(eglGetCurrentContext() != EGL_NO_CONTEXT) { - ALOGV("ERROR: should not have a context yet"); - } - - display = eglGetDisplay(EGL_DEFAULT_DISPLAY); - GLUtils::checkEglError("eglGetDisplay"); - - EGLint majorVersion; - EGLint minorVersion; - EGLBoolean returnValue = eglInitialize(display, &majorVersion, &minorVersion); - GLUtils::checkEglError("eglInitialize", returnValue); - - EGLint numConfigs; - static const EGLint configAttribs[] = { - EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, - EGL_RED_SIZE, 8, - EGL_GREEN_SIZE, 8, - EGL_BLUE_SIZE, 8, - EGL_ALPHA_SIZE, 8, - EGL_STENCIL_SIZE, 8, - EGL_NONE - }; - - eglChooseConfig(display, configAttribs, &m_surfaceConfig, 1, &numConfigs); - GLUtils::checkEglError("eglChooseConfig"); - - static const EGLint contextAttribs[] = { - EGL_CONTEXT_CLIENT_VERSION, 2, - EGL_NONE - }; - - m_surfaceContext = eglCreateContext(display, m_surfaceConfig, NULL, contextAttribs); - GLUtils::checkEglError("eglCreateContext"); - } else { - display = eglGetCurrentDisplay(); - GLUtils::checkEglError("eglGetCurrentDisplay"); - } - - TransferQueue* tileQueue = TilesManager::instance()->transferQueue(); - if (tileQueue->m_eglSurface == EGL_NO_SURFACE) { - - const float tileWidth = renderInfo.tileSize.width(); - const float tileHeight = renderInfo.tileSize.height(); - - ANativeWindow* anw = tileQueue->m_ANW.get(); - - int result = ANativeWindow_setBuffersGeometry(anw, (int)tileWidth, - (int)tileHeight, WINDOW_FORMAT_RGBA_8888); - - renderInfo.textureInfo->m_width = tileWidth; - renderInfo.textureInfo->m_height = tileHeight; - tileQueue->m_eglSurface = eglCreateWindowSurface(display, m_surfaceConfig, anw, NULL); - - GLUtils::checkEglError("eglCreateWindowSurface"); - ALOGV("eglCreateWindowSurface"); - } - - EGLBoolean returnValue = eglMakeCurrent(display, tileQueue->m_eglSurface, tileQueue->m_eglSurface, m_surfaceContext); - GLUtils::checkEglError("eglMakeCurrent", returnValue); - ALOGV("eglMakeCurrent"); - - if (!m_tileDeviceSurface) { - - GrPlatformRenderTargetDesc renderTargetDesc; - renderTargetDesc.fWidth = TilesManager::tileWidth(); - renderTargetDesc.fHeight = TilesManager::tileHeight(); - renderTargetDesc.fConfig = kRGBA_8888_PM_GrPixelConfig; - renderTargetDesc.fSampleCnt = 0; - renderTargetDesc.fStencilBits = 8; - renderTargetDesc.fRenderTargetHandle = 0; - - GrContext* grContext = getGrContext(); - GrRenderTarget* renderTarget = grContext->createPlatformRenderTarget(renderTargetDesc); - - m_tileDeviceSurface = new SkGpuDevice(grContext, renderTarget); - renderTarget->unref(); - ALOGV("generated device %p", m_tileDeviceSurface); - } - - GLUtils::checkGlError("getDeviceForTile"); - - // We must reset the Ganesh context only after we are sure we have - // re-established our EGLContext as the current context. - if (m_tileDeviceSurface && contextNeedsReset) - getGrContext()->resetContext(); - - return m_tileDeviceSurface; -} - - - -} // namespace WebCore - -#endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/android/GaneshContext.h b/Source/WebCore/platform/graphics/android/GaneshContext.h deleted file mode 100644 index 57e8e19..0000000 --- a/Source/WebCore/platform/graphics/android/GaneshContext.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2011, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef GaneshContext_h -#define GaneshContext_h - -#if USE(ACCELERATED_COMPOSITING) - -#include "BaseRenderer.h" -#include "GrContext.h" -#include "SkGpuDevice.h" -#include - -namespace WebCore { - -class GaneshContext { -public: - static GaneshContext* instance(); - - SkDevice* getDeviceForTile(const TileRenderInfo& renderInfo); - - void flush(); - -private: - - GaneshContext(); - - GrContext* getGrContext(); - GrContext* m_grContext; - - SkGpuDevice* m_tileDeviceSurface; - EGLConfig m_surfaceConfig; - EGLContext m_surfaceContext; - - static GaneshContext* gInstance; -}; - -} // namespace WebCore - -#endif // USE(ACCELERATED_COMPOSITING) -#endif // GaneshContext_h diff --git a/Source/WebCore/platform/graphics/android/GaneshRenderer.cpp b/Source/WebCore/platform/graphics/android/GaneshRenderer.cpp deleted file mode 100644 index 208adb6..0000000 --- a/Source/WebCore/platform/graphics/android/GaneshRenderer.cpp +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright 2011, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#define LOG_TAG "GaneshRenderer" -#define LOG_NDEBUG 1 - -#include "config.h" -#include "GaneshRenderer.h" - -#if USE(ACCELERATED_COMPOSITING) - -#include "AndroidLog.h" -#include "GaneshContext.h" -#include "SkCanvas.h" -#include "SkGpuDevice.h" -#include "TilesManager.h" -#include "TransferQueue.h" - -namespace WebCore { - -GaneshRenderer::GaneshRenderer() : BaseRenderer(BaseRenderer::Ganesh) -{ -#ifdef DEBUG_COUNT - ClassTracker::instance()->increment("GaneshRenderer"); -#endif -} - -GaneshRenderer::~GaneshRenderer() -{ -#ifdef DEBUG_COUNT - ClassTracker::instance()->decrement("GaneshRenderer"); -#endif -} - -void GaneshRenderer::setupCanvas(const TileRenderInfo& renderInfo, SkCanvas* canvas) -{ - GaneshContext* ganesh = GaneshContext::instance(); - - TransferQueue* tileQueue = TilesManager::instance()->transferQueue(); - - tileQueue->lockQueue(); - - bool ready = tileQueue->readyForUpdate(); - if (!ready) { - ALOGV("!ready"); - tileQueue->unlockQueue(); - return; - } - - SkDevice* device = NULL; - if (renderInfo.tileSize.width() == TilesManager::tileWidth() - && renderInfo.tileSize.height() == TilesManager::tileHeight()) { - device = ganesh->getDeviceForTile(renderInfo); - } else { - // TODO support arbitrary sizes for layers - ALOGV("ERROR: expected (%d,%d) actual (%d,%d)", - TilesManager::tileWidth(), TilesManager::tileHeight(), - renderInfo.tileSize.width(), renderInfo.tileSize.height()); - } - - // set the GPU device to the canvas - canvas->setDevice(device); -} - -void GaneshRenderer::setupPartialInval(const TileRenderInfo& renderInfo, SkCanvas* canvas) -{ - // set the clip to our invalRect - SkRect clipRect = SkRect::MakeLTRB(renderInfo.invalRect->fLeft, - renderInfo.invalRect->fTop, - renderInfo.invalRect->fRight, - renderInfo.invalRect->fBottom); - canvas->clipRect(clipRect); -} - -void GaneshRenderer::renderingComplete(const TileRenderInfo& renderInfo, SkCanvas* canvas) -{ - ALOGV("rendered to tile (%d,%d)", renderInfo.x, renderInfo.y); - - GaneshContext::instance()->flush(); - - // In SurfaceTextureMode we must call swapBuffers to unlock and post the - // tile's ANativeWindow (i.e. SurfaceTexture) buffer - TransferQueue* tileQueue = TilesManager::instance()->transferQueue(); - eglSwapBuffers(eglGetCurrentDisplay(), tileQueue->m_eglSurface); - tileQueue->addItemInTransferQueue(&renderInfo, GpuUpload, 0); - tileQueue->unlockQueue(); -} - -} // namespace WebCore - -#endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/android/GaneshRenderer.h b/Source/WebCore/platform/graphics/android/GaneshRenderer.h deleted file mode 100644 index d7eda24..0000000 --- a/Source/WebCore/platform/graphics/android/GaneshRenderer.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright 2011, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef GaneshRenderer_h -#define GaneshRenderer_h - -#if USE(ACCELERATED_COMPOSITING) - -#include "BaseRenderer.h" -#include "SkRect.h" - -class SkCanvas; -class SkDevice; - -namespace WebCore { - -/** - * - */ -class GaneshRenderer : public BaseRenderer { -public: - GaneshRenderer(); - ~GaneshRenderer(); - -protected: - - virtual void setupCanvas(const TileRenderInfo& renderInfo, SkCanvas* canvas); - virtual void setupPartialInval(const TileRenderInfo& renderInfo, SkCanvas* canvas); - virtual void renderingComplete(const TileRenderInfo& renderInfo, SkCanvas* canvas); - virtual void checkForPureColor(TileRenderInfo& renderInfo, SkCanvas* canvas) { - renderInfo.isPureColor = false; - } - -}; - -} // namespace WebCore - -#endif // USE(ACCELERATED_COMPOSITING) -#endif // GaneshRenderer_h diff --git a/Source/WebCore/platform/graphics/android/GlyphMapAndroid.cpp b/Source/WebCore/platform/graphics/android/GlyphMapAndroid.cpp deleted file mode 100644 index a327b79..0000000 --- a/Source/WebCore/platform/graphics/android/GlyphMapAndroid.cpp +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright 2009, The Android Open Source Project - * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" - -#include "EmojiFont.h" -#include "Font.h" -#include "GlyphPageTreeNode.h" -#include "HarfbuzzSkia.h" -#include "SimpleFontData.h" -#include "SkFontHost.h" -#include "SkPaint.h" -#include "SkTemplates.h" -#include "SkUtils.h" -#include "VerticalTextMap.h" - - -using namespace android; - -namespace WebCore { - -#define NO_BREAK_SPACE_UNICHAR 0xA0 - -static int substituteWithVerticalGlyphs(const FontPlatformData& platformData, uint16_t* glyphs, unsigned bufferLength) -{ - HB_FaceRec_* hbFace = platformData.harfbuzzFace(); - if (!hbFace->gsub) { - // if there is no GSUB table, treat it as not covered - return 0Xffff; - } - - HB_Buffer buffer; - hb_buffer_new(&buffer); - for (unsigned i = 0; i < bufferLength; ++i) - hb_buffer_add_glyph(buffer, glyphs[i], 0, i); - - HB_UShort scriptIndex; - HB_UShort featureIndex; - - HB_GSUB_Select_Script(hbFace->gsub, HB_MAKE_TAG('D', 'F', 'L', 'T'), &scriptIndex); - HB_GSUB_Select_Feature(hbFace->gsub, HB_MAKE_TAG('v', 'e', 'r', 't'), scriptIndex, 0xffff, &featureIndex); - HB_GSUB_Add_Feature(hbFace->gsub, featureIndex, 1); - HB_GSUB_Select_Feature(hbFace->gsub, HB_MAKE_TAG('v', 'r', 't', '2'), scriptIndex, 0xffff, &featureIndex); - HB_GSUB_Add_Feature(hbFace->gsub, featureIndex, 1); - - int error = HB_GSUB_Apply_String(hbFace->gsub, buffer); - if (!error) { - for (unsigned i = 0; i < bufferLength; ++i) - glyphs[i] = static_cast(buffer->out_string[i].gindex); - } - return error; -} - -bool GlyphPage::fill(unsigned offset, unsigned length, UChar* buffer, unsigned bufferLength, const SimpleFontData* fontData) -{ - if (SkUTF16_IsHighSurrogate(buffer[bufferLength-1])) { - SkDebugf("%s last char is high-surrogate", __FUNCTION__); - return false; - } - - SkPaint paint; - fontData->platformData().setupPaint(&paint); - paint.setTextEncoding(SkPaint::kUTF16_TextEncoding); - - SkAutoSTMalloc glyphStorage(length); - uint16_t* glyphs = glyphStorage.get(); - UChar *textBuffer = buffer; - UChar vTextBuffer[bufferLength]; - - if (fontData->platformData().orientation() == Vertical && !fontData->hasVerticalGlyphs()) { - // Convert to vertical form if there is no vertical glyphs. - for (unsigned i = 0; i < bufferLength; ++i) { - vTextBuffer[i] = VerticalTextMap::getVerticalForm(buffer[i]); - if (!vTextBuffer[i]) - vTextBuffer[i] = buffer[i]; - } - textBuffer = vTextBuffer; - } - - unsigned count = paint.textToGlyphs(textBuffer, bufferLength << 1, glyphs); - if (count != length) { - SkDebugf("%s count != length\n", __FUNCTION__); - return false; - } - - if (fontData->hasVerticalGlyphs()) { - bool lookVariants = false; - for (unsigned i = 0; i < bufferLength; ++i) { - if (!Font::isCJKIdeograph(textBuffer[i])) { - lookVariants = true; - continue; - } - } - if (lookVariants) - substituteWithVerticalGlyphs(fontData->platformData(), glyphs, bufferLength); - } - - unsigned allGlyphs = 0; // track if any of the glyphIDs are non-zero - - // search for emoji. If we knew for sure that buffer was a contiguous range - // of chars, we could quick-reject the range to avoid this loop (usually) - if (EmojiFont::IsAvailable()) { - const UChar* curr = textBuffer; - for (unsigned i = 0; i < length; i++) { - SkUnichar uni = SkUTF16_NextUnichar(&curr); - uint16_t glyphID = glyphs[i]; - // only sniff if the normal font failed to recognize it - if (!glyphID) - glyphID = EmojiFont::UnicharToGlyph(uni); - setGlyphDataForIndex(offset + i, glyphID, fontData); - allGlyphs |= glyphID; - } - } else { - for (unsigned i = 0; i < length; i++) { - uint16_t glyphID = glyphs[i]; - setGlyphDataForIndex(offset + i, glyphID, fontData); - allGlyphs |= glyphID; - } - } - return allGlyphs != 0; -} - -} diff --git a/Source/WebCore/platform/graphics/android/HarfbuzzSkia.cpp b/Source/WebCore/platform/graphics/android/HarfbuzzSkia.cpp deleted file mode 100644 index 7c3a6b4..0000000 --- a/Source/WebCore/platform/graphics/android/HarfbuzzSkia.cpp +++ /dev/null @@ -1,221 +0,0 @@ -/* - * Copyright 2010, The Android Open Source Project - * Copyright 2010, Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" - -#include "FontPlatformData.h" - -#include -#include -#include -#include -#include -#include -#include - -extern "C" { -#include "harfbuzz-shaper.h" -} - -// This file implements the callbacks which Harfbuzz requires by using Skia -// calls. See the Harfbuzz source for references about what these callbacks do. - -namespace WebCore { - -static HB_Fixed SkiaScalarToHarfbuzzFixed(SkScalar value) -{ - // HB_Fixed is a 26.6 fixed point format. - return value * 64; -} - -static HB_Bool stringToGlyphs(HB_Font hbFont, const HB_UChar16* characters, hb_uint32 length, HB_Glyph* glyphs, hb_uint32* glyphsSize, HB_Bool isRTL) -{ - FontPlatformData* font = reinterpret_cast(hbFont->userData); - SkPaint paint; - - font->setupPaint(&paint); - paint.setTextEncoding(SkPaint::kUTF16_TextEncoding); - int numGlyphs = paint.textToGlyphs(characters, length * sizeof(uint16_t), reinterpret_cast(glyphs)); - - // HB_Glyph is 32-bit, but Skia outputs only 16-bit numbers. So our - // |glyphs| array needs to be converted. - for (int i = numGlyphs - 1; i >= 0; --i) { - uint16_t value; - // We use a memcpy to avoid breaking strict aliasing rules. - memcpy(&value, reinterpret_cast(glyphs) + sizeof(uint16_t) * i, sizeof(value)); - glyphs[i] = value; - } - - *glyphsSize = numGlyphs; - return 1; -} - -static void glyphsToAdvances(HB_Font hbFont, const HB_Glyph* glyphs, hb_uint32 numGlyphs, HB_Fixed* advances, int flags) -{ - FontPlatformData* font = reinterpret_cast(hbFont->userData); - SkPaint paint; - - font->setupPaint(&paint); - paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); - - OwnArrayPtr glyphs16 = adoptArrayPtr(new uint16_t[numGlyphs]); - if (!glyphs16.get()) - return; - for (unsigned i = 0; i < numGlyphs; ++i) - glyphs16[i] = glyphs[i]; - paint.getTextWidths(glyphs16.get(), numGlyphs * sizeof(uint16_t), reinterpret_cast(advances)); - - // The |advances| values which Skia outputs are SkScalars, which are floats - // in Chromium. However, Harfbuzz wants them in 26.6 fixed point format. - // These two formats are both 32-bits long. - for (unsigned i = 0; i < numGlyphs; ++i) { - float value; - // We use a memcpy to avoid breaking strict aliasing rules. - memcpy(&value, reinterpret_cast(advances) + sizeof(float) * i, sizeof(value)); - advances[i] = SkiaScalarToHarfbuzzFixed(value); - } -} - -static HB_Bool canRender(HB_Font hbFont, const HB_UChar16* characters, hb_uint32 length) -{ - FontPlatformData* font = reinterpret_cast(hbFont->userData); - SkPaint paint; - - font->setupPaint(&paint); - paint.setTextEncoding(SkPaint::kUTF16_TextEncoding); - - OwnArrayPtr glyphs16 = adoptArrayPtr(new uint16_t[length]); - glyphs16.get(); - int numGlyphs = paint.textToGlyphs(characters, length * sizeof(uint16_t), glyphs16.get()); - - for (int i = 0; i < numGlyphs; ++i) { - if (!glyphs16[i]) - return false; - } - - return true; -} - -static HB_Error getOutlinePoint(HB_Font hbFont, HB_Glyph glyph, int flags, hb_uint32 point, HB_Fixed* xPos, HB_Fixed* yPos, hb_uint32* resultingNumPoints) -{ - FontPlatformData* font = reinterpret_cast(hbFont->userData); - SkPaint paint; - - if (flags & HB_ShaperFlag_UseDesignMetrics) - return HB_Err_Invalid_Argument; // This is requesting pre-hinted positions. We can't support this. - - font->setupPaint(&paint); - paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); - uint16_t glyph16 = glyph; - SkPath path; - paint.getTextPath(&glyph16, sizeof(glyph16), 0, 0, &path); - uint32_t numPoints = path.getPoints(0, 0); - if (point >= numPoints) - return HB_Err_Invalid_SubTable; - SkPoint* points = reinterpret_cast(fastMalloc(sizeof(SkPoint) * (point + 1))); - if (!points) - return HB_Err_Invalid_SubTable; - // Skia does let us get a single point from the path. - path.getPoints(points, point + 1); - *xPos = SkiaScalarToHarfbuzzFixed(points[point].fX); - *yPos = SkiaScalarToHarfbuzzFixed(points[point].fY); - *resultingNumPoints = numPoints; - fastFree(points); - - return HB_Err_Ok; -} - -static void getGlyphMetrics(HB_Font hbFont, HB_Glyph glyph, HB_GlyphMetrics* metrics) -{ - FontPlatformData* font = reinterpret_cast(hbFont->userData); - SkPaint paint; - - font->setupPaint(&paint); - paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); - uint16_t glyph16 = glyph; - SkScalar width; - SkRect bounds; - paint.getTextWidths(&glyph16, sizeof(glyph16), &width, &bounds); - - metrics->x = SkiaScalarToHarfbuzzFixed(bounds.fLeft); - metrics->y = SkiaScalarToHarfbuzzFixed(bounds.fTop); - metrics->width = SkiaScalarToHarfbuzzFixed(bounds.width()); - metrics->height = SkiaScalarToHarfbuzzFixed(bounds.height()); - - metrics->xOffset = SkiaScalarToHarfbuzzFixed(width); - // We can't actually get the |y| correct because Skia doesn't export - // the vertical advance. However, nor we do ever render vertical text at - // the moment so it's unimportant. - metrics->yOffset = 0; -} - -static HB_Fixed getFontMetric(HB_Font hbFont, HB_FontMetric metric) -{ - FontPlatformData* font = reinterpret_cast(hbFont->userData); - SkPaint paint; - - font->setupPaint(&paint); - SkPaint::FontMetrics skiaMetrics; - paint.getFontMetrics(&skiaMetrics); - - switch (metric) { - case HB_FontAscent: - return SkiaScalarToHarfbuzzFixed(-skiaMetrics.fAscent); - // We don't support getting the rest of the metrics and Harfbuzz doesn't seem to need them. - default: - return 0; - } -} - -HB_FontClass harfbuzzSkiaClass = { - stringToGlyphs, - glyphsToAdvances, - canRender, - getOutlinePoint, - getGlyphMetrics, - getFontMetric, -}; - -HB_Error harfbuzzSkiaGetTable(void* voidface, const HB_Tag tag, HB_Byte* buffer, HB_UInt* len) -{ - FontPlatformData* font = reinterpret_cast(voidface); - - const size_t tableSize = SkFontHost::GetTableSize(font->uniqueID(), tag); - if (!tableSize) - return HB_Err_Invalid_Argument; - // If Harfbuzz specified a NULL buffer then it's asking for the size of the table. - if (!buffer) { - *len = tableSize; - return HB_Err_Ok; - } - - if (*len < tableSize) - return HB_Err_Invalid_Argument; - SkFontHost::GetTableData(font->uniqueID(), tag, 0, tableSize, buffer); - return HB_Err_Ok; -} - -} // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/HarfbuzzSkia.h b/Source/WebCore/platform/graphics/android/HarfbuzzSkia.h deleted file mode 100644 index d26bbe2..0000000 --- a/Source/WebCore/platform/graphics/android/HarfbuzzSkia.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2010, The Android Open Source Project - * Copyright 2010, Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef HarfbuzzSkia_h -#define HarfbuzzSkia_h - -extern "C" { -#include "harfbuzz-shaper.h" -#include "harfbuzz-unicode.h" -} - -namespace WebCore { - HB_Error harfbuzzSkiaGetTable(void* voidface, const HB_Tag, HB_Byte* buffer, HB_UInt* len); - extern const HB_FontClass harfbuzzSkiaClass; -} // namespace WebCore - -#endif diff --git a/Source/WebCore/platform/graphics/android/IFrameContentLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/IFrameContentLayerAndroid.cpp deleted file mode 100644 index dadb13d..0000000 --- a/Source/WebCore/platform/graphics/android/IFrameContentLayerAndroid.cpp +++ /dev/null @@ -1,42 +0,0 @@ -#define LOG_TAG "IFrameContentLayerAndroid" -#define LOG_NDEBUG 1 - -#include "config.h" -#include "IFrameContentLayerAndroid.h" - -#include "AndroidLog.h" - -#if USE(ACCELERATED_COMPOSITING) - -namespace WebCore { - -bool IFrameContentLayerAndroid::scrollTo(int x, int y) -{ - IntRect scrollBounds; - getScrollBounds(&scrollBounds); - if (!scrollBounds.width() && !scrollBounds.height()) - return false; - SkScalar newX = SkScalarPin(x, scrollBounds.x(), scrollBounds.width()); - SkScalar newY = SkScalarPin(y, scrollBounds.y(), scrollBounds.height()); - // Check for no change. - if (newX == m_iframeScrollOffset.x() && newY == m_iframeScrollOffset.y()) - return false; - newX = newX - m_iframeScrollOffset.x(); - newY = newY - m_iframeScrollOffset.y(); - setScrollOffset(IntPoint(newX, newY)); - return true; -} - -void IFrameContentLayerAndroid::getScrollRect(SkIRect* out) const -{ - const SkPoint& pos = getPosition(); - out->fLeft = m_scrollLimits.fLeft - pos.fX + m_iframeScrollOffset.x(); - out->fTop = m_scrollLimits.fTop - pos.fY + m_iframeScrollOffset.y(); - - out->fRight = getSize().width() - m_scrollLimits.width(); - out->fBottom = getSize().height() - m_scrollLimits.height(); -} - -} // namespace WebCore - -#endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/android/IFrameContentLayerAndroid.h b/Source/WebCore/platform/graphics/android/IFrameContentLayerAndroid.h deleted file mode 100644 index 64b2d06..0000000 --- a/Source/WebCore/platform/graphics/android/IFrameContentLayerAndroid.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright 2012, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef IFrameContentLayerAndroid_h -#define IFrameContentLayerAndroid_h - -#if USE(ACCELERATED_COMPOSITING) - -#include "ScrollableLayerAndroid.h" - -namespace WebCore { - -class IFrameContentLayerAndroid : public ScrollableLayerAndroid { - -public: - IFrameContentLayerAndroid(RenderLayer* owner) - : ScrollableLayerAndroid(owner) {} - IFrameContentLayerAndroid(const ScrollableLayerAndroid& layer) - : ScrollableLayerAndroid(layer) {} - IFrameContentLayerAndroid(const LayerAndroid& layer) - : ScrollableLayerAndroid(layer) {} - IFrameContentLayerAndroid(const IFrameContentLayerAndroid& layer) - : ScrollableLayerAndroid(layer) - , m_iframeScrollOffset(layer.m_iframeScrollOffset) {} - - virtual ~IFrameContentLayerAndroid() {}; - - // isIFrame() return true for compatibility reason (see ViewStateSerializer) - virtual bool isIFrame() const { return true; } - virtual bool isIFrameContent() const { return true; } - - virtual LayerAndroid* copy() const { return new IFrameContentLayerAndroid(*this); } - virtual SubclassType subclassType() { return LayerAndroid::IFrameContentLayer; } - - // Scrolls to the given position in the layer. - // Returns whether or not any scrolling was required. - virtual bool scrollTo(int x, int y); - - // Fills the rect with the current scroll offset and the maximum scroll offset. - // fLeft = scrollX - // fTop = scrollY - // fRight = maxScrollX - // fBottom = maxScrollY - virtual void getScrollRect(SkIRect*) const; - - void setIFrameScrollOffset(IntPoint offset) { m_iframeScrollOffset = offset; } - -private: - IntPoint m_iframeScrollOffset; -}; - -} - -#endif // USE(ACCELERATED_COMPOSITING) - -#endif // IFrameContentLayerAndroid_h diff --git a/Source/WebCore/platform/graphics/android/IFrameLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/IFrameLayerAndroid.cpp deleted file mode 100644 index 3532542..0000000 --- a/Source/WebCore/platform/graphics/android/IFrameLayerAndroid.cpp +++ /dev/null @@ -1,40 +0,0 @@ -#define LOG_TAG "IFrameLayerAndroid" -#define LOG_NDEBUG 1 - -#include "config.h" -#include "IFrameLayerAndroid.h" - -#if USE(ACCELERATED_COMPOSITING) - -#include "AndroidLog.h" -#include "DumpLayer.h" - -namespace WebCore { - -IFrameLayerAndroid* IFrameLayerAndroid::updatePosition(SkRect viewport, - IFrameLayerAndroid* parentIframeLayer) -{ - // As we are an iframe, accumulate the offset from the parent with - // the current position, and change the parent pointer. - - // If this is the top level, take the current position - SkPoint parentOffset; - parentOffset.set(0,0); - if (parentIframeLayer) - parentOffset = parentIframeLayer->getPosition(); - - SkPoint offset = parentOffset + getPosition(); - m_iframeOffset = IntPoint(offset.fX, offset.fY); - - return this; -} - -void IFrameLayerAndroid::dumpLayer(FILE* file, int indentLevel) const -{ - writeIntVal(file, indentLevel + 1, "m_isIframe", true); - writeIntPoint(file, indentLevel + 1, "m_iframeOffset", m_iframeOffset); -} - -} // namespace WebCore - -#endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/android/IFrameLayerAndroid.h b/Source/WebCore/platform/graphics/android/IFrameLayerAndroid.h deleted file mode 100644 index e12188a..0000000 --- a/Source/WebCore/platform/graphics/android/IFrameLayerAndroid.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright 2012, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef IFrameLayerAndroid_h -#define IFrameLayerAndroid_h - -#if USE(ACCELERATED_COMPOSITING) - -#include "LayerAndroid.h" - -namespace WebCore { - -class IFrameLayerAndroid : public LayerAndroid { - -public: - IFrameLayerAndroid(RenderLayer* owner) - : LayerAndroid(owner) {} - IFrameLayerAndroid(const LayerAndroid& layer) - : LayerAndroid(layer) {} - IFrameLayerAndroid(const IFrameLayerAndroid& layer) - : LayerAndroid(layer) - , m_iframeOffset(layer.m_iframeOffset) {} - - virtual ~IFrameLayerAndroid() {}; - - virtual bool isIFrame() const { return true; } - - virtual LayerAndroid* copy() const { return new IFrameLayerAndroid(*this); } - virtual SubclassType subclassType() { return LayerAndroid::IFrameLayer; } - - virtual IFrameLayerAndroid* updatePosition(SkRect viewport, - IFrameLayerAndroid* parentIframeLayer); - - virtual void dumpLayer(FILE*, int indentLevel) const; - - const IntPoint& iframeOffset() const { return m_iframeOffset; } - -private: - IntPoint m_iframeOffset; -}; - -} - -#endif // USE(ACCELERATED_COMPOSITING) - -#endif // IFrameLayerAndroid_h diff --git a/Source/WebCore/platform/graphics/android/ImageTexture.cpp b/Source/WebCore/platform/graphics/android/ImageTexture.cpp deleted file mode 100644 index b2ead6a..0000000 --- a/Source/WebCore/platform/graphics/android/ImageTexture.cpp +++ /dev/null @@ -1,256 +0,0 @@ -/* - * Copyright 2011, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#define LOG_TAG "ImageTexture" -#define LOG_NDEBUG 1 - -#include "config.h" -#include "ImageTexture.h" - -#include "AndroidLog.h" -#include "ClassTracker.h" -#include "ImagesManager.h" -#include "LayerAndroid.h" -#include "SkDevice.h" -#include "SkPicture.h" -#include "TileGrid.h" -#include "TilesManager.h" - -namespace WebCore { - -// CRC computation adapted from Tools/DumpRenderTree/CyclicRedundancyCheck.cpp -static void makeCrcTable(unsigned crcTable[256]) -{ - for (unsigned i = 0; i < 256; i++) { - unsigned c = i; - for (int k = 0; k < 8; k++) { - if (c & 1) - c = -306674912 ^ ((c >> 1) & 0x7fffffff); - else - c = c >> 1; - } - crcTable[i] = c; - } -} - -unsigned computeCrc(uint8_t* buffer, size_t size) -{ - static unsigned crcTable[256]; - static bool crcTableComputed = false; - if (!crcTableComputed) { - makeCrcTable(crcTable); - crcTableComputed = true; - } - - unsigned crc = 0xffffffffL; - for (size_t i = 0; i < size; ++i) - crc = crcTable[(crc ^ buffer[i]) & 0xff] ^ ((crc >> 8) & 0x00ffffffL); - return crc ^ 0xffffffffL; -} - -ImageTexture::ImageTexture(SkBitmap* bmp, unsigned crc) - : m_image(bmp) - , m_texture(0) - , m_layer(0) - , m_picture(0) - , m_crc(crc) -{ -#ifdef DEBUG_COUNT - ClassTracker::instance()->increment("ImageTexture"); -#endif - if (!m_image) - return; - - // NOTE: This constructor is called on the webcore thread - - // Create a picture containing the image (needed for TileGrid) - m_picture = new SkPicture(); - SkCanvas* pcanvas = m_picture->beginRecording(m_image->width(), m_image->height()); - pcanvas->clear(SkColorSetARGBInline(0, 0, 0, 0)); - pcanvas->drawBitmap(*m_image, 0, 0); - m_picture->endRecording(); -} - -ImageTexture::~ImageTexture() -{ -#ifdef DEBUG_COUNT - ClassTracker::instance()->decrement("ImageTexture"); -#endif - delete m_image; - delete m_texture; - SkSafeUnref(m_picture); -} - -SkBitmap* ImageTexture::convertBitmap(SkBitmap* bitmap) -{ - SkBitmap* img = new SkBitmap(); - int w = bitmap->width(); - int h = bitmap->height(); - - // Create a copy of the image - img->setConfig(SkBitmap::kARGB_8888_Config, w, h); - img->allocPixels(); - SkDevice* device = new SkDevice(*img); - SkCanvas canvas; - canvas.setDevice(device); - device->unref(); - SkRect dest; - dest.set(0, 0, w, h); - img->setIsOpaque(false); - img->eraseARGB(0, 0, 0, 0); - canvas.drawBitmapRect(*bitmap, 0, dest); - - return img; -} - -unsigned ImageTexture::computeCRC(const SkBitmap* bitmap) -{ - if (!bitmap) - return 0; - bitmap->lockPixels(); - uint8_t* img = static_cast(bitmap->getPixels()); - unsigned crc = computeCrc(img, bitmap->getSize()); - bitmap->unlockPixels(); - return crc; -} - -bool ImageTexture::equalsCRC(unsigned crc) -{ - return m_crc == crc; -} - -int ImageTexture::nbTextures() -{ - if (!hasContentToShow()) - return 0; - if (!m_texture) - return 0; - - // TODO: take in account the visible clip (need to maintain - // a list of the clients layer, etc.) - IntRect visibleArea(0, 0, m_image->width(), m_image->height()); - int nbTextures = m_texture->nbTextures(visibleArea, 1.0); - ALOGV("ImageTexture %p, %d x %d needs %d textures", - this, m_image->width(), m_image->height(), - nbTextures); - return nbTextures; -} - -bool ImageTexture::hasContentToShow() -{ - // Don't display 1x1 image -- no need to allocate a full texture for this - if (!m_image) - return false; - if (m_image->width() == 1 && m_image->height() == 1) - return false; - return true; -} - -bool ImageTexture::prepareGL(GLWebViewState* state) -{ - if (!hasContentToShow()) - return false; - - if (!m_texture && m_picture) { - bool isLayerTile = true; - m_texture = new TileGrid(isLayerTile); - SkRegion region; - region.setRect(0, 0, m_image->width(), m_image->height()); - m_texture->markAsDirty(region); - } - - if (!m_texture) - return false; - - IntRect unclippedArea(0, 0, m_image->width(), m_image->height()); - m_texture->prepareGL(state, 1.0, unclippedArea, unclippedArea, this); - if (m_texture->isReady()) { - m_texture->swapTiles(); - return false; - } - return true; -} - -const TransformationMatrix* ImageTexture::transform() -{ - if (!m_layer) - return 0; - - FloatPoint p(0, 0); - p = m_layer->drawTransform()->mapPoint(p); - IntRect layerArea = m_layer->unclippedArea(); - float scaleW = static_cast(layerArea.width()) / static_cast(m_image->width()); - float scaleH = static_cast(layerArea.height()) / static_cast(m_image->height()); - TransformationMatrix d = *(m_layer->drawTransform()); - TransformationMatrix m; - m.scaleNonUniform(scaleW, scaleH); - m_layerMatrix = d.multiply(m); - return &m_layerMatrix; -} - -float ImageTexture::opacity() -{ - if (!m_layer) - return 1.0; - return m_layer->drawOpacity(); -} - -bool ImageTexture::paint(Tile* tile, SkCanvas* canvas) -{ - if (!m_picture) { - ALOGV("IT %p COULDNT PAINT, NO PICTURE", this); - return false; - } - - ALOGV("IT %p painting tile %d, %d with picture %p", this, tile->x(), tile->y(), m_picture); - canvas->drawPicture(*m_picture); - - return true; -} - -void ImageTexture::drawGL(LayerAndroid* layer, float opacity) -{ - if (!layer) - return; - if (!hasContentToShow()) - return; - - // TileGrid::draw() will call us back to know the - // transform and opacity, so we need to set m_layer - m_layer = layer; - if (m_texture) { - IntRect visibleArea = m_layer->visibleArea(); - m_texture->drawGL(visibleArea, opacity, transform()); - } - m_layer = 0; -} - -void ImageTexture::drawCanvas(SkCanvas* canvas, SkRect& rect) -{ - if (canvas && m_image) - canvas->drawBitmapRect(*m_image, 0, rect); -} - -} // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/ImageTexture.h b/Source/WebCore/platform/graphics/android/ImageTexture.h deleted file mode 100644 index 34430f1..0000000 --- a/Source/WebCore/platform/graphics/android/ImageTexture.h +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright 2011, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef ImageTexture_h -#define ImageTexture_h - -#include "GLUtils.h" -#include "SkBitmap.h" -#include "SkBitmapRef.h" -#include "SkPicture.h" -#include "SkRefCnt.h" -#include "TilePainter.h" - -namespace WebCore { - -class GLWebViewState; -class LayerAndroid; -class TexturesResult; -class TileGrid; - -///////////////////////////////////////////////////////////////////////////////// -// Image sharing codepath for layers -///////////////////////////////////////////////////////////////////////////////// -// -// Layers containing only an image take a slightly different codepath; -// GraphicsLayer::setContentsToImage() is called on the webcore thread, -// passing an Image instance. We get the native image (an SkBitmap) and create -// an ImageTexture instance with it (or increment the refcount of an existing -// instance if the SkBitmap is similar to one already stored in ImagesManager, -// i.e. if two GraphicsLayer share the same image). -// -// To detect if an image is similar, we compute and use a CRC. Each ImageTexture -// is stored in ImagesManager using its CRC as a hash key. -// Simply comparing the address is not enough -- different image could end up -// at the same address (i.e. the image is deallocated then a new one is -// reallocated at the old address) -// -// Each ImageTexture's CRC being unique, LayerAndroid instances simply store that -// and retain/release the corresponding ImageTexture (so that -// queued painting request will work correctly and not crash...). -// LayerAndroid running on the UI thread will get the corresponding -// ImageTexture at draw time. -// -// ImageTexture recopy the original SkBitmap so that they can safely be used -// on a different thread; it uses TileGrid to allocate and paint the image, -// so that we can share the same textures and limits as the rest of the layers. -// -///////////////////////////////////////////////////////////////////////////////// -class ImageTexture : public TilePainter { -public: - ImageTexture(SkBitmap* bmp, unsigned crc); - virtual ~ImageTexture(); - - bool prepareGL(GLWebViewState*); - void drawGL(LayerAndroid* layer, float opacity); - void drawCanvas(SkCanvas*, SkRect&); - bool hasContentToShow(); - SkBitmap* bitmap() { return m_image; } - unsigned imageCRC() { return m_crc; } - - static SkBitmap* convertBitmap(SkBitmap* bitmap); - - static unsigned computeCRC(const SkBitmap* bitmap); - bool equalsCRC(unsigned crc); - - // methods used by TileGrid - virtual bool paint(Tile* tile, SkCanvas* canvas); - virtual float opacity(); - - int nbTextures(); - - virtual SurfaceType type() { return TilePainter::Image; } - -private: - const TransformationMatrix* transform(); - - SkBitmapRef* m_imageRef; - SkBitmap* m_image; - TileGrid* m_texture; - LayerAndroid* m_layer; - SkPicture* m_picture; - TransformationMatrix m_layerMatrix; - unsigned m_crc; -}; - -} // namespace WebCore - -#endif // ImageTexture diff --git a/Source/WebCore/platform/graphics/android/ImagesManager.cpp b/Source/WebCore/platform/graphics/android/ImagesManager.cpp deleted file mode 100644 index 8452503..0000000 --- a/Source/WebCore/platform/graphics/android/ImagesManager.cpp +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright 2011, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#define LOG_TAG "ImagesManager" -#define LOG_NDEBUG 1 - -#include "config.h" -#include "ImagesManager.h" - -#include "AndroidLog.h" -#include "SkCanvas.h" -#include "SkDevice.h" -#include "SkRefCnt.h" -#include "ImageTexture.h" - -namespace WebCore { - -ImagesManager* ImagesManager::instance() -{ - if (!gInstance) - gInstance = new ImagesManager(); - - return gInstance; -} - -ImagesManager* ImagesManager::gInstance = 0; - -ImageTexture* ImagesManager::setImage(SkBitmapRef* imgRef) -{ - if (!imgRef) - return 0; - - SkBitmap* bitmap = &imgRef->bitmap(); - ImageTexture* image = 0; - SkBitmap* img = 0; - unsigned crc = 0; - - img = ImageTexture::convertBitmap(bitmap); - crc = ImageTexture::computeCRC(img); - - { - android::Mutex::Autolock lock(m_imagesLock); - if (m_images.contains(crc)) { - image = m_images.get(crc); - SkSafeRef(image); - return image; - } - } - - // the image is not in the map, we add it - - image = new ImageTexture(img, crc); - - android::Mutex::Autolock lock(m_imagesLock); - m_images.set(crc, image); - - return image; -} - -ImageTexture* ImagesManager::retainImage(unsigned imgCRC) -{ - if (!imgCRC) - return 0; - - android::Mutex::Autolock lock(m_imagesLock); - ImageTexture* image = 0; - if (m_images.contains(imgCRC)) { - image = m_images.get(imgCRC); - SkSafeRef(image); - } - return image; -} - -void ImagesManager::releaseImage(unsigned imgCRC) -{ - if (!imgCRC) - return; - - android::Mutex::Autolock lock(m_imagesLock); - if (m_images.contains(imgCRC)) { - ImageTexture* image = m_images.get(imgCRC); - if (image->getRefCnt() == 1) - m_images.remove(imgCRC); - SkSafeUnref(image); - } -} - -int ImagesManager::nbTextures() -{ - android::Mutex::Autolock lock(m_imagesLock); - HashMap::iterator end = m_images.end(); - int i = 0; - int nb = 0; - for (HashMap::iterator it = m_images.begin(); it != end; ++it) { - nb += it->second->nbTextures(); - i++; - } - return nb; -} - -bool ImagesManager::prepareTextures(GLWebViewState* state) -{ - bool ret = false; - android::Mutex::Autolock lock(m_imagesLock); - HashMap::iterator end = m_images.end(); - for (HashMap::iterator it = m_images.begin(); it != end; ++it) { - ret |= it->second->prepareGL(state); - } - return ret; -} - -} // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/ImagesManager.h b/Source/WebCore/platform/graphics/android/ImagesManager.h deleted file mode 100644 index b915a46..0000000 --- a/Source/WebCore/platform/graphics/android/ImagesManager.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2011, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef ImagesManager_h -#define ImagesManager_h - -#include "HashMap.h" -#include "SkBitmap.h" -#include "SkBitmapRef.h" -#include "SkRefCnt.h" -#include "Vector.h" - -#include - -namespace WebCore { - -class ImageTexture; -class GLWebViewState; - -class ImagesManager { -public: - static ImagesManager* instance(); - - ImageTexture* setImage(SkBitmapRef* imgRef); - ImageTexture* retainImage(unsigned imgCRC); - void releaseImage(unsigned imgCRC); - - bool prepareTextures(GLWebViewState*); - int nbTextures(); - -private: - ImagesManager() {} - - static ImagesManager* gInstance; - - android::Mutex m_imagesLock; - HashMap m_images; -}; - -} // namespace WebCore - -#endif // ImagesManager diff --git a/Source/WebCore/platform/graphics/android/InspectorCanvas.cpp b/Source/WebCore/platform/graphics/android/InspectorCanvas.cpp deleted file mode 100644 index f9edb74..0000000 --- a/Source/WebCore/platform/graphics/android/InspectorCanvas.cpp +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright 2011, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#define LOG_TAG "InspectorCanvas" -#define LOG_NDEBUG 1 - -#include "config.h" -#include "InspectorCanvas.h" - -#include "AndroidLog.h" -#include "SkPicture.h" - -namespace WebCore { - - -void InspectorCanvas::setHasText() -{ - m_hasText = true; - setHasContent(); -} - -void InspectorCanvas::setHasContent() -{ - m_hasContent = true; - if (m_hasText) { - // has text. Have to paint properly, so no further - // information is useful - m_picture->abortPlayback(); - } -} - -void InspectorCanvas::setIsBackground(const SkPaint& paint) -{ - // TODO: if the paint is a solid color, opaque, and the last instruction in - // the picture, replace the picture with simple draw rect info - setHasContent(); -} - -void InspectorCanvas::commonDrawBitmap(const SkBitmap& bitmap, - const SkIRect* rect, - const SkMatrix&, - const SkPaint&) -{ - setHasContent(); -} - -void InspectorCanvas::drawPaint(const SkPaint& paint) -{ - setHasContent(); -} - -void InspectorCanvas::drawPath(const SkPath&, const SkPaint& paint) -{ - setHasContent(); -} -void InspectorCanvas::drawPoints(PointMode, size_t, - const SkPoint [], const SkPaint& paint) -{ - setHasContent(); -} - -void InspectorCanvas::drawRect(const SkRect& rect, const SkPaint& paint) -{ - if (rect.fLeft == 0 - && rect.fTop == 0 - && rect.width() >= m_picture->width() - && rect.height() >= m_picture->height()) { - // rect same size as canvas, treat layer as a single color rect until - // more content is drawn - setIsBackground(paint); - } else { - // regular rect drawing path - setHasContent(); - } - ALOGV("draw rect at %f %f, size %f %f, picture size %d %d", - rect.fLeft, rect.fTop, rect.width(), rect.height(), - m_picture->width(), m_picture->height()); -} -void InspectorCanvas::drawSprite(const SkBitmap& , int , int , - const SkPaint* paint) -{ - setHasContent(); -} - -void InspectorCanvas::drawText(const void*, size_t byteLength, SkScalar, - SkScalar, const SkPaint& paint) -{ - setHasText(); -} - -void InspectorCanvas::drawPosText(const void* , size_t byteLength, - const SkPoint [], const SkPaint& paint) -{ - setHasText(); -} - -void InspectorCanvas::drawPosTextH(const void*, size_t byteLength, - const SkScalar [], SkScalar, - const SkPaint& paint) -{ - setHasText(); -} - -void InspectorCanvas::drawTextOnPath(const void*, size_t byteLength, - const SkPath&, const SkMatrix*, - const SkPaint& paint) -{ - setHasText(); -} - -} // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/InspectorCanvas.h b/Source/WebCore/platform/graphics/android/InspectorCanvas.h deleted file mode 100644 index 415a579..0000000 --- a/Source/WebCore/platform/graphics/android/InspectorCanvas.h +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright 2011, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef InspectorCanvas_h -#define InspectorCanvas_h - -#include "SkBounder.h" -#include "SkCanvas.h" - -namespace WebCore { - -class InspectorBounder : public SkBounder { - virtual bool onIRect(const SkIRect& rect) - { - return false; - } -}; - -class InspectorCanvas : public SkCanvas { -public: - InspectorCanvas(SkBounder* bounder, SkPicture* picture) - : m_picture(picture) - , m_hasText(false) - , m_hasContent(false) - { - setBounder(bounder); - } - - bool hasText() {return m_hasText;} - bool hasContent() {return m_hasContent;} - - virtual bool clipPath(const SkPath&, SkRegion::Op) { - return true; - } - - virtual void commonDrawBitmap(const SkBitmap& bitmap, - const SkIRect* rect, - const SkMatrix&, - const SkPaint&); - - virtual void drawPaint(const SkPaint& paint); - virtual void drawPath(const SkPath&, const SkPaint& paint); - virtual void drawPoints(PointMode, size_t, - const SkPoint [], const SkPaint& paint); - - virtual void drawRect(const SkRect& , const SkPaint& paint); - virtual void drawSprite(const SkBitmap& , int , int , - const SkPaint* paint = NULL); - - virtual void drawText(const void*, size_t byteLength, SkScalar, - SkScalar, const SkPaint& paint); - virtual void drawPosText(const void* , size_t byteLength, - const SkPoint [], const SkPaint& paint); - virtual void drawPosTextH(const void*, size_t byteLength, - const SkScalar [], SkScalar, - const SkPaint& paint); - virtual void drawTextOnPath(const void*, size_t byteLength, - const SkPath&, const SkMatrix*, - const SkPaint& paint); - -private: - - // vector instructions exist, must repaint at any scale - void setHasText(); - - // painting is required - void setHasContent(); - - // rect covering entire content, don't need to use a texture if nothing else - // is painted - void setIsBackground(const SkPaint& paint); - - SkPicture* m_picture; - bool m_hasText; - bool m_hasContent; -}; - -} // namespace WebCore - -#endif // InspectorCanvas_h diff --git a/Source/WebCore/platform/graphics/android/Layer.cpp b/Source/WebCore/platform/graphics/android/Layer.cpp deleted file mode 100644 index 48e36fc..0000000 --- a/Source/WebCore/platform/graphics/android/Layer.cpp +++ /dev/null @@ -1,237 +0,0 @@ -#define LOG_TAG "Layer" -#define LOG_NDEBUG 1 - -#include "config.h" -#include "Layer.h" - -#include "AndroidLog.h" -#include "SkCanvas.h" - -//#define DEBUG_DRAW_LAYER_BOUNDS -//#define DEBUG_TRACK_NEW_DELETE - -#ifdef DEBUG_TRACK_NEW_DELETE - static int gLayerAllocCount; -#endif - -/////////////////////////////////////////////////////////////////////////////// - -Layer::Layer() { - fParent = NULL; - m_opacity = SK_Scalar1; - m_size.set(0, 0); - m_position.set(0, 0); - m_anchorPoint.set(SK_ScalarHalf, SK_ScalarHalf); - - m_matrix.reset(); - m_childrenMatrix.reset(); - m_shouldInheritFromRootTransform = false; - - m_hasOverflowChildren = false; - m_state = 0; - -#ifdef DEBUG_TRACK_NEW_DELETE - gLayerAllocCount += 1; - SkDebugf("Layer new: %d\n", gLayerAllocCount); -#endif -} - -Layer::Layer(const Layer& src) : INHERITED() { - fParent = NULL; - m_opacity = src.m_opacity; - m_size = src.m_size; - m_position = src.m_position; - m_anchorPoint = src.m_anchorPoint; - - m_matrix = src.m_matrix; - m_childrenMatrix = src.m_childrenMatrix; - m_shouldInheritFromRootTransform = src.m_shouldInheritFromRootTransform; - - m_hasOverflowChildren = src.m_hasOverflowChildren; - m_state = 0; - -#ifdef DEBUG_TRACK_NEW_DELETE - gLayerAllocCount += 1; - SkDebugf("Layer copy: %d\n", gLayerAllocCount); -#endif -} - -Layer::~Layer() { - removeChildren(); - -#ifdef DEBUG_TRACK_NEW_DELETE - gLayerAllocCount -= 1; - SkDebugf("Layer delete: %d\n", gLayerAllocCount); -#endif -} - -/////////////////////////////////////////////////////////////////////////////// - -int Layer::countChildren() const { - return m_children.count(); -} - -Layer* Layer::getChild(int index) const { - if ((unsigned)index < (unsigned)m_children.count()) { - SkASSERT(m_children[index]->fParent == this); - return m_children[index]; - } - return NULL; -} - -Layer* Layer::addChild(Layer* child) { - SkASSERT(this != child); - child->ref(); - child->detachFromParent(); - SkASSERT(child->fParent == NULL); - child->fParent = this; - - *m_children.append() = child; - return child; -} - -void Layer::detachFromParent() { - if (fParent) { - int index = fParent->m_children.find(this); - SkASSERT(index >= 0); - fParent->m_children.remove(index); - fParent = NULL; - unref(); // this call might delete us - } -} - -void Layer::removeChildren() { - int count = m_children.count(); - for (int i = 0; i < count; i++) { - Layer* child = m_children[i]; - SkASSERT(child->fParent == this); - child->fParent = NULL; // in case it has more than one owner - child->unref(); - } - m_children.reset(); -} - -Layer* Layer::getRootLayer() const { - const Layer* root = this; - while (root->fParent != NULL) { - root = root->fParent; - } - return const_cast(root); -} - -/////////////////////////////////////////////////////////////////////////////// - -void Layer::getLocalTransform(SkMatrix* matrix) const { - matrix->setTranslate(m_position.fX, m_position.fY); - - SkScalar tx = SkScalarMul(m_anchorPoint.fX, m_size.width()); - SkScalar ty = SkScalarMul(m_anchorPoint.fY, m_size.height()); - matrix->preTranslate(tx, ty); - matrix->preConcat(getMatrix()); - matrix->preTranslate(-tx, -ty); -} - -void Layer::localToAncestor(const Layer* ancestor, SkMatrix* matrix) const { - if (this == ancestor) { - matrix->setIdentity(); - return; - } - - getLocalTransform(matrix); - - // Fixed position layers simply use the root layer's transform. - if (shouldInheritFromRootTransform()) { - ASSERT(!ancestor); - matrix->postConcat(getRootLayer()->getMatrix()); - return; - } - - // Apply the local and child transforms for every layer between this layer - // and ancestor. - ASSERT(isAncestor(ancestor)); - for (const Layer* layer = this->fParent; layer != ancestor; layer = layer->fParent) { - SkMatrix tmp; - layer->getLocalTransform(&tmp); - tmp.preConcat(layer->getChildrenMatrix()); - matrix->postConcat(tmp); - } - - // If ancestor is not the root layer, apply its child transformation too. - if (ancestor) - matrix->postConcat(ancestor->getChildrenMatrix()); -} - -/////////////////////////////////////////////////////////////////////////////// - -#include "SkString.h" - -void Layer::draw(SkCanvas* canvas, android::DrawExtra* extra, SkScalar opacity) { -#if 0 - SkString str1, str2; - // getMatrix().toDumpString(&str1); - // getChildrenMatrix().toDumpString(&str2); - SkDebugf("--- drawlayer %p opacity %g size [%g %g] pos [%g %g] matrix %s children %s\n", - this, opacity * getOpacity(), m_size.width(), m_size.height(), - m_position.fX, m_position.fY, str1.c_str(), str2.c_str()); -#endif - - opacity = SkScalarMul(opacity, getOpacity()); - if (opacity <= 0) { -// SkDebugf("---- abort drawing %p opacity %g\n", this, opacity); - return; - } - - SkAutoCanvasRestore acr(canvas, true); - - // apply our local transform - { - SkMatrix tmp; - getLocalTransform(&tmp); - if (shouldInheritFromRootTransform()) { - // should we also apply the root's childrenMatrix? - canvas->setMatrix(getRootLayer()->getMatrix()); - } - canvas->concat(tmp); - } - - onDraw(canvas, opacity, extra, FlattenedLayers); - -#ifdef DEBUG_DRAW_LAYER_BOUNDS - { - SkRect r = SkRect::MakeSize(getSize()); - SkPaint p; - p.setAntiAlias(true); - p.setStyle(SkPaint::kStroke_Style); - p.setStrokeWidth(SkIntToScalar(2)); - p.setColor(0xFFFF44DD); - canvas->drawRect(r, p); - canvas->drawLine(r.fLeft, r.fTop, r.fRight, r.fBottom, p); - canvas->drawLine(r.fLeft, r.fBottom, r.fRight, r.fTop, p); - } -#endif - - int count = countChildren(); - if (count > 0) { - canvas->concat(getChildrenMatrix()); - for (int i = 0; i < count; i++) { - getChild(i)->draw(canvas, extra, opacity); - } - } -} - -bool Layer::isAncestor(const Layer* possibleAncestor) const { - if (!possibleAncestor) - return true; - for (const Layer* layer = getParent(); layer; layer = layer->getParent()) { - if (layer == possibleAncestor) - return true; - } - return false; -} - -void Layer::setState(WebCore::GLWebViewState* state) { - m_state = state; - int count = countChildren(); - for (int i = 0; i < count; i++) - m_children[i]->setState(state); -} diff --git a/Source/WebCore/platform/graphics/android/Layer.h b/Source/WebCore/platform/graphics/android/Layer.h deleted file mode 100644 index 996547b..0000000 --- a/Source/WebCore/platform/graphics/android/Layer.h +++ /dev/null @@ -1,184 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef Layer_DEFINED -#define Layer_DEFINED - -#include "DrawExtra.h" -#include "TestExport.h" -#include "SkRefCnt.h" -#include "SkTDArray.h" -#include "SkColor.h" -#include "SkMatrix.h" -#include "SkPoint.h" -#include "SkRect.h" -#include "SkRegion.h" -#include "SkSize.h" - -namespace WebCore { -class IntRect; -class GLWebViewState; -}; - -class SkCanvas; - -class TEST_EXPORT Layer : public SkRefCnt { - -public: - Layer(); - Layer(const Layer&); - virtual ~Layer(); - - // Whether the layer should apply its tranform directly onto the root - // layer, rather than using the transforms of all ancestor layers. This is - // used for fixed position layers. - bool shouldInheritFromRootTransform() const { return m_shouldInheritFromRootTransform; } - SkScalar getOpacity() const { return m_opacity; } - const SkSize& getSize() const { return m_size; } - const SkPoint& getPosition() const { return m_position; } - const SkPoint& getAnchorPoint() const { return m_anchorPoint; } - const SkMatrix& getMatrix() const { return m_matrix; } - const SkMatrix& getChildrenMatrix() const { return m_childrenMatrix; } - - SkScalar getWidth() const { return m_size.width(); } - SkScalar getHeight() const { return m_size.height(); } - - void setShouldInheritFromRootTransform(bool inherit) { m_shouldInheritFromRootTransform = inherit; } - void setOpacity(SkScalar opacity) { m_opacity = opacity; } - void setSize(SkScalar w, SkScalar h) { m_size.set(w, h); } - void setPosition(SkScalar x, SkScalar y) { m_position.set(x, y); } - void setAnchorPoint(SkScalar x, SkScalar y) { m_anchorPoint.set(x, y); } - void setMatrix(const SkMatrix& matrix) { m_matrix = matrix; } - void setChildrenMatrix(const SkMatrix& matrix) { m_childrenMatrix = matrix; } - -// rendering asset management - void markAsDirty(const SkRegion& invalRegion) { - m_dirtyRegion.op(invalRegion, SkRegion::kUnion_Op); - } - - bool isDirty() { - return !m_dirtyRegion.isEmpty(); - } - -// drawing - - WebCore::GLWebViewState* state() { return m_state; } - void setState(WebCore::GLWebViewState* state); - -// children - - /** Return the number of layers in our child list. - */ - int countChildren() const; - - /** Return the child at the specified index (starting at 0). This does not - affect the reference count of the child. - */ - Layer* getChild(int index) const; - - /** Add this layer to our child list at the end (top-most), and ref() it. - If it was already in another hierarchy, remove it from that list. - Return the new child. - */ - Layer* addChild(Layer* child); - - /** Remove this layer from its parent's list (or do nothing if it has no - parent.) If it had a parent, then unref() is called. - */ - void detachFromParent(); - - /** Remove, and unref(), all of the layers in our child list. - */ - void removeChildren(); - - /** Return our parent layer, or NULL if we have none. - */ - Layer* getParent() const { return fParent; } - - /** Return the root layer in this hiearchy. If this layer is the root - (i.e. has no parent), then this returns itself. - */ - Layer* getRootLayer() const; - - // coordinate system transformations - - /** Return, in matrix, the matix transfomations that are applied locally - when this layer draws (i.e. its position and matrix/anchorPoint). - This does not include the childrenMatrix, since that is only applied - after this layer draws (but before its children draw). - */ - virtual void getLocalTransform(SkMatrix* matrix) const; - - /** Return, in matrix, the concatenation of transforms that are applied - from this layer's root parent to the layer itself. - This is the matrix that is applied to the layer during drawing. - */ - void localToGlobal(SkMatrix* matrix) const { localToAncestor(0, matrix); } - - /** Return, as a matrix, the transform that converts from this layer's local - space to the space of the given ancestor layer. Use NULL for ancestor to - represent the root layer. Note that this method must not be called on a - fixed position layer with ancestor != NULL. - - For non-fixed position layers, the following holds (in pseudo-code for - brevity) ... - SkMatrix localToAncestor = layer->localToAncestor(ancestor); - SkMatrix ancestorToGlobal = ancestor->localToAncestor(NULL); - SkMatrix localToGlobal = layer->localToGlobal(); - ASSERT(localToAncestor * ancestorToGlobal == localToGlobal); - */ - void localToAncestor(const Layer* ancestor, SkMatrix* matrix) const; - - // paint method - - virtual bool drawCanvas(SkCanvas*) { return false; } - void draw(SkCanvas*, android::DrawExtra* extra, SkScalar opacity = SK_Scalar1); - - void setHasOverflowChildren(bool value) { m_hasOverflowChildren = value; } - - virtual bool contentIsScrollable() const { return false; } - - typedef enum { MergedLayers, UnmergedLayers, FlattenedLayers } PaintStyle; -protected: - virtual void onDraw(SkCanvas*, SkScalar opacity, android::DrawExtra* extra, PaintStyle style) {} - - bool m_hasOverflowChildren; - - bool isAncestor(const Layer*) const; - - Layer* fParent; - SkScalar m_opacity; - SkSize m_size; - // The position of the origin of the layer, relative to the parent layer. - SkPoint m_position; - // The point in the layer used as the origin for local transformations, - // expressed as a fraction of the layer size. - SkPoint m_anchorPoint; - SkMatrix m_matrix; - SkMatrix m_childrenMatrix; - bool m_shouldInheritFromRootTransform; - - SkTDArray m_children; - - // invalidation region - SkRegion m_dirtyRegion; - - WebCore::GLWebViewState* m_state; - - typedef SkRefCnt INHERITED; -}; - -#endif diff --git a/Source/WebCore/platform/graphics/android/LayerAndroid.cpp b/Source/WebCore/platform/graphics/android/LayerAndroid.cpp deleted file mode 100644 index df3fa42..0000000 --- a/Source/WebCore/platform/graphics/android/LayerAndroid.cpp +++ /dev/null @@ -1,1034 +0,0 @@ -#define LOG_TAG "LayerAndroid" -#define LOG_NDEBUG 1 - -#include "config.h" -#include "LayerAndroid.h" - -#if USE(ACCELERATED_COMPOSITING) - -#include "AndroidLog.h" -#include "AndroidAnimation.h" -#include "ClassTracker.h" -#include "DrawExtra.h" -#include "DumpLayer.h" -#include "FixedPositioning.h" -#include "GLUtils.h" -#include "GLWebViewState.h" -#include "ImagesManager.h" -#include "InspectorCanvas.h" -#include "LayerContent.h" -#include "MediaLayer.h" -#include "ParseCanvas.h" -#include "PictureLayerContent.h" -#include "SkBitmapRef.h" -#include "SkDrawFilter.h" -#include "SkPaint.h" -#include "SkPicture.h" -#include "Surface.h" -#include "TilesManager.h" - -#include -#include -#include - -#define DISABLE_LAYER_MERGE -#undef DISABLE_LAYER_MERGE - -#define LAYER_MERGING_DEBUG -#undef LAYER_MERGING_DEBUG - -namespace WebCore { - -static int gUniqueId; - -class OpacityDrawFilter : public SkDrawFilter { -public: - OpacityDrawFilter(int opacity) : m_opacity(opacity) { } - virtual void filter(SkPaint* paint, Type) - { - paint->setAlpha(m_opacity); - } -private: - int m_opacity; -}; - -/////////////////////////////////////////////////////////////////////////////// - -LayerAndroid::LayerAndroid(RenderLayer* owner) : Layer(), - m_uniqueId(++gUniqueId), - m_haveClip(false), - m_backfaceVisibility(true), - m_visible(true), - m_preserves3D(false), - m_anchorPointZ(0), - m_isPositionAbsolute(false), - m_fixedPosition(0), - m_zValue(0), - m_content(0), - m_imageCRC(0), - m_scale(1), - m_lastComputeTextureSize(0), - m_owningLayer(owner), - m_type(LayerAndroid::WebCoreLayer), - m_intrinsicallyComposited(true), - m_surface(0) -{ - m_backgroundColor = 0; - - m_preserves3D = false; - m_dirtyRegion.setEmpty(); -#ifdef DEBUG_COUNT - ClassTracker::instance()->increment("LayerAndroid"); - ClassTracker::instance()->add(this); -#endif -} - -LayerAndroid::LayerAndroid(const LayerAndroid& layer) : Layer(layer), - m_uniqueId(layer.m_uniqueId), - m_haveClip(layer.m_haveClip), - m_isPositionAbsolute(layer.m_isPositionAbsolute), - m_fixedPosition(0), - m_zValue(layer.m_zValue), - m_owningLayer(layer.m_owningLayer), - m_type(LayerAndroid::UILayer), - m_intrinsicallyComposited(layer.m_intrinsicallyComposited), - m_surface(0) -{ - m_imageCRC = layer.m_imageCRC; - if (m_imageCRC) - ImagesManager::instance()->retainImage(m_imageCRC); - - m_transform = layer.m_transform; - m_backfaceVisibility = layer.m_backfaceVisibility; - m_visible = layer.m_visible; - m_backgroundColor = layer.m_backgroundColor; - - m_offset = layer.m_offset; - - m_content = layer.m_content; - SkSafeRef(m_content); - - m_preserves3D = layer.m_preserves3D; - m_anchorPointZ = layer.m_anchorPointZ; - - if (layer.m_fixedPosition) { - m_fixedPosition = new FixedPositioning(this, *layer.m_fixedPosition); - Layer::setShouldInheritFromRootTransform(true); - } - - m_drawTransform = layer.m_drawTransform; - m_childrenTransform = layer.m_childrenTransform; - m_dirtyRegion = layer.m_dirtyRegion; - m_scale = layer.m_scale; - m_lastComputeTextureSize = 0; - - // If we have absolute elements, we may need to reorder them if they - // are followed by another layer that is not also absolutely positioned. - // (as absolutely positioned elements are out of the normal flow) - bool hasAbsoluteChildren = false; - bool hasOnlyAbsoluteFollowers = true; - for (int i = 0; i < layer.countChildren(); i++) { - if (layer.getChild(i)->isPositionAbsolute()) { - hasAbsoluteChildren = true; - continue; - } - if (hasAbsoluteChildren - && !layer.getChild(i)->isPositionAbsolute()) { - hasOnlyAbsoluteFollowers = false; - break; - } - } - - if (hasAbsoluteChildren && !hasOnlyAbsoluteFollowers) { - Vector normalLayers; - Vector absoluteLayers; - for (int i = 0; i < layer.countChildren(); i++) { - LayerAndroid* child = layer.getChild(i); - if (child->isPositionAbsolute() - || child->isPositionFixed()) - absoluteLayers.append(child); - else - normalLayers.append(child); - } - for (unsigned int i = 0; i < normalLayers.size(); i++) - addChild(normalLayers[i]->copy())->unref(); - for (unsigned int i = 0; i < absoluteLayers.size(); i++) - addChild(absoluteLayers[i]->copy())->unref(); - } else { - for (int i = 0; i < layer.countChildren(); i++) - addChild(layer.getChild(i)->copy())->unref(); - } - - KeyframesMap::const_iterator end = layer.m_animations.end(); - for (KeyframesMap::const_iterator it = layer.m_animations.begin(); it != end; ++it) { - m_animations.add(it->first, it->second); - } - -#ifdef DEBUG_COUNT - ClassTracker::instance()->increment("LayerAndroid - recopy (UI)"); - ClassTracker::instance()->add(this); -#endif -} - -LayerAndroid::~LayerAndroid() -{ - if (m_imageCRC) - ImagesManager::instance()->releaseImage(m_imageCRC); - if (m_fixedPosition) - delete m_fixedPosition; - - SkSafeUnref(m_content); - // Don't unref m_surface, owned by BaseLayerAndroid - m_animations.clear(); -#ifdef DEBUG_COUNT - ClassTracker::instance()->remove(this); - if (m_type == LayerAndroid::WebCoreLayer) - ClassTracker::instance()->decrement("LayerAndroid"); - else if (m_type == LayerAndroid::UILayer) - ClassTracker::instance()->decrement("LayerAndroid - recopy (UI)"); -#endif -} - -bool LayerAndroid::hasText() -{ - return m_content && m_content->hasText(); -} - -static int gDebugNbAnims = 0; - -bool LayerAndroid::evaluateAnimations() -{ - double time = WTF::currentTime(); - gDebugNbAnims = 0; - return evaluateAnimations(time); -} - -bool LayerAndroid::hasAnimations() const -{ - for (int i = 0; i < countChildren(); i++) { - if (getChild(i)->hasAnimations()) - return true; - } - return !!m_animations.size(); -} - -bool LayerAndroid::evaluateAnimations(double time) -{ - bool hasRunningAnimations = false; - for (int i = 0; i < countChildren(); i++) { - if (getChild(i)->evaluateAnimations(time)) - hasRunningAnimations = true; - } - - m_hasRunningAnimations = false; - int nbAnims = 0; - KeyframesMap::const_iterator end = m_animations.end(); - for (KeyframesMap::const_iterator it = m_animations.begin(); it != end; ++it) { - gDebugNbAnims++; - nbAnims++; - LayerAndroid* currentLayer = const_cast(this); - m_hasRunningAnimations |= (it->second)->evaluate(currentLayer, time); - } - - return hasRunningAnimations || m_hasRunningAnimations; -} - -void LayerAndroid::initAnimations() { - // tell auto-initializing animations to start now - for (int i = 0; i < countChildren(); i++) - getChild(i)->initAnimations(); - - KeyframesMap::const_iterator localBegin = m_animations.begin(); - KeyframesMap::const_iterator localEnd = m_animations.end(); - for (KeyframesMap::const_iterator localIt = localBegin; localIt != localEnd; ++localIt) - (localIt->second)->suggestBeginTime(WTF::currentTime()); -} - -void LayerAndroid::addDirtyArea() -{ - IntSize layerSize(getSize().width(), getSize().height()); - - FloatRect area = TilesManager::instance()->shader()->rectInInvScreenCoord(m_drawTransform, layerSize); - FloatRect clippingRect = TilesManager::instance()->shader()->rectInScreenCoord(m_clippingRect); - FloatRect clip = TilesManager::instance()->shader()->convertScreenCoordToInvScreenCoord(clippingRect); - - area.intersect(clip); - IntRect dirtyArea(area.x(), area.y(), area.width(), area.height()); - m_state->addDirtyArea(dirtyArea); -} - -void LayerAndroid::addAnimation(PassRefPtr prpAnim) -{ - RefPtr anim = prpAnim; - pair key(anim->name(), anim->type()); - removeAnimationsForProperty(anim->type()); - m_animations.add(key, anim); -} - -void LayerAndroid::removeAnimationsForProperty(AnimatedPropertyID property) -{ - KeyframesMap::const_iterator end = m_animations.end(); - Vector > toDelete; - for (KeyframesMap::const_iterator it = m_animations.begin(); it != end; ++it) { - if ((it->second)->type() == property) - toDelete.append(it->first); - } - - for (unsigned int i = 0; i < toDelete.size(); i++) - m_animations.remove(toDelete[i]); -} - -void LayerAndroid::removeAnimationsForKeyframes(const String& name) -{ - KeyframesMap::const_iterator end = m_animations.end(); - Vector > toDelete; - for (KeyframesMap::const_iterator it = m_animations.begin(); it != end; ++it) { - if ((it->second)->name() == name) - toDelete.append(it->first); - } - - for (unsigned int i = 0; i < toDelete.size(); i++) - m_animations.remove(toDelete[i]); -} - -// We only use the bounding rect of the layer as mask... -// FIXME: use a real mask? -void LayerAndroid::setMaskLayer(LayerAndroid* layer) -{ - if (layer) - m_haveClip = true; -} - -void LayerAndroid::setBackgroundColor(SkColor color) -{ - m_backgroundColor = color; -} - -FloatPoint LayerAndroid::translation() const -{ - TransformationMatrix::DecomposedType tDecomp; - m_transform.decompose(tDecomp); - FloatPoint p(tDecomp.translateX, tDecomp.translateY); - return p; -} - -SkRect LayerAndroid::bounds() const -{ - SkRect rect; - bounds(&rect); - return rect; -} - -void LayerAndroid::bounds(SkRect* rect) const -{ - const SkPoint& pos = this->getPosition(); - const SkSize& size = this->getSize(); - - // The returned rect has the translation applied - // FIXME: apply the full transform to the rect, - // and fix the text selection accordingly - FloatPoint p(pos.fX, pos.fY); - p = m_transform.mapPoint(p); - rect->fLeft = p.x(); - rect->fTop = p.y(); - rect->fRight = p.x() + size.width(); - rect->fBottom = p.y() + size.height(); -} - -static bool boundsIsUnique(const SkTDArray& region, - const SkRect& local) -{ - for (int i = 0; i < region.count(); i++) { - if (region[i].contains(local)) - return false; - } - return true; -} - -void LayerAndroid::clipArea(SkTDArray* region) const -{ - SkRect local; - local.set(0, 0, std::numeric_limits::max(), - std::numeric_limits::max()); - clipInner(region, local); -} - -void LayerAndroid::clipInner(SkTDArray* region, - const SkRect& local) const -{ - SkRect localBounds; - bounds(&localBounds); - localBounds.intersect(local); - if (localBounds.isEmpty()) - return; - if (m_content && boundsIsUnique(*region, localBounds)) - *region->append() = localBounds; - for (int i = 0; i < countChildren(); i++) - getChild(i)->clipInner(region, m_haveClip ? localBounds : local); -} - -IFrameLayerAndroid* LayerAndroid::updatePosition(SkRect viewport, - IFrameLayerAndroid* parentIframeLayer) -{ - // subclasses can implement this virtual function to modify their position - if (m_fixedPosition) - return m_fixedPosition->updatePosition(viewport, parentIframeLayer); - return parentIframeLayer; -} - -void LayerAndroid::updateLayerPositions(SkRect viewport, IFrameLayerAndroid* parentIframeLayer) -{ - ALOGV("updating fixed positions, using viewport %fx%f - %fx%f", - viewport.fLeft, viewport.fTop, - viewport.width(), viewport.height()); - - IFrameLayerAndroid* iframeLayer = updatePosition(viewport, parentIframeLayer); - - int count = this->countChildren(); - for (int i = 0; i < count; i++) - this->getChild(i)->updateLayerPositions(viewport, iframeLayer); -} - -void LayerAndroid::updatePositions() -{ - // apply the viewport to us - if (!isPositionFixed()) { - // turn our fields into a matrix. - // - // FIXME: this should happen in the caller, and we should remove these - // fields from our subclass - SkMatrix matrix; - GLUtils::toSkMatrix(matrix, m_transform); - this->setMatrix(matrix); - } - - // now apply it to our children - int count = this->countChildren(); - for (int i = 0; i < count; i++) - this->getChild(i)->updatePositions(); -} - -void LayerAndroid::updateGLPositionsAndScale(const TransformationMatrix& parentMatrix, - const FloatRect& clipping, float opacity, float scale) -{ - m_atomicSync.lock(); - IntSize layerSize(getSize().width(), getSize().height()); - FloatPoint anchorPoint(getAnchorPoint().fX, getAnchorPoint().fY); - FloatPoint position(getPosition().fX - m_offset.x(), getPosition().fY - m_offset.y()); - float originX = anchorPoint.x() * layerSize.width(); - float originY = anchorPoint.y() * layerSize.height(); - TransformationMatrix localMatrix; - if (!isPositionFixed()) - localMatrix = parentMatrix; - localMatrix.translate3d(originX + position.x(), - originY + position.y(), - anchorPointZ()); - localMatrix.multiply(m_transform); - localMatrix.translate3d(-originX, - -originY, - -anchorPointZ()); - - m_atomicSync.unlock(); - setDrawTransform(localMatrix); - if (m_drawTransform.isIdentityOrTranslation()) { - // adjust the translation coordinates of the draw transform matrix so - // that layers (defined in content coordinates) will align to display/view pixels - float desiredContentX = round(m_drawTransform.m41() * scale) / scale; - float desiredContentY = round(m_drawTransform.m42() * scale) / scale; - ALOGV("fudging translation from %f, %f to %f, %f", - m_drawTransform.m41(), m_drawTransform.m42(), - desiredContentX, desiredContentY); - m_drawTransform.setM41(desiredContentX); - m_drawTransform.setM42(desiredContentY); - } - - m_zValue = TilesManager::instance()->shader()->zValue(m_drawTransform, getSize().width(), getSize().height()); - - m_atomicSync.lock(); - m_scale = scale; - m_atomicSync.unlock(); - - opacity *= getOpacity(); - setDrawOpacity(opacity); - - if (m_haveClip) { - // The clipping rect calculation and intersetion will be done in documents coordinates. - FloatRect rect(0, 0, layerSize.width(), layerSize.height()); - FloatRect clip = m_drawTransform.mapRect(rect); - clip.intersect(clipping); - setDrawClip(clip); - } else { - setDrawClip(clipping); - } - ALOGV("%s - %d %f %f %f %f", - subclassType() == BaseLayer ? "BASE" : "nonbase", - m_haveClip, m_clippingRect.x(), m_clippingRect.y(), m_clippingRect.width(), m_clippingRect.height()); - - if (!m_backfaceVisibility - && m_drawTransform.inverse().m33() < 0) { - setVisible(false); - return; - } else { - setVisible(true); - } - - int count = this->countChildren(); - if (!count) - return; - - // Flatten to 2D if the layer doesn't preserve 3D. - if (!preserves3D()) { - localMatrix.setM13(0); - localMatrix.setM23(0); - localMatrix.setM31(0); - localMatrix.setM32(0); - localMatrix.setM33(1); - localMatrix.setM34(0); - localMatrix.setM43(0); - } - - // now apply it to our children - - TransformationMatrix childMatrix; - childMatrix = localMatrix; - childMatrix.translate3d(m_offset.x(), m_offset.y(), 0); - if (!m_childrenTransform.isIdentity()) { - childMatrix.translate(getSize().width() * 0.5f, getSize().height() * 0.5f); - childMatrix.multiply(m_childrenTransform); - childMatrix.translate(-getSize().width() * 0.5f, -getSize().height() * 0.5f); - } - for (int i = 0; i < count; i++) - this->getChild(i)->updateGLPositionsAndScale(childMatrix, drawClip(), opacity, scale); -} - -bool LayerAndroid::visible() { - // TODO: avoid climbing tree each access - LayerAndroid* current = this; - while (current->getParent()) { - if (!current->m_visible) - return false; - current = static_cast(current->getParent()); - } - return true; -} - -void LayerAndroid::setContentsImage(SkBitmapRef* img) -{ - ImageTexture* image = ImagesManager::instance()->setImage(img); - ImagesManager::instance()->releaseImage(m_imageCRC); - m_imageCRC = image ? image->imageCRC() : 0; -} - -void LayerAndroid::setContent(LayerContent* content) -{ - SkSafeRef(content); - SkSafeUnref(m_content); - m_content = content; -} - -bool LayerAndroid::needsTexture() -{ - return m_content && !m_content->isEmpty(); -} - -IntRect LayerAndroid::clippedRect() const -{ - IntRect r(0, 0, getWidth(), getHeight()); - IntRect tr = m_drawTransform.mapRect(r); - IntRect cr = TilesManager::instance()->shader()->clippedRectWithViewport(tr); - IntRect rect = m_drawTransform.inverse().mapRect(cr); - return rect; -} - -int LayerAndroid::nbLayers() -{ - int nb = 0; - int count = this->countChildren(); - for (int i = 0; i < count; i++) - nb += this->getChild(i)->nbLayers(); - return nb+1; -} - -int LayerAndroid::nbTexturedLayers() -{ - int nb = 0; - int count = this->countChildren(); - for (int i = 0; i < count; i++) - nb += this->getChild(i)->nbTexturedLayers(); - if (needsTexture()) - nb++; - return nb; -} - -void LayerAndroid::showLayer(int indent) -{ - char spaces[256]; - memset(spaces, 0, 256); - for (int i = 0; i < indent; i++) - spaces[i] = ' '; - - if (!indent) { - ALOGD("\n\n--- LAYERS TREE ---"); - IntRect documentViewport(TilesManager::instance()->shader()->documentViewport()); - ALOGD("documentViewport(%d, %d, %d, %d)", - documentViewport.x(), documentViewport.y(), - documentViewport.width(), documentViewport.height()); - } - - IntRect r(0, 0, getWidth(), getHeight()); - IntRect tr = m_drawTransform.mapRect(r); - IntRect visible = visibleArea(); - IntRect clip(m_clippingRect.x(), m_clippingRect.y(), - m_clippingRect.width(), m_clippingRect.height()); - ALOGD("%s %s (%d) [%d:0x%x] - %s %s - area (%d, %d, %d, %d) - visible (%d, %d, %d, %d) " - "clip (%d, %d, %d, %d) %s %s m_content(%x), pic w: %d h: %d", - spaces, subclassName().latin1().data(), subclassType(), uniqueId(), m_owningLayer, - needsTexture() ? "needs a texture" : "no texture", - m_imageCRC ? "has an image" : "no image", - tr.x(), tr.y(), tr.width(), tr.height(), - visible.x(), visible.y(), visible.width(), visible.height(), - clip.x(), clip.y(), clip.width(), clip.height(), - contentIsScrollable() ? "SCROLLABLE" : "", - isPositionFixed() ? "FIXED" : "", - m_content, - m_content ? m_content->width() : -1, - m_content ? m_content->height() : -1); - - int count = this->countChildren(); - for (int i = 0; i < count; i++) - this->getChild(i)->showLayer(indent + 1); -} - -void LayerAndroid::mergeInvalsInto(LayerAndroid* replacementTree) -{ - int count = this->countChildren(); - for (int i = 0; i < count; i++) - this->getChild(i)->mergeInvalsInto(replacementTree); - - LayerAndroid* replacementLayer = replacementTree->findById(uniqueId()); - if (replacementLayer) - replacementLayer->markAsDirty(m_dirtyRegion); -} - -bool LayerAndroid::updateWithTree(LayerAndroid* newTree) -{ -// Disable fast update for now -#if (0) - bool needsRepaint = false; - int count = this->countChildren(); - for (int i = 0; i < count; i++) - needsRepaint |= this->getChild(i)->updateWithTree(newTree); - - if (newTree) { - LayerAndroid* newLayer = newTree->findById(uniqueId()); - needsRepaint |= updateWithLayer(newLayer); - } - return needsRepaint; -#else - return true; -#endif -} - -// Return true to indicate to WebViewCore that the updates -// are too complicated to be fully handled and we need a full -// call to webkit (e.g. handle repaints) -bool LayerAndroid::updateWithLayer(LayerAndroid* layer) -{ - if (!layer) - return true; - - android::AutoMutex lock(m_atomicSync); - m_position = layer->m_position; - m_anchorPoint = layer->m_anchorPoint; - m_size = layer->m_size; - m_opacity = layer->m_opacity; - m_transform = layer->m_transform; - - if (m_imageCRC != layer->m_imageCRC) - m_visible = false; - - if ((m_content != layer->m_content) - || (m_imageCRC != layer->m_imageCRC)) - return true; - - return false; -} - -static inline bool compareLayerZ(const LayerAndroid* a, const LayerAndroid* b) -{ - return a->zValue() > b->zValue(); -} - -bool LayerAndroid::canJoinSurface(Surface* surface) -{ -#ifdef DISABLE_LAYER_MERGE - return false; -#else - // returns true if the layer can be merged onto the surface (group of layers) - if (!surface) - return false; - - LayerAndroid* lastLayer = surface->getFirstLayer(); - - // isolate non-tiled layers - // TODO: remove this check so that multiple tiled layers with a invisible - // one inbetween can be merged - if (!needsTexture() || !lastLayer->needsTexture()) - return false; - - // isolate clipped layers - // TODO: paint correctly with clip when merged - if (m_haveClip || lastLayer->m_haveClip) - return false; - - // isolate intrinsically composited layers - if (m_intrinsicallyComposited || lastLayer->m_intrinsicallyComposited) - return false; - - // TODO: investigate potential for combining transformed layers - if (!m_drawTransform.isIdentityOrTranslation() - || !lastLayer->m_drawTransform.isIdentityOrTranslation()) - return false; - - // currently, we don't surface zoomable with non-zoomable layers (unless the - // surface or the layer doesn't need a texture) - if (surface->needsTexture() && needsTexture() && m_content->hasText() != surface->hasText()) - return false; - - // TODO: compare other layer properties - fixed? overscroll? transformed? - return true; -#endif -} - -void LayerAndroid::assignSurfaces(LayerMergeState* mergeState) -{ - // recurse through layers in draw order, and merge layers when able - - bool needNewSurface = !mergeState->currentSurface - || mergeState->nonMergeNestedLevel > 0 - || !canJoinSurface(mergeState->currentSurface); - - if (needNewSurface) { - mergeState->currentSurface = new Surface(); - mergeState->surfaceList->append(mergeState->currentSurface); - } - -#ifdef LAYER_MERGING_DEBUG - ALOGD("%*slayer %p(%d) rl %p %s surface %p, fixed %d, anim %d, intCom %d, haveClip %d scroll %d", - 4*mergeState->depth, "", this, m_uniqueId, m_owningLayer, - needNewSurface ? "NEW" : "joins", mergeState->currentSurface, - isPositionFixed(), m_animations.size() != 0, - m_intrinsicallyComposited, - m_haveClip, - contentIsScrollable()); -#endif - - mergeState->currentSurface->addLayer(this, m_drawTransform); - m_surface = mergeState->currentSurface; - - if (m_haveClip || contentIsScrollable() || isPositionFixed()) { - // disable layer merging within the children of these layer types - mergeState->nonMergeNestedLevel++; - } - - - // pass the surface through children in drawing order, so that they may - // attach themselves (and paint on it) if possible, or ignore it and create - // a new one if not - int count = this->countChildren(); - if (count > 0) { - mergeState->depth++; - Vector sublayers; - for (int i = 0; i < count; i++) - sublayers.append(getChild(i)); - - // sort for the transparency - std::stable_sort(sublayers.begin(), sublayers.end(), compareLayerZ); - for (int i = 0; i < count; i++) - sublayers[i]->assignSurfaces(mergeState); - mergeState->depth--; - } - - if (m_haveClip || contentIsScrollable() || isPositionFixed()) { - // re-enable joining - mergeState->nonMergeNestedLevel--; - - // disallow layers painting after to join with this surface - mergeState->currentSurface = 0; - } -} - -// We call this in WebViewCore, when copying the tree of layers. -// As we construct a new tree that will be passed on the UI, -// we mark the webkit-side tree as having no more dirty region -// (otherwise we would continuously have those dirty region UI-side) -void LayerAndroid::clearDirtyRegion() -{ - int count = this->countChildren(); - for (int i = 0; i < count; i++) - this->getChild(i)->clearDirtyRegion(); - - m_dirtyRegion.setEmpty(); -} - -int LayerAndroid::setHwAccelerated(bool hwAccelerated) -{ - int flags = InvalidateNone; - int count = this->countChildren(); - for (int i = 0; i < count; i++) - flags |= this->getChild(i)->setHwAccelerated(hwAccelerated); - - return flags | onSetHwAccelerated(hwAccelerated); -} - -IntRect LayerAndroid::unclippedArea() -{ - IntRect area; - area.setX(0); - area.setY(0); - area.setWidth(getSize().width()); - area.setHeight(getSize().height()); - return area; -} - -IntRect LayerAndroid::visibleArea() -{ - IntRect area = unclippedArea(); - // First, we get the transformed area of the layer, - // in document coordinates - IntRect rect = m_drawTransform.mapRect(area); - int dx = rect.x(); - int dy = rect.y(); - - // Then we apply the clipping - IntRect clip(m_clippingRect); - rect.intersect(clip); - - // Now clip with the viewport in documents coordinate - IntRect documentViewport(TilesManager::instance()->shader()->documentViewport()); - rect.intersect(documentViewport); - - // Finally, let's return the visible area, in layers coordinate - rect.move(-dx, -dy); - return rect; -} - -bool LayerAndroid::drawCanvas(SkCanvas* canvas, bool drawChildren, PaintStyle style) -{ - if (!m_visible) - return false; - - bool askScreenUpdate = false; - - { - SkAutoCanvasRestore acr(canvas, true); - SkRect r; - r.set(m_clippingRect.x(), m_clippingRect.y(), - m_clippingRect.x() + m_clippingRect.width(), - m_clippingRect.y() + m_clippingRect.height()); - canvas->clipRect(r); - SkMatrix matrix; - GLUtils::toSkMatrix(matrix, m_drawTransform); - SkMatrix canvasMatrix = canvas->getTotalMatrix(); - matrix.postConcat(canvasMatrix); - canvas->setMatrix(matrix); - onDraw(canvas, m_drawOpacity, 0, style); - } - - if (!drawChildren) - return false; - - // When the layer is dirty, the UI thread should be notified to redraw. - askScreenUpdate |= drawChildrenCanvas(canvas, style); - m_atomicSync.lock(); - if (askScreenUpdate || m_hasRunningAnimations || m_drawTransform.hasPerspective()) - addDirtyArea(); - - m_atomicSync.unlock(); - return askScreenUpdate; -} - -bool LayerAndroid::drawGL(bool layerTilesDisabled) -{ - if (!layerTilesDisabled && m_imageCRC) { - ImageTexture* imageTexture = ImagesManager::instance()->retainImage(m_imageCRC); - if (imageTexture) - imageTexture->drawGL(this, getOpacity()); - ImagesManager::instance()->releaseImage(m_imageCRC); - } - - m_state->glExtras()->drawGL(this); - bool askScreenUpdate = false; - - m_atomicSync.lock(); - if (m_hasRunningAnimations || m_drawTransform.hasPerspective()) { - askScreenUpdate = true; - addDirtyArea(); - } - - m_atomicSync.unlock(); - return askScreenUpdate; -} - -bool LayerAndroid::drawChildrenCanvas(SkCanvas* canvas, PaintStyle style) -{ - bool askScreenUpdate = false; - int count = this->countChildren(); - if (count > 0) { - Vector sublayers; - for (int i = 0; i < count; i++) - sublayers.append(this->getChild(i)); - - // now we sort for the transparency - std::stable_sort(sublayers.begin(), sublayers.end(), compareLayerZ); - for (int i = 0; i < count; i++) { - LayerAndroid* layer = sublayers[i]; - askScreenUpdate |= layer->drawCanvas(canvas, true, style); - } - } - - return askScreenUpdate; -} - -void LayerAndroid::contentDraw(SkCanvas* canvas, PaintStyle style) -{ - if (m_content) - m_content->draw(canvas); - - if (TilesManager::instance()->getShowVisualIndicator()) { - float w = getSize().width(); - float h = getSize().height(); - SkPaint paint; - - if (style == MergedLayers) - paint.setARGB(255, 255, 255, 0); - else if (style == UnmergedLayers) - paint.setARGB(255, 255, 0, 0); - else if (style == FlattenedLayers) - paint.setARGB(255, 255, 0, 255); - - canvas->drawLine(0, 0, w, h, paint); - canvas->drawLine(0, h, w, 0, paint); - - canvas->drawLine(0, 0, 0, h-1, paint); - canvas->drawLine(0, h-1, w-1, h-1, paint); - canvas->drawLine(w-1, h-1, w-1, 0, paint); - canvas->drawLine(w-1, 0, 0, 0, paint); - } - - if (m_fixedPosition) - return m_fixedPosition->contentDraw(canvas, style); -} - -void LayerAndroid::onDraw(SkCanvas* canvas, SkScalar opacity, - android::DrawExtra* extra, PaintStyle style) -{ - if (m_haveClip) { - SkRect r; - r.set(0, 0, getSize().width(), getSize().height()); - canvas->clipRect(r); - return; - } - - if (masksToBounds() || !m_content) - return; - - // we just have this save/restore for opacity... - SkAutoCanvasRestore restore(canvas, true); - - int canvasOpacity = SkScalarRound(opacity * 255); - if (canvasOpacity < 255) - canvas->setDrawFilter(new OpacityDrawFilter(canvasOpacity)); - - if (m_imageCRC) { - ImageTexture* imageTexture = ImagesManager::instance()->retainImage(m_imageCRC); - m_dirtyRegion.setEmpty(); - if (imageTexture) { - SkRect dest; - dest.set(0, 0, getSize().width(), getSize().height()); - imageTexture->drawCanvas(canvas, dest); - } - ImagesManager::instance()->releaseImage(m_imageCRC); - } - contentDraw(canvas, style); - if (extra) - extra->draw(canvas, this); -} - -void LayerAndroid::setFixedPosition(FixedPositioning* position) { - if (m_fixedPosition && m_fixedPosition != position) - delete m_fixedPosition; - m_fixedPosition = position; -} - -void LayerAndroid::dumpLayer(FILE* file, int indentLevel) const -{ - writeHexVal(file, indentLevel + 1, "layer", (int)this); - writeIntVal(file, indentLevel + 1, "layerId", m_uniqueId); - writeIntVal(file, indentLevel + 1, "haveClip", m_haveClip); - writeIntVal(file, indentLevel + 1, "isFixed", isPositionFixed()); - - writeFloatVal(file, indentLevel + 1, "opacity", getOpacity()); - writeSize(file, indentLevel + 1, "size", getSize()); - writePoint(file, indentLevel + 1, "position", getPosition()); - writePoint(file, indentLevel + 1, "anchor", getAnchorPoint()); - - writeMatrix(file, indentLevel + 1, "drawMatrix", m_drawTransform); - writeMatrix(file, indentLevel + 1, "transformMatrix", m_transform); - writeRect(file, indentLevel + 1, "clippingRect", SkRect(m_clippingRect)); - - if (m_content) { - writeIntVal(file, indentLevel + 1, "m_content.width", m_content->width()); - writeIntVal(file, indentLevel + 1, "m_content.height", m_content->height()); - } - - if (m_fixedPosition) - return m_fixedPosition->dumpLayer(file, indentLevel); -} - -void LayerAndroid::dumpLayers(FILE* file, int indentLevel) const -{ - writeln(file, indentLevel, "{"); - - dumpLayer(file, indentLevel); - - if (countChildren()) { - writeln(file, indentLevel + 1, "children = ["); - for (int i = 0; i < countChildren(); i++) { - if (i > 0) - writeln(file, indentLevel + 1, ", "); - getChild(i)->dumpLayers(file, indentLevel + 1); - } - writeln(file, indentLevel + 1, "];"); - } - writeln(file, indentLevel, "}"); -} - -void LayerAndroid::dumpToLog() const -{ - FILE* file = fopen("/data/data/com.android.browser/layertmp", "w"); - dumpLayers(file, 0); - fclose(file); - file = fopen("/data/data/com.android.browser/layertmp", "r"); - char buffer[512]; - bzero(buffer, sizeof(buffer)); - while (fgets(buffer, sizeof(buffer), file)) - SkDebugf("%s", buffer); - fclose(file); -} - -LayerAndroid* LayerAndroid::findById(int match) -{ - if (m_uniqueId == match) - return this; - for (int i = 0; i < countChildren(); i++) { - LayerAndroid* result = getChild(i)->findById(match); - if (result) - return result; - } - return 0; -} - -} // namespace WebCore - -#endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/android/LayerAndroid.h b/Source/WebCore/platform/graphics/android/LayerAndroid.h deleted file mode 100644 index 6239418..0000000 --- a/Source/WebCore/platform/graphics/android/LayerAndroid.h +++ /dev/null @@ -1,394 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef LayerAndroid_h -#define LayerAndroid_h - -#if USE(ACCELERATED_COMPOSITING) - -#include "FloatPoint.h" -#include "FloatPoint3D.h" -#include "FloatRect.h" -#include "GraphicsLayerClient.h" -#include "ImageTexture.h" -#include "Layer.h" -#include "PlatformString.h" -#include "RefPtr.h" -#include "SkBitmap.h" -#include "SkColor.h" -#include "SkRegion.h" -#include "SkStream.h" -#include "TransformationMatrix.h" - -#include -#include - -#ifndef BZERO_DEFINED -#define BZERO_DEFINED -// http://www.opengroup.org/onlinepubs/000095399/functions/bzero.html -// For maximum portability, it is recommended to replace the function call to bzero() as follows: -#define bzero(b, len) (memset((b), '\0', (len)), (void) 0) -#endif - -class SkBitmapRef; -class SkCanvas; -class SkMatrix; -class SkPicture; - -namespace WebCore { -class LayerAndroid; -class LayerContent; -class ImageTexture; -class Surface; -} - -namespace android { -class DrawExtra; -void serializeLayer(WebCore::LayerAndroid* layer, SkWStream* stream); -WebCore::LayerAndroid* deserializeLayer(int version, SkStream* stream); -void cleanupImageRefs(WebCore::LayerAndroid* layer); -} - -using namespace android; - -namespace WebCore { - -class AndroidAnimation; -class FixedPositioning; -class GLWebViewState; -class IFrameLayerAndroid; -class LayerMergeState; -class RenderLayer; -class PaintedSurface; - -class TexturesResult { -public: - TexturesResult() - : fixed(0) - , scrollable(0) - , clipped(0) - , full(0) - {} - - int fixed; - int scrollable; - int clipped; - int full; -}; - -class TEST_EXPORT LayerAndroid : public Layer { -public: - typedef enum { UndefinedLayer, WebCoreLayer, UILayer } LayerType; - typedef enum { StandardLayer, ScrollableLayer, - IFrameLayer, IFrameContentLayer, - CanvasLayer, BaseLayer } SubclassType; - typedef enum { InvalidateNone = 0, InvalidateLayers } InvalidateFlags; - - String subclassName() - { - switch (subclassType()) { - case LayerAndroid::StandardLayer: - return "StandardLayer"; - case LayerAndroid::ScrollableLayer: - return "ScrollableLayer"; - case LayerAndroid::IFrameLayer: - return "IFrameLayer"; - case LayerAndroid::IFrameContentLayer: - return "IFrameContentLayer"; - case LayerAndroid::CanvasLayer: - return "CanvasLayer"; - case LayerAndroid::BaseLayer: - return "BaseLayer"; - } - return "Undefined"; - } - - LayerAndroid(RenderLayer* owner); - LayerAndroid(const LayerAndroid& layer); - virtual ~LayerAndroid(); - - void setBackfaceVisibility(bool value) { m_backfaceVisibility = value; } - void setTransform(const TransformationMatrix& matrix) { m_transform = matrix; } - FloatPoint translation() const; - // Returns a rect describing the bounds of the layer with the local - // transformation applied, expressed relative to the parent layer. - // FIXME: Currently we use only the translation component of the local - // transformation. - SkRect bounds() const; - IntRect clippedRect() const; - bool outsideViewport(); - - IntRect unclippedArea(); - IntRect visibleArea(); - - virtual bool needsTexture(); - - // Debug helper methods - int nbLayers(); - int nbTexturedLayers(); - void showLayer(int indent = 0); - - float getScale() { return m_scale; } - - virtual bool drawGL(bool layerTilesDisabled); - virtual bool drawCanvas(SkCanvas* canvas, bool drawChildren, PaintStyle style); - bool drawChildrenCanvas(SkCanvas* canvas, PaintStyle style); - - void updateGLPositionsAndScale(const TransformationMatrix& parentMatrix, - const FloatRect& clip, float opacity, float scale); - void setDrawOpacity(float opacity) { m_drawOpacity = opacity; } - float drawOpacity() { return m_drawOpacity; } - bool visible(); - void setVisible(bool value) { m_visible = value; } - - bool preserves3D() { return m_preserves3D; } - void setPreserves3D(bool value) { m_preserves3D = value; } - void setAnchorPointZ(float z) { m_anchorPointZ = z; } - float anchorPointZ() { return m_anchorPointZ; } - void setDrawTransform(const TransformationMatrix& transform) { m_drawTransform = transform; } - virtual const TransformationMatrix* drawTransform() const { return &m_drawTransform; } - void setChildrenTransform(const TransformationMatrix& t) { m_childrenTransform = t; } - void setDrawClip(const FloatRect& rect) { m_clippingRect = rect; } - const FloatRect& drawClip() { return m_clippingRect; } - - const IntPoint& scrollOffset() const { return m_offset; } - void setScrollOffset(IntPoint offset) { m_offset = offset; } - void setBackgroundColor(SkColor color); - void setMaskLayer(LayerAndroid*); - void setMasksToBounds(bool masksToBounds) - { - m_haveClip = masksToBounds; - } - bool masksToBounds() const { return m_haveClip; } - - LayerContent* content() { return m_content; } - void setContent(LayerContent* content); - - void addAnimation(PassRefPtr anim); - void removeAnimationsForProperty(AnimatedPropertyID property); - void removeAnimationsForKeyframes(const String& name); - bool evaluateAnimations(); - bool evaluateAnimations(double time); - void initAnimations(); - bool hasAnimations() const; - void addDirtyArea(); - - virtual void dumpLayer(FILE*, int indentLevel) const; - void dumpLayers(FILE*, int indentLevel) const; - void dumpToLog() const; - - /** Call this with the current viewport (scrolling, zoom) to update - the position of the fixed layers. - - This call is recursive, so it should be called on the root of the - hierarchy. - */ - void updateLayerPositions(SkRect viewPort, IFrameLayerAndroid* parentIframeLayer = 0); - virtual IFrameLayerAndroid* updatePosition(SkRect viewport, - IFrameLayerAndroid* parentIframeLayer); - - /** Call this to update the position attribute, so that later calls - like bounds() will report the corrected position. - - This call is recursive, so it should be called on the root of the - hierarchy. - */ - void updatePositions(); - - void clipArea(SkTDArray* region) const; - const LayerAndroid* find(int* xPtr, int* yPtr, SkPicture* root) const; - const LayerAndroid* findById(int uniqueID) const - { - return const_cast(this)->findById(uniqueID); - } - LayerAndroid* findById(int uniqueID); - LayerAndroid* getChild(int index) const - { - return static_cast(this->INHERITED::getChild(index)); - } - int uniqueId() const { return m_uniqueId; } - - /** This sets a content image -- calling it means we will use - the image directly when drawing the layer instead of using - the content painted by WebKit. - Images are handled in ImagesManager, as they can be shared - between layers. - */ - void setContentsImage(SkBitmapRef* img); - - void bounds(SkRect*) const; - - virtual LayerAndroid* copy() const { return new LayerAndroid(*this); } - - virtual void clearDirtyRegion(); - - virtual void contentDraw(SkCanvas* canvas, PaintStyle style); - - virtual bool isMedia() const { return false; } - virtual bool isVideo() const { return false; } - virtual bool isIFrame() const { return false; } - virtual bool isIFrameContent() const { return false; } - - bool isPositionFixed() const { return m_fixedPosition; } - void setAbsolutePosition(bool isAbsolute) { m_isPositionAbsolute = isAbsolute; } - bool isPositionAbsolute() { return m_isPositionAbsolute; } - void setFixedPosition(FixedPositioning* position); - FixedPositioning* fixedPosition() { return m_fixedPosition; } - - RenderLayer* owningLayer() const { return m_owningLayer; } - - float zValue() const { return m_zValue; } - - // ViewStateSerializer friends - friend void android::serializeLayer(LayerAndroid* layer, SkWStream* stream); - friend LayerAndroid* android::deserializeLayer(int version, SkStream* stream); - friend void android::cleanupImageRefs(LayerAndroid* layer); - - // Update layers using another tree. Only works for basic properties - // such as the position, the transform. Return true if anything more - // complex is needed. - bool updateWithTree(LayerAndroid*); - virtual bool updateWithLayer(LayerAndroid*); - - LayerType type() { return m_type; } - virtual SubclassType subclassType() { return LayerAndroid::StandardLayer; } - - bool hasText(); - - void copyAnimationStartTimesRecursive(LayerAndroid* oldTree); - -// rendering asset management - SkRegion* getInvalRegion() { return &m_dirtyRegion; } - void mergeInvalsInto(LayerAndroid* replacementTree); - - bool canJoinSurface(Surface* surface); - void assignSurfaces(LayerMergeState* mergeState); - Surface* surface() { return m_surface; } - - void setIntrinsicallyComposited(bool intCom) { m_intrinsicallyComposited = intCom; } - - int setHwAccelerated(bool hwAccelerated); - -protected: - virtual void onDraw(SkCanvas*, SkScalar opacity, android::DrawExtra* extra, PaintStyle style); - virtual InvalidateFlags onSetHwAccelerated(bool hwAccelerated) { return InvalidateNone; } - IntPoint m_offset; - TransformationMatrix m_drawTransform; - int m_uniqueId; - -private: -#if DUMP_NAV_CACHE - friend class CachedLayer::Debug; // debugging access only -#endif - - void copyAnimationStartTimes(LayerAndroid* oldLayer); - bool prepareContext(bool force = false); - void clipInner(SkTDArray* region, const SkRect& local) const; - - // ------------------------------------------------------------------- - // Fields to be serialized - // ------------------------------------------------------------------- - - bool m_haveClip; - bool m_backgroundColorSet; - - bool m_backfaceVisibility; - bool m_visible; - - SkColor m_backgroundColor; - - bool m_preserves3D; - float m_anchorPointZ; - float m_drawOpacity; - - bool m_isPositionAbsolute; - FixedPositioning* m_fixedPosition; - - typedef HashMap, RefPtr > KeyframesMap; - KeyframesMap m_animations; - - TransformationMatrix m_transform; - TransformationMatrix m_childrenTransform; - - // ------------------------------------------------------------------- - // Fields that are not serialized (generated, cached, or non-serializable) - // ------------------------------------------------------------------- - - float m_zValue; - - FloatRect m_clippingRect; - - // Note that m_content and m_imageCRC are mutually exclusive; - // m_content is used when WebKit is asked to paint the layer's - // content, while m_imageCRC references an image that we directly - // composite, using the layer's dimensions as a destination rect. - // We do this as if the layer only contains an image, directly compositing - // it is a much faster method than using m_content. - LayerContent* m_content; - unsigned m_imageCRC; - - // used to signal the framework we need a repaint - bool m_hasRunningAnimations; - - float m_scale; - - // We try to not always compute the texture size, as this is quite heavy - static const double s_computeTextureDelay = 0.2; // 200 ms - double m_lastComputeTextureSize; - - // This mutex serves two purposes. (1) It ensures that certain operations - // happen atomically and (2) it makes sure those operations are synchronized - // across all threads and cores. - android::Mutex m_atomicSync; - - RenderLayer* m_owningLayer; - - LayerType m_type; - SubclassType m_subclassType; - - bool m_intrinsicallyComposited; - - Surface* m_surface; - - typedef Layer INHERITED; -}; - -} - -#else - -class SkPicture; - -namespace WebCore { - -class LayerAndroid { -public: - LayerAndroid(SkPicture* picture) : - m_recordingPicture(picture), // does not assign ownership - m_uniqueId(-1) - {} - SkPicture* picture() const { return m_recordingPicture; } - int uniqueId() const { return m_uniqueId; } -private: - SkPicture* m_recordingPicture; - int m_uniqueId; -}; - -} - -#endif // USE(ACCELERATED_COMPOSITING) - -#endif // LayerAndroid_h diff --git a/Source/WebCore/platform/graphics/android/LayerContent.h b/Source/WebCore/platform/graphics/android/LayerContent.h deleted file mode 100644 index 97bc32a..0000000 --- a/Source/WebCore/platform/graphics/android/LayerContent.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2012, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef LayerContent_h -#define LayerContent_h - -#include "SkRefCnt.h" -#include - -class SkCanvas; -class SkPicture; -class SkWStream; - -namespace WebCore { - -class LayerContent : public SkRefCnt { -public: - virtual int width() = 0; - virtual int height() = 0; - virtual bool isEmpty() = 0; - virtual void checkForOptimisations() = 0; - virtual bool hasText() = 0; - virtual void draw(SkCanvas* canvas) = 0; - - virtual void serialize(SkWStream* stream) = 0; - -protected: - // used to prevent parallel draws, as both SkPicture and PictureSet don't support them - android::Mutex m_drawLock; -}; - -} // WebCore - -#endif // LayerContent_h diff --git a/Source/WebCore/platform/graphics/android/MediaLayer.cpp b/Source/WebCore/platform/graphics/android/MediaLayer.cpp deleted file mode 100644 index 6227ea4..0000000 --- a/Source/WebCore/platform/graphics/android/MediaLayer.cpp +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "MediaLayer" -#define LOG_NDEBUG 1 - -#include "config.h" -#include "MediaLayer.h" - -#include "AndroidLog.h" -#include "MediaTexture.h" -#include "TilesManager.h" - -#if USE(ACCELERATED_COMPOSITING) - -namespace WebCore { - -MediaLayer::MediaLayer(jobject webViewRef, jobject webViewCoreRef) : LayerAndroid((RenderLayer*) NULL) -{ - m_mediaTexture = new MediaTexture(webViewRef, webViewCoreRef); - m_mediaTexture->incStrong(this); - - m_isCopy = false; - m_outlineSize = 0; - ALOGV("Creating Media Layer %p", this); -} - -MediaLayer::MediaLayer(const MediaLayer& layer) : LayerAndroid(layer) -{ - m_mediaTexture = layer.m_mediaTexture; - m_mediaTexture->incStrong(this); - - m_isCopy = true; - m_outlineSize = layer.m_outlineSize; - ALOGV("Creating Media Layer Copy %p -> %p", &layer, this); -} - -MediaLayer::~MediaLayer() -{ - ALOGV("Deleting Media Layer"); - m_mediaTexture->decStrong(this); -} - -bool MediaLayer::drawGL(bool layerTilesDisabled) -{ - FloatRect clippingRect = TilesManager::instance()->shader()->rectInScreenCoord(drawClip()); - TilesManager::instance()->shader()->clip(clippingRect); - - // when the plugin gains focus webkit applies an outline to the - // widget, which causes the layer to expand to accommodate the - // outline. Therefore, we shrink the rect by the outline's dimensions - // to ensure the plugin does not draw outside of its bounds. - SkRect mediaBounds; - mediaBounds.set(0, 0, getSize().width(), getSize().height()); - mediaBounds.inset(m_outlineSize, m_outlineSize); - - // check to see if we need to create a content or video texture - m_mediaTexture->initNativeWindowIfNeeded(); - - // the layer's shader draws the content inverted so we must undo - // that change in the transformation matrix - TransformationMatrix m = m_drawTransform; - if (!m_mediaTexture->isContentInverted()) { - m.flipY(); - m.translate(0, -getSize().height()); - } - - // draw any content or video if present - m_mediaTexture->draw(m, m_drawTransform, mediaBounds); - return false; -} - -ANativeWindow* MediaLayer::acquireNativeWindowForContent() -{ - return m_mediaTexture->getNativeWindowForContent(); -} - - -ANativeWindow* MediaLayer::acquireNativeWindowForVideo() -{ - return m_mediaTexture->requestNativeWindowForVideo(); -} - -void MediaLayer::setWindowDimensionsForVideo(const ANativeWindow* window, const SkRect& dimensions) -{ - //TODO validate that the dimensions do not exceed the plugin's bounds - m_mediaTexture->setDimensions(window, dimensions); -} - -void MediaLayer::releaseNativeWindowForVideo(ANativeWindow* window) -{ - m_mediaTexture->releaseNativeWindow(window); -} - -void MediaLayer::setFramerateCallback(const ANativeWindow* window, FramerateCallbackProc callback) -{ - m_mediaTexture->setFramerateCallback(window, callback); -} - -} // namespace WebCore - -#endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/android/MediaLayer.h b/Source/WebCore/platform/graphics/android/MediaLayer.h deleted file mode 100644 index 2f39d74..0000000 --- a/Source/WebCore/platform/graphics/android/MediaLayer.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef MediaLayer_h -#define MediaLayer_h - -#if USE(ACCELERATED_COMPOSITING) - -#include "MediaTexture.h" -#include "LayerAndroid.h" -#include - -namespace android { - class SurfaceTexture; -} - -namespace WebCore { - -class MediaLayer : public LayerAndroid { - -public: - MediaLayer(jobject webViewRef, jobject webViewCoreRef); - MediaLayer(const MediaLayer& layer); - virtual ~MediaLayer(); - - virtual bool drawGL(bool layerTilesDisabled); - virtual void paintBitmapGL() const { }; - virtual bool needsTexture() { return false; } - - virtual bool isMedia() const { return true; } - virtual LayerAndroid* copy() const { return new MediaLayer(*this); } - - void invertContents(bool invert) { m_mediaTexture->invertContents(invert); } - void setOutlineSize(int size) { m_outlineSize = size; } - - // function to setup the primary SurfaceTexture in the renderer's context - ANativeWindow* acquireNativeWindowForContent(); - - // functions to manipulate secondary layers for video playback - ANativeWindow* acquireNativeWindowForVideo(); - void setWindowDimensionsForVideo(const ANativeWindow* window, const SkRect& dimensions); - void releaseNativeWindowForVideo(ANativeWindow* window); - void setFramerateCallback(const ANativeWindow* window, FramerateCallbackProc callback); - -private: - bool m_isCopy; - int m_outlineSize; - - // SurfaceTexture member variables - MediaTexture* m_mediaTexture; -}; - -} // namespace WebCore - -#endif // USE(ACCELERATED_COMPOSITING) - -#endif // MediaLayer_h diff --git a/Source/WebCore/platform/graphics/android/MediaListener.h b/Source/WebCore/platform/graphics/android/MediaListener.h deleted file mode 100644 index 2dfc08b..0000000 --- a/Source/WebCore/platform/graphics/android/MediaListener.h +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef MediaListener_h -#define MediaListener_h - -#if USE(ACCELERATED_COMPOSITING) - -#include -#include -#include -#include -#include "MediaTexture.h" -#include "WebCoreJni.h" - -namespace WebCore { - -class MediaListener : public android::SurfaceTexture::FrameAvailableListener { - -public: - MediaListener(jobject weakWebViewRef, - const sp& surfaceTexture, - const sp& nativeWindow) - : m_weakWebViewRef(weakWebViewRef) - , m_postInvalMethod(0) - , m_frameAvailable(false) - , m_surfaceTexture(surfaceTexture) - , m_nativeWindow(nativeWindow) - , m_framerateCallback(0) - { - if (!m_weakWebViewRef) - return; - - JNIEnv* env = JSC::Bindings::getJNIEnv(); - jobject localWebViewRef = env->NewLocalRef(m_weakWebViewRef); - if (localWebViewRef) { - jclass wvClass = env->GetObjectClass(localWebViewRef); - m_postInvalMethod = env->GetMethodID(wvClass, "postInvalidate", "()V"); - env->DeleteLocalRef(wvClass); - env->DeleteLocalRef(localWebViewRef); - } - checkException(env); - } - - virtual void onFrameAvailable() - { - JNIEnv* env = JSC::Bindings::getJNIEnv(); - jobject localWebViewRef = env->NewLocalRef(m_weakWebViewRef); - if (localWebViewRef) { - env->CallVoidMethod(localWebViewRef, m_postInvalMethod); - env->DeleteLocalRef(localWebViewRef); - } - checkException(env); - if (!m_frameAvailable) { - m_frameAvailable = true; - } - if (m_framerateCallback) - m_framerateCallback(m_nativeWindow.get(), m_surfaceTexture->getTimestamp()); - } - - bool isFrameAvailable() { return m_frameAvailable; } - void setFramerateCallback(FramerateCallbackProc callback) { m_framerateCallback = callback; } - -private: - jobject m_weakWebViewRef; - jmethodID m_postInvalMethod; - bool m_frameAvailable; - sp m_surfaceTexture; - sp m_nativeWindow; - FramerateCallbackProc m_framerateCallback; -}; - -} // namespace WebCore - -#endif // USE(ACCELERATED_COMPOSITING) -#endif // MediaListener_h diff --git a/Source/WebCore/platform/graphics/android/MediaPlayerPrivateAndroid.h b/Source/WebCore/platform/graphics/android/MediaPlayerPrivateAndroid.h deleted file mode 100644 index 535e7ae..0000000 --- a/Source/WebCore/platform/graphics/android/MediaPlayerPrivateAndroid.h +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright 2009,2010 The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef MediaPlayerPrivateAndroid_h -#define MediaPlayerPrivateAndroid_h - -#if ENABLE(VIDEO) - -class SkBitmap; - -#include "MediaPlayerPrivate.h" -#include "TimeRanges.h" -#include "VideoLayerAndroid.h" - -namespace WebCore { - -class MediaPlayerPrivate : public MediaPlayerPrivateInterface { -public: - virtual ~MediaPlayerPrivate(); - - static void registerMediaEngine(MediaEngineRegistrar); - - virtual void load(const String& url) = 0; - virtual void cancelLoad() { } - - virtual void play() = 0; - virtual void pause(); - - virtual IntSize naturalSize() const { return m_naturalSize; } - - virtual bool supportsFullscreen() const = 0; - virtual bool hasAudio() const = 0; - virtual bool hasVideo() const = 0; - - virtual void setVisible(bool); - - virtual float duration() const { return m_duration; } - - virtual float currentTime() const { return m_currentTime; }; - virtual void seek(float time); - virtual bool seeking() const { return false; } - - virtual void setEndTime(float time) { } - - virtual void setRate(float) { } - virtual bool paused() const { return m_paused; } - - virtual void setVolume(float) { } - - virtual MediaPlayer::NetworkState networkState() const { return m_networkState; } - virtual MediaPlayer::ReadyState readyState() const { return m_readyState; } - - virtual float maxTimeSeekable() const { return 0; } - virtual PassRefPtr buffered() const { return TimeRanges::create(); } - - virtual int dataRate() const { return 0; } - - virtual bool totalBytesKnown() const { return totalBytes() > 0; } - virtual unsigned totalBytes() const { return 0; } - virtual unsigned bytesLoaded() const { return 0; } - - virtual void setSize(const IntSize&) { } - - virtual bool canLoadPoster() const { return false; } - virtual void setPoster(const String&) { } - virtual void prepareToPlay(); - - virtual void paint(GraphicsContext*, const IntRect&) { } - - virtual void onPrepared(int duration, int width, int height) { } - void onEnded(); - void onPaused(); - virtual void onPosterFetched(SkBitmap*) { } - void onBuffering(int percent); - void onTimeupdate(int position); - void onRestoreState(); - - // These following two functions are used to turn on inline video support - bool supportsAcceleratedRendering() const { return true; } - LayerAndroid* platformLayer() const - { - return m_videoLayer; - } - void onStopFullscreen(); - -protected: - // Android-specific methods and fields. - static MediaPlayerPrivateInterface* create(MediaPlayer* player); - static void getSupportedTypes(HashSet&) { } - static MediaPlayer::SupportsType supportsType(const String& type, const String& codecs); - - MediaPlayerPrivate(MediaPlayer *); - virtual void createJavaPlayerIfNeeded() { } - - MediaPlayer* m_player; - String m_url; - struct JavaGlue; - JavaGlue* m_glue; - - float m_duration; - float m_currentTime; - - bool m_paused; - MediaPlayer::ReadyState m_readyState; - MediaPlayer::NetworkState m_networkState; - - SkBitmap* m_poster; // not owned - String m_posterUrl; - - IntSize m_naturalSize; - bool m_naturalSizeUnknown; - - bool m_isVisible; - VideoLayerAndroid* m_videoLayer; -}; - -} // namespace WebCore - -#endif - -#endif // MediaPlayerPrivateAndroid_h diff --git a/Source/WebCore/platform/graphics/android/MediaTexture.cpp b/Source/WebCore/platform/graphics/android/MediaTexture.cpp deleted file mode 100644 index dffe6c2..0000000 --- a/Source/WebCore/platform/graphics/android/MediaTexture.cpp +++ /dev/null @@ -1,316 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "MediaTexture" -#define LOG_NDEBUG 1 - -#include "config.h" -#include "MediaTexture.h" - -#include "AndroidLog.h" -#include "DrawQuadData.h" -#include "TilesManager.h" -#include "GLUtils.h" -#include "MediaListener.h" - -#if USE(ACCELERATED_COMPOSITING) - -#include -#include -#include -#include -#include "WebCoreJni.h" - -// Limits the number of ANativeWindows that can be allocated for video playback. -// The limit is currently set to 2 as that is the current max number of -// simultaneous HW decodes that our OMX implementation allows. This forces the -// media producer to use their own SW decoders for subsequent video streams. -#define MAX_WINDOW_COUNT 2 - -namespace WebCore { - -MediaTexture::MediaTexture(jobject webViewRef, jobject webViewCoreRef) : android::LightRefBase() -{ - JNIEnv* env = JSC::Bindings::getJNIEnv(); - m_weakWebViewRef = env->NewWeakGlobalRef(webViewRef); - m_weakWebViewCoreRef = env->NewWeakGlobalRef(webViewCoreRef); - - m_contentTexture = 0; - m_isContentInverted = false; - m_newWindowRequest = false; -} - -MediaTexture::~MediaTexture() -{ - if (m_contentTexture) - deleteTexture(m_contentTexture, true); - for (unsigned int i = 0; i < m_videoTextures.size(); i++) { - deleteTexture(m_videoTextures[i], true); - } - - JNIEnv* env = JSC::Bindings::getJNIEnv(); - env->DeleteWeakGlobalRef(m_weakWebViewRef); - env->DeleteWeakGlobalRef(m_weakWebViewCoreRef); -} - -bool MediaTexture::isContentInverted() -{ - android::Mutex::Autolock lock(m_mediaLock); - return m_isContentInverted; -} -void MediaTexture::invertContents(bool invertContent) -{ - android::Mutex::Autolock lock(m_mediaLock); - m_isContentInverted = invertContent; -} - -void MediaTexture::initNativeWindowIfNeeded() -{ - { - android::Mutex::Autolock lock(m_mediaLock); - - // check to see if there are any unused textures to delete - if (m_unusedTextures.size() != 0) { - for (unsigned int i = 0; i < m_unusedTextures.size(); i++) { - glDeleteTextures(1, &m_unusedTextures[i]); - } - m_unusedTextures.clear(); - } - - // create a content texture if none exists - if (!m_contentTexture) { - m_contentTexture = createTexture(); - - // send a message to the WebKit thread to notify the plugin that it can draw - if (m_weakWebViewCoreRef) { - JNIEnv* env = JSC::Bindings::getJNIEnv(); - jobject localWebViewCoreRef = env->NewLocalRef(m_weakWebViewCoreRef); - if (localWebViewCoreRef) { - jclass wvClass = env->GetObjectClass(localWebViewCoreRef); - jmethodID sendPluginDrawMsg = - env->GetMethodID(wvClass, "sendPluginDrawMsg", "()V"); - env->CallVoidMethod(localWebViewCoreRef, sendPluginDrawMsg); - env->DeleteLocalRef(wvClass); - env->DeleteLocalRef(localWebViewCoreRef); - } - checkException(env); - } - } - - // finally create a video texture if needed - if (!m_newWindowRequest) - return; - - // add the texture and add it to the list - TextureWrapper* videoTexture = createTexture(); - m_videoTextures.append(videoTexture); - - // setup the state variables to signal the other thread - m_newWindowRequest = false; - m_newWindow = videoTexture->nativeWindow; - } - - // signal the WebKit thread in case it is waiting - m_newMediaRequestCond.signal(); -} - -void MediaTexture::draw(const TransformationMatrix& contentMatrix, - const TransformationMatrix& videoMatrix, - const SkRect& mediaBounds) -{ - android::Mutex::Autolock lock(m_mediaLock); - - if (mediaBounds.isEmpty()) - return; - - // draw all the video textures first - for (unsigned int i = 0; i < m_videoTextures.size(); i++) { - - TextureWrapper* video = m_videoTextures[i]; - - if (!video->surfaceTexture.get() || video->dimensions.isEmpty() - || !video->mediaListener->isFrameAvailable()) - continue; - - video->surfaceTexture->updateTexImage(); - - float surfaceMatrix[16]; - video->surfaceTexture->getTransformMatrix(surfaceMatrix); - - SkRect dimensions = video->dimensions; - dimensions.offset(mediaBounds.fLeft, mediaBounds.fTop); - -#ifdef DEBUG - if (!mediaBounds.contains(dimensions)) { - ALOGV("The video exceeds is parent's bounds."); - } -#endif // DEBUG - - TilesManager::instance()->shader()->drawVideoLayerQuad(videoMatrix, - surfaceMatrix, dimensions, video->textureId); - } - - if (!m_contentTexture->mediaListener->isFrameAvailable()) - return; - - m_contentTexture->surfaceTexture->updateTexImage(); - - sp buf = m_contentTexture->surfaceTexture->getCurrentBuffer(); - - PixelFormat f = buf->getPixelFormat(); - // only attempt to use alpha blending if alpha channel exists - bool forceAlphaBlending = !( - PIXEL_FORMAT_RGBX_8888 == f || - PIXEL_FORMAT_RGB_888 == f || - PIXEL_FORMAT_RGB_565 == f); - - TextureQuadData data(m_contentTexture->textureId, GL_TEXTURE_EXTERNAL_OES, - GL_LINEAR, LayerQuad, &contentMatrix, &mediaBounds, - 1.0f, forceAlphaBlending); - TilesManager::instance()->shader()->drawQuad(&data); -} - -ANativeWindow* MediaTexture::requestNativeWindowForVideo() -{ - android::Mutex::Autolock lock(m_mediaLock); - - // the window was not ready before the timeout so return it this time - if (ANativeWindow* window = m_newWindow.get()) { - m_newWindow.clear(); - return window; - } - - // we only allow for so many textures, so return NULL if we exceed that limit - else if (m_videoTextures.size() >= MAX_WINDOW_COUNT) { - return 0; - } - - m_newWindowRequest = true; - - // post an inval message to the UI thread to fulfill the request - if (m_weakWebViewRef) { - JNIEnv* env = JSC::Bindings::getJNIEnv(); - jobject localWebViewRef = env->NewLocalRef(m_weakWebViewRef); - if (localWebViewRef) { - jclass wvClass = env->GetObjectClass(localWebViewRef); - jmethodID postInvalMethod = env->GetMethodID(wvClass, "postInvalidate", "()V"); - env->CallVoidMethod(localWebViewRef, postInvalMethod); - env->DeleteLocalRef(wvClass); - env->DeleteLocalRef(localWebViewRef); - } - checkException(env); - } - - //block until the request can be fulfilled or we time out - bool timedOut = false; - while (m_newWindowRequest && !timedOut) { - int ret = m_newMediaRequestCond.waitRelative(m_mediaLock, 500000000); // .5 sec - timedOut = ret == TIMED_OUT; - } - - // if the window is ready then return it otherwise return NULL - if (ANativeWindow* window = m_newWindow.get()) { - m_newWindow.clear(); - return window; - } - return 0; -} - -ANativeWindow* MediaTexture::getNativeWindowForContent() -{ - android::Mutex::Autolock lock(m_mediaLock); - if (m_contentTexture) - return m_contentTexture->nativeWindow.get(); - else - return 0; -} - -void MediaTexture::releaseNativeWindow(const ANativeWindow* window) -{ - android::Mutex::Autolock lock(m_mediaLock); - for (unsigned int i = 0; i < m_videoTextures.size(); i++) { - if (m_videoTextures[i]->nativeWindow.get() == window) { - deleteTexture(m_videoTextures[i]); - m_videoTextures.remove(i); - break; - } - } -} - -void MediaTexture::setDimensions(const ANativeWindow* window, - const SkRect& dimensions) -{ - android::Mutex::Autolock lock(m_mediaLock); - for (unsigned int i = 0; i < m_videoTextures.size(); i++) { - if (m_videoTextures[i]->nativeWindow.get() == window) { - m_videoTextures[i]->dimensions = dimensions; - break; - } - } -} - -void MediaTexture::setFramerateCallback(const ANativeWindow* window, - FramerateCallbackProc callback) -{ - android::Mutex::Autolock lock(m_mediaLock); - for (unsigned int i = 0; i < m_videoTextures.size(); i++) { - if (m_videoTextures[i]->nativeWindow.get() == window) { - m_videoTextures[i]->mediaListener->setFramerateCallback(callback); - break; - } - } -} - -MediaTexture::TextureWrapper* MediaTexture::createTexture() -{ - TextureWrapper* wrapper = new TextureWrapper(); - - // populate the wrapper - glGenTextures(1, &wrapper->textureId); - wrapper->surfaceTexture = new android::SurfaceTexture(wrapper->textureId); - wrapper->nativeWindow = new android::SurfaceTextureClient(wrapper->surfaceTexture); - wrapper->dimensions.setEmpty(); - - // setup callback - wrapper->mediaListener = new MediaListener(m_weakWebViewRef, - wrapper->surfaceTexture, - wrapper->nativeWindow); - wrapper->surfaceTexture->setFrameAvailableListener(wrapper->mediaListener); - - return wrapper; -} - -void MediaTexture::deleteTexture(TextureWrapper* texture, bool force) -{ - if (texture->surfaceTexture.get()) - texture->surfaceTexture->setFrameAvailableListener(0); - - if (force) - glDeleteTextures(1, &texture->textureId); - else - m_unusedTextures.append(texture->textureId); - - // clear the strong pointer references - texture->mediaListener.clear(); - texture->nativeWindow.clear(); - texture->surfaceTexture.clear(); - - delete texture; -} - -} // namespace WebCore - -#endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/android/MediaTexture.h b/Source/WebCore/platform/graphics/android/MediaTexture.h deleted file mode 100644 index 9ea7be2..0000000 --- a/Source/WebCore/platform/graphics/android/MediaTexture.h +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef MediaTexture_h -#define MediaTexture_h - -#if USE(ACCELERATED_COMPOSITING) - -#include "RefPtr.h" -#include "LayerAndroid.h" -#include "Vector.h" -#include -#include -#include -#include - -namespace android { - class SurfaceTexture; -} - -namespace WebCore { - -typedef void (*FramerateCallbackProc)(ANativeWindow* window, int64_t timestamp); - -class MediaListener; - -class MediaTexture : public android::LightRefBase { - -public: - MediaTexture(jobject webViewRef, jobject webViewCoreRef); - ~MediaTexture(); - - bool isContentInverted(); - void invertContents(bool invertContent); - - void initNativeWindowIfNeeded(); - void draw(const TransformationMatrix& contentMatrix, - const TransformationMatrix& videoMatrix, - const SkRect& mediaBounds); - - ANativeWindow* getNativeWindowForContent(); - ANativeWindow* requestNativeWindowForVideo(); - - void releaseNativeWindow(const ANativeWindow* window); - void setDimensions(const ANativeWindow* window, const SkRect& dimensions); - void setFramerateCallback(const ANativeWindow* window, - FramerateCallbackProc callback); - -private: - struct TextureWrapper { - GLuint textureId; - sp surfaceTexture; - sp nativeWindow; - sp mediaListener; - SkRect dimensions; // only used by the video layer - }; - - TextureWrapper* createTexture(); - void deleteTexture(TextureWrapper* item, bool force = false); - - TextureWrapper* m_contentTexture; - Vector m_videoTextures; - Vector m_unusedTextures; - - // used to track if the content is to be drawn inverted - bool m_isContentInverted; - - // used to generate new video textures - bool m_newWindowRequest; - sp m_newWindow; - - jobject m_weakWebViewRef; - jobject m_weakWebViewCoreRef; - - android::Mutex m_mediaLock; - android::Condition m_newMediaRequestCond; -}; - - -} // namespace WebCore - -#endif // USE(ACCELERATED_COMPOSITING) - -#endif // MediaTexture_h diff --git a/Source/WebCore/platform/graphics/android/PaintTileOperation.cpp b/Source/WebCore/platform/graphics/android/PaintTileOperation.cpp deleted file mode 100644 index b5e435b..0000000 --- a/Source/WebCore/platform/graphics/android/PaintTileOperation.cpp +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright 2011, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#define LOG_TAG "PaintTileOperation" -#define LOG_NDEBUG 1 - -#include "config.h" -#include "PaintTileOperation.h" - -#include "AndroidLog.h" -#include "GLWebViewState.h" -#include "ImageTexture.h" -#include "ImagesManager.h" -#include "LayerAndroid.h" -#include "TilesManager.h" - -namespace WebCore { - -PaintTileOperation::PaintTileOperation(Tile* tile, TilePainter* painter, - GLWebViewState* state, bool isLowResPrefetch) - : m_tile(tile) - , m_painter(painter) - , m_state(state) - , m_isLowResPrefetch(isLowResPrefetch) -{ - if (m_tile) - m_tile->setRepaintPending(true); - SkSafeRef(m_painter); -} - -PaintTileOperation::~PaintTileOperation() -{ - if (m_tile) { - m_tile->setRepaintPending(false); - m_tile = 0; - } - - if (m_painter && m_painter->type() == TilePainter::Image) { - ImageTexture* image = static_cast(m_painter); - ImagesManager::instance()->releaseImage(image->imageCRC()); - } else { - SkSafeUnref(m_painter); - } -} - -bool PaintTileOperation::operator==(const QueuedOperation* operation) -{ - const PaintTileOperation* op = static_cast(operation); - return op->m_tile == m_tile; -} - -void PaintTileOperation::run() -{ - if (m_tile) { - m_tile->paintBitmap(m_painter); - m_tile->setRepaintPending(false); - m_tile = 0; - } -} - -int PaintTileOperation::priority() -{ - if (!m_tile) - return -1; - - int priority = 200000; - - // prioritize low res while scrolling - if (m_isLowResPrefetch) - priority = m_state->isScrolling() ? 0 : 400000; - - // prioritize higher draw count - unsigned long long currentDraw = TilesManager::instance()->getDrawGLCount(); - unsigned long long drawDelta = currentDraw - m_tile->drawCount(); - priority += 100000 * (int)std::min(drawDelta, (unsigned long long)1000); - - // prioritize unpainted tiles, within the same drawCount - if (m_tile->frontTexture()) - priority += 50000; - - // for base tiles, prioritize based on position - if (!m_tile->isLayerTile()) { - bool goingDown = m_state->goingDown(); - priority += m_tile->x(); - - if (goingDown) - priority += 100000 - (1 + m_tile->y()) * 1000; - else - priority += m_tile->y() * 1000; - } - - return priority; -} - -} diff --git a/Source/WebCore/platform/graphics/android/PaintTileOperation.h b/Source/WebCore/platform/graphics/android/PaintTileOperation.h deleted file mode 100644 index 1d376bf..0000000 --- a/Source/WebCore/platform/graphics/android/PaintTileOperation.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright 2010, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef PaintTileSetOperation_h -#define PaintTileSetOperation_h - -#include "Tile.h" -#include "QueuedOperation.h" -#include "SkRefCnt.h" - -namespace WebCore { - -class LayerAndroid; -class TilePainter; -class ImageTexture; - -class PaintTileOperation : public QueuedOperation { -public: - PaintTileOperation(Tile* tile, TilePainter* painter, - GLWebViewState* state, bool isLowResPrefetch); - virtual ~PaintTileOperation(); - virtual bool operator==(const QueuedOperation* operation); - virtual void run(); - // returns a rendering priority for m_tile, lower values are processed faster - virtual int priority(); - TilePainter* painter() { return m_painter; } - float scale() { return m_tile->scale(); } - -private: - Tile* m_tile; - TilePainter* m_painter; - GLWebViewState* m_state; - bool m_isLowResPrefetch; -}; - -class ScaleFilter : public OperationFilter { -public: - ScaleFilter(const TilePainter* painter, float scale) - : m_painter(painter) - , m_scale(scale) {} - virtual bool check(QueuedOperation* operation) - { - PaintTileOperation* op = static_cast(operation); - return ((op->painter() == m_painter) && (op->scale() != m_scale)); - } -private: - const TilePainter* m_painter; - float m_scale; -}; - - -class TilePainterFilter : public OperationFilter { -public: - TilePainterFilter(TilePainter* painter) : m_painter(painter) {} - virtual bool check(QueuedOperation* operation) - { - PaintTileOperation* op = static_cast(operation); - return op->painter() == m_painter; - } -private: - TilePainter* m_painter; -}; - -} - -#endif // PaintTileSetOperation_h diff --git a/Source/WebCore/platform/graphics/android/PictureLayerContent.cpp b/Source/WebCore/platform/graphics/android/PictureLayerContent.cpp deleted file mode 100644 index 4398146..0000000 --- a/Source/WebCore/platform/graphics/android/PictureLayerContent.cpp +++ /dev/null @@ -1,106 +0,0 @@ -#include "config.h" -#include "PictureLayerContent.h" - -#include "InspectorCanvas.h" -#include "SkPicture.h" - -namespace WebCore { - -PictureLayerContent::PictureLayerContent(SkPicture* picture) - : m_picture(picture) - , m_checkedContent(false) - , m_hasText(true) -{ - SkSafeRef(m_picture); -} - -PictureLayerContent::PictureLayerContent(const PictureLayerContent& content) - : m_picture(content.m_picture) - , m_checkedContent(content.m_checkedContent) - , m_hasText(content.m_hasText) -{ - SkSafeRef(m_picture); -} - -PictureLayerContent::~PictureLayerContent() -{ - SkSafeUnref(m_picture); -} - -int PictureLayerContent::width() -{ - if (!m_picture) - return 0; - return m_picture->width(); -} - -int PictureLayerContent::height() -{ - if (!m_picture) - return 0; - return m_picture->height(); -} - -bool PictureLayerContent::isEmpty() -{ - if (!m_picture) - return true; - if (m_picture->width() == 0 - || m_picture->height() == 0) - return true; - return false; -} - -void PictureLayerContent::checkForOptimisations() -{ - if (!m_checkedContent) - hasText(); // for now only check the presence of text -} - -bool PictureLayerContent::hasText() -{ - if (m_checkedContent) - return m_hasText; - - // Let's check if we have text or not. If we don't, we can limit - // ourselves to scale 1! - InspectorBounder inspectorBounder; - InspectorCanvas checker(&inspectorBounder, m_picture); - SkBitmap bitmap; - bitmap.setConfig(SkBitmap::kARGB_8888_Config, - m_picture->width(), - m_picture->height()); - checker.setBitmapDevice(bitmap); - checker.drawPicture(*m_picture); - m_hasText = checker.hasText(); - if (!checker.hasContent()) { - // no content to draw, discard picture so UI / tile generation - // doesn't bother with it - SkSafeUnref(m_picture); - m_picture = 0; - } - - m_checkedContent = true; - - return m_hasText; -} - -void PictureLayerContent::draw(SkCanvas* canvas) -{ - if (!m_picture) - return; - - android::Mutex::Autolock lock(m_drawLock); - SkRect r = SkRect::MakeWH(width(), height()); - canvas->clipRect(r); - canvas->drawPicture(*m_picture); -} - -void PictureLayerContent::serialize(SkWStream* stream) -{ - if (!m_picture) - return; - m_picture->serialize(stream); -} - -} // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/PictureLayerContent.h b/Source/WebCore/platform/graphics/android/PictureLayerContent.h deleted file mode 100644 index 94bdfac..0000000 --- a/Source/WebCore/platform/graphics/android/PictureLayerContent.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2012, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef PictureLayerContent_h -#define PictureLayerContent_h - -#include "LayerContent.h" - -namespace WebCore { - -class PictureLayerContent : public LayerContent { -public: - PictureLayerContent(SkPicture* picture); - PictureLayerContent(const PictureLayerContent& content); - ~PictureLayerContent(); - - virtual int width(); - virtual int height(); - virtual bool isEmpty(); - virtual void checkForOptimisations(); - virtual bool hasText(); - virtual void draw(SkCanvas* canvas); - virtual void serialize(SkWStream* stream); - -private: - SkPicture* m_picture; - bool m_checkedContent; - bool m_hasText; -}; - -} // WebCore - -#endif // PictureLayerContent_h diff --git a/Source/WebCore/platform/graphics/android/PictureSetLayerContent.cpp b/Source/WebCore/platform/graphics/android/PictureSetLayerContent.cpp deleted file mode 100644 index 8b72b0a..0000000 --- a/Source/WebCore/platform/graphics/android/PictureSetLayerContent.cpp +++ /dev/null @@ -1,41 +0,0 @@ -#include "config.h" -#include "PictureSetLayerContent.h" - -#include "SkCanvas.h" -#include "SkPicture.h" - -namespace WebCore { - -PictureSetLayerContent::PictureSetLayerContent(const android::PictureSet& pictureSet) -{ - m_pictureSet.set(pictureSet); -} - -PictureSetLayerContent::~PictureSetLayerContent() -{ - m_pictureSet.clear(); -} - -void PictureSetLayerContent::draw(SkCanvas* canvas) -{ - if (m_pictureSet.isEmpty()) - return; - - android::Mutex::Autolock lock(m_drawLock); - SkRect r = SkRect::MakeWH(width(), height()); - canvas->clipRect(r); - m_pictureSet.draw(canvas); -} - -void PictureSetLayerContent::serialize(SkWStream* stream) -{ - if (!stream) - return; - SkPicture picture; - draw(picture.beginRecording(m_pictureSet.width(), m_pictureSet.height(), - SkPicture::kUsePathBoundsForClip_RecordingFlag)); - picture.endRecording(); - picture.serialize(stream); -} - -} // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/PictureSetLayerContent.h b/Source/WebCore/platform/graphics/android/PictureSetLayerContent.h deleted file mode 100644 index 61fc3f4..0000000 --- a/Source/WebCore/platform/graphics/android/PictureSetLayerContent.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2012, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef PictureSetLayerContent_h -#define PictureSetLayerContent_h - -#include "LayerContent.h" -#include "PictureSet.h" - -namespace WebCore { - -class PictureSetLayerContent : public LayerContent { -public: - PictureSetLayerContent(const android::PictureSet& pictureSet); - ~PictureSetLayerContent(); - - virtual int width() { return m_pictureSet.width(); } - virtual int height() { return m_pictureSet.height(); } - virtual bool isEmpty() { return m_pictureSet.isEmpty(); } - virtual void checkForOptimisations() {} - virtual bool hasText() { return true; } - virtual void draw(SkCanvas* canvas); - virtual void serialize(SkWStream* stream); - -private: - android::PictureSet m_pictureSet; -}; - -} // WebCore - -#endif // PictureLayerContent_h diff --git a/Source/WebCore/platform/graphics/android/QueuedOperation.h b/Source/WebCore/platform/graphics/android/QueuedOperation.h deleted file mode 100644 index f98efcd..0000000 --- a/Source/WebCore/platform/graphics/android/QueuedOperation.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2010, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef QueuedOperation_h -#define QueuedOperation_h - -namespace WebCore { - -class QueuedOperation { -public: - virtual ~QueuedOperation() {} - virtual void run() = 0; - virtual bool operator==(const QueuedOperation* operation) = 0; - virtual int priority() = 0; -}; - -class OperationFilter { -public: - virtual ~OperationFilter() {} - virtual bool check(QueuedOperation* operation) = 0; -}; - -} - -#endif // QueuedOperation_h diff --git a/Source/WebCore/platform/graphics/android/RasterRenderer.cpp b/Source/WebCore/platform/graphics/android/RasterRenderer.cpp deleted file mode 100644 index b880eef..0000000 --- a/Source/WebCore/platform/graphics/android/RasterRenderer.cpp +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright 2011, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#define LOG_TAG "RasterRenderer" -#define LOG_NDEBUG 1 - -#include "config.h" -#include "RasterRenderer.h" - -#if USE(ACCELERATED_COMPOSITING) - -#include "AndroidLog.h" -#include "GLUtils.h" -#include "SkBitmap.h" -#include "SkBitmapRef.h" -#include "SkCanvas.h" -#include "SkDevice.h" -#include "Tile.h" -#include "TilesManager.h" - -namespace WebCore { - -SkBitmap* RasterRenderer::g_bitmap = 0; - -RasterRenderer::RasterRenderer() : BaseRenderer(BaseRenderer::Raster) -{ -#ifdef DEBUG_COUNT - ClassTracker::instance()->increment("RasterRenderer"); -#endif - if (!g_bitmap) { - g_bitmap = new SkBitmap(); - g_bitmap->setConfig(SkBitmap::kARGB_8888_Config, - TilesManager::instance()->tileWidth(), - TilesManager::instance()->tileHeight()); - g_bitmap->allocPixels(); - } -} - -RasterRenderer::~RasterRenderer() -{ -#ifdef DEBUG_COUNT - ClassTracker::instance()->decrement("RasterRenderer"); -#endif -} - -void RasterRenderer::setupCanvas(const TileRenderInfo& renderInfo, SkCanvas* canvas) -{ - if (renderInfo.baseTile->isLayerTile()) { - g_bitmap->setIsOpaque(false); - g_bitmap->eraseARGB(0, 0, 0, 0); - } else { - Color defaultBackground = Color::white; - Color* background = renderInfo.tilePainter->background(); - if (!background) { - ALOGV("No background color for base layer!"); - background = &defaultBackground; - } - ALOGV("setupCanvas use background on Base Layer %x", background->rgb()); - g_bitmap->setIsOpaque(!background->hasAlpha()); - g_bitmap->eraseARGB(background->alpha(), background->red(), - background->green(), background->blue()); - } - - SkDevice* device = new SkDevice(*g_bitmap); - - canvas->setDevice(device); - - device->unref(); - - // If we have a partially painted bitmap - if (renderInfo.invalRect) { - SkRect clipRect = SkRect::MakeWH(renderInfo.invalRect->width(), - renderInfo.invalRect->height()); - // ensure the canvas origin is translated to the coordinates of our inval rect - canvas->clipRect(clipRect); - canvas->translate(-renderInfo.invalRect->fLeft, -renderInfo.invalRect->fTop); - } -} - -void RasterRenderer::renderingComplete(const TileRenderInfo& renderInfo, SkCanvas* canvas) -{ - const SkBitmap& bitmap = canvas->getDevice()->accessBitmap(false); - GLUtils::paintTextureWithBitmap(&renderInfo, bitmap); -} - -void RasterRenderer::checkForPureColor(TileRenderInfo& renderInfo, SkCanvas* canvas) -{ - renderInfo.isPureColor = GLUtils::isPureColorBitmap(*g_bitmap, renderInfo.pureColor); -} - -} // namespace WebCore - -#endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/android/RasterRenderer.h b/Source/WebCore/platform/graphics/android/RasterRenderer.h deleted file mode 100644 index 39e00f2..0000000 --- a/Source/WebCore/platform/graphics/android/RasterRenderer.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2011, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef RasterRenderer_h -#define RasterRenderer_h - -#if USE(ACCELERATED_COMPOSITING) - -#include "BaseRenderer.h" -#include "SkBitmap.h" -#include "SkRect.h" - -class SkCanvas; -class SkDevice; - -namespace WebCore { - -/** - * - */ -class RasterRenderer : public BaseRenderer { -public: - RasterRenderer(); - ~RasterRenderer(); - -protected: - - virtual void setupCanvas(const TileRenderInfo& renderInfo, SkCanvas* canvas); - virtual void renderingComplete(const TileRenderInfo& renderInfo, SkCanvas* canvas); - virtual void checkForPureColor(TileRenderInfo& renderInfo, SkCanvas* canvas); - -private: - static SkBitmap* g_bitmap; - -}; - -} // namespace WebCore - -#endif // USE(ACCELERATED_COMPOSITING) -#endif // RasterRenderer_h diff --git a/Source/WebCore/platform/graphics/android/ScrollableLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/ScrollableLayerAndroid.cpp deleted file mode 100644 index f28c31d..0000000 --- a/Source/WebCore/platform/graphics/android/ScrollableLayerAndroid.cpp +++ /dev/null @@ -1,80 +0,0 @@ -#define LOG_TAG "ScrollableLayerAndroid" -#define LOG_NDEBUG 1 - -#include "config.h" -#include "ScrollableLayerAndroid.h" - -#include "GLWebViewState.h" - -#if USE(ACCELERATED_COMPOSITING) - -#include "AndroidLog.h" - -namespace WebCore { - -bool ScrollableLayerAndroid::scrollTo(int x, int y) -{ - IntRect scrollBounds; - getScrollBounds(&scrollBounds); - if (!scrollBounds.width() && !scrollBounds.height()) - return false; - SkScalar newX = SkScalarPin(x, scrollBounds.x(), scrollBounds.width()); - SkScalar newY = SkScalarPin(y, scrollBounds.y(), scrollBounds.height()); - // Check for no change. - if (newX == m_offset.x() && newY == m_offset.y()) - return false; - setScrollOffset(IntPoint(newX, newY)); - return true; -} - -void ScrollableLayerAndroid::getScrollBounds(IntRect* out) const -{ - const SkPoint& pos = getPosition(); - out->setX(m_scrollLimits.fLeft - pos.fX); - out->setY(m_scrollLimits.fTop - pos.fY); - out->setWidth(getSize().width() - m_scrollLimits.width()); - out->setHeight(getSize().height() - m_scrollLimits.height()); -} - -void ScrollableLayerAndroid::getScrollRect(SkIRect* out) const -{ - const SkPoint& pos = getPosition(); - out->fLeft = m_scrollLimits.fLeft - pos.fX + m_offset.x(); - out->fTop = m_scrollLimits.fTop - pos.fY + m_offset.y(); - - out->fRight = getSize().width() - m_scrollLimits.width(); - out->fBottom = getSize().height() - m_scrollLimits.height(); -} - -bool ScrollableLayerAndroid::scrollRectIntoView(const SkIRect& rect) -{ - // Apply the local transform to the rect to get it relative to the parent - // layer. - SkMatrix localTransform; - getLocalTransform(&localTransform); - SkRect transformedRect; - transformedRect.set(rect); - localTransform.mapRect(&transformedRect); - - // Test left before right to prioritize left alignment if transformedRect is wider than - // visible area. - int x = m_scrollLimits.fLeft; - if (transformedRect.fLeft < m_scrollLimits.fLeft) - x = transformedRect.fLeft; - else if (transformedRect.fRight > m_scrollLimits.fRight) - x = transformedRect.fRight - std::max(m_scrollLimits.width(), transformedRect.width()); - - // Test top before bottom to prioritize top alignment if transformedRect is taller than - // visible area. - int y = m_scrollLimits.fTop; - if (transformedRect.fTop < m_scrollLimits.fTop) - y = transformedRect.fTop; - else if (transformedRect.fBottom > m_scrollLimits.fBottom) - y = transformedRect.fBottom - std::max(m_scrollLimits.height(), transformedRect.height()); - - return scrollTo(x - getPosition().fX, y - getPosition().fY); -} - -} // namespace WebCore - -#endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/android/ScrollableLayerAndroid.h b/Source/WebCore/platform/graphics/android/ScrollableLayerAndroid.h deleted file mode 100644 index 1f289e6..0000000 --- a/Source/WebCore/platform/graphics/android/ScrollableLayerAndroid.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ScrollableLayerAndroid_h -#define ScrollableLayerAndroid_h - -#if USE(ACCELERATED_COMPOSITING) - -#include "LayerAndroid.h" - -namespace WebCore { - -class ScrollableLayerAndroid : public LayerAndroid { - -public: - ScrollableLayerAndroid(RenderLayer* owner) - : LayerAndroid(owner) {} - ScrollableLayerAndroid(const ScrollableLayerAndroid& layer) - : LayerAndroid(layer) - , m_scrollLimits(layer.m_scrollLimits) {} - ScrollableLayerAndroid(const LayerAndroid& layer) - : LayerAndroid(layer) - { - m_scrollLimits.setEmpty(); - } - virtual ~ScrollableLayerAndroid() {}; - - virtual bool contentIsScrollable() const { return true; } - - virtual LayerAndroid* copy() const { return new ScrollableLayerAndroid(*this); } - virtual SubclassType subclassType() { return LayerAndroid::ScrollableLayer; } - - virtual bool updateWithLayer(LayerAndroid*) { return true; } - - // Scrolls to the given position in the layer. - // Returns whether or not any scrolling was required. - virtual bool scrollTo(int x, int y); - - // Fills the rect with the current scroll offset and the maximum scroll offset. - // fLeft = scrollX - // fTop = scrollY - // fRight = maxScrollX - // fBottom = maxScrollY - virtual void getScrollRect(SkIRect*) const; - - void setScrollLimits(float x, float y, float width, float height) - { - m_scrollLimits.set(x, y, x + width, y + height); - } - - // Given a rect in the layer, scrolls to bring the rect into view. Uses a - // lazy approach, whereby we scroll as little as possible to bring the - // entire rect into view. If the size of the rect exceeds that of the - // visible area of the layer, we favor the top and left of the rect. - // Returns whether or not any scrolling was required. - bool scrollRectIntoView(const SkIRect&); - - friend void android::serializeLayer(LayerAndroid* layer, SkWStream* stream); - friend LayerAndroid* android::deserializeLayer(int version, SkStream* stream); - -protected: - - void getScrollBounds(IntRect*) const; - - // The position of the visible area of the layer, relative to the parent - // layer. This is fixed during scrolling. We acheive scrolling by modifying - // the position of the layer. - SkRect m_scrollLimits; -}; - -} - -#endif // USE(ACCELERATED_COMPOSITING) - -#endif // LayerAndroid_h diff --git a/Source/WebCore/platform/graphics/android/ShaderProgram.cpp b/Source/WebCore/platform/graphics/android/ShaderProgram.cpp deleted file mode 100644 index a0d9e56..0000000 --- a/Source/WebCore/platform/graphics/android/ShaderProgram.cpp +++ /dev/null @@ -1,730 +0,0 @@ -/* - * Copyright 2010, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#define LOG_TAG "ShaderProgram" -#define LOG_NDEBUG 1 - -#include "config.h" -#include "ShaderProgram.h" - -#if USE(ACCELERATED_COMPOSITING) - -#include "AndroidLog.h" -#include "DrawQuadData.h" -#include "FloatPoint3D.h" -#include "GLUtils.h" -#include "TilesManager.h" - -#include -#include - -namespace WebCore { - -static const char gVertexShader[] = - "attribute vec4 vPosition;\n" - "uniform mat4 projectionMatrix;\n" - "varying vec2 v_texCoord;\n" - "void main() {\n" - " gl_Position = projectionMatrix * vPosition;\n" - " v_texCoord = vec2(vPosition);\n" - "}\n"; - -static const char gFragmentShader[] = - "precision mediump float;\n" - "varying vec2 v_texCoord; \n" - "uniform float alpha; \n" - "uniform sampler2D s_texture; \n" - "void main() {\n" - " gl_FragColor = texture2D(s_texture, v_texCoord); \n" - " gl_FragColor *= alpha; " - "}\n"; - -// We could pass the pureColor into either Vertex or Frag Shader. -// The reason we passed the color into the Vertex Shader is that some driver -// might create redundant copy when uniforms in fragment shader changed. -static const char gPureColorVertexShader[] = - "attribute vec4 vPosition;\n" - "uniform mat4 projectionMatrix;\n" - "uniform vec4 inputColor;\n" - "varying vec4 v_color;\n" - "void main() {\n" - " gl_Position = projectionMatrix * vPosition;\n" - " v_color = inputColor;\n" - "}\n"; - -static const char gPureColorFragmentShader[] = - "precision mediump float;\n" - "varying vec4 v_color;\n" - "void main() {\n" - " gl_FragColor = v_color;\n" - "}\n"; - -static const char gFragmentShaderInverted[] = - "precision mediump float;\n" - "varying vec2 v_texCoord; \n" - "uniform float alpha; \n" - "uniform float contrast; \n" - "uniform sampler2D s_texture; \n" - "void main() {\n" - " vec4 pixel = texture2D(s_texture, v_texCoord); \n" - " float a = pixel.a; \n" - " float color = a - (0.2989 * pixel.r + 0.5866 * pixel.g + 0.1145 * pixel.b);\n" - " color = ((color - a/2.0) * contrast) + a/2.0; \n" - " pixel.rgb = vec3(color, color, color); \n " - " gl_FragColor = pixel; \n" - " gl_FragColor *= alpha; \n" - "}\n"; - -static const char gVideoVertexShader[] = - "attribute vec4 vPosition;\n" - "uniform mat4 textureMatrix;\n" - "uniform mat4 projectionMatrix;\n" - "varying vec2 v_texCoord;\n" - "void main() {\n" - " gl_Position = projectionMatrix * vPosition;\n" - " v_texCoord = vec2(textureMatrix * vec4(vPosition.x, 1.0 - vPosition.y, 0.0, 1.0));\n" - "}\n"; - -static const char gVideoFragmentShader[] = - "#extension GL_OES_EGL_image_external : require\n" - "precision mediump float;\n" - "uniform samplerExternalOES s_yuvTexture;\n" - "varying vec2 v_texCoord;\n" - "void main() {\n" - " gl_FragColor = texture2D(s_yuvTexture, v_texCoord);\n" - "}\n"; - -static const char gSurfaceTextureOESFragmentShader[] = - "#extension GL_OES_EGL_image_external : require\n" - "precision mediump float;\n" - "varying vec2 v_texCoord; \n" - "uniform float alpha; \n" - "uniform samplerExternalOES s_texture; \n" - "void main() {\n" - " gl_FragColor = texture2D(s_texture, v_texCoord); \n" - " gl_FragColor *= alpha; " - "}\n"; - -static const char gSurfaceTextureOESFragmentShaderInverted[] = - "#extension GL_OES_EGL_image_external : require\n" - "precision mediump float;\n" - "varying vec2 v_texCoord; \n" - "uniform float alpha; \n" - "uniform float contrast; \n" - "uniform samplerExternalOES s_texture; \n" - "void main() {\n" - " vec4 pixel = texture2D(s_texture, v_texCoord); \n" - " float a = pixel.a; \n" - " float color = a - (0.2989 * pixel.r + 0.5866 * pixel.g + 0.1145 * pixel.b);\n" - " color = ((color - a/2.0) * contrast) + a/2.0; \n" - " pixel.rgb = vec3(color, color, color); \n " - " gl_FragColor = pixel; \n" - " gl_FragColor *= alpha; \n" - "}\n"; - -GLuint ShaderProgram::loadShader(GLenum shaderType, const char* pSource) -{ - GLuint shader = glCreateShader(shaderType); - if (shader) { - glShaderSource(shader, 1, &pSource, 0); - glCompileShader(shader); - GLint compiled = 0; - glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled); - if (!compiled) { - GLint infoLen = 0; - glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen); - if (infoLen) { - char* buf = (char*) malloc(infoLen); - if (buf) { - glGetShaderInfoLog(shader, infoLen, 0, buf); - ALOGE("could not compile shader %d:\n%s\n", shaderType, buf); - free(buf); - } - glDeleteShader(shader); - shader = 0; - } - } - } - return shader; -} - -GLint ShaderProgram::createProgram(const char* pVertexSource, const char* pFragmentSource) -{ - GLuint vertexShader = loadShader(GL_VERTEX_SHADER, pVertexSource); - if (!vertexShader) { - ALOGE("couldn't load the vertex shader!"); - return -1; - } - - GLuint pixelShader = loadShader(GL_FRAGMENT_SHADER, pFragmentSource); - if (!pixelShader) { - ALOGE("couldn't load the pixel shader!"); - return -1; - } - - GLuint program = glCreateProgram(); - if (program) { - glAttachShader(program, vertexShader); - GLUtils::checkGlError("glAttachShader vertex"); - glAttachShader(program, pixelShader); - GLUtils::checkGlError("glAttachShader pixel"); - glLinkProgram(program); - GLint linkStatus = GL_FALSE; - glGetProgramiv(program, GL_LINK_STATUS, &linkStatus); - if (linkStatus != GL_TRUE) { - GLint bufLength = 0; - glGetProgramiv(program, GL_INFO_LOG_LENGTH, &bufLength); - if (bufLength) { - char* buf = (char*) malloc(bufLength); - if (buf) { - glGetProgramInfoLog(program, bufLength, 0, buf); - ALOGE("could not link program:\n%s\n", buf); - free(buf); - } - } - glDeleteProgram(program); - program = -1; - } - } - - ShaderResource newResource(program, vertexShader, pixelShader); - m_resources.append(newResource); - return program; -} - -ShaderProgram::ShaderProgram() - : m_blendingEnabled(false) - , m_contrast(1) - , m_alphaLayer(false) - , m_currentScale(1.0f) - , m_needsInit(true) -{ -} - -void ShaderProgram::cleanupGLResources() -{ - for (unsigned int i = 0; i < m_resources.size(); i++) { - glDetachShader(m_resources[i].program, m_resources[i].vertexShader); - glDetachShader(m_resources[i].program, m_resources[i].fragmentShader); - glDeleteShader(m_resources[i].vertexShader); - glDeleteShader(m_resources[i].fragmentShader); - glDeleteProgram(m_resources[i].program); - } - glDeleteBuffers(1, m_textureBuffer); - - m_resources.clear(); - m_needsInit = true; - GLUtils::checkGlError("cleanupGLResources"); - - return; -} - -void ShaderProgram::initGLResources() -{ - // To detect whether or not resources for ShaderProgram allocated - // successfully, we clean up pre-existing errors here and will check for - // new errors at the end of this function. - GLUtils::checkGlError("before initGLResources"); - - GLint tex2DProgram = createProgram(gVertexShader, gFragmentShader); - GLint pureColorProgram = createProgram(gPureColorVertexShader, gPureColorFragmentShader); - GLint tex2DInvProgram = createProgram(gVertexShader, gFragmentShaderInverted); - GLint videoProgram = createProgram(gVideoVertexShader, gVideoFragmentShader); - GLint texOESProgram = - createProgram(gVertexShader, gSurfaceTextureOESFragmentShader); - GLint texOESInvProgram = - createProgram(gVertexShader, gSurfaceTextureOESFragmentShaderInverted); - - if (tex2DProgram == -1 - || pureColorProgram == -1 - || tex2DInvProgram == -1 - || videoProgram == -1 - || texOESProgram == -1 - || texOESInvProgram == -1) { - m_needsInit = true; - return; - } - - GLint pureColorPosition = glGetAttribLocation(pureColorProgram, "vPosition"); - GLint pureColorProjMtx = glGetUniformLocation(pureColorProgram, "projectionMatrix"); - GLint pureColorValue = glGetUniformLocation(pureColorProgram, "inputColor"); - m_handleArray[PureColor].init(-1, -1, pureColorPosition, pureColorProgram, - pureColorProjMtx, pureColorValue, -1, -1); - - GLint tex2DAlpha = glGetUniformLocation(tex2DProgram, "alpha"); - GLint tex2DPosition = glGetAttribLocation(tex2DProgram, "vPosition"); - GLint tex2DProjMtx = glGetUniformLocation(tex2DProgram, "projectionMatrix"); - GLint tex2DTexSampler = glGetUniformLocation(tex2DProgram, "s_texture"); - m_handleArray[Tex2D].init(tex2DAlpha, -1, tex2DPosition, tex2DProgram, - tex2DProjMtx, -1, tex2DTexSampler, -1); - - GLint tex2DInvAlpha = glGetUniformLocation(tex2DInvProgram, "alpha"); - GLint tex2DInvContrast = glGetUniformLocation(tex2DInvProgram, "contrast"); - GLint tex2DInvPosition = glGetAttribLocation(tex2DInvProgram, "vPosition"); - GLint tex2DInvProjMtx = glGetUniformLocation(tex2DInvProgram, "projectionMatrix"); - GLint tex2DInvTexSampler = glGetUniformLocation(tex2DInvProgram, "s_texture"); - m_handleArray[Tex2DInv].init(tex2DInvAlpha, tex2DInvContrast, - tex2DInvPosition, tex2DInvProgram, - tex2DInvProjMtx, -1, - tex2DInvTexSampler, -1); - - GLint texOESAlpha = glGetUniformLocation(texOESProgram, "alpha"); - GLint texOESPosition = glGetAttribLocation(texOESProgram, "vPosition"); - GLint texOESProjMtx = glGetUniformLocation(texOESProgram, "projectionMatrix"); - GLint texOESTexSampler = glGetUniformLocation(texOESProgram, "s_texture"); - m_handleArray[TexOES].init(texOESAlpha, -1, texOESPosition, texOESProgram, - texOESProjMtx, -1, texOESTexSampler, -1); - - GLint texOESInvAlpha = glGetUniformLocation(texOESInvProgram, "alpha"); - GLint texOESInvContrast = glGetUniformLocation(texOESInvProgram, "contrast"); - GLint texOESInvPosition = glGetAttribLocation(texOESInvProgram, "vPosition"); - GLint texOESInvProjMtx = glGetUniformLocation(texOESInvProgram, "projectionMatrix"); - GLint texOESInvTexSampler = glGetUniformLocation(texOESInvProgram, "s_texture"); - m_handleArray[TexOESInv].init(texOESInvAlpha, texOESInvContrast, - texOESInvPosition, texOESInvProgram, - texOESInvProjMtx, -1, - texOESInvTexSampler, -1); - - GLint videoPosition = glGetAttribLocation(videoProgram, "vPosition"); - GLint videoProjMtx = glGetUniformLocation(videoProgram, "projectionMatrix"); - GLint videoTexSampler = glGetUniformLocation(videoProgram, "s_yuvTexture"); - GLint videoTexMtx = glGetUniformLocation(videoProgram, "textureMatrix"); - m_handleArray[Video].init(-1, -1, videoPosition, videoProgram, - videoProjMtx, -1, videoTexSampler, - videoTexMtx); - - const GLfloat coord[] = { - 0.0f, 0.0f, // C - 1.0f, 0.0f, // D - 0.0f, 1.0f, // A - 1.0f, 1.0f // B - }; - - glGenBuffers(1, m_textureBuffer); - glBindBuffer(GL_ARRAY_BUFFER, m_textureBuffer[0]); - glBufferData(GL_ARRAY_BUFFER, 2 * 4 * sizeof(GLfloat), coord, GL_STATIC_DRAW); - - TransformationMatrix matrix; - // Map x,y from (0,1) to (-1, 1) - matrix.scale3d(2, 2, 1); - matrix.translate3d(-0.5, -0.5, 0); - GLUtils::toGLMatrix(m_transferProjMtx, matrix); - - m_needsInit = GLUtils::checkGlError("initGLResources"); - return; -} - -void ShaderProgram::resetBlending() -{ - glDisable(GL_BLEND); - glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - glBlendEquation(GL_FUNC_ADD); - m_blendingEnabled = false; -} - -void ShaderProgram::setBlendingState(bool enableBlending) -{ - if (enableBlending == m_blendingEnabled) - return; - - if (enableBlending) - glEnable(GL_BLEND); - else - glDisable(GL_BLEND); - - m_blendingEnabled = enableBlending; -} - -///////////////////////////////////////////////////////////////////////////////////////// -// Drawing -///////////////////////////////////////////////////////////////////////////////////////// - -void ShaderProgram::setupDrawing(const IntRect& viewRect, const SkRect& visibleRect, - const IntRect& webViewRect, int titleBarHeight, - const IntRect& screenClip, float scale) -{ - m_webViewRect = webViewRect; - m_titleBarHeight = titleBarHeight; - - //// viewport //// - TransformationMatrix ortho; - GLUtils::setOrthographicMatrix(ortho, visibleRect.fLeft, visibleRect.fTop, - visibleRect.fRight, visibleRect.fBottom, -1000, 1000); - // In most case , visibleRect / viewRect * scale should 1.0, but for the - // translation case, the scale factor can be 1 but visibleRect is smaller - // than viewRect, we need to tune in this factor to make sure we scale them - // right. Conceptually, that means, no matter how animation affects the - // visibleRect, the scaling should respect the viewRect if zoomScale is 1.0. - // Note that at TiledPage, we already scale the tile size inversely to make - // zooming animation right. - float orthoScaleX = scale * visibleRect.width() / viewRect.width(); - float orthoScaleY = scale * visibleRect.height() / viewRect.height(); - - TransformationMatrix orthoScale; - orthoScale.scale3d(orthoScaleX, orthoScaleY, 1.0); - - m_projectionMatrix = ortho * orthoScale; - m_viewport = visibleRect; - m_currentScale = scale; - - - //// viewRect //// - m_viewRect = viewRect; - - // We do clipping using glScissor, which needs to take - // coordinates in screen space. The following matrix transform - // content coordinates in screen coordinates. - TransformationMatrix viewTranslate; - viewTranslate.translate(1.0, 1.0); - - TransformationMatrix viewScale; - viewScale.scale3d(m_viewRect.width() * 0.5f, m_viewRect.height() * 0.5f, 1); - - m_documentToScreenMatrix = viewScale * viewTranslate * m_projectionMatrix; - - viewTranslate.scale3d(1, -1, 1); - m_documentToInvScreenMatrix = viewScale * viewTranslate * m_projectionMatrix; - - IntRect rect(0, 0, m_webViewRect.width(), m_webViewRect.height()); - m_documentViewport = m_documentToScreenMatrix.inverse().mapRect(rect); - - - //// clipping //// - IntRect mclip = screenClip; - - // the clip from frameworks is in full screen coordinates - mclip.setY(screenClip.y() - m_webViewRect.y() - m_titleBarHeight); - FloatRect tclip = convertInvScreenCoordToScreenCoord(mclip); - m_screenClip.setLocation(IntPoint(tclip.x(), tclip.y())); - // use ceilf to handle view -> doc -> view coord rounding errors - m_screenClip.setSize(IntSize(ceilf(tclip.width()), ceilf(tclip.height()))); - - resetBlending(); -} - -// Calculate the right color value sent into the shader considering the (0,1) -// clamp and alpha blending. -Color ShaderProgram::shaderColor(Color pureColor, float opacity) -{ - float r = pureColor.red() / 255.0; - float g = pureColor.green() / 255.0; - float b = pureColor.blue() / 255.0; - float a = pureColor.alpha() / 255.0; - - if (TilesManager::instance()->invertedScreen()) { - float intensity = a - (0.2989 * r + 0.5866 * g + 0.1145 * b); - intensity = ((intensity - a / 2.0) * m_contrast) + a / 2.0; - intensity *= opacity; - return Color(intensity, intensity, intensity, a * opacity); - } - return Color(r * opacity, g * opacity, b * opacity, a * opacity); -} - -// For shaders using texture, it is easy to get the type from the textureTarget. -ShaderType ShaderProgram::getTextureShaderType(GLenum textureTarget) -{ - ShaderType type = UndefinedShader; - if (textureTarget == GL_TEXTURE_2D) { - if (!TilesManager::instance()->invertedScreen()) - type = Tex2D; - else { - // With the new GPU texture upload path, we do not use an FBO - // to blit the texture we receive from the TexturesGenerator thread. - // To implement inverted rendering, we thus have to do the rendering - // live, by using a different shader. - type = Tex2DInv; - } - } else if (textureTarget == GL_TEXTURE_EXTERNAL_OES) { - if (!TilesManager::instance()->invertedScreen()) - type = TexOES; - else - type = TexOESInv; - } - return type; -} - -// This function transform a clip rect extracted from the current layer -// into a clip rect in screen coordinates -- used by the clipping rects -FloatRect ShaderProgram::rectInScreenCoord(const TransformationMatrix& drawMatrix, const IntSize& size) -{ - FloatRect srect(0, 0, size.width(), size.height()); - TransformationMatrix renderMatrix = m_documentToScreenMatrix * drawMatrix; - return renderMatrix.mapRect(srect); -} - -// used by the partial screen invals -FloatRect ShaderProgram::rectInInvScreenCoord(const TransformationMatrix& drawMatrix, const IntSize& size) -{ - FloatRect srect(0, 0, size.width(), size.height()); - TransformationMatrix renderMatrix = m_documentToInvScreenMatrix * drawMatrix; - return renderMatrix.mapRect(srect); -} - -FloatRect ShaderProgram::rectInInvScreenCoord(const FloatRect& rect) -{ - return m_documentToInvScreenMatrix.mapRect(rect); -} - -FloatRect ShaderProgram::rectInScreenCoord(const FloatRect& rect) -{ - return m_documentToScreenMatrix.mapRect(rect); -} - -FloatRect ShaderProgram::convertScreenCoordToDocumentCoord(const FloatRect& rect) -{ - return m_documentToScreenMatrix.inverse().mapRect(rect); -} - -FloatRect ShaderProgram::convertInvScreenCoordToScreenCoord(const FloatRect& rect) -{ - FloatRect documentRect = m_documentToInvScreenMatrix.inverse().mapRect(rect); - return rectInScreenCoord(documentRect); -} - -FloatRect ShaderProgram::convertScreenCoordToInvScreenCoord(const FloatRect& rect) -{ - FloatRect documentRect = m_documentToScreenMatrix.inverse().mapRect(rect); - return rectInInvScreenCoord(documentRect); -} - -// clip is in screen coordinates -void ShaderProgram::clip(const FloatRect& clip) -{ - if (clip == m_clipRect) - return; - - ALOGV("--clipping rect %f %f, %f x %f", - clip.x(), clip.y(), clip.width(), clip.height()); - - // we should only call glScissor in this function, so that we can easily - // track the current clipping rect. - - IntRect screenClip(clip.x(), - clip.y(), - clip.width(), clip.height()); - - if (!m_screenClip.isEmpty()) - screenClip.intersect(m_screenClip); - - screenClip.setY(screenClip.y() + m_viewRect.y()); - if (screenClip.x() < 0) { - int w = screenClip.width(); - w += screenClip.x(); - screenClip.setX(0); - screenClip.setWidth(w); - } - if (screenClip.y() < 0) { - int h = screenClip.height(); - h += screenClip.y(); - screenClip.setY(0); - screenClip.setHeight(h); - } - - glScissor(screenClip.x(), screenClip.y(), screenClip.width(), screenClip.height()); - - m_clipRect = clip; -} - -IntRect ShaderProgram::clippedRectWithViewport(const IntRect& rect, int margin) -{ - IntRect viewport(m_viewport.fLeft - margin, m_viewport.fTop - margin, - m_viewport.width() + margin, m_viewport.height() + margin); - viewport.intersect(rect); - return viewport; -} - -float ShaderProgram::zValue(const TransformationMatrix& drawMatrix, float w, float h) -{ - TransformationMatrix modifiedDrawMatrix = drawMatrix; - modifiedDrawMatrix.scale3d(w, h, 1); - TransformationMatrix renderMatrix = m_projectionMatrix * modifiedDrawMatrix; - FloatPoint3D point(0.5, 0.5, 0.0); - FloatPoint3D result = renderMatrix.mapPoint(point); - return result.z(); -} - -void ShaderProgram::drawQuadInternal(ShaderType type, const GLfloat* matrix, - int textureId, float opacity, - GLenum textureTarget, GLenum filter, - const Color& pureColor) -{ - glUseProgram(m_handleArray[type].programHandle); - glUniformMatrix4fv(m_handleArray[type].projMtxHandle, 1, GL_FALSE, matrix); - - if (type != PureColor) { - glActiveTexture(GL_TEXTURE0); - glUniform1i(m_handleArray[type].texSamplerHandle, 0); - glBindTexture(textureTarget, textureId); - glTexParameteri(textureTarget, GL_TEXTURE_MIN_FILTER, filter); - glTexParameteri(textureTarget, GL_TEXTURE_MAG_FILTER, filter); - glUniform1f(m_handleArray[type].alphaHandle, opacity); - - GLint contrastHandle = m_handleArray[type].contrastHandle; - if (contrastHandle != -1) - glUniform1f(contrastHandle, m_contrast); - } else { - glUniform4f(m_handleArray[type].pureColorHandle, - pureColor.red() / 255.0, pureColor.green() / 255.0, - pureColor.blue() / 255.0, pureColor.alpha() / 255.0); - } - - GLint positionHandle = m_handleArray[type].positionHandle; - glBindBuffer(GL_ARRAY_BUFFER, m_textureBuffer[0]); - glEnableVertexAttribArray(positionHandle); - glVertexAttribPointer(positionHandle, 2, GL_FLOAT, GL_FALSE, 0, 0); - - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); -} - -// Calculate the matrix given the geometry. -GLfloat* ShaderProgram::getProjectionMatrix(const DrawQuadData* data) -{ - DrawQuadType type = data->type(); - const TransformationMatrix* matrix = data->drawMatrix(); - const SkRect* geometry = data->geometry(); - if (type == Blit) - return m_transferProjMtx; - TransformationMatrix modifiedDrawMatrix; - if (type == LayerQuad) - modifiedDrawMatrix = *matrix; - // move the drawing depending on where the texture is on the layer - modifiedDrawMatrix.translate(geometry->fLeft, geometry->fTop); - modifiedDrawMatrix.scale3d(geometry->width(), geometry->height(), 1); - - TransformationMatrix renderMatrix; - if (!m_alphaLayer) - renderMatrix = m_projectionMatrix * m_repositionMatrix - * m_webViewMatrix * modifiedDrawMatrix; - else - renderMatrix = m_projectionMatrix * modifiedDrawMatrix; - - GLUtils::toGLMatrix(m_tileProjMatrix, renderMatrix); - return m_tileProjMatrix; -} - -void ShaderProgram::drawQuad(const DrawQuadData* data) -{ - GLfloat* matrix = getProjectionMatrix(data); - - float opacity = data->opacity(); - bool forceBlending = data->forceBlending(); - bool enableBlending = forceBlending || opacity < 1.0; - - ShaderType shaderType = UndefinedShader; - int textureId = 0; - GLint textureFilter = 0; - GLenum textureTarget = 0; - - Color quadColor = data->quadColor(); - if (data->pureColor()) { - shaderType = PureColor; - quadColor = shaderColor(quadColor, opacity); - enableBlending = enableBlending || quadColor.hasAlpha(); - if (!quadColor.alpha() && enableBlending) - return; - } else { - textureId = data->textureId(); - textureFilter = data->textureFilter(); - textureTarget = data->textureTarget(); - shaderType = getTextureShaderType(textureTarget); - } - setBlendingState(enableBlending); - drawQuadInternal(shaderType, matrix, textureId, opacity, - textureTarget, textureFilter, quadColor); -} - -void ShaderProgram::drawVideoLayerQuad(const TransformationMatrix& drawMatrix, - float* textureMatrix, SkRect& geometry, - int textureId) -{ - // switch to our custom yuv video rendering program - glUseProgram(m_handleArray[Video].programHandle); - - TransformationMatrix modifiedDrawMatrix = drawMatrix; - modifiedDrawMatrix.translate(geometry.fLeft, geometry.fTop); - modifiedDrawMatrix.scale3d(geometry.width(), geometry.height(), 1); - TransformationMatrix renderMatrix = m_projectionMatrix * modifiedDrawMatrix; - - GLfloat projectionMatrix[16]; - GLUtils::toGLMatrix(projectionMatrix, renderMatrix); - glUniformMatrix4fv(m_handleArray[Video].projMtxHandle, 1, GL_FALSE, - projectionMatrix); - glUniformMatrix4fv(m_handleArray[Video].videoMtxHandle, 1, GL_FALSE, - textureMatrix); - - glActiveTexture(GL_TEXTURE0); - glUniform1i(m_handleArray[Video].texSamplerHandle, 0); - glBindTexture(GL_TEXTURE_EXTERNAL_OES, textureId); - - GLint videoPosition = m_handleArray[Video].positionHandle; - glBindBuffer(GL_ARRAY_BUFFER, m_textureBuffer[0]); - glEnableVertexAttribArray(videoPosition); - glVertexAttribPointer(videoPosition, 2, GL_FLOAT, GL_FALSE, 0, 0); - - setBlendingState(false); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); -} - -void ShaderProgram::setWebViewMatrix(const float* matrix, bool alphaLayer) -{ - GLUtils::convertToTransformationMatrix(matrix, m_webViewMatrix); - m_alphaLayer = alphaLayer; -} - -void ShaderProgram::calculateAnimationDelta() -{ - // The matrix contains the scrolling info, so this rect is starting from - // the m_viewport. - // So we just need to map the webview's visible rect using the matrix, - // calculate the difference b/t transformed rect and the webViewRect, - // then we can get the delta x , y caused by the animation. - // Note that the Y is for reporting back to GL viewport, so it is inverted. - // When it is alpha animation, then we rely on the framework implementation - // such that there is no matrix applied in native webkit. - if (!m_alphaLayer) { - FloatRect rect(m_viewport.fLeft * m_currentScale, - m_viewport.fTop * m_currentScale, - m_webViewRect.width(), - m_webViewRect.height()); - rect = m_webViewMatrix.mapRect(rect); - m_animationDelta.setX(rect.x() - m_webViewRect.x() ); - m_animationDelta.setY(rect.y() + rect.height() - m_webViewRect.y() - - m_webViewRect.height() - m_titleBarHeight); - - m_repositionMatrix.makeIdentity(); - m_repositionMatrix.translate3d(-m_webViewRect.x(), -m_webViewRect.y() - m_titleBarHeight, 0); - m_repositionMatrix.translate3d(m_viewport.fLeft * m_currentScale, m_viewport.fTop * m_currentScale, 0); - m_repositionMatrix.translate3d(-m_animationDelta.x(), -m_animationDelta.y(), 0); - } else { - m_animationDelta.setX(0); - m_animationDelta.setY(0); - m_repositionMatrix.makeIdentity(); - } - -} - -} // namespace WebCore - -#endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/android/ShaderProgram.h b/Source/WebCore/platform/graphics/android/ShaderProgram.h deleted file mode 100644 index b233f2b..0000000 --- a/Source/WebCore/platform/graphics/android/ShaderProgram.h +++ /dev/null @@ -1,234 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ShaderProgram_h -#define ShaderProgram_h - -#if USE(ACCELERATED_COMPOSITING) - -#include "Color.h" -#include "FloatRect.h" -#include "IntRect.h" -#include "SkRect.h" -#include "TransformationMatrix.h" -#include - -#define MAX_CONTRAST 5 - -namespace WebCore { - -class DrawQuadData; -class PureColorQuadData; -class TextureQuadData; - -enum ShaderType { - UndefinedShader = -1, - PureColor, - Tex2D, - Tex2DInv, - TexOES, - TexOESInv, - Video, - // When growing this enum list, make sure to insert before the - // MaxShaderNumber and init the m_handleArray accordingly. - MaxShaderNumber -}; - -struct ShaderHandles { - ShaderHandles() - : alphaHandle(-1) - , contrastHandle(-1) - , positionHandle(-1) - , programHandle(-1) - , projMtxHandle(-1) - , pureColorHandle(-1) - , texSamplerHandle(-1) - , videoMtxHandle(-1) - { - } - - void init(GLint alphaHdl, GLint contrastHdl, GLint posHdl, GLint pgmHdl, - GLint projMtxHdl, GLint colorHdl, GLint texSamplerHdl, - GLint videoMtxHdl) - { - alphaHandle = alphaHdl; - contrastHandle = contrastHdl; - positionHandle = posHdl; - programHandle = pgmHdl; - projMtxHandle = projMtxHdl; - pureColorHandle = colorHdl; - texSamplerHandle = texSamplerHdl; - videoMtxHandle = videoMtxHdl; - } - - GLint alphaHandle; - GLint contrastHandle; - GLint positionHandle; - GLint programHandle; - GLint projMtxHandle; - GLint pureColorHandle; - GLint texSamplerHandle; - GLint videoMtxHandle; -}; - -struct ShaderResource { - ShaderResource() - : program(-1) - , vertexShader(-1) - , fragmentShader(-1) - { - }; - - ShaderResource(GLuint prog, GLuint vertex, GLuint fragment) - : program(prog) - , vertexShader(vertex) - , fragmentShader(fragment) - { - }; - - GLuint program; - GLuint vertexShader; - GLuint fragmentShader; -}; - -class ShaderProgram { -public: - ShaderProgram(); - void initGLResources(); - void cleanupGLResources(); - // Drawing - void setupDrawing(const IntRect& viewRect, const SkRect& visibleRect, - const IntRect& webViewRect, int titleBarHeight, - const IntRect& screenClip, float scale); - float zValue(const TransformationMatrix& drawMatrix, float w, float h); - - // For drawQuad and drawLayerQuad, they can handle 3 cases for now: - // 1) textureTarget == GL_TEXTURE_2D - // Normal texture in GL_TEXTURE_2D target. - // 2) textureTarget == GL_TEXTURE_EXTERNAL_OES - // Surface texture in GL_TEXTURE_EXTERNAL_OES target. - // 3) textureId == 0 - // No texture needed, just a pureColor quad. - void drawQuad(const DrawQuadData* data); - void drawVideoLayerQuad(const TransformationMatrix& drawMatrix, - float* textureMatrix, SkRect& geometry, int textureId); - FloatRect rectInScreenCoord(const TransformationMatrix& drawMatrix, - const IntSize& size); - FloatRect rectInInvScreenCoord(const TransformationMatrix& drawMatrix, - const IntSize& size); - - FloatRect rectInInvScreenCoord(const FloatRect& rect); - FloatRect rectInScreenCoord(const FloatRect& rect); - FloatRect convertScreenCoordToDocumentCoord(const FloatRect& rect); - FloatRect convertInvScreenCoordToScreenCoord(const FloatRect& rect); - FloatRect convertScreenCoordToInvScreenCoord(const FloatRect& rect); - - void clip(const FloatRect& rect); - IntRect clippedRectWithViewport(const IntRect& rect, int margin = 0); - FloatRect documentViewport() { return m_documentViewport; } - - float contrast() { return m_contrast; } - void setContrast(float c) - { - float contrast = c; - if (contrast < 0) - contrast = 0; - if (contrast > MAX_CONTRAST) - contrast = MAX_CONTRAST; - m_contrast = contrast; - } - void setWebViewMatrix(const float* matrix, bool alphaLayer); - - // This delta is the delta from the layout pos and the current animation pos. - // Basically, in terms of layout, the webview is still in the original layout - // pos, as without animation. Such that the viewport and visible rect etc are - // still in that pos, too, except the clipping info. - // Our rendering approach is after applying all the matrix, webView is - // rendered as if it was at the original layout pos, but then offset the - // glViewport to match the animation. - void calculateAnimationDelta(); - int getAnimationDeltaX() { return m_animationDelta.x(); } - int getAnimationDeltaY() { return m_animationDelta.y(); } - bool needsInit() { return m_needsInit; } - -private: - GLuint loadShader(GLenum shaderType, const char* pSource); - GLint createProgram(const char* vertexSource, const char* fragmentSource); - GLfloat* getProjectionMatrix(const DrawQuadData* data); - void setBlendingState(bool enableBlending); - void drawQuadInternal(ShaderType type, const GLfloat* matrix, int textureId, - float opacity, GLenum textureTarget, GLenum filter, - const Color& pureColor); - Color shaderColor(Color pureColor, float opacity); - ShaderType getTextureShaderType(GLenum textureTarget); - void resetBlending(); - - bool m_blendingEnabled; - - TransformationMatrix m_projectionMatrix; - GLuint m_textureBuffer[1]; - - TransformationMatrix m_documentToScreenMatrix; - TransformationMatrix m_documentToInvScreenMatrix; - SkRect m_viewport; - IntRect m_viewRect; - FloatRect m_clipRect; - IntRect m_screenClip; - int m_titleBarHeight; - IntRect m_webViewRect; - - FloatRect m_documentViewport; - - float m_contrast; - - bool m_alphaLayer; - TransformationMatrix m_webViewMatrix; - float m_currentScale; - - // After the webViewTranform, we need to reposition the rect to match our viewport. - // Basically, the webViewTransformMatrix should apply on the screen resolution. - // So we start by doing the scale and translate to get each tile into screen coordinates. - // After applying the webViewTransformMatrix, b/c the way it currently set up - // for scroll and titlebar, we need to offset both of them. - // Finally, map everything back to (-1, 1) by using the m_projectionMatrix. - // TODO: Given that m_webViewMatrix contains most of the tranformation - // information, we should be able to get rid of some parameter we got from - // Java side and simplify our code. - TransformationMatrix m_repositionMatrix; - IntPoint m_animationDelta; - - // Put all the uniform location (handle) info into an array, and group them - // by the shader's type, this can help to clean up the interface. - // TODO: use the type and data comparison to skip GL call if possible. - ShaderHandles m_handleArray[MaxShaderNumber]; - - // If there is any GL error happens such that the Shaders are not initialized - // successfully at the first time, then we need to init again when we draw. - bool m_needsInit; - - // For transfer queue blitting, we need a special matrix map from (0,1) to - // (-1,1) - GLfloat m_transferProjMtx[16]; - - GLfloat m_tileProjMatrix[16]; - - Vector m_resources; -}; - -} // namespace WebCore - -#endif // USE(ACCELERATED_COMPOSITING) -#endif // ShaderProgram_h diff --git a/Source/WebCore/platform/graphics/android/Surface.cpp b/Source/WebCore/platform/graphics/android/Surface.cpp deleted file mode 100644 index 3ed3aad..0000000 --- a/Source/WebCore/platform/graphics/android/Surface.cpp +++ /dev/null @@ -1,346 +0,0 @@ -/* - * Copyright 2012, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#define LOG_TAG "Surface" -#define LOG_NDEBUG 1 - -#include "config.h" -#include "Surface.h" - -#include "AndroidLog.h" -#include "ClassTracker.h" -#include "LayerAndroid.h" -#include "GLWebViewState.h" -#include "SkCanvas.h" -#include "SurfaceBacking.h" -#include "TilesManager.h" - -// Surfaces with an area larger than 2048*2048 should never be unclipped -#define MAX_UNCLIPPED_AREA 4194304 - -namespace WebCore { - -Surface::Surface() - : m_surfaceBacking(0) - , m_needsTexture(false) - , m_hasText(false) -{ -#ifdef DEBUG_COUNT - ClassTracker::instance()->increment("Surface"); -#endif -} - -Surface::~Surface() -{ - for (unsigned int i = 0; i < m_layers.size(); i++) - SkSafeUnref(m_layers[i]); - if (m_surfaceBacking) - SkSafeUnref(m_surfaceBacking); -#ifdef DEBUG_COUNT - ClassTracker::instance()->decrement("Surface"); -#endif -} - -bool Surface::tryUpdateSurface(Surface* oldSurface) -{ - if (!needsTexture() || !oldSurface->needsTexture()) - return false; - - // merge surfaces based on first layer ID - if (getFirstLayer()->uniqueId() != oldSurface->getFirstLayer()->uniqueId()) - return false; - - m_surfaceBacking = oldSurface->m_surfaceBacking; - SkSafeRef(m_surfaceBacking); - - ALOGV("%p taking old SurfBack %p from surface %p, nt %d", - this, m_surfaceBacking, oldSurface, oldSurface->needsTexture()); - - if (!m_surfaceBacking) { - // no SurfBack to inval, so don't worry about it. - return true; - } - - if (singleLayer() && oldSurface->singleLayer()) { - // both are single matching layers, simply apply inval - SkRegion* layerInval = getFirstLayer()->getInvalRegion(); - m_surfaceBacking->markAsDirty(*layerInval); - } else { - SkRegion invalRegion; - bool fullInval = m_layers.size() != oldSurface->m_layers.size(); - if (!fullInval) { - for (unsigned int i = 0; i < m_layers.size(); i++) { - if (m_layers[i]->uniqueId() != oldSurface->m_layers[i]->uniqueId()) { - // layer list has changed, fully invalidate - // TODO: partially invalidate based on layer size/position - fullInval = true; - break; - } else if (!m_layers[i]->getInvalRegion()->isEmpty()) { - // merge layer inval - translate the layer's inval region into surface coordinates - SkPoint pos = m_layers[i]->getPosition(); - m_layers[i]->getInvalRegion()->translate(pos.fX, pos.fY); - invalRegion.op(*(m_layers[i]->getInvalRegion()), SkRegion::kUnion_Op); - break; - } - } - } - - if (fullInval) - invalRegion.setRect(-1e8, -1e8, 2e8, 2e8); - - m_surfaceBacking->markAsDirty(invalRegion); - } - return true; -} - -void Surface::addLayer(LayerAndroid* layer, const TransformationMatrix& transform) -{ - m_layers.append(layer); - SkSafeRef(layer); - - m_needsTexture |= layer->needsTexture(); - m_hasText |= layer->hasText(); - - // calculate area size for comparison later - IntRect rect = layer->unclippedArea(); - SkPoint pos = layer->getPosition(); - rect.setLocation(IntPoint(pos.fX, pos.fY)); - - if (layer->needsTexture()) { - if (m_unclippedArea.isEmpty()) { - m_drawTransform = transform; - m_drawTransform.translate3d(-pos.fX, -pos.fY, 0); - m_unclippedArea = rect; - } else - m_unclippedArea.unite(rect); - ALOGV("Surf %p adding LA %p, size %d, %d %dx%d, now Surf size %d,%d %dx%d", - this, layer, rect.x(), rect.y(), rect.width(), rect.height(), - m_unclippedArea.x(), m_unclippedArea.y(), - m_unclippedArea.width(), m_unclippedArea.height()); - } -} - -IntRect Surface::visibleArea() -{ - if (singleLayer()) - return getFirstLayer()->visibleArea(); - - IntRect rect = m_unclippedArea; - - // clip with the viewport in documents coordinate - IntRect documentViewport(TilesManager::instance()->shader()->documentViewport()); - rect.intersect(documentViewport); - - // TODO: handle recursive layer clip - - return rect; -} - -IntRect Surface::unclippedArea() -{ - if (singleLayer()) - return getFirstLayer()->unclippedArea(); - return m_unclippedArea; -} - -bool Surface::useAggressiveRendering() -{ - // When the background is semi-opaque, 0 < alpha < 255, we had to turn off - // low res to avoid artifacts from double drawing. - // TODO: avoid double drawing for low res tiles. - return isBase() - && (!m_background.alpha() - || !m_background.hasAlpha()); -} - -void Surface::prepareGL(bool layerTilesDisabled) -{ - bool tilesDisabled = layerTilesDisabled && !isBase(); - if (!m_surfaceBacking) { - ALOGV("prepareGL on Surf %p, no SurfBack, needsTexture? %d", - this, m_surfaceBacking, needsTexture()); - - if (!needsTexture()) - return; - - m_surfaceBacking = new SurfaceBacking(isBase()); - } - - if (tilesDisabled) { - m_surfaceBacking->discardTextures(); - } else { - bool allowZoom = hasText(); // only allow for scale > 1 if painting vectors - IntRect prepareArea = computePrepareArea(); - IntRect fullArea = unclippedArea(); - - ALOGV("prepareGL on Surf %p with SurfBack %p, %d layers", - this, m_surfaceBacking, m_layers.size()); - - m_surfaceBacking->prepareGL(getFirstLayer()->state(), allowZoom, - prepareArea, fullArea, - this, useAggressiveRendering()); - } -} - -bool Surface::drawGL(bool layerTilesDisabled) -{ - bool tilesDisabled = layerTilesDisabled && !isBase(); - if (!getFirstLayer()->visible()) - return false; - - if (!isBase()) { - // TODO: why are clipping regions wrong for base layer? - FloatRect drawClip = getFirstLayer()->drawClip(); - FloatRect clippingRect = TilesManager::instance()->shader()->rectInScreenCoord(drawClip); - TilesManager::instance()->shader()->clip(clippingRect); - } - - bool askRedraw = false; - if (m_surfaceBacking && !tilesDisabled) { - ALOGV("drawGL on Surf %p with SurfBack %p", this, m_surfaceBacking); - - // TODO: why this visibleArea is different from visibleRect at zooming for base? - IntRect drawArea = visibleArea(); - m_surfaceBacking->drawGL(drawArea, opacity(), drawTransform(), - useAggressiveRendering(), background()); - } - - // draw member layers (draws image textures, glextras) - for (unsigned int i = 0; i < m_layers.size(); i++) - askRedraw |= m_layers[i]->drawGL(tilesDisabled); - - return askRedraw; -} - -void Surface::swapTiles() -{ - if (!m_surfaceBacking) - return; - - m_surfaceBacking->swapTiles(); -} - -bool Surface::isReady() -{ - if (!m_surfaceBacking) - return true; - - return m_surfaceBacking->isReady(); -} - -IntRect Surface::computePrepareArea() { - IntRect area; - - if (!getFirstLayer()->contentIsScrollable() - && !isBase() - && getFirstLayer()->state()->layersRenderingMode() == GLWebViewState::kAllTextures) { - - area = unclippedArea(); - - double total = ((double) area.width()) * ((double) area.height()); - if (total > MAX_UNCLIPPED_AREA) - area = visibleArea(); - } else { - area = visibleArea(); - } - - return area; -} - -void Surface::computeTexturesAmount(TexturesResult* result) -{ - if (!m_surfaceBacking || isBase()) - return; - - m_surfaceBacking->computeTexturesAmount(result, getFirstLayer()); -} - -bool Surface::isBase() -{ - // base layer surface - // - doesn't use layer tiles (disables blending, doesn't compute textures amount) - // - ignores clip rects - // - only prepares clippedArea - return getFirstLayer()->subclassType() == LayerAndroid::BaseLayer; -} - -bool Surface::paint(Tile* tile, SkCanvas* canvas) -{ - if (singleLayer()) { - getFirstLayer()->contentDraw(canvas, Layer::UnmergedLayers); - - // TODO: double buffer by disabling SurfaceCollection swaps and position - // updates until painting complete - - // In single surface mode, draw layer content onto the base layer - if (isBase() - && getFirstLayer()->countChildren() - && getFirstLayer()->state()->layersRenderingMode() > GLWebViewState::kClippedTextures) - getFirstLayer()->getChild(0)->drawCanvas(canvas, true, Layer::FlattenedLayers); - } else { - SkAutoCanvasRestore acr(canvas, true); - SkMatrix matrix; - GLUtils::toSkMatrix(matrix, m_drawTransform); - - SkMatrix inverse; - inverse.reset(); - matrix.invert(&inverse); - - SkMatrix canvasMatrix = canvas->getTotalMatrix(); - inverse.postConcat(canvasMatrix); - canvas->setMatrix(inverse); - - for (unsigned int i=0; idrawCanvas(canvas, false, Layer::MergedLayers); - } - return true; -} - -float Surface::opacity() -{ - if (singleLayer()) - return getFirstLayer()->drawOpacity(); - return 1.0; -} - -Color* Surface::background() -{ - if (!isBase() || !m_background.isValid()) - return 0; - return &m_background; -} - -const TransformationMatrix* Surface::drawTransform() -{ - // single layer surfaces query the layer's draw transform, while multi-layer - // surfaces copy the draw transform once, during initialization - // TODO: support fixed multi-layer surfaces by querying the changing drawTransform - if (singleLayer()) - return getFirstLayer()->drawTransform(); - - return &m_drawTransform; -} - -} // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/Surface.h b/Source/WebCore/platform/graphics/android/Surface.h deleted file mode 100644 index 27c997e..0000000 --- a/Source/WebCore/platform/graphics/android/Surface.h +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright 2012, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef Surface_h -#define Surface_h - -#include "Color.h" -#include "IntRect.h" -#include "TilePainter.h" -#include "Vector.h" - -class SkCanvas; -class SkRegion; - -namespace WebCore { - -class Tile; -class SurfaceBacking; -class LayerAndroid; -class TexturesResult; - -class Surface : public TilePainter { -public: - Surface(); - virtual ~Surface(); - - bool tryUpdateSurface(Surface* oldSurface); - - void addLayer(LayerAndroid* layer, const TransformationMatrix& transform); - void prepareGL(bool layerTilesDisabled); - bool drawGL(bool layerTilesDisabled); - void swapTiles(); - bool isReady(); - - void computeTexturesAmount(TexturesResult* result); - - LayerAndroid* getFirstLayer() { return m_layers[0]; } - bool needsTexture() { return m_needsTexture; } - bool hasText() { return m_hasText; } - bool isBase(); - void setBackground(Color background) { m_background = background; } - - // TilePainter methods - virtual bool paint(Tile* tile, SkCanvas* canvas); - virtual float opacity(); - virtual Color* background(); - -private: - IntRect computePrepareArea(); - IntRect visibleArea(); - IntRect unclippedArea(); - bool singleLayer() { return m_layers.size() == 1; } - void updateBackground(const Color& background); - bool useAggressiveRendering(); - - const TransformationMatrix* drawTransform(); - IntRect m_unclippedArea; - TransformationMatrix m_drawTransform; - - SurfaceBacking* m_surfaceBacking; - bool m_needsTexture; - bool m_hasText; - Vector m_layers; - - Color m_background; -}; - -class LayerMergeState { -public: - LayerMergeState(Vector* const allGroups) - : surfaceList(allGroups) - , currentSurface(0) - , nonMergeNestedLevel(-1) // start at -1 to ignore first LayerAndroid's clipping - , depth(0) - {} - - // vector storing all generated layer groups - Vector* const surfaceList; - - // currently merging group. if cleared, no more layers may join - Surface* currentSurface; - - // records depth within non-mergeable parents (clipping, fixed, scrolling) - // and disable merging therein. - int nonMergeNestedLevel; - - // counts layer tree depth for debugging - int depth; -}; - -} // namespace WebCore - -#endif //#define Surface_h diff --git a/Source/WebCore/platform/graphics/android/SurfaceBacking.cpp b/Source/WebCore/platform/graphics/android/SurfaceBacking.cpp deleted file mode 100644 index 7c8f570..0000000 --- a/Source/WebCore/platform/graphics/android/SurfaceBacking.cpp +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright 2011, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#define LOG_TAG "SurfaceBacking" -#define LOG_NDEBUG 1 - -#include "config.h" -#include "SurfaceBacking.h" - -#include "AndroidLog.h" -#include "Color.h" -#include "GLWebViewState.h" -#include "LayerAndroid.h" - -#define LOW_RES_PREFETCH_SCALE_MODIFIER 0.3f - -namespace WebCore { - -SurfaceBacking::SurfaceBacking(bool isBaseSurface) -{ - m_frontTexture = new TileGrid(isBaseSurface); - m_backTexture = new TileGrid(isBaseSurface); - m_scale = -1; - m_futureScale = -1; - m_zooming = false; -} - -SurfaceBacking::~SurfaceBacking() -{ - delete m_frontTexture; - delete m_backTexture; -} - -void SurfaceBacking::prepareGL(GLWebViewState* state, bool allowZoom, - const IntRect& prepareArea, const IntRect& unclippedArea, - TilePainter* painter, bool aggressiveRendering) -{ - float scale = state->scale(); - if (scale > 1 && !allowZoom) - scale = 1; - - if (m_scale == -1) { - m_scale = scale; - m_futureScale = scale; - } - - if (m_futureScale != scale) { - m_futureScale = scale; - m_zoomUpdateTime = WTF::currentTime() + SurfaceBacking::s_zoomUpdateDelay; - m_zooming = true; - } - - bool useExpandPrefetch = aggressiveRendering; - ALOGV("Prepare SurfBack %p, scale %.2f, m_scale %.2f, futScale: %.2f, zooming: %d, f %p, b %p", - this, scale, m_scale, m_futureScale, m_zooming, - m_frontTexture, m_backTexture); - - if (!m_zooming) { - m_frontTexture->prepareGL(state, m_scale, - prepareArea, unclippedArea, painter, false, useExpandPrefetch); - if (aggressiveRendering) { - // prepare the back tiled texture to render content in low res - float lowResPrefetchScale = m_scale * LOW_RES_PREFETCH_SCALE_MODIFIER; - m_backTexture->prepareGL(state, lowResPrefetchScale, - prepareArea, unclippedArea, painter, true, useExpandPrefetch); - m_backTexture->swapTiles(); - } - } else if (m_zoomUpdateTime < WTF::currentTime()) { - m_backTexture->prepareGL(state, m_futureScale, - prepareArea, unclippedArea, painter, false, useExpandPrefetch); - if (m_backTexture->isReady()) { - // zooming completed, swap the textures and new front tiles - swapTileGrids(); - - m_frontTexture->swapTiles(); - m_backTexture->discardTextures(); - - m_scale = m_futureScale; - m_zooming = false; - } - } -} - -void SurfaceBacking::drawGL(const IntRect& visibleArea, float opacity, - const TransformationMatrix* transform, - bool aggressiveRendering, const Color* background) -{ - // draw low res prefetch page, if needed - if (aggressiveRendering && !m_zooming && m_frontTexture->isMissingContent()) - m_backTexture->drawGL(visibleArea, opacity, transform); - - m_frontTexture->drawGL(visibleArea, opacity, transform, background); -} - -void SurfaceBacking::markAsDirty(const SkRegion& dirtyArea) -{ - m_backTexture->markAsDirty(dirtyArea); - m_frontTexture->markAsDirty(dirtyArea); -} - -void SurfaceBacking::swapTiles() -{ - m_backTexture->swapTiles(); - m_frontTexture->swapTiles(); -} - -void SurfaceBacking::computeTexturesAmount(TexturesResult* result, LayerAndroid* layer) -{ - // TODO: shouldn't use layer, as this SB may paint multiple layers - if (!layer) - return; - - IntRect unclippedArea = layer->unclippedArea(); - IntRect clippedVisibleArea = layer->visibleArea(); - - // get two numbers here: - // - textures needed for a clipped area - // - textures needed for an un-clipped area - TileGrid* tiledTexture = m_zooming ? m_backTexture : m_frontTexture; - int nbTexturesUnclipped = tiledTexture->nbTextures(unclippedArea, m_scale); - int nbTexturesClipped = tiledTexture->nbTextures(clippedVisibleArea, m_scale); - - // Set kFixedLayers level - if (layer->isPositionFixed()) - result->fixed += nbTexturesClipped; - - // Set kScrollableAndFixedLayers level - if (layer->contentIsScrollable() - || layer->isPositionFixed()) - result->scrollable += nbTexturesClipped; - - // Set kClippedTextures level - result->clipped += nbTexturesClipped; - - // Set kAllTextures level - if (layer->contentIsScrollable()) - result->full += nbTexturesClipped; - else - result->full += nbTexturesUnclipped; -} - -void SurfaceBacking::swapTileGrids() -{ - TileGrid* temp = m_frontTexture; - m_frontTexture = m_backTexture; - m_backTexture = temp; -} - -} // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/SurfaceBacking.h b/Source/WebCore/platform/graphics/android/SurfaceBacking.h deleted file mode 100644 index b04e462..0000000 --- a/Source/WebCore/platform/graphics/android/SurfaceBacking.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright 2011, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef SurfaceBacking_h -#define SurfaceBacking_h - -#include "SkRefCnt.h" -#include "TileGrid.h" - -namespace WebCore { - -class LayerAndroid; -class TexturesResult; -class TilePainter; - -class SurfaceBacking : public SkRefCnt { -// TODO: investigate webkit threadsafe ref counting -public: - SurfaceBacking(bool isBaseSurface); - ~SurfaceBacking(); - void prepareGL(GLWebViewState* state, bool allowZoom, - const IntRect& prepareArea, const IntRect& unclippedArea, - TilePainter* painter, bool aggressiveRendering); - void swapTiles(); - void drawGL(const IntRect& visibleArea, float opacity, - const TransformationMatrix* transform, bool aggressiveRendering, - const Color* background); - void markAsDirty(const SkRegion& dirtyArea); - void computeTexturesAmount(TexturesResult* result, LayerAndroid* layer); - void discardTextures() - { - m_frontTexture->discardTextures(); - m_backTexture->discardTextures(); - } - bool isReady() - { - return !m_zooming && m_frontTexture->isReady() && m_scale > 0; - } - - int nbTextures(IntRect& area, float scale) - { - // TODO: consider the zooming case for the backTexture - if (!m_frontTexture) - return 0; - return m_frontTexture->nbTextures(area, scale); - } - -private: - void swapTileGrids(); - - // Delay before we schedule a new tile at the new scale factor - static const double s_zoomUpdateDelay = 0.2; // 200 ms - - TileGrid* m_frontTexture; - TileGrid* m_backTexture; - float m_scale; - float m_futureScale; - double m_zoomUpdateTime; - bool m_zooming; -}; - -} // namespace WebCore - -#endif // SurfaceBacking_h diff --git a/Source/WebCore/platform/graphics/android/SurfaceCollection.cpp b/Source/WebCore/platform/graphics/android/SurfaceCollection.cpp deleted file mode 100644 index 0bbaf91..0000000 --- a/Source/WebCore/platform/graphics/android/SurfaceCollection.cpp +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Copyright 2012, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#define LOG_TAG "SurfaceCollection" -#define LOG_NDEBUG 1 - -#include "config.h" -#include "SurfaceCollection.h" - -#include "AndroidLog.h" -#include "BaseLayerAndroid.h" -#include "ClassTracker.h" -#include "GLWebViewState.h" -#include "LayerAndroid.h" -#include "Surface.h" -#include "ScrollableLayerAndroid.h" -#include "TilesManager.h" - -namespace WebCore { - -//////////////////////////////////////////////////////////////////////////////// -// TILED PAINTING / SURFACES // -//////////////////////////////////////////////////////////////////////////////// - -SurfaceCollection::SurfaceCollection(LayerAndroid* layer) - : m_compositedRoot(layer) -{ - // layer must be non-null. - SkSafeRef(m_compositedRoot); - - // calculate draw transforms and z values - SkRect visibleRect = SkRect::MakeLTRB(0, 0, 1, 1); - m_compositedRoot->updateLayerPositions(visibleRect); - // TODO: updateGLPositionsAndScale? - - // allocate surfaces for layers, merging where possible - ALOGV("new tree, allocating surfaces for tree %p", m_baseLayer); - - LayerMergeState layerMergeState(&m_surfaces); - m_compositedRoot->assignSurfaces(&layerMergeState); - - // set the layersurfaces' update count, to be drawn on painted tiles - unsigned int updateCount = TilesManager::instance()->incWebkitContentUpdates(); - for (unsigned int i = 0; i < m_surfaces.size(); i++) { - m_surfaces[i]->setUpdateCount(updateCount); - if (m_surfaces[i]->isBase()) - m_surfaces[i]->setBackground(getBackground()); - } - -#ifdef DEBUG_COUNT - ClassTracker::instance()->increment("SurfaceCollection"); -#endif -} - -SurfaceCollection::~SurfaceCollection() -{ - SkSafeUnref(m_compositedRoot); - for (unsigned int i = 0; i < m_surfaces.size(); i++) - SkSafeUnref(m_surfaces[i]); - m_surfaces.clear(); - -#ifdef DEBUG_COUNT - ClassTracker::instance()->decrement("SurfaceCollection"); -#endif -} - -void SurfaceCollection::prepareGL(const SkRect& visibleRect) -{ - updateLayerPositions(visibleRect); - bool layerTilesDisabled = m_compositedRoot->state()->layersRenderingMode() - > GLWebViewState::kClippedTextures; - for (unsigned int i = 0; i < m_surfaces.size(); i++) - m_surfaces[i]->prepareGL(layerTilesDisabled); -} - -bool SurfaceCollection::drawGL(const SkRect& visibleRect) -{ -#ifdef DEBUG_COUNT - ClassTracker::instance()->show(); -#endif - - bool needsRedraw = false; - updateLayerPositions(visibleRect); - bool layerTilesDisabled = m_compositedRoot->state()->layersRenderingMode() - > GLWebViewState::kClippedTextures; - for (unsigned int i = 0; i < m_surfaces.size(); i++) - needsRedraw |= m_surfaces[i]->drawGL(layerTilesDisabled); - - return needsRedraw; -} - -Color SurfaceCollection::getBackground() -{ - return static_cast(m_compositedRoot)->getBackgroundColor(); -} - -void SurfaceCollection::swapTiles() -{ - for (unsigned int i = 0; i < m_surfaces.size(); i++) - m_surfaces[i]->swapTiles(); -} - -bool SurfaceCollection::isReady() -{ - // Override layer readiness check for single surface mode - if (m_compositedRoot->state()->layersRenderingMode() > GLWebViewState::kClippedTextures) { - // TODO: single surface mode should be properly double buffered - return true; - } - - for (unsigned int i = 0; i < m_surfaces.size(); i++) { - if (!m_surfaces[i]->isReady()) { - ALOGV("layer surface %p isn't ready", m_surfaces[i]); - return false; - } - } - return true; -} - -void SurfaceCollection::computeTexturesAmount(TexturesResult* result) -{ - for (unsigned int i = 0; i < m_surfaces.size(); i++) - m_surfaces[i]->computeTexturesAmount(result); -} - -//////////////////////////////////////////////////////////////////////////////// -// RECURSIVE ANIMATION / INVALS / LAYERS // -//////////////////////////////////////////////////////////////////////////////// - -void SurfaceCollection::setIsPainting(SurfaceCollection* drawingSurface) -{ - if (!drawingSurface) - return; - - for (unsigned int i = 0; i < m_surfaces.size(); i++) { - Surface* newSurface = m_surfaces[i]; - if (!newSurface->needsTexture()) - continue; - - for (unsigned int j = 0; j < drawingSurface->m_surfaces.size(); j++) { - Surface* oldSurface = drawingSurface->m_surfaces[j]; - if (newSurface->tryUpdateSurface(oldSurface)) - break; - } - } -} - -void SurfaceCollection::setIsDrawing() -{ - m_compositedRoot->initAnimations(); -} - -void SurfaceCollection::mergeInvalsInto(SurfaceCollection* replacementSurface) -{ - m_compositedRoot->mergeInvalsInto(replacementSurface->m_compositedRoot); -} - -void SurfaceCollection::evaluateAnimations(double currentTime) -{ - m_compositedRoot->evaluateAnimations(currentTime); -} - -bool SurfaceCollection::hasCompositedLayers() -{ - return m_compositedRoot->countChildren(); -} - -bool SurfaceCollection::hasCompositedAnimations() -{ - return m_compositedRoot->hasAnimations(); -} - -void SurfaceCollection::updateScrollableLayer(int layerId, int x, int y) -{ - LayerAndroid* layer = m_compositedRoot->findById(layerId); - if (layer && layer->contentIsScrollable()) - static_cast(layer)->scrollTo(x, y); -} - -void SurfaceCollection::updateLayerPositions(const SkRect& visibleRect) -{ - TransformationMatrix ident; - m_compositedRoot->updateLayerPositions(visibleRect); - FloatRect clip(0, 0, 1e10, 1e10); - m_compositedRoot->updateGLPositionsAndScale( - ident, clip, 1, m_compositedRoot->state()->scale()); - -#ifdef DEBUG - m_compositedRoot->showLayer(0); - ALOGV("We have %d layers, %d textured", - m_compositedRoot->nbLayers(), - m_compositedRoot->nbTexturedLayers()); -#endif -} - -} // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/SurfaceCollection.h b/Source/WebCore/platform/graphics/android/SurfaceCollection.h deleted file mode 100644 index 6450c9c..0000000 --- a/Source/WebCore/platform/graphics/android/SurfaceCollection.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright 2012, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef SurfaceCollection_h -#define SurfaceCollection_h - -#include "Color.h" -#include "SkRect.h" -#include "SkRefCnt.h" - -#include - -class SkCanvas; -class SkRegion; - -namespace WebCore { - -class LayerAndroid; -class Surface; -class TexturesResult; - -class SurfaceCollection : public SkRefCnt { -// TODO: investigate webkit threadsafe ref counting -public: - SurfaceCollection(LayerAndroid* compositedRoot); - virtual ~SurfaceCollection(); - - // Tiled painting methods (executed on groups) - void prepareGL(const SkRect& visibleRect); - bool drawGL(const SkRect& visibleRect); - Color getBackground(); - void swapTiles(); - bool isReady(); - void computeTexturesAmount(TexturesResult* result); - - // Recursive tree methods (animations, invals, etc) - void setIsPainting(SurfaceCollection* drawingSurfaceCollection); - void setIsDrawing(); - void mergeInvalsInto(SurfaceCollection* replacementSurfaceCollection); - void evaluateAnimations(double currentTime); - - bool hasCompositedLayers(); - bool hasCompositedAnimations(); - void updateScrollableLayer(int layerId, int x, int y); - -private: - void updateLayerPositions(const SkRect& visibleRect); - LayerAndroid* m_compositedRoot; - WTF::Vector m_surfaces; -}; - -} // namespace WebCore - -#endif //#define SurfaceCollection_h diff --git a/Source/WebCore/platform/graphics/android/SurfaceCollectionManager.cpp b/Source/WebCore/platform/graphics/android/SurfaceCollectionManager.cpp deleted file mode 100644 index 8fb4d4b..0000000 --- a/Source/WebCore/platform/graphics/android/SurfaceCollectionManager.cpp +++ /dev/null @@ -1,258 +0,0 @@ -/* - * Copyright 2011, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#define LOG_TAG "SurfaceCollectionManager" -#define LOG_NDEBUG 1 - -#include "config.h" -#include "SurfaceCollectionManager.h" - -#include "AndroidLog.h" -#include "private/hwui/DrawGlInfo.h" -#include "TilesManager.h" -#include "SurfaceCollection.h" - -namespace WebCore { - -SurfaceCollectionManager::SurfaceCollectionManager(GLWebViewState* state) - : m_state(state) - , m_drawingCollection(0) - , m_paintingCollection(0) - , m_queuedCollection(0) - , m_fastSwapMode(false) -{ -} - -SurfaceCollectionManager::~SurfaceCollectionManager() -{ - clearCollections(); -} - -// the painting collection has finished painting: -// discard the drawing collection -// swap the painting collection in place of the drawing collection -// and start painting the queued collection -void SurfaceCollectionManager::swap() -{ - // swap can't be called unless painting just finished - ASSERT(m_paintingCollection); - - android::Mutex::Autolock lock(m_paintSwapLock); - - ALOGV("SWAPPING, D %p, P %p, Q %p", - m_drawingCollection, m_paintingCollection, m_queuedCollection); - - // if we have a drawing collection, discard it since the painting collection is done - if (m_drawingCollection) { - ALOGV("destroying drawing collection %p", m_drawingCollection); - SkSafeUnref(m_drawingCollection); - } - - // painting collection becomes the drawing collection - ALOGV("drawing collection %p", m_paintingCollection); - m_paintingCollection->setIsDrawing(); // initialize animations - - if (m_queuedCollection) { - // start painting with the queued collection - ALOGV("now painting collection %p", m_queuedCollection); - m_queuedCollection->setIsPainting(m_paintingCollection); - } - m_drawingCollection = m_paintingCollection; - m_paintingCollection = m_queuedCollection; - m_queuedCollection = 0; - - ALOGV("SWAPPING COMPLETE, D %p, P %p, Q %p", - m_drawingCollection, m_paintingCollection, m_queuedCollection); -} - -// clear all of the content in the three collections held by the collection manager -void SurfaceCollectionManager::clearCollections() -{ - ALOGV("SurfaceCollectionManager %p removing PS from state %p", this, m_state); - - SkSafeUnref(m_drawingCollection); - m_drawingCollection = 0; - SkSafeUnref(m_paintingCollection); - m_paintingCollection = 0; - SkSafeUnref(m_queuedCollection); - m_queuedCollection = 0; -} - -// a new layer collection has arrived, queue it if we're painting something already, -// or start painting it if we aren't. Returns true if the manager has two collections -// already queued. -bool SurfaceCollectionManager::updateWithSurfaceCollection(SurfaceCollection* newCollection, - bool brandNew) -{ - // can't have a queued collection unless have a painting collection too - ASSERT(m_paintingCollection || !m_queuedCollection); - - android::Mutex::Autolock lock(m_paintSwapLock); - - if (!newCollection || brandNew) { - clearCollections(); - if (brandNew) { - m_paintingCollection = newCollection; - m_paintingCollection->setIsPainting(m_drawingCollection); - } - return false; - } - - ALOGV("updateWithSurfaceCollection - %p, has children %d, has animations %d", - newCollection, newCollection->hasCompositedLayers(), - newCollection->hasCompositedAnimations()); - - if (m_queuedCollection || m_paintingCollection) { - // currently painting, so defer this new collection - if (m_queuedCollection) { - // already have a queued collection, copy over invals so the regions are - // eventually repainted and let the old queued collection be discarded - m_queuedCollection->mergeInvalsInto(newCollection); - - if (!TilesManager::instance()->useDoubleBuffering()) { - // not double buffering, count discarded collection/webkit paint as an update - TilesManager::instance()->incContentUpdates(); - } - - ALOGV("DISCARDING collection - %p, has children %d, has animations %d", - newCollection, newCollection->hasCompositedLayers(), - newCollection->hasCompositedAnimations()); - } - SkSafeUnref(m_queuedCollection); - m_queuedCollection = newCollection; - } else { - // don't have painting collection, paint this one! - m_paintingCollection = newCollection; - m_paintingCollection->setIsPainting(m_drawingCollection); - } - return m_drawingCollection && TilesManager::instance()->useDoubleBuffering(); -} - -void SurfaceCollectionManager::updateScrollableLayer(int layerId, int x, int y) -{ - if (m_queuedCollection) - m_queuedCollection->updateScrollableLayer(layerId, x, y); - if (m_paintingCollection) - m_paintingCollection->updateScrollableLayer(layerId, x, y); - if (m_drawingCollection) - m_drawingCollection->updateScrollableLayer(layerId, x, y); -} - -int SurfaceCollectionManager::drawGL(double currentTime, IntRect& viewRect, - SkRect& visibleRect, float scale, - bool enterFastSwapMode, - bool* collectionsSwappedPtr, bool* newCollectionHasAnimPtr, - TexturesResult* texturesResultPtr, bool shouldDraw) -{ - m_fastSwapMode |= enterFastSwapMode; - - ALOGV("drawGL, D %p, P %p, Q %p, fastSwap %d shouldDraw %d", - m_drawingCollection, m_paintingCollection, - m_queuedCollection, m_fastSwapMode, shouldDraw); - - bool didCollectionSwap = false; - if (m_paintingCollection) { - ALOGV("preparing painting collection %p", m_paintingCollection); - - m_paintingCollection->evaluateAnimations(currentTime); - - m_paintingCollection->prepareGL(visibleRect); - m_paintingCollection->computeTexturesAmount(texturesResultPtr); - - if (!TilesManager::instance()->useDoubleBuffering() || m_paintingCollection->isReady()) { - ALOGV("have painting collection %p ready, swapping!", m_paintingCollection); - didCollectionSwap = true; - TilesManager::instance()->incContentUpdates(); - if (collectionsSwappedPtr) - *collectionsSwappedPtr = true; - if (newCollectionHasAnimPtr) - *newCollectionHasAnimPtr = m_paintingCollection->hasCompositedAnimations(); - swap(); - } - } else if (m_drawingCollection) { - ALOGV("preparing drawing collection %p", m_drawingCollection); - m_drawingCollection->prepareGL(visibleRect); - m_drawingCollection->computeTexturesAmount(texturesResultPtr); - } - - // ask for kStatusInvoke while painting, kStatusDraw if we have content to be redrawn next frame - // returning 0 indicates all painting complete, no framework inval needed. - int returnFlags = 0; - - if (m_paintingCollection) - returnFlags |= uirenderer::DrawGlInfo::kStatusInvoke; - - if (!shouldDraw) { - if (didCollectionSwap) { - m_drawingCollection->swapTiles(); - returnFlags |= uirenderer::DrawGlInfo::kStatusDraw; - } - - return returnFlags; - } - - // =========================================================================== - // Don't have a drawing collection, draw white background - Color background = Color::white; - if (m_drawingCollection) { - bool drawingReady = didCollectionSwap || m_drawingCollection->isReady(); - - // call the page swap callback if registration happened without more collections enqueued - if (collectionsSwappedPtr && drawingReady && !m_paintingCollection) - *collectionsSwappedPtr = true; - - if (didCollectionSwap || m_fastSwapMode || (drawingReady && !m_paintingCollection)) - m_drawingCollection->swapTiles(); - - if (drawingReady) { - // exit fast swap mode, as content is up to date - m_fastSwapMode = false; - } else { - // drawing isn't ready, must redraw - returnFlags |= uirenderer::DrawGlInfo::kStatusInvoke; - } - - m_drawingCollection->evaluateAnimations(currentTime); - - ALOGV("drawing collection %p", m_drawingCollection); - background = m_drawingCollection->getBackground(); - } else if (m_paintingCollection) { - // Use paintingCollection background color while tiles are not done painting. - background = m_paintingCollection->getBackground(); - } - - // Start doing the actual GL drawing. - ALOGV("background is %x", background.rgb()); - // If background is opaque, we can safely and efficiently clear it here. - // Otherwise, we have to calculate all the missing tiles and blend the background. - GLUtils::clearBackgroundIfOpaque(&background); - if (m_drawingCollection && m_drawingCollection->drawGL(visibleRect)) - returnFlags |= uirenderer::DrawGlInfo::kStatusDraw; - - ALOGV("returnFlags %d, m_paintingCollection %d ", returnFlags, m_paintingCollection); - return returnFlags; -} - -} // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/SurfaceCollectionManager.h b/Source/WebCore/platform/graphics/android/SurfaceCollectionManager.h deleted file mode 100644 index cc98899..0000000 --- a/Source/WebCore/platform/graphics/android/SurfaceCollectionManager.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright 2011, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef SurfaceCollectionManager_h -#define SurfaceCollectionManager_h - -#include "TestExport.h" -#include - -class SkRect; -class SkCanvas; - -namespace WebCore { - -class GLWebViewState; -class IntRect; -class TexturesResult; -class SurfaceCollection; - -class TEST_EXPORT SurfaceCollectionManager { -public: - SurfaceCollectionManager(GLWebViewState* state); - - ~SurfaceCollectionManager(); - - bool updateWithSurfaceCollection(SurfaceCollection* collection, bool brandNew); - - void updateScrollableLayer(int layerId, int x, int y); - - int drawGL(double currentTime, IntRect& viewRect, - SkRect& visibleRect, float scale, - bool enterFastSwapMode, bool* collectionsSwappedPtr, bool* newCollectionHasAnimPtr, - TexturesResult* texturesResultPtr, bool shouldDraw); - -private: - void swap(); - void clearCollections(); - - android::Mutex m_paintSwapLock; - - GLWebViewState* m_state; - - SurfaceCollection* m_drawingCollection; - SurfaceCollection* m_paintingCollection; - SurfaceCollection* m_queuedCollection; - - bool m_fastSwapMode; -}; - -} // namespace WebCore - -#endif //#define SurfaceCollectionManager_h diff --git a/Source/WebCore/platform/graphics/android/TestExport.h b/Source/WebCore/platform/graphics/android/TestExport.h deleted file mode 100644 index 15d7cc3..0000000 --- a/Source/WebCore/platform/graphics/android/TestExport.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2011, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef TestExport_h -#define TestExport_h - -// classes used outside of the .so, in tests, are declared with this attribute -#define TEST_EXPORT __attribute__((visibility("default"))) - -#endif // #define TestExport_h diff --git a/Source/WebCore/platform/graphics/android/TextureInfo.cpp b/Source/WebCore/platform/graphics/android/TextureInfo.cpp deleted file mode 100644 index f5c8b02..0000000 --- a/Source/WebCore/platform/graphics/android/TextureInfo.cpp +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright 2011, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "TextureInfo.h" - -#include "WebCoreJni.h" - -#include -#include -#include -#include - -namespace WebCore { - -TextureInfo::TextureInfo() -{ - m_textureId = GL_NO_TEXTURE; - m_width = 0; - m_height = 0; - m_internalFormat = 0; -} - -bool TextureInfo::equalsAttributes(const TextureInfo* otherTexture) -{ - return otherTexture->m_width == m_width - && otherTexture->m_height == m_height - && otherTexture->m_internalFormat == m_internalFormat; -} - -void TextureInfo::copyAttributes(const TextureInfo* sourceTexture) -{ - m_width = sourceTexture->m_width; - m_height = sourceTexture->m_height; - m_internalFormat = sourceTexture->m_internalFormat; -} - -bool TextureInfo::operator==(const TextureInfo& otherTexture) -{ - return otherTexture.m_textureId == m_textureId && equalsAttributes(&otherTexture); -} - -} // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/TextureInfo.h b/Source/WebCore/platform/graphics/android/TextureInfo.h deleted file mode 100644 index 7d182c3..0000000 --- a/Source/WebCore/platform/graphics/android/TextureInfo.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright 2011, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef TextureInfo_h -#define TextureInfo_h - -#include -#include -#include -#include -#include -using android::sp; - -namespace android { -class SurfaceTexture; -} - -namespace WebCore { - -static const GLuint GL_NO_TEXTURE = 0; -/** - * TextureInfo is a class that stores both the texture and metadata about the - * texture. - */ - -class TextureInfo { -public: - TextureInfo(); - - bool equalsAttributes(const TextureInfo* otherTexture); - void copyAttributes(const TextureInfo* sourceTexture); - - bool operator==(const TextureInfo& otherTexture); - - GLuint m_textureId; - int32_t m_width; - int32_t m_height; - GLenum m_internalFormat; -}; - -} // namespace WebCore - -#endif // TextureInfo_h diff --git a/Source/WebCore/platform/graphics/android/TextureOwner.h b/Source/WebCore/platform/graphics/android/TextureOwner.h deleted file mode 100644 index b12d8b7..0000000 --- a/Source/WebCore/platform/graphics/android/TextureOwner.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2010, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef TextureOwner_h -#define TextureOwner_h - -class SkCanvas; -class Layer; - -namespace WebCore { - -class TileTexture; -class GLWebViewState; - -class TextureOwner { -public: - virtual ~TextureOwner() { } - virtual bool removeTexture(TileTexture* texture) = 0; - virtual bool isRepaintPending() = 0; - virtual unsigned long long drawCount() = 0; -}; - -} - -#endif // TextureOwner_h diff --git a/Source/WebCore/platform/graphics/android/TexturesGenerator.cpp b/Source/WebCore/platform/graphics/android/TexturesGenerator.cpp deleted file mode 100644 index f884e52..0000000 --- a/Source/WebCore/platform/graphics/android/TexturesGenerator.cpp +++ /dev/null @@ -1,182 +0,0 @@ -/* - * Copyright 2010, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#define LOG_TAG "TexturesGenerator" -#define LOG_NDEBUG 1 - -#include "config.h" -#include "TexturesGenerator.h" - -#if USE(ACCELERATED_COMPOSITING) - -#include "AndroidLog.h" -#include "GLUtils.h" -#include "PaintTileOperation.h" -#include "TilesManager.h" -#include "TransferQueue.h" - -namespace WebCore { - -void TexturesGenerator::scheduleOperation(QueuedOperation* operation) -{ - { - android::Mutex::Autolock lock(mRequestedOperationsLock); - mRequestedOperations.append(operation); - } - mRequestedOperationsCond.signal(); -} - -void TexturesGenerator::removeOperationsForFilter(OperationFilter* filter, bool waitForRunning) -{ - if (!filter) - return; - - android::Mutex::Autolock lock(mRequestedOperationsLock); - for (unsigned int i = 0; i < mRequestedOperations.size();) { - QueuedOperation* operation = mRequestedOperations[i]; - if (filter->check(operation)) { - mRequestedOperations.remove(i); - delete operation; - } else { - i++; - } - } - - if (waitForRunning && m_currentOperation) { - QueuedOperation* operation = m_currentOperation; - - if (operation && filter->check(operation)) { - m_waitForCompletion = true; - // The reason we are signaling the transferQueue is : - // TransferQueue may be waiting a slot to work on, but now UI - // thread is waiting for Tex Gen thread to finish first before the - // UI thread can free a slot for the transferQueue. - // Therefore, it could be a deadlock. - // The solution is use this as a flag to tell Tex Gen thread that - // UI thread is waiting now, Tex Gen thread should not wait for the - // queue any more. - m_tilesManager->transferQueue()->interruptTransferQueue(true); - } - - delete filter; - - // At this point, it means that we are currently executing an operation that - // we want to be removed -- we should wait until it is done, so that - // when we return our caller can be sure that there is no more operations - // in the queue matching the given filter. - while (m_waitForCompletion) - mRequestedOperationsCond.wait(mRequestedOperationsLock); - } else { - delete filter; - } -} - -status_t TexturesGenerator::readyToRun() -{ - ALOGV("Thread ready to run"); - return NO_ERROR; -} - -// Must be called from within a lock! -QueuedOperation* TexturesGenerator::popNext() -{ - // Priority can change between when it was added and now - // Hence why the entire queue is rescanned - QueuedOperation* current = mRequestedOperations.last(); - int currentPriority = current->priority(); - if (currentPriority < 0) { - mRequestedOperations.removeLast(); - return current; - } - int currentIndex = mRequestedOperations.size() - 1; - // Scan from the back to make removing faster (less items to copy) - for (int i = mRequestedOperations.size() - 2; i >= 0; i--) { - QueuedOperation *next = mRequestedOperations[i]; - int nextPriority = next->priority(); - if (nextPriority < 0) { - // Found a very high priority item, go ahead and just handle it now - mRequestedOperations.remove(i); - return next; - } - // pick items preferrably by priority, or if equal, by order of - // insertion (as we add items at the back of the queue) - if (nextPriority <= currentPriority) { - current = next; - currentPriority = nextPriority; - currentIndex = i; - } - } - mRequestedOperations.remove(currentIndex); - return current; -} - -bool TexturesGenerator::threadLoop() -{ - // Check if we have any pending operations. - mRequestedOperationsLock.lock(); - while (!mRequestedOperations.size()) - mRequestedOperationsCond.wait(mRequestedOperationsLock); - - ALOGV("threadLoop, got signal"); - mRequestedOperationsLock.unlock(); - - m_currentOperation = 0; - bool stop = false; - while (!stop) { - mRequestedOperationsLock.lock(); - ALOGV("threadLoop, %d operations in the queue", mRequestedOperations.size()); - if (mRequestedOperations.size()) - m_currentOperation = popNext(); - mRequestedOperationsLock.unlock(); - - if (m_currentOperation) { - ALOGV("threadLoop, painting the request with priority %d", - m_currentOperation->priority()); - m_currentOperation->run(); - } - - QueuedOperation* oldOperation = m_currentOperation; - mRequestedOperationsLock.lock(); - if (m_currentOperation) - m_currentOperation = 0; - if (!mRequestedOperations.size()) - stop = true; - if (m_waitForCompletion) { - m_waitForCompletion = false; - m_tilesManager->transferQueue()->interruptTransferQueue(false); - mRequestedOperationsCond.signal(); - } - mRequestedOperationsLock.unlock(); - if (oldOperation) - delete oldOperation; // delete outside lock - } - ALOGV("threadLoop empty"); - - return true; -} - -} // namespace WebCore - -#endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/android/TexturesGenerator.h b/Source/WebCore/platform/graphics/android/TexturesGenerator.h deleted file mode 100644 index 08f69ae..0000000 --- a/Source/WebCore/platform/graphics/android/TexturesGenerator.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2010, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef TexturesGenerator_h -#define TexturesGenerator_h - -#if USE(ACCELERATED_COMPOSITING) - -#include "QueuedOperation.h" -#include "TilePainter.h" -#include - -#include - -namespace WebCore { - -using namespace android; - -class TilesManager; - -class TexturesGenerator : public Thread { -public: - TexturesGenerator(TilesManager* instance) : Thread(false) - , m_waitForCompletion(false) - , m_currentOperation(0) - , m_tilesManager(instance) { } - virtual ~TexturesGenerator() { } - virtual status_t readyToRun(); - - void removeOperationsForFilter(OperationFilter* filter, bool waitForRunning = true); - - void scheduleOperation(QueuedOperation* operation); - -private: - QueuedOperation* popNext(); - virtual bool threadLoop(); - WTF::Vector mRequestedOperations; - android::Mutex mRequestedOperationsLock; - android::Condition mRequestedOperationsCond; - bool m_waitForCompletion; - QueuedOperation* m_currentOperation; - TilesManager* m_tilesManager; -}; - -} // namespace WebCore - -#endif // USE(ACCELERATED_COMPOSITING) -#endif // TexturesGenerator_h diff --git a/Source/WebCore/platform/graphics/android/Tile.cpp b/Source/WebCore/platform/graphics/android/Tile.cpp deleted file mode 100644 index 35fded1..0000000 --- a/Source/WebCore/platform/graphics/android/Tile.cpp +++ /dev/null @@ -1,528 +0,0 @@ -/* - * Copyright 2010, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#define LOG_TAG "Tile" -#define LOG_NDEBUG 1 - -#include "config.h" -#include "Tile.h" - -#if USE(ACCELERATED_COMPOSITING) - -#include "AndroidLog.h" -#include "GLUtils.h" -#include "RasterRenderer.h" -#include "TextureInfo.h" -#include "TileTexture.h" -#include "TilesManager.h" - -// If the dirty portion of a tile exceeds this ratio, fully repaint. -// Lower values give fewer partial repaints, thus fewer front-to-back -// texture copies (cost will vary by device). It's a tradeoff between -// the rasterization cost and the FBO texture recopy cost when using -// GPU for the transfer queue. -#define MAX_INVAL_AREA 0.6 - -namespace WebCore { - -Tile::Tile(bool isLayerTile) - : m_x(-1) - , m_y(-1) - , m_frontTexture(0) - , m_backTexture(0) - , m_scale(1) - , m_dirty(true) - , m_repaintPending(false) - , m_fullRepaint(true) - , m_isLayerTile(isLayerTile) - , m_drawCount(0) - , m_state(Unpainted) -{ -#ifdef DEBUG_COUNT - ClassTracker::instance()->increment("Tile"); -#endif - m_renderer = BaseRenderer::createRenderer(); -} - -Tile::~Tile() -{ - if (m_backTexture) - m_backTexture->release(this); - if (m_frontTexture) - m_frontTexture->release(this); - - delete m_renderer; - -#ifdef DEBUG_COUNT - ClassTracker::instance()->decrement("Tile"); -#endif -} - -// All the following functions must be called from the main GL thread. - -void Tile::setContents(int x, int y, float scale, bool isExpandedPrefetchTile) -{ - // TODO: investigate whether below check/discard is necessary - if ((m_x != x) - || (m_y != y) - || (m_scale != scale)) { - // neither texture is relevant - discardTextures(); - } - - android::AutoMutex lock(m_atomicSync); - m_x = x; - m_y = y; - m_scale = scale; - m_drawCount = TilesManager::instance()->getDrawGLCount(); - if (isExpandedPrefetchTile) - m_drawCount--; // deprioritize expanded painting region -} - -void Tile::reserveTexture() -{ - TileTexture* texture = TilesManager::instance()->getAvailableTexture(this); - - android::AutoMutex lock(m_atomicSync); - if (texture && m_backTexture != texture) { - ALOGV("tile %p reserving texture %p, back was %p (front %p)", - this, texture, m_backTexture, m_frontTexture); - m_state = Unpainted; - m_backTexture = texture; - } - - if (m_state == UpToDate) { - ALOGV("moving tile %p to unpainted, since it reserved while up to date", this); - m_dirty = true; - m_state = Unpainted; - } -} - -bool Tile::removeTexture(TileTexture* texture) -{ - ALOGV("%p removeTexture %p, back %p front %p", - this, texture, m_backTexture, m_frontTexture); - // We update atomically, so paintBitmap() can see the correct value - android::AutoMutex lock(m_atomicSync); - if (m_frontTexture == texture) { - if (m_state == UpToDate) { - ALOGV("front texture removed, state was UpToDate, now becoming unpainted, bt is %p", m_backTexture); - m_state = Unpainted; - } - - m_frontTexture = 0; - } - if (m_backTexture == texture) { - m_state = Unpainted; - m_backTexture = 0; - } - - // mark dirty regardless of which texture was taken - the back texture may - // have been ready to swap - m_dirty = true; - - return true; -} - -void Tile::markAsDirty(const SkRegion& dirtyArea) -{ - if (dirtyArea.isEmpty()) - return; - android::AutoMutex lock(m_atomicSync); - m_dirtyArea.op(dirtyArea, SkRegion::kUnion_Op); - - // Check if we actually intersect with the area - bool intersect = false; - SkRegion::Iterator cliperator(dirtyArea); - SkRect realTileRect; - SkRect dirtyRect; - while (!cliperator.done()) { - dirtyRect.set(cliperator.rect()); - if (intersectWithRect(m_x, m_y, TilesManager::tileWidth(), TilesManager::tileHeight(), - m_scale, dirtyRect, realTileRect)) { - intersect = true; - break; - } - cliperator.next(); - } - - if (!intersect) - return; - - m_dirty = true; - if (m_state == UpToDate) { - // We only mark a tile as unpainted in 'markAsDirty' if its status is - // UpToDate: marking dirty means we need to repaint, but don't stop the - // current paint - m_state = Unpainted; - } else if (m_state != Unpainted) { - // TODO: fix it so that they can paint while deferring the markAsDirty - // call (or block updates) - ALOGV("Warning: tried to mark tile %p at %d, %d islayertile %d as dirty, state %d", - this, m_x, m_y, isLayerTile(), m_state); - - // prefetch tiles can be marked dirty while in the process of painting, - // due to not using an update lock. force them to fail validate step. - m_state = Unpainted; - } -} - -bool Tile::isDirty() -{ - android::AutoMutex lock(m_atomicSync); - return m_dirty; -} - -bool Tile::isRepaintPending() -{ - android::AutoMutex lock(m_atomicSync); - return m_repaintPending; -} - -void Tile::setRepaintPending(bool pending) -{ - android::AutoMutex lock(m_atomicSync); - m_repaintPending = pending; -} - -bool Tile::drawGL(float opacity, const SkRect& rect, float scale, - const TransformationMatrix* transform, - bool forceBlending) -{ - if (m_x < 0 || m_y < 0 || m_scale != scale) - return false; - - // No need to mutex protect reads of m_backTexture as it is only written to by - // the consumer thread. - if (!m_frontTexture) - return false; - - m_frontTexture->drawGL(isLayerTile(), rect, opacity, transform, forceBlending); - return true; -} - -bool Tile::isTileReady() -{ - // Return true if the tile's most recently drawn texture is up to date - android::AutoMutex lock(m_atomicSync); - TileTexture * texture = (m_state == ReadyToSwap) ? m_backTexture : m_frontTexture; - - if (!texture) - return false; - - if (texture->owner() != this) - return false; - - if (m_dirty) - return false; - - if (m_state != ReadyToSwap && m_state != UpToDate) - return false; - - return true; -} - -bool Tile::intersectWithRect(int x, int y, int tileWidth, int tileHeight, - float scale, const SkRect& dirtyRect, - SkRect& realTileRect) -{ - // compute the rect to corresponds to pixels - realTileRect.fLeft = x * tileWidth; - realTileRect.fTop = y * tileHeight; - realTileRect.fRight = realTileRect.fLeft + tileWidth; - realTileRect.fBottom = realTileRect.fTop + tileHeight; - - // scale the dirtyRect for intersect computation. - SkRect realDirtyRect = SkRect::MakeWH(dirtyRect.width() * scale, - dirtyRect.height() * scale); - realDirtyRect.offset(dirtyRect.fLeft * scale, dirtyRect.fTop * scale); - - if (!realTileRect.intersect(realDirtyRect)) - return false; - return true; -} - -bool Tile::isTileVisible(const IntRect& viewTileBounds) -{ - return (m_x >= viewTileBounds.x() - && m_x < viewTileBounds.x() + viewTileBounds.width() - && m_y >= viewTileBounds.y() - && m_y < viewTileBounds.y() + viewTileBounds.height()); -} - -// This is called from the texture generation thread -void Tile::paintBitmap(TilePainter* painter) -{ - // We acquire the values below atomically. This ensures that we are reading - // values correctly across cores. Further, once we have these values they - // can be updated by other threads without consequence. - m_atomicSync.lock(); - bool dirty = m_dirty; - TileTexture* texture = m_backTexture; - SkRegion dirtyArea = m_dirtyArea; - float scale = m_scale; - const int x = m_x; - const int y = m_y; - - if (!dirty || !texture) { - m_atomicSync.unlock(); - return; - } - if (m_state != Unpainted) { - ALOGV("Warning: started painting tile %p, but was at state %d, ft %p bt %p", - this, m_state, m_frontTexture, m_backTexture); - } - m_state = PaintingStarted; - TextureInfo* textureInfo = texture->getTextureInfo(); - m_atomicSync.unlock(); - - // at this point we can safely check the ownership (if the texture got - // transferred to another Tile under us) - if (texture->owner() != this) { - return; - } - - // swap out the renderer if necessary - BaseRenderer::swapRendererIfNeeded(m_renderer); - // setup the common renderInfo fields; - TileRenderInfo renderInfo; - renderInfo.x = x; - renderInfo.y = y; - renderInfo.scale = scale; - renderInfo.tileSize = texture->getSize(); - renderInfo.tilePainter = painter; - renderInfo.baseTile = this; - renderInfo.textureInfo = textureInfo; - - const float tileWidth = renderInfo.tileSize.width(); - const float tileHeight = renderInfo.tileSize.height(); - - SkRegion::Iterator cliperator(dirtyArea); - - bool fullRepaint = false; - - if (m_fullRepaint - || textureInfo->m_width != tileWidth - || textureInfo->m_height != tileHeight) { - fullRepaint = true; - } - - // For now, only do full repaint - fullRepaint = true; - - if (!fullRepaint) { - // compute the partial inval area - SkIRect totalRect; - totalRect.set(0, 0, 0, 0); - float tileSurface = tileWidth * tileHeight; - float tileSurfaceCap = MAX_INVAL_AREA * tileSurface; - - // We join all the invals in the same tile for now - while (!fullRepaint && !cliperator.done()) { - SkRect realTileRect; - SkRect dirtyRect; - dirtyRect.set(cliperator.rect()); - bool intersect = intersectWithRect(x, y, tileWidth, tileHeight, - scale, dirtyRect, realTileRect); - if (intersect) { - // initialize finalRealRect to the rounded values of realTileRect - SkIRect finalRealRect; - realTileRect.roundOut(&finalRealRect); - - // stash the int values of the current width and height - const int iWidth = finalRealRect.width(); - const int iHeight = finalRealRect.height(); - - if (iWidth == tileWidth || iHeight == tileHeight) { - fullRepaint = true; - break; - } - - // translate the rect into tile space coordinates - finalRealRect.fLeft = finalRealRect.fLeft % static_cast(tileWidth); - finalRealRect.fTop = finalRealRect.fTop % static_cast(tileHeight); - finalRealRect.fRight = finalRealRect.fLeft + iWidth; - finalRealRect.fBottom = finalRealRect.fTop + iHeight; - totalRect.join(finalRealRect); - float repaintSurface = totalRect.width() * totalRect.height(); - - if (repaintSurface > tileSurfaceCap) { - fullRepaint = true; - break; - } - } - - cliperator.next(); - } - - if (!fullRepaint) { - renderInfo.invalRect = &totalRect; - m_renderer->renderTiledContent(renderInfo); - } - } - - // Do a full repaint if needed - if (fullRepaint) { - renderInfo.invalRect = 0; - m_renderer->renderTiledContent(renderInfo); - } - - m_atomicSync.lock(); - - if (texture == m_backTexture) { - // set the fullrepaint flags - m_fullRepaint = false; - - // The various checks to see if we are still dirty... - - m_dirty = false; - - if (m_scale != scale) - m_dirty = true; - - if (fullRepaint) - m_dirtyArea.setEmpty(); - else - m_dirtyArea.op(dirtyArea, SkRegion::kDifference_Op); - - if (!m_dirtyArea.isEmpty()) - m_dirty = true; - - ALOGV("painted tile %p (%d, %d), texture %p, dirty=%d", this, x, y, texture, m_dirty); - - validatePaint(); - } else { - ALOGV("tile %p no longer owns texture %p, m_state %d. ft %p bt %p", - this, texture, m_state, m_frontTexture, m_backTexture); - } - - m_atomicSync.unlock(); -} - -void Tile::discardTextures() { - android::AutoMutex lock(m_atomicSync); - ALOGV("%p discarding bt %p, ft %p", - this, m_backTexture, m_frontTexture); - if (m_frontTexture) { - m_frontTexture->release(this); - m_frontTexture = 0; - } - if (m_backTexture) { - m_backTexture->release(this); - m_backTexture = 0; - } - m_dirtyArea.setEmpty(); - m_fullRepaint = true; - - m_dirty = true; - m_state = Unpainted; -} - -void Tile::discardBackTexture() { - android::AutoMutex lock(m_atomicSync); - if (m_backTexture) { - m_backTexture->release(this); - m_backTexture = 0; - } - m_state = Unpainted; - m_dirty = true; -} - -bool Tile::swapTexturesIfNeeded() { - android::AutoMutex lock(m_atomicSync); - if (m_state == ReadyToSwap) { - // discard old texture and swap the new one in its place - if (m_frontTexture) - m_frontTexture->release(this); - - m_frontTexture = m_backTexture; - m_backTexture = 0; - m_state = UpToDate; - ALOGV("display texture for %p at %d, %d front is now %p, back is %p", - this, m_x, m_y, m_frontTexture, m_backTexture); - - return true; - } - return false; -} - -void Tile::backTextureTransfer() { - android::AutoMutex lock(m_atomicSync); - if (m_state == PaintingStarted) - m_state = TransferredUnvalidated; - else if (m_state == ValidatedUntransferred) - m_state = ReadyToSwap; - else { - // shouldn't have transferred a tile in any other state, log - ALOGV("Note: transferred tile %p at %d %d, state wasn't paintingstarted or validated: %d", - this, m_x, m_y, m_state); - } -} - -void Tile::backTextureTransferFail() { - // transfer failed for some reason, mark dirty so it will (repaint and) be - // retransferred. - android::AutoMutex lock(m_atomicSync); - m_state = Unpainted; - m_dirty = true; - // whether validatePaint is called before or after, it won't do anything -} - -void Tile::validatePaint() { - // ONLY CALL while m_atomicSync is locked (at the end of paintBitmap()) - - if (!m_dirty) { - // since after the paint, the tile isn't dirty, 'validate' it - this - // may happed before or after the transfer queue operation. Only - // when both have happened, mark as 'ReadyToSwap' - if (m_state == PaintingStarted) - m_state = ValidatedUntransferred; - else if (m_state == TransferredUnvalidated) { - // When the backTexture has been marked pureColor, we will skip the - // transfer and marked as ReadyToSwap, in this case, we don't want - // to reset m_dirty bit to true. - m_state = ReadyToSwap; - } else { - ALOGV("Note: validated tile %p at %d %d, state wasn't paintingstarted or transferred %d", - this, m_x, m_y, m_state); - // failed transferring, in which case mark dirty (since - // paintBitmap() may have cleared m_dirty) - m_dirty = true; - } - - if (m_deferredDirty) { - ALOGV("Note: deferred dirty flag set, possibly a missed paint on tile %p", this); - m_deferredDirty = false; - } - } else { - ALOGV("Note: paint was unsuccessful."); - m_state = Unpainted; - } - -} - -} // namespace WebCore - -#endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/android/Tile.h b/Source/WebCore/platform/graphics/android/Tile.h deleted file mode 100644 index 7010301..0000000 --- a/Source/WebCore/platform/graphics/android/Tile.h +++ /dev/null @@ -1,191 +0,0 @@ -/* - * Copyright 2010, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef Tile_h -#define Tile_h - -#if USE(ACCELERATED_COMPOSITING) - -#include "BaseRenderer.h" -#include "SkRect.h" -#include "SkRegion.h" -#include "TextureOwner.h" -#include "TilePainter.h" - -#include - -namespace WebCore { - -class TextureInfo; -class TileTexture; -class GLWebViewState; - -/** - * An individual tile that is used to construct part of a webpage's BaseLayer of - * content. Each tile is assigned to a TiledPage and is responsible for drawing - * and displaying their section of the page. The lifecycle of a tile is: - * - * 1. Each tile is created on the main GL thread and assigned to a specific - * location within a TiledPage. - * 2. When needed the tile is passed to the background thread where it paints - * the BaseLayer's most recent PictureSet to a bitmap which is then uploaded - * to the GPU. - * 3. After the bitmap is uploaded to the GPU the main GL thread then uses the - * tile's drawGL() function to display the tile to the screen. - * 4. Steps 2-3 are repeated as necessary. - * 5. The tile is destroyed when the user navigates to a new page. - * - */ -class Tile : public TextureOwner { -public: - - // eventually, m_dirty might be rolled into the state machine, but note - // that a tile that's continually marked dirty from animation should still - // progress through the state machine and be drawn periodically (esp. for - // layers) - - // /-> TransferredUnvalidated (TQ interrupts paint) -\ (TQ & paint done) - // Unpainted -> PaintingStarted -- -> ReadyToSwap -> UpToDate - // ^ \-> ValidatedUntransferred (paint finish before TQ) -/ - // | - // \--... (From any state when marked dirty. should usually come from UpToDate if the updates are locked) - // - - enum TextureState{ - // back texture is completely unpainted - Unpainted = 0, - // has started painting, but haven't been transferred or validated - PaintingStarted = 1, - // back texture painted, transferred before validating in PaintBitmap() - TransferredUnvalidated = 2, - // back texture painted, validated before transferring in TransferQueue - ValidatedUntransferred = 3, - // back texture has been blitted, will be swapped when next available - ReadyToSwap = 4, - // has been swapped, is ready to draw, all is well - UpToDate = 5, - }; - - Tile(bool isLayerTile = false); - ~Tile(); - - bool isLayerTile() { return m_isLayerTile; } - - void setContents(int x, int y, float scale, bool isExpandedPrefetchTile); - - void reserveTexture(); - - bool isTileReady(); - - // Return false when real draw didn't happen for any reason. - bool drawGL(float opacity, const SkRect& rect, float scale, - const TransformationMatrix* transform, - bool forceBlending = false); - - // the only thread-safe function called by the background thread - void paintBitmap(TilePainter* painter); - - bool intersectWithRect(int x, int y, int tileWidth, int tileHeight, - float scale, const SkRect& dirtyRect, - SkRect& realTileRect); - bool isTileVisible(const IntRect& viewTileBounds); - - void markAsDirty(const SkRegion& dirtyArea); - bool isDirty(); - virtual bool isRepaintPending(); - void setRepaintPending(bool pending); - float scale() const { return m_scale; } - TextureState textureState() const { return m_state; } - - int x() const { return m_x; } - int y() const { return m_y; } - TileTexture* frontTexture() { return m_frontTexture; } - TileTexture* backTexture() { return m_backTexture; } - - // only used for prioritization - the higher, the more relevant the tile is - unsigned long long drawCount() { return m_drawCount; } - void discardTextures(); - void discardBackTexture(); - bool swapTexturesIfNeeded(); - void backTextureTransfer(); - void backTextureTransferFail(); - - // TextureOwner implementation - virtual bool removeTexture(TileTexture* texture); - -private: - void validatePaint(); - - int m_x; - int m_y; - - // The remaining variables can be updated throughout the lifetime of the object - - TileTexture* m_frontTexture; - TileTexture* m_backTexture; - float m_scale; - - // used to signal that the that the tile is out-of-date and needs to be - // redrawn in the backTexture - bool m_dirty; - - // currently only for debugging, to be used for tracking down dropped repaints - bool m_deferredDirty; - - // used to signal that a repaint is pending - bool m_repaintPending; - - // store the dirty region - SkRegion m_dirtyArea; - bool m_fullRepaint; - - // This mutex serves two purposes. (1) It ensures that certain operations - // happen atomically and (2) it makes sure those operations are synchronized - // across all threads and cores. - android::Mutex m_atomicSync; - - BaseRenderer* m_renderer; - - bool m_isLayerTile; - - // the most recent GL draw before this tile was prepared. used for - // prioritization and caching. tiles with old drawcounts and textures they - // own are used for new tiles and rendering - unsigned long long m_drawCount; - - // Tracks the state of painting for the tile. High level overview: - // 1) Unpainted - until paint starts (and if marked dirty, in most cases) - // 2) PaintingStarted - until paint completes - // 3) TransferredUnvalidated - if transferred first - // or ValidatedUntransferred - if validated first - // 4) ReadyToSwap - if painted and transferred, but not swapped - // 5) UpToDate - until marked dirty again - TextureState m_state; -}; - -} // namespace WebCore - -#endif // USE(ACCELERATED_COMPOSITING) -#endif // Tile_h diff --git a/Source/WebCore/platform/graphics/android/TileGrid.cpp b/Source/WebCore/platform/graphics/android/TileGrid.cpp deleted file mode 100644 index 0e900a9..0000000 --- a/Source/WebCore/platform/graphics/android/TileGrid.cpp +++ /dev/null @@ -1,376 +0,0 @@ -/* - * Copyright 2011, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#define LOG_TAG "TileGrid" -#define LOG_NDEBUG 1 - -#include "config.h" -#include "TileGrid.h" - -#include "AndroidLog.h" -#include "DrawQuadData.h" -#include "GLWebViewState.h" -#include "PaintTileOperation.h" -#include "Tile.h" -#include "TilesManager.h" - -#include - -#define EXPANDED_BOUNDS_INFLATE 1 -#define EXPANDED_PREFETCH_BOUNDS_Y_INFLATE 1 - -namespace WebCore { - -TileGrid::TileGrid(bool isBaseSurface) - : m_prevTileY(0) - , m_scale(1) - , m_isBaseSurface(isBaseSurface) -{ - m_dirtyRegion.setEmpty(); -#ifdef DEBUG_COUNT - ClassTracker::instance()->increment("TileGrid"); -#endif -} - -TileGrid::~TileGrid() -{ -#ifdef DEBUG_COUNT - ClassTracker::instance()->decrement("TileGrid"); -#endif - removeTiles(); -} - -bool TileGrid::isReady() -{ - bool tilesAllReady = true; - bool tilesVisible = false; - for (unsigned int i = 0; i < m_tiles.size(); i++) { - Tile* tile = m_tiles[i]; - if (tile->isTileVisible(m_area)) { - tilesVisible = true; - if (!tile->isTileReady()) { - tilesAllReady = false; - break; - } - } - } - // For now, if no textures are available, consider ourselves as ready - // in order to unblock the zooming process. - // FIXME: have a better system -- maybe keeping the last scale factor - // able to fully render everything - ALOGV("TT %p, ready %d, visible %d, texturesRemain %d", - this, tilesAllReady, tilesVisible, - TilesManager::instance()->layerTexturesRemain()); - - return !TilesManager::instance()->layerTexturesRemain() - || !tilesVisible || tilesAllReady; -} - -bool TileGrid::isMissingContent() -{ - for (unsigned int i = 0; i < m_tiles.size(); i++) - if (m_tiles[i]->isTileVisible(m_area) && !m_tiles[i]->frontTexture()) - return true; - return false; -} - -void TileGrid::swapTiles() -{ - int swaps = 0; - for (unsigned int i = 0; i < m_tiles.size(); i++) - if (m_tiles[i]->swapTexturesIfNeeded()) - swaps++; - ALOGV("TT %p swapping, swaps = %d", this, swaps); -} - -IntRect TileGrid::computeTilesArea(const IntRect& contentArea, float scale) -{ - IntRect computedArea; - IntRect area(contentArea.x() * scale, - contentArea.y() * scale, - ceilf(contentArea.width() * scale), - ceilf(contentArea.height() * scale)); - - ALOGV("TT %p prepare, scale %f, area %d x %d", this, scale, area.width(), area.height()); - - if (area.width() == 0 && area.height() == 0) { - computedArea.setWidth(0); - computedArea.setHeight(0); - return computedArea; - } - - int tileWidth = TilesManager::tileWidth(); - int tileHeight = TilesManager::tileHeight(); - - computedArea.setX(area.x() / tileWidth); - computedArea.setY(area.y() / tileHeight); - float right = (area.x() + area.width()) / (float) tileWidth; - float bottom = (area.y() + area.height()) / (float) tileHeight; - computedArea.setWidth(ceilf(right) - computedArea.x()); - computedArea.setHeight(ceilf(bottom) - computedArea.y()); - return computedArea; -} - -void TileGrid::prepareGL(GLWebViewState* state, float scale, - const IntRect& prepareArea, const IntRect& unclippedArea, - TilePainter* painter, bool isLowResPrefetch, bool useExpandPrefetch) -{ - // first, how many tiles do we need - m_area = computeTilesArea(prepareArea, scale); - if (m_area.isEmpty()) - return; - - ALOGV("prepare TileGrid %p with scale %.2f, prepareArea " - " %d, %d - %d x %d, corresponding to %d, %d x - %d x %d tiles", - this, scale, - prepareArea.x(), prepareArea.y(), - prepareArea.width(), prepareArea.height(), - m_area.x(), m_area.y(), - m_area.width(), m_area.height()); - - bool goingDown = m_prevTileY < m_area.y(); - m_prevTileY = m_area.y(); - - if (scale != m_scale) - TilesManager::instance()->removeOperationsForFilter(new ScaleFilter(painter, m_scale)); - - m_scale = scale; - - // apply dirty region to affected tiles - if (!m_dirtyRegion.isEmpty()) { - for (unsigned int i = 0; i < m_tiles.size(); i++) - m_tiles[i]->markAsDirty(m_dirtyRegion); - - // log inval region for the base surface - if (m_isBaseSurface && TilesManager::instance()->getProfiler()->enabled()) { - SkRegion::Iterator iterator(m_dirtyRegion); - while (!iterator.done()) { - SkIRect r = iterator.rect(); - TilesManager::instance()->getProfiler()->nextInval(r, scale); - iterator.next(); - } - } - m_dirtyRegion.setEmpty(); - } - - // prepare standard bounds (clearing ExpandPrefetch flag) - for (int i = 0; i < m_area.width(); i++) { - if (goingDown) { - for (int j = 0; j < m_area.height(); j++) - prepareTile(m_area.x() + i, m_area.y() + j, - painter, state, isLowResPrefetch, false); - } else { - for (int j = m_area.height() - 1; j >= 0; j--) - prepareTile(m_area.x() + i, m_area.y() + j, - painter, state, isLowResPrefetch, false); - } - } - - // prepare expanded bounds - if (useExpandPrefetch) { - IntRect fullArea = computeTilesArea(unclippedArea, scale); - IntRect expandedArea = m_area; - expandedArea.inflate(EXPANDED_BOUNDS_INFLATE); - - if (isLowResPrefetch) - expandedArea.inflate(EXPANDED_PREFETCH_BOUNDS_Y_INFLATE); - - // clip painting area to content - expandedArea.intersect(fullArea); - - for (int i = expandedArea.x(); i < expandedArea.maxX(); i++) - for (int j = expandedArea.y(); j < expandedArea.maxY(); j++) - if (!m_area.contains(i, j)) - prepareTile(i, j, painter, state, isLowResPrefetch, true); - } -} - -void TileGrid::markAsDirty(const SkRegion& invalRegion) -{ - ALOGV("TT %p markAsDirty, current region empty %d, new empty %d", - this, m_dirtyRegion.isEmpty(), invalRegion.isEmpty()); - m_dirtyRegion.op(invalRegion, SkRegion::kUnion_Op); -} - -void TileGrid::prepareTile(int x, int y, TilePainter* painter, - GLWebViewState* state, bool isLowResPrefetch, bool isExpandPrefetch) -{ - Tile* tile = getTile(x, y); - if (!tile) { - bool isLayerTile = !m_isBaseSurface; - tile = new Tile(isLayerTile); - m_tiles.append(tile); - } - - ALOGV("preparing tile %p at %d, %d, painter is %p", tile, x, y, painter); - - tile->setContents(x, y, m_scale, isExpandPrefetch); - - // TODO: move below (which is largely the same for layers / tiled page) into - // prepareGL() function - - if (tile->isDirty() || !tile->frontTexture()) - tile->reserveTexture(); - - if (tile->backTexture() && tile->isDirty() && !tile->isRepaintPending()) { - ALOGV("painting TT %p's tile %d %d for LG %p", this, x, y, painter); - PaintTileOperation *operation = new PaintTileOperation(tile, painter, - state, isLowResPrefetch); - TilesManager::instance()->scheduleOperation(operation); - } -} - -Tile* TileGrid::getTile(int x, int y) -{ - for (unsigned int i = 0; i x() == x && tile->y() == y) - return tile; - } - return 0; -} - -int TileGrid::nbTextures(IntRect& area, float scale) -{ - IntRect tileBounds = computeTilesArea(area, scale); - int numberTextures = tileBounds.width() * tileBounds.height(); - - // add the number of dirty tiles in the bounds, as they take up double - // textures for double buffering - for (unsigned int i = 0; i isDirty() - && tile->x() >= tileBounds.x() && tile->x() <= tileBounds.maxX() - && tile->y() >= tileBounds.y() && tile->y() <= tileBounds.maxY()) - numberTextures++; - } - return numberTextures; -} - -void TileGrid::drawGL(const IntRect& visibleArea, float opacity, - const TransformationMatrix* transform, - const Color* background) -{ - m_area = computeTilesArea(visibleArea, m_scale); - if (m_area.width() == 0 || m_area.height() == 0) - return; - - float invScale = 1 / m_scale; - const float tileWidth = TilesManager::tileWidth() * invScale; - const float tileHeight = TilesManager::tileHeight() * invScale; - - int drawn = 0; - - SkRegion missingRegion; - bool semiOpaqueBaseSurface = - background ? (background->hasAlpha() && background->alpha() > 0) : false; - if (semiOpaqueBaseSurface) { - SkIRect totalArea = SkIRect::MakeXYWH(m_area.x(), m_area.y(), - m_area.width(), m_area.height()); - missingRegion = SkRegion(totalArea); - } - - for (unsigned int i = 0; i < m_tiles.size(); i++) { - Tile* tile = m_tiles[i]; - - bool tileInView = tile->isTileVisible(m_area); - if (tileInView) { - SkRect rect; - rect.fLeft = tile->x() * tileWidth; - rect.fTop = tile->y() * tileHeight; - rect.fRight = rect.fLeft + tileWidth; - rect.fBottom = rect.fTop + tileHeight; - ALOGV("tile %p (layer tile: %d) %d,%d at scale %.2f vs %.2f [ready: %d] dirty: %d", - tile, tile->isLayerTile(), tile->x(), tile->y(), - tile->scale(), m_scale, tile->isTileReady(), tile->isDirty()); - - bool forceBaseBlending = background ? background->hasAlpha() : false; - bool success = tile->drawGL(opacity, rect, m_scale, transform, - forceBaseBlending); - if (semiOpaqueBaseSurface && success) { - // Cut the successful drawn tile area from the missing region. - missingRegion.op(SkIRect::MakeXYWH(tile->x(), tile->y(), 1, 1), - SkRegion::kDifference_Op); - } - if (tile->frontTexture()) - drawn++; - } - - if (semiOpaqueBaseSurface) - TilesManager::instance()->getProfiler()->nextTile(tile, invScale, tileInView); - } - - // Draw missing Regions with blend turned on - if (semiOpaqueBaseSurface) - drawMissingRegion(missingRegion, opacity, background); - - ALOGV("TT %p drew %d tiles, scale %f", - this, drawn, m_scale); -} - -void TileGrid::drawMissingRegion(const SkRegion& region, float opacity, - const Color* background) -{ - SkRegion::Iterator iterator(region); - const float tileWidth = TilesManager::tileWidth() / m_scale; - const float tileHeight = TilesManager::tileHeight() / m_scale; - ShaderProgram* shader = TilesManager::instance()->shader(); - while (!iterator.done()) { - SkIRect r = iterator.rect(); - SkRect rect; - rect.fLeft = r.x() * tileWidth; - rect.fTop = r.y() * tileHeight; - rect.fRight = rect.fLeft + tileWidth * r.width(); - rect.fBottom = rect.fTop + tileHeight * r.height(); - ALOGV("draw tile x y, %d %d (%d %d) opacity %f", r.x(), r.y(), - r.width(), r.height(), opacity); - // Skia is using pre-multiplied color. - Color postAlpha = Color(background->red() * background->alpha() / 255, - background->green() * background->alpha() / 255, - background->blue() * background->alpha() / 255, - background->alpha() ); - - PureColorQuadData backGroundData(postAlpha, BaseQuad, 0, &rect, opacity); - TilesManager::instance()->shader()->drawQuad(&backGroundData); - iterator.next(); - } -} - -void TileGrid::removeTiles() -{ - for (unsigned int i = 0; i < m_tiles.size(); i++) { - delete m_tiles[i]; - } - m_tiles.clear(); -} - -void TileGrid::discardTextures() -{ - ALOGV("TT %p discarding textures", this); - for (unsigned int i = 0; i < m_tiles.size(); i++) - m_tiles[i]->discardTextures(); -} - -} // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/TileGrid.h b/Source/WebCore/platform/graphics/android/TileGrid.h deleted file mode 100644 index ffb6c7e..0000000 --- a/Source/WebCore/platform/graphics/android/TileGrid.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright 2011, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef TileGrid_h -#define TileGrid_h - -#include "IntRect.h" -#include "SkRegion.h" - -#include - -namespace WebCore { - -class Color; -class GLWebViewState; -class Tile; -class TilePainter; -class TransformationMatrix; - -class TileGrid { -public: - TileGrid(bool isBaseSurface); - virtual ~TileGrid(); - - static IntRect computeTilesArea(const IntRect& contentArea, float scale); - - void prepareGL(GLWebViewState* state, float scale, - const IntRect& prepareArea, const IntRect& unclippedArea, - TilePainter* painter, bool isLowResPrefetch = false, - bool useExpandPrefetch = false); - void swapTiles(); - void drawGL(const IntRect& visibleArea, float opacity, - const TransformationMatrix* transform, const Color* background = 0); - - void prepareTile(int x, int y, TilePainter* painter, - GLWebViewState* state, bool isLowResPrefetch, bool isExpandPrefetch); - void markAsDirty(const SkRegion& dirtyArea); - - Tile* getTile(int x, int y); - - void removeTiles(); - void discardTextures(); - - bool isReady(); - bool isMissingContent(); - - int nbTextures(IntRect& area, float scale); - -private: - void drawMissingRegion(const SkRegion& region, float opacity, const Color* tileBackground); - WTF::Vector m_tiles; - - IntRect m_area; - - SkRegion m_dirtyRegion; - - int m_prevTileY; - float m_scale; - - bool m_isBaseSurface; -}; - -} // namespace WebCore - -#endif // TileGrid_h diff --git a/Source/WebCore/platform/graphics/android/TilePainter.h b/Source/WebCore/platform/graphics/android/TilePainter.h deleted file mode 100644 index d992aee..0000000 --- a/Source/WebCore/platform/graphics/android/TilePainter.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2011, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef TilePainter_h -#define TilePainter_h - -#include "TransformationMatrix.h" -#include "SkRefCnt.h" - -class SkCanvas; - -namespace WebCore { - -class Tile; -class Color; - -class TilePainter : public SkRefCnt { -// TODO: investigate webkit threadsafe ref counting -public: - virtual ~TilePainter() { } - virtual bool paint(Tile* tile, SkCanvas* canvas) = 0; - virtual float opacity() { return 1.0; } - enum SurfaceType { Painted, Image }; - virtual SurfaceType type() { return Painted; } - virtual Color* background() { return 0; } - - unsigned int getUpdateCount() { return m_updateCount; } - void setUpdateCount(unsigned int updateCount) { m_updateCount = updateCount; } - -private: - unsigned int m_updateCount; -}; - -} - -#endif // TilePainter_h diff --git a/Source/WebCore/platform/graphics/android/TileTexture.cpp b/Source/WebCore/platform/graphics/android/TileTexture.cpp deleted file mode 100644 index 39effd7..0000000 --- a/Source/WebCore/platform/graphics/android/TileTexture.cpp +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright 2010, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#define LOG_TAG "TileTexture" -#define LOG_NDEBUG 1 - -#include "config.h" -#include "TileTexture.h" - -#include "AndroidLog.h" -#include "Tile.h" -#include "ClassTracker.h" -#include "DrawQuadData.h" -#include "GLUtils.h" -#include "GLWebViewState.h" -#include "TextureOwner.h" -#include "TilesManager.h" - -namespace WebCore { - -TileTexture::TileTexture(uint32_t w, uint32_t h) - : m_owner(0) - , m_isPureColor(false) -{ - m_size.set(w, h); - m_ownTextureId = 0; - -#ifdef DEBUG_COUNT - ClassTracker::instance()->increment("TileTexture"); -#endif -} - -TileTexture::~TileTexture() -{ -#ifdef DEBUG_COUNT - ClassTracker::instance()->decrement("TileTexture"); -#endif -} - -void TileTexture::requireGLTexture() -{ - if (!m_ownTextureId) - m_ownTextureId = GLUtils::createTileGLTexture(m_size.width(), m_size.height()); -} - -void TileTexture::discardGLTexture() -{ - if (m_ownTextureId) - GLUtils::deleteTexture(&m_ownTextureId); - - if (m_owner) { - // clear both Tile->Texture and Texture->Tile links - m_owner->removeTexture(this); - release(m_owner); - } -} - -bool TileTexture::acquire(TextureOwner* owner, bool force) -{ - if (m_owner == owner) - return true; - - return setOwner(owner, force); -} - -bool TileTexture::setOwner(TextureOwner* owner, bool force) -{ - bool proceed = true; - if (m_owner && m_owner != owner) - proceed = m_owner->removeTexture(this); - - if (proceed) { - m_owner = owner; - return true; - } - - return false; -} - -bool TileTexture::release(TextureOwner* owner) -{ - ALOGV("texture %p releasing tile %p, m_owner %p", this, owner, m_owner); - if (m_owner != owner) - return false; - - m_owner = 0; - return true; -} - -void TileTexture::transferComplete() -{ - if (m_owner) { - Tile* owner = static_cast(m_owner); - owner->backTextureTransfer(); - } else - ALOGE("ERROR: owner missing after transfer of texture %p", this); -} - -void TileTexture::drawGL(bool isLayer, const SkRect& rect, float opacity, - const TransformationMatrix* transform, - bool forceBlending) -{ - ShaderProgram* shader = TilesManager::instance()->shader(); - - if (isLayer && !transform) { - ALOGE("ERROR: Missing tranform for layers!"); - return; - } - - // For base layer, we just follow the forceBlending, otherwise, blending is - // always turned on. - // TODO: Don't blend tiles if they are fully opaque. - forceBlending |= isLayer; - DrawQuadData commonData(isLayer ? LayerQuad : BaseQuad, transform, &rect, - opacity, forceBlending); - if (isPureColor()) { - PureColorQuadData data(commonData, pureColor()); - shader->drawQuad(&data); - } else { - TextureQuadData data(commonData, m_ownTextureId, GL_TEXTURE_2D, GL_LINEAR); - shader->drawQuad(&data); - } -} - -} // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/TileTexture.h b/Source/WebCore/platform/graphics/android/TileTexture.h deleted file mode 100644 index 5fe43b0..0000000 --- a/Source/WebCore/platform/graphics/android/TileTexture.h +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright 2010, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef TileTexture_h -#define TileTexture_h - -#include "TextureInfo.h" -#include "Color.h" -#include "SkBitmap.h" -#include "SkRect.h" -#include "SkSize.h" - -#include - -class SkCanvas; - -namespace WebCore { - -class TextureOwner; -class Tile; -class TransformationMatrix; - -class TileTexture { -public: - // This object is to be constructed on the consumer's thread and must have - // a width and height greater than 0. - TileTexture(uint32_t w, uint32_t h); - virtual ~TileTexture(); - - // allows consumer thread to assign ownership of the texture to the tile. It - // returns false if ownership cannot be transferred because the tile is busy - bool acquire(TextureOwner* owner, bool force = false); - bool release(TextureOwner* owner); - - // set the texture owner if not busy. Return false if busy, true otherwise. - bool setOwner(TextureOwner* owner, bool force = false); - - // private member accessor functions - TextureOwner* owner() { return m_owner; } // only used by the consumer thread - - const SkSize& getSize() const { return m_size; } - - // OpenGL ID of backing texture, 0 when not allocated - GLuint m_ownTextureId; - // these are used for dynamically (de)allocating backing graphics memory - void requireGLTexture(); - void discardGLTexture(); - - void transferComplete(); - - TextureInfo* getTextureInfo() { return &m_ownTextureInfo; } - - // Make sure the following pureColor getter/setter are only read/written - // in UI thread. Therefore no need for a lock. - void setPure(bool pure) { m_isPureColor = pure; } - bool isPureColor() {return m_isPureColor; } - void setPureColor(const Color& color) { m_pureColor = color; setPure(true); } - Color pureColor() { return m_pureColor; } - - void drawGL(bool isLayer, const SkRect& rect, float opacity, - const TransformationMatrix* transform, bool forceBlending = false); -private: - TextureInfo m_ownTextureInfo; - SkSize m_size; - - // Tile owning the texture, only modified by UI thread - TextureOwner* m_owner; - - // When the whole tile is single color, skip the transfer queue and draw - // it directly through shader. - bool m_isPureColor; - Color m_pureColor; -}; - -} // namespace WebCore - -#endif // TileTexture_h diff --git a/Source/WebCore/platform/graphics/android/TilesManager.cpp b/Source/WebCore/platform/graphics/android/TilesManager.cpp deleted file mode 100644 index e8b8cd1..0000000 --- a/Source/WebCore/platform/graphics/android/TilesManager.cpp +++ /dev/null @@ -1,449 +0,0 @@ -/* - * Copyright 2010, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#define LOG_TAG "TilesManager" -#define LOG_NDEBUG 1 - -#include "config.h" -#include "TilesManager.h" - -#if USE(ACCELERATED_COMPOSITING) - -#include "AndroidLog.h" -#include "GLWebViewState.h" -#include "SkCanvas.h" -#include "SkDevice.h" -#include "SkPaint.h" -#include "Tile.h" -#include "TileTexture.h" -#include "TransferQueue.h" - -#include -#include -#include -#include -#include - -// Important: We need at least twice as many textures as is needed to cover -// one viewport, otherwise the allocation may stall. -// We need n textures for one TiledPage, and another n textures for the -// second page used when scaling. -// In our case, we use 256*256 textures. On the tablet, this equates to -// at least 60 textures, or 112 with expanded tile boundaries. -// 112(tiles)*256*256*4(bpp)*2(pages) = 56MB -// It turns out the viewport dependent value m_maxTextureCount is a reasonable -// number to cap the layer tile texturs, it worked on both phones and tablets. -// TODO: after merge the pool of base tiles and layer tiles, we should revisit -// the logic of allocation management. -#define MAX_TEXTURE_ALLOCATION ((6+TILE_PREFETCH_DISTANCE*2)*(5+TILE_PREFETCH_DISTANCE*2)*4) -#define TILE_WIDTH 256 -#define TILE_HEIGHT 256 - -#define BYTES_PER_PIXEL 4 // 8888 config - -#define LAYER_TEXTURES_DESTROY_TIMEOUT 60 // If we do not need layers for 60 seconds, free the textures - -namespace WebCore { - -GLint TilesManager::getMaxTextureSize() -{ - static GLint maxTextureSize = 0; - if (!maxTextureSize) - glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize); - return maxTextureSize; -} - -int TilesManager::getMaxTextureAllocation() -{ - return MAX_TEXTURE_ALLOCATION; -} - -TilesManager::TilesManager() - : m_layerTexturesRemain(true) - , m_highEndGfx(false) - , m_maxTextureCount(0) - , m_maxLayerTextureCount(0) - , m_generatorReady(false) - , m_showVisualIndicator(false) - , m_invertedScreen(false) - , m_useMinimalMemory(true) - , m_useDoubleBuffering(true) - , m_contentUpdates(0) - , m_webkitContentUpdates(0) - , m_queue(0) - , m_drawGLCount(1) - , m_lastTimeLayersUsed(0) - , m_hasLayerTextures(false) -{ - ALOGV("TilesManager ctor"); - m_textures.reserveCapacity(MAX_TEXTURE_ALLOCATION); - m_availableTextures.reserveCapacity(MAX_TEXTURE_ALLOCATION); - m_tilesTextures.reserveCapacity(MAX_TEXTURE_ALLOCATION); - m_availableTilesTextures.reserveCapacity(MAX_TEXTURE_ALLOCATION); - m_pixmapsGenerationThread = new TexturesGenerator(this); - m_pixmapsGenerationThread->run("TexturesGenerator"); -} - -void TilesManager::allocateTiles() -{ - int nbTexturesToAllocate = m_maxTextureCount - m_textures.size(); - ALOGV("%d tiles to allocate (%d textures planned)", nbTexturesToAllocate, m_maxTextureCount); - int nbTexturesAllocated = 0; - for (int i = 0; i < nbTexturesToAllocate; i++) { - TileTexture* texture = new TileTexture( - tileWidth(), tileHeight()); - // the atomic load ensures that the texture has been fully initialized - // before we pass a pointer for other threads to operate on - TileTexture* loadedTexture = - reinterpret_cast( - android_atomic_acquire_load(reinterpret_cast(&texture))); - m_textures.append(loadedTexture); - nbTexturesAllocated++; - } - - int nbLayersTexturesToAllocate = m_maxLayerTextureCount - m_tilesTextures.size(); - ALOGV("%d layers tiles to allocate (%d textures planned)", - nbLayersTexturesToAllocate, m_maxLayerTextureCount); - int nbLayersTexturesAllocated = 0; - for (int i = 0; i < nbLayersTexturesToAllocate; i++) { - TileTexture* texture = new TileTexture( - tileWidth(), tileHeight()); - // the atomic load ensures that the texture has been fully initialized - // before we pass a pointer for other threads to operate on - TileTexture* loadedTexture = - reinterpret_cast( - android_atomic_acquire_load(reinterpret_cast(&texture))); - m_tilesTextures.append(loadedTexture); - nbLayersTexturesAllocated++; - } - ALOGV("allocated %d textures for base (total: %d, %d Mb), %d textures for layers (total: %d, %d Mb)", - nbTexturesAllocated, m_textures.size(), - m_textures.size() * TILE_WIDTH * TILE_HEIGHT * 4 / 1024 / 1024, - nbLayersTexturesAllocated, m_tilesTextures.size(), - m_tilesTextures.size() * tileWidth() * tileHeight() * 4 / 1024 / 1024); -} - -void TilesManager::discardTextures(bool allTextures, bool glTextures) -{ - const unsigned int max = m_textures.size(); - - unsigned long long sparedDrawCount = ~0; // by default, spare no textures - if (!allTextures) { - // if we're not deallocating all textures, spare those with max drawcount - sparedDrawCount = 0; - for (unsigned int i = 0; i < max; i++) { - TextureOwner* owner = m_textures[i]->owner(); - if (owner) - sparedDrawCount = std::max(sparedDrawCount, owner->drawCount()); - } - } - discardTexturesVector(sparedDrawCount, m_textures, glTextures); - discardTexturesVector(sparedDrawCount, m_tilesTextures, glTextures); -} - -void TilesManager::discardTexturesVector(unsigned long long sparedDrawCount, - WTF::Vector& textures, - bool deallocateGLTextures) -{ - const unsigned int max = textures.size(); - int dealloc = 0; - WTF::Vector discardedIndex; - for (unsigned int i = 0; i < max; i++) { - TextureOwner* owner = textures[i]->owner(); - if (!owner || owner->drawCount() < sparedDrawCount) { - if (deallocateGLTextures) { - // deallocate textures' gl memory - textures[i]->discardGLTexture(); - discardedIndex.append(i); - } else if (owner) { - // simply detach textures from owner - static_cast(owner)->discardTextures(); - } - dealloc++; - } - } - - bool base = textures == m_textures; - // Clean up the vector of TileTextures and reset the max texture count. - if (discardedIndex.size()) { - android::Mutex::Autolock lock(m_texturesLock); - for (int i = discardedIndex.size() - 1; i >= 0; i--) - textures.remove(discardedIndex[i]); - - int remainedTextureNumber = textures.size(); - int* countPtr = base ? &m_maxTextureCount : &m_maxLayerTextureCount; - if (remainedTextureNumber < *countPtr) { - ALOGV("reset maxTextureCount for %s tiles from %d to %d", - base ? "base" : "layer", *countPtr, remainedTextureNumber); - *countPtr = remainedTextureNumber; - } - - } - - ALOGV("Discarded %d %s textures (out of %d %s tiles)", - dealloc, (deallocateGLTextures ? "gl" : ""), - max, base ? "base" : "layer"); -} - -void TilesManager::gatherTexturesNumbers(int* nbTextures, int* nbAllocatedTextures, - int* nbLayerTextures, int* nbAllocatedLayerTextures) -{ - *nbTextures = m_textures.size(); - for (unsigned int i = 0; i < m_textures.size(); i++) { - TileTexture* texture = m_textures[i]; - if (texture->m_ownTextureId) - *nbAllocatedTextures += 1; - } - *nbLayerTextures = m_tilesTextures.size(); - for (unsigned int i = 0; i < m_tilesTextures.size(); i++) { - TileTexture* texture = m_tilesTextures[i]; - if (texture->m_ownTextureId) - *nbAllocatedLayerTextures += 1; - } -} - -void TilesManager::printTextures() -{ -#ifdef DEBUG - ALOGV("++++++"); - for (unsigned int i = 0; i < m_textures.size(); i++) { - TileTexture* texture = m_textures[i]; - Tile* o = 0; - if (texture->owner()) - o = (Tile*) texture->owner(); - int x = -1; - int y = -1; - if (o) { - x = o->x(); - y = o->y(); - } - ALOGV("[%d] texture %x owner: %x (%d, %d) scale: %.2f", - i, texture, o, x, y, o ? o->scale() : 0); - } - ALOGV("------"); -#endif // DEBUG -} - -void TilesManager::gatherTextures() -{ - android::Mutex::Autolock lock(m_texturesLock); - m_availableTextures = m_textures; - m_availableTilesTextures = m_tilesTextures; - m_layerTexturesRemain = true; -} - -TileTexture* TilesManager::getAvailableTexture(Tile* owner) -{ - android::Mutex::Autolock lock(m_texturesLock); - - // Sanity check that the tile does not already own a texture - if (owner->backTexture() && owner->backTexture()->owner() == owner) { - ALOGV("same owner (%d, %d), getAvailableBackTexture(%x) => texture %x", - owner->x(), owner->y(), owner, owner->backTexture()); - if (owner->isLayerTile()) - m_availableTilesTextures.remove(m_availableTilesTextures.find(owner->backTexture())); - else - m_availableTextures.remove(m_availableTextures.find(owner->backTexture())); - return owner->backTexture(); - } - - WTF::Vector* availableTexturePool; - if (owner->isLayerTile()) { - availableTexturePool = &m_availableTilesTextures; - } else { - availableTexturePool = &m_availableTextures; - } - - // The heuristic for selecting a texture is as follows: - // 1. Skip textures currently being painted, they can't be painted while - // busy anyway - // 2. If a tile isn't owned, break with that one - // 3. Don't let tiles acquire their front textures - // 4. Otherwise, use the least recently prepared tile, but ignoring tiles - // drawn in the last frame to avoid flickering - - TileTexture* farthestTexture = 0; - unsigned long long oldestDrawCount = getDrawGLCount() - 1; - const unsigned int max = availableTexturePool->size(); - for (unsigned int i = 0; i < max; i++) { - TileTexture* texture = (*availableTexturePool)[i]; - Tile* currentOwner = static_cast(texture->owner()); - if (!currentOwner) { - // unused texture! take it! - farthestTexture = texture; - break; - } - - if (currentOwner == owner) { - // Don't let a tile acquire its own front texture, as the - // acquisition logic doesn't handle that - continue; - } - - unsigned long long textureDrawCount = currentOwner->drawCount(); - if (oldestDrawCount > textureDrawCount) { - farthestTexture = texture; - oldestDrawCount = textureDrawCount; - } - } - - if (farthestTexture) { - Tile* previousOwner = static_cast(farthestTexture->owner()); - if (farthestTexture->acquire(owner)) { - if (previousOwner) { - previousOwner->removeTexture(farthestTexture); - - ALOGV("%s texture %p stolen from tile %d, %d for %d, %d, drawCount was %llu (now %llu)", - owner->isLayerTile() ? "LAYER" : "BASE", - farthestTexture, previousOwner->x(), previousOwner->y(), - owner->x(), owner->y(), - oldestDrawCount, getDrawGLCount()); - } - - availableTexturePool->remove(availableTexturePool->find(farthestTexture)); - return farthestTexture; - } - } else { - if (owner->isLayerTile()) { - // couldn't find a tile for a layer, layers shouldn't request redraw - // TODO: once we do layer prefetching, don't set this for those - // tiles - m_layerTexturesRemain = false; - } - } - - ALOGV("Couldn't find an available texture for %s tile %x (%d, %d) out of %d available", - owner->isLayerTile() ? "LAYER" : "BASE", - owner, owner->x(), owner->y(), max); -#ifdef DEBUG - printTextures(); -#endif // DEBUG - return 0; -} - -void TilesManager::setHighEndGfx(bool highEnd) -{ - m_highEndGfx = highEnd; -} - -bool TilesManager::highEndGfx() -{ - return m_highEndGfx; -} - -int TilesManager::maxTextureCount() -{ - android::Mutex::Autolock lock(m_texturesLock); - return m_maxTextureCount; -} - -int TilesManager::maxLayerTextureCount() -{ - android::Mutex::Autolock lock(m_texturesLock); - return m_maxLayerTextureCount; -} - -void TilesManager::setMaxTextureCount(int max) -{ - ALOGV("setMaxTextureCount: %d (current: %d, total:%d)", - max, m_maxTextureCount, MAX_TEXTURE_ALLOCATION); - if (m_maxTextureCount == MAX_TEXTURE_ALLOCATION || - max <= m_maxTextureCount) - return; - - android::Mutex::Autolock lock(m_texturesLock); - - if (max < MAX_TEXTURE_ALLOCATION) - m_maxTextureCount = max; - else - m_maxTextureCount = MAX_TEXTURE_ALLOCATION; - - allocateTiles(); -} - -void TilesManager::setMaxLayerTextureCount(int max) -{ - ALOGV("setMaxLayerTextureCount: %d (current: %d, total:%d)", - max, m_maxLayerTextureCount, MAX_TEXTURE_ALLOCATION); - if (!max && m_hasLayerTextures) { - double secondsSinceLayersUsed = WTF::currentTime() - m_lastTimeLayersUsed; - if (secondsSinceLayersUsed > LAYER_TEXTURES_DESTROY_TIMEOUT) { - unsigned long long sparedDrawCount = ~0; // by default, spare no textures - bool deleteGLTextures = true; - discardTexturesVector(sparedDrawCount, m_tilesTextures, deleteGLTextures); - m_hasLayerTextures = false; - } - return; - } - m_lastTimeLayersUsed = WTF::currentTime(); - if (m_maxLayerTextureCount == MAX_TEXTURE_ALLOCATION || - max <= m_maxLayerTextureCount) - return; - - android::Mutex::Autolock lock(m_texturesLock); - - if (max < MAX_TEXTURE_ALLOCATION) - m_maxLayerTextureCount = max; - else - m_maxLayerTextureCount = MAX_TEXTURE_ALLOCATION; - - allocateTiles(); - m_hasLayerTextures = true; -} - -TransferQueue* TilesManager::transferQueue() -{ - // m_queue will be created on the UI thread, although it may - // be accessed from the TexturesGenerator. However, that can only happen after - // a previous transferQueue() call due to a prepare. - if (!m_queue) - m_queue = new TransferQueue(m_useMinimalMemory); - return m_queue; -} - -float TilesManager::tileWidth() -{ - return TILE_WIDTH; -} - -float TilesManager::tileHeight() -{ - return TILE_HEIGHT; -} - -TilesManager* TilesManager::instance() -{ - if (!gInstance) { - gInstance = new TilesManager(); - ALOGV("instance(), new gInstance is %x", gInstance); - } - return gInstance; -} - -TilesManager* TilesManager::gInstance = 0; - -} // namespace WebCore - -#endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/android/TilesManager.h b/Source/WebCore/platform/graphics/android/TilesManager.h deleted file mode 100644 index 92c56d3..0000000 --- a/Source/WebCore/platform/graphics/android/TilesManager.h +++ /dev/null @@ -1,209 +0,0 @@ -/* - * Copyright 2010, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef TilesManager_h -#define TilesManager_h - -#if USE(ACCELERATED_COMPOSITING) - -#include "LayerAndroid.h" -#include "ShaderProgram.h" -#include "TexturesGenerator.h" -#include "TilesProfiler.h" -#include "VideoLayerManager.h" -#include -#include - -namespace WebCore { - -class OperationFilter; -class Tile; -class TileTexture; -class TransferQueue; - -class TilesManager { -public: - // May only be called from the UI thread - static TilesManager* instance(); - static GLint getMaxTextureSize(); - static int getMaxTextureAllocation(); - - static bool hardwareAccelerationEnabled() - { - return gInstance != 0; - } - - void removeOperationsForFilter(OperationFilter* filter, bool waitForRunning = false) - { - m_pixmapsGenerationThread->removeOperationsForFilter(filter, waitForRunning); - } - - void scheduleOperation(QueuedOperation* operation) - { - m_pixmapsGenerationThread->scheduleOperation(operation); - } - - ShaderProgram* shader() { return &m_shader; } - TransferQueue* transferQueue(); - VideoLayerManager* videoLayerManager() { return &m_videoLayerManager; } - - void gatherTextures(); - bool layerTexturesRemain() { return m_layerTexturesRemain; } - void gatherTexturesNumbers(int* nbTextures, int* nbAllocatedTextures, - int* nbLayerTextures, int* nbAllocatedLayerTextures); - - TileTexture* getAvailableTexture(Tile* owner); - - void printTextures(); - - // m_highEndGfx is written/read only on UI thread, no need for a lock. - void setHighEndGfx(bool highEnd); - bool highEndGfx(); - - int maxTextureCount(); - int maxLayerTextureCount(); - void setMaxTextureCount(int max); - void setMaxLayerTextureCount(int max); - static float tileWidth(); - static float tileHeight(); - - void allocateTiles(); - - // remove all tiles from textures (and optionally deallocate gl memory) - void discardTextures(bool allTextures, bool glTextures); - - bool getShowVisualIndicator() - { - return m_showVisualIndicator; - } - - void setShowVisualIndicator(bool showVisualIndicator) - { - m_showVisualIndicator = showVisualIndicator; - } - - TilesProfiler* getProfiler() - { - return &m_profiler; - } - - bool invertedScreen() - { - return m_invertedScreen; - } - - void setInvertedScreen(bool invert) - { - m_invertedScreen = invert; - } - - void setInvertedScreenContrast(float contrast) - { - m_shader.setContrast(contrast); - } - - void setUseMinimalMemory(bool useMinimalMemory) - { - m_useMinimalMemory = useMinimalMemory; - } - - bool useMinimalMemory() - { - return m_useMinimalMemory; - } - - void setUseDoubleBuffering(bool useDoubleBuffering) - { - m_useDoubleBuffering = useDoubleBuffering; - } - bool useDoubleBuffering() { return m_useDoubleBuffering; } - - - unsigned int incWebkitContentUpdates() { return m_webkitContentUpdates++; } - - void incContentUpdates() { m_contentUpdates++; } - unsigned int getContentUpdates() { return m_contentUpdates; } - void clearContentUpdates() { m_contentUpdates = 0; } - - void incDrawGLCount() - { - m_drawGLCount++; - } - - unsigned long long getDrawGLCount() - { - return m_drawGLCount; - } - -private: - TilesManager(); - - void discardTexturesVector(unsigned long long sparedDrawCount, - WTF::Vector& textures, - bool deallocateGLTextures); - - WTF::Vector m_textures; - WTF::Vector m_availableTextures; - - WTF::Vector m_tilesTextures; - WTF::Vector m_availableTilesTextures; - bool m_layerTexturesRemain; - - bool m_highEndGfx; - int m_maxTextureCount; - int m_maxLayerTextureCount; - - bool m_generatorReady; - - bool m_showVisualIndicator; - bool m_invertedScreen; - - bool m_useMinimalMemory; - - bool m_useDoubleBuffering; - unsigned int m_contentUpdates; // nr of successful tiled paints - unsigned int m_webkitContentUpdates; // nr of paints from webkit - - sp m_pixmapsGenerationThread; - - android::Mutex m_texturesLock; - - static TilesManager* gInstance; - - ShaderProgram m_shader; - TransferQueue* m_queue; - - VideoLayerManager m_videoLayerManager; - - TilesProfiler m_profiler; - unsigned long long m_drawGLCount; - double m_lastTimeLayersUsed; - bool m_hasLayerTextures; -}; - -} // namespace WebCore - -#endif // USE(ACCELERATED_COMPOSITING) -#endif // TilesManager_h diff --git a/Source/WebCore/platform/graphics/android/TilesProfiler.cpp b/Source/WebCore/platform/graphics/android/TilesProfiler.cpp deleted file mode 100644 index 4f0c6b5..0000000 --- a/Source/WebCore/platform/graphics/android/TilesProfiler.cpp +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright 2010, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#define LOG_TAG "TilesProfiler" -#define LOG_NDEBUG 1 - -#include "config.h" -#include "TilesProfiler.h" - -#if USE(ACCELERATED_COMPOSITING) - -#include "AndroidLog.h" -#include "Tile.h" -#include "TilesManager.h" -#include - -// Hard limit on amount of frames (and thus memory) profiling can take -#define MAX_PROF_FRAMES 400 -#define INVAL_CODE -2 - -namespace WebCore { -TilesProfiler::TilesProfiler() - : m_enabled(false) -{ -} - -void TilesProfiler::start() -{ - m_enabled = true; - m_goodTiles = 0; - m_badTiles = 0; - m_records.clear(); - m_time = currentTimeMS(); - ALOGV("initializing tileprofiling"); -} - -float TilesProfiler::stop() -{ - m_enabled = false; - ALOGV("completed tile profiling, observed %d frames", m_records.size()); - return (1.0 * m_goodTiles) / (m_goodTiles + m_badTiles); -} - -void TilesProfiler::clear() -{ - ALOGV("clearing tile profiling of its %d frames", m_records.size()); - m_records.clear(); -} - -void TilesProfiler::nextFrame(int left, int top, int right, int bottom, float scale) -{ - if (!m_enabled || (m_records.size() > MAX_PROF_FRAMES)) - return; - - double currentTime = currentTimeMS(); - double timeDelta = currentTime - m_time; - m_time = currentTime; - -#ifdef DEBUG - if (m_records.size() != 0) { - ALOGD("completed tile profiling frame, observed %d tiles. %f ms since last", - m_records[0].size(), timeDelta); - } -#endif // DEBUG - - m_records.append(WTF::Vector()); - - //first record designates viewport - m_records.last().append(TileProfileRecord( - left, top, right, bottom, - scale, true, (int)(timeDelta * 1000))); -} - -void TilesProfiler::nextTile(Tile* tile, float scale, bool inView) -{ - if (!m_enabled || (m_records.size() > MAX_PROF_FRAMES) || (m_records.size() == 0)) - return; - - bool isReady = tile->isTileReady(); - int left = tile->x() * TilesManager::tileWidth(); - int top = tile->y() * TilesManager::tileWidth(); - int right = left + TilesManager::tileWidth(); - int bottom = top + TilesManager::tileWidth(); - - if (inView) { - if (isReady) - m_goodTiles++; - else - m_badTiles++; - } - m_records.last().append(TileProfileRecord( - left, top, right, bottom, - scale, isReady, (int)tile->drawCount())); - ALOGV("adding tile %d %d %d %d, scale %f", left, top, right, bottom, scale); -} - -void TilesProfiler::nextInval(const SkIRect& rect, float scale) -{ - if (!m_enabled || (m_records.size() > MAX_PROF_FRAMES) || (m_records.size() == 0)) - return; - - m_records.last().append(TileProfileRecord( - rect.x(), rect.y(), - rect.right(), rect.bottom(), scale, false, INVAL_CODE)); - ALOGV("adding inval region %d %d %d %d, scale %f", rect.x(), rect.y(), - rect.right(), rect.bottom(), scale); -} - -} // namespace WebCore - -#endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/android/TilesProfiler.h b/Source/WebCore/platform/graphics/android/TilesProfiler.h deleted file mode 100644 index b39ae2f..0000000 --- a/Source/WebCore/platform/graphics/android/TilesProfiler.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright 2011, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef TilesProfiler_h -#define TilesProfiler_h - -#if USE(ACCELERATED_COMPOSITING) - -#include "IntRect.h" -#include "SkRect.h" -#include - -namespace WebCore { - -class Tile; - -struct TileProfileRecord { - TileProfileRecord(int left, int top, int right, int bottom, float scale, int isReady, int level) { - this->left = left; - this->top = top; - this->right = right; - this->bottom = bottom; - this->scale = scale; - this->isReady = isReady; - this->level = level; - } - int left, top, right, bottom; - bool isReady; - int level; - float scale; -}; - -class TilesProfiler { -public: - TilesProfiler(); - - void start(); - float stop(); - void clear(); - void nextFrame(int left, int top, int right, int bottom, float scale); - void nextTile(Tile* tile, float scale, bool inView); - void nextInval(const SkIRect& rect, float scale); - int numFrames() { - return m_records.size(); - }; - - int numTilesInFrame(int frame) { - return m_records[frame].size(); - } - - TileProfileRecord* getTile(int frame, int tile) { - return &m_records[frame][tile]; - } - - bool enabled() { return m_enabled; } - -private: - bool m_enabled; - unsigned int m_goodTiles; - unsigned int m_badTiles; - WTF::Vector > m_records; - double m_time; -}; - -} // namespace WebCore - -#endif // USE(ACCELERATED_COMPOSITING) -#endif // TilesProfiler_h diff --git a/Source/WebCore/platform/graphics/android/TransferQueue.cpp b/Source/WebCore/platform/graphics/android/TransferQueue.cpp deleted file mode 100644 index ec0d9e7..0000000 --- a/Source/WebCore/platform/graphics/android/TransferQueue.cpp +++ /dev/null @@ -1,644 +0,0 @@ -/* - * Copyright 2011, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#define LOG_TAG "TransferQueue" -#define LOG_NDEBUG 1 - -#include "config.h" -#include "TransferQueue.h" - -#if USE(ACCELERATED_COMPOSITING) - -#include "AndroidLog.h" -#include "DrawQuadData.h" -#include "GLUtils.h" -#include "Tile.h" -#include "TileTexture.h" -#include "TilesManager.h" -#include -#include -#include - -// For simple webView usage, MINIMAL_SIZE is recommended for memory saving. -// In browser case, EFFICIENT_SIZE is preferred. -#define MINIMAL_SIZE 1 -#define EFFICIENT_SIZE 6 - -// Set this to 1 if we would like to take the new GpuUpload approach which -// relied on the glCopyTexSubImage2D instead of a glDraw call -#define GPU_UPLOAD_WITHOUT_DRAW 1 - -namespace WebCore { - -TransferQueue::TransferQueue(bool useMinimalMem) - : m_eglSurface(EGL_NO_SURFACE) - , m_transferQueueIndex(0) - , m_fboID(0) - , m_sharedSurfaceTextureId(0) - , m_hasGLContext(true) - , m_interruptedByRemovingOp(false) - , m_currentDisplay(EGL_NO_DISPLAY) - , m_currentUploadType(DEFAULT_UPLOAD_TYPE) -{ - memset(&m_GLStateBeforeBlit, 0, sizeof(m_GLStateBeforeBlit)); - m_transferQueueSize = useMinimalMem ? MINIMAL_SIZE : EFFICIENT_SIZE; - m_emptyItemCount = m_transferQueueSize; - m_transferQueue = new TileTransferData[m_transferQueueSize]; -} - -TransferQueue::~TransferQueue() -{ - android::Mutex::Autolock lock(m_transferQueueItemLocks); - cleanupGLResources(); - delete[] m_transferQueue; -} - -// This should be called within the m_transferQueueItemLocks. -// Now only called by emptyQueue() and destructor. -void TransferQueue::cleanupGLResources() -{ - if (m_sharedSurfaceTexture.get()) { - m_sharedSurfaceTexture->abandon(); - m_sharedSurfaceTexture.clear(); - } - if (m_fboID) { - glDeleteFramebuffers(1, &m_fboID); - m_fboID = 0; - } - if (m_sharedSurfaceTextureId) { - glDeleteTextures(1, &m_sharedSurfaceTextureId); - m_sharedSurfaceTextureId = 0; - } -} - -void TransferQueue::initGLResources(int width, int height) -{ - android::Mutex::Autolock lock(m_transferQueueItemLocks); - if (!m_sharedSurfaceTextureId) { - glGenTextures(1, &m_sharedSurfaceTextureId); - sp bufferQueue(new BufferQueue(true)); - m_sharedSurfaceTexture = -#if GPU_UPLOAD_WITHOUT_DRAW - new android::SurfaceTexture(m_sharedSurfaceTextureId, true, - GL_TEXTURE_2D, false, bufferQueue); -#else - new android::SurfaceTexture(m_sharedSurfaceTextureId, true, - GL_TEXTURE_EXTERNAL_OES, true, - bufferQueue); -#endif - m_ANW = new android::SurfaceTextureClient(m_sharedSurfaceTexture); - m_sharedSurfaceTexture->setSynchronousMode(true); - - int extraBuffersNeeded = 0; - m_ANW->query(m_ANW.get(), NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, - &extraBuffersNeeded); - bufferQueue->setBufferCount(m_transferQueueSize + extraBuffersNeeded); - - int result = native_window_set_buffers_geometry(m_ANW.get(), - width, height, HAL_PIXEL_FORMAT_RGBA_8888); - GLUtils::checkSurfaceTextureError("native_window_set_buffers_geometry", result); - result = native_window_set_usage(m_ANW.get(), - GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN); - GLUtils::checkSurfaceTextureError("native_window_set_usage", result); - } - - if (!m_fboID) - glGenFramebuffers(1, &m_fboID); -} - -// When bliting, if the item from the transfer queue is mismatching b/t the -// Tile and the content, then the item is considered as obsolete, and -// the content is discarded. -bool TransferQueue::checkObsolete(const TileTransferData* data) -{ - Tile* baseTilePtr = data->savedTilePtr; - if (!baseTilePtr) { - ALOGV("Invalid savedTilePtr , such that the tile is obsolete"); - return true; - } - - TileTexture* baseTileTexture = baseTilePtr->backTexture(); - if (!baseTileTexture || baseTileTexture != data->savedTileTexturePtr) { - ALOGV("Invalid baseTileTexture %p (vs expected %p), such that the tile is obsolete", - baseTileTexture, data->savedTileTexturePtr); - return true; - } - - return false; -} - -void TransferQueue::blitTileFromQueue(GLuint fboID, TileTexture* destTex, - TileTexture* frontTex, - GLuint srcTexId, GLenum srcTexTarget, - int index) -{ -#if GPU_UPLOAD_WITHOUT_DRAW - glBindFramebuffer(GL_FRAMEBUFFER, fboID); - glBindTexture(GL_TEXTURE_2D, destTex->m_ownTextureId); - - int textureWidth = destTex->getSize().width(); - int textureHeight = destTex->getSize().height(); - - IntRect inval = m_transferQueue[index].invalRect; - bool partialInval = !inval.isEmpty(); - - if (partialInval && frontTex) { - // recopy the previous texture to the new one, as - // the partial update will not cover the entire texture - glFramebufferTexture2D(GL_FRAMEBUFFER, - GL_COLOR_ATTACHMENT0, - GL_TEXTURE_2D, - frontTex->m_ownTextureId, - 0); - glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, - textureWidth, textureHeight); - } - - glFramebufferTexture2D(GL_FRAMEBUFFER, - GL_COLOR_ATTACHMENT0, - GL_TEXTURE_2D, - srcTexId, - 0); - - if (!partialInval) { - glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, - textureWidth, textureHeight); - } else { - glCopyTexSubImage2D(GL_TEXTURE_2D, 0, inval.x(), inval.y(), 0, 0, - inval.width(), inval.height()); - } - -#else - // Then set up the FBO and copy the SurfTex content in. - glBindFramebuffer(GL_FRAMEBUFFER, fboID); - glFramebufferTexture2D(GL_FRAMEBUFFER, - GL_COLOR_ATTACHMENT0, - GL_TEXTURE_2D, - destTex->m_ownTextureId, - 0); - setGLStateForCopy(destTex->getSize().width(), - destTex->getSize().height()); - GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); - if (status != GL_FRAMEBUFFER_COMPLETE) { - ALOGV("Error: glCheckFramebufferStatus failed"); - glBindFramebuffer(GL_FRAMEBUFFER, 0); - return; - } - - // Use empty rect to set up the special matrix to draw. - SkRect rect = SkRect::MakeEmpty(); - - TextureQuadData data(srcTexId, GL_NEAREST, srcTexTarget, Blit, 0, 0, 1.0, false); - TilesManager::instance()->shader()->drawQuad(&data); - - // To workaround a sync issue on some platforms, we should insert the sync - // here while in the current FBO. - // This will essentially kick off the GPU command buffer, and the Tex Gen - // thread will then have to wait for this buffer to finish before writing - // into the same memory. - EGLDisplay dpy = eglGetCurrentDisplay(); - if (m_currentDisplay != dpy) - m_currentDisplay = dpy; - if (m_currentDisplay != EGL_NO_DISPLAY) { - if (m_transferQueue[index].m_syncKHR != EGL_NO_SYNC_KHR) - eglDestroySyncKHR(m_currentDisplay, m_transferQueue[index].m_syncKHR); - m_transferQueue[index].m_syncKHR = eglCreateSyncKHR(m_currentDisplay, - EGL_SYNC_FENCE_KHR, - 0); - } - GLUtils::checkEglError("CreateSyncKHR"); -#endif -} - -void TransferQueue::interruptTransferQueue(bool interrupt) -{ - m_transferQueueItemLocks.lock(); - m_interruptedByRemovingOp = interrupt; - if (m_interruptedByRemovingOp) - m_transferQueueItemCond.signal(); - m_transferQueueItemLocks.unlock(); -} - -// This function must be called inside the m_transferQueueItemLocks, for the -// wait, m_interruptedByRemovingOp and getHasGLContext(). -// Only called by updateQueueWithBitmap() for now. -bool TransferQueue::readyForUpdate() -{ - if (!getHasGLContext()) - return false; - // Don't use a while loop since when the WebView tear down, the emptyCount - // will still be 0, and we bailed out b/c of GL context lost. - if (!m_emptyItemCount) { - if (m_interruptedByRemovingOp) - return false; - m_transferQueueItemCond.wait(m_transferQueueItemLocks); - if (m_interruptedByRemovingOp) - return false; - } - - if (!getHasGLContext()) - return false; - - // Disable this wait until we figure out why this didn't work on some - // drivers b/5332112. -#if 0 - if (m_currentUploadType == GpuUpload - && m_currentDisplay != EGL_NO_DISPLAY) { - // Check the GPU fence - EGLSyncKHR syncKHR = m_transferQueue[getNextTransferQueueIndex()].m_syncKHR; - if (syncKHR != EGL_NO_SYNC_KHR) - eglClientWaitSyncKHR(m_currentDisplay, - syncKHR, - EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, - EGL_FOREVER_KHR); - } - GLUtils::checkEglError("WaitSyncKHR"); -#endif - - return true; -} - -// Both getHasGLContext and setHasGLContext should be called within the lock. -bool TransferQueue::getHasGLContext() -{ - return m_hasGLContext; -} - -void TransferQueue::setHasGLContext(bool hasContext) -{ - m_hasGLContext = hasContext; -} - -void TransferQueue::setPendingDiscardWithLock() -{ - android::Mutex::Autolock lock(m_transferQueueItemLocks); - setPendingDiscard(); -} - -void TransferQueue::emptyQueue() -{ - android::Mutex::Autolock lock(m_transferQueueItemLocks); - setPendingDiscard(); - cleanupPendingDiscard(); - cleanupGLResources(); -} - -// Set all the content in the queue to pendingDiscard, after this, there will -// be nothing added to the queue, and this can be called in any thread. -// However, in order to discard the content in the Surface Texture using -// updateTexImage, cleanupPendingDiscard need to be called on the UI thread. -// Must be called within a m_transferQueueItemLocks. -void TransferQueue::setPendingDiscard() -{ - for (int i = 0 ; i < m_transferQueueSize; i++) - if (m_transferQueue[i].status == pendingBlit) - m_transferQueue[i].status = pendingDiscard; - - m_pureColorTileQueue.clear(); - - bool GLContextExisted = getHasGLContext(); - // Unblock the Tex Gen thread first before Tile Page deletion. - // Otherwise, there will be a deadlock while removing operations. - setHasGLContext(false); - - // Only signal once when GL context lost. - if (GLContextExisted) - m_transferQueueItemCond.signal(); -} - -void TransferQueue::updatePureColorTiles() -{ - for (unsigned int i = 0 ; i < m_pureColorTileQueue.size(); i++) { - TileTransferData* data = &m_pureColorTileQueue[i]; - if (data->status == pendingBlit) { - TileTexture* destTexture = 0; - bool obsoleteTile = checkObsolete(data); - if (!obsoleteTile) { - destTexture = data->savedTilePtr->backTexture(); - destTexture->setPureColor(data->pureColor); - destTexture->transferComplete(); - } - } else if (data->status == emptyItem || data->status == pendingDiscard) { - // The queue should be clear instead of setting to different status. - ALOGV("Warning: Don't expect an emptyItem here."); - } - } - m_pureColorTileQueue.clear(); -} - -// Call on UI thread to copy from the shared Surface Texture to the Tile's texture. -void TransferQueue::updateDirtyTiles() -{ - android::Mutex::Autolock lock(m_transferQueueItemLocks); - - cleanupPendingDiscard(); - if (!getHasGLContext()) - setHasGLContext(true); - - // Check the pure color tile first, since it is simpler. - updatePureColorTiles(); - - // Start from the oldest item, we call the updateTexImage to retrive - // the texture and blit that into each Tile's texture. - const int nextItemIndex = getNextTransferQueueIndex(); - int index = nextItemIndex; - bool usedFboForUpload = false; - for (int k = 0; k < m_transferQueueSize ; k++) { - if (m_transferQueue[index].status == pendingBlit) { - bool obsoleteTile = checkObsolete(&m_transferQueue[index]); - // Save the needed info, update the Surf Tex, clean up the item in - // the queue. Then either move on to next item or copy the content. - TileTexture* destTexture = 0; - TileTexture* frontTexture = 0; - if (!obsoleteTile) { - destTexture = m_transferQueue[index].savedTilePtr->backTexture(); - // while destTexture is guaranteed to not be null, frontTexture - // might be (first transfer) - frontTexture = m_transferQueue[index].savedTilePtr->frontTexture(); - } - - if (m_transferQueue[index].uploadType == GpuUpload) { - status_t result = m_sharedSurfaceTexture->updateTexImage(); - if (result != OK) - ALOGE("unexpected error: updateTexImage return %d", result); - } - m_transferQueue[index].savedTilePtr = 0; - m_transferQueue[index].status = emptyItem; - if (obsoleteTile) { - ALOGV("Warning: the texture is obsolete for this baseTile"); - index = (index + 1) % m_transferQueueSize; - continue; - } - - // guarantee that we have a texture to blit into - destTexture->requireGLTexture(); - - if (m_transferQueue[index].uploadType == CpuUpload) { - // Here we just need to upload the bitmap content to the GL Texture - GLUtils::updateTextureWithBitmap(destTexture->m_ownTextureId, - *m_transferQueue[index].bitmap, - m_transferQueue[index].invalRect); - } else { - if (!usedFboForUpload) { - saveGLState(); - usedFboForUpload = true; - } - blitTileFromQueue(m_fboID, destTexture, frontTexture, - m_sharedSurfaceTextureId, - m_sharedSurfaceTexture->getCurrentTextureTarget(), - index); - } - - destTexture->setPure(false); - destTexture->transferComplete(); - - ALOGV("Blit tile x, y %d %d with dest texture %p to destTexture->m_ownTextureId %d", - m_transferQueue[index].savedTilePtr, - destTexture, - destTexture->m_ownTextureId); - } - index = (index + 1) % m_transferQueueSize; - } - - // Clean up FBO setup. Doing this for both CPU/GPU upload can make the - // dynamic switch possible. Moving this out from the loop can save some - // milli-seconds. - if (usedFboForUpload) { - glBindFramebuffer(GL_FRAMEBUFFER, 0); // rebind the standard FBO - restoreGLState(); - GLUtils::checkGlError("updateDirtyTiles"); - } - - m_emptyItemCount = m_transferQueueSize; - m_transferQueueItemCond.signal(); -} - -void TransferQueue::updateQueueWithBitmap(const TileRenderInfo* renderInfo, - const SkBitmap& bitmap) -{ - if (!tryUpdateQueueWithBitmap(renderInfo, bitmap)) { - // failed placing bitmap in queue, discard tile's texture so it will be - // re-enqueued (and repainted) - Tile* tile = renderInfo->baseTile; - if (tile) - tile->backTextureTransferFail(); - } -} - -bool TransferQueue::tryUpdateQueueWithBitmap(const TileRenderInfo* renderInfo, - const SkBitmap& bitmap) -{ - // This lock need to cover the full update since it is possible that queue - // will be cleaned up in the middle of this update without the lock. - // The Surface Texture will not block us since the readyForUpdate will check - // availability of the slots in the queue first. - android::Mutex::Autolock lock(m_transferQueueItemLocks); - bool ready = readyForUpdate(); - TextureUploadType currentUploadType = m_currentUploadType; - if (!ready) { - ALOGV("Quit bitmap update: not ready! for tile x y %d %d", - renderInfo->x, renderInfo->y); - return false; - } - if (currentUploadType == GpuUpload) { - // a) Dequeue the Surface Texture and write into the buffer - if (!m_ANW.get()) { - ALOGV("ERROR: ANW is null"); - return false; - } - - if (!GLUtils::updateSharedSurfaceTextureWithBitmap(m_ANW.get(), bitmap)) - return false; - } - - // b) After update the Surface Texture, now udpate the transfer queue info. - addItemInTransferQueue(renderInfo, currentUploadType, &bitmap); - - ALOGV("Bitmap updated x, y %d %d, baseTile %p", - renderInfo->x, renderInfo->y, renderInfo->baseTile); - return true; -} - -void TransferQueue::addItemInPureColorQueue(const TileRenderInfo* renderInfo) -{ - // The pure color tiles' queue will be read from UI thread and written in - // Tex Gen thread, thus we need to have a lock here. - android::Mutex::Autolock lock(m_transferQueueItemLocks); - TileTransferData data; - addItemCommon(renderInfo, GpuUpload, &data); - data.pureColor = renderInfo->pureColor; - m_pureColorTileQueue.append(data); -} - -// Translates the info from TileRenderInfo and others to TileTransferData. -// This is used by pure color tiles and normal tiles. -void TransferQueue::addItemCommon(const TileRenderInfo* renderInfo, - TextureUploadType type, - TileTransferData* data) -{ - data->savedTileTexturePtr = renderInfo->baseTile->backTexture(); - data->savedTilePtr = renderInfo->baseTile; - data->status = pendingBlit; - data->uploadType = type; - - IntRect inval(0, 0, 0, 0); - if (renderInfo->invalRect) { - inval.setX(renderInfo->invalRect->fLeft); - inval.setY(renderInfo->invalRect->fTop); - inval.setWidth(renderInfo->invalRect->width()); - inval.setHeight(renderInfo->invalRect->height()); - } - data->invalRect = inval; -} - -// Note that there should be lock/unlock around this function call. -// Currently only called by GLUtils::updateSharedSurfaceTextureWithBitmap. -void TransferQueue::addItemInTransferQueue(const TileRenderInfo* renderInfo, - TextureUploadType type, - const SkBitmap* bitmap) -{ - m_transferQueueIndex = (m_transferQueueIndex + 1) % m_transferQueueSize; - - int index = m_transferQueueIndex; - if (m_transferQueue[index].savedTilePtr - || m_transferQueue[index].status != emptyItem) { - ALOGV("ERROR update a tile which is dirty already @ index %d", index); - } - - TileTransferData* data = &m_transferQueue[index]; - addItemCommon(renderInfo, type, data); - if (type == CpuUpload && bitmap) { - // Lazily create the bitmap - if (!m_transferQueue[index].bitmap) { - m_transferQueue[index].bitmap = new SkBitmap(); - int w = bitmap->width(); - int h = bitmap->height(); - m_transferQueue[index].bitmap->setConfig(bitmap->config(), w, h); - } - bitmap->copyTo(m_transferQueue[index].bitmap, bitmap->config()); - } - - m_emptyItemCount--; -} - -void TransferQueue::setTextureUploadType(TextureUploadType type) -{ - android::Mutex::Autolock lock(m_transferQueueItemLocks); - if (m_currentUploadType == type) - return; - - setPendingDiscard(); - - m_currentUploadType = type; - ALOGD("Now we set the upload to %s", m_currentUploadType == GpuUpload ? "GpuUpload" : "CpuUpload"); -} - -// Note: this need to be called within the lock and on the UI thread. -// Only called by updateDirtyTiles() and emptyQueue() for now -void TransferQueue::cleanupPendingDiscard() -{ - int index = getNextTransferQueueIndex(); - - for (int i = 0 ; i < m_transferQueueSize; i++) { - if (m_transferQueue[index].status == pendingDiscard) { - // No matter what the current upload type is, as long as there has - // been a Surf Tex enqueue operation, this updateTexImage need to - // be called to keep things in sync. - if (m_transferQueue[index].uploadType == GpuUpload) { - status_t result = m_sharedSurfaceTexture->updateTexImage(); - if (result != OK) - ALOGE("unexpected error: updateTexImage return %d", result); - } - - // since tiles in the queue may be from another webview, remove - // their textures so that they will be repainted / retransferred - Tile* tile = m_transferQueue[index].savedTilePtr; - TileTexture* texture = m_transferQueue[index].savedTileTexturePtr; - if (tile && texture && texture->owner() == tile) { - // since tile destruction removes textures on the UI thread, the - // texture->owner ptr guarantees the tile is valid - tile->discardBackTexture(); - ALOGV("transfer queue discarded tile %p, removed texture", tile); - } - - m_transferQueue[index].savedTilePtr = 0; - m_transferQueue[index].savedTileTexturePtr = 0; - m_transferQueue[index].status = emptyItem; - } - index = (index + 1) % m_transferQueueSize; - } -} - -void TransferQueue::saveGLState() -{ - glGetIntegerv(GL_VIEWPORT, m_GLStateBeforeBlit.viewport); - glGetBooleanv(GL_SCISSOR_TEST, m_GLStateBeforeBlit.scissor); - glGetBooleanv(GL_DEPTH_TEST, m_GLStateBeforeBlit.depth); -#ifdef DEBUG - glGetFloatv(GL_COLOR_CLEAR_VALUE, m_GLStateBeforeBlit.clearColor); -#endif -} - -void TransferQueue::setGLStateForCopy(int width, int height) -{ - // Need to match the texture size. - glViewport(0, 0, width, height); - glDisable(GL_SCISSOR_TEST); - glDisable(GL_DEPTH_TEST); - // Clear the content is only for debug purpose. -#ifdef DEBUG - glClearColor(0, 0, 0, 0); - glClear(GL_COLOR_BUFFER_BIT); -#endif -} - -void TransferQueue::restoreGLState() -{ - glViewport(m_GLStateBeforeBlit.viewport[0], - m_GLStateBeforeBlit.viewport[1], - m_GLStateBeforeBlit.viewport[2], - m_GLStateBeforeBlit.viewport[3]); - - if (m_GLStateBeforeBlit.scissor[0]) - glEnable(GL_SCISSOR_TEST); - - if (m_GLStateBeforeBlit.depth[0]) - glEnable(GL_DEPTH_TEST); -#ifdef DEBUG - glClearColor(m_GLStateBeforeBlit.clearColor[0], - m_GLStateBeforeBlit.clearColor[1], - m_GLStateBeforeBlit.clearColor[2], - m_GLStateBeforeBlit.clearColor[3]); -#endif -} - -int TransferQueue::getNextTransferQueueIndex() -{ - return (m_transferQueueIndex + 1) % m_transferQueueSize; -} - -} // namespace WebCore - -#endif // USE(ACCELERATED_COMPOSITING diff --git a/Source/WebCore/platform/graphics/android/TransferQueue.h b/Source/WebCore/platform/graphics/android/TransferQueue.h deleted file mode 100644 index 65ff116..0000000 --- a/Source/WebCore/platform/graphics/android/TransferQueue.h +++ /dev/null @@ -1,234 +0,0 @@ -/* - * Copyright 2011, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef TransferQueue_h -#define TransferQueue_h - -#if USE(ACCELERATED_COMPOSITING) - -#include "GLUtils.h" -#include "ShaderProgram.h" -#include "SkBitmap.h" -#include -#include - -namespace WebCore { - -class Tile; -class TileTexture; - -struct GLState { - GLint viewport[4]; - GLboolean scissor[1]; - GLboolean depth[1]; - GLfloat clearColor[4]; -}; - - -// While in the queue, the Tile can be re-used, the updated bitmap -// can be discarded. In order to track this obsolete base tiles, we save -// the Tile's Info to make the comparison. -// At the time of base tile's dtor or webview destroy, we want to discard -// all the data in the queue. However, we have to do the Surface Texture -// update in the same GL context as the UI thread. So we mark the status -// as pendingDiscard, and delay the Surface Texture operation to the next -// draw call. - -enum TransferItemStatus { - emptyItem = 0, // S.T. buffer ready for new content - pendingBlit = 1, // Ready for bliting into tile's GL Tex. - pendingDiscard = 2 // Waiting for the next draw call to discard -}; - -enum TextureUploadType { - CpuUpload = 0, - GpuUpload = 1 -}; - -#define DEFAULT_UPLOAD_TYPE GpuUpload - -class TileTransferData { -public: - TileTransferData() - : status(emptyItem) - , savedTilePtr(0) - , savedTileTexturePtr(0) - , uploadType(DEFAULT_UPLOAD_TYPE) - , bitmap(0) - , m_syncKHR(EGL_NO_SYNC_KHR) - { - } - - ~TileTransferData() - { - // Bitmap will be created lazily, need to delete them at dtor. - delete bitmap; - } - - TransferItemStatus status; - Tile* savedTilePtr; - TileTexture* savedTileTexturePtr; - IntRect invalRect; - TextureUploadType uploadType; - // This is only useful in Cpu upload code path, so it will be dynamically - // lazily allocated. - SkBitmap* bitmap; - - // Specific data to the pure color tiles' queue. - Color pureColor; - - // Sync object for GPU fence, this is the only the info passed from UI - // thread to Tex Gen thread. The reason of having this is due to the - // missing sync mechanism on Surface Texture on some vendor. b/5122031. - // Bascially the idea is that when UI thread utilize one buffer from - // the surface texture, we'll need to kick off the GPU commands, and only - // when those particular commands finish, we could write into this buffer - // again in Tex Gen thread. - EGLSyncKHR m_syncKHR; -}; - -class TransferQueue { -public: - TransferQueue(bool useMinimalMem); - ~TransferQueue(); - - // This will be called by the browser through nativeSetProperty - void setTextureUploadType(TextureUploadType type); - void cleanupGLResources(); - void updateDirtyTiles(); - - void initGLResources(int width, int height); - - // insert the bitmap into the queue, mark the tile dirty if failing - void updateQueueWithBitmap(const TileRenderInfo* renderInfo, - const SkBitmap& bitmap); - - void addItemInTransferQueue(const TileRenderInfo* info, - TextureUploadType type, - const SkBitmap* bitmap); - // Check if the item @ index is ready for update. - // The lock will be done when returning true. - bool readyForUpdate(); - - void interruptTransferQueue(bool); - - void lockQueue() { m_transferQueueItemLocks.lock(); } - void unlockQueue() { m_transferQueueItemLocks.unlock(); } - - void addItemInPureColorQueue(const TileRenderInfo* renderInfo); - - void setPendingDiscardWithLock(); - void emptyQueue(); - - bool needsInit() { return !m_sharedSurfaceTextureId; } - // This queue can be accessed from UI and TexGen thread, therefore, we need - // a lock to protect its access - TileTransferData* m_transferQueue; - - android::sp m_ANW; - - // EGL wrapper around m_ANW for use by the GaneshRenderer - EGLSurface m_eglSurface; - -private: - // return true if successfully inserted into queue - bool tryUpdateQueueWithBitmap(const TileRenderInfo* renderInfo, - const SkBitmap& bitmap); - bool getHasGLContext(); - void setHasGLContext(bool hasContext); - - int getNextTransferQueueIndex(); - - // Save and restore the GL State while switching from/to FBO. - void saveGLState(); - void setGLStateForCopy(int width, int height); - void restoreGLState(); - - // Check the current transfer queue item is obsolete or not. - bool checkObsolete(const TileTransferData* data); - - void setPendingDiscard(); - // Before each draw call and the blit operation, clean up all the - // pendingDiscard items. - void cleanupPendingDiscard(); - - void blitTileFromQueue(GLuint fboID, TileTexture* destTex, - TileTexture* frontTex, - GLuint srcTexId, GLenum srcTexTarget, - int index); - - void addItemCommon(const TileRenderInfo* renderInfo, - TextureUploadType type, TileTransferData* data); - - void updatePureColorTiles(); - // Note that the m_transferQueueIndex only changed in the TexGen thread - // where we are going to move on to update the next item in the queue. - int m_transferQueueIndex; - - GLuint m_fboID; // The FBO used for copy the SurfTex to each tile - - GLuint m_sharedSurfaceTextureId; - - // GLContext can be lost when WebView destroyed. - bool m_hasGLContext; - - GLState m_GLStateBeforeBlit; - android::sp m_sharedSurfaceTexture; - - int m_emptyItemCount; - - bool m_interruptedByRemovingOp; - - // We are using wait/signal to handle our own queue sync. - // First of all, if we don't have our own lock, then while WebView is - // destroyed, the UI thread will wait for the Tex Gen to get out from - // dequeue operation, which will not succeed. B/c at this moment, we - // already lost the GL Context. - // Now we maintain a counter, which is m_emptyItemCount. When this reach - // 0, then we need the Tex Gen thread to wait. UI thread can signal this - // wait after calling updateTexImage at the draw call , or after WebView - // is destroyed. - android::Mutex m_transferQueueItemLocks; - android::Condition m_transferQueueItemCond; - - EGLDisplay m_currentDisplay; - - // This should be GpuUpload for production, but for debug purpose or working - // around driver/HW issue, we can set it to CpuUpload. - TextureUploadType m_currentUploadType; - - // The non-pure-color tile are 1 to 1 mapping with Surface Texture which is - // resource limited. To get better performance, it is better to separate - // the pure color tile into another queue. - WTF::Vector m_pureColorTileQueue; - - // The number of items transfer queue can buffer up. - int m_transferQueueSize; -}; - -} // namespace WebCore - -#endif // USE(ACCELERATED_COMPOSITING) -#endif // TransferQueue_h diff --git a/Source/WebCore/platform/graphics/android/VerticalTextMap.cpp b/Source/WebCore/platform/graphics/android/VerticalTextMap.cpp deleted file mode 100644 index 42aa385..0000000 --- a/Source/WebCore/platform/graphics/android/VerticalTextMap.cpp +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright 2011, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "config.h" -#include "VerticalTextMap.h" - -#include -#include -#include -#include - -static const UChar vTextCnvTable[][2] = { - {0x0021, 0xfe15}, // exclamation mark - {0x0028, 0xfe35}, // left paren - {0x0029, 0xfe36}, // right paren - {0x002c, 0xfe10}, // comma - {0x002d, 0xfe32}, // hyphen - {0x003a, 0xfe30}, // colon - {0x003b, 0xfe14}, // semicolon - {0x003f, 0xfe16}, // question mark - {0x005b, 0xfe47}, // left square bracket - {0x005d, 0xfe48}, // right square bracket - {0x007b, 0xfe37}, // left curly bracket - {0x007d, 0xfe38}, // right curly bracket - {0x007e, 0x007c}, // tilde to vertical line - {0x00ab, 0xfe3d}, // left pointing double angle quotation mark - {0x00bb, 0xfe3e}, // right pointing double angle quotation mark - {0x2010, 0xfe32}, // hyphen - {0x2013, 0xfe32}, // en dash - {0x2014, 0xfe31}, // em dash - {0x2015, 0xfe31}, // horizontal bar - {0x2025, 0xfe30}, // two dot leader - {0x2026, 0xfe19}, // three dot leader - {0x3001, 0xfe11}, // Ideographic comma - {0x3002, 0xfe12}, // Ideographic full stop - {0x3008, 0xfe3f}, // left angle bracket - {0x3009, 0xfe40}, // right angle bracket - {0x300a, 0xfe3d}, // left double angle bracket - {0x300b, 0xfe3e}, // right double angle bracket - {0x300c, 0xfe41}, // left corner bracket - {0x300d, 0xfe42}, // right corner bracket - {0x300e, 0xfe43}, // left white corner bracket - {0x300f, 0xfe44}, // right white corner bracket - {0x3010, 0xfe3b}, // left black lenticular bracket - {0x3011, 0xfe3c}, // right black lenticular bracket - {0x3014, 0xfe39}, // left black lenticular bracket - {0x3015, 0xfe3a}, // right tortise shell bracket - {0x3016, 0xfe17}, // left white lenticular bracket - {0x3017, 0xfe18}, // right white lenticular bracket - {0x30fc, 0x3021}, // prolonged sound - {0xfe4f, 0xfe34}, // wavy low line - {0xff08, 0xfe35}, // full width left paren - {0xff09, 0xfe36}, // full width right paren - {0xff0c, 0xfe10}, // full width comma - {0xff3b, 0xfe47}, // full width left square bracket - {0xff3d, 0xfe48}, // full width right square bracket - {0xff5b, 0xfe37}, // full width left curly bracket - {0xff5c, 0xfe31}, // fullwidth vertical line - {0xff5d, 0xfe38}, // full width right curly bracket - {0xff5e, 0x007c}, // tilde to vertical line - {0xff64, 0xfe11}, // halfwidth ideo comma - {0xff61, 0xfe12}, // halfwidth ideo full stop -}; - -namespace WebCore { - -static WTF::Mutex verticalTextHashMapMutex; -static HashMap* verticalTextHashMap = 0; - -UChar VerticalTextMap::getVerticalForm(UChar c) { - { - MutexLocker lock(verticalTextHashMapMutex); - if (!verticalTextHashMap) { - // Lazy initialization. - verticalTextHashMap = new HashMap; - for (size_t i = 0; i < WTF_ARRAY_LENGTH(vTextCnvTable); ++i) - verticalTextHashMap->set(vTextCnvTable[i][0], vTextCnvTable[i][1]); - } - } - return verticalTextHashMap->get(c); -} - -} diff --git a/Source/WebCore/platform/graphics/android/VerticalTextMap.h b/Source/WebCore/platform/graphics/android/VerticalTextMap.h deleted file mode 100644 index 2955589..0000000 --- a/Source/WebCore/platform/graphics/android/VerticalTextMap.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2011, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef android_VerticalTextMap_DEFINED -#define android_VerticalTextMap_DEFINED - -#include "WebViewCore.h" -#include -#include -#include - -namespace WebCore { -class VerticalTextMap { -public: - // This function converts given char to its corresponding vertical form. - // Rerturns 0 if there is no vertical form. - static UChar getVerticalForm(UChar c); -}; -} - -#endif diff --git a/Source/WebCore/platform/graphics/android/VideoLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/VideoLayerAndroid.cpp deleted file mode 100644 index 39bbec6..0000000 --- a/Source/WebCore/platform/graphics/android/VideoLayerAndroid.cpp +++ /dev/null @@ -1,220 +0,0 @@ -/* - * Copyright 2011 The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#define LOG_TAG "VideoLayerAndroid" -#define LOG_NDEBUG 1 - -#include "config.h" -#include "VideoLayerAndroid.h" - -#include "AndroidLog.h" -#include "DrawQuadData.h" -#include "ShaderProgram.h" -#include "TilesManager.h" -#include -#include - -#if USE(ACCELERATED_COMPOSITING) - -namespace WebCore { - -double VideoLayerAndroid::m_rotateDegree = 0; - -VideoLayerAndroid::VideoLayerAndroid() - : LayerAndroid((RenderLayer*)0) -{ - init(); -} - -VideoLayerAndroid::VideoLayerAndroid(const VideoLayerAndroid& layer) - : LayerAndroid(layer) -{ - init(); -} - -void VideoLayerAndroid::init() -{ - // m_surfaceTexture is only useful on UI thread, no need to copy. - // And it will be set at setBaseLayer timeframe - m_playerState = INITIALIZED; -} - -// We can use this function to set the Layer to point to surface texture. -void VideoLayerAndroid::setSurfaceTexture(sp texture, - int textureName, PlayerState playerState) -{ - m_surfaceTexture = texture; - m_playerState = playerState; - TilesManager::instance()->videoLayerManager()->registerTexture(uniqueId(), textureName); -} - -void VideoLayerAndroid::showPreparingAnimation(const SkRect& rect, - const SkRect innerRect) -{ - ShaderProgram* shader = TilesManager::instance()->shader(); - VideoLayerManager* manager = TilesManager::instance()->videoLayerManager(); - // Paint the video content's background. - PureColorQuadData backGroundQuadData(Color(128, 128, 128, 255), LayerQuad, - &m_drawTransform, &rect); - shader->drawQuad(&backGroundQuadData); - - TransformationMatrix addReverseRotation; - TransformationMatrix addRotation = m_drawTransform; - addRotation.translate(innerRect.fLeft, innerRect.fTop); - double halfButtonSize = manager->getButtonSize() / 2; - addRotation.translate(halfButtonSize, halfButtonSize); - addReverseRotation = addRotation; - addRotation.rotate(m_rotateDegree); - addRotation.translate(-halfButtonSize, -halfButtonSize); - - SkRect size = SkRect::MakeWH(innerRect.width(), innerRect.height()); - - TextureQuadData spinnerQuadData(manager->getSpinnerOuterTextureId(), - GL_TEXTURE_2D, GL_LINEAR, - LayerQuad, &addRotation, &size); - shader->drawQuad(&spinnerQuadData); - - addReverseRotation.rotate(-m_rotateDegree); - addReverseRotation.translate(-halfButtonSize, -halfButtonSize); - - spinnerQuadData.updateTextureId(manager->getSpinnerInnerTextureId()); - spinnerQuadData.updateDrawMatrix(&addReverseRotation); - shader->drawQuad(&spinnerQuadData); - - m_rotateDegree += ROTATESTEP; -} - -SkRect VideoLayerAndroid::calVideoRect(const SkRect& rect) -{ - SkRect videoRect = rect; - VideoLayerManager* manager = TilesManager::instance()->videoLayerManager(); - float aspectRatio = manager->getAspectRatio(uniqueId()); - float deltaY = rect.height() - rect.width() / aspectRatio; - if (deltaY >= 0) - videoRect.inset(0, deltaY / 2); - else { - float deltaX = rect.width() - rect.height() * aspectRatio; - if (deltaX >= 0) - videoRect.inset(deltaX / 2, 0); - } - return videoRect; -} - -bool VideoLayerAndroid::drawGL(bool layerTilesDisabled) -{ - // Lazily allocated the textures. - TilesManager* tilesManager = TilesManager::instance(); - VideoLayerManager* manager = tilesManager->videoLayerManager(); - manager->initGLResourcesIfNeeded(); - - ShaderProgram* shader = tilesManager->shader(); - - SkRect rect = SkRect::MakeSize(getSize()); - GLfloat surfaceMatrix[16]; - - // Calculate the video rect based on the aspect ratio and the element rect. - SkRect videoRect = calVideoRect(rect); - PureColorQuadData pureColorQuadData(Color(0, 0, 0, 255), LayerQuad, - &m_drawTransform, &rect); - - if (videoRect != rect) { - // Paint the whole video element with black color when video content - // can't cover the whole area. - shader->drawQuad(&pureColorQuadData); - } - - // Inner rect is for the progressing / play / pause animation. - SkRect innerRect = SkRect::MakeWH(manager->getButtonSize(), - manager->getButtonSize()); - if (innerRect.contains(videoRect)) - innerRect = videoRect; - double buttonSize = manager->getButtonSize(); - innerRect.offset(videoRect.fLeft + (videoRect.width() - buttonSize) / 2, - videoRect.fTop + (videoRect.height() - buttonSize) / 2); - - // When we are drawing the animation of the play/pause button in the - // middle of the video, we need to ask for redraw. - bool needRedraw = false; - TextureQuadData iconQuadData(0, GL_TEXTURE_2D, GL_LINEAR, LayerQuad, - &m_drawTransform, &innerRect); - // Draw the poster image, the progressing image or the Video depending - // on the player's state. - if (m_playerState == PREPARING) { - // Show the progressing animation, with two rotating circles - showPreparingAnimation(videoRect, innerRect); - needRedraw = true; - } else if (m_playerState == PLAYING && m_surfaceTexture.get()) { - // Show the real video. - m_surfaceTexture->updateTexImage(); - m_surfaceTexture->getTransformMatrix(surfaceMatrix); - GLuint textureId = manager->getTextureId(uniqueId()); - shader->drawVideoLayerQuad(m_drawTransform, surfaceMatrix, - videoRect, textureId); - manager->updateMatrix(uniqueId(), surfaceMatrix); - - // Use the scale to control the fading the sizing during animation - double scale = manager->drawIcon(uniqueId(), PlayIcon); - if (scale) { - innerRect.inset(manager->getButtonSize() / 4 * scale, - manager->getButtonSize() / 4 * scale); - iconQuadData.updateTextureId(manager->getPlayTextureId()); - iconQuadData.updateOpacity(scale); - shader->drawQuad(&iconQuadData); - needRedraw = true; - } - } else { - GLuint textureId = manager->getTextureId(uniqueId()); - GLfloat* matrix = manager->getMatrix(uniqueId()); - if (textureId && matrix) { - // Show the screen shot for each video. - shader->drawVideoLayerQuad(m_drawTransform, matrix, - videoRect, textureId); - } else { - // Show the static poster b/c there is no screen shot available. - pureColorQuadData.updateColor(Color(128, 128, 128, 255)); - shader->drawQuad(&pureColorQuadData); - - iconQuadData.updateTextureId(manager->getPosterTextureId()); - iconQuadData.updateOpacity(1.0); - shader->drawQuad(&iconQuadData); - } - - // Use the scale to control the fading and the sizing during animation. - double scale = manager->drawIcon(uniqueId(), PauseIcon); - if (scale) { - innerRect.inset(manager->getButtonSize() / 4 * scale, - manager->getButtonSize() / 4 * scale); - iconQuadData.updateTextureId(manager->getPauseTextureId()); - iconQuadData.updateOpacity(scale); - shader->drawQuad(&iconQuadData); - needRedraw = true; - } - - } - return needRedraw; -} - -} -#endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/android/VideoLayerAndroid.h b/Source/WebCore/platform/graphics/android/VideoLayerAndroid.h deleted file mode 100644 index dd88a85..0000000 --- a/Source/WebCore/platform/graphics/android/VideoLayerAndroid.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright 2011 The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef VideoLayerAndroid_h -#define VideoLayerAndroid_h - -#if USE(ACCELERATED_COMPOSITING) - -#include "GLUtils.h" -#include "LayerAndroid.h" -#include - -namespace android { -class SurfaceTexture; -} - -namespace WebCore { - -// state get from UI thread to decide which image to draw. -// PREPARING should be the progressing image -// PLAYING will be the Video (Surface Texture). -// Otherwise will draw a static image. -// NOTE: These values are matching the ones in HTML5VideoView.java -// Please keep them in sync when changed here. -typedef enum {INITIALIZED, PREPARING, PREPARED, PLAYING, RELEASED} PlayerState; - -class VideoLayerAndroid : public LayerAndroid { - -public: - VideoLayerAndroid(); - explicit VideoLayerAndroid(const VideoLayerAndroid& layer); - - virtual bool isVideo() const { return true; } - virtual LayerAndroid* copy() const { return new VideoLayerAndroid(*this); } - - // The following 3 functions are called in UI thread only. - virtual bool drawGL(bool layerTilesDisabled); - void setSurfaceTexture(sp texture, int textureName, PlayerState playerState); - -private: - void init(); - void showPreparingAnimation(const SkRect& rect, - const SkRect innerRect); - SkRect calVideoRect(const SkRect& rect); - // Surface texture for showing the video is actually allocated in Java side - // and passed into this native code. - sp m_surfaceTexture; - - PlayerState m_playerState; - - static double m_rotateDegree; - - static const int ROTATESTEP = 12; -}; - -} // namespace WebCore - -#endif // USE(ACCELERATED_COMPOSITING) - -#endif // VideoLayerAndroid_h diff --git a/Source/WebCore/platform/graphics/android/VideoLayerManager.cpp b/Source/WebCore/platform/graphics/android/VideoLayerManager.cpp deleted file mode 100644 index 6501f98..0000000 --- a/Source/WebCore/platform/graphics/android/VideoLayerManager.cpp +++ /dev/null @@ -1,385 +0,0 @@ -/* - * Copyright 2011 The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#define LOG_TAG "VideoLayerManager" -#define LOG_NDEBUG 1 - -#include "config.h" -#include "VideoLayerManager.h" - -#include "AndroidLog.h" -#include "RenderSkinMediaButton.h" -#include "SkCanvas.h" -#include - -#if USE(ACCELERATED_COMPOSITING) - -// The animation of the play/pause icon will last for PLAY_PAUSE_ICON_SHOW_TIME -// seconds. -#define PLAY_PAUSE_ICON_SHOW_TIME 1 - -// Define the max sum of all the video's sizes. -// Note that video_size = width * height. If there is no compression, then the -// maximum memory consumption could be 4 * video_size. -// Setting this to 2M, means that maximum memory consumption of all the -// screenshots would not be above 8M. -#define MAX_VIDEOSIZE_SUM 2097152 - -// We don't preload the video data, so we don't have the exact size yet. -// Assuming 16:9 by default, this will be corrected after video prepared. -#define DEFAULT_VIDEO_ASPECT_RATIO 1.78 - -#define VIDEO_TEXTURE_NUMBER 5 -#define VIDEO_BUTTON_SIZE 64 - -namespace WebCore { - -VideoLayerManager::VideoLayerManager() - : m_currentTimeStamp(0) - , m_createdTexture(false) - , m_posterTextureId(0) - , m_spinnerOuterTextureId(0) - , m_spinnerInnerTextureId(0) - , m_playTextureId(0) - , m_pauseTextureId(0) - , m_buttonRect(0, 0, VIDEO_BUTTON_SIZE, VIDEO_BUTTON_SIZE) -{ -} - -int VideoLayerManager::getButtonSize() -{ - return VIDEO_BUTTON_SIZE; -} - -GLuint VideoLayerManager::createTextureFromImage(int buttonType) -{ - SkRect rect = SkRect(m_buttonRect); - SkBitmap bitmap; - bitmap.setConfig(SkBitmap::kARGB_8888_Config, rect.width(), rect.height()); - bitmap.allocPixels(); - bitmap.eraseColor(0); - - SkCanvas canvas(bitmap); - canvas.drawARGB(0, 0, 0, 0, SkXfermode::kClear_Mode); - RenderSkinMediaButton::Draw(&canvas, m_buttonRect, buttonType, true, 0, - false); - - GLuint texture; - glGenTextures(1, &texture); - - GLUtils::createTextureWithBitmap(texture, bitmap); - bitmap.reset(); - return texture; -} - -// Should be called at the VideoLayerAndroid::drawGL to make sure we allocate -// the GL resources lazily. -void VideoLayerManager::initGLResourcesIfNeeded() -{ - if (!m_createdTexture) { - ALOGD("Reinit GLResource for VideoLayer"); - initGLResources(); - } -} - -void VideoLayerManager::initGLResources() -{ - GLUtils::checkGlError("before initGLResources()"); - if (!m_createdTexture) { - m_spinnerOuterTextureId = - createTextureFromImage(RenderSkinMediaButton::SPINNER_OUTER); - m_spinnerInnerTextureId = - createTextureFromImage(RenderSkinMediaButton::SPINNER_INNER); - m_posterTextureId = - createTextureFromImage(RenderSkinMediaButton::VIDEO); - m_playTextureId = createTextureFromImage(RenderSkinMediaButton::PLAY); - m_pauseTextureId = createTextureFromImage(RenderSkinMediaButton::PAUSE); - } - m_createdTexture = !GLUtils::checkGlError("initGLResources()"); - return; -} - -void VideoLayerManager::cleanupGLResources() -{ - if (m_createdTexture) { - GLuint videoTextures[VIDEO_TEXTURE_NUMBER] = { m_spinnerOuterTextureId, - m_spinnerInnerTextureId, m_posterTextureId, m_playTextureId, - m_pauseTextureId }; - - glDeleteTextures(VIDEO_TEXTURE_NUMBER, videoTextures); - m_createdTexture = false; - } - // Delete the texture in retired mode, but have not hit draw call to be - // removed. - deleteUnusedTextures(); - - // Go over the registered GL textures (screen shot textures) and delete them. - android::Mutex::Autolock lock(m_videoLayerInfoMapLock); - InfoIterator end = m_videoLayerInfoMap.end(); - for (InfoIterator it = m_videoLayerInfoMap.begin(); it != end; ++it) { - // The map include every video has been played, so their textureId can - // be deleted already, like hitting onTrimMemory multiple times. - if (it->second->textureId) { - ALOGV("delete texture from the map %d", it->second->textureId); - glDeleteTextures(1, &it->second->textureId); - // Set the textureID to 0 to show the video icon. - it->second->textureId = 0; - } - } - - GLUtils::checkGlError("cleanupGLResources()"); - return; -} - -// Getting TextureId for GL draw call, in the UI thread. -GLuint VideoLayerManager::getTextureId(const int layerId) -{ - android::Mutex::Autolock lock(m_videoLayerInfoMapLock); - GLuint result = 0; - if (m_videoLayerInfoMap.contains(layerId)) - result = m_videoLayerInfoMap.get(layerId)->textureId; - return result; -} - -// Getting the aspect ratio for GL draw call, in the UI thread. -float VideoLayerManager::getAspectRatio(const int layerId) -{ - android::Mutex::Autolock lock(m_videoLayerInfoMapLock); - float result = 0; - if (m_videoLayerInfoMap.contains(layerId)) - result = m_videoLayerInfoMap.get(layerId)->aspectRatio; - return result; -} - -// Getting matrix for GL draw call, in the UI thread. -GLfloat* VideoLayerManager::getMatrix(const int layerId) -{ - android::Mutex::Autolock lock(m_videoLayerInfoMapLock); - GLfloat* result = 0; - if (m_videoLayerInfoMap.contains(layerId)) - result = m_videoLayerInfoMap.get(layerId)->surfaceMatrix; - return result; -} - -int VideoLayerManager::getTotalMemUsage() -{ - int sum = 0; - InfoIterator end = m_videoLayerInfoMap.end(); - for (InfoIterator it = m_videoLayerInfoMap.begin(); it != end; ++it) - sum += it->second->videoSize; - return sum; -} - -// When the video start, we know its texture info, so we register when we -// recieve the setSurfaceTexture call, this happens on UI thread. -void VideoLayerManager::registerTexture(const int layerId, const GLuint textureId) -{ - android::Mutex::Autolock lock(m_videoLayerInfoMapLock); - // If the texture has been registered, then early return. - if (m_videoLayerInfoMap.get(layerId)) { - GLuint oldTextureId = m_videoLayerInfoMap.get(layerId)->textureId; - if (oldTextureId != textureId) - removeLayerInternal(layerId); - else - return; - } - // The old info is deleted and now complete the new info and store it. - VideoLayerInfo* pInfo = new VideoLayerInfo(); - pInfo->textureId = textureId; - memset(pInfo->surfaceMatrix, 0, sizeof(pInfo->surfaceMatrix)); - pInfo->videoSize = 0; - pInfo->aspectRatio = DEFAULT_VIDEO_ASPECT_RATIO; - m_currentTimeStamp++; - pInfo->timeStamp = m_currentTimeStamp; - pInfo->lastIconShownTime = 0; - pInfo->iconState = Registered; - - m_videoLayerInfoMap.add(layerId, pInfo); - ALOGV("GL texture %d regisered for layerId %d", textureId, layerId); - - return; -} - -// Only when the video is prepared, we got the video size. So we should update -// the size for the video accordingly. -// This is called from webcore thread, from MediaPlayerPrivateAndroid. -void VideoLayerManager::updateVideoLayerSize(const int layerId, const int size, - const float ratio) -{ - android::Mutex::Autolock lock(m_videoLayerInfoMapLock); - if (m_videoLayerInfoMap.contains(layerId)) { - VideoLayerInfo* pInfo = m_videoLayerInfoMap.get(layerId); - if (pInfo) { - pInfo->videoSize = size; - pInfo->aspectRatio = ratio; - } - } - - // If the memory usage is out of bound, then just delete the oldest ones. - // Because we only recycle the texture before the current timestamp, the - // current video's texture will not be deleted. - while (getTotalMemUsage() > MAX_VIDEOSIZE_SUM) - if (!recycleTextureMem()) - break; - return; -} - -// This is called only from UI thread, at drawGL time. -void VideoLayerManager::updateMatrix(const int layerId, const GLfloat* matrix) -{ - android::Mutex::Autolock lock(m_videoLayerInfoMapLock); - if (m_videoLayerInfoMap.contains(layerId)) { - // If the existing video layer's matrix is matching the incoming one, - // then skip the update. - VideoLayerInfo* pInfo = m_videoLayerInfoMap.get(layerId); - ASSERT(matrix); - if (pInfo && !memcmp(matrix, pInfo->surfaceMatrix, sizeof(pInfo->surfaceMatrix))) - return; - memcpy(pInfo->surfaceMatrix, matrix, sizeof(pInfo->surfaceMatrix)); - } else { - ALOGV("Error: should not reach here, the layerId %d should exist!", layerId); - ASSERT(false); - } - return; -} - -// This is called on the webcore thread, save the GL texture for recycle in -// the retired queue. They will be deleted in deleteUnusedTextures() in the UI -// thread. -// Return true when we found one texture to retire. -bool VideoLayerManager::recycleTextureMem() -{ - // Find the oldest texture int the m_videoLayerInfoMap, put it in m_retiredTextures - int oldestTimeStamp = m_currentTimeStamp; - int oldestLayerId = -1; - - InfoIterator end = m_videoLayerInfoMap.end(); -#ifdef DEBUG - ALOGV("VideoLayerManager::recycleTextureMem m_videoLayerInfoMap contains"); - for (InfoIterator it = m_videoLayerInfoMap.begin(); it != end; ++it) - ALOGV(" layerId %d, textureId %d, videoSize %d, timeStamp %d ", - it->first, it->second->textureId, it->second->videoSize, it->second->timeStamp); -#endif - for (InfoIterator it = m_videoLayerInfoMap.begin(); it != end; ++it) { - if (it->second->timeStamp < oldestTimeStamp) { - oldestTimeStamp = it->second->timeStamp; - oldestLayerId = it->first; - } - } - - bool foundTextureToRetire = (oldestLayerId != -1); - if (foundTextureToRetire) - removeLayerInternal(oldestLayerId); - - return foundTextureToRetire; -} - -// This is only called in the UI thread, b/c glDeleteTextures need to be called -// on the right context. -void VideoLayerManager::deleteUnusedTextures() -{ - m_retiredTexturesLock.lock(); - int size = m_retiredTextures.size(); - if (size > 0) { - GLuint* textureNames = new GLuint[size]; - int index = 0; - Vector::const_iterator end = m_retiredTextures.end(); - for (Vector::const_iterator it = m_retiredTextures.begin(); - it != end; ++it) { - GLuint textureName = *it; - if (textureName) { - textureNames[index] = textureName; - index++; - ALOGV("GL texture %d will be deleted", textureName); - } - } - glDeleteTextures(size, textureNames); - delete textureNames; - m_retiredTextures.clear(); - } - m_retiredTexturesLock.unlock(); - GLUtils::checkGlError("deleteUnusedTextures"); - return; -} - -// This can be called in the webcore thread in the media player's dtor. -void VideoLayerManager::removeLayer(const int layerId) -{ - android::Mutex::Autolock lock(m_videoLayerInfoMapLock); - removeLayerInternal(layerId); -} - -// This can be called on both UI and webcore thread. Since this is a private -// function, it is up to the public function to handle the lock for -// m_videoLayerInfoMap. -void VideoLayerManager::removeLayerInternal(const int layerId) -{ - // Delete the layerInfo corresponding to this layerId and remove from the map. - if (m_videoLayerInfoMap.contains(layerId)) { - GLuint textureId = m_videoLayerInfoMap.get(layerId)->textureId; - if (textureId) { - // Buffer up the retired textures in either UI or webcore thread, - // will be purged at deleteUnusedTextures in the UI thread. - m_retiredTexturesLock.lock(); - m_retiredTextures.append(textureId); - m_retiredTexturesLock.unlock(); - } - delete m_videoLayerInfoMap.get(layerId); - m_videoLayerInfoMap.remove(layerId); - } - return; -} - -double VideoLayerManager::drawIcon(const int layerId, IconType type) -{ - // When ratio 0 is returned, the Icon should not be drawn. - double ratio = 0; - - android::Mutex::Autolock lock(m_videoLayerInfoMapLock); - if (m_videoLayerInfoMap.contains(layerId)) { - VideoLayerInfo* pInfo = m_videoLayerInfoMap.get(layerId); - // If this is state switching moment, reset the time and state - if ((type == PlayIcon && pInfo->iconState != PlayIconShown) - || (type == PauseIcon && pInfo->iconState != PauseIconShown)) { - pInfo->lastIconShownTime = WTF::currentTime(); - pInfo->iconState = (type == PlayIcon) ? PlayIconShown : PauseIconShown; - } - - // After switching the state, we calculate the ratio depending on the - // time interval. - if ((type == PlayIcon && pInfo->iconState == PlayIconShown) - || (type == PauseIcon && pInfo->iconState == PauseIconShown)) { - double delta = WTF::currentTime() - pInfo->lastIconShownTime; - ratio = 1.0 - (delta / PLAY_PAUSE_ICON_SHOW_TIME); - } - } - - if (ratio > 1 || ratio < 0) - ratio = 0; - return ratio; -} - -} -#endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/android/VideoLayerManager.h b/Source/WebCore/platform/graphics/android/VideoLayerManager.h deleted file mode 100644 index 6c02534..0000000 --- a/Source/WebCore/platform/graphics/android/VideoLayerManager.h +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright 2011 The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef VideoLayerManager_h -#define VideoLayerManager_h - -#include "GLUtils.h" -#include "IntRect.h" -#include -#include -#include - -#if USE(ACCELERATED_COMPOSITING) - -namespace WebCore { - -enum IconState { - Registered, - PlayIconShown, - PauseIconShown -}; - -enum IconType { - PlayIcon, - PauseIcon -}; - -// Every video layer can use its uniqueId to query VideoLayerManager about such -// info globally. -struct VideoLayerInfo { - GLuint textureId; // GL texture bound with the surface texture. - int videoSize; // The size of the video. - float aspectRatio; // The aspect ratio of the video. - int timeStamp; // Used to decide which VideoLayerInfo is the oldest one. - GLfloat surfaceMatrix[16]; - - double lastIconShownTime; - IconState iconState; -}; - - -class VideoLayerManager { - -public: - typedef HashMap::const_iterator InfoIterator; - - VideoLayerManager(); - - // Register the texture when we got setSurfaceTexture call. - void registerTexture(const int layerId, const GLuint textureId); - // Update the size when the video is prepared. - void updateVideoLayerSize(const int layerId, const int size, const float ratio); - // At draw time, update the matrix for every video frame update. - void updateMatrix(const int layerId, const GLfloat* matrix); - // Remove the layer info from the mapping. - void removeLayer(const int layerId); - - // Return the texture name corresponding to the layerId - GLuint getTextureId(const int layerId); - // Return the matrix for surface texture corresponding to the layerId - GLfloat* getMatrix(const int layerId); - // Return the aspect ratio for the video corresponding to the layerId - float getAspectRatio(const int layerId); - - // Delete the GL textures - void deleteUnusedTextures(); - - double drawIcon(const int layerId, IconType type); - - GLuint getSpinnerInnerTextureId() { return m_spinnerInnerTextureId; } - GLuint getSpinnerOuterTextureId() { return m_spinnerOuterTextureId; } - GLuint getPosterTextureId() { return m_posterTextureId; } - GLuint getPlayTextureId() { return m_playTextureId; } - GLuint getPauseTextureId() { return m_pauseTextureId; } - - void initGLResourcesIfNeeded(); - void cleanupGLResources(); - - static int getButtonSize(); -private: - // Get the sum of all the video size stored in m_videoLayerInfoMap. - int getTotalMemUsage(); - // If the memory consumption is out of bound, recycle some textures. - bool recycleTextureMem(); - // The private function to remove layer. - void removeLayerInternal(const int layerId); - void initGLResources(); - // Indexed by each layer's uniqueId, this map contains the important info - // used for showing the video when playing or the screenshot when paused. - HashMap m_videoLayerInfoMap; - android::Mutex m_videoLayerInfoMapLock; - - // Everytime we add one item to the map, we update the timestamp. - int m_currentTimeStamp; - - // The retiredTextures is used to communicate between UI thread and webcore - // thread. Basically, GL textures are determined to retire in the webcore - // thread, and really get deleted in the UI thread. - Vector m_retiredTextures; - android::Mutex m_retiredTexturesLock; - - GLuint createTextureFromImage(int buttonType); - - // Texture for showing the static image will be created at native side. - bool m_createdTexture; - GLuint m_posterTextureId; - GLuint m_spinnerOuterTextureId; - GLuint m_spinnerInnerTextureId; - GLuint m_playTextureId; - GLuint m_pauseTextureId; - - IntRect m_buttonRect; -}; - -} // namespace WebCore - -#endif // USE(ACCELERATED_COMPOSITING) - // -#endif // VideoLayerManager_h diff --git a/Source/WebCore/platform/graphics/android/android_graphics.h b/Source/WebCore/platform/graphics/android/android_graphics.h deleted file mode 100644 index 7faa781..0000000 --- a/Source/WebCore/platform/graphics/android/android_graphics.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2007, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef android_graphics_DEFINED -#define android_graphics_DEFINED - -namespace WebCore { - class GraphicsContext; -} -class SkCanvas; - -// TODO: Move this somewhere else. The implementation for this is actually in -// GraphicsContextAndroid.cpp, but this is used by a handful of other files -SkCanvas* android_gc2canvas(WebCore::GraphicsContext* gc); - -// used to inflate node cache entry -#define CURSOR_RING_HIT_TEST_RADIUS 5 - - -#endif diff --git a/Source/WebCore/platform/graphics/android/context/android_graphics.h b/Source/WebCore/platform/graphics/android/context/android_graphics.h new file mode 100644 index 0000000..7faa781 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/context/android_graphics.h @@ -0,0 +1,42 @@ +/* + * Copyright 2007, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef android_graphics_DEFINED +#define android_graphics_DEFINED + +namespace WebCore { + class GraphicsContext; +} +class SkCanvas; + +// TODO: Move this somewhere else. The implementation for this is actually in +// GraphicsContextAndroid.cpp, but this is used by a handful of other files +SkCanvas* android_gc2canvas(WebCore::GraphicsContext* gc); + +// used to inflate node cache entry +#define CURSOR_RING_HIT_TEST_RADIUS 5 + + +#endif diff --git a/Source/WebCore/platform/graphics/android/fonts/FontAndroid.cpp b/Source/WebCore/platform/graphics/android/fonts/FontAndroid.cpp new file mode 100644 index 0000000..3146612 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/fonts/FontAndroid.cpp @@ -0,0 +1,1192 @@ +/* + * Copyright 2009, The Android Open Source Project + * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#include "EmojiFont.h" +#include "GraphicsOperationCollection.h" +#include "GraphicsOperation.h" +#include "Font.h" +#include "FontData.h" +#include "FontFallbackList.h" +#include "GraphicsContext.h" +#include "GlyphBuffer.h" +#include "IntRect.h" +#include "NotImplemented.h" +#include "PlatformGraphicsContext.h" +#include "SkCanvas.h" +#include "SkColorFilter.h" +#include "SkLayerDrawLooper.h" +#include "SkPaint.h" +#include "SkTemplates.h" +#include "SkTypeface.h" +#include "SkUtils.h" +#include "TextRun.h" + +#ifdef SUPPORT_COMPLEX_SCRIPTS +#include "HarfbuzzSkia.h" +#include +#include +#include +#include +#include +#include +#include +#include +#endif + +using namespace android; + +namespace WebCore { + +typedef std::pair FallbackFontKey; +typedef HashMap FallbackHash; + +static void updateForFont(SkPaint* paint, const SimpleFontData* font) { + font->platformData().setupPaint(paint); + paint->setTextEncoding(SkPaint::kGlyphID_TextEncoding); +} + +static SkPaint* setupFill(SkPaint* paint, GraphicsContext* gc, + const SimpleFontData* font) { + gc->setupFillPaint(paint); + updateForFont(paint, font); + return paint; +} + +static SkPaint* setupStroke(SkPaint* paint, GraphicsContext* gc, + const SimpleFontData* font) { + gc->setupStrokePaint(paint); + updateForFont(paint, font); + return paint; +} + +static bool setupForText(SkPaint* paint, GraphicsContext* gc, + const SimpleFontData* font) { + int mode = gc->textDrawingMode() & (TextModeFill | TextModeStroke); + if (!mode) + return false; + + paint->setVerticalText(font->platformData().orientation() == Vertical); + + FloatSize shadowOffset; + float shadowBlur; + Color shadowColor; + ColorSpace shadowColorSpace; + bool hasShadow = gc->getShadow(shadowOffset, shadowBlur, shadowColor, shadowColorSpace); + bool hasBothStrokeAndFill = + (mode & (TextModeStroke | TextModeFill)) == (TextModeStroke | TextModeFill); + if (hasShadow || hasBothStrokeAndFill) { + SkLayerDrawLooper* looper = new SkLayerDrawLooper; + paint->setLooper(looper)->unref(); + + // The layerDrawLooper uses at the root paint to determine the text + // encoding so we need to make sure it is properly configured. + updateForFont(paint, font); + + // Specify the behavior of the looper + SkLayerDrawLooper::LayerInfo info; + info.fPaintBits = SkLayerDrawLooper::kEntirePaint_Bits; + info.fColorMode = SkXfermode::kSrc_Mode; + info.fFlagsMask = SkPaint::kAllFlags; + + // The paint is only valid until the looper receives another call to + // addLayer(). Therefore, we must cache certain state for later use. + bool hasFillPaint = false; + bool hasStrokePaint = false; + SkScalar strokeWidth; + + if ((mode & TextModeStroke) && gc->willStroke()) { + strokeWidth = setupStroke(looper->addLayer(info), gc, font)->getStrokeWidth(); + hasStrokePaint = true; + } + if ((mode & TextModeFill) && gc->willFill()) { + setupFill(looper->addLayer(info), gc, font); + hasFillPaint = true; + } + + if (hasShadow) { + SkPaint shadowPaint; + SkPoint offset; + if (gc->setupShadowPaint(&shadowPaint, &offset)) { + + // add an offset to the looper when creating a shadow layer + info.fOffset.set(offset.fX, offset.fY); + + SkPaint* p = looper->addLayer(info); + *p = shadowPaint; + + // Currently, only GraphicsContexts associated with the + // HTMLCanvasElement have shadows ignore transforms set. This + // allows us to distinguish between CSS and Canvas shadows which + // have different rendering specifications. + if (gc->shadowsIgnoreTransforms()) { + SkColorFilter* cf = SkColorFilter::CreateModeFilter(p->getColor(), + SkXfermode::kSrcIn_Mode); + p->setColorFilter(cf)->unref(); + } else { // in CSS + p->setShader(NULL); + } + + if (hasStrokePaint && !hasFillPaint) { + // stroke the shadow if we have stroke but no fill + p->setStyle(SkPaint::kStroke_Style); + p->setStrokeWidth(strokeWidth); + } + updateForFont(p, font); + } + } + } else if (mode & TextModeFill) { + (void)setupFill(paint, gc, font); + } else if (mode & TextModeStroke) { + (void)setupStroke(paint, gc, font); + } else { + return false; + } + return true; +} + +bool Font::canReturnFallbackFontsForComplexText() +{ + return false; +} + +bool Font::canExpandAroundIdeographsInComplexText() +{ + return false; +} + +void Font::drawGlyphs(GraphicsContext* gc, const SimpleFontData* font, + const GlyphBuffer& glyphBuffer, int from, int numGlyphs, + const FloatPoint& point) const +{ + // compile-time assert + SkASSERT(sizeof(GlyphBufferGlyph) == sizeof(uint16_t)); + + SkPaint paint; + if (!setupForText(&paint, gc, font)) { + return; + } + + SkScalar x = SkFloatToScalar(point.x()); + SkScalar y = SkFloatToScalar(point.y()); + const GlyphBufferGlyph* glyphs = glyphBuffer.glyphs(from); + const GlyphBufferAdvance* adv = glyphBuffer.advances(from); + SkAutoSTMalloc<32, SkPoint> storage(numGlyphs), storage2(numGlyphs), storage3(numGlyphs); + SkPoint* pos = storage.get(); + + SkCanvas* canvas = gc->platformContext()->recordingCanvas(); + + /* We need an array of [x,y,x,y,x,y,...], but webkit is giving us + point.xy + [width, height, width, height, ...], so we have to convert + */ + + if (font->platformData().orientation() == Vertical) + y += SkFloatToScalar(font->fontMetrics().floatAscent(IdeographicBaseline) - font->fontMetrics().floatAscent()); + + if (EmojiFont::IsAvailable()) { + // set filtering, to make scaled images look nice(r) + paint.setFilterBitmap(true); + + int localIndex = 0; + int localCount = 0; + for (int i = 0; i < numGlyphs; i++) { + if (EmojiFont::IsEmojiGlyph(glyphs[i])) { + if (localCount) + canvas->drawPosText(&glyphs[localIndex], + localCount * sizeof(uint16_t), + &pos[localIndex], paint); + EmojiFont::Draw(canvas, glyphs[i], x, y, paint); + // reset local index/count track for "real" glyphs + localCount = 0; + localIndex = i + 1; + } else { + pos[i].set(x, y); + localCount += 1; + } + x += SkFloatToScalar(adv[i].width()); + y += SkFloatToScalar(adv[i].height()); + } + // draw the last run of glyphs (if any) + if (localCount) + canvas->drawPosText(&glyphs[localIndex], + localCount * sizeof(uint16_t), + &pos[localIndex], paint); + } else { + for (int i = 0; i < numGlyphs; i++) { + pos[i].set(x, y); + y += SkFloatToScalar(adv[i].height()); + x += SkFloatToScalar(adv[i].width()); + } + + if (font->platformData().orientation() == Vertical) { + canvas->save(); + canvas->rotate(-90); + SkMatrix rotator; + rotator.reset(); + rotator.setRotate(90); + rotator.mapPoints(pos, numGlyphs); + } + + canvas->drawPosText(glyphs, numGlyphs * sizeof(uint16_t), pos, paint); + + if (font->platformData().orientation() == Vertical) + canvas->restore(); + } + gc->platformContext()->endRecording(); +} + +void Font::drawEmphasisMarksForComplexText(WebCore::GraphicsContext*, WebCore::TextRun const&, WTF::AtomicString const&, WebCore::FloatPoint const&, int, int) const +{ + notImplemented(); +} + +#ifndef SUPPORT_COMPLEX_SCRIPTS + +FloatRect Font::selectionRectForComplexText(const TextRun& run, + const FloatPoint& point, int h, int, int) const +{ + SkPaint paint; + SkScalar width, left; + SkPaint::FontMetrics metrics; + + primaryFont()->platformData().setupPaint(&paint); + + width = paint.measureText(run.characters(), run.length() << 1); + SkScalar spacing = paint.getFontMetrics(&metrics); + + return FloatRect(point.x(), + point.y(), + roundf(SkScalarToFloat(width)), + roundf(SkScalarToFloat(spacing))); +} + +void Font::drawComplexText(GraphicsContext* gc, TextRun const& run, + FloatPoint const& point, int, int) const +{ + SkCanvas* canvas = gc->platformContext()->mCanvas; + SkPaint paint; + + if (!setupForText(&paint, gc, primaryFont())) { + return; + } + + // go to chars, instead of glyphs, which was set by setupForText() + paint.setTextEncoding(SkPaint::kUTF16_TextEncoding); + + canvas->drawText(run.characters(), run.length() << 1, + SkFloatToScalar(point.x()), SkFloatToScalar(point.y()), + paint); +} + +float Font::floatWidthForComplexText(const TextRun& run, HashSet*, GlyphOverflow*) const +{ + SkPaint paint; + + primaryFont()->platformData().setupPaint(&paint); + +//printf("--------- complext measure %d chars\n", run.to() - run.from()); + + SkScalar width = paint.measureText(run.characters(), run.length() << 1); + return SkScalarToFloat(width); +} + +int Font::offsetForPositionForComplexText(const TextRun& run, float x, + bool includePartialGlyphs) const +{ + SkPaint paint; + int count = run.length(); + SkAutoSTMalloc<64, SkScalar> storage(count); + SkScalar* widths = storage.get(); + + primaryFont()->platformData().setupPaint(&paint); + + count = paint.getTextWidths(run.characters(), count << 1, widths); + + if (count > 0) + { + SkScalar pos = 0; + for (int i = 0; i < count; i++) + { + if (x < SkScalarRound(pos + SkScalarHalf(widths[i]))) + return i; + pos += widths[i]; + } + } + return count; +} + +#else + +// TODO Should we remove the multilayer support? +// If yes. remove isCanvasMultiLayered() and adjustTextRenderMode(). +static bool isCanvasMultiLayered(SkCanvas* canvas) +{ + SkCanvas::LayerIter layerIterator(canvas, false); + layerIterator.next(); + return !layerIterator.done(); +} + +static void adjustTextRenderMode(SkPaint* paint, bool isCanvasMultiLayered) +{ + // Our layers only have a single alpha channel. This means that subpixel + // rendered text cannot be compositied correctly when the layer is + // collapsed. Therefore, subpixel text is disabled when we are drawing + // onto a layer. + if (isCanvasMultiLayered) + paint->setLCDRenderText(false); +} + +// Harfbuzz uses 26.6 fixed point values for pixel offsets. However, we don't +// handle subpixel positioning so this function is used to truncate Harfbuzz +// values to a number of pixels. +static int truncateFixedPointToInteger(HB_Fixed value) +{ + return value >> 6; +} + +// TextRunWalker walks a TextRun and presents each script run in sequence. A +// TextRun is a sequence of code-points with the same embedding level (i.e. they +// are all left-to-right or right-to-left). A script run is a subsequence where +// all the characters have the same script (e.g. Arabic, Thai etc). Shaping is +// only ever done with script runs since the shapers only know how to deal with +// a single script. +// +// After creating it, the script runs are either iterated backwards or forwards. +// It defaults to backwards for RTL and forwards otherwise (which matches the +// presentation order), however you can set it with |setBackwardsIteration|. +// +// Once you have setup the object, call |nextScriptRun| to get the first script +// run. This will return false when the iteration is complete. At any time you +// can call |reset| to start over again. +class TextRunWalker { +public: + TextRunWalker(const TextRun&, int, int, const Font*); + ~TextRunWalker(); + + bool isWordBreak(unsigned, bool); + // setPadding sets a number of pixels to be distributed across the TextRun. + // WebKit uses this to justify text. + void setPadding(int); + void reset(); + void setBackwardsIteration(bool); + // Advance to the next script run, returning false when the end of the + // TextRun has been reached. + bool nextScriptRun(); + float widthOfFullRun(); + + // setWordSpacingAdjustment sets a delta (in pixels) which is applied at + // each word break in the TextRun. + void setWordSpacingAdjustment(int wordSpacingAdjustment) + { + m_wordSpacingAdjustment = wordSpacingAdjustment; + } + + // setLetterSpacingAdjustment sets an additional number of pixels that is + // added to the advance after each output cluster. This matches the behaviour + // of WidthIterator::advance. + // + // (NOTE: currently does nothing because I don't know how to get the + // cluster information from Harfbuzz.) + void setLetterSpacingAdjustment(int letterSpacingAdjustment) + { + m_letterSpacing = letterSpacingAdjustment; + } + + // setWordAndLetterSpacing calls setWordSpacingAdjustment() and + // setLetterSpacingAdjustment() to override m_wordSpacingAdjustment + // and m_letterSpacing. + void setWordAndLetterSpacing(int wordSpacingAdjustment, int letterSpacingAdjustment); + + // Set the x offset for the next script run. This affects the values in + // |xPositions| + void setXOffsetToZero() { m_offsetX = 0; } + bool rtl() const { return m_run.rtl(); } + const uint16_t* glyphs() const { return m_glyphs16; } + + // Return the length of the array returned by |glyphs| + unsigned length() const { return m_item.num_glyphs; } + + // Return the offset for each of the glyphs. Note that this is translated + // by the current x offset and that the x offset is updated for each script + // run. + const SkPoint* positions() const { return m_positions; } + + // Get the advances (widths) for each glyph. + const HB_Fixed* advances() const { return m_item.advances; } + + // Return the width (in px) of the current script run. + unsigned width() const { return m_pixelWidth; } + + // Return the cluster log for the current script run. For example: + // script run: f i a n c é (fi gets ligatured) + // log clutrs: 0 0 1 2 3 4 + // So, for each input code point, the log tells you which output glyph was + // generated for it. + const unsigned short* logClusters() const { return m_item.log_clusters; } + + // return the number of code points in the current script run + unsigned numCodePoints() const { return m_numCodePoints; } + + const FontPlatformData* fontPlatformDataForScriptRun() { + return reinterpret_cast(m_item.font->userData); + } + +private: + enum CustomScript { + Bengali, + Devanagari, + Hebrew, + HebrewBold, + Naskh, + Tamil, + Thai, + NUM_SCRIPTS + }; + + static const char* paths[NUM_SCRIPTS]; + + void setupFontForScriptRun(); + const FontPlatformData* setupComplexFont(CustomScript script, + const FontPlatformData& platformData); + HB_FontRec* allocHarfbuzzFont(); + void deleteGlyphArrays(); + void createGlyphArrays(int); + void resetGlyphArrays(); + void shapeGlyphs(); + void setGlyphPositions(bool); + + static void normalizeSpacesAndMirrorChars(const UChar* source, bool rtl, + UChar* destination, int length); + static const TextRun& getNormalizedTextRun(const TextRun& originalRun, + OwnPtr& normalizedRun, OwnArrayPtr& normalizedBuffer); + + // This matches the logic in RenderBlock::findNextLineBreak + static bool isCodepointSpace(HB_UChar16 c) { return c == ' ' || c == '\t'; } + + const Font* const m_font; + HB_ShaperItem m_item; + uint16_t* m_glyphs16; // A vector of 16-bit glyph ids. + SkPoint* m_positions; // A vector of positions for each glyph. + ssize_t m_indexOfNextScriptRun; // Indexes the script run in |m_run|. + const int m_startingX; // Offset in pixels of the first script run. + const int m_startingY; // Offset in pixels of the first script run. + int m_offsetX; // Offset in pixels to the start of the next script run. + unsigned m_pixelWidth; // Width (in px) of the current script run. + unsigned m_numCodePoints; // Code points in current script run. + unsigned m_glyphsArrayCapacity; // Current size of all the Harfbuzz arrays. + + OwnPtr m_normalizedRun; + OwnArrayPtr m_normalizedBuffer; // A buffer for normalized run. + const TextRun& m_run; + bool m_iterateBackwards; + int m_wordSpacingAdjustment; // delta adjustment (pixels) for each word break. + float m_padding; // pixels to be distributed over the line at word breaks. + float m_padPerWordBreak; // pixels to be added to each word break. + float m_padError; // |m_padPerWordBreak| might have a fractional component. + // Since we only add a whole number of padding pixels at + // each word break we accumulate error. This is the + // number of pixels that we are behind so far. + unsigned m_letterSpacing; // pixels to be added after each glyph. +}; + + +// Indexed using enum CustomScript +const char* TextRunWalker::paths[] = { + "/system/fonts/Lohit-Bengali.ttf", + "/system/fonts/Lohit-Devanagari.ttf", + "/system/fonts/DroidSansHebrew-Regular.ttf", + "/system/fonts/DroidSansHebrew-Bold.ttf", + "/system/fonts/DroidNaskh-Regular.ttf", + "/system/fonts/Lohit-Tamil.ttf", + "/system/fonts/DroidSansThai.ttf" +}; + +TextRunWalker::TextRunWalker(const TextRun& run, int startingX, int startingY, const Font* font) + : m_font(font) + , m_startingX(startingX) + , m_startingY(startingY) + , m_offsetX(m_startingX) + , m_run(getNormalizedTextRun(run, m_normalizedRun, m_normalizedBuffer)) + , m_iterateBackwards(m_run.rtl()) + , m_wordSpacingAdjustment(0) + , m_padding(0) + , m_padPerWordBreak(0) + , m_padError(0) + , m_letterSpacing(0) +{ + // Do not use |run| inside this constructor. Use |m_run| instead. + + memset(&m_item, 0, sizeof(m_item)); + // We cannot know, ahead of time, how many glyphs a given script run + // will produce. We take a guess that script runs will not produce more + // than twice as many glyphs as there are code points plus a bit of + // padding and fallback if we find that we are wrong. + createGlyphArrays((m_run.length() + 2) * 2); + + m_item.log_clusters = new unsigned short[m_run.length()]; + + m_item.face = 0; + m_item.font = allocHarfbuzzFont(); + + m_item.item.bidiLevel = m_run.rtl(); + + m_item.string = m_run.characters(); + m_item.stringLength = m_run.length(); + + reset(); +} + +TextRunWalker::~TextRunWalker() +{ + fastFree(m_item.font); + deleteGlyphArrays(); + delete[] m_item.log_clusters; +} + +bool TextRunWalker::isWordBreak(unsigned index, bool isRTL) +{ + if (!isRTL) + return index && isCodepointSpace(m_item.string[index]) + && !isCodepointSpace(m_item.string[index - 1]); + return index != m_item.stringLength - 1 && isCodepointSpace(m_item.string[index]) + && !isCodepointSpace(m_item.string[index + 1]); +} + +// setPadding sets a number of pixels to be distributed across the TextRun. +// WebKit uses this to justify text. +void TextRunWalker::setPadding(int padding) +{ + m_padding = padding; + if (!m_padding) + return; + + // If we have padding to distribute, then we try to give an equal + // amount to each space. The last space gets the smaller amount, if + // any. + unsigned numWordBreaks = 0; + bool isRTL = m_iterateBackwards; + + for (unsigned i = 0; i < m_item.stringLength; i++) { + if (isWordBreak(i, isRTL)) + numWordBreaks++; + } + + if (numWordBreaks) + m_padPerWordBreak = m_padding / numWordBreaks; + else + m_padPerWordBreak = 0; +} + +void TextRunWalker::reset() +{ + if (m_iterateBackwards) + m_indexOfNextScriptRun = m_run.length() - 1; + else + m_indexOfNextScriptRun = 0; + m_offsetX = m_startingX; +} + +void TextRunWalker::setBackwardsIteration(bool isBackwards) +{ + m_iterateBackwards = isBackwards; + reset(); +} + +// Advance to the next script run, returning false when the end of the +// TextRun has been reached. +bool TextRunWalker::nextScriptRun() +{ + if (m_iterateBackwards) { + // In right-to-left mode we need to render the shaped glyph backwards and + // also render the script runs themselves backwards. So given a TextRun: + // AAAAAAACTTTTTTT (A = Arabic, C = Common, T = Thai) + // we render: + // TTTTTTCAAAAAAA + // (and the glyphs in each A, C and T section are backwards too) + if (!hb_utf16_script_run_prev(&m_numCodePoints, &m_item.item, m_run.characters(), + m_run.length(), &m_indexOfNextScriptRun)) + return false; + } else { + if (!hb_utf16_script_run_next(&m_numCodePoints, &m_item.item, m_run.characters(), + m_run.length(), &m_indexOfNextScriptRun)) + return false; + + // It is actually wrong to consider script runs at all in this code. + // Other WebKit code (e.g. Mac) segments complex text just by finding + // the longest span of text covered by a single font. + // But we currently need to call hb_utf16_script_run_next anyway to fill + // in the harfbuzz data structures to e.g. pick the correct script's shaper. + // So we allow that to run first, then do a second pass over the range it + // found and take the largest subregion that stays within a single font. + const FontData* glyphData = m_font->glyphDataForCharacter( + m_item.string[m_item.item.pos], false).fontData; + unsigned endOfRun; + for (endOfRun = 1; endOfRun < m_item.item.length; ++endOfRun) { + const FontData* nextGlyphData = m_font->glyphDataForCharacter( + m_item.string[m_item.item.pos + endOfRun], false).fontData; + if (nextGlyphData != glyphData) + break; + } + m_item.item.length = endOfRun; + m_indexOfNextScriptRun = m_item.item.pos + endOfRun; + } + + setupFontForScriptRun(); + shapeGlyphs(); + setGlyphPositions(rtl()); + + return true; +} + +float TextRunWalker::widthOfFullRun() +{ + float widthSum = 0; + while (nextScriptRun()) + widthSum += width(); + + return widthSum; +} + +void TextRunWalker::setWordAndLetterSpacing(int wordSpacingAdjustment, + int letterSpacingAdjustment) +{ + setWordSpacingAdjustment(wordSpacingAdjustment); + setLetterSpacingAdjustment(letterSpacingAdjustment); +} + +const FontPlatformData* TextRunWalker::setupComplexFont( + CustomScript script, + const FontPlatformData& platformData) +{ + static FallbackHash fallbackPlatformData; + + FallbackFontKey key(script, platformData.size()); + FontPlatformData* newPlatformData = 0; + + if (!fallbackPlatformData.contains(key)) { + SkTypeface* typeface = SkTypeface::CreateFromFile(paths[script]); + newPlatformData = new FontPlatformData(platformData, typeface); + SkSafeUnref(typeface); + fallbackPlatformData.set(key, newPlatformData); + } + + if (!newPlatformData) + newPlatformData = fallbackPlatformData.get(key); + + // If we couldn't allocate a new FontPlatformData, revert to the one passed + return newPlatformData ? newPlatformData : &platformData; +} + +void TextRunWalker::setupFontForScriptRun() +{ + const FontData* fontData = m_font->glyphDataForCharacter(m_run[0], false).fontData; + const FontPlatformData& platformData = + fontData->fontDataForCharacter(' ')->platformData(); + const FontPlatformData* complexPlatformData = &platformData; + + switch (m_item.item.script) { + case HB_Script_Bengali: + complexPlatformData = setupComplexFont(Bengali, platformData); + break; + case HB_Script_Devanagari: + complexPlatformData = setupComplexFont(Devanagari, platformData); + break; + case HB_Script_Hebrew: + switch (platformData.typeface()->style()) { + case SkTypeface::kBold: + case SkTypeface::kBoldItalic: + complexPlatformData = setupComplexFont(HebrewBold, platformData); + break; + case SkTypeface::kNormal: + case SkTypeface::kItalic: + default: + complexPlatformData = setupComplexFont(Hebrew, platformData); + break; + } + break; + case HB_Script_Arabic: + complexPlatformData = setupComplexFont(Naskh, platformData); + break; + case HB_Script_Tamil: + complexPlatformData = setupComplexFont(Tamil, platformData); + break; + case HB_Script_Thai: + complexPlatformData = setupComplexFont(Thai, platformData); + break; + default: + // HB_Script_Common; includes Ethiopic + complexPlatformData = &platformData; + break; + } + m_item.face = complexPlatformData->harfbuzzFace(); + m_item.font->userData = const_cast(complexPlatformData); + + int size = complexPlatformData->size(); + m_item.font->x_ppem = size; + m_item.font->y_ppem = size; + // x_ and y_scale are the conversion factors from font design space (fEmSize) to 1/64th of device pixels in 16.16 format. + const int devicePixelFraction = 64; + const int multiplyFor16Dot16 = 1 << 16; + int scale = devicePixelFraction * size * multiplyFor16Dot16 / complexPlatformData->emSizeInFontUnits(); + m_item.font->x_scale = scale; + m_item.font->y_scale = scale; +} + +HB_FontRec* TextRunWalker::allocHarfbuzzFont() +{ + HB_FontRec* font = reinterpret_cast(fastMalloc(sizeof(HB_FontRec))); + memset(font, 0, sizeof(HB_FontRec)); + font->klass = &harfbuzzSkiaClass; + font->userData = 0; + + return font; +} + +void TextRunWalker::deleteGlyphArrays() +{ + delete[] m_item.glyphs; + delete[] m_item.attributes; + delete[] m_item.advances; + delete[] m_item.offsets; + delete[] m_glyphs16; + delete[] m_positions; +} + +void TextRunWalker::createGlyphArrays(int size) +{ + m_item.glyphs = new HB_Glyph[size]; + m_item.attributes = new HB_GlyphAttributes[size]; + m_item.advances = new HB_Fixed[size]; + m_item.offsets = new HB_FixedPoint[size]; + + m_glyphs16 = new uint16_t[size]; + m_positions = new SkPoint[size]; + + m_item.num_glyphs = size; + m_glyphsArrayCapacity = size; // Save the GlyphArrays size. +} + +void TextRunWalker::resetGlyphArrays() +{ + int size = m_item.num_glyphs; + // All the types here don't have pointers. It is safe to reset to + // zero unless Harfbuzz breaks the compatibility in the future. + memset(m_item.glyphs, 0, size * sizeof(m_item.glyphs[0])); + memset(m_item.attributes, 0, size * sizeof(m_item.attributes[0])); + memset(m_item.advances, 0, size * sizeof(m_item.advances[0])); + memset(m_item.offsets, 0, size * sizeof(m_item.offsets[0])); + memset(m_glyphs16, 0, size * sizeof(m_glyphs16[0])); + memset(m_positions, 0, size * sizeof(m_positions[0])); +} + +void TextRunWalker::shapeGlyphs() +{ + // HB_ShapeItem() resets m_item.num_glyphs. If the previous call to + // HB_ShapeItem() used less space than was available, the capacity of + // the array may be larger than the current value of m_item.num_glyphs. + // So, we need to reset the num_glyphs to the capacity of the array. + m_item.num_glyphs = m_glyphsArrayCapacity; + resetGlyphArrays(); + while (!HB_ShapeItem(&m_item)) { + // We overflowed our arrays. Resize and retry. + // HB_ShapeItem fills in m_item.num_glyphs with the needed size. + deleteGlyphArrays(); + createGlyphArrays(m_item.num_glyphs << 1); + resetGlyphArrays(); + } +} + +void TextRunWalker::setGlyphPositions(bool isRTL) +{ + int position = 0; + // logClustersIndex indexes logClusters for the first (or last when + // RTL) codepoint of the current glyph. Each time we advance a glyph, + // we skip over all the codepoints that contributed to the current + // glyph. + unsigned logClustersIndex = isRTL && m_item.num_glyphs ? m_item.num_glyphs - 1 : 0; + + for (unsigned iter = 0; iter < m_item.num_glyphs; ++iter) { + // Glyphs are stored in logical order, but for layout purposes we + // always go left to right. + int i = isRTL ? m_item.num_glyphs - iter - 1 : iter; + + m_glyphs16[i] = m_item.glyphs[i]; + int offsetX = truncateFixedPointToInteger(m_item.offsets[i].x); + int offsetY = truncateFixedPointToInteger(m_item.offsets[i].y); + m_positions[i].set(SkIntToScalar(m_offsetX + position) + offsetX, m_startingY + offsetY); + + int advance = truncateFixedPointToInteger(m_item.advances[i]); + // The first half of the conjunction works around the case where + // output glyphs aren't associated with any codepoints by the + // clusters log. + if (logClustersIndex < m_item.item.length + && isWordBreak(m_item.item.pos + logClustersIndex, isRTL)) { + advance += m_wordSpacingAdjustment; + + if (m_padding > 0) { + int toPad = roundf(m_padPerWordBreak + m_padError); + m_padError += m_padPerWordBreak - toPad; + + if (m_padding < toPad) + toPad = m_padding; + m_padding -= toPad; + advance += toPad; + } + } + + // ZeroWidthJoiners and ZeroWidthNonJoiners should be stripped by + // Harfbuzz, but aren't. Check for zwj and zwnj and replace with a + // zero width space. We get the glyph data for space instead of + // zeroWidthSpace because the latter was seen to render with an + // unexpected code point (the symbol for a cloud). Since the standard + // space is in page zero and since we've also confirmed that there is + // no advance on this glyph, that should be ok. + if (0 == m_item.advances[i]) { + const HB_UChar16 c = m_item.string[m_item.item.pos + logClustersIndex]; + if ((c == zeroWidthJoiner) || (c == zeroWidthNonJoiner)) { + static Glyph spaceGlyph = m_font->glyphDataForCharacter(space, false).glyph; + m_glyphs16[i] = spaceGlyph; + } + } + + // TODO We would like to add m_letterSpacing after each cluster, but I + // don't know where the cluster information is. This is typically + // fine for Roman languages, but breaks more complex languages + // terribly. + // advance += m_letterSpacing; + + if (isRTL) { + while (logClustersIndex > 0 && logClusters()[logClustersIndex] == i) + logClustersIndex--; + } else { + while (logClustersIndex < m_item.item.length + && logClusters()[logClustersIndex] == i) + logClustersIndex++; + } + + position += advance; + } + + m_pixelWidth = position; + m_offsetX += m_pixelWidth; +} + +void TextRunWalker::normalizeSpacesAndMirrorChars(const UChar* source, bool rtl, + UChar* destination, int length) +{ + int position = 0; + bool error = false; + // Iterate characters in source and mirror character if needed. + while (position < length) { + UChar32 character; + int nextPosition = position; + U16_NEXT(source, nextPosition, length, character); + + if (Font::treatAsSpace(character)) + character = space; + else if (Font::treatAsZeroWidthSpaceInComplexScript(character)) + character = zeroWidthSpace; + else if (rtl) + character = u_charMirror(character); + + U16_APPEND(destination, position, length, character, error); + ASSERT(!error); + position = nextPosition; + } +} + +const TextRun& TextRunWalker::getNormalizedTextRun(const TextRun& originalRun, + OwnPtr& normalizedRun, OwnArrayPtr& normalizedBuffer) +{ + // Normalize the text run in three ways: + // 1) Convert the |originalRun| to NFC normalized form if combining diacritical marks + // (U+0300..) are used in the run. This conversion is necessary since most OpenType + // fonts (e.g., Arial) don't have substitution rules for the diacritical marks in + // their GSUB tables. + // + // Note that we don't use the icu::Normalizer::isNormalized(UNORM_NFC) API here since + // the API returns FALSE (= not normalized) for complex runs that don't require NFC + // normalization (e.g., Arabic text). Unless the run contains the diacritical marks, + // Harfbuzz will do the same thing for us using the GSUB table. + // 2) Convert spacing characters into plain spaces, as some fonts will provide glyphs + // for characters like '\n' otherwise. + // 3) Convert mirrored characters such as parenthesis for rtl text. + + // Convert to NFC form if the text has diacritical marks. + icu::UnicodeString normalizedString; + UErrorCode error = U_ZERO_ERROR; + + for (int16_t i = 0; i < originalRun.length(); ++i) { + UChar ch = originalRun[i]; + if (::ublock_getCode(ch) == UBLOCK_COMBINING_DIACRITICAL_MARKS) { + icu::Normalizer::normalize(icu::UnicodeString(originalRun.characters(), + originalRun.length()), UNORM_NFC, 0 /* no options */, + normalizedString, error); + if (U_FAILURE(error)) + return originalRun; + break; + } + } + + // Normalize space and mirror parenthesis for rtl text. + int normalizedBufferLength; + const UChar* sourceText; + if (normalizedString.isEmpty()) { + normalizedBufferLength = originalRun.length(); + sourceText = originalRun.characters(); + } else { + normalizedBufferLength = normalizedString.length(); + sourceText = normalizedString.getBuffer(); + } + + normalizedBuffer = adoptArrayPtr(new UChar[normalizedBufferLength + 1]); + + normalizeSpacesAndMirrorChars(sourceText, originalRun.rtl(), normalizedBuffer.get(), + normalizedBufferLength); + + normalizedRun = adoptPtr(new TextRun(originalRun)); + normalizedRun->setText(normalizedBuffer.get(), normalizedBufferLength); + return *normalizedRun; +} + +FloatRect Font::selectionRectForComplexText(const TextRun& run, + const FloatPoint& point, int height, int from, int to) const +{ + + int fromX = -1, toX = -1, fromAdvance = -1, toAdvance = -1; + TextRunWalker walker(run, 0, 0, this); + walker.setWordAndLetterSpacing(wordSpacing(), letterSpacing()); + + // Base will point to the x offset for the current script run. Note that, in + // the LTR case, width will be 0. + int base = walker.rtl() ? walker.widthOfFullRun() : 0; + const int leftEdge = base; + + // We want to enumerate the script runs in code point order in the following + // code. This call also resets |walker|. + walker.setBackwardsIteration(false); + + while (walker.nextScriptRun() && (fromX == -1 || toX == -1)) { + // TextRunWalker will helpfully accumulate the x offsets for different + // script runs for us. For this code, however, we always want the x + // offsets to start from zero so we call this before each script run. + walker.setXOffsetToZero(); + + if (walker.rtl()) + base -= walker.width(); + + int numCodePoints = static_cast(walker.numCodePoints()); + if (fromX == -1 && from < numCodePoints) { + // |from| is within this script run. So we index the clusters log to + // find which glyph this code-point contributed to and find its x + // position. + int glyph = walker.logClusters()[from]; + fromX = base + walker.positions()[glyph].x(); + fromAdvance = walker.advances()[glyph]; + } else if (!walker.rtl()) + from -= numCodePoints; + + if (toX == -1 && to < numCodePoints) { + int glyph = walker.logClusters()[to]; + toX = base + walker.positions()[glyph].x(); + toAdvance = walker.advances()[glyph]; + } else if (!walker.rtl()) + to -= numCodePoints; + + if (!walker.rtl()) + base += walker.width(); + } + + // The position in question might be just after the text. + const int rightEdge = base; + if (fromX == -1 && !from) + fromX = leftEdge; + else if (walker.rtl()) + fromX += truncateFixedPointToInteger(fromAdvance); + + if (toX == -1 && !to) + toX = rightEdge; + + ASSERT(fromX != -1 && toX != -1); + + if (fromX < toX) + return FloatRect(point.x() + fromX, point.y(), toX - fromX, height); + + return FloatRect(point.x() + toX, point.y(), fromX - toX, height); +} + +void Font::drawComplexText(GraphicsContext* gc, TextRun const& run, + FloatPoint const& point, int, int) const +{ + if (!run.length()) + return; + + int mode = gc->textDrawingMode(); + bool fill = mode & TextModeFill; + bool stroke = mode & TextModeStroke; + if (!fill && !stroke) + return; + + SkPaint fillPaint, strokePaint; + if (fill) + setupFill(&fillPaint, gc, primaryFont()); + if (stroke) + setupStroke(&strokePaint, gc, primaryFont()); + + SkCanvas* canvas = gc->platformContext()->recordingCanvas(); + + bool haveMultipleLayers = isCanvasMultiLayered(canvas); + TextRunWalker walker(run, point.x(), point.y(), this); + walker.setWordAndLetterSpacing(wordSpacing(), letterSpacing()); + walker.setPadding(run.expansion()); + + while (walker.nextScriptRun()) { + if (fill) { + walker.fontPlatformDataForScriptRun()->setupPaint(&fillPaint); + adjustTextRenderMode(&fillPaint, haveMultipleLayers); + canvas->drawPosText(walker.glyphs(), walker.length() << 1, + walker.positions(), fillPaint); + } + if (stroke) { + walker.fontPlatformDataForScriptRun()->setupPaint(&strokePaint); + adjustTextRenderMode(&strokePaint, haveMultipleLayers); + canvas->drawPosText(walker.glyphs(), walker.length() << 1, + walker.positions(), strokePaint); + } + } + + gc->platformContext()->endRecording(); +} + +float Font::floatWidthForComplexText(const TextRun& run, + HashSet*, GlyphOverflow*) const +{ + TextRunWalker walker(run, 0, 0, this); + walker.setWordAndLetterSpacing(wordSpacing(), letterSpacing()); + return walker.widthOfFullRun(); +} + +static int glyphIndexForXPositionInScriptRun(const TextRunWalker& walker, int x) +{ + const HB_Fixed* advances = walker.advances(); + int glyphIndex; + if (walker.rtl()) { + for (glyphIndex = walker.length() - 1; glyphIndex >= 0; --glyphIndex) { + if (x < truncateFixedPointToInteger(advances[glyphIndex])) + break; + x -= truncateFixedPointToInteger(advances[glyphIndex]); + } + } else { + for (glyphIndex = 0; glyphIndex < static_cast(walker.length()); + ++glyphIndex) { + if (x < truncateFixedPointToInteger(advances[glyphIndex])) + break; + x -= truncateFixedPointToInteger(advances[glyphIndex]); + } + } + + return glyphIndex; +} + +int Font::offsetForPositionForComplexText(const TextRun& run, float x, + bool includePartialGlyphs) const +{ + // (Mac code ignores includePartialGlyphs, and they don't know what it's + // supposed to do, so we just ignore it as well.) + TextRunWalker walker(run, 0, 0, this); + walker.setWordAndLetterSpacing(wordSpacing(), letterSpacing()); + + // If this is RTL text, the first glyph from the left is actually the last + // code point. So we need to know how many code points there are total in + // order to subtract. This is different from the length of the TextRun + // because UTF-16 surrogate pairs are a single code point, but 32-bits long. + // In LTR we leave this as 0 so that we get the correct value for + // |basePosition|, below. + unsigned totalCodePoints = 0; + if (walker.rtl()) { + ssize_t offset = 0; + while (offset < run.length()) { + utf16_to_code_point(run.characters(), run.length(), &offset); + totalCodePoints++; + } + } + + unsigned basePosition = totalCodePoints; + + // For RTL: + // code-point order: abcd efg hijkl + // on screen: lkjih gfe dcba + // ^ ^ + // | | + // basePosition--| | + // totalCodePoints----| + // Since basePosition is currently the total number of code-points, the + // first thing we do is decrement it so that it's pointing to the start of + // the current script-run. + // + // For LTR, basePosition is zero so it already points to the start of the + // first script run. + while (walker.nextScriptRun()) { + if (walker.rtl()) + basePosition -= walker.numCodePoints(); + + if (x >= 0 && x < static_cast(walker.width())) { + // The x value in question is within this script run. We consider + // each glyph in presentation order and stop when we find the one + // covering this position. + const int glyphIndex = glyphIndexForXPositionInScriptRun(walker, x); + + // Now that we have a glyph index, we have to turn that into a + // code-point index. Because of ligatures, several code-points may + // have gone into a single glyph. We iterate over the clusters log + // and find the first code-point which contributed to the glyph. + + // Some shapers (i.e. Khmer) will produce cluster logs which report + // that /no/ code points contributed to certain glyphs. Because of + // this, we take any code point which contributed to the glyph in + // question, or any subsequent glyph. If we run off the end, then + // we take the last code point. + const unsigned short* log = walker.logClusters(); + for (unsigned j = 0; j < walker.numCodePoints(); ++j) { + if (log[j] >= glyphIndex) + return basePosition + j; + } + + return basePosition + walker.numCodePoints() - 1; + } + + x -= walker.width(); + + if (!walker.rtl()) + basePosition += walker.numCodePoints(); + } + + return basePosition; +} +#endif + +} diff --git a/Source/WebCore/platform/graphics/android/fonts/FontCacheAndroid.cpp b/Source/WebCore/platform/graphics/android/fonts/FontCacheAndroid.cpp new file mode 100644 index 0000000..5696a46 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/fonts/FontCacheAndroid.cpp @@ -0,0 +1,195 @@ +/* + * Copyright 2009, The Android Open Source Project + * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "FontCache.h" + +#include "Font.h" +#include "FontPlatformData.h" +#include "NotImplemented.h" +#include "SimpleFontData.h" +#include "SkPaint.h" +#include "SkTypeface.h" +#include "SkUtils.h" + +namespace WebCore { + +static const char* getFallbackFontName(const FontDescription& fontDescription) +{ + switch (fontDescription.genericFamily()) { + case FontDescription::StandardFamily: + case FontDescription::SerifFamily: + return "serif"; + case FontDescription::SansSerifFamily: + return "sans-serif"; + case FontDescription::MonospaceFamily: + return "monospace"; + case FontDescription::CursiveFamily: + return "cursive"; + case FontDescription::FantasyFamily: + return "fantasy"; + case FontDescription::NoFamily: + default: + return ""; + } +} + +static bool isFallbackFamily(String family) +{ + return family.startsWith("-webkit-") + || equalIgnoringCase(family, "serif") + || equalIgnoringCase(family, "sans-serif") + || equalIgnoringCase(family, "sans") + || equalIgnoringCase(family, "monospace") + || equalIgnoringCase(family, "times") // skia aliases for serif + || equalIgnoringCase(family, "times new roman") + || equalIgnoringCase(family, "palatino") + || equalIgnoringCase(family, "georgia") + || equalIgnoringCase(family, "baskerville") + || equalIgnoringCase(family, "goudy") + || equalIgnoringCase(family, "cursive") + || equalIgnoringCase(family, "fantasy") + || equalIgnoringCase(family, "ITC Stone Serif") + || equalIgnoringCase(family, "arial") // skia aliases for sans-serif + || equalIgnoringCase(family, "helvetica") + || equalIgnoringCase(family, "tahoma") + || equalIgnoringCase(family, "verdana") + || equalIgnoringCase(family, "courier") // skia aliases for monospace + || equalIgnoringCase(family, "courier new") + || equalIgnoringCase(family, "monaco"); +} + +static char* AtomicStringToUTF8String(const AtomicString& utf16) +{ + SkASSERT(sizeof(uint16_t) == sizeof(utf16.characters()[0])); + const uint16_t* uni = (uint16_t*)utf16.characters(); + + size_t bytes = SkUTF16_ToUTF8(uni, utf16.length(), 0); + char* utf8 = (char*)sk_malloc_throw(bytes + 1); + + (void)SkUTF16_ToUTF8(uni, utf16.length(), utf8); + utf8[bytes] = 0; + return utf8; +} + + +void FontCache::platformInit() +{ +} + +const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, const UChar* characters, int length) +{ + // since all of our fonts logically map to the fallback, we can always claim + // that each font supports all characters. + return font.primaryFont(); +} + +SimpleFontData* FontCache::getSimilarFontPlatformData(const Font& font) +{ + return 0; +} + +SimpleFontData* FontCache::getLastResortFallbackFont(const FontDescription& description) +{ + static const AtomicString sansStr("sans-serif"); + static const AtomicString serifStr("serif"); + static const AtomicString monospaceStr("monospace"); + + FontPlatformData* fontPlatformData = 0; + switch (description.genericFamily()) { + case FontDescription::SerifFamily: + fontPlatformData = getCachedFontPlatformData(description, serifStr); + break; + case FontDescription::MonospaceFamily: + fontPlatformData = getCachedFontPlatformData(description, monospaceStr); + break; + case FontDescription::SansSerifFamily: + default: + fontPlatformData = getCachedFontPlatformData(description, sansStr); + break; + } + + ASSERT(fontPlatformData); + return getCachedFontData(fontPlatformData); +} + +FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontDescription, const AtomicString& family) +{ + char* storage = 0; + const char* name = 0; + FontPlatformData* result = 0; + + if (family.length()) { + storage = AtomicStringToUTF8String(family); + name = storage; + } else + name = getFallbackFontName(fontDescription); + + int style = SkTypeface::kNormal; + if (fontDescription.weight() >= FontWeightBold) + style |= SkTypeface::kBold; + if (fontDescription.italic()) + style |= SkTypeface::kItalic; + + // CreateFromName always returns a typeface, falling back to a default font + // if the one requested is not found. Calling Equal() with a null pointer + // serves to compare the returned font against the default, with the caveat + // that the default is always of normal style. If we detect the default, we + // ignore it and allow WebCore to give us the next font on the CSS fallback + // list. The only exception is if the family name is a commonly used generic + // family, as when called by getSimilarFontPlatformData() and + // getLastResortFallbackFont(). In this case, the default font is an + // acceptable result. + + SkTypeface* tf = SkTypeface::CreateFromName(name, SkTypeface::kNormal); + + if (!SkTypeface::Equal(tf, 0) || isFallbackFamily(family.string())) { + // We had to use normal styling to see if this was a default font. If + // we need bold or italic, replace with the corrected typeface. + if (style != SkTypeface::kNormal) { + tf->unref(); + tf = SkTypeface::CreateFromName(name, (SkTypeface::Style)style); + } + + result = new FontPlatformData(tf, fontDescription.computedSize(), + (style & SkTypeface::kBold) && !tf->isBold(), + (style & SkTypeface::kItalic) && !tf->isItalic(), + fontDescription.orientation(), + fontDescription.textOrientation()); + } + + tf->unref(); + sk_free(storage); + return result; +} + + // new as of SVN change 36269, Sept 8, 2008 +void FontCache::getTraitsInFamily(const AtomicString& familyName, Vector& traitsMasks) +{ + // Don't understand this yet, but it seems safe to leave unimplemented +} + +} diff --git a/Source/WebCore/platform/graphics/android/fonts/FontCustomPlatformData.cpp b/Source/WebCore/platform/graphics/android/fonts/FontCustomPlatformData.cpp new file mode 100644 index 0000000..693386e --- /dev/null +++ b/Source/WebCore/platform/graphics/android/fonts/FontCustomPlatformData.cpp @@ -0,0 +1,89 @@ +/* + * Copyright 2008, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "FontCustomPlatformData.h" + +#include "SkTypeface.h" +#include "SkStream.h" +#include "SharedBuffer.h" +#include "FontPlatformData.h" + +namespace WebCore { + +FontCustomPlatformData::FontCustomPlatformData(SkTypeface* face) +{ + SkSafeRef(face); + m_typeface = face; +} + +FontCustomPlatformData::~FontCustomPlatformData() +{ + SkSafeUnref(m_typeface); + // the unref is enough to release the font data... +} + +FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, + FontOrientation fontOrientation, TextOrientation textOrientation, FontWidthVariant, FontRenderingMode) +{ + // turn bold/italic into fakeBold/fakeItalic + if (m_typeface != NULL) { + if (m_typeface->isBold() == bold) + bold = false; + if (m_typeface->isItalic() == italic) + italic = false; + } + return FontPlatformData(m_typeface, size, bold, italic, fontOrientation, textOrientation); +} + +FontCustomPlatformData* createFontCustomPlatformData(SharedBuffer* buffer) +{ + // pass true until we know how we can share the data, and not have to + // make a copy of it. + SkStream* stream = new SkMemoryStream(buffer->data(), buffer->size(), true); + SkTypeface* face = SkTypeface::CreateFromStream(stream); + // Release the stream. + stream->unref(); + if (0 == face) { + SkDebugf("--------- SkTypeface::CreateFromBuffer failed %d\n", + buffer->size()); + return NULL; + } + + SkAutoUnref aur(face); + + return new FontCustomPlatformData(face); +} + +bool FontCustomPlatformData::supportsFormat(const String& format) +{ + return equalIgnoringCase(format, "truetype") || equalIgnoringCase(format, "opentype") +#if ENABLE(OPENTYPE_SANITIZER) + || equalIgnoringCase(format, "woff") +#endif + ; +} + +} diff --git a/Source/WebCore/platform/graphics/android/fonts/FontCustomPlatformData.h b/Source/WebCore/platform/graphics/android/fonts/FontCustomPlatformData.h new file mode 100644 index 0000000..47e5e71 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/fonts/FontCustomPlatformData.h @@ -0,0 +1,62 @@ +/* + * Copyright 2008, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef FontCustomPlatformData_h +#define FontCustomPlatformData_h + +#include "FontOrientation.h" +#include "FontRenderingMode.h" +#include "FontWidthVariant.h" +#include "TextOrientation.h" +#include +#include + +class SkTypeface; + +namespace WebCore { + +class FontPlatformData; +class SharedBuffer; + +class FontCustomPlatformData { + WTF_MAKE_NONCOPYABLE(FontCustomPlatformData); +public: + FontCustomPlatformData(SkTypeface* face); + ~FontCustomPlatformData(); + + SkTypeface* typeface() const { return m_typeface; } + + FontPlatformData fontPlatformData(int size, bool bold, bool italic, FontOrientation, TextOrientation, FontWidthVariant, FontRenderingMode); + + static bool supportsFormat(const String&); +private: + SkTypeface* m_typeface; +}; + +FontCustomPlatformData* createFontCustomPlatformData(SharedBuffer* buffer); + +} // namespace WebCore + +#endif // FontCustomPlatformData_h diff --git a/Source/WebCore/platform/graphics/android/fonts/FontDataAndroid.cpp b/Source/WebCore/platform/graphics/android/fonts/FontDataAndroid.cpp new file mode 100644 index 0000000..88822df --- /dev/null +++ b/Source/WebCore/platform/graphics/android/fonts/FontDataAndroid.cpp @@ -0,0 +1,146 @@ +/* + * Copyright 2009, The Android Open Source Project + * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#include "EmojiFont.h" +#include "Font.h" +#include "FontCache.h" +#include "SimpleFontData.h" +#include "FloatRect.h" +#include "FontDescription.h" +#include "SkFontHost.h" +#include "SkPaint.h" +#include "SkTypeface.h" +#include "SkTime.h" + +using namespace android; + +namespace WebCore { + +void SimpleFontData::platformInit() +{ + SkPaint paint; + SkPaint::FontMetrics skiaFontMetrics; + + m_platformData.setupPaint(&paint); + paint.getFontMetrics(&skiaFontMetrics); + + float d = SkScalarToFloat(skiaFontMetrics.fDescent); + float s = SkScalarToFloat(skiaFontMetrics.fDescent - skiaFontMetrics.fAscent); + float a = s - d; + + m_fontMetrics.setAscent(a); + m_fontMetrics.setDescent(d); + m_fontMetrics.setXHeight(SkScalarToFloat(-skiaFontMetrics.fAscent) * 0.56f); // hack I stole from the window's port + float lineGap = SkScalarToFloat(skiaFontMetrics.fLeading); + if (platformData().orientation() == Vertical && lineGap == 0) { + lineGap = skiaFontMetrics.fAvgCharWidth * 0.56f; + } + m_fontMetrics.setLineGap(lineGap); + m_fontMetrics.setLineSpacing(a + d + lineGap); + + if (platformData().orientation() == Vertical && !isTextOrientationFallback()) { + static const uint32_t vheaTag = SkSetFourByteTag('v', 'h', 'e', 'a'); + static const uint32_t vorgTag = SkSetFourByteTag('V', 'O', 'R', 'G'); + const SkFontID fontID = m_platformData.uniqueID(); + size_t vheaSize = SkFontHost::GetTableSize(fontID, vheaTag); + size_t vorgSize = SkFontHost::GetTableSize(fontID, vorgTag); + if ((vheaSize > 0) || (vorgSize > 0)) + m_hasVerticalGlyphs = true; + } +} + +void SimpleFontData::platformCharWidthInit() +{ + m_avgCharWidth = 0.f; + m_maxCharWidth = 0.f; + initCharWidths(); +} + +void SimpleFontData::platformDestroy() +{ +} + +SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const +{ + if (!m_derivedFontData) + m_derivedFontData = DerivedFontData::create(isCustomFont()); + if (!m_derivedFontData->smallCaps) + m_derivedFontData->smallCaps = new SimpleFontData(FontPlatformData(m_platformData, fontDescription.computedSize() * 0.7f)); + + return m_derivedFontData->smallCaps.get(); +} + +SimpleFontData* SimpleFontData::emphasisMarkFontData(const FontDescription& fontDescription) const +{ + if (!m_derivedFontData) + m_derivedFontData = DerivedFontData::create(isCustomFont()); + if (!m_derivedFontData->emphasisMark) + m_derivedFontData->emphasisMark = new SimpleFontData(FontPlatformData(m_platformData, fontDescription.computedSize() * 0.5f)); + + return m_derivedFontData->emphasisMark.get(); +} + +bool SimpleFontData::containsCharacters(const UChar* characters, int length) const +{ + SkPaint paint; + + m_platformData.setupPaint(&paint); + paint.setTextEncoding(SkPaint::kUTF16_TextEncoding); + return paint.containsText(characters, length << 1); +} + +void SimpleFontData::determinePitch() +{ + m_treatAsFixedPitch = m_platformData.isFixedPitch(); +} + +FloatRect SimpleFontData::platformBoundsForGlyph(Glyph) const +{ + return FloatRect(); +} + +float SimpleFontData::platformWidthForGlyph(Glyph glyph) const +{ + SkASSERT(sizeof(glyph) == 2); // compile-time assert + + SkPaint paint; + + m_platformData.setupPaint(&paint); + + float advanceWidth; + if (EmojiFont::IsEmojiGlyph(glyph)) + advanceWidth = EmojiFont::GetAdvanceWidth(glyph, paint); + else { + paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); + advanceWidth = SkScalarToFloat(paint.measureText(&glyph, 2)); + } + return advanceWidth; +} + + +} diff --git a/Source/WebCore/platform/graphics/android/fonts/FontPlatformData.h b/Source/WebCore/platform/graphics/android/fonts/FontPlatformData.h new file mode 100644 index 0000000..1e46971 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/fonts/FontPlatformData.h @@ -0,0 +1,131 @@ +/* + * Copyright 2009, The Android Open Source Project + * Copyright (C) 2006 Apple Computer, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// This file is part of the internal font implementation. It should not be included by anyone other than +// FontMac.cpp, FontWin.cpp and Font.cpp. + +#ifndef FontPlatformData_h +#define FontPlatformData_h + +#include "FontOrientation.h" +#include "TextOrientation.h" +#include + +#ifndef NDEBUG +#include "PlatformString.h" +#endif + +class SkPaint; +class SkTypeface; + +struct HB_FaceRec_; + +namespace WebCore { + +class FontPlatformData { +public: + static FontPlatformData Deleted() { + return FontPlatformData(NULL, -1, false, false); + } + + FontPlatformData(); + FontPlatformData(const FontPlatformData&); + FontPlatformData(SkTypeface*, float textSize, bool fakeBold, bool fakeItalic, + FontOrientation = Horizontal, TextOrientation = TextOrientationVerticalRight); + FontPlatformData(const FontPlatformData& src, float textSize); + FontPlatformData(float size, bool syntheticBold, bool syntheticOblique); + FontPlatformData(const FontPlatformData& src, SkTypeface* typeface); + + ~FontPlatformData(); + + FontPlatformData(WTF::HashTableDeletedValueType) + : mTypeface(hashTableDeletedFontValue()) { } + bool isHashTableDeletedValue() const { + return mTypeface == hashTableDeletedFontValue(); + } + + FontOrientation orientation() const { return mOrientation; } + void setOrientation(FontOrientation orientation) { mOrientation = orientation; } + FontPlatformData& operator=(const FontPlatformData&); + bool operator==(const FontPlatformData& a) const; + + void setupPaint(SkPaint*) const; + + // ------------------------------------------------------------------------- + // Return Skia's unique id for this font. This encodes both the style and + // the font's file name so refers to a single face. + // ------------------------------------------------------------------------- + uint32_t uniqueID() const; + + float size() const { return mTextSize; } + unsigned hash() const; + int emSizeInFontUnits() const; + bool isFixedPitch() const; + +#ifndef NDEBUG + String description() const { return ""; } +#endif + + HB_FaceRec_* harfbuzzFace() const; + SkTypeface* typeface() const { return mTypeface; } + +private: + class RefCountedHarfbuzzFace : public RefCounted { + public: + static PassRefPtr create(HB_FaceRec_* harfbuzzFace) + { + return adoptRef(new RefCountedHarfbuzzFace(harfbuzzFace)); + } + + ~RefCountedHarfbuzzFace(); + + HB_FaceRec_* face() const { return m_harfbuzzFace; } + + private: + RefCountedHarfbuzzFace(HB_FaceRec_* harfbuzzFace) : m_harfbuzzFace(harfbuzzFace) + { + } + + HB_FaceRec_* m_harfbuzzFace; + }; + + SkTypeface* mTypeface; + float mTextSize; + mutable int mEmSizeInFontUnits; + bool mFakeBold; + bool mFakeItalic; + FontOrientation mOrientation; + TextOrientation mTextOrientation; + mutable RefPtr m_harfbuzzFace; + + static SkTypeface* hashTableDeletedFontValue() { + return reinterpret_cast(-1); + } +}; + +} /* namespace */ + +#endif diff --git a/Source/WebCore/platform/graphics/android/fonts/FontPlatformDataAndroid.cpp b/Source/WebCore/platform/graphics/android/fonts/FontPlatformDataAndroid.cpp new file mode 100644 index 0000000..fc254c0 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/fonts/FontPlatformDataAndroid.cpp @@ -0,0 +1,273 @@ +/* + * Copyright 2009, The Android Open Source Project + * Copyright (C) 2006 Apple Computer, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +//This file is part of the internal font implementation. It should not be included by anyone other than +// FontMac.cpp, FontWin.cpp and Font.cpp. + +#include "config.h" +#include "FontPlatformData.h" + +#ifdef SUPPORT_COMPLEX_SCRIPTS +#include "HarfbuzzSkia.h" +#endif +#include "SkAdvancedTypefaceMetrics.h" +#include "SkPaint.h" +#include "SkTypeface.h" + +//#define TRACE_FONTPLATFORMDATA_LIFE +//#define COUNT_FONTPLATFORMDATA_LIFE + +#ifdef COUNT_FONTPLATFORMDATA_LIFE +static int gCount; +static int gMaxCount; + +static void inc_count() +{ + if (++gCount > gMaxCount) + { + gMaxCount = gCount; + SkDebugf("---------- FontPlatformData %d\n", gMaxCount); + } +} + +static void dec_count() { --gCount; } +#else + #define inc_count() + #define dec_count() +#endif + +#ifdef TRACE_FONTPLATFORMDATA_LIFE + #define trace(num) SkDebugf("FontPlatformData%d %p %g %d %d\n", num, mTypeface, mTextSize, mFakeBold, mFakeItalic) +#else + #define trace(num) +#endif + +namespace WebCore { + +FontPlatformData::RefCountedHarfbuzzFace::~RefCountedHarfbuzzFace() +{ +#ifdef SUPPORT_COMPLEX_SCRIPTS + HB_FreeFace(m_harfbuzzFace); +#endif +} + +FontPlatformData::FontPlatformData() + : mTypeface(NULL), mTextSize(0), mEmSizeInFontUnits(0), mFakeBold(false), mFakeItalic(false), + mOrientation(Horizontal), mTextOrientation(TextOrientationVerticalRight) +{ + inc_count(); + trace(1); +} + +FontPlatformData::FontPlatformData(const FontPlatformData& src) +{ + if (hashTableDeletedFontValue() != src.mTypeface) { + SkSafeRef(src.mTypeface); + } + + mTypeface = src.mTypeface; + mTextSize = src.mTextSize; + mEmSizeInFontUnits = src.mEmSizeInFontUnits; + mFakeBold = src.mFakeBold; + mFakeItalic = src.mFakeItalic; + m_harfbuzzFace = src.m_harfbuzzFace; + mOrientation = src.mOrientation; + mTextOrientation = src.mTextOrientation; + + inc_count(); + trace(2); +} + +FontPlatformData::FontPlatformData(SkTypeface* tf, float textSize, bool fakeBold, bool fakeItalic, + FontOrientation orientation, TextOrientation textOrientation) + : mTypeface(tf), mTextSize(textSize), mEmSizeInFontUnits(0), mFakeBold(fakeBold), mFakeItalic(fakeItalic), + mOrientation(orientation), mTextOrientation(textOrientation) +{ + if (hashTableDeletedFontValue() != mTypeface) { + SkSafeRef(mTypeface); + } + + inc_count(); + trace(3); +} + +FontPlatformData::FontPlatformData(const FontPlatformData& src, float textSize) + : mTypeface(src.mTypeface), mTextSize(textSize), mEmSizeInFontUnits(src.mEmSizeInFontUnits), mFakeBold(src.mFakeBold), mFakeItalic(src.mFakeItalic), + mOrientation(src.mOrientation), mTextOrientation(src.mTextOrientation), m_harfbuzzFace(src.m_harfbuzzFace) +{ + if (hashTableDeletedFontValue() != mTypeface) { + SkSafeRef(mTypeface); + } + + inc_count(); + trace(4); +} + +FontPlatformData::FontPlatformData(float size, bool bold, bool oblique) + : mTypeface(NULL), mTextSize(size), mEmSizeInFontUnits(0), mFakeBold(bold), mFakeItalic(oblique), + mOrientation(Horizontal), mTextOrientation(TextOrientationVerticalRight) +{ + inc_count(); + trace(5); +} + +FontPlatformData::FontPlatformData(const FontPlatformData& src, SkTypeface* tf) + : mTypeface(tf), mTextSize(src.mTextSize), mEmSizeInFontUnits(0), mFakeBold(src.mFakeBold), + mFakeItalic(src.mFakeItalic), mOrientation(src.mOrientation), + mTextOrientation(src.mTextOrientation) +{ + if (hashTableDeletedFontValue() != mTypeface) { + SkSafeRef(mTypeface); + } + + inc_count(); + trace(6); +} + +FontPlatformData::~FontPlatformData() +{ + dec_count(); +#ifdef TRACE_FONTPLATFORMDATA_LIFE + SkDebugf("----------- ~FontPlatformData\n"); +#endif + + if (hashTableDeletedFontValue() != mTypeface) { + SkSafeUnref(mTypeface); + } +} + +int FontPlatformData::emSizeInFontUnits() const +{ + if (mEmSizeInFontUnits) + return mEmSizeInFontUnits; + + SkAdvancedTypefaceMetrics* metrics = 0; + if (mTypeface) + metrics = mTypeface->getAdvancedTypefaceMetrics(SkAdvancedTypefaceMetrics::kNo_PerGlyphInfo); + if (metrics) { + mEmSizeInFontUnits = metrics->fEmSize; + metrics->unref(); + } else + mEmSizeInFontUnits = 1000; // default value copied from Skia. + return mEmSizeInFontUnits; +} + +FontPlatformData& FontPlatformData::operator=(const FontPlatformData& src) +{ + if (hashTableDeletedFontValue() != src.mTypeface) { + SkSafeRef(src.mTypeface); + } + if (hashTableDeletedFontValue() != mTypeface) { + SkSafeUnref(mTypeface); + } + + mTypeface = src.mTypeface; + mEmSizeInFontUnits = src.mEmSizeInFontUnits; + mTextSize = src.mTextSize; + mFakeBold = src.mFakeBold; + mFakeItalic = src.mFakeItalic; + m_harfbuzzFace = src.m_harfbuzzFace; + mOrientation = src.mOrientation; + mTextOrientation = src.mTextOrientation; + + return *this; +} + +void FontPlatformData::setupPaint(SkPaint* paint) const +{ + if (hashTableDeletedFontValue() == mTypeface) + paint->setTypeface(0); + else + paint->setTypeface(mTypeface); + + paint->setAntiAlias(true); + paint->setSubpixelText(true); + paint->setHinting(SkPaint::kSlight_Hinting); + paint->setTextSize(SkFloatToScalar(mTextSize)); + paint->setFakeBoldText(mFakeBold); + paint->setTextSkewX(mFakeItalic ? -SK_Scalar1/4 : 0); +#ifndef SUPPORT_COMPLEX_SCRIPTS + paint->setTextEncoding(SkPaint::kUTF16_TextEncoding); +#endif +} + +uint32_t FontPlatformData::uniqueID() const +{ + if (hashTableDeletedFontValue() == mTypeface) + return SkTypeface::UniqueID(0); + else + return SkTypeface::UniqueID(mTypeface); +} + +bool FontPlatformData::operator==(const FontPlatformData& a) const +{ + return mTypeface == a.mTypeface && + mTextSize == a.mTextSize && + mFakeBold == a.mFakeBold && + mFakeItalic == a.mFakeItalic && + mOrientation == a.mOrientation && + mTextOrientation == a.mTextOrientation; +} + +unsigned FontPlatformData::hash() const +{ + unsigned h; + + if (hashTableDeletedFontValue() == mTypeface) { + h = reinterpret_cast(mTypeface); + } else { + h = SkTypeface::UniqueID(mTypeface); + } + + uint32_t sizeAsInt = *reinterpret_cast(&mTextSize); + + h ^= 0x01010101 * ((static_cast(mTextOrientation) << 3) | (static_cast(mOrientation) << 2) | + ((int)mFakeBold << 1) | (int)mFakeItalic); + h ^= sizeAsInt; + return h; +} + +bool FontPlatformData::isFixedPitch() const +{ + if (mTypeface && (mTypeface != hashTableDeletedFontValue())) + return mTypeface->isFixedWidth(); + else + return false; +} + +HB_FaceRec_* FontPlatformData::harfbuzzFace() const +{ +#ifdef SUPPORT_COMPLEX_SCRIPTS + if (!m_harfbuzzFace) + m_harfbuzzFace = RefCountedHarfbuzzFace::create( + HB_NewFace(const_cast(this), harfbuzzSkiaGetTable)); + + return m_harfbuzzFace->face(); +#else + return NULL; +#endif +} +} diff --git a/Source/WebCore/platform/graphics/android/fonts/GlyphMapAndroid.cpp b/Source/WebCore/platform/graphics/android/fonts/GlyphMapAndroid.cpp new file mode 100644 index 0000000..a327b79 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/fonts/GlyphMapAndroid.cpp @@ -0,0 +1,146 @@ +/* + * Copyright 2009, The Android Open Source Project + * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#include "EmojiFont.h" +#include "Font.h" +#include "GlyphPageTreeNode.h" +#include "HarfbuzzSkia.h" +#include "SimpleFontData.h" +#include "SkFontHost.h" +#include "SkPaint.h" +#include "SkTemplates.h" +#include "SkUtils.h" +#include "VerticalTextMap.h" + + +using namespace android; + +namespace WebCore { + +#define NO_BREAK_SPACE_UNICHAR 0xA0 + +static int substituteWithVerticalGlyphs(const FontPlatformData& platformData, uint16_t* glyphs, unsigned bufferLength) +{ + HB_FaceRec_* hbFace = platformData.harfbuzzFace(); + if (!hbFace->gsub) { + // if there is no GSUB table, treat it as not covered + return 0Xffff; + } + + HB_Buffer buffer; + hb_buffer_new(&buffer); + for (unsigned i = 0; i < bufferLength; ++i) + hb_buffer_add_glyph(buffer, glyphs[i], 0, i); + + HB_UShort scriptIndex; + HB_UShort featureIndex; + + HB_GSUB_Select_Script(hbFace->gsub, HB_MAKE_TAG('D', 'F', 'L', 'T'), &scriptIndex); + HB_GSUB_Select_Feature(hbFace->gsub, HB_MAKE_TAG('v', 'e', 'r', 't'), scriptIndex, 0xffff, &featureIndex); + HB_GSUB_Add_Feature(hbFace->gsub, featureIndex, 1); + HB_GSUB_Select_Feature(hbFace->gsub, HB_MAKE_TAG('v', 'r', 't', '2'), scriptIndex, 0xffff, &featureIndex); + HB_GSUB_Add_Feature(hbFace->gsub, featureIndex, 1); + + int error = HB_GSUB_Apply_String(hbFace->gsub, buffer); + if (!error) { + for (unsigned i = 0; i < bufferLength; ++i) + glyphs[i] = static_cast(buffer->out_string[i].gindex); + } + return error; +} + +bool GlyphPage::fill(unsigned offset, unsigned length, UChar* buffer, unsigned bufferLength, const SimpleFontData* fontData) +{ + if (SkUTF16_IsHighSurrogate(buffer[bufferLength-1])) { + SkDebugf("%s last char is high-surrogate", __FUNCTION__); + return false; + } + + SkPaint paint; + fontData->platformData().setupPaint(&paint); + paint.setTextEncoding(SkPaint::kUTF16_TextEncoding); + + SkAutoSTMalloc glyphStorage(length); + uint16_t* glyphs = glyphStorage.get(); + UChar *textBuffer = buffer; + UChar vTextBuffer[bufferLength]; + + if (fontData->platformData().orientation() == Vertical && !fontData->hasVerticalGlyphs()) { + // Convert to vertical form if there is no vertical glyphs. + for (unsigned i = 0; i < bufferLength; ++i) { + vTextBuffer[i] = VerticalTextMap::getVerticalForm(buffer[i]); + if (!vTextBuffer[i]) + vTextBuffer[i] = buffer[i]; + } + textBuffer = vTextBuffer; + } + + unsigned count = paint.textToGlyphs(textBuffer, bufferLength << 1, glyphs); + if (count != length) { + SkDebugf("%s count != length\n", __FUNCTION__); + return false; + } + + if (fontData->hasVerticalGlyphs()) { + bool lookVariants = false; + for (unsigned i = 0; i < bufferLength; ++i) { + if (!Font::isCJKIdeograph(textBuffer[i])) { + lookVariants = true; + continue; + } + } + if (lookVariants) + substituteWithVerticalGlyphs(fontData->platformData(), glyphs, bufferLength); + } + + unsigned allGlyphs = 0; // track if any of the glyphIDs are non-zero + + // search for emoji. If we knew for sure that buffer was a contiguous range + // of chars, we could quick-reject the range to avoid this loop (usually) + if (EmojiFont::IsAvailable()) { + const UChar* curr = textBuffer; + for (unsigned i = 0; i < length; i++) { + SkUnichar uni = SkUTF16_NextUnichar(&curr); + uint16_t glyphID = glyphs[i]; + // only sniff if the normal font failed to recognize it + if (!glyphID) + glyphID = EmojiFont::UnicharToGlyph(uni); + setGlyphDataForIndex(offset + i, glyphID, fontData); + allGlyphs |= glyphID; + } + } else { + for (unsigned i = 0; i < length; i++) { + uint16_t glyphID = glyphs[i]; + setGlyphDataForIndex(offset + i, glyphID, fontData); + allGlyphs |= glyphID; + } + } + return allGlyphs != 0; +} + +} diff --git a/Source/WebCore/platform/graphics/android/fonts/HarfbuzzSkia.cpp b/Source/WebCore/platform/graphics/android/fonts/HarfbuzzSkia.cpp new file mode 100644 index 0000000..7c3a6b4 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/fonts/HarfbuzzSkia.cpp @@ -0,0 +1,221 @@ +/* + * Copyright 2010, The Android Open Source Project + * Copyright 2010, Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#include "FontPlatformData.h" + +#include +#include +#include +#include +#include +#include +#include + +extern "C" { +#include "harfbuzz-shaper.h" +} + +// This file implements the callbacks which Harfbuzz requires by using Skia +// calls. See the Harfbuzz source for references about what these callbacks do. + +namespace WebCore { + +static HB_Fixed SkiaScalarToHarfbuzzFixed(SkScalar value) +{ + // HB_Fixed is a 26.6 fixed point format. + return value * 64; +} + +static HB_Bool stringToGlyphs(HB_Font hbFont, const HB_UChar16* characters, hb_uint32 length, HB_Glyph* glyphs, hb_uint32* glyphsSize, HB_Bool isRTL) +{ + FontPlatformData* font = reinterpret_cast(hbFont->userData); + SkPaint paint; + + font->setupPaint(&paint); + paint.setTextEncoding(SkPaint::kUTF16_TextEncoding); + int numGlyphs = paint.textToGlyphs(characters, length * sizeof(uint16_t), reinterpret_cast(glyphs)); + + // HB_Glyph is 32-bit, but Skia outputs only 16-bit numbers. So our + // |glyphs| array needs to be converted. + for (int i = numGlyphs - 1; i >= 0; --i) { + uint16_t value; + // We use a memcpy to avoid breaking strict aliasing rules. + memcpy(&value, reinterpret_cast(glyphs) + sizeof(uint16_t) * i, sizeof(value)); + glyphs[i] = value; + } + + *glyphsSize = numGlyphs; + return 1; +} + +static void glyphsToAdvances(HB_Font hbFont, const HB_Glyph* glyphs, hb_uint32 numGlyphs, HB_Fixed* advances, int flags) +{ + FontPlatformData* font = reinterpret_cast(hbFont->userData); + SkPaint paint; + + font->setupPaint(&paint); + paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); + + OwnArrayPtr glyphs16 = adoptArrayPtr(new uint16_t[numGlyphs]); + if (!glyphs16.get()) + return; + for (unsigned i = 0; i < numGlyphs; ++i) + glyphs16[i] = glyphs[i]; + paint.getTextWidths(glyphs16.get(), numGlyphs * sizeof(uint16_t), reinterpret_cast(advances)); + + // The |advances| values which Skia outputs are SkScalars, which are floats + // in Chromium. However, Harfbuzz wants them in 26.6 fixed point format. + // These two formats are both 32-bits long. + for (unsigned i = 0; i < numGlyphs; ++i) { + float value; + // We use a memcpy to avoid breaking strict aliasing rules. + memcpy(&value, reinterpret_cast(advances) + sizeof(float) * i, sizeof(value)); + advances[i] = SkiaScalarToHarfbuzzFixed(value); + } +} + +static HB_Bool canRender(HB_Font hbFont, const HB_UChar16* characters, hb_uint32 length) +{ + FontPlatformData* font = reinterpret_cast(hbFont->userData); + SkPaint paint; + + font->setupPaint(&paint); + paint.setTextEncoding(SkPaint::kUTF16_TextEncoding); + + OwnArrayPtr glyphs16 = adoptArrayPtr(new uint16_t[length]); + glyphs16.get(); + int numGlyphs = paint.textToGlyphs(characters, length * sizeof(uint16_t), glyphs16.get()); + + for (int i = 0; i < numGlyphs; ++i) { + if (!glyphs16[i]) + return false; + } + + return true; +} + +static HB_Error getOutlinePoint(HB_Font hbFont, HB_Glyph glyph, int flags, hb_uint32 point, HB_Fixed* xPos, HB_Fixed* yPos, hb_uint32* resultingNumPoints) +{ + FontPlatformData* font = reinterpret_cast(hbFont->userData); + SkPaint paint; + + if (flags & HB_ShaperFlag_UseDesignMetrics) + return HB_Err_Invalid_Argument; // This is requesting pre-hinted positions. We can't support this. + + font->setupPaint(&paint); + paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); + uint16_t glyph16 = glyph; + SkPath path; + paint.getTextPath(&glyph16, sizeof(glyph16), 0, 0, &path); + uint32_t numPoints = path.getPoints(0, 0); + if (point >= numPoints) + return HB_Err_Invalid_SubTable; + SkPoint* points = reinterpret_cast(fastMalloc(sizeof(SkPoint) * (point + 1))); + if (!points) + return HB_Err_Invalid_SubTable; + // Skia does let us get a single point from the path. + path.getPoints(points, point + 1); + *xPos = SkiaScalarToHarfbuzzFixed(points[point].fX); + *yPos = SkiaScalarToHarfbuzzFixed(points[point].fY); + *resultingNumPoints = numPoints; + fastFree(points); + + return HB_Err_Ok; +} + +static void getGlyphMetrics(HB_Font hbFont, HB_Glyph glyph, HB_GlyphMetrics* metrics) +{ + FontPlatformData* font = reinterpret_cast(hbFont->userData); + SkPaint paint; + + font->setupPaint(&paint); + paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); + uint16_t glyph16 = glyph; + SkScalar width; + SkRect bounds; + paint.getTextWidths(&glyph16, sizeof(glyph16), &width, &bounds); + + metrics->x = SkiaScalarToHarfbuzzFixed(bounds.fLeft); + metrics->y = SkiaScalarToHarfbuzzFixed(bounds.fTop); + metrics->width = SkiaScalarToHarfbuzzFixed(bounds.width()); + metrics->height = SkiaScalarToHarfbuzzFixed(bounds.height()); + + metrics->xOffset = SkiaScalarToHarfbuzzFixed(width); + // We can't actually get the |y| correct because Skia doesn't export + // the vertical advance. However, nor we do ever render vertical text at + // the moment so it's unimportant. + metrics->yOffset = 0; +} + +static HB_Fixed getFontMetric(HB_Font hbFont, HB_FontMetric metric) +{ + FontPlatformData* font = reinterpret_cast(hbFont->userData); + SkPaint paint; + + font->setupPaint(&paint); + SkPaint::FontMetrics skiaMetrics; + paint.getFontMetrics(&skiaMetrics); + + switch (metric) { + case HB_FontAscent: + return SkiaScalarToHarfbuzzFixed(-skiaMetrics.fAscent); + // We don't support getting the rest of the metrics and Harfbuzz doesn't seem to need them. + default: + return 0; + } +} + +HB_FontClass harfbuzzSkiaClass = { + stringToGlyphs, + glyphsToAdvances, + canRender, + getOutlinePoint, + getGlyphMetrics, + getFontMetric, +}; + +HB_Error harfbuzzSkiaGetTable(void* voidface, const HB_Tag tag, HB_Byte* buffer, HB_UInt* len) +{ + FontPlatformData* font = reinterpret_cast(voidface); + + const size_t tableSize = SkFontHost::GetTableSize(font->uniqueID(), tag); + if (!tableSize) + return HB_Err_Invalid_Argument; + // If Harfbuzz specified a NULL buffer then it's asking for the size of the table. + if (!buffer) { + *len = tableSize; + return HB_Err_Ok; + } + + if (*len < tableSize) + return HB_Err_Invalid_Argument; + SkFontHost::GetTableData(font->uniqueID(), tag, 0, tableSize, buffer); + return HB_Err_Ok; +} + +} // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/fonts/HarfbuzzSkia.h b/Source/WebCore/platform/graphics/android/fonts/HarfbuzzSkia.h new file mode 100644 index 0000000..d26bbe2 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/fonts/HarfbuzzSkia.h @@ -0,0 +1,40 @@ +/* + * Copyright 2010, The Android Open Source Project + * Copyright 2010, Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef HarfbuzzSkia_h +#define HarfbuzzSkia_h + +extern "C" { +#include "harfbuzz-shaper.h" +#include "harfbuzz-unicode.h" +} + +namespace WebCore { + HB_Error harfbuzzSkiaGetTable(void* voidface, const HB_Tag, HB_Byte* buffer, HB_UInt* len); + extern const HB_FontClass harfbuzzSkiaClass; +} // namespace WebCore + +#endif diff --git a/Source/WebCore/platform/graphics/android/fonts/VerticalTextMap.cpp b/Source/WebCore/platform/graphics/android/fonts/VerticalTextMap.cpp new file mode 100644 index 0000000..42aa385 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/fonts/VerticalTextMap.cpp @@ -0,0 +1,106 @@ +/* + * Copyright 2011, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "config.h" +#include "VerticalTextMap.h" + +#include +#include +#include +#include + +static const UChar vTextCnvTable[][2] = { + {0x0021, 0xfe15}, // exclamation mark + {0x0028, 0xfe35}, // left paren + {0x0029, 0xfe36}, // right paren + {0x002c, 0xfe10}, // comma + {0x002d, 0xfe32}, // hyphen + {0x003a, 0xfe30}, // colon + {0x003b, 0xfe14}, // semicolon + {0x003f, 0xfe16}, // question mark + {0x005b, 0xfe47}, // left square bracket + {0x005d, 0xfe48}, // right square bracket + {0x007b, 0xfe37}, // left curly bracket + {0x007d, 0xfe38}, // right curly bracket + {0x007e, 0x007c}, // tilde to vertical line + {0x00ab, 0xfe3d}, // left pointing double angle quotation mark + {0x00bb, 0xfe3e}, // right pointing double angle quotation mark + {0x2010, 0xfe32}, // hyphen + {0x2013, 0xfe32}, // en dash + {0x2014, 0xfe31}, // em dash + {0x2015, 0xfe31}, // horizontal bar + {0x2025, 0xfe30}, // two dot leader + {0x2026, 0xfe19}, // three dot leader + {0x3001, 0xfe11}, // Ideographic comma + {0x3002, 0xfe12}, // Ideographic full stop + {0x3008, 0xfe3f}, // left angle bracket + {0x3009, 0xfe40}, // right angle bracket + {0x300a, 0xfe3d}, // left double angle bracket + {0x300b, 0xfe3e}, // right double angle bracket + {0x300c, 0xfe41}, // left corner bracket + {0x300d, 0xfe42}, // right corner bracket + {0x300e, 0xfe43}, // left white corner bracket + {0x300f, 0xfe44}, // right white corner bracket + {0x3010, 0xfe3b}, // left black lenticular bracket + {0x3011, 0xfe3c}, // right black lenticular bracket + {0x3014, 0xfe39}, // left black lenticular bracket + {0x3015, 0xfe3a}, // right tortise shell bracket + {0x3016, 0xfe17}, // left white lenticular bracket + {0x3017, 0xfe18}, // right white lenticular bracket + {0x30fc, 0x3021}, // prolonged sound + {0xfe4f, 0xfe34}, // wavy low line + {0xff08, 0xfe35}, // full width left paren + {0xff09, 0xfe36}, // full width right paren + {0xff0c, 0xfe10}, // full width comma + {0xff3b, 0xfe47}, // full width left square bracket + {0xff3d, 0xfe48}, // full width right square bracket + {0xff5b, 0xfe37}, // full width left curly bracket + {0xff5c, 0xfe31}, // fullwidth vertical line + {0xff5d, 0xfe38}, // full width right curly bracket + {0xff5e, 0x007c}, // tilde to vertical line + {0xff64, 0xfe11}, // halfwidth ideo comma + {0xff61, 0xfe12}, // halfwidth ideo full stop +}; + +namespace WebCore { + +static WTF::Mutex verticalTextHashMapMutex; +static HashMap* verticalTextHashMap = 0; + +UChar VerticalTextMap::getVerticalForm(UChar c) { + { + MutexLocker lock(verticalTextHashMapMutex); + if (!verticalTextHashMap) { + // Lazy initialization. + verticalTextHashMap = new HashMap; + for (size_t i = 0; i < WTF_ARRAY_LENGTH(vTextCnvTable); ++i) + verticalTextHashMap->set(vTextCnvTable[i][0], vTextCnvTable[i][1]); + } + } + return verticalTextHashMap->get(c); +} + +} diff --git a/Source/WebCore/platform/graphics/android/fonts/VerticalTextMap.h b/Source/WebCore/platform/graphics/android/fonts/VerticalTextMap.h new file mode 100644 index 0000000..2955589 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/fonts/VerticalTextMap.h @@ -0,0 +1,44 @@ +/* + * Copyright 2011, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef android_VerticalTextMap_DEFINED +#define android_VerticalTextMap_DEFINED + +#include "WebViewCore.h" +#include +#include +#include + +namespace WebCore { +class VerticalTextMap { +public: + // This function converts given char to its corresponding vertical form. + // Rerturns 0 if there is no vertical form. + static UChar getVerticalForm(UChar c); +}; +} + +#endif diff --git a/Source/WebCore/platform/graphics/android/layers/AndroidAnimation.cpp b/Source/WebCore/platform/graphics/android/layers/AndroidAnimation.cpp new file mode 100644 index 0000000..0ef84b9 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/layers/AndroidAnimation.cpp @@ -0,0 +1,333 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "AndroidAnimation" +#define LOG_NDEBUG 1 + +#include "config.h" +#include "AndroidAnimation.h" + +#if USE(ACCELERATED_COMPOSITING) + +#include "AndroidLog.h" +#include "Animation.h" +#include "GraphicsLayerAndroid.h" +#include "Timer.h" +#include "TimingFunction.h" +#include "TranslateTransformOperation.h" +#include "UnitBezier.h" + +namespace WebCore { + +static int gUniqueId; + +static long gDebugAndroidAnimationInstances; + +long AndroidAnimation::instancesCount() +{ + return gDebugAndroidAnimationInstances; +} + +AndroidAnimation::AndroidAnimation(AnimatedPropertyID type, + const Animation* animation, + KeyframeValueList* operations, + double beginTime) + : m_beginTime(beginTime) + , m_duration(animation->duration()) + , m_fillsBackwards(animation->fillsBackwards()) + , m_fillsForwards(animation->fillsForwards()) + , m_iterationCount(animation->iterationCount()) + , m_direction(animation->direction()) + , m_timingFunction(animation->timingFunction()) + , m_type(type) + , m_operations(operations) + , m_uniqueId(++gUniqueId) + , m_hasFinished(false) +{ + ASSERT(m_timingFunction); + + gDebugAndroidAnimationInstances++; +} + +AndroidAnimation::~AndroidAnimation() +{ + gDebugAndroidAnimationInstances--; +} + +void AndroidAnimation::suggestBeginTime(double time) +{ + if (m_beginTime <= 0.000001) // overflow or not yet set + m_beginTime = time; +} + +double AndroidAnimation::elapsedTime(double time) +{ + double elapsedTime = (m_beginTime < 0.000001) ? 0 : time - m_beginTime; + + if (m_duration <= 0) + m_duration = 0.000001; + + if (elapsedTime < 0) // animation not yet started. + return 0; + + return elapsedTime; +} + +bool AndroidAnimation::checkIterationsAndProgress(double time, float* finalProgress) +{ + double progress = elapsedTime(time); + double dur = m_duration; + if (m_iterationCount > 0) + dur *= m_iterationCount; + + if (m_duration <= 0) + return false; + + // If not infinite, return false if we are done + if (m_iterationCount > 0 && progress > dur) { + *finalProgress = 1.0; + if (!m_hasFinished) { + // first time past duration, continue with progress 1.0 so the + // element's final position lines up with it's last keyframe + m_hasFinished = true; + return true; + } + + return false; + } + + double fractionalTime = progress / m_duration; + int integralTime = static_cast(fractionalTime); + + fractionalTime -= integralTime; + + if ((m_direction == Animation::AnimationDirectionAlternate) && (integralTime & 1)) + fractionalTime = 1 - fractionalTime; + + *finalProgress = fractionalTime; + return true; +} + +double AndroidAnimation::applyTimingFunction(float from, float to, double progress, + const TimingFunction* tf) +{ + double fractionalTime = progress; + double offset = from; + double scale = 1.0 / (to - from); + + if (scale != 1 || offset) + fractionalTime = (fractionalTime - offset) * scale; + + const TimingFunction* timingFunction = tf; + + if (!timingFunction) + timingFunction = m_timingFunction.get(); + + if (timingFunction && timingFunction->isCubicBezierTimingFunction()) { + const CubicBezierTimingFunction* bezierFunction = static_cast(timingFunction); + UnitBezier bezier(bezierFunction->x1(), + bezierFunction->y1(), + bezierFunction->x2(), + bezierFunction->y2()); + if (m_duration > 0) + fractionalTime = bezier.solve(fractionalTime, 1.0f / (200.0f * m_duration)); + } else if (timingFunction && timingFunction->isStepsTimingFunction()) { + const StepsTimingFunction* stepFunction = static_cast(timingFunction); + if (stepFunction->stepAtStart()) { + fractionalTime = (floor(stepFunction->numberOfSteps() * fractionalTime) + 1) / stepFunction->numberOfSteps(); + if (fractionalTime > 1.0) + fractionalTime = 1.0; + } else { + fractionalTime = floor(stepFunction->numberOfSteps() * fractionalTime) / stepFunction->numberOfSteps(); + } + } + return fractionalTime; +} + +bool AndroidAnimation::evaluate(LayerAndroid* layer, double time) +{ + float progress; + if (!checkIterationsAndProgress(time, &progress) + && !(m_fillsBackwards || m_fillsForwards)) + return false; + + if (progress < 0) { + // The animation hasn't started yet + if (m_fillsBackwards || m_beginTime <= 0.000001) { + // in this case we want to apply the initial keyframe to the layer + applyForProgress(layer, 0); + } + // we still want to be evaluated until we get progress > 0 + return true; + } + + if (progress > 1) { + if (!m_fillsForwards) + return false; + progress = 1; + } + + if (!m_operations->size()) + return false; + + applyForProgress(layer, progress); + + return true; +} + +PassRefPtr AndroidOpacityAnimation::create( + const Animation* animation, + KeyframeValueList* operations, + double beginTime) +{ + return adoptRef(new AndroidOpacityAnimation(animation, operations, + beginTime)); +} + +AndroidOpacityAnimation::AndroidOpacityAnimation(const Animation* animation, + KeyframeValueList* operations, + double beginTime) + : AndroidAnimation(AnimatedPropertyOpacity, animation, operations, beginTime) +{ +} + +void AndroidAnimation::pickValues(double progress, int* start, int* end) +{ + float distance = -1; + unsigned int foundAt = 0; + for (unsigned int i = 0; i < m_operations->size(); i++) { + const AnimationValue* value = m_operations->at(i); + float key = value->keyTime(); + float d = progress - key; + if (distance == -1 || (d >= 0 && d < distance && i + 1 < m_operations->size())) { + distance = d; + foundAt = i; + } + } + + *start = foundAt; + + if (foundAt + 1 < m_operations->size()) + *end = foundAt + 1; + else + *end = foundAt; +} + +void AndroidOpacityAnimation::applyForProgress(LayerAndroid* layer, float progress) +{ + // First, we need to get the from and to values + int from, to; + pickValues(progress, &from, &to); + FloatAnimationValue* fromValue = (FloatAnimationValue*) m_operations->at(from); + FloatAnimationValue* toValue = (FloatAnimationValue*) m_operations->at(to); + + ALOGV("[layer %d] opacity fromValue %x, key %.2f, toValue %x, key %.2f for progress %.2f", + layer->uniqueId(), + fromValue, fromValue->keyTime(), + toValue, toValue->keyTime(), progress); + + // We now have the correct two values to work with, let's compute the + // progress value + + const TimingFunction* timingFunction = fromValue->timingFunction(); + progress = applyTimingFunction(fromValue->keyTime(), toValue->keyTime(), + progress, timingFunction); + + + float value = fromValue->value() + ((toValue->value() - fromValue->value()) * progress); + + layer->setOpacity(value); +} + +PassRefPtr AndroidTransformAnimation::create( + const Animation* animation, + KeyframeValueList* operations, + double beginTime) +{ + return adoptRef(new AndroidTransformAnimation(animation, operations, beginTime)); +} + +AndroidTransformAnimation::AndroidTransformAnimation(const Animation* animation, + KeyframeValueList* operations, + double beginTime) + : AndroidAnimation(AnimatedPropertyWebkitTransform, animation, operations, beginTime) +{ +} + +void AndroidTransformAnimation::applyForProgress(LayerAndroid* layer, float progress) +{ + // First, we need to get the from and to values + int from, to; + pickValues(progress, &from, &to); + + TransformAnimationValue* fromValue = (TransformAnimationValue*) m_operations->at(from); + TransformAnimationValue* toValue = (TransformAnimationValue*) m_operations->at(to); + + ALOGV("[layer %d] fromValue %x, key %.2f, toValue %x, key %.2f for progress %.2f", + layer->uniqueId(), + fromValue, fromValue->keyTime(), + toValue, toValue->keyTime(), progress); + + // We now have the correct two values to work with, let's compute the + // progress value + + const TimingFunction* timingFunction = fromValue->timingFunction(); + float p = applyTimingFunction(fromValue->keyTime(), toValue->keyTime(), + progress, timingFunction); + ALOGV("progress %.2f => %.2f from: %.2f to: %.2f", progress, p, fromValue->keyTime(), + toValue->keyTime()); + progress = p; + + // With both values and the progress, we also need to check out that + // the operations are compatible (i.e. we are animating the same number + // of values; if not we do a matrix blend) + + TransformationMatrix transformMatrix; + bool valid = true; + unsigned int fromSize = fromValue->value()->size(); + if (fromSize) { + if (toValue->value()->size() != fromSize) + valid = false; + else { + for (unsigned int j = 0; j < fromSize && valid; j++) { + if (!fromValue->value()->operations()[j]->isSameType( + *toValue->value()->operations()[j])) + valid = false; + } + } + } + + IntSize size(layer->getSize().width(), layer->getSize().height()); + if (valid) { + for (size_t i = 0; i < toValue->value()->size(); ++i) + toValue->value()->operations()[i]->blend(fromValue->value()->at(i), + progress)->apply(transformMatrix, size); + } else { + TransformationMatrix source; + + fromValue->value()->apply(size, source); + toValue->value()->apply(size, transformMatrix); + + transformMatrix.blend(source, progress); + } + + // Set the final transform on the layer + layer->setTransform(transformMatrix); +} + +} // namespace WebCore + +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/android/layers/AndroidAnimation.h b/Source/WebCore/platform/graphics/android/layers/AndroidAnimation.h new file mode 100644 index 0000000..dca769f --- /dev/null +++ b/Source/WebCore/platform/graphics/android/layers/AndroidAnimation.h @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef AndroidAnimation_h +#define AndroidAnimation_h + +#if USE(ACCELERATED_COMPOSITING) + +#include "FloatPoint.h" +#include "FloatPoint3D.h" +#include "GraphicsLayer.h" +#include "HashMap.h" +#include "LayerAndroid.h" +#include "RefPtr.h" +#include "Timer.h" +#include "TransformOperation.h" +#include "Vector.h" + +namespace WebCore { + +class TimingFunction; + +class AndroidAnimation : public ThreadSafeRefCounted { +public: + AndroidAnimation(AnimatedPropertyID type, + const Animation* animation, + KeyframeValueList* operations, + double beginTime); + + virtual ~AndroidAnimation(); + void suggestBeginTime(double time); + double elapsedTime(double time); + void pickValues(double progress, int* start, int* end); + bool checkIterationsAndProgress(double time, float* finalProgress); + double applyTimingFunction(float from, float to, double progress, + const TimingFunction* timingFunction); + bool evaluate(LayerAndroid* layer, double time); + virtual void applyForProgress(LayerAndroid* layer, float progress) = 0; + static long instancesCount(); + void setName(const String& name) { m_name = name; } + String name() { return m_name; } + AnimatedPropertyID type() { return m_type; } + bool fillsBackwards() { return m_fillsBackwards; } + bool fillsForwards() { return m_fillsForwards; } + int uniqueId() { return m_uniqueId; } + +protected: + double m_beginTime; + double m_duration; + bool m_fillsBackwards; + bool m_fillsForwards; + int m_iterationCount; + int m_direction; + RefPtr m_timingFunction; + String m_name; + AnimatedPropertyID m_type; + KeyframeValueList* m_operations; + int m_uniqueId; + bool m_hasFinished; +}; + +class AndroidOpacityAnimation : public AndroidAnimation { +public: + static PassRefPtr create(const Animation* animation, + KeyframeValueList* operations, + double beginTime); + AndroidOpacityAnimation(const Animation* animation, + KeyframeValueList* operations, + double beginTime); + + virtual void applyForProgress(LayerAndroid* layer, float progress); +}; + +class AndroidTransformAnimation : public AndroidAnimation { +public: + static PassRefPtr create( + const Animation* animation, + KeyframeValueList* operations, + double beginTime); + AndroidTransformAnimation(const Animation* animation, + KeyframeValueList* operations, + double beginTime); + + virtual void applyForProgress(LayerAndroid* layer, float progress); +}; + +} // namespace WebCore + + +#endif // USE(ACCELERATED_COMPOSITING) + +#endif // AndroidAnimation_h diff --git a/Source/WebCore/platform/graphics/android/layers/BaseLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/layers/BaseLayerAndroid.cpp new file mode 100644 index 0000000..1de5ae7 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/layers/BaseLayerAndroid.cpp @@ -0,0 +1,56 @@ +/* + * Copyright 2012, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define LOG_TAG "BaseLayerAndroid" +#define LOG_NDEBUG 1 + +#include "config.h" +#include "BaseLayerAndroid.h" + +#include "AndroidLog.h" +#include "GLWebViewState.h" +#include "LayerContent.h" + +namespace WebCore { + +// Note: this must match the use of ID 0 specifying the base layer in DrawExtra +#define BASE_UNIQUE_ID 0 + +BaseLayerAndroid::BaseLayerAndroid(LayerContent* content) + : LayerAndroid((RenderLayer*)0) + , m_color(Color::white) +{ + setContent(content); + setSize(content->width(), content->height()); + m_uniqueId = BASE_UNIQUE_ID; +} + +void BaseLayerAndroid::getLocalTransform(SkMatrix* matrix) const +{ + // base layer doesn't use size in transform calculation + matrix->preConcat(getMatrix()); +} + +} // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/layers/BaseLayerAndroid.h b/Source/WebCore/platform/graphics/android/layers/BaseLayerAndroid.h new file mode 100644 index 0000000..0ef39c8 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/layers/BaseLayerAndroid.h @@ -0,0 +1,59 @@ +/* + * Copyright 2012, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef BaseLayerAndroid_h +#define BaseLayerAndroid_h + +#include "Color.h" +#include "LayerAndroid.h" + +namespace WebCore { + +class RenderLayerCompositor; + +class BaseLayerAndroid : public LayerAndroid { + +public: + BaseLayerAndroid(LayerContent* content); + + virtual ~BaseLayerAndroid() {}; + + virtual SubclassType subclassType() { return LayerAndroid::BaseLayer; } + virtual bool needsTexture() { return true; } + + void setBackgroundColor(Color& color) { m_color = color; } + Color getBackgroundColor() { return m_color; } + + virtual void getLocalTransform(SkMatrix* matrix) const; + virtual const TransformationMatrix* drawTransform() const { return 0; } + +private: + // TODO: move to SurfaceCollection. + Color m_color; +}; + +} // namespace WebCore + +#endif //BaseLayerAndroid_h diff --git a/Source/WebCore/platform/graphics/android/layers/CanvasLayer.cpp b/Source/WebCore/platform/graphics/android/layers/CanvasLayer.cpp new file mode 100644 index 0000000..1813903 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/layers/CanvasLayer.cpp @@ -0,0 +1,220 @@ +/* + * Copyright 2012, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define LOG_TAG "CanvasLayer" +#define LOG_NDEBUG 1 + +#include "config.h" +#include "CanvasLayer.h" + +#if USE(ACCELERATED_COMPOSITING) + +#include "AndroidLog.h" +#include "CanvasTexture.h" +#include "DrawQuadData.h" +#include "Image.h" +#include "ImageBuffer.h" +#include "RenderLayerCompositor.h" +#include "SkBitmap.h" +#include "SkBitmapRef.h" +#include "SkCanvas.h" +#include "TilesManager.h" + +namespace WebCore { + +CanvasLayer::CanvasLayer(RenderLayer* owner, HTMLCanvasElement* canvas) + : LayerAndroid(owner) + , m_canvas(canvas) + , m_dirtyCanvas() + , m_bitmap(0) +{ + init(); + m_canvas->addObserver(this); +} + +CanvasLayer::CanvasLayer(const CanvasLayer& layer) + : LayerAndroid(layer) + , m_canvas(0) + , m_bitmap(0) +{ + init(); + if (!layer.m_canvas) { + // The canvas has already been destroyed - this shouldn't happen + ALOGW("Creating a CanvasLayer for a destroyed canvas!"); + m_contentRect = IntRect(); + m_offsetFromRenderer = IntSize(); + m_texture->setHwAccelerated(false); + return; + } + // We are making a copy for the UI, sync the interesting bits + m_contentRect = layer.contentRect(); + m_offsetFromRenderer = layer.offsetFromRenderer(); + bool previousState = m_texture->hasValidTexture(); + if (!previousState && layer.m_dirtyCanvas.isEmpty()) { + // We were previously in software and don't have anything new to draw, + // so stay in software + m_bitmap = layer.bitmap(); + SkSafeRef(m_bitmap); + } else { + // Attempt to upload to a surface texture + if (!m_texture->uploadImageBuffer(layer.m_canvas->buffer())) { + // Blargh, no surface texture or ImageBuffer - fall back to software + m_bitmap = layer.bitmap(); + SkSafeRef(m_bitmap); + // Merge the canvas invals with the layer's invals to repaint the needed + // tiles. + SkRegion::Iterator iter(layer.m_dirtyCanvas); + const IntPoint& offset = m_contentRect.location(); + for (; !iter.done(); iter.next()) { + SkIRect diff = iter.rect(); + diff.fLeft += offset.x(); + diff.fRight += offset.x(); + diff.fTop += offset.y(); + diff.fBottom += offset.y(); + m_dirtyRegion.op(diff, SkRegion::kUnion_Op); + } + } + if (previousState != m_texture->hasValidTexture()) { + // Need to do a full inval of the canvas content as we are mode switching + m_dirtyRegion.op(m_contentRect.x(), m_contentRect.y(), + m_contentRect.maxX(), m_contentRect.maxY(), SkRegion::kUnion_Op); + } + } +} + +CanvasLayer::~CanvasLayer() +{ + if (m_canvas) + m_canvas->removeObserver(this); + SkSafeUnref(m_bitmap); +} + +void CanvasLayer::init() +{ + m_texture = CanvasTexture::getCanvasTexture(this); +} + +void CanvasLayer::canvasChanged(HTMLCanvasElement*, const FloatRect& changedRect) +{ + if (!m_texture->hasValidTexture()) { + // We only need to track invals if we aren't using a SurfaceTexture. + // If we drop out of hwa, we will do a full inval anyway + SkIRect irect = SkIRect::MakeXYWH(changedRect.x(), changedRect.y(), + changedRect.width(), changedRect.height()); + m_dirtyCanvas.op(irect, SkRegion::kUnion_Op); + } + owningLayer()->compositor()->scheduleLayerFlush(); +} + +void CanvasLayer::canvasResized(HTMLCanvasElement*) +{ + const IntSize& size = m_canvas->size(); + m_dirtyCanvas.setRect(0, 0, size.width(), size.height()); + // If we are smaller than one tile, don't bother using a surface texture + if (size.width() <= TilesManager::tileWidth() + && size.height() <= TilesManager::tileHeight()) + m_texture->setSize(IntSize()); + else + m_texture->setSize(size); +} + +void CanvasLayer::canvasDestroyed(HTMLCanvasElement*) +{ + m_canvas = 0; +} + +void CanvasLayer::clearDirtyRegion() +{ + LayerAndroid::clearDirtyRegion(); + m_dirtyCanvas.setEmpty(); + if (m_canvas) + m_canvas->clearDirtyRect(); +} + +SkBitmapRef* CanvasLayer::bitmap() const +{ + if (!m_canvas || !m_canvas->buffer()) + return 0; + return m_canvas->copiedImage()->nativeImageForCurrentFrame(); +} + +IntRect CanvasLayer::contentRect() const +{ + if (!m_canvas + || !m_canvas->renderer() + || !m_canvas->renderer()->style() + || !m_canvas->inDocument() + || m_canvas->renderer()->style()->visibility() != VISIBLE) + return IntRect(); + return m_canvas->renderBox()->contentBoxRect(); +} + +IntSize CanvasLayer::offsetFromRenderer() const +{ + return m_canvas->renderBox()->layer()->backing()->graphicsLayer()->offsetFromRenderer(); +} + +bool CanvasLayer::needsTexture() +{ + return m_bitmap || LayerAndroid::needsTexture(); +} + +void CanvasLayer::contentDraw(SkCanvas* canvas, PaintStyle style) +{ + LayerAndroid::contentDraw(canvas, style); + if (!m_bitmap) + return; + SkBitmap& bitmap = m_bitmap->bitmap(); + SkRect dst = SkRect::MakeXYWH(m_contentRect.x() - m_offsetFromRenderer.width(), + m_contentRect.y() - m_offsetFromRenderer.height(), + m_contentRect.width(), m_contentRect.height()); + canvas->drawBitmapRect(bitmap, 0, dst, 0); +} + +bool CanvasLayer::drawGL(bool layerTilesDisabled) +{ + bool ret = LayerAndroid::drawGL(layerTilesDisabled); + m_texture->requireTexture(); + if (!m_bitmap && m_texture->updateTexImage()) { + SkRect rect = SkRect::MakeXYWH(m_contentRect.x() - m_offsetFromRenderer.width(), + m_contentRect.y() - m_offsetFromRenderer.height(), + m_contentRect.width(), m_contentRect.height()); + TextureQuadData data(m_texture->texture(), GL_TEXTURE_EXTERNAL_OES, + GL_LINEAR, LayerQuad, &m_drawTransform, &rect); + TilesManager::instance()->shader()->drawQuad(&data); + } + return ret; +} + +LayerAndroid::InvalidateFlags CanvasLayer::onSetHwAccelerated(bool hwAccelerated) +{ + if (m_texture->setHwAccelerated(hwAccelerated)) + return LayerAndroid::InvalidateLayers; + return LayerAndroid::InvalidateNone; +} + +} // namespace WebCore + +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/android/layers/CanvasLayer.h b/Source/WebCore/platform/graphics/android/layers/CanvasLayer.h new file mode 100644 index 0000000..532dbf2 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/layers/CanvasLayer.h @@ -0,0 +1,81 @@ +/* + * Copyright 2012, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CanvasLayer_h +#define CanvasLayer_h + +#if USE(ACCELERATED_COMPOSITING) + +#include "HTMLCanvasElement.h" +#include "ImageData.h" +#include "LayerAndroid.h" +#include "RenderLayer.h" + +#include + +namespace WebCore { + +class CanvasTexture; + +class CanvasLayer : public LayerAndroid, private CanvasObserver { +public: + CanvasLayer(RenderLayer* owner, HTMLCanvasElement* canvas); + CanvasLayer(const CanvasLayer& layer); + virtual ~CanvasLayer(); + + virtual LayerAndroid* copy() const { return new CanvasLayer(*this); } + virtual SubclassType subclassType() { return LayerAndroid::CanvasLayer; } + virtual void clearDirtyRegion(); + + virtual bool drawGL(bool layerTilesDisabled); + virtual void contentDraw(SkCanvas* canvas, PaintStyle style); + virtual bool needsTexture(); + +protected: + virtual InvalidateFlags onSetHwAccelerated(bool hwAccelerated); + +private: + virtual void canvasChanged(HTMLCanvasElement*, const FloatRect& changedRect); + virtual void canvasResized(HTMLCanvasElement*); + virtual void canvasDestroyed(HTMLCanvasElement*); + + void init(); + SkBitmapRef* bitmap() const; + IntRect contentRect() const; + IntSize offsetFromRenderer() const; + + HTMLCanvasElement* m_canvas; + IntRect m_contentRect; + IntSize m_offsetFromRenderer; + SkRegion m_dirtyCanvas; + SkBitmapRef* m_bitmap; + RefPtr m_texture; +}; + +} // namespace WebCore + +#endif // USE(ACCELERATED_COMPOSITING) + +#endif // CanvasLayer_h diff --git a/Source/WebCore/platform/graphics/android/layers/CanvasTexture.cpp b/Source/WebCore/platform/graphics/android/layers/CanvasTexture.cpp new file mode 100644 index 0000000..e4b2bc6 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/layers/CanvasTexture.cpp @@ -0,0 +1,225 @@ +/* + * Copyright 2012, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define LOG_TAG "CanvasTexture" +#define LOG_NDEBUG 1 + +#include "config.h" +#include "CanvasTexture.h" + +#if USE(ACCELERATED_COMPOSITING) + +#include "android_graphics.h" +#include "AndroidLog.h" +#include "GLUtils.h" +#include "Image.h" +#include "ImageBuffer.h" +#include "SkBitmap.h" +#include "SkBitmapRef.h" +#include "SkDevice.h" +#include "SkPixelRef.h" + +#include +#include +#include + +namespace WebCore { + +static int s_maxTextureSize = 0; +static HashMap s_textures; +static android::Mutex s_texturesLock; + +/******************************************** + * Called by both threads + ********************************************/ + +PassRefPtr CanvasTexture::getCanvasTexture(CanvasLayer* layer) +{ + android::Mutex::Autolock lock(s_texturesLock); + RefPtr texture = s_textures.get(layer->uniqueId()); + if (texture.get()) + return texture.release(); + return adoptRef(new CanvasTexture(layer->uniqueId())); +} + +bool CanvasTexture::setHwAccelerated(bool hwAccelerated) +{ + android::Mutex::Autolock lock(m_surfaceLock); + if (m_useHwAcceleration == hwAccelerated) + return false; + m_useHwAcceleration = hwAccelerated; + if (!m_ANW.get()) + return false; + destroySurfaceTextureLocked(); + return true; +} + +/******************************************** + * Called by WebKit thread + ********************************************/ + +void CanvasTexture::setSize(const IntSize& size) +{ + android::Mutex::Autolock lock(m_surfaceLock); + if (m_size == size) + return; + m_size = size; + if (m_ANW.get()) { + if (useSurfaceTexture()) { + int result = native_window_set_buffers_dimensions(m_ANW.get(), + m_size.width(), m_size.height()); + GLUtils::checkSurfaceTextureError("native_window_set_buffers_dimensions", result); + if (result != NO_ERROR) + m_useHwAcceleration = false; // On error, drop out of HWA + } + if (!useSurfaceTexture()) + destroySurfaceTextureLocked(); + } +} + +SurfaceTextureClient* CanvasTexture::nativeWindow() +{ + android::Mutex::Autolock lock(m_surfaceLock); + if (m_ANW.get()) + return m_ANW.get(); + if (!m_texture) + return 0; + if (!useSurfaceTexture()) + return 0; + m_surfaceTexture = new android::SurfaceTexture(m_texture, false); + m_ANW = new android::SurfaceTextureClient(m_surfaceTexture); + int result = native_window_set_buffers_format(m_ANW.get(), HAL_PIXEL_FORMAT_RGBA_8888); + GLUtils::checkSurfaceTextureError("native_window_set_buffers_format", result); + if (result == NO_ERROR) { + result = native_window_set_buffers_dimensions(m_ANW.get(), + m_size.width(), m_size.height()); + GLUtils::checkSurfaceTextureError("native_window_set_buffers_dimensions", result); + } + if (result != NO_ERROR) { + m_useHwAcceleration = false; + destroySurfaceTextureLocked(); + return 0; + } + return m_ANW.get(); +} + +bool CanvasTexture::uploadImageBuffer(ImageBuffer* imageBuffer) +{ + m_hasValidTexture = false; + SurfaceTextureClient* anw = nativeWindow(); + if (!anw) + return false; + // Size mismatch, early abort (will fall back to software) + if (imageBuffer->size() != m_size) + return false; + GraphicsContext* gc = imageBuffer ? imageBuffer->context() : 0; + if (!gc) + return false; + const SkBitmap& bitmap = android_gc2canvas(gc)->getDevice()->accessBitmap(false); + if (!GLUtils::updateSharedSurfaceTextureWithBitmap(anw, bitmap)) + return false; + m_hasValidTexture = true; + return true; +} + +/******************************************** + * Called by UI thread WITH GL context + ********************************************/ + +CanvasTexture::~CanvasTexture() +{ + if (m_layerId) { + s_texturesLock.lock(); + s_textures.remove(m_layerId); + s_texturesLock.unlock(); + } + if (m_texture) + GLUtils::deleteTexture(&m_texture); +} + +void CanvasTexture::requireTexture() +{ + android::Mutex::Autolock lock(m_surfaceLock); + if (!m_texture) + glGenTextures(1, &m_texture); + if (!s_maxTextureSize) + glGetIntegerv(GL_MAX_TEXTURE_SIZE, &s_maxTextureSize); +} + +bool CanvasTexture::updateTexImage() +{ + android::Mutex::Autolock lock(m_surfaceLock); + if (!m_surfaceTexture.get()) + return false; + status_t result = m_surfaceTexture->updateTexImage(); + if (result != OK) { + ALOGE("unexpected error: updateTexImage return %d", result); + return false; + } + return true; +} + +/******************************************** + * Called by both threads + ********************************************/ + +void CanvasTexture::destroySurfaceTextureLocked() +{ + if (m_ANW.get()) { + m_ANW.clear(); + m_surfaceTexture->abandon(); + m_surfaceTexture.clear(); + } +} + +/******************************************** + * Called by WebKit thread + ********************************************/ + +CanvasTexture::CanvasTexture(int layerId) + : m_size() + , m_layerId(layerId) + , m_texture(0) + , m_surfaceTexture(0) + , m_ANW(0) + , m_hasValidTexture(false) + , m_useHwAcceleration(true) +{ + s_textures.add(m_layerId, this); +} + +// TODO: Have a global limit as well as a way to react to low memory situations +bool CanvasTexture::useSurfaceTexture() +{ + if (!m_useHwAcceleration) + return false; + if (m_size.isEmpty()) + return false; + return (m_size.width() < s_maxTextureSize) && (m_size.height() < s_maxTextureSize); +} + +} // namespace WebCore + +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/android/layers/CanvasTexture.h b/Source/WebCore/platform/graphics/android/layers/CanvasTexture.h new file mode 100644 index 0000000..98962a0 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/layers/CanvasTexture.h @@ -0,0 +1,95 @@ +/* + * Copyright 2012, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CanvasTexture_h +#define CanvasTexture_h + +#if USE(ACCELERATED_COMPOSITING) + +#include "CanvasLayer.h" + +#include +#include + +namespace android { +class SurfaceTexture; +class SurfaceTextureClient; +} + +namespace WebCore { + +class CanvasTexture : public ThreadSafeRefCounted { + +public: + /******************************************** + * Called by both threads + ********************************************/ + static PassRefPtr getCanvasTexture(CanvasLayer* layer); + bool setHwAccelerated(bool hwAccelerated); + + /******************************************** + * Called by WebKit thread + ********************************************/ + void setSize(const IntSize& size); + SurfaceTextureClient* nativeWindow(); + bool uploadImageBuffer(ImageBuffer* imageBuffer); + bool hasValidTexture() { return m_hasValidTexture; } + + /******************************************** + * Called by UI thread WITH GL context + ********************************************/ + virtual ~CanvasTexture(); + void requireTexture(); + GLuint texture() { requireTexture(); return m_texture; } + bool updateTexImage(); + +private: + /******************************************** + * Called by both threads + ********************************************/ + void destroySurfaceTextureLocked(); + + /******************************************** + * Called by WebKit thread + ********************************************/ + CanvasTexture(int layerId); + bool useSurfaceTexture(); + + IntSize m_size; + int m_layerId; + GLuint m_texture; + android::Mutex m_surfaceLock; + sp m_surfaceTexture; + sp m_ANW; + bool m_hasValidTexture; + bool m_useHwAcceleration; + +}; + +} // namespace WebCore + +#endif // USE(ACCELERATED_COMPOSITING) + +#endif // CanvasTexture_h diff --git a/Source/WebCore/platform/graphics/android/layers/DumpLayer.cpp b/Source/WebCore/platform/graphics/android/layers/DumpLayer.cpp new file mode 100644 index 0000000..5551965 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/layers/DumpLayer.cpp @@ -0,0 +1,83 @@ +#include "config.h" +#include "DumpLayer.h" + +#if USE(ACCELERATED_COMPOSITING) + +namespace WebCore { + +void lwrite(FILE* file, const char* str) +{ + fwrite(str, sizeof(char), strlen(str), file); +} + +void writeIndent(FILE* file, int indentLevel) +{ + if (indentLevel) + fprintf(file, "%*s", indentLevel*2, " "); +} + +void writeln(FILE* file, int indentLevel, const char* str) +{ + writeIndent(file, indentLevel); + lwrite(file, str); + lwrite(file, "\n"); +} + +void writeIntVal(FILE* file, int indentLevel, const char* str, int value) +{ + writeIndent(file, indentLevel); + fprintf(file, "%s = %d;\n", str, value); +} + +void writeHexVal(FILE* file, int indentLevel, const char* str, int value) +{ + writeIndent(file, indentLevel); + fprintf(file, "%s = %x;\n", str, value); +} + +void writeFloatVal(FILE* file, int indentLevel, const char* str, float value) +{ + writeIndent(file, indentLevel); + fprintf(file, "%s = %.3f;\n", str, value); +} + +void writePoint(FILE* file, int indentLevel, const char* str, SkPoint point) +{ + writeIndent(file, indentLevel); + fprintf(file, "%s = { x = %.3f; y = %.3f; };\n", str, point.fX, point.fY); +} + +void writeIntPoint(FILE* file, int indentLevel, const char* str, IntPoint point) +{ + writeIndent(file, indentLevel); + fprintf(file, "%s = { x = %d; y = %d; };\n", str, point.x(), point.y()); +} + +void writeSize(FILE* file, int indentLevel, const char* str, SkSize size) +{ + writeIndent(file, indentLevel); + fprintf(file, "%s = { w = %.3f; h = %.3f; };\n", str, size.width(), size.height()); +} + +void writeRect(FILE* file, int indentLevel, const char* str, SkRect rect) +{ + writeIndent(file, indentLevel); + fprintf(file, "%s = { x = %.3f; y = %.3f; w = %.3f; h = %.3f; };\n", + str, rect.fLeft, rect.fTop, rect.width(), rect.height()); +} + +void writeMatrix(FILE* file, int indentLevel, const char* str, const TransformationMatrix& matrix) +{ + writeIndent(file, indentLevel); + fprintf(file, "%s = { (%.2f,%.2f,%.2f,%.2f),(%.2f,%.2f,%.2f,%.2f)," + "(%.2f,%.2f,%.2f,%.2f),(%.2f,%.2f,%.2f,%.2f) };\n", + str, + matrix.m11(), matrix.m12(), matrix.m13(), matrix.m14(), + matrix.m21(), matrix.m22(), matrix.m23(), matrix.m24(), + matrix.m31(), matrix.m32(), matrix.m33(), matrix.m34(), + matrix.m41(), matrix.m42(), matrix.m43(), matrix.m44()); +} + +} // namespace WebCore + +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/android/layers/DumpLayer.h b/Source/WebCore/platform/graphics/android/layers/DumpLayer.h new file mode 100644 index 0000000..5b30952 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/layers/DumpLayer.h @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef DumpLayer_h +#define DumpLayer_h + +#include "IntPoint.h" +#include "SkPoint.h" +#include "SkRect.h" +#include "SkSize.h" +#include "TransformationMatrix.h" + +// Debug tools : dump the layers tree in a file. +// The format is simple: +// properties have the form: key = value; +// all statements are finished with a semi-colon. +// value can be: +// - int +// - float +// - array of elements +// - composed type +// a composed type enclose properties in { and } +// an array enclose composed types in { }, separated with a comma. +// exemple: +// { +// x = 3; +// y = 4; +// value = { +// x = 3; +// y = 4; +// }; +// anarray = [ +// { x = 3; }, +// { y = 4; } +// ]; +// } + +namespace WebCore { + +void lwrite(FILE* file, const char* str); +void writeIndent(FILE* file, int indentLevel); +void writeln(FILE* file, int indentLevel, const char* str); +void writeIntVal(FILE* file, int indentLevel, const char* str, int value); +void writeHexVal(FILE* file, int indentLevel, const char* str, int value); +void writeFloatVal(FILE* file, int indentLevel, const char* str, float value); +void writePoint(FILE* file, int indentLevel, const char* str, SkPoint point); +void writeIntPoint(FILE* file, int indentLevel, const char* str, IntPoint point); +void writeSize(FILE* file, int indentLevel, const char* str, SkSize size); +void writeRect(FILE* file, int indentLevel, const char* str, SkRect rect); +void writeMatrix(FILE* file, int indentLevel, const char* str, const TransformationMatrix& matrix); + +} + +#endif // DumpLayer_h diff --git a/Source/WebCore/platform/graphics/android/layers/FixedPositioning.cpp b/Source/WebCore/platform/graphics/android/layers/FixedPositioning.cpp new file mode 100644 index 0000000..c7909c4 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/layers/FixedPositioning.cpp @@ -0,0 +1,106 @@ +#define LOG_TAG "FixedPositioning" +#define LOG_NDEBUG 1 + +#include "config.h" +#include "FixedPositioning.h" + +#include "AndroidLog.h" +#include "DumpLayer.h" +#include "IFrameLayerAndroid.h" +#include "TilesManager.h" +#include "SkCanvas.h" + +#if USE(ACCELERATED_COMPOSITING) + +namespace WebCore { + +// Called when copying the layer tree to the UI +FixedPositioning::FixedPositioning(LayerAndroid* layer, const FixedPositioning& position) + : m_layer(layer) + , m_fixedLeft(position.m_fixedLeft) + , m_fixedTop(position.m_fixedTop) + , m_fixedRight(position.m_fixedRight) + , m_fixedBottom(position.m_fixedBottom) + , m_fixedMarginLeft(position.m_fixedMarginLeft) + , m_fixedMarginTop(position.m_fixedMarginTop) + , m_fixedMarginRight(position.m_fixedMarginRight) + , m_fixedMarginBottom(position.m_fixedMarginBottom) + , m_fixedRect(position.m_fixedRect) + , m_renderLayerPos(position.m_renderLayerPos) +{ +} + +// Executed on the UI +IFrameLayerAndroid* FixedPositioning::updatePosition(SkRect viewport, + IFrameLayerAndroid* parentIframeLayer) +{ + // So if this is a fixed layer inside a iframe, use the iframe offset + // and the iframe's size as the viewport and pass to the children + if (parentIframeLayer) { + viewport = SkRect::MakeXYWH(parentIframeLayer->iframeOffset().x(), + parentIframeLayer->iframeOffset().y(), + parentIframeLayer->getSize().width(), + parentIframeLayer->getSize().height()); + } + float w = viewport.width(); + float h = viewport.height(); + float dx = viewport.fLeft; + float dy = viewport.fTop; + float x = dx; + float y = dy; + + // It turns out that when it is 'auto', we should use the webkit value + // from the original render layer's X,Y, that will take care of alignment + // with the parent's layer and fix Margin etc. + if (!(m_fixedLeft.defined() || m_fixedRight.defined())) + x += m_renderLayerPos.x(); + else if (m_fixedLeft.defined() || !m_fixedRight.defined()) + x += m_fixedMarginLeft.calcFloatValue(w) + m_fixedLeft.calcFloatValue(w) - m_fixedRect.fLeft; + else + x += w - m_fixedMarginRight.calcFloatValue(w) - m_fixedRight.calcFloatValue(w) - m_fixedRect.fRight; + + if (!(m_fixedTop.defined() || m_fixedBottom.defined())) + y += m_renderLayerPos.y(); + else if (m_fixedTop.defined() || !m_fixedBottom.defined()) + y += m_fixedMarginTop.calcFloatValue(h) + m_fixedTop.calcFloatValue(h) - m_fixedRect.fTop; + else + y += h - m_fixedMarginBottom.calcFloatValue(h) - m_fixedBottom.calcFloatValue(h) - m_fixedRect.fBottom; + + m_layer->setPosition(x, y); + + return parentIframeLayer; +} + +void FixedPositioning::contentDraw(SkCanvas* canvas, Layer::PaintStyle style) +{ + if (TilesManager::instance()->getShowVisualIndicator()) { + SkPaint paint; + paint.setARGB(80, 255, 0, 0); + canvas->drawRect(m_fixedRect, paint); + } +} + +void writeLength(FILE* file, int indentLevel, const char* str, SkLength length) +{ + if (!length.defined()) + return; + writeIndent(file, indentLevel); + fprintf(file, "%s = { type = %d; value = %.2f; };\n", str, length.type, length.value); +} + +void FixedPositioning::dumpLayer(FILE* file, int indentLevel) const +{ + writeLength(file, indentLevel + 1, "fixedLeft", m_fixedLeft); + writeLength(file, indentLevel + 1, "fixedTop", m_fixedTop); + writeLength(file, indentLevel + 1, "fixedRight", m_fixedRight); + writeLength(file, indentLevel + 1, "fixedBottom", m_fixedBottom); + writeLength(file, indentLevel + 1, "fixedMarginLeft", m_fixedMarginLeft); + writeLength(file, indentLevel + 1, "fixedMarginTop", m_fixedMarginTop); + writeLength(file, indentLevel + 1, "fixedMarginRight", m_fixedMarginRight); + writeLength(file, indentLevel + 1, "fixedMarginBottom", m_fixedMarginBottom); + writeRect(file, indentLevel + 1, "fixedRect", m_fixedRect); +} + +} // namespace WebCore + +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/android/layers/FixedPositioning.h b/Source/WebCore/platform/graphics/android/layers/FixedPositioning.h new file mode 100644 index 0000000..973113b --- /dev/null +++ b/Source/WebCore/platform/graphics/android/layers/FixedPositioning.h @@ -0,0 +1,128 @@ +/* + * Copyright 2012, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef FixedPositioning_h +#define FixedPositioning_h + +#if USE(ACCELERATED_COMPOSITING) + +#include "LayerAndroid.h" + +namespace WebCore { + +class IFrameLayerAndroid; + +struct SkLength { + enum SkLengthType { Undefined, Auto, Relative, + Percent, Fixed, Static, Intrinsic, MinIntrinsic }; + SkLengthType type; + SkScalar value; + SkLength() + { + type = Undefined; + value = 0; + } + bool defined() const + { + if (type == Undefined) + return false; + return true; + } + float calcFloatValue(float max) const + { + switch (type) { + case Percent: + return (max * value) / 100.0f; + case Fixed: + return value; + default: + return value; + } + } +}; + +class FixedPositioning { + +public: + FixedPositioning(LayerAndroid* layer = 0) : m_layer(layer) {} + FixedPositioning(LayerAndroid* layer, const FixedPositioning& position); + virtual ~FixedPositioning() {}; + + void setFixedPosition(SkLength left, // CSS left property + SkLength top, // CSS top property + SkLength right, // CSS right property + SkLength bottom, // CSS bottom property + SkLength marginLeft, // CSS margin-left property + SkLength marginTop, // CSS margin-top property + SkLength marginRight, // CSS margin-right property + SkLength marginBottom, // CSS margin-bottom property + const IntPoint& renderLayerPos, // For undefined fixed position + SkRect viewRect) { // view rect, can be smaller than the layer's + m_fixedLeft = left; + m_fixedTop = top; + m_fixedRight = right; + m_fixedBottom = bottom; + m_fixedMarginLeft = marginLeft; + m_fixedMarginTop = marginTop; + m_fixedMarginRight = marginRight; + m_fixedMarginBottom = marginBottom; + m_fixedRect = viewRect; + m_renderLayerPos = renderLayerPos; + } + + IFrameLayerAndroid* updatePosition(SkRect viewPort, + IFrameLayerAndroid* parentIframeLayer); + + void contentDraw(SkCanvas* canvas, Layer::PaintStyle style); + + void dumpLayer(FILE*, int indentLevel) const; + + // ViewStateSerializer friends + friend void android::serializeLayer(LayerAndroid* layer, SkWStream* stream); + friend LayerAndroid* android::deserializeLayer(int version, SkStream* stream); + +private: + LayerAndroid* m_layer; + + SkLength m_fixedLeft; + SkLength m_fixedTop; + SkLength m_fixedRight; + SkLength m_fixedBottom; + SkLength m_fixedMarginLeft; + SkLength m_fixedMarginTop; + SkLength m_fixedMarginRight; + SkLength m_fixedMarginBottom; + SkRect m_fixedRect; + + // When fixed element is undefined or auto, the render layer's position + // is needed for offset computation + IntPoint m_renderLayerPos; +}; + +} + +#endif // USE(ACCELERATED_COMPOSITING) + +#endif // FixedPositioning_h diff --git a/Source/WebCore/platform/graphics/android/layers/IFrameContentLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/layers/IFrameContentLayerAndroid.cpp new file mode 100644 index 0000000..dadb13d --- /dev/null +++ b/Source/WebCore/platform/graphics/android/layers/IFrameContentLayerAndroid.cpp @@ -0,0 +1,42 @@ +#define LOG_TAG "IFrameContentLayerAndroid" +#define LOG_NDEBUG 1 + +#include "config.h" +#include "IFrameContentLayerAndroid.h" + +#include "AndroidLog.h" + +#if USE(ACCELERATED_COMPOSITING) + +namespace WebCore { + +bool IFrameContentLayerAndroid::scrollTo(int x, int y) +{ + IntRect scrollBounds; + getScrollBounds(&scrollBounds); + if (!scrollBounds.width() && !scrollBounds.height()) + return false; + SkScalar newX = SkScalarPin(x, scrollBounds.x(), scrollBounds.width()); + SkScalar newY = SkScalarPin(y, scrollBounds.y(), scrollBounds.height()); + // Check for no change. + if (newX == m_iframeScrollOffset.x() && newY == m_iframeScrollOffset.y()) + return false; + newX = newX - m_iframeScrollOffset.x(); + newY = newY - m_iframeScrollOffset.y(); + setScrollOffset(IntPoint(newX, newY)); + return true; +} + +void IFrameContentLayerAndroid::getScrollRect(SkIRect* out) const +{ + const SkPoint& pos = getPosition(); + out->fLeft = m_scrollLimits.fLeft - pos.fX + m_iframeScrollOffset.x(); + out->fTop = m_scrollLimits.fTop - pos.fY + m_iframeScrollOffset.y(); + + out->fRight = getSize().width() - m_scrollLimits.width(); + out->fBottom = getSize().height() - m_scrollLimits.height(); +} + +} // namespace WebCore + +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/android/layers/IFrameContentLayerAndroid.h b/Source/WebCore/platform/graphics/android/layers/IFrameContentLayerAndroid.h new file mode 100644 index 0000000..64b2d06 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/layers/IFrameContentLayerAndroid.h @@ -0,0 +1,78 @@ +/* + * Copyright 2012, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef IFrameContentLayerAndroid_h +#define IFrameContentLayerAndroid_h + +#if USE(ACCELERATED_COMPOSITING) + +#include "ScrollableLayerAndroid.h" + +namespace WebCore { + +class IFrameContentLayerAndroid : public ScrollableLayerAndroid { + +public: + IFrameContentLayerAndroid(RenderLayer* owner) + : ScrollableLayerAndroid(owner) {} + IFrameContentLayerAndroid(const ScrollableLayerAndroid& layer) + : ScrollableLayerAndroid(layer) {} + IFrameContentLayerAndroid(const LayerAndroid& layer) + : ScrollableLayerAndroid(layer) {} + IFrameContentLayerAndroid(const IFrameContentLayerAndroid& layer) + : ScrollableLayerAndroid(layer) + , m_iframeScrollOffset(layer.m_iframeScrollOffset) {} + + virtual ~IFrameContentLayerAndroid() {}; + + // isIFrame() return true for compatibility reason (see ViewStateSerializer) + virtual bool isIFrame() const { return true; } + virtual bool isIFrameContent() const { return true; } + + virtual LayerAndroid* copy() const { return new IFrameContentLayerAndroid(*this); } + virtual SubclassType subclassType() { return LayerAndroid::IFrameContentLayer; } + + // Scrolls to the given position in the layer. + // Returns whether or not any scrolling was required. + virtual bool scrollTo(int x, int y); + + // Fills the rect with the current scroll offset and the maximum scroll offset. + // fLeft = scrollX + // fTop = scrollY + // fRight = maxScrollX + // fBottom = maxScrollY + virtual void getScrollRect(SkIRect*) const; + + void setIFrameScrollOffset(IntPoint offset) { m_iframeScrollOffset = offset; } + +private: + IntPoint m_iframeScrollOffset; +}; + +} + +#endif // USE(ACCELERATED_COMPOSITING) + +#endif // IFrameContentLayerAndroid_h diff --git a/Source/WebCore/platform/graphics/android/layers/IFrameLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/layers/IFrameLayerAndroid.cpp new file mode 100644 index 0000000..3532542 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/layers/IFrameLayerAndroid.cpp @@ -0,0 +1,40 @@ +#define LOG_TAG "IFrameLayerAndroid" +#define LOG_NDEBUG 1 + +#include "config.h" +#include "IFrameLayerAndroid.h" + +#if USE(ACCELERATED_COMPOSITING) + +#include "AndroidLog.h" +#include "DumpLayer.h" + +namespace WebCore { + +IFrameLayerAndroid* IFrameLayerAndroid::updatePosition(SkRect viewport, + IFrameLayerAndroid* parentIframeLayer) +{ + // As we are an iframe, accumulate the offset from the parent with + // the current position, and change the parent pointer. + + // If this is the top level, take the current position + SkPoint parentOffset; + parentOffset.set(0,0); + if (parentIframeLayer) + parentOffset = parentIframeLayer->getPosition(); + + SkPoint offset = parentOffset + getPosition(); + m_iframeOffset = IntPoint(offset.fX, offset.fY); + + return this; +} + +void IFrameLayerAndroid::dumpLayer(FILE* file, int indentLevel) const +{ + writeIntVal(file, indentLevel + 1, "m_isIframe", true); + writeIntPoint(file, indentLevel + 1, "m_iframeOffset", m_iframeOffset); +} + +} // namespace WebCore + +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/android/layers/IFrameLayerAndroid.h b/Source/WebCore/platform/graphics/android/layers/IFrameLayerAndroid.h new file mode 100644 index 0000000..e12188a --- /dev/null +++ b/Source/WebCore/platform/graphics/android/layers/IFrameLayerAndroid.h @@ -0,0 +1,68 @@ +/* + * Copyright 2012, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef IFrameLayerAndroid_h +#define IFrameLayerAndroid_h + +#if USE(ACCELERATED_COMPOSITING) + +#include "LayerAndroid.h" + +namespace WebCore { + +class IFrameLayerAndroid : public LayerAndroid { + +public: + IFrameLayerAndroid(RenderLayer* owner) + : LayerAndroid(owner) {} + IFrameLayerAndroid(const LayerAndroid& layer) + : LayerAndroid(layer) {} + IFrameLayerAndroid(const IFrameLayerAndroid& layer) + : LayerAndroid(layer) + , m_iframeOffset(layer.m_iframeOffset) {} + + virtual ~IFrameLayerAndroid() {}; + + virtual bool isIFrame() const { return true; } + + virtual LayerAndroid* copy() const { return new IFrameLayerAndroid(*this); } + virtual SubclassType subclassType() { return LayerAndroid::IFrameLayer; } + + virtual IFrameLayerAndroid* updatePosition(SkRect viewport, + IFrameLayerAndroid* parentIframeLayer); + + virtual void dumpLayer(FILE*, int indentLevel) const; + + const IntPoint& iframeOffset() const { return m_iframeOffset; } + +private: + IntPoint m_iframeOffset; +}; + +} + +#endif // USE(ACCELERATED_COMPOSITING) + +#endif // IFrameLayerAndroid_h diff --git a/Source/WebCore/platform/graphics/android/layers/Layer.cpp b/Source/WebCore/platform/graphics/android/layers/Layer.cpp new file mode 100644 index 0000000..48e36fc --- /dev/null +++ b/Source/WebCore/platform/graphics/android/layers/Layer.cpp @@ -0,0 +1,237 @@ +#define LOG_TAG "Layer" +#define LOG_NDEBUG 1 + +#include "config.h" +#include "Layer.h" + +#include "AndroidLog.h" +#include "SkCanvas.h" + +//#define DEBUG_DRAW_LAYER_BOUNDS +//#define DEBUG_TRACK_NEW_DELETE + +#ifdef DEBUG_TRACK_NEW_DELETE + static int gLayerAllocCount; +#endif + +/////////////////////////////////////////////////////////////////////////////// + +Layer::Layer() { + fParent = NULL; + m_opacity = SK_Scalar1; + m_size.set(0, 0); + m_position.set(0, 0); + m_anchorPoint.set(SK_ScalarHalf, SK_ScalarHalf); + + m_matrix.reset(); + m_childrenMatrix.reset(); + m_shouldInheritFromRootTransform = false; + + m_hasOverflowChildren = false; + m_state = 0; + +#ifdef DEBUG_TRACK_NEW_DELETE + gLayerAllocCount += 1; + SkDebugf("Layer new: %d\n", gLayerAllocCount); +#endif +} + +Layer::Layer(const Layer& src) : INHERITED() { + fParent = NULL; + m_opacity = src.m_opacity; + m_size = src.m_size; + m_position = src.m_position; + m_anchorPoint = src.m_anchorPoint; + + m_matrix = src.m_matrix; + m_childrenMatrix = src.m_childrenMatrix; + m_shouldInheritFromRootTransform = src.m_shouldInheritFromRootTransform; + + m_hasOverflowChildren = src.m_hasOverflowChildren; + m_state = 0; + +#ifdef DEBUG_TRACK_NEW_DELETE + gLayerAllocCount += 1; + SkDebugf("Layer copy: %d\n", gLayerAllocCount); +#endif +} + +Layer::~Layer() { + removeChildren(); + +#ifdef DEBUG_TRACK_NEW_DELETE + gLayerAllocCount -= 1; + SkDebugf("Layer delete: %d\n", gLayerAllocCount); +#endif +} + +/////////////////////////////////////////////////////////////////////////////// + +int Layer::countChildren() const { + return m_children.count(); +} + +Layer* Layer::getChild(int index) const { + if ((unsigned)index < (unsigned)m_children.count()) { + SkASSERT(m_children[index]->fParent == this); + return m_children[index]; + } + return NULL; +} + +Layer* Layer::addChild(Layer* child) { + SkASSERT(this != child); + child->ref(); + child->detachFromParent(); + SkASSERT(child->fParent == NULL); + child->fParent = this; + + *m_children.append() = child; + return child; +} + +void Layer::detachFromParent() { + if (fParent) { + int index = fParent->m_children.find(this); + SkASSERT(index >= 0); + fParent->m_children.remove(index); + fParent = NULL; + unref(); // this call might delete us + } +} + +void Layer::removeChildren() { + int count = m_children.count(); + for (int i = 0; i < count; i++) { + Layer* child = m_children[i]; + SkASSERT(child->fParent == this); + child->fParent = NULL; // in case it has more than one owner + child->unref(); + } + m_children.reset(); +} + +Layer* Layer::getRootLayer() const { + const Layer* root = this; + while (root->fParent != NULL) { + root = root->fParent; + } + return const_cast(root); +} + +/////////////////////////////////////////////////////////////////////////////// + +void Layer::getLocalTransform(SkMatrix* matrix) const { + matrix->setTranslate(m_position.fX, m_position.fY); + + SkScalar tx = SkScalarMul(m_anchorPoint.fX, m_size.width()); + SkScalar ty = SkScalarMul(m_anchorPoint.fY, m_size.height()); + matrix->preTranslate(tx, ty); + matrix->preConcat(getMatrix()); + matrix->preTranslate(-tx, -ty); +} + +void Layer::localToAncestor(const Layer* ancestor, SkMatrix* matrix) const { + if (this == ancestor) { + matrix->setIdentity(); + return; + } + + getLocalTransform(matrix); + + // Fixed position layers simply use the root layer's transform. + if (shouldInheritFromRootTransform()) { + ASSERT(!ancestor); + matrix->postConcat(getRootLayer()->getMatrix()); + return; + } + + // Apply the local and child transforms for every layer between this layer + // and ancestor. + ASSERT(isAncestor(ancestor)); + for (const Layer* layer = this->fParent; layer != ancestor; layer = layer->fParent) { + SkMatrix tmp; + layer->getLocalTransform(&tmp); + tmp.preConcat(layer->getChildrenMatrix()); + matrix->postConcat(tmp); + } + + // If ancestor is not the root layer, apply its child transformation too. + if (ancestor) + matrix->postConcat(ancestor->getChildrenMatrix()); +} + +/////////////////////////////////////////////////////////////////////////////// + +#include "SkString.h" + +void Layer::draw(SkCanvas* canvas, android::DrawExtra* extra, SkScalar opacity) { +#if 0 + SkString str1, str2; + // getMatrix().toDumpString(&str1); + // getChildrenMatrix().toDumpString(&str2); + SkDebugf("--- drawlayer %p opacity %g size [%g %g] pos [%g %g] matrix %s children %s\n", + this, opacity * getOpacity(), m_size.width(), m_size.height(), + m_position.fX, m_position.fY, str1.c_str(), str2.c_str()); +#endif + + opacity = SkScalarMul(opacity, getOpacity()); + if (opacity <= 0) { +// SkDebugf("---- abort drawing %p opacity %g\n", this, opacity); + return; + } + + SkAutoCanvasRestore acr(canvas, true); + + // apply our local transform + { + SkMatrix tmp; + getLocalTransform(&tmp); + if (shouldInheritFromRootTransform()) { + // should we also apply the root's childrenMatrix? + canvas->setMatrix(getRootLayer()->getMatrix()); + } + canvas->concat(tmp); + } + + onDraw(canvas, opacity, extra, FlattenedLayers); + +#ifdef DEBUG_DRAW_LAYER_BOUNDS + { + SkRect r = SkRect::MakeSize(getSize()); + SkPaint p; + p.setAntiAlias(true); + p.setStyle(SkPaint::kStroke_Style); + p.setStrokeWidth(SkIntToScalar(2)); + p.setColor(0xFFFF44DD); + canvas->drawRect(r, p); + canvas->drawLine(r.fLeft, r.fTop, r.fRight, r.fBottom, p); + canvas->drawLine(r.fLeft, r.fBottom, r.fRight, r.fTop, p); + } +#endif + + int count = countChildren(); + if (count > 0) { + canvas->concat(getChildrenMatrix()); + for (int i = 0; i < count; i++) { + getChild(i)->draw(canvas, extra, opacity); + } + } +} + +bool Layer::isAncestor(const Layer* possibleAncestor) const { + if (!possibleAncestor) + return true; + for (const Layer* layer = getParent(); layer; layer = layer->getParent()) { + if (layer == possibleAncestor) + return true; + } + return false; +} + +void Layer::setState(WebCore::GLWebViewState* state) { + m_state = state; + int count = countChildren(); + for (int i = 0; i < count; i++) + m_children[i]->setState(state); +} diff --git a/Source/WebCore/platform/graphics/android/layers/Layer.h b/Source/WebCore/platform/graphics/android/layers/Layer.h new file mode 100644 index 0000000..996547b --- /dev/null +++ b/Source/WebCore/platform/graphics/android/layers/Layer.h @@ -0,0 +1,184 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef Layer_DEFINED +#define Layer_DEFINED + +#include "DrawExtra.h" +#include "TestExport.h" +#include "SkRefCnt.h" +#include "SkTDArray.h" +#include "SkColor.h" +#include "SkMatrix.h" +#include "SkPoint.h" +#include "SkRect.h" +#include "SkRegion.h" +#include "SkSize.h" + +namespace WebCore { +class IntRect; +class GLWebViewState; +}; + +class SkCanvas; + +class TEST_EXPORT Layer : public SkRefCnt { + +public: + Layer(); + Layer(const Layer&); + virtual ~Layer(); + + // Whether the layer should apply its tranform directly onto the root + // layer, rather than using the transforms of all ancestor layers. This is + // used for fixed position layers. + bool shouldInheritFromRootTransform() const { return m_shouldInheritFromRootTransform; } + SkScalar getOpacity() const { return m_opacity; } + const SkSize& getSize() const { return m_size; } + const SkPoint& getPosition() const { return m_position; } + const SkPoint& getAnchorPoint() const { return m_anchorPoint; } + const SkMatrix& getMatrix() const { return m_matrix; } + const SkMatrix& getChildrenMatrix() const { return m_childrenMatrix; } + + SkScalar getWidth() const { return m_size.width(); } + SkScalar getHeight() const { return m_size.height(); } + + void setShouldInheritFromRootTransform(bool inherit) { m_shouldInheritFromRootTransform = inherit; } + void setOpacity(SkScalar opacity) { m_opacity = opacity; } + void setSize(SkScalar w, SkScalar h) { m_size.set(w, h); } + void setPosition(SkScalar x, SkScalar y) { m_position.set(x, y); } + void setAnchorPoint(SkScalar x, SkScalar y) { m_anchorPoint.set(x, y); } + void setMatrix(const SkMatrix& matrix) { m_matrix = matrix; } + void setChildrenMatrix(const SkMatrix& matrix) { m_childrenMatrix = matrix; } + +// rendering asset management + void markAsDirty(const SkRegion& invalRegion) { + m_dirtyRegion.op(invalRegion, SkRegion::kUnion_Op); + } + + bool isDirty() { + return !m_dirtyRegion.isEmpty(); + } + +// drawing + + WebCore::GLWebViewState* state() { return m_state; } + void setState(WebCore::GLWebViewState* state); + +// children + + /** Return the number of layers in our child list. + */ + int countChildren() const; + + /** Return the child at the specified index (starting at 0). This does not + affect the reference count of the child. + */ + Layer* getChild(int index) const; + + /** Add this layer to our child list at the end (top-most), and ref() it. + If it was already in another hierarchy, remove it from that list. + Return the new child. + */ + Layer* addChild(Layer* child); + + /** Remove this layer from its parent's list (or do nothing if it has no + parent.) If it had a parent, then unref() is called. + */ + void detachFromParent(); + + /** Remove, and unref(), all of the layers in our child list. + */ + void removeChildren(); + + /** Return our parent layer, or NULL if we have none. + */ + Layer* getParent() const { return fParent; } + + /** Return the root layer in this hiearchy. If this layer is the root + (i.e. has no parent), then this returns itself. + */ + Layer* getRootLayer() const; + + // coordinate system transformations + + /** Return, in matrix, the matix transfomations that are applied locally + when this layer draws (i.e. its position and matrix/anchorPoint). + This does not include the childrenMatrix, since that is only applied + after this layer draws (but before its children draw). + */ + virtual void getLocalTransform(SkMatrix* matrix) const; + + /** Return, in matrix, the concatenation of transforms that are applied + from this layer's root parent to the layer itself. + This is the matrix that is applied to the layer during drawing. + */ + void localToGlobal(SkMatrix* matrix) const { localToAncestor(0, matrix); } + + /** Return, as a matrix, the transform that converts from this layer's local + space to the space of the given ancestor layer. Use NULL for ancestor to + represent the root layer. Note that this method must not be called on a + fixed position layer with ancestor != NULL. + + For non-fixed position layers, the following holds (in pseudo-code for + brevity) ... + SkMatrix localToAncestor = layer->localToAncestor(ancestor); + SkMatrix ancestorToGlobal = ancestor->localToAncestor(NULL); + SkMatrix localToGlobal = layer->localToGlobal(); + ASSERT(localToAncestor * ancestorToGlobal == localToGlobal); + */ + void localToAncestor(const Layer* ancestor, SkMatrix* matrix) const; + + // paint method + + virtual bool drawCanvas(SkCanvas*) { return false; } + void draw(SkCanvas*, android::DrawExtra* extra, SkScalar opacity = SK_Scalar1); + + void setHasOverflowChildren(bool value) { m_hasOverflowChildren = value; } + + virtual bool contentIsScrollable() const { return false; } + + typedef enum { MergedLayers, UnmergedLayers, FlattenedLayers } PaintStyle; +protected: + virtual void onDraw(SkCanvas*, SkScalar opacity, android::DrawExtra* extra, PaintStyle style) {} + + bool m_hasOverflowChildren; + + bool isAncestor(const Layer*) const; + + Layer* fParent; + SkScalar m_opacity; + SkSize m_size; + // The position of the origin of the layer, relative to the parent layer. + SkPoint m_position; + // The point in the layer used as the origin for local transformations, + // expressed as a fraction of the layer size. + SkPoint m_anchorPoint; + SkMatrix m_matrix; + SkMatrix m_childrenMatrix; + bool m_shouldInheritFromRootTransform; + + SkTDArray m_children; + + // invalidation region + SkRegion m_dirtyRegion; + + WebCore::GLWebViewState* m_state; + + typedef SkRefCnt INHERITED; +}; + +#endif diff --git a/Source/WebCore/platform/graphics/android/layers/LayerAndroid.cpp b/Source/WebCore/platform/graphics/android/layers/LayerAndroid.cpp new file mode 100644 index 0000000..df3fa42 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/layers/LayerAndroid.cpp @@ -0,0 +1,1034 @@ +#define LOG_TAG "LayerAndroid" +#define LOG_NDEBUG 1 + +#include "config.h" +#include "LayerAndroid.h" + +#if USE(ACCELERATED_COMPOSITING) + +#include "AndroidLog.h" +#include "AndroidAnimation.h" +#include "ClassTracker.h" +#include "DrawExtra.h" +#include "DumpLayer.h" +#include "FixedPositioning.h" +#include "GLUtils.h" +#include "GLWebViewState.h" +#include "ImagesManager.h" +#include "InspectorCanvas.h" +#include "LayerContent.h" +#include "MediaLayer.h" +#include "ParseCanvas.h" +#include "PictureLayerContent.h" +#include "SkBitmapRef.h" +#include "SkDrawFilter.h" +#include "SkPaint.h" +#include "SkPicture.h" +#include "Surface.h" +#include "TilesManager.h" + +#include +#include +#include + +#define DISABLE_LAYER_MERGE +#undef DISABLE_LAYER_MERGE + +#define LAYER_MERGING_DEBUG +#undef LAYER_MERGING_DEBUG + +namespace WebCore { + +static int gUniqueId; + +class OpacityDrawFilter : public SkDrawFilter { +public: + OpacityDrawFilter(int opacity) : m_opacity(opacity) { } + virtual void filter(SkPaint* paint, Type) + { + paint->setAlpha(m_opacity); + } +private: + int m_opacity; +}; + +/////////////////////////////////////////////////////////////////////////////// + +LayerAndroid::LayerAndroid(RenderLayer* owner) : Layer(), + m_uniqueId(++gUniqueId), + m_haveClip(false), + m_backfaceVisibility(true), + m_visible(true), + m_preserves3D(false), + m_anchorPointZ(0), + m_isPositionAbsolute(false), + m_fixedPosition(0), + m_zValue(0), + m_content(0), + m_imageCRC(0), + m_scale(1), + m_lastComputeTextureSize(0), + m_owningLayer(owner), + m_type(LayerAndroid::WebCoreLayer), + m_intrinsicallyComposited(true), + m_surface(0) +{ + m_backgroundColor = 0; + + m_preserves3D = false; + m_dirtyRegion.setEmpty(); +#ifdef DEBUG_COUNT + ClassTracker::instance()->increment("LayerAndroid"); + ClassTracker::instance()->add(this); +#endif +} + +LayerAndroid::LayerAndroid(const LayerAndroid& layer) : Layer(layer), + m_uniqueId(layer.m_uniqueId), + m_haveClip(layer.m_haveClip), + m_isPositionAbsolute(layer.m_isPositionAbsolute), + m_fixedPosition(0), + m_zValue(layer.m_zValue), + m_owningLayer(layer.m_owningLayer), + m_type(LayerAndroid::UILayer), + m_intrinsicallyComposited(layer.m_intrinsicallyComposited), + m_surface(0) +{ + m_imageCRC = layer.m_imageCRC; + if (m_imageCRC) + ImagesManager::instance()->retainImage(m_imageCRC); + + m_transform = layer.m_transform; + m_backfaceVisibility = layer.m_backfaceVisibility; + m_visible = layer.m_visible; + m_backgroundColor = layer.m_backgroundColor; + + m_offset = layer.m_offset; + + m_content = layer.m_content; + SkSafeRef(m_content); + + m_preserves3D = layer.m_preserves3D; + m_anchorPointZ = layer.m_anchorPointZ; + + if (layer.m_fixedPosition) { + m_fixedPosition = new FixedPositioning(this, *layer.m_fixedPosition); + Layer::setShouldInheritFromRootTransform(true); + } + + m_drawTransform = layer.m_drawTransform; + m_childrenTransform = layer.m_childrenTransform; + m_dirtyRegion = layer.m_dirtyRegion; + m_scale = layer.m_scale; + m_lastComputeTextureSize = 0; + + // If we have absolute elements, we may need to reorder them if they + // are followed by another layer that is not also absolutely positioned. + // (as absolutely positioned elements are out of the normal flow) + bool hasAbsoluteChildren = false; + bool hasOnlyAbsoluteFollowers = true; + for (int i = 0; i < layer.countChildren(); i++) { + if (layer.getChild(i)->isPositionAbsolute()) { + hasAbsoluteChildren = true; + continue; + } + if (hasAbsoluteChildren + && !layer.getChild(i)->isPositionAbsolute()) { + hasOnlyAbsoluteFollowers = false; + break; + } + } + + if (hasAbsoluteChildren && !hasOnlyAbsoluteFollowers) { + Vector normalLayers; + Vector absoluteLayers; + for (int i = 0; i < layer.countChildren(); i++) { + LayerAndroid* child = layer.getChild(i); + if (child->isPositionAbsolute() + || child->isPositionFixed()) + absoluteLayers.append(child); + else + normalLayers.append(child); + } + for (unsigned int i = 0; i < normalLayers.size(); i++) + addChild(normalLayers[i]->copy())->unref(); + for (unsigned int i = 0; i < absoluteLayers.size(); i++) + addChild(absoluteLayers[i]->copy())->unref(); + } else { + for (int i = 0; i < layer.countChildren(); i++) + addChild(layer.getChild(i)->copy())->unref(); + } + + KeyframesMap::const_iterator end = layer.m_animations.end(); + for (KeyframesMap::const_iterator it = layer.m_animations.begin(); it != end; ++it) { + m_animations.add(it->first, it->second); + } + +#ifdef DEBUG_COUNT + ClassTracker::instance()->increment("LayerAndroid - recopy (UI)"); + ClassTracker::instance()->add(this); +#endif +} + +LayerAndroid::~LayerAndroid() +{ + if (m_imageCRC) + ImagesManager::instance()->releaseImage(m_imageCRC); + if (m_fixedPosition) + delete m_fixedPosition; + + SkSafeUnref(m_content); + // Don't unref m_surface, owned by BaseLayerAndroid + m_animations.clear(); +#ifdef DEBUG_COUNT + ClassTracker::instance()->remove(this); + if (m_type == LayerAndroid::WebCoreLayer) + ClassTracker::instance()->decrement("LayerAndroid"); + else if (m_type == LayerAndroid::UILayer) + ClassTracker::instance()->decrement("LayerAndroid - recopy (UI)"); +#endif +} + +bool LayerAndroid::hasText() +{ + return m_content && m_content->hasText(); +} + +static int gDebugNbAnims = 0; + +bool LayerAndroid::evaluateAnimations() +{ + double time = WTF::currentTime(); + gDebugNbAnims = 0; + return evaluateAnimations(time); +} + +bool LayerAndroid::hasAnimations() const +{ + for (int i = 0; i < countChildren(); i++) { + if (getChild(i)->hasAnimations()) + return true; + } + return !!m_animations.size(); +} + +bool LayerAndroid::evaluateAnimations(double time) +{ + bool hasRunningAnimations = false; + for (int i = 0; i < countChildren(); i++) { + if (getChild(i)->evaluateAnimations(time)) + hasRunningAnimations = true; + } + + m_hasRunningAnimations = false; + int nbAnims = 0; + KeyframesMap::const_iterator end = m_animations.end(); + for (KeyframesMap::const_iterator it = m_animations.begin(); it != end; ++it) { + gDebugNbAnims++; + nbAnims++; + LayerAndroid* currentLayer = const_cast(this); + m_hasRunningAnimations |= (it->second)->evaluate(currentLayer, time); + } + + return hasRunningAnimations || m_hasRunningAnimations; +} + +void LayerAndroid::initAnimations() { + // tell auto-initializing animations to start now + for (int i = 0; i < countChildren(); i++) + getChild(i)->initAnimations(); + + KeyframesMap::const_iterator localBegin = m_animations.begin(); + KeyframesMap::const_iterator localEnd = m_animations.end(); + for (KeyframesMap::const_iterator localIt = localBegin; localIt != localEnd; ++localIt) + (localIt->second)->suggestBeginTime(WTF::currentTime()); +} + +void LayerAndroid::addDirtyArea() +{ + IntSize layerSize(getSize().width(), getSize().height()); + + FloatRect area = TilesManager::instance()->shader()->rectInInvScreenCoord(m_drawTransform, layerSize); + FloatRect clippingRect = TilesManager::instance()->shader()->rectInScreenCoord(m_clippingRect); + FloatRect clip = TilesManager::instance()->shader()->convertScreenCoordToInvScreenCoord(clippingRect); + + area.intersect(clip); + IntRect dirtyArea(area.x(), area.y(), area.width(), area.height()); + m_state->addDirtyArea(dirtyArea); +} + +void LayerAndroid::addAnimation(PassRefPtr prpAnim) +{ + RefPtr anim = prpAnim; + pair key(anim->name(), anim->type()); + removeAnimationsForProperty(anim->type()); + m_animations.add(key, anim); +} + +void LayerAndroid::removeAnimationsForProperty(AnimatedPropertyID property) +{ + KeyframesMap::const_iterator end = m_animations.end(); + Vector > toDelete; + for (KeyframesMap::const_iterator it = m_animations.begin(); it != end; ++it) { + if ((it->second)->type() == property) + toDelete.append(it->first); + } + + for (unsigned int i = 0; i < toDelete.size(); i++) + m_animations.remove(toDelete[i]); +} + +void LayerAndroid::removeAnimationsForKeyframes(const String& name) +{ + KeyframesMap::const_iterator end = m_animations.end(); + Vector > toDelete; + for (KeyframesMap::const_iterator it = m_animations.begin(); it != end; ++it) { + if ((it->second)->name() == name) + toDelete.append(it->first); + } + + for (unsigned int i = 0; i < toDelete.size(); i++) + m_animations.remove(toDelete[i]); +} + +// We only use the bounding rect of the layer as mask... +// FIXME: use a real mask? +void LayerAndroid::setMaskLayer(LayerAndroid* layer) +{ + if (layer) + m_haveClip = true; +} + +void LayerAndroid::setBackgroundColor(SkColor color) +{ + m_backgroundColor = color; +} + +FloatPoint LayerAndroid::translation() const +{ + TransformationMatrix::DecomposedType tDecomp; + m_transform.decompose(tDecomp); + FloatPoint p(tDecomp.translateX, tDecomp.translateY); + return p; +} + +SkRect LayerAndroid::bounds() const +{ + SkRect rect; + bounds(&rect); + return rect; +} + +void LayerAndroid::bounds(SkRect* rect) const +{ + const SkPoint& pos = this->getPosition(); + const SkSize& size = this->getSize(); + + // The returned rect has the translation applied + // FIXME: apply the full transform to the rect, + // and fix the text selection accordingly + FloatPoint p(pos.fX, pos.fY); + p = m_transform.mapPoint(p); + rect->fLeft = p.x(); + rect->fTop = p.y(); + rect->fRight = p.x() + size.width(); + rect->fBottom = p.y() + size.height(); +} + +static bool boundsIsUnique(const SkTDArray& region, + const SkRect& local) +{ + for (int i = 0; i < region.count(); i++) { + if (region[i].contains(local)) + return false; + } + return true; +} + +void LayerAndroid::clipArea(SkTDArray* region) const +{ + SkRect local; + local.set(0, 0, std::numeric_limits::max(), + std::numeric_limits::max()); + clipInner(region, local); +} + +void LayerAndroid::clipInner(SkTDArray* region, + const SkRect& local) const +{ + SkRect localBounds; + bounds(&localBounds); + localBounds.intersect(local); + if (localBounds.isEmpty()) + return; + if (m_content && boundsIsUnique(*region, localBounds)) + *region->append() = localBounds; + for (int i = 0; i < countChildren(); i++) + getChild(i)->clipInner(region, m_haveClip ? localBounds : local); +} + +IFrameLayerAndroid* LayerAndroid::updatePosition(SkRect viewport, + IFrameLayerAndroid* parentIframeLayer) +{ + // subclasses can implement this virtual function to modify their position + if (m_fixedPosition) + return m_fixedPosition->updatePosition(viewport, parentIframeLayer); + return parentIframeLayer; +} + +void LayerAndroid::updateLayerPositions(SkRect viewport, IFrameLayerAndroid* parentIframeLayer) +{ + ALOGV("updating fixed positions, using viewport %fx%f - %fx%f", + viewport.fLeft, viewport.fTop, + viewport.width(), viewport.height()); + + IFrameLayerAndroid* iframeLayer = updatePosition(viewport, parentIframeLayer); + + int count = this->countChildren(); + for (int i = 0; i < count; i++) + this->getChild(i)->updateLayerPositions(viewport, iframeLayer); +} + +void LayerAndroid::updatePositions() +{ + // apply the viewport to us + if (!isPositionFixed()) { + // turn our fields into a matrix. + // + // FIXME: this should happen in the caller, and we should remove these + // fields from our subclass + SkMatrix matrix; + GLUtils::toSkMatrix(matrix, m_transform); + this->setMatrix(matrix); + } + + // now apply it to our children + int count = this->countChildren(); + for (int i = 0; i < count; i++) + this->getChild(i)->updatePositions(); +} + +void LayerAndroid::updateGLPositionsAndScale(const TransformationMatrix& parentMatrix, + const FloatRect& clipping, float opacity, float scale) +{ + m_atomicSync.lock(); + IntSize layerSize(getSize().width(), getSize().height()); + FloatPoint anchorPoint(getAnchorPoint().fX, getAnchorPoint().fY); + FloatPoint position(getPosition().fX - m_offset.x(), getPosition().fY - m_offset.y()); + float originX = anchorPoint.x() * layerSize.width(); + float originY = anchorPoint.y() * layerSize.height(); + TransformationMatrix localMatrix; + if (!isPositionFixed()) + localMatrix = parentMatrix; + localMatrix.translate3d(originX + position.x(), + originY + position.y(), + anchorPointZ()); + localMatrix.multiply(m_transform); + localMatrix.translate3d(-originX, + -originY, + -anchorPointZ()); + + m_atomicSync.unlock(); + setDrawTransform(localMatrix); + if (m_drawTransform.isIdentityOrTranslation()) { + // adjust the translation coordinates of the draw transform matrix so + // that layers (defined in content coordinates) will align to display/view pixels + float desiredContentX = round(m_drawTransform.m41() * scale) / scale; + float desiredContentY = round(m_drawTransform.m42() * scale) / scale; + ALOGV("fudging translation from %f, %f to %f, %f", + m_drawTransform.m41(), m_drawTransform.m42(), + desiredContentX, desiredContentY); + m_drawTransform.setM41(desiredContentX); + m_drawTransform.setM42(desiredContentY); + } + + m_zValue = TilesManager::instance()->shader()->zValue(m_drawTransform, getSize().width(), getSize().height()); + + m_atomicSync.lock(); + m_scale = scale; + m_atomicSync.unlock(); + + opacity *= getOpacity(); + setDrawOpacity(opacity); + + if (m_haveClip) { + // The clipping rect calculation and intersetion will be done in documents coordinates. + FloatRect rect(0, 0, layerSize.width(), layerSize.height()); + FloatRect clip = m_drawTransform.mapRect(rect); + clip.intersect(clipping); + setDrawClip(clip); + } else { + setDrawClip(clipping); + } + ALOGV("%s - %d %f %f %f %f", + subclassType() == BaseLayer ? "BASE" : "nonbase", + m_haveClip, m_clippingRect.x(), m_clippingRect.y(), m_clippingRect.width(), m_clippingRect.height()); + + if (!m_backfaceVisibility + && m_drawTransform.inverse().m33() < 0) { + setVisible(false); + return; + } else { + setVisible(true); + } + + int count = this->countChildren(); + if (!count) + return; + + // Flatten to 2D if the layer doesn't preserve 3D. + if (!preserves3D()) { + localMatrix.setM13(0); + localMatrix.setM23(0); + localMatrix.setM31(0); + localMatrix.setM32(0); + localMatrix.setM33(1); + localMatrix.setM34(0); + localMatrix.setM43(0); + } + + // now apply it to our children + + TransformationMatrix childMatrix; + childMatrix = localMatrix; + childMatrix.translate3d(m_offset.x(), m_offset.y(), 0); + if (!m_childrenTransform.isIdentity()) { + childMatrix.translate(getSize().width() * 0.5f, getSize().height() * 0.5f); + childMatrix.multiply(m_childrenTransform); + childMatrix.translate(-getSize().width() * 0.5f, -getSize().height() * 0.5f); + } + for (int i = 0; i < count; i++) + this->getChild(i)->updateGLPositionsAndScale(childMatrix, drawClip(), opacity, scale); +} + +bool LayerAndroid::visible() { + // TODO: avoid climbing tree each access + LayerAndroid* current = this; + while (current->getParent()) { + if (!current->m_visible) + return false; + current = static_cast(current->getParent()); + } + return true; +} + +void LayerAndroid::setContentsImage(SkBitmapRef* img) +{ + ImageTexture* image = ImagesManager::instance()->setImage(img); + ImagesManager::instance()->releaseImage(m_imageCRC); + m_imageCRC = image ? image->imageCRC() : 0; +} + +void LayerAndroid::setContent(LayerContent* content) +{ + SkSafeRef(content); + SkSafeUnref(m_content); + m_content = content; +} + +bool LayerAndroid::needsTexture() +{ + return m_content && !m_content->isEmpty(); +} + +IntRect LayerAndroid::clippedRect() const +{ + IntRect r(0, 0, getWidth(), getHeight()); + IntRect tr = m_drawTransform.mapRect(r); + IntRect cr = TilesManager::instance()->shader()->clippedRectWithViewport(tr); + IntRect rect = m_drawTransform.inverse().mapRect(cr); + return rect; +} + +int LayerAndroid::nbLayers() +{ + int nb = 0; + int count = this->countChildren(); + for (int i = 0; i < count; i++) + nb += this->getChild(i)->nbLayers(); + return nb+1; +} + +int LayerAndroid::nbTexturedLayers() +{ + int nb = 0; + int count = this->countChildren(); + for (int i = 0; i < count; i++) + nb += this->getChild(i)->nbTexturedLayers(); + if (needsTexture()) + nb++; + return nb; +} + +void LayerAndroid::showLayer(int indent) +{ + char spaces[256]; + memset(spaces, 0, 256); + for (int i = 0; i < indent; i++) + spaces[i] = ' '; + + if (!indent) { + ALOGD("\n\n--- LAYERS TREE ---"); + IntRect documentViewport(TilesManager::instance()->shader()->documentViewport()); + ALOGD("documentViewport(%d, %d, %d, %d)", + documentViewport.x(), documentViewport.y(), + documentViewport.width(), documentViewport.height()); + } + + IntRect r(0, 0, getWidth(), getHeight()); + IntRect tr = m_drawTransform.mapRect(r); + IntRect visible = visibleArea(); + IntRect clip(m_clippingRect.x(), m_clippingRect.y(), + m_clippingRect.width(), m_clippingRect.height()); + ALOGD("%s %s (%d) [%d:0x%x] - %s %s - area (%d, %d, %d, %d) - visible (%d, %d, %d, %d) " + "clip (%d, %d, %d, %d) %s %s m_content(%x), pic w: %d h: %d", + spaces, subclassName().latin1().data(), subclassType(), uniqueId(), m_owningLayer, + needsTexture() ? "needs a texture" : "no texture", + m_imageCRC ? "has an image" : "no image", + tr.x(), tr.y(), tr.width(), tr.height(), + visible.x(), visible.y(), visible.width(), visible.height(), + clip.x(), clip.y(), clip.width(), clip.height(), + contentIsScrollable() ? "SCROLLABLE" : "", + isPositionFixed() ? "FIXED" : "", + m_content, + m_content ? m_content->width() : -1, + m_content ? m_content->height() : -1); + + int count = this->countChildren(); + for (int i = 0; i < count; i++) + this->getChild(i)->showLayer(indent + 1); +} + +void LayerAndroid::mergeInvalsInto(LayerAndroid* replacementTree) +{ + int count = this->countChildren(); + for (int i = 0; i < count; i++) + this->getChild(i)->mergeInvalsInto(replacementTree); + + LayerAndroid* replacementLayer = replacementTree->findById(uniqueId()); + if (replacementLayer) + replacementLayer->markAsDirty(m_dirtyRegion); +} + +bool LayerAndroid::updateWithTree(LayerAndroid* newTree) +{ +// Disable fast update for now +#if (0) + bool needsRepaint = false; + int count = this->countChildren(); + for (int i = 0; i < count; i++) + needsRepaint |= this->getChild(i)->updateWithTree(newTree); + + if (newTree) { + LayerAndroid* newLayer = newTree->findById(uniqueId()); + needsRepaint |= updateWithLayer(newLayer); + } + return needsRepaint; +#else + return true; +#endif +} + +// Return true to indicate to WebViewCore that the updates +// are too complicated to be fully handled and we need a full +// call to webkit (e.g. handle repaints) +bool LayerAndroid::updateWithLayer(LayerAndroid* layer) +{ + if (!layer) + return true; + + android::AutoMutex lock(m_atomicSync); + m_position = layer->m_position; + m_anchorPoint = layer->m_anchorPoint; + m_size = layer->m_size; + m_opacity = layer->m_opacity; + m_transform = layer->m_transform; + + if (m_imageCRC != layer->m_imageCRC) + m_visible = false; + + if ((m_content != layer->m_content) + || (m_imageCRC != layer->m_imageCRC)) + return true; + + return false; +} + +static inline bool compareLayerZ(const LayerAndroid* a, const LayerAndroid* b) +{ + return a->zValue() > b->zValue(); +} + +bool LayerAndroid::canJoinSurface(Surface* surface) +{ +#ifdef DISABLE_LAYER_MERGE + return false; +#else + // returns true if the layer can be merged onto the surface (group of layers) + if (!surface) + return false; + + LayerAndroid* lastLayer = surface->getFirstLayer(); + + // isolate non-tiled layers + // TODO: remove this check so that multiple tiled layers with a invisible + // one inbetween can be merged + if (!needsTexture() || !lastLayer->needsTexture()) + return false; + + // isolate clipped layers + // TODO: paint correctly with clip when merged + if (m_haveClip || lastLayer->m_haveClip) + return false; + + // isolate intrinsically composited layers + if (m_intrinsicallyComposited || lastLayer->m_intrinsicallyComposited) + return false; + + // TODO: investigate potential for combining transformed layers + if (!m_drawTransform.isIdentityOrTranslation() + || !lastLayer->m_drawTransform.isIdentityOrTranslation()) + return false; + + // currently, we don't surface zoomable with non-zoomable layers (unless the + // surface or the layer doesn't need a texture) + if (surface->needsTexture() && needsTexture() && m_content->hasText() != surface->hasText()) + return false; + + // TODO: compare other layer properties - fixed? overscroll? transformed? + return true; +#endif +} + +void LayerAndroid::assignSurfaces(LayerMergeState* mergeState) +{ + // recurse through layers in draw order, and merge layers when able + + bool needNewSurface = !mergeState->currentSurface + || mergeState->nonMergeNestedLevel > 0 + || !canJoinSurface(mergeState->currentSurface); + + if (needNewSurface) { + mergeState->currentSurface = new Surface(); + mergeState->surfaceList->append(mergeState->currentSurface); + } + +#ifdef LAYER_MERGING_DEBUG + ALOGD("%*slayer %p(%d) rl %p %s surface %p, fixed %d, anim %d, intCom %d, haveClip %d scroll %d", + 4*mergeState->depth, "", this, m_uniqueId, m_owningLayer, + needNewSurface ? "NEW" : "joins", mergeState->currentSurface, + isPositionFixed(), m_animations.size() != 0, + m_intrinsicallyComposited, + m_haveClip, + contentIsScrollable()); +#endif + + mergeState->currentSurface->addLayer(this, m_drawTransform); + m_surface = mergeState->currentSurface; + + if (m_haveClip || contentIsScrollable() || isPositionFixed()) { + // disable layer merging within the children of these layer types + mergeState->nonMergeNestedLevel++; + } + + + // pass the surface through children in drawing order, so that they may + // attach themselves (and paint on it) if possible, or ignore it and create + // a new one if not + int count = this->countChildren(); + if (count > 0) { + mergeState->depth++; + Vector sublayers; + for (int i = 0; i < count; i++) + sublayers.append(getChild(i)); + + // sort for the transparency + std::stable_sort(sublayers.begin(), sublayers.end(), compareLayerZ); + for (int i = 0; i < count; i++) + sublayers[i]->assignSurfaces(mergeState); + mergeState->depth--; + } + + if (m_haveClip || contentIsScrollable() || isPositionFixed()) { + // re-enable joining + mergeState->nonMergeNestedLevel--; + + // disallow layers painting after to join with this surface + mergeState->currentSurface = 0; + } +} + +// We call this in WebViewCore, when copying the tree of layers. +// As we construct a new tree that will be passed on the UI, +// we mark the webkit-side tree as having no more dirty region +// (otherwise we would continuously have those dirty region UI-side) +void LayerAndroid::clearDirtyRegion() +{ + int count = this->countChildren(); + for (int i = 0; i < count; i++) + this->getChild(i)->clearDirtyRegion(); + + m_dirtyRegion.setEmpty(); +} + +int LayerAndroid::setHwAccelerated(bool hwAccelerated) +{ + int flags = InvalidateNone; + int count = this->countChildren(); + for (int i = 0; i < count; i++) + flags |= this->getChild(i)->setHwAccelerated(hwAccelerated); + + return flags | onSetHwAccelerated(hwAccelerated); +} + +IntRect LayerAndroid::unclippedArea() +{ + IntRect area; + area.setX(0); + area.setY(0); + area.setWidth(getSize().width()); + area.setHeight(getSize().height()); + return area; +} + +IntRect LayerAndroid::visibleArea() +{ + IntRect area = unclippedArea(); + // First, we get the transformed area of the layer, + // in document coordinates + IntRect rect = m_drawTransform.mapRect(area); + int dx = rect.x(); + int dy = rect.y(); + + // Then we apply the clipping + IntRect clip(m_clippingRect); + rect.intersect(clip); + + // Now clip with the viewport in documents coordinate + IntRect documentViewport(TilesManager::instance()->shader()->documentViewport()); + rect.intersect(documentViewport); + + // Finally, let's return the visible area, in layers coordinate + rect.move(-dx, -dy); + return rect; +} + +bool LayerAndroid::drawCanvas(SkCanvas* canvas, bool drawChildren, PaintStyle style) +{ + if (!m_visible) + return false; + + bool askScreenUpdate = false; + + { + SkAutoCanvasRestore acr(canvas, true); + SkRect r; + r.set(m_clippingRect.x(), m_clippingRect.y(), + m_clippingRect.x() + m_clippingRect.width(), + m_clippingRect.y() + m_clippingRect.height()); + canvas->clipRect(r); + SkMatrix matrix; + GLUtils::toSkMatrix(matrix, m_drawTransform); + SkMatrix canvasMatrix = canvas->getTotalMatrix(); + matrix.postConcat(canvasMatrix); + canvas->setMatrix(matrix); + onDraw(canvas, m_drawOpacity, 0, style); + } + + if (!drawChildren) + return false; + + // When the layer is dirty, the UI thread should be notified to redraw. + askScreenUpdate |= drawChildrenCanvas(canvas, style); + m_atomicSync.lock(); + if (askScreenUpdate || m_hasRunningAnimations || m_drawTransform.hasPerspective()) + addDirtyArea(); + + m_atomicSync.unlock(); + return askScreenUpdate; +} + +bool LayerAndroid::drawGL(bool layerTilesDisabled) +{ + if (!layerTilesDisabled && m_imageCRC) { + ImageTexture* imageTexture = ImagesManager::instance()->retainImage(m_imageCRC); + if (imageTexture) + imageTexture->drawGL(this, getOpacity()); + ImagesManager::instance()->releaseImage(m_imageCRC); + } + + m_state->glExtras()->drawGL(this); + bool askScreenUpdate = false; + + m_atomicSync.lock(); + if (m_hasRunningAnimations || m_drawTransform.hasPerspective()) { + askScreenUpdate = true; + addDirtyArea(); + } + + m_atomicSync.unlock(); + return askScreenUpdate; +} + +bool LayerAndroid::drawChildrenCanvas(SkCanvas* canvas, PaintStyle style) +{ + bool askScreenUpdate = false; + int count = this->countChildren(); + if (count > 0) { + Vector sublayers; + for (int i = 0; i < count; i++) + sublayers.append(this->getChild(i)); + + // now we sort for the transparency + std::stable_sort(sublayers.begin(), sublayers.end(), compareLayerZ); + for (int i = 0; i < count; i++) { + LayerAndroid* layer = sublayers[i]; + askScreenUpdate |= layer->drawCanvas(canvas, true, style); + } + } + + return askScreenUpdate; +} + +void LayerAndroid::contentDraw(SkCanvas* canvas, PaintStyle style) +{ + if (m_content) + m_content->draw(canvas); + + if (TilesManager::instance()->getShowVisualIndicator()) { + float w = getSize().width(); + float h = getSize().height(); + SkPaint paint; + + if (style == MergedLayers) + paint.setARGB(255, 255, 255, 0); + else if (style == UnmergedLayers) + paint.setARGB(255, 255, 0, 0); + else if (style == FlattenedLayers) + paint.setARGB(255, 255, 0, 255); + + canvas->drawLine(0, 0, w, h, paint); + canvas->drawLine(0, h, w, 0, paint); + + canvas->drawLine(0, 0, 0, h-1, paint); + canvas->drawLine(0, h-1, w-1, h-1, paint); + canvas->drawLine(w-1, h-1, w-1, 0, paint); + canvas->drawLine(w-1, 0, 0, 0, paint); + } + + if (m_fixedPosition) + return m_fixedPosition->contentDraw(canvas, style); +} + +void LayerAndroid::onDraw(SkCanvas* canvas, SkScalar opacity, + android::DrawExtra* extra, PaintStyle style) +{ + if (m_haveClip) { + SkRect r; + r.set(0, 0, getSize().width(), getSize().height()); + canvas->clipRect(r); + return; + } + + if (masksToBounds() || !m_content) + return; + + // we just have this save/restore for opacity... + SkAutoCanvasRestore restore(canvas, true); + + int canvasOpacity = SkScalarRound(opacity * 255); + if (canvasOpacity < 255) + canvas->setDrawFilter(new OpacityDrawFilter(canvasOpacity)); + + if (m_imageCRC) { + ImageTexture* imageTexture = ImagesManager::instance()->retainImage(m_imageCRC); + m_dirtyRegion.setEmpty(); + if (imageTexture) { + SkRect dest; + dest.set(0, 0, getSize().width(), getSize().height()); + imageTexture->drawCanvas(canvas, dest); + } + ImagesManager::instance()->releaseImage(m_imageCRC); + } + contentDraw(canvas, style); + if (extra) + extra->draw(canvas, this); +} + +void LayerAndroid::setFixedPosition(FixedPositioning* position) { + if (m_fixedPosition && m_fixedPosition != position) + delete m_fixedPosition; + m_fixedPosition = position; +} + +void LayerAndroid::dumpLayer(FILE* file, int indentLevel) const +{ + writeHexVal(file, indentLevel + 1, "layer", (int)this); + writeIntVal(file, indentLevel + 1, "layerId", m_uniqueId); + writeIntVal(file, indentLevel + 1, "haveClip", m_haveClip); + writeIntVal(file, indentLevel + 1, "isFixed", isPositionFixed()); + + writeFloatVal(file, indentLevel + 1, "opacity", getOpacity()); + writeSize(file, indentLevel + 1, "size", getSize()); + writePoint(file, indentLevel + 1, "position", getPosition()); + writePoint(file, indentLevel + 1, "anchor", getAnchorPoint()); + + writeMatrix(file, indentLevel + 1, "drawMatrix", m_drawTransform); + writeMatrix(file, indentLevel + 1, "transformMatrix", m_transform); + writeRect(file, indentLevel + 1, "clippingRect", SkRect(m_clippingRect)); + + if (m_content) { + writeIntVal(file, indentLevel + 1, "m_content.width", m_content->width()); + writeIntVal(file, indentLevel + 1, "m_content.height", m_content->height()); + } + + if (m_fixedPosition) + return m_fixedPosition->dumpLayer(file, indentLevel); +} + +void LayerAndroid::dumpLayers(FILE* file, int indentLevel) const +{ + writeln(file, indentLevel, "{"); + + dumpLayer(file, indentLevel); + + if (countChildren()) { + writeln(file, indentLevel + 1, "children = ["); + for (int i = 0; i < countChildren(); i++) { + if (i > 0) + writeln(file, indentLevel + 1, ", "); + getChild(i)->dumpLayers(file, indentLevel + 1); + } + writeln(file, indentLevel + 1, "];"); + } + writeln(file, indentLevel, "}"); +} + +void LayerAndroid::dumpToLog() const +{ + FILE* file = fopen("/data/data/com.android.browser/layertmp", "w"); + dumpLayers(file, 0); + fclose(file); + file = fopen("/data/data/com.android.browser/layertmp", "r"); + char buffer[512]; + bzero(buffer, sizeof(buffer)); + while (fgets(buffer, sizeof(buffer), file)) + SkDebugf("%s", buffer); + fclose(file); +} + +LayerAndroid* LayerAndroid::findById(int match) +{ + if (m_uniqueId == match) + return this; + for (int i = 0; i < countChildren(); i++) { + LayerAndroid* result = getChild(i)->findById(match); + if (result) + return result; + } + return 0; +} + +} // namespace WebCore + +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/android/layers/LayerAndroid.h b/Source/WebCore/platform/graphics/android/layers/LayerAndroid.h new file mode 100644 index 0000000..6239418 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/layers/LayerAndroid.h @@ -0,0 +1,394 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LayerAndroid_h +#define LayerAndroid_h + +#if USE(ACCELERATED_COMPOSITING) + +#include "FloatPoint.h" +#include "FloatPoint3D.h" +#include "FloatRect.h" +#include "GraphicsLayerClient.h" +#include "ImageTexture.h" +#include "Layer.h" +#include "PlatformString.h" +#include "RefPtr.h" +#include "SkBitmap.h" +#include "SkColor.h" +#include "SkRegion.h" +#include "SkStream.h" +#include "TransformationMatrix.h" + +#include +#include + +#ifndef BZERO_DEFINED +#define BZERO_DEFINED +// http://www.opengroup.org/onlinepubs/000095399/functions/bzero.html +// For maximum portability, it is recommended to replace the function call to bzero() as follows: +#define bzero(b, len) (memset((b), '\0', (len)), (void) 0) +#endif + +class SkBitmapRef; +class SkCanvas; +class SkMatrix; +class SkPicture; + +namespace WebCore { +class LayerAndroid; +class LayerContent; +class ImageTexture; +class Surface; +} + +namespace android { +class DrawExtra; +void serializeLayer(WebCore::LayerAndroid* layer, SkWStream* stream); +WebCore::LayerAndroid* deserializeLayer(int version, SkStream* stream); +void cleanupImageRefs(WebCore::LayerAndroid* layer); +} + +using namespace android; + +namespace WebCore { + +class AndroidAnimation; +class FixedPositioning; +class GLWebViewState; +class IFrameLayerAndroid; +class LayerMergeState; +class RenderLayer; +class PaintedSurface; + +class TexturesResult { +public: + TexturesResult() + : fixed(0) + , scrollable(0) + , clipped(0) + , full(0) + {} + + int fixed; + int scrollable; + int clipped; + int full; +}; + +class TEST_EXPORT LayerAndroid : public Layer { +public: + typedef enum { UndefinedLayer, WebCoreLayer, UILayer } LayerType; + typedef enum { StandardLayer, ScrollableLayer, + IFrameLayer, IFrameContentLayer, + CanvasLayer, BaseLayer } SubclassType; + typedef enum { InvalidateNone = 0, InvalidateLayers } InvalidateFlags; + + String subclassName() + { + switch (subclassType()) { + case LayerAndroid::StandardLayer: + return "StandardLayer"; + case LayerAndroid::ScrollableLayer: + return "ScrollableLayer"; + case LayerAndroid::IFrameLayer: + return "IFrameLayer"; + case LayerAndroid::IFrameContentLayer: + return "IFrameContentLayer"; + case LayerAndroid::CanvasLayer: + return "CanvasLayer"; + case LayerAndroid::BaseLayer: + return "BaseLayer"; + } + return "Undefined"; + } + + LayerAndroid(RenderLayer* owner); + LayerAndroid(const LayerAndroid& layer); + virtual ~LayerAndroid(); + + void setBackfaceVisibility(bool value) { m_backfaceVisibility = value; } + void setTransform(const TransformationMatrix& matrix) { m_transform = matrix; } + FloatPoint translation() const; + // Returns a rect describing the bounds of the layer with the local + // transformation applied, expressed relative to the parent layer. + // FIXME: Currently we use only the translation component of the local + // transformation. + SkRect bounds() const; + IntRect clippedRect() const; + bool outsideViewport(); + + IntRect unclippedArea(); + IntRect visibleArea(); + + virtual bool needsTexture(); + + // Debug helper methods + int nbLayers(); + int nbTexturedLayers(); + void showLayer(int indent = 0); + + float getScale() { return m_scale; } + + virtual bool drawGL(bool layerTilesDisabled); + virtual bool drawCanvas(SkCanvas* canvas, bool drawChildren, PaintStyle style); + bool drawChildrenCanvas(SkCanvas* canvas, PaintStyle style); + + void updateGLPositionsAndScale(const TransformationMatrix& parentMatrix, + const FloatRect& clip, float opacity, float scale); + void setDrawOpacity(float opacity) { m_drawOpacity = opacity; } + float drawOpacity() { return m_drawOpacity; } + bool visible(); + void setVisible(bool value) { m_visible = value; } + + bool preserves3D() { return m_preserves3D; } + void setPreserves3D(bool value) { m_preserves3D = value; } + void setAnchorPointZ(float z) { m_anchorPointZ = z; } + float anchorPointZ() { return m_anchorPointZ; } + void setDrawTransform(const TransformationMatrix& transform) { m_drawTransform = transform; } + virtual const TransformationMatrix* drawTransform() const { return &m_drawTransform; } + void setChildrenTransform(const TransformationMatrix& t) { m_childrenTransform = t; } + void setDrawClip(const FloatRect& rect) { m_clippingRect = rect; } + const FloatRect& drawClip() { return m_clippingRect; } + + const IntPoint& scrollOffset() const { return m_offset; } + void setScrollOffset(IntPoint offset) { m_offset = offset; } + void setBackgroundColor(SkColor color); + void setMaskLayer(LayerAndroid*); + void setMasksToBounds(bool masksToBounds) + { + m_haveClip = masksToBounds; + } + bool masksToBounds() const { return m_haveClip; } + + LayerContent* content() { return m_content; } + void setContent(LayerContent* content); + + void addAnimation(PassRefPtr anim); + void removeAnimationsForProperty(AnimatedPropertyID property); + void removeAnimationsForKeyframes(const String& name); + bool evaluateAnimations(); + bool evaluateAnimations(double time); + void initAnimations(); + bool hasAnimations() const; + void addDirtyArea(); + + virtual void dumpLayer(FILE*, int indentLevel) const; + void dumpLayers(FILE*, int indentLevel) const; + void dumpToLog() const; + + /** Call this with the current viewport (scrolling, zoom) to update + the position of the fixed layers. + + This call is recursive, so it should be called on the root of the + hierarchy. + */ + void updateLayerPositions(SkRect viewPort, IFrameLayerAndroid* parentIframeLayer = 0); + virtual IFrameLayerAndroid* updatePosition(SkRect viewport, + IFrameLayerAndroid* parentIframeLayer); + + /** Call this to update the position attribute, so that later calls + like bounds() will report the corrected position. + + This call is recursive, so it should be called on the root of the + hierarchy. + */ + void updatePositions(); + + void clipArea(SkTDArray* region) const; + const LayerAndroid* find(int* xPtr, int* yPtr, SkPicture* root) const; + const LayerAndroid* findById(int uniqueID) const + { + return const_cast(this)->findById(uniqueID); + } + LayerAndroid* findById(int uniqueID); + LayerAndroid* getChild(int index) const + { + return static_cast(this->INHERITED::getChild(index)); + } + int uniqueId() const { return m_uniqueId; } + + /** This sets a content image -- calling it means we will use + the image directly when drawing the layer instead of using + the content painted by WebKit. + Images are handled in ImagesManager, as they can be shared + between layers. + */ + void setContentsImage(SkBitmapRef* img); + + void bounds(SkRect*) const; + + virtual LayerAndroid* copy() const { return new LayerAndroid(*this); } + + virtual void clearDirtyRegion(); + + virtual void contentDraw(SkCanvas* canvas, PaintStyle style); + + virtual bool isMedia() const { return false; } + virtual bool isVideo() const { return false; } + virtual bool isIFrame() const { return false; } + virtual bool isIFrameContent() const { return false; } + + bool isPositionFixed() const { return m_fixedPosition; } + void setAbsolutePosition(bool isAbsolute) { m_isPositionAbsolute = isAbsolute; } + bool isPositionAbsolute() { return m_isPositionAbsolute; } + void setFixedPosition(FixedPositioning* position); + FixedPositioning* fixedPosition() { return m_fixedPosition; } + + RenderLayer* owningLayer() const { return m_owningLayer; } + + float zValue() const { return m_zValue; } + + // ViewStateSerializer friends + friend void android::serializeLayer(LayerAndroid* layer, SkWStream* stream); + friend LayerAndroid* android::deserializeLayer(int version, SkStream* stream); + friend void android::cleanupImageRefs(LayerAndroid* layer); + + // Update layers using another tree. Only works for basic properties + // such as the position, the transform. Return true if anything more + // complex is needed. + bool updateWithTree(LayerAndroid*); + virtual bool updateWithLayer(LayerAndroid*); + + LayerType type() { return m_type; } + virtual SubclassType subclassType() { return LayerAndroid::StandardLayer; } + + bool hasText(); + + void copyAnimationStartTimesRecursive(LayerAndroid* oldTree); + +// rendering asset management + SkRegion* getInvalRegion() { return &m_dirtyRegion; } + void mergeInvalsInto(LayerAndroid* replacementTree); + + bool canJoinSurface(Surface* surface); + void assignSurfaces(LayerMergeState* mergeState); + Surface* surface() { return m_surface; } + + void setIntrinsicallyComposited(bool intCom) { m_intrinsicallyComposited = intCom; } + + int setHwAccelerated(bool hwAccelerated); + +protected: + virtual void onDraw(SkCanvas*, SkScalar opacity, android::DrawExtra* extra, PaintStyle style); + virtual InvalidateFlags onSetHwAccelerated(bool hwAccelerated) { return InvalidateNone; } + IntPoint m_offset; + TransformationMatrix m_drawTransform; + int m_uniqueId; + +private: +#if DUMP_NAV_CACHE + friend class CachedLayer::Debug; // debugging access only +#endif + + void copyAnimationStartTimes(LayerAndroid* oldLayer); + bool prepareContext(bool force = false); + void clipInner(SkTDArray* region, const SkRect& local) const; + + // ------------------------------------------------------------------- + // Fields to be serialized + // ------------------------------------------------------------------- + + bool m_haveClip; + bool m_backgroundColorSet; + + bool m_backfaceVisibility; + bool m_visible; + + SkColor m_backgroundColor; + + bool m_preserves3D; + float m_anchorPointZ; + float m_drawOpacity; + + bool m_isPositionAbsolute; + FixedPositioning* m_fixedPosition; + + typedef HashMap, RefPtr > KeyframesMap; + KeyframesMap m_animations; + + TransformationMatrix m_transform; + TransformationMatrix m_childrenTransform; + + // ------------------------------------------------------------------- + // Fields that are not serialized (generated, cached, or non-serializable) + // ------------------------------------------------------------------- + + float m_zValue; + + FloatRect m_clippingRect; + + // Note that m_content and m_imageCRC are mutually exclusive; + // m_content is used when WebKit is asked to paint the layer's + // content, while m_imageCRC references an image that we directly + // composite, using the layer's dimensions as a destination rect. + // We do this as if the layer only contains an image, directly compositing + // it is a much faster method than using m_content. + LayerContent* m_content; + unsigned m_imageCRC; + + // used to signal the framework we need a repaint + bool m_hasRunningAnimations; + + float m_scale; + + // We try to not always compute the texture size, as this is quite heavy + static const double s_computeTextureDelay = 0.2; // 200 ms + double m_lastComputeTextureSize; + + // This mutex serves two purposes. (1) It ensures that certain operations + // happen atomically and (2) it makes sure those operations are synchronized + // across all threads and cores. + android::Mutex m_atomicSync; + + RenderLayer* m_owningLayer; + + LayerType m_type; + SubclassType m_subclassType; + + bool m_intrinsicallyComposited; + + Surface* m_surface; + + typedef Layer INHERITED; +}; + +} + +#else + +class SkPicture; + +namespace WebCore { + +class LayerAndroid { +public: + LayerAndroid(SkPicture* picture) : + m_recordingPicture(picture), // does not assign ownership + m_uniqueId(-1) + {} + SkPicture* picture() const { return m_recordingPicture; } + int uniqueId() const { return m_uniqueId; } +private: + SkPicture* m_recordingPicture; + int m_uniqueId; +}; + +} + +#endif // USE(ACCELERATED_COMPOSITING) + +#endif // LayerAndroid_h diff --git a/Source/WebCore/platform/graphics/android/layers/LayerContent.h b/Source/WebCore/platform/graphics/android/layers/LayerContent.h new file mode 100644 index 0000000..97bc32a --- /dev/null +++ b/Source/WebCore/platform/graphics/android/layers/LayerContent.h @@ -0,0 +1,56 @@ +/* + * Copyright 2012, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef LayerContent_h +#define LayerContent_h + +#include "SkRefCnt.h" +#include + +class SkCanvas; +class SkPicture; +class SkWStream; + +namespace WebCore { + +class LayerContent : public SkRefCnt { +public: + virtual int width() = 0; + virtual int height() = 0; + virtual bool isEmpty() = 0; + virtual void checkForOptimisations() = 0; + virtual bool hasText() = 0; + virtual void draw(SkCanvas* canvas) = 0; + + virtual void serialize(SkWStream* stream) = 0; + +protected: + // used to prevent parallel draws, as both SkPicture and PictureSet don't support them + android::Mutex m_drawLock; +}; + +} // WebCore + +#endif // LayerContent_h diff --git a/Source/WebCore/platform/graphics/android/layers/MediaLayer.cpp b/Source/WebCore/platform/graphics/android/layers/MediaLayer.cpp new file mode 100644 index 0000000..6227ea4 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/layers/MediaLayer.cpp @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "MediaLayer" +#define LOG_NDEBUG 1 + +#include "config.h" +#include "MediaLayer.h" + +#include "AndroidLog.h" +#include "MediaTexture.h" +#include "TilesManager.h" + +#if USE(ACCELERATED_COMPOSITING) + +namespace WebCore { + +MediaLayer::MediaLayer(jobject webViewRef, jobject webViewCoreRef) : LayerAndroid((RenderLayer*) NULL) +{ + m_mediaTexture = new MediaTexture(webViewRef, webViewCoreRef); + m_mediaTexture->incStrong(this); + + m_isCopy = false; + m_outlineSize = 0; + ALOGV("Creating Media Layer %p", this); +} + +MediaLayer::MediaLayer(const MediaLayer& layer) : LayerAndroid(layer) +{ + m_mediaTexture = layer.m_mediaTexture; + m_mediaTexture->incStrong(this); + + m_isCopy = true; + m_outlineSize = layer.m_outlineSize; + ALOGV("Creating Media Layer Copy %p -> %p", &layer, this); +} + +MediaLayer::~MediaLayer() +{ + ALOGV("Deleting Media Layer"); + m_mediaTexture->decStrong(this); +} + +bool MediaLayer::drawGL(bool layerTilesDisabled) +{ + FloatRect clippingRect = TilesManager::instance()->shader()->rectInScreenCoord(drawClip()); + TilesManager::instance()->shader()->clip(clippingRect); + + // when the plugin gains focus webkit applies an outline to the + // widget, which causes the layer to expand to accommodate the + // outline. Therefore, we shrink the rect by the outline's dimensions + // to ensure the plugin does not draw outside of its bounds. + SkRect mediaBounds; + mediaBounds.set(0, 0, getSize().width(), getSize().height()); + mediaBounds.inset(m_outlineSize, m_outlineSize); + + // check to see if we need to create a content or video texture + m_mediaTexture->initNativeWindowIfNeeded(); + + // the layer's shader draws the content inverted so we must undo + // that change in the transformation matrix + TransformationMatrix m = m_drawTransform; + if (!m_mediaTexture->isContentInverted()) { + m.flipY(); + m.translate(0, -getSize().height()); + } + + // draw any content or video if present + m_mediaTexture->draw(m, m_drawTransform, mediaBounds); + return false; +} + +ANativeWindow* MediaLayer::acquireNativeWindowForContent() +{ + return m_mediaTexture->getNativeWindowForContent(); +} + + +ANativeWindow* MediaLayer::acquireNativeWindowForVideo() +{ + return m_mediaTexture->requestNativeWindowForVideo(); +} + +void MediaLayer::setWindowDimensionsForVideo(const ANativeWindow* window, const SkRect& dimensions) +{ + //TODO validate that the dimensions do not exceed the plugin's bounds + m_mediaTexture->setDimensions(window, dimensions); +} + +void MediaLayer::releaseNativeWindowForVideo(ANativeWindow* window) +{ + m_mediaTexture->releaseNativeWindow(window); +} + +void MediaLayer::setFramerateCallback(const ANativeWindow* window, FramerateCallbackProc callback) +{ + m_mediaTexture->setFramerateCallback(window, callback); +} + +} // namespace WebCore + +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/android/layers/MediaLayer.h b/Source/WebCore/platform/graphics/android/layers/MediaLayer.h new file mode 100644 index 0000000..2f39d74 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/layers/MediaLayer.h @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MediaLayer_h +#define MediaLayer_h + +#if USE(ACCELERATED_COMPOSITING) + +#include "MediaTexture.h" +#include "LayerAndroid.h" +#include + +namespace android { + class SurfaceTexture; +} + +namespace WebCore { + +class MediaLayer : public LayerAndroid { + +public: + MediaLayer(jobject webViewRef, jobject webViewCoreRef); + MediaLayer(const MediaLayer& layer); + virtual ~MediaLayer(); + + virtual bool drawGL(bool layerTilesDisabled); + virtual void paintBitmapGL() const { }; + virtual bool needsTexture() { return false; } + + virtual bool isMedia() const { return true; } + virtual LayerAndroid* copy() const { return new MediaLayer(*this); } + + void invertContents(bool invert) { m_mediaTexture->invertContents(invert); } + void setOutlineSize(int size) { m_outlineSize = size; } + + // function to setup the primary SurfaceTexture in the renderer's context + ANativeWindow* acquireNativeWindowForContent(); + + // functions to manipulate secondary layers for video playback + ANativeWindow* acquireNativeWindowForVideo(); + void setWindowDimensionsForVideo(const ANativeWindow* window, const SkRect& dimensions); + void releaseNativeWindowForVideo(ANativeWindow* window); + void setFramerateCallback(const ANativeWindow* window, FramerateCallbackProc callback); + +private: + bool m_isCopy; + int m_outlineSize; + + // SurfaceTexture member variables + MediaTexture* m_mediaTexture; +}; + +} // namespace WebCore + +#endif // USE(ACCELERATED_COMPOSITING) + +#endif // MediaLayer_h diff --git a/Source/WebCore/platform/graphics/android/layers/MediaListener.h b/Source/WebCore/platform/graphics/android/layers/MediaListener.h new file mode 100644 index 0000000..2dfc08b --- /dev/null +++ b/Source/WebCore/platform/graphics/android/layers/MediaListener.h @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MediaListener_h +#define MediaListener_h + +#if USE(ACCELERATED_COMPOSITING) + +#include +#include +#include +#include +#include "MediaTexture.h" +#include "WebCoreJni.h" + +namespace WebCore { + +class MediaListener : public android::SurfaceTexture::FrameAvailableListener { + +public: + MediaListener(jobject weakWebViewRef, + const sp& surfaceTexture, + const sp& nativeWindow) + : m_weakWebViewRef(weakWebViewRef) + , m_postInvalMethod(0) + , m_frameAvailable(false) + , m_surfaceTexture(surfaceTexture) + , m_nativeWindow(nativeWindow) + , m_framerateCallback(0) + { + if (!m_weakWebViewRef) + return; + + JNIEnv* env = JSC::Bindings::getJNIEnv(); + jobject localWebViewRef = env->NewLocalRef(m_weakWebViewRef); + if (localWebViewRef) { + jclass wvClass = env->GetObjectClass(localWebViewRef); + m_postInvalMethod = env->GetMethodID(wvClass, "postInvalidate", "()V"); + env->DeleteLocalRef(wvClass); + env->DeleteLocalRef(localWebViewRef); + } + checkException(env); + } + + virtual void onFrameAvailable() + { + JNIEnv* env = JSC::Bindings::getJNIEnv(); + jobject localWebViewRef = env->NewLocalRef(m_weakWebViewRef); + if (localWebViewRef) { + env->CallVoidMethod(localWebViewRef, m_postInvalMethod); + env->DeleteLocalRef(localWebViewRef); + } + checkException(env); + if (!m_frameAvailable) { + m_frameAvailable = true; + } + if (m_framerateCallback) + m_framerateCallback(m_nativeWindow.get(), m_surfaceTexture->getTimestamp()); + } + + bool isFrameAvailable() { return m_frameAvailable; } + void setFramerateCallback(FramerateCallbackProc callback) { m_framerateCallback = callback; } + +private: + jobject m_weakWebViewRef; + jmethodID m_postInvalMethod; + bool m_frameAvailable; + sp m_surfaceTexture; + sp m_nativeWindow; + FramerateCallbackProc m_framerateCallback; +}; + +} // namespace WebCore + +#endif // USE(ACCELERATED_COMPOSITING) +#endif // MediaListener_h diff --git a/Source/WebCore/platform/graphics/android/layers/MediaPlayerPrivateAndroid.h b/Source/WebCore/platform/graphics/android/layers/MediaPlayerPrivateAndroid.h new file mode 100644 index 0000000..535e7ae --- /dev/null +++ b/Source/WebCore/platform/graphics/android/layers/MediaPlayerPrivateAndroid.h @@ -0,0 +1,143 @@ +/* + * Copyright 2009,2010 The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef MediaPlayerPrivateAndroid_h +#define MediaPlayerPrivateAndroid_h + +#if ENABLE(VIDEO) + +class SkBitmap; + +#include "MediaPlayerPrivate.h" +#include "TimeRanges.h" +#include "VideoLayerAndroid.h" + +namespace WebCore { + +class MediaPlayerPrivate : public MediaPlayerPrivateInterface { +public: + virtual ~MediaPlayerPrivate(); + + static void registerMediaEngine(MediaEngineRegistrar); + + virtual void load(const String& url) = 0; + virtual void cancelLoad() { } + + virtual void play() = 0; + virtual void pause(); + + virtual IntSize naturalSize() const { return m_naturalSize; } + + virtual bool supportsFullscreen() const = 0; + virtual bool hasAudio() const = 0; + virtual bool hasVideo() const = 0; + + virtual void setVisible(bool); + + virtual float duration() const { return m_duration; } + + virtual float currentTime() const { return m_currentTime; }; + virtual void seek(float time); + virtual bool seeking() const { return false; } + + virtual void setEndTime(float time) { } + + virtual void setRate(float) { } + virtual bool paused() const { return m_paused; } + + virtual void setVolume(float) { } + + virtual MediaPlayer::NetworkState networkState() const { return m_networkState; } + virtual MediaPlayer::ReadyState readyState() const { return m_readyState; } + + virtual float maxTimeSeekable() const { return 0; } + virtual PassRefPtr buffered() const { return TimeRanges::create(); } + + virtual int dataRate() const { return 0; } + + virtual bool totalBytesKnown() const { return totalBytes() > 0; } + virtual unsigned totalBytes() const { return 0; } + virtual unsigned bytesLoaded() const { return 0; } + + virtual void setSize(const IntSize&) { } + + virtual bool canLoadPoster() const { return false; } + virtual void setPoster(const String&) { } + virtual void prepareToPlay(); + + virtual void paint(GraphicsContext*, const IntRect&) { } + + virtual void onPrepared(int duration, int width, int height) { } + void onEnded(); + void onPaused(); + virtual void onPosterFetched(SkBitmap*) { } + void onBuffering(int percent); + void onTimeupdate(int position); + void onRestoreState(); + + // These following two functions are used to turn on inline video support + bool supportsAcceleratedRendering() const { return true; } + LayerAndroid* platformLayer() const + { + return m_videoLayer; + } + void onStopFullscreen(); + +protected: + // Android-specific methods and fields. + static MediaPlayerPrivateInterface* create(MediaPlayer* player); + static void getSupportedTypes(HashSet&) { } + static MediaPlayer::SupportsType supportsType(const String& type, const String& codecs); + + MediaPlayerPrivate(MediaPlayer *); + virtual void createJavaPlayerIfNeeded() { } + + MediaPlayer* m_player; + String m_url; + struct JavaGlue; + JavaGlue* m_glue; + + float m_duration; + float m_currentTime; + + bool m_paused; + MediaPlayer::ReadyState m_readyState; + MediaPlayer::NetworkState m_networkState; + + SkBitmap* m_poster; // not owned + String m_posterUrl; + + IntSize m_naturalSize; + bool m_naturalSizeUnknown; + + bool m_isVisible; + VideoLayerAndroid* m_videoLayer; +}; + +} // namespace WebCore + +#endif + +#endif // MediaPlayerPrivateAndroid_h diff --git a/Source/WebCore/platform/graphics/android/layers/MediaTexture.cpp b/Source/WebCore/platform/graphics/android/layers/MediaTexture.cpp new file mode 100644 index 0000000..dffe6c2 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/layers/MediaTexture.cpp @@ -0,0 +1,316 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "MediaTexture" +#define LOG_NDEBUG 1 + +#include "config.h" +#include "MediaTexture.h" + +#include "AndroidLog.h" +#include "DrawQuadData.h" +#include "TilesManager.h" +#include "GLUtils.h" +#include "MediaListener.h" + +#if USE(ACCELERATED_COMPOSITING) + +#include +#include +#include +#include +#include "WebCoreJni.h" + +// Limits the number of ANativeWindows that can be allocated for video playback. +// The limit is currently set to 2 as that is the current max number of +// simultaneous HW decodes that our OMX implementation allows. This forces the +// media producer to use their own SW decoders for subsequent video streams. +#define MAX_WINDOW_COUNT 2 + +namespace WebCore { + +MediaTexture::MediaTexture(jobject webViewRef, jobject webViewCoreRef) : android::LightRefBase() +{ + JNIEnv* env = JSC::Bindings::getJNIEnv(); + m_weakWebViewRef = env->NewWeakGlobalRef(webViewRef); + m_weakWebViewCoreRef = env->NewWeakGlobalRef(webViewCoreRef); + + m_contentTexture = 0; + m_isContentInverted = false; + m_newWindowRequest = false; +} + +MediaTexture::~MediaTexture() +{ + if (m_contentTexture) + deleteTexture(m_contentTexture, true); + for (unsigned int i = 0; i < m_videoTextures.size(); i++) { + deleteTexture(m_videoTextures[i], true); + } + + JNIEnv* env = JSC::Bindings::getJNIEnv(); + env->DeleteWeakGlobalRef(m_weakWebViewRef); + env->DeleteWeakGlobalRef(m_weakWebViewCoreRef); +} + +bool MediaTexture::isContentInverted() +{ + android::Mutex::Autolock lock(m_mediaLock); + return m_isContentInverted; +} +void MediaTexture::invertContents(bool invertContent) +{ + android::Mutex::Autolock lock(m_mediaLock); + m_isContentInverted = invertContent; +} + +void MediaTexture::initNativeWindowIfNeeded() +{ + { + android::Mutex::Autolock lock(m_mediaLock); + + // check to see if there are any unused textures to delete + if (m_unusedTextures.size() != 0) { + for (unsigned int i = 0; i < m_unusedTextures.size(); i++) { + glDeleteTextures(1, &m_unusedTextures[i]); + } + m_unusedTextures.clear(); + } + + // create a content texture if none exists + if (!m_contentTexture) { + m_contentTexture = createTexture(); + + // send a message to the WebKit thread to notify the plugin that it can draw + if (m_weakWebViewCoreRef) { + JNIEnv* env = JSC::Bindings::getJNIEnv(); + jobject localWebViewCoreRef = env->NewLocalRef(m_weakWebViewCoreRef); + if (localWebViewCoreRef) { + jclass wvClass = env->GetObjectClass(localWebViewCoreRef); + jmethodID sendPluginDrawMsg = + env->GetMethodID(wvClass, "sendPluginDrawMsg", "()V"); + env->CallVoidMethod(localWebViewCoreRef, sendPluginDrawMsg); + env->DeleteLocalRef(wvClass); + env->DeleteLocalRef(localWebViewCoreRef); + } + checkException(env); + } + } + + // finally create a video texture if needed + if (!m_newWindowRequest) + return; + + // add the texture and add it to the list + TextureWrapper* videoTexture = createTexture(); + m_videoTextures.append(videoTexture); + + // setup the state variables to signal the other thread + m_newWindowRequest = false; + m_newWindow = videoTexture->nativeWindow; + } + + // signal the WebKit thread in case it is waiting + m_newMediaRequestCond.signal(); +} + +void MediaTexture::draw(const TransformationMatrix& contentMatrix, + const TransformationMatrix& videoMatrix, + const SkRect& mediaBounds) +{ + android::Mutex::Autolock lock(m_mediaLock); + + if (mediaBounds.isEmpty()) + return; + + // draw all the video textures first + for (unsigned int i = 0; i < m_videoTextures.size(); i++) { + + TextureWrapper* video = m_videoTextures[i]; + + if (!video->surfaceTexture.get() || video->dimensions.isEmpty() + || !video->mediaListener->isFrameAvailable()) + continue; + + video->surfaceTexture->updateTexImage(); + + float surfaceMatrix[16]; + video->surfaceTexture->getTransformMatrix(surfaceMatrix); + + SkRect dimensions = video->dimensions; + dimensions.offset(mediaBounds.fLeft, mediaBounds.fTop); + +#ifdef DEBUG + if (!mediaBounds.contains(dimensions)) { + ALOGV("The video exceeds is parent's bounds."); + } +#endif // DEBUG + + TilesManager::instance()->shader()->drawVideoLayerQuad(videoMatrix, + surfaceMatrix, dimensions, video->textureId); + } + + if (!m_contentTexture->mediaListener->isFrameAvailable()) + return; + + m_contentTexture->surfaceTexture->updateTexImage(); + + sp buf = m_contentTexture->surfaceTexture->getCurrentBuffer(); + + PixelFormat f = buf->getPixelFormat(); + // only attempt to use alpha blending if alpha channel exists + bool forceAlphaBlending = !( + PIXEL_FORMAT_RGBX_8888 == f || + PIXEL_FORMAT_RGB_888 == f || + PIXEL_FORMAT_RGB_565 == f); + + TextureQuadData data(m_contentTexture->textureId, GL_TEXTURE_EXTERNAL_OES, + GL_LINEAR, LayerQuad, &contentMatrix, &mediaBounds, + 1.0f, forceAlphaBlending); + TilesManager::instance()->shader()->drawQuad(&data); +} + +ANativeWindow* MediaTexture::requestNativeWindowForVideo() +{ + android::Mutex::Autolock lock(m_mediaLock); + + // the window was not ready before the timeout so return it this time + if (ANativeWindow* window = m_newWindow.get()) { + m_newWindow.clear(); + return window; + } + + // we only allow for so many textures, so return NULL if we exceed that limit + else if (m_videoTextures.size() >= MAX_WINDOW_COUNT) { + return 0; + } + + m_newWindowRequest = true; + + // post an inval message to the UI thread to fulfill the request + if (m_weakWebViewRef) { + JNIEnv* env = JSC::Bindings::getJNIEnv(); + jobject localWebViewRef = env->NewLocalRef(m_weakWebViewRef); + if (localWebViewRef) { + jclass wvClass = env->GetObjectClass(localWebViewRef); + jmethodID postInvalMethod = env->GetMethodID(wvClass, "postInvalidate", "()V"); + env->CallVoidMethod(localWebViewRef, postInvalMethod); + env->DeleteLocalRef(wvClass); + env->DeleteLocalRef(localWebViewRef); + } + checkException(env); + } + + //block until the request can be fulfilled or we time out + bool timedOut = false; + while (m_newWindowRequest && !timedOut) { + int ret = m_newMediaRequestCond.waitRelative(m_mediaLock, 500000000); // .5 sec + timedOut = ret == TIMED_OUT; + } + + // if the window is ready then return it otherwise return NULL + if (ANativeWindow* window = m_newWindow.get()) { + m_newWindow.clear(); + return window; + } + return 0; +} + +ANativeWindow* MediaTexture::getNativeWindowForContent() +{ + android::Mutex::Autolock lock(m_mediaLock); + if (m_contentTexture) + return m_contentTexture->nativeWindow.get(); + else + return 0; +} + +void MediaTexture::releaseNativeWindow(const ANativeWindow* window) +{ + android::Mutex::Autolock lock(m_mediaLock); + for (unsigned int i = 0; i < m_videoTextures.size(); i++) { + if (m_videoTextures[i]->nativeWindow.get() == window) { + deleteTexture(m_videoTextures[i]); + m_videoTextures.remove(i); + break; + } + } +} + +void MediaTexture::setDimensions(const ANativeWindow* window, + const SkRect& dimensions) +{ + android::Mutex::Autolock lock(m_mediaLock); + for (unsigned int i = 0; i < m_videoTextures.size(); i++) { + if (m_videoTextures[i]->nativeWindow.get() == window) { + m_videoTextures[i]->dimensions = dimensions; + break; + } + } +} + +void MediaTexture::setFramerateCallback(const ANativeWindow* window, + FramerateCallbackProc callback) +{ + android::Mutex::Autolock lock(m_mediaLock); + for (unsigned int i = 0; i < m_videoTextures.size(); i++) { + if (m_videoTextures[i]->nativeWindow.get() == window) { + m_videoTextures[i]->mediaListener->setFramerateCallback(callback); + break; + } + } +} + +MediaTexture::TextureWrapper* MediaTexture::createTexture() +{ + TextureWrapper* wrapper = new TextureWrapper(); + + // populate the wrapper + glGenTextures(1, &wrapper->textureId); + wrapper->surfaceTexture = new android::SurfaceTexture(wrapper->textureId); + wrapper->nativeWindow = new android::SurfaceTextureClient(wrapper->surfaceTexture); + wrapper->dimensions.setEmpty(); + + // setup callback + wrapper->mediaListener = new MediaListener(m_weakWebViewRef, + wrapper->surfaceTexture, + wrapper->nativeWindow); + wrapper->surfaceTexture->setFrameAvailableListener(wrapper->mediaListener); + + return wrapper; +} + +void MediaTexture::deleteTexture(TextureWrapper* texture, bool force) +{ + if (texture->surfaceTexture.get()) + texture->surfaceTexture->setFrameAvailableListener(0); + + if (force) + glDeleteTextures(1, &texture->textureId); + else + m_unusedTextures.append(texture->textureId); + + // clear the strong pointer references + texture->mediaListener.clear(); + texture->nativeWindow.clear(); + texture->surfaceTexture.clear(); + + delete texture; +} + +} // namespace WebCore + +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/android/layers/MediaTexture.h b/Source/WebCore/platform/graphics/android/layers/MediaTexture.h new file mode 100644 index 0000000..9ea7be2 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/layers/MediaTexture.h @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MediaTexture_h +#define MediaTexture_h + +#if USE(ACCELERATED_COMPOSITING) + +#include "RefPtr.h" +#include "LayerAndroid.h" +#include "Vector.h" +#include +#include +#include +#include + +namespace android { + class SurfaceTexture; +} + +namespace WebCore { + +typedef void (*FramerateCallbackProc)(ANativeWindow* window, int64_t timestamp); + +class MediaListener; + +class MediaTexture : public android::LightRefBase { + +public: + MediaTexture(jobject webViewRef, jobject webViewCoreRef); + ~MediaTexture(); + + bool isContentInverted(); + void invertContents(bool invertContent); + + void initNativeWindowIfNeeded(); + void draw(const TransformationMatrix& contentMatrix, + const TransformationMatrix& videoMatrix, + const SkRect& mediaBounds); + + ANativeWindow* getNativeWindowForContent(); + ANativeWindow* requestNativeWindowForVideo(); + + void releaseNativeWindow(const ANativeWindow* window); + void setDimensions(const ANativeWindow* window, const SkRect& dimensions); + void setFramerateCallback(const ANativeWindow* window, + FramerateCallbackProc callback); + +private: + struct TextureWrapper { + GLuint textureId; + sp surfaceTexture; + sp nativeWindow; + sp mediaListener; + SkRect dimensions; // only used by the video layer + }; + + TextureWrapper* createTexture(); + void deleteTexture(TextureWrapper* item, bool force = false); + + TextureWrapper* m_contentTexture; + Vector m_videoTextures; + Vector m_unusedTextures; + + // used to track if the content is to be drawn inverted + bool m_isContentInverted; + + // used to generate new video textures + bool m_newWindowRequest; + sp m_newWindow; + + jobject m_weakWebViewRef; + jobject m_weakWebViewCoreRef; + + android::Mutex m_mediaLock; + android::Condition m_newMediaRequestCond; +}; + + +} // namespace WebCore + +#endif // USE(ACCELERATED_COMPOSITING) + +#endif // MediaTexture_h diff --git a/Source/WebCore/platform/graphics/android/layers/PictureLayerContent.cpp b/Source/WebCore/platform/graphics/android/layers/PictureLayerContent.cpp new file mode 100644 index 0000000..4398146 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/layers/PictureLayerContent.cpp @@ -0,0 +1,106 @@ +#include "config.h" +#include "PictureLayerContent.h" + +#include "InspectorCanvas.h" +#include "SkPicture.h" + +namespace WebCore { + +PictureLayerContent::PictureLayerContent(SkPicture* picture) + : m_picture(picture) + , m_checkedContent(false) + , m_hasText(true) +{ + SkSafeRef(m_picture); +} + +PictureLayerContent::PictureLayerContent(const PictureLayerContent& content) + : m_picture(content.m_picture) + , m_checkedContent(content.m_checkedContent) + , m_hasText(content.m_hasText) +{ + SkSafeRef(m_picture); +} + +PictureLayerContent::~PictureLayerContent() +{ + SkSafeUnref(m_picture); +} + +int PictureLayerContent::width() +{ + if (!m_picture) + return 0; + return m_picture->width(); +} + +int PictureLayerContent::height() +{ + if (!m_picture) + return 0; + return m_picture->height(); +} + +bool PictureLayerContent::isEmpty() +{ + if (!m_picture) + return true; + if (m_picture->width() == 0 + || m_picture->height() == 0) + return true; + return false; +} + +void PictureLayerContent::checkForOptimisations() +{ + if (!m_checkedContent) + hasText(); // for now only check the presence of text +} + +bool PictureLayerContent::hasText() +{ + if (m_checkedContent) + return m_hasText; + + // Let's check if we have text or not. If we don't, we can limit + // ourselves to scale 1! + InspectorBounder inspectorBounder; + InspectorCanvas checker(&inspectorBounder, m_picture); + SkBitmap bitmap; + bitmap.setConfig(SkBitmap::kARGB_8888_Config, + m_picture->width(), + m_picture->height()); + checker.setBitmapDevice(bitmap); + checker.drawPicture(*m_picture); + m_hasText = checker.hasText(); + if (!checker.hasContent()) { + // no content to draw, discard picture so UI / tile generation + // doesn't bother with it + SkSafeUnref(m_picture); + m_picture = 0; + } + + m_checkedContent = true; + + return m_hasText; +} + +void PictureLayerContent::draw(SkCanvas* canvas) +{ + if (!m_picture) + return; + + android::Mutex::Autolock lock(m_drawLock); + SkRect r = SkRect::MakeWH(width(), height()); + canvas->clipRect(r); + canvas->drawPicture(*m_picture); +} + +void PictureLayerContent::serialize(SkWStream* stream) +{ + if (!m_picture) + return; + m_picture->serialize(stream); +} + +} // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/layers/PictureLayerContent.h b/Source/WebCore/platform/graphics/android/layers/PictureLayerContent.h new file mode 100644 index 0000000..94bdfac --- /dev/null +++ b/Source/WebCore/platform/graphics/android/layers/PictureLayerContent.h @@ -0,0 +1,55 @@ +/* + * Copyright 2012, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef PictureLayerContent_h +#define PictureLayerContent_h + +#include "LayerContent.h" + +namespace WebCore { + +class PictureLayerContent : public LayerContent { +public: + PictureLayerContent(SkPicture* picture); + PictureLayerContent(const PictureLayerContent& content); + ~PictureLayerContent(); + + virtual int width(); + virtual int height(); + virtual bool isEmpty(); + virtual void checkForOptimisations(); + virtual bool hasText(); + virtual void draw(SkCanvas* canvas); + virtual void serialize(SkWStream* stream); + +private: + SkPicture* m_picture; + bool m_checkedContent; + bool m_hasText; +}; + +} // WebCore + +#endif // PictureLayerContent_h diff --git a/Source/WebCore/platform/graphics/android/layers/PictureSetLayerContent.cpp b/Source/WebCore/platform/graphics/android/layers/PictureSetLayerContent.cpp new file mode 100644 index 0000000..8b72b0a --- /dev/null +++ b/Source/WebCore/platform/graphics/android/layers/PictureSetLayerContent.cpp @@ -0,0 +1,41 @@ +#include "config.h" +#include "PictureSetLayerContent.h" + +#include "SkCanvas.h" +#include "SkPicture.h" + +namespace WebCore { + +PictureSetLayerContent::PictureSetLayerContent(const android::PictureSet& pictureSet) +{ + m_pictureSet.set(pictureSet); +} + +PictureSetLayerContent::~PictureSetLayerContent() +{ + m_pictureSet.clear(); +} + +void PictureSetLayerContent::draw(SkCanvas* canvas) +{ + if (m_pictureSet.isEmpty()) + return; + + android::Mutex::Autolock lock(m_drawLock); + SkRect r = SkRect::MakeWH(width(), height()); + canvas->clipRect(r); + m_pictureSet.draw(canvas); +} + +void PictureSetLayerContent::serialize(SkWStream* stream) +{ + if (!stream) + return; + SkPicture picture; + draw(picture.beginRecording(m_pictureSet.width(), m_pictureSet.height(), + SkPicture::kUsePathBoundsForClip_RecordingFlag)); + picture.endRecording(); + picture.serialize(stream); +} + +} // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/layers/PictureSetLayerContent.h b/Source/WebCore/platform/graphics/android/layers/PictureSetLayerContent.h new file mode 100644 index 0000000..61fc3f4 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/layers/PictureSetLayerContent.h @@ -0,0 +1,53 @@ +/* + * Copyright 2012, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef PictureSetLayerContent_h +#define PictureSetLayerContent_h + +#include "LayerContent.h" +#include "PictureSet.h" + +namespace WebCore { + +class PictureSetLayerContent : public LayerContent { +public: + PictureSetLayerContent(const android::PictureSet& pictureSet); + ~PictureSetLayerContent(); + + virtual int width() { return m_pictureSet.width(); } + virtual int height() { return m_pictureSet.height(); } + virtual bool isEmpty() { return m_pictureSet.isEmpty(); } + virtual void checkForOptimisations() {} + virtual bool hasText() { return true; } + virtual void draw(SkCanvas* canvas); + virtual void serialize(SkWStream* stream); + +private: + android::PictureSet m_pictureSet; +}; + +} // WebCore + +#endif // PictureLayerContent_h diff --git a/Source/WebCore/platform/graphics/android/layers/ScrollableLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/layers/ScrollableLayerAndroid.cpp new file mode 100644 index 0000000..f28c31d --- /dev/null +++ b/Source/WebCore/platform/graphics/android/layers/ScrollableLayerAndroid.cpp @@ -0,0 +1,80 @@ +#define LOG_TAG "ScrollableLayerAndroid" +#define LOG_NDEBUG 1 + +#include "config.h" +#include "ScrollableLayerAndroid.h" + +#include "GLWebViewState.h" + +#if USE(ACCELERATED_COMPOSITING) + +#include "AndroidLog.h" + +namespace WebCore { + +bool ScrollableLayerAndroid::scrollTo(int x, int y) +{ + IntRect scrollBounds; + getScrollBounds(&scrollBounds); + if (!scrollBounds.width() && !scrollBounds.height()) + return false; + SkScalar newX = SkScalarPin(x, scrollBounds.x(), scrollBounds.width()); + SkScalar newY = SkScalarPin(y, scrollBounds.y(), scrollBounds.height()); + // Check for no change. + if (newX == m_offset.x() && newY == m_offset.y()) + return false; + setScrollOffset(IntPoint(newX, newY)); + return true; +} + +void ScrollableLayerAndroid::getScrollBounds(IntRect* out) const +{ + const SkPoint& pos = getPosition(); + out->setX(m_scrollLimits.fLeft - pos.fX); + out->setY(m_scrollLimits.fTop - pos.fY); + out->setWidth(getSize().width() - m_scrollLimits.width()); + out->setHeight(getSize().height() - m_scrollLimits.height()); +} + +void ScrollableLayerAndroid::getScrollRect(SkIRect* out) const +{ + const SkPoint& pos = getPosition(); + out->fLeft = m_scrollLimits.fLeft - pos.fX + m_offset.x(); + out->fTop = m_scrollLimits.fTop - pos.fY + m_offset.y(); + + out->fRight = getSize().width() - m_scrollLimits.width(); + out->fBottom = getSize().height() - m_scrollLimits.height(); +} + +bool ScrollableLayerAndroid::scrollRectIntoView(const SkIRect& rect) +{ + // Apply the local transform to the rect to get it relative to the parent + // layer. + SkMatrix localTransform; + getLocalTransform(&localTransform); + SkRect transformedRect; + transformedRect.set(rect); + localTransform.mapRect(&transformedRect); + + // Test left before right to prioritize left alignment if transformedRect is wider than + // visible area. + int x = m_scrollLimits.fLeft; + if (transformedRect.fLeft < m_scrollLimits.fLeft) + x = transformedRect.fLeft; + else if (transformedRect.fRight > m_scrollLimits.fRight) + x = transformedRect.fRight - std::max(m_scrollLimits.width(), transformedRect.width()); + + // Test top before bottom to prioritize top alignment if transformedRect is taller than + // visible area. + int y = m_scrollLimits.fTop; + if (transformedRect.fTop < m_scrollLimits.fTop) + y = transformedRect.fTop; + else if (transformedRect.fBottom > m_scrollLimits.fBottom) + y = transformedRect.fBottom - std::max(m_scrollLimits.height(), transformedRect.height()); + + return scrollTo(x - getPosition().fX, y - getPosition().fY); +} + +} // namespace WebCore + +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/android/layers/ScrollableLayerAndroid.h b/Source/WebCore/platform/graphics/android/layers/ScrollableLayerAndroid.h new file mode 100644 index 0000000..1f289e6 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/layers/ScrollableLayerAndroid.h @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ScrollableLayerAndroid_h +#define ScrollableLayerAndroid_h + +#if USE(ACCELERATED_COMPOSITING) + +#include "LayerAndroid.h" + +namespace WebCore { + +class ScrollableLayerAndroid : public LayerAndroid { + +public: + ScrollableLayerAndroid(RenderLayer* owner) + : LayerAndroid(owner) {} + ScrollableLayerAndroid(const ScrollableLayerAndroid& layer) + : LayerAndroid(layer) + , m_scrollLimits(layer.m_scrollLimits) {} + ScrollableLayerAndroid(const LayerAndroid& layer) + : LayerAndroid(layer) + { + m_scrollLimits.setEmpty(); + } + virtual ~ScrollableLayerAndroid() {}; + + virtual bool contentIsScrollable() const { return true; } + + virtual LayerAndroid* copy() const { return new ScrollableLayerAndroid(*this); } + virtual SubclassType subclassType() { return LayerAndroid::ScrollableLayer; } + + virtual bool updateWithLayer(LayerAndroid*) { return true; } + + // Scrolls to the given position in the layer. + // Returns whether or not any scrolling was required. + virtual bool scrollTo(int x, int y); + + // Fills the rect with the current scroll offset and the maximum scroll offset. + // fLeft = scrollX + // fTop = scrollY + // fRight = maxScrollX + // fBottom = maxScrollY + virtual void getScrollRect(SkIRect*) const; + + void setScrollLimits(float x, float y, float width, float height) + { + m_scrollLimits.set(x, y, x + width, y + height); + } + + // Given a rect in the layer, scrolls to bring the rect into view. Uses a + // lazy approach, whereby we scroll as little as possible to bring the + // entire rect into view. If the size of the rect exceeds that of the + // visible area of the layer, we favor the top and left of the rect. + // Returns whether or not any scrolling was required. + bool scrollRectIntoView(const SkIRect&); + + friend void android::serializeLayer(LayerAndroid* layer, SkWStream* stream); + friend LayerAndroid* android::deserializeLayer(int version, SkStream* stream); + +protected: + + void getScrollBounds(IntRect*) const; + + // The position of the visible area of the layer, relative to the parent + // layer. This is fixed during scrolling. We acheive scrolling by modifying + // the position of the layer. + SkRect m_scrollLimits; +}; + +} + +#endif // USE(ACCELERATED_COMPOSITING) + +#endif // LayerAndroid_h diff --git a/Source/WebCore/platform/graphics/android/layers/VideoLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/layers/VideoLayerAndroid.cpp new file mode 100644 index 0000000..39bbec6 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/layers/VideoLayerAndroid.cpp @@ -0,0 +1,220 @@ +/* + * Copyright 2011 The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define LOG_TAG "VideoLayerAndroid" +#define LOG_NDEBUG 1 + +#include "config.h" +#include "VideoLayerAndroid.h" + +#include "AndroidLog.h" +#include "DrawQuadData.h" +#include "ShaderProgram.h" +#include "TilesManager.h" +#include +#include + +#if USE(ACCELERATED_COMPOSITING) + +namespace WebCore { + +double VideoLayerAndroid::m_rotateDegree = 0; + +VideoLayerAndroid::VideoLayerAndroid() + : LayerAndroid((RenderLayer*)0) +{ + init(); +} + +VideoLayerAndroid::VideoLayerAndroid(const VideoLayerAndroid& layer) + : LayerAndroid(layer) +{ + init(); +} + +void VideoLayerAndroid::init() +{ + // m_surfaceTexture is only useful on UI thread, no need to copy. + // And it will be set at setBaseLayer timeframe + m_playerState = INITIALIZED; +} + +// We can use this function to set the Layer to point to surface texture. +void VideoLayerAndroid::setSurfaceTexture(sp texture, + int textureName, PlayerState playerState) +{ + m_surfaceTexture = texture; + m_playerState = playerState; + TilesManager::instance()->videoLayerManager()->registerTexture(uniqueId(), textureName); +} + +void VideoLayerAndroid::showPreparingAnimation(const SkRect& rect, + const SkRect innerRect) +{ + ShaderProgram* shader = TilesManager::instance()->shader(); + VideoLayerManager* manager = TilesManager::instance()->videoLayerManager(); + // Paint the video content's background. + PureColorQuadData backGroundQuadData(Color(128, 128, 128, 255), LayerQuad, + &m_drawTransform, &rect); + shader->drawQuad(&backGroundQuadData); + + TransformationMatrix addReverseRotation; + TransformationMatrix addRotation = m_drawTransform; + addRotation.translate(innerRect.fLeft, innerRect.fTop); + double halfButtonSize = manager->getButtonSize() / 2; + addRotation.translate(halfButtonSize, halfButtonSize); + addReverseRotation = addRotation; + addRotation.rotate(m_rotateDegree); + addRotation.translate(-halfButtonSize, -halfButtonSize); + + SkRect size = SkRect::MakeWH(innerRect.width(), innerRect.height()); + + TextureQuadData spinnerQuadData(manager->getSpinnerOuterTextureId(), + GL_TEXTURE_2D, GL_LINEAR, + LayerQuad, &addRotation, &size); + shader->drawQuad(&spinnerQuadData); + + addReverseRotation.rotate(-m_rotateDegree); + addReverseRotation.translate(-halfButtonSize, -halfButtonSize); + + spinnerQuadData.updateTextureId(manager->getSpinnerInnerTextureId()); + spinnerQuadData.updateDrawMatrix(&addReverseRotation); + shader->drawQuad(&spinnerQuadData); + + m_rotateDegree += ROTATESTEP; +} + +SkRect VideoLayerAndroid::calVideoRect(const SkRect& rect) +{ + SkRect videoRect = rect; + VideoLayerManager* manager = TilesManager::instance()->videoLayerManager(); + float aspectRatio = manager->getAspectRatio(uniqueId()); + float deltaY = rect.height() - rect.width() / aspectRatio; + if (deltaY >= 0) + videoRect.inset(0, deltaY / 2); + else { + float deltaX = rect.width() - rect.height() * aspectRatio; + if (deltaX >= 0) + videoRect.inset(deltaX / 2, 0); + } + return videoRect; +} + +bool VideoLayerAndroid::drawGL(bool layerTilesDisabled) +{ + // Lazily allocated the textures. + TilesManager* tilesManager = TilesManager::instance(); + VideoLayerManager* manager = tilesManager->videoLayerManager(); + manager->initGLResourcesIfNeeded(); + + ShaderProgram* shader = tilesManager->shader(); + + SkRect rect = SkRect::MakeSize(getSize()); + GLfloat surfaceMatrix[16]; + + // Calculate the video rect based on the aspect ratio and the element rect. + SkRect videoRect = calVideoRect(rect); + PureColorQuadData pureColorQuadData(Color(0, 0, 0, 255), LayerQuad, + &m_drawTransform, &rect); + + if (videoRect != rect) { + // Paint the whole video element with black color when video content + // can't cover the whole area. + shader->drawQuad(&pureColorQuadData); + } + + // Inner rect is for the progressing / play / pause animation. + SkRect innerRect = SkRect::MakeWH(manager->getButtonSize(), + manager->getButtonSize()); + if (innerRect.contains(videoRect)) + innerRect = videoRect; + double buttonSize = manager->getButtonSize(); + innerRect.offset(videoRect.fLeft + (videoRect.width() - buttonSize) / 2, + videoRect.fTop + (videoRect.height() - buttonSize) / 2); + + // When we are drawing the animation of the play/pause button in the + // middle of the video, we need to ask for redraw. + bool needRedraw = false; + TextureQuadData iconQuadData(0, GL_TEXTURE_2D, GL_LINEAR, LayerQuad, + &m_drawTransform, &innerRect); + // Draw the poster image, the progressing image or the Video depending + // on the player's state. + if (m_playerState == PREPARING) { + // Show the progressing animation, with two rotating circles + showPreparingAnimation(videoRect, innerRect); + needRedraw = true; + } else if (m_playerState == PLAYING && m_surfaceTexture.get()) { + // Show the real video. + m_surfaceTexture->updateTexImage(); + m_surfaceTexture->getTransformMatrix(surfaceMatrix); + GLuint textureId = manager->getTextureId(uniqueId()); + shader->drawVideoLayerQuad(m_drawTransform, surfaceMatrix, + videoRect, textureId); + manager->updateMatrix(uniqueId(), surfaceMatrix); + + // Use the scale to control the fading the sizing during animation + double scale = manager->drawIcon(uniqueId(), PlayIcon); + if (scale) { + innerRect.inset(manager->getButtonSize() / 4 * scale, + manager->getButtonSize() / 4 * scale); + iconQuadData.updateTextureId(manager->getPlayTextureId()); + iconQuadData.updateOpacity(scale); + shader->drawQuad(&iconQuadData); + needRedraw = true; + } + } else { + GLuint textureId = manager->getTextureId(uniqueId()); + GLfloat* matrix = manager->getMatrix(uniqueId()); + if (textureId && matrix) { + // Show the screen shot for each video. + shader->drawVideoLayerQuad(m_drawTransform, matrix, + videoRect, textureId); + } else { + // Show the static poster b/c there is no screen shot available. + pureColorQuadData.updateColor(Color(128, 128, 128, 255)); + shader->drawQuad(&pureColorQuadData); + + iconQuadData.updateTextureId(manager->getPosterTextureId()); + iconQuadData.updateOpacity(1.0); + shader->drawQuad(&iconQuadData); + } + + // Use the scale to control the fading and the sizing during animation. + double scale = manager->drawIcon(uniqueId(), PauseIcon); + if (scale) { + innerRect.inset(manager->getButtonSize() / 4 * scale, + manager->getButtonSize() / 4 * scale); + iconQuadData.updateTextureId(manager->getPauseTextureId()); + iconQuadData.updateOpacity(scale); + shader->drawQuad(&iconQuadData); + needRedraw = true; + } + + } + return needRedraw; +} + +} +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/android/layers/VideoLayerAndroid.h b/Source/WebCore/platform/graphics/android/layers/VideoLayerAndroid.h new file mode 100644 index 0000000..dd88a85 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/layers/VideoLayerAndroid.h @@ -0,0 +1,82 @@ +/* + * Copyright 2011 The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef VideoLayerAndroid_h +#define VideoLayerAndroid_h + +#if USE(ACCELERATED_COMPOSITING) + +#include "GLUtils.h" +#include "LayerAndroid.h" +#include + +namespace android { +class SurfaceTexture; +} + +namespace WebCore { + +// state get from UI thread to decide which image to draw. +// PREPARING should be the progressing image +// PLAYING will be the Video (Surface Texture). +// Otherwise will draw a static image. +// NOTE: These values are matching the ones in HTML5VideoView.java +// Please keep them in sync when changed here. +typedef enum {INITIALIZED, PREPARING, PREPARED, PLAYING, RELEASED} PlayerState; + +class VideoLayerAndroid : public LayerAndroid { + +public: + VideoLayerAndroid(); + explicit VideoLayerAndroid(const VideoLayerAndroid& layer); + + virtual bool isVideo() const { return true; } + virtual LayerAndroid* copy() const { return new VideoLayerAndroid(*this); } + + // The following 3 functions are called in UI thread only. + virtual bool drawGL(bool layerTilesDisabled); + void setSurfaceTexture(sp texture, int textureName, PlayerState playerState); + +private: + void init(); + void showPreparingAnimation(const SkRect& rect, + const SkRect innerRect); + SkRect calVideoRect(const SkRect& rect); + // Surface texture for showing the video is actually allocated in Java side + // and passed into this native code. + sp m_surfaceTexture; + + PlayerState m_playerState; + + static double m_rotateDegree; + + static const int ROTATESTEP = 12; +}; + +} // namespace WebCore + +#endif // USE(ACCELERATED_COMPOSITING) + +#endif // VideoLayerAndroid_h diff --git a/Source/WebCore/platform/graphics/android/layers/VideoLayerManager.cpp b/Source/WebCore/platform/graphics/android/layers/VideoLayerManager.cpp new file mode 100644 index 0000000..6501f98 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/layers/VideoLayerManager.cpp @@ -0,0 +1,385 @@ +/* + * Copyright 2011 The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define LOG_TAG "VideoLayerManager" +#define LOG_NDEBUG 1 + +#include "config.h" +#include "VideoLayerManager.h" + +#include "AndroidLog.h" +#include "RenderSkinMediaButton.h" +#include "SkCanvas.h" +#include + +#if USE(ACCELERATED_COMPOSITING) + +// The animation of the play/pause icon will last for PLAY_PAUSE_ICON_SHOW_TIME +// seconds. +#define PLAY_PAUSE_ICON_SHOW_TIME 1 + +// Define the max sum of all the video's sizes. +// Note that video_size = width * height. If there is no compression, then the +// maximum memory consumption could be 4 * video_size. +// Setting this to 2M, means that maximum memory consumption of all the +// screenshots would not be above 8M. +#define MAX_VIDEOSIZE_SUM 2097152 + +// We don't preload the video data, so we don't have the exact size yet. +// Assuming 16:9 by default, this will be corrected after video prepared. +#define DEFAULT_VIDEO_ASPECT_RATIO 1.78 + +#define VIDEO_TEXTURE_NUMBER 5 +#define VIDEO_BUTTON_SIZE 64 + +namespace WebCore { + +VideoLayerManager::VideoLayerManager() + : m_currentTimeStamp(0) + , m_createdTexture(false) + , m_posterTextureId(0) + , m_spinnerOuterTextureId(0) + , m_spinnerInnerTextureId(0) + , m_playTextureId(0) + , m_pauseTextureId(0) + , m_buttonRect(0, 0, VIDEO_BUTTON_SIZE, VIDEO_BUTTON_SIZE) +{ +} + +int VideoLayerManager::getButtonSize() +{ + return VIDEO_BUTTON_SIZE; +} + +GLuint VideoLayerManager::createTextureFromImage(int buttonType) +{ + SkRect rect = SkRect(m_buttonRect); + SkBitmap bitmap; + bitmap.setConfig(SkBitmap::kARGB_8888_Config, rect.width(), rect.height()); + bitmap.allocPixels(); + bitmap.eraseColor(0); + + SkCanvas canvas(bitmap); + canvas.drawARGB(0, 0, 0, 0, SkXfermode::kClear_Mode); + RenderSkinMediaButton::Draw(&canvas, m_buttonRect, buttonType, true, 0, + false); + + GLuint texture; + glGenTextures(1, &texture); + + GLUtils::createTextureWithBitmap(texture, bitmap); + bitmap.reset(); + return texture; +} + +// Should be called at the VideoLayerAndroid::drawGL to make sure we allocate +// the GL resources lazily. +void VideoLayerManager::initGLResourcesIfNeeded() +{ + if (!m_createdTexture) { + ALOGD("Reinit GLResource for VideoLayer"); + initGLResources(); + } +} + +void VideoLayerManager::initGLResources() +{ + GLUtils::checkGlError("before initGLResources()"); + if (!m_createdTexture) { + m_spinnerOuterTextureId = + createTextureFromImage(RenderSkinMediaButton::SPINNER_OUTER); + m_spinnerInnerTextureId = + createTextureFromImage(RenderSkinMediaButton::SPINNER_INNER); + m_posterTextureId = + createTextureFromImage(RenderSkinMediaButton::VIDEO); + m_playTextureId = createTextureFromImage(RenderSkinMediaButton::PLAY); + m_pauseTextureId = createTextureFromImage(RenderSkinMediaButton::PAUSE); + } + m_createdTexture = !GLUtils::checkGlError("initGLResources()"); + return; +} + +void VideoLayerManager::cleanupGLResources() +{ + if (m_createdTexture) { + GLuint videoTextures[VIDEO_TEXTURE_NUMBER] = { m_spinnerOuterTextureId, + m_spinnerInnerTextureId, m_posterTextureId, m_playTextureId, + m_pauseTextureId }; + + glDeleteTextures(VIDEO_TEXTURE_NUMBER, videoTextures); + m_createdTexture = false; + } + // Delete the texture in retired mode, but have not hit draw call to be + // removed. + deleteUnusedTextures(); + + // Go over the registered GL textures (screen shot textures) and delete them. + android::Mutex::Autolock lock(m_videoLayerInfoMapLock); + InfoIterator end = m_videoLayerInfoMap.end(); + for (InfoIterator it = m_videoLayerInfoMap.begin(); it != end; ++it) { + // The map include every video has been played, so their textureId can + // be deleted already, like hitting onTrimMemory multiple times. + if (it->second->textureId) { + ALOGV("delete texture from the map %d", it->second->textureId); + glDeleteTextures(1, &it->second->textureId); + // Set the textureID to 0 to show the video icon. + it->second->textureId = 0; + } + } + + GLUtils::checkGlError("cleanupGLResources()"); + return; +} + +// Getting TextureId for GL draw call, in the UI thread. +GLuint VideoLayerManager::getTextureId(const int layerId) +{ + android::Mutex::Autolock lock(m_videoLayerInfoMapLock); + GLuint result = 0; + if (m_videoLayerInfoMap.contains(layerId)) + result = m_videoLayerInfoMap.get(layerId)->textureId; + return result; +} + +// Getting the aspect ratio for GL draw call, in the UI thread. +float VideoLayerManager::getAspectRatio(const int layerId) +{ + android::Mutex::Autolock lock(m_videoLayerInfoMapLock); + float result = 0; + if (m_videoLayerInfoMap.contains(layerId)) + result = m_videoLayerInfoMap.get(layerId)->aspectRatio; + return result; +} + +// Getting matrix for GL draw call, in the UI thread. +GLfloat* VideoLayerManager::getMatrix(const int layerId) +{ + android::Mutex::Autolock lock(m_videoLayerInfoMapLock); + GLfloat* result = 0; + if (m_videoLayerInfoMap.contains(layerId)) + result = m_videoLayerInfoMap.get(layerId)->surfaceMatrix; + return result; +} + +int VideoLayerManager::getTotalMemUsage() +{ + int sum = 0; + InfoIterator end = m_videoLayerInfoMap.end(); + for (InfoIterator it = m_videoLayerInfoMap.begin(); it != end; ++it) + sum += it->second->videoSize; + return sum; +} + +// When the video start, we know its texture info, so we register when we +// recieve the setSurfaceTexture call, this happens on UI thread. +void VideoLayerManager::registerTexture(const int layerId, const GLuint textureId) +{ + android::Mutex::Autolock lock(m_videoLayerInfoMapLock); + // If the texture has been registered, then early return. + if (m_videoLayerInfoMap.get(layerId)) { + GLuint oldTextureId = m_videoLayerInfoMap.get(layerId)->textureId; + if (oldTextureId != textureId) + removeLayerInternal(layerId); + else + return; + } + // The old info is deleted and now complete the new info and store it. + VideoLayerInfo* pInfo = new VideoLayerInfo(); + pInfo->textureId = textureId; + memset(pInfo->surfaceMatrix, 0, sizeof(pInfo->surfaceMatrix)); + pInfo->videoSize = 0; + pInfo->aspectRatio = DEFAULT_VIDEO_ASPECT_RATIO; + m_currentTimeStamp++; + pInfo->timeStamp = m_currentTimeStamp; + pInfo->lastIconShownTime = 0; + pInfo->iconState = Registered; + + m_videoLayerInfoMap.add(layerId, pInfo); + ALOGV("GL texture %d regisered for layerId %d", textureId, layerId); + + return; +} + +// Only when the video is prepared, we got the video size. So we should update +// the size for the video accordingly. +// This is called from webcore thread, from MediaPlayerPrivateAndroid. +void VideoLayerManager::updateVideoLayerSize(const int layerId, const int size, + const float ratio) +{ + android::Mutex::Autolock lock(m_videoLayerInfoMapLock); + if (m_videoLayerInfoMap.contains(layerId)) { + VideoLayerInfo* pInfo = m_videoLayerInfoMap.get(layerId); + if (pInfo) { + pInfo->videoSize = size; + pInfo->aspectRatio = ratio; + } + } + + // If the memory usage is out of bound, then just delete the oldest ones. + // Because we only recycle the texture before the current timestamp, the + // current video's texture will not be deleted. + while (getTotalMemUsage() > MAX_VIDEOSIZE_SUM) + if (!recycleTextureMem()) + break; + return; +} + +// This is called only from UI thread, at drawGL time. +void VideoLayerManager::updateMatrix(const int layerId, const GLfloat* matrix) +{ + android::Mutex::Autolock lock(m_videoLayerInfoMapLock); + if (m_videoLayerInfoMap.contains(layerId)) { + // If the existing video layer's matrix is matching the incoming one, + // then skip the update. + VideoLayerInfo* pInfo = m_videoLayerInfoMap.get(layerId); + ASSERT(matrix); + if (pInfo && !memcmp(matrix, pInfo->surfaceMatrix, sizeof(pInfo->surfaceMatrix))) + return; + memcpy(pInfo->surfaceMatrix, matrix, sizeof(pInfo->surfaceMatrix)); + } else { + ALOGV("Error: should not reach here, the layerId %d should exist!", layerId); + ASSERT(false); + } + return; +} + +// This is called on the webcore thread, save the GL texture for recycle in +// the retired queue. They will be deleted in deleteUnusedTextures() in the UI +// thread. +// Return true when we found one texture to retire. +bool VideoLayerManager::recycleTextureMem() +{ + // Find the oldest texture int the m_videoLayerInfoMap, put it in m_retiredTextures + int oldestTimeStamp = m_currentTimeStamp; + int oldestLayerId = -1; + + InfoIterator end = m_videoLayerInfoMap.end(); +#ifdef DEBUG + ALOGV("VideoLayerManager::recycleTextureMem m_videoLayerInfoMap contains"); + for (InfoIterator it = m_videoLayerInfoMap.begin(); it != end; ++it) + ALOGV(" layerId %d, textureId %d, videoSize %d, timeStamp %d ", + it->first, it->second->textureId, it->second->videoSize, it->second->timeStamp); +#endif + for (InfoIterator it = m_videoLayerInfoMap.begin(); it != end; ++it) { + if (it->second->timeStamp < oldestTimeStamp) { + oldestTimeStamp = it->second->timeStamp; + oldestLayerId = it->first; + } + } + + bool foundTextureToRetire = (oldestLayerId != -1); + if (foundTextureToRetire) + removeLayerInternal(oldestLayerId); + + return foundTextureToRetire; +} + +// This is only called in the UI thread, b/c glDeleteTextures need to be called +// on the right context. +void VideoLayerManager::deleteUnusedTextures() +{ + m_retiredTexturesLock.lock(); + int size = m_retiredTextures.size(); + if (size > 0) { + GLuint* textureNames = new GLuint[size]; + int index = 0; + Vector::const_iterator end = m_retiredTextures.end(); + for (Vector::const_iterator it = m_retiredTextures.begin(); + it != end; ++it) { + GLuint textureName = *it; + if (textureName) { + textureNames[index] = textureName; + index++; + ALOGV("GL texture %d will be deleted", textureName); + } + } + glDeleteTextures(size, textureNames); + delete textureNames; + m_retiredTextures.clear(); + } + m_retiredTexturesLock.unlock(); + GLUtils::checkGlError("deleteUnusedTextures"); + return; +} + +// This can be called in the webcore thread in the media player's dtor. +void VideoLayerManager::removeLayer(const int layerId) +{ + android::Mutex::Autolock lock(m_videoLayerInfoMapLock); + removeLayerInternal(layerId); +} + +// This can be called on both UI and webcore thread. Since this is a private +// function, it is up to the public function to handle the lock for +// m_videoLayerInfoMap. +void VideoLayerManager::removeLayerInternal(const int layerId) +{ + // Delete the layerInfo corresponding to this layerId and remove from the map. + if (m_videoLayerInfoMap.contains(layerId)) { + GLuint textureId = m_videoLayerInfoMap.get(layerId)->textureId; + if (textureId) { + // Buffer up the retired textures in either UI or webcore thread, + // will be purged at deleteUnusedTextures in the UI thread. + m_retiredTexturesLock.lock(); + m_retiredTextures.append(textureId); + m_retiredTexturesLock.unlock(); + } + delete m_videoLayerInfoMap.get(layerId); + m_videoLayerInfoMap.remove(layerId); + } + return; +} + +double VideoLayerManager::drawIcon(const int layerId, IconType type) +{ + // When ratio 0 is returned, the Icon should not be drawn. + double ratio = 0; + + android::Mutex::Autolock lock(m_videoLayerInfoMapLock); + if (m_videoLayerInfoMap.contains(layerId)) { + VideoLayerInfo* pInfo = m_videoLayerInfoMap.get(layerId); + // If this is state switching moment, reset the time and state + if ((type == PlayIcon && pInfo->iconState != PlayIconShown) + || (type == PauseIcon && pInfo->iconState != PauseIconShown)) { + pInfo->lastIconShownTime = WTF::currentTime(); + pInfo->iconState = (type == PlayIcon) ? PlayIconShown : PauseIconShown; + } + + // After switching the state, we calculate the ratio depending on the + // time interval. + if ((type == PlayIcon && pInfo->iconState == PlayIconShown) + || (type == PauseIcon && pInfo->iconState == PauseIconShown)) { + double delta = WTF::currentTime() - pInfo->lastIconShownTime; + ratio = 1.0 - (delta / PLAY_PAUSE_ICON_SHOW_TIME); + } + } + + if (ratio > 1 || ratio < 0) + ratio = 0; + return ratio; +} + +} +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/android/layers/VideoLayerManager.h b/Source/WebCore/platform/graphics/android/layers/VideoLayerManager.h new file mode 100644 index 0000000..6c02534 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/layers/VideoLayerManager.h @@ -0,0 +1,141 @@ +/* + * Copyright 2011 The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef VideoLayerManager_h +#define VideoLayerManager_h + +#include "GLUtils.h" +#include "IntRect.h" +#include +#include +#include + +#if USE(ACCELERATED_COMPOSITING) + +namespace WebCore { + +enum IconState { + Registered, + PlayIconShown, + PauseIconShown +}; + +enum IconType { + PlayIcon, + PauseIcon +}; + +// Every video layer can use its uniqueId to query VideoLayerManager about such +// info globally. +struct VideoLayerInfo { + GLuint textureId; // GL texture bound with the surface texture. + int videoSize; // The size of the video. + float aspectRatio; // The aspect ratio of the video. + int timeStamp; // Used to decide which VideoLayerInfo is the oldest one. + GLfloat surfaceMatrix[16]; + + double lastIconShownTime; + IconState iconState; +}; + + +class VideoLayerManager { + +public: + typedef HashMap::const_iterator InfoIterator; + + VideoLayerManager(); + + // Register the texture when we got setSurfaceTexture call. + void registerTexture(const int layerId, const GLuint textureId); + // Update the size when the video is prepared. + void updateVideoLayerSize(const int layerId, const int size, const float ratio); + // At draw time, update the matrix for every video frame update. + void updateMatrix(const int layerId, const GLfloat* matrix); + // Remove the layer info from the mapping. + void removeLayer(const int layerId); + + // Return the texture name corresponding to the layerId + GLuint getTextureId(const int layerId); + // Return the matrix for surface texture corresponding to the layerId + GLfloat* getMatrix(const int layerId); + // Return the aspect ratio for the video corresponding to the layerId + float getAspectRatio(const int layerId); + + // Delete the GL textures + void deleteUnusedTextures(); + + double drawIcon(const int layerId, IconType type); + + GLuint getSpinnerInnerTextureId() { return m_spinnerInnerTextureId; } + GLuint getSpinnerOuterTextureId() { return m_spinnerOuterTextureId; } + GLuint getPosterTextureId() { return m_posterTextureId; } + GLuint getPlayTextureId() { return m_playTextureId; } + GLuint getPauseTextureId() { return m_pauseTextureId; } + + void initGLResourcesIfNeeded(); + void cleanupGLResources(); + + static int getButtonSize(); +private: + // Get the sum of all the video size stored in m_videoLayerInfoMap. + int getTotalMemUsage(); + // If the memory consumption is out of bound, recycle some textures. + bool recycleTextureMem(); + // The private function to remove layer. + void removeLayerInternal(const int layerId); + void initGLResources(); + // Indexed by each layer's uniqueId, this map contains the important info + // used for showing the video when playing or the screenshot when paused. + HashMap m_videoLayerInfoMap; + android::Mutex m_videoLayerInfoMapLock; + + // Everytime we add one item to the map, we update the timestamp. + int m_currentTimeStamp; + + // The retiredTextures is used to communicate between UI thread and webcore + // thread. Basically, GL textures are determined to retire in the webcore + // thread, and really get deleted in the UI thread. + Vector m_retiredTextures; + android::Mutex m_retiredTexturesLock; + + GLuint createTextureFromImage(int buttonType); + + // Texture for showing the static image will be created at native side. + bool m_createdTexture; + GLuint m_posterTextureId; + GLuint m_spinnerOuterTextureId; + GLuint m_spinnerInnerTextureId; + GLuint m_playTextureId; + GLuint m_pauseTextureId; + + IntRect m_buttonRect; +}; + +} // namespace WebCore + +#endif // USE(ACCELERATED_COMPOSITING) + // +#endif // VideoLayerManager_h diff --git a/Source/WebCore/platform/graphics/android/rendering/BaseRenderer.cpp b/Source/WebCore/platform/graphics/android/rendering/BaseRenderer.cpp new file mode 100644 index 0000000..833aea9 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/rendering/BaseRenderer.cpp @@ -0,0 +1,165 @@ +/* + * Copyright 2011, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define LOG_TAG "BaseRenderer" +#define LOG_NDEBUG 1 + +#include "config.h" +#include "BaseRenderer.h" + +#if USE(ACCELERATED_COMPOSITING) + +#include "AndroidLog.h" +#include "GaneshRenderer.h" +#include "GLUtils.h" +#include "RasterRenderer.h" +#include "SkBitmap.h" +#include "SkBitmapRef.h" +#include "SkCanvas.h" +#include "SkDevice.h" +#include "SkPicture.h" +#include "SkTypeface.h" +#include "Tile.h" +#include "TilesManager.h" + +#include + +#define UPDATE_COUNT_MASK 0xFF // displayed count wraps at 256 +#define UPDATE_COUNT_ALPHA_MASK 0x1F // alpha wraps at 32 + +namespace WebCore { + +BaseRenderer::RendererType BaseRenderer::g_currentType = BaseRenderer::Raster; + +BaseRenderer* BaseRenderer::createRenderer() +{ + if (g_currentType == Raster) + return new RasterRenderer(); + else if (g_currentType == Ganesh) + return new GaneshRenderer(); + return NULL; +} + +void BaseRenderer::swapRendererIfNeeded(BaseRenderer*& renderer) +{ + if (renderer->getType() == g_currentType) + return; + + delete renderer; + renderer = createRenderer(); +} + +void BaseRenderer::drawTileInfo(SkCanvas* canvas, + const TileRenderInfo& renderInfo, int updateCount, double renderDuration) +{ + static SkTypeface* s_typeface = 0; + if (!s_typeface) + s_typeface = SkTypeface::CreateFromName("", SkTypeface::kBold); + SkPaint paint; + paint.setTextSize(17); + char str[256]; + snprintf(str, 256, " (%d,%d) %.2fx %d %.1fms", renderInfo.x, renderInfo.y, + renderInfo.scale, updateCount, renderDuration); + paint.setARGB(128, 255, 255, 255); + canvas->drawRectCoords(0, 0, renderInfo.tileSize.fWidth, 17, paint); + paint.setARGB(255, 255, 0, 0); + paint.setTypeface(s_typeface); + canvas->drawText(str, strlen(str), 20, 15, paint); +} + +void BaseRenderer::renderTiledContent(TileRenderInfo& renderInfo) +{ + const bool visualIndicator = TilesManager::instance()->getShowVisualIndicator(); + const SkSize& tileSize = renderInfo.tileSize; + + SkCanvas canvas; + setupCanvas(renderInfo, &canvas); + + if (!canvas.getDevice()) { + // TODO: consider ALOGE + ALOGV("Error: No Device"); + return; + } + + double before; + if (visualIndicator) { + canvas.save(); + before = currentTimeMS(); + } + + setupPartialInval(renderInfo, &canvas); + canvas.translate(-renderInfo.x * tileSize.width(), -renderInfo.y * tileSize.height()); + canvas.scale(renderInfo.scale, renderInfo.scale); + renderInfo.tilePainter->paint(renderInfo.baseTile, &canvas); + if (renderInfo.baseTile && renderInfo.baseTile->backTexture()) + checkForPureColor(renderInfo, &canvas); + else + renderInfo.isPureColor = false; + + if (visualIndicator) { + double after = currentTimeMS(); + canvas.restore(); + unsigned int updateCount = renderInfo.tilePainter->getUpdateCount() & UPDATE_COUNT_MASK; + const int color = updateCount & UPDATE_COUNT_ALPHA_MASK; + + // only color the invalidated area + SkPaint paint; + paint.setARGB(color, 0, 255, 0); + if (renderInfo.invalRect) + canvas.drawIRect(*renderInfo.invalRect, paint); + else { + SkIRect rect; + rect.set(0, 0, tileSize.width(), tileSize.height()); + canvas.drawIRect(rect, paint); + } + + if (renderInfo.invalRect) { + // if partial inval... + int x = renderInfo.invalRect->fLeft; + int y = renderInfo.invalRect->fTop; + int w = renderInfo.invalRect->width(); + int h = renderInfo.invalRect->height(); + + paint.setARGB(128, 255, 255, 0); + canvas.drawLine(x, y, x + w, y + h, paint); + canvas.drawLine(x, y + h, x + w, y, paint); + } + drawTileInfo(&canvas, renderInfo, updateCount, after - before); + + // paint the tile boundaries + paint.setARGB(64, 255, 0, 0); + paint.setStrokeWidth(3); + canvas.drawLine(0, 0, tileSize.width(), tileSize.height(), paint); + paint.setARGB(64, 0, 255, 0); + canvas.drawLine(0, tileSize.height(), tileSize.width(), 0, paint); + paint.setARGB(128, 0, 0, 255); + canvas.drawLine(tileSize.width(), 0, tileSize.width(), tileSize.height(), paint); + } + renderingComplete(renderInfo, &canvas); +} + +} // namespace WebCore + +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/android/rendering/BaseRenderer.h b/Source/WebCore/platform/graphics/android/rendering/BaseRenderer.h new file mode 100644 index 0000000..f225871 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/rendering/BaseRenderer.h @@ -0,0 +1,107 @@ +/* + * Copyright 2011, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef BaseRenderer_h +#define BaseRenderer_h + +#if USE(ACCELERATED_COMPOSITING) + +#include "Color.h" +#include "SkRect.h" +#include + +class SkCanvas; +class SkDevice; + +namespace WebCore { + +class TextureInfo; +class TilePainter; +class Tile; + +struct TileRenderInfo { + // coordinates of the tile + int x; + int y; + + // current scale factor + float scale; + + // inval rectangle with coordinates in the tile's coordinate space + SkIRect* invalRect; + + // the expected size of the tile + SkSize tileSize; + + // the painter object in charge of drawing our content + TilePainter* tilePainter; + + // the base tile calling us + Tile* baseTile; + + // info about the texture that we are to render into + TextureInfo* textureInfo; + + bool isPureColor; + Color pureColor; +}; + +/** + * + */ +class BaseRenderer { +public: + enum RendererType { Raster, Ganesh }; + BaseRenderer(RendererType type) : m_type(type) {} + virtual ~BaseRenderer() {} + + void renderTiledContent(TileRenderInfo& renderInfo); + + RendererType getType() { return m_type; } + + static BaseRenderer* createRenderer(); + static void swapRendererIfNeeded(BaseRenderer*& renderer); + static RendererType getCurrentRendererType() { return g_currentType; } + static void setCurrentRendererType(RendererType type) { g_currentType = type; } + +protected: + + virtual void setupCanvas(const TileRenderInfo& renderInfo, SkCanvas* canvas) = 0; + virtual void setupPartialInval(const TileRenderInfo& renderInfo, SkCanvas* canvas) {} + virtual void renderingComplete(const TileRenderInfo& renderInfo, SkCanvas* canvas) = 0; + virtual void checkForPureColor(TileRenderInfo& renderInfo, SkCanvas* canvas) = 0; + + void drawTileInfo(SkCanvas* canvas, const TileRenderInfo& renderInfo, + int updateCount, double renderDuration); + +private: + RendererType m_type; + static RendererType g_currentType; +}; + +} // namespace WebCore + +#endif // USE(ACCELERATED_COMPOSITING) +#endif // BaseRenderer_h diff --git a/Source/WebCore/platform/graphics/android/rendering/DrawQuadData.h b/Source/WebCore/platform/graphics/android/rendering/DrawQuadData.h new file mode 100644 index 0000000..687808d --- /dev/null +++ b/Source/WebCore/platform/graphics/android/rendering/DrawQuadData.h @@ -0,0 +1,172 @@ +/* + * Copyright 2012, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef DrawQuadData_h +#define DrawQuadData_h + +#if USE(ACCELERATED_COMPOSITING) + +#include "Color.h" +#include "SkRect.h" +#include + +namespace WebCore { + +class TransformationMatrix; + +enum DrawQuadType { + BaseQuad, + LayerQuad, + Blit // 1:1 straight pixel blit +}; + +// Both PureColorQuadData and TextureQuadData share the data from DrawQuadData. +class DrawQuadData { +public: + DrawQuadData(DrawQuadType type = BaseQuad, + const TransformationMatrix* drawMatrix = 0, + const SkRect* geometry = 0, + float opacity = 1.0f, + bool forceBlending = true) + : m_type(type) + , m_drawMatrix(drawMatrix) + , m_geometry(geometry) + , m_opacity(opacity) + , m_forceBlending(forceBlending) + { + } + + DrawQuadData(const DrawQuadData& data) + : m_type(data.m_type) + , m_drawMatrix(data.m_drawMatrix) + , m_geometry(data.m_geometry) + , m_opacity(data.m_opacity) + , m_forceBlending(data.m_forceBlending) + { + } + + virtual ~DrawQuadData() {}; + + DrawQuadType type() const { return m_type; } + const TransformationMatrix* drawMatrix() const { return m_drawMatrix; } + const SkRect* geometry() const { return m_geometry; } + float opacity() const { return m_opacity; } + bool forceBlending() const { return m_forceBlending; } + + void updateDrawMatrix(TransformationMatrix* matrix) { m_drawMatrix = matrix; } + void updateGeometry(SkRect* rect) { m_geometry = rect; } + void updateOpacity(float opacity) { m_opacity = opacity; } + + virtual bool pureColor() const { return false; } + + virtual Color quadColor() const { return Color(); } + + virtual int textureId() const { return 0; } + virtual GLint textureFilter() const { return 0; } + virtual GLenum textureTarget() const { return 0; } + +private: + DrawQuadType m_type; + const TransformationMatrix* m_drawMatrix; + const SkRect* m_geometry; + float m_opacity; + bool m_forceBlending; +}; + +class PureColorQuadData : public DrawQuadData { +public: + PureColorQuadData(Color color, + DrawQuadType type = BaseQuad, + const TransformationMatrix* drawMatrix = 0, + const SkRect* geometry = 0, + float opacity = 1.0f, + bool forceBlending = true) + : DrawQuadData(type, drawMatrix, geometry, opacity, forceBlending) + { + m_quadColor = color; + } + + PureColorQuadData(const DrawQuadData& data, Color color) + : DrawQuadData(data) + { + m_quadColor = color; + } + + virtual ~PureColorQuadData() {}; + virtual bool pureColor() const { return true; } + virtual Color quadColor() const { return m_quadColor; } + void updateColor(const Color& color) { m_quadColor = color; } + +private: + Color m_quadColor; +}; + +class TextureQuadData : public DrawQuadData { +public: + TextureQuadData(int textureId, + GLenum textureTarget = GL_TEXTURE_2D, + GLint textureFilter = GL_LINEAR, + DrawQuadType type = BaseQuad, + const TransformationMatrix* drawMatrix = 0, + const SkRect* geometry = 0, + float opacity = 1.0f, + bool forceBlending = true) + : DrawQuadData(type, drawMatrix, geometry, opacity, forceBlending) + { + m_textureId = textureId; + m_textureTarget = textureTarget; + m_textureFilter = textureFilter; + } + + TextureQuadData(const DrawQuadData& data, + int textureId, + GLenum textureTarget = GL_TEXTURE_2D, + GLint textureFilter = GL_LINEAR) + : DrawQuadData(data) + { + m_textureId = textureId; + m_textureTarget = textureTarget; + m_textureFilter = textureFilter; + } + + virtual ~TextureQuadData() {}; + virtual bool pureColor() const { return false; } + + virtual int textureId() const { return m_textureId; } + virtual GLint textureFilter() const { return m_textureFilter; } + virtual GLenum textureTarget() const { return m_textureTarget; } + + void updateTextureId(int newId) { m_textureId = newId; } + +private: + int m_textureId; + GLint m_textureFilter; + GLenum m_textureTarget; +}; + +} // namespace WebCore + +#endif // USE(ACCELERATED_COMPOSITING) +#endif // DrawQuadData_h diff --git a/Source/WebCore/platform/graphics/android/rendering/GLExtras.cpp b/Source/WebCore/platform/graphics/android/rendering/GLExtras.cpp new file mode 100644 index 0000000..6498ecf --- /dev/null +++ b/Source/WebCore/platform/graphics/android/rendering/GLExtras.cpp @@ -0,0 +1,139 @@ +/* + * Copyright 2011, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define LOG_TAG "GLExtras" +#define LOG_NDEBUG 1 + +#include "config.h" + +#include "AndroidLog.h" +#include "DrawExtra.h" +#include "DrawQuadData.h" +#include "GLExtras.h" +#include "IntRect.h" +#include "SkPath.h" +#include "TilesManager.h" +#include "android_graphics.h" + +// Touch ring border width. This is doubled if the ring is not pressed +#define RING_BORDER_WIDTH 1 + +GLExtras::GLExtras() + : m_drawExtra(0) + , m_viewport() +{ +} + +GLExtras::~GLExtras() +{ +} + +void GLExtras::drawRing(SkRect& srcRect, Color color, const TransformationMatrix* drawMat) +{ + if (srcRect.fRight <= srcRect.fLeft || srcRect.fBottom <= srcRect.fTop) { + // Invalid rect, reject it + return; + } + ALOGV("drawQuad [%fx%f, %f, %f]", srcRect.fLeft, srcRect.fTop, + srcRect.width(), srcRect.height()); + // Pull the alpha out of the color so that the shader applies it correctly. + // Otherwise we either don't have blending enabled, or the alpha will get + // double applied + Color colorWithoutAlpha(0xFF000000 | color.rgb()); + float alpha = color.alpha() / (float) 255; + + PureColorQuadData data(colorWithoutAlpha, drawMat ? LayerQuad : BaseQuad, + drawMat, &srcRect, alpha, false); + TilesManager::instance()->shader()->drawQuad(&data); +} + +void GLExtras::drawRegion(const SkRegion& region, bool fill, bool drawBorder, + const TransformationMatrix* drawMat, Color color) +{ + if (region.isEmpty()) + return; + if (fill) { + SkRegion::Iterator rgnIter(region); + while (!rgnIter.done()) { + const SkIRect& ir = rgnIter.rect(); + SkRect r; + r.set(ir.fLeft, ir.fTop, ir.fRight, ir.fBottom); + drawRing(r, color, drawMat); + rgnIter.next(); + } + } + if (fill && !drawBorder) + return; + SkPath path; + if (!region.getBoundaryPath(&path)) + return; + SkPath::Iter iter(path, true); + SkPath::Verb verb; + SkPoint pts[4]; + SkRegion clip; + SkIRect startRect; + while ((verb = iter.next(pts)) != SkPath::kDone_Verb) { + if (verb == SkPath::kLine_Verb) { + SkRect r; + r.set(pts, 2); + SkIRect line; + int borderWidth = RING_BORDER_WIDTH; + if (!fill) + borderWidth *= 2; + line.fLeft = r.fLeft - borderWidth; + line.fRight = r.fRight + borderWidth; + line.fTop = r.fTop - borderWidth; + line.fBottom = r.fBottom + borderWidth; + if (clip.intersects(line)) { + clip.op(line, SkRegion::kReverseDifference_Op); + if (clip.isEmpty()) + continue; // Nothing to draw, continue + line = clip.getBounds(); + if (SkIRect::Intersects(startRect, line)) { + clip.op(startRect, SkRegion::kDifference_Op); + if (clip.isEmpty()) + continue; // Nothing to draw, continue + line = clip.getBounds(); + } + } else { + clip.setRect(line); + } + r.set(line.fLeft, line.fTop, line.fRight, line.fBottom); + drawRing(r, color, drawMat); + if (startRect.isEmpty()) { + startRect.set(line.fLeft, line.fTop, line.fRight, line.fBottom); + } + } + if (verb == SkPath::kMove_Verb) { + startRect.setEmpty(); + } + } +} + +void GLExtras::drawGL(const LayerAndroid* layer) +{ + if (m_drawExtra) + m_drawExtra->drawGL(this, layer); +} diff --git a/Source/WebCore/platform/graphics/android/rendering/GLExtras.h b/Source/WebCore/platform/graphics/android/rendering/GLExtras.h new file mode 100644 index 0000000..59a7c3c --- /dev/null +++ b/Source/WebCore/platform/graphics/android/rendering/GLExtras.h @@ -0,0 +1,60 @@ +/* + * Copyright 2011, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef GLExtras_h +#define GLExtras_h + +#include "Color.h" +#include "DrawExtra.h" +#include "SkRect.h" +#include "SkRegion.h" + +namespace WebCore { + +class LayerAndroid; +class TransformationMatrix; + +class GLExtras { +public: + GLExtras(); + virtual ~GLExtras(); + + void drawGL(const LayerAndroid* layer); + void setDrawExtra(android::DrawExtra* extra) { m_drawExtra = extra; } + void setViewport(const SkRect & viewport) { m_viewport = viewport; } + + void drawRegion(const SkRegion& region, bool fill, bool drawBorder, + const TransformationMatrix* drawMat, Color color = COLOR_HOLO_LIGHT); + +private: + void drawRing(SkRect& srcRect, Color color, const TransformationMatrix* drawMat); + + android::DrawExtra* m_drawExtra; + SkRect m_viewport; +}; + +} // namespace WebCore + +#endif // GLExtras_h diff --git a/Source/WebCore/platform/graphics/android/rendering/GLUtils.cpp b/Source/WebCore/platform/graphics/android/rendering/GLUtils.cpp new file mode 100644 index 0000000..26bd55d --- /dev/null +++ b/Source/WebCore/platform/graphics/android/rendering/GLUtils.cpp @@ -0,0 +1,669 @@ +/* + * Copyright 2010, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define LOG_TAG "GLUtils" +#define LOG_NDEBUG 1 + +#include "config.h" +#include "GLUtils.h" + +#if USE(ACCELERATED_COMPOSITING) + +#include "AndroidLog.h" +#include "BaseRenderer.h" +#include "TextureInfo.h" +#include "Tile.h" +#include "TilesManager.h" +#include "TransferQueue.h" + +#include +#include +#include + +// We will limit GL error logging for LOG_VOLUME_PER_CYCLE times every +// LOG_VOLUME_PER_CYCLE seconds. +#define LOG_CYCLE 30.0 +#define LOG_VOLUME_PER_CYCLE 20 + +struct ANativeWindowBuffer; + +namespace WebCore { + +using namespace android; + +///////////////////////////////////////////////////////////////////////////////////////// +// Matrix utilities +///////////////////////////////////////////////////////////////////////////////////////// + +void GLUtils::toGLMatrix(GLfloat* flattened, const TransformationMatrix& m) +{ + flattened[0] = m.m11(); // scaleX + flattened[1] = m.m12(); // skewY + flattened[2] = m.m13(); + flattened[3] = m.m14(); // persp0 + flattened[4] = m.m21(); // skewX + flattened[5] = m.m22(); // scaleY + flattened[6] = m.m23(); + flattened[7] = m.m24(); // persp1 + flattened[8] = m.m31(); + flattened[9] = m.m32(); + flattened[10] = m.m33(); + flattened[11] = m.m34(); + flattened[12] = m.m41(); // transX + flattened[13] = m.m42(); // transY + flattened[14] = m.m43(); + flattened[15] = m.m44(); // persp2 +} + +void GLUtils::toSkMatrix(SkMatrix& matrix, const TransformationMatrix& m) +{ + matrix[0] = m.m11(); // scaleX + matrix[1] = m.m21(); // skewX + matrix[2] = m.m41(); // transX + matrix[3] = m.m12(); // skewY + matrix[4] = m.m22(); // scaleY + matrix[5] = m.m42(); // transY + matrix[6] = m.m14(); // persp0 + matrix[7] = m.m24(); // persp1 + matrix[8] = m.m44(); // persp2 +} + +void GLUtils::setOrthographicMatrix(TransformationMatrix& ortho, float left, float top, + float right, float bottom, float nearZ, float farZ) +{ + float deltaX = right - left; + float deltaY = top - bottom; + float deltaZ = farZ - nearZ; + if (!deltaX || !deltaY || !deltaZ) + return; + + ortho.setM11(2.0f / deltaX); + ortho.setM41(-(right + left) / deltaX); + ortho.setM22(2.0f / deltaY); + ortho.setM42(-(top + bottom) / deltaY); + ortho.setM33(-2.0f / deltaZ); + ortho.setM43(-(nearZ + farZ) / deltaZ); +} + +///////////////////////////////////////////////////////////////////////////////////////// +// GL & EGL error checks +///////////////////////////////////////////////////////////////////////////////////////// + +double GLUtils::m_previousLogTime = 0; +int GLUtils::m_currentLogCounter = 0; + +bool GLUtils::allowGLLog() +{ + if (m_currentLogCounter < LOG_VOLUME_PER_CYCLE) { + m_currentLogCounter++; + return true; + } + + // when we are in Log cycle and over the log limit, just return false + double currentTime = WTF::currentTime(); + double delta = currentTime - m_previousLogTime; + bool inLogCycle = (delta <= LOG_CYCLE) && (delta > 0); + if (inLogCycle) + return false; + + // When we are out of Log Cycle and over the log limit, we need to reset + // the counter and timer. + m_previousLogTime = currentTime; + m_currentLogCounter = 0; + return false; +} + +static void crashIfOOM(GLint errorCode) +{ + const GLint OOM_ERROR_CODE = 0x505; + if (errorCode == OOM_ERROR_CODE) { + ALOGE("ERROR: Fatal OOM detected."); + CRASH(); + } +} + +void GLUtils::checkEglError(const char* op, EGLBoolean returnVal) +{ + if (returnVal != EGL_TRUE) { +#ifndef DEBUG + if (allowGLLog()) +#endif + ALOGE("EGL ERROR - %s() returned %d\n", op, returnVal); + } + + for (EGLint error = eglGetError(); error != EGL_SUCCESS; error = eglGetError()) { +#ifndef DEBUG + if (allowGLLog()) +#endif + ALOGE("after %s() eglError (0x%x)\n", op, error); + crashIfOOM(error); + } +} + +bool GLUtils::checkGlError(const char* op) +{ + bool ret = false; + for (GLint error = glGetError(); error; error = glGetError()) { +#ifndef DEBUG + if (allowGLLog()) +#endif + ALOGE("GL ERROR - after %s() glError (0x%x)\n", op, error); + crashIfOOM(error); + ret = true; + } + return ret; +} + +bool GLUtils::checkGlErrorOn(void* p, const char* op) +{ + bool ret = false; + for (GLint error = glGetError(); error; error = glGetError()) { +#ifndef DEBUG + if (allowGLLog()) +#endif + ALOGE("GL ERROR on %x - after %s() glError (0x%x)\n", p, op, error); + crashIfOOM(error); + ret = true; + } + return ret; +} + +void GLUtils::checkSurfaceTextureError(const char* functionName, int status) +{ + if (status != NO_ERROR) { +#ifndef DEBUG + if (allowGLLog()) +#endif + ALOGE("ERROR at calling %s status is (%d)", functionName, status); + } +} +///////////////////////////////////////////////////////////////////////////////////////// +// GL & EGL extension checks +///////////////////////////////////////////////////////////////////////////////////////// + +bool GLUtils::isEGLImageSupported() +{ + const char* eglExtensions = eglQueryString(eglGetCurrentDisplay(), EGL_EXTENSIONS); + const char* glExtensions = reinterpret_cast(glGetString(GL_EXTENSIONS)); + + return eglExtensions && glExtensions + && strstr(eglExtensions, "EGL_KHR_image_base") + && strstr(eglExtensions, "EGL_KHR_gl_texture_2D_image") + && strstr(glExtensions, "GL_OES_EGL_image"); +} + +bool GLUtils::isEGLFenceSyncSupported() +{ + const char* eglExtensions = eglQueryString(eglGetCurrentDisplay(), EGL_EXTENSIONS); + return eglExtensions && strstr(eglExtensions, "EGL_KHR_fence_sync"); +} + +///////////////////////////////////////////////////////////////////////////////////////// +// Textures utilities +///////////////////////////////////////////////////////////////////////////////////////// + +static GLenum getInternalFormat(SkBitmap::Config config) +{ + switch (config) { + case SkBitmap::kA8_Config: + return GL_ALPHA; + case SkBitmap::kARGB_4444_Config: + return GL_RGBA; + case SkBitmap::kARGB_8888_Config: + return GL_RGBA; + case SkBitmap::kRGB_565_Config: + return GL_RGB; + default: + return -1; + } +} + +static GLenum getType(SkBitmap::Config config) +{ + switch (config) { + case SkBitmap::kA8_Config: + return GL_UNSIGNED_BYTE; + case SkBitmap::kARGB_4444_Config: + return GL_UNSIGNED_SHORT_4_4_4_4; + case SkBitmap::kARGB_8888_Config: + return GL_UNSIGNED_BYTE; + case SkBitmap::kIndex8_Config: + return -1; // No type for compressed data. + case SkBitmap::kRGB_565_Config: + return GL_UNSIGNED_SHORT_5_6_5; + default: + return -1; + } +} + +static EGLConfig defaultPbufferConfig(EGLDisplay display) +{ + EGLConfig config; + EGLint numConfigs; + + static const EGLint configAttribs[] = { + EGL_SURFACE_TYPE, EGL_PBUFFER_BIT, + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, + EGL_NONE + }; + + eglChooseConfig(display, configAttribs, &config, 1, &numConfigs); + GLUtils::checkEglError("eglPbufferConfig"); + if (numConfigs != 1) + ALOGI("eglPbufferConfig failed (%d)\n", numConfigs); + + return config; +} + +static EGLSurface createPbufferSurface(EGLDisplay display, const EGLConfig& config, + EGLint* errorCode) +{ + const EGLint attribList[] = { + EGL_WIDTH, 1, + EGL_HEIGHT, 1, + EGL_NONE + }; + EGLSurface surface = eglCreatePbufferSurface(display, config, attribList); + + if (errorCode) + *errorCode = eglGetError(); + else + GLUtils::checkEglError("eglCreatePbufferSurface"); + + if (surface == EGL_NO_SURFACE) + return EGL_NO_SURFACE; + + return surface; +} + +EGLContext GLUtils::createBackgroundContext(EGLContext sharedContext) +{ + checkEglError(""); + EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); + checkEglError("eglGetDisplay"); + if (display == EGL_NO_DISPLAY) { + ALOGE("eglGetDisplay returned EGL_NO_DISPLAY"); + return EGL_NO_CONTEXT; + } + + EGLint majorVersion; + EGLint minorVersion; + EGLBoolean returnValue = eglInitialize(display, &majorVersion, &minorVersion); + checkEglError("eglInitialize", returnValue); + if (returnValue != EGL_TRUE) { + ALOGE("eglInitialize failed\n"); + return EGL_NO_CONTEXT; + } + + EGLConfig config = defaultPbufferConfig(display); + EGLSurface surface = createPbufferSurface(display, config, 0); + + EGLint surfaceConfigId; + EGLBoolean success = eglGetConfigAttrib(display, config, EGL_CONFIG_ID, &surfaceConfigId); + + EGLint contextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; + EGLContext context = eglCreateContext(display, config, sharedContext, contextAttribs); + checkEglError("eglCreateContext"); + if (context == EGL_NO_CONTEXT) { + ALOGE("eglCreateContext failed\n"); + return EGL_NO_CONTEXT; + } + + returnValue = eglMakeCurrent(display, surface, surface, context); + checkEglError("eglMakeCurrent", returnValue); + if (returnValue != EGL_TRUE) { + ALOGE("eglMakeCurrent failed\n"); + return EGL_NO_CONTEXT; + } + + return context; +} + +void GLUtils::deleteTexture(GLuint* texture) +{ + glDeleteTextures(1, texture); + GLUtils::checkGlError("glDeleteTexture"); + *texture = 0; +} + +GLuint GLUtils::createSampleColorTexture(int r, int g, int b) +{ + GLuint texture; + glGenTextures(1, &texture); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + GLubyte pixels[4 *3] = { + r, g, b, + r, g, b, + r, g, b, + r, g, b + }; + glBindTexture(GL_TEXTURE_2D, texture); + GLUtils::checkGlError("glBindTexture"); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 2, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, pixels); + GLUtils::checkGlError("glTexImage2D"); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + return texture; +} + +GLuint GLUtils::createSampleTexture() +{ + GLuint texture; + glGenTextures(1, &texture); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + GLubyte pixels[4 *3] = { + 255, 0, 0, + 0, 255, 0, + 0, 0, 255, + 255, 255, 0 + }; + glBindTexture(GL_TEXTURE_2D, texture); + GLUtils::checkGlError("glBindTexture"); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 2, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, pixels); + GLUtils::checkGlError("glTexImage2D"); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + return texture; +} + +GLuint GLUtils::createTileGLTexture(int width, int height) +{ + GLuint texture; + glGenTextures(1, &texture); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + GLubyte* pixels = 0; +#ifdef DEBUG + int length = width * height * 4; + pixels = new GLubyte[length]; + for (int i = 0; i < length; i++) + pixels[i] = i % 256; +#endif + glBindTexture(GL_TEXTURE_2D, texture); + GLUtils::checkGlError("glBindTexture"); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + GLUtils::checkGlError("glTexImage2D"); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); +#ifdef DEBUG + delete pixels; +#endif + return texture; +} + +bool GLUtils::isPureColorBitmap(const SkBitmap& bitmap, Color& pureColor) +{ + // If the bitmap is the pure color, skip the transfer step, and update the Tile Info. + // This check is taking < 1ms if we do full bitmap check per tile. + // TODO: use the SkPicture to determine whether or not a tile is single color. + pureColor = Color(Color::transparent); + bitmap.lockPixels(); + bool sameColor = true; + int bitmapWidth = bitmap.width(); + + // Create a row of pure color using the first pixel. + // TODO: improve the perf here, by either picking a random pixel, or + // creating an array of rows with pre-defined commonly used color, add + // smart LUT to speed things up if possible. + int* firstPixelPtr = static_cast (bitmap.getPixels()); + int* pixelsRow = new int[bitmapWidth]; + for (int i = 0; i < bitmapWidth; i++) + pixelsRow[i] = (*firstPixelPtr); + + // Then compare the pure color row with each row of the bitmap. + for (int j = 0; j < bitmap.height(); j++) { + if (memcmp(pixelsRow, &firstPixelPtr[bitmapWidth * j], 4 * bitmapWidth)) { + sameColor = false; + break; + } + } + delete pixelsRow; + pixelsRow = 0; + + if (sameColor) { + char* rgbaPtr = static_cast(bitmap.getPixels()); + pureColor = Color(rgbaPtr[0], rgbaPtr[1], rgbaPtr[2], rgbaPtr[3]); + ALOGV("sameColor tile found , %x at (%d, %d, %d, %d)", + *firstPixelPtr, rgbaPtr[0], rgbaPtr[1], rgbaPtr[2], rgbaPtr[3]); + } + bitmap.unlockPixels(); + + return sameColor; +} + +// Return true when the tile is pure color. +bool GLUtils::skipTransferForPureColor(const TileRenderInfo* renderInfo, + const SkBitmap& bitmap) +{ + bool skipTransfer = false; + Tile* tilePtr = renderInfo->baseTile; + + // TODO: use pure color for partial invals as well + if (renderInfo->invalRect) + return false; + + if (tilePtr) { + TileTexture* tileTexture = tilePtr->backTexture(); + // Check the bitmap, and make everything ready here. + if (tileTexture && renderInfo->isPureColor) { + // update basetile's info + // Note that we are skipping the whole TransferQueue. + renderInfo->textureInfo->m_width = bitmap.width(); + renderInfo->textureInfo->m_height = bitmap.height(); + renderInfo->textureInfo->m_internalFormat = GL_RGBA; + + TilesManager::instance()->transferQueue()->addItemInPureColorQueue(renderInfo); + + skipTransfer = true; + } + } + return skipTransfer; +} + +void GLUtils::paintTextureWithBitmap(const TileRenderInfo* renderInfo, + const SkBitmap& bitmap) +{ + if (!renderInfo) + return; + const SkSize& requiredSize = renderInfo->tileSize; + TextureInfo* textureInfo = renderInfo->textureInfo; + + if (skipTransferForPureColor(renderInfo, bitmap)) + return; + + if (requiredSize.equals(textureInfo->m_width, textureInfo->m_height)) + GLUtils::updateQueueWithBitmap(renderInfo, bitmap); + else { + if (!requiredSize.equals(bitmap.width(), bitmap.height())) { + ALOGV("The bitmap size (%d,%d) does not equal the texture size (%d,%d)", + bitmap.width(), bitmap.height(), + requiredSize.width(), requiredSize.height()); + } + GLUtils::updateQueueWithBitmap(renderInfo, bitmap); + + textureInfo->m_width = bitmap.width(); + textureInfo->m_height = bitmap.height(); + textureInfo->m_internalFormat = GL_RGBA; + } +} + +void GLUtils::updateQueueWithBitmap(const TileRenderInfo* renderInfo, const SkBitmap& bitmap) +{ + if (!renderInfo + || !renderInfo->textureInfo + || !renderInfo->baseTile) + return; + + TilesManager::instance()->transferQueue()->updateQueueWithBitmap(renderInfo, bitmap); +} + +bool GLUtils::updateSharedSurfaceTextureWithBitmap(ANativeWindow* anw, const SkBitmap& bitmap) +{ + SkAutoLockPixels alp(bitmap); + if (!bitmap.getPixels()) + return false; + ANativeWindow_Buffer buffer; + if (ANativeWindow_lock(anw, &buffer, 0)) + return false; + if (buffer.width < bitmap.width() || buffer.height < bitmap.height()) { + ALOGW("bitmap (%dx%d) too large for buffer (%dx%d)!", + bitmap.width(), bitmap.height(), + buffer.width, buffer.height); + ANativeWindow_unlockAndPost(anw); + return false; + } + uint8_t* img = (uint8_t*)buffer.bits; + int row; + int bpp = 4; // Now we only deal with RGBA8888 format. + bitmap.lockPixels(); + uint8_t* bitmapOrigin = static_cast(bitmap.getPixels()); + + if (buffer.stride != bitmap.width()) + // Copied line by line since we need to handle the offsets and stride. + for (row = 0 ; row < bitmap.height(); row ++) { + uint8_t* dst = &(img[buffer.stride * row * bpp]); + uint8_t* src = &(bitmapOrigin[bitmap.width() * row * bpp]); + memcpy(dst, src, bpp * bitmap.width()); + } + else + memcpy(img, bitmapOrigin, bpp * bitmap.width() * bitmap.height()); + + bitmap.unlockPixels(); + ANativeWindow_unlockAndPost(anw); + return true; +} + +void GLUtils::createTextureWithBitmap(GLuint texture, const SkBitmap& bitmap, GLint filter) +{ + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glBindTexture(GL_TEXTURE_2D, texture); + GLUtils::checkGlError("glBindTexture"); + SkBitmap::Config config = bitmap.getConfig(); + int internalformat = getInternalFormat(config); + int type = getType(config); + bitmap.lockPixels(); + glTexImage2D(GL_TEXTURE_2D, 0, internalformat, bitmap.width(), bitmap.height(), + 0, internalformat, type, bitmap.getPixels()); + bitmap.unlockPixels(); + if (GLUtils::checkGlError("glTexImage2D")) { +#ifndef DEBUG + if (allowGLLog()) +#endif + ALOGE("GL ERROR: glTexImage2D parameters are : bitmap.width() %d, bitmap.height() %d," + " internalformat 0x%x, type 0x%x, bitmap.getPixels() %p", + bitmap.width(), bitmap.height(), internalformat, type, bitmap.getPixels()); + } + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter); + + // The following is a workaround -- remove when EGLImage texture upload is fixed. + GLuint fboID; + glGenFramebuffers(1, &fboID); + glBindFramebuffer(GL_FRAMEBUFFER, fboID); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0); + glCheckFramebufferStatus(GL_FRAMEBUFFER); // should return GL_FRAMEBUFFER_COMPLETE + + glBindFramebuffer(GL_FRAMEBUFFER, 0); // rebind the standard FBO + glDeleteFramebuffers(1, &fboID); +} + +void GLUtils::updateTextureWithBitmap(GLuint texture, const SkBitmap& bitmap, + const IntRect& inval, GLint filter) +{ + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glBindTexture(GL_TEXTURE_2D, texture); + GLUtils::checkGlError("glBindTexture"); + SkBitmap::Config config = bitmap.getConfig(); + int internalformat = getInternalFormat(config); + int type = getType(config); + bitmap.lockPixels(); + if (inval.isEmpty()) { + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, bitmap.width(), bitmap.height(), + internalformat, type, bitmap.getPixels()); + } else { + glTexSubImage2D(GL_TEXTURE_2D, 0, inval.x(), inval.y(), inval.width(), inval.height(), + internalformat, type, bitmap.getPixels()); + } + bitmap.unlockPixels(); + if (GLUtils::checkGlError("glTexSubImage2D")) { +#ifndef DEBUG + if (allowGLLog()) +#endif + ALOGE("GL ERROR: glTexSubImage2D parameters are : bitmap.width() %d, bitmap.height() %d," + " internalformat 0x%x, type 0x%x, bitmap.getPixels() %p", + bitmap.width(), bitmap.height(), internalformat, type, bitmap.getPixels()); + } + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter); +} + +void GLUtils::createEGLImageFromTexture(GLuint texture, EGLImageKHR* image) +{ + EGLClientBuffer buffer = reinterpret_cast(texture); + static const EGLint attr[] = { EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE }; + *image = eglCreateImageKHR(eglGetCurrentDisplay(), eglGetCurrentContext(), + EGL_GL_TEXTURE_2D_KHR, buffer, attr); + GLUtils::checkEglError("eglCreateImage", (*image != EGL_NO_IMAGE_KHR)); +} + +void GLUtils::createTextureFromEGLImage(GLuint texture, EGLImageKHR image, GLint filter) +{ + glBindTexture(GL_TEXTURE_2D, texture); + GLUtils::checkGlError("glBindTexture"); + glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)image); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter); +} + +void GLUtils::convertToTransformationMatrix(const float* matrix, TransformationMatrix& transformMatrix) +{ + transformMatrix.setMatrix( + matrix[0], matrix[1], matrix[2], matrix[3], + matrix[4], matrix[5], matrix[6], matrix[7], + matrix[8], matrix[9], matrix[10], matrix[11], + matrix[12], matrix[13], matrix[14], matrix[15]); +} + +void GLUtils::clearBackgroundIfOpaque(const Color* backgroundColor) +{ + if (!backgroundColor->hasAlpha()) { + if (TilesManager::instance()->invertedScreen()) { + float color = 1.0 - ((((float) backgroundColor->red() / 255.0) + + ((float) backgroundColor->green() / 255.0) + + ((float) backgroundColor->blue() / 255.0)) / 3.0); + glClearColor(color, color, color, 1); + } else { + glClearColor((float)backgroundColor->red() / 255.0, + (float)backgroundColor->green() / 255.0, + (float)backgroundColor->blue() / 255.0, 1); + } + glClear(GL_COLOR_BUFFER_BIT); + } +} + +} // namespace WebCore + +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/android/rendering/GLUtils.h b/Source/WebCore/platform/graphics/android/rendering/GLUtils.h new file mode 100644 index 0000000..d4a2e84 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/rendering/GLUtils.h @@ -0,0 +1,98 @@ +/* + * Copyright 2010, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef GLUtils_h +#define GLUtils_h + +#if USE(ACCELERATED_COMPOSITING) + +#include "Color.h" +#include "SkBitmap.h" +#include "SkMatrix.h" +#include "TransformationMatrix.h" +#include +#include +#include +#include + +namespace android { + +class SurfaceTexture; + +} // namespace android + +namespace WebCore { + +class TileRenderInfo; + +class GLUtils { + +public: + // Matrix utilities + static void toGLMatrix(GLfloat* flattened, const TransformationMatrix& matrix); + static void toSkMatrix(SkMatrix& skmatrix, const TransformationMatrix& matrix); + static void setOrthographicMatrix(TransformationMatrix& ortho, float left, float top, + float right, float bottom, float nearZ, float farZ); + + // GL & EGL error checks + static void checkEglError(const char* op, EGLBoolean returnVal = EGL_TRUE); + static bool checkGlErrorOn(void* p, const char* op); + static bool checkGlError(const char* op); + static void checkSurfaceTextureError(const char* functionName, int status); + + // GL & EGL extension checks + static bool isEGLImageSupported(); + static bool isEGLFenceSyncSupported(); + + // Texture utilities + static EGLContext createBackgroundContext(EGLContext sharedContext); + static void deleteTexture(GLuint* texture); + static GLuint createSampleColorTexture(int r, int g, int b); + static GLuint createSampleTexture(); + static GLuint createTileGLTexture(int width, int height); + + static void createTextureWithBitmap(GLuint texture, const SkBitmap& bitmap, GLint filter = GL_LINEAR); + static void updateTextureWithBitmap(GLuint texture, const SkBitmap& bitmap, const IntRect&, GLint filter = GL_LINEAR); + static void createEGLImageFromTexture(GLuint texture, EGLImageKHR* image); + static void createTextureFromEGLImage(GLuint texture, EGLImageKHR image, GLint filter = GL_LINEAR); + + static void paintTextureWithBitmap(const TileRenderInfo* renderInfo, const SkBitmap& bitmap); + static void updateQueueWithBitmap(const TileRenderInfo* , const SkBitmap& bitmap); + static bool updateSharedSurfaceTextureWithBitmap(ANativeWindow* anw, const SkBitmap& bitmap); + static void convertToTransformationMatrix(const float* matrix, TransformationMatrix& transformMatrix); + + static bool isPureColorBitmap(const SkBitmap& bitmap, Color& pureColor); + static bool skipTransferForPureColor(const TileRenderInfo* renderInfo, + const SkBitmap& bitmap); + static void clearBackgroundIfOpaque(const Color* backgroundColor); + static bool allowGLLog(); + static double m_previousLogTime; + static int m_currentLogCounter; +}; + +} // namespace WebCore + +#endif // USE(ACCELERATED_COMPOSITING) +#endif // GLUtils_h diff --git a/Source/WebCore/platform/graphics/android/rendering/GaneshContext.cpp b/Source/WebCore/platform/graphics/android/rendering/GaneshContext.cpp new file mode 100644 index 0000000..bf43652 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/rendering/GaneshContext.cpp @@ -0,0 +1,184 @@ +/* + * Copyright 2011, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define LOG_TAG "GaneshContext" +#define LOG_NDEBUG 1 + +#include "config.h" +#include "GaneshContext.h" + +#include "AndroidLog.h" +#include "GLUtils.h" +#include "TextureInfo.h" +#include "TilesManager.h" +#include "TransferQueue.h" + +#include "android/native_window.h" + +#if USE(ACCELERATED_COMPOSITING) + +namespace WebCore { + +GaneshContext::GaneshContext() + : m_grContext(0) + , m_tileDeviceSurface(0) + , m_surfaceConfig(0) + , m_surfaceContext(EGL_NO_CONTEXT) +{ +} + +GaneshContext* GaneshContext::gInstance = 0; + +GaneshContext* GaneshContext::instance() +{ + if (!gInstance) + gInstance = new GaneshContext(); + return gInstance; +} + +GrContext* GaneshContext::getGrContext() +{ + if (!m_grContext) { + m_grContext = GrContext::Create(kOpenGL_Shaders_GrEngine, NULL); + } + return m_grContext; +} + +void GaneshContext::flush() +{ + if (m_grContext) + m_grContext->flush(); +} + +SkDevice* GaneshContext::getDeviceForTile(const TileRenderInfo& renderInfo) +{ + // Ganesh should be the only code in the rendering thread that is using GL + // and setting the EGLContext. If this is not the case then we need to + // reset the Ganesh context to prevent rendering issues. + bool contextNeedsReset = false; + if (eglGetCurrentContext() != m_surfaceContext) { + ALOGV("Warning: EGLContext has Changed! %p, %p", + m_surfaceContext, eglGetCurrentContext()); + contextNeedsReset = true; + } + + EGLDisplay display; + + if (!m_surfaceContext) { + + if(eglGetCurrentContext() != EGL_NO_CONTEXT) { + ALOGV("ERROR: should not have a context yet"); + } + + display = eglGetDisplay(EGL_DEFAULT_DISPLAY); + GLUtils::checkEglError("eglGetDisplay"); + + EGLint majorVersion; + EGLint minorVersion; + EGLBoolean returnValue = eglInitialize(display, &majorVersion, &minorVersion); + GLUtils::checkEglError("eglInitialize", returnValue); + + EGLint numConfigs; + static const EGLint configAttribs[] = { + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, + EGL_RED_SIZE, 8, + EGL_GREEN_SIZE, 8, + EGL_BLUE_SIZE, 8, + EGL_ALPHA_SIZE, 8, + EGL_STENCIL_SIZE, 8, + EGL_NONE + }; + + eglChooseConfig(display, configAttribs, &m_surfaceConfig, 1, &numConfigs); + GLUtils::checkEglError("eglChooseConfig"); + + static const EGLint contextAttribs[] = { + EGL_CONTEXT_CLIENT_VERSION, 2, + EGL_NONE + }; + + m_surfaceContext = eglCreateContext(display, m_surfaceConfig, NULL, contextAttribs); + GLUtils::checkEglError("eglCreateContext"); + } else { + display = eglGetCurrentDisplay(); + GLUtils::checkEglError("eglGetCurrentDisplay"); + } + + TransferQueue* tileQueue = TilesManager::instance()->transferQueue(); + if (tileQueue->m_eglSurface == EGL_NO_SURFACE) { + + const float tileWidth = renderInfo.tileSize.width(); + const float tileHeight = renderInfo.tileSize.height(); + + ANativeWindow* anw = tileQueue->m_ANW.get(); + + int result = ANativeWindow_setBuffersGeometry(anw, (int)tileWidth, + (int)tileHeight, WINDOW_FORMAT_RGBA_8888); + + renderInfo.textureInfo->m_width = tileWidth; + renderInfo.textureInfo->m_height = tileHeight; + tileQueue->m_eglSurface = eglCreateWindowSurface(display, m_surfaceConfig, anw, NULL); + + GLUtils::checkEglError("eglCreateWindowSurface"); + ALOGV("eglCreateWindowSurface"); + } + + EGLBoolean returnValue = eglMakeCurrent(display, tileQueue->m_eglSurface, tileQueue->m_eglSurface, m_surfaceContext); + GLUtils::checkEglError("eglMakeCurrent", returnValue); + ALOGV("eglMakeCurrent"); + + if (!m_tileDeviceSurface) { + + GrPlatformRenderTargetDesc renderTargetDesc; + renderTargetDesc.fWidth = TilesManager::tileWidth(); + renderTargetDesc.fHeight = TilesManager::tileHeight(); + renderTargetDesc.fConfig = kRGBA_8888_PM_GrPixelConfig; + renderTargetDesc.fSampleCnt = 0; + renderTargetDesc.fStencilBits = 8; + renderTargetDesc.fRenderTargetHandle = 0; + + GrContext* grContext = getGrContext(); + GrRenderTarget* renderTarget = grContext->createPlatformRenderTarget(renderTargetDesc); + + m_tileDeviceSurface = new SkGpuDevice(grContext, renderTarget); + renderTarget->unref(); + ALOGV("generated device %p", m_tileDeviceSurface); + } + + GLUtils::checkGlError("getDeviceForTile"); + + // We must reset the Ganesh context only after we are sure we have + // re-established our EGLContext as the current context. + if (m_tileDeviceSurface && contextNeedsReset) + getGrContext()->resetContext(); + + return m_tileDeviceSurface; +} + + + +} // namespace WebCore + +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/android/rendering/GaneshContext.h b/Source/WebCore/platform/graphics/android/rendering/GaneshContext.h new file mode 100644 index 0000000..57e8e19 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/rendering/GaneshContext.h @@ -0,0 +1,63 @@ +/* + * Copyright 2011, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef GaneshContext_h +#define GaneshContext_h + +#if USE(ACCELERATED_COMPOSITING) + +#include "BaseRenderer.h" +#include "GrContext.h" +#include "SkGpuDevice.h" +#include + +namespace WebCore { + +class GaneshContext { +public: + static GaneshContext* instance(); + + SkDevice* getDeviceForTile(const TileRenderInfo& renderInfo); + + void flush(); + +private: + + GaneshContext(); + + GrContext* getGrContext(); + GrContext* m_grContext; + + SkGpuDevice* m_tileDeviceSurface; + EGLConfig m_surfaceConfig; + EGLContext m_surfaceContext; + + static GaneshContext* gInstance; +}; + +} // namespace WebCore + +#endif // USE(ACCELERATED_COMPOSITING) +#endif // GaneshContext_h diff --git a/Source/WebCore/platform/graphics/android/rendering/GaneshRenderer.cpp b/Source/WebCore/platform/graphics/android/rendering/GaneshRenderer.cpp new file mode 100644 index 0000000..208adb6 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/rendering/GaneshRenderer.cpp @@ -0,0 +1,113 @@ +/* + * Copyright 2011, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define LOG_TAG "GaneshRenderer" +#define LOG_NDEBUG 1 + +#include "config.h" +#include "GaneshRenderer.h" + +#if USE(ACCELERATED_COMPOSITING) + +#include "AndroidLog.h" +#include "GaneshContext.h" +#include "SkCanvas.h" +#include "SkGpuDevice.h" +#include "TilesManager.h" +#include "TransferQueue.h" + +namespace WebCore { + +GaneshRenderer::GaneshRenderer() : BaseRenderer(BaseRenderer::Ganesh) +{ +#ifdef DEBUG_COUNT + ClassTracker::instance()->increment("GaneshRenderer"); +#endif +} + +GaneshRenderer::~GaneshRenderer() +{ +#ifdef DEBUG_COUNT + ClassTracker::instance()->decrement("GaneshRenderer"); +#endif +} + +void GaneshRenderer::setupCanvas(const TileRenderInfo& renderInfo, SkCanvas* canvas) +{ + GaneshContext* ganesh = GaneshContext::instance(); + + TransferQueue* tileQueue = TilesManager::instance()->transferQueue(); + + tileQueue->lockQueue(); + + bool ready = tileQueue->readyForUpdate(); + if (!ready) { + ALOGV("!ready"); + tileQueue->unlockQueue(); + return; + } + + SkDevice* device = NULL; + if (renderInfo.tileSize.width() == TilesManager::tileWidth() + && renderInfo.tileSize.height() == TilesManager::tileHeight()) { + device = ganesh->getDeviceForTile(renderInfo); + } else { + // TODO support arbitrary sizes for layers + ALOGV("ERROR: expected (%d,%d) actual (%d,%d)", + TilesManager::tileWidth(), TilesManager::tileHeight(), + renderInfo.tileSize.width(), renderInfo.tileSize.height()); + } + + // set the GPU device to the canvas + canvas->setDevice(device); +} + +void GaneshRenderer::setupPartialInval(const TileRenderInfo& renderInfo, SkCanvas* canvas) +{ + // set the clip to our invalRect + SkRect clipRect = SkRect::MakeLTRB(renderInfo.invalRect->fLeft, + renderInfo.invalRect->fTop, + renderInfo.invalRect->fRight, + renderInfo.invalRect->fBottom); + canvas->clipRect(clipRect); +} + +void GaneshRenderer::renderingComplete(const TileRenderInfo& renderInfo, SkCanvas* canvas) +{ + ALOGV("rendered to tile (%d,%d)", renderInfo.x, renderInfo.y); + + GaneshContext::instance()->flush(); + + // In SurfaceTextureMode we must call swapBuffers to unlock and post the + // tile's ANativeWindow (i.e. SurfaceTexture) buffer + TransferQueue* tileQueue = TilesManager::instance()->transferQueue(); + eglSwapBuffers(eglGetCurrentDisplay(), tileQueue->m_eglSurface); + tileQueue->addItemInTransferQueue(&renderInfo, GpuUpload, 0); + tileQueue->unlockQueue(); +} + +} // namespace WebCore + +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/android/rendering/GaneshRenderer.h b/Source/WebCore/platform/graphics/android/rendering/GaneshRenderer.h new file mode 100644 index 0000000..d7eda24 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/rendering/GaneshRenderer.h @@ -0,0 +1,61 @@ +/* + * Copyright 2011, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef GaneshRenderer_h +#define GaneshRenderer_h + +#if USE(ACCELERATED_COMPOSITING) + +#include "BaseRenderer.h" +#include "SkRect.h" + +class SkCanvas; +class SkDevice; + +namespace WebCore { + +/** + * + */ +class GaneshRenderer : public BaseRenderer { +public: + GaneshRenderer(); + ~GaneshRenderer(); + +protected: + + virtual void setupCanvas(const TileRenderInfo& renderInfo, SkCanvas* canvas); + virtual void setupPartialInval(const TileRenderInfo& renderInfo, SkCanvas* canvas); + virtual void renderingComplete(const TileRenderInfo& renderInfo, SkCanvas* canvas); + virtual void checkForPureColor(TileRenderInfo& renderInfo, SkCanvas* canvas) { + renderInfo.isPureColor = false; + } + +}; + +} // namespace WebCore + +#endif // USE(ACCELERATED_COMPOSITING) +#endif // GaneshRenderer_h diff --git a/Source/WebCore/platform/graphics/android/rendering/ImageTexture.cpp b/Source/WebCore/platform/graphics/android/rendering/ImageTexture.cpp new file mode 100644 index 0000000..b2ead6a --- /dev/null +++ b/Source/WebCore/platform/graphics/android/rendering/ImageTexture.cpp @@ -0,0 +1,256 @@ +/* + * Copyright 2011, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define LOG_TAG "ImageTexture" +#define LOG_NDEBUG 1 + +#include "config.h" +#include "ImageTexture.h" + +#include "AndroidLog.h" +#include "ClassTracker.h" +#include "ImagesManager.h" +#include "LayerAndroid.h" +#include "SkDevice.h" +#include "SkPicture.h" +#include "TileGrid.h" +#include "TilesManager.h" + +namespace WebCore { + +// CRC computation adapted from Tools/DumpRenderTree/CyclicRedundancyCheck.cpp +static void makeCrcTable(unsigned crcTable[256]) +{ + for (unsigned i = 0; i < 256; i++) { + unsigned c = i; + for (int k = 0; k < 8; k++) { + if (c & 1) + c = -306674912 ^ ((c >> 1) & 0x7fffffff); + else + c = c >> 1; + } + crcTable[i] = c; + } +} + +unsigned computeCrc(uint8_t* buffer, size_t size) +{ + static unsigned crcTable[256]; + static bool crcTableComputed = false; + if (!crcTableComputed) { + makeCrcTable(crcTable); + crcTableComputed = true; + } + + unsigned crc = 0xffffffffL; + for (size_t i = 0; i < size; ++i) + crc = crcTable[(crc ^ buffer[i]) & 0xff] ^ ((crc >> 8) & 0x00ffffffL); + return crc ^ 0xffffffffL; +} + +ImageTexture::ImageTexture(SkBitmap* bmp, unsigned crc) + : m_image(bmp) + , m_texture(0) + , m_layer(0) + , m_picture(0) + , m_crc(crc) +{ +#ifdef DEBUG_COUNT + ClassTracker::instance()->increment("ImageTexture"); +#endif + if (!m_image) + return; + + // NOTE: This constructor is called on the webcore thread + + // Create a picture containing the image (needed for TileGrid) + m_picture = new SkPicture(); + SkCanvas* pcanvas = m_picture->beginRecording(m_image->width(), m_image->height()); + pcanvas->clear(SkColorSetARGBInline(0, 0, 0, 0)); + pcanvas->drawBitmap(*m_image, 0, 0); + m_picture->endRecording(); +} + +ImageTexture::~ImageTexture() +{ +#ifdef DEBUG_COUNT + ClassTracker::instance()->decrement("ImageTexture"); +#endif + delete m_image; + delete m_texture; + SkSafeUnref(m_picture); +} + +SkBitmap* ImageTexture::convertBitmap(SkBitmap* bitmap) +{ + SkBitmap* img = new SkBitmap(); + int w = bitmap->width(); + int h = bitmap->height(); + + // Create a copy of the image + img->setConfig(SkBitmap::kARGB_8888_Config, w, h); + img->allocPixels(); + SkDevice* device = new SkDevice(*img); + SkCanvas canvas; + canvas.setDevice(device); + device->unref(); + SkRect dest; + dest.set(0, 0, w, h); + img->setIsOpaque(false); + img->eraseARGB(0, 0, 0, 0); + canvas.drawBitmapRect(*bitmap, 0, dest); + + return img; +} + +unsigned ImageTexture::computeCRC(const SkBitmap* bitmap) +{ + if (!bitmap) + return 0; + bitmap->lockPixels(); + uint8_t* img = static_cast(bitmap->getPixels()); + unsigned crc = computeCrc(img, bitmap->getSize()); + bitmap->unlockPixels(); + return crc; +} + +bool ImageTexture::equalsCRC(unsigned crc) +{ + return m_crc == crc; +} + +int ImageTexture::nbTextures() +{ + if (!hasContentToShow()) + return 0; + if (!m_texture) + return 0; + + // TODO: take in account the visible clip (need to maintain + // a list of the clients layer, etc.) + IntRect visibleArea(0, 0, m_image->width(), m_image->height()); + int nbTextures = m_texture->nbTextures(visibleArea, 1.0); + ALOGV("ImageTexture %p, %d x %d needs %d textures", + this, m_image->width(), m_image->height(), + nbTextures); + return nbTextures; +} + +bool ImageTexture::hasContentToShow() +{ + // Don't display 1x1 image -- no need to allocate a full texture for this + if (!m_image) + return false; + if (m_image->width() == 1 && m_image->height() == 1) + return false; + return true; +} + +bool ImageTexture::prepareGL(GLWebViewState* state) +{ + if (!hasContentToShow()) + return false; + + if (!m_texture && m_picture) { + bool isLayerTile = true; + m_texture = new TileGrid(isLayerTile); + SkRegion region; + region.setRect(0, 0, m_image->width(), m_image->height()); + m_texture->markAsDirty(region); + } + + if (!m_texture) + return false; + + IntRect unclippedArea(0, 0, m_image->width(), m_image->height()); + m_texture->prepareGL(state, 1.0, unclippedArea, unclippedArea, this); + if (m_texture->isReady()) { + m_texture->swapTiles(); + return false; + } + return true; +} + +const TransformationMatrix* ImageTexture::transform() +{ + if (!m_layer) + return 0; + + FloatPoint p(0, 0); + p = m_layer->drawTransform()->mapPoint(p); + IntRect layerArea = m_layer->unclippedArea(); + float scaleW = static_cast(layerArea.width()) / static_cast(m_image->width()); + float scaleH = static_cast(layerArea.height()) / static_cast(m_image->height()); + TransformationMatrix d = *(m_layer->drawTransform()); + TransformationMatrix m; + m.scaleNonUniform(scaleW, scaleH); + m_layerMatrix = d.multiply(m); + return &m_layerMatrix; +} + +float ImageTexture::opacity() +{ + if (!m_layer) + return 1.0; + return m_layer->drawOpacity(); +} + +bool ImageTexture::paint(Tile* tile, SkCanvas* canvas) +{ + if (!m_picture) { + ALOGV("IT %p COULDNT PAINT, NO PICTURE", this); + return false; + } + + ALOGV("IT %p painting tile %d, %d with picture %p", this, tile->x(), tile->y(), m_picture); + canvas->drawPicture(*m_picture); + + return true; +} + +void ImageTexture::drawGL(LayerAndroid* layer, float opacity) +{ + if (!layer) + return; + if (!hasContentToShow()) + return; + + // TileGrid::draw() will call us back to know the + // transform and opacity, so we need to set m_layer + m_layer = layer; + if (m_texture) { + IntRect visibleArea = m_layer->visibleArea(); + m_texture->drawGL(visibleArea, opacity, transform()); + } + m_layer = 0; +} + +void ImageTexture::drawCanvas(SkCanvas* canvas, SkRect& rect) +{ + if (canvas && m_image) + canvas->drawBitmapRect(*m_image, 0, rect); +} + +} // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/rendering/ImageTexture.h b/Source/WebCore/platform/graphics/android/rendering/ImageTexture.h new file mode 100644 index 0000000..34430f1 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/rendering/ImageTexture.h @@ -0,0 +1,110 @@ +/* + * Copyright 2011, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ImageTexture_h +#define ImageTexture_h + +#include "GLUtils.h" +#include "SkBitmap.h" +#include "SkBitmapRef.h" +#include "SkPicture.h" +#include "SkRefCnt.h" +#include "TilePainter.h" + +namespace WebCore { + +class GLWebViewState; +class LayerAndroid; +class TexturesResult; +class TileGrid; + +///////////////////////////////////////////////////////////////////////////////// +// Image sharing codepath for layers +///////////////////////////////////////////////////////////////////////////////// +// +// Layers containing only an image take a slightly different codepath; +// GraphicsLayer::setContentsToImage() is called on the webcore thread, +// passing an Image instance. We get the native image (an SkBitmap) and create +// an ImageTexture instance with it (or increment the refcount of an existing +// instance if the SkBitmap is similar to one already stored in ImagesManager, +// i.e. if two GraphicsLayer share the same image). +// +// To detect if an image is similar, we compute and use a CRC. Each ImageTexture +// is stored in ImagesManager using its CRC as a hash key. +// Simply comparing the address is not enough -- different image could end up +// at the same address (i.e. the image is deallocated then a new one is +// reallocated at the old address) +// +// Each ImageTexture's CRC being unique, LayerAndroid instances simply store that +// and retain/release the corresponding ImageTexture (so that +// queued painting request will work correctly and not crash...). +// LayerAndroid running on the UI thread will get the corresponding +// ImageTexture at draw time. +// +// ImageTexture recopy the original SkBitmap so that they can safely be used +// on a different thread; it uses TileGrid to allocate and paint the image, +// so that we can share the same textures and limits as the rest of the layers. +// +///////////////////////////////////////////////////////////////////////////////// +class ImageTexture : public TilePainter { +public: + ImageTexture(SkBitmap* bmp, unsigned crc); + virtual ~ImageTexture(); + + bool prepareGL(GLWebViewState*); + void drawGL(LayerAndroid* layer, float opacity); + void drawCanvas(SkCanvas*, SkRect&); + bool hasContentToShow(); + SkBitmap* bitmap() { return m_image; } + unsigned imageCRC() { return m_crc; } + + static SkBitmap* convertBitmap(SkBitmap* bitmap); + + static unsigned computeCRC(const SkBitmap* bitmap); + bool equalsCRC(unsigned crc); + + // methods used by TileGrid + virtual bool paint(Tile* tile, SkCanvas* canvas); + virtual float opacity(); + + int nbTextures(); + + virtual SurfaceType type() { return TilePainter::Image; } + +private: + const TransformationMatrix* transform(); + + SkBitmapRef* m_imageRef; + SkBitmap* m_image; + TileGrid* m_texture; + LayerAndroid* m_layer; + SkPicture* m_picture; + TransformationMatrix m_layerMatrix; + unsigned m_crc; +}; + +} // namespace WebCore + +#endif // ImageTexture diff --git a/Source/WebCore/platform/graphics/android/rendering/ImagesManager.cpp b/Source/WebCore/platform/graphics/android/rendering/ImagesManager.cpp new file mode 100644 index 0000000..8452503 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/rendering/ImagesManager.cpp @@ -0,0 +1,134 @@ +/* + * Copyright 2011, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define LOG_TAG "ImagesManager" +#define LOG_NDEBUG 1 + +#include "config.h" +#include "ImagesManager.h" + +#include "AndroidLog.h" +#include "SkCanvas.h" +#include "SkDevice.h" +#include "SkRefCnt.h" +#include "ImageTexture.h" + +namespace WebCore { + +ImagesManager* ImagesManager::instance() +{ + if (!gInstance) + gInstance = new ImagesManager(); + + return gInstance; +} + +ImagesManager* ImagesManager::gInstance = 0; + +ImageTexture* ImagesManager::setImage(SkBitmapRef* imgRef) +{ + if (!imgRef) + return 0; + + SkBitmap* bitmap = &imgRef->bitmap(); + ImageTexture* image = 0; + SkBitmap* img = 0; + unsigned crc = 0; + + img = ImageTexture::convertBitmap(bitmap); + crc = ImageTexture::computeCRC(img); + + { + android::Mutex::Autolock lock(m_imagesLock); + if (m_images.contains(crc)) { + image = m_images.get(crc); + SkSafeRef(image); + return image; + } + } + + // the image is not in the map, we add it + + image = new ImageTexture(img, crc); + + android::Mutex::Autolock lock(m_imagesLock); + m_images.set(crc, image); + + return image; +} + +ImageTexture* ImagesManager::retainImage(unsigned imgCRC) +{ + if (!imgCRC) + return 0; + + android::Mutex::Autolock lock(m_imagesLock); + ImageTexture* image = 0; + if (m_images.contains(imgCRC)) { + image = m_images.get(imgCRC); + SkSafeRef(image); + } + return image; +} + +void ImagesManager::releaseImage(unsigned imgCRC) +{ + if (!imgCRC) + return; + + android::Mutex::Autolock lock(m_imagesLock); + if (m_images.contains(imgCRC)) { + ImageTexture* image = m_images.get(imgCRC); + if (image->getRefCnt() == 1) + m_images.remove(imgCRC); + SkSafeUnref(image); + } +} + +int ImagesManager::nbTextures() +{ + android::Mutex::Autolock lock(m_imagesLock); + HashMap::iterator end = m_images.end(); + int i = 0; + int nb = 0; + for (HashMap::iterator it = m_images.begin(); it != end; ++it) { + nb += it->second->nbTextures(); + i++; + } + return nb; +} + +bool ImagesManager::prepareTextures(GLWebViewState* state) +{ + bool ret = false; + android::Mutex::Autolock lock(m_imagesLock); + HashMap::iterator end = m_images.end(); + for (HashMap::iterator it = m_images.begin(); it != end; ++it) { + ret |= it->second->prepareGL(state); + } + return ret; +} + +} // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/rendering/ImagesManager.h b/Source/WebCore/platform/graphics/android/rendering/ImagesManager.h new file mode 100644 index 0000000..b915a46 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/rendering/ImagesManager.h @@ -0,0 +1,64 @@ +/* + * Copyright 2011, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ImagesManager_h +#define ImagesManager_h + +#include "HashMap.h" +#include "SkBitmap.h" +#include "SkBitmapRef.h" +#include "SkRefCnt.h" +#include "Vector.h" + +#include + +namespace WebCore { + +class ImageTexture; +class GLWebViewState; + +class ImagesManager { +public: + static ImagesManager* instance(); + + ImageTexture* setImage(SkBitmapRef* imgRef); + ImageTexture* retainImage(unsigned imgCRC); + void releaseImage(unsigned imgCRC); + + bool prepareTextures(GLWebViewState*); + int nbTextures(); + +private: + ImagesManager() {} + + static ImagesManager* gInstance; + + android::Mutex m_imagesLock; + HashMap m_images; +}; + +} // namespace WebCore + +#endif // ImagesManager diff --git a/Source/WebCore/platform/graphics/android/rendering/InspectorCanvas.cpp b/Source/WebCore/platform/graphics/android/rendering/InspectorCanvas.cpp new file mode 100644 index 0000000..f9edb74 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/rendering/InspectorCanvas.cpp @@ -0,0 +1,133 @@ +/* + * Copyright 2011, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define LOG_TAG "InspectorCanvas" +#define LOG_NDEBUG 1 + +#include "config.h" +#include "InspectorCanvas.h" + +#include "AndroidLog.h" +#include "SkPicture.h" + +namespace WebCore { + + +void InspectorCanvas::setHasText() +{ + m_hasText = true; + setHasContent(); +} + +void InspectorCanvas::setHasContent() +{ + m_hasContent = true; + if (m_hasText) { + // has text. Have to paint properly, so no further + // information is useful + m_picture->abortPlayback(); + } +} + +void InspectorCanvas::setIsBackground(const SkPaint& paint) +{ + // TODO: if the paint is a solid color, opaque, and the last instruction in + // the picture, replace the picture with simple draw rect info + setHasContent(); +} + +void InspectorCanvas::commonDrawBitmap(const SkBitmap& bitmap, + const SkIRect* rect, + const SkMatrix&, + const SkPaint&) +{ + setHasContent(); +} + +void InspectorCanvas::drawPaint(const SkPaint& paint) +{ + setHasContent(); +} + +void InspectorCanvas::drawPath(const SkPath&, const SkPaint& paint) +{ + setHasContent(); +} +void InspectorCanvas::drawPoints(PointMode, size_t, + const SkPoint [], const SkPaint& paint) +{ + setHasContent(); +} + +void InspectorCanvas::drawRect(const SkRect& rect, const SkPaint& paint) +{ + if (rect.fLeft == 0 + && rect.fTop == 0 + && rect.width() >= m_picture->width() + && rect.height() >= m_picture->height()) { + // rect same size as canvas, treat layer as a single color rect until + // more content is drawn + setIsBackground(paint); + } else { + // regular rect drawing path + setHasContent(); + } + ALOGV("draw rect at %f %f, size %f %f, picture size %d %d", + rect.fLeft, rect.fTop, rect.width(), rect.height(), + m_picture->width(), m_picture->height()); +} +void InspectorCanvas::drawSprite(const SkBitmap& , int , int , + const SkPaint* paint) +{ + setHasContent(); +} + +void InspectorCanvas::drawText(const void*, size_t byteLength, SkScalar, + SkScalar, const SkPaint& paint) +{ + setHasText(); +} + +void InspectorCanvas::drawPosText(const void* , size_t byteLength, + const SkPoint [], const SkPaint& paint) +{ + setHasText(); +} + +void InspectorCanvas::drawPosTextH(const void*, size_t byteLength, + const SkScalar [], SkScalar, + const SkPaint& paint) +{ + setHasText(); +} + +void InspectorCanvas::drawTextOnPath(const void*, size_t byteLength, + const SkPath&, const SkMatrix*, + const SkPaint& paint) +{ + setHasText(); +} + +} // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/rendering/InspectorCanvas.h b/Source/WebCore/platform/graphics/android/rendering/InspectorCanvas.h new file mode 100644 index 0000000..415a579 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/rendering/InspectorCanvas.h @@ -0,0 +1,102 @@ +/* + * Copyright 2011, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef InspectorCanvas_h +#define InspectorCanvas_h + +#include "SkBounder.h" +#include "SkCanvas.h" + +namespace WebCore { + +class InspectorBounder : public SkBounder { + virtual bool onIRect(const SkIRect& rect) + { + return false; + } +}; + +class InspectorCanvas : public SkCanvas { +public: + InspectorCanvas(SkBounder* bounder, SkPicture* picture) + : m_picture(picture) + , m_hasText(false) + , m_hasContent(false) + { + setBounder(bounder); + } + + bool hasText() {return m_hasText;} + bool hasContent() {return m_hasContent;} + + virtual bool clipPath(const SkPath&, SkRegion::Op) { + return true; + } + + virtual void commonDrawBitmap(const SkBitmap& bitmap, + const SkIRect* rect, + const SkMatrix&, + const SkPaint&); + + virtual void drawPaint(const SkPaint& paint); + virtual void drawPath(const SkPath&, const SkPaint& paint); + virtual void drawPoints(PointMode, size_t, + const SkPoint [], const SkPaint& paint); + + virtual void drawRect(const SkRect& , const SkPaint& paint); + virtual void drawSprite(const SkBitmap& , int , int , + const SkPaint* paint = NULL); + + virtual void drawText(const void*, size_t byteLength, SkScalar, + SkScalar, const SkPaint& paint); + virtual void drawPosText(const void* , size_t byteLength, + const SkPoint [], const SkPaint& paint); + virtual void drawPosTextH(const void*, size_t byteLength, + const SkScalar [], SkScalar, + const SkPaint& paint); + virtual void drawTextOnPath(const void*, size_t byteLength, + const SkPath&, const SkMatrix*, + const SkPaint& paint); + +private: + + // vector instructions exist, must repaint at any scale + void setHasText(); + + // painting is required + void setHasContent(); + + // rect covering entire content, don't need to use a texture if nothing else + // is painted + void setIsBackground(const SkPaint& paint); + + SkPicture* m_picture; + bool m_hasText; + bool m_hasContent; +}; + +} // namespace WebCore + +#endif // InspectorCanvas_h diff --git a/Source/WebCore/platform/graphics/android/rendering/PaintTileOperation.cpp b/Source/WebCore/platform/graphics/android/rendering/PaintTileOperation.cpp new file mode 100644 index 0000000..b5e435b --- /dev/null +++ b/Source/WebCore/platform/graphics/android/rendering/PaintTileOperation.cpp @@ -0,0 +1,117 @@ +/* + * Copyright 2011, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define LOG_TAG "PaintTileOperation" +#define LOG_NDEBUG 1 + +#include "config.h" +#include "PaintTileOperation.h" + +#include "AndroidLog.h" +#include "GLWebViewState.h" +#include "ImageTexture.h" +#include "ImagesManager.h" +#include "LayerAndroid.h" +#include "TilesManager.h" + +namespace WebCore { + +PaintTileOperation::PaintTileOperation(Tile* tile, TilePainter* painter, + GLWebViewState* state, bool isLowResPrefetch) + : m_tile(tile) + , m_painter(painter) + , m_state(state) + , m_isLowResPrefetch(isLowResPrefetch) +{ + if (m_tile) + m_tile->setRepaintPending(true); + SkSafeRef(m_painter); +} + +PaintTileOperation::~PaintTileOperation() +{ + if (m_tile) { + m_tile->setRepaintPending(false); + m_tile = 0; + } + + if (m_painter && m_painter->type() == TilePainter::Image) { + ImageTexture* image = static_cast(m_painter); + ImagesManager::instance()->releaseImage(image->imageCRC()); + } else { + SkSafeUnref(m_painter); + } +} + +bool PaintTileOperation::operator==(const QueuedOperation* operation) +{ + const PaintTileOperation* op = static_cast(operation); + return op->m_tile == m_tile; +} + +void PaintTileOperation::run() +{ + if (m_tile) { + m_tile->paintBitmap(m_painter); + m_tile->setRepaintPending(false); + m_tile = 0; + } +} + +int PaintTileOperation::priority() +{ + if (!m_tile) + return -1; + + int priority = 200000; + + // prioritize low res while scrolling + if (m_isLowResPrefetch) + priority = m_state->isScrolling() ? 0 : 400000; + + // prioritize higher draw count + unsigned long long currentDraw = TilesManager::instance()->getDrawGLCount(); + unsigned long long drawDelta = currentDraw - m_tile->drawCount(); + priority += 100000 * (int)std::min(drawDelta, (unsigned long long)1000); + + // prioritize unpainted tiles, within the same drawCount + if (m_tile->frontTexture()) + priority += 50000; + + // for base tiles, prioritize based on position + if (!m_tile->isLayerTile()) { + bool goingDown = m_state->goingDown(); + priority += m_tile->x(); + + if (goingDown) + priority += 100000 - (1 + m_tile->y()) * 1000; + else + priority += m_tile->y() * 1000; + } + + return priority; +} + +} diff --git a/Source/WebCore/platform/graphics/android/rendering/PaintTileOperation.h b/Source/WebCore/platform/graphics/android/rendering/PaintTileOperation.h new file mode 100644 index 0000000..1d376bf --- /dev/null +++ b/Source/WebCore/platform/graphics/android/rendering/PaintTileOperation.h @@ -0,0 +1,88 @@ +/* + * Copyright 2010, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef PaintTileSetOperation_h +#define PaintTileSetOperation_h + +#include "Tile.h" +#include "QueuedOperation.h" +#include "SkRefCnt.h" + +namespace WebCore { + +class LayerAndroid; +class TilePainter; +class ImageTexture; + +class PaintTileOperation : public QueuedOperation { +public: + PaintTileOperation(Tile* tile, TilePainter* painter, + GLWebViewState* state, bool isLowResPrefetch); + virtual ~PaintTileOperation(); + virtual bool operator==(const QueuedOperation* operation); + virtual void run(); + // returns a rendering priority for m_tile, lower values are processed faster + virtual int priority(); + TilePainter* painter() { return m_painter; } + float scale() { return m_tile->scale(); } + +private: + Tile* m_tile; + TilePainter* m_painter; + GLWebViewState* m_state; + bool m_isLowResPrefetch; +}; + +class ScaleFilter : public OperationFilter { +public: + ScaleFilter(const TilePainter* painter, float scale) + : m_painter(painter) + , m_scale(scale) {} + virtual bool check(QueuedOperation* operation) + { + PaintTileOperation* op = static_cast(operation); + return ((op->painter() == m_painter) && (op->scale() != m_scale)); + } +private: + const TilePainter* m_painter; + float m_scale; +}; + + +class TilePainterFilter : public OperationFilter { +public: + TilePainterFilter(TilePainter* painter) : m_painter(painter) {} + virtual bool check(QueuedOperation* operation) + { + PaintTileOperation* op = static_cast(operation); + return op->painter() == m_painter; + } +private: + TilePainter* m_painter; +}; + +} + +#endif // PaintTileSetOperation_h diff --git a/Source/WebCore/platform/graphics/android/rendering/QueuedOperation.h b/Source/WebCore/platform/graphics/android/rendering/QueuedOperation.h new file mode 100644 index 0000000..f98efcd --- /dev/null +++ b/Source/WebCore/platform/graphics/android/rendering/QueuedOperation.h @@ -0,0 +1,47 @@ +/* + * Copyright 2010, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef QueuedOperation_h +#define QueuedOperation_h + +namespace WebCore { + +class QueuedOperation { +public: + virtual ~QueuedOperation() {} + virtual void run() = 0; + virtual bool operator==(const QueuedOperation* operation) = 0; + virtual int priority() = 0; +}; + +class OperationFilter { +public: + virtual ~OperationFilter() {} + virtual bool check(QueuedOperation* operation) = 0; +}; + +} + +#endif // QueuedOperation_h diff --git a/Source/WebCore/platform/graphics/android/rendering/RasterRenderer.cpp b/Source/WebCore/platform/graphics/android/rendering/RasterRenderer.cpp new file mode 100644 index 0000000..b880eef --- /dev/null +++ b/Source/WebCore/platform/graphics/android/rendering/RasterRenderer.cpp @@ -0,0 +1,115 @@ +/* + * Copyright 2011, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define LOG_TAG "RasterRenderer" +#define LOG_NDEBUG 1 + +#include "config.h" +#include "RasterRenderer.h" + +#if USE(ACCELERATED_COMPOSITING) + +#include "AndroidLog.h" +#include "GLUtils.h" +#include "SkBitmap.h" +#include "SkBitmapRef.h" +#include "SkCanvas.h" +#include "SkDevice.h" +#include "Tile.h" +#include "TilesManager.h" + +namespace WebCore { + +SkBitmap* RasterRenderer::g_bitmap = 0; + +RasterRenderer::RasterRenderer() : BaseRenderer(BaseRenderer::Raster) +{ +#ifdef DEBUG_COUNT + ClassTracker::instance()->increment("RasterRenderer"); +#endif + if (!g_bitmap) { + g_bitmap = new SkBitmap(); + g_bitmap->setConfig(SkBitmap::kARGB_8888_Config, + TilesManager::instance()->tileWidth(), + TilesManager::instance()->tileHeight()); + g_bitmap->allocPixels(); + } +} + +RasterRenderer::~RasterRenderer() +{ +#ifdef DEBUG_COUNT + ClassTracker::instance()->decrement("RasterRenderer"); +#endif +} + +void RasterRenderer::setupCanvas(const TileRenderInfo& renderInfo, SkCanvas* canvas) +{ + if (renderInfo.baseTile->isLayerTile()) { + g_bitmap->setIsOpaque(false); + g_bitmap->eraseARGB(0, 0, 0, 0); + } else { + Color defaultBackground = Color::white; + Color* background = renderInfo.tilePainter->background(); + if (!background) { + ALOGV("No background color for base layer!"); + background = &defaultBackground; + } + ALOGV("setupCanvas use background on Base Layer %x", background->rgb()); + g_bitmap->setIsOpaque(!background->hasAlpha()); + g_bitmap->eraseARGB(background->alpha(), background->red(), + background->green(), background->blue()); + } + + SkDevice* device = new SkDevice(*g_bitmap); + + canvas->setDevice(device); + + device->unref(); + + // If we have a partially painted bitmap + if (renderInfo.invalRect) { + SkRect clipRect = SkRect::MakeWH(renderInfo.invalRect->width(), + renderInfo.invalRect->height()); + // ensure the canvas origin is translated to the coordinates of our inval rect + canvas->clipRect(clipRect); + canvas->translate(-renderInfo.invalRect->fLeft, -renderInfo.invalRect->fTop); + } +} + +void RasterRenderer::renderingComplete(const TileRenderInfo& renderInfo, SkCanvas* canvas) +{ + const SkBitmap& bitmap = canvas->getDevice()->accessBitmap(false); + GLUtils::paintTextureWithBitmap(&renderInfo, bitmap); +} + +void RasterRenderer::checkForPureColor(TileRenderInfo& renderInfo, SkCanvas* canvas) +{ + renderInfo.isPureColor = GLUtils::isPureColorBitmap(*g_bitmap, renderInfo.pureColor); +} + +} // namespace WebCore + +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/android/rendering/RasterRenderer.h b/Source/WebCore/platform/graphics/android/rendering/RasterRenderer.h new file mode 100644 index 0000000..39e00f2 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/rendering/RasterRenderer.h @@ -0,0 +1,62 @@ +/* + * Copyright 2011, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef RasterRenderer_h +#define RasterRenderer_h + +#if USE(ACCELERATED_COMPOSITING) + +#include "BaseRenderer.h" +#include "SkBitmap.h" +#include "SkRect.h" + +class SkCanvas; +class SkDevice; + +namespace WebCore { + +/** + * + */ +class RasterRenderer : public BaseRenderer { +public: + RasterRenderer(); + ~RasterRenderer(); + +protected: + + virtual void setupCanvas(const TileRenderInfo& renderInfo, SkCanvas* canvas); + virtual void renderingComplete(const TileRenderInfo& renderInfo, SkCanvas* canvas); + virtual void checkForPureColor(TileRenderInfo& renderInfo, SkCanvas* canvas); + +private: + static SkBitmap* g_bitmap; + +}; + +} // namespace WebCore + +#endif // USE(ACCELERATED_COMPOSITING) +#endif // RasterRenderer_h diff --git a/Source/WebCore/platform/graphics/android/rendering/ShaderProgram.cpp b/Source/WebCore/platform/graphics/android/rendering/ShaderProgram.cpp new file mode 100644 index 0000000..a0d9e56 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/rendering/ShaderProgram.cpp @@ -0,0 +1,730 @@ +/* + * Copyright 2010, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define LOG_TAG "ShaderProgram" +#define LOG_NDEBUG 1 + +#include "config.h" +#include "ShaderProgram.h" + +#if USE(ACCELERATED_COMPOSITING) + +#include "AndroidLog.h" +#include "DrawQuadData.h" +#include "FloatPoint3D.h" +#include "GLUtils.h" +#include "TilesManager.h" + +#include +#include + +namespace WebCore { + +static const char gVertexShader[] = + "attribute vec4 vPosition;\n" + "uniform mat4 projectionMatrix;\n" + "varying vec2 v_texCoord;\n" + "void main() {\n" + " gl_Position = projectionMatrix * vPosition;\n" + " v_texCoord = vec2(vPosition);\n" + "}\n"; + +static const char gFragmentShader[] = + "precision mediump float;\n" + "varying vec2 v_texCoord; \n" + "uniform float alpha; \n" + "uniform sampler2D s_texture; \n" + "void main() {\n" + " gl_FragColor = texture2D(s_texture, v_texCoord); \n" + " gl_FragColor *= alpha; " + "}\n"; + +// We could pass the pureColor into either Vertex or Frag Shader. +// The reason we passed the color into the Vertex Shader is that some driver +// might create redundant copy when uniforms in fragment shader changed. +static const char gPureColorVertexShader[] = + "attribute vec4 vPosition;\n" + "uniform mat4 projectionMatrix;\n" + "uniform vec4 inputColor;\n" + "varying vec4 v_color;\n" + "void main() {\n" + " gl_Position = projectionMatrix * vPosition;\n" + " v_color = inputColor;\n" + "}\n"; + +static const char gPureColorFragmentShader[] = + "precision mediump float;\n" + "varying vec4 v_color;\n" + "void main() {\n" + " gl_FragColor = v_color;\n" + "}\n"; + +static const char gFragmentShaderInverted[] = + "precision mediump float;\n" + "varying vec2 v_texCoord; \n" + "uniform float alpha; \n" + "uniform float contrast; \n" + "uniform sampler2D s_texture; \n" + "void main() {\n" + " vec4 pixel = texture2D(s_texture, v_texCoord); \n" + " float a = pixel.a; \n" + " float color = a - (0.2989 * pixel.r + 0.5866 * pixel.g + 0.1145 * pixel.b);\n" + " color = ((color - a/2.0) * contrast) + a/2.0; \n" + " pixel.rgb = vec3(color, color, color); \n " + " gl_FragColor = pixel; \n" + " gl_FragColor *= alpha; \n" + "}\n"; + +static const char gVideoVertexShader[] = + "attribute vec4 vPosition;\n" + "uniform mat4 textureMatrix;\n" + "uniform mat4 projectionMatrix;\n" + "varying vec2 v_texCoord;\n" + "void main() {\n" + " gl_Position = projectionMatrix * vPosition;\n" + " v_texCoord = vec2(textureMatrix * vec4(vPosition.x, 1.0 - vPosition.y, 0.0, 1.0));\n" + "}\n"; + +static const char gVideoFragmentShader[] = + "#extension GL_OES_EGL_image_external : require\n" + "precision mediump float;\n" + "uniform samplerExternalOES s_yuvTexture;\n" + "varying vec2 v_texCoord;\n" + "void main() {\n" + " gl_FragColor = texture2D(s_yuvTexture, v_texCoord);\n" + "}\n"; + +static const char gSurfaceTextureOESFragmentShader[] = + "#extension GL_OES_EGL_image_external : require\n" + "precision mediump float;\n" + "varying vec2 v_texCoord; \n" + "uniform float alpha; \n" + "uniform samplerExternalOES s_texture; \n" + "void main() {\n" + " gl_FragColor = texture2D(s_texture, v_texCoord); \n" + " gl_FragColor *= alpha; " + "}\n"; + +static const char gSurfaceTextureOESFragmentShaderInverted[] = + "#extension GL_OES_EGL_image_external : require\n" + "precision mediump float;\n" + "varying vec2 v_texCoord; \n" + "uniform float alpha; \n" + "uniform float contrast; \n" + "uniform samplerExternalOES s_texture; \n" + "void main() {\n" + " vec4 pixel = texture2D(s_texture, v_texCoord); \n" + " float a = pixel.a; \n" + " float color = a - (0.2989 * pixel.r + 0.5866 * pixel.g + 0.1145 * pixel.b);\n" + " color = ((color - a/2.0) * contrast) + a/2.0; \n" + " pixel.rgb = vec3(color, color, color); \n " + " gl_FragColor = pixel; \n" + " gl_FragColor *= alpha; \n" + "}\n"; + +GLuint ShaderProgram::loadShader(GLenum shaderType, const char* pSource) +{ + GLuint shader = glCreateShader(shaderType); + if (shader) { + glShaderSource(shader, 1, &pSource, 0); + glCompileShader(shader); + GLint compiled = 0; + glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled); + if (!compiled) { + GLint infoLen = 0; + glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen); + if (infoLen) { + char* buf = (char*) malloc(infoLen); + if (buf) { + glGetShaderInfoLog(shader, infoLen, 0, buf); + ALOGE("could not compile shader %d:\n%s\n", shaderType, buf); + free(buf); + } + glDeleteShader(shader); + shader = 0; + } + } + } + return shader; +} + +GLint ShaderProgram::createProgram(const char* pVertexSource, const char* pFragmentSource) +{ + GLuint vertexShader = loadShader(GL_VERTEX_SHADER, pVertexSource); + if (!vertexShader) { + ALOGE("couldn't load the vertex shader!"); + return -1; + } + + GLuint pixelShader = loadShader(GL_FRAGMENT_SHADER, pFragmentSource); + if (!pixelShader) { + ALOGE("couldn't load the pixel shader!"); + return -1; + } + + GLuint program = glCreateProgram(); + if (program) { + glAttachShader(program, vertexShader); + GLUtils::checkGlError("glAttachShader vertex"); + glAttachShader(program, pixelShader); + GLUtils::checkGlError("glAttachShader pixel"); + glLinkProgram(program); + GLint linkStatus = GL_FALSE; + glGetProgramiv(program, GL_LINK_STATUS, &linkStatus); + if (linkStatus != GL_TRUE) { + GLint bufLength = 0; + glGetProgramiv(program, GL_INFO_LOG_LENGTH, &bufLength); + if (bufLength) { + char* buf = (char*) malloc(bufLength); + if (buf) { + glGetProgramInfoLog(program, bufLength, 0, buf); + ALOGE("could not link program:\n%s\n", buf); + free(buf); + } + } + glDeleteProgram(program); + program = -1; + } + } + + ShaderResource newResource(program, vertexShader, pixelShader); + m_resources.append(newResource); + return program; +} + +ShaderProgram::ShaderProgram() + : m_blendingEnabled(false) + , m_contrast(1) + , m_alphaLayer(false) + , m_currentScale(1.0f) + , m_needsInit(true) +{ +} + +void ShaderProgram::cleanupGLResources() +{ + for (unsigned int i = 0; i < m_resources.size(); i++) { + glDetachShader(m_resources[i].program, m_resources[i].vertexShader); + glDetachShader(m_resources[i].program, m_resources[i].fragmentShader); + glDeleteShader(m_resources[i].vertexShader); + glDeleteShader(m_resources[i].fragmentShader); + glDeleteProgram(m_resources[i].program); + } + glDeleteBuffers(1, m_textureBuffer); + + m_resources.clear(); + m_needsInit = true; + GLUtils::checkGlError("cleanupGLResources"); + + return; +} + +void ShaderProgram::initGLResources() +{ + // To detect whether or not resources for ShaderProgram allocated + // successfully, we clean up pre-existing errors here and will check for + // new errors at the end of this function. + GLUtils::checkGlError("before initGLResources"); + + GLint tex2DProgram = createProgram(gVertexShader, gFragmentShader); + GLint pureColorProgram = createProgram(gPureColorVertexShader, gPureColorFragmentShader); + GLint tex2DInvProgram = createProgram(gVertexShader, gFragmentShaderInverted); + GLint videoProgram = createProgram(gVideoVertexShader, gVideoFragmentShader); + GLint texOESProgram = + createProgram(gVertexShader, gSurfaceTextureOESFragmentShader); + GLint texOESInvProgram = + createProgram(gVertexShader, gSurfaceTextureOESFragmentShaderInverted); + + if (tex2DProgram == -1 + || pureColorProgram == -1 + || tex2DInvProgram == -1 + || videoProgram == -1 + || texOESProgram == -1 + || texOESInvProgram == -1) { + m_needsInit = true; + return; + } + + GLint pureColorPosition = glGetAttribLocation(pureColorProgram, "vPosition"); + GLint pureColorProjMtx = glGetUniformLocation(pureColorProgram, "projectionMatrix"); + GLint pureColorValue = glGetUniformLocation(pureColorProgram, "inputColor"); + m_handleArray[PureColor].init(-1, -1, pureColorPosition, pureColorProgram, + pureColorProjMtx, pureColorValue, -1, -1); + + GLint tex2DAlpha = glGetUniformLocation(tex2DProgram, "alpha"); + GLint tex2DPosition = glGetAttribLocation(tex2DProgram, "vPosition"); + GLint tex2DProjMtx = glGetUniformLocation(tex2DProgram, "projectionMatrix"); + GLint tex2DTexSampler = glGetUniformLocation(tex2DProgram, "s_texture"); + m_handleArray[Tex2D].init(tex2DAlpha, -1, tex2DPosition, tex2DProgram, + tex2DProjMtx, -1, tex2DTexSampler, -1); + + GLint tex2DInvAlpha = glGetUniformLocation(tex2DInvProgram, "alpha"); + GLint tex2DInvContrast = glGetUniformLocation(tex2DInvProgram, "contrast"); + GLint tex2DInvPosition = glGetAttribLocation(tex2DInvProgram, "vPosition"); + GLint tex2DInvProjMtx = glGetUniformLocation(tex2DInvProgram, "projectionMatrix"); + GLint tex2DInvTexSampler = glGetUniformLocation(tex2DInvProgram, "s_texture"); + m_handleArray[Tex2DInv].init(tex2DInvAlpha, tex2DInvContrast, + tex2DInvPosition, tex2DInvProgram, + tex2DInvProjMtx, -1, + tex2DInvTexSampler, -1); + + GLint texOESAlpha = glGetUniformLocation(texOESProgram, "alpha"); + GLint texOESPosition = glGetAttribLocation(texOESProgram, "vPosition"); + GLint texOESProjMtx = glGetUniformLocation(texOESProgram, "projectionMatrix"); + GLint texOESTexSampler = glGetUniformLocation(texOESProgram, "s_texture"); + m_handleArray[TexOES].init(texOESAlpha, -1, texOESPosition, texOESProgram, + texOESProjMtx, -1, texOESTexSampler, -1); + + GLint texOESInvAlpha = glGetUniformLocation(texOESInvProgram, "alpha"); + GLint texOESInvContrast = glGetUniformLocation(texOESInvProgram, "contrast"); + GLint texOESInvPosition = glGetAttribLocation(texOESInvProgram, "vPosition"); + GLint texOESInvProjMtx = glGetUniformLocation(texOESInvProgram, "projectionMatrix"); + GLint texOESInvTexSampler = glGetUniformLocation(texOESInvProgram, "s_texture"); + m_handleArray[TexOESInv].init(texOESInvAlpha, texOESInvContrast, + texOESInvPosition, texOESInvProgram, + texOESInvProjMtx, -1, + texOESInvTexSampler, -1); + + GLint videoPosition = glGetAttribLocation(videoProgram, "vPosition"); + GLint videoProjMtx = glGetUniformLocation(videoProgram, "projectionMatrix"); + GLint videoTexSampler = glGetUniformLocation(videoProgram, "s_yuvTexture"); + GLint videoTexMtx = glGetUniformLocation(videoProgram, "textureMatrix"); + m_handleArray[Video].init(-1, -1, videoPosition, videoProgram, + videoProjMtx, -1, videoTexSampler, + videoTexMtx); + + const GLfloat coord[] = { + 0.0f, 0.0f, // C + 1.0f, 0.0f, // D + 0.0f, 1.0f, // A + 1.0f, 1.0f // B + }; + + glGenBuffers(1, m_textureBuffer); + glBindBuffer(GL_ARRAY_BUFFER, m_textureBuffer[0]); + glBufferData(GL_ARRAY_BUFFER, 2 * 4 * sizeof(GLfloat), coord, GL_STATIC_DRAW); + + TransformationMatrix matrix; + // Map x,y from (0,1) to (-1, 1) + matrix.scale3d(2, 2, 1); + matrix.translate3d(-0.5, -0.5, 0); + GLUtils::toGLMatrix(m_transferProjMtx, matrix); + + m_needsInit = GLUtils::checkGlError("initGLResources"); + return; +} + +void ShaderProgram::resetBlending() +{ + glDisable(GL_BLEND); + glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + glBlendEquation(GL_FUNC_ADD); + m_blendingEnabled = false; +} + +void ShaderProgram::setBlendingState(bool enableBlending) +{ + if (enableBlending == m_blendingEnabled) + return; + + if (enableBlending) + glEnable(GL_BLEND); + else + glDisable(GL_BLEND); + + m_blendingEnabled = enableBlending; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// Drawing +///////////////////////////////////////////////////////////////////////////////////////// + +void ShaderProgram::setupDrawing(const IntRect& viewRect, const SkRect& visibleRect, + const IntRect& webViewRect, int titleBarHeight, + const IntRect& screenClip, float scale) +{ + m_webViewRect = webViewRect; + m_titleBarHeight = titleBarHeight; + + //// viewport //// + TransformationMatrix ortho; + GLUtils::setOrthographicMatrix(ortho, visibleRect.fLeft, visibleRect.fTop, + visibleRect.fRight, visibleRect.fBottom, -1000, 1000); + // In most case , visibleRect / viewRect * scale should 1.0, but for the + // translation case, the scale factor can be 1 but visibleRect is smaller + // than viewRect, we need to tune in this factor to make sure we scale them + // right. Conceptually, that means, no matter how animation affects the + // visibleRect, the scaling should respect the viewRect if zoomScale is 1.0. + // Note that at TiledPage, we already scale the tile size inversely to make + // zooming animation right. + float orthoScaleX = scale * visibleRect.width() / viewRect.width(); + float orthoScaleY = scale * visibleRect.height() / viewRect.height(); + + TransformationMatrix orthoScale; + orthoScale.scale3d(orthoScaleX, orthoScaleY, 1.0); + + m_projectionMatrix = ortho * orthoScale; + m_viewport = visibleRect; + m_currentScale = scale; + + + //// viewRect //// + m_viewRect = viewRect; + + // We do clipping using glScissor, which needs to take + // coordinates in screen space. The following matrix transform + // content coordinates in screen coordinates. + TransformationMatrix viewTranslate; + viewTranslate.translate(1.0, 1.0); + + TransformationMatrix viewScale; + viewScale.scale3d(m_viewRect.width() * 0.5f, m_viewRect.height() * 0.5f, 1); + + m_documentToScreenMatrix = viewScale * viewTranslate * m_projectionMatrix; + + viewTranslate.scale3d(1, -1, 1); + m_documentToInvScreenMatrix = viewScale * viewTranslate * m_projectionMatrix; + + IntRect rect(0, 0, m_webViewRect.width(), m_webViewRect.height()); + m_documentViewport = m_documentToScreenMatrix.inverse().mapRect(rect); + + + //// clipping //// + IntRect mclip = screenClip; + + // the clip from frameworks is in full screen coordinates + mclip.setY(screenClip.y() - m_webViewRect.y() - m_titleBarHeight); + FloatRect tclip = convertInvScreenCoordToScreenCoord(mclip); + m_screenClip.setLocation(IntPoint(tclip.x(), tclip.y())); + // use ceilf to handle view -> doc -> view coord rounding errors + m_screenClip.setSize(IntSize(ceilf(tclip.width()), ceilf(tclip.height()))); + + resetBlending(); +} + +// Calculate the right color value sent into the shader considering the (0,1) +// clamp and alpha blending. +Color ShaderProgram::shaderColor(Color pureColor, float opacity) +{ + float r = pureColor.red() / 255.0; + float g = pureColor.green() / 255.0; + float b = pureColor.blue() / 255.0; + float a = pureColor.alpha() / 255.0; + + if (TilesManager::instance()->invertedScreen()) { + float intensity = a - (0.2989 * r + 0.5866 * g + 0.1145 * b); + intensity = ((intensity - a / 2.0) * m_contrast) + a / 2.0; + intensity *= opacity; + return Color(intensity, intensity, intensity, a * opacity); + } + return Color(r * opacity, g * opacity, b * opacity, a * opacity); +} + +// For shaders using texture, it is easy to get the type from the textureTarget. +ShaderType ShaderProgram::getTextureShaderType(GLenum textureTarget) +{ + ShaderType type = UndefinedShader; + if (textureTarget == GL_TEXTURE_2D) { + if (!TilesManager::instance()->invertedScreen()) + type = Tex2D; + else { + // With the new GPU texture upload path, we do not use an FBO + // to blit the texture we receive from the TexturesGenerator thread. + // To implement inverted rendering, we thus have to do the rendering + // live, by using a different shader. + type = Tex2DInv; + } + } else if (textureTarget == GL_TEXTURE_EXTERNAL_OES) { + if (!TilesManager::instance()->invertedScreen()) + type = TexOES; + else + type = TexOESInv; + } + return type; +} + +// This function transform a clip rect extracted from the current layer +// into a clip rect in screen coordinates -- used by the clipping rects +FloatRect ShaderProgram::rectInScreenCoord(const TransformationMatrix& drawMatrix, const IntSize& size) +{ + FloatRect srect(0, 0, size.width(), size.height()); + TransformationMatrix renderMatrix = m_documentToScreenMatrix * drawMatrix; + return renderMatrix.mapRect(srect); +} + +// used by the partial screen invals +FloatRect ShaderProgram::rectInInvScreenCoord(const TransformationMatrix& drawMatrix, const IntSize& size) +{ + FloatRect srect(0, 0, size.width(), size.height()); + TransformationMatrix renderMatrix = m_documentToInvScreenMatrix * drawMatrix; + return renderMatrix.mapRect(srect); +} + +FloatRect ShaderProgram::rectInInvScreenCoord(const FloatRect& rect) +{ + return m_documentToInvScreenMatrix.mapRect(rect); +} + +FloatRect ShaderProgram::rectInScreenCoord(const FloatRect& rect) +{ + return m_documentToScreenMatrix.mapRect(rect); +} + +FloatRect ShaderProgram::convertScreenCoordToDocumentCoord(const FloatRect& rect) +{ + return m_documentToScreenMatrix.inverse().mapRect(rect); +} + +FloatRect ShaderProgram::convertInvScreenCoordToScreenCoord(const FloatRect& rect) +{ + FloatRect documentRect = m_documentToInvScreenMatrix.inverse().mapRect(rect); + return rectInScreenCoord(documentRect); +} + +FloatRect ShaderProgram::convertScreenCoordToInvScreenCoord(const FloatRect& rect) +{ + FloatRect documentRect = m_documentToScreenMatrix.inverse().mapRect(rect); + return rectInInvScreenCoord(documentRect); +} + +// clip is in screen coordinates +void ShaderProgram::clip(const FloatRect& clip) +{ + if (clip == m_clipRect) + return; + + ALOGV("--clipping rect %f %f, %f x %f", + clip.x(), clip.y(), clip.width(), clip.height()); + + // we should only call glScissor in this function, so that we can easily + // track the current clipping rect. + + IntRect screenClip(clip.x(), + clip.y(), + clip.width(), clip.height()); + + if (!m_screenClip.isEmpty()) + screenClip.intersect(m_screenClip); + + screenClip.setY(screenClip.y() + m_viewRect.y()); + if (screenClip.x() < 0) { + int w = screenClip.width(); + w += screenClip.x(); + screenClip.setX(0); + screenClip.setWidth(w); + } + if (screenClip.y() < 0) { + int h = screenClip.height(); + h += screenClip.y(); + screenClip.setY(0); + screenClip.setHeight(h); + } + + glScissor(screenClip.x(), screenClip.y(), screenClip.width(), screenClip.height()); + + m_clipRect = clip; +} + +IntRect ShaderProgram::clippedRectWithViewport(const IntRect& rect, int margin) +{ + IntRect viewport(m_viewport.fLeft - margin, m_viewport.fTop - margin, + m_viewport.width() + margin, m_viewport.height() + margin); + viewport.intersect(rect); + return viewport; +} + +float ShaderProgram::zValue(const TransformationMatrix& drawMatrix, float w, float h) +{ + TransformationMatrix modifiedDrawMatrix = drawMatrix; + modifiedDrawMatrix.scale3d(w, h, 1); + TransformationMatrix renderMatrix = m_projectionMatrix * modifiedDrawMatrix; + FloatPoint3D point(0.5, 0.5, 0.0); + FloatPoint3D result = renderMatrix.mapPoint(point); + return result.z(); +} + +void ShaderProgram::drawQuadInternal(ShaderType type, const GLfloat* matrix, + int textureId, float opacity, + GLenum textureTarget, GLenum filter, + const Color& pureColor) +{ + glUseProgram(m_handleArray[type].programHandle); + glUniformMatrix4fv(m_handleArray[type].projMtxHandle, 1, GL_FALSE, matrix); + + if (type != PureColor) { + glActiveTexture(GL_TEXTURE0); + glUniform1i(m_handleArray[type].texSamplerHandle, 0); + glBindTexture(textureTarget, textureId); + glTexParameteri(textureTarget, GL_TEXTURE_MIN_FILTER, filter); + glTexParameteri(textureTarget, GL_TEXTURE_MAG_FILTER, filter); + glUniform1f(m_handleArray[type].alphaHandle, opacity); + + GLint contrastHandle = m_handleArray[type].contrastHandle; + if (contrastHandle != -1) + glUniform1f(contrastHandle, m_contrast); + } else { + glUniform4f(m_handleArray[type].pureColorHandle, + pureColor.red() / 255.0, pureColor.green() / 255.0, + pureColor.blue() / 255.0, pureColor.alpha() / 255.0); + } + + GLint positionHandle = m_handleArray[type].positionHandle; + glBindBuffer(GL_ARRAY_BUFFER, m_textureBuffer[0]); + glEnableVertexAttribArray(positionHandle); + glVertexAttribPointer(positionHandle, 2, GL_FLOAT, GL_FALSE, 0, 0); + + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); +} + +// Calculate the matrix given the geometry. +GLfloat* ShaderProgram::getProjectionMatrix(const DrawQuadData* data) +{ + DrawQuadType type = data->type(); + const TransformationMatrix* matrix = data->drawMatrix(); + const SkRect* geometry = data->geometry(); + if (type == Blit) + return m_transferProjMtx; + TransformationMatrix modifiedDrawMatrix; + if (type == LayerQuad) + modifiedDrawMatrix = *matrix; + // move the drawing depending on where the texture is on the layer + modifiedDrawMatrix.translate(geometry->fLeft, geometry->fTop); + modifiedDrawMatrix.scale3d(geometry->width(), geometry->height(), 1); + + TransformationMatrix renderMatrix; + if (!m_alphaLayer) + renderMatrix = m_projectionMatrix * m_repositionMatrix + * m_webViewMatrix * modifiedDrawMatrix; + else + renderMatrix = m_projectionMatrix * modifiedDrawMatrix; + + GLUtils::toGLMatrix(m_tileProjMatrix, renderMatrix); + return m_tileProjMatrix; +} + +void ShaderProgram::drawQuad(const DrawQuadData* data) +{ + GLfloat* matrix = getProjectionMatrix(data); + + float opacity = data->opacity(); + bool forceBlending = data->forceBlending(); + bool enableBlending = forceBlending || opacity < 1.0; + + ShaderType shaderType = UndefinedShader; + int textureId = 0; + GLint textureFilter = 0; + GLenum textureTarget = 0; + + Color quadColor = data->quadColor(); + if (data->pureColor()) { + shaderType = PureColor; + quadColor = shaderColor(quadColor, opacity); + enableBlending = enableBlending || quadColor.hasAlpha(); + if (!quadColor.alpha() && enableBlending) + return; + } else { + textureId = data->textureId(); + textureFilter = data->textureFilter(); + textureTarget = data->textureTarget(); + shaderType = getTextureShaderType(textureTarget); + } + setBlendingState(enableBlending); + drawQuadInternal(shaderType, matrix, textureId, opacity, + textureTarget, textureFilter, quadColor); +} + +void ShaderProgram::drawVideoLayerQuad(const TransformationMatrix& drawMatrix, + float* textureMatrix, SkRect& geometry, + int textureId) +{ + // switch to our custom yuv video rendering program + glUseProgram(m_handleArray[Video].programHandle); + + TransformationMatrix modifiedDrawMatrix = drawMatrix; + modifiedDrawMatrix.translate(geometry.fLeft, geometry.fTop); + modifiedDrawMatrix.scale3d(geometry.width(), geometry.height(), 1); + TransformationMatrix renderMatrix = m_projectionMatrix * modifiedDrawMatrix; + + GLfloat projectionMatrix[16]; + GLUtils::toGLMatrix(projectionMatrix, renderMatrix); + glUniformMatrix4fv(m_handleArray[Video].projMtxHandle, 1, GL_FALSE, + projectionMatrix); + glUniformMatrix4fv(m_handleArray[Video].videoMtxHandle, 1, GL_FALSE, + textureMatrix); + + glActiveTexture(GL_TEXTURE0); + glUniform1i(m_handleArray[Video].texSamplerHandle, 0); + glBindTexture(GL_TEXTURE_EXTERNAL_OES, textureId); + + GLint videoPosition = m_handleArray[Video].positionHandle; + glBindBuffer(GL_ARRAY_BUFFER, m_textureBuffer[0]); + glEnableVertexAttribArray(videoPosition); + glVertexAttribPointer(videoPosition, 2, GL_FLOAT, GL_FALSE, 0, 0); + + setBlendingState(false); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); +} + +void ShaderProgram::setWebViewMatrix(const float* matrix, bool alphaLayer) +{ + GLUtils::convertToTransformationMatrix(matrix, m_webViewMatrix); + m_alphaLayer = alphaLayer; +} + +void ShaderProgram::calculateAnimationDelta() +{ + // The matrix contains the scrolling info, so this rect is starting from + // the m_viewport. + // So we just need to map the webview's visible rect using the matrix, + // calculate the difference b/t transformed rect and the webViewRect, + // then we can get the delta x , y caused by the animation. + // Note that the Y is for reporting back to GL viewport, so it is inverted. + // When it is alpha animation, then we rely on the framework implementation + // such that there is no matrix applied in native webkit. + if (!m_alphaLayer) { + FloatRect rect(m_viewport.fLeft * m_currentScale, + m_viewport.fTop * m_currentScale, + m_webViewRect.width(), + m_webViewRect.height()); + rect = m_webViewMatrix.mapRect(rect); + m_animationDelta.setX(rect.x() - m_webViewRect.x() ); + m_animationDelta.setY(rect.y() + rect.height() - m_webViewRect.y() + - m_webViewRect.height() - m_titleBarHeight); + + m_repositionMatrix.makeIdentity(); + m_repositionMatrix.translate3d(-m_webViewRect.x(), -m_webViewRect.y() - m_titleBarHeight, 0); + m_repositionMatrix.translate3d(m_viewport.fLeft * m_currentScale, m_viewport.fTop * m_currentScale, 0); + m_repositionMatrix.translate3d(-m_animationDelta.x(), -m_animationDelta.y(), 0); + } else { + m_animationDelta.setX(0); + m_animationDelta.setY(0); + m_repositionMatrix.makeIdentity(); + } + +} + +} // namespace WebCore + +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/android/rendering/ShaderProgram.h b/Source/WebCore/platform/graphics/android/rendering/ShaderProgram.h new file mode 100644 index 0000000..b233f2b --- /dev/null +++ b/Source/WebCore/platform/graphics/android/rendering/ShaderProgram.h @@ -0,0 +1,234 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ShaderProgram_h +#define ShaderProgram_h + +#if USE(ACCELERATED_COMPOSITING) + +#include "Color.h" +#include "FloatRect.h" +#include "IntRect.h" +#include "SkRect.h" +#include "TransformationMatrix.h" +#include + +#define MAX_CONTRAST 5 + +namespace WebCore { + +class DrawQuadData; +class PureColorQuadData; +class TextureQuadData; + +enum ShaderType { + UndefinedShader = -1, + PureColor, + Tex2D, + Tex2DInv, + TexOES, + TexOESInv, + Video, + // When growing this enum list, make sure to insert before the + // MaxShaderNumber and init the m_handleArray accordingly. + MaxShaderNumber +}; + +struct ShaderHandles { + ShaderHandles() + : alphaHandle(-1) + , contrastHandle(-1) + , positionHandle(-1) + , programHandle(-1) + , projMtxHandle(-1) + , pureColorHandle(-1) + , texSamplerHandle(-1) + , videoMtxHandle(-1) + { + } + + void init(GLint alphaHdl, GLint contrastHdl, GLint posHdl, GLint pgmHdl, + GLint projMtxHdl, GLint colorHdl, GLint texSamplerHdl, + GLint videoMtxHdl) + { + alphaHandle = alphaHdl; + contrastHandle = contrastHdl; + positionHandle = posHdl; + programHandle = pgmHdl; + projMtxHandle = projMtxHdl; + pureColorHandle = colorHdl; + texSamplerHandle = texSamplerHdl; + videoMtxHandle = videoMtxHdl; + } + + GLint alphaHandle; + GLint contrastHandle; + GLint positionHandle; + GLint programHandle; + GLint projMtxHandle; + GLint pureColorHandle; + GLint texSamplerHandle; + GLint videoMtxHandle; +}; + +struct ShaderResource { + ShaderResource() + : program(-1) + , vertexShader(-1) + , fragmentShader(-1) + { + }; + + ShaderResource(GLuint prog, GLuint vertex, GLuint fragment) + : program(prog) + , vertexShader(vertex) + , fragmentShader(fragment) + { + }; + + GLuint program; + GLuint vertexShader; + GLuint fragmentShader; +}; + +class ShaderProgram { +public: + ShaderProgram(); + void initGLResources(); + void cleanupGLResources(); + // Drawing + void setupDrawing(const IntRect& viewRect, const SkRect& visibleRect, + const IntRect& webViewRect, int titleBarHeight, + const IntRect& screenClip, float scale); + float zValue(const TransformationMatrix& drawMatrix, float w, float h); + + // For drawQuad and drawLayerQuad, they can handle 3 cases for now: + // 1) textureTarget == GL_TEXTURE_2D + // Normal texture in GL_TEXTURE_2D target. + // 2) textureTarget == GL_TEXTURE_EXTERNAL_OES + // Surface texture in GL_TEXTURE_EXTERNAL_OES target. + // 3) textureId == 0 + // No texture needed, just a pureColor quad. + void drawQuad(const DrawQuadData* data); + void drawVideoLayerQuad(const TransformationMatrix& drawMatrix, + float* textureMatrix, SkRect& geometry, int textureId); + FloatRect rectInScreenCoord(const TransformationMatrix& drawMatrix, + const IntSize& size); + FloatRect rectInInvScreenCoord(const TransformationMatrix& drawMatrix, + const IntSize& size); + + FloatRect rectInInvScreenCoord(const FloatRect& rect); + FloatRect rectInScreenCoord(const FloatRect& rect); + FloatRect convertScreenCoordToDocumentCoord(const FloatRect& rect); + FloatRect convertInvScreenCoordToScreenCoord(const FloatRect& rect); + FloatRect convertScreenCoordToInvScreenCoord(const FloatRect& rect); + + void clip(const FloatRect& rect); + IntRect clippedRectWithViewport(const IntRect& rect, int margin = 0); + FloatRect documentViewport() { return m_documentViewport; } + + float contrast() { return m_contrast; } + void setContrast(float c) + { + float contrast = c; + if (contrast < 0) + contrast = 0; + if (contrast > MAX_CONTRAST) + contrast = MAX_CONTRAST; + m_contrast = contrast; + } + void setWebViewMatrix(const float* matrix, bool alphaLayer); + + // This delta is the delta from the layout pos and the current animation pos. + // Basically, in terms of layout, the webview is still in the original layout + // pos, as without animation. Such that the viewport and visible rect etc are + // still in that pos, too, except the clipping info. + // Our rendering approach is after applying all the matrix, webView is + // rendered as if it was at the original layout pos, but then offset the + // glViewport to match the animation. + void calculateAnimationDelta(); + int getAnimationDeltaX() { return m_animationDelta.x(); } + int getAnimationDeltaY() { return m_animationDelta.y(); } + bool needsInit() { return m_needsInit; } + +private: + GLuint loadShader(GLenum shaderType, const char* pSource); + GLint createProgram(const char* vertexSource, const char* fragmentSource); + GLfloat* getProjectionMatrix(const DrawQuadData* data); + void setBlendingState(bool enableBlending); + void drawQuadInternal(ShaderType type, const GLfloat* matrix, int textureId, + float opacity, GLenum textureTarget, GLenum filter, + const Color& pureColor); + Color shaderColor(Color pureColor, float opacity); + ShaderType getTextureShaderType(GLenum textureTarget); + void resetBlending(); + + bool m_blendingEnabled; + + TransformationMatrix m_projectionMatrix; + GLuint m_textureBuffer[1]; + + TransformationMatrix m_documentToScreenMatrix; + TransformationMatrix m_documentToInvScreenMatrix; + SkRect m_viewport; + IntRect m_viewRect; + FloatRect m_clipRect; + IntRect m_screenClip; + int m_titleBarHeight; + IntRect m_webViewRect; + + FloatRect m_documentViewport; + + float m_contrast; + + bool m_alphaLayer; + TransformationMatrix m_webViewMatrix; + float m_currentScale; + + // After the webViewTranform, we need to reposition the rect to match our viewport. + // Basically, the webViewTransformMatrix should apply on the screen resolution. + // So we start by doing the scale and translate to get each tile into screen coordinates. + // After applying the webViewTransformMatrix, b/c the way it currently set up + // for scroll and titlebar, we need to offset both of them. + // Finally, map everything back to (-1, 1) by using the m_projectionMatrix. + // TODO: Given that m_webViewMatrix contains most of the tranformation + // information, we should be able to get rid of some parameter we got from + // Java side and simplify our code. + TransformationMatrix m_repositionMatrix; + IntPoint m_animationDelta; + + // Put all the uniform location (handle) info into an array, and group them + // by the shader's type, this can help to clean up the interface. + // TODO: use the type and data comparison to skip GL call if possible. + ShaderHandles m_handleArray[MaxShaderNumber]; + + // If there is any GL error happens such that the Shaders are not initialized + // successfully at the first time, then we need to init again when we draw. + bool m_needsInit; + + // For transfer queue blitting, we need a special matrix map from (0,1) to + // (-1,1) + GLfloat m_transferProjMtx[16]; + + GLfloat m_tileProjMatrix[16]; + + Vector m_resources; +}; + +} // namespace WebCore + +#endif // USE(ACCELERATED_COMPOSITING) +#endif // ShaderProgram_h diff --git a/Source/WebCore/platform/graphics/android/rendering/Surface.cpp b/Source/WebCore/platform/graphics/android/rendering/Surface.cpp new file mode 100644 index 0000000..3ed3aad --- /dev/null +++ b/Source/WebCore/platform/graphics/android/rendering/Surface.cpp @@ -0,0 +1,346 @@ +/* + * Copyright 2012, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define LOG_TAG "Surface" +#define LOG_NDEBUG 1 + +#include "config.h" +#include "Surface.h" + +#include "AndroidLog.h" +#include "ClassTracker.h" +#include "LayerAndroid.h" +#include "GLWebViewState.h" +#include "SkCanvas.h" +#include "SurfaceBacking.h" +#include "TilesManager.h" + +// Surfaces with an area larger than 2048*2048 should never be unclipped +#define MAX_UNCLIPPED_AREA 4194304 + +namespace WebCore { + +Surface::Surface() + : m_surfaceBacking(0) + , m_needsTexture(false) + , m_hasText(false) +{ +#ifdef DEBUG_COUNT + ClassTracker::instance()->increment("Surface"); +#endif +} + +Surface::~Surface() +{ + for (unsigned int i = 0; i < m_layers.size(); i++) + SkSafeUnref(m_layers[i]); + if (m_surfaceBacking) + SkSafeUnref(m_surfaceBacking); +#ifdef DEBUG_COUNT + ClassTracker::instance()->decrement("Surface"); +#endif +} + +bool Surface::tryUpdateSurface(Surface* oldSurface) +{ + if (!needsTexture() || !oldSurface->needsTexture()) + return false; + + // merge surfaces based on first layer ID + if (getFirstLayer()->uniqueId() != oldSurface->getFirstLayer()->uniqueId()) + return false; + + m_surfaceBacking = oldSurface->m_surfaceBacking; + SkSafeRef(m_surfaceBacking); + + ALOGV("%p taking old SurfBack %p from surface %p, nt %d", + this, m_surfaceBacking, oldSurface, oldSurface->needsTexture()); + + if (!m_surfaceBacking) { + // no SurfBack to inval, so don't worry about it. + return true; + } + + if (singleLayer() && oldSurface->singleLayer()) { + // both are single matching layers, simply apply inval + SkRegion* layerInval = getFirstLayer()->getInvalRegion(); + m_surfaceBacking->markAsDirty(*layerInval); + } else { + SkRegion invalRegion; + bool fullInval = m_layers.size() != oldSurface->m_layers.size(); + if (!fullInval) { + for (unsigned int i = 0; i < m_layers.size(); i++) { + if (m_layers[i]->uniqueId() != oldSurface->m_layers[i]->uniqueId()) { + // layer list has changed, fully invalidate + // TODO: partially invalidate based on layer size/position + fullInval = true; + break; + } else if (!m_layers[i]->getInvalRegion()->isEmpty()) { + // merge layer inval - translate the layer's inval region into surface coordinates + SkPoint pos = m_layers[i]->getPosition(); + m_layers[i]->getInvalRegion()->translate(pos.fX, pos.fY); + invalRegion.op(*(m_layers[i]->getInvalRegion()), SkRegion::kUnion_Op); + break; + } + } + } + + if (fullInval) + invalRegion.setRect(-1e8, -1e8, 2e8, 2e8); + + m_surfaceBacking->markAsDirty(invalRegion); + } + return true; +} + +void Surface::addLayer(LayerAndroid* layer, const TransformationMatrix& transform) +{ + m_layers.append(layer); + SkSafeRef(layer); + + m_needsTexture |= layer->needsTexture(); + m_hasText |= layer->hasText(); + + // calculate area size for comparison later + IntRect rect = layer->unclippedArea(); + SkPoint pos = layer->getPosition(); + rect.setLocation(IntPoint(pos.fX, pos.fY)); + + if (layer->needsTexture()) { + if (m_unclippedArea.isEmpty()) { + m_drawTransform = transform; + m_drawTransform.translate3d(-pos.fX, -pos.fY, 0); + m_unclippedArea = rect; + } else + m_unclippedArea.unite(rect); + ALOGV("Surf %p adding LA %p, size %d, %d %dx%d, now Surf size %d,%d %dx%d", + this, layer, rect.x(), rect.y(), rect.width(), rect.height(), + m_unclippedArea.x(), m_unclippedArea.y(), + m_unclippedArea.width(), m_unclippedArea.height()); + } +} + +IntRect Surface::visibleArea() +{ + if (singleLayer()) + return getFirstLayer()->visibleArea(); + + IntRect rect = m_unclippedArea; + + // clip with the viewport in documents coordinate + IntRect documentViewport(TilesManager::instance()->shader()->documentViewport()); + rect.intersect(documentViewport); + + // TODO: handle recursive layer clip + + return rect; +} + +IntRect Surface::unclippedArea() +{ + if (singleLayer()) + return getFirstLayer()->unclippedArea(); + return m_unclippedArea; +} + +bool Surface::useAggressiveRendering() +{ + // When the background is semi-opaque, 0 < alpha < 255, we had to turn off + // low res to avoid artifacts from double drawing. + // TODO: avoid double drawing for low res tiles. + return isBase() + && (!m_background.alpha() + || !m_background.hasAlpha()); +} + +void Surface::prepareGL(bool layerTilesDisabled) +{ + bool tilesDisabled = layerTilesDisabled && !isBase(); + if (!m_surfaceBacking) { + ALOGV("prepareGL on Surf %p, no SurfBack, needsTexture? %d", + this, m_surfaceBacking, needsTexture()); + + if (!needsTexture()) + return; + + m_surfaceBacking = new SurfaceBacking(isBase()); + } + + if (tilesDisabled) { + m_surfaceBacking->discardTextures(); + } else { + bool allowZoom = hasText(); // only allow for scale > 1 if painting vectors + IntRect prepareArea = computePrepareArea(); + IntRect fullArea = unclippedArea(); + + ALOGV("prepareGL on Surf %p with SurfBack %p, %d layers", + this, m_surfaceBacking, m_layers.size()); + + m_surfaceBacking->prepareGL(getFirstLayer()->state(), allowZoom, + prepareArea, fullArea, + this, useAggressiveRendering()); + } +} + +bool Surface::drawGL(bool layerTilesDisabled) +{ + bool tilesDisabled = layerTilesDisabled && !isBase(); + if (!getFirstLayer()->visible()) + return false; + + if (!isBase()) { + // TODO: why are clipping regions wrong for base layer? + FloatRect drawClip = getFirstLayer()->drawClip(); + FloatRect clippingRect = TilesManager::instance()->shader()->rectInScreenCoord(drawClip); + TilesManager::instance()->shader()->clip(clippingRect); + } + + bool askRedraw = false; + if (m_surfaceBacking && !tilesDisabled) { + ALOGV("drawGL on Surf %p with SurfBack %p", this, m_surfaceBacking); + + // TODO: why this visibleArea is different from visibleRect at zooming for base? + IntRect drawArea = visibleArea(); + m_surfaceBacking->drawGL(drawArea, opacity(), drawTransform(), + useAggressiveRendering(), background()); + } + + // draw member layers (draws image textures, glextras) + for (unsigned int i = 0; i < m_layers.size(); i++) + askRedraw |= m_layers[i]->drawGL(tilesDisabled); + + return askRedraw; +} + +void Surface::swapTiles() +{ + if (!m_surfaceBacking) + return; + + m_surfaceBacking->swapTiles(); +} + +bool Surface::isReady() +{ + if (!m_surfaceBacking) + return true; + + return m_surfaceBacking->isReady(); +} + +IntRect Surface::computePrepareArea() { + IntRect area; + + if (!getFirstLayer()->contentIsScrollable() + && !isBase() + && getFirstLayer()->state()->layersRenderingMode() == GLWebViewState::kAllTextures) { + + area = unclippedArea(); + + double total = ((double) area.width()) * ((double) area.height()); + if (total > MAX_UNCLIPPED_AREA) + area = visibleArea(); + } else { + area = visibleArea(); + } + + return area; +} + +void Surface::computeTexturesAmount(TexturesResult* result) +{ + if (!m_surfaceBacking || isBase()) + return; + + m_surfaceBacking->computeTexturesAmount(result, getFirstLayer()); +} + +bool Surface::isBase() +{ + // base layer surface + // - doesn't use layer tiles (disables blending, doesn't compute textures amount) + // - ignores clip rects + // - only prepares clippedArea + return getFirstLayer()->subclassType() == LayerAndroid::BaseLayer; +} + +bool Surface::paint(Tile* tile, SkCanvas* canvas) +{ + if (singleLayer()) { + getFirstLayer()->contentDraw(canvas, Layer::UnmergedLayers); + + // TODO: double buffer by disabling SurfaceCollection swaps and position + // updates until painting complete + + // In single surface mode, draw layer content onto the base layer + if (isBase() + && getFirstLayer()->countChildren() + && getFirstLayer()->state()->layersRenderingMode() > GLWebViewState::kClippedTextures) + getFirstLayer()->getChild(0)->drawCanvas(canvas, true, Layer::FlattenedLayers); + } else { + SkAutoCanvasRestore acr(canvas, true); + SkMatrix matrix; + GLUtils::toSkMatrix(matrix, m_drawTransform); + + SkMatrix inverse; + inverse.reset(); + matrix.invert(&inverse); + + SkMatrix canvasMatrix = canvas->getTotalMatrix(); + inverse.postConcat(canvasMatrix); + canvas->setMatrix(inverse); + + for (unsigned int i=0; idrawCanvas(canvas, false, Layer::MergedLayers); + } + return true; +} + +float Surface::opacity() +{ + if (singleLayer()) + return getFirstLayer()->drawOpacity(); + return 1.0; +} + +Color* Surface::background() +{ + if (!isBase() || !m_background.isValid()) + return 0; + return &m_background; +} + +const TransformationMatrix* Surface::drawTransform() +{ + // single layer surfaces query the layer's draw transform, while multi-layer + // surfaces copy the draw transform once, during initialization + // TODO: support fixed multi-layer surfaces by querying the changing drawTransform + if (singleLayer()) + return getFirstLayer()->drawTransform(); + + return &m_drawTransform; +} + +} // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/rendering/Surface.h b/Source/WebCore/platform/graphics/android/rendering/Surface.h new file mode 100644 index 0000000..27c997e --- /dev/null +++ b/Source/WebCore/platform/graphics/android/rendering/Surface.h @@ -0,0 +1,115 @@ +/* + * Copyright 2012, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef Surface_h +#define Surface_h + +#include "Color.h" +#include "IntRect.h" +#include "TilePainter.h" +#include "Vector.h" + +class SkCanvas; +class SkRegion; + +namespace WebCore { + +class Tile; +class SurfaceBacking; +class LayerAndroid; +class TexturesResult; + +class Surface : public TilePainter { +public: + Surface(); + virtual ~Surface(); + + bool tryUpdateSurface(Surface* oldSurface); + + void addLayer(LayerAndroid* layer, const TransformationMatrix& transform); + void prepareGL(bool layerTilesDisabled); + bool drawGL(bool layerTilesDisabled); + void swapTiles(); + bool isReady(); + + void computeTexturesAmount(TexturesResult* result); + + LayerAndroid* getFirstLayer() { return m_layers[0]; } + bool needsTexture() { return m_needsTexture; } + bool hasText() { return m_hasText; } + bool isBase(); + void setBackground(Color background) { m_background = background; } + + // TilePainter methods + virtual bool paint(Tile* tile, SkCanvas* canvas); + virtual float opacity(); + virtual Color* background(); + +private: + IntRect computePrepareArea(); + IntRect visibleArea(); + IntRect unclippedArea(); + bool singleLayer() { return m_layers.size() == 1; } + void updateBackground(const Color& background); + bool useAggressiveRendering(); + + const TransformationMatrix* drawTransform(); + IntRect m_unclippedArea; + TransformationMatrix m_drawTransform; + + SurfaceBacking* m_surfaceBacking; + bool m_needsTexture; + bool m_hasText; + Vector m_layers; + + Color m_background; +}; + +class LayerMergeState { +public: + LayerMergeState(Vector* const allGroups) + : surfaceList(allGroups) + , currentSurface(0) + , nonMergeNestedLevel(-1) // start at -1 to ignore first LayerAndroid's clipping + , depth(0) + {} + + // vector storing all generated layer groups + Vector* const surfaceList; + + // currently merging group. if cleared, no more layers may join + Surface* currentSurface; + + // records depth within non-mergeable parents (clipping, fixed, scrolling) + // and disable merging therein. + int nonMergeNestedLevel; + + // counts layer tree depth for debugging + int depth; +}; + +} // namespace WebCore + +#endif //#define Surface_h diff --git a/Source/WebCore/platform/graphics/android/rendering/SurfaceBacking.cpp b/Source/WebCore/platform/graphics/android/rendering/SurfaceBacking.cpp new file mode 100644 index 0000000..7c8f570 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/rendering/SurfaceBacking.cpp @@ -0,0 +1,171 @@ +/* + * Copyright 2011, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define LOG_TAG "SurfaceBacking" +#define LOG_NDEBUG 1 + +#include "config.h" +#include "SurfaceBacking.h" + +#include "AndroidLog.h" +#include "Color.h" +#include "GLWebViewState.h" +#include "LayerAndroid.h" + +#define LOW_RES_PREFETCH_SCALE_MODIFIER 0.3f + +namespace WebCore { + +SurfaceBacking::SurfaceBacking(bool isBaseSurface) +{ + m_frontTexture = new TileGrid(isBaseSurface); + m_backTexture = new TileGrid(isBaseSurface); + m_scale = -1; + m_futureScale = -1; + m_zooming = false; +} + +SurfaceBacking::~SurfaceBacking() +{ + delete m_frontTexture; + delete m_backTexture; +} + +void SurfaceBacking::prepareGL(GLWebViewState* state, bool allowZoom, + const IntRect& prepareArea, const IntRect& unclippedArea, + TilePainter* painter, bool aggressiveRendering) +{ + float scale = state->scale(); + if (scale > 1 && !allowZoom) + scale = 1; + + if (m_scale == -1) { + m_scale = scale; + m_futureScale = scale; + } + + if (m_futureScale != scale) { + m_futureScale = scale; + m_zoomUpdateTime = WTF::currentTime() + SurfaceBacking::s_zoomUpdateDelay; + m_zooming = true; + } + + bool useExpandPrefetch = aggressiveRendering; + ALOGV("Prepare SurfBack %p, scale %.2f, m_scale %.2f, futScale: %.2f, zooming: %d, f %p, b %p", + this, scale, m_scale, m_futureScale, m_zooming, + m_frontTexture, m_backTexture); + + if (!m_zooming) { + m_frontTexture->prepareGL(state, m_scale, + prepareArea, unclippedArea, painter, false, useExpandPrefetch); + if (aggressiveRendering) { + // prepare the back tiled texture to render content in low res + float lowResPrefetchScale = m_scale * LOW_RES_PREFETCH_SCALE_MODIFIER; + m_backTexture->prepareGL(state, lowResPrefetchScale, + prepareArea, unclippedArea, painter, true, useExpandPrefetch); + m_backTexture->swapTiles(); + } + } else if (m_zoomUpdateTime < WTF::currentTime()) { + m_backTexture->prepareGL(state, m_futureScale, + prepareArea, unclippedArea, painter, false, useExpandPrefetch); + if (m_backTexture->isReady()) { + // zooming completed, swap the textures and new front tiles + swapTileGrids(); + + m_frontTexture->swapTiles(); + m_backTexture->discardTextures(); + + m_scale = m_futureScale; + m_zooming = false; + } + } +} + +void SurfaceBacking::drawGL(const IntRect& visibleArea, float opacity, + const TransformationMatrix* transform, + bool aggressiveRendering, const Color* background) +{ + // draw low res prefetch page, if needed + if (aggressiveRendering && !m_zooming && m_frontTexture->isMissingContent()) + m_backTexture->drawGL(visibleArea, opacity, transform); + + m_frontTexture->drawGL(visibleArea, opacity, transform, background); +} + +void SurfaceBacking::markAsDirty(const SkRegion& dirtyArea) +{ + m_backTexture->markAsDirty(dirtyArea); + m_frontTexture->markAsDirty(dirtyArea); +} + +void SurfaceBacking::swapTiles() +{ + m_backTexture->swapTiles(); + m_frontTexture->swapTiles(); +} + +void SurfaceBacking::computeTexturesAmount(TexturesResult* result, LayerAndroid* layer) +{ + // TODO: shouldn't use layer, as this SB may paint multiple layers + if (!layer) + return; + + IntRect unclippedArea = layer->unclippedArea(); + IntRect clippedVisibleArea = layer->visibleArea(); + + // get two numbers here: + // - textures needed for a clipped area + // - textures needed for an un-clipped area + TileGrid* tiledTexture = m_zooming ? m_backTexture : m_frontTexture; + int nbTexturesUnclipped = tiledTexture->nbTextures(unclippedArea, m_scale); + int nbTexturesClipped = tiledTexture->nbTextures(clippedVisibleArea, m_scale); + + // Set kFixedLayers level + if (layer->isPositionFixed()) + result->fixed += nbTexturesClipped; + + // Set kScrollableAndFixedLayers level + if (layer->contentIsScrollable() + || layer->isPositionFixed()) + result->scrollable += nbTexturesClipped; + + // Set kClippedTextures level + result->clipped += nbTexturesClipped; + + // Set kAllTextures level + if (layer->contentIsScrollable()) + result->full += nbTexturesClipped; + else + result->full += nbTexturesUnclipped; +} + +void SurfaceBacking::swapTileGrids() +{ + TileGrid* temp = m_frontTexture; + m_frontTexture = m_backTexture; + m_backTexture = temp; +} + +} // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/rendering/SurfaceBacking.h b/Source/WebCore/platform/graphics/android/rendering/SurfaceBacking.h new file mode 100644 index 0000000..b04e462 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/rendering/SurfaceBacking.h @@ -0,0 +1,86 @@ +/* + * Copyright 2011, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef SurfaceBacking_h +#define SurfaceBacking_h + +#include "SkRefCnt.h" +#include "TileGrid.h" + +namespace WebCore { + +class LayerAndroid; +class TexturesResult; +class TilePainter; + +class SurfaceBacking : public SkRefCnt { +// TODO: investigate webkit threadsafe ref counting +public: + SurfaceBacking(bool isBaseSurface); + ~SurfaceBacking(); + void prepareGL(GLWebViewState* state, bool allowZoom, + const IntRect& prepareArea, const IntRect& unclippedArea, + TilePainter* painter, bool aggressiveRendering); + void swapTiles(); + void drawGL(const IntRect& visibleArea, float opacity, + const TransformationMatrix* transform, bool aggressiveRendering, + const Color* background); + void markAsDirty(const SkRegion& dirtyArea); + void computeTexturesAmount(TexturesResult* result, LayerAndroid* layer); + void discardTextures() + { + m_frontTexture->discardTextures(); + m_backTexture->discardTextures(); + } + bool isReady() + { + return !m_zooming && m_frontTexture->isReady() && m_scale > 0; + } + + int nbTextures(IntRect& area, float scale) + { + // TODO: consider the zooming case for the backTexture + if (!m_frontTexture) + return 0; + return m_frontTexture->nbTextures(area, scale); + } + +private: + void swapTileGrids(); + + // Delay before we schedule a new tile at the new scale factor + static const double s_zoomUpdateDelay = 0.2; // 200 ms + + TileGrid* m_frontTexture; + TileGrid* m_backTexture; + float m_scale; + float m_futureScale; + double m_zoomUpdateTime; + bool m_zooming; +}; + +} // namespace WebCore + +#endif // SurfaceBacking_h diff --git a/Source/WebCore/platform/graphics/android/rendering/SurfaceCollection.cpp b/Source/WebCore/platform/graphics/android/rendering/SurfaceCollection.cpp new file mode 100644 index 0000000..0bbaf91 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/rendering/SurfaceCollection.cpp @@ -0,0 +1,218 @@ +/* + * Copyright 2012, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define LOG_TAG "SurfaceCollection" +#define LOG_NDEBUG 1 + +#include "config.h" +#include "SurfaceCollection.h" + +#include "AndroidLog.h" +#include "BaseLayerAndroid.h" +#include "ClassTracker.h" +#include "GLWebViewState.h" +#include "LayerAndroid.h" +#include "Surface.h" +#include "ScrollableLayerAndroid.h" +#include "TilesManager.h" + +namespace WebCore { + +//////////////////////////////////////////////////////////////////////////////// +// TILED PAINTING / SURFACES // +//////////////////////////////////////////////////////////////////////////////// + +SurfaceCollection::SurfaceCollection(LayerAndroid* layer) + : m_compositedRoot(layer) +{ + // layer must be non-null. + SkSafeRef(m_compositedRoot); + + // calculate draw transforms and z values + SkRect visibleRect = SkRect::MakeLTRB(0, 0, 1, 1); + m_compositedRoot->updateLayerPositions(visibleRect); + // TODO: updateGLPositionsAndScale? + + // allocate surfaces for layers, merging where possible + ALOGV("new tree, allocating surfaces for tree %p", m_baseLayer); + + LayerMergeState layerMergeState(&m_surfaces); + m_compositedRoot->assignSurfaces(&layerMergeState); + + // set the layersurfaces' update count, to be drawn on painted tiles + unsigned int updateCount = TilesManager::instance()->incWebkitContentUpdates(); + for (unsigned int i = 0; i < m_surfaces.size(); i++) { + m_surfaces[i]->setUpdateCount(updateCount); + if (m_surfaces[i]->isBase()) + m_surfaces[i]->setBackground(getBackground()); + } + +#ifdef DEBUG_COUNT + ClassTracker::instance()->increment("SurfaceCollection"); +#endif +} + +SurfaceCollection::~SurfaceCollection() +{ + SkSafeUnref(m_compositedRoot); + for (unsigned int i = 0; i < m_surfaces.size(); i++) + SkSafeUnref(m_surfaces[i]); + m_surfaces.clear(); + +#ifdef DEBUG_COUNT + ClassTracker::instance()->decrement("SurfaceCollection"); +#endif +} + +void SurfaceCollection::prepareGL(const SkRect& visibleRect) +{ + updateLayerPositions(visibleRect); + bool layerTilesDisabled = m_compositedRoot->state()->layersRenderingMode() + > GLWebViewState::kClippedTextures; + for (unsigned int i = 0; i < m_surfaces.size(); i++) + m_surfaces[i]->prepareGL(layerTilesDisabled); +} + +bool SurfaceCollection::drawGL(const SkRect& visibleRect) +{ +#ifdef DEBUG_COUNT + ClassTracker::instance()->show(); +#endif + + bool needsRedraw = false; + updateLayerPositions(visibleRect); + bool layerTilesDisabled = m_compositedRoot->state()->layersRenderingMode() + > GLWebViewState::kClippedTextures; + for (unsigned int i = 0; i < m_surfaces.size(); i++) + needsRedraw |= m_surfaces[i]->drawGL(layerTilesDisabled); + + return needsRedraw; +} + +Color SurfaceCollection::getBackground() +{ + return static_cast(m_compositedRoot)->getBackgroundColor(); +} + +void SurfaceCollection::swapTiles() +{ + for (unsigned int i = 0; i < m_surfaces.size(); i++) + m_surfaces[i]->swapTiles(); +} + +bool SurfaceCollection::isReady() +{ + // Override layer readiness check for single surface mode + if (m_compositedRoot->state()->layersRenderingMode() > GLWebViewState::kClippedTextures) { + // TODO: single surface mode should be properly double buffered + return true; + } + + for (unsigned int i = 0; i < m_surfaces.size(); i++) { + if (!m_surfaces[i]->isReady()) { + ALOGV("layer surface %p isn't ready", m_surfaces[i]); + return false; + } + } + return true; +} + +void SurfaceCollection::computeTexturesAmount(TexturesResult* result) +{ + for (unsigned int i = 0; i < m_surfaces.size(); i++) + m_surfaces[i]->computeTexturesAmount(result); +} + +//////////////////////////////////////////////////////////////////////////////// +// RECURSIVE ANIMATION / INVALS / LAYERS // +//////////////////////////////////////////////////////////////////////////////// + +void SurfaceCollection::setIsPainting(SurfaceCollection* drawingSurface) +{ + if (!drawingSurface) + return; + + for (unsigned int i = 0; i < m_surfaces.size(); i++) { + Surface* newSurface = m_surfaces[i]; + if (!newSurface->needsTexture()) + continue; + + for (unsigned int j = 0; j < drawingSurface->m_surfaces.size(); j++) { + Surface* oldSurface = drawingSurface->m_surfaces[j]; + if (newSurface->tryUpdateSurface(oldSurface)) + break; + } + } +} + +void SurfaceCollection::setIsDrawing() +{ + m_compositedRoot->initAnimations(); +} + +void SurfaceCollection::mergeInvalsInto(SurfaceCollection* replacementSurface) +{ + m_compositedRoot->mergeInvalsInto(replacementSurface->m_compositedRoot); +} + +void SurfaceCollection::evaluateAnimations(double currentTime) +{ + m_compositedRoot->evaluateAnimations(currentTime); +} + +bool SurfaceCollection::hasCompositedLayers() +{ + return m_compositedRoot->countChildren(); +} + +bool SurfaceCollection::hasCompositedAnimations() +{ + return m_compositedRoot->hasAnimations(); +} + +void SurfaceCollection::updateScrollableLayer(int layerId, int x, int y) +{ + LayerAndroid* layer = m_compositedRoot->findById(layerId); + if (layer && layer->contentIsScrollable()) + static_cast(layer)->scrollTo(x, y); +} + +void SurfaceCollection::updateLayerPositions(const SkRect& visibleRect) +{ + TransformationMatrix ident; + m_compositedRoot->updateLayerPositions(visibleRect); + FloatRect clip(0, 0, 1e10, 1e10); + m_compositedRoot->updateGLPositionsAndScale( + ident, clip, 1, m_compositedRoot->state()->scale()); + +#ifdef DEBUG + m_compositedRoot->showLayer(0); + ALOGV("We have %d layers, %d textured", + m_compositedRoot->nbLayers(), + m_compositedRoot->nbTexturedLayers()); +#endif +} + +} // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/rendering/SurfaceCollection.h b/Source/WebCore/platform/graphics/android/rendering/SurfaceCollection.h new file mode 100644 index 0000000..6450c9c --- /dev/null +++ b/Source/WebCore/platform/graphics/android/rendering/SurfaceCollection.h @@ -0,0 +1,76 @@ +/* + * Copyright 2012, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef SurfaceCollection_h +#define SurfaceCollection_h + +#include "Color.h" +#include "SkRect.h" +#include "SkRefCnt.h" + +#include + +class SkCanvas; +class SkRegion; + +namespace WebCore { + +class LayerAndroid; +class Surface; +class TexturesResult; + +class SurfaceCollection : public SkRefCnt { +// TODO: investigate webkit threadsafe ref counting +public: + SurfaceCollection(LayerAndroid* compositedRoot); + virtual ~SurfaceCollection(); + + // Tiled painting methods (executed on groups) + void prepareGL(const SkRect& visibleRect); + bool drawGL(const SkRect& visibleRect); + Color getBackground(); + void swapTiles(); + bool isReady(); + void computeTexturesAmount(TexturesResult* result); + + // Recursive tree methods (animations, invals, etc) + void setIsPainting(SurfaceCollection* drawingSurfaceCollection); + void setIsDrawing(); + void mergeInvalsInto(SurfaceCollection* replacementSurfaceCollection); + void evaluateAnimations(double currentTime); + + bool hasCompositedLayers(); + bool hasCompositedAnimations(); + void updateScrollableLayer(int layerId, int x, int y); + +private: + void updateLayerPositions(const SkRect& visibleRect); + LayerAndroid* m_compositedRoot; + WTF::Vector m_surfaces; +}; + +} // namespace WebCore + +#endif //#define SurfaceCollection_h diff --git a/Source/WebCore/platform/graphics/android/rendering/SurfaceCollectionManager.cpp b/Source/WebCore/platform/graphics/android/rendering/SurfaceCollectionManager.cpp new file mode 100644 index 0000000..8fb4d4b --- /dev/null +++ b/Source/WebCore/platform/graphics/android/rendering/SurfaceCollectionManager.cpp @@ -0,0 +1,258 @@ +/* + * Copyright 2011, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define LOG_TAG "SurfaceCollectionManager" +#define LOG_NDEBUG 1 + +#include "config.h" +#include "SurfaceCollectionManager.h" + +#include "AndroidLog.h" +#include "private/hwui/DrawGlInfo.h" +#include "TilesManager.h" +#include "SurfaceCollection.h" + +namespace WebCore { + +SurfaceCollectionManager::SurfaceCollectionManager(GLWebViewState* state) + : m_state(state) + , m_drawingCollection(0) + , m_paintingCollection(0) + , m_queuedCollection(0) + , m_fastSwapMode(false) +{ +} + +SurfaceCollectionManager::~SurfaceCollectionManager() +{ + clearCollections(); +} + +// the painting collection has finished painting: +// discard the drawing collection +// swap the painting collection in place of the drawing collection +// and start painting the queued collection +void SurfaceCollectionManager::swap() +{ + // swap can't be called unless painting just finished + ASSERT(m_paintingCollection); + + android::Mutex::Autolock lock(m_paintSwapLock); + + ALOGV("SWAPPING, D %p, P %p, Q %p", + m_drawingCollection, m_paintingCollection, m_queuedCollection); + + // if we have a drawing collection, discard it since the painting collection is done + if (m_drawingCollection) { + ALOGV("destroying drawing collection %p", m_drawingCollection); + SkSafeUnref(m_drawingCollection); + } + + // painting collection becomes the drawing collection + ALOGV("drawing collection %p", m_paintingCollection); + m_paintingCollection->setIsDrawing(); // initialize animations + + if (m_queuedCollection) { + // start painting with the queued collection + ALOGV("now painting collection %p", m_queuedCollection); + m_queuedCollection->setIsPainting(m_paintingCollection); + } + m_drawingCollection = m_paintingCollection; + m_paintingCollection = m_queuedCollection; + m_queuedCollection = 0; + + ALOGV("SWAPPING COMPLETE, D %p, P %p, Q %p", + m_drawingCollection, m_paintingCollection, m_queuedCollection); +} + +// clear all of the content in the three collections held by the collection manager +void SurfaceCollectionManager::clearCollections() +{ + ALOGV("SurfaceCollectionManager %p removing PS from state %p", this, m_state); + + SkSafeUnref(m_drawingCollection); + m_drawingCollection = 0; + SkSafeUnref(m_paintingCollection); + m_paintingCollection = 0; + SkSafeUnref(m_queuedCollection); + m_queuedCollection = 0; +} + +// a new layer collection has arrived, queue it if we're painting something already, +// or start painting it if we aren't. Returns true if the manager has two collections +// already queued. +bool SurfaceCollectionManager::updateWithSurfaceCollection(SurfaceCollection* newCollection, + bool brandNew) +{ + // can't have a queued collection unless have a painting collection too + ASSERT(m_paintingCollection || !m_queuedCollection); + + android::Mutex::Autolock lock(m_paintSwapLock); + + if (!newCollection || brandNew) { + clearCollections(); + if (brandNew) { + m_paintingCollection = newCollection; + m_paintingCollection->setIsPainting(m_drawingCollection); + } + return false; + } + + ALOGV("updateWithSurfaceCollection - %p, has children %d, has animations %d", + newCollection, newCollection->hasCompositedLayers(), + newCollection->hasCompositedAnimations()); + + if (m_queuedCollection || m_paintingCollection) { + // currently painting, so defer this new collection + if (m_queuedCollection) { + // already have a queued collection, copy over invals so the regions are + // eventually repainted and let the old queued collection be discarded + m_queuedCollection->mergeInvalsInto(newCollection); + + if (!TilesManager::instance()->useDoubleBuffering()) { + // not double buffering, count discarded collection/webkit paint as an update + TilesManager::instance()->incContentUpdates(); + } + + ALOGV("DISCARDING collection - %p, has children %d, has animations %d", + newCollection, newCollection->hasCompositedLayers(), + newCollection->hasCompositedAnimations()); + } + SkSafeUnref(m_queuedCollection); + m_queuedCollection = newCollection; + } else { + // don't have painting collection, paint this one! + m_paintingCollection = newCollection; + m_paintingCollection->setIsPainting(m_drawingCollection); + } + return m_drawingCollection && TilesManager::instance()->useDoubleBuffering(); +} + +void SurfaceCollectionManager::updateScrollableLayer(int layerId, int x, int y) +{ + if (m_queuedCollection) + m_queuedCollection->updateScrollableLayer(layerId, x, y); + if (m_paintingCollection) + m_paintingCollection->updateScrollableLayer(layerId, x, y); + if (m_drawingCollection) + m_drawingCollection->updateScrollableLayer(layerId, x, y); +} + +int SurfaceCollectionManager::drawGL(double currentTime, IntRect& viewRect, + SkRect& visibleRect, float scale, + bool enterFastSwapMode, + bool* collectionsSwappedPtr, bool* newCollectionHasAnimPtr, + TexturesResult* texturesResultPtr, bool shouldDraw) +{ + m_fastSwapMode |= enterFastSwapMode; + + ALOGV("drawGL, D %p, P %p, Q %p, fastSwap %d shouldDraw %d", + m_drawingCollection, m_paintingCollection, + m_queuedCollection, m_fastSwapMode, shouldDraw); + + bool didCollectionSwap = false; + if (m_paintingCollection) { + ALOGV("preparing painting collection %p", m_paintingCollection); + + m_paintingCollection->evaluateAnimations(currentTime); + + m_paintingCollection->prepareGL(visibleRect); + m_paintingCollection->computeTexturesAmount(texturesResultPtr); + + if (!TilesManager::instance()->useDoubleBuffering() || m_paintingCollection->isReady()) { + ALOGV("have painting collection %p ready, swapping!", m_paintingCollection); + didCollectionSwap = true; + TilesManager::instance()->incContentUpdates(); + if (collectionsSwappedPtr) + *collectionsSwappedPtr = true; + if (newCollectionHasAnimPtr) + *newCollectionHasAnimPtr = m_paintingCollection->hasCompositedAnimations(); + swap(); + } + } else if (m_drawingCollection) { + ALOGV("preparing drawing collection %p", m_drawingCollection); + m_drawingCollection->prepareGL(visibleRect); + m_drawingCollection->computeTexturesAmount(texturesResultPtr); + } + + // ask for kStatusInvoke while painting, kStatusDraw if we have content to be redrawn next frame + // returning 0 indicates all painting complete, no framework inval needed. + int returnFlags = 0; + + if (m_paintingCollection) + returnFlags |= uirenderer::DrawGlInfo::kStatusInvoke; + + if (!shouldDraw) { + if (didCollectionSwap) { + m_drawingCollection->swapTiles(); + returnFlags |= uirenderer::DrawGlInfo::kStatusDraw; + } + + return returnFlags; + } + + // =========================================================================== + // Don't have a drawing collection, draw white background + Color background = Color::white; + if (m_drawingCollection) { + bool drawingReady = didCollectionSwap || m_drawingCollection->isReady(); + + // call the page swap callback if registration happened without more collections enqueued + if (collectionsSwappedPtr && drawingReady && !m_paintingCollection) + *collectionsSwappedPtr = true; + + if (didCollectionSwap || m_fastSwapMode || (drawingReady && !m_paintingCollection)) + m_drawingCollection->swapTiles(); + + if (drawingReady) { + // exit fast swap mode, as content is up to date + m_fastSwapMode = false; + } else { + // drawing isn't ready, must redraw + returnFlags |= uirenderer::DrawGlInfo::kStatusInvoke; + } + + m_drawingCollection->evaluateAnimations(currentTime); + + ALOGV("drawing collection %p", m_drawingCollection); + background = m_drawingCollection->getBackground(); + } else if (m_paintingCollection) { + // Use paintingCollection background color while tiles are not done painting. + background = m_paintingCollection->getBackground(); + } + + // Start doing the actual GL drawing. + ALOGV("background is %x", background.rgb()); + // If background is opaque, we can safely and efficiently clear it here. + // Otherwise, we have to calculate all the missing tiles and blend the background. + GLUtils::clearBackgroundIfOpaque(&background); + if (m_drawingCollection && m_drawingCollection->drawGL(visibleRect)) + returnFlags |= uirenderer::DrawGlInfo::kStatusDraw; + + ALOGV("returnFlags %d, m_paintingCollection %d ", returnFlags, m_paintingCollection); + return returnFlags; +} + +} // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/rendering/SurfaceCollectionManager.h b/Source/WebCore/platform/graphics/android/rendering/SurfaceCollectionManager.h new file mode 100644 index 0000000..cc98899 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/rendering/SurfaceCollectionManager.h @@ -0,0 +1,74 @@ +/* + * Copyright 2011, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef SurfaceCollectionManager_h +#define SurfaceCollectionManager_h + +#include "TestExport.h" +#include + +class SkRect; +class SkCanvas; + +namespace WebCore { + +class GLWebViewState; +class IntRect; +class TexturesResult; +class SurfaceCollection; + +class TEST_EXPORT SurfaceCollectionManager { +public: + SurfaceCollectionManager(GLWebViewState* state); + + ~SurfaceCollectionManager(); + + bool updateWithSurfaceCollection(SurfaceCollection* collection, bool brandNew); + + void updateScrollableLayer(int layerId, int x, int y); + + int drawGL(double currentTime, IntRect& viewRect, + SkRect& visibleRect, float scale, + bool enterFastSwapMode, bool* collectionsSwappedPtr, bool* newCollectionHasAnimPtr, + TexturesResult* texturesResultPtr, bool shouldDraw); + +private: + void swap(); + void clearCollections(); + + android::Mutex m_paintSwapLock; + + GLWebViewState* m_state; + + SurfaceCollection* m_drawingCollection; + SurfaceCollection* m_paintingCollection; + SurfaceCollection* m_queuedCollection; + + bool m_fastSwapMode; +}; + +} // namespace WebCore + +#endif //#define SurfaceCollectionManager_h diff --git a/Source/WebCore/platform/graphics/android/rendering/TextureInfo.cpp b/Source/WebCore/platform/graphics/android/rendering/TextureInfo.cpp new file mode 100644 index 0000000..f5c8b02 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/rendering/TextureInfo.cpp @@ -0,0 +1,65 @@ +/* + * Copyright 2011, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "TextureInfo.h" + +#include "WebCoreJni.h" + +#include +#include +#include +#include + +namespace WebCore { + +TextureInfo::TextureInfo() +{ + m_textureId = GL_NO_TEXTURE; + m_width = 0; + m_height = 0; + m_internalFormat = 0; +} + +bool TextureInfo::equalsAttributes(const TextureInfo* otherTexture) +{ + return otherTexture->m_width == m_width + && otherTexture->m_height == m_height + && otherTexture->m_internalFormat == m_internalFormat; +} + +void TextureInfo::copyAttributes(const TextureInfo* sourceTexture) +{ + m_width = sourceTexture->m_width; + m_height = sourceTexture->m_height; + m_internalFormat = sourceTexture->m_internalFormat; +} + +bool TextureInfo::operator==(const TextureInfo& otherTexture) +{ + return otherTexture.m_textureId == m_textureId && equalsAttributes(&otherTexture); +} + +} // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/rendering/TextureInfo.h b/Source/WebCore/platform/graphics/android/rendering/TextureInfo.h new file mode 100644 index 0000000..7d182c3 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/rendering/TextureInfo.h @@ -0,0 +1,65 @@ +/* + * Copyright 2011, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef TextureInfo_h +#define TextureInfo_h + +#include +#include +#include +#include +#include +using android::sp; + +namespace android { +class SurfaceTexture; +} + +namespace WebCore { + +static const GLuint GL_NO_TEXTURE = 0; +/** + * TextureInfo is a class that stores both the texture and metadata about the + * texture. + */ + +class TextureInfo { +public: + TextureInfo(); + + bool equalsAttributes(const TextureInfo* otherTexture); + void copyAttributes(const TextureInfo* sourceTexture); + + bool operator==(const TextureInfo& otherTexture); + + GLuint m_textureId; + int32_t m_width; + int32_t m_height; + GLenum m_internalFormat; +}; + +} // namespace WebCore + +#endif // TextureInfo_h diff --git a/Source/WebCore/platform/graphics/android/rendering/TextureOwner.h b/Source/WebCore/platform/graphics/android/rendering/TextureOwner.h new file mode 100644 index 0000000..b12d8b7 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/rendering/TextureOwner.h @@ -0,0 +1,47 @@ +/* + * Copyright 2010, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef TextureOwner_h +#define TextureOwner_h + +class SkCanvas; +class Layer; + +namespace WebCore { + +class TileTexture; +class GLWebViewState; + +class TextureOwner { +public: + virtual ~TextureOwner() { } + virtual bool removeTexture(TileTexture* texture) = 0; + virtual bool isRepaintPending() = 0; + virtual unsigned long long drawCount() = 0; +}; + +} + +#endif // TextureOwner_h diff --git a/Source/WebCore/platform/graphics/android/rendering/TexturesGenerator.cpp b/Source/WebCore/platform/graphics/android/rendering/TexturesGenerator.cpp new file mode 100644 index 0000000..f884e52 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/rendering/TexturesGenerator.cpp @@ -0,0 +1,182 @@ +/* + * Copyright 2010, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define LOG_TAG "TexturesGenerator" +#define LOG_NDEBUG 1 + +#include "config.h" +#include "TexturesGenerator.h" + +#if USE(ACCELERATED_COMPOSITING) + +#include "AndroidLog.h" +#include "GLUtils.h" +#include "PaintTileOperation.h" +#include "TilesManager.h" +#include "TransferQueue.h" + +namespace WebCore { + +void TexturesGenerator::scheduleOperation(QueuedOperation* operation) +{ + { + android::Mutex::Autolock lock(mRequestedOperationsLock); + mRequestedOperations.append(operation); + } + mRequestedOperationsCond.signal(); +} + +void TexturesGenerator::removeOperationsForFilter(OperationFilter* filter, bool waitForRunning) +{ + if (!filter) + return; + + android::Mutex::Autolock lock(mRequestedOperationsLock); + for (unsigned int i = 0; i < mRequestedOperations.size();) { + QueuedOperation* operation = mRequestedOperations[i]; + if (filter->check(operation)) { + mRequestedOperations.remove(i); + delete operation; + } else { + i++; + } + } + + if (waitForRunning && m_currentOperation) { + QueuedOperation* operation = m_currentOperation; + + if (operation && filter->check(operation)) { + m_waitForCompletion = true; + // The reason we are signaling the transferQueue is : + // TransferQueue may be waiting a slot to work on, but now UI + // thread is waiting for Tex Gen thread to finish first before the + // UI thread can free a slot for the transferQueue. + // Therefore, it could be a deadlock. + // The solution is use this as a flag to tell Tex Gen thread that + // UI thread is waiting now, Tex Gen thread should not wait for the + // queue any more. + m_tilesManager->transferQueue()->interruptTransferQueue(true); + } + + delete filter; + + // At this point, it means that we are currently executing an operation that + // we want to be removed -- we should wait until it is done, so that + // when we return our caller can be sure that there is no more operations + // in the queue matching the given filter. + while (m_waitForCompletion) + mRequestedOperationsCond.wait(mRequestedOperationsLock); + } else { + delete filter; + } +} + +status_t TexturesGenerator::readyToRun() +{ + ALOGV("Thread ready to run"); + return NO_ERROR; +} + +// Must be called from within a lock! +QueuedOperation* TexturesGenerator::popNext() +{ + // Priority can change between when it was added and now + // Hence why the entire queue is rescanned + QueuedOperation* current = mRequestedOperations.last(); + int currentPriority = current->priority(); + if (currentPriority < 0) { + mRequestedOperations.removeLast(); + return current; + } + int currentIndex = mRequestedOperations.size() - 1; + // Scan from the back to make removing faster (less items to copy) + for (int i = mRequestedOperations.size() - 2; i >= 0; i--) { + QueuedOperation *next = mRequestedOperations[i]; + int nextPriority = next->priority(); + if (nextPriority < 0) { + // Found a very high priority item, go ahead and just handle it now + mRequestedOperations.remove(i); + return next; + } + // pick items preferrably by priority, or if equal, by order of + // insertion (as we add items at the back of the queue) + if (nextPriority <= currentPriority) { + current = next; + currentPriority = nextPriority; + currentIndex = i; + } + } + mRequestedOperations.remove(currentIndex); + return current; +} + +bool TexturesGenerator::threadLoop() +{ + // Check if we have any pending operations. + mRequestedOperationsLock.lock(); + while (!mRequestedOperations.size()) + mRequestedOperationsCond.wait(mRequestedOperationsLock); + + ALOGV("threadLoop, got signal"); + mRequestedOperationsLock.unlock(); + + m_currentOperation = 0; + bool stop = false; + while (!stop) { + mRequestedOperationsLock.lock(); + ALOGV("threadLoop, %d operations in the queue", mRequestedOperations.size()); + if (mRequestedOperations.size()) + m_currentOperation = popNext(); + mRequestedOperationsLock.unlock(); + + if (m_currentOperation) { + ALOGV("threadLoop, painting the request with priority %d", + m_currentOperation->priority()); + m_currentOperation->run(); + } + + QueuedOperation* oldOperation = m_currentOperation; + mRequestedOperationsLock.lock(); + if (m_currentOperation) + m_currentOperation = 0; + if (!mRequestedOperations.size()) + stop = true; + if (m_waitForCompletion) { + m_waitForCompletion = false; + m_tilesManager->transferQueue()->interruptTransferQueue(false); + mRequestedOperationsCond.signal(); + } + mRequestedOperationsLock.unlock(); + if (oldOperation) + delete oldOperation; // delete outside lock + } + ALOGV("threadLoop empty"); + + return true; +} + +} // namespace WebCore + +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/android/rendering/TexturesGenerator.h b/Source/WebCore/platform/graphics/android/rendering/TexturesGenerator.h new file mode 100644 index 0000000..08f69ae --- /dev/null +++ b/Source/WebCore/platform/graphics/android/rendering/TexturesGenerator.h @@ -0,0 +1,70 @@ +/* + * Copyright 2010, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef TexturesGenerator_h +#define TexturesGenerator_h + +#if USE(ACCELERATED_COMPOSITING) + +#include "QueuedOperation.h" +#include "TilePainter.h" +#include + +#include + +namespace WebCore { + +using namespace android; + +class TilesManager; + +class TexturesGenerator : public Thread { +public: + TexturesGenerator(TilesManager* instance) : Thread(false) + , m_waitForCompletion(false) + , m_currentOperation(0) + , m_tilesManager(instance) { } + virtual ~TexturesGenerator() { } + virtual status_t readyToRun(); + + void removeOperationsForFilter(OperationFilter* filter, bool waitForRunning = true); + + void scheduleOperation(QueuedOperation* operation); + +private: + QueuedOperation* popNext(); + virtual bool threadLoop(); + WTF::Vector mRequestedOperations; + android::Mutex mRequestedOperationsLock; + android::Condition mRequestedOperationsCond; + bool m_waitForCompletion; + QueuedOperation* m_currentOperation; + TilesManager* m_tilesManager; +}; + +} // namespace WebCore + +#endif // USE(ACCELERATED_COMPOSITING) +#endif // TexturesGenerator_h diff --git a/Source/WebCore/platform/graphics/android/rendering/Tile.cpp b/Source/WebCore/platform/graphics/android/rendering/Tile.cpp new file mode 100644 index 0000000..35fded1 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/rendering/Tile.cpp @@ -0,0 +1,528 @@ +/* + * Copyright 2010, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define LOG_TAG "Tile" +#define LOG_NDEBUG 1 + +#include "config.h" +#include "Tile.h" + +#if USE(ACCELERATED_COMPOSITING) + +#include "AndroidLog.h" +#include "GLUtils.h" +#include "RasterRenderer.h" +#include "TextureInfo.h" +#include "TileTexture.h" +#include "TilesManager.h" + +// If the dirty portion of a tile exceeds this ratio, fully repaint. +// Lower values give fewer partial repaints, thus fewer front-to-back +// texture copies (cost will vary by device). It's a tradeoff between +// the rasterization cost and the FBO texture recopy cost when using +// GPU for the transfer queue. +#define MAX_INVAL_AREA 0.6 + +namespace WebCore { + +Tile::Tile(bool isLayerTile) + : m_x(-1) + , m_y(-1) + , m_frontTexture(0) + , m_backTexture(0) + , m_scale(1) + , m_dirty(true) + , m_repaintPending(false) + , m_fullRepaint(true) + , m_isLayerTile(isLayerTile) + , m_drawCount(0) + , m_state(Unpainted) +{ +#ifdef DEBUG_COUNT + ClassTracker::instance()->increment("Tile"); +#endif + m_renderer = BaseRenderer::createRenderer(); +} + +Tile::~Tile() +{ + if (m_backTexture) + m_backTexture->release(this); + if (m_frontTexture) + m_frontTexture->release(this); + + delete m_renderer; + +#ifdef DEBUG_COUNT + ClassTracker::instance()->decrement("Tile"); +#endif +} + +// All the following functions must be called from the main GL thread. + +void Tile::setContents(int x, int y, float scale, bool isExpandedPrefetchTile) +{ + // TODO: investigate whether below check/discard is necessary + if ((m_x != x) + || (m_y != y) + || (m_scale != scale)) { + // neither texture is relevant + discardTextures(); + } + + android::AutoMutex lock(m_atomicSync); + m_x = x; + m_y = y; + m_scale = scale; + m_drawCount = TilesManager::instance()->getDrawGLCount(); + if (isExpandedPrefetchTile) + m_drawCount--; // deprioritize expanded painting region +} + +void Tile::reserveTexture() +{ + TileTexture* texture = TilesManager::instance()->getAvailableTexture(this); + + android::AutoMutex lock(m_atomicSync); + if (texture && m_backTexture != texture) { + ALOGV("tile %p reserving texture %p, back was %p (front %p)", + this, texture, m_backTexture, m_frontTexture); + m_state = Unpainted; + m_backTexture = texture; + } + + if (m_state == UpToDate) { + ALOGV("moving tile %p to unpainted, since it reserved while up to date", this); + m_dirty = true; + m_state = Unpainted; + } +} + +bool Tile::removeTexture(TileTexture* texture) +{ + ALOGV("%p removeTexture %p, back %p front %p", + this, texture, m_backTexture, m_frontTexture); + // We update atomically, so paintBitmap() can see the correct value + android::AutoMutex lock(m_atomicSync); + if (m_frontTexture == texture) { + if (m_state == UpToDate) { + ALOGV("front texture removed, state was UpToDate, now becoming unpainted, bt is %p", m_backTexture); + m_state = Unpainted; + } + + m_frontTexture = 0; + } + if (m_backTexture == texture) { + m_state = Unpainted; + m_backTexture = 0; + } + + // mark dirty regardless of which texture was taken - the back texture may + // have been ready to swap + m_dirty = true; + + return true; +} + +void Tile::markAsDirty(const SkRegion& dirtyArea) +{ + if (dirtyArea.isEmpty()) + return; + android::AutoMutex lock(m_atomicSync); + m_dirtyArea.op(dirtyArea, SkRegion::kUnion_Op); + + // Check if we actually intersect with the area + bool intersect = false; + SkRegion::Iterator cliperator(dirtyArea); + SkRect realTileRect; + SkRect dirtyRect; + while (!cliperator.done()) { + dirtyRect.set(cliperator.rect()); + if (intersectWithRect(m_x, m_y, TilesManager::tileWidth(), TilesManager::tileHeight(), + m_scale, dirtyRect, realTileRect)) { + intersect = true; + break; + } + cliperator.next(); + } + + if (!intersect) + return; + + m_dirty = true; + if (m_state == UpToDate) { + // We only mark a tile as unpainted in 'markAsDirty' if its status is + // UpToDate: marking dirty means we need to repaint, but don't stop the + // current paint + m_state = Unpainted; + } else if (m_state != Unpainted) { + // TODO: fix it so that they can paint while deferring the markAsDirty + // call (or block updates) + ALOGV("Warning: tried to mark tile %p at %d, %d islayertile %d as dirty, state %d", + this, m_x, m_y, isLayerTile(), m_state); + + // prefetch tiles can be marked dirty while in the process of painting, + // due to not using an update lock. force them to fail validate step. + m_state = Unpainted; + } +} + +bool Tile::isDirty() +{ + android::AutoMutex lock(m_atomicSync); + return m_dirty; +} + +bool Tile::isRepaintPending() +{ + android::AutoMutex lock(m_atomicSync); + return m_repaintPending; +} + +void Tile::setRepaintPending(bool pending) +{ + android::AutoMutex lock(m_atomicSync); + m_repaintPending = pending; +} + +bool Tile::drawGL(float opacity, const SkRect& rect, float scale, + const TransformationMatrix* transform, + bool forceBlending) +{ + if (m_x < 0 || m_y < 0 || m_scale != scale) + return false; + + // No need to mutex protect reads of m_backTexture as it is only written to by + // the consumer thread. + if (!m_frontTexture) + return false; + + m_frontTexture->drawGL(isLayerTile(), rect, opacity, transform, forceBlending); + return true; +} + +bool Tile::isTileReady() +{ + // Return true if the tile's most recently drawn texture is up to date + android::AutoMutex lock(m_atomicSync); + TileTexture * texture = (m_state == ReadyToSwap) ? m_backTexture : m_frontTexture; + + if (!texture) + return false; + + if (texture->owner() != this) + return false; + + if (m_dirty) + return false; + + if (m_state != ReadyToSwap && m_state != UpToDate) + return false; + + return true; +} + +bool Tile::intersectWithRect(int x, int y, int tileWidth, int tileHeight, + float scale, const SkRect& dirtyRect, + SkRect& realTileRect) +{ + // compute the rect to corresponds to pixels + realTileRect.fLeft = x * tileWidth; + realTileRect.fTop = y * tileHeight; + realTileRect.fRight = realTileRect.fLeft + tileWidth; + realTileRect.fBottom = realTileRect.fTop + tileHeight; + + // scale the dirtyRect for intersect computation. + SkRect realDirtyRect = SkRect::MakeWH(dirtyRect.width() * scale, + dirtyRect.height() * scale); + realDirtyRect.offset(dirtyRect.fLeft * scale, dirtyRect.fTop * scale); + + if (!realTileRect.intersect(realDirtyRect)) + return false; + return true; +} + +bool Tile::isTileVisible(const IntRect& viewTileBounds) +{ + return (m_x >= viewTileBounds.x() + && m_x < viewTileBounds.x() + viewTileBounds.width() + && m_y >= viewTileBounds.y() + && m_y < viewTileBounds.y() + viewTileBounds.height()); +} + +// This is called from the texture generation thread +void Tile::paintBitmap(TilePainter* painter) +{ + // We acquire the values below atomically. This ensures that we are reading + // values correctly across cores. Further, once we have these values they + // can be updated by other threads without consequence. + m_atomicSync.lock(); + bool dirty = m_dirty; + TileTexture* texture = m_backTexture; + SkRegion dirtyArea = m_dirtyArea; + float scale = m_scale; + const int x = m_x; + const int y = m_y; + + if (!dirty || !texture) { + m_atomicSync.unlock(); + return; + } + if (m_state != Unpainted) { + ALOGV("Warning: started painting tile %p, but was at state %d, ft %p bt %p", + this, m_state, m_frontTexture, m_backTexture); + } + m_state = PaintingStarted; + TextureInfo* textureInfo = texture->getTextureInfo(); + m_atomicSync.unlock(); + + // at this point we can safely check the ownership (if the texture got + // transferred to another Tile under us) + if (texture->owner() != this) { + return; + } + + // swap out the renderer if necessary + BaseRenderer::swapRendererIfNeeded(m_renderer); + // setup the common renderInfo fields; + TileRenderInfo renderInfo; + renderInfo.x = x; + renderInfo.y = y; + renderInfo.scale = scale; + renderInfo.tileSize = texture->getSize(); + renderInfo.tilePainter = painter; + renderInfo.baseTile = this; + renderInfo.textureInfo = textureInfo; + + const float tileWidth = renderInfo.tileSize.width(); + const float tileHeight = renderInfo.tileSize.height(); + + SkRegion::Iterator cliperator(dirtyArea); + + bool fullRepaint = false; + + if (m_fullRepaint + || textureInfo->m_width != tileWidth + || textureInfo->m_height != tileHeight) { + fullRepaint = true; + } + + // For now, only do full repaint + fullRepaint = true; + + if (!fullRepaint) { + // compute the partial inval area + SkIRect totalRect; + totalRect.set(0, 0, 0, 0); + float tileSurface = tileWidth * tileHeight; + float tileSurfaceCap = MAX_INVAL_AREA * tileSurface; + + // We join all the invals in the same tile for now + while (!fullRepaint && !cliperator.done()) { + SkRect realTileRect; + SkRect dirtyRect; + dirtyRect.set(cliperator.rect()); + bool intersect = intersectWithRect(x, y, tileWidth, tileHeight, + scale, dirtyRect, realTileRect); + if (intersect) { + // initialize finalRealRect to the rounded values of realTileRect + SkIRect finalRealRect; + realTileRect.roundOut(&finalRealRect); + + // stash the int values of the current width and height + const int iWidth = finalRealRect.width(); + const int iHeight = finalRealRect.height(); + + if (iWidth == tileWidth || iHeight == tileHeight) { + fullRepaint = true; + break; + } + + // translate the rect into tile space coordinates + finalRealRect.fLeft = finalRealRect.fLeft % static_cast(tileWidth); + finalRealRect.fTop = finalRealRect.fTop % static_cast(tileHeight); + finalRealRect.fRight = finalRealRect.fLeft + iWidth; + finalRealRect.fBottom = finalRealRect.fTop + iHeight; + totalRect.join(finalRealRect); + float repaintSurface = totalRect.width() * totalRect.height(); + + if (repaintSurface > tileSurfaceCap) { + fullRepaint = true; + break; + } + } + + cliperator.next(); + } + + if (!fullRepaint) { + renderInfo.invalRect = &totalRect; + m_renderer->renderTiledContent(renderInfo); + } + } + + // Do a full repaint if needed + if (fullRepaint) { + renderInfo.invalRect = 0; + m_renderer->renderTiledContent(renderInfo); + } + + m_atomicSync.lock(); + + if (texture == m_backTexture) { + // set the fullrepaint flags + m_fullRepaint = false; + + // The various checks to see if we are still dirty... + + m_dirty = false; + + if (m_scale != scale) + m_dirty = true; + + if (fullRepaint) + m_dirtyArea.setEmpty(); + else + m_dirtyArea.op(dirtyArea, SkRegion::kDifference_Op); + + if (!m_dirtyArea.isEmpty()) + m_dirty = true; + + ALOGV("painted tile %p (%d, %d), texture %p, dirty=%d", this, x, y, texture, m_dirty); + + validatePaint(); + } else { + ALOGV("tile %p no longer owns texture %p, m_state %d. ft %p bt %p", + this, texture, m_state, m_frontTexture, m_backTexture); + } + + m_atomicSync.unlock(); +} + +void Tile::discardTextures() { + android::AutoMutex lock(m_atomicSync); + ALOGV("%p discarding bt %p, ft %p", + this, m_backTexture, m_frontTexture); + if (m_frontTexture) { + m_frontTexture->release(this); + m_frontTexture = 0; + } + if (m_backTexture) { + m_backTexture->release(this); + m_backTexture = 0; + } + m_dirtyArea.setEmpty(); + m_fullRepaint = true; + + m_dirty = true; + m_state = Unpainted; +} + +void Tile::discardBackTexture() { + android::AutoMutex lock(m_atomicSync); + if (m_backTexture) { + m_backTexture->release(this); + m_backTexture = 0; + } + m_state = Unpainted; + m_dirty = true; +} + +bool Tile::swapTexturesIfNeeded() { + android::AutoMutex lock(m_atomicSync); + if (m_state == ReadyToSwap) { + // discard old texture and swap the new one in its place + if (m_frontTexture) + m_frontTexture->release(this); + + m_frontTexture = m_backTexture; + m_backTexture = 0; + m_state = UpToDate; + ALOGV("display texture for %p at %d, %d front is now %p, back is %p", + this, m_x, m_y, m_frontTexture, m_backTexture); + + return true; + } + return false; +} + +void Tile::backTextureTransfer() { + android::AutoMutex lock(m_atomicSync); + if (m_state == PaintingStarted) + m_state = TransferredUnvalidated; + else if (m_state == ValidatedUntransferred) + m_state = ReadyToSwap; + else { + // shouldn't have transferred a tile in any other state, log + ALOGV("Note: transferred tile %p at %d %d, state wasn't paintingstarted or validated: %d", + this, m_x, m_y, m_state); + } +} + +void Tile::backTextureTransferFail() { + // transfer failed for some reason, mark dirty so it will (repaint and) be + // retransferred. + android::AutoMutex lock(m_atomicSync); + m_state = Unpainted; + m_dirty = true; + // whether validatePaint is called before or after, it won't do anything +} + +void Tile::validatePaint() { + // ONLY CALL while m_atomicSync is locked (at the end of paintBitmap()) + + if (!m_dirty) { + // since after the paint, the tile isn't dirty, 'validate' it - this + // may happed before or after the transfer queue operation. Only + // when both have happened, mark as 'ReadyToSwap' + if (m_state == PaintingStarted) + m_state = ValidatedUntransferred; + else if (m_state == TransferredUnvalidated) { + // When the backTexture has been marked pureColor, we will skip the + // transfer and marked as ReadyToSwap, in this case, we don't want + // to reset m_dirty bit to true. + m_state = ReadyToSwap; + } else { + ALOGV("Note: validated tile %p at %d %d, state wasn't paintingstarted or transferred %d", + this, m_x, m_y, m_state); + // failed transferring, in which case mark dirty (since + // paintBitmap() may have cleared m_dirty) + m_dirty = true; + } + + if (m_deferredDirty) { + ALOGV("Note: deferred dirty flag set, possibly a missed paint on tile %p", this); + m_deferredDirty = false; + } + } else { + ALOGV("Note: paint was unsuccessful."); + m_state = Unpainted; + } + +} + +} // namespace WebCore + +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/android/rendering/Tile.h b/Source/WebCore/platform/graphics/android/rendering/Tile.h new file mode 100644 index 0000000..7010301 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/rendering/Tile.h @@ -0,0 +1,191 @@ +/* + * Copyright 2010, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef Tile_h +#define Tile_h + +#if USE(ACCELERATED_COMPOSITING) + +#include "BaseRenderer.h" +#include "SkRect.h" +#include "SkRegion.h" +#include "TextureOwner.h" +#include "TilePainter.h" + +#include + +namespace WebCore { + +class TextureInfo; +class TileTexture; +class GLWebViewState; + +/** + * An individual tile that is used to construct part of a webpage's BaseLayer of + * content. Each tile is assigned to a TiledPage and is responsible for drawing + * and displaying their section of the page. The lifecycle of a tile is: + * + * 1. Each tile is created on the main GL thread and assigned to a specific + * location within a TiledPage. + * 2. When needed the tile is passed to the background thread where it paints + * the BaseLayer's most recent PictureSet to a bitmap which is then uploaded + * to the GPU. + * 3. After the bitmap is uploaded to the GPU the main GL thread then uses the + * tile's drawGL() function to display the tile to the screen. + * 4. Steps 2-3 are repeated as necessary. + * 5. The tile is destroyed when the user navigates to a new page. + * + */ +class Tile : public TextureOwner { +public: + + // eventually, m_dirty might be rolled into the state machine, but note + // that a tile that's continually marked dirty from animation should still + // progress through the state machine and be drawn periodically (esp. for + // layers) + + // /-> TransferredUnvalidated (TQ interrupts paint) -\ (TQ & paint done) + // Unpainted -> PaintingStarted -- -> ReadyToSwap -> UpToDate + // ^ \-> ValidatedUntransferred (paint finish before TQ) -/ + // | + // \--... (From any state when marked dirty. should usually come from UpToDate if the updates are locked) + // + + enum TextureState{ + // back texture is completely unpainted + Unpainted = 0, + // has started painting, but haven't been transferred or validated + PaintingStarted = 1, + // back texture painted, transferred before validating in PaintBitmap() + TransferredUnvalidated = 2, + // back texture painted, validated before transferring in TransferQueue + ValidatedUntransferred = 3, + // back texture has been blitted, will be swapped when next available + ReadyToSwap = 4, + // has been swapped, is ready to draw, all is well + UpToDate = 5, + }; + + Tile(bool isLayerTile = false); + ~Tile(); + + bool isLayerTile() { return m_isLayerTile; } + + void setContents(int x, int y, float scale, bool isExpandedPrefetchTile); + + void reserveTexture(); + + bool isTileReady(); + + // Return false when real draw didn't happen for any reason. + bool drawGL(float opacity, const SkRect& rect, float scale, + const TransformationMatrix* transform, + bool forceBlending = false); + + // the only thread-safe function called by the background thread + void paintBitmap(TilePainter* painter); + + bool intersectWithRect(int x, int y, int tileWidth, int tileHeight, + float scale, const SkRect& dirtyRect, + SkRect& realTileRect); + bool isTileVisible(const IntRect& viewTileBounds); + + void markAsDirty(const SkRegion& dirtyArea); + bool isDirty(); + virtual bool isRepaintPending(); + void setRepaintPending(bool pending); + float scale() const { return m_scale; } + TextureState textureState() const { return m_state; } + + int x() const { return m_x; } + int y() const { return m_y; } + TileTexture* frontTexture() { return m_frontTexture; } + TileTexture* backTexture() { return m_backTexture; } + + // only used for prioritization - the higher, the more relevant the tile is + unsigned long long drawCount() { return m_drawCount; } + void discardTextures(); + void discardBackTexture(); + bool swapTexturesIfNeeded(); + void backTextureTransfer(); + void backTextureTransferFail(); + + // TextureOwner implementation + virtual bool removeTexture(TileTexture* texture); + +private: + void validatePaint(); + + int m_x; + int m_y; + + // The remaining variables can be updated throughout the lifetime of the object + + TileTexture* m_frontTexture; + TileTexture* m_backTexture; + float m_scale; + + // used to signal that the that the tile is out-of-date and needs to be + // redrawn in the backTexture + bool m_dirty; + + // currently only for debugging, to be used for tracking down dropped repaints + bool m_deferredDirty; + + // used to signal that a repaint is pending + bool m_repaintPending; + + // store the dirty region + SkRegion m_dirtyArea; + bool m_fullRepaint; + + // This mutex serves two purposes. (1) It ensures that certain operations + // happen atomically and (2) it makes sure those operations are synchronized + // across all threads and cores. + android::Mutex m_atomicSync; + + BaseRenderer* m_renderer; + + bool m_isLayerTile; + + // the most recent GL draw before this tile was prepared. used for + // prioritization and caching. tiles with old drawcounts and textures they + // own are used for new tiles and rendering + unsigned long long m_drawCount; + + // Tracks the state of painting for the tile. High level overview: + // 1) Unpainted - until paint starts (and if marked dirty, in most cases) + // 2) PaintingStarted - until paint completes + // 3) TransferredUnvalidated - if transferred first + // or ValidatedUntransferred - if validated first + // 4) ReadyToSwap - if painted and transferred, but not swapped + // 5) UpToDate - until marked dirty again + TextureState m_state; +}; + +} // namespace WebCore + +#endif // USE(ACCELERATED_COMPOSITING) +#endif // Tile_h diff --git a/Source/WebCore/platform/graphics/android/rendering/TileGrid.cpp b/Source/WebCore/platform/graphics/android/rendering/TileGrid.cpp new file mode 100644 index 0000000..0e900a9 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/rendering/TileGrid.cpp @@ -0,0 +1,376 @@ +/* + * Copyright 2011, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define LOG_TAG "TileGrid" +#define LOG_NDEBUG 1 + +#include "config.h" +#include "TileGrid.h" + +#include "AndroidLog.h" +#include "DrawQuadData.h" +#include "GLWebViewState.h" +#include "PaintTileOperation.h" +#include "Tile.h" +#include "TilesManager.h" + +#include + +#define EXPANDED_BOUNDS_INFLATE 1 +#define EXPANDED_PREFETCH_BOUNDS_Y_INFLATE 1 + +namespace WebCore { + +TileGrid::TileGrid(bool isBaseSurface) + : m_prevTileY(0) + , m_scale(1) + , m_isBaseSurface(isBaseSurface) +{ + m_dirtyRegion.setEmpty(); +#ifdef DEBUG_COUNT + ClassTracker::instance()->increment("TileGrid"); +#endif +} + +TileGrid::~TileGrid() +{ +#ifdef DEBUG_COUNT + ClassTracker::instance()->decrement("TileGrid"); +#endif + removeTiles(); +} + +bool TileGrid::isReady() +{ + bool tilesAllReady = true; + bool tilesVisible = false; + for (unsigned int i = 0; i < m_tiles.size(); i++) { + Tile* tile = m_tiles[i]; + if (tile->isTileVisible(m_area)) { + tilesVisible = true; + if (!tile->isTileReady()) { + tilesAllReady = false; + break; + } + } + } + // For now, if no textures are available, consider ourselves as ready + // in order to unblock the zooming process. + // FIXME: have a better system -- maybe keeping the last scale factor + // able to fully render everything + ALOGV("TT %p, ready %d, visible %d, texturesRemain %d", + this, tilesAllReady, tilesVisible, + TilesManager::instance()->layerTexturesRemain()); + + return !TilesManager::instance()->layerTexturesRemain() + || !tilesVisible || tilesAllReady; +} + +bool TileGrid::isMissingContent() +{ + for (unsigned int i = 0; i < m_tiles.size(); i++) + if (m_tiles[i]->isTileVisible(m_area) && !m_tiles[i]->frontTexture()) + return true; + return false; +} + +void TileGrid::swapTiles() +{ + int swaps = 0; + for (unsigned int i = 0; i < m_tiles.size(); i++) + if (m_tiles[i]->swapTexturesIfNeeded()) + swaps++; + ALOGV("TT %p swapping, swaps = %d", this, swaps); +} + +IntRect TileGrid::computeTilesArea(const IntRect& contentArea, float scale) +{ + IntRect computedArea; + IntRect area(contentArea.x() * scale, + contentArea.y() * scale, + ceilf(contentArea.width() * scale), + ceilf(contentArea.height() * scale)); + + ALOGV("TT %p prepare, scale %f, area %d x %d", this, scale, area.width(), area.height()); + + if (area.width() == 0 && area.height() == 0) { + computedArea.setWidth(0); + computedArea.setHeight(0); + return computedArea; + } + + int tileWidth = TilesManager::tileWidth(); + int tileHeight = TilesManager::tileHeight(); + + computedArea.setX(area.x() / tileWidth); + computedArea.setY(area.y() / tileHeight); + float right = (area.x() + area.width()) / (float) tileWidth; + float bottom = (area.y() + area.height()) / (float) tileHeight; + computedArea.setWidth(ceilf(right) - computedArea.x()); + computedArea.setHeight(ceilf(bottom) - computedArea.y()); + return computedArea; +} + +void TileGrid::prepareGL(GLWebViewState* state, float scale, + const IntRect& prepareArea, const IntRect& unclippedArea, + TilePainter* painter, bool isLowResPrefetch, bool useExpandPrefetch) +{ + // first, how many tiles do we need + m_area = computeTilesArea(prepareArea, scale); + if (m_area.isEmpty()) + return; + + ALOGV("prepare TileGrid %p with scale %.2f, prepareArea " + " %d, %d - %d x %d, corresponding to %d, %d x - %d x %d tiles", + this, scale, + prepareArea.x(), prepareArea.y(), + prepareArea.width(), prepareArea.height(), + m_area.x(), m_area.y(), + m_area.width(), m_area.height()); + + bool goingDown = m_prevTileY < m_area.y(); + m_prevTileY = m_area.y(); + + if (scale != m_scale) + TilesManager::instance()->removeOperationsForFilter(new ScaleFilter(painter, m_scale)); + + m_scale = scale; + + // apply dirty region to affected tiles + if (!m_dirtyRegion.isEmpty()) { + for (unsigned int i = 0; i < m_tiles.size(); i++) + m_tiles[i]->markAsDirty(m_dirtyRegion); + + // log inval region for the base surface + if (m_isBaseSurface && TilesManager::instance()->getProfiler()->enabled()) { + SkRegion::Iterator iterator(m_dirtyRegion); + while (!iterator.done()) { + SkIRect r = iterator.rect(); + TilesManager::instance()->getProfiler()->nextInval(r, scale); + iterator.next(); + } + } + m_dirtyRegion.setEmpty(); + } + + // prepare standard bounds (clearing ExpandPrefetch flag) + for (int i = 0; i < m_area.width(); i++) { + if (goingDown) { + for (int j = 0; j < m_area.height(); j++) + prepareTile(m_area.x() + i, m_area.y() + j, + painter, state, isLowResPrefetch, false); + } else { + for (int j = m_area.height() - 1; j >= 0; j--) + prepareTile(m_area.x() + i, m_area.y() + j, + painter, state, isLowResPrefetch, false); + } + } + + // prepare expanded bounds + if (useExpandPrefetch) { + IntRect fullArea = computeTilesArea(unclippedArea, scale); + IntRect expandedArea = m_area; + expandedArea.inflate(EXPANDED_BOUNDS_INFLATE); + + if (isLowResPrefetch) + expandedArea.inflate(EXPANDED_PREFETCH_BOUNDS_Y_INFLATE); + + // clip painting area to content + expandedArea.intersect(fullArea); + + for (int i = expandedArea.x(); i < expandedArea.maxX(); i++) + for (int j = expandedArea.y(); j < expandedArea.maxY(); j++) + if (!m_area.contains(i, j)) + prepareTile(i, j, painter, state, isLowResPrefetch, true); + } +} + +void TileGrid::markAsDirty(const SkRegion& invalRegion) +{ + ALOGV("TT %p markAsDirty, current region empty %d, new empty %d", + this, m_dirtyRegion.isEmpty(), invalRegion.isEmpty()); + m_dirtyRegion.op(invalRegion, SkRegion::kUnion_Op); +} + +void TileGrid::prepareTile(int x, int y, TilePainter* painter, + GLWebViewState* state, bool isLowResPrefetch, bool isExpandPrefetch) +{ + Tile* tile = getTile(x, y); + if (!tile) { + bool isLayerTile = !m_isBaseSurface; + tile = new Tile(isLayerTile); + m_tiles.append(tile); + } + + ALOGV("preparing tile %p at %d, %d, painter is %p", tile, x, y, painter); + + tile->setContents(x, y, m_scale, isExpandPrefetch); + + // TODO: move below (which is largely the same for layers / tiled page) into + // prepareGL() function + + if (tile->isDirty() || !tile->frontTexture()) + tile->reserveTexture(); + + if (tile->backTexture() && tile->isDirty() && !tile->isRepaintPending()) { + ALOGV("painting TT %p's tile %d %d for LG %p", this, x, y, painter); + PaintTileOperation *operation = new PaintTileOperation(tile, painter, + state, isLowResPrefetch); + TilesManager::instance()->scheduleOperation(operation); + } +} + +Tile* TileGrid::getTile(int x, int y) +{ + for (unsigned int i = 0; i x() == x && tile->y() == y) + return tile; + } + return 0; +} + +int TileGrid::nbTextures(IntRect& area, float scale) +{ + IntRect tileBounds = computeTilesArea(area, scale); + int numberTextures = tileBounds.width() * tileBounds.height(); + + // add the number of dirty tiles in the bounds, as they take up double + // textures for double buffering + for (unsigned int i = 0; i isDirty() + && tile->x() >= tileBounds.x() && tile->x() <= tileBounds.maxX() + && tile->y() >= tileBounds.y() && tile->y() <= tileBounds.maxY()) + numberTextures++; + } + return numberTextures; +} + +void TileGrid::drawGL(const IntRect& visibleArea, float opacity, + const TransformationMatrix* transform, + const Color* background) +{ + m_area = computeTilesArea(visibleArea, m_scale); + if (m_area.width() == 0 || m_area.height() == 0) + return; + + float invScale = 1 / m_scale; + const float tileWidth = TilesManager::tileWidth() * invScale; + const float tileHeight = TilesManager::tileHeight() * invScale; + + int drawn = 0; + + SkRegion missingRegion; + bool semiOpaqueBaseSurface = + background ? (background->hasAlpha() && background->alpha() > 0) : false; + if (semiOpaqueBaseSurface) { + SkIRect totalArea = SkIRect::MakeXYWH(m_area.x(), m_area.y(), + m_area.width(), m_area.height()); + missingRegion = SkRegion(totalArea); + } + + for (unsigned int i = 0; i < m_tiles.size(); i++) { + Tile* tile = m_tiles[i]; + + bool tileInView = tile->isTileVisible(m_area); + if (tileInView) { + SkRect rect; + rect.fLeft = tile->x() * tileWidth; + rect.fTop = tile->y() * tileHeight; + rect.fRight = rect.fLeft + tileWidth; + rect.fBottom = rect.fTop + tileHeight; + ALOGV("tile %p (layer tile: %d) %d,%d at scale %.2f vs %.2f [ready: %d] dirty: %d", + tile, tile->isLayerTile(), tile->x(), tile->y(), + tile->scale(), m_scale, tile->isTileReady(), tile->isDirty()); + + bool forceBaseBlending = background ? background->hasAlpha() : false; + bool success = tile->drawGL(opacity, rect, m_scale, transform, + forceBaseBlending); + if (semiOpaqueBaseSurface && success) { + // Cut the successful drawn tile area from the missing region. + missingRegion.op(SkIRect::MakeXYWH(tile->x(), tile->y(), 1, 1), + SkRegion::kDifference_Op); + } + if (tile->frontTexture()) + drawn++; + } + + if (semiOpaqueBaseSurface) + TilesManager::instance()->getProfiler()->nextTile(tile, invScale, tileInView); + } + + // Draw missing Regions with blend turned on + if (semiOpaqueBaseSurface) + drawMissingRegion(missingRegion, opacity, background); + + ALOGV("TT %p drew %d tiles, scale %f", + this, drawn, m_scale); +} + +void TileGrid::drawMissingRegion(const SkRegion& region, float opacity, + const Color* background) +{ + SkRegion::Iterator iterator(region); + const float tileWidth = TilesManager::tileWidth() / m_scale; + const float tileHeight = TilesManager::tileHeight() / m_scale; + ShaderProgram* shader = TilesManager::instance()->shader(); + while (!iterator.done()) { + SkIRect r = iterator.rect(); + SkRect rect; + rect.fLeft = r.x() * tileWidth; + rect.fTop = r.y() * tileHeight; + rect.fRight = rect.fLeft + tileWidth * r.width(); + rect.fBottom = rect.fTop + tileHeight * r.height(); + ALOGV("draw tile x y, %d %d (%d %d) opacity %f", r.x(), r.y(), + r.width(), r.height(), opacity); + // Skia is using pre-multiplied color. + Color postAlpha = Color(background->red() * background->alpha() / 255, + background->green() * background->alpha() / 255, + background->blue() * background->alpha() / 255, + background->alpha() ); + + PureColorQuadData backGroundData(postAlpha, BaseQuad, 0, &rect, opacity); + TilesManager::instance()->shader()->drawQuad(&backGroundData); + iterator.next(); + } +} + +void TileGrid::removeTiles() +{ + for (unsigned int i = 0; i < m_tiles.size(); i++) { + delete m_tiles[i]; + } + m_tiles.clear(); +} + +void TileGrid::discardTextures() +{ + ALOGV("TT %p discarding textures", this); + for (unsigned int i = 0; i < m_tiles.size(); i++) + m_tiles[i]->discardTextures(); +} + +} // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/rendering/TileGrid.h b/Source/WebCore/platform/graphics/android/rendering/TileGrid.h new file mode 100644 index 0000000..ffb6c7e --- /dev/null +++ b/Source/WebCore/platform/graphics/android/rendering/TileGrid.h @@ -0,0 +1,87 @@ +/* + * Copyright 2011, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef TileGrid_h +#define TileGrid_h + +#include "IntRect.h" +#include "SkRegion.h" + +#include + +namespace WebCore { + +class Color; +class GLWebViewState; +class Tile; +class TilePainter; +class TransformationMatrix; + +class TileGrid { +public: + TileGrid(bool isBaseSurface); + virtual ~TileGrid(); + + static IntRect computeTilesArea(const IntRect& contentArea, float scale); + + void prepareGL(GLWebViewState* state, float scale, + const IntRect& prepareArea, const IntRect& unclippedArea, + TilePainter* painter, bool isLowResPrefetch = false, + bool useExpandPrefetch = false); + void swapTiles(); + void drawGL(const IntRect& visibleArea, float opacity, + const TransformationMatrix* transform, const Color* background = 0); + + void prepareTile(int x, int y, TilePainter* painter, + GLWebViewState* state, bool isLowResPrefetch, bool isExpandPrefetch); + void markAsDirty(const SkRegion& dirtyArea); + + Tile* getTile(int x, int y); + + void removeTiles(); + void discardTextures(); + + bool isReady(); + bool isMissingContent(); + + int nbTextures(IntRect& area, float scale); + +private: + void drawMissingRegion(const SkRegion& region, float opacity, const Color* tileBackground); + WTF::Vector m_tiles; + + IntRect m_area; + + SkRegion m_dirtyRegion; + + int m_prevTileY; + float m_scale; + + bool m_isBaseSurface; +}; + +} // namespace WebCore + +#endif // TileGrid_h diff --git a/Source/WebCore/platform/graphics/android/rendering/TilePainter.h b/Source/WebCore/platform/graphics/android/rendering/TilePainter.h new file mode 100644 index 0000000..d992aee --- /dev/null +++ b/Source/WebCore/platform/graphics/android/rendering/TilePainter.h @@ -0,0 +1,58 @@ +/* + * Copyright 2011, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef TilePainter_h +#define TilePainter_h + +#include "TransformationMatrix.h" +#include "SkRefCnt.h" + +class SkCanvas; + +namespace WebCore { + +class Tile; +class Color; + +class TilePainter : public SkRefCnt { +// TODO: investigate webkit threadsafe ref counting +public: + virtual ~TilePainter() { } + virtual bool paint(Tile* tile, SkCanvas* canvas) = 0; + virtual float opacity() { return 1.0; } + enum SurfaceType { Painted, Image }; + virtual SurfaceType type() { return Painted; } + virtual Color* background() { return 0; } + + unsigned int getUpdateCount() { return m_updateCount; } + void setUpdateCount(unsigned int updateCount) { m_updateCount = updateCount; } + +private: + unsigned int m_updateCount; +}; + +} + +#endif // TilePainter_h diff --git a/Source/WebCore/platform/graphics/android/rendering/TileTexture.cpp b/Source/WebCore/platform/graphics/android/rendering/TileTexture.cpp new file mode 100644 index 0000000..39effd7 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/rendering/TileTexture.cpp @@ -0,0 +1,147 @@ +/* + * Copyright 2010, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define LOG_TAG "TileTexture" +#define LOG_NDEBUG 1 + +#include "config.h" +#include "TileTexture.h" + +#include "AndroidLog.h" +#include "Tile.h" +#include "ClassTracker.h" +#include "DrawQuadData.h" +#include "GLUtils.h" +#include "GLWebViewState.h" +#include "TextureOwner.h" +#include "TilesManager.h" + +namespace WebCore { + +TileTexture::TileTexture(uint32_t w, uint32_t h) + : m_owner(0) + , m_isPureColor(false) +{ + m_size.set(w, h); + m_ownTextureId = 0; + +#ifdef DEBUG_COUNT + ClassTracker::instance()->increment("TileTexture"); +#endif +} + +TileTexture::~TileTexture() +{ +#ifdef DEBUG_COUNT + ClassTracker::instance()->decrement("TileTexture"); +#endif +} + +void TileTexture::requireGLTexture() +{ + if (!m_ownTextureId) + m_ownTextureId = GLUtils::createTileGLTexture(m_size.width(), m_size.height()); +} + +void TileTexture::discardGLTexture() +{ + if (m_ownTextureId) + GLUtils::deleteTexture(&m_ownTextureId); + + if (m_owner) { + // clear both Tile->Texture and Texture->Tile links + m_owner->removeTexture(this); + release(m_owner); + } +} + +bool TileTexture::acquire(TextureOwner* owner, bool force) +{ + if (m_owner == owner) + return true; + + return setOwner(owner, force); +} + +bool TileTexture::setOwner(TextureOwner* owner, bool force) +{ + bool proceed = true; + if (m_owner && m_owner != owner) + proceed = m_owner->removeTexture(this); + + if (proceed) { + m_owner = owner; + return true; + } + + return false; +} + +bool TileTexture::release(TextureOwner* owner) +{ + ALOGV("texture %p releasing tile %p, m_owner %p", this, owner, m_owner); + if (m_owner != owner) + return false; + + m_owner = 0; + return true; +} + +void TileTexture::transferComplete() +{ + if (m_owner) { + Tile* owner = static_cast(m_owner); + owner->backTextureTransfer(); + } else + ALOGE("ERROR: owner missing after transfer of texture %p", this); +} + +void TileTexture::drawGL(bool isLayer, const SkRect& rect, float opacity, + const TransformationMatrix* transform, + bool forceBlending) +{ + ShaderProgram* shader = TilesManager::instance()->shader(); + + if (isLayer && !transform) { + ALOGE("ERROR: Missing tranform for layers!"); + return; + } + + // For base layer, we just follow the forceBlending, otherwise, blending is + // always turned on. + // TODO: Don't blend tiles if they are fully opaque. + forceBlending |= isLayer; + DrawQuadData commonData(isLayer ? LayerQuad : BaseQuad, transform, &rect, + opacity, forceBlending); + if (isPureColor()) { + PureColorQuadData data(commonData, pureColor()); + shader->drawQuad(&data); + } else { + TextureQuadData data(commonData, m_ownTextureId, GL_TEXTURE_2D, GL_LINEAR); + shader->drawQuad(&data); + } +} + +} // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/rendering/TileTexture.h b/Source/WebCore/platform/graphics/android/rendering/TileTexture.h new file mode 100644 index 0000000..5fe43b0 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/rendering/TileTexture.h @@ -0,0 +1,99 @@ +/* + * Copyright 2010, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef TileTexture_h +#define TileTexture_h + +#include "TextureInfo.h" +#include "Color.h" +#include "SkBitmap.h" +#include "SkRect.h" +#include "SkSize.h" + +#include + +class SkCanvas; + +namespace WebCore { + +class TextureOwner; +class Tile; +class TransformationMatrix; + +class TileTexture { +public: + // This object is to be constructed on the consumer's thread and must have + // a width and height greater than 0. + TileTexture(uint32_t w, uint32_t h); + virtual ~TileTexture(); + + // allows consumer thread to assign ownership of the texture to the tile. It + // returns false if ownership cannot be transferred because the tile is busy + bool acquire(TextureOwner* owner, bool force = false); + bool release(TextureOwner* owner); + + // set the texture owner if not busy. Return false if busy, true otherwise. + bool setOwner(TextureOwner* owner, bool force = false); + + // private member accessor functions + TextureOwner* owner() { return m_owner; } // only used by the consumer thread + + const SkSize& getSize() const { return m_size; } + + // OpenGL ID of backing texture, 0 when not allocated + GLuint m_ownTextureId; + // these are used for dynamically (de)allocating backing graphics memory + void requireGLTexture(); + void discardGLTexture(); + + void transferComplete(); + + TextureInfo* getTextureInfo() { return &m_ownTextureInfo; } + + // Make sure the following pureColor getter/setter are only read/written + // in UI thread. Therefore no need for a lock. + void setPure(bool pure) { m_isPureColor = pure; } + bool isPureColor() {return m_isPureColor; } + void setPureColor(const Color& color) { m_pureColor = color; setPure(true); } + Color pureColor() { return m_pureColor; } + + void drawGL(bool isLayer, const SkRect& rect, float opacity, + const TransformationMatrix* transform, bool forceBlending = false); +private: + TextureInfo m_ownTextureInfo; + SkSize m_size; + + // Tile owning the texture, only modified by UI thread + TextureOwner* m_owner; + + // When the whole tile is single color, skip the transfer queue and draw + // it directly through shader. + bool m_isPureColor; + Color m_pureColor; +}; + +} // namespace WebCore + +#endif // TileTexture_h diff --git a/Source/WebCore/platform/graphics/android/rendering/TilesManager.cpp b/Source/WebCore/platform/graphics/android/rendering/TilesManager.cpp new file mode 100644 index 0000000..e8b8cd1 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/rendering/TilesManager.cpp @@ -0,0 +1,449 @@ +/* + * Copyright 2010, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define LOG_TAG "TilesManager" +#define LOG_NDEBUG 1 + +#include "config.h" +#include "TilesManager.h" + +#if USE(ACCELERATED_COMPOSITING) + +#include "AndroidLog.h" +#include "GLWebViewState.h" +#include "SkCanvas.h" +#include "SkDevice.h" +#include "SkPaint.h" +#include "Tile.h" +#include "TileTexture.h" +#include "TransferQueue.h" + +#include +#include +#include +#include +#include + +// Important: We need at least twice as many textures as is needed to cover +// one viewport, otherwise the allocation may stall. +// We need n textures for one TiledPage, and another n textures for the +// second page used when scaling. +// In our case, we use 256*256 textures. On the tablet, this equates to +// at least 60 textures, or 112 with expanded tile boundaries. +// 112(tiles)*256*256*4(bpp)*2(pages) = 56MB +// It turns out the viewport dependent value m_maxTextureCount is a reasonable +// number to cap the layer tile texturs, it worked on both phones and tablets. +// TODO: after merge the pool of base tiles and layer tiles, we should revisit +// the logic of allocation management. +#define MAX_TEXTURE_ALLOCATION ((6+TILE_PREFETCH_DISTANCE*2)*(5+TILE_PREFETCH_DISTANCE*2)*4) +#define TILE_WIDTH 256 +#define TILE_HEIGHT 256 + +#define BYTES_PER_PIXEL 4 // 8888 config + +#define LAYER_TEXTURES_DESTROY_TIMEOUT 60 // If we do not need layers for 60 seconds, free the textures + +namespace WebCore { + +GLint TilesManager::getMaxTextureSize() +{ + static GLint maxTextureSize = 0; + if (!maxTextureSize) + glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize); + return maxTextureSize; +} + +int TilesManager::getMaxTextureAllocation() +{ + return MAX_TEXTURE_ALLOCATION; +} + +TilesManager::TilesManager() + : m_layerTexturesRemain(true) + , m_highEndGfx(false) + , m_maxTextureCount(0) + , m_maxLayerTextureCount(0) + , m_generatorReady(false) + , m_showVisualIndicator(false) + , m_invertedScreen(false) + , m_useMinimalMemory(true) + , m_useDoubleBuffering(true) + , m_contentUpdates(0) + , m_webkitContentUpdates(0) + , m_queue(0) + , m_drawGLCount(1) + , m_lastTimeLayersUsed(0) + , m_hasLayerTextures(false) +{ + ALOGV("TilesManager ctor"); + m_textures.reserveCapacity(MAX_TEXTURE_ALLOCATION); + m_availableTextures.reserveCapacity(MAX_TEXTURE_ALLOCATION); + m_tilesTextures.reserveCapacity(MAX_TEXTURE_ALLOCATION); + m_availableTilesTextures.reserveCapacity(MAX_TEXTURE_ALLOCATION); + m_pixmapsGenerationThread = new TexturesGenerator(this); + m_pixmapsGenerationThread->run("TexturesGenerator"); +} + +void TilesManager::allocateTiles() +{ + int nbTexturesToAllocate = m_maxTextureCount - m_textures.size(); + ALOGV("%d tiles to allocate (%d textures planned)", nbTexturesToAllocate, m_maxTextureCount); + int nbTexturesAllocated = 0; + for (int i = 0; i < nbTexturesToAllocate; i++) { + TileTexture* texture = new TileTexture( + tileWidth(), tileHeight()); + // the atomic load ensures that the texture has been fully initialized + // before we pass a pointer for other threads to operate on + TileTexture* loadedTexture = + reinterpret_cast( + android_atomic_acquire_load(reinterpret_cast(&texture))); + m_textures.append(loadedTexture); + nbTexturesAllocated++; + } + + int nbLayersTexturesToAllocate = m_maxLayerTextureCount - m_tilesTextures.size(); + ALOGV("%d layers tiles to allocate (%d textures planned)", + nbLayersTexturesToAllocate, m_maxLayerTextureCount); + int nbLayersTexturesAllocated = 0; + for (int i = 0; i < nbLayersTexturesToAllocate; i++) { + TileTexture* texture = new TileTexture( + tileWidth(), tileHeight()); + // the atomic load ensures that the texture has been fully initialized + // before we pass a pointer for other threads to operate on + TileTexture* loadedTexture = + reinterpret_cast( + android_atomic_acquire_load(reinterpret_cast(&texture))); + m_tilesTextures.append(loadedTexture); + nbLayersTexturesAllocated++; + } + ALOGV("allocated %d textures for base (total: %d, %d Mb), %d textures for layers (total: %d, %d Mb)", + nbTexturesAllocated, m_textures.size(), + m_textures.size() * TILE_WIDTH * TILE_HEIGHT * 4 / 1024 / 1024, + nbLayersTexturesAllocated, m_tilesTextures.size(), + m_tilesTextures.size() * tileWidth() * tileHeight() * 4 / 1024 / 1024); +} + +void TilesManager::discardTextures(bool allTextures, bool glTextures) +{ + const unsigned int max = m_textures.size(); + + unsigned long long sparedDrawCount = ~0; // by default, spare no textures + if (!allTextures) { + // if we're not deallocating all textures, spare those with max drawcount + sparedDrawCount = 0; + for (unsigned int i = 0; i < max; i++) { + TextureOwner* owner = m_textures[i]->owner(); + if (owner) + sparedDrawCount = std::max(sparedDrawCount, owner->drawCount()); + } + } + discardTexturesVector(sparedDrawCount, m_textures, glTextures); + discardTexturesVector(sparedDrawCount, m_tilesTextures, glTextures); +} + +void TilesManager::discardTexturesVector(unsigned long long sparedDrawCount, + WTF::Vector& textures, + bool deallocateGLTextures) +{ + const unsigned int max = textures.size(); + int dealloc = 0; + WTF::Vector discardedIndex; + for (unsigned int i = 0; i < max; i++) { + TextureOwner* owner = textures[i]->owner(); + if (!owner || owner->drawCount() < sparedDrawCount) { + if (deallocateGLTextures) { + // deallocate textures' gl memory + textures[i]->discardGLTexture(); + discardedIndex.append(i); + } else if (owner) { + // simply detach textures from owner + static_cast(owner)->discardTextures(); + } + dealloc++; + } + } + + bool base = textures == m_textures; + // Clean up the vector of TileTextures and reset the max texture count. + if (discardedIndex.size()) { + android::Mutex::Autolock lock(m_texturesLock); + for (int i = discardedIndex.size() - 1; i >= 0; i--) + textures.remove(discardedIndex[i]); + + int remainedTextureNumber = textures.size(); + int* countPtr = base ? &m_maxTextureCount : &m_maxLayerTextureCount; + if (remainedTextureNumber < *countPtr) { + ALOGV("reset maxTextureCount for %s tiles from %d to %d", + base ? "base" : "layer", *countPtr, remainedTextureNumber); + *countPtr = remainedTextureNumber; + } + + } + + ALOGV("Discarded %d %s textures (out of %d %s tiles)", + dealloc, (deallocateGLTextures ? "gl" : ""), + max, base ? "base" : "layer"); +} + +void TilesManager::gatherTexturesNumbers(int* nbTextures, int* nbAllocatedTextures, + int* nbLayerTextures, int* nbAllocatedLayerTextures) +{ + *nbTextures = m_textures.size(); + for (unsigned int i = 0; i < m_textures.size(); i++) { + TileTexture* texture = m_textures[i]; + if (texture->m_ownTextureId) + *nbAllocatedTextures += 1; + } + *nbLayerTextures = m_tilesTextures.size(); + for (unsigned int i = 0; i < m_tilesTextures.size(); i++) { + TileTexture* texture = m_tilesTextures[i]; + if (texture->m_ownTextureId) + *nbAllocatedLayerTextures += 1; + } +} + +void TilesManager::printTextures() +{ +#ifdef DEBUG + ALOGV("++++++"); + for (unsigned int i = 0; i < m_textures.size(); i++) { + TileTexture* texture = m_textures[i]; + Tile* o = 0; + if (texture->owner()) + o = (Tile*) texture->owner(); + int x = -1; + int y = -1; + if (o) { + x = o->x(); + y = o->y(); + } + ALOGV("[%d] texture %x owner: %x (%d, %d) scale: %.2f", + i, texture, o, x, y, o ? o->scale() : 0); + } + ALOGV("------"); +#endif // DEBUG +} + +void TilesManager::gatherTextures() +{ + android::Mutex::Autolock lock(m_texturesLock); + m_availableTextures = m_textures; + m_availableTilesTextures = m_tilesTextures; + m_layerTexturesRemain = true; +} + +TileTexture* TilesManager::getAvailableTexture(Tile* owner) +{ + android::Mutex::Autolock lock(m_texturesLock); + + // Sanity check that the tile does not already own a texture + if (owner->backTexture() && owner->backTexture()->owner() == owner) { + ALOGV("same owner (%d, %d), getAvailableBackTexture(%x) => texture %x", + owner->x(), owner->y(), owner, owner->backTexture()); + if (owner->isLayerTile()) + m_availableTilesTextures.remove(m_availableTilesTextures.find(owner->backTexture())); + else + m_availableTextures.remove(m_availableTextures.find(owner->backTexture())); + return owner->backTexture(); + } + + WTF::Vector* availableTexturePool; + if (owner->isLayerTile()) { + availableTexturePool = &m_availableTilesTextures; + } else { + availableTexturePool = &m_availableTextures; + } + + // The heuristic for selecting a texture is as follows: + // 1. Skip textures currently being painted, they can't be painted while + // busy anyway + // 2. If a tile isn't owned, break with that one + // 3. Don't let tiles acquire their front textures + // 4. Otherwise, use the least recently prepared tile, but ignoring tiles + // drawn in the last frame to avoid flickering + + TileTexture* farthestTexture = 0; + unsigned long long oldestDrawCount = getDrawGLCount() - 1; + const unsigned int max = availableTexturePool->size(); + for (unsigned int i = 0; i < max; i++) { + TileTexture* texture = (*availableTexturePool)[i]; + Tile* currentOwner = static_cast(texture->owner()); + if (!currentOwner) { + // unused texture! take it! + farthestTexture = texture; + break; + } + + if (currentOwner == owner) { + // Don't let a tile acquire its own front texture, as the + // acquisition logic doesn't handle that + continue; + } + + unsigned long long textureDrawCount = currentOwner->drawCount(); + if (oldestDrawCount > textureDrawCount) { + farthestTexture = texture; + oldestDrawCount = textureDrawCount; + } + } + + if (farthestTexture) { + Tile* previousOwner = static_cast(farthestTexture->owner()); + if (farthestTexture->acquire(owner)) { + if (previousOwner) { + previousOwner->removeTexture(farthestTexture); + + ALOGV("%s texture %p stolen from tile %d, %d for %d, %d, drawCount was %llu (now %llu)", + owner->isLayerTile() ? "LAYER" : "BASE", + farthestTexture, previousOwner->x(), previousOwner->y(), + owner->x(), owner->y(), + oldestDrawCount, getDrawGLCount()); + } + + availableTexturePool->remove(availableTexturePool->find(farthestTexture)); + return farthestTexture; + } + } else { + if (owner->isLayerTile()) { + // couldn't find a tile for a layer, layers shouldn't request redraw + // TODO: once we do layer prefetching, don't set this for those + // tiles + m_layerTexturesRemain = false; + } + } + + ALOGV("Couldn't find an available texture for %s tile %x (%d, %d) out of %d available", + owner->isLayerTile() ? "LAYER" : "BASE", + owner, owner->x(), owner->y(), max); +#ifdef DEBUG + printTextures(); +#endif // DEBUG + return 0; +} + +void TilesManager::setHighEndGfx(bool highEnd) +{ + m_highEndGfx = highEnd; +} + +bool TilesManager::highEndGfx() +{ + return m_highEndGfx; +} + +int TilesManager::maxTextureCount() +{ + android::Mutex::Autolock lock(m_texturesLock); + return m_maxTextureCount; +} + +int TilesManager::maxLayerTextureCount() +{ + android::Mutex::Autolock lock(m_texturesLock); + return m_maxLayerTextureCount; +} + +void TilesManager::setMaxTextureCount(int max) +{ + ALOGV("setMaxTextureCount: %d (current: %d, total:%d)", + max, m_maxTextureCount, MAX_TEXTURE_ALLOCATION); + if (m_maxTextureCount == MAX_TEXTURE_ALLOCATION || + max <= m_maxTextureCount) + return; + + android::Mutex::Autolock lock(m_texturesLock); + + if (max < MAX_TEXTURE_ALLOCATION) + m_maxTextureCount = max; + else + m_maxTextureCount = MAX_TEXTURE_ALLOCATION; + + allocateTiles(); +} + +void TilesManager::setMaxLayerTextureCount(int max) +{ + ALOGV("setMaxLayerTextureCount: %d (current: %d, total:%d)", + max, m_maxLayerTextureCount, MAX_TEXTURE_ALLOCATION); + if (!max && m_hasLayerTextures) { + double secondsSinceLayersUsed = WTF::currentTime() - m_lastTimeLayersUsed; + if (secondsSinceLayersUsed > LAYER_TEXTURES_DESTROY_TIMEOUT) { + unsigned long long sparedDrawCount = ~0; // by default, spare no textures + bool deleteGLTextures = true; + discardTexturesVector(sparedDrawCount, m_tilesTextures, deleteGLTextures); + m_hasLayerTextures = false; + } + return; + } + m_lastTimeLayersUsed = WTF::currentTime(); + if (m_maxLayerTextureCount == MAX_TEXTURE_ALLOCATION || + max <= m_maxLayerTextureCount) + return; + + android::Mutex::Autolock lock(m_texturesLock); + + if (max < MAX_TEXTURE_ALLOCATION) + m_maxLayerTextureCount = max; + else + m_maxLayerTextureCount = MAX_TEXTURE_ALLOCATION; + + allocateTiles(); + m_hasLayerTextures = true; +} + +TransferQueue* TilesManager::transferQueue() +{ + // m_queue will be created on the UI thread, although it may + // be accessed from the TexturesGenerator. However, that can only happen after + // a previous transferQueue() call due to a prepare. + if (!m_queue) + m_queue = new TransferQueue(m_useMinimalMemory); + return m_queue; +} + +float TilesManager::tileWidth() +{ + return TILE_WIDTH; +} + +float TilesManager::tileHeight() +{ + return TILE_HEIGHT; +} + +TilesManager* TilesManager::instance() +{ + if (!gInstance) { + gInstance = new TilesManager(); + ALOGV("instance(), new gInstance is %x", gInstance); + } + return gInstance; +} + +TilesManager* TilesManager::gInstance = 0; + +} // namespace WebCore + +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/android/rendering/TilesManager.h b/Source/WebCore/platform/graphics/android/rendering/TilesManager.h new file mode 100644 index 0000000..92c56d3 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/rendering/TilesManager.h @@ -0,0 +1,209 @@ +/* + * Copyright 2010, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef TilesManager_h +#define TilesManager_h + +#if USE(ACCELERATED_COMPOSITING) + +#include "LayerAndroid.h" +#include "ShaderProgram.h" +#include "TexturesGenerator.h" +#include "TilesProfiler.h" +#include "VideoLayerManager.h" +#include +#include + +namespace WebCore { + +class OperationFilter; +class Tile; +class TileTexture; +class TransferQueue; + +class TilesManager { +public: + // May only be called from the UI thread + static TilesManager* instance(); + static GLint getMaxTextureSize(); + static int getMaxTextureAllocation(); + + static bool hardwareAccelerationEnabled() + { + return gInstance != 0; + } + + void removeOperationsForFilter(OperationFilter* filter, bool waitForRunning = false) + { + m_pixmapsGenerationThread->removeOperationsForFilter(filter, waitForRunning); + } + + void scheduleOperation(QueuedOperation* operation) + { + m_pixmapsGenerationThread->scheduleOperation(operation); + } + + ShaderProgram* shader() { return &m_shader; } + TransferQueue* transferQueue(); + VideoLayerManager* videoLayerManager() { return &m_videoLayerManager; } + + void gatherTextures(); + bool layerTexturesRemain() { return m_layerTexturesRemain; } + void gatherTexturesNumbers(int* nbTextures, int* nbAllocatedTextures, + int* nbLayerTextures, int* nbAllocatedLayerTextures); + + TileTexture* getAvailableTexture(Tile* owner); + + void printTextures(); + + // m_highEndGfx is written/read only on UI thread, no need for a lock. + void setHighEndGfx(bool highEnd); + bool highEndGfx(); + + int maxTextureCount(); + int maxLayerTextureCount(); + void setMaxTextureCount(int max); + void setMaxLayerTextureCount(int max); + static float tileWidth(); + static float tileHeight(); + + void allocateTiles(); + + // remove all tiles from textures (and optionally deallocate gl memory) + void discardTextures(bool allTextures, bool glTextures); + + bool getShowVisualIndicator() + { + return m_showVisualIndicator; + } + + void setShowVisualIndicator(bool showVisualIndicator) + { + m_showVisualIndicator = showVisualIndicator; + } + + TilesProfiler* getProfiler() + { + return &m_profiler; + } + + bool invertedScreen() + { + return m_invertedScreen; + } + + void setInvertedScreen(bool invert) + { + m_invertedScreen = invert; + } + + void setInvertedScreenContrast(float contrast) + { + m_shader.setContrast(contrast); + } + + void setUseMinimalMemory(bool useMinimalMemory) + { + m_useMinimalMemory = useMinimalMemory; + } + + bool useMinimalMemory() + { + return m_useMinimalMemory; + } + + void setUseDoubleBuffering(bool useDoubleBuffering) + { + m_useDoubleBuffering = useDoubleBuffering; + } + bool useDoubleBuffering() { return m_useDoubleBuffering; } + + + unsigned int incWebkitContentUpdates() { return m_webkitContentUpdates++; } + + void incContentUpdates() { m_contentUpdates++; } + unsigned int getContentUpdates() { return m_contentUpdates; } + void clearContentUpdates() { m_contentUpdates = 0; } + + void incDrawGLCount() + { + m_drawGLCount++; + } + + unsigned long long getDrawGLCount() + { + return m_drawGLCount; + } + +private: + TilesManager(); + + void discardTexturesVector(unsigned long long sparedDrawCount, + WTF::Vector& textures, + bool deallocateGLTextures); + + WTF::Vector m_textures; + WTF::Vector m_availableTextures; + + WTF::Vector m_tilesTextures; + WTF::Vector m_availableTilesTextures; + bool m_layerTexturesRemain; + + bool m_highEndGfx; + int m_maxTextureCount; + int m_maxLayerTextureCount; + + bool m_generatorReady; + + bool m_showVisualIndicator; + bool m_invertedScreen; + + bool m_useMinimalMemory; + + bool m_useDoubleBuffering; + unsigned int m_contentUpdates; // nr of successful tiled paints + unsigned int m_webkitContentUpdates; // nr of paints from webkit + + sp m_pixmapsGenerationThread; + + android::Mutex m_texturesLock; + + static TilesManager* gInstance; + + ShaderProgram m_shader; + TransferQueue* m_queue; + + VideoLayerManager m_videoLayerManager; + + TilesProfiler m_profiler; + unsigned long long m_drawGLCount; + double m_lastTimeLayersUsed; + bool m_hasLayerTextures; +}; + +} // namespace WebCore + +#endif // USE(ACCELERATED_COMPOSITING) +#endif // TilesManager_h diff --git a/Source/WebCore/platform/graphics/android/rendering/TilesProfiler.cpp b/Source/WebCore/platform/graphics/android/rendering/TilesProfiler.cpp new file mode 100644 index 0000000..4f0c6b5 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/rendering/TilesProfiler.cpp @@ -0,0 +1,133 @@ +/* + * Copyright 2010, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define LOG_TAG "TilesProfiler" +#define LOG_NDEBUG 1 + +#include "config.h" +#include "TilesProfiler.h" + +#if USE(ACCELERATED_COMPOSITING) + +#include "AndroidLog.h" +#include "Tile.h" +#include "TilesManager.h" +#include + +// Hard limit on amount of frames (and thus memory) profiling can take +#define MAX_PROF_FRAMES 400 +#define INVAL_CODE -2 + +namespace WebCore { +TilesProfiler::TilesProfiler() + : m_enabled(false) +{ +} + +void TilesProfiler::start() +{ + m_enabled = true; + m_goodTiles = 0; + m_badTiles = 0; + m_records.clear(); + m_time = currentTimeMS(); + ALOGV("initializing tileprofiling"); +} + +float TilesProfiler::stop() +{ + m_enabled = false; + ALOGV("completed tile profiling, observed %d frames", m_records.size()); + return (1.0 * m_goodTiles) / (m_goodTiles + m_badTiles); +} + +void TilesProfiler::clear() +{ + ALOGV("clearing tile profiling of its %d frames", m_records.size()); + m_records.clear(); +} + +void TilesProfiler::nextFrame(int left, int top, int right, int bottom, float scale) +{ + if (!m_enabled || (m_records.size() > MAX_PROF_FRAMES)) + return; + + double currentTime = currentTimeMS(); + double timeDelta = currentTime - m_time; + m_time = currentTime; + +#ifdef DEBUG + if (m_records.size() != 0) { + ALOGD("completed tile profiling frame, observed %d tiles. %f ms since last", + m_records[0].size(), timeDelta); + } +#endif // DEBUG + + m_records.append(WTF::Vector()); + + //first record designates viewport + m_records.last().append(TileProfileRecord( + left, top, right, bottom, + scale, true, (int)(timeDelta * 1000))); +} + +void TilesProfiler::nextTile(Tile* tile, float scale, bool inView) +{ + if (!m_enabled || (m_records.size() > MAX_PROF_FRAMES) || (m_records.size() == 0)) + return; + + bool isReady = tile->isTileReady(); + int left = tile->x() * TilesManager::tileWidth(); + int top = tile->y() * TilesManager::tileWidth(); + int right = left + TilesManager::tileWidth(); + int bottom = top + TilesManager::tileWidth(); + + if (inView) { + if (isReady) + m_goodTiles++; + else + m_badTiles++; + } + m_records.last().append(TileProfileRecord( + left, top, right, bottom, + scale, isReady, (int)tile->drawCount())); + ALOGV("adding tile %d %d %d %d, scale %f", left, top, right, bottom, scale); +} + +void TilesProfiler::nextInval(const SkIRect& rect, float scale) +{ + if (!m_enabled || (m_records.size() > MAX_PROF_FRAMES) || (m_records.size() == 0)) + return; + + m_records.last().append(TileProfileRecord( + rect.x(), rect.y(), + rect.right(), rect.bottom(), scale, false, INVAL_CODE)); + ALOGV("adding inval region %d %d %d %d, scale %f", rect.x(), rect.y(), + rect.right(), rect.bottom(), scale); +} + +} // namespace WebCore + +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/android/rendering/TilesProfiler.h b/Source/WebCore/platform/graphics/android/rendering/TilesProfiler.h new file mode 100644 index 0000000..b39ae2f --- /dev/null +++ b/Source/WebCore/platform/graphics/android/rendering/TilesProfiler.h @@ -0,0 +1,90 @@ +/* + * Copyright 2011, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef TilesProfiler_h +#define TilesProfiler_h + +#if USE(ACCELERATED_COMPOSITING) + +#include "IntRect.h" +#include "SkRect.h" +#include + +namespace WebCore { + +class Tile; + +struct TileProfileRecord { + TileProfileRecord(int left, int top, int right, int bottom, float scale, int isReady, int level) { + this->left = left; + this->top = top; + this->right = right; + this->bottom = bottom; + this->scale = scale; + this->isReady = isReady; + this->level = level; + } + int left, top, right, bottom; + bool isReady; + int level; + float scale; +}; + +class TilesProfiler { +public: + TilesProfiler(); + + void start(); + float stop(); + void clear(); + void nextFrame(int left, int top, int right, int bottom, float scale); + void nextTile(Tile* tile, float scale, bool inView); + void nextInval(const SkIRect& rect, float scale); + int numFrames() { + return m_records.size(); + }; + + int numTilesInFrame(int frame) { + return m_records[frame].size(); + } + + TileProfileRecord* getTile(int frame, int tile) { + return &m_records[frame][tile]; + } + + bool enabled() { return m_enabled; } + +private: + bool m_enabled; + unsigned int m_goodTiles; + unsigned int m_badTiles; + WTF::Vector > m_records; + double m_time; +}; + +} // namespace WebCore + +#endif // USE(ACCELERATED_COMPOSITING) +#endif // TilesProfiler_h diff --git a/Source/WebCore/platform/graphics/android/rendering/TransferQueue.cpp b/Source/WebCore/platform/graphics/android/rendering/TransferQueue.cpp new file mode 100644 index 0000000..ec0d9e7 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/rendering/TransferQueue.cpp @@ -0,0 +1,644 @@ +/* + * Copyright 2011, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define LOG_TAG "TransferQueue" +#define LOG_NDEBUG 1 + +#include "config.h" +#include "TransferQueue.h" + +#if USE(ACCELERATED_COMPOSITING) + +#include "AndroidLog.h" +#include "DrawQuadData.h" +#include "GLUtils.h" +#include "Tile.h" +#include "TileTexture.h" +#include "TilesManager.h" +#include +#include +#include + +// For simple webView usage, MINIMAL_SIZE is recommended for memory saving. +// In browser case, EFFICIENT_SIZE is preferred. +#define MINIMAL_SIZE 1 +#define EFFICIENT_SIZE 6 + +// Set this to 1 if we would like to take the new GpuUpload approach which +// relied on the glCopyTexSubImage2D instead of a glDraw call +#define GPU_UPLOAD_WITHOUT_DRAW 1 + +namespace WebCore { + +TransferQueue::TransferQueue(bool useMinimalMem) + : m_eglSurface(EGL_NO_SURFACE) + , m_transferQueueIndex(0) + , m_fboID(0) + , m_sharedSurfaceTextureId(0) + , m_hasGLContext(true) + , m_interruptedByRemovingOp(false) + , m_currentDisplay(EGL_NO_DISPLAY) + , m_currentUploadType(DEFAULT_UPLOAD_TYPE) +{ + memset(&m_GLStateBeforeBlit, 0, sizeof(m_GLStateBeforeBlit)); + m_transferQueueSize = useMinimalMem ? MINIMAL_SIZE : EFFICIENT_SIZE; + m_emptyItemCount = m_transferQueueSize; + m_transferQueue = new TileTransferData[m_transferQueueSize]; +} + +TransferQueue::~TransferQueue() +{ + android::Mutex::Autolock lock(m_transferQueueItemLocks); + cleanupGLResources(); + delete[] m_transferQueue; +} + +// This should be called within the m_transferQueueItemLocks. +// Now only called by emptyQueue() and destructor. +void TransferQueue::cleanupGLResources() +{ + if (m_sharedSurfaceTexture.get()) { + m_sharedSurfaceTexture->abandon(); + m_sharedSurfaceTexture.clear(); + } + if (m_fboID) { + glDeleteFramebuffers(1, &m_fboID); + m_fboID = 0; + } + if (m_sharedSurfaceTextureId) { + glDeleteTextures(1, &m_sharedSurfaceTextureId); + m_sharedSurfaceTextureId = 0; + } +} + +void TransferQueue::initGLResources(int width, int height) +{ + android::Mutex::Autolock lock(m_transferQueueItemLocks); + if (!m_sharedSurfaceTextureId) { + glGenTextures(1, &m_sharedSurfaceTextureId); + sp bufferQueue(new BufferQueue(true)); + m_sharedSurfaceTexture = +#if GPU_UPLOAD_WITHOUT_DRAW + new android::SurfaceTexture(m_sharedSurfaceTextureId, true, + GL_TEXTURE_2D, false, bufferQueue); +#else + new android::SurfaceTexture(m_sharedSurfaceTextureId, true, + GL_TEXTURE_EXTERNAL_OES, true, + bufferQueue); +#endif + m_ANW = new android::SurfaceTextureClient(m_sharedSurfaceTexture); + m_sharedSurfaceTexture->setSynchronousMode(true); + + int extraBuffersNeeded = 0; + m_ANW->query(m_ANW.get(), NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, + &extraBuffersNeeded); + bufferQueue->setBufferCount(m_transferQueueSize + extraBuffersNeeded); + + int result = native_window_set_buffers_geometry(m_ANW.get(), + width, height, HAL_PIXEL_FORMAT_RGBA_8888); + GLUtils::checkSurfaceTextureError("native_window_set_buffers_geometry", result); + result = native_window_set_usage(m_ANW.get(), + GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN); + GLUtils::checkSurfaceTextureError("native_window_set_usage", result); + } + + if (!m_fboID) + glGenFramebuffers(1, &m_fboID); +} + +// When bliting, if the item from the transfer queue is mismatching b/t the +// Tile and the content, then the item is considered as obsolete, and +// the content is discarded. +bool TransferQueue::checkObsolete(const TileTransferData* data) +{ + Tile* baseTilePtr = data->savedTilePtr; + if (!baseTilePtr) { + ALOGV("Invalid savedTilePtr , such that the tile is obsolete"); + return true; + } + + TileTexture* baseTileTexture = baseTilePtr->backTexture(); + if (!baseTileTexture || baseTileTexture != data->savedTileTexturePtr) { + ALOGV("Invalid baseTileTexture %p (vs expected %p), such that the tile is obsolete", + baseTileTexture, data->savedTileTexturePtr); + return true; + } + + return false; +} + +void TransferQueue::blitTileFromQueue(GLuint fboID, TileTexture* destTex, + TileTexture* frontTex, + GLuint srcTexId, GLenum srcTexTarget, + int index) +{ +#if GPU_UPLOAD_WITHOUT_DRAW + glBindFramebuffer(GL_FRAMEBUFFER, fboID); + glBindTexture(GL_TEXTURE_2D, destTex->m_ownTextureId); + + int textureWidth = destTex->getSize().width(); + int textureHeight = destTex->getSize().height(); + + IntRect inval = m_transferQueue[index].invalRect; + bool partialInval = !inval.isEmpty(); + + if (partialInval && frontTex) { + // recopy the previous texture to the new one, as + // the partial update will not cover the entire texture + glFramebufferTexture2D(GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, + frontTex->m_ownTextureId, + 0); + glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, + textureWidth, textureHeight); + } + + glFramebufferTexture2D(GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, + srcTexId, + 0); + + if (!partialInval) { + glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, + textureWidth, textureHeight); + } else { + glCopyTexSubImage2D(GL_TEXTURE_2D, 0, inval.x(), inval.y(), 0, 0, + inval.width(), inval.height()); + } + +#else + // Then set up the FBO and copy the SurfTex content in. + glBindFramebuffer(GL_FRAMEBUFFER, fboID); + glFramebufferTexture2D(GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, + destTex->m_ownTextureId, + 0); + setGLStateForCopy(destTex->getSize().width(), + destTex->getSize().height()); + GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + if (status != GL_FRAMEBUFFER_COMPLETE) { + ALOGV("Error: glCheckFramebufferStatus failed"); + glBindFramebuffer(GL_FRAMEBUFFER, 0); + return; + } + + // Use empty rect to set up the special matrix to draw. + SkRect rect = SkRect::MakeEmpty(); + + TextureQuadData data(srcTexId, GL_NEAREST, srcTexTarget, Blit, 0, 0, 1.0, false); + TilesManager::instance()->shader()->drawQuad(&data); + + // To workaround a sync issue on some platforms, we should insert the sync + // here while in the current FBO. + // This will essentially kick off the GPU command buffer, and the Tex Gen + // thread will then have to wait for this buffer to finish before writing + // into the same memory. + EGLDisplay dpy = eglGetCurrentDisplay(); + if (m_currentDisplay != dpy) + m_currentDisplay = dpy; + if (m_currentDisplay != EGL_NO_DISPLAY) { + if (m_transferQueue[index].m_syncKHR != EGL_NO_SYNC_KHR) + eglDestroySyncKHR(m_currentDisplay, m_transferQueue[index].m_syncKHR); + m_transferQueue[index].m_syncKHR = eglCreateSyncKHR(m_currentDisplay, + EGL_SYNC_FENCE_KHR, + 0); + } + GLUtils::checkEglError("CreateSyncKHR"); +#endif +} + +void TransferQueue::interruptTransferQueue(bool interrupt) +{ + m_transferQueueItemLocks.lock(); + m_interruptedByRemovingOp = interrupt; + if (m_interruptedByRemovingOp) + m_transferQueueItemCond.signal(); + m_transferQueueItemLocks.unlock(); +} + +// This function must be called inside the m_transferQueueItemLocks, for the +// wait, m_interruptedByRemovingOp and getHasGLContext(). +// Only called by updateQueueWithBitmap() for now. +bool TransferQueue::readyForUpdate() +{ + if (!getHasGLContext()) + return false; + // Don't use a while loop since when the WebView tear down, the emptyCount + // will still be 0, and we bailed out b/c of GL context lost. + if (!m_emptyItemCount) { + if (m_interruptedByRemovingOp) + return false; + m_transferQueueItemCond.wait(m_transferQueueItemLocks); + if (m_interruptedByRemovingOp) + return false; + } + + if (!getHasGLContext()) + return false; + + // Disable this wait until we figure out why this didn't work on some + // drivers b/5332112. +#if 0 + if (m_currentUploadType == GpuUpload + && m_currentDisplay != EGL_NO_DISPLAY) { + // Check the GPU fence + EGLSyncKHR syncKHR = m_transferQueue[getNextTransferQueueIndex()].m_syncKHR; + if (syncKHR != EGL_NO_SYNC_KHR) + eglClientWaitSyncKHR(m_currentDisplay, + syncKHR, + EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, + EGL_FOREVER_KHR); + } + GLUtils::checkEglError("WaitSyncKHR"); +#endif + + return true; +} + +// Both getHasGLContext and setHasGLContext should be called within the lock. +bool TransferQueue::getHasGLContext() +{ + return m_hasGLContext; +} + +void TransferQueue::setHasGLContext(bool hasContext) +{ + m_hasGLContext = hasContext; +} + +void TransferQueue::setPendingDiscardWithLock() +{ + android::Mutex::Autolock lock(m_transferQueueItemLocks); + setPendingDiscard(); +} + +void TransferQueue::emptyQueue() +{ + android::Mutex::Autolock lock(m_transferQueueItemLocks); + setPendingDiscard(); + cleanupPendingDiscard(); + cleanupGLResources(); +} + +// Set all the content in the queue to pendingDiscard, after this, there will +// be nothing added to the queue, and this can be called in any thread. +// However, in order to discard the content in the Surface Texture using +// updateTexImage, cleanupPendingDiscard need to be called on the UI thread. +// Must be called within a m_transferQueueItemLocks. +void TransferQueue::setPendingDiscard() +{ + for (int i = 0 ; i < m_transferQueueSize; i++) + if (m_transferQueue[i].status == pendingBlit) + m_transferQueue[i].status = pendingDiscard; + + m_pureColorTileQueue.clear(); + + bool GLContextExisted = getHasGLContext(); + // Unblock the Tex Gen thread first before Tile Page deletion. + // Otherwise, there will be a deadlock while removing operations. + setHasGLContext(false); + + // Only signal once when GL context lost. + if (GLContextExisted) + m_transferQueueItemCond.signal(); +} + +void TransferQueue::updatePureColorTiles() +{ + for (unsigned int i = 0 ; i < m_pureColorTileQueue.size(); i++) { + TileTransferData* data = &m_pureColorTileQueue[i]; + if (data->status == pendingBlit) { + TileTexture* destTexture = 0; + bool obsoleteTile = checkObsolete(data); + if (!obsoleteTile) { + destTexture = data->savedTilePtr->backTexture(); + destTexture->setPureColor(data->pureColor); + destTexture->transferComplete(); + } + } else if (data->status == emptyItem || data->status == pendingDiscard) { + // The queue should be clear instead of setting to different status. + ALOGV("Warning: Don't expect an emptyItem here."); + } + } + m_pureColorTileQueue.clear(); +} + +// Call on UI thread to copy from the shared Surface Texture to the Tile's texture. +void TransferQueue::updateDirtyTiles() +{ + android::Mutex::Autolock lock(m_transferQueueItemLocks); + + cleanupPendingDiscard(); + if (!getHasGLContext()) + setHasGLContext(true); + + // Check the pure color tile first, since it is simpler. + updatePureColorTiles(); + + // Start from the oldest item, we call the updateTexImage to retrive + // the texture and blit that into each Tile's texture. + const int nextItemIndex = getNextTransferQueueIndex(); + int index = nextItemIndex; + bool usedFboForUpload = false; + for (int k = 0; k < m_transferQueueSize ; k++) { + if (m_transferQueue[index].status == pendingBlit) { + bool obsoleteTile = checkObsolete(&m_transferQueue[index]); + // Save the needed info, update the Surf Tex, clean up the item in + // the queue. Then either move on to next item or copy the content. + TileTexture* destTexture = 0; + TileTexture* frontTexture = 0; + if (!obsoleteTile) { + destTexture = m_transferQueue[index].savedTilePtr->backTexture(); + // while destTexture is guaranteed to not be null, frontTexture + // might be (first transfer) + frontTexture = m_transferQueue[index].savedTilePtr->frontTexture(); + } + + if (m_transferQueue[index].uploadType == GpuUpload) { + status_t result = m_sharedSurfaceTexture->updateTexImage(); + if (result != OK) + ALOGE("unexpected error: updateTexImage return %d", result); + } + m_transferQueue[index].savedTilePtr = 0; + m_transferQueue[index].status = emptyItem; + if (obsoleteTile) { + ALOGV("Warning: the texture is obsolete for this baseTile"); + index = (index + 1) % m_transferQueueSize; + continue; + } + + // guarantee that we have a texture to blit into + destTexture->requireGLTexture(); + + if (m_transferQueue[index].uploadType == CpuUpload) { + // Here we just need to upload the bitmap content to the GL Texture + GLUtils::updateTextureWithBitmap(destTexture->m_ownTextureId, + *m_transferQueue[index].bitmap, + m_transferQueue[index].invalRect); + } else { + if (!usedFboForUpload) { + saveGLState(); + usedFboForUpload = true; + } + blitTileFromQueue(m_fboID, destTexture, frontTexture, + m_sharedSurfaceTextureId, + m_sharedSurfaceTexture->getCurrentTextureTarget(), + index); + } + + destTexture->setPure(false); + destTexture->transferComplete(); + + ALOGV("Blit tile x, y %d %d with dest texture %p to destTexture->m_ownTextureId %d", + m_transferQueue[index].savedTilePtr, + destTexture, + destTexture->m_ownTextureId); + } + index = (index + 1) % m_transferQueueSize; + } + + // Clean up FBO setup. Doing this for both CPU/GPU upload can make the + // dynamic switch possible. Moving this out from the loop can save some + // milli-seconds. + if (usedFboForUpload) { + glBindFramebuffer(GL_FRAMEBUFFER, 0); // rebind the standard FBO + restoreGLState(); + GLUtils::checkGlError("updateDirtyTiles"); + } + + m_emptyItemCount = m_transferQueueSize; + m_transferQueueItemCond.signal(); +} + +void TransferQueue::updateQueueWithBitmap(const TileRenderInfo* renderInfo, + const SkBitmap& bitmap) +{ + if (!tryUpdateQueueWithBitmap(renderInfo, bitmap)) { + // failed placing bitmap in queue, discard tile's texture so it will be + // re-enqueued (and repainted) + Tile* tile = renderInfo->baseTile; + if (tile) + tile->backTextureTransferFail(); + } +} + +bool TransferQueue::tryUpdateQueueWithBitmap(const TileRenderInfo* renderInfo, + const SkBitmap& bitmap) +{ + // This lock need to cover the full update since it is possible that queue + // will be cleaned up in the middle of this update without the lock. + // The Surface Texture will not block us since the readyForUpdate will check + // availability of the slots in the queue first. + android::Mutex::Autolock lock(m_transferQueueItemLocks); + bool ready = readyForUpdate(); + TextureUploadType currentUploadType = m_currentUploadType; + if (!ready) { + ALOGV("Quit bitmap update: not ready! for tile x y %d %d", + renderInfo->x, renderInfo->y); + return false; + } + if (currentUploadType == GpuUpload) { + // a) Dequeue the Surface Texture and write into the buffer + if (!m_ANW.get()) { + ALOGV("ERROR: ANW is null"); + return false; + } + + if (!GLUtils::updateSharedSurfaceTextureWithBitmap(m_ANW.get(), bitmap)) + return false; + } + + // b) After update the Surface Texture, now udpate the transfer queue info. + addItemInTransferQueue(renderInfo, currentUploadType, &bitmap); + + ALOGV("Bitmap updated x, y %d %d, baseTile %p", + renderInfo->x, renderInfo->y, renderInfo->baseTile); + return true; +} + +void TransferQueue::addItemInPureColorQueue(const TileRenderInfo* renderInfo) +{ + // The pure color tiles' queue will be read from UI thread and written in + // Tex Gen thread, thus we need to have a lock here. + android::Mutex::Autolock lock(m_transferQueueItemLocks); + TileTransferData data; + addItemCommon(renderInfo, GpuUpload, &data); + data.pureColor = renderInfo->pureColor; + m_pureColorTileQueue.append(data); +} + +// Translates the info from TileRenderInfo and others to TileTransferData. +// This is used by pure color tiles and normal tiles. +void TransferQueue::addItemCommon(const TileRenderInfo* renderInfo, + TextureUploadType type, + TileTransferData* data) +{ + data->savedTileTexturePtr = renderInfo->baseTile->backTexture(); + data->savedTilePtr = renderInfo->baseTile; + data->status = pendingBlit; + data->uploadType = type; + + IntRect inval(0, 0, 0, 0); + if (renderInfo->invalRect) { + inval.setX(renderInfo->invalRect->fLeft); + inval.setY(renderInfo->invalRect->fTop); + inval.setWidth(renderInfo->invalRect->width()); + inval.setHeight(renderInfo->invalRect->height()); + } + data->invalRect = inval; +} + +// Note that there should be lock/unlock around this function call. +// Currently only called by GLUtils::updateSharedSurfaceTextureWithBitmap. +void TransferQueue::addItemInTransferQueue(const TileRenderInfo* renderInfo, + TextureUploadType type, + const SkBitmap* bitmap) +{ + m_transferQueueIndex = (m_transferQueueIndex + 1) % m_transferQueueSize; + + int index = m_transferQueueIndex; + if (m_transferQueue[index].savedTilePtr + || m_transferQueue[index].status != emptyItem) { + ALOGV("ERROR update a tile which is dirty already @ index %d", index); + } + + TileTransferData* data = &m_transferQueue[index]; + addItemCommon(renderInfo, type, data); + if (type == CpuUpload && bitmap) { + // Lazily create the bitmap + if (!m_transferQueue[index].bitmap) { + m_transferQueue[index].bitmap = new SkBitmap(); + int w = bitmap->width(); + int h = bitmap->height(); + m_transferQueue[index].bitmap->setConfig(bitmap->config(), w, h); + } + bitmap->copyTo(m_transferQueue[index].bitmap, bitmap->config()); + } + + m_emptyItemCount--; +} + +void TransferQueue::setTextureUploadType(TextureUploadType type) +{ + android::Mutex::Autolock lock(m_transferQueueItemLocks); + if (m_currentUploadType == type) + return; + + setPendingDiscard(); + + m_currentUploadType = type; + ALOGD("Now we set the upload to %s", m_currentUploadType == GpuUpload ? "GpuUpload" : "CpuUpload"); +} + +// Note: this need to be called within the lock and on the UI thread. +// Only called by updateDirtyTiles() and emptyQueue() for now +void TransferQueue::cleanupPendingDiscard() +{ + int index = getNextTransferQueueIndex(); + + for (int i = 0 ; i < m_transferQueueSize; i++) { + if (m_transferQueue[index].status == pendingDiscard) { + // No matter what the current upload type is, as long as there has + // been a Surf Tex enqueue operation, this updateTexImage need to + // be called to keep things in sync. + if (m_transferQueue[index].uploadType == GpuUpload) { + status_t result = m_sharedSurfaceTexture->updateTexImage(); + if (result != OK) + ALOGE("unexpected error: updateTexImage return %d", result); + } + + // since tiles in the queue may be from another webview, remove + // their textures so that they will be repainted / retransferred + Tile* tile = m_transferQueue[index].savedTilePtr; + TileTexture* texture = m_transferQueue[index].savedTileTexturePtr; + if (tile && texture && texture->owner() == tile) { + // since tile destruction removes textures on the UI thread, the + // texture->owner ptr guarantees the tile is valid + tile->discardBackTexture(); + ALOGV("transfer queue discarded tile %p, removed texture", tile); + } + + m_transferQueue[index].savedTilePtr = 0; + m_transferQueue[index].savedTileTexturePtr = 0; + m_transferQueue[index].status = emptyItem; + } + index = (index + 1) % m_transferQueueSize; + } +} + +void TransferQueue::saveGLState() +{ + glGetIntegerv(GL_VIEWPORT, m_GLStateBeforeBlit.viewport); + glGetBooleanv(GL_SCISSOR_TEST, m_GLStateBeforeBlit.scissor); + glGetBooleanv(GL_DEPTH_TEST, m_GLStateBeforeBlit.depth); +#ifdef DEBUG + glGetFloatv(GL_COLOR_CLEAR_VALUE, m_GLStateBeforeBlit.clearColor); +#endif +} + +void TransferQueue::setGLStateForCopy(int width, int height) +{ + // Need to match the texture size. + glViewport(0, 0, width, height); + glDisable(GL_SCISSOR_TEST); + glDisable(GL_DEPTH_TEST); + // Clear the content is only for debug purpose. +#ifdef DEBUG + glClearColor(0, 0, 0, 0); + glClear(GL_COLOR_BUFFER_BIT); +#endif +} + +void TransferQueue::restoreGLState() +{ + glViewport(m_GLStateBeforeBlit.viewport[0], + m_GLStateBeforeBlit.viewport[1], + m_GLStateBeforeBlit.viewport[2], + m_GLStateBeforeBlit.viewport[3]); + + if (m_GLStateBeforeBlit.scissor[0]) + glEnable(GL_SCISSOR_TEST); + + if (m_GLStateBeforeBlit.depth[0]) + glEnable(GL_DEPTH_TEST); +#ifdef DEBUG + glClearColor(m_GLStateBeforeBlit.clearColor[0], + m_GLStateBeforeBlit.clearColor[1], + m_GLStateBeforeBlit.clearColor[2], + m_GLStateBeforeBlit.clearColor[3]); +#endif +} + +int TransferQueue::getNextTransferQueueIndex() +{ + return (m_transferQueueIndex + 1) % m_transferQueueSize; +} + +} // namespace WebCore + +#endif // USE(ACCELERATED_COMPOSITING diff --git a/Source/WebCore/platform/graphics/android/rendering/TransferQueue.h b/Source/WebCore/platform/graphics/android/rendering/TransferQueue.h new file mode 100644 index 0000000..65ff116 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/rendering/TransferQueue.h @@ -0,0 +1,234 @@ +/* + * Copyright 2011, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef TransferQueue_h +#define TransferQueue_h + +#if USE(ACCELERATED_COMPOSITING) + +#include "GLUtils.h" +#include "ShaderProgram.h" +#include "SkBitmap.h" +#include +#include + +namespace WebCore { + +class Tile; +class TileTexture; + +struct GLState { + GLint viewport[4]; + GLboolean scissor[1]; + GLboolean depth[1]; + GLfloat clearColor[4]; +}; + + +// While in the queue, the Tile can be re-used, the updated bitmap +// can be discarded. In order to track this obsolete base tiles, we save +// the Tile's Info to make the comparison. +// At the time of base tile's dtor or webview destroy, we want to discard +// all the data in the queue. However, we have to do the Surface Texture +// update in the same GL context as the UI thread. So we mark the status +// as pendingDiscard, and delay the Surface Texture operation to the next +// draw call. + +enum TransferItemStatus { + emptyItem = 0, // S.T. buffer ready for new content + pendingBlit = 1, // Ready for bliting into tile's GL Tex. + pendingDiscard = 2 // Waiting for the next draw call to discard +}; + +enum TextureUploadType { + CpuUpload = 0, + GpuUpload = 1 +}; + +#define DEFAULT_UPLOAD_TYPE GpuUpload + +class TileTransferData { +public: + TileTransferData() + : status(emptyItem) + , savedTilePtr(0) + , savedTileTexturePtr(0) + , uploadType(DEFAULT_UPLOAD_TYPE) + , bitmap(0) + , m_syncKHR(EGL_NO_SYNC_KHR) + { + } + + ~TileTransferData() + { + // Bitmap will be created lazily, need to delete them at dtor. + delete bitmap; + } + + TransferItemStatus status; + Tile* savedTilePtr; + TileTexture* savedTileTexturePtr; + IntRect invalRect; + TextureUploadType uploadType; + // This is only useful in Cpu upload code path, so it will be dynamically + // lazily allocated. + SkBitmap* bitmap; + + // Specific data to the pure color tiles' queue. + Color pureColor; + + // Sync object for GPU fence, this is the only the info passed from UI + // thread to Tex Gen thread. The reason of having this is due to the + // missing sync mechanism on Surface Texture on some vendor. b/5122031. + // Bascially the idea is that when UI thread utilize one buffer from + // the surface texture, we'll need to kick off the GPU commands, and only + // when those particular commands finish, we could write into this buffer + // again in Tex Gen thread. + EGLSyncKHR m_syncKHR; +}; + +class TransferQueue { +public: + TransferQueue(bool useMinimalMem); + ~TransferQueue(); + + // This will be called by the browser through nativeSetProperty + void setTextureUploadType(TextureUploadType type); + void cleanupGLResources(); + void updateDirtyTiles(); + + void initGLResources(int width, int height); + + // insert the bitmap into the queue, mark the tile dirty if failing + void updateQueueWithBitmap(const TileRenderInfo* renderInfo, + const SkBitmap& bitmap); + + void addItemInTransferQueue(const TileRenderInfo* info, + TextureUploadType type, + const SkBitmap* bitmap); + // Check if the item @ index is ready for update. + // The lock will be done when returning true. + bool readyForUpdate(); + + void interruptTransferQueue(bool); + + void lockQueue() { m_transferQueueItemLocks.lock(); } + void unlockQueue() { m_transferQueueItemLocks.unlock(); } + + void addItemInPureColorQueue(const TileRenderInfo* renderInfo); + + void setPendingDiscardWithLock(); + void emptyQueue(); + + bool needsInit() { return !m_sharedSurfaceTextureId; } + // This queue can be accessed from UI and TexGen thread, therefore, we need + // a lock to protect its access + TileTransferData* m_transferQueue; + + android::sp m_ANW; + + // EGL wrapper around m_ANW for use by the GaneshRenderer + EGLSurface m_eglSurface; + +private: + // return true if successfully inserted into queue + bool tryUpdateQueueWithBitmap(const TileRenderInfo* renderInfo, + const SkBitmap& bitmap); + bool getHasGLContext(); + void setHasGLContext(bool hasContext); + + int getNextTransferQueueIndex(); + + // Save and restore the GL State while switching from/to FBO. + void saveGLState(); + void setGLStateForCopy(int width, int height); + void restoreGLState(); + + // Check the current transfer queue item is obsolete or not. + bool checkObsolete(const TileTransferData* data); + + void setPendingDiscard(); + // Before each draw call and the blit operation, clean up all the + // pendingDiscard items. + void cleanupPendingDiscard(); + + void blitTileFromQueue(GLuint fboID, TileTexture* destTex, + TileTexture* frontTex, + GLuint srcTexId, GLenum srcTexTarget, + int index); + + void addItemCommon(const TileRenderInfo* renderInfo, + TextureUploadType type, TileTransferData* data); + + void updatePureColorTiles(); + // Note that the m_transferQueueIndex only changed in the TexGen thread + // where we are going to move on to update the next item in the queue. + int m_transferQueueIndex; + + GLuint m_fboID; // The FBO used for copy the SurfTex to each tile + + GLuint m_sharedSurfaceTextureId; + + // GLContext can be lost when WebView destroyed. + bool m_hasGLContext; + + GLState m_GLStateBeforeBlit; + android::sp m_sharedSurfaceTexture; + + int m_emptyItemCount; + + bool m_interruptedByRemovingOp; + + // We are using wait/signal to handle our own queue sync. + // First of all, if we don't have our own lock, then while WebView is + // destroyed, the UI thread will wait for the Tex Gen to get out from + // dequeue operation, which will not succeed. B/c at this moment, we + // already lost the GL Context. + // Now we maintain a counter, which is m_emptyItemCount. When this reach + // 0, then we need the Tex Gen thread to wait. UI thread can signal this + // wait after calling updateTexImage at the draw call , or after WebView + // is destroyed. + android::Mutex m_transferQueueItemLocks; + android::Condition m_transferQueueItemCond; + + EGLDisplay m_currentDisplay; + + // This should be GpuUpload for production, but for debug purpose or working + // around driver/HW issue, we can set it to CpuUpload. + TextureUploadType m_currentUploadType; + + // The non-pure-color tile are 1 to 1 mapping with Surface Texture which is + // resource limited. To get better performance, it is better to separate + // the pure color tile into another queue. + WTF::Vector m_pureColorTileQueue; + + // The number of items transfer queue can buffer up. + int m_transferQueueSize; +}; + +} // namespace WebCore + +#endif // USE(ACCELERATED_COMPOSITING) +#endif // TransferQueue_h diff --git a/Source/WebCore/platform/graphics/android/utils/ClassTracker.cpp b/Source/WebCore/platform/graphics/android/utils/ClassTracker.cpp new file mode 100644 index 0000000..98e33d9 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/utils/ClassTracker.cpp @@ -0,0 +1,121 @@ +/* + * Copyright 2010, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define LOG_TAG "ClassTracker" +#define LOG_NDEBUG 1 + +#include "config.h" +#include "ClassTracker.h" + +#include "AndroidLog.h" +#include "LayerAndroid.h" +#include "TilesManager.h" + +#include + +#define DEBUG_LAYERS +#undef DEBUG_LAYERS + +namespace WebCore { + +ClassTracker* ClassTracker::instance() +{ + if (!gInstance) + gInstance = new ClassTracker(); + return gInstance; +} + +ClassTracker* ClassTracker::gInstance = 0; + +void ClassTracker::increment(String name) +{ + android::Mutex::Autolock lock(m_lock); + int value = 0; + if (m_classes.contains(name)) + value = m_classes.get(name); + + m_classes.set(name, value + 1); +} + +void ClassTracker::decrement(String name) +{ + android::Mutex::Autolock lock(m_lock); + int value = 0; + if (m_classes.contains(name)) + value = m_classes.get(name); + + m_classes.set(name, value - 1); +} + +void ClassTracker::add(LayerAndroid* layer) +{ + android::Mutex::Autolock lock(m_lock); + m_layers.append(layer); +} + +void ClassTracker::remove(LayerAndroid* layer) +{ + android::Mutex::Autolock lock(m_lock); + m_layers.remove(m_layers.find(layer)); +} + +void ClassTracker::show() +{ + android::Mutex::Autolock lock(m_lock); + ALOGD("*** Tracking %d classes ***", m_classes.size()); + for (HashMap::iterator iter = m_classes.begin(); iter != m_classes.end(); ++iter) { + ALOGD("class %s has %d instances", + iter->first.latin1().data(), iter->second); + } + ALOGD("*** %d Layers ***", m_layers.size()); + int nbTextures = 0; + int nbAllocatedTextures = 0; + int nbLayerTextures = 0; + int nbAllocatedLayerTextures = 0; + float textureSize = 256 * 256 * 4 / 1024.0 / 1024.0; + TilesManager::instance()->gatherTexturesNumbers(&nbTextures, &nbAllocatedTextures, + &nbLayerTextures, &nbAllocatedLayerTextures); + ALOGD("*** textures: %d/%d (%.2f Mb), layer textures: %d/%d (%.2f Mb) : total used %.2f Mb", + nbAllocatedTextures, nbTextures, + nbAllocatedTextures * textureSize, + nbAllocatedLayerTextures, nbLayerTextures, + nbAllocatedLayerTextures * textureSize, + (nbAllocatedTextures + nbAllocatedLayerTextures) * textureSize); + +#ifdef DEBUG_LAYERS + for (unsigned int i = 0; i < m_layers.size(); i++) { + LayerAndroid* layer = m_layers[i]; + ALOGD("[%d/%d] layer %x (%.2f, %.2f) of type %d, refcount(%d) has texture %x has image ref %x (%x) root: %x parent: %x", + i, m_layers.size(), layer, + layer->getWidth(), layer->getHeight(), + layer->type(), layer->getRefCnt(), + layer->texture(), layer->imageRef(), + layer->imageTexture(), (LayerAndroid*) layer->getRootLayer(), + (LayerAndroid*) layer->getParent()); + } +#endif +} + +} // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/utils/ClassTracker.h b/Source/WebCore/platform/graphics/android/utils/ClassTracker.h new file mode 100644 index 0000000..d169883 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/utils/ClassTracker.h @@ -0,0 +1,58 @@ +/* + * Copyright 2010, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ClassTracker_h +#define ClassTracker_h + +#include +#include +#include + +#define DEBUG_COUNT // Add instances tracking +#undef DEBUG_COUNT + +namespace WebCore { + +class LayerAndroid; + +class ClassTracker { +public: + static ClassTracker* instance(); + void show(); + void increment(String name); + void decrement(String name); + void add(LayerAndroid*); + void remove(LayerAndroid*); +private: + ClassTracker() {}; + HashMap m_classes; + Vector m_layers; + static ClassTracker* gInstance; + android::Mutex m_lock; +}; + +} + +#endif // ClassTracker_h diff --git a/Source/WebCore/platform/graphics/android/utils/TestExport.h b/Source/WebCore/platform/graphics/android/utils/TestExport.h new file mode 100644 index 0000000..15d7cc3 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/utils/TestExport.h @@ -0,0 +1,32 @@ +/* + * Copyright 2011, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef TestExport_h +#define TestExport_h + +// classes used outside of the .so, in tests, are declared with this attribute +#define TEST_EXPORT __attribute__((visibility("default"))) + +#endif // #define TestExport_h -- cgit v1.1