From cd57cc5a246367c2558fefa04ae9eca8f4d545d2 Mon Sep 17 00:00:00 2001 From: "enne@chromium.org" Date: Fri, 12 Oct 2012 22:43:41 +0000 Subject: [cc] Rename all cc/ filenames to Chromium style BUG=155413 Review URL: https://codereview.chromium.org/11122003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@161671 0039d316-1c4b-4281-b951-d872f2087c98 --- cc/BitmapCanvasLayerTextureUpdater.cpp | 89 -- cc/BitmapCanvasLayerTextureUpdater.h | 57 +- cc/BitmapSkPictureCanvasLayerTextureUpdater.cpp | 84 -- cc/BitmapSkPictureCanvasLayerTextureUpdater.h | 45 +- cc/CCActiveAnimation.cpp | 212 --- cc/CCActiveAnimation.h | 159 +- cc/CCAnimationCurve.cpp | 33 - cc/CCAnimationCurve.h | 54 +- cc/CCAnimationEvents.h | 35 +- cc/CCAppendQuadsData.h | 34 +- cc/CCCheckerboardDrawQuad.cpp | 28 - cc/CCCheckerboardDrawQuad.h | 31 +- cc/CCCompletionEvent.h | 62 +- cc/CCDamageTracker.cpp | 349 ----- cc/CCDamageTracker.h | 63 +- cc/CCDebugBorderDrawQuad.cpp | 32 - cc/CCDebugBorderDrawQuad.h | 33 +- cc/CCDebugRectHistory.cpp | 120 -- cc/CCDebugRectHistory.h | 85 +- cc/CCDelayBasedTimeSource.cpp | 232 --- cc/CCDelayBasedTimeSource.h | 79 +- cc/CCDelegatedRendererLayerImpl.cpp | 185 --- cc/CCDelegatedRendererLayerImpl.h | 48 +- cc/CCDirectRenderer.cpp | 237 --- cc/CCDirectRenderer.h | 103 +- cc/CCDrawQuad.cpp | 100 -- cc/CCDrawQuad.h | 94 +- cc/CCFontAtlas.cpp | 73 - cc/CCFontAtlas.h | 68 +- cc/CCFrameRateController.cpp | 161 -- cc/CCFrameRateController.h | 82 +- cc/CCFrameRateCounter.cpp | 132 -- cc/CCFrameRateCounter.h | 70 +- cc/CCGraphicsContext.h | 16 +- cc/CCHeadsUpDisplayLayerImpl.cpp | 296 ---- cc/CCHeadsUpDisplayLayerImpl.h | 55 +- cc/CCIOSurfaceDrawQuad.cpp | 30 - cc/CCIOSurfaceDrawQuad.h | 40 +- cc/CCIOSurfaceLayerImpl.cpp | 118 -- cc/CCIOSurfaceLayerImpl.h | 41 +- cc/CCInputHandler.h | 83 +- cc/CCKeyframedAnimationCurve.cpp | 223 --- cc/CCKeyframedAnimationCurve.h | 107 +- cc/CCLayerAnimationController.cpp | 407 ------ cc/CCLayerAnimationController.h | 110 +- cc/CCLayerImpl.cpp | 685 --------- cc/CCLayerImpl.h | 399 +---- cc/CCLayerIterator.cpp | 153 -- cc/CCLayerIterator.h | 206 +-- cc/CCLayerQuad.cpp | 74 - cc/CCLayerQuad.h | 106 +- cc/CCLayerSorter.cpp | 445 ------ cc/CCLayerSorter.h | 92 +- cc/CCLayerTilingData.cpp | 158 -- cc/CCLayerTilingData.h | 101 +- cc/CCLayerTreeHost.cpp | 861 ----------- cc/CCLayerTreeHost.h | 297 +--- cc/CCLayerTreeHostClient.h | 41 +- cc/CCLayerTreeHostCommon.cpp | 865 ----------- cc/CCLayerTreeHostCommon.h | 96 +- cc/CCLayerTreeHostImpl.cpp | 1462 ------------------- cc/CCLayerTreeHostImpl.h | 356 +---- cc/CCMathUtil.cpp | 379 ----- cc/CCMathUtil.h | 105 +- cc/CCOcclusionTracker.cpp | 482 ------ cc/CCOcclusionTracker.h | 103 +- cc/CCOverdrawMetrics.cpp | 190 --- cc/CCOverdrawMetrics.h | 95 +- cc/CCPageScaleAnimation.cpp | 159 -- cc/CCPageScaleAnimation.h | 74 +- cc/CCPrioritizedTexture.cpp | 180 --- cc/CCPrioritizedTexture.h | 140 +- cc/CCPrioritizedTextureManager.cpp | 410 ------ cc/CCPrioritizedTextureManager.h | 157 +- cc/CCPriorityCalculator.cpp | 84 -- cc/CCPriorityCalculator.h | 32 +- cc/CCProxy.cpp | 105 -- cc/CCProxy.h | 129 +- cc/CCQuadCuller.cpp | 94 -- cc/CCQuadCuller.h | 35 +- cc/CCQuadSink.h | 28 +- cc/CCRenderPass.cpp | 106 -- cc/CCRenderPass.h | 140 +- cc/CCRenderPassDrawQuad.cpp | 50 - cc/CCRenderPassDrawQuad.h | 51 +- cc/CCRenderPassSink.h | 18 +- cc/CCRenderSurface.cpp | 253 ---- cc/CCRenderSurface.h | 132 +- cc/CCRenderSurfaceFilters.cpp | 446 ------ cc/CCRenderSurfaceFilters.h | 32 +- cc/CCRenderer.cpp | 21 - cc/CCRenderer.h | 82 +- cc/CCRendererGL.cpp | 1530 -------------------- cc/CCRendererGL.h | 240 +-- cc/CCRendererSoftware.cpp | 279 ---- cc/CCRendererSoftware.h | 74 +- cc/CCRenderingStats.h | 36 +- cc/CCResourceProvider.cpp | 708 --------- cc/CCResourceProvider.h | 273 +--- cc/CCScheduler.cpp | 192 --- cc/CCScheduler.h | 109 +- cc/CCSchedulerStateMachine.cpp | 317 ---- cc/CCSchedulerStateMachine.h | 161 +- cc/CCScopedTexture.cpp | 51 - cc/CCScopedTexture.h | 44 +- cc/CCScopedThreadProxy.cpp | 21 - cc/CCScopedThreadProxy.h | 74 +- cc/CCScrollbarAnimationController.cpp | 97 -- cc/CCScrollbarAnimationController.h | 62 +- cc/CCScrollbarAnimationControllerLinearFade.cpp | 77 - cc/CCScrollbarAnimationControllerLinearFade.h | 37 +- cc/CCScrollbarGeometryFixedThumb.cpp | 94 -- cc/CCScrollbarGeometryFixedThumb.h | 37 +- cc/CCScrollbarGeometryStub.cpp | 109 -- cc/CCScrollbarGeometryStub.h | 50 +- cc/CCScrollbarLayerImpl.cpp | 206 --- cc/CCScrollbarLayerImpl.h | 110 +- cc/CCSettings.cpp | 50 - cc/CCSettings.h | 38 +- cc/CCSharedQuadState.cpp | 35 - cc/CCSharedQuadState.h | 31 +- cc/CCSingleThreadProxy.cpp | 385 ----- cc/CCSingleThreadProxy.h | 134 +- cc/CCSolidColorDrawQuad.cpp | 32 - cc/CCSolidColorDrawQuad.h | 31 +- cc/CCSolidColorLayerImpl.cpp | 53 - cc/CCSolidColorLayerImpl.h | 32 +- cc/CCStreamVideoDrawQuad.cpp | 29 - cc/CCStreamVideoDrawQuad.h | 33 +- cc/CCTexture.cpp | 32 - cc/CCTexture.h | 40 +- cc/CCTextureDrawQuad.cpp | 36 - cc/CCTextureDrawQuad.h | 39 +- cc/CCTextureLayerImpl.cpp | 84 -- cc/CCTextureLayerImpl.h | 46 +- cc/CCTextureUpdateController.cpp | 197 --- cc/CCTextureUpdateController.h | 75 +- cc/CCTextureUpdateQueue.cpp | 75 - cc/CCTextureUpdateQueue.h | 45 +- cc/CCThread.h | 43 +- cc/CCThreadProxy.cpp | 957 ------------ cc/CCThreadProxy.h | 185 +-- cc/CCThreadTask.h | 305 +--- cc/CCTileDrawQuad.cpp | 39 - cc/CCTileDrawQuad.h | 52 +- cc/CCTiledLayerImpl.cpp | 253 ---- cc/CCTiledLayerImpl.h | 62 +- cc/CCTimeSource.h | 40 +- cc/CCTimer.cpp | 80 - cc/CCTimer.h | 41 +- cc/CCTimingFunction.cpp | 74 - cc/CCTimingFunction.h | 60 +- cc/CCVideoLayerImpl.cpp | 391 ----- cc/CCVideoLayerImpl.h | 87 +- cc/CCYUVVideoDrawQuad.cpp | 30 - cc/CCYUVVideoDrawQuad.h | 34 +- cc/CanvasLayerTextureUpdater.cpp | 70 - cc/CanvasLayerTextureUpdater.h | 39 +- cc/ContentLayerChromium.cpp | 113 -- cc/ContentLayerChromium.h | 67 +- cc/ContentLayerChromiumClient.h | 22 +- cc/DelegatedRendererLayerChromium.cpp | 33 - cc/DelegatedRendererLayerChromium.h | 24 +- ...ameBufferSkPictureCanvasLayerTextureUpdater.cpp | 119 -- cc/FrameBufferSkPictureCanvasLayerTextureUpdater.h | 52 +- cc/GeometryBinding.cpp | 61 - cc/GeometryBinding.h | 48 +- cc/HeadsUpDisplayLayerChromium.cpp | 75 - cc/HeadsUpDisplayLayerChromium.h | 36 +- cc/IOSurfaceLayerChromium.cpp | 56 - cc/IOSurfaceLayerChromium.h | 36 +- cc/ImageLayerChromium.cpp | 163 --- cc/ImageLayerChromium.h | 48 +- cc/LayerChromium.cpp | 799 ---------- cc/LayerChromium.h | 390 +---- cc/LayerPainterChromium.h | 26 +- cc/LayerTextureSubImage.cpp | 117 -- cc/LayerTextureSubImage.h | 46 +- cc/LayerTextureUpdater.cpp | 25 - cc/LayerTextureUpdater.h | 69 +- cc/PlatformColor.h | 58 +- cc/ProgramBinding.cpp | 147 -- cc/ProgramBinding.h | 84 +- cc/RateLimiter.cpp | 87 -- cc/RateLimiter.h | 53 +- cc/RenderSurfaceChromium.cpp | 42 - cc/RenderSurfaceChromium.h | 107 +- cc/ScrollbarLayerChromium.cpp | 290 ---- cc/ScrollbarLayerChromium.h | 68 +- cc/ShaderChromium.cpp | 888 ------------ cc/ShaderChromium.h | 353 +---- cc/SkPictureCanvasLayerTextureUpdater.cpp | 47 - cc/SkPictureCanvasLayerTextureUpdater.h | 48 +- cc/SolidColorLayerChromium.cpp | 36 - cc/SolidColorLayerChromium.h | 31 +- cc/TextureCopier.cpp | 101 -- cc/TextureCopier.h | 68 +- cc/TextureLayerChromium.cpp | 135 -- cc/TextureLayerChromium.h | 77 +- cc/TextureLayerChromiumClient.h | 29 +- cc/TextureUploader.h | 30 +- cc/ThrottledTextureUploader.cpp | 186 --- cc/ThrottledTextureUploader.h | 74 +- cc/TiledLayerChromium.cpp | 820 ----------- cc/TiledLayerChromium.h | 105 +- cc/TreeSynchronizer.cpp | 112 -- cc/TreeSynchronizer.h | 41 +- cc/UnthrottledTextureUploader.cpp | 30 - cc/UnthrottledTextureUploader.h | 34 +- cc/VideoLayerChromium.cpp | 37 - cc/VideoLayerChromium.h | 39 +- cc/active_animation.cc | 212 +++ cc/active_animation.h | 158 ++ cc/animation_curve.cc | 33 + cc/animation_curve.h | 53 + cc/animation_events.h | 34 + cc/append_quads_data.h | 33 + cc/bitmap_canvas_layer_texture_updater.cc | 89 ++ cc/bitmap_canvas_layer_texture_updater.h | 56 +- ...itmap_skpicture_canvas_layer_texture_updater.cc | 84 ++ cc/bitmap_skpicture_canvas_layer_texture_updater.h | 44 +- cc/canvas_layer_texture_updater.cc | 70 + cc/canvas_layer_texture_updater.h | 38 +- cc/cc.gyp | 194 +-- cc/checkerboard_draw_quad.cc | 28 + cc/checkerboard_draw_quad.h | 30 + cc/completion_event.h | 61 +- cc/content_layer.cc | 113 ++ cc/content_layer.h | 66 +- cc/content_layer_client.h | 21 + cc/damage_tracker.cc | 349 +++++ cc/damage_tracker.h | 62 +- cc/debug_border_draw_quad.cc | 32 + cc/debug_border_draw_quad.h | 32 + cc/debug_rect_history.cc | 120 ++ cc/debug_rect_history.h | 84 ++ cc/delay_based_time_source.cc | 232 +++ cc/delay_based_time_source.h | 78 +- cc/delegated_renderer_layer.cc | 33 + cc/delegated_renderer_layer.h | 23 + cc/delegated_renderer_layer_impl.cc | 185 +++ cc/delegated_renderer_layer_impl.h | 47 + cc/direct_renderer.cc | 237 +++ cc/direct_renderer.h | 102 ++ cc/draw_quad.cc | 100 ++ cc/draw_quad.h | 93 ++ cc/font_atlas.cc | 73 + cc/font_atlas.h | 67 + ...uffer_skpicture_canvas_layer_texture_updater.cc | 119 ++ ...buffer_skpicture_canvas_layer_texture_updater.h | 51 +- cc/frame_rate_controller.cc | 161 ++ cc/frame_rate_controller.h | 81 +- cc/frame_rate_counter.cc | 132 ++ cc/frame_rate_counter.h | 69 + cc/geometry_binding.cc | 61 + cc/geometry_binding.h | 47 +- cc/gl_renderer.cc | 1530 ++++++++++++++++++++ cc/gl_renderer.h | 239 ++- cc/graphics_context.h | 15 + cc/heads_up_display_layer.cc | 75 + cc/heads_up_display_layer.h | 35 + cc/heads_up_display_layer_impl.cc | 296 ++++ cc/heads_up_display_layer_impl.h | 54 + cc/image_layer.cc | 163 +++ cc/image_layer.h | 47 +- cc/input_handler.h | 82 +- cc/io_surface_draw_quad.cc | 30 + cc/io_surface_draw_quad.h | 39 + cc/io_surface_layer.cc | 56 + cc/io_surface_layer.h | 35 + cc/io_surface_layer_impl.cc | 118 ++ cc/io_surface_layer_impl.h | 40 + cc/keyframed_animation_curve.cc | 223 +++ cc/keyframed_animation_curve.h | 106 ++ cc/layer.cc | 799 ++++++++++ cc/layer.h | 389 ++++- cc/layer_animation_controller.cc | 407 ++++++ cc/layer_animation_controller.h | 109 ++ cc/layer_impl.cc | 685 +++++++++ cc/layer_impl.h | 398 ++++- cc/layer_iterator.cc | 153 ++ cc/layer_iterator.h | 205 +++ cc/layer_painter.h | 25 +- cc/layer_quad.cc | 74 + cc/layer_quad.h | 105 +- cc/layer_sorter.cc | 445 ++++++ cc/layer_sorter.h | 91 +- cc/layer_texture_sub_image.cc | 117 ++ cc/layer_texture_sub_image.h | 45 +- cc/layer_texture_updater.cc | 25 + cc/layer_texture_updater.h | 68 +- cc/layer_tiling_data.cc | 158 ++ cc/layer_tiling_data.h | 100 +- cc/layer_tree_host.cc | 861 +++++++++++ cc/layer_tree_host.h | 296 +++- cc/layer_tree_host_client.h | 40 + cc/layer_tree_host_common.cc | 865 +++++++++++ cc/layer_tree_host_common.h | 95 +- cc/layer_tree_host_impl.cc | 1462 +++++++++++++++++++ cc/layer_tree_host_impl.h | 355 ++++- cc/math_util.cc | 379 +++++ cc/math_util.h | 104 ++ cc/occlusion_tracker.cc | 482 ++++++ cc/occlusion_tracker.h | 102 ++ cc/overdraw_metrics.cc | 190 +++ cc/overdraw_metrics.h | 94 ++ cc/page_scale_animation.cc | 159 ++ cc/page_scale_animation.h | 73 +- cc/platform_color.h | 57 +- cc/prioritized_texture.cc | 180 +++ cc/prioritized_texture.h | 139 ++ cc/prioritized_texture_manager.cc | 410 ++++++ cc/prioritized_texture_manager.h | 156 ++ cc/priority_calculator.cc | 84 ++ cc/priority_calculator.h | 31 +- cc/program_binding.cc | 147 ++ cc/program_binding.h | 83 +- cc/proxy.cc | 105 ++ cc/proxy.h | 128 +- cc/quad_culler.cc | 94 ++ cc/quad_culler.h | 34 + cc/quad_sink.h | 27 + cc/rate_limiter.cc | 87 ++ cc/rate_limiter.h | 52 +- cc/render_pass.cc | 106 ++ cc/render_pass.h | 139 +- cc/render_pass_draw_quad.cc | 50 + cc/render_pass_draw_quad.h | 50 +- cc/render_pass_sink.h | 17 + cc/render_surface.cc | 42 + cc/render_surface.h | 106 +- cc/render_surface_filters.cc | 446 ++++++ cc/render_surface_filters.h | 31 + cc/render_surface_impl.cc | 253 ++++ cc/render_surface_impl.h | 131 +- cc/renderer.cc | 21 + cc/renderer.h | 81 ++ cc/rendering_stats.h | 35 + cc/resource_provider.cc | 708 +++++++++ cc/resource_provider.h | 272 ++++ cc/scheduler.cc | 192 +++ cc/scheduler.h | 108 +- cc/scheduler_state_machine.cc | 317 ++++ cc/scheduler_state_machine.h | 160 +- cc/scoped_texture.cc | 51 + cc/scoped_texture.h | 43 + cc/scoped_thread_proxy.cc | 21 + cc/scoped_thread_proxy.h | 73 +- cc/scrollbar_animation_controller.cc | 97 ++ cc/scrollbar_animation_controller.h | 61 + cc/scrollbar_animation_controller_linear_fade.cc | 77 + cc/scrollbar_animation_controller_linear_fade.h | 36 + cc/scrollbar_geometry_fixed_thumb.cc | 94 ++ cc/scrollbar_geometry_fixed_thumb.h | 36 + cc/scrollbar_geometry_stub.cc | 109 ++ cc/scrollbar_geometry_stub.h | 49 + cc/scrollbar_layer.cc | 290 ++++ cc/scrollbar_layer.h | 67 + cc/scrollbar_layer_impl.cc | 206 +++ cc/scrollbar_layer_impl.h | 109 ++ cc/settings.cc | 50 + cc/settings.h | 37 + cc/shader.cc | 888 ++++++++++++ cc/shader.h | 352 ++++- cc/shared_quad_state.cc | 35 + cc/shared_quad_state.h | 30 + cc/single_thread_proxy.cc | 385 +++++ cc/single_thread_proxy.h | 133 +- cc/skpicture_canvas_layer_texture_updater.cc | 47 + cc/skpicture_canvas_layer_texture_updater.h | 47 +- cc/software_renderer.cc | 279 ++++ cc/software_renderer.h | 73 + cc/solid_color_draw_quad.cc | 32 + cc/solid_color_draw_quad.h | 30 + cc/solid_color_layer.cc | 36 + cc/solid_color_layer.h | 30 + cc/solid_color_layer_impl.cc | 53 + cc/solid_color_layer_impl.h | 31 + cc/stream_video_draw_quad.cc | 29 + cc/stream_video_draw_quad.h | 32 + cc/stubs/Extensions3D.h | 25 +- cc/stubs/Extensions3DChromium.h | 54 +- cc/stubs/FloatPoint.h | 51 +- cc/stubs/FloatPoint3D.h | 50 +- cc/stubs/FloatQuad.h | 56 +- cc/stubs/FloatRect.h | 56 +- cc/stubs/FloatSize.h | 43 +- cc/stubs/GraphicsContext3D.h | 74 +- cc/stubs/GraphicsTypes3D.h | 18 +- cc/stubs/IntPoint.h | 40 +- cc/stubs/IntRect.h | 41 +- cc/stubs/IntSize.h | 34 +- cc/stubs/NotImplemented.h | 10 +- cc/stubs/SkiaUtils.h | 17 +- cc/stubs/TilingData.h | 18 +- cc/stubs/TraceEvent.h | 10 +- cc/stubs/UnitBezier.h | 14 +- cc/stubs/extensions_3d.h | 24 +- cc/stubs/extensions_3d_chromium.h | 53 +- cc/stubs/float_point.h | 50 +- cc/stubs/float_point_3d.h | 49 +- cc/stubs/float_quad.h | 55 +- cc/stubs/float_rect.h | 55 +- cc/stubs/float_size.h | 42 +- cc/stubs/graphics_context_3d.h | 73 +- cc/stubs/graphics_types_3d.h | 17 +- cc/stubs/int_point.h | 39 +- cc/stubs/int_rect.h | 40 +- cc/stubs/int_size.h | 33 +- cc/stubs/not_implemented.h | 9 +- cc/stubs/skia_utils.h | 16 +- cc/stubs/tiling_data.h | 17 +- cc/stubs/trace_event.h | 9 +- cc/stubs/unit_bezier.h | 13 +- cc/texture.cc | 32 + cc/texture.h | 39 + cc/texture_copier.cc | 101 ++ cc/texture_copier.h | 67 + cc/texture_draw_quad.cc | 36 + cc/texture_draw_quad.h | 38 + cc/texture_layer.cc | 135 ++ cc/texture_layer.h | 76 +- cc/texture_layer_client.h | 28 + cc/texture_layer_impl.cc | 84 ++ cc/texture_layer_impl.h | 45 + cc/texture_update_controller.cc | 197 +++ cc/texture_update_controller.h | 74 + cc/texture_update_queue.cc | 75 + cc/texture_update_queue.h | 44 + cc/texture_uploader.h | 29 + cc/thread.h | 42 +- cc/thread_proxy.cc | 957 ++++++++++++ cc/thread_proxy.h | 184 ++- cc/thread_task.h | 304 +++- cc/throttled_texture_uploader.cc | 186 +++ cc/throttled_texture_uploader.h | 73 + cc/tile_draw_quad.cc | 39 + cc/tile_draw_quad.h | 51 + cc/tiled_layer.cc | 820 +++++++++++ cc/tiled_layer.h | 104 +- cc/tiled_layer_impl.cc | 253 ++++ cc/tiled_layer_impl.h | 61 +- cc/time_source.h | 39 +- cc/timer.cc | 80 + cc/timer.h | 40 +- cc/timing_function.cc | 74 + cc/timing_function.h | 59 + cc/tree_synchronizer.cc | 112 ++ cc/tree_synchronizer.h | 40 +- cc/unthrottled_texture_uploader.cc | 30 + cc/unthrottled_texture_uploader.h | 33 + cc/video_layer.cc | 37 + cc/video_layer.h | 38 +- cc/video_layer_impl.cc | 391 +++++ cc/video_layer_impl.h | 86 ++ cc/yuv_video_draw_quad.cc | 30 + cc/yuv_video_draw_quad.h | 33 + 457 files changed, 32407 insertions(+), 32014 deletions(-) delete mode 100644 cc/BitmapCanvasLayerTextureUpdater.cpp delete mode 100644 cc/BitmapSkPictureCanvasLayerTextureUpdater.cpp delete mode 100644 cc/CCActiveAnimation.cpp delete mode 100644 cc/CCAnimationCurve.cpp delete mode 100644 cc/CCCheckerboardDrawQuad.cpp delete mode 100644 cc/CCDamageTracker.cpp delete mode 100644 cc/CCDebugBorderDrawQuad.cpp delete mode 100644 cc/CCDebugRectHistory.cpp delete mode 100644 cc/CCDelayBasedTimeSource.cpp delete mode 100644 cc/CCDelegatedRendererLayerImpl.cpp delete mode 100644 cc/CCDirectRenderer.cpp delete mode 100644 cc/CCDrawQuad.cpp delete mode 100644 cc/CCFontAtlas.cpp delete mode 100644 cc/CCFrameRateController.cpp delete mode 100644 cc/CCFrameRateCounter.cpp delete mode 100644 cc/CCHeadsUpDisplayLayerImpl.cpp delete mode 100644 cc/CCIOSurfaceDrawQuad.cpp delete mode 100644 cc/CCIOSurfaceLayerImpl.cpp delete mode 100644 cc/CCKeyframedAnimationCurve.cpp delete mode 100644 cc/CCLayerAnimationController.cpp delete mode 100644 cc/CCLayerImpl.cpp delete mode 100644 cc/CCLayerIterator.cpp delete mode 100644 cc/CCLayerQuad.cpp delete mode 100644 cc/CCLayerSorter.cpp delete mode 100644 cc/CCLayerTilingData.cpp delete mode 100644 cc/CCLayerTreeHost.cpp delete mode 100644 cc/CCLayerTreeHostCommon.cpp delete mode 100644 cc/CCLayerTreeHostImpl.cpp delete mode 100644 cc/CCMathUtil.cpp delete mode 100644 cc/CCOcclusionTracker.cpp delete mode 100644 cc/CCOverdrawMetrics.cpp delete mode 100644 cc/CCPageScaleAnimation.cpp delete mode 100644 cc/CCPrioritizedTexture.cpp delete mode 100644 cc/CCPrioritizedTextureManager.cpp delete mode 100644 cc/CCPriorityCalculator.cpp delete mode 100644 cc/CCProxy.cpp delete mode 100644 cc/CCQuadCuller.cpp delete mode 100644 cc/CCRenderPass.cpp delete mode 100644 cc/CCRenderPassDrawQuad.cpp delete mode 100644 cc/CCRenderSurface.cpp delete mode 100644 cc/CCRenderSurfaceFilters.cpp delete mode 100644 cc/CCRenderer.cpp delete mode 100644 cc/CCRendererGL.cpp delete mode 100644 cc/CCRendererSoftware.cpp delete mode 100644 cc/CCResourceProvider.cpp delete mode 100644 cc/CCScheduler.cpp delete mode 100644 cc/CCSchedulerStateMachine.cpp delete mode 100644 cc/CCScopedTexture.cpp delete mode 100644 cc/CCScopedThreadProxy.cpp delete mode 100644 cc/CCScrollbarAnimationController.cpp delete mode 100644 cc/CCScrollbarAnimationControllerLinearFade.cpp delete mode 100644 cc/CCScrollbarGeometryFixedThumb.cpp delete mode 100644 cc/CCScrollbarGeometryStub.cpp delete mode 100644 cc/CCScrollbarLayerImpl.cpp delete mode 100644 cc/CCSettings.cpp delete mode 100644 cc/CCSharedQuadState.cpp delete mode 100644 cc/CCSingleThreadProxy.cpp delete mode 100644 cc/CCSolidColorDrawQuad.cpp delete mode 100644 cc/CCSolidColorLayerImpl.cpp delete mode 100644 cc/CCStreamVideoDrawQuad.cpp delete mode 100644 cc/CCTexture.cpp delete mode 100644 cc/CCTextureDrawQuad.cpp delete mode 100644 cc/CCTextureLayerImpl.cpp delete mode 100644 cc/CCTextureUpdateController.cpp delete mode 100644 cc/CCTextureUpdateQueue.cpp delete mode 100644 cc/CCThreadProxy.cpp delete mode 100644 cc/CCTileDrawQuad.cpp delete mode 100644 cc/CCTiledLayerImpl.cpp delete mode 100644 cc/CCTimer.cpp delete mode 100644 cc/CCTimingFunction.cpp delete mode 100644 cc/CCVideoLayerImpl.cpp delete mode 100644 cc/CCYUVVideoDrawQuad.cpp delete mode 100644 cc/CanvasLayerTextureUpdater.cpp delete mode 100644 cc/ContentLayerChromium.cpp delete mode 100644 cc/DelegatedRendererLayerChromium.cpp delete mode 100644 cc/FrameBufferSkPictureCanvasLayerTextureUpdater.cpp delete mode 100644 cc/GeometryBinding.cpp delete mode 100644 cc/HeadsUpDisplayLayerChromium.cpp delete mode 100644 cc/IOSurfaceLayerChromium.cpp delete mode 100644 cc/ImageLayerChromium.cpp delete mode 100644 cc/LayerChromium.cpp delete mode 100644 cc/LayerTextureSubImage.cpp delete mode 100644 cc/LayerTextureUpdater.cpp delete mode 100644 cc/ProgramBinding.cpp delete mode 100644 cc/RateLimiter.cpp delete mode 100644 cc/RenderSurfaceChromium.cpp delete mode 100644 cc/ScrollbarLayerChromium.cpp delete mode 100644 cc/ShaderChromium.cpp delete mode 100644 cc/SkPictureCanvasLayerTextureUpdater.cpp delete mode 100644 cc/SolidColorLayerChromium.cpp delete mode 100644 cc/TextureCopier.cpp delete mode 100644 cc/TextureLayerChromium.cpp delete mode 100644 cc/ThrottledTextureUploader.cpp delete mode 100644 cc/TiledLayerChromium.cpp delete mode 100644 cc/TreeSynchronizer.cpp delete mode 100644 cc/UnthrottledTextureUploader.cpp delete mode 100644 cc/VideoLayerChromium.cpp create mode 100644 cc/active_animation.cc create mode 100644 cc/animation_curve.cc create mode 100644 cc/bitmap_canvas_layer_texture_updater.cc create mode 100644 cc/bitmap_skpicture_canvas_layer_texture_updater.cc create mode 100644 cc/canvas_layer_texture_updater.cc create mode 100644 cc/checkerboard_draw_quad.cc create mode 100644 cc/content_layer.cc create mode 100644 cc/damage_tracker.cc create mode 100644 cc/debug_border_draw_quad.cc create mode 100644 cc/debug_rect_history.cc create mode 100644 cc/delay_based_time_source.cc create mode 100644 cc/delegated_renderer_layer.cc create mode 100644 cc/delegated_renderer_layer_impl.cc create mode 100644 cc/direct_renderer.cc create mode 100644 cc/draw_quad.cc create mode 100644 cc/font_atlas.cc create mode 100644 cc/frame_buffer_skpicture_canvas_layer_texture_updater.cc create mode 100644 cc/frame_rate_controller.cc create mode 100644 cc/frame_rate_counter.cc create mode 100644 cc/geometry_binding.cc create mode 100644 cc/gl_renderer.cc create mode 100644 cc/heads_up_display_layer.cc create mode 100644 cc/heads_up_display_layer_impl.cc create mode 100644 cc/image_layer.cc create mode 100644 cc/io_surface_draw_quad.cc create mode 100644 cc/io_surface_layer.cc create mode 100644 cc/io_surface_layer_impl.cc create mode 100644 cc/keyframed_animation_curve.cc create mode 100644 cc/layer.cc create mode 100644 cc/layer_animation_controller.cc create mode 100644 cc/layer_impl.cc create mode 100644 cc/layer_iterator.cc create mode 100644 cc/layer_quad.cc create mode 100644 cc/layer_sorter.cc create mode 100644 cc/layer_texture_sub_image.cc create mode 100644 cc/layer_texture_updater.cc create mode 100644 cc/layer_tiling_data.cc create mode 100644 cc/layer_tree_host.cc create mode 100644 cc/layer_tree_host_common.cc create mode 100644 cc/layer_tree_host_impl.cc create mode 100644 cc/math_util.cc create mode 100644 cc/occlusion_tracker.cc create mode 100644 cc/overdraw_metrics.cc create mode 100644 cc/page_scale_animation.cc create mode 100644 cc/prioritized_texture.cc create mode 100644 cc/prioritized_texture_manager.cc create mode 100644 cc/priority_calculator.cc create mode 100644 cc/program_binding.cc create mode 100644 cc/proxy.cc create mode 100644 cc/quad_culler.cc create mode 100644 cc/rate_limiter.cc create mode 100644 cc/render_pass.cc create mode 100644 cc/render_pass_draw_quad.cc create mode 100644 cc/render_surface.cc create mode 100644 cc/render_surface_filters.cc create mode 100644 cc/render_surface_impl.cc create mode 100644 cc/renderer.cc create mode 100644 cc/resource_provider.cc create mode 100644 cc/scheduler.cc create mode 100644 cc/scheduler_state_machine.cc create mode 100644 cc/scoped_texture.cc create mode 100644 cc/scoped_thread_proxy.cc create mode 100644 cc/scrollbar_animation_controller.cc create mode 100644 cc/scrollbar_animation_controller_linear_fade.cc create mode 100644 cc/scrollbar_geometry_fixed_thumb.cc create mode 100644 cc/scrollbar_geometry_stub.cc create mode 100644 cc/scrollbar_layer.cc create mode 100644 cc/scrollbar_layer_impl.cc create mode 100644 cc/settings.cc create mode 100644 cc/shader.cc create mode 100644 cc/shared_quad_state.cc create mode 100644 cc/single_thread_proxy.cc create mode 100644 cc/skpicture_canvas_layer_texture_updater.cc create mode 100644 cc/software_renderer.cc create mode 100644 cc/solid_color_draw_quad.cc create mode 100644 cc/solid_color_layer.cc create mode 100644 cc/solid_color_layer_impl.cc create mode 100644 cc/stream_video_draw_quad.cc create mode 100644 cc/texture.cc create mode 100644 cc/texture_copier.cc create mode 100644 cc/texture_draw_quad.cc create mode 100644 cc/texture_layer.cc create mode 100644 cc/texture_layer_impl.cc create mode 100644 cc/texture_update_controller.cc create mode 100644 cc/texture_update_queue.cc create mode 100644 cc/thread_proxy.cc create mode 100644 cc/throttled_texture_uploader.cc create mode 100644 cc/tile_draw_quad.cc create mode 100644 cc/tiled_layer.cc create mode 100644 cc/tiled_layer_impl.cc create mode 100644 cc/timer.cc create mode 100644 cc/timing_function.cc create mode 100644 cc/tree_synchronizer.cc create mode 100644 cc/unthrottled_texture_uploader.cc create mode 100644 cc/video_layer.cc create mode 100644 cc/video_layer_impl.cc create mode 100644 cc/yuv_video_draw_quad.cc diff --git a/cc/BitmapCanvasLayerTextureUpdater.cpp b/cc/BitmapCanvasLayerTextureUpdater.cpp deleted file mode 100644 index 3231b7d..0000000 --- a/cc/BitmapCanvasLayerTextureUpdater.cpp +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - - -#include "config.h" - -#if USE(ACCELERATED_COMPOSITING) - -#include "BitmapCanvasLayerTextureUpdater.h" - -#include "LayerPainterChromium.h" -#include "PlatformColor.h" -#include "skia/ext/platform_canvas.h" - -namespace cc { - -BitmapCanvasLayerTextureUpdater::Texture::Texture(BitmapCanvasLayerTextureUpdater* textureUpdater, scoped_ptr texture) - : LayerTextureUpdater::Texture(texture.Pass()) - , m_textureUpdater(textureUpdater) -{ -} - -BitmapCanvasLayerTextureUpdater::Texture::~Texture() -{ -} - -void BitmapCanvasLayerTextureUpdater::Texture::updateRect(CCResourceProvider* resourceProvider, const IntRect& sourceRect, const IntSize& destOffset) -{ - textureUpdater()->updateTextureRect(resourceProvider, texture(), sourceRect, destOffset); -} - -PassRefPtr BitmapCanvasLayerTextureUpdater::create(PassOwnPtr painter) -{ - return adoptRef(new BitmapCanvasLayerTextureUpdater(painter)); -} - -BitmapCanvasLayerTextureUpdater::BitmapCanvasLayerTextureUpdater(PassOwnPtr painter) - : CanvasLayerTextureUpdater(painter) - , m_opaque(false) -{ -} - -BitmapCanvasLayerTextureUpdater::~BitmapCanvasLayerTextureUpdater() -{ -} - -PassOwnPtr BitmapCanvasLayerTextureUpdater::createTexture(CCPrioritizedTextureManager* manager) -{ - return adoptPtr(new Texture(this, CCPrioritizedTexture::create(manager))); -} - -LayerTextureUpdater::SampledTexelFormat BitmapCanvasLayerTextureUpdater::sampledTexelFormat(GC3Denum textureFormat) -{ - // The component order may be bgra if we uploaded bgra pixels to rgba textures. - return PlatformColor::sameComponentOrder(textureFormat) ? - LayerTextureUpdater::SampledTexelFormatRGBA : LayerTextureUpdater::SampledTexelFormatBGRA; -} - -void BitmapCanvasLayerTextureUpdater::prepareToUpdate(const IntRect& contentRect, const IntSize& tileSize, float contentsWidthScale, float contentsHeightScale, IntRect& resultingOpaqueRect, CCRenderingStats& stats) -{ - if (m_canvasSize != contentRect.size()) { - m_canvasSize = contentRect.size(); - m_canvas = adoptPtr(skia::CreateBitmapCanvas(m_canvasSize.width(), m_canvasSize.height(), m_opaque)); - } - - paintContents(m_canvas.get(), contentRect, contentsWidthScale, contentsHeightScale, resultingOpaqueRect, stats); -} - -void BitmapCanvasLayerTextureUpdater::updateTextureRect(CCResourceProvider* resourceProvider, CCPrioritizedTexture* texture, const IntRect& sourceRect, const IntSize& destOffset) -{ - const SkBitmap& bitmap = m_canvas->getDevice()->accessBitmap(false); - bitmap.lockPixels(); - - texture->upload(resourceProvider, static_cast(bitmap.getPixels()), contentRect(), sourceRect, destOffset); - bitmap.unlockPixels(); -} - -void BitmapCanvasLayerTextureUpdater::setOpaque(bool opaque) -{ - if (opaque != m_opaque) { - m_canvas.clear(); - m_canvasSize = IntSize(); - } - m_opaque = opaque; -} - -} // namespace cc -#endif // USE(ACCELERATED_COMPOSITING) diff --git a/cc/BitmapCanvasLayerTextureUpdater.h b/cc/BitmapCanvasLayerTextureUpdater.h index 8cf4e25..bf8f6fe 100644 --- a/cc/BitmapCanvasLayerTextureUpdater.h +++ b/cc/BitmapCanvasLayerTextureUpdater.h @@ -1,57 +1,6 @@ -// Copyright 2011 The Chromium Authors. All rights reserved. +// Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. - -#ifndef BitmapCanvasLayerTextureUpdater_h -#define BitmapCanvasLayerTextureUpdater_h - -#if USE(ACCELERATED_COMPOSITING) - -#include "CanvasLayerTextureUpdater.h" - -class SkCanvas; - -namespace cc { - -class LayerPainterChromium; - -// This class rasterizes the contentRect into a skia bitmap canvas. It then updates -// textures by copying from the canvas into the texture, using MapSubImage if -// possible. -class BitmapCanvasLayerTextureUpdater : public CanvasLayerTextureUpdater { -public: - class Texture : public LayerTextureUpdater::Texture { - public: - Texture(BitmapCanvasLayerTextureUpdater*, scoped_ptr); - virtual ~Texture(); - - virtual void updateRect(CCResourceProvider*, const IntRect& sourceRect, const IntSize& destOffset) OVERRIDE; - - private: - BitmapCanvasLayerTextureUpdater* textureUpdater() { return m_textureUpdater; } - - BitmapCanvasLayerTextureUpdater* m_textureUpdater; - }; - - static PassRefPtr create(PassOwnPtr); - virtual ~BitmapCanvasLayerTextureUpdater(); - - virtual PassOwnPtr createTexture(CCPrioritizedTextureManager*) OVERRIDE; - virtual SampledTexelFormat sampledTexelFormat(GC3Denum textureFormat) OVERRIDE; - virtual void prepareToUpdate(const IntRect& contentRect, const IntSize& tileSize, float contentsWidthScale, float contentsHeightScale, IntRect& resultingOpaqueRect, CCRenderingStats&) OVERRIDE; - void updateTextureRect(CCResourceProvider*, CCPrioritizedTexture*, const IntRect& sourceRect, const IntSize& destOffset); - - virtual void setOpaque(bool) OVERRIDE; - -protected: - explicit BitmapCanvasLayerTextureUpdater(PassOwnPtr); - - OwnPtr m_canvas; - IntSize m_canvasSize; - bool m_opaque; -}; - -} // namespace cc -#endif // USE(ACCELERATED_COMPOSITING) -#endif // BitmapCanvasLayerTextureUpdater_h +// Temporary forwarding header +#include "cc/bitmap_canvas_layer_texture_updater.h" diff --git a/cc/BitmapSkPictureCanvasLayerTextureUpdater.cpp b/cc/BitmapSkPictureCanvasLayerTextureUpdater.cpp deleted file mode 100644 index 93c8483..0000000 --- a/cc/BitmapSkPictureCanvasLayerTextureUpdater.cpp +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - - -#include "config.h" - -#if USE(ACCELERATED_COMPOSITING) - -#include "BitmapSkPictureCanvasLayerTextureUpdater.h" - -#include "CCRenderingStats.h" -#include "LayerPainterChromium.h" -#include "PlatformColor.h" -#include "SkCanvas.h" -#include "SkDevice.h" -#include - -namespace cc { - -BitmapSkPictureCanvasLayerTextureUpdater::Texture::Texture(BitmapSkPictureCanvasLayerTextureUpdater* textureUpdater, scoped_ptr texture) - : CanvasLayerTextureUpdater::Texture(texture.Pass()) - , m_textureUpdater(textureUpdater) -{ -} - -void BitmapSkPictureCanvasLayerTextureUpdater::Texture::prepareRect(const IntRect& sourceRect, CCRenderingStats& stats) -{ - m_bitmap.setConfig(SkBitmap::kARGB_8888_Config, sourceRect.width(), sourceRect.height()); - m_bitmap.allocPixels(); - m_bitmap.setIsOpaque(m_textureUpdater->layerIsOpaque()); - SkDevice device(m_bitmap); - SkCanvas canvas(&device); - double paintBeginTime = monotonicallyIncreasingTime(); - textureUpdater()->paintContentsRect(&canvas, sourceRect, stats); - stats.totalPaintTimeInSeconds += monotonicallyIncreasingTime() - paintBeginTime; -} - -void BitmapSkPictureCanvasLayerTextureUpdater::Texture::updateRect(CCResourceProvider* resourceProvider, const IntRect& sourceRect, const IntSize& destOffset) -{ - m_bitmap.lockPixels(); - texture()->upload(resourceProvider, static_cast(m_bitmap.getPixels()), sourceRect, sourceRect, destOffset); - m_bitmap.unlockPixels(); - m_bitmap.reset(); -} - -PassRefPtr BitmapSkPictureCanvasLayerTextureUpdater::create(PassOwnPtr painter) -{ - return adoptRef(new BitmapSkPictureCanvasLayerTextureUpdater(painter)); -} - -BitmapSkPictureCanvasLayerTextureUpdater::BitmapSkPictureCanvasLayerTextureUpdater(PassOwnPtr painter) - : SkPictureCanvasLayerTextureUpdater(painter) -{ -} - -BitmapSkPictureCanvasLayerTextureUpdater::~BitmapSkPictureCanvasLayerTextureUpdater() -{ -} - -PassOwnPtr BitmapSkPictureCanvasLayerTextureUpdater::createTexture(CCPrioritizedTextureManager* manager) -{ - return adoptPtr(new Texture(this, CCPrioritizedTexture::create(manager))); -} - -LayerTextureUpdater::SampledTexelFormat BitmapSkPictureCanvasLayerTextureUpdater::sampledTexelFormat(GC3Denum textureFormat) -{ - // The component order may be bgra if we uploaded bgra pixels to rgba textures. - return PlatformColor::sameComponentOrder(textureFormat) ? - LayerTextureUpdater::SampledTexelFormatRGBA : LayerTextureUpdater::SampledTexelFormatBGRA; -} - -void BitmapSkPictureCanvasLayerTextureUpdater::paintContentsRect(SkCanvas* canvas, const IntRect& sourceRect, CCRenderingStats& stats) -{ - // Translate the origin of contentRect to that of sourceRect. - canvas->translate(contentRect().x() - sourceRect.x(), - contentRect().y() - sourceRect.y()); - double rasterizeBeginTime = monotonicallyIncreasingTime(); - drawPicture(canvas); - stats.totalRasterizeTimeInSeconds += monotonicallyIncreasingTime() - rasterizeBeginTime; -} - -} // namespace cc -#endif // USE(ACCELERATED_COMPOSITING) diff --git a/cc/BitmapSkPictureCanvasLayerTextureUpdater.h b/cc/BitmapSkPictureCanvasLayerTextureUpdater.h index 140f9be..2e6dc44 100644 --- a/cc/BitmapSkPictureCanvasLayerTextureUpdater.h +++ b/cc/BitmapSkPictureCanvasLayerTextureUpdater.h @@ -1,45 +1,6 @@ -// Copyright 2011 The Chromium Authors. All rights reserved. +// Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. - -#ifndef BitmapSkPictureCanvasLayerTextureUpdater_h -#define BitmapSkPictureCanvasLayerTextureUpdater_h - -#if USE(ACCELERATED_COMPOSITING) -#include "SkBitmap.h" -#include "SkPictureCanvasLayerTextureUpdater.h" - -namespace cc { - -// This class records the contentRect into an SkPicture, then software rasterizes -// the SkPicture into bitmaps for each tile. This implements CCSettings::perTilePainting. -class BitmapSkPictureCanvasLayerTextureUpdater : public SkPictureCanvasLayerTextureUpdater { -public: - class Texture : public CanvasLayerTextureUpdater::Texture { - public: - Texture(BitmapSkPictureCanvasLayerTextureUpdater*, scoped_ptr); - - virtual void prepareRect(const IntRect& sourceRect, CCRenderingStats&) OVERRIDE; - virtual void updateRect(CCResourceProvider*, const IntRect& sourceRect, const IntSize& destOffset) OVERRIDE; - - private: - BitmapSkPictureCanvasLayerTextureUpdater* textureUpdater() { return m_textureUpdater; } - - SkBitmap m_bitmap; - BitmapSkPictureCanvasLayerTextureUpdater* m_textureUpdater; - }; - - static PassRefPtr create(PassOwnPtr); - virtual ~BitmapSkPictureCanvasLayerTextureUpdater(); - - virtual PassOwnPtr createTexture(CCPrioritizedTextureManager*) OVERRIDE; - virtual SampledTexelFormat sampledTexelFormat(GC3Denum textureFormat) OVERRIDE; - void paintContentsRect(SkCanvas*, const IntRect& sourceRect, CCRenderingStats&); - -private: - explicit BitmapSkPictureCanvasLayerTextureUpdater(PassOwnPtr); -}; -} // namespace cc -#endif // USE(ACCELERATED_COMPOSITING) -#endif // BitmapSkPictureCanvasLayerTextureUpdater_h +// Temporary forwarding header +#include "cc/bitmap_skpicture_canvas_layer_texture_updater.h" diff --git a/cc/CCActiveAnimation.cpp b/cc/CCActiveAnimation.cpp deleted file mode 100644 index b1817d1..0000000 --- a/cc/CCActiveAnimation.cpp +++ /dev/null @@ -1,212 +0,0 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "config.h" - -#include "CCActiveAnimation.h" - -#include "CCAnimationCurve.h" -#include "TraceEvent.h" -#ifdef LOG -#undef LOG -#endif -#include "base/string_util.h" -#include - -namespace { - -// This should match the RunState enum. -static const char* const s_runStateNames[] = { - "WaitingForNextTick", - "WaitingForTargetAvailability", - "WaitingForStartTime", - "WaitingForDeletion", - "Running", - "Paused", - "Finished", - "Aborted" -}; - -COMPILE_ASSERT(static_cast(cc::CCActiveAnimation::RunStateEnumSize) == arraysize(s_runStateNames), RunState_names_match_enum); - -// This should match the TargetProperty enum. -static const char* const s_targetPropertyNames[] = { - "Transform", - "Opacity" -}; - -COMPILE_ASSERT(static_cast(cc::CCActiveAnimation::TargetPropertyEnumSize) == arraysize(s_targetPropertyNames), TargetProperty_names_match_enum); - -} // namespace - -namespace cc { - -scoped_ptr CCActiveAnimation::create(scoped_ptr curve, int animationId, int groupId, TargetProperty targetProperty) -{ - return make_scoped_ptr(new CCActiveAnimation(curve.Pass(), animationId, groupId, targetProperty)); -} - -CCActiveAnimation::CCActiveAnimation(scoped_ptr curve, int animationId, int groupId, TargetProperty targetProperty) - : m_curve(curve.Pass()) - , m_id(animationId) - , m_group(groupId) - , m_targetProperty(targetProperty) - , m_runState(WaitingForTargetAvailability) - , m_iterations(1) - , m_startTime(0) - , m_alternatesDirection(false) - , m_timeOffset(0) - , m_needsSynchronizedStartTime(false) - , m_suspended(false) - , m_pauseTime(0) - , m_totalPausedTime(0) - , m_isControllingInstance(false) -{ -} - -CCActiveAnimation::~CCActiveAnimation() -{ - if (m_runState == Running || m_runState == Paused) - setRunState(Aborted, 0); -} - -void CCActiveAnimation::setRunState(RunState runState, double monotonicTime) -{ - if (m_suspended) - return; - - char nameBuffer[256]; - base::snprintf(nameBuffer, sizeof(nameBuffer), "%s-%d%s", s_targetPropertyNames[m_targetProperty], m_group, m_isControllingInstance ? "(impl)" : ""); - - bool isWaitingToStart = m_runState == WaitingForNextTick - || m_runState == WaitingForTargetAvailability - || m_runState == WaitingForStartTime; - - if (isWaitingToStart && runState == Running) - TRACE_EVENT_ASYNC_BEGIN1("cc", "CCActiveAnimation", this, "Name", TRACE_STR_COPY(nameBuffer)); - - bool wasFinished = isFinished(); - - const char* oldRunStateName = s_runStateNames[m_runState]; - - if (runState == Running && m_runState == Paused) - m_totalPausedTime += monotonicTime - m_pauseTime; - else if (runState == Paused) - m_pauseTime = monotonicTime; - m_runState = runState; - - const char* newRunStateName = s_runStateNames[runState]; - - if (!wasFinished && isFinished()) - TRACE_EVENT_ASYNC_END0("cc", "CCActiveAnimation", this); - - char stateBuffer[256]; - base::snprintf(stateBuffer, sizeof(stateBuffer), "%s->%s", oldRunStateName, newRunStateName); - - TRACE_EVENT_INSTANT2("cc", "CCLayerAnimationController::setRunState", "Name", TRACE_STR_COPY(nameBuffer), "State", TRACE_STR_COPY(stateBuffer)); -} - -void CCActiveAnimation::suspend(double monotonicTime) -{ - setRunState(Paused, monotonicTime); - m_suspended = true; -} - -void CCActiveAnimation::resume(double monotonicTime) -{ - m_suspended = false; - setRunState(Running, monotonicTime); -} - -bool CCActiveAnimation::isFinishedAt(double monotonicTime) const -{ - if (isFinished()) - return true; - - if (m_needsSynchronizedStartTime) - return false; - - return m_runState == Running - && m_iterations >= 0 - && m_iterations * m_curve->duration() <= monotonicTime - startTime() - m_totalPausedTime; -} - -double CCActiveAnimation::trimTimeToCurrentIteration(double monotonicTime) const -{ - double trimmed = monotonicTime + m_timeOffset; - - // If we're paused, time is 'stuck' at the pause time. - if (m_runState == Paused) - trimmed = m_pauseTime; - - // Returned time should always be relative to the start time and should subtract - // all time spent paused. - trimmed -= m_startTime + m_totalPausedTime; - - // Zero is always the start of the animation. - if (trimmed <= 0) - return 0; - - // Always return zero if we have no iterations. - if (!m_iterations) - return 0; - - // Don't attempt to trim if we have no duration. - if (m_curve->duration() <= 0) - return 0; - - // If less than an iteration duration, just return trimmed. - if (trimmed < m_curve->duration()) - return trimmed; - - // If greater than or equal to the total duration, return iteration duration. - if (m_iterations >= 0 && trimmed >= m_curve->duration() * m_iterations) { - if (m_alternatesDirection && !(m_iterations % 2)) - return 0; - return m_curve->duration(); - } - - // We need to know the current iteration if we're alternating. - int iteration = static_cast(trimmed / m_curve->duration()); - - // Calculate x where trimmed = x + n * m_curve->duration() for some positive integer n. - trimmed = fmod(trimmed, m_curve->duration()); - - // If we're alternating and on an odd iteration, reverse the direction. - if (m_alternatesDirection && iteration % 2 == 1) - return m_curve->duration() - trimmed; - - return trimmed; -} - -scoped_ptr CCActiveAnimation::clone(InstanceType instanceType) const -{ - return cloneAndInitialize(instanceType, m_runState, m_startTime); -} - -scoped_ptr CCActiveAnimation::cloneAndInitialize(InstanceType instanceType, RunState initialRunState, double startTime) const -{ - scoped_ptr toReturn(new CCActiveAnimation(m_curve->clone(), m_id, m_group, m_targetProperty)); - toReturn->m_runState = initialRunState; - toReturn->m_iterations = m_iterations; - toReturn->m_startTime = startTime; - toReturn->m_pauseTime = m_pauseTime; - toReturn->m_totalPausedTime = m_totalPausedTime; - toReturn->m_timeOffset = m_timeOffset; - toReturn->m_alternatesDirection = m_alternatesDirection; - toReturn->m_isControllingInstance = instanceType == ControllingInstance; - return toReturn.Pass(); -} - -void CCActiveAnimation::pushPropertiesTo(CCActiveAnimation* other) const -{ - // Currently, we only push changes due to pausing and resuming animations on the main thread. - if (m_runState == CCActiveAnimation::Paused || other->m_runState == CCActiveAnimation::Paused) { - other->m_runState = m_runState; - other->m_pauseTime = m_pauseTime; - other->m_totalPausedTime = m_totalPausedTime; - } -} - -} // namespace cc diff --git a/cc/CCActiveAnimation.h b/cc/CCActiveAnimation.h index b8d3607..e5737a8 100644 --- a/cc/CCActiveAnimation.h +++ b/cc/CCActiveAnimation.h @@ -2,160 +2,5 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CCActiveAnimation_h -#define CCActiveAnimation_h - -#include "base/basictypes.h" -#include "base/memory/scoped_ptr.h" - -namespace cc { - -class CCAnimationCurve; - -// A CCActiveAnimation, contains all the state required to play a CCAnimationCurve. -// Specifically, the affected property, the run state (paused, finished, etc.), -// loop count, last pause time, and the total time spent paused. -class CCActiveAnimation { -public: - // Animations begin in one of the 'waiting' states. Animations waiting for the next tick - // will start the next time the controller animates. Animations waiting for target - // availibility will run as soon as their target property is free (and all the animations - // animating with it are also able to run). Animations waiting for their start time to - // come have be scheduled to run at a particular point in time. When this time arrives, - // the controller will move the animations into the Running state. Running animations - // may toggle between Running and Paused, and may be stopped by moving into either the - // Aborted or Finished states. A Finished animation was allowed to run to completion, but - // an Aborted animation was not. - enum RunState { - WaitingForNextTick = 0, - WaitingForTargetAvailability, - WaitingForStartTime, - WaitingForDeletion, - Running, - Paused, - Finished, - Aborted, - // This sentinel must be last. - RunStateEnumSize - }; - - enum TargetProperty { - Transform = 0, - Opacity, - // This sentinel must be last. - TargetPropertyEnumSize - }; - - static scoped_ptr create(scoped_ptr, int animationId, int groupId, TargetProperty); - - virtual ~CCActiveAnimation(); - - int id() const { return m_id; } - int group() const { return m_group; } - TargetProperty targetProperty() const { return m_targetProperty; } - - RunState runState() const { return m_runState; } - void setRunState(RunState, double monotonicTime); - - // This is the number of times that the animation will play. If this - // value is zero the animation will not play. If it is negative, then - // the animation will loop indefinitely. - int iterations() const { return m_iterations; } - void setIterations(int n) { m_iterations = n; } - - double startTime() const { return m_startTime; } - void setStartTime(double monotonicTime) { m_startTime = monotonicTime; } - bool hasSetStartTime() const { return m_startTime; } - - double timeOffset() const { return m_timeOffset; } - void setTimeOffset(double monotonicTime) { m_timeOffset = monotonicTime; } - - void suspend(double monotonicTime); - void resume(double monotonicTime); - - // If alternatesDirection is true, on odd numbered iterations we reverse the curve. - bool alternatesDirection() const { return m_alternatesDirection; } - void setAlternatesDirection(bool alternates) { m_alternatesDirection = alternates; } - - bool isFinishedAt(double monotonicTime) const; - bool isFinished() const { return m_runState == Finished - || m_runState == Aborted - || m_runState == WaitingForDeletion; } - - CCAnimationCurve* curve() { return m_curve.get(); } - const CCAnimationCurve* curve() const { return m_curve.get(); } - - // If this is true, even if the animation is running, it will not be tickable until - // it is given a start time. This is true for animations running on the main thread. - bool needsSynchronizedStartTime() const { return m_needsSynchronizedStartTime; } - void setNeedsSynchronizedStartTime(bool needsSynchronizedStartTime) { m_needsSynchronizedStartTime = needsSynchronizedStartTime; } - - // Takes the given absolute time, and using the start time and the number - // of iterations, returns the relative time in the current iteration. - double trimTimeToCurrentIteration(double monotonicTime) const; - - enum InstanceType { - ControllingInstance = 0, - NonControllingInstance - }; - - scoped_ptr clone(InstanceType) const; - scoped_ptr cloneAndInitialize(InstanceType, RunState initialRunState, double startTime) const; - bool isControllingInstance() const { return m_isControllingInstance; } - - void pushPropertiesTo(CCActiveAnimation*) const; - -private: - CCActiveAnimation(scoped_ptr, int animationId, int groupId, TargetProperty); - - scoped_ptr m_curve; - - // IDs are not necessarily unique. - int m_id; - - // Animations that must be run together are called 'grouped' and have the same group id - // Grouped animations are guaranteed to start at the same time and no other animations - // may animate any of the group's target properties until all animations in the - // group have finished animating. Note: an active animation's group id and target - // property uniquely identify that animation. - int m_group; - - TargetProperty m_targetProperty; - RunState m_runState; - int m_iterations; - double m_startTime; - bool m_alternatesDirection; - - // The time offset effectively pushes the start of the animation back in time. This is - // used for resuming paused animations -- an animation is added with a non-zero time - // offset, causing the animation to skip ahead to the desired point in time. - double m_timeOffset; - - bool m_needsSynchronizedStartTime; - - // When an animation is suspended, it behaves as if it is paused and it also ignores - // all run state changes until it is resumed. This is used for testing purposes. - bool m_suspended; - - // These are used in trimTimeToCurrentIteration to account for time - // spent while paused. This is not included in AnimationState since it - // there is absolutely no need for clients of this controller to know - // about these values. - double m_pauseTime; - double m_totalPausedTime; - - // Animations lead dual lives. An active animation will be conceptually owned by - // two controllers, one on the impl thread and one on the main. In reality, there - // will be two separate CCActiveAnimation instances for the same animation. They - // will have the same group id and the same target property (these two values - // uniquely identify an animation). The instance on the impl thread is the instance - // that ultimately controls the values of the animating layer and so we will refer - // to it as the 'controlling instance'. - bool m_isControllingInstance; - - DISALLOW_COPY_AND_ASSIGN(CCActiveAnimation); -}; - -} // namespace cc - -#endif // CCActiveAnimation_h +// Temporary forwarding header +#include "cc/active_animation.h" diff --git a/cc/CCAnimationCurve.cpp b/cc/CCAnimationCurve.cpp deleted file mode 100644 index 7cd0158..0000000 --- a/cc/CCAnimationCurve.cpp +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "config.h" - -#include "CCAnimationCurve.h" - -namespace cc { - -const CCFloatAnimationCurve* CCAnimationCurve::toFloatAnimationCurve() const -{ - ASSERT(type() == CCAnimationCurve::Float); - return static_cast(this); -} - -CCAnimationCurve::Type CCFloatAnimationCurve::type() const -{ - return Float; -} - -const CCTransformAnimationCurve* CCAnimationCurve::toTransformAnimationCurve() const -{ - ASSERT(type() == CCAnimationCurve::Transform); - return static_cast(this); -} - -CCAnimationCurve::Type CCTransformAnimationCurve::type() const -{ - return Transform; -} - -} // namespace cc diff --git a/cc/CCAnimationCurve.h b/cc/CCAnimationCurve.h index 7ed6e7a..71cd0fa 100644 --- a/cc/CCAnimationCurve.h +++ b/cc/CCAnimationCurve.h @@ -2,55 +2,5 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CCAnimationCurve_h -#define CCAnimationCurve_h - -#include "base/memory/scoped_ptr.h" -#include - -namespace cc { - -class CCFloatAnimationCurve; -class CCTransformAnimationCurve; -class IntSize; -class TransformOperations; - -// An animation curve is a function that returns a value given a time. -// There are currently only two types of curve, float and transform. -class CCAnimationCurve { -public: - enum Type { Float, Transform }; - - virtual ~CCAnimationCurve() { } - - virtual double duration() const = 0; - virtual Type type() const = 0; - virtual scoped_ptr clone() const = 0; - - const CCFloatAnimationCurve* toFloatAnimationCurve() const; - const CCTransformAnimationCurve* toTransformAnimationCurve() const; -}; - -class CCFloatAnimationCurve : public CCAnimationCurve { -public: - virtual ~CCFloatAnimationCurve() { } - - virtual float getValue(double t) const = 0; - - // Partial CCAnimation implementation. - virtual Type type() const OVERRIDE; -}; - -class CCTransformAnimationCurve : public CCAnimationCurve { -public: - virtual ~CCTransformAnimationCurve() { } - - virtual WebKit::WebTransformationMatrix getValue(double t) const = 0; - - // Partial CCAnimation implementation. - virtual Type type() const OVERRIDE; -}; - -} // namespace cc - -#endif // CCAnimation_h +// Temporary forwarding header +#include "cc/animation_curve.h" diff --git a/cc/CCAnimationEvents.h b/cc/CCAnimationEvents.h index 5e86ef7..988f56e 100644 --- a/cc/CCAnimationEvents.h +++ b/cc/CCAnimationEvents.h @@ -2,36 +2,5 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CCAnimationEvents_h -#define CCAnimationEvents_h - -#include - -#include "CCActiveAnimation.h" - -namespace cc { - -struct CCAnimationEvent { - enum Type { Started, Finished }; - - CCAnimationEvent(Type type, int layerId, int groupId, CCActiveAnimation::TargetProperty targetProperty, double monotonicTime) - : type(type) - , layerId(layerId) - , groupId(groupId) - , targetProperty(targetProperty) - , monotonicTime(monotonicTime) - { - } - - Type type; - int layerId; - int groupId; - CCActiveAnimation::TargetProperty targetProperty; - double monotonicTime; -}; - -typedef std::vector CCAnimationEventsVector; - -} // namespace cc - -#endif // CCAnimationEvents_h +// Temporary forwarding header +#include "cc/animation_events.h" diff --git a/cc/CCAppendQuadsData.h b/cc/CCAppendQuadsData.h index b086de0..7a11591 100644 --- a/cc/CCAppendQuadsData.h +++ b/cc/CCAppendQuadsData.h @@ -2,35 +2,5 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CCAppendQuadsData_h -#define CCAppendQuadsData_h - -#include "CCRenderPass.h" - -namespace cc { - -struct CCAppendQuadsData { - CCAppendQuadsData() - : hadOcclusionFromOutsideTargetSurface(false) - , hadMissingTiles(false) - , renderPassId(0, 0) - { - } - - explicit CCAppendQuadsData(CCRenderPass::Id renderPassId) - : hadOcclusionFromOutsideTargetSurface(false) - , hadMissingTiles(false) - , renderPassId(renderPassId) - { - } - - // Set by the QuadCuller. - bool hadOcclusionFromOutsideTargetSurface; - // Set by the layer appending quads. - bool hadMissingTiles; - // Given to the layer appending quads. - const CCRenderPass::Id renderPassId; -}; - -} -#endif // CCCCAppendQuadsData_h +// Temporary forwarding header +#include "cc/append_quads_data.h" diff --git a/cc/CCCheckerboardDrawQuad.cpp b/cc/CCCheckerboardDrawQuad.cpp deleted file mode 100644 index f1b34a3..0000000 --- a/cc/CCCheckerboardDrawQuad.cpp +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "config.h" - -#include "CCCheckerboardDrawQuad.h" - -namespace cc { - -scoped_ptr CCCheckerboardDrawQuad::create(const CCSharedQuadState* sharedQuadState, const IntRect& quadRect, SkColor color) -{ - return make_scoped_ptr(new CCCheckerboardDrawQuad(sharedQuadState, quadRect, color)); -} - -CCCheckerboardDrawQuad::CCCheckerboardDrawQuad(const CCSharedQuadState* sharedQuadState, const IntRect& quadRect, SkColor color) - : CCDrawQuad(sharedQuadState, CCDrawQuad::Checkerboard, quadRect) - , m_color(color) -{ -} - -const CCCheckerboardDrawQuad* CCCheckerboardDrawQuad::materialCast(const CCDrawQuad* quad) -{ - ASSERT(quad->material() == CCDrawQuad::Checkerboard); - return static_cast(quad); -} - -} // namespace cc diff --git a/cc/CCCheckerboardDrawQuad.h b/cc/CCCheckerboardDrawQuad.h index 1ef147f..ceb42db 100644 --- a/cc/CCCheckerboardDrawQuad.h +++ b/cc/CCCheckerboardDrawQuad.h @@ -2,32 +2,5 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CCCheckerboardDrawQuad_h -#define CCCheckerboardDrawQuad_h - -#include "CCDrawQuad.h" -#include "base/memory/scoped_ptr.h" -#include "SkColor.h" - -namespace cc { - -#pragma pack(push, 4) - -class CCCheckerboardDrawQuad : public CCDrawQuad { -public: - static scoped_ptr create(const CCSharedQuadState*, const IntRect&, SkColor); - - SkColor color() const { return m_color; }; - - static const CCCheckerboardDrawQuad* materialCast(const CCDrawQuad*); -private: - CCCheckerboardDrawQuad(const CCSharedQuadState*, const IntRect&, SkColor); - - SkColor m_color; -}; - -#pragma pack(pop) - -} - -#endif +// Temporary forwarding header +#include "cc/checkerboard_draw_quad.h" diff --git a/cc/CCCompletionEvent.h b/cc/CCCompletionEvent.h index 462e4ba..f422075 100644 --- a/cc/CCCompletionEvent.h +++ b/cc/CCCompletionEvent.h @@ -1,62 +1,6 @@ -// Copyright 2011 The Chromium Authors. All rights reserved. +// Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CCCompletionEvent_h -#define CCCompletionEvent_h - -#include "base/synchronization/waitable_event.h" - -namespace cc { - -// Used for making blocking calls from one thread to another. Use only when -// absolutely certain that doing-so will not lead to a deadlock. -// -// It is safe to destroy this object as soon as wait() returns. -class CCCompletionEvent { -public: - CCCompletionEvent() - : m_event(false /* manual_reset */, false /* initially_signaled */) - { -#ifndef NDEBUG - m_waited = false; - m_signaled = false; -#endif - } - - ~CCCompletionEvent() - { - ASSERT(m_waited); - ASSERT(m_signaled); - } - - void wait() - { - ASSERT(!m_waited); -#ifndef NDEBUG - m_waited = true; -#endif - m_event.Wait(); - } - - void signal() - { - ASSERT(!m_signaled); -#ifndef NDEBUG - m_signaled = true; -#endif - m_event.Signal(); - } - -private: - base::WaitableEvent m_event; -#ifndef NDEBUG - // Used to assert that wait() and signal() are each called exactly once. - bool m_waited; - bool m_signaled; -#endif -}; - -} - -#endif +// Temporary forwarding header +#include "cc/completion_event.h" diff --git a/cc/CCDamageTracker.cpp b/cc/CCDamageTracker.cpp deleted file mode 100644 index bd1c31f..0000000 --- a/cc/CCDamageTracker.cpp +++ /dev/null @@ -1,349 +0,0 @@ -// Copyright 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "config.h" - -#if USE(ACCELERATED_COMPOSITING) - -#include "CCDamageTracker.h" - -#include "CCLayerImpl.h" -#include "CCLayerTreeHostCommon.h" -#include "CCMathUtil.h" -#include "CCRenderSurface.h" -#include - -using WebKit::WebTransformationMatrix; - -namespace cc { - -scoped_ptr CCDamageTracker::create() -{ - return make_scoped_ptr(new CCDamageTracker()); -} - -CCDamageTracker::CCDamageTracker() - : m_forceFullDamageNextUpdate(false), - m_currentRectHistory(new RectMap), - m_nextRectHistory(new RectMap) -{ -} - -CCDamageTracker::~CCDamageTracker() -{ -} - -static inline void expandRectWithFilters(FloatRect& rect, const WebKit::WebFilterOperations& filters) -{ - int top, right, bottom, left; - filters.getOutsets(top, right, bottom, left); - rect.move(-left, -top); - rect.expand(left + right, top + bottom); -} - -static inline void expandDamageRectInsideRectWithFilters(FloatRect& damageRect, const FloatRect& preFilterRect, const WebKit::WebFilterOperations& filters) -{ - FloatRect expandedDamageRect = damageRect; - expandRectWithFilters(expandedDamageRect, filters); - FloatRect filterRect = preFilterRect; - expandRectWithFilters(filterRect, filters); - - expandedDamageRect.intersect(filterRect); - damageRect.unite(expandedDamageRect); -} - -void CCDamageTracker::updateDamageTrackingState(const std::vector& layerList, int targetSurfaceLayerID, bool targetSurfacePropertyChangedOnlyFromDescendant, const IntRect& targetSurfaceContentRect, CCLayerImpl* targetSurfaceMaskLayer, const WebKit::WebFilterOperations& filters) -{ - // - // This function computes the "damage rect" of a target surface, and updates the state - // that is used to correctly track damage across frames. The damage rect is the region - // of the surface that may have changed and needs to be redrawn. This can be used to - // scissor what is actually drawn, to save GPU computation and bandwidth. - // - // The surface's damage rect is computed as the union of all possible changes that - // have happened to the surface since the last frame was drawn. This includes: - // - any changes for existing layers/surfaces that contribute to the target surface - // - layers/surfaces that existed in the previous frame, but no longer exist. - // - // The basic algorithm for computing the damage region is as follows: - // - // 1. compute damage caused by changes in active/new layers - // for each layer in the layerList: - // if the layer is actually a renderSurface: - // add the surface's damage to our target surface. - // else - // add the layer's damage to the target surface. - // - // 2. compute damage caused by the target surface's mask, if it exists. - // - // 3. compute damage caused by old layers/surfaces that no longer exist - // for each leftover layer: - // add the old layer/surface bounds to the target surface damage. - // - // 4. combine all partial damage rects to get the full damage rect. - // - // Additional important points: - // - // - This algorithm is implicitly recursive; it assumes that descendant surfaces have - // already computed their damage. - // - // - Changes to layers/surfaces indicate "damage" to the target surface; If a layer is - // not changed, it does NOT mean that the layer can skip drawing. All layers that - // overlap the damaged region still need to be drawn. For example, if a layer - // changed its opacity, then layers underneath must be re-drawn as well, even if - // they did not change. - // - // - If a layer/surface property changed, the old bounds and new bounds may overlap... - // i.e. some of the exposed region may not actually be exposing anything. But this - // does not artificially inflate the damage rect. If the layer changed, its entire - // old bounds would always need to be redrawn, regardless of how much it overlaps - // with the layer's new bounds, which also need to be entirely redrawn. - // - // - See comments in the rest of the code to see what exactly is considered a "change" - // in a layer/surface. - // - // - To correctly manage exposed rects, two RectMaps are maintained: - // - // 1. The "current" map contains all the layer bounds that contributed to the - // previous frame (even outside the previous damaged area). If a layer changes - // or does not exist anymore, those regions are then exposed and damage the - // target surface. As the algorithm progresses, entries are removed from the - // map until it has only leftover layers that no longer exist. - // - // 2. The "next" map starts out empty, and as the algorithm progresses, every - // layer/surface that contributes to the surface is added to the map. - // - // 3. After the damage rect is computed, the two maps are swapped, so that the - // damage tracker is ready for the next frame. - // - - // These functions cannot be bypassed with early-exits, even if we know what the - // damage will be for this frame, because we need to update the damage tracker state - // to correctly track the next frame. - FloatRect damageFromActiveLayers = trackDamageFromActiveLayers(layerList, targetSurfaceLayerID); - FloatRect damageFromSurfaceMask = trackDamageFromSurfaceMask(targetSurfaceMaskLayer); - FloatRect damageFromLeftoverRects = trackDamageFromLeftoverRects(); - - FloatRect damageRectForThisUpdate; - - if (m_forceFullDamageNextUpdate || targetSurfacePropertyChangedOnlyFromDescendant) { - damageRectForThisUpdate = targetSurfaceContentRect; - m_forceFullDamageNextUpdate = false; - } else { - // FIXME: can we clamp this damage to the surface's content rect? (affects performance, but not correctness) - damageRectForThisUpdate = damageFromActiveLayers; - damageRectForThisUpdate.uniteIfNonZero(damageFromSurfaceMask); - damageRectForThisUpdate.uniteIfNonZero(damageFromLeftoverRects); - - if (filters.hasFilterThatMovesPixels()) - expandRectWithFilters(damageRectForThisUpdate, filters); - } - - // Damage accumulates until we are notified that we actually did draw on that frame. - m_currentDamageRect.uniteIfNonZero(damageRectForThisUpdate); - - // The next history map becomes the current map for the next frame. Note this must - // happen every frame to correctly track changes, even if damage accumulates over - // multiple frames before actually being drawn. - swap(m_currentRectHistory, m_nextRectHistory); -} - -FloatRect CCDamageTracker::removeRectFromCurrentFrame(int layerID, bool& layerIsNew) -{ - layerIsNew = !m_currentRectHistory->contains(layerID); - - // take() will remove the entry from the map, or if not found, return a default (empty) rect. - return m_currentRectHistory->take(layerID); -} - -void CCDamageTracker::saveRectForNextFrame(int layerID, const FloatRect& targetSpaceRect) -{ - // This layer should not yet exist in next frame's history. - ASSERT(layerID > 0); - ASSERT(m_nextRectHistory->find(layerID) == m_nextRectHistory->end()); - m_nextRectHistory->set(layerID, targetSpaceRect); -} - -FloatRect CCDamageTracker::trackDamageFromActiveLayers(const std::vector& layerList, int targetSurfaceLayerID) -{ - FloatRect damageRect = FloatRect(); - - for (unsigned layerIndex = 0; layerIndex < layerList.size(); ++layerIndex) { - // Visit layers in back-to-front order. - CCLayerImpl* layer = layerList[layerIndex]; - - if (CCLayerTreeHostCommon::renderSurfaceContributesToTarget(layer, targetSurfaceLayerID)) - extendDamageForRenderSurface(layer, damageRect); - else - extendDamageForLayer(layer, damageRect); - } - - return damageRect; -} - -FloatRect CCDamageTracker::trackDamageFromSurfaceMask(CCLayerImpl* targetSurfaceMaskLayer) -{ - FloatRect damageRect = FloatRect(); - - if (!targetSurfaceMaskLayer) - return damageRect; - - // Currently, if there is any change to the mask, we choose to damage the entire - // surface. This could potentially be optimized later, but it is not expected to be a - // common case. - if (targetSurfaceMaskLayer->layerPropertyChanged() || !targetSurfaceMaskLayer->updateRect().isEmpty()) - damageRect = FloatRect(FloatPoint::zero(), FloatSize(targetSurfaceMaskLayer->bounds())); - - return damageRect; -} - -FloatRect CCDamageTracker::trackDamageFromLeftoverRects() -{ - // After computing damage for all active layers, any leftover items in the current - // rect history correspond to layers/surfaces that no longer exist. So, these regions - // are now exposed on the target surface. - - FloatRect damageRect = FloatRect(); - - for (RectMap::iterator it = m_currentRectHistory->begin(); it != m_currentRectHistory->end(); ++it) -#if WTF_NEW_HASHMAP_ITERATORS_INTERFACE - damageRect.unite(it->value); -#else - damageRect.unite(it->second); -#endif - - m_currentRectHistory->clear(); - - return damageRect; -} - -static bool layerNeedsToRedrawOntoItsTargetSurface(CCLayerImpl* layer) -{ - // If the layer does NOT own a surface but has SurfacePropertyChanged, - // this means that its target surface is affected and needs to be redrawn. - // However, if the layer DOES own a surface, then the SurfacePropertyChanged - // flag should not be used here, because that flag represents whether the - // layer's surface has changed. - if (layer->renderSurface()) - return layer->layerPropertyChanged(); - return layer->layerPropertyChanged() || layer->layerSurfacePropertyChanged(); -} - -void CCDamageTracker::extendDamageForLayer(CCLayerImpl* layer, FloatRect& targetDamageRect) -{ - // There are two ways that a layer can damage a region of the target surface: - // 1. Property change (e.g. opacity, position, transforms): - // - the entire region of the layer itself damages the surface. - // - the old layer region also damages the surface, because this region is now exposed. - // - note that in many cases the old and new layer rects may overlap, which is fine. - // - // 2. Repaint/update: If a region of the layer that was repainted/updated, that - // region damages the surface. - // - // Property changes take priority over update rects. - // - // This method is called when we want to consider how a layer contributes to its - // targetRenderSurface, even if that layer owns the targetRenderSurface itself. - // To consider how a layer's targetSurface contributes to the ancestorSurface, - // extendDamageForRenderSurface() must be called instead. - - bool layerIsNew = false; - FloatRect oldRectInTargetSpace = removeRectFromCurrentFrame(layer->id(), layerIsNew); - - FloatRect rectInTargetSpace = CCMathUtil::mapClippedRect(layer->drawTransform(), FloatRect(FloatPoint::zero(), layer->contentBounds())); - saveRectForNextFrame(layer->id(), rectInTargetSpace); - - if (layerIsNew || layerNeedsToRedrawOntoItsTargetSurface(layer)) { - // If a layer is new or has changed, then its entire layer rect affects the target surface. - targetDamageRect.uniteIfNonZero(rectInTargetSpace); - - // The layer's old region is now exposed on the target surface, too. - // Note oldRectInTargetSpace is already in target space. - targetDamageRect.uniteIfNonZero(oldRectInTargetSpace); - } else if (!layer->updateRect().isEmpty()) { - // If the layer properties havent changed, then the the target surface is only - // affected by the layer's update area, which could be empty. - FloatRect updateContentRect = layer->updateRect(); - float widthScale = layer->contentBounds().width() / static_cast(layer->bounds().width()); - float heightScale = layer->contentBounds().height() / static_cast(layer->bounds().height()); - updateContentRect.scale(widthScale, heightScale); - - FloatRect updateRectInTargetSpace = CCMathUtil::mapClippedRect(layer->drawTransform(), updateContentRect); - targetDamageRect.uniteIfNonZero(updateRectInTargetSpace); - } -} - -void CCDamageTracker::extendDamageForRenderSurface(CCLayerImpl* layer, FloatRect& targetDamageRect) -{ - // There are two ways a "descendant surface" can damage regions of the "target surface": - // 1. Property change: - // - a surface's geometry can change because of - // - changes to descendants (i.e. the subtree) that affect the surface's content rect - // - changes to ancestor layers that propagate their property changes to their entire subtree. - // - just like layers, both the old surface rect and new surface rect will - // damage the target surface in this case. - // - // 2. Damage rect: This surface may have been damaged by its own layerList as well, and that damage - // should propagate to the target surface. - // - - CCRenderSurface* renderSurface = layer->renderSurface(); - - bool surfaceIsNew = false; - FloatRect oldSurfaceRect = removeRectFromCurrentFrame(layer->id(), surfaceIsNew); - - FloatRect surfaceRectInTargetSpace = renderSurface->drawableContentRect(); // already includes replica if it exists. - saveRectForNextFrame(layer->id(), surfaceRectInTargetSpace); - - FloatRect damageRectInLocalSpace; - if (surfaceIsNew || renderSurface->surfacePropertyChanged() || layer->layerSurfacePropertyChanged()) { - // The entire surface contributes damage. - damageRectInLocalSpace = renderSurface->contentRect(); - - // The surface's old region is now exposed on the target surface, too. - targetDamageRect.uniteIfNonZero(oldSurfaceRect); - } else { - // Only the surface's damageRect will damage the target surface. - damageRectInLocalSpace = renderSurface->damageTracker()->currentDamageRect(); - } - - // If there was damage, transform it to target space, and possibly contribute its reflection if needed. - if (!damageRectInLocalSpace.isEmpty()) { - const WebTransformationMatrix& drawTransform = renderSurface->drawTransform(); - FloatRect damageRectInTargetSpace = CCMathUtil::mapClippedRect(drawTransform, damageRectInLocalSpace); - targetDamageRect.uniteIfNonZero(damageRectInTargetSpace); - - if (layer->replicaLayer()) { - const WebTransformationMatrix& replicaDrawTransform = renderSurface->replicaDrawTransform(); - targetDamageRect.uniteIfNonZero(CCMathUtil::mapClippedRect(replicaDrawTransform, damageRectInLocalSpace)); - } - } - - // If there was damage on the replica's mask, then the target surface receives that damage as well. - if (layer->replicaLayer() && layer->replicaLayer()->maskLayer()) { - CCLayerImpl* replicaMaskLayer = layer->replicaLayer()->maskLayer(); - - bool replicaIsNew = false; - removeRectFromCurrentFrame(replicaMaskLayer->id(), replicaIsNew); - - const WebTransformationMatrix& replicaDrawTransform = renderSurface->replicaDrawTransform(); - FloatRect replicaMaskLayerRect = CCMathUtil::mapClippedRect(replicaDrawTransform, FloatRect(FloatPoint::zero(), FloatSize(replicaMaskLayer->bounds().width(), replicaMaskLayer->bounds().height()))); - saveRectForNextFrame(replicaMaskLayer->id(), replicaMaskLayerRect); - - // In the current implementation, a change in the replica mask damages the entire replica region. - if (replicaIsNew || replicaMaskLayer->layerPropertyChanged() || !replicaMaskLayer->updateRect().isEmpty()) - targetDamageRect.uniteIfNonZero(replicaMaskLayerRect); - } - - // If the layer has a background filter, this may cause pixels in our surface to be expanded, so we will need to expand any damage - // at or below this layer. We expand the damage from this layer too, as we need to readback those pixels from the surface with only - // the contents of layers below this one in them. This means we need to redraw any pixels in the surface being used for the blur in - // this layer this frame. - if (layer->backgroundFilters().hasFilterThatMovesPixels()) - expandDamageRectInsideRectWithFilters(targetDamageRect, surfaceRectInTargetSpace, layer->backgroundFilters()); -} - -} // namespace cc - -#endif // USE(ACCELERATED_COMPOSITING) diff --git a/cc/CCDamageTracker.h b/cc/CCDamageTracker.h index c7550a2..5e48bc6 100644 --- a/cc/CCDamageTracker.h +++ b/cc/CCDamageTracker.h @@ -1,63 +1,6 @@ -// Copyright 2011 The Chromium Authors. All rights reserved. +// Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CCDamageTracker_h -#define CCDamageTracker_h - -#include "base/memory/scoped_ptr.h" -#include "FloatRect.h" -#include -#include -#include - -namespace WebKit { -class WebFilterOperations; -} - -namespace cc { - -class CCLayerImpl; -class CCRenderSurface; - -// Computes the region where pixels have actually changed on a RenderSurface. This region is used -// to scissor what is actually drawn to the screen to save GPU computation and bandwidth. -class CCDamageTracker { -public: - static scoped_ptr create(); - ~CCDamageTracker(); - - void didDrawDamagedArea() { m_currentDamageRect = FloatRect(); } - void forceFullDamageNextUpdate() { m_forceFullDamageNextUpdate = true; } - void updateDamageTrackingState(const std::vector& layerList, int targetSurfaceLayerID, bool targetSurfacePropertyChangedOnlyFromDescendant, const IntRect& targetSurfaceContentRect, CCLayerImpl* targetSurfaceMaskLayer, const WebKit::WebFilterOperations&); - - const FloatRect& currentDamageRect() { return m_currentDamageRect; } - -private: - CCDamageTracker(); - - FloatRect trackDamageFromActiveLayers(const std::vector& layerList, int targetSurfaceLayerID); - FloatRect trackDamageFromSurfaceMask(CCLayerImpl* targetSurfaceMaskLayer); - FloatRect trackDamageFromLeftoverRects(); - - FloatRect removeRectFromCurrentFrame(int layerID, bool& layerIsNew); - void saveRectForNextFrame(int layerID, const FloatRect& targetSpaceRect); - - // These helper functions are used only in trackDamageFromActiveLayers(). - void extendDamageForLayer(CCLayerImpl*, FloatRect& targetDamageRect); - void extendDamageForRenderSurface(CCLayerImpl*, FloatRect& targetDamageRect); - - // To correctly track exposed regions, two hashtables of rects are maintained. - // The "current" map is used to compute exposed regions of the current frame, while - // the "next" map is used to collect layer rects that are used in the next frame. - typedef HashMap RectMap; - scoped_ptr m_currentRectHistory; - scoped_ptr m_nextRectHistory; - - FloatRect m_currentDamageRect; - bool m_forceFullDamageNextUpdate; -}; - -} // namespace cc - -#endif // CCDamageTracker_h +// Temporary forwarding header +#include "cc/damage_tracker.h" diff --git a/cc/CCDebugBorderDrawQuad.cpp b/cc/CCDebugBorderDrawQuad.cpp deleted file mode 100644 index aabf9e2..0000000 --- a/cc/CCDebugBorderDrawQuad.cpp +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "config.h" - -#include "CCDebugBorderDrawQuad.h" - -namespace cc { - -scoped_ptr CCDebugBorderDrawQuad::create(const CCSharedQuadState* sharedQuadState, const IntRect& quadRect, SkColor color, int width) -{ - return make_scoped_ptr(new CCDebugBorderDrawQuad(sharedQuadState, quadRect, color, width)); -} - -CCDebugBorderDrawQuad::CCDebugBorderDrawQuad(const CCSharedQuadState* sharedQuadState, const IntRect& quadRect, SkColor color, int width) - : CCDrawQuad(sharedQuadState, CCDrawQuad::DebugBorder, quadRect) - , m_color(color) - , m_width(width) -{ - m_quadOpaque = false; - if (SkColorGetA(m_color) < 255) - m_needsBlending = true; -} - -const CCDebugBorderDrawQuad* CCDebugBorderDrawQuad::materialCast(const CCDrawQuad* quad) -{ - ASSERT(quad->material() == CCDrawQuad::DebugBorder); - return static_cast(quad); -} - -} // namespace cc diff --git a/cc/CCDebugBorderDrawQuad.h b/cc/CCDebugBorderDrawQuad.h index fbba1c6..3b275fa 100644 --- a/cc/CCDebugBorderDrawQuad.h +++ b/cc/CCDebugBorderDrawQuad.h @@ -2,34 +2,5 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CCDebugBorderDrawQuad_h -#define CCDebugBorderDrawQuad_h - -#include "CCDrawQuad.h" -#include "SkColor.h" -#include "base/memory/scoped_ptr.h" - -namespace cc { - -#pragma pack(push, 4) - -class CCDebugBorderDrawQuad : public CCDrawQuad { -public: - static scoped_ptr create(const CCSharedQuadState*, const IntRect&, SkColor, int width); - - SkColor color() const { return m_color; }; - int width() const { return m_width; } - - static const CCDebugBorderDrawQuad* materialCast(const CCDrawQuad*); -private: - CCDebugBorderDrawQuad(const CCSharedQuadState*, const IntRect&, SkColor, int width); - - SkColor m_color; - int m_width; -}; - -#pragma pack(pop) - -} - -#endif +// Temporary forwarding header +#include "cc/debug_border_draw_quad.h" diff --git a/cc/CCDebugRectHistory.cpp b/cc/CCDebugRectHistory.cpp deleted file mode 100644 index 7f3c2ea..0000000 --- a/cc/CCDebugRectHistory.cpp +++ /dev/null @@ -1,120 +0,0 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "config.h" - -#if USE(ACCELERATED_COMPOSITING) -#include "CCDebugRectHistory.h" - -#include "CCDamageTracker.h" -#include "CCLayerImpl.h" -#include "CCLayerTreeHost.h" -#include "CCMathUtil.h" - -namespace cc { - -CCDebugRectHistory::CCDebugRectHistory() -{ -} - -CCDebugRectHistory::~CCDebugRectHistory() -{ -} - -void CCDebugRectHistory::saveDebugRectsForCurrentFrame(CCLayerImpl* rootLayer, const std::vector& renderSurfaceLayerList, const Vector& occludingScreenSpaceRects, const CCLayerTreeSettings& settings) -{ - // For now, clear all rects from previous frames. In the future we may want to store - // all debug rects for a history of many frames. - m_debugRects.clear(); - - if (settings.showPaintRects) - savePaintRects(rootLayer); - - if (settings.showPropertyChangedRects) - savePropertyChangedRects(renderSurfaceLayerList); - - if (settings.showSurfaceDamageRects) - saveSurfaceDamageRects(renderSurfaceLayerList); - - if (settings.showScreenSpaceRects) - saveScreenSpaceRects(renderSurfaceLayerList); - - if (settings.showOccludingRects) - saveOccludingRects(occludingScreenSpaceRects); -} - - -void CCDebugRectHistory::savePaintRects(CCLayerImpl* layer) -{ - // We would like to visualize where any layer's paint rect (update rect) has changed, - // regardless of whether this layer is skipped for actual drawing or not. Therefore - // we traverse recursively over all layers, not just the render surface list. - - if (!layer->updateRect().isEmpty() && layer->drawsContent()) { - FloatRect updateContentRect = layer->updateRect(); - updateContentRect.scale(layer->contentBounds().width() / static_cast(layer->bounds().width()), layer->contentBounds().height() / static_cast(layer->bounds().height())); - m_debugRects.append(CCDebugRect(PaintRectType, CCMathUtil::mapClippedRect(layer->screenSpaceTransform(), updateContentRect))); - } - - for (unsigned i = 0; i < layer->children().size(); ++i) - savePaintRects(layer->children()[i]); -} - -void CCDebugRectHistory::savePropertyChangedRects(const std::vector& renderSurfaceLayerList) -{ - for (int surfaceIndex = renderSurfaceLayerList.size() - 1; surfaceIndex >= 0 ; --surfaceIndex) { - CCLayerImpl* renderSurfaceLayer = renderSurfaceLayerList[surfaceIndex]; - CCRenderSurface* renderSurface = renderSurfaceLayer->renderSurface(); - ASSERT(renderSurface); - - const std::vector& layerList = renderSurface->layerList(); - for (unsigned layerIndex = 0; layerIndex < layerList.size(); ++layerIndex) { - CCLayerImpl* layer = layerList[layerIndex]; - - if (CCLayerTreeHostCommon::renderSurfaceContributesToTarget(layer, renderSurfaceLayer->id())) - continue; - - if (layer->layerIsAlwaysDamaged()) - continue; - - if (layer->layerPropertyChanged() || layer->layerSurfacePropertyChanged()) - m_debugRects.append(CCDebugRect(PropertyChangedRectType, CCMathUtil::mapClippedRect(layer->screenSpaceTransform(), FloatRect(FloatPoint::zero(), layer->contentBounds())))); - } - } -} - -void CCDebugRectHistory::saveSurfaceDamageRects(const std::vector& renderSurfaceLayerList) -{ - for (int surfaceIndex = renderSurfaceLayerList.size() - 1; surfaceIndex >= 0 ; --surfaceIndex) { - CCLayerImpl* renderSurfaceLayer = renderSurfaceLayerList[surfaceIndex]; - CCRenderSurface* renderSurface = renderSurfaceLayer->renderSurface(); - ASSERT(renderSurface); - - m_debugRects.append(CCDebugRect(SurfaceDamageRectType, CCMathUtil::mapClippedRect(renderSurface->screenSpaceTransform(), renderSurface->damageTracker()->currentDamageRect()))); - } -} - -void CCDebugRectHistory::saveScreenSpaceRects(const std::vector& renderSurfaceLayerList) -{ - for (int surfaceIndex = renderSurfaceLayerList.size() - 1; surfaceIndex >= 0 ; --surfaceIndex) { - CCLayerImpl* renderSurfaceLayer = renderSurfaceLayerList[surfaceIndex]; - CCRenderSurface* renderSurface = renderSurfaceLayer->renderSurface(); - ASSERT(renderSurface); - - m_debugRects.append(CCDebugRect(ScreenSpaceRectType, CCMathUtil::mapClippedRect(renderSurface->screenSpaceTransform(), renderSurface->contentRect()))); - - if (renderSurfaceLayer->replicaLayer()) - m_debugRects.append(CCDebugRect(ReplicaScreenSpaceRectType, CCMathUtil::mapClippedRect(renderSurface->replicaScreenSpaceTransform(), renderSurface->contentRect()))); - } -} - -void CCDebugRectHistory::saveOccludingRects(const Vector& occludingRects) -{ - for (size_t i = 0; i < occludingRects.size(); ++i) - m_debugRects.append(CCDebugRect(OccludingRectType, occludingRects[i])); -} - -} // namespace cc - -#endif // USE(ACCELERATED_COMPOSITING) diff --git a/cc/CCDebugRectHistory.h b/cc/CCDebugRectHistory.h index 1b03f34..690febe 100644 --- a/cc/CCDebugRectHistory.h +++ b/cc/CCDebugRectHistory.h @@ -2,86 +2,5 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CCDebugRectHistory_h -#define CCDebugRectHistory_h - -#if USE(ACCELERATED_COMPOSITING) - -#include "base/basictypes.h" -#include "FloatRect.h" -#include "IntRect.h" -#include -#include -#include - -namespace cc { - -class CCLayerImpl; -struct CCLayerTreeSettings; - -// There are currently six types of debug rects: -// -// - Paint rects (update rects): regions of a layer that needed to be re-uploaded to the -// texture resource; in most cases implying that they had to be repainted, too. -// -// - Property-changed rects: enclosing bounds of layers that cause changes to the screen -// even if the layer did not change internally. (For example, if the layer's opacity or -// position changes.) -// -// - Surface damage rects: the aggregate damage on a target surface that is caused by all -// layers and surfaces that contribute to it. This includes (1) paint rects, (2) property- -// changed rects, and (3) newly exposed areas. -// -// - Screen space rects: this is the region the contents occupy in screen space. -// -// - Replica screen space rects: this is the region the replica's contents occupy in screen space. -// -// - Occluding rects: these are the regions that contribute to the occluded region. -// -enum DebugRectType { PaintRectType, PropertyChangedRectType, SurfaceDamageRectType, ScreenSpaceRectType, ReplicaScreenSpaceRectType, OccludingRectType }; - -struct CCDebugRect { - CCDebugRect(DebugRectType newType, FloatRect newRect) - : type(newType) - , rect(newRect) { } - - DebugRectType type; - FloatRect rect; -}; - -// This class maintains a history of rects of various types that can be used -// for debugging purposes. The overhead of collecting rects is performed only if -// the appropriate CCLayerTreeSettings are enabled. -class CCDebugRectHistory { -public: - static PassOwnPtr create() - { - return adoptPtr(new CCDebugRectHistory()); - } - - ~CCDebugRectHistory(); - - // Note: Saving debug rects must happen before layers' change tracking is reset. - void saveDebugRectsForCurrentFrame(CCLayerImpl* rootLayer, const std::vector& renderSurfaceLayerList, const Vector& occludingScreenSpaceRects, const CCLayerTreeSettings&); - - const Vector& debugRects() { return m_debugRects; } - -private: - CCDebugRectHistory(); - - void savePaintRects(CCLayerImpl*); - void savePropertyChangedRects(const std::vector& renderSurfaceLayerList); - void saveSurfaceDamageRects(const std::vector& renderSurfaceLayerList); - void saveScreenSpaceRects(const std::vector& renderSurfaceLayerList); - void saveOccludingRects(const Vector& occludingScreenSpaceRects); - - Vector m_debugRects; - - DISALLOW_COPY_AND_ASSIGN(CCDebugRectHistory); -}; - -} // namespace cc - -#endif // USE(ACCELERATED_COMPOSITING) - -#endif +// Temporary forwarding header +#include "cc/debug_rect_history.h" diff --git a/cc/CCDelayBasedTimeSource.cpp b/cc/CCDelayBasedTimeSource.cpp deleted file mode 100644 index 6e34a07..0000000 --- a/cc/CCDelayBasedTimeSource.cpp +++ /dev/null @@ -1,232 +0,0 @@ -// Copyright 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "config.h" - -#include "CCDelayBasedTimeSource.h" - -#include "TraceEvent.h" -#include -#include -#include - -namespace cc { - -namespace { - -// doubleTickThreshold prevents ticks from running within the specified fraction of an interval. -// This helps account for jitter in the timebase as well as quick timer reactivation. -const double doubleTickThreshold = 0.25; - -// intervalChangeThreshold is the fraction of the interval that will trigger an immediate interval change. -// phaseChangeThreshold is the fraction of the interval that will trigger an immediate phase change. -// If the changes are within the thresholds, the change will take place on the next tick. -// If either change is outside the thresholds, the next tick will be canceled and reissued immediately. -const double intervalChangeThreshold = 0.25; -const double phaseChangeThreshold = 0.25; - -} - - -PassRefPtr CCDelayBasedTimeSource::create(base::TimeDelta interval, CCThread* thread) -{ - return adoptRef(new CCDelayBasedTimeSource(interval, thread)); -} - -CCDelayBasedTimeSource::CCDelayBasedTimeSource(base::TimeDelta interval, CCThread* thread) - : m_client(0) - , m_hasTickTarget(false) - , m_currentParameters(interval, base::TimeTicks()) - , m_nextParameters(interval, base::TimeTicks()) - , m_state(STATE_INACTIVE) - , m_timer(thread, this) -{ - turnOffVerifier(); -} - -CCDelayBasedTimeSource::~CCDelayBasedTimeSource() -{ -} - -void CCDelayBasedTimeSource::setActive(bool active) -{ - TRACE_EVENT1("cc", "CCDelayBasedTimeSource::setActive", "active", active); - if (!active) { - m_state = STATE_INACTIVE; - m_timer.stop(); - return; - } - - if (m_state == STATE_STARTING || m_state == STATE_ACTIVE) - return; - - if (!m_hasTickTarget) { - // Becoming active the first time is deferred: we post a 0-delay task. When - // it runs, we use that to establish the timebase, become truly active, and - // fire the first tick. - m_state = STATE_STARTING; - m_timer.startOneShot(0); - return; - } - - m_state = STATE_ACTIVE; - - postNextTickTask(now()); -} - -bool CCDelayBasedTimeSource::active() const -{ - return m_state != STATE_INACTIVE; -} - -base::TimeTicks CCDelayBasedTimeSource::lastTickTime() -{ - return m_lastTickTime; -} - -base::TimeTicks CCDelayBasedTimeSource::nextTickTime() -{ - return active() ? m_currentParameters.tickTarget : base::TimeTicks(); -} - -void CCDelayBasedTimeSource::onTimerFired() -{ - ASSERT(m_state != STATE_INACTIVE); - - base::TimeTicks now = this->now(); - m_lastTickTime = now; - - if (m_state == STATE_STARTING) { - setTimebaseAndInterval(now, m_currentParameters.interval); - m_state = STATE_ACTIVE; - } - - postNextTickTask(now); - - // Fire the tick - if (m_client) - m_client->onTimerTick(); -} - -void CCDelayBasedTimeSource::setClient(CCTimeSourceClient* client) -{ - m_client = client; -} - -void CCDelayBasedTimeSource::setTimebaseAndInterval(base::TimeTicks timebase, base::TimeDelta interval) -{ - m_nextParameters.interval = interval; - m_nextParameters.tickTarget = timebase; - m_hasTickTarget = true; - - if (m_state != STATE_ACTIVE) { - // If we aren't active, there's no need to reset the timer. - return; - } - - // If the change in interval is larger than the change threshold, - // request an immediate reset. - double intervalDelta = std::abs((interval - m_currentParameters.interval).InSecondsF()); - double intervalChange = intervalDelta / interval.InSecondsF(); - if (intervalChange > intervalChangeThreshold) { - setActive(false); - setActive(true); - return; - } - - // If the change in phase is greater than the change threshold in either - // direction, request an immediate reset. This logic might result in a false - // negative if there is a simultaneous small change in the interval and the - // fmod just happens to return something near zero. Assuming the timebase - // is very recent though, which it should be, we'll still be ok because the - // old clock and new clock just happen to line up. - double targetDelta = std::abs((timebase - m_currentParameters.tickTarget).InSecondsF()); - double phaseChange = fmod(targetDelta, interval.InSecondsF()) / interval.InSecondsF(); - if (phaseChange > phaseChangeThreshold && phaseChange < (1.0 - phaseChangeThreshold)) { - setActive(false); - setActive(true); - return; - } -} - -base::TimeTicks CCDelayBasedTimeSource::now() const -{ - return base::TimeTicks::Now(); -} - -// This code tries to achieve an average tick rate as close to m_interval as possible. -// To do this, it has to deal with a few basic issues: -// 1. postDelayedTask can delay only at a millisecond granularity. So, 16.666 has to -// posted as 16 or 17. -// 2. A delayed task may come back a bit late (a few ms), or really late (frames later) -// -// The basic idea with this scheduler here is to keep track of where we *want* to run in -// m_tickTarget. We update this with the exact interval. -// -// Then, when we post our task, we take the floor of (m_tickTarget and now()). If we -// started at now=0, and 60FPs (all times in milliseconds): -// now=0 target=16.667 postDelayedTask(16) -// -// When our callback runs, we figure out how far off we were from that goal. Because of the flooring -// operation, and assuming our timer runs exactly when it should, this yields: -// now=16 target=16.667 -// -// Since we can't post a 0.667 ms task to get to now=16, we just treat this as a tick. Then, -// we update target to be 33.333. We now post another task based on the difference between our target -// and now: -// now=16 tickTarget=16.667 newTarget=33.333 --> postDelayedTask(floor(33.333 - 16)) --> postDelayedTask(17) -// -// Over time, with no late tasks, this leads to us posting tasks like this: -// now=0 tickTarget=0 newTarget=16.667 --> tick(), postDelayedTask(16) -// now=16 tickTarget=16.667 newTarget=33.333 --> tick(), postDelayedTask(17) -// now=33 tickTarget=33.333 newTarget=50.000 --> tick(), postDelayedTask(17) -// now=50 tickTarget=50.000 newTarget=66.667 --> tick(), postDelayedTask(16) -// -// We treat delays in tasks differently depending on the amount of delay we encounter. Suppose we -// posted a task with a target=16.667: -// Case 1: late but not unrecoverably-so -// now=18 tickTarget=16.667 -// -// Case 2: so late we obviously missed the tick -// now=25.0 tickTarget=16.667 -// -// We treat the first case as a tick anyway, and assume the delay was -// unusual. Thus, we compute the newTarget based on the old timebase: -// now=18 tickTarget=16.667 newTarget=33.333 --> tick(), postDelayedTask(floor(33.333-18)) --> postDelayedTask(15) -// This brings us back to 18+15 = 33, which was where we would have been if the task hadn't been late. -// -// For the really late delay, we we move to the next logical tick. The timebase is not reset. -// now=37 tickTarget=16.667 newTarget=50.000 --> tick(), postDelayedTask(floor(50.000-37)) --> postDelayedTask(13) -base::TimeTicks CCDelayBasedTimeSource::nextTickTarget(base::TimeTicks now) -{ - base::TimeDelta newInterval = m_nextParameters.interval; - int intervalsElapsed = static_cast(floor((now - m_nextParameters.tickTarget).InSecondsF() / newInterval.InSecondsF())); - base::TimeTicks lastEffectiveTick = m_nextParameters.tickTarget + newInterval * intervalsElapsed; - base::TimeTicks newTickTarget = lastEffectiveTick + newInterval; - ASSERT(newTickTarget > now); - - // Avoid double ticks when: - // 1) Turning off the timer and turning it right back on. - // 2) Jittery data is passed to setTimebaseAndInterval(). - if (newTickTarget - m_lastTickTime <= newInterval / static_cast(1.0 / doubleTickThreshold)) - newTickTarget += newInterval; - - return newTickTarget; -} - -void CCDelayBasedTimeSource::postNextTickTask(base::TimeTicks now) -{ - base::TimeTicks newTickTarget = nextTickTarget(now); - - // Post another task *before* the tick and update state - base::TimeDelta delay = newTickTarget - now; - ASSERT(delay.InMillisecondsF() <= - m_nextParameters.interval.InMillisecondsF() * (1.0 + doubleTickThreshold)); - m_timer.startOneShot(delay.InSecondsF()); - - m_nextParameters.tickTarget = newTickTarget; - m_currentParameters = m_nextParameters; -} - -} diff --git a/cc/CCDelayBasedTimeSource.h b/cc/CCDelayBasedTimeSource.h index bf183f7..249666c1 100644 --- a/cc/CCDelayBasedTimeSource.h +++ b/cc/CCDelayBasedTimeSource.h @@ -1,79 +1,6 @@ -// Copyright 2011 The Chromium Authors. All rights reserved. +// Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CCDelayBasedTimeSource_h -#define CCDelayBasedTimeSource_h - -#include "CCTimeSource.h" -#include "CCTimer.h" -#include - -namespace cc { - -class CCThread; - -// This timer implements a time source that achieves the specified interval -// in face of millisecond-precision delayed callbacks and random queueing delays. -class CCDelayBasedTimeSource : public CCTimeSource, CCTimerClient { -public: - static PassRefPtr create(base::TimeDelta interval, CCThread*); - - virtual ~CCDelayBasedTimeSource(); - - virtual void setClient(CCTimeSourceClient* client) OVERRIDE; - - // CCTimeSource implementation - virtual void setTimebaseAndInterval(base::TimeTicks timebase, base::TimeDelta interval) OVERRIDE; - - virtual void setActive(bool) OVERRIDE; - virtual bool active() const OVERRIDE; - - // Get the last and next tick times. nextTimeTime() returns null when - // inactive. - virtual base::TimeTicks lastTickTime() OVERRIDE; - virtual base::TimeTicks nextTickTime() OVERRIDE; - - // CCTimerClient implementation. - virtual void onTimerFired() OVERRIDE; - - // Virtual for testing. - virtual base::TimeTicks now() const; - -protected: - CCDelayBasedTimeSource(base::TimeDelta interval, CCThread*); - base::TimeTicks nextTickTarget(base::TimeTicks now); - void postNextTickTask(base::TimeTicks now); - - enum State { - STATE_INACTIVE, - STATE_STARTING, - STATE_ACTIVE, - }; - - struct Parameters { - Parameters(base::TimeDelta interval, base::TimeTicks tickTarget) - : interval(interval), tickTarget(tickTarget) - { } - base::TimeDelta interval; - base::TimeTicks tickTarget; - }; - - CCTimeSourceClient* m_client; - bool m_hasTickTarget; - base::TimeTicks m_lastTickTime; - - // m_currentParameters should only be written by postNextTickTask. - // m_nextParameters will take effect on the next call to postNextTickTask. - // Maintaining a pending set of parameters allows nextTickTime() to always - // reflect the actual time we expect onTimerFired to be called. - Parameters m_currentParameters; - Parameters m_nextParameters; - - State m_state; - CCThread* m_thread; - CCTimer m_timer; -}; - -} -#endif // CCDelayBasedTimeSource_h +// Temporary forwarding header +#include "cc/delay_based_time_source.h" diff --git a/cc/CCDelegatedRendererLayerImpl.cpp b/cc/CCDelegatedRendererLayerImpl.cpp deleted file mode 100644 index 02d5698..0000000 --- a/cc/CCDelegatedRendererLayerImpl.cpp +++ /dev/null @@ -1,185 +0,0 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "config.h" - -#include "CCDelegatedRendererLayerImpl.h" - -#include "CCAppendQuadsData.h" -#include "CCQuadSink.h" -#include "CCMathUtil.h" -#include "CCRenderPassDrawQuad.h" -#include "CCRenderPassSink.h" - -namespace cc { - -CCDelegatedRendererLayerImpl::CCDelegatedRendererLayerImpl(int id) - : CCLayerImpl(id) -{ -} - -CCDelegatedRendererLayerImpl::~CCDelegatedRendererLayerImpl() -{ - clearRenderPasses(); -} - -bool CCDelegatedRendererLayerImpl::descendantDrawsContent() -{ - // FIXME: This could possibly return false even though there are some - // quads present as they could all be from a single layer (or set of - // layers without children). If this happens, then make a test that - // ensures the opacity is being changed on quads in the root RenderPass - // when this layer doesn't own a RenderSurface. - return !m_renderPassesInDrawOrder.isEmpty(); -} - -bool CCDelegatedRendererLayerImpl::hasContributingDelegatedRenderPasses() const -{ - // The root RenderPass for the layer is merged with its target - // RenderPass in each frame. So we only have extra RenderPasses - // to merge when we have a non-root RenderPass present. - return m_renderPassesInDrawOrder.size() > 1; -} - -void CCDelegatedRendererLayerImpl::setRenderPasses(ScopedPtrVector& renderPassesInDrawOrder) -{ - FloatRect oldRootDamage; - if (!m_renderPassesInDrawOrder.isEmpty()) - oldRootDamage = m_renderPassesInDrawOrder.last()->damageRect(); - - clearRenderPasses(); - - for (size_t i = 0; i < renderPassesInDrawOrder.size(); ++i) { - m_renderPassesIndexById.insert(std::pair(renderPassesInDrawOrder[i]->id(), i)); - m_renderPassesInDrawOrder.append(renderPassesInDrawOrder.take(i)); - } - renderPassesInDrawOrder.clear(); - - if (!m_renderPassesInDrawOrder.isEmpty()) { - FloatRect newRootDamage = m_renderPassesInDrawOrder.last()->damageRect(); - m_renderPassesInDrawOrder.last()->setDamageRect(unionRect(oldRootDamage, newRootDamage)); - } -} - -void CCDelegatedRendererLayerImpl::clearRenderPasses() -{ - // FIXME: Release the resources back to the nested compositor. - m_renderPassesIndexById.clear(); - m_renderPassesInDrawOrder.clear(); -} - -void CCDelegatedRendererLayerImpl::didLoseContext() -{ - clearRenderPasses(); -} - -static inline int indexToId(int index) { return index + 1; } -static inline int idToIndex(int id) { return id - 1; } - -CCRenderPass::Id CCDelegatedRendererLayerImpl::firstContributingRenderPassId() const -{ - return CCRenderPass::Id(id(), indexToId(0)); -} - -CCRenderPass::Id CCDelegatedRendererLayerImpl::nextContributingRenderPassId(CCRenderPass::Id previous) const -{ - return CCRenderPass::Id(previous.layerId, previous.index + 1); -} - -CCRenderPass::Id CCDelegatedRendererLayerImpl::convertDelegatedRenderPassId(CCRenderPass::Id delegatedRenderPassId) const -{ - base::hash_map::const_iterator it = m_renderPassesIndexById.find(delegatedRenderPassId); - ASSERT(it != m_renderPassesIndexById.end()); - unsigned delegatedRenderPassIndex = it->second; - return CCRenderPass::Id(id(), indexToId(delegatedRenderPassIndex)); -} - -void CCDelegatedRendererLayerImpl::appendContributingRenderPasses(CCRenderPassSink& renderPassSink) -{ - ASSERT(hasContributingDelegatedRenderPasses()); - - for (size_t i = 0; i < m_renderPassesInDrawOrder.size() - 1; ++i) { - CCRenderPass::Id outputRenderPassId = convertDelegatedRenderPassId(m_renderPassesInDrawOrder[i]->id()); - - // Don't clash with the RenderPass we generate if we own a RenderSurface. - ASSERT(outputRenderPassId.index > 0); - - renderPassSink.appendRenderPass(m_renderPassesInDrawOrder[i]->copy(outputRenderPassId)); - } -} - -void CCDelegatedRendererLayerImpl::appendQuads(CCQuadSink& quadSink, CCAppendQuadsData& appendQuadsData) -{ - if (m_renderPassesInDrawOrder.isEmpty()) - return; - - CCRenderPass::Id targetRenderPassId = appendQuadsData.renderPassId; - - // If the index of the renderPassId is 0, then it is a renderPass generated for a layer - // in this compositor, not the delegated renderer. Then we want to merge our root renderPass with - // the target renderPass. Otherwise, it is some renderPass which we added from the delegated - // renderer. - bool shouldMergeRootRenderPassWithTarget = !targetRenderPassId.index; - if (shouldMergeRootRenderPassWithTarget) { - // Verify that the renderPass we are appending to is created our renderTarget. - ASSERT(targetRenderPassId.layerId == renderTarget()->id()); - - CCRenderPass* rootDelegatedRenderPass = m_renderPassesInDrawOrder.last(); - appendRenderPassQuads(quadSink, appendQuadsData, rootDelegatedRenderPass); - } else { - // Verify that the renderPass we are appending to was created by us. - ASSERT(targetRenderPassId.layerId == id()); - - int renderPassIndex = idToIndex(targetRenderPassId.index); - CCRenderPass* delegatedRenderPass = m_renderPassesInDrawOrder[renderPassIndex]; - appendRenderPassQuads(quadSink, appendQuadsData, delegatedRenderPass); - } -} - -void CCDelegatedRendererLayerImpl::appendRenderPassQuads(CCQuadSink& quadSink, CCAppendQuadsData& appendQuadsData, CCRenderPass* delegatedRenderPass) const -{ - const CCSharedQuadState* currentSharedQuadState = 0; - CCSharedQuadState* copiedSharedQuadState = 0; - for (size_t i = 0; i < delegatedRenderPass->quadList().size(); ++i) { - CCDrawQuad* quad = delegatedRenderPass->quadList()[i]; - - if (quad->sharedQuadState() != currentSharedQuadState) { - currentSharedQuadState = quad->sharedQuadState(); - copiedSharedQuadState = quadSink.useSharedQuadState(currentSharedQuadState->copy()); - bool targetIsFromDelegatedRendererLayer = appendQuadsData.renderPassId.layerId == id(); - if (!targetIsFromDelegatedRendererLayer) { - // Should be the root render pass. - ASSERT(delegatedRenderPass == m_renderPassesInDrawOrder.last()); - // This layer must be drawing to a renderTarget other than itself. - ASSERT(renderTarget() != this); - - copiedSharedQuadState->clippedRectInTarget = CCMathUtil::mapClippedRect(drawTransform(), copiedSharedQuadState->clippedRectInTarget); - copiedSharedQuadState->quadTransform = copiedSharedQuadState->quadTransform * drawTransform(); - copiedSharedQuadState->opacity *= drawOpacity(); - } - } - ASSERT(copiedSharedQuadState); - - scoped_ptr copyQuad; - if (quad->material() != CCDrawQuad::RenderPass) - copyQuad = quad->copy(copiedSharedQuadState); - else { - CCRenderPass::Id contributingDelegatedRenderPassId = CCRenderPassDrawQuad::materialCast(quad)->renderPassId(); - CCRenderPass::Id contributingRenderPassId = convertDelegatedRenderPassId(contributingDelegatedRenderPassId); - ASSERT(contributingRenderPassId != appendQuadsData.renderPassId); - - copyQuad = CCRenderPassDrawQuad::materialCast(quad)->copy(copiedSharedQuadState, contributingRenderPassId).PassAs(); - } - ASSERT(copyQuad.get()); - - quadSink.append(copyQuad.Pass(), appendQuadsData); - } -} - -const char* CCDelegatedRendererLayerImpl::layerTypeAsString() const -{ - return "DelegatedRendererLayer"; -} - -} diff --git a/cc/CCDelegatedRendererLayerImpl.h b/cc/CCDelegatedRendererLayerImpl.h index 4ed842e..08952e3 100644 --- a/cc/CCDelegatedRendererLayerImpl.h +++ b/cc/CCDelegatedRendererLayerImpl.h @@ -2,49 +2,5 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CCDelegatedRendererLayerImpl_h -#define CCDelegatedRendererLayerImpl_h - -#include "CCLayerImpl.h" -#include "cc/scoped_ptr_vector.h" - -namespace cc { - -class CCDelegatedRendererLayerImpl : public CCLayerImpl { -public: - static scoped_ptr create(int id) { return make_scoped_ptr(new CCDelegatedRendererLayerImpl(id)); } - virtual ~CCDelegatedRendererLayerImpl(); - - virtual bool descendantDrawsContent() OVERRIDE; - virtual bool hasContributingDelegatedRenderPasses() const OVERRIDE; - - // This gives ownership of the RenderPasses to the layer. - void setRenderPasses(ScopedPtrVector&); - void clearRenderPasses(); - - virtual void didLoseContext() OVERRIDE; - - virtual CCRenderPass::Id firstContributingRenderPassId() const OVERRIDE; - virtual CCRenderPass::Id nextContributingRenderPassId(CCRenderPass::Id) const OVERRIDE; - - void appendContributingRenderPasses(CCRenderPassSink&); - virtual void appendQuads(CCQuadSink&, CCAppendQuadsData&) OVERRIDE; - -private: - explicit CCDelegatedRendererLayerImpl(int); - - CCRenderPass::Id convertDelegatedRenderPassId(CCRenderPass::Id delegatedRenderPassId) const; - - void appendRenderPassQuads(CCQuadSink&, CCAppendQuadsData&, CCRenderPass* fromDelegatedRenderPass) const; - - PassOwnPtr createCopyOfQuad(const CCDrawQuad*); - - virtual const char* layerTypeAsString() const OVERRIDE; - - ScopedPtrVector m_renderPassesInDrawOrder; - base::hash_map m_renderPassesIndexById; -}; - -} - -#endif // CCDelegatedRendererLayerImpl_h +// Temporary forwarding header +#include "cc/delegated_renderer_layer_impl.h" diff --git a/cc/CCDirectRenderer.cpp b/cc/CCDirectRenderer.cpp deleted file mode 100644 index 23fa1d3..0000000 --- a/cc/CCDirectRenderer.cpp +++ /dev/null @@ -1,237 +0,0 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "config.h" - -#include "CCDirectRenderer.h" - -#include "CCMathUtil.h" -#include -#include - -using WebKit::WebTransformationMatrix; - -static WebTransformationMatrix orthoProjectionMatrix(float left, float right, float bottom, float top) -{ - // Use the standard formula to map the clipping frustum to the cube from - // [-1, -1, -1] to [1, 1, 1]. - float deltaX = right - left; - float deltaY = top - bottom; - WebTransformationMatrix proj; - if (!deltaX || !deltaY) - return proj; - proj.setM11(2.0f / deltaX); - proj.setM41(-(right + left) / deltaX); - proj.setM22(2.0f / deltaY); - proj.setM42(-(top + bottom) / deltaY); - - // Z component of vertices is always set to zero as we don't use the depth buffer - // while drawing. - proj.setM33(0); - - return proj; -} - -static WebTransformationMatrix windowMatrix(int x, int y, int width, int height) -{ - WebTransformationMatrix canvas; - - // Map to window position and scale up to pixel coordinates. - canvas.translate3d(x, y, 0); - canvas.scale3d(width, height, 0); - - // Map from ([-1, -1] to [1, 1]) -> ([0, 0] to [1, 1]) - canvas.translate3d(0.5, 0.5, 0.5); - canvas.scale3d(0.5, 0.5, 0.5); - - return canvas; -} - -namespace cc { - -CCDirectRenderer::DrawingFrame::DrawingFrame() - : rootRenderPass(0) - , currentRenderPass(0) - , currentTexture(0) - , flippedY(false) -{ -} - -CCDirectRenderer::DrawingFrame::~DrawingFrame() -{ -} - -// -// static -FloatRect CCDirectRenderer::quadVertexRect() -{ - return FloatRect(-0.5, -0.5, 1, 1); -} - -// static -void CCDirectRenderer::quadRectTransform(WebKit::WebTransformationMatrix* quadRectTransform, const WebKit::WebTransformationMatrix& quadTransform, const FloatRect& quadRect) -{ - *quadRectTransform = quadTransform; - quadRectTransform->translate(0.5 * quadRect.width() + quadRect.x(), 0.5 * quadRect.height() + quadRect.y()); - quadRectTransform->scaleNonUniform(quadRect.width(), quadRect.height()); -} - -// static -void CCDirectRenderer::initializeMatrices(DrawingFrame& frame, const IntRect& drawRect, bool flipY) -{ - if (flipY) - frame.projectionMatrix = orthoProjectionMatrix(drawRect.x(), drawRect.maxX(), drawRect.maxY(), drawRect.y()); - else - frame.projectionMatrix = orthoProjectionMatrix(drawRect.x(), drawRect.maxX(), drawRect.y(), drawRect.maxY()); - frame.windowMatrix = windowMatrix(0, 0, drawRect.width(), drawRect.height()); - frame.flippedY = flipY; -} - -// static -IntRect CCDirectRenderer::moveScissorToWindowSpace(const DrawingFrame& frame, FloatRect scissorRect) -{ - IntRect scissorRectInCanvasSpace = enclosingIntRect(scissorRect); - // The scissor coordinates must be supplied in viewport space so we need to offset - // by the relative position of the top left corner of the current render pass. - IntRect framebufferOutputRect = frame.currentRenderPass->outputRect(); - scissorRectInCanvasSpace.setX(scissorRectInCanvasSpace.x() - framebufferOutputRect.x()); - if (frame.flippedY && !frame.currentTexture) - scissorRectInCanvasSpace.setY(framebufferOutputRect.height() - (scissorRectInCanvasSpace.maxY() - framebufferOutputRect.y())); - else - scissorRectInCanvasSpace.setY(scissorRectInCanvasSpace.y() - framebufferOutputRect.y()); - return scissorRectInCanvasSpace; -} - -CCDirectRenderer::CCDirectRenderer(CCRendererClient* client, CCResourceProvider* resourceProvider) - : CCRenderer(client) - , m_resourceProvider(resourceProvider) -{ -} - -CCDirectRenderer::~CCDirectRenderer() -{ -} - -void CCDirectRenderer::decideRenderPassAllocationsForFrame(const CCRenderPassList& renderPassesInDrawOrder) -{ - base::hash_map renderPassesInFrame; - for (size_t i = 0; i < renderPassesInDrawOrder.size(); ++i) - renderPassesInFrame.insert(std::pair(renderPassesInDrawOrder[i]->id(), renderPassesInDrawOrder[i])); - - std::vector passesToDelete; - ScopedPtrHashMap::const_iterator passIterator; - for (passIterator = m_renderPassTextures.begin(); passIterator != m_renderPassTextures.end(); ++passIterator) { - base::hash_map::const_iterator it = renderPassesInFrame.find(passIterator->first); - if (it == renderPassesInFrame.end()) { - passesToDelete.push_back(passIterator->first); - continue; - } - - const CCRenderPass* renderPassInFrame = it->second; - const IntSize& requiredSize = renderPassTextureSize(renderPassInFrame); - GC3Denum requiredFormat = renderPassTextureFormat(renderPassInFrame); - CachedTexture* texture = passIterator->second; - ASSERT(texture); - - if (texture->id() && (texture->size() != requiredSize || texture->format() != requiredFormat)) - texture->free(); - } - - // Delete RenderPass textures from the previous frame that will not be used again. - for (size_t i = 0; i < passesToDelete.size(); ++i) - m_renderPassTextures.erase(passesToDelete[i]); - - for (size_t i = 0; i < renderPassesInDrawOrder.size(); ++i) { - if (!m_renderPassTextures.contains(renderPassesInDrawOrder[i]->id())) { - scoped_ptr texture = CachedTexture::create(m_resourceProvider); - m_renderPassTextures.set(renderPassesInDrawOrder[i]->id(), texture.Pass()); - } - } -} - -void CCDirectRenderer::drawFrame(const CCRenderPassList& renderPassesInDrawOrder, const CCRenderPassIdHashMap& renderPassesById) -{ - const CCRenderPass* rootRenderPass = renderPassesInDrawOrder.back(); - ASSERT(rootRenderPass); - - DrawingFrame frame; - frame.renderPassesById = &renderPassesById; - frame.rootRenderPass = rootRenderPass; - frame.rootDamageRect = capabilities().usingPartialSwap ? rootRenderPass->damageRect() : rootRenderPass->outputRect(); - frame.rootDamageRect.intersect(IntRect(IntPoint::zero(), viewportSize())); - - beginDrawingFrame(frame); - for (size_t i = 0; i < renderPassesInDrawOrder.size(); ++i) - drawRenderPass(frame, renderPassesInDrawOrder[i]); - finishDrawingFrame(frame); -} - -void CCDirectRenderer::drawRenderPass(DrawingFrame& frame, const CCRenderPass* renderPass) -{ - if (!useRenderPass(frame, renderPass)) - return; - - frame.scissorRectInRenderPassSpace = frame.currentRenderPass->outputRect(); - if (frame.rootDamageRect != frame.rootRenderPass->outputRect()) { - WebTransformationMatrix inverseTransformToRoot = frame.currentRenderPass->transformToRootTarget().inverse(); - frame.scissorRectInRenderPassSpace.intersect(CCMathUtil::projectClippedRect(inverseTransformToRoot, frame.rootDamageRect)); - } - - enableScissorTestRect(moveScissorToWindowSpace(frame, frame.scissorRectInRenderPassSpace)); - clearFramebuffer(frame); - - const CCQuadList& quadList = renderPass->quadList(); - for (CCQuadList::constBackToFrontIterator it = quadList.backToFrontBegin(); it != quadList.backToFrontEnd(); ++it) { - FloatRect quadScissorRect = frame.scissorRectInRenderPassSpace; - quadScissorRect.intersect((*it)->clippedRectInTarget()); - if (!quadScissorRect.isEmpty()) { - enableScissorTestRect(moveScissorToWindowSpace(frame, quadScissorRect)); - drawQuad(frame, *it); - } - } - - CachedTexture* texture = m_renderPassTextures.get(renderPass->id()); - if (texture) - texture->setIsComplete(!renderPass->hasOcclusionFromOutsideTargetSurface()); -} - -bool CCDirectRenderer::useRenderPass(DrawingFrame& frame, const CCRenderPass* renderPass) -{ - frame.currentRenderPass = renderPass; - frame.currentTexture = 0; - - if (renderPass == frame.rootRenderPass) { - bindFramebufferToOutputSurface(frame); - initializeMatrices(frame, renderPass->outputRect(), flippedFramebuffer()); - setDrawViewportSize(renderPass->outputRect().size()); - return true; - } - - CachedTexture* texture = m_renderPassTextures.get(renderPass->id()); - ASSERT(texture); - if (!texture->id() && !texture->allocate(CCRenderer::ImplPool, renderPassTextureSize(renderPass), renderPassTextureFormat(renderPass), CCResourceProvider::TextureUsageFramebuffer)) - return false; - - return bindFramebufferToTexture(frame, texture, renderPass->outputRect()); -} - -bool CCDirectRenderer::haveCachedResourcesForRenderPassId(CCRenderPass::Id id) const -{ - CachedTexture* texture = m_renderPassTextures.get(id); - return texture && texture->id() && texture->isComplete(); -} - -// static -IntSize CCDirectRenderer::renderPassTextureSize(const CCRenderPass* pass) -{ - return pass->outputRect().size(); -} - -// static -GC3Denum CCDirectRenderer::renderPassTextureFormat(const CCRenderPass*) -{ - return GraphicsContext3D::RGBA; -} - -} diff --git a/cc/CCDirectRenderer.h b/cc/CCDirectRenderer.h index 73e6dc6..3e61292 100644 --- a/cc/CCDirectRenderer.h +++ b/cc/CCDirectRenderer.h @@ -2,104 +2,5 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CCDirectRenderer_h -#define CCDirectRenderer_h - -#include "base/basictypes.h" -#include "CCRenderer.h" -#include "CCResourceProvider.h" -#include "CCScopedTexture.h" - -namespace cc { - -class CCResourceProvider; - -// This is the base class for code shared between the GL and software -// renderer implementations. "Direct" refers to the fact that it does not -// delegate rendering to another compositor. -class CCDirectRenderer : public CCRenderer { -public: - virtual ~CCDirectRenderer(); - - CCResourceProvider* resourceProvider() const { return m_resourceProvider; } - - virtual void decideRenderPassAllocationsForFrame(const CCRenderPassList& renderPassesInDrawOrder) OVERRIDE; - virtual bool haveCachedResourcesForRenderPassId(CCRenderPass::Id) const OVERRIDE; - virtual void drawFrame(const CCRenderPassList& renderPassesInDrawOrder, const CCRenderPassIdHashMap& renderPassesById) OVERRIDE; - -protected: - CCDirectRenderer(CCRendererClient* client, CCResourceProvider* resourceProvider); - - struct DrawingFrame { - DrawingFrame(); - ~DrawingFrame(); - - const CCRenderPassIdHashMap* renderPassesById; - const CCRenderPass* rootRenderPass; - const CCRenderPass* currentRenderPass; - const CCScopedTexture* currentTexture; - - FloatRect rootDamageRect; - - WebKit::WebTransformationMatrix projectionMatrix; - WebKit::WebTransformationMatrix windowMatrix; - bool flippedY; - FloatRect scissorRectInRenderPassSpace; - }; - - class CachedTexture : public CCScopedTexture { - public: - static scoped_ptr create(CCResourceProvider* resourceProvider) { - return make_scoped_ptr(new CachedTexture(resourceProvider)); - } - virtual ~CachedTexture() {} - - bool isComplete() const { return m_isComplete; } - void setIsComplete(bool isComplete) { m_isComplete = isComplete; } - - protected: - explicit CachedTexture(CCResourceProvider* resourceProvider) - : CCScopedTexture(resourceProvider) - , m_isComplete(false) - { - } - - private: - bool m_isComplete; - - DISALLOW_COPY_AND_ASSIGN(CachedTexture); - }; - - static FloatRect quadVertexRect(); - static void quadRectTransform(WebKit::WebTransformationMatrix* quadRectTransform, const WebKit::WebTransformationMatrix& quadTransform, const FloatRect& quadRect); - static void initializeMatrices(DrawingFrame&, const IntRect& drawRect, bool flipY); - static IntRect moveScissorToWindowSpace(const DrawingFrame&, FloatRect scissorRect); - - bool haveCachedResources(CCRenderPass::Id) const; - static IntSize renderPassTextureSize(const CCRenderPass*); - static GC3Denum renderPassTextureFormat(const CCRenderPass*); - - void drawRenderPass(DrawingFrame&, const CCRenderPass*); - bool useRenderPass(DrawingFrame&, const CCRenderPass*); - - virtual void bindFramebufferToOutputSurface(DrawingFrame&) = 0; - virtual bool bindFramebufferToTexture(DrawingFrame&, const CCScopedTexture*, const IntRect& framebufferRect) = 0; - virtual void setDrawViewportSize(const IntSize&) = 0; - virtual void enableScissorTestRect(const IntRect& scissorRect) = 0; - virtual void disableScissorTest() = 0; - virtual void clearFramebuffer(DrawingFrame&) = 0; - virtual void drawQuad(DrawingFrame&, const CCDrawQuad*) = 0; - virtual void beginDrawingFrame(DrawingFrame&) = 0; - virtual void finishDrawingFrame(DrawingFrame&) = 0; - virtual bool flippedFramebuffer() const = 0; - - ScopedPtrHashMap m_renderPassTextures; - CCResourceProvider* m_resourceProvider; - -private: - DISALLOW_COPY_AND_ASSIGN(CCDirectRenderer); -}; - -} // namespace cc - -#endif // CCDirectRenderer_h +// Temporary forwarding header +#include "cc/direct_renderer.h" diff --git a/cc/CCDrawQuad.cpp b/cc/CCDrawQuad.cpp deleted file mode 100644 index b88eac6..0000000 --- a/cc/CCDrawQuad.cpp +++ /dev/null @@ -1,100 +0,0 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "config.h" -#include "CCDrawQuad.h" - -#include "CCCheckerboardDrawQuad.h" -#include "CCDebugBorderDrawQuad.h" -#include "CCIOSurfaceDrawQuad.h" -#include "CCRenderPassDrawQuad.h" -#include "CCSolidColorDrawQuad.h" -#include "CCStreamVideoDrawQuad.h" -#include "CCTextureDrawQuad.h" -#include "CCTileDrawQuad.h" -#include "CCYUVVideoDrawQuad.h" -#include "IntRect.h" - -namespace cc { - -CCDrawQuad::CCDrawQuad(const CCSharedQuadState* sharedQuadState, Material material, const IntRect& quadRect) - : m_sharedQuadState(sharedQuadState) - , m_sharedQuadStateId(sharedQuadState->id) - , m_material(material) - , m_quadRect(quadRect) - , m_quadVisibleRect(quadRect) - , m_quadOpaque(true) - , m_needsBlending(false) -{ - ASSERT(m_sharedQuadState); - ASSERT(m_material != Invalid); -} - -IntRect CCDrawQuad::opaqueRect() const -{ - if (opacity() != 1) - return IntRect(); - if (m_sharedQuadState->opaque && m_quadOpaque) - return m_quadRect; - return m_opaqueRect; -} - -void CCDrawQuad::setQuadVisibleRect(const IntRect& quadVisibleRect) -{ - IntRect intersection = quadVisibleRect; - intersection.intersect(m_quadRect); - m_quadVisibleRect = intersection; -} - -unsigned CCDrawQuad::size() const -{ - switch (material()) { - case Checkerboard: - return sizeof(CCCheckerboardDrawQuad); - case DebugBorder: - return sizeof(CCDebugBorderDrawQuad); - case IOSurfaceContent: - return sizeof(CCIOSurfaceDrawQuad); - case TextureContent: - return sizeof(CCTextureDrawQuad); - case SolidColor: - return sizeof(CCSolidColorDrawQuad); - case TiledContent: - return sizeof(CCTileDrawQuad); - case StreamVideoContent: - return sizeof(CCStreamVideoDrawQuad); - case RenderPass: - return sizeof(CCRenderPassDrawQuad); - case YUVVideoContent: - return sizeof(CCYUVVideoDrawQuad); - case Invalid: - break; - } - - CRASH(); - return sizeof(CCDrawQuad); -} - -scoped_ptr CCDrawQuad::copy(const CCSharedQuadState* copiedSharedQuadState) const -{ - // RenderPass quads have their own copy() method. - ASSERT(material() != RenderPass); - - unsigned bytes = size(); - ASSERT(bytes); - - scoped_ptr copyQuad(reinterpret_cast(new char[bytes])); - memcpy(copyQuad.get(), this, bytes); - copyQuad->setSharedQuadState(copiedSharedQuadState); - - return copyQuad.Pass(); -} - -void CCDrawQuad::setSharedQuadState(const CCSharedQuadState* sharedQuadState) -{ - m_sharedQuadState = sharedQuadState; - m_sharedQuadStateId = sharedQuadState->id; -} - -} diff --git a/cc/CCDrawQuad.h b/cc/CCDrawQuad.h index 05a6906..ca1a094 100644 --- a/cc/CCDrawQuad.h +++ b/cc/CCDrawQuad.h @@ -2,95 +2,5 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CCDrawQuad_h -#define CCDrawQuad_h - -#include "CCSharedQuadState.h" - -namespace cc { - -// WARNING! All CCXYZDrawQuad classes must remain PODs (plain old data). -// They are intended to be "serializable" by copying their raw bytes, so they -// must not contain any non-bit-copyable member variables! -// -// Furthermore, the class members need to be packed so they are aligned -// properly and don't have paddings/gaps, otherwise memory check tools -// like Valgrind will complain about uninitialized memory usage when -// transferring these classes over the wire. -#pragma pack(push, 4) - -// CCDrawQuad is a bag of data used for drawing a quad. Because different -// materials need different bits of per-quad data to render, classes that derive -// from CCDrawQuad store additional data in their derived instance. The Material -// enum is used to "safely" downcast to the derived class. -class CCDrawQuad { -public: - enum Material { - Invalid, - Checkerboard, - DebugBorder, - IOSurfaceContent, - RenderPass, - TextureContent, - SolidColor, - TiledContent, - YUVVideoContent, - StreamVideoContent, - }; - - IntRect quadRect() const { return m_quadRect; } - const WebKit::WebTransformationMatrix& quadTransform() const { return m_sharedQuadState->quadTransform; } - IntRect visibleContentRect() const { return m_sharedQuadState->visibleContentRect; } - IntRect clippedRectInTarget() const { return m_sharedQuadState->clippedRectInTarget; } - float opacity() const { return m_sharedQuadState->opacity; } - // For the purposes of blending, what part of the contents of this quad are opaque? - IntRect opaqueRect() const; - bool needsBlending() const { return m_needsBlending || !opaqueRect().contains(m_quadVisibleRect); } - - // Allows changing the rect that gets drawn to make it smaller. Parameter passed - // in will be clipped to quadRect(). - void setQuadVisibleRect(const IntRect&); - IntRect quadVisibleRect() const { return m_quadVisibleRect; } - bool isDebugQuad() const { return m_material == DebugBorder; } - - Material material() const { return m_material; } - - // Returns transfer size of this object based on the derived class (by - // looking at the material type). - unsigned size() const; - - scoped_ptr copy(const CCSharedQuadState* copiedSharedQuadState) const; - - const CCSharedQuadState* sharedQuadState() const { return m_sharedQuadState; } - int sharedQuadStateId() const { return m_sharedQuadStateId; } - void setSharedQuadState(const CCSharedQuadState*); - -protected: - CCDrawQuad(const CCSharedQuadState*, Material, const IntRect&); - - // Stores state common to a large bundle of quads; kept separate for memory - // efficiency. There is special treatment to reconstruct these pointers - // during serialization. - const CCSharedQuadState* m_sharedQuadState; - int m_sharedQuadStateId; - - Material m_material; - IntRect m_quadRect; - IntRect m_quadVisibleRect; - - // By default, the shared quad state determines whether or not this quad is - // opaque or needs blending. Derived classes can override with these - // variables. - bool m_quadOpaque; - bool m_needsBlending; - - // Be default, this rect is empty. It is used when the shared quad state and above - // variables determine that the quad is not fully opaque but may be partially opaque. - IntRect m_opaqueRect; -}; - -#pragma pack(pop) - -} - -#endif +// Temporary forwarding header +#include "cc/draw_quad.h" diff --git a/cc/CCFontAtlas.cpp b/cc/CCFontAtlas.cpp deleted file mode 100644 index 8be8b63..0000000 --- a/cc/CCFontAtlas.cpp +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "config.h" - -#if USE(ACCELERATED_COMPOSITING) -#include "CCFontAtlas.h" - -#include "base/string_split.h" -#include "ui/gfx/point.h" -#include "CCProxy.h" -#include "SkCanvas.h" -#include - -namespace cc { - -using namespace std; - -CCFontAtlas::CCFontAtlas(SkBitmap bitmap, IntRect asciiToRectTable[128], int fontHeight) - : m_atlas(bitmap) - , m_fontHeight(fontHeight) -{ - for (size_t i = 0; i < 128; ++i) - m_asciiToRectTable[i] = asciiToRectTable[i]; -} - -CCFontAtlas::~CCFontAtlas() -{ -} - -void CCFontAtlas::drawText(SkCanvas* canvas, const SkPaint& paint, const std::string& text, const gfx::Point& destPosition, const IntSize& clip) const -{ - ASSERT(CCProxy::isImplThread()); - - std::vector lines; - base::SplitString(text, '\n', &lines); - - gfx::Point position = destPosition; - for (size_t i = 0; i < lines.size(); ++i) { - drawOneLineOfTextInternal(canvas, paint, lines[i], position); - position.set_y(position.y() + m_fontHeight); - if (position.y() > clip.height()) - return; - } -} - -void CCFontAtlas::drawOneLineOfTextInternal(SkCanvas* canvas, const SkPaint& paint, const std::string& textLine, const gfx::Point& destPosition) const -{ - ASSERT(CCProxy::isImplThread()); - - gfx::Point position = destPosition; - for (unsigned i = 0; i < textLine.length(); ++i) { - // If the ASCII code is out of bounds, then index 0 is used, which is just a plain rectangle glyph. - int asciiIndex = (textLine[i] < 128) ? textLine[i] : 0; - IntRect glyphBounds = m_asciiToRectTable[asciiIndex]; - SkIRect source = SkIRect::MakeXYWH(glyphBounds.x(), glyphBounds.y(), glyphBounds.width(), glyphBounds.height()); - canvas->drawBitmapRect(m_atlas, &source, SkRect::MakeXYWH(position.x(), position.y(), glyphBounds.width(), glyphBounds.height()), &paint); - position.set_x(position.x() + glyphBounds.width()); - } -} - -void CCFontAtlas::drawDebugAtlas(SkCanvas* canvas, const gfx::Point& destPosition) const -{ - ASSERT(CCProxy::isImplThread()); - - SkIRect source = SkIRect::MakeWH(m_atlas.width(), m_atlas.height()); - canvas->drawBitmapRect(m_atlas, &source, SkRect::MakeXYWH(destPosition.x(), destPosition.y(), m_atlas.width(), m_atlas.height())); -} - -} // namespace cc - -#endif // USE(ACCELERATED_COMPOSITING) diff --git a/cc/CCFontAtlas.h b/cc/CCFontAtlas.h index 2881ee9..18463e4 100644 --- a/cc/CCFontAtlas.h +++ b/cc/CCFontAtlas.h @@ -2,69 +2,5 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CCFontAtlas_h -#define CCFontAtlas_h - -#if USE(ACCELERATED_COMPOSITING) - -#include - -#include "base/basictypes.h" -#include "base/memory/scoped_ptr.h" -#include "IntRect.h" -#include "SkBitmap.h" - -class SkCanvas; - -namespace gfx { -class Point; -} - -namespace cc { - -class Color; -class FontDescription; -class GraphicsContext; -class IntSize; - -// This class provides basic ability to draw text onto the heads-up display. -class CCFontAtlas { -public: - static scoped_ptr create(SkBitmap bitmap, IntRect asciiToRectTable[128], int fontHeight) - { - return make_scoped_ptr(new CCFontAtlas(bitmap, asciiToRectTable, fontHeight)); - } - ~CCFontAtlas(); - - // Draws multiple lines of text where each line of text is separated by '\n'. - // - Correct glyphs will be drawn for ASCII codes in the range 32-127; any characters - // outside that range will be displayed as a default rectangle glyph. - // - IntSize clip is used to avoid wasting time drawing things that are outside the - // target canvas bounds. - // - Should only be called only on the impl thread. - void drawText(SkCanvas*, const SkPaint&, const std::string& text, const gfx::Point& destPosition, const IntSize& clip) const; - - // Draws the entire atlas at the specified position, just for debugging purposes. - void drawDebugAtlas(SkCanvas*, const gfx::Point& destPosition) const; - -private: - CCFontAtlas(SkBitmap, IntRect asciiToRectTable[128], int fontHeight); - - void drawOneLineOfTextInternal(SkCanvas*, const SkPaint&, const std::string&, const gfx::Point& destPosition) const; - - // The actual texture atlas containing all the pre-rendered glyphs. - SkBitmap m_atlas; - - // The look-up tables mapping ascii characters to their IntRect locations on the atlas. - IntRect m_asciiToRectTable[128]; - - int m_fontHeight; - - DISALLOW_COPY_AND_ASSIGN(CCFontAtlas); -}; - -} // namespace cc - -#endif // USE(ACCELERATED_COMPOSITING) - -#endif +// Temporary forwarding header +#include "cc/font_atlas.h" diff --git a/cc/CCFrameRateController.cpp b/cc/CCFrameRateController.cpp deleted file mode 100644 index c996ebd..0000000 --- a/cc/CCFrameRateController.cpp +++ /dev/null @@ -1,161 +0,0 @@ -// Copyright 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "config.h" - -#include "CCFrameRateController.h" - -#include "CCDelayBasedTimeSource.h" -#include "CCTimeSource.h" -#include "TraceEvent.h" -#include - -namespace { - -// This will be the maximum number of pending frames unless -// CCFrameRateController::setMaxFramesPending is called. -const int defaultMaxFramesPending = 2; - -} // namespace - -namespace cc { - -class CCFrameRateControllerTimeSourceAdapter : public CCTimeSourceClient { -public: - static scoped_ptr create(CCFrameRateController* frameRateController) { - return make_scoped_ptr(new CCFrameRateControllerTimeSourceAdapter(frameRateController)); - } - virtual ~CCFrameRateControllerTimeSourceAdapter() {} - - virtual void onTimerTick() OVERRIDE { - m_frameRateController->onTimerTick(); - } - -private: - explicit CCFrameRateControllerTimeSourceAdapter(CCFrameRateController* frameRateController) - : m_frameRateController(frameRateController) {} - - CCFrameRateController* m_frameRateController; -}; - -CCFrameRateController::CCFrameRateController(PassRefPtr timer) - : m_client(0) - , m_numFramesPending(0) - , m_maxFramesPending(defaultMaxFramesPending) - , m_timeSource(timer) - , m_active(false) - , m_swapBuffersCompleteSupported(true) - , m_isTimeSourceThrottling(true) -{ - m_timeSourceClientAdapter = CCFrameRateControllerTimeSourceAdapter::create(this); - m_timeSource->setClient(m_timeSourceClientAdapter.get()); -} - -CCFrameRateController::CCFrameRateController(CCThread* thread) - : m_client(0) - , m_numFramesPending(0) - , m_maxFramesPending(defaultMaxFramesPending) - , m_active(false) - , m_swapBuffersCompleteSupported(true) - , m_isTimeSourceThrottling(false) - , m_manualTicker(new CCTimer(thread, this)) -{ -} - -CCFrameRateController::~CCFrameRateController() -{ - if (m_isTimeSourceThrottling) - m_timeSource->setActive(false); -} - -void CCFrameRateController::setActive(bool active) -{ - if (m_active == active) - return; - TRACE_EVENT1("cc", "CCFrameRateController::setActive", "active", active); - m_active = active; - - if (m_isTimeSourceThrottling) - m_timeSource->setActive(active); - else { - if (active) - postManualTick(); - else - m_manualTicker->stop(); - } -} - -void CCFrameRateController::setMaxFramesPending(int maxFramesPending) -{ - ASSERT(maxFramesPending > 0); - m_maxFramesPending = maxFramesPending; -} - -void CCFrameRateController::setTimebaseAndInterval(base::TimeTicks timebase, base::TimeDelta interval) -{ - if (m_isTimeSourceThrottling) - m_timeSource->setTimebaseAndInterval(timebase, interval); -} - -void CCFrameRateController::setSwapBuffersCompleteSupported(bool supported) -{ - m_swapBuffersCompleteSupported = supported; -} - -void CCFrameRateController::onTimerTick() -{ - ASSERT(m_active); - - // Check if we have too many frames in flight. - bool throttled = m_numFramesPending >= m_maxFramesPending; - - if (m_client) - m_client->vsyncTick(throttled); - - if (m_swapBuffersCompleteSupported && !m_isTimeSourceThrottling && m_numFramesPending < m_maxFramesPending) - postManualTick(); -} - -void CCFrameRateController::postManualTick() -{ - if (m_active) - m_manualTicker->startOneShot(0); -} - -void CCFrameRateController::onTimerFired() -{ - onTimerTick(); -} - -void CCFrameRateController::didBeginFrame() -{ - if (m_swapBuffersCompleteSupported) - m_numFramesPending++; - else if (!m_isTimeSourceThrottling) - postManualTick(); -} - -void CCFrameRateController::didFinishFrame() -{ - ASSERT(m_swapBuffersCompleteSupported); - - m_numFramesPending--; - if (!m_isTimeSourceThrottling) - postManualTick(); -} - -void CCFrameRateController::didAbortAllPendingFrames() -{ - m_numFramesPending = 0; -} - -base::TimeTicks CCFrameRateController::nextTickTime() -{ - if (m_isTimeSourceThrottling) - return m_timeSource->nextTickTime(); - - return base::TimeTicks(); -} - -} diff --git a/cc/CCFrameRateController.h b/cc/CCFrameRateController.h index 2aeeae1..e8d28b53 100644 --- a/cc/CCFrameRateController.h +++ b/cc/CCFrameRateController.h @@ -1,82 +1,6 @@ -// Copyright 2011 The Chromium Authors. All rights reserved. +// Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CCFrameRateController_h -#define CCFrameRateController_h - -#include "base/memory/scoped_ptr.h" -#include "base/time.h" -#include "CCTimer.h" -#include -#include - -namespace cc { - -class CCThread; -class CCTimeSource; - -class CCFrameRateControllerClient { -public: - // Throttled is true when we have a maximum number of frames pending. - virtual void vsyncTick(bool throttled) = 0; - -protected: - virtual ~CCFrameRateControllerClient() {} -}; - -class CCFrameRateControllerTimeSourceAdapter; - -class CCFrameRateController : public CCTimerClient { -public: - explicit CCFrameRateController(PassRefPtr); - // Alternate form of CCFrameRateController with unthrottled frame-rate. - explicit CCFrameRateController(CCThread*); - virtual ~CCFrameRateController(); - - void setClient(CCFrameRateControllerClient* client) { m_client = client; } - - void setActive(bool); - - // Use the following methods to adjust target frame rate. - // - // Multiple frames can be in-progress, but for every didBeginFrame, a - // didFinishFrame should be posted. - // - // If the rendering pipeline crashes, call didAbortAllPendingFrames. - void didBeginFrame(); - void didFinishFrame(); - void didAbortAllPendingFrames(); - void setMaxFramesPending(int); // 0 for unlimited. - - // This returns null for unthrottled frame-rate. - base::TimeTicks nextTickTime(); - - void setTimebaseAndInterval(base::TimeTicks timebase, base::TimeDelta interval); - void setSwapBuffersCompleteSupported(bool); - -protected: - friend class CCFrameRateControllerTimeSourceAdapter; - void onTimerTick(); - - void postManualTick(); - - // CCTimerClient implementation (used for unthrottled frame-rate). - virtual void onTimerFired() OVERRIDE; - - CCFrameRateControllerClient* m_client; - int m_numFramesPending; - int m_maxFramesPending; - RefPtr m_timeSource; - scoped_ptr m_timeSourceClientAdapter; - bool m_active; - bool m_swapBuffersCompleteSupported; - - // Members for unthrottled frame-rate. - bool m_isTimeSourceThrottling; - scoped_ptr m_manualTicker; -}; - -} // namespace cc - -#endif // CCFrameRateController_h +// Temporary forwarding header +#include "cc/frame_rate_controller.h" diff --git a/cc/CCFrameRateCounter.cpp b/cc/CCFrameRateCounter.cpp deleted file mode 100644 index 80074ed..0000000 --- a/cc/CCFrameRateCounter.cpp +++ /dev/null @@ -1,132 +0,0 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "config.h" - -#if USE(ACCELERATED_COMPOSITING) -#include "CCFrameRateCounter.h" - -#include - -#include "CCProxy.h" -#include -#include - -namespace cc { - -const double CCFrameRateCounter::kFrameTooFast = 1.0 / 70.0; // measured in seconds -const double CCFrameRateCounter::kFrameTooSlow = 1.0 / 12.0; -const double CCFrameRateCounter::kDroppedFrameTime = 1.0 / 50.0; - -// safeMod works on -1, returning m-1 in that case. -static inline int safeMod(int number, int modulus) -{ - return (number + modulus) % modulus; -} - -inline double CCFrameRateCounter::frameInterval(int frameNumber) const -{ - return m_timeStampHistory[frameIndex(frameNumber)] - - m_timeStampHistory[frameIndex(frameNumber - 1)]; -} - -inline int CCFrameRateCounter::frameIndex(int frameNumber) const -{ - return safeMod(frameNumber, kTimeStampHistorySize); -} - -CCFrameRateCounter::CCFrameRateCounter() - : m_currentFrameNumber(1) - , m_droppedFrameCount(0) -{ - m_timeStampHistory[0] = currentTime(); - m_timeStampHistory[1] = m_timeStampHistory[0]; - for (int i = 2; i < kTimeStampHistorySize; i++) - m_timeStampHistory[i] = 0; -} - -void CCFrameRateCounter::markBeginningOfFrame(double timestamp) -{ - m_timeStampHistory[frameIndex(m_currentFrameNumber)] = timestamp; - double frameIntervalSeconds = frameInterval(m_currentFrameNumber); - - if (CCProxy::hasImplThread() && m_currentFrameNumber > 0) { - double drawDelayMs = frameIntervalSeconds * 1000.0; - WebKit::Platform::current()->histogramCustomCounts("Renderer4.CompositorThreadImplDrawDelay", static_cast(drawDelayMs), 1, 120, 60); - } - - if (!isBadFrameInterval(frameIntervalSeconds) && frameIntervalSeconds > kDroppedFrameTime) - ++m_droppedFrameCount; -} - -void CCFrameRateCounter::markEndOfFrame() -{ - m_currentFrameNumber += 1; -} - -bool CCFrameRateCounter::isBadFrameInterval(double intervalBetweenConsecutiveFrames) const -{ - bool schedulerAllowsDoubleFrames = !CCProxy::hasImplThread(); - bool intervalTooFast = schedulerAllowsDoubleFrames && intervalBetweenConsecutiveFrames < kFrameTooFast; - bool intervalTooSlow = intervalBetweenConsecutiveFrames > kFrameTooSlow; - return intervalTooFast || intervalTooSlow; -} - -bool CCFrameRateCounter::isBadFrame(int frameNumber) const -{ - return isBadFrameInterval(frameInterval(frameNumber)); -} - -void CCFrameRateCounter::getAverageFPSAndStandardDeviation(double& averageFPS, double& standardDeviation) const -{ - int frame = m_currentFrameNumber - 1; - averageFPS = 0; - int averageFPSCount = 0; - double fpsVarianceNumerator = 0; - - // Walk backwards through the samples looking for a run of good frame - // timings from which to compute the mean and standard deviation. - // - // Slow frames occur just because the user is inactive, and should be - // ignored. Fast frames are ignored if the scheduler is in single-thread - // mode in order to represent the true frame rate in spite of the fact that - // the first few swapbuffers happen instantly which skews the statistics - // too much for short lived animations. - // - // isBadFrame encapsulates the frame too slow/frame too fast logic. - while (1) { - if (!isBadFrame(frame)) { - averageFPSCount++; - double secForLastFrame = m_timeStampHistory[frameIndex(frame)] - - m_timeStampHistory[frameIndex(frame - 1)]; - double x = 1.0 / secForLastFrame; - double deltaFromAverage = x - averageFPS; - // Change with caution - numerics. http://en.wikipedia.org/wiki/Standard_deviation - averageFPS = averageFPS + deltaFromAverage / averageFPSCount; - fpsVarianceNumerator = fpsVarianceNumerator + deltaFromAverage * (x - averageFPS); - } - if (averageFPSCount && isBadFrame(frame)) { - // We've gathered a run of good samples, so stop. - break; - } - --frame; - if (frameIndex(frame) == frameIndex(m_currentFrameNumber) || frame < 0) { - // We've gone through all available historical data, so stop. - break; - } - } - - standardDeviation = sqrt(fpsVarianceNumerator / averageFPSCount); -} - -double CCFrameRateCounter::timeStampOfRecentFrame(int n) -{ - ASSERT(n >= 0 && n < kTimeStampHistorySize); - int desiredIndex = (frameIndex(m_currentFrameNumber) + n) % kTimeStampHistorySize; - return m_timeStampHistory[desiredIndex]; -} - -} // namespace cc - -#endif // USE(ACCELERATED_COMPOSITING) diff --git a/cc/CCFrameRateCounter.h b/cc/CCFrameRateCounter.h index 76b4224..1a4708c 100644 --- a/cc/CCFrameRateCounter.h +++ b/cc/CCFrameRateCounter.h @@ -2,71 +2,5 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CCFrameRateCounter_h -#define CCFrameRateCounter_h - -#if USE(ACCELERATED_COMPOSITING) - -#include "base/basictypes.h" -#include - -namespace cc { - -// This class maintains a history of timestamps, and provides functionality to -// intelligently compute average frames per second (and standard deviation). -class CCFrameRateCounter { -public: - static PassOwnPtr create() - { - return adoptPtr(new CCFrameRateCounter()); - } - - void markBeginningOfFrame(double timestamp); - void markEndOfFrame(); - int currentFrameNumber() const { return m_currentFrameNumber; } - void getAverageFPSAndStandardDeviation(double& averageFPS, double& standardDeviation) const; - int timeStampHistorySize() const { return kTimeStampHistorySize; } - - // n = 0 returns the oldest frame retained in the history, - // while n = timeStampHistorySize() - 1 returns the timestamp most recent frame. - double timeStampOfRecentFrame(int /* n */); - - // This is a heuristic that can be used to ignore frames in a reasonable way. Returns - // true if the given frame interval is too fast or too slow, based on constant thresholds. - bool isBadFrameInterval(double intervalBetweenConsecutiveFrames) const; - - int droppedFrameCount() const { return m_droppedFrameCount; } - -private: - CCFrameRateCounter(); - - double frameInterval(int frameNumber) const; - int frameIndex(int frameNumber) const; - bool isBadFrame(int frameNumber) const; - - // Two thresholds (measured in seconds) that describe what is considered to be a "no-op frame" that should not be counted. - // - if the frame is too fast, then given our compositor implementation, the frame probably was a no-op and did not draw. - // - if the frame is too slow, then there is probably not animating content, so we should not pollute the average. - static const double kFrameTooFast; - static const double kFrameTooSlow; - - // If a frame takes longer than this threshold (measured in seconds) then we - // (naively) assume that it missed a screen refresh; that is, we dropped a frame. - // FIXME: Determine this threshold based on monitor refresh rate, crbug.com/138642. - static const double kDroppedFrameTime; - - static const int kTimeStampHistorySize = 120; - - int m_currentFrameNumber; - double m_timeStampHistory[kTimeStampHistorySize]; - - int m_droppedFrameCount; - - DISALLOW_COPY_AND_ASSIGN(CCFrameRateCounter); -}; - -} // namespace cc - -#endif // USE(ACCELERATED_COMPOSITING) - -#endif +// Temporary forwarding header +#include "cc/frame_rate_counter.h" diff --git a/cc/CCGraphicsContext.h b/cc/CCGraphicsContext.h index 6eb5b34..1193f1f 100644 --- a/cc/CCGraphicsContext.h +++ b/cc/CCGraphicsContext.h @@ -2,17 +2,5 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CCGraphicsContext_h -#define CCGraphicsContext_h - -#include -#include - -namespace cc { - -// FIXME: rename fully to CCOutputSurface. -typedef WebKit::WebCompositorOutputSurface CCGraphicsContext; - -} // namespace cc - -#endif // CCGraphicsContext_h +// Temporary forwarding header +#include "cc/graphics_context.h" diff --git a/cc/CCHeadsUpDisplayLayerImpl.cpp b/cc/CCHeadsUpDisplayLayerImpl.cpp deleted file mode 100644 index 58a490e..0000000 --- a/cc/CCHeadsUpDisplayLayerImpl.cpp +++ /dev/null @@ -1,296 +0,0 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "config.h" - -#include "CCHeadsUpDisplayLayerImpl.h" - -#include "base/stringprintf.h" -#include "ui/gfx/point.h" -#include "CCDebugRectHistory.h" -#include "CCFontAtlas.h" -#include "CCFrameRateCounter.h" -#include "CCLayerTreeHostImpl.h" -#include "CCQuadSink.h" -#include "CCTextureDrawQuad.h" -#include "Extensions3DChromium.h" -#include "GraphicsContext3D.h" -#include "SkBitmap.h" -#include "SkColorMatrixFilter.h" -#include "SkPaint.h" -#include "skia/ext/platform_canvas.h" - -namespace cc { - -static inline SkPaint createPaint() -{ - // The SkCanvas is in RGBA but the shader is expecting BGRA, so we need to - // swizzle our colors when drawing to the SkCanvas. - SkColorMatrix swizzleMatrix; - for (int i = 0; i < 20; ++i) - swizzleMatrix.fMat[i] = 0; - swizzleMatrix.fMat[0 + 5 * 2] = 1; - swizzleMatrix.fMat[1 + 5 * 1] = 1; - swizzleMatrix.fMat[2 + 5 * 0] = 1; - swizzleMatrix.fMat[3 + 5 * 3] = 1; - - SkPaint paint; - paint.setColorFilter(new SkColorMatrixFilter(swizzleMatrix))->unref(); - return paint; -} - -CCHeadsUpDisplayLayerImpl::CCHeadsUpDisplayLayerImpl(int id) - : CCLayerImpl(id) -{ -} - -CCHeadsUpDisplayLayerImpl::~CCHeadsUpDisplayLayerImpl() -{ -} - -void CCHeadsUpDisplayLayerImpl::setFontAtlas(scoped_ptr fontAtlas) -{ - m_fontAtlas = fontAtlas.Pass(); -} - -void CCHeadsUpDisplayLayerImpl::willDraw(CCResourceProvider* resourceProvider) -{ - CCLayerImpl::willDraw(resourceProvider); - - if (!m_hudTexture) - m_hudTexture = CCScopedTexture::create(resourceProvider); - - // FIXME: Scale the HUD by deviceScale to make it more friendly under high DPI. - - if (m_hudTexture->size() != bounds()) - m_hudTexture->free(); - - if (!m_hudTexture->id()) - m_hudTexture->allocate(CCRenderer::ImplPool, bounds(), GraphicsContext3D::RGBA, CCResourceProvider::TextureUsageAny); -} - -void CCHeadsUpDisplayLayerImpl::appendQuads(CCQuadSink& quadSink, CCAppendQuadsData& appendQuadsData) -{ - if (!m_hudTexture->id()) - return; - - CCSharedQuadState* sharedQuadState = quadSink.useSharedQuadState(createSharedQuadState()); - - IntRect quadRect(IntPoint(), bounds()); - bool premultipliedAlpha = true; - FloatRect uvRect(0, 0, 1, 1); - bool flipped = false; - quadSink.append(CCTextureDrawQuad::create(sharedQuadState, quadRect, m_hudTexture->id(), premultipliedAlpha, uvRect, flipped).PassAs(), appendQuadsData); -} - -void CCHeadsUpDisplayLayerImpl::updateHudTexture(CCResourceProvider* resourceProvider) -{ - if (!m_hudTexture->id()) - return; - - SkISize canvasSize; - if (m_hudCanvas) - canvasSize = m_hudCanvas->getDeviceSize(); - else - canvasSize.set(0, 0); - - if (canvasSize.fWidth != bounds().width() || canvasSize.fHeight != bounds().height() || !m_hudCanvas) - m_hudCanvas = adoptPtr(skia::CreateBitmapCanvas(bounds().width(), bounds().height(), false /* opaque */)); - - m_hudCanvas->clear(SkColorSetARGB(0, 0, 0, 0)); - drawHudContents(m_hudCanvas.get()); - - const SkBitmap* bitmap = &m_hudCanvas->getDevice()->accessBitmap(false); - SkAutoLockPixels locker(*bitmap); - - IntRect layerRect(IntPoint(), bounds()); - ASSERT(bitmap->config() == SkBitmap::kARGB_8888_Config); - resourceProvider->upload(m_hudTexture->id(), static_cast(bitmap->getPixels()), layerRect, layerRect, IntSize()); -} - -void CCHeadsUpDisplayLayerImpl::didDraw(CCResourceProvider* resourceProvider) -{ - CCLayerImpl::didDraw(resourceProvider); - - if (!m_hudTexture->id()) - return; - - // FIXME: the following assert will not be true when sending resources to a - // parent compositor. We will probably need to hold on to m_hudTexture for - // longer, and have several HUD textures in the pipeline. - ASSERT(!resourceProvider->inUseByConsumer(m_hudTexture->id())); -} - -void CCHeadsUpDisplayLayerImpl::didLoseContext() -{ - m_hudTexture.clear(); -} - -bool CCHeadsUpDisplayLayerImpl::layerIsAlwaysDamaged() const -{ - return true; -} - -void CCHeadsUpDisplayLayerImpl::drawHudContents(SkCanvas* canvas) -{ - const CCLayerTreeSettings& settings = layerTreeHostImpl()->settings(); - - if (settings.showPlatformLayerTree) { - SkPaint paint = createPaint(); - paint.setColor(SkColorSetARGB(192, 0, 0, 0)); - canvas->drawRect(SkRect::MakeXYWH(0, 0, bounds().width(), bounds().height()), paint); - } - - int fpsCounterHeight = 40; - int fpsCounterTop = 2; - int platformLayerTreeTop; - - if (settings.showFPSCounter) - platformLayerTreeTop = fpsCounterTop + fpsCounterHeight; - else - platformLayerTreeTop = 0; - - if (settings.showFPSCounter) - drawFPSCounter(canvas, layerTreeHostImpl()->fpsCounter(), fpsCounterTop, fpsCounterHeight); - - if (settings.showPlatformLayerTree && m_fontAtlas.get()) { - std::string layerTree = layerTreeHostImpl()->layerTreeAsText(); - m_fontAtlas->drawText(canvas, createPaint(), layerTree, gfx::Point(2, platformLayerTreeTop), bounds()); - } - - if (settings.showDebugRects()) - drawDebugRects(canvas, layerTreeHostImpl()->debugRectHistory()); -} - -void CCHeadsUpDisplayLayerImpl::drawFPSCounter(SkCanvas* canvas, CCFrameRateCounter* fpsCounter, int top, int height) -{ - float textWidth = 170; // so text fits on linux. - float graphWidth = fpsCounter->timeStampHistorySize(); - - // Draw the FPS text. - drawFPSCounterText(canvas, fpsCounter, top, textWidth, height); - - // Draw FPS graph. - const double loFPS = 0; - const double hiFPS = 80; - SkPaint paint = createPaint(); - paint.setColor(SkColorSetRGB(154, 205, 50)); - canvas->drawRect(SkRect::MakeXYWH(2 + textWidth, top, graphWidth, height / 2), paint); - - paint.setColor(SkColorSetRGB(255, 250, 205)); - canvas->drawRect(SkRect::MakeXYWH(2 + textWidth, top + height / 2, graphWidth, height / 2), paint); - - int graphLeft = static_cast(textWidth + 3); - int x = 0; - double h = static_cast(height - 2); - SkPath path; - for (int i = 0; i < fpsCounter->timeStampHistorySize() - 1; ++i) { - int j = i + 1; - double delta = fpsCounter->timeStampOfRecentFrame(j) - fpsCounter->timeStampOfRecentFrame(i); - - // Skip plotting this particular instantaneous frame rate if it is not likely to have been valid. - if (fpsCounter->isBadFrameInterval(delta)) { - x += 1; - continue; - } - - double fps = 1.0 / delta; - - // Clamp the FPS to the range we want to plot visually. - double p = 1 - ((fps - loFPS) / (hiFPS - loFPS)); - if (p < 0) - p = 0; - if (p > 1) - p = 1; - - // Plot this data point. - SkPoint cur = SkPoint::Make(graphLeft + x, 1 + top + p*h); - if (path.isEmpty()) - path.moveTo(cur); - else - path.lineTo(cur); - x += 1; - } - paint.setColor(SK_ColorRED); - paint.setStyle(SkPaint::kStroke_Style); - paint.setStrokeWidth(1); - paint.setAntiAlias(true); - canvas->drawPath(path, paint); -} - -void CCHeadsUpDisplayLayerImpl::drawFPSCounterText(SkCanvas* canvas, CCFrameRateCounter* fpsCounter, int top, int width, int height) -{ - double averageFPS, stdDeviation; - fpsCounter->getAverageFPSAndStandardDeviation(averageFPS, stdDeviation); - - // Draw background. - SkPaint paint = createPaint(); - paint.setColor(SK_ColorBLACK); - canvas->drawRect(SkRect::MakeXYWH(2, top, width, height), paint); - - // Draw FPS text. - if (m_fontAtlas.get()) - m_fontAtlas->drawText(canvas, createPaint(), base::StringPrintf("FPS: %4.1f +/- %3.1f", averageFPS, stdDeviation), gfx::Point(10, height / 3), IntSize(width, height)); -} - -void CCHeadsUpDisplayLayerImpl::drawDebugRects(SkCanvas* canvas, CCDebugRectHistory* debugRectHistory) -{ - const Vector& debugRects = debugRectHistory->debugRects(); - - for (size_t i = 0; i < debugRects.size(); ++i) { - SkColor strokeColor = 0; - SkColor fillColor = 0; - - switch (debugRects[i].type) { - case PaintRectType: - // Paint rects in red - strokeColor = SkColorSetARGB(255, 255, 0, 0); - fillColor = SkColorSetARGB(30, 255, 0, 0); - break; - case PropertyChangedRectType: - // Property-changed rects in blue - strokeColor = SkColorSetARGB(255, 255, 0, 0); - fillColor = SkColorSetARGB(30, 0, 0, 255); - break; - case SurfaceDamageRectType: - // Surface damage rects in yellow-orange - strokeColor = SkColorSetARGB(255, 200, 100, 0); - fillColor = SkColorSetARGB(30, 200, 100, 0); - break; - case ReplicaScreenSpaceRectType: - // Screen space rects in green. - strokeColor = SkColorSetARGB(255, 100, 200, 0); - fillColor = SkColorSetARGB(30, 100, 200, 0); - break; - case ScreenSpaceRectType: - // Screen space rects in purple. - strokeColor = SkColorSetARGB(255, 100, 0, 200); - fillColor = SkColorSetARGB(10, 100, 0, 200); - break; - case OccludingRectType: - // Occluding rects in a reddish color. - strokeColor = SkColorSetARGB(255, 200, 0, 100); - fillColor = SkColorSetARGB(10, 200, 0, 100); - break; - } - - const FloatRect& rect = debugRects[i].rect; - SkRect skRect = SkRect::MakeXYWH(rect.x(), rect.y(), rect.width(), rect.height()); - SkPaint paint = createPaint(); - paint.setColor(fillColor); - canvas->drawRect(skRect, paint); - - paint.setColor(strokeColor); - paint.setStyle(SkPaint::kStroke_Style); - paint.setStrokeWidth(2); - canvas->drawRect(skRect, paint); - } -} - -const char* CCHeadsUpDisplayLayerImpl::layerTypeAsString() const -{ - return "HeadsUpDisplayLayer"; -} - -} diff --git a/cc/CCHeadsUpDisplayLayerImpl.h b/cc/CCHeadsUpDisplayLayerImpl.h index 47e7cfe..ec7b160 100644 --- a/cc/CCHeadsUpDisplayLayerImpl.h +++ b/cc/CCHeadsUpDisplayLayerImpl.h @@ -2,56 +2,5 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CCHeadsUpDisplayLayerImpl_h -#define CCHeadsUpDisplayLayerImpl_h - -#include "base/memory/scoped_ptr.h" -#include "CCFontAtlas.h" -#include "CCLayerImpl.h" -#include "CCScopedTexture.h" - -class SkCanvas; - -namespace cc { - -class CCDebugRectHistory; -class CCFontAtlas; -class CCFrameRateCounter; - -class CCHeadsUpDisplayLayerImpl : public CCLayerImpl { -public: - static scoped_ptr create(int id) - { - return make_scoped_ptr(new CCHeadsUpDisplayLayerImpl(id)); - } - virtual ~CCHeadsUpDisplayLayerImpl(); - - void setFontAtlas(scoped_ptr); - - virtual void willDraw(CCResourceProvider*) OVERRIDE; - virtual void appendQuads(CCQuadSink&, CCAppendQuadsData&) OVERRIDE; - void updateHudTexture(CCResourceProvider*); - virtual void didDraw(CCResourceProvider*) OVERRIDE; - - virtual void didLoseContext() OVERRIDE; - - virtual bool layerIsAlwaysDamaged() const OVERRIDE; - -private: - explicit CCHeadsUpDisplayLayerImpl(int); - - virtual const char* layerTypeAsString() const OVERRIDE; - - void drawHudContents(SkCanvas*); - void drawFPSCounter(SkCanvas*, CCFrameRateCounter*, int top, int height); - void drawFPSCounterText(SkCanvas*, CCFrameRateCounter*, int top, int width, int height); - void drawDebugRects(SkCanvas*, CCDebugRectHistory*); - - scoped_ptr m_fontAtlas; - OwnPtr m_hudTexture; - OwnPtr m_hudCanvas; -}; - -} // namespace cc - -#endif // CCHeadsUpDisplayLayerImpl_h +// Temporary forwarding header +#include "cc/heads_up_display_layer_impl.h" diff --git a/cc/CCIOSurfaceDrawQuad.cpp b/cc/CCIOSurfaceDrawQuad.cpp deleted file mode 100644 index 5d50043..0000000 --- a/cc/CCIOSurfaceDrawQuad.cpp +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "config.h" - -#include "CCIOSurfaceDrawQuad.h" - -namespace cc { - -scoped_ptr CCIOSurfaceDrawQuad::create(const CCSharedQuadState* sharedQuadState, const IntRect& quadRect, const IntSize& ioSurfaceSize, unsigned ioSurfaceTextureId, Orientation orientation) -{ - return make_scoped_ptr(new CCIOSurfaceDrawQuad(sharedQuadState, quadRect, ioSurfaceSize, ioSurfaceTextureId, orientation)); -} - -CCIOSurfaceDrawQuad::CCIOSurfaceDrawQuad(const CCSharedQuadState* sharedQuadState, const IntRect& quadRect, const IntSize& ioSurfaceSize, unsigned ioSurfaceTextureId, Orientation orientation) - : CCDrawQuad(sharedQuadState, CCDrawQuad::IOSurfaceContent, quadRect) - , m_ioSurfaceSize(ioSurfaceSize) - , m_ioSurfaceTextureId(ioSurfaceTextureId) - , m_orientation(orientation) -{ -} - -const CCIOSurfaceDrawQuad* CCIOSurfaceDrawQuad::materialCast(const CCDrawQuad* quad) -{ - ASSERT(quad->material() == CCDrawQuad::IOSurfaceContent); - return static_cast(quad); -} - -} // namespace cc diff --git a/cc/CCIOSurfaceDrawQuad.h b/cc/CCIOSurfaceDrawQuad.h index bb5b028..e0faa3e 100644 --- a/cc/CCIOSurfaceDrawQuad.h +++ b/cc/CCIOSurfaceDrawQuad.h @@ -2,41 +2,5 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CCIOSurfaceDrawQuad_h -#define CCIOSurfaceDrawQuad_h - -#include "CCDrawQuad.h" -#include "IntSize.h" -#include "base/memory/scoped_ptr.h" - -namespace cc { - -#pragma pack(push, 4) - -class CCIOSurfaceDrawQuad : public CCDrawQuad { -public: - enum Orientation { - Flipped, - Unflipped - }; - - static scoped_ptr create(const CCSharedQuadState*, const IntRect&, const IntSize& ioSurfaceSize, unsigned ioSurfaceTextureId, Orientation); - - IntSize ioSurfaceSize() const { return m_ioSurfaceSize; } - unsigned ioSurfaceTextureId() const { return m_ioSurfaceTextureId; } - Orientation orientation() const { return m_orientation; } - - static const CCIOSurfaceDrawQuad* materialCast(const CCDrawQuad*); -private: - CCIOSurfaceDrawQuad(const CCSharedQuadState*, const IntRect&, const IntSize& ioSurfaceSize, unsigned ioSurfaceTextureId, Orientation); - - IntSize m_ioSurfaceSize; - unsigned m_ioSurfaceTextureId; - Orientation m_orientation; -}; - -#pragma pack(pop) - -} - -#endif +// Temporary forwarding header +#include "cc/io_surface_draw_quad.h" diff --git a/cc/CCIOSurfaceLayerImpl.cpp b/cc/CCIOSurfaceLayerImpl.cpp deleted file mode 100644 index 689a003..0000000 --- a/cc/CCIOSurfaceLayerImpl.cpp +++ /dev/null @@ -1,118 +0,0 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "config.h" - -#if USE(ACCELERATED_COMPOSITING) - -#include "CCIOSurfaceLayerImpl.h" - -#include "base/stringprintf.h" -#include "CCGraphicsContext.h" -#include "CCIOSurfaceDrawQuad.h" -#include "CCLayerTreeHostImpl.h" -#include "CCQuadSink.h" -#include "CCRendererGL.h" // For the GLC() macro. -#include "Extensions3D.h" -#include - -namespace cc { - -CCIOSurfaceLayerImpl::CCIOSurfaceLayerImpl(int id) - : CCLayerImpl(id) - , m_ioSurfaceId(0) - , m_ioSurfaceChanged(false) - , m_ioSurfaceTextureId(0) -{ -} - -CCIOSurfaceLayerImpl::~CCIOSurfaceLayerImpl() -{ - if (!m_ioSurfaceTextureId) - return; - - CCGraphicsContext* context = layerTreeHostImpl()->context(); - // FIXME: Implement this path for software compositing. - WebKit::WebGraphicsContext3D* context3d = context->context3D(); - if (context3d) - context3d->deleteTexture(m_ioSurfaceTextureId); -} - -void CCIOSurfaceLayerImpl::willDraw(CCResourceProvider* resourceProvider) -{ - CCLayerImpl::willDraw(resourceProvider); - - if (m_ioSurfaceChanged) { - WebKit::WebGraphicsContext3D* context3d = resourceProvider->graphicsContext3D(); - if (!context3d) { - // FIXME: Implement this path for software compositing. - return; - } - - // FIXME: Do this in a way that we can track memory usage. - if (!m_ioSurfaceTextureId) - m_ioSurfaceTextureId = context3d->createTexture(); - - GLC(context3d, context3d->activeTexture(GraphicsContext3D::TEXTURE0)); - GLC(context3d, context3d->bindTexture(Extensions3D::TEXTURE_RECTANGLE_ARB, m_ioSurfaceTextureId)); - GLC(context3d, context3d->texParameteri(Extensions3D::TEXTURE_RECTANGLE_ARB, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR)); - GLC(context3d, context3d->texParameteri(Extensions3D::TEXTURE_RECTANGLE_ARB, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR)); - GLC(context3d, context3d->texParameteri(Extensions3D::TEXTURE_RECTANGLE_ARB, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE)); - GLC(context3d, context3d->texParameteri(Extensions3D::TEXTURE_RECTANGLE_ARB, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE)); - context3d->texImageIOSurface2DCHROMIUM(Extensions3D::TEXTURE_RECTANGLE_ARB, - m_ioSurfaceSize.width(), - m_ioSurfaceSize.height(), - m_ioSurfaceId, - 0); - // Do not check for error conditions. texImageIOSurface2DCHROMIUM is supposed to hold on to - // the last good IOSurface if the new one is already closed. This is only a possibility - // during live resizing of plugins. However, it seems that this is not sufficient to - // completely guard against garbage being drawn. If this is found to be a significant issue, - // it may be necessary to explicitly tell the embedder when to free the surfaces it has - // allocated. - m_ioSurfaceChanged = false; - } -} - -void CCIOSurfaceLayerImpl::appendQuads(CCQuadSink& quadSink, CCAppendQuadsData& appendQuadsData) -{ - CCSharedQuadState* sharedQuadState = quadSink.useSharedQuadState(createSharedQuadState()); - appendDebugBorderQuad(quadSink, sharedQuadState, appendQuadsData); - - IntRect quadRect(IntPoint(), contentBounds()); - quadSink.append(CCIOSurfaceDrawQuad::create(sharedQuadState, quadRect, m_ioSurfaceSize, m_ioSurfaceTextureId, CCIOSurfaceDrawQuad::Flipped).PassAs(), appendQuadsData); -} - -void CCIOSurfaceLayerImpl::dumpLayerProperties(std::string* str, int indent) const -{ - str->append(indentString(indent)); - base::StringAppendF(str, "iosurface id: %u texture id: %u\n", m_ioSurfaceId, m_ioSurfaceTextureId); - CCLayerImpl::dumpLayerProperties(str, indent); -} - -void CCIOSurfaceLayerImpl::didLoseContext() -{ - // We don't have a valid texture ID in the new context; however, - // the IOSurface is still valid. - m_ioSurfaceTextureId = 0; - m_ioSurfaceChanged = true; -} - -void CCIOSurfaceLayerImpl::setIOSurfaceProperties(unsigned ioSurfaceId, const IntSize& size) -{ - if (m_ioSurfaceId != ioSurfaceId) - m_ioSurfaceChanged = true; - - m_ioSurfaceId = ioSurfaceId; - m_ioSurfaceSize = size; -} - -const char* CCIOSurfaceLayerImpl::layerTypeAsString() const -{ - return "IOSurfaceLayer"; -} - -} - -#endif // USE(ACCELERATED_COMPOSITING) diff --git a/cc/CCIOSurfaceLayerImpl.h b/cc/CCIOSurfaceLayerImpl.h index 238e27e..6cbf984 100644 --- a/cc/CCIOSurfaceLayerImpl.h +++ b/cc/CCIOSurfaceLayerImpl.h @@ -2,42 +2,5 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CCIOSurfaceLayerImpl_h -#define CCIOSurfaceLayerImpl_h - -#include "CCLayerImpl.h" -#include "IntSize.h" - -namespace cc { - -class CCIOSurfaceLayerImpl : public CCLayerImpl { -public: - static scoped_ptr create(int id) - { - return make_scoped_ptr(new CCIOSurfaceLayerImpl(id)); - } - virtual ~CCIOSurfaceLayerImpl(); - - void setIOSurfaceProperties(unsigned ioSurfaceId, const IntSize&); - - virtual void appendQuads(CCQuadSink&, CCAppendQuadsData&) OVERRIDE; - - virtual void willDraw(CCResourceProvider*) OVERRIDE; - virtual void didLoseContext() OVERRIDE; - - virtual void dumpLayerProperties(std::string*, int indent) const OVERRIDE; - -private: - explicit CCIOSurfaceLayerImpl(int); - - virtual const char* layerTypeAsString() const OVERRIDE; - - unsigned m_ioSurfaceId; - IntSize m_ioSurfaceSize; - bool m_ioSurfaceChanged; - unsigned m_ioSurfaceTextureId; -}; - -} - -#endif // CCIOSurfaceLayerImpl_h +// Temporary forwarding header +#include "cc/io_surface_layer_impl.h" diff --git a/cc/CCInputHandler.h b/cc/CCInputHandler.h index 7188cab..88f1b37 100644 --- a/cc/CCInputHandler.h +++ b/cc/CCInputHandler.h @@ -1,83 +1,6 @@ -// Copyright 2011 The Chromium Authors. All rights reserved. +// Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CCInputHandler_h -#define CCInputHandler_h - -#include "base/basictypes.h" -#include - -namespace cc { - -class IntPoint; -class IntSize; - -// The CCInputHandler is a way for the embedders to interact with -// the impl thread side of the compositor implementation. -// -// There is one CCInputHandler for every CCLayerTreeHost. It is -// created on the main thread and used only on the impl thread. -// -// The CCInputHandler is constructed with a CCInputHandlerClient, which is the -// interface by which the handler can manipulate the LayerTree. -class CCInputHandlerClient { -public: - enum ScrollStatus { ScrollOnMainThread, ScrollStarted, ScrollIgnored }; - enum ScrollInputType { Gesture, Wheel }; - - // Selects a layer to be scrolled at a given point in window coordinates. - // Returns ScrollStarted if the layer at the coordinates can be scrolled, - // ScrollOnMainThread if the scroll event should instead be delegated to the - // main thread, or ScrollIgnored if there is nothing to be scrolled at the - // given coordinates. - virtual ScrollStatus scrollBegin(const IntPoint&, ScrollInputType) = 0; - - // Scroll the selected layer starting at the given window coordinate. If - // there is no room to move the layer in the requested direction, its first - // ancestor layer that can be scrolled will be moved instead. Should only be - // called if scrollBegin() returned ScrollStarted. - virtual void scrollBy(const IntPoint&, const IntSize&) = 0; - - // Stop scrolling the selected layer. Should only be called if scrollBegin() - // returned ScrollStarted. - virtual void scrollEnd() = 0; - - virtual void pinchGestureBegin() = 0; - virtual void pinchGestureUpdate(float magnifyDelta, const IntPoint& anchor) = 0; - virtual void pinchGestureEnd() = 0; - - virtual void startPageScaleAnimation(const IntSize& targetPosition, - bool anchorPoint, - float pageScale, - double startTime, - double duration) = 0; - - // Request another callback to CCInputHandler::animate(). - virtual void scheduleAnimation() = 0; - -protected: - CCInputHandlerClient() { } - virtual ~CCInputHandlerClient() { } - -private: - DISALLOW_COPY_AND_ASSIGN(CCInputHandlerClient); -}; - -class CCInputHandler { -public: - virtual ~CCInputHandler() { } - - virtual void bindToClient(CCInputHandlerClient*) = 0; - virtual void animate(double monotonicTime) = 0; - -protected: - CCInputHandler() { } - -private: - DISALLOW_COPY_AND_ASSIGN(CCInputHandler); -}; - -} - -#endif +// Temporary forwarding header +#include "cc/input_handler.h" diff --git a/cc/CCKeyframedAnimationCurve.cpp b/cc/CCKeyframedAnimationCurve.cpp deleted file mode 100644 index a6b368e..0000000 --- a/cc/CCKeyframedAnimationCurve.cpp +++ /dev/null @@ -1,223 +0,0 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "config.h" - -#include "CCKeyframedAnimationCurve.h" - -using WebKit::WebTransformationMatrix; - -namespace cc { - -namespace { - -template -void insertKeyframe(scoped_ptr keyframe, ScopedPtrVector& keyframes) -{ - // Usually, the keyframes will be added in order, so this loop would be unnecessary and - // we should skip it if possible. - if (!keyframes.isEmpty() && keyframe->time() < keyframes.last()->time()) { - for (size_t i = 0; i < keyframes.size(); ++i) { - if (keyframe->time() < keyframes[i]->time()) { - keyframes.insert(i, keyframe.Pass()); - return; - } - } - } - - keyframes.append(keyframe.Pass()); -} - -scoped_ptr cloneTimingFunction(const CCTimingFunction* timingFunction) -{ - ASSERT(timingFunction); - scoped_ptr curve(timingFunction->clone()); - return scoped_ptr(static_cast(curve.release())); -} - -} // namespace - -CCKeyframe::CCKeyframe(double time, scoped_ptr timingFunction) - : m_time(time) - , m_timingFunction(timingFunction.Pass()) -{ -} - -CCKeyframe::~CCKeyframe() -{ -} - -double CCKeyframe::time() const -{ - return m_time; -} - -const CCTimingFunction* CCKeyframe::timingFunction() const -{ - return m_timingFunction.get(); -} - -scoped_ptr CCFloatKeyframe::create(double time, float value, scoped_ptr timingFunction) -{ - return make_scoped_ptr(new CCFloatKeyframe(time, value, timingFunction.Pass())); -} - -CCFloatKeyframe::CCFloatKeyframe(double time, float value, scoped_ptr timingFunction) - : CCKeyframe(time, timingFunction.Pass()) - , m_value(value) -{ -} - -CCFloatKeyframe::~CCFloatKeyframe() -{ -} - -float CCFloatKeyframe::value() const -{ - return m_value; -} - -scoped_ptr CCFloatKeyframe::clone() const -{ - scoped_ptr func; - if (timingFunction()) - func = cloneTimingFunction(timingFunction()); - return CCFloatKeyframe::create(time(), value(), func.Pass()); -} - -scoped_ptr CCTransformKeyframe::create(double time, const WebKit::WebTransformOperations& value, scoped_ptr timingFunction) -{ - return make_scoped_ptr(new CCTransformKeyframe(time, value, timingFunction.Pass())); -} - -CCTransformKeyframe::CCTransformKeyframe(double time, const WebKit::WebTransformOperations& value, scoped_ptr timingFunction) - : CCKeyframe(time, timingFunction.Pass()) - , m_value(value) -{ -} - -CCTransformKeyframe::~CCTransformKeyframe() -{ -} - -const WebKit::WebTransformOperations& CCTransformKeyframe::value() const -{ - return m_value; -} - -scoped_ptr CCTransformKeyframe::clone() const -{ - scoped_ptr func; - if (timingFunction()) - func = cloneTimingFunction(timingFunction()); - return CCTransformKeyframe::create(time(), value(), func.Pass()); -} - -scoped_ptr CCKeyframedFloatAnimationCurve::create() -{ - return make_scoped_ptr(new CCKeyframedFloatAnimationCurve); -} - -CCKeyframedFloatAnimationCurve::CCKeyframedFloatAnimationCurve() -{ -} - -CCKeyframedFloatAnimationCurve::~CCKeyframedFloatAnimationCurve() -{ -} - -void CCKeyframedFloatAnimationCurve::addKeyframe(scoped_ptr keyframe) -{ - insertKeyframe(keyframe.Pass(), m_keyframes); -} - -double CCKeyframedFloatAnimationCurve::duration() const -{ - return m_keyframes.last()->time() - m_keyframes.first()->time(); -} - -scoped_ptr CCKeyframedFloatAnimationCurve::clone() const -{ - scoped_ptr toReturn(CCKeyframedFloatAnimationCurve::create()); - for (size_t i = 0; i < m_keyframes.size(); ++i) - toReturn->addKeyframe(m_keyframes[i]->clone()); - return toReturn.PassAs(); -} - -float CCKeyframedFloatAnimationCurve::getValue(double t) const -{ - if (t <= m_keyframes.first()->time()) - return m_keyframes.first()->value(); - - if (t >= m_keyframes.last()->time()) - return m_keyframes.last()->value(); - - size_t i = 0; - for (; i < m_keyframes.size() - 1; ++i) { - if (t < m_keyframes[i+1]->time()) - break; - } - - float progress = static_cast((t - m_keyframes[i]->time()) / (m_keyframes[i+1]->time() - m_keyframes[i]->time())); - - if (m_keyframes[i]->timingFunction()) - progress = m_keyframes[i]->timingFunction()->getValue(progress); - - return m_keyframes[i]->value() + (m_keyframes[i+1]->value() - m_keyframes[i]->value()) * progress; -} - -scoped_ptr CCKeyframedTransformAnimationCurve::create() -{ - return make_scoped_ptr(new CCKeyframedTransformAnimationCurve); -} - -CCKeyframedTransformAnimationCurve::CCKeyframedTransformAnimationCurve() -{ -} - -CCKeyframedTransformAnimationCurve::~CCKeyframedTransformAnimationCurve() -{ -} - -void CCKeyframedTransformAnimationCurve::addKeyframe(scoped_ptr keyframe) -{ - insertKeyframe(keyframe.Pass(), m_keyframes); -} - -double CCKeyframedTransformAnimationCurve::duration() const -{ - return m_keyframes.last()->time() - m_keyframes.first()->time(); -} - -scoped_ptr CCKeyframedTransformAnimationCurve::clone() const -{ - scoped_ptr toReturn(CCKeyframedTransformAnimationCurve::create()); - for (size_t i = 0; i < m_keyframes.size(); ++i) - toReturn->addKeyframe(m_keyframes[i]->clone()); - return toReturn.PassAs(); -} - -WebTransformationMatrix CCKeyframedTransformAnimationCurve::getValue(double t) const -{ - if (t <= m_keyframes.first()->time()) - return m_keyframes.first()->value().apply(); - - if (t >= m_keyframes.last()->time()) - return m_keyframes.last()->value().apply(); - - size_t i = 0; - for (; i < m_keyframes.size() - 1; ++i) { - if (t < m_keyframes[i+1]->time()) - break; - } - - double progress = (t - m_keyframes[i]->time()) / (m_keyframes[i+1]->time() - m_keyframes[i]->time()); - - if (m_keyframes[i]->timingFunction()) - progress = m_keyframes[i]->timingFunction()->getValue(progress); - - return m_keyframes[i+1]->value().blend(m_keyframes[i]->value(), progress); -} - -} // namespace cc diff --git a/cc/CCKeyframedAnimationCurve.h b/cc/CCKeyframedAnimationCurve.h index 066e5c6..3cd919d5 100644 --- a/cc/CCKeyframedAnimationCurve.h +++ b/cc/CCKeyframedAnimationCurve.h @@ -2,108 +2,5 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CCKeyframedAnimationCurve_h -#define CCKeyframedAnimationCurve_h - -#include "CCAnimationCurve.h" -#include "CCTimingFunction.h" -#include "scoped_ptr_vector.h" -#include - -namespace cc { - -class CCKeyframe { -public: - double time() const; - const CCTimingFunction* timingFunction() const; - -protected: - CCKeyframe(double time, scoped_ptr); - virtual ~CCKeyframe(); - -private: - double m_time; - scoped_ptr m_timingFunction; -}; - -class CCFloatKeyframe : public CCKeyframe { -public: - static scoped_ptr create(double time, float value, scoped_ptr); - virtual ~CCFloatKeyframe(); - - float value() const; - - scoped_ptr clone() const; - -private: - CCFloatKeyframe(double time, float value, scoped_ptr); - - float m_value; -}; - -class CCTransformKeyframe : public CCKeyframe { -public: - static scoped_ptr create(double time, const WebKit::WebTransformOperations& value, scoped_ptr); - virtual ~CCTransformKeyframe(); - - const WebKit::WebTransformOperations& value() const; - - scoped_ptr clone() const; - -private: - CCTransformKeyframe(double time, const WebKit::WebTransformOperations& value, scoped_ptr); - - WebKit::WebTransformOperations m_value; -}; - -class CCKeyframedFloatAnimationCurve : public CCFloatAnimationCurve { -public: - // It is required that the keyframes be sorted by time. - static scoped_ptr create(); - - virtual ~CCKeyframedFloatAnimationCurve(); - - void addKeyframe(scoped_ptr); - - // CCAnimationCurve implementation - virtual double duration() const OVERRIDE; - virtual scoped_ptr clone() const OVERRIDE; - - // CCFloatAnimationCurve implementation - virtual float getValue(double t) const OVERRIDE; - -private: - CCKeyframedFloatAnimationCurve(); - - // Always sorted in order of increasing time. No two keyframes have the - // same time. - ScopedPtrVector m_keyframes; -}; - -class CCKeyframedTransformAnimationCurve : public CCTransformAnimationCurve { -public: - // It is required that the keyframes be sorted by time. - static scoped_ptr create(); - - virtual ~CCKeyframedTransformAnimationCurve(); - - void addKeyframe(scoped_ptr); - - // CCAnimationCurve implementation - virtual double duration() const OVERRIDE; - virtual scoped_ptr clone() const OVERRIDE; - - // CCTransformAnimationCurve implementation - virtual WebKit::WebTransformationMatrix getValue(double t) const OVERRIDE; - -private: - CCKeyframedTransformAnimationCurve(); - - // Always sorted in order of increasing time. No two keyframes have the - // same time. - ScopedPtrVector m_keyframes; -}; - -} // namespace cc - -#endif // CCKeyframedAnimationCurve_h +// Temporary forwarding header +#include "cc/keyframed_animation_curve.h" diff --git a/cc/CCLayerAnimationController.cpp b/cc/CCLayerAnimationController.cpp deleted file mode 100644 index 2025db8..0000000 --- a/cc/CCLayerAnimationController.cpp +++ /dev/null @@ -1,407 +0,0 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "config.h" - -#include "CCLayerAnimationController.h" - -#include "CCActiveAnimation.h" -#include "CCKeyframedAnimationCurve.h" -#include -#include -#include - -using WebKit::WebTransformationMatrix; - -namespace cc { - -CCLayerAnimationController::CCLayerAnimationController(CCLayerAnimationControllerClient* client) - : m_forceSync(false) - , m_client(client) -{ -} - -CCLayerAnimationController::~CCLayerAnimationController() -{ -} - -scoped_ptr CCLayerAnimationController::create(CCLayerAnimationControllerClient* client) -{ - return make_scoped_ptr(new CCLayerAnimationController(client)); -} - -void CCLayerAnimationController::pauseAnimation(int animationId, double timeOffset) -{ - for (size_t i = 0; i < m_activeAnimations.size(); ++i) { - if (m_activeAnimations[i]->id() == animationId) - m_activeAnimations[i]->setRunState(CCActiveAnimation::Paused, timeOffset + m_activeAnimations[i]->startTime()); - } -} - -void CCLayerAnimationController::removeAnimation(int animationId) -{ - for (size_t i = 0; i < m_activeAnimations.size();) { - if (m_activeAnimations[i]->id() == animationId) - m_activeAnimations.remove(i); - else - i++; - } -} - -void CCLayerAnimationController::removeAnimation(int animationId, CCActiveAnimation::TargetProperty targetProperty) -{ - for (size_t i = 0; i < m_activeAnimations.size();) { - if (m_activeAnimations[i]->id() == animationId && m_activeAnimations[i]->targetProperty() == targetProperty) - m_activeAnimations.remove(i); - else - i++; - } -} - -// According to render layer backing, these are for testing only. -void CCLayerAnimationController::suspendAnimations(double monotonicTime) -{ - for (size_t i = 0; i < m_activeAnimations.size(); ++i) { - if (!m_activeAnimations[i]->isFinished()) - m_activeAnimations[i]->setRunState(CCActiveAnimation::Paused, monotonicTime); - } -} - -// Looking at GraphicsLayerCA, this appears to be the analog to suspendAnimations, which is for testing. -void CCLayerAnimationController::resumeAnimations(double monotonicTime) -{ - for (size_t i = 0; i < m_activeAnimations.size(); ++i) { - if (m_activeAnimations[i]->runState() == CCActiveAnimation::Paused) - m_activeAnimations[i]->setRunState(CCActiveAnimation::Running, monotonicTime); - } -} - -// Ensures that the list of active animations on the main thread and the impl thread -// are kept in sync. -void CCLayerAnimationController::pushAnimationUpdatesTo(CCLayerAnimationController* controllerImpl) -{ - if (m_forceSync) { - replaceImplThreadAnimations(controllerImpl); - m_forceSync = false; - } else { - purgeAnimationsMarkedForDeletion(); - pushNewAnimationsToImplThread(controllerImpl); - - // Remove finished impl side animations only after pushing, - // and only after the animations are deleted on the main thread - // this insures we will never push an animation twice. - removeAnimationsCompletedOnMainThread(controllerImpl); - - pushPropertiesToImplThread(controllerImpl); - } -} - -void CCLayerAnimationController::animate(double monotonicTime, CCAnimationEventsVector* events) -{ - startAnimationsWaitingForNextTick(monotonicTime, events); - startAnimationsWaitingForStartTime(monotonicTime, events); - startAnimationsWaitingForTargetAvailability(monotonicTime, events); - resolveConflicts(monotonicTime); - tickAnimations(monotonicTime); - markAnimationsForDeletion(monotonicTime, events); - startAnimationsWaitingForTargetAvailability(monotonicTime, events); -} - -void CCLayerAnimationController::addAnimation(scoped_ptr animation) -{ - m_activeAnimations.append(animation.Pass()); -} - -CCActiveAnimation* CCLayerAnimationController::getActiveAnimation(int groupId, CCActiveAnimation::TargetProperty targetProperty) const -{ - for (size_t i = 0; i < m_activeAnimations.size(); ++i) - if (m_activeAnimations[i]->group() == groupId && m_activeAnimations[i]->targetProperty() == targetProperty) - return m_activeAnimations[i]; - return 0; -} - -CCActiveAnimation* CCLayerAnimationController::getActiveAnimation(CCActiveAnimation::TargetProperty targetProperty) const -{ - for (size_t i = 0; i < m_activeAnimations.size(); ++i) { - size_t index = m_activeAnimations.size() - i - 1; - if (m_activeAnimations[index]->targetProperty() == targetProperty) - return m_activeAnimations[index]; - } - return 0; -} - -bool CCLayerAnimationController::hasActiveAnimation() const -{ - for (size_t i = 0; i < m_activeAnimations.size(); ++i) { - if (!m_activeAnimations[i]->isFinished()) - return true; - } - return false; -} - -bool CCLayerAnimationController::isAnimatingProperty(CCActiveAnimation::TargetProperty targetProperty) const -{ - for (size_t i = 0; i < m_activeAnimations.size(); ++i) { - if (m_activeAnimations[i]->runState() != CCActiveAnimation::Finished && m_activeAnimations[i]->runState() != CCActiveAnimation::Aborted && m_activeAnimations[i]->targetProperty() == targetProperty) - return true; - } - return false; -} - -void CCLayerAnimationController::notifyAnimationStarted(const CCAnimationEvent& event) -{ - for (size_t i = 0; i < m_activeAnimations.size(); ++i) { - if (m_activeAnimations[i]->group() == event.groupId && m_activeAnimations[i]->targetProperty() == event.targetProperty && m_activeAnimations[i]->needsSynchronizedStartTime()) { - m_activeAnimations[i]->setNeedsSynchronizedStartTime(false); - m_activeAnimations[i]->setStartTime(event.monotonicTime); - return; - } - } -} - -void CCLayerAnimationController::setClient(CCLayerAnimationControllerClient* client) -{ - m_client = client; -} - -void CCLayerAnimationController::pushNewAnimationsToImplThread(CCLayerAnimationController* controllerImpl) const -{ - // Any new animations owned by the main thread's controller are cloned and adde to the impl thread's controller. - for (size_t i = 0; i < m_activeAnimations.size(); ++i) { - // If the animation is already running on the impl thread, there is no need to copy it over. - if (controllerImpl->getActiveAnimation(m_activeAnimations[i]->group(), m_activeAnimations[i]->targetProperty())) - continue; - - // If the animation is not running on the impl thread, it does not necessarily mean that it needs - // to be copied over and started; it may have already finished. In this case, the impl thread animation - // will have already notified that it has started and the main thread animation will no longer need - // a synchronized start time. - if (!m_activeAnimations[i]->needsSynchronizedStartTime()) - continue; - - // The new animation should be set to run as soon as possible. - CCActiveAnimation::RunState initialRunState = CCActiveAnimation::WaitingForTargetAvailability; - double startTime = 0; - scoped_ptr toAdd(m_activeAnimations[i]->cloneAndInitialize(CCActiveAnimation::ControllingInstance, initialRunState, startTime)); - ASSERT(!toAdd->needsSynchronizedStartTime()); - controllerImpl->addAnimation(toAdd.Pass()); - } -} - -void CCLayerAnimationController::removeAnimationsCompletedOnMainThread(CCLayerAnimationController* controllerImpl) const -{ - // Delete all impl thread animations for which there is no corresponding main thread animation. - // Each iteration, controller->m_activeAnimations.size() is decremented or i is incremented - // guaranteeing progress towards loop termination. - for (size_t i = 0; i < controllerImpl->m_activeAnimations.size();) { - CCActiveAnimation* current = getActiveAnimation(controllerImpl->m_activeAnimations[i]->group(), controllerImpl->m_activeAnimations[i]->targetProperty()); - if (!current) - controllerImpl->m_activeAnimations.remove(i); - else - i++; - } -} - -void CCLayerAnimationController::pushPropertiesToImplThread(CCLayerAnimationController* controllerImpl) const -{ - for (size_t i = 0; i < m_activeAnimations.size(); ++i) { - CCActiveAnimation* currentImpl = controllerImpl->getActiveAnimation(m_activeAnimations[i]->group(), m_activeAnimations[i]->targetProperty()); - if (currentImpl) - m_activeAnimations[i]->pushPropertiesTo(currentImpl); - } -} - -void CCLayerAnimationController::startAnimationsWaitingForNextTick(double monotonicTime, CCAnimationEventsVector* events) -{ - for (size_t i = 0; i < m_activeAnimations.size(); ++i) { - if (m_activeAnimations[i]->runState() == CCActiveAnimation::WaitingForNextTick) { - m_activeAnimations[i]->setRunState(CCActiveAnimation::Running, monotonicTime); - if (!m_activeAnimations[i]->hasSetStartTime()) - m_activeAnimations[i]->setStartTime(monotonicTime); - if (events) - events->push_back(CCAnimationEvent(CCAnimationEvent::Started, m_client->id(), m_activeAnimations[i]->group(), m_activeAnimations[i]->targetProperty(), monotonicTime)); - } - } -} - -void CCLayerAnimationController::startAnimationsWaitingForStartTime(double monotonicTime, CCAnimationEventsVector* events) -{ - for (size_t i = 0; i < m_activeAnimations.size(); ++i) { - if (m_activeAnimations[i]->runState() == CCActiveAnimation::WaitingForStartTime && m_activeAnimations[i]->startTime() <= monotonicTime) { - m_activeAnimations[i]->setRunState(CCActiveAnimation::Running, monotonicTime); - if (events) - events->push_back(CCAnimationEvent(CCAnimationEvent::Started, m_client->id(), m_activeAnimations[i]->group(), m_activeAnimations[i]->targetProperty(), monotonicTime)); - } - } -} - -void CCLayerAnimationController::startAnimationsWaitingForTargetAvailability(double monotonicTime, CCAnimationEventsVector* events) -{ - // First collect running properties. - TargetProperties blockedProperties; - for (size_t i = 0; i < m_activeAnimations.size(); ++i) { - if (m_activeAnimations[i]->runState() == CCActiveAnimation::Running || m_activeAnimations[i]->runState() == CCActiveAnimation::Finished) - blockedProperties.insert(m_activeAnimations[i]->targetProperty()); - } - - for (size_t i = 0; i < m_activeAnimations.size(); ++i) { - if (m_activeAnimations[i]->runState() == CCActiveAnimation::WaitingForTargetAvailability) { - // Collect all properties for animations with the same group id (they should all also be in the list of animations). - TargetProperties enqueuedProperties; - enqueuedProperties.insert(m_activeAnimations[i]->targetProperty()); - for (size_t j = i + 1; j < m_activeAnimations.size(); ++j) { - if (m_activeAnimations[i]->group() == m_activeAnimations[j]->group()) - enqueuedProperties.insert(m_activeAnimations[j]->targetProperty()); - } - - // Check to see if intersection of the list of properties affected by the group and the list of currently - // blocked properties is null. In any case, the group's target properties need to be added to the list - // of blocked properties. - bool nullIntersection = true; - for (TargetProperties::iterator pIter = enqueuedProperties.begin(); pIter != enqueuedProperties.end(); ++pIter) { - if (!blockedProperties.insert(*pIter).second) - nullIntersection = false; - } - - // If the intersection is null, then we are free to start the animations in the group. - if (nullIntersection) { - m_activeAnimations[i]->setRunState(CCActiveAnimation::Running, monotonicTime); - if (!m_activeAnimations[i]->hasSetStartTime()) - m_activeAnimations[i]->setStartTime(monotonicTime); - if (events) - events->push_back(CCAnimationEvent(CCAnimationEvent::Started, m_client->id(), m_activeAnimations[i]->group(), m_activeAnimations[i]->targetProperty(), monotonicTime)); - for (size_t j = i + 1; j < m_activeAnimations.size(); ++j) { - if (m_activeAnimations[i]->group() == m_activeAnimations[j]->group()) { - m_activeAnimations[j]->setRunState(CCActiveAnimation::Running, monotonicTime); - if (!m_activeAnimations[j]->hasSetStartTime()) - m_activeAnimations[j]->setStartTime(monotonicTime); - } - } - } - } - } -} - -void CCLayerAnimationController::resolveConflicts(double monotonicTime) -{ - // Find any animations that are animating the same property and resolve the - // confict. We could eventually blend, but for now we'll just abort the - // previous animation (where 'previous' means: (1) has a prior start time or - // (2) has an equal start time, but was added to the queue earlier, i.e., - // has a lower index in m_activeAnimations). - for (size_t i = 0; i < m_activeAnimations.size(); ++i) { - if (m_activeAnimations[i]->runState() == CCActiveAnimation::Running) { - for (size_t j = i + 1; j < m_activeAnimations.size(); ++j) { - if (m_activeAnimations[j]->runState() == CCActiveAnimation::Running && m_activeAnimations[i]->targetProperty() == m_activeAnimations[j]->targetProperty()) { - if (m_activeAnimations[i]->startTime() > m_activeAnimations[j]->startTime()) - m_activeAnimations[j]->setRunState(CCActiveAnimation::Aborted, monotonicTime); - else - m_activeAnimations[i]->setRunState(CCActiveAnimation::Aborted, monotonicTime); - } - } - } - } -} - -void CCLayerAnimationController::markAnimationsForDeletion(double monotonicTime, CCAnimationEventsVector* events) -{ - for (size_t i = 0; i < m_activeAnimations.size(); i++) { - int groupId = m_activeAnimations[i]->group(); - bool allAnimsWithSameIdAreFinished = false; - // If an animation is finished, and not already marked for deletion, - // Find out if all other animations in the same group are also finished. - if (m_activeAnimations[i]->isFinished()) { - allAnimsWithSameIdAreFinished = true; - for (size_t j = 0; j < m_activeAnimations.size(); ++j) { - if (groupId == m_activeAnimations[j]->group() && !m_activeAnimations[j]->isFinished()) { - allAnimsWithSameIdAreFinished = false; - break; - } - } - } - if (allAnimsWithSameIdAreFinished) { - // We now need to remove all animations with the same group id as groupId - // (and send along animation finished notifications, if necessary). - for (size_t j = i; j < m_activeAnimations.size(); j++) { - if (groupId == m_activeAnimations[j]->group()) { - if (events) - events->push_back(CCAnimationEvent(CCAnimationEvent::Finished, m_client->id(), m_activeAnimations[j]->group(), m_activeAnimations[j]->targetProperty(), monotonicTime)); - m_activeAnimations[j]->setRunState(CCActiveAnimation::WaitingForDeletion, monotonicTime); - } - } - } - } -} - -void CCLayerAnimationController::purgeAnimationsMarkedForDeletion() -{ - for (size_t i = 0; i < m_activeAnimations.size();) { - if (m_activeAnimations[i]->runState() == CCActiveAnimation::WaitingForDeletion) - m_activeAnimations.remove(i); - else - i++; - } -} - -void CCLayerAnimationController::replaceImplThreadAnimations(CCLayerAnimationController* controllerImpl) const -{ - controllerImpl->m_activeAnimations.clear(); - for (size_t i = 0; i < m_activeAnimations.size(); ++i) { - scoped_ptr toAdd; - if (m_activeAnimations[i]->needsSynchronizedStartTime()) { - // We haven't received an animation started notification yet, so it - // is important that we add it in a 'waiting' and not 'running' state. - CCActiveAnimation::RunState initialRunState = CCActiveAnimation::WaitingForTargetAvailability; - double startTime = 0; - toAdd = m_activeAnimations[i]->cloneAndInitialize(CCActiveAnimation::ControllingInstance, initialRunState, startTime).Pass(); - } else - toAdd = m_activeAnimations[i]->clone(CCActiveAnimation::ControllingInstance).Pass(); - - controllerImpl->addAnimation(toAdd.Pass()); - } -} - -void CCLayerAnimationController::tickAnimations(double monotonicTime) -{ - for (size_t i = 0; i < m_activeAnimations.size(); ++i) { - if (m_activeAnimations[i]->runState() == CCActiveAnimation::Running || m_activeAnimations[i]->runState() == CCActiveAnimation::Paused) { - double trimmed = m_activeAnimations[i]->trimTimeToCurrentIteration(monotonicTime); - - // Animation assumes its initial value until it gets the synchronized start time - // from the impl thread and can start ticking. - if (m_activeAnimations[i]->needsSynchronizedStartTime()) - trimmed = 0; - - switch (m_activeAnimations[i]->targetProperty()) { - - case CCActiveAnimation::Transform: { - const CCTransformAnimationCurve* transformAnimationCurve = m_activeAnimations[i]->curve()->toTransformAnimationCurve(); - const WebTransformationMatrix matrix = transformAnimationCurve->getValue(trimmed); - if (m_activeAnimations[i]->isFinishedAt(monotonicTime)) - m_activeAnimations[i]->setRunState(CCActiveAnimation::Finished, monotonicTime); - - m_client->setTransformFromAnimation(matrix); - break; - } - - case CCActiveAnimation::Opacity: { - const CCFloatAnimationCurve* floatAnimationCurve = m_activeAnimations[i]->curve()->toFloatAnimationCurve(); - const float opacity = floatAnimationCurve->getValue(trimmed); - if (m_activeAnimations[i]->isFinishedAt(monotonicTime)) - m_activeAnimations[i]->setRunState(CCActiveAnimation::Finished, monotonicTime); - - m_client->setOpacityFromAnimation(opacity); - break; - } - - // Do nothing for sentinel value. - case CCActiveAnimation::TargetPropertyEnumSize: - ASSERT_NOT_REACHED(); - - } - } - } -} - -} // namespace cc diff --git a/cc/CCLayerAnimationController.h b/cc/CCLayerAnimationController.h index 2fdb91c..9f44af2 100644 --- a/cc/CCLayerAnimationController.h +++ b/cc/CCLayerAnimationController.h @@ -2,111 +2,5 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CCLayerAnimationController_h -#define CCLayerAnimationController_h - -#include "CCAnimationEvents.h" - -#include "base/basictypes.h" -#include "base/hash_tables.h" -#include "base/memory/scoped_ptr.h" -#include "cc/scoped_ptr_vector.h" - -namespace WebKit { -class WebTransformationMatrix; -} - -namespace cc { - -class Animation; -class IntSize; -class KeyframeValueList; - -class CCLayerAnimationControllerClient { -public: - virtual ~CCLayerAnimationControllerClient() { } - - virtual int id() const = 0; - virtual void setOpacityFromAnimation(float) = 0; - virtual float opacity() const = 0; - virtual void setTransformFromAnimation(const WebKit::WebTransformationMatrix&) = 0; - virtual const WebKit::WebTransformationMatrix& transform() const = 0; -}; - -class CCLayerAnimationController { -public: - static scoped_ptr create(CCLayerAnimationControllerClient*); - - virtual ~CCLayerAnimationController(); - - // These methods are virtual for testing. - virtual void addAnimation(scoped_ptr); - virtual void pauseAnimation(int animationId, double timeOffset); - virtual void removeAnimation(int animationId); - virtual void removeAnimation(int animationId, CCActiveAnimation::TargetProperty); - virtual void suspendAnimations(double monotonicTime); - virtual void resumeAnimations(double monotonicTime); - - // Ensures that the list of active animations on the main thread and the impl thread - // are kept in sync. This function does not take ownership of the impl thread controller. - virtual void pushAnimationUpdatesTo(CCLayerAnimationController*); - - void animate(double monotonicTime, CCAnimationEventsVector*); - - // Returns the active animation in the given group, animating the given property, if such an - // animation exists. - CCActiveAnimation* getActiveAnimation(int groupId, CCActiveAnimation::TargetProperty) const; - - // Returns the active animation animating the given property that is either running, or is - // next to run, if such an animation exists. - CCActiveAnimation* getActiveAnimation(CCActiveAnimation::TargetProperty) const; - - // Returns true if there are any animations that have neither finished nor aborted. - bool hasActiveAnimation() const; - - // Returns true if there is an animation currently animating the given property, or - // if there is an animation scheduled to animate this property in the future. - bool isAnimatingProperty(CCActiveAnimation::TargetProperty) const; - - // This is called in response to an animation being started on the impl thread. This - // function updates the corresponding main thread animation's start time. - void notifyAnimationStarted(const CCAnimationEvent&); - - // If a sync is forced, then the next time animation updates are pushed to the impl - // thread, all animations will be transferred. - void setForceSync() { m_forceSync = true; } - - void setClient(CCLayerAnimationControllerClient*); - -protected: - explicit CCLayerAnimationController(CCLayerAnimationControllerClient*); - -private: - typedef base::hash_set TargetProperties; - - void pushNewAnimationsToImplThread(CCLayerAnimationController*) const; - void removeAnimationsCompletedOnMainThread(CCLayerAnimationController*) const; - void pushPropertiesToImplThread(CCLayerAnimationController*) const; - void replaceImplThreadAnimations(CCLayerAnimationController*) const; - - void startAnimationsWaitingForNextTick(double monotonicTime, CCAnimationEventsVector*); - void startAnimationsWaitingForStartTime(double monotonicTime, CCAnimationEventsVector*); - void startAnimationsWaitingForTargetAvailability(double monotonicTime, CCAnimationEventsVector*); - void resolveConflicts(double monotonicTime); - void markAnimationsForDeletion(double monotonicTime, CCAnimationEventsVector*); - void purgeAnimationsMarkedForDeletion(); - - void tickAnimations(double monotonicTime); - - // If this is true, we force a sync to the impl thread. - bool m_forceSync; - - CCLayerAnimationControllerClient* m_client; - ScopedPtrVector m_activeAnimations; - - DISALLOW_COPY_AND_ASSIGN(CCLayerAnimationController); -}; - -} // namespace cc - -#endif // CCLayerAnimationController_h +// Temporary forwarding header +#include "cc/layer_animation_controller.h" diff --git a/cc/CCLayerImpl.cpp b/cc/CCLayerImpl.cpp deleted file mode 100644 index 16c9356..0000000 --- a/cc/CCLayerImpl.cpp +++ /dev/null @@ -1,685 +0,0 @@ -// Copyright 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "config.h" - -#if USE(ACCELERATED_COMPOSITING) - -#include "CCLayerImpl.h" - -#include "base/stringprintf.h" -#include "CCDebugBorderDrawQuad.h" -#include "CCLayerSorter.h" -#include "CCMathUtil.h" -#include "CCProxy.h" -#include "CCQuadSink.h" -#include "CCScrollbarAnimationController.h" -#include "CCSettings.h" -#include "TraceEvent.h" - -using WebKit::WebTransformationMatrix; - -namespace cc { - -CCLayerImpl::CCLayerImpl(int id) - : m_parent(0) - , m_maskLayerId(-1) - , m_replicaLayerId(-1) - , m_layerId(id) - , m_layerTreeHostImpl(0) - , m_anchorPoint(0.5, 0.5) - , m_anchorPointZ(0) - , m_scrollable(false) - , m_shouldScrollOnMainThread(false) - , m_haveWheelEventHandlers(false) - , m_backgroundColor(0) - , m_doubleSided(true) - , m_layerPropertyChanged(false) - , m_layerSurfacePropertyChanged(false) - , m_masksToBounds(false) - , m_contentsOpaque(false) - , m_opacity(1.0) - , m_preserves3D(false) - , m_useParentBackfaceVisibility(false) - , m_drawCheckerboardForMissingTiles(false) - , m_useLCDText(false) - , m_drawsContent(false) - , m_forceRenderSurface(false) - , m_isContainerForFixedPositionLayers(false) - , m_fixedToContainerLayer(false) - , m_renderTarget(0) - , m_drawDepth(0) - , m_drawOpacity(0) - , m_drawOpacityIsAnimating(false) - , m_debugBorderColor(0) - , m_debugBorderWidth(0) - , m_drawTransformIsAnimating(false) - , m_screenSpaceTransformIsAnimating(false) -#ifndef NDEBUG - , m_betweenWillDrawAndDidDraw(false) -#endif - , m_layerAnimationController(CCLayerAnimationController::create(this)) -{ - ASSERT(CCProxy::isImplThread()); - ASSERT(m_layerId > 0); -} - -CCLayerImpl::~CCLayerImpl() -{ - ASSERT(CCProxy::isImplThread()); -#ifndef NDEBUG - ASSERT(!m_betweenWillDrawAndDidDraw); -#endif -} - -void CCLayerImpl::addChild(scoped_ptr child) -{ - child->setParent(this); - m_children.append(child.Pass()); -} - -void CCLayerImpl::removeFromParent() -{ - if (!m_parent) - return; - - CCLayerImpl* parent = m_parent; - m_parent = 0; - - for (size_t i = 0; i < parent->m_children.size(); ++i) { - if (parent->m_children[i] == this) { - parent->m_children.remove(i); - return; - } - } -} - -void CCLayerImpl::removeAllChildren() -{ - while (m_children.size()) - m_children[0]->removeFromParent(); -} - -void CCLayerImpl::clearChildList() -{ - m_children.clear(); -} - -void CCLayerImpl::createRenderSurface() -{ - ASSERT(!m_renderSurface); - m_renderSurface = adoptPtr(new CCRenderSurface(this)); - setRenderTarget(this); -} - -bool CCLayerImpl::descendantDrawsContent() -{ - for (size_t i = 0; i < m_children.size(); ++i) { - if (m_children[i]->drawsContent() || m_children[i]->descendantDrawsContent()) - return true; - } - return false; -} - -scoped_ptr CCLayerImpl::createSharedQuadState() const -{ - return CCSharedQuadState::create(m_drawTransform, m_visibleContentRect, m_drawableContentRect, m_drawOpacity, m_contentsOpaque); -} - -void CCLayerImpl::willDraw(CCResourceProvider*) -{ -#ifndef NDEBUG - // willDraw/didDraw must be matched. - ASSERT(!m_betweenWillDrawAndDidDraw); - m_betweenWillDrawAndDidDraw = true; -#endif -} - -void CCLayerImpl::didDraw(CCResourceProvider*) -{ -#ifndef NDEBUG - ASSERT(m_betweenWillDrawAndDidDraw); - m_betweenWillDrawAndDidDraw = false; -#endif -} - -void CCLayerImpl::appendDebugBorderQuad(CCQuadSink& quadList, const CCSharedQuadState* sharedQuadState, CCAppendQuadsData& appendQuadsData) const -{ - if (!hasDebugBorders()) - return; - - IntRect contentRect(IntPoint(), contentBounds()); - quadList.append(CCDebugBorderDrawQuad::create(sharedQuadState, contentRect, debugBorderColor(), debugBorderWidth()).PassAs(), appendQuadsData); -} - -bool CCLayerImpl::hasContributingDelegatedRenderPasses() const -{ - return false; -} - -CCRenderPass::Id CCLayerImpl::firstContributingRenderPassId() const -{ - return CCRenderPass::Id(0, 0); -} - -CCRenderPass::Id CCLayerImpl::nextContributingRenderPassId(CCRenderPass::Id) const -{ - return CCRenderPass::Id(0, 0); -} - -CCResourceProvider::ResourceId CCLayerImpl::contentsResourceId() const -{ - ASSERT_NOT_REACHED(); - return 0; -} - -FloatSize CCLayerImpl::scrollBy(const FloatSize& scroll) -{ - IntSize minDelta = -toSize(m_scrollPosition); - IntSize maxDelta = m_maxScrollPosition - toSize(m_scrollPosition); - // Clamp newDelta so that position + delta stays within scroll bounds. - FloatSize newDelta = (m_scrollDelta + scroll).expandedTo(minDelta).shrunkTo(maxDelta); - FloatSize unscrolled = m_scrollDelta + scroll - newDelta; - - if (m_scrollDelta == newDelta) - return unscrolled; - - m_scrollDelta = newDelta; - if (m_scrollbarAnimationController) - m_scrollbarAnimationController->updateScrollOffset(this); - noteLayerPropertyChangedForSubtree(); - - return unscrolled; -} - -CCInputHandlerClient::ScrollStatus CCLayerImpl::tryScroll(const IntPoint& viewportPoint, CCInputHandlerClient::ScrollInputType type) const -{ - if (shouldScrollOnMainThread()) { - TRACE_EVENT0("cc", "CCLayerImpl::tryScroll: Failed shouldScrollOnMainThread"); - return CCInputHandlerClient::ScrollOnMainThread; - } - - if (!screenSpaceTransform().isInvertible()) { - TRACE_EVENT0("cc", "CCLayerImpl::tryScroll: Ignored nonInvertibleTransform"); - return CCInputHandlerClient::ScrollIgnored; - } - - if (!nonFastScrollableRegion().isEmpty()) { - bool clipped = false; - FloatPoint hitTestPointInLocalSpace = CCMathUtil::projectPoint(screenSpaceTransform().inverse(), FloatPoint(viewportPoint), clipped); - if (!clipped && nonFastScrollableRegion().contains(flooredIntPoint(hitTestPointInLocalSpace))) { - TRACE_EVENT0("cc", "CCLayerImpl::tryScroll: Failed nonFastScrollableRegion"); - return CCInputHandlerClient::ScrollOnMainThread; - } - } - - if (type == CCInputHandlerClient::Wheel && haveWheelEventHandlers()) { - TRACE_EVENT0("cc", "CCLayerImpl::tryScroll: Failed wheelEventHandlers"); - return CCInputHandlerClient::ScrollOnMainThread; - } - - if (!scrollable()) { - TRACE_EVENT0("cc", "CCLayerImpl::tryScroll: Ignored not scrollable"); - return CCInputHandlerClient::ScrollIgnored; - } - - return CCInputHandlerClient::ScrollStarted; -} - -bool CCLayerImpl::drawCheckerboardForMissingTiles() const -{ - return m_drawCheckerboardForMissingTiles && !CCSettings::backgroundColorInsteadOfCheckerboard(); -} - -IntRect CCLayerImpl::layerRectToContentRect(const WebKit::WebRect& layerRect) -{ - float widthScale = static_cast(contentBounds().width()) / bounds().width(); - float heightScale = static_cast(contentBounds().height()) / bounds().height(); - FloatRect contentRect(layerRect.x, layerRect.y, layerRect.width, layerRect.height); - contentRect.scale(widthScale, heightScale); - return enclosingIntRect(contentRect); -} - -std::string CCLayerImpl::indentString(int indent) -{ - std::string str; - for (int i = 0; i != indent; ++i) - str.append(" "); - return str; -} - -void CCLayerImpl::dumpLayerProperties(std::string* str, int indent) const -{ - std::string indentStr = indentString(indent); - str->append(indentStr); - base::StringAppendF(str, "layer ID: %d\n", m_layerId); - - str->append(indentStr); - base::StringAppendF(str, "bounds: %d, %d\n", bounds().width(), bounds().height()); - - if (m_renderTarget) { - str->append(indentStr); - base::StringAppendF(str, "renderTarget: %d\n", m_renderTarget->m_layerId); - } - - str->append(indentStr); - base::StringAppendF(str, "drawTransform: %f, %f, %f, %f // %f, %f, %f, %f // %f, %f, %f, %f // %f, %f, %f, %f\n", - m_drawTransform.m11(), m_drawTransform.m12(), m_drawTransform.m13(), m_drawTransform.m14(), - m_drawTransform.m21(), m_drawTransform.m22(), m_drawTransform.m23(), m_drawTransform.m24(), - m_drawTransform.m31(), m_drawTransform.m32(), m_drawTransform.m33(), m_drawTransform.m34(), - m_drawTransform.m41(), m_drawTransform.m42(), m_drawTransform.m43(), m_drawTransform.m44()); - - str->append(indentStr); - base::StringAppendF(str, "drawsContent: %s\n", m_drawsContent ? "yes" : "no"); -} - -void sortLayers(std::vector::iterator first, std::vector::iterator end, CCLayerSorter* layerSorter) -{ - TRACE_EVENT0("cc", "CCLayerImpl::sortLayers"); - layerSorter->sort(first, end); -} - -std::string CCLayerImpl::layerTreeAsText() const -{ - std::string str; - dumpLayer(&str, 0); - return str; -} - -void CCLayerImpl::dumpLayer(std::string* str, int indent) const -{ - str->append(indentString(indent)); - base::StringAppendF(str, "%s(%s)\n", layerTypeAsString(), m_debugName.data()); - dumpLayerProperties(str, indent+2); - if (m_replicaLayer) { - str->append(indentString(indent+2)); - str->append("Replica:\n"); - m_replicaLayer->dumpLayer(str, indent+3); - } - if (m_maskLayer) { - str->append(indentString(indent+2)); - str->append("Mask:\n"); - m_maskLayer->dumpLayer(str, indent+3); - } - for (size_t i = 0; i < m_children.size(); ++i) - m_children[i]->dumpLayer(str, indent+1); -} - -void CCLayerImpl::setStackingOrderChanged(bool stackingOrderChanged) -{ - // We don't need to store this flag; we only need to track that the change occurred. - if (stackingOrderChanged) - noteLayerPropertyChangedForSubtree(); -} - -bool CCLayerImpl::layerSurfacePropertyChanged() const -{ - if (m_layerSurfacePropertyChanged) - return true; - - // If this layer's surface property hasn't changed, we want to see if - // some layer above us has changed this property. This is done for the - // case when such parent layer does not draw content, and therefore will - // not be traversed by the damage tracker. We need to make sure that - // property change on such layer will be caught by its descendants. - CCLayerImpl* current = this->m_parent; - while (current && !current->m_renderSurface) { - if (current->m_layerSurfacePropertyChanged) - return true; - current = current->m_parent; - } - - return false; -} - -void CCLayerImpl::noteLayerPropertyChangedForSubtree() -{ - m_layerPropertyChanged = true; - noteLayerPropertyChangedForDescendants(); -} - -void CCLayerImpl::noteLayerPropertyChangedForDescendants() -{ - for (size_t i = 0; i < m_children.size(); ++i) - m_children[i]->noteLayerPropertyChangedForSubtree(); -} - -const char* CCLayerImpl::layerTypeAsString() const -{ - return "LayerChromium"; -} - -void CCLayerImpl::resetAllChangeTrackingForSubtree() -{ - m_layerPropertyChanged = false; - m_layerSurfacePropertyChanged = false; - - m_updateRect = FloatRect(); - - if (m_renderSurface) - m_renderSurface->resetPropertyChangedFlag(); - - if (m_maskLayer) - m_maskLayer->resetAllChangeTrackingForSubtree(); - - if (m_replicaLayer) - m_replicaLayer->resetAllChangeTrackingForSubtree(); // also resets the replica mask, if it exists. - - for (size_t i = 0; i < m_children.size(); ++i) - m_children[i]->resetAllChangeTrackingForSubtree(); -} - -bool CCLayerImpl::layerIsAlwaysDamaged() const -{ - return false; -} - -int CCLayerImpl::id() const -{ - return m_layerId; -} - -float CCLayerImpl::opacity() const -{ - return m_opacity; -} - -void CCLayerImpl::setOpacityFromAnimation(float opacity) -{ - setOpacity(opacity); -} - -const WebKit::WebTransformationMatrix& CCLayerImpl::transform() const -{ - return m_transform; -} - -void CCLayerImpl::setTransformFromAnimation(const WebTransformationMatrix& transform) -{ - setTransform(transform); -} - -void CCLayerImpl::setBounds(const IntSize& bounds) -{ - if (m_bounds == bounds) - return; - - m_bounds = bounds; - - if (masksToBounds()) - noteLayerPropertyChangedForSubtree(); - else - m_layerPropertyChanged = true; -} - -void CCLayerImpl::setMaskLayer(scoped_ptr maskLayer) -{ - m_maskLayer = maskLayer.Pass(); - - int newLayerId = m_maskLayer ? m_maskLayer->id() : -1; - if (newLayerId == m_maskLayerId) - return; - - m_maskLayerId = newLayerId; - noteLayerPropertyChangedForSubtree(); -} - -void CCLayerImpl::setReplicaLayer(scoped_ptr replicaLayer) -{ - m_replicaLayer = replicaLayer.Pass(); - - int newLayerId = m_replicaLayer ? m_replicaLayer->id() : -1; - if (newLayerId == m_replicaLayerId) - return; - - m_replicaLayerId = newLayerId; - noteLayerPropertyChangedForSubtree(); -} - -void CCLayerImpl::setDrawsContent(bool drawsContent) -{ - if (m_drawsContent == drawsContent) - return; - - m_drawsContent = drawsContent; - m_layerPropertyChanged = true; -} - -void CCLayerImpl::setAnchorPoint(const FloatPoint& anchorPoint) -{ - if (m_anchorPoint == anchorPoint) - return; - - m_anchorPoint = anchorPoint; - noteLayerPropertyChangedForSubtree(); -} - -void CCLayerImpl::setAnchorPointZ(float anchorPointZ) -{ - if (m_anchorPointZ == anchorPointZ) - return; - - m_anchorPointZ = anchorPointZ; - noteLayerPropertyChangedForSubtree(); -} - -void CCLayerImpl::setBackgroundColor(SkColor backgroundColor) -{ - if (m_backgroundColor == backgroundColor) - return; - - m_backgroundColor = backgroundColor; - m_layerPropertyChanged = true; -} - -void CCLayerImpl::setFilters(const WebKit::WebFilterOperations& filters) -{ - if (m_filters == filters) - return; - - m_filters = filters; - noteLayerPropertyChangedForSubtree(); -} - -void CCLayerImpl::setBackgroundFilters(const WebKit::WebFilterOperations& backgroundFilters) -{ - if (m_backgroundFilters == backgroundFilters) - return; - - m_backgroundFilters = backgroundFilters; - m_layerPropertyChanged = true; -} - -void CCLayerImpl::setMasksToBounds(bool masksToBounds) -{ - if (m_masksToBounds == masksToBounds) - return; - - m_masksToBounds = masksToBounds; - noteLayerPropertyChangedForSubtree(); -} - -void CCLayerImpl::setContentsOpaque(bool opaque) -{ - if (m_contentsOpaque == opaque) - return; - - m_contentsOpaque = opaque; - noteLayerPropertyChangedForSubtree(); -} - -void CCLayerImpl::setOpacity(float opacity) -{ - if (m_opacity == opacity) - return; - - m_opacity = opacity; - m_layerSurfacePropertyChanged = true; -} - -bool CCLayerImpl::opacityIsAnimating() const -{ - return m_layerAnimationController->isAnimatingProperty(CCActiveAnimation::Opacity); -} - -void CCLayerImpl::setPosition(const FloatPoint& position) -{ - if (m_position == position) - return; - - m_position = position; - noteLayerPropertyChangedForSubtree(); -} - -void CCLayerImpl::setPreserves3D(bool preserves3D) -{ - if (m_preserves3D == preserves3D) - return; - - m_preserves3D = preserves3D; - noteLayerPropertyChangedForSubtree(); -} - -void CCLayerImpl::setSublayerTransform(const WebTransformationMatrix& sublayerTransform) -{ - if (m_sublayerTransform == sublayerTransform) - return; - - m_sublayerTransform = sublayerTransform; - // sublayer transform does not affect the current layer; it affects only its children. - noteLayerPropertyChangedForDescendants(); -} - -void CCLayerImpl::setTransform(const WebTransformationMatrix& transform) -{ - if (m_transform == transform) - return; - - m_transform = transform; - m_layerSurfacePropertyChanged = true; -} - -bool CCLayerImpl::transformIsAnimating() const -{ - return m_layerAnimationController->isAnimatingProperty(CCActiveAnimation::Transform); -} - -void CCLayerImpl::setDebugBorderColor(SkColor debugBorderColor) -{ - if (m_debugBorderColor == debugBorderColor) - return; - - m_debugBorderColor = debugBorderColor; - m_layerPropertyChanged = true; -} - -void CCLayerImpl::setDebugBorderWidth(float debugBorderWidth) -{ - if (m_debugBorderWidth == debugBorderWidth) - return; - - m_debugBorderWidth = debugBorderWidth; - m_layerPropertyChanged = true; -} - -bool CCLayerImpl::hasDebugBorders() const -{ - return SkColorGetA(m_debugBorderColor) && debugBorderWidth() > 0; -} - -void CCLayerImpl::setContentBounds(const IntSize& contentBounds) -{ - if (m_contentBounds == contentBounds) - return; - - m_contentBounds = contentBounds; - m_layerPropertyChanged = true; -} - -void CCLayerImpl::setScrollPosition(const IntPoint& scrollPosition) -{ - if (m_scrollPosition == scrollPosition) - return; - - m_scrollPosition = scrollPosition; - noteLayerPropertyChangedForSubtree(); -} - -void CCLayerImpl::setScrollDelta(const FloatSize& scrollDelta) -{ - if (m_scrollDelta == scrollDelta) - return; - - m_scrollDelta = scrollDelta; - noteLayerPropertyChangedForSubtree(); -} - -void CCLayerImpl::setImplTransform(const WebKit::WebTransformationMatrix& transform) -{ - if (m_implTransform == transform) - return; - - m_implTransform = transform; - noteLayerPropertyChangedForSubtree(); -} - -void CCLayerImpl::setDoubleSided(bool doubleSided) -{ - if (m_doubleSided == doubleSided) - return; - - m_doubleSided = doubleSided; - noteLayerPropertyChangedForSubtree(); -} - -Region CCLayerImpl::visibleContentOpaqueRegion() const -{ - if (contentsOpaque()) - return visibleContentRect(); - return Region(); -} - -void CCLayerImpl::didLoseContext() -{ -} - -void CCLayerImpl::setMaxScrollPosition(const IntSize& maxScrollPosition) -{ - m_maxScrollPosition = maxScrollPosition; - - if (!m_scrollbarAnimationController) - return; - m_scrollbarAnimationController->updateScrollOffset(this); -} - -CCScrollbarLayerImpl* CCLayerImpl::horizontalScrollbarLayer() const -{ - return m_scrollbarAnimationController ? m_scrollbarAnimationController->horizontalScrollbarLayer() : 0; -} - -void CCLayerImpl::setHorizontalScrollbarLayer(CCScrollbarLayerImpl* scrollbarLayer) -{ - if (!m_scrollbarAnimationController) - m_scrollbarAnimationController = CCScrollbarAnimationController::create(this); - m_scrollbarAnimationController->setHorizontalScrollbarLayer(scrollbarLayer); - m_scrollbarAnimationController->updateScrollOffset(this); -} - -CCScrollbarLayerImpl* CCLayerImpl::verticalScrollbarLayer() const -{ - return m_scrollbarAnimationController ? m_scrollbarAnimationController->verticalScrollbarLayer() : 0; -} - -void CCLayerImpl::setVerticalScrollbarLayer(CCScrollbarLayerImpl* scrollbarLayer) -{ - if (!m_scrollbarAnimationController) - m_scrollbarAnimationController = CCScrollbarAnimationController::create(this); - m_scrollbarAnimationController->setVerticalScrollbarLayer(scrollbarLayer); - m_scrollbarAnimationController->updateScrollOffset(this); -} - -} - - -#endif // USE(ACCELERATED_COMPOSITING) diff --git a/cc/CCLayerImpl.h b/cc/CCLayerImpl.h index e34ccc8..2f36527 100644 --- a/cc/CCLayerImpl.h +++ b/cc/CCLayerImpl.h @@ -1,399 +1,6 @@ -// Copyright 2011 The Chromium Authors. All rights reserved. +// Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CCLayerImpl_h -#define CCLayerImpl_h - -#include "base/memory/scoped_ptr.h" -#include "cc/scoped_ptr_vector.h" -#include "CCInputHandler.h" -#include "CCLayerAnimationController.h" -#include "CCRenderPass.h" -#include "CCRenderSurface.h" -#include "CCResourceProvider.h" -#include "CCSharedQuadState.h" -#include "FloatRect.h" -#include "IntRect.h" -#include "Region.h" -#include "SkColor.h" -#include -#include -#include -#include - -namespace cc { - -class CCLayerSorter; -class CCLayerTreeHostImpl; -class CCQuadSink; -class CCRenderer; -class CCScrollbarAnimationController; -class CCScrollbarLayerImpl; -class LayerChromium; - -struct CCAppendQuadsData; - -class CCLayerImpl : public CCLayerAnimationControllerClient { -public: - static scoped_ptr create(int id) - { - return make_scoped_ptr(new CCLayerImpl(id)); - } - - virtual ~CCLayerImpl(); - - // CCLayerAnimationControllerClient implementation. - virtual int id() const OVERRIDE; - virtual void setOpacityFromAnimation(float) OVERRIDE; - virtual float opacity() const OVERRIDE; - virtual void setTransformFromAnimation(const WebKit::WebTransformationMatrix&) OVERRIDE; - virtual const WebKit::WebTransformationMatrix& transform() const OVERRIDE; - - // Tree structure. - CCLayerImpl* parent() const { return m_parent; } - const ScopedPtrVector& children() const { return m_children; } - void addChild(scoped_ptr); - void removeFromParent(); - void removeAllChildren(); - - void setMaskLayer(scoped_ptr); - CCLayerImpl* maskLayer() const { return m_maskLayer.get(); } - - void setReplicaLayer(scoped_ptr); - CCLayerImpl* replicaLayer() const { return m_replicaLayer.get(); } - - bool hasMask() const { return m_maskLayer; } - bool hasReplica() const { return m_replicaLayer; } - bool replicaHasMask() const { return m_replicaLayer && (m_maskLayer || m_replicaLayer->m_maskLayer); } - - CCLayerTreeHostImpl* layerTreeHostImpl() const { return m_layerTreeHostImpl; } - void setLayerTreeHostImpl(CCLayerTreeHostImpl* hostImpl) { m_layerTreeHostImpl = hostImpl; } - - scoped_ptr createSharedQuadState() const; - // willDraw must be called before appendQuads. If willDraw is called, - // didDraw is guaranteed to be called before another willDraw or before - // the layer is destroyed. To enforce this, any class that overrides - // willDraw/didDraw must call the base class version. - virtual void willDraw(CCResourceProvider*); - virtual void appendQuads(CCQuadSink&, CCAppendQuadsData&) { } - virtual void didDraw(CCResourceProvider*); - - virtual CCResourceProvider::ResourceId contentsResourceId() const; - - virtual bool hasContributingDelegatedRenderPasses() const; - virtual CCRenderPass::Id firstContributingRenderPassId() const; - virtual CCRenderPass::Id nextContributingRenderPassId(CCRenderPass::Id) const; - - // Returns true if this layer has content to draw. - void setDrawsContent(bool); - bool drawsContent() const { return m_drawsContent; } - - bool forceRenderSurface() const { return m_forceRenderSurface; } - void setForceRenderSurface(bool force) { m_forceRenderSurface = force; } - - // Returns true if any of the layer's descendants has content to draw. - virtual bool descendantDrawsContent(); - - void setAnchorPoint(const FloatPoint&); - const FloatPoint& anchorPoint() const { return m_anchorPoint; } - - void setAnchorPointZ(float); - float anchorPointZ() const { return m_anchorPointZ; } - - void setBackgroundColor(SkColor); - SkColor backgroundColor() const { return m_backgroundColor; } - - void setFilters(const WebKit::WebFilterOperations&); - const WebKit::WebFilterOperations& filters() const { return m_filters; } - - void setBackgroundFilters(const WebKit::WebFilterOperations&); - const WebKit::WebFilterOperations& backgroundFilters() const { return m_backgroundFilters; } - - void setMasksToBounds(bool); - bool masksToBounds() const { return m_masksToBounds; } - - void setContentsOpaque(bool); - bool contentsOpaque() const { return m_contentsOpaque; } - - void setOpacity(float); - bool opacityIsAnimating() const; - - void setPosition(const FloatPoint&); - const FloatPoint& position() const { return m_position; } - - void setIsContainerForFixedPositionLayers(bool isContainerForFixedPositionLayers) { m_isContainerForFixedPositionLayers = isContainerForFixedPositionLayers; } - bool isContainerForFixedPositionLayers() const { return m_isContainerForFixedPositionLayers; } - - void setFixedToContainerLayer(bool fixedToContainerLayer = true) { m_fixedToContainerLayer = fixedToContainerLayer;} - bool fixedToContainerLayer() const { return m_fixedToContainerLayer; } - - void setPreserves3D(bool); - bool preserves3D() const { return m_preserves3D; } - - void setUseParentBackfaceVisibility(bool useParentBackfaceVisibility) { m_useParentBackfaceVisibility = useParentBackfaceVisibility; } - bool useParentBackfaceVisibility() const { return m_useParentBackfaceVisibility; } - - void setUseLCDText(bool useLCDText) { m_useLCDText = useLCDText; } - bool useLCDText() const { return m_useLCDText; } - - void setSublayerTransform(const WebKit::WebTransformationMatrix&); - const WebKit::WebTransformationMatrix& sublayerTransform() const { return m_sublayerTransform; } - - // Debug layer border - visual effect only, do not change geometry/clipping/etc. - void setDebugBorderColor(SkColor); - SkColor debugBorderColor() const { return m_debugBorderColor; } - void setDebugBorderWidth(float); - float debugBorderWidth() const { return m_debugBorderWidth; } - bool hasDebugBorders() const; - - // Debug layer name. - void setDebugName(const std::string& debugName) { m_debugName = debugName; } - std::string debugName() const { return m_debugName; } - - CCRenderSurface* renderSurface() const { return m_renderSurface.get(); } - void createRenderSurface(); - void clearRenderSurface() { m_renderSurface.clear(); } - - float drawOpacity() const { return m_drawOpacity; } - void setDrawOpacity(float opacity) { m_drawOpacity = opacity; } - - bool drawOpacityIsAnimating() const { return m_drawOpacityIsAnimating; } - void setDrawOpacityIsAnimating(bool drawOpacityIsAnimating) { m_drawOpacityIsAnimating = drawOpacityIsAnimating; } - - CCLayerImpl* renderTarget() const { ASSERT(!m_renderTarget || m_renderTarget->renderSurface()); return m_renderTarget; } - void setRenderTarget(CCLayerImpl* target) { m_renderTarget = target; } - - void setBounds(const IntSize&); - const IntSize& bounds() const { return m_bounds; } - - const IntSize& contentBounds() const { return m_contentBounds; } - void setContentBounds(const IntSize&); - - const IntPoint& scrollPosition() const { return m_scrollPosition; } - void setScrollPosition(const IntPoint&); - - const IntSize& maxScrollPosition() const {return m_maxScrollPosition; } - void setMaxScrollPosition(const IntSize&); - - const FloatSize& scrollDelta() const { return m_scrollDelta; } - void setScrollDelta(const FloatSize&); - - const WebKit::WebTransformationMatrix& implTransform() const { return m_implTransform; } - void setImplTransform(const WebKit::WebTransformationMatrix& transform); - - const IntSize& sentScrollDelta() const { return m_sentScrollDelta; } - void setSentScrollDelta(const IntSize& sentScrollDelta) { m_sentScrollDelta = sentScrollDelta; } - - // Returns the delta of the scroll that was outside of the bounds of the initial scroll - FloatSize scrollBy(const FloatSize& scroll); - - bool scrollable() const { return m_scrollable; } - void setScrollable(bool scrollable) { m_scrollable = scrollable; } - - bool shouldScrollOnMainThread() const { return m_shouldScrollOnMainThread; } - void setShouldScrollOnMainThread(bool shouldScrollOnMainThread) { m_shouldScrollOnMainThread = shouldScrollOnMainThread; } - - bool haveWheelEventHandlers() const { return m_haveWheelEventHandlers; } - void setHaveWheelEventHandlers(bool haveWheelEventHandlers) { m_haveWheelEventHandlers = haveWheelEventHandlers; } - - const Region& nonFastScrollableRegion() const { return m_nonFastScrollableRegion; } - void setNonFastScrollableRegion(const Region& region) { m_nonFastScrollableRegion = region; } - - void setDrawCheckerboardForMissingTiles(bool checkerboard) { m_drawCheckerboardForMissingTiles = checkerboard; } - bool drawCheckerboardForMissingTiles() const; - - CCInputHandlerClient::ScrollStatus tryScroll(const IntPoint& viewportPoint, CCInputHandlerClient::ScrollInputType) const; - - const IntRect& visibleContentRect() const { return m_visibleContentRect; } - void setVisibleContentRect(const IntRect& visibleContentRect) { m_visibleContentRect = visibleContentRect; } - - bool doubleSided() const { return m_doubleSided; } - void setDoubleSided(bool); - - void setTransform(const WebKit::WebTransformationMatrix&); - bool transformIsAnimating() const; - - const WebKit::WebTransformationMatrix& drawTransform() const { return m_drawTransform; } - void setDrawTransform(const WebKit::WebTransformationMatrix& matrix) { m_drawTransform = matrix; } - const WebKit::WebTransformationMatrix& screenSpaceTransform() const { return m_screenSpaceTransform; } - void setScreenSpaceTransform(const WebKit::WebTransformationMatrix& matrix) { m_screenSpaceTransform = matrix; } - - bool drawTransformIsAnimating() const { return m_drawTransformIsAnimating; } - void setDrawTransformIsAnimating(bool animating) { m_drawTransformIsAnimating = animating; } - bool screenSpaceTransformIsAnimating() const { return m_screenSpaceTransformIsAnimating; } - void setScreenSpaceTransformIsAnimating(bool animating) { m_screenSpaceTransformIsAnimating = animating; } - - const IntRect& drawableContentRect() const { return m_drawableContentRect; } - void setDrawableContentRect(const IntRect& rect) { m_drawableContentRect = rect; } - const FloatRect& updateRect() const { return m_updateRect; } - void setUpdateRect(const FloatRect& updateRect) { m_updateRect = updateRect; } - - std::string layerTreeAsText() const; - - void setStackingOrderChanged(bool); - - bool layerPropertyChanged() const { return m_layerPropertyChanged || layerIsAlwaysDamaged(); } - bool layerSurfacePropertyChanged() const; - - void resetAllChangeTrackingForSubtree(); - - virtual bool layerIsAlwaysDamaged() const; - - CCLayerAnimationController* layerAnimationController() { return m_layerAnimationController.get(); } - - virtual Region visibleContentOpaqueRegion() const; - - // Indicates that the context previously used to render this layer - // was lost and that a new one has been created. Won't be called - // until the new context has been created successfully. - virtual void didLoseContext(); - - CCScrollbarAnimationController* scrollbarAnimationController() const { return m_scrollbarAnimationController.get(); } - - CCScrollbarLayerImpl* horizontalScrollbarLayer() const; - void setHorizontalScrollbarLayer(CCScrollbarLayerImpl*); - - CCScrollbarLayerImpl* verticalScrollbarLayer() const; - void setVerticalScrollbarLayer(CCScrollbarLayerImpl*); - -protected: - explicit CCLayerImpl(int); - - void appendDebugBorderQuad(CCQuadSink&, const CCSharedQuadState*, CCAppendQuadsData&) const; - - IntRect layerRectToContentRect(const WebKit::WebRect& layerRect); - - virtual void dumpLayerProperties(std::string*, int indent) const; - static std::string indentString(int indent); - -private: - void setParent(CCLayerImpl* parent) { m_parent = parent; } - friend class TreeSynchronizer; - void clearChildList(); // Warning: This does not preserve tree structure invariants and so is only exposed to the tree synchronizer. - - void noteLayerPropertyChangedForSubtree(); - - // Note carefully this does not affect the current layer. - void noteLayerPropertyChangedForDescendants(); - - virtual const char* layerTypeAsString() const; - - void dumpLayer(std::string*, int indent) const; - - // Properties internal to CCLayerImpl - CCLayerImpl* m_parent; - ScopedPtrVector m_children; - // m_maskLayer can be temporarily stolen during tree sync, we need this ID to confirm newly assigned layer is still the previous one - int m_maskLayerId; - scoped_ptr m_maskLayer; - int m_replicaLayerId; // ditto - scoped_ptr m_replicaLayer; - int m_layerId; - CCLayerTreeHostImpl* m_layerTreeHostImpl; - - // Properties synchronized from the associated LayerChromium. - FloatPoint m_anchorPoint; - float m_anchorPointZ; - IntSize m_bounds; - IntSize m_contentBounds; - IntPoint m_scrollPosition; - bool m_scrollable; - bool m_shouldScrollOnMainThread; - bool m_haveWheelEventHandlers; - Region m_nonFastScrollableRegion; - SkColor m_backgroundColor; - - // Whether the "back" of this layer should draw. - bool m_doubleSided; - - // Tracks if drawing-related properties have changed since last redraw. - bool m_layerPropertyChanged; - - // Indicates that a property has changed on this layer that would not - // affect the pixels on its target surface, but would require redrawing - // but would require redrawing the targetSurface onto its ancestor targetSurface. - // For layers that do not own a surface this flag acts as m_layerPropertyChanged. - bool m_layerSurfacePropertyChanged; - - // Uses layer's content space. - IntRect m_visibleContentRect; - bool m_masksToBounds; - bool m_contentsOpaque; - float m_opacity; - FloatPoint m_position; - bool m_preserves3D; - bool m_useParentBackfaceVisibility; - bool m_drawCheckerboardForMissingTiles; - WebKit::WebTransformationMatrix m_sublayerTransform; - WebKit::WebTransformationMatrix m_transform; - bool m_useLCDText; - - bool m_drawsContent; - bool m_forceRenderSurface; - - // Set for the layer that other layers are fixed to. - bool m_isContainerForFixedPositionLayers; - // This is true if the layer should be fixed to the closest ancestor container. - bool m_fixedToContainerLayer; - - FloatSize m_scrollDelta; - IntSize m_sentScrollDelta; - IntSize m_maxScrollPosition; - WebKit::WebTransformationMatrix m_implTransform; - - // The layer whose coordinate space this layer draws into. This can be - // either the same layer (m_renderTarget == this) or an ancestor of this - // layer. - CCLayerImpl* m_renderTarget; - - // The global depth value of the center of the layer. This value is used - // to sort layers from back to front. - float m_drawDepth; - float m_drawOpacity; - bool m_drawOpacityIsAnimating; - - // Debug borders. - SkColor m_debugBorderColor; - float m_debugBorderWidth; - - // Debug layer name. - std::string m_debugName; - - WebKit::WebFilterOperations m_filters; - WebKit::WebFilterOperations m_backgroundFilters; - - WebKit::WebTransformationMatrix m_drawTransform; - WebKit::WebTransformationMatrix m_screenSpaceTransform; - bool m_drawTransformIsAnimating; - bool m_screenSpaceTransformIsAnimating; - -#ifndef NDEBUG - bool m_betweenWillDrawAndDidDraw; -#endif - - // Render surface associated with this layer. The layer and its descendants - // will render to this surface. - OwnPtr m_renderSurface; - - // Hierarchical bounding rect containing the layer and its descendants. - // Uses target surface's space. - IntRect m_drawableContentRect; - - // Rect indicating what was repainted/updated during update. - // Note that plugin layers bypass this and leave it empty. - // Uses layer's content space. - FloatRect m_updateRect; - - // Manages animations for this layer. - scoped_ptr m_layerAnimationController; - - // Manages scrollbars for this layer - OwnPtr m_scrollbarAnimationController; -}; - -void sortLayers(std::vector::iterator first, std::vector::iterator end, CCLayerSorter*); - -} - -#endif // CCLayerImpl_h +// Temporary forwarding header +#include "cc/layer_impl.h" diff --git a/cc/CCLayerIterator.cpp b/cc/CCLayerIterator.cpp deleted file mode 100644 index 71fde80..0000000 --- a/cc/CCLayerIterator.cpp +++ /dev/null @@ -1,153 +0,0 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "config.h" - -#if USE(ACCELERATED_COMPOSITING) - -#include "CCLayerIterator.h" - -#include "CCLayerImpl.h" -#include "CCRenderSurface.h" -#include "LayerChromium.h" -#include "RenderSurfaceChromium.h" - -namespace cc { - -template -void CCLayerIteratorActions::BackToFront::begin(CCLayerIterator& it) -{ - it.m_targetRenderSurfaceLayerIndex = 0; - it.m_currentLayerIndex = CCLayerIteratorValue::LayerIndexRepresentingTargetRenderSurface; - - m_highestTargetRenderSurfaceLayer = 0; -} - -template -void CCLayerIteratorActions::BackToFront::end(CCLayerIterator& it) -{ - it.m_targetRenderSurfaceLayerIndex = CCLayerIteratorValue::InvalidTargetRenderSurfaceLayerIndex; - it.m_currentLayerIndex = 0; -} - -template -void CCLayerIteratorActions::BackToFront::next(CCLayerIterator& it) -{ - // If the current layer has a RS, move to its layer list. Otherwise, visit the next layer in the current RS layer list. - if (it.currentLayerRepresentsContributingRenderSurface()) { - // Save our position in the childLayer list for the RenderSurface, then jump to the next RenderSurface. Save where we - // came from in the next RenderSurface so we can get back to it. - it.targetRenderSurface()->m_currentLayerIndexHistory = it.m_currentLayerIndex; - int previousTargetRenderSurfaceLayer = it.m_targetRenderSurfaceLayerIndex; - - it.m_targetRenderSurfaceLayerIndex = ++m_highestTargetRenderSurfaceLayer; - it.m_currentLayerIndex = CCLayerIteratorValue::LayerIndexRepresentingTargetRenderSurface; - - it.targetRenderSurface()->m_targetRenderSurfaceLayerIndexHistory = previousTargetRenderSurfaceLayer; - } else { - ++it.m_currentLayerIndex; - - int targetRenderSurfaceNumChildren = it.targetRenderSurfaceChildren().size(); - while (it.m_currentLayerIndex == targetRenderSurfaceNumChildren) { - // Jump back to the previous RenderSurface, and get back the position where we were in that list, and move to the next position there. - if (!it.m_targetRenderSurfaceLayerIndex) { - // End of the list - it.m_targetRenderSurfaceLayerIndex = CCLayerIteratorValue::InvalidTargetRenderSurfaceLayerIndex; - it.m_currentLayerIndex = 0; - return; - } - it.m_targetRenderSurfaceLayerIndex = it.targetRenderSurface()->m_targetRenderSurfaceLayerIndexHistory; - it.m_currentLayerIndex = it.targetRenderSurface()->m_currentLayerIndexHistory + 1; - - targetRenderSurfaceNumChildren = it.targetRenderSurfaceChildren().size(); - } - } -} - -template -void CCLayerIteratorActions::FrontToBack::begin(CCLayerIterator& it) -{ - it.m_targetRenderSurfaceLayerIndex = 0; - it.m_currentLayerIndex = it.targetRenderSurfaceChildren().size() - 1; - goToHighestInSubtree(it); -} - -template -void CCLayerIteratorActions::FrontToBack::end(CCLayerIterator& it) -{ - it.m_targetRenderSurfaceLayerIndex = CCLayerIteratorValue::InvalidTargetRenderSurfaceLayerIndex; - it.m_currentLayerIndex = 0; -} - -template -void CCLayerIteratorActions::FrontToBack::next(CCLayerIterator& it) -{ - // Moves to the previous layer in the current RS layer list. Then we check if the - // new current layer has its own RS, in which case there are things in that RS layer list that are higher, so - // we find the highest layer in that subtree. - // If we move back past the front of the list, we jump up to the previous RS layer list, picking up again where we - // had previously recursed into the current RS layer list. - - if (!it.currentLayerRepresentsTargetRenderSurface()) { - // Subtracting one here will eventually cause the current layer to become that layer - // representing the target render surface. - --it.m_currentLayerIndex; - goToHighestInSubtree(it); - } else { - while (it.currentLayerRepresentsTargetRenderSurface()) { - if (!it.m_targetRenderSurfaceLayerIndex) { - // End of the list - it.m_targetRenderSurfaceLayerIndex = CCLayerIteratorValue::InvalidTargetRenderSurfaceLayerIndex; - it.m_currentLayerIndex = 0; - return; - } - it.m_targetRenderSurfaceLayerIndex = it.targetRenderSurface()->m_targetRenderSurfaceLayerIndexHistory; - it.m_currentLayerIndex = it.targetRenderSurface()->m_currentLayerIndexHistory; - } - } -} - -template -void CCLayerIteratorActions::FrontToBack::goToHighestInSubtree(CCLayerIterator& it) -{ - if (it.currentLayerRepresentsTargetRenderSurface()) - return; - while (it.currentLayerRepresentsContributingRenderSurface()) { - // Save where we were in the current target surface, move to the next one, and save the target surface that we - // came from there so we can go back to it. - it.targetRenderSurface()->m_currentLayerIndexHistory = it.m_currentLayerIndex; - int previousTargetRenderSurfaceLayer = it.m_targetRenderSurfaceLayerIndex; - - for (LayerType* layer = it.currentLayer(); it.targetRenderSurfaceLayer() != layer; ++it.m_targetRenderSurfaceLayerIndex) { } - it.m_currentLayerIndex = it.targetRenderSurfaceChildren().size() - 1; - - it.targetRenderSurface()->m_targetRenderSurfaceLayerIndexHistory = previousTargetRenderSurfaceLayer; - } -} - -typedef std::vector > LayerChromiumList; -typedef std::vector CCLayerImplList; - -// Declare each of the above functions for LayerChromium and CCLayerImpl classes so that they are linked. -template void CCLayerIteratorActions::BackToFront::begin(CCLayerIterator &); -template void CCLayerIteratorActions::BackToFront::end(CCLayerIterator&); -template void CCLayerIteratorActions::BackToFront::next(CCLayerIterator&); - -template void CCLayerIteratorActions::BackToFront::begin(CCLayerIterator&); -template void CCLayerIteratorActions::BackToFront::end(CCLayerIterator&); -template void CCLayerIteratorActions::BackToFront::next(CCLayerIterator&); - -template void CCLayerIteratorActions::FrontToBack::next(CCLayerIterator&); -template void CCLayerIteratorActions::FrontToBack::end(CCLayerIterator&); -template void CCLayerIteratorActions::FrontToBack::begin(CCLayerIterator&); -template void CCLayerIteratorActions::FrontToBack::goToHighestInSubtree(CCLayerIterator&); - -template void CCLayerIteratorActions::FrontToBack::next(CCLayerIterator&); -template void CCLayerIteratorActions::FrontToBack::end(CCLayerIterator&); -template void CCLayerIteratorActions::FrontToBack::begin(CCLayerIterator&); -template void CCLayerIteratorActions::FrontToBack::goToHighestInSubtree(CCLayerIterator&); - -} // namespace cc - -#endif // USE(ACCELERATED_COMPOSITING) diff --git a/cc/CCLayerIterator.h b/cc/CCLayerIterator.h index 4d36080..1b0f9d4 100644 --- a/cc/CCLayerIterator.h +++ b/cc/CCLayerIterator.h @@ -2,207 +2,5 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CCLayerIterator_h -#define CCLayerIterator_h - -#include "CCLayerTreeHostCommon.h" - -#include "base/memory/ref_counted.h" - -namespace cc { - -// These classes provide means to iterate over the RenderSurface-Layer tree. - -// Example code follows, for a tree of LayerChromium/RenderSurfaceChromium objects. See below for details. -// -// void doStuffOnLayers(const std::vector >& renderSurfaceLayerList) -// { -// typedef CCLayerIterator CCLayerIteratorType; -// -// CCLayerIteratorType end = CCLayerIteratorType::end(&renderSurfaceLayerList); -// for (CCLayerIteratorType it = CCLayerIteratorType::begin(&renderSurfaceLayerList); it != end; ++it) { -// // Only one of these will be true -// if (it.representsTargetRenderSurface()) -// foo(*it); // *it is a layer representing a target RenderSurface -// if (it.representsContributingRenderSurface()) -// bar(*it); // *it is a layer representing a RenderSurface that contributes to the layer's target RenderSurface -// if (it.representsItself()) -// baz(*it); // *it is a layer representing itself, as it contributes to its own target RenderSurface -// } -// } - -// A RenderSurface R may be referred to in one of two different contexts. One RenderSurface is "current" at any time, for -// whatever operation is being performed. This current surface is referred to as a target surface. For example, when R is -// being painted it would be the target surface. Once R has been painted, its contents may be included into another -// surface S. While S is considered the target surface when it is being painted, R is called a contributing surface -// in this context as it contributes to the content of the target surface S. -// -// The iterator's current position in the tree always points to some layer. The state of the iterator indicates the role of the -// layer, and will be one of the following three states. A single layer L will appear in the iteration process in at least one, -// and possibly all, of these states. -// 1. Representing the target surface: The iterator in this state, pointing at layer L, indicates that the target RenderSurface -// is now the surface owned by L. This will occur exactly once for each RenderSurface in the tree. -// 2. Representing a contributing surface: The iterator in this state, pointing at layer L, refers to the RenderSurface owned -// by L as a contributing surface, without changing the current target RenderSurface. -// 3. Representing itself: The iterator in this state, pointing at layer L, refers to the layer itself, as a child of the -// current target RenderSurface. -// -// The BackToFront iterator will return a layer representing the target surface before returning layers representing themselves -// as children of the current target surface. Whereas the FrontToBack ordering will iterate over children layers of a surface -// before the layer representing the surface as a target surface. -// -// To use the iterators: -// -// Create a stepping iterator and end iterator by calling CCLayerIterator::begin() and CCLayerIterator::end() and passing in the -// list of layers owning target RenderSurfaces. Step through the tree by incrementing the stepping iterator while it is != to -// the end iterator. At each step the iterator knows what the layer is representing, and you can query the iterator to decide -// what actions to perform with the layer given what it represents. - -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -// Non-templated constants -struct CCLayerIteratorValue { - static const int InvalidTargetRenderSurfaceLayerIndex = -1; - // This must be -1 since the iterator action code assumes that this value can be - // reached by subtracting one from the position of the first layer in the current - // target surface's child layer list, which is 0. - static const int LayerIndexRepresentingTargetRenderSurface = -1; -}; - -// The position of a layer iterator that is independent of its many template types. -template -struct CCLayerIteratorPosition { - bool representsTargetRenderSurface; - bool representsContributingRenderSurface; - bool representsItself; - LayerType* targetRenderSurfaceLayer; - LayerType* currentLayer; -}; - -// An iterator class for walking over layers in the RenderSurface-Layer tree. -template -class CCLayerIterator { - typedef CCLayerIterator CCLayerIteratorType; - -public: - CCLayerIterator() : m_renderSurfaceLayerList(0) { } - - static CCLayerIteratorType begin(const LayerList* renderSurfaceLayerList) { return CCLayerIteratorType(renderSurfaceLayerList, true); } - static CCLayerIteratorType end(const LayerList* renderSurfaceLayerList) { return CCLayerIteratorType(renderSurfaceLayerList, false); } - - CCLayerIteratorType& operator++() { m_actions.next(*this); return *this; } - bool operator==(const CCLayerIterator& other) const - { - return m_targetRenderSurfaceLayerIndex == other.m_targetRenderSurfaceLayerIndex - && m_currentLayerIndex == other.m_currentLayerIndex; - } - bool operator!=(const CCLayerIteratorType& other) const { return !(*this == other); } - - LayerType* operator->() const { return currentLayer(); } - LayerType* operator*() const { return currentLayer(); } - - bool representsTargetRenderSurface() const { return currentLayerRepresentsTargetRenderSurface(); } - bool representsContributingRenderSurface() const { return !representsTargetRenderSurface() && currentLayerRepresentsContributingRenderSurface(); } - bool representsItself() const { return !representsTargetRenderSurface() && !representsContributingRenderSurface(); } - - LayerType* targetRenderSurfaceLayer() const { return getRawPtr((*m_renderSurfaceLayerList)[m_targetRenderSurfaceLayerIndex]); } - - operator const CCLayerIteratorPosition() const - { - CCLayerIteratorPosition position; - position.representsTargetRenderSurface = representsTargetRenderSurface(); - position.representsContributingRenderSurface = representsContributingRenderSurface(); - position.representsItself = representsItself(); - position.targetRenderSurfaceLayer = targetRenderSurfaceLayer(); - position.currentLayer = currentLayer(); - return position; - } - -private: - CCLayerIterator(const LayerList* renderSurfaceLayerList, bool start) - : m_renderSurfaceLayerList(renderSurfaceLayerList) - , m_targetRenderSurfaceLayerIndex(0) - { - for (size_t i = 0; i < renderSurfaceLayerList->size(); ++i) { - if (!(*renderSurfaceLayerList)[i]->renderSurface()) { - ASSERT_NOT_REACHED(); - m_actions.end(*this); - return; - } - } - - if (start && !renderSurfaceLayerList->empty()) - m_actions.begin(*this); - else - m_actions.end(*this); - } - - inline static LayerChromium* getRawPtr(const scoped_refptr& ptr) { return ptr.get(); } - inline static CCLayerImpl* getRawPtr(CCLayerImpl* ptr) { return ptr; } - - inline LayerType* currentLayer() const { return currentLayerRepresentsTargetRenderSurface() ? targetRenderSurfaceLayer() : getRawPtr(targetRenderSurfaceChildren()[m_currentLayerIndex]); } - - inline bool currentLayerRepresentsContributingRenderSurface() const { return CCLayerTreeHostCommon::renderSurfaceContributesToTarget(currentLayer(), targetRenderSurfaceLayer()->id()); } - inline bool currentLayerRepresentsTargetRenderSurface() const { return m_currentLayerIndex == CCLayerIteratorValue::LayerIndexRepresentingTargetRenderSurface; } - - inline RenderSurfaceType* targetRenderSurface() const { return targetRenderSurfaceLayer()->renderSurface(); } - inline const LayerList& targetRenderSurfaceChildren() const { return targetRenderSurface()->layerList(); } - - IteratorActionType m_actions; - const LayerList* m_renderSurfaceLayerList; - - // The iterator's current position. - - // A position in the renderSurfaceLayerList. This points to a layer which owns the current target surface. - // This is a value from 0 to n-1 (n = size of renderSurfaceLayerList = number of surfaces). A value outside of - // this range (for example, CCLayerIteratorValue::InvalidTargetRenderSurfaceLayerIndex) is used to - // indicate a position outside the bounds of the tree. - int m_targetRenderSurfaceLayerIndex; - // A position in the list of layers that are children of the current target surface. When pointing to one of - // these layers, this is a value from 0 to n-1 (n = number of children). Since the iterator must also stop at - // the layers representing the target surface, this is done by setting the currentLayerIndex to a value of - // CCLayerIteratorValue::LayerRepresentingTargetRenderSurface. - int m_currentLayerIndex; - - friend struct CCLayerIteratorActions; -}; - -// Orderings for iterating over the RenderSurface-Layer tree. -struct CCLayerIteratorActions { - // Walks layers sorted by z-order from back to front. - class BackToFront { - public: - template - void begin(CCLayerIterator&); - - template - void end(CCLayerIterator&); - - template - void next(CCLayerIterator&); - - private: - int m_highestTargetRenderSurfaceLayer; - }; - - // Walks layers sorted by z-order from front to back - class FrontToBack { - public: - template - void begin(CCLayerIterator&); - - template - void end(CCLayerIterator&); - - template - void next(CCLayerIterator&); - - private: - template - void goToHighestInSubtree(CCLayerIterator&); - }; -}; - -} // namespace cc - -#endif +// Temporary forwarding header +#include "cc/layer_iterator.h" diff --git a/cc/CCLayerQuad.cpp b/cc/CCLayerQuad.cpp deleted file mode 100644 index 9642622..0000000 --- a/cc/CCLayerQuad.cpp +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - - -#include "config.h" - -#if USE(ACCELERATED_COMPOSITING) - -#include "CCLayerQuad.h" - -namespace cc { - -CCLayerQuad::Edge::Edge(const FloatPoint& p, const FloatPoint& q) -{ - ASSERT(p != q); - - FloatPoint tangent(p.y() - q.y(), q.x() - p.x()); - float cross2 = p.x() * q.y() - q.x() * p.y(); - - set(tangent.x(), tangent.y(), cross2); - scale(1.0f / tangent.length()); -} - -CCLayerQuad::CCLayerQuad(const FloatQuad& quad) -{ - // Create edges. - m_left = Edge(quad.p4(), quad.p1()); - m_right = Edge(quad.p2(), quad.p3()); - m_top = Edge(quad.p1(), quad.p2()); - m_bottom = Edge(quad.p3(), quad.p4()); - - float sign = quad.isCounterclockwise() ? -1 : 1; - m_left.scale(sign); - m_right.scale(sign); - m_top.scale(sign); - m_bottom.scale(sign); -} - -CCLayerQuad::CCLayerQuad(const Edge& left, const Edge& top, const Edge& right, const Edge& bottom) - : m_left(left) - , m_top(top) - , m_right(right) - , m_bottom(bottom) -{ -} - -FloatQuad CCLayerQuad::floatQuad() const -{ - return FloatQuad(m_left.intersect(m_top), - m_top.intersect(m_right), - m_right.intersect(m_bottom), - m_bottom.intersect(m_left)); -} - -void CCLayerQuad::toFloatArray(float flattened[12]) const -{ - flattened[0] = m_left.x(); - flattened[1] = m_left.y(); - flattened[2] = m_left.z(); - flattened[3] = m_top.x(); - flattened[4] = m_top.y(); - flattened[5] = m_top.z(); - flattened[6] = m_right.x(); - flattened[7] = m_right.y(); - flattened[8] = m_right.z(); - flattened[9] = m_bottom.x(); - flattened[10] = m_bottom.y(); - flattened[11] = m_bottom.z(); -} - -} // namespace cc - -#endif // USE(ACCELERATED_COMPOSITING) diff --git a/cc/CCLayerQuad.h b/cc/CCLayerQuad.h index 8be296f..813ee03 100644 --- a/cc/CCLayerQuad.h +++ b/cc/CCLayerQuad.h @@ -1,106 +1,6 @@ -// Copyright 2011 The Chromium Authors. All rights reserved. +// Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. - -#ifndef CCLayerQuad_h -#define CCLayerQuad_h - -#if USE(ACCELERATED_COMPOSITING) - -#include "FloatPoint3D.h" -#include "FloatQuad.h" - -static const float kAntiAliasingInflateDistance = 0.5f; - -namespace cc { - -class CCLayerQuad { -public: - class Edge { - public: - Edge() - : m_x(0) - , m_y(0) - , m_z(0) - { - } - Edge(const FloatPoint&, const FloatPoint&); - - float x() const { return m_x; } - float y() const { return m_y; } - float z() const { return m_z; } - - void setX(float x) { m_x = x; } - void setY(float y) { m_y = y; } - void setZ(float z) { m_z = z; } - void set(float x, float y, float z) - { - m_x = x; - m_y = y; - m_z = z; - } - - void moveX(float dx) { m_x += dx; } - void moveY(float dy) { m_y += dy; } - void moveZ(float dz) { m_z += dz; } - void move(float dx, float dy, float dz) - { - m_x += dx; - m_y += dy; - m_z += dz; - } - - void scaleX(float sx) { m_x *= sx; } - void scaleY(float sy) { m_y *= sy; } - void scaleZ(float sz) { m_z *= sz; } - void scale(float sx, float sy, float sz) - { - m_x *= sx; - m_y *= sy; - m_z *= sz; - } - void scale(float s) { scale(s, s, s); } - - FloatPoint intersect(const Edge& e) const - { - return FloatPoint( - (y() * e.z() - e.y() * z()) / (x() * e.y() - e.x() * y()), - (x() * e.z() - e.x() * z()) / (e.x() * y() - x() * e.y())); - } - - private: - float m_x; - float m_y; - float m_z; - }; - - CCLayerQuad(const Edge& left, const Edge& top, const Edge& right, const Edge& bottom); - CCLayerQuad(const FloatQuad&); - - Edge left() const { return m_left; } - Edge top() const { return m_top; } - Edge right() const { return m_right; } - Edge bottom() const { return m_bottom; } - - void inflateX(float dx) { m_left.moveZ(dx); m_right.moveZ(dx); } - void inflateY(float dy) { m_top.moveZ(dy); m_bottom.moveZ(dy); } - void inflate(float d) { inflateX(d); inflateY(d); } - void inflateAntiAliasingDistance() { inflate(kAntiAliasingInflateDistance); } - - FloatQuad floatQuad() const; - - void toFloatArray(float[12]) const; - -private: - Edge m_left; - Edge m_top; - Edge m_right; - Edge m_bottom; -}; - -} - -#endif // USE(ACCELERATED_COMPOSITING) - -#endif +// Temporary forwarding header +#include "cc/layer_quad.h" diff --git a/cc/CCLayerSorter.cpp b/cc/CCLayerSorter.cpp deleted file mode 100644 index cf85777..0000000 --- a/cc/CCLayerSorter.cpp +++ /dev/null @@ -1,445 +0,0 @@ -// Copyright 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "config.h" - -#include "CCLayerSorter.h" - -#include "CCMathUtil.h" -#include "CCRenderSurface.h" -#include -#include -#include - -using namespace std; -using WebKit::WebTransformationMatrix; - -#define LOG_CHANNEL_PREFIX Log -#define SHOW_DEBUG_LOG 0 - -#if !defined( NDEBUG ) -#if SHOW_DEBUG_LOG -static WTFLogChannel LogCCLayerSorter = { 0x00000000, "", WTFLogChannelOn }; -#else -static WTFLogChannel LogCCLayerSorter = { 0x00000000, "", WTFLogChannelOff }; -#endif -#endif - -namespace cc { - -inline static float perpProduct(const FloatSize& u, const FloatSize& v) -{ - return u.width() * v.height() - u.height() * v.width(); -} - -// Tests if two edges defined by their endpoints (a,b) and (c,d) intersect. Returns true and the -// point of intersection if they do and false otherwise. -static bool edgeEdgeTest(const FloatPoint& a, const FloatPoint& b, const FloatPoint& c, const FloatPoint& d, FloatPoint& r) -{ - FloatSize u = b - a; - FloatSize v = d - c; - FloatSize w = a - c; - - float denom = perpProduct(u, v); - - // If denom == 0 then the edges are parallel. While they could be overlapping - // we don't bother to check here as the we'll find their intersections from the - // corner to quad tests. - if (!denom) - return false; - - float s = perpProduct(v, w) / denom; - if (s < 0 || s > 1) - return false; - - float t = perpProduct(u, w) / denom; - if (t < 0 || t > 1) - return false; - - u.scale(s); - r = a + u; - return true; -} - -CCLayerSorter::GraphNode::GraphNode(CCLayerImpl* cclayer) - : layer(cclayer) - , incomingEdgeWeight(0) -{ -} - -CCLayerSorter::GraphNode::~GraphNode() -{ -} - -CCLayerSorter::CCLayerSorter() - : m_zRange(0) -{ -} - -CCLayerSorter::~CCLayerSorter() -{ -} - -// Checks whether layer "a" draws on top of layer "b". The weight value returned is an indication of -// the maximum z-depth difference between the layers or zero if the layers are found to be intesecting -// (some features are in front and some are behind). -CCLayerSorter::ABCompareResult CCLayerSorter::checkOverlap(LayerShape* a, LayerShape* b, float zThreshold, float& weight) -{ - weight = 0; - - // Early out if the projected bounds don't overlap. - if (!a->projectedBounds.intersects(b->projectedBounds)) - return None; - - FloatPoint aPoints[4] = {a->projectedQuad.p1(), a->projectedQuad.p2(), a->projectedQuad.p3(), a->projectedQuad.p4() }; - FloatPoint bPoints[4] = {b->projectedQuad.p1(), b->projectedQuad.p2(), b->projectedQuad.p3(), b->projectedQuad.p4() }; - - // Make a list of points that inside both layer quad projections. - Vector overlapPoints; - - // Check all four corners of one layer against the other layer's quad. - for (int i = 0; i < 4; ++i) { - if (a->projectedQuad.containsPoint(bPoints[i])) - overlapPoints.append(bPoints[i]); - if (b->projectedQuad.containsPoint(aPoints[i])) - overlapPoints.append(aPoints[i]); - } - - // Check all the edges of one layer for intersection with the other layer's edges. - FloatPoint r; - for (int ea = 0; ea < 4; ++ea) - for (int eb = 0; eb < 4; ++eb) - if (edgeEdgeTest(aPoints[ea], aPoints[(ea + 1) % 4], - bPoints[eb], bPoints[(eb + 1) % 4], - r)) - overlapPoints.append(r); - - if (!overlapPoints.size()) - return None; - - // Check the corresponding layer depth value for all overlap points to determine - // which layer is in front. - float maxPositive = 0; - float maxNegative = 0; - for (unsigned o = 0; o < overlapPoints.size(); o++) { - float za = a->layerZFromProjectedPoint(overlapPoints[o]); - float zb = b->layerZFromProjectedPoint(overlapPoints[o]); - - float diff = za - zb; - if (diff > maxPositive) - maxPositive = diff; - if (diff < maxNegative) - maxNegative = diff; - } - - float maxDiff = (fabsf(maxPositive) > fabsf(maxNegative) ? maxPositive : maxNegative); - - // If the results are inconsistent (and the z difference substantial to rule out - // numerical errors) then the layers are intersecting. We will still return an - // order based on the maximum depth difference but with an edge weight of zero - // these layers will get priority if a graph cycle is present and needs to be broken. - if (maxPositive > zThreshold && maxNegative < -zThreshold) - weight = 0; - else - weight = fabsf(maxDiff); - - // Maintain relative order if the layers have the same depth at all intersection points. - if (maxDiff <= 0) - return ABeforeB; - - return BBeforeA; -} - -CCLayerSorter::LayerShape::LayerShape() -{ -} - -CCLayerSorter::LayerShape::LayerShape(float width, float height, const WebTransformationMatrix& drawTransform) -{ - FloatQuad layerQuad(FloatRect(0, 0, width, height)); - - // Compute the projection of the layer quad onto the z = 0 plane. - - FloatPoint clippedQuad[8]; - int numVerticesInClippedQuad; - CCMathUtil::mapClippedQuad(drawTransform, layerQuad, clippedQuad, numVerticesInClippedQuad); - - if (numVerticesInClippedQuad < 3) { - projectedBounds = FloatRect(); - return; - } - - projectedBounds = CCMathUtil::computeEnclosingRectOfVertices(clippedQuad, numVerticesInClippedQuad); - - // NOTE: it will require very significant refactoring and overhead to deal with - // generalized polygons or multiple quads per layer here. For the sake of layer - // sorting it is equally correct to take a subsection of the polygon that can be made - // into a quad. This will only be incorrect in the case of intersecting layers, which - // are not supported yet anyway. - projectedQuad.setP1(clippedQuad[0]); - projectedQuad.setP2(clippedQuad[1]); - projectedQuad.setP3(clippedQuad[2]); - if (numVerticesInClippedQuad >= 4) - projectedQuad.setP4(clippedQuad[3]); - else - projectedQuad.setP4(clippedQuad[2]); // this will be a degenerate quad that is actually a triangle. - - // Compute the normal of the layer's plane. - bool clipped = false; - FloatPoint3D c1 = CCMathUtil::mapPoint(drawTransform, FloatPoint3D(0, 0, 0), clipped); - FloatPoint3D c2 = CCMathUtil::mapPoint(drawTransform, FloatPoint3D(0, 1, 0), clipped); - FloatPoint3D c3 = CCMathUtil::mapPoint(drawTransform, FloatPoint3D(1, 0, 0), clipped); - // FIXME: Deal with clipping. - FloatPoint3D c12 = c2 - c1; - FloatPoint3D c13 = c3 - c1; - layerNormal = c13.cross(c12); - - transformOrigin = c1; -} - -// Returns the Z coordinate of a point on the layer that projects -// to point p which lies on the z = 0 plane. It does it by computing the -// intersection of a line starting from p along the Z axis and the plane -// of the layer. -float CCLayerSorter::LayerShape::layerZFromProjectedPoint(const FloatPoint& p) const -{ - const FloatPoint3D zAxis(0, 0, 1); - FloatPoint3D w = FloatPoint3D(p) - transformOrigin; - - float d = layerNormal.dot(zAxis); - float n = -layerNormal.dot(w); - - // Check if layer is parallel to the z = 0 axis which will make it - // invisible and hence returning zero is fine. - if (!d) - return 0; - - // The intersection point would be given by: - // p + (n / d) * u but since we are only interested in the - // z coordinate and p's z coord is zero, all we need is the value of n/d. - return n / d; -} - -void CCLayerSorter::createGraphNodes(LayerList::iterator first, LayerList::iterator last) -{ -#if !defined( NDEBUG ) - LOG(CCLayerSorter, "Creating graph nodes:\n"); -#endif - float minZ = FLT_MAX; - float maxZ = -FLT_MAX; - for (LayerList::const_iterator it = first; it < last; it++) { - m_nodes.append(GraphNode(*it)); - GraphNode& node = m_nodes.at(m_nodes.size() - 1); - CCRenderSurface* renderSurface = node.layer->renderSurface(); - if (!node.layer->drawsContent() && !renderSurface) - continue; - -#if !defined( NDEBUG ) - LOG(CCLayerSorter, "Layer %d (%d x %d)\n", node.layer->id(), node.layer->bounds().width(), node.layer->bounds().height()); -#endif - - WebTransformationMatrix drawTransform; - float layerWidth, layerHeight; - if (renderSurface) { - drawTransform = renderSurface->drawTransform(); - layerWidth = renderSurface->contentRect().width(); - layerHeight = renderSurface->contentRect().height(); - } else { - drawTransform = node.layer->drawTransform(); - layerWidth = node.layer->contentBounds().width(); - layerHeight = node.layer->contentBounds().height(); - } - - node.shape = LayerShape(layerWidth, layerHeight, drawTransform); - - maxZ = max(maxZ, node.shape.transformOrigin.z()); - minZ = min(minZ, node.shape.transformOrigin.z()); - } - - m_zRange = fabsf(maxZ - minZ); -} - -void CCLayerSorter::createGraphEdges() -{ -#if !defined( NDEBUG ) - LOG(CCLayerSorter, "Edges:\n"); -#endif - // Fraction of the total zRange below which z differences - // are not considered reliable. - const float zThresholdFactor = 0.01f; - float zThreshold = m_zRange * zThresholdFactor; - - for (unsigned na = 0; na < m_nodes.size(); na++) { - GraphNode& nodeA = m_nodes[na]; - if (!nodeA.layer->drawsContent() && !nodeA.layer->renderSurface()) - continue; - for (unsigned nb = na + 1; nb < m_nodes.size(); nb++) { - GraphNode& nodeB = m_nodes[nb]; - if (!nodeB.layer->drawsContent() && !nodeB.layer->renderSurface()) - continue; - float weight = 0; - ABCompareResult overlapResult = checkOverlap(&nodeA.shape, &nodeB.shape, zThreshold, weight); - GraphNode* startNode = 0; - GraphNode* endNode = 0; - if (overlapResult == ABeforeB) { - startNode = &nodeA; - endNode = &nodeB; - } else if (overlapResult == BBeforeA) { - startNode = &nodeB; - endNode = &nodeA; - } - - if (startNode) { -#if !defined( NDEBUG ) - LOG(CCLayerSorter, "%d -> %d\n", startNode->layer->id(), endNode->layer->id()); -#endif - m_edges.append(GraphEdge(startNode, endNode, weight)); - } - } - } - - for (unsigned i = 0; i < m_edges.size(); i++) { - GraphEdge& edge = m_edges[i]; - m_activeEdges.add(&edge, &edge); - edge.from->outgoing.append(&edge); - edge.to->incoming.append(&edge); - edge.to->incomingEdgeWeight += edge.weight; - } -} - -// Finds and removes an edge from the list by doing a swap with the -// last element of the list. -void CCLayerSorter::removeEdgeFromList(GraphEdge* edge, Vector& list) -{ - size_t edgeIndex = list.find(edge); - ASSERT(edgeIndex != notFound); - if (list.size() == 1) { - ASSERT(!edgeIndex); - list.clear(); - return; - } - if (edgeIndex != list.size() - 1) - list[edgeIndex] = list[list.size() - 1]; - - list.removeLast(); -} - -// Sorts the given list of layers such that they can be painted in a back-to-front -// order. Sorting produces correct results for non-intersecting layers that don't have -// cyclical order dependencies. Cycles and intersections are broken (somewhat) aribtrarily. -// Sorting of layers is done via a topological sort of a directed graph whose nodes are -// the layers themselves. An edge from node A to node B signifies that layer A needs to -// be drawn before layer B. If A and B have no dependency between each other, then we -// preserve the ordering of those layers as they were in the original list. -// -// The draw order between two layers is determined by projecting the two triangles making -// up each layer quad to the Z = 0 plane, finding points of intersection between the triangles -// and backprojecting those points to the plane of the layer to determine the corresponding Z -// coordinate. The layer with the lower Z coordinate (farther from the eye) needs to be rendered -// first. -// -// If the layer projections don't intersect, then no edges (dependencies) are created -// between them in the graph. HOWEVER, in this case we still need to preserve the ordering -// of the original list of layers, since that list should already have proper z-index -// ordering of layers. -// -void CCLayerSorter::sort(LayerList::iterator first, LayerList::iterator last) -{ -#if !defined( NDEBUG ) - LOG(CCLayerSorter, "Sorting start ----\n"); -#endif - createGraphNodes(first, last); - - createGraphEdges(); - - Vector sortedList; - Deque noIncomingEdgeNodeList; - - // Find all the nodes that don't have incoming edges. - for (NodeList::iterator la = m_nodes.begin(); la < m_nodes.end(); la++) { - if (!la->incoming.size()) - noIncomingEdgeNodeList.append(la); - } - -#if !defined( NDEBUG ) - LOG(CCLayerSorter, "Sorted list: "); -#endif - while (m_activeEdges.size() || noIncomingEdgeNodeList.size()) { - while (noIncomingEdgeNodeList.size()) { - - // It is necessary to preserve the existing ordering of layers, when there are - // no explicit dependencies (because this existing ordering has correct - // z-index/layout ordering). To preserve this ordering, we process Nodes in - // the same order that they were added to the list. - GraphNode* fromNode = noIncomingEdgeNodeList.takeFirst(); - - // Add it to the final list. - sortedList.append(fromNode); - -#if !defined( NDEBUG ) - LOG(CCLayerSorter, "%d, ", fromNode->layer->id()); -#endif - - // Remove all its outgoing edges from the graph. - for (unsigned i = 0; i < fromNode->outgoing.size(); i++) { - GraphEdge* outgoingEdge = fromNode->outgoing[i]; - - m_activeEdges.remove(outgoingEdge); - removeEdgeFromList(outgoingEdge, outgoingEdge->to->incoming); - outgoingEdge->to->incomingEdgeWeight -= outgoingEdge->weight; - - if (!outgoingEdge->to->incoming.size()) - noIncomingEdgeNodeList.append(outgoingEdge->to); - } - fromNode->outgoing.clear(); - } - - if (!m_activeEdges.size()) - break; - - // If there are still active edges but the list of nodes without incoming edges - // is empty then we have run into a cycle. Break the cycle by finding the node - // with the smallest overall incoming edge weight and use it. This will favor - // nodes that have zero-weight incoming edges i.e. layers that are being - // occluded by a layer that intersects them. - float minIncomingEdgeWeight = FLT_MAX; - GraphNode* nextNode = 0; - for (unsigned i = 0; i < m_nodes.size(); i++) { - if (m_nodes[i].incoming.size() && m_nodes[i].incomingEdgeWeight < minIncomingEdgeWeight) { - minIncomingEdgeWeight = m_nodes[i].incomingEdgeWeight; - nextNode = &m_nodes[i]; - } - } - ASSERT(nextNode); - // Remove all its incoming edges. - for (unsigned e = 0; e < nextNode->incoming.size(); e++) { - GraphEdge* incomingEdge = nextNode->incoming[e]; - - m_activeEdges.remove(incomingEdge); - removeEdgeFromList(incomingEdge, incomingEdge->from->outgoing); - } - nextNode->incoming.clear(); - nextNode->incomingEdgeWeight = 0; - noIncomingEdgeNodeList.append(nextNode); -#if !defined( NDEBUG ) - LOG(CCLayerSorter, "Breaking cycle by cleaning up incoming edges from %d (weight = %f)\n", nextNode->layer->id(), minIncomingEdgeWeight); -#endif - } - - // Note: The original elements of the list are in no danger of having their ref count go to zero - // here as they are all nodes of the layer hierarchy and are kept alive by their parent nodes. - int count = 0; - for (LayerList::iterator it = first; it < last; it++) - *it = sortedList[count++]->layer; - -#if !defined( NDEBUG ) - LOG(CCLayerSorter, "Sorting end ----\n"); -#endif - - m_nodes.clear(); - m_edges.clear(); - m_activeEdges.clear(); -} - -} diff --git a/cc/CCLayerSorter.h b/cc/CCLayerSorter.h index d4ca664..a2fd49c 100644 --- a/cc/CCLayerSorter.h +++ b/cc/CCLayerSorter.h @@ -1,92 +1,6 @@ -// Copyright 2011 The Chromium Authors. All rights reserved. +// Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CCLayerSorter_h -#define CCLayerSorter_h - -#include "base/basictypes.h" -#include "CCLayerImpl.h" -#include "FloatPoint3D.h" -#include "FloatQuad.h" -#include "FloatRect.h" -#include -#include -#include - -namespace WebKit { -class WebTransformationMatrix; -} - -namespace cc { - -class CCLayerSorter { -public: - CCLayerSorter(); - ~CCLayerSorter(); - - typedef std::vector LayerList; - - void sort(LayerList::iterator first, LayerList::iterator last); - - // Holds various useful properties derived from a layer's 3D outline. - struct LayerShape { - LayerShape(); - LayerShape(float width, float height, const WebKit::WebTransformationMatrix& drawTransform); - - float layerZFromProjectedPoint(const FloatPoint&) const; - - FloatPoint3D layerNormal; - FloatPoint3D transformOrigin; - FloatQuad projectedQuad; - FloatRect projectedBounds; - }; - - enum ABCompareResult { - ABeforeB, - BBeforeA, - None - }; - - static ABCompareResult checkOverlap(LayerShape*, LayerShape*, float zThreshold, float& weight); - -private: - struct GraphEdge; - - struct GraphNode { - explicit GraphNode(CCLayerImpl* cclayer); - ~GraphNode(); - - CCLayerImpl* layer; - LayerShape shape; - Vector incoming; - Vector outgoing; - float incomingEdgeWeight; - }; - - struct GraphEdge { - GraphEdge(GraphNode* fromNode, GraphNode* toNode, float weight) : from(fromNode), to(toNode), weight(weight) { }; - - GraphNode* from; - GraphNode* to; - float weight; - }; - - typedef Vector NodeList; - typedef Vector EdgeList; - NodeList m_nodes; - EdgeList m_edges; - float m_zRange; - - typedef HashMap EdgeMap; - EdgeMap m_activeEdges; - - void createGraphNodes(LayerList::iterator first, LayerList::iterator last); - void createGraphEdges(); - void removeEdgeFromList(GraphEdge*, Vector&); - - DISALLOW_COPY_AND_ASSIGN(CCLayerSorter); -}; - -} -#endif +// Temporary forwarding header +#include "cc/layer_sorter.h" diff --git a/cc/CCLayerTilingData.cpp b/cc/CCLayerTilingData.cpp deleted file mode 100644 index 12c7aef..0000000 --- a/cc/CCLayerTilingData.cpp +++ /dev/null @@ -1,158 +0,0 @@ -// Copyright 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - - -#include "config.h" - -#if USE(ACCELERATED_COMPOSITING) - -#include "CCLayerTilingData.h" - -using namespace std; - -namespace cc { - -PassOwnPtr CCLayerTilingData::create(const IntSize& tileSize, BorderTexelOption border) -{ - return adoptPtr(new CCLayerTilingData(tileSize, border)); -} - -CCLayerTilingData::CCLayerTilingData(const IntSize& tileSize, BorderTexelOption border) - : m_tilingData(tileSize, IntSize(), border == HasBorderTexels) -{ - setTileSize(tileSize); -} - -CCLayerTilingData::~CCLayerTilingData() -{ -} - -void CCLayerTilingData::setTileSize(const IntSize& size) -{ - if (tileSize() == size) - return; - - reset(); - - m_tilingData.setMaxTextureSize(size); -} - -IntSize CCLayerTilingData::tileSize() const -{ - return m_tilingData.maxTextureSize(); -} - -void CCLayerTilingData::setBorderTexelOption(BorderTexelOption borderTexelOption) -{ - bool borderTexels = borderTexelOption == HasBorderTexels; - if (hasBorderTexels() == borderTexels) - return; - - reset(); - m_tilingData.setHasBorderTexels(borderTexels); -} - -const CCLayerTilingData& CCLayerTilingData::operator=(const CCLayerTilingData& tiler) -{ - m_tilingData = tiler.m_tilingData; - - return *this; -} - -void CCLayerTilingData::addTile(PassOwnPtr tile, int i, int j) -{ - ASSERT(!tileAt(i, j)); - tile->moveTo(i, j); - m_tiles.add(make_pair(i, j), tile); -} - -PassOwnPtr CCLayerTilingData::takeTile(int i, int j) -{ - return m_tiles.take(make_pair(i, j)); -} - -CCLayerTilingData::Tile* CCLayerTilingData::tileAt(int i, int j) const -{ - return m_tiles.get(make_pair(i, j)); -} - -void CCLayerTilingData::reset() -{ - m_tiles.clear(); -} - -void CCLayerTilingData::contentRectToTileIndices(const IntRect& contentRect, int& left, int& top, int& right, int& bottom) const -{ - // An empty rect doesn't result in an empty set of tiles, so don't pass an empty rect. - // FIXME: Possibly we should fill a vector of tiles instead, - // since the normal use of this function is to enumerate some tiles. - ASSERT(!contentRect.isEmpty()); - - left = m_tilingData.tileXIndexFromSrcCoord(contentRect.x()); - top = m_tilingData.tileYIndexFromSrcCoord(contentRect.y()); - right = m_tilingData.tileXIndexFromSrcCoord(contentRect.maxX() - 1); - bottom = m_tilingData.tileYIndexFromSrcCoord(contentRect.maxY() - 1); -} - -IntRect CCLayerTilingData::tileRect(const Tile* tile) const -{ - IntRect tileRect = m_tilingData.tileBoundsWithBorder(tile->i(), tile->j()); - tileRect.setSize(tileSize()); - return tileRect; -} - -Region CCLayerTilingData::opaqueRegionInContentRect(const IntRect& contentRect) const -{ - if (contentRect.isEmpty()) - return Region(); - - Region opaqueRegion; - int left, top, right, bottom; - contentRectToTileIndices(contentRect, left, top, right, bottom); - for (int j = top; j <= bottom; ++j) { - for (int i = left; i <= right; ++i) { - Tile* tile = tileAt(i, j); - if (!tile) - continue; - - IntRect tileOpaqueRect = intersection(contentRect, tile->opaqueRect()); - opaqueRegion.unite(tileOpaqueRect); - } - } - return opaqueRegion; -} - -void CCLayerTilingData::setBounds(const IntSize& size) -{ - m_tilingData.setTotalSize(size); - if (size.isEmpty()) { - m_tiles.clear(); - return; - } - - // Any tiles completely outside our new bounds are invalid and should be dropped. - int left, top, right, bottom; - contentRectToTileIndices(IntRect(IntPoint(), size), left, top, right, bottom); - Vector invalidTileKeys; - for (TileMap::const_iterator it = m_tiles.begin(); it != m_tiles.end(); ++it) { -#if WTF_NEW_HASHMAP_ITERATORS_INTERFACE - if (it->key.first > right || it->key.second > bottom) - invalidTileKeys.append(it->key); -#else - if (it->first.first > right || it->first.second > bottom) - invalidTileKeys.append(it->first); -#endif - } - for (size_t i = 0; i < invalidTileKeys.size(); ++i) - m_tiles.remove(invalidTileKeys[i]); -} - -IntSize CCLayerTilingData::bounds() const -{ - return m_tilingData.totalSize(); -} - -} // namespace cc - -#endif // USE(ACCELERATED_COMPOSITING) diff --git a/cc/CCLayerTilingData.h b/cc/CCLayerTilingData.h index c73f057..2883037 100644 --- a/cc/CCLayerTilingData.h +++ b/cc/CCLayerTilingData.h @@ -1,101 +1,6 @@ -// Copyright 2011 The Chromium Authors. All rights reserved. +// Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. - -#ifndef CCLayerTilingData_h -#define CCLayerTilingData_h - -#if USE(ACCELERATED_COMPOSITING) - -#include "base/basictypes.h" -#include "IntRect.h" -#include "Region.h" -#include "TilingData.h" -#include -#include -#include - -namespace cc { - -class CCLayerTilingData { -public: - enum BorderTexelOption { HasBorderTexels, NoBorderTexels }; - - ~CCLayerTilingData(); - - static PassOwnPtr create(const IntSize& tileSize, BorderTexelOption); - - bool hasEmptyBounds() const { return m_tilingData.hasEmptyBounds(); } - int numTilesX() const { return m_tilingData.numTilesX(); } - int numTilesY() const { return m_tilingData.numTilesY(); } - IntRect tileBounds(int i, int j) const { return m_tilingData.tileBounds(i, j); } - IntPoint textureOffset(int xIndex, int yIndex) const { return m_tilingData.textureOffset(xIndex, yIndex); } - - // Change the tile size. This may invalidate all the existing tiles. - void setTileSize(const IntSize&); - IntSize tileSize() const; - // Change the border texel setting. This may invalidate all existing tiles. - void setBorderTexelOption(BorderTexelOption); - bool hasBorderTexels() const { return m_tilingData.borderTexels(); } - - bool isEmpty() const { return hasEmptyBounds() || !tiles().size(); } - - const CCLayerTilingData& operator=(const CCLayerTilingData&); - - class Tile { - public: - Tile() : m_i(-1), m_j(-1) { } - virtual ~Tile() { } - - int i() const { return m_i; } - int j() const { return m_j; } - void moveTo(int i, int j) { m_i = i; m_j = j; } - - const IntRect& opaqueRect() const { return m_opaqueRect; } - void setOpaqueRect(const IntRect& opaqueRect) { m_opaqueRect = opaqueRect; } - private: - int m_i; - int m_j; - IntRect m_opaqueRect; - DISALLOW_COPY_AND_ASSIGN(Tile); - }; - // Default hash key traits for integers disallow 0 and -1 as a key, so - // use a custom hash trait which disallows -1 and -2 instead. - typedef std::pair TileMapKey; - struct TileMapKeyTraits : HashTraits { - static const bool emptyValueIsZero = false; - static const bool needsDestruction = false; - static TileMapKey emptyValue() { return std::make_pair(-1, -1); } - static void constructDeletedValue(TileMapKey& slot) { slot = std::make_pair(-2, -2); } - static bool isDeletedValue(TileMapKey value) { return value.first == -2 && value.second == -2; } - }; - typedef HashMap, DefaultHash::Hash, TileMapKeyTraits> TileMap; - - void addTile(PassOwnPtr, int, int); - PassOwnPtr takeTile(int, int); - Tile* tileAt(int, int) const; - const TileMap& tiles() const { return m_tiles; } - - void setBounds(const IntSize&); - IntSize bounds() const; - - void contentRectToTileIndices(const IntRect&, int &left, int &top, int &right, int &bottom) const; - IntRect tileRect(const Tile*) const; - - Region opaqueRegionInContentRect(const IntRect&) const; - - void reset(); - -protected: - CCLayerTilingData(const IntSize& tileSize, BorderTexelOption); - - TileMap m_tiles; - TilingData m_tilingData; -}; - -} - -#endif // USE(ACCELERATED_COMPOSITING) - -#endif +// Temporary forwarding header +#include "cc/layer_tiling_data.h" diff --git a/cc/CCLayerTreeHost.cpp b/cc/CCLayerTreeHost.cpp deleted file mode 100644 index d75a3d3..0000000 --- a/cc/CCLayerTreeHost.cpp +++ /dev/null @@ -1,861 +0,0 @@ -// Copyright 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "config.h" - -#include "CCLayerTreeHost.h" - -#include "CCFontAtlas.h" -#include "CCGraphicsContext.h" -#include "CCHeadsUpDisplayLayerImpl.h" -#include "CCLayerAnimationController.h" -#include "CCLayerIterator.h" -#include "CCLayerTreeHostClient.h" -#include "CCLayerTreeHostCommon.h" -#include "CCLayerTreeHostImpl.h" -#include "CCOcclusionTracker.h" -#include "CCOverdrawMetrics.h" -#include "CCSettings.h" -#include "CCSingleThreadProxy.h" -#include "CCThreadProxy.h" -#include "HeadsUpDisplayLayerChromium.h" -#include "LayerChromium.h" -#include "Region.h" -#include "TraceEvent.h" -#include "TreeSynchronizer.h" - -using namespace std; -using WebKit::WebTransformationMatrix; - -namespace { -static int numLayerTreeInstances; -} - -namespace cc { - -bool CCLayerTreeHost::s_needsFilterContext = false; - -CCLayerTreeSettings::CCLayerTreeSettings() - : acceleratePainting(false) - , showFPSCounter(false) - , showPlatformLayerTree(false) - , showPaintRects(false) - , showPropertyChangedRects(false) - , showSurfaceDamageRects(false) - , showScreenSpaceRects(false) - , showReplicaScreenSpaceRects(false) - , showOccludingRects(false) - , renderVSyncEnabled(true) - , refreshRate(0) - , maxPartialTextureUpdates(std::numeric_limits::max()) - , defaultTileSize(IntSize(256, 256)) - , maxUntiledLayerSize(IntSize(512, 512)) - , minimumOcclusionTrackingSize(IntSize(160, 160)) -{ -} - -CCLayerTreeSettings::~CCLayerTreeSettings() -{ -} - -RendererCapabilities::RendererCapabilities() - : bestTextureFormat(0) - , contextHasCachedFrontBuffer(false) - , usingPartialSwap(false) - , usingAcceleratedPainting(false) - , usingSetVisibility(false) - , usingSwapCompleteCallback(false) - , usingGpuMemoryManager(false) - , usingDiscardFramebuffer(false) - , usingEglImage(false) - , maxTextureSize(0) -{ -} - -RendererCapabilities::~RendererCapabilities() -{ -} - -bool CCLayerTreeHost::anyLayerTreeHostInstanceExists() -{ - return numLayerTreeInstances > 0; -} - -scoped_ptr CCLayerTreeHost::create(CCLayerTreeHostClient* client, const CCLayerTreeSettings& settings) -{ - scoped_ptr layerTreeHost(new CCLayerTreeHost(client, settings)); - if (!layerTreeHost->initialize()) - return scoped_ptr(); - return layerTreeHost.Pass(); -} - -CCLayerTreeHost::CCLayerTreeHost(CCLayerTreeHostClient* client, const CCLayerTreeSettings& settings) - : m_animating(false) - , m_needsAnimateLayers(false) - , m_client(client) - , m_commitNumber(0) - , m_renderingStats() - , m_rendererInitialized(false) - , m_contextLost(false) - , m_numTimesRecreateShouldFail(0) - , m_numFailedRecreateAttempts(0) - , m_settings(settings) - , m_deviceScaleFactor(1) - , m_visible(true) - , m_pageScaleFactor(1) - , m_minPageScaleFactor(1) - , m_maxPageScaleFactor(1) - , m_triggerIdleUpdates(true) - , m_backgroundColor(SK_ColorWHITE) - , m_hasTransparentBackground(false) - , m_partialTextureUpdateRequests(0) -{ - ASSERT(CCProxy::isMainThread()); - numLayerTreeInstances++; -} - -bool CCLayerTreeHost::initialize() -{ - TRACE_EVENT0("cc", "CCLayerTreeHost::initialize"); - - if (CCProxy::hasImplThread()) - m_proxy = CCThreadProxy::create(this); - else - m_proxy = CCSingleThreadProxy::create(this); - m_proxy->start(); - - return m_proxy->initializeContext(); -} - -CCLayerTreeHost::~CCLayerTreeHost() -{ - if (m_rootLayer) - m_rootLayer->setLayerTreeHost(0); - ASSERT(CCProxy::isMainThread()); - TRACE_EVENT0("cc", "CCLayerTreeHost::~CCLayerTreeHost"); - ASSERT(m_proxy.get()); - m_proxy->stop(); - m_proxy.reset(); - numLayerTreeInstances--; - RateLimiterMap::iterator it = m_rateLimiters.begin(); - if (it != m_rateLimiters.end()) - it->second->stop(); -} - -void CCLayerTreeHost::setSurfaceReady() -{ - m_proxy->setSurfaceReady(); -} - -void CCLayerTreeHost::initializeRenderer() -{ - TRACE_EVENT0("cc", "CCLayerTreeHost::initializeRenderer"); - if (!m_proxy->initializeRenderer()) { - // Uh oh, better tell the client that we can't do anything with this context. - m_client->didRecreateOutputSurface(false); - return; - } - - // Update m_settings based on capabilities that we got back from the renderer. - m_settings.acceleratePainting = m_proxy->rendererCapabilities().usingAcceleratedPainting; - - // Update m_settings based on partial update capability. - m_settings.maxPartialTextureUpdates = min(m_settings.maxPartialTextureUpdates, m_proxy->maxPartialTextureUpdates()); - - m_contentsTextureManager = CCPrioritizedTextureManager::create(0, m_proxy->rendererCapabilities().maxTextureSize, CCRenderer::ContentPool); - m_surfaceMemoryPlaceholder = m_contentsTextureManager->createTexture(IntSize(), GraphicsContext3D::RGBA); - - m_rendererInitialized = true; - - m_settings.defaultTileSize = IntSize(min(m_settings.defaultTileSize.width(), m_proxy->rendererCapabilities().maxTextureSize), - min(m_settings.defaultTileSize.height(), m_proxy->rendererCapabilities().maxTextureSize)); - m_settings.maxUntiledLayerSize = IntSize(min(m_settings.maxUntiledLayerSize.width(), m_proxy->rendererCapabilities().maxTextureSize), - min(m_settings.maxUntiledLayerSize.height(), m_proxy->rendererCapabilities().maxTextureSize)); -} - -CCLayerTreeHost::RecreateResult CCLayerTreeHost::recreateContext() -{ - TRACE_EVENT0("cc", "CCLayerTreeHost::recreateContext"); - ASSERT(m_contextLost); - - bool recreated = false; - if (!m_numTimesRecreateShouldFail) - recreated = m_proxy->recreateContext(); - else - m_numTimesRecreateShouldFail--; - - if (recreated) { - m_client->didRecreateOutputSurface(true); - m_contextLost = false; - return RecreateSucceeded; - } - - // Tolerate a certain number of recreation failures to work around races - // in the context-lost machinery. - m_numFailedRecreateAttempts++; - if (m_numFailedRecreateAttempts < 5) { - // FIXME: The single thread does not self-schedule context - // recreation. So force another recreation attempt to happen by requesting - // another commit. - if (!CCProxy::hasImplThread()) - setNeedsCommit(); - return RecreateFailedButTryAgain; - } - - // We have tried too many times to recreate the context. Tell the host to fall - // back to software rendering. - m_client->didRecreateOutputSurface(false); - return RecreateFailedAndGaveUp; -} - -void CCLayerTreeHost::deleteContentsTexturesOnImplThread(CCResourceProvider* resourceProvider) -{ - ASSERT(CCProxy::isImplThread()); - if (m_rendererInitialized) - m_contentsTextureManager->clearAllMemory(resourceProvider); -} - -void CCLayerTreeHost::acquireLayerTextures() -{ - ASSERT(CCProxy::isMainThread()); - m_proxy->acquireLayerTextures(); -} - -void CCLayerTreeHost::updateAnimations(double monotonicFrameBeginTime) -{ - m_animating = true; - m_client->animate(monotonicFrameBeginTime); - animateLayers(monotonicFrameBeginTime); - m_animating = false; - - m_renderingStats.numAnimationFrames++; -} - -void CCLayerTreeHost::layout() -{ - m_client->layout(); -} - -void CCLayerTreeHost::beginCommitOnImplThread(CCLayerTreeHostImpl* hostImpl) -{ - ASSERT(CCProxy::isImplThread()); - TRACE_EVENT0("cc", "CCLayerTreeHost::commitTo"); - - m_contentsTextureManager->reduceMemory(hostImpl->resourceProvider()); -} - -// This function commits the CCLayerTreeHost to an impl tree. When modifying -// this function, keep in mind that the function *runs* on the impl thread! Any -// code that is logically a main thread operation, e.g. deletion of a LayerChromium, -// should be delayed until the CCLayerTreeHost::commitComplete, which will run -// after the commit, but on the main thread. -void CCLayerTreeHost::finishCommitOnImplThread(CCLayerTreeHostImpl* hostImpl) -{ - ASSERT(CCProxy::isImplThread()); - - hostImpl->setRootLayer(TreeSynchronizer::synchronizeTrees(rootLayer(), hostImpl->detachLayerTree(), hostImpl)); - - if (m_rootLayer && m_hudLayer) - hostImpl->setHudLayer(static_cast(CCLayerTreeHostCommon::findLayerInSubtree(hostImpl->rootLayer(), m_hudLayer->id()))); - else - hostImpl->setHudLayer(0); - - // We may have added an animation during the tree sync. This will cause both layer tree hosts - // to visit their controllers. - if (rootLayer() && m_needsAnimateLayers) - hostImpl->setNeedsAnimateLayers(); - - hostImpl->setSourceFrameNumber(commitNumber()); - hostImpl->setViewportSize(layoutViewportSize(), deviceViewportSize()); - hostImpl->setDeviceScaleFactor(deviceScaleFactor()); - hostImpl->setPageScaleFactorAndLimits(m_pageScaleFactor, m_minPageScaleFactor, m_maxPageScaleFactor); - hostImpl->setBackgroundColor(m_backgroundColor); - hostImpl->setHasTransparentBackground(m_hasTransparentBackground); - - m_commitNumber++; -} - -void CCLayerTreeHost::setFontAtlas(scoped_ptr fontAtlas) -{ - m_fontAtlas = fontAtlas.Pass(); - setNeedsCommit(); -} - -void CCLayerTreeHost::willCommit() -{ - m_client->willCommit(); - if (m_rootLayer && m_settings.showDebugInfo()) { - if (!m_hudLayer) - m_hudLayer = HeadsUpDisplayLayerChromium::create(); - - if (m_fontAtlas.get()) - m_hudLayer->setFontAtlas(m_fontAtlas.Pass()); - - if (!m_hudLayer->parent()) - m_rootLayer->addChild(m_hudLayer); - } -} - -void CCLayerTreeHost::commitComplete() -{ - m_deleteTextureAfterCommitList.clear(); - m_client->didCommit(); -} - -scoped_ptr CCLayerTreeHost::createContext() -{ - return m_client->createOutputSurface(); -} - -scoped_ptr CCLayerTreeHost::createInputHandler() -{ - return m_client->createInputHandler(); -} - -scoped_ptr CCLayerTreeHost::createLayerTreeHostImpl(CCLayerTreeHostImplClient* client) -{ - return CCLayerTreeHostImpl::create(m_settings, client); -} - -void CCLayerTreeHost::didLoseContext() -{ - TRACE_EVENT0("cc", "CCLayerTreeHost::didLoseContext"); - ASSERT(CCProxy::isMainThread()); - m_contextLost = true; - m_numFailedRecreateAttempts = 0; - setNeedsCommit(); -} - -bool CCLayerTreeHost::compositeAndReadback(void *pixels, const IntRect& rect) -{ - m_triggerIdleUpdates = false; - bool ret = m_proxy->compositeAndReadback(pixels, rect); - m_triggerIdleUpdates = true; - return ret; -} - -void CCLayerTreeHost::finishAllRendering() -{ - if (!m_rendererInitialized) - return; - m_proxy->finishAllRendering(); -} - -void CCLayerTreeHost::renderingStats(CCRenderingStats* stats) const -{ - *stats = m_renderingStats; - m_proxy->renderingStats(stats); -} - -const RendererCapabilities& CCLayerTreeHost::rendererCapabilities() const -{ - return m_proxy->rendererCapabilities(); -} - -void CCLayerTreeHost::setNeedsAnimate() -{ - ASSERT(CCProxy::hasImplThread()); - m_proxy->setNeedsAnimate(); -} - -void CCLayerTreeHost::setNeedsCommit() -{ - m_proxy->setNeedsCommit(); -} - -void CCLayerTreeHost::setNeedsRedraw() -{ - m_proxy->setNeedsRedraw(); - if (!CCThreadProxy::implThread()) - m_client->scheduleComposite(); -} - -bool CCLayerTreeHost::commitRequested() const -{ - return m_proxy->commitRequested(); -} - -void CCLayerTreeHost::setAnimationEvents(scoped_ptr events, double wallClockTime) -{ - ASSERT(CCThreadProxy::isMainThread()); - setAnimationEventsRecursive(*events.get(), m_rootLayer.get(), wallClockTime); -} - -void CCLayerTreeHost::didAddAnimation() -{ - m_needsAnimateLayers = true; - m_proxy->didAddAnimation(); -} - -void CCLayerTreeHost::setRootLayer(scoped_refptr rootLayer) -{ - if (m_rootLayer == rootLayer) - return; - - if (m_rootLayer) - m_rootLayer->setLayerTreeHost(0); - m_rootLayer = rootLayer; - if (m_rootLayer) - m_rootLayer->setLayerTreeHost(this); - - if (m_hudLayer) - m_hudLayer->removeFromParent(); - - setNeedsCommit(); -} - -void CCLayerTreeHost::setViewportSize(const IntSize& layoutViewportSize, const IntSize& deviceViewportSize) -{ - if (layoutViewportSize == m_layoutViewportSize && deviceViewportSize == m_deviceViewportSize) - return; - - m_layoutViewportSize = layoutViewportSize; - m_deviceViewportSize = deviceViewportSize; - - setNeedsCommit(); -} - -void CCLayerTreeHost::setPageScaleFactorAndLimits(float pageScaleFactor, float minPageScaleFactor, float maxPageScaleFactor) -{ - if (pageScaleFactor == m_pageScaleFactor && minPageScaleFactor == m_minPageScaleFactor && maxPageScaleFactor == m_maxPageScaleFactor) - return; - - m_pageScaleFactor = pageScaleFactor; - m_minPageScaleFactor = minPageScaleFactor; - m_maxPageScaleFactor = maxPageScaleFactor; - setNeedsCommit(); -} - -void CCLayerTreeHost::setVisible(bool visible) -{ - if (m_visible == visible) - return; - m_visible = visible; - m_proxy->setVisible(visible); -} - -void CCLayerTreeHost::reduceContentsTexturesMemoryOnImplThread(size_t limitBytes, CCResourceProvider* resourceProvider) -{ - ASSERT(CCProxy::isImplThread()); - ASSERT(m_contentsTextureManager.get()); - m_contentsTextureManager->reduceMemoryOnImplThread(limitBytes, resourceProvider); -} - -bool CCLayerTreeHost::evictedContentsTexturesBackingsExist() const -{ - ASSERT(CCProxy::isImplThread()); - ASSERT(m_contentsTextureManager.get()); - return m_contentsTextureManager->evictedBackingsExist(); -} - -void CCLayerTreeHost::getEvictedContentTexturesBackings(CCPrioritizedTextureManager::BackingVector& evictedBackings) -{ - ASSERT(CCProxy::isImplThread()); - evictedBackings.clear(); - if (m_rendererInitialized) - m_contentsTextureManager->getEvictedBackings(evictedBackings); -} - -void CCLayerTreeHost::unlinkEvictedContentTexturesBackings(const CCPrioritizedTextureManager::BackingVector& evictedBackings) -{ - ASSERT(CCProxy::isMainThread()); - ASSERT(m_contentsTextureManager.get()); - m_contentsTextureManager->unlinkEvictedBackings(evictedBackings); -} - -bool CCLayerTreeHost::deleteEvictedContentTexturesBackings() -{ - ASSERT(CCProxy::isImplThread() && CCProxy::isMainThreadBlocked()); - ASSERT(m_contentsTextureManager.get()); - return m_contentsTextureManager->deleteEvictedBackings(); -} - -void CCLayerTreeHost::startPageScaleAnimation(const IntSize& targetPosition, bool useAnchor, float scale, double durationSec) -{ - m_proxy->startPageScaleAnimation(targetPosition, useAnchor, scale, durationSec); -} - -void CCLayerTreeHost::loseContext(int numTimes) -{ - TRACE_EVENT1("cc", "CCLayerTreeHost::loseCompositorContext", "numTimes", numTimes); - m_numTimesRecreateShouldFail = numTimes - 1; - m_proxy->loseContext(); -} - -CCPrioritizedTextureManager* CCLayerTreeHost::contentsTextureManager() const -{ - return m_contentsTextureManager.get(); -} - -void CCLayerTreeHost::composite() -{ - ASSERT(!CCThreadProxy::implThread()); - static_cast(m_proxy.get())->compositeImmediately(); -} - -void CCLayerTreeHost::scheduleComposite() -{ - m_client->scheduleComposite(); -} - -bool CCLayerTreeHost::initializeRendererIfNeeded() -{ - if (!m_rendererInitialized) { - initializeRenderer(); - // If we couldn't initialize, then bail since we're returning to software mode. - if (!m_rendererInitialized) - return false; - } - if (m_contextLost) { - if (recreateContext() != RecreateSucceeded) - return false; - } - return true; -} - -void CCLayerTreeHost::updateLayers(CCTextureUpdateQueue& queue, size_t memoryAllocationLimitBytes) -{ - ASSERT(m_rendererInitialized); - ASSERT(memoryAllocationLimitBytes); - - if (!rootLayer()) - return; - - if (layoutViewportSize().isEmpty()) - return; - - m_contentsTextureManager->setMaxMemoryLimitBytes(memoryAllocationLimitBytes); - - updateLayers(rootLayer(), queue); -} - -static void setScale(LayerChromium* layer, float deviceScaleFactor, float pageScaleFactor) -{ - if (layer->boundsContainPageScale()) - layer->setContentsScale(deviceScaleFactor); - else - layer->setContentsScale(deviceScaleFactor * pageScaleFactor); -} - -static LayerChromium* findFirstScrollableLayer(LayerChromium* layer) -{ - if (!layer) - return 0; - - if (layer->scrollable()) - return layer; - - for (size_t i = 0; i < layer->children().size(); ++i) { - LayerChromium* found = findFirstScrollableLayer(layer->children()[i].get()); - if (found) - return found; - } - - return 0; -} - -static void updateLayerScale(LayerChromium* layer, float deviceScaleFactor, float pageScaleFactor) -{ - setScale(layer, deviceScaleFactor, pageScaleFactor); - - LayerChromium* maskLayer = layer->maskLayer(); - if (maskLayer) - setScale(maskLayer, deviceScaleFactor, pageScaleFactor); - - LayerChromium* replicaMaskLayer = layer->replicaLayer() ? layer->replicaLayer()->maskLayer() : 0; - if (replicaMaskLayer) - setScale(replicaMaskLayer, deviceScaleFactor, pageScaleFactor); - - const std::vector >& children = layer->children(); - for (unsigned int i = 0; i < children.size(); ++i) - updateLayerScale(children[i].get(), deviceScaleFactor, pageScaleFactor); -} - -void CCLayerTreeHost::updateLayers(LayerChromium* rootLayer, CCTextureUpdateQueue& queue) -{ - TRACE_EVENT0("cc", "CCLayerTreeHost::updateLayers"); - - updateLayerScale(rootLayer, m_deviceScaleFactor, m_pageScaleFactor); - - LayerList updateList; - - { - if (CCSettings::pageScalePinchZoomEnabled()) { - LayerChromium* rootScroll = findFirstScrollableLayer(rootLayer); - if (rootScroll) - rootScroll->setImplTransform(m_implTransform); - } - - TRACE_EVENT0("cc", "CCLayerTreeHost::updateLayers::calcDrawEtc"); - CCLayerTreeHostCommon::calculateDrawTransforms(rootLayer, deviceViewportSize(), m_deviceScaleFactor, rendererCapabilities().maxTextureSize, updateList); - } - - // Reset partial texture update requests. - m_partialTextureUpdateRequests = 0; - - bool needMoreUpdates = paintLayerContents(updateList, queue); - if (m_triggerIdleUpdates && needMoreUpdates) - setNeedsCommit(); - - for (size_t i = 0; i < updateList.size(); ++i) - updateList[i]->clearRenderSurface(); -} - -void CCLayerTreeHost::setPrioritiesForSurfaces(size_t surfaceMemoryBytes) -{ - // Surfaces have a place holder for their memory since they are managed - // independantly but should still be tracked and reduce other memory usage. - m_surfaceMemoryPlaceholder->setTextureManager(m_contentsTextureManager.get()); - m_surfaceMemoryPlaceholder->setRequestPriority(CCPriorityCalculator::renderSurfacePriority()); - m_surfaceMemoryPlaceholder->setToSelfManagedMemoryPlaceholder(surfaceMemoryBytes); -} - -void CCLayerTreeHost::setPrioritiesForLayers(const LayerList& updateList) -{ - // Use BackToFront since it's cheap and this isn't order-dependent. - typedef CCLayerIterator CCLayerIteratorType; - - CCPriorityCalculator calculator; - CCLayerIteratorType end = CCLayerIteratorType::end(&updateList); - for (CCLayerIteratorType it = CCLayerIteratorType::begin(&updateList); it != end; ++it) { - if (it.representsItself()) - it->setTexturePriorities(calculator); - else if (it.representsTargetRenderSurface()) { - if (it->maskLayer()) - it->maskLayer()->setTexturePriorities(calculator); - if (it->replicaLayer() && it->replicaLayer()->maskLayer()) - it->replicaLayer()->maskLayer()->setTexturePriorities(calculator); - } - } -} - -void CCLayerTreeHost::prioritizeTextures(const LayerList& renderSurfaceLayerList, CCOverdrawMetrics& metrics) -{ - m_contentsTextureManager->clearPriorities(); - - size_t memoryForRenderSurfacesMetric = calculateMemoryForRenderSurfaces(renderSurfaceLayerList); - - setPrioritiesForLayers(renderSurfaceLayerList); - setPrioritiesForSurfaces(memoryForRenderSurfacesMetric); - - metrics.didUseContentsTextureMemoryBytes(m_contentsTextureManager->memoryAboveCutoffBytes()); - metrics.didUseRenderSurfaceTextureMemoryBytes(memoryForRenderSurfacesMetric); - - m_contentsTextureManager->prioritizeTextures(); -} - -size_t CCLayerTreeHost::calculateMemoryForRenderSurfaces(const LayerList& updateList) -{ - size_t readbackBytes = 0; - size_t maxBackgroundTextureBytes = 0; - size_t contentsTextureBytes = 0; - - // Start iteration at 1 to skip the root surface as it does not have a texture cost. - for (size_t i = 1; i < updateList.size(); ++i) { - LayerChromium* renderSurfaceLayer = updateList[i].get(); - RenderSurfaceChromium* renderSurface = renderSurfaceLayer->renderSurface(); - - size_t bytes = CCTexture::memorySizeBytes(renderSurface->contentRect().size(), GraphicsContext3D::RGBA); - contentsTextureBytes += bytes; - - if (renderSurfaceLayer->backgroundFilters().isEmpty()) - continue; - - if (bytes > maxBackgroundTextureBytes) - maxBackgroundTextureBytes = bytes; - if (!readbackBytes) - readbackBytes = CCTexture::memorySizeBytes(m_deviceViewportSize, GraphicsContext3D::RGBA); - } - return readbackBytes + maxBackgroundTextureBytes + contentsTextureBytes; -} - -bool CCLayerTreeHost::paintMasksForRenderSurface(LayerChromium* renderSurfaceLayer, CCTextureUpdateQueue& queue) -{ - // Note: Masks and replicas only exist for layers that own render surfaces. If we reach this point - // in code, we already know that at least something will be drawn into this render surface, so the - // mask and replica should be painted. - - bool needMoreUpdates = false; - LayerChromium* maskLayer = renderSurfaceLayer->maskLayer(); - if (maskLayer) { - maskLayer->update(queue, 0, m_renderingStats); - needMoreUpdates |= maskLayer->needMoreUpdates(); - } - - LayerChromium* replicaMaskLayer = renderSurfaceLayer->replicaLayer() ? renderSurfaceLayer->replicaLayer()->maskLayer() : 0; - if (replicaMaskLayer) { - replicaMaskLayer->update(queue, 0, m_renderingStats); - needMoreUpdates |= replicaMaskLayer->needMoreUpdates(); - } - return needMoreUpdates; -} - -bool CCLayerTreeHost::paintLayerContents(const LayerList& renderSurfaceLayerList, CCTextureUpdateQueue& queue) -{ - // Use FrontToBack to allow for testing occlusion and performing culling during the tree walk. - typedef CCLayerIterator CCLayerIteratorType; - - bool needMoreUpdates = false; - bool recordMetricsForFrame = true; // FIXME: In the future, disable this when about:tracing is off. - CCOcclusionTracker occlusionTracker(m_rootLayer->renderSurface()->contentRect(), recordMetricsForFrame); - occlusionTracker.setMinimumTrackingSize(m_settings.minimumOcclusionTrackingSize); - - prioritizeTextures(renderSurfaceLayerList, occlusionTracker.overdrawMetrics()); - - CCLayerIteratorType end = CCLayerIteratorType::end(&renderSurfaceLayerList); - for (CCLayerIteratorType it = CCLayerIteratorType::begin(&renderSurfaceLayerList); it != end; ++it) { - occlusionTracker.enterLayer(it); - - if (it.representsTargetRenderSurface()) { - ASSERT(it->renderSurface()->drawOpacity() || it->renderSurface()->drawOpacityIsAnimating()); - needMoreUpdates |= paintMasksForRenderSurface(*it, queue); - } else if (it.representsItself()) { - ASSERT(!it->bounds().isEmpty()); - it->update(queue, &occlusionTracker, m_renderingStats); - needMoreUpdates |= it->needMoreUpdates(); - } - - occlusionTracker.leaveLayer(it); - } - - occlusionTracker.overdrawMetrics().recordMetrics(this); - - return needMoreUpdates; -} - -void CCLayerTreeHost::applyScrollAndScale(const CCScrollAndScaleSet& info) -{ - if (!m_rootLayer) - return; - - LayerChromium* rootScrollLayer = findFirstScrollableLayer(m_rootLayer.get()); - IntSize rootScrollDelta; - - for (size_t i = 0; i < info.scrolls.size(); ++i) { - LayerChromium* layer = CCLayerTreeHostCommon::findLayerInSubtree(m_rootLayer.get(), info.scrolls[i].layerId); - if (!layer) - continue; - if (layer == rootScrollLayer) - rootScrollDelta += info.scrolls[i].scrollDelta; - else - layer->setScrollPosition(layer->scrollPosition() + info.scrolls[i].scrollDelta); - } - if (!rootScrollDelta.isZero() || info.pageScaleDelta != 1) - m_client->applyScrollAndScale(rootScrollDelta, info.pageScaleDelta); -} - -void CCLayerTreeHost::setImplTransform(const WebKit::WebTransformationMatrix& transform) -{ - m_implTransform = transform; -} - -void CCLayerTreeHost::startRateLimiter(WebKit::WebGraphicsContext3D* context) -{ - if (m_animating) - return; - - ASSERT(context); - RateLimiterMap::iterator it = m_rateLimiters.find(context); - if (it != m_rateLimiters.end()) - it->second->start(); - else { - scoped_refptr rateLimiter = RateLimiter::create(context, this); - m_rateLimiters[context] = rateLimiter; - rateLimiter->start(); - } -} - -void CCLayerTreeHost::stopRateLimiter(WebKit::WebGraphicsContext3D* context) -{ - RateLimiterMap::iterator it = m_rateLimiters.find(context); - if (it != m_rateLimiters.end()) { - it->second->stop(); - m_rateLimiters.erase(it); - } -} - -void CCLayerTreeHost::rateLimit() -{ - // Force a no-op command on the compositor context, so that any ratelimiting commands will wait for the compositing - // context, and therefore for the SwapBuffers. - m_proxy->forceSerializeOnSwapBuffers(); -} - -bool CCLayerTreeHost::bufferedUpdates() -{ - return m_settings.maxPartialTextureUpdates != numeric_limits::max(); -} - -bool CCLayerTreeHost::requestPartialTextureUpdate() -{ - if (m_partialTextureUpdateRequests >= m_settings.maxPartialTextureUpdates) - return false; - - m_partialTextureUpdateRequests++; - return true; -} - -void CCLayerTreeHost::deleteTextureAfterCommit(scoped_ptr texture) -{ - m_deleteTextureAfterCommitList.append(texture.Pass()); -} - -void CCLayerTreeHost::setDeviceScaleFactor(float deviceScaleFactor) -{ - if (deviceScaleFactor == m_deviceScaleFactor) - return; - m_deviceScaleFactor = deviceScaleFactor; - - setNeedsCommit(); -} - -void CCLayerTreeHost::animateLayers(double monotonicTime) -{ - if (!CCSettings::acceleratedAnimationEnabled() || !m_needsAnimateLayers) - return; - - TRACE_EVENT0("cc", "CCLayerTreeHostImpl::animateLayers"); - m_needsAnimateLayers = animateLayersRecursive(m_rootLayer.get(), monotonicTime); -} - -bool CCLayerTreeHost::animateLayersRecursive(LayerChromium* current, double monotonicTime) -{ - if (!current) - return false; - - bool subtreeNeedsAnimateLayers = false; - CCLayerAnimationController* currentController = current->layerAnimationController(); - currentController->animate(monotonicTime, 0); - - // If the current controller still has an active animation, we must continue animating layers. - if (currentController->hasActiveAnimation()) - subtreeNeedsAnimateLayers = true; - - for (size_t i = 0; i < current->children().size(); ++i) { - if (animateLayersRecursive(current->children()[i].get(), monotonicTime)) - subtreeNeedsAnimateLayers = true; - } - - return subtreeNeedsAnimateLayers; -} - -void CCLayerTreeHost::setAnimationEventsRecursive(const CCAnimationEventsVector& events, LayerChromium* layer, double wallClockTime) -{ - if (!layer) - return; - - for (size_t eventIndex = 0; eventIndex < events.size(); ++eventIndex) { - if (layer->id() == events[eventIndex].layerId) { - if (events[eventIndex].type == CCAnimationEvent::Started) - layer->notifyAnimationStarted(events[eventIndex], wallClockTime); - else - layer->notifyAnimationFinished(wallClockTime); - } - } - - for (size_t childIndex = 0; childIndex < layer->children().size(); ++childIndex) - setAnimationEventsRecursive(events, layer->children()[childIndex].get(), wallClockTime); -} - -} // namespace cc diff --git a/cc/CCLayerTreeHost.h b/cc/CCLayerTreeHost.h index 277b1f0..e82fc46 100644 --- a/cc/CCLayerTreeHost.h +++ b/cc/CCLayerTreeHost.h @@ -1,297 +1,6 @@ -// Copyright 2011 The Chromium Authors. All rights reserved. +// Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CCLayerTreeHost_h -#define CCLayerTreeHost_h - -#include "base/basictypes.h" -#include "base/hash_tables.h" -#include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" -#include "CCAnimationEvents.h" -#include "CCGraphicsContext.h" -#include "CCLayerTreeHostClient.h" -#include "CCLayerTreeHostCommon.h" -#include "CCOcclusionTracker.h" -#include "CCPrioritizedTextureManager.h" -#include "CCProxy.h" -#include "CCRenderingStats.h" -#include "IntRect.h" -#include "RateLimiter.h" -#include "scoped_ptr_vector.h" -#include "SkColor.h" -#include - -#if defined(COMPILER_GCC) -namespace BASE_HASH_NAMESPACE { -template<> -struct hash { - size_t operator()(WebKit::WebGraphicsContext3D* ptr) const { - return hash()(reinterpret_cast(ptr)); - } -}; -} // namespace BASE_HASH_NAMESPACE -#endif // COMPILER - -namespace cc { - -class CCFontAtlas; -class CCLayerChromium; -class CCLayerTreeHostImpl; -class CCLayerTreeHostImplClient; -class CCPrioritizedTextureManager; -class CCTextureUpdateQueue; -class HeadsUpDisplayLayerChromium; -class Region; -struct CCScrollAndScaleSet; - -struct CCLayerTreeSettings { - CCLayerTreeSettings(); - ~CCLayerTreeSettings(); - - bool acceleratePainting; - bool showFPSCounter; - bool showPlatformLayerTree; - bool showPaintRects; - bool showPropertyChangedRects; - bool showSurfaceDamageRects; - bool showScreenSpaceRects; - bool showReplicaScreenSpaceRects; - bool showOccludingRects; - bool renderVSyncEnabled; - double refreshRate; - size_t maxPartialTextureUpdates; - IntSize defaultTileSize; - IntSize maxUntiledLayerSize; - IntSize minimumOcclusionTrackingSize; - - bool showDebugInfo() const { return showPlatformLayerTree || showFPSCounter || showDebugRects(); } - bool showDebugRects() const { return showPaintRects || showPropertyChangedRects || showSurfaceDamageRects || showScreenSpaceRects || showReplicaScreenSpaceRects || showOccludingRects; } -}; - -// Provides information on an Impl's rendering capabilities back to the CCLayerTreeHost -struct RendererCapabilities { - RendererCapabilities(); - ~RendererCapabilities(); - - GC3Denum bestTextureFormat; - bool contextHasCachedFrontBuffer; - bool usingPartialSwap; - bool usingAcceleratedPainting; - bool usingSetVisibility; - bool usingSwapCompleteCallback; - bool usingGpuMemoryManager; - bool usingDiscardFramebuffer; - bool usingEglImage; - int maxTextureSize; -}; - -class CCLayerTreeHost : public RateLimiterClient { -public: - static scoped_ptr create(CCLayerTreeHostClient*, const CCLayerTreeSettings&); - virtual ~CCLayerTreeHost(); - - void setSurfaceReady(); - - // Returns true if any CCLayerTreeHost is alive. - static bool anyLayerTreeHostInstanceExists(); - - static bool needsFilterContext() { return s_needsFilterContext; } - static void setNeedsFilterContext(bool needsFilterContext) { s_needsFilterContext = needsFilterContext; } - bool needsSharedContext() const { return needsFilterContext() || settings().acceleratePainting; } - - // CCLayerTreeHost interface to CCProxy. - void willBeginFrame() { m_client->willBeginFrame(); } - void didBeginFrame() { m_client->didBeginFrame(); } - void updateAnimations(double monotonicFrameBeginTime); - void layout(); - void beginCommitOnImplThread(CCLayerTreeHostImpl*); - void finishCommitOnImplThread(CCLayerTreeHostImpl*); - void willCommit(); - void commitComplete(); - scoped_ptr createContext(); - scoped_ptr createInputHandler(); - virtual scoped_ptr createLayerTreeHostImpl(CCLayerTreeHostImplClient*); - void didLoseContext(); - enum RecreateResult { - RecreateSucceeded, - RecreateFailedButTryAgain, - RecreateFailedAndGaveUp, - }; - RecreateResult recreateContext(); - void didCommitAndDrawFrame() { m_client->didCommitAndDrawFrame(); } - void didCompleteSwapBuffers() { m_client->didCompleteSwapBuffers(); } - void deleteContentsTexturesOnImplThread(CCResourceProvider*); - virtual void acquireLayerTextures(); - // Returns false if we should abort this frame due to initialization failure. - bool initializeRendererIfNeeded(); - void updateLayers(CCTextureUpdateQueue&, size_t contentsMemoryLimitBytes); - - CCLayerTreeHostClient* client() { return m_client; } - - // Only used when compositing on the main thread. - void composite(); - void scheduleComposite(); - - // Composites and attempts to read back the result into the provided - // buffer. If it wasn't possible, e.g. due to context lost, will return - // false. - bool compositeAndReadback(void *pixels, const IntRect&); - - void finishAllRendering(); - - int commitNumber() const { return m_commitNumber; } - - void renderingStats(CCRenderingStats*) const; - - const RendererCapabilities& rendererCapabilities() const; - - // Test only hook - void loseContext(int numTimes); - - void setNeedsAnimate(); - // virtual for testing - virtual void setNeedsCommit(); - void setNeedsRedraw(); - bool commitRequested() const; - - void setAnimationEvents(scoped_ptr, double wallClockTime); - virtual void didAddAnimation(); - - LayerChromium* rootLayer() { return m_rootLayer.get(); } - const LayerChromium* rootLayer() const { return m_rootLayer.get(); } - void setRootLayer(scoped_refptr); - - const CCLayerTreeSettings& settings() const { return m_settings; } - - void setViewportSize(const IntSize& layoutViewportSize, const IntSize& deviceViewportSize); - - const IntSize& layoutViewportSize() const { return m_layoutViewportSize; } - const IntSize& deviceViewportSize() const { return m_deviceViewportSize; } - - void setPageScaleFactorAndLimits(float pageScaleFactor, float minPageScaleFactor, float maxPageScaleFactor); - - void setBackgroundColor(SkColor color) { m_backgroundColor = color; } - - void setHasTransparentBackground(bool transparent) { m_hasTransparentBackground = transparent; } - - CCPrioritizedTextureManager* contentsTextureManager() const; - - // Delete contents textures' backing resources until they use only bytesLimit bytes. This may - // be called on the impl thread while the main thread is running. - void reduceContentsTexturesMemoryOnImplThread(size_t bytesLimit, CCResourceProvider*); - // Returns true if there any evicted backing textures that have not been deleted. - bool evictedContentsTexturesBackingsExist() const; - // Retrieve the list of all contents textures' backings that have been evicted, to pass to the - // main thread to unlink them from their owning textures. - void getEvictedContentTexturesBackings(CCPrioritizedTextureManager::BackingVector&); - // Unlink the list of contents textures' backings from their owning textures on the main thread - // before updating layers. - void unlinkEvictedContentTexturesBackings(const CCPrioritizedTextureManager::BackingVector&); - // Deletes all evicted backings, unlinking them from their owning textures if needed. - // Returns true if this function had to unlink any backings from their owning texture when - // destroying them. If this was the case, the impl layer tree may contain invalid resources. - bool deleteEvictedContentTexturesBackings(); - - bool visible() const { return m_visible; } - void setVisible(bool); - - void startPageScaleAnimation(const IntSize& targetPosition, bool useAnchor, float scale, double durationSec); - - void applyScrollAndScale(const CCScrollAndScaleSet&); - void setImplTransform(const WebKit::WebTransformationMatrix&); - - void startRateLimiter(WebKit::WebGraphicsContext3D*); - void stopRateLimiter(WebKit::WebGraphicsContext3D*); - - // RateLimitClient implementation - virtual void rateLimit() OVERRIDE; - - bool bufferedUpdates(); - bool requestPartialTextureUpdate(); - void deleteTextureAfterCommit(scoped_ptr); - - void setDeviceScaleFactor(float); - float deviceScaleFactor() const { return m_deviceScaleFactor; } - - void setFontAtlas(scoped_ptr); - - HeadsUpDisplayLayerChromium* hudLayer() const { return m_hudLayer.get(); } - -protected: - CCLayerTreeHost(CCLayerTreeHostClient*, const CCLayerTreeSettings&); - bool initialize(); - -private: - typedef std::vector > LayerList; - - void initializeRenderer(); - - void update(LayerChromium*, CCTextureUpdateQueue&, const CCOcclusionTracker*); - bool paintLayerContents(const LayerList&, CCTextureUpdateQueue&); - bool paintMasksForRenderSurface(LayerChromium*, CCTextureUpdateQueue&); - - void updateLayers(LayerChromium*, CCTextureUpdateQueue&); - - void prioritizeTextures(const LayerList&, CCOverdrawMetrics&); - void setPrioritiesForSurfaces(size_t surfaceMemoryBytes); - void setPrioritiesForLayers(const LayerList&); - size_t calculateMemoryForRenderSurfaces(const LayerList& updateList); - - void animateLayers(double monotonicTime); - bool animateLayersRecursive(LayerChromium* current, double monotonicTime); - void setAnimationEventsRecursive(const CCAnimationEventsVector&, LayerChromium*, double wallClockTime); - - bool m_animating; - bool m_needsAnimateLayers; - - CCLayerTreeHostClient* m_client; - - int m_commitNumber; - CCRenderingStats m_renderingStats; - - scoped_ptr m_proxy; - bool m_rendererInitialized; - bool m_contextLost; - int m_numTimesRecreateShouldFail; - int m_numFailedRecreateAttempts; - - scoped_refptr m_rootLayer; - scoped_refptr m_hudLayer; - scoped_ptr m_fontAtlas; - - scoped_ptr m_contentsTextureManager; - scoped_ptr m_surfaceMemoryPlaceholder; - - CCLayerTreeSettings m_settings; - - IntSize m_layoutViewportSize; - IntSize m_deviceViewportSize; - float m_deviceScaleFactor; - - bool m_visible; - - typedef base::hash_map > RateLimiterMap; - RateLimiterMap m_rateLimiters; - - float m_pageScaleFactor; - float m_minPageScaleFactor, m_maxPageScaleFactor; - WebKit::WebTransformationMatrix m_implTransform; - bool m_triggerIdleUpdates; - - SkColor m_backgroundColor; - bool m_hasTransparentBackground; - - typedef ScopedPtrVector TextureList; - TextureList m_deleteTextureAfterCommitList; - size_t m_partialTextureUpdateRequests; - - static bool s_needsFilterContext; - - DISALLOW_COPY_AND_ASSIGN(CCLayerTreeHost); -}; - -} // namespace cc - -#endif +// Temporary forwarding header +#include "cc/layer_tree_host.h" diff --git a/cc/CCLayerTreeHostClient.h b/cc/CCLayerTreeHostClient.h index 1c88a75..4a4f608 100644 --- a/cc/CCLayerTreeHostClient.h +++ b/cc/CCLayerTreeHostClient.h @@ -2,42 +2,5 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CCLayerTreeHostClient_h -#define CCLayerTreeHostClient_h - -#include "base/memory/scoped_ptr.h" - -namespace WebKit { -class WebCompositorOutputSurface; -} - -namespace cc { -class CCInputHandler; -class IntSize; - -class CCLayerTreeHostClient { -public: - virtual void willBeginFrame() = 0; - // Marks finishing compositing-related tasks on the main thread. In threaded mode, this corresponds to didCommit(). - virtual void didBeginFrame() = 0; - virtual void animate(double frameBeginTime) = 0; - virtual void layout() = 0; - virtual void applyScrollAndScale(const IntSize& scrollDelta, float pageScale) = 0; - virtual scoped_ptr createOutputSurface() = 0; - virtual void didRecreateOutputSurface(bool success) = 0; - virtual scoped_ptr createInputHandler() = 0; - virtual void willCommit() = 0; - virtual void didCommit() = 0; - virtual void didCommitAndDrawFrame() = 0; - virtual void didCompleteSwapBuffers() = 0; - - // Used only in the single-threaded path. - virtual void scheduleComposite() = 0; - -protected: - virtual ~CCLayerTreeHostClient() { } -}; - -} - -#endif // CCLayerTreeHostClient_h +// Temporary forwarding header +#include "cc/layer_tree_host_client.h" diff --git a/cc/CCLayerTreeHostCommon.cpp b/cc/CCLayerTreeHostCommon.cpp deleted file mode 100644 index 24274a6f..0000000 --- a/cc/CCLayerTreeHostCommon.cpp +++ /dev/null @@ -1,865 +0,0 @@ -// Copyright 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - - -#include "config.h" - -#include "CCLayerTreeHostCommon.h" - -#include "CCLayerImpl.h" -#include "CCLayerIterator.h" -#include "CCLayerSorter.h" -#include "CCMathUtil.h" -#include "CCRenderSurface.h" -#include "FloatQuad.h" -#include "IntRect.h" -#include "LayerChromium.h" -#include "RenderSurfaceChromium.h" -#include - -using WebKit::WebTransformationMatrix; - -namespace cc { - -CCScrollAndScaleSet::CCScrollAndScaleSet() -{ -} - -CCScrollAndScaleSet::~CCScrollAndScaleSet() -{ -} - -IntRect CCLayerTreeHostCommon::calculateVisibleRect(const IntRect& targetSurfaceRect, const IntRect& layerBoundRect, const WebTransformationMatrix& transform) -{ - // Is this layer fully contained within the target surface? - IntRect layerInSurfaceSpace = CCMathUtil::mapClippedRect(transform, layerBoundRect); - if (targetSurfaceRect.contains(layerInSurfaceSpace)) - return layerBoundRect; - - // If the layer doesn't fill up the entire surface, then find the part of - // the surface rect where the layer could be visible. This avoids trying to - // project surface rect points that are behind the projection point. - IntRect minimalSurfaceRect = targetSurfaceRect; - minimalSurfaceRect.intersect(layerInSurfaceSpace); - - // Project the corners of the target surface rect into the layer space. - // This bounding rectangle may be larger than it needs to be (being - // axis-aligned), but is a reasonable filter on the space to consider. - // Non-invertible transforms will create an empty rect here. - const WebTransformationMatrix surfaceToLayer = transform.inverse(); - IntRect layerRect = enclosingIntRect(CCMathUtil::projectClippedRect(surfaceToLayer, FloatRect(minimalSurfaceRect))); - layerRect.intersect(layerBoundRect); - return layerRect; -} - -template -static inline bool layerIsInExisting3DRenderingContext(LayerType* layer) -{ - // According to current W3C spec on CSS transforms, a layer is part of an established - // 3d rendering context if its parent has transform-style of preserves-3d. - return layer->parent() && layer->parent()->preserves3D(); -} - -template -static bool layerIsRootOfNewRenderingContext(LayerType* layer) -{ - // According to current W3C spec on CSS transforms (Section 6.1), a layer is the - // beginning of 3d rendering context if its parent does not have transform-style: - // preserve-3d, but this layer itself does. - if (layer->parent()) - return !layer->parent()->preserves3D() && layer->preserves3D(); - - return layer->preserves3D(); -} - -template -static bool isLayerBackFaceVisible(LayerType* layer) -{ - // The current W3C spec on CSS transforms says that backface visibility should be - // determined differently depending on whether the layer is in a "3d rendering - // context" or not. For Chromium code, we can determine whether we are in a 3d - // rendering context by checking if the parent preserves 3d. - - if (layerIsInExisting3DRenderingContext(layer)) - return layer->drawTransform().isBackFaceVisible(); - - // In this case, either the layer establishes a new 3d rendering context, or is not in - // a 3d rendering context at all. - return layer->transform().isBackFaceVisible(); -} - -template -static bool isSurfaceBackFaceVisible(LayerType* layer, const WebTransformationMatrix& drawTransform) -{ - if (layerIsInExisting3DRenderingContext(layer)) - return drawTransform.isBackFaceVisible(); - - if (layerIsRootOfNewRenderingContext(layer)) - return layer->transform().isBackFaceVisible(); - - // If the renderSurface is not part of a new or existing rendering context, then the - // layers that contribute to this surface will decide back-face visibility for themselves. - return false; -} - -template -static inline bool layerClipsSubtree(LayerType* layer) -{ - return layer->masksToBounds() || layer->maskLayer(); -} - -template -static IntRect calculateVisibleContentRect(LayerType* layer) -{ - ASSERT(layer->renderTarget()); - - // Nothing is visible if the layer bounds are empty. - if (!layer->drawsContent() || layer->contentBounds().isEmpty() || layer->drawableContentRect().isEmpty()) - return IntRect(); - - IntRect targetSurfaceClipRect; - - // First, compute visible bounds in target surface space. - if (layer->renderTarget()->renderSurface()->clipRect().isEmpty()) - targetSurfaceClipRect = layer->drawableContentRect(); - else { - // In this case the target surface does clip layers that contribute to it. So, we - // have convert the current surface's clipRect from its ancestor surface space to - // the current surface space. - targetSurfaceClipRect = enclosingIntRect(CCMathUtil::projectClippedRect(layer->renderTarget()->renderSurface()->drawTransform().inverse(), layer->renderTarget()->renderSurface()->clipRect())); - targetSurfaceClipRect.intersect(layer->drawableContentRect()); - } - - if (targetSurfaceClipRect.isEmpty()) - return IntRect(); - - return CCLayerTreeHostCommon::calculateVisibleRect(targetSurfaceClipRect, IntRect(IntPoint(), layer->contentBounds()), layer->drawTransform()); -} - -static bool isScaleOrTranslation(const WebTransformationMatrix& m) -{ - return !m.m12() && !m.m13() && !m.m14() - && !m.m21() && !m.m23() && !m.m24() - && !m.m31() && !m.m32() && !m.m43() - && m.m44(); -} - -static inline bool transformToParentIsKnown(CCLayerImpl*) -{ - return true; -} - -static inline bool transformToParentIsKnown(LayerChromium* layer) -{ - return !layer->transformIsAnimating(); -} - -static inline bool transformToScreenIsKnown(CCLayerImpl*) -{ - return true; -} - -static inline bool transformToScreenIsKnown(LayerChromium* layer) -{ - return !layer->screenSpaceTransformIsAnimating(); -} - -template -static bool layerShouldBeSkipped(LayerType* layer) -{ - // Layers can be skipped if any of these conditions are met. - // - does not draw content. - // - is transparent - // - has empty bounds - // - the layer is not double-sided, but its back face is visible. - // - // Some additional conditions need to be computed at a later point after the recursion is finished. - // - the intersection of render surface content and layer clipRect is empty - // - the visibleContentRect is empty - // - // Note, if the layer should not have been drawn due to being fully transparent, - // we would have skipped the entire subtree and never made it into this function, - // so it is safe to omit this check here. - - if (!layer->drawsContent() || layer->bounds().isEmpty()) - return true; - - LayerType* backfaceTestLayer = layer; - if (layer->useParentBackfaceVisibility()) { - ASSERT(layer->parent()); - ASSERT(!layer->parent()->useParentBackfaceVisibility()); - backfaceTestLayer = layer->parent(); - } - - // The layer should not be drawn if (1) it is not double-sided and (2) the back of the layer is known to be facing the screen. - if (!backfaceTestLayer->doubleSided() && transformToScreenIsKnown(backfaceTestLayer) && isLayerBackFaceVisible(backfaceTestLayer)) - return true; - - return false; -} - -static inline bool subtreeShouldBeSkipped(CCLayerImpl* layer) -{ - // The opacity of a layer always applies to its children (either implicitly - // via a render surface or explicitly if the parent preserves 3D), so the - // entire subtree can be skipped if this layer is fully transparent. - return !layer->opacity(); -} - -static inline bool subtreeShouldBeSkipped(LayerChromium* layer) -{ - // If the opacity is being animated then the opacity on the main thread is unreliable - // (since the impl thread may be using a different opacity), so it should not be trusted. - // In particular, it should not cause the subtree to be skipped. - return !layer->opacity() && !layer->opacityIsAnimating(); -} - -template -static bool subtreeShouldRenderToSeparateSurface(LayerType* layer, bool axisAlignedWithRespectToParent) -{ - // The root layer has a special render surface that is set up externally, so - // it shouldn't be treated as a surface in this code. - if (!layer->parent()) - return false; - - // Cache this value, because otherwise it walks the entire subtree several times. - bool descendantDrawsContent = layer->descendantDrawsContent(); - - // - // A layer and its descendants should render onto a new RenderSurface if any of these rules hold: - // - - // If we force it. - if (layer->forceRenderSurface()) - return true; - - // If the layer uses a mask. - if (layer->maskLayer()) - return true; - - // If the layer has a reflection. - if (layer->replicaLayer()) - return true; - - // If the layer uses a CSS filter. - if (!layer->filters().isEmpty() || !layer->backgroundFilters().isEmpty()) - return true; - - // If the layer flattens its subtree (i.e. the layer doesn't preserve-3d), but it is - // treated as a 3D object by its parent (i.e. parent does preserve-3d). - if (layerIsInExisting3DRenderingContext(layer) && !layer->preserves3D() && descendantDrawsContent) - return true; - - // If the layer clips its descendants but it is not axis-aligned with respect to its parent. - if (layerClipsSubtree(layer) && !axisAlignedWithRespectToParent && descendantDrawsContent) - return true; - - // If the layer has opacity != 1 and does not have a preserves-3d transform style. - if (layer->opacity() != 1 && !layer->preserves3D() && descendantDrawsContent) - return true; - - return false; -} - -WebTransformationMatrix computeScrollCompensationForThisLayer(CCLayerImpl* scrollingLayer, const WebTransformationMatrix& parentMatrix) -{ - // For every layer that has non-zero scrollDelta, we have to compute a transform that can undo the - // scrollDelta translation. In particular, we want this matrix to premultiply a fixed-position layer's - // parentMatrix, so we design this transform in three steps as follows. The steps described here apply - // from right-to-left, so Step 1 would be the right-most matrix: - // - // Step 1. transform from target surface space to the exact space where scrollDelta is actually applied. - // -- this is inverse of the matrix in step 3 - // Step 2. undo the scrollDelta - // -- this is just a translation by scrollDelta. - // Step 3. transform back to target surface space. - // -- this transform is the "partialLayerOriginTransform" = (parentMatrix * scale(layer->pageScaleDelta())); - // - // These steps create a matrix that both start and end in targetSurfaceSpace. So this matrix can - // pre-multiply any fixed-position layer's drawTransform to undo the scrollDeltas -- as long as - // that fixed position layer is fixed onto the same renderTarget as this scrollingLayer. - // - - WebTransformationMatrix partialLayerOriginTransform = parentMatrix; - partialLayerOriginTransform.multiply(scrollingLayer->implTransform()); - - WebTransformationMatrix scrollCompensationForThisLayer = partialLayerOriginTransform; // Step 3 - scrollCompensationForThisLayer.translate(scrollingLayer->scrollDelta().width(), scrollingLayer->scrollDelta().height()); // Step 2 - scrollCompensationForThisLayer.multiply(partialLayerOriginTransform.inverse()); // Step 1 - return scrollCompensationForThisLayer; -} - -WebTransformationMatrix computeScrollCompensationMatrixForChildren(LayerChromium* currentLayer, const WebTransformationMatrix& currentParentMatrix, const WebTransformationMatrix& currentScrollCompensation) -{ - // The main thread (i.e. LayerChromium) does not need to worry about scroll compensation. - // So we can just return an identity matrix here. - return WebTransformationMatrix(); -} - -WebTransformationMatrix computeScrollCompensationMatrixForChildren(CCLayerImpl* layer, const WebTransformationMatrix& parentMatrix, const WebTransformationMatrix& currentScrollCompensationMatrix) -{ - // "Total scroll compensation" is the transform needed to cancel out all scrollDelta translations that - // occurred since the nearest container layer, even if there are renderSurfaces in-between. - // - // There are some edge cases to be aware of, that are not explicit in the code: - // - A layer that is both a fixed-position and container should not be its own container, instead, that means - // it is fixed to an ancestor, and is a container for any fixed-position descendants. - // - A layer that is a fixed-position container and has a renderSurface should behave the same as a container - // without a renderSurface, the renderSurface is irrelevant in that case. - // - A layer that does not have an explicit container is simply fixed to the viewport - // (i.e. the root renderSurface, and it would still compensate for root layer's scrollDelta). - // - If the fixed-position layer has its own renderSurface, then the renderSurface is - // the one who gets fixed. - // - // This function needs to be called AFTER layers create their own renderSurfaces. - // - - // Avoid the overheads (including stack allocation and matrix initialization/copy) if we know that the scroll compensation doesn't need to be reset or adjusted. - if (!layer->isContainerForFixedPositionLayers() && layer->scrollDelta().isZero() && !layer->renderSurface()) - return currentScrollCompensationMatrix; - - // Start as identity matrix. - WebTransformationMatrix nextScrollCompensationMatrix; - - // If this layer is not a container, then it inherits the existing scroll compensations. - if (!layer->isContainerForFixedPositionLayers()) - nextScrollCompensationMatrix = currentScrollCompensationMatrix; - - // If the current layer has a non-zero scrollDelta, then we should compute its local scrollCompensation - // and accumulate it to the nextScrollCompensationMatrix. - if (!layer->scrollDelta().isZero()) { - WebTransformationMatrix scrollCompensationForThisLayer = computeScrollCompensationForThisLayer(layer, parentMatrix); - nextScrollCompensationMatrix.multiply(scrollCompensationForThisLayer); - } - - // If the layer created its own renderSurface, we have to adjust nextScrollCompensationMatrix. - // The adjustment allows us to continue using the scrollCompensation on the next surface. - // Step 1 (right-most in the math): transform from the new surface to the original ancestor surface - // Step 2: apply the scroll compensation - // Step 3: transform back to the new surface. - if (layer->renderSurface() && !nextScrollCompensationMatrix.isIdentity()) - nextScrollCompensationMatrix = layer->renderSurface()->drawTransform().inverse() * nextScrollCompensationMatrix * layer->renderSurface()->drawTransform(); - - return nextScrollCompensationMatrix; -} - -// Should be called just before the recursive calculateDrawTransformsInternal(). -template -void setupRootLayerAndSurfaceForRecursion(LayerType* rootLayer, LayerList& renderSurfaceLayerList, const IntSize& deviceViewportSize) -{ - if (!rootLayer->renderSurface()) - rootLayer->createRenderSurface(); - - rootLayer->renderSurface()->setContentRect(IntRect(IntPoint::zero(), deviceViewportSize)); - rootLayer->renderSurface()->clearLayerLists(); - - ASSERT(renderSurfaceLayerList.empty()); - renderSurfaceLayerList.push_back(rootLayer); -} - -// Recursively walks the layer tree starting at the given node and computes all the -// necessary transformations, clipRects, render surfaces, etc. -template -static void calculateDrawTransformsInternal(LayerType* layer, LayerType* rootLayer, const WebTransformationMatrix& parentMatrix, - const WebTransformationMatrix& fullHierarchyMatrix, const WebTransformationMatrix& currentScrollCompensationMatrix, - const IntRect& clipRectFromAncestor, bool ancestorClipsSubtree, - RenderSurfaceType* nearestAncestorThatMovesPixels, LayerList& renderSurfaceLayerList, LayerList& layerList, - LayerSorter* layerSorter, int maxTextureSize, float deviceScaleFactor, IntRect& drawableContentRectOfSubtree) -{ - // This function computes the new matrix transformations recursively for this - // layer and all its descendants. It also computes the appropriate render surfaces. - // Some important points to remember: - // - // 0. Here, transforms are notated in Matrix x Vector order, and in words we describe what - // the transform does from left to right. - // - // 1. In our terminology, the "layer origin" refers to the top-left corner of a layer, and the - // positive Y-axis points downwards. This interpretation is valid because the orthographic - // projection applied at draw time flips the Y axis appropriately. - // - // 2. The anchor point, when given as a FloatPoint object, is specified in "unit layer space", - // where the bounds of the layer map to [0, 1]. However, as a WebTransformationMatrix object, - // the transform to the anchor point is specified in "layer space", where the bounds - // of the layer map to [bounds.width(), bounds.height()]. - // - // 3. Definition of various transforms used: - // M[parent] is the parent matrix, with respect to the nearest render surface, passed down recursively. - // M[root] is the full hierarchy, with respect to the root, passed down recursively. - // Tr[origin] is the translation matrix from the parent's origin to this layer's origin. - // Tr[origin2anchor] is the translation from the layer's origin to its anchor point - // Tr[origin2center] is the translation from the layer's origin to its center - // M[layer] is the layer's matrix (applied at the anchor point) - // M[sublayer] is the layer's sublayer transform (applied at the layer's center) - // S[layer2content] is the ratio of a layer's contentBounds() to its bounds(). - // - // Some composite transforms can help in understanding the sequence of transforms: - // compositeLayerTransform = Tr[origin2anchor] * M[layer] * Tr[origin2anchor].inverse() - // compositeSublayerTransform = Tr[origin2center] * M[sublayer] * Tr[origin2center].inverse() - // - // In words, the layer transform is applied about the anchor point, and the sublayer transform is - // applied about the center of the layer. - // - // 4. When a layer (or render surface) is drawn, it is drawn into a "target render surface". Therefore the draw - // transform does not necessarily transform from screen space to local layer space. Instead, the draw transform - // is the transform between the "target render surface space" and local layer space. Note that render surfaces, - // except for the root, also draw themselves into a different target render surface, and so their draw - // transform and origin transforms are also described with respect to the target. - // - // Using these definitions, then: - // - // The draw transform for the layer is: - // M[draw] = M[parent] * Tr[origin] * compositeLayerTransform * S[layer2content] - // = M[parent] * Tr[layer->position() + anchor] * M[layer] * Tr[anchor2origin] * S[layer2content] - // - // Interpreting the math left-to-right, this transforms from the layer's render surface to the origin of the layer in content space. - // - // The screen space transform is: - // M[screenspace] = M[root] * Tr[origin] * compositeLayerTransform * S[layer2content] - // = M[root] * Tr[layer->position() + anchor] * M[layer] * Tr[anchor2origin] * S[layer2content] - // - // Interpreting the math left-to-right, this transforms from the root render surface's content space to the local layer's origin in layer space. - // - // The transform hierarchy that is passed on to children (i.e. the child's parentMatrix) is: - // M[parent]_for_child = M[parent] * Tr[origin] * compositeLayerTransform * compositeSublayerTransform - // = M[parent] * Tr[layer->position() + anchor] * M[layer] * Tr[anchor2origin] * compositeSublayerTransform - // - // and a similar matrix for the full hierarchy with respect to the root. - // - // Finally, note that the final matrix used by the shader for the layer is P * M[draw] * S . This final product - // is computed in drawTexturedQuad(), where: - // P is the projection matrix - // S is the scale adjustment (to scale up a canonical quad to the layer's size) - // - // When a render surface has a replica layer, that layer's transform is used to draw a second copy of the surface. - // Transforms named here are relative to the surface, unless they specify they are relative to the replica layer. - // - // We will denote a scale by device scale S[deviceScale] - // - // The render surface draw transform to its target surface origin is: - // M[surfaceDraw] = M[owningLayer->Draw] - // - // The render surface origin transform to its the root (screen space) origin is: - // M[surface2root] = M[owningLayer->screenspace] * S[deviceScale].inverse() - // - // The replica draw transform to its target surface origin is: - // M[replicaDraw] = S[deviceScale] * M[surfaceDraw] * Tr[replica->position() + replica->anchor()] * Tr[replica] * Tr[origin2anchor].inverse() * S[contentsScale].inverse() - // - // The replica draw transform to the root (screen space) origin is: - // M[replica2root] = M[surface2root] * Tr[replica->position()] * Tr[replica] * Tr[origin2anchor].inverse() - // - - // If we early-exit anywhere in this function, the drawableContentRect of this subtree should be considered empty. - drawableContentRectOfSubtree = IntRect(); - - if (subtreeShouldBeSkipped(layer)) - return; - - IntRect clipRectForSubtree; - bool subtreeShouldBeClipped = false; - - float drawOpacity = layer->opacity(); - bool drawOpacityIsAnimating = layer->opacityIsAnimating(); - if (layer->parent() && layer->parent()->preserves3D()) { - drawOpacity *= layer->parent()->drawOpacity(); - drawOpacityIsAnimating |= layer->parent()->drawOpacityIsAnimating(); - } - - IntSize bounds = layer->bounds(); - FloatPoint anchorPoint = layer->anchorPoint(); - FloatPoint position = layer->position() - layer->scrollDelta(); - - WebTransformationMatrix layerLocalTransform; - // LT = M[impl transformation] - layerLocalTransform.multiply(layer->implTransform()); - // LT = M[impl transformation] * Tr[origin] * Tr[origin2anchor] - layerLocalTransform.translate3d(position.x() + anchorPoint.x() * bounds.width(), position.y() + anchorPoint.y() * bounds.height(), layer->anchorPointZ()); - // LT = M[impl transformation] * Tr[origin] * Tr[origin2anchor] * M[layer] - layerLocalTransform.multiply(layer->transform()); - // LT = S[impl transformation] * Tr[origin] * Tr[origin2anchor] * M[layer] * Tr[anchor2origin] - layerLocalTransform.translate3d(-anchorPoint.x() * bounds.width(), -anchorPoint.y() * bounds.height(), -layer->anchorPointZ()); - - WebTransformationMatrix combinedTransform = parentMatrix; - combinedTransform.multiply(layerLocalTransform); - - if (layer->fixedToContainerLayer()) { - // Special case: this layer is a composited fixed-position layer; we need to - // explicitly compensate for all ancestors' nonzero scrollDeltas to keep this layer - // fixed correctly. - combinedTransform = currentScrollCompensationMatrix * combinedTransform; - } - - // The drawTransform that gets computed below is effectively the layer's drawTransform, unless - // the layer itself creates a renderSurface. In that case, the renderSurface re-parents the transforms. - WebTransformationMatrix drawTransform = combinedTransform; - if (!layer->contentBounds().isEmpty() && !layer->bounds().isEmpty()) { - // M[draw] = M[parent] * LT * S[layer2content] - drawTransform.scaleNonUniform(layer->bounds().width() / static_cast(layer->contentBounds().width()), - layer->bounds().height() / static_cast(layer->contentBounds().height())); - } - - // layerScreenSpaceTransform represents the transform between root layer's "screen space" and local content space. - WebTransformationMatrix layerScreenSpaceTransform = fullHierarchyMatrix; - if (!layer->preserves3D()) - CCMathUtil::flattenTransformTo2d(layerScreenSpaceTransform); - layerScreenSpaceTransform.multiply(drawTransform); - layer->setScreenSpaceTransform(layerScreenSpaceTransform); - - bool animatingTransformToTarget = layer->transformIsAnimating(); - bool animatingTransformToScreen = animatingTransformToTarget; - if (layer->parent()) { - animatingTransformToTarget |= layer->parent()->drawTransformIsAnimating(); - animatingTransformToScreen |= layer->parent()->screenSpaceTransformIsAnimating(); - } - - FloatRect contentRect(FloatPoint(), layer->contentBounds()); - - // fullHierarchyMatrix is the matrix that transforms objects between screen space (except projection matrix) and the most recent RenderSurface's space. - // nextHierarchyMatrix will only change if this layer uses a new RenderSurface, otherwise remains the same. - WebTransformationMatrix nextHierarchyMatrix = fullHierarchyMatrix; - WebTransformationMatrix sublayerMatrix; - - if (subtreeShouldRenderToSeparateSurface(layer, isScaleOrTranslation(combinedTransform))) { - // Check back-face visibility before continuing with this surface and its subtree - if (!layer->doubleSided() && transformToParentIsKnown(layer) && isSurfaceBackFaceVisible(layer, combinedTransform)) - return; - - if (!layer->renderSurface()) - layer->createRenderSurface(); - - RenderSurfaceType* renderSurface = layer->renderSurface(); - renderSurface->clearLayerLists(); - - // The origin of the new surface is the upper left corner of the layer. - renderSurface->setDrawTransform(drawTransform); - WebTransformationMatrix layerDrawTransform; - layerDrawTransform.scale(deviceScaleFactor); - if (!layer->contentBounds().isEmpty() && !layer->bounds().isEmpty()) { - layerDrawTransform.scaleNonUniform(layer->bounds().width() / static_cast(layer->contentBounds().width()), - layer->bounds().height() / static_cast(layer->contentBounds().height())); - } - layer->setDrawTransform(layerDrawTransform); - - // The sublayer matrix transforms centered layer rects into target - // surface content space. - sublayerMatrix.makeIdentity(); - sublayerMatrix.scale(deviceScaleFactor); - - // The opacity value is moved from the layer to its surface, so that the entire subtree properly inherits opacity. - renderSurface->setDrawOpacity(drawOpacity); - renderSurface->setDrawOpacityIsAnimating(drawOpacityIsAnimating); - layer->setDrawOpacity(1); - layer->setDrawOpacityIsAnimating(false); - - renderSurface->setTargetSurfaceTransformsAreAnimating(animatingTransformToTarget); - renderSurface->setScreenSpaceTransformsAreAnimating(animatingTransformToScreen); - animatingTransformToTarget = false; - layer->setDrawTransformIsAnimating(animatingTransformToTarget); - layer->setScreenSpaceTransformIsAnimating(animatingTransformToScreen); - - // Update the aggregate hierarchy matrix to include the transform of the - // newly created RenderSurface. - nextHierarchyMatrix.multiply(renderSurface->drawTransform()); - - // The new renderSurface here will correctly clip the entire subtree. So, we do - // not need to continue propagating the clipping state further down the tree. This - // way, we can avoid transforming clipRects from ancestor target surface space to - // current target surface space that could cause more w < 0 headaches. - subtreeShouldBeClipped = false; - - if (layer->maskLayer()) { - layer->maskLayer()->setRenderTarget(layer); - layer->maskLayer()->setVisibleContentRect(IntRect(IntPoint(), layer->contentBounds())); - } - - if (layer->replicaLayer() && layer->replicaLayer()->maskLayer()) { - layer->replicaLayer()->maskLayer()->setRenderTarget(layer); - layer->replicaLayer()->maskLayer()->setVisibleContentRect(IntRect(IntPoint(), layer->contentBounds())); - } - - if (layer->filters().hasFilterThatMovesPixels()) - nearestAncestorThatMovesPixels = renderSurface; - - // The render surface clipRect is expressed in the space where this surface draws, i.e. the same space as clipRectFromAncestor. - if (ancestorClipsSubtree) - renderSurface->setClipRect(clipRectFromAncestor); - else - renderSurface->setClipRect(IntRect()); - - renderSurface->setNearestAncestorThatMovesPixels(nearestAncestorThatMovesPixels); - - renderSurfaceLayerList.push_back(layer); - } else { - layer->setDrawTransform(drawTransform); - layer->setDrawTransformIsAnimating(animatingTransformToTarget); - layer->setScreenSpaceTransformIsAnimating(animatingTransformToScreen); - sublayerMatrix = combinedTransform; - - layer->setDrawOpacity(drawOpacity); - layer->setDrawOpacityIsAnimating(drawOpacityIsAnimating); - - if (layer != rootLayer) { - ASSERT(layer->parent()); - layer->clearRenderSurface(); - - // Layers without renderSurfaces directly inherit the ancestor's clip status. - subtreeShouldBeClipped = ancestorClipsSubtree; - if (ancestorClipsSubtree) - clipRectForSubtree = clipRectFromAncestor; - - // Layers that are not their own renderTarget will render into the target of their nearest ancestor. - layer->setRenderTarget(layer->parent()->renderTarget()); - } else { - // FIXME: This root layer special case code should eventually go away. https://bugs.webkit.org/show_bug.cgi?id=92290 - ASSERT(!layer->parent()); - ASSERT(layer->renderSurface()); - ASSERT(ancestorClipsSubtree); - layer->renderSurface()->setClipRect(clipRectFromAncestor); - subtreeShouldBeClipped = false; - } - } - - IntRect rectInTargetSpace = enclosingIntRect(CCMathUtil::mapClippedRect(layer->drawTransform(), contentRect)); - - if (layerClipsSubtree(layer)) { - subtreeShouldBeClipped = true; - if (ancestorClipsSubtree && !layer->renderSurface()) { - clipRectForSubtree = clipRectFromAncestor; - clipRectForSubtree.intersect(rectInTargetSpace); - } else - clipRectForSubtree = rectInTargetSpace; - } - - // Flatten to 2D if the layer doesn't preserve 3D. - if (!layer->preserves3D()) - CCMathUtil::flattenTransformTo2d(sublayerMatrix); - - // Apply the sublayer transform at the center of the layer. - sublayerMatrix.translate(0.5 * bounds.width(), 0.5 * bounds.height()); - sublayerMatrix.multiply(layer->sublayerTransform()); - sublayerMatrix.translate(-0.5 * bounds.width(), -0.5 * bounds.height()); - - LayerList& descendants = (layer->renderSurface() ? layer->renderSurface()->layerList() : layerList); - - // Any layers that are appended after this point are in the layer's subtree and should be included in the sorting process. - unsigned sortingStartIndex = descendants.size(); - - if (!layerShouldBeSkipped(layer)) - descendants.push_back(layer); - - WebTransformationMatrix nextScrollCompensationMatrix = computeScrollCompensationMatrixForChildren(layer, parentMatrix, currentScrollCompensationMatrix);; - - IntRect accumulatedDrawableContentRectOfChildren; - for (size_t i = 0; i < layer->children().size(); ++i) { - LayerType* child = CCLayerTreeHostCommon::getChildAsRawPtr(layer->children(), i); - IntRect drawableContentRectOfChildSubtree; - calculateDrawTransformsInternal(child, rootLayer, sublayerMatrix, nextHierarchyMatrix, nextScrollCompensationMatrix, - clipRectForSubtree, subtreeShouldBeClipped, nearestAncestorThatMovesPixels, - renderSurfaceLayerList, descendants, layerSorter, maxTextureSize, deviceScaleFactor, drawableContentRectOfChildSubtree); - if (!drawableContentRectOfChildSubtree.isEmpty()) { - accumulatedDrawableContentRectOfChildren.unite(drawableContentRectOfChildSubtree); - if (child->renderSurface()) - descendants.push_back(child); - } - } - - // Compute the total drawableContentRect for this subtree (the rect is in targetSurface space) - IntRect localDrawableContentRectOfSubtree = accumulatedDrawableContentRectOfChildren; - if (layer->drawsContent()) - localDrawableContentRectOfSubtree.unite(rectInTargetSpace); - if (subtreeShouldBeClipped) - localDrawableContentRectOfSubtree.intersect(clipRectForSubtree); - - // Compute the layer's drawable content rect (the rect is in targetSurface space) - IntRect drawableContentRectOfLayer = rectInTargetSpace; - if (subtreeShouldBeClipped) - drawableContentRectOfLayer.intersect(clipRectForSubtree); - layer->setDrawableContentRect(drawableContentRectOfLayer); - - // Compute the layer's visible content rect (the rect is in content space) - IntRect visibleContentRectOfLayer = calculateVisibleContentRect(layer); - layer->setVisibleContentRect(visibleContentRectOfLayer); - - // Compute the remaining properties for the render surface, if the layer has one. - if (layer->renderSurface() && layer != rootLayer) { - RenderSurfaceType* renderSurface = layer->renderSurface(); - IntRect clippedContentRect = localDrawableContentRectOfSubtree; - - // Don't clip if the layer is reflected as the reflection shouldn't be - // clipped. If the layer is animating, then the surface's transform to - // its target is not known on the main thread, and we should not use it - // to clip. - if (!layer->replicaLayer() && transformToParentIsKnown(layer)) { - // Note, it is correct to use ancestorClipsSubtree here, because we are looking at this layer's renderSurface, not the layer itself. - if (ancestorClipsSubtree && !clippedContentRect.isEmpty()) { - IntRect surfaceClipRect = CCLayerTreeHostCommon::calculateVisibleRect(renderSurface->clipRect(), clippedContentRect, renderSurface->drawTransform()); - clippedContentRect.intersect(surfaceClipRect); - } - } - - // The RenderSurface backing texture cannot exceed the maximum supported - // texture size. - clippedContentRect.setWidth(std::min(clippedContentRect.width(), maxTextureSize)); - clippedContentRect.setHeight(std::min(clippedContentRect.height(), maxTextureSize)); - - if (clippedContentRect.isEmpty()) - renderSurface->clearLayerLists(); - - renderSurface->setContentRect(clippedContentRect); - renderSurface->setScreenSpaceTransform(layer->screenSpaceTransform()); - - if (layer->replicaLayer()) { - WebTransformationMatrix surfaceOriginToReplicaOriginTransform; - surfaceOriginToReplicaOriginTransform.scale(deviceScaleFactor); - surfaceOriginToReplicaOriginTransform.translate(layer->replicaLayer()->position().x() + layer->replicaLayer()->anchorPoint().x() * bounds.width(), - layer->replicaLayer()->position().y() + layer->replicaLayer()->anchorPoint().y() * bounds.height()); - surfaceOriginToReplicaOriginTransform.multiply(layer->replicaLayer()->transform()); - surfaceOriginToReplicaOriginTransform.translate(-layer->replicaLayer()->anchorPoint().x() * bounds.width(), -layer->replicaLayer()->anchorPoint().y() * bounds.height()); - surfaceOriginToReplicaOriginTransform.scale(1 / deviceScaleFactor); - - // Compute the replica's "originTransform" that maps from the replica's origin space to the target surface origin space. - WebTransformationMatrix replicaOriginTransform = layer->renderSurface()->drawTransform() * surfaceOriginToReplicaOriginTransform; - renderSurface->setReplicaDrawTransform(replicaOriginTransform); - - // Compute the replica's "screenSpaceTransform" that maps from the replica's origin space to the screen's origin space. - WebTransformationMatrix replicaScreenSpaceTransform = layer->renderSurface()->screenSpaceTransform() * surfaceOriginToReplicaOriginTransform; - renderSurface->setReplicaScreenSpaceTransform(replicaScreenSpaceTransform); - } - - // If a render surface has no layer list, then it and none of its children needed to get drawn. - if (!layer->renderSurface()->layerList().size()) { - // FIXME: Originally we asserted that this layer was already at the end of the - // list, and only needed to remove that layer. For now, we remove the - // entire subtree of surfaces to fix a crash bug. The root cause is - // https://bugs.webkit.org/show_bug.cgi?id=74147 and we should be able - // to put the original assert after fixing that. - while (renderSurfaceLayerList.back() != layer) { - renderSurfaceLayerList.back()->clearRenderSurface(); - renderSurfaceLayerList.pop_back(); - } - ASSERT(renderSurfaceLayerList.back() == layer); - renderSurfaceLayerList.pop_back(); - layer->clearRenderSurface(); - return; - } - } - - // If neither this layer nor any of its children were added, early out. - if (sortingStartIndex == descendants.size()) - return; - - // If preserves-3d then sort all the descendants in 3D so that they can be - // drawn from back to front. If the preserves-3d property is also set on the parent then - // skip the sorting as the parent will sort all the descendants anyway. - if (descendants.size() && layer->preserves3D() && (!layer->parent() || !layer->parent()->preserves3D())) - sortLayers(descendants.begin() + sortingStartIndex, descendants.end(), layerSorter); - - if (layer->renderSurface()) - drawableContentRectOfSubtree = enclosingIntRect(layer->renderSurface()->drawableContentRect()); - else - drawableContentRectOfSubtree = localDrawableContentRectOfSubtree; - - if (layer->hasContributingDelegatedRenderPasses()) - layer->renderTarget()->renderSurface()->addContributingDelegatedRenderPassLayer(layer); -} - -void CCLayerTreeHostCommon::calculateDrawTransforms(LayerChromium* rootLayer, const IntSize& deviceViewportSize, float deviceScaleFactor, int maxTextureSize, std::vector >& renderSurfaceLayerList) -{ - IntRect totalDrawableContentRect; - WebTransformationMatrix identityMatrix; - WebTransformationMatrix deviceScaleTransform; - deviceScaleTransform.scale(deviceScaleFactor); - - setupRootLayerAndSurfaceForRecursion > >(rootLayer, renderSurfaceLayerList, deviceViewportSize); - - cc::calculateDrawTransformsInternal >, RenderSurfaceChromium, void>(rootLayer, rootLayer, deviceScaleTransform, identityMatrix, identityMatrix, - rootLayer->renderSurface()->contentRect(), true, 0, renderSurfaceLayerList, - rootLayer->renderSurface()->layerList(), 0, maxTextureSize, deviceScaleFactor, totalDrawableContentRect); -} - -void CCLayerTreeHostCommon::calculateDrawTransforms(CCLayerImpl* rootLayer, const IntSize& deviceViewportSize, float deviceScaleFactor, CCLayerSorter* layerSorter, int maxTextureSize, std::vector& renderSurfaceLayerList) -{ - IntRect totalDrawableContentRect; - WebTransformationMatrix identityMatrix; - WebTransformationMatrix deviceScaleTransform; - deviceScaleTransform.scale(deviceScaleFactor); - - setupRootLayerAndSurfaceForRecursion >(rootLayer, renderSurfaceLayerList, deviceViewportSize); - - cc::calculateDrawTransformsInternal, CCRenderSurface, CCLayerSorter>(rootLayer, rootLayer, deviceScaleTransform, identityMatrix, identityMatrix, - rootLayer->renderSurface()->contentRect(), true, 0, renderSurfaceLayerList, - rootLayer->renderSurface()->layerList(), layerSorter, maxTextureSize, deviceScaleFactor, totalDrawableContentRect); -} - -static bool pointHitsRect(const IntPoint& viewportPoint, const WebTransformationMatrix& localSpaceToScreenSpaceTransform, FloatRect localSpaceRect) -{ - // If the transform is not invertible, then assume that this point doesn't hit this rect. - if (!localSpaceToScreenSpaceTransform.isInvertible()) - return false; - - // Transform the hit test point from screen space to the local space of the given rect. - bool clipped = false; - FloatPoint hitTestPointInLocalSpace = CCMathUtil::projectPoint(localSpaceToScreenSpaceTransform.inverse(), FloatPoint(viewportPoint), clipped); - - // If projectPoint could not project to a valid value, then we assume that this point doesn't hit this rect. - if (clipped) - return false; - - return localSpaceRect.contains(hitTestPointInLocalSpace); -} - -static bool pointIsClippedBySurfaceOrClipRect(const IntPoint& viewportPoint, CCLayerImpl* layer) -{ - CCLayerImpl* currentLayer = layer; - - // Walk up the layer tree and hit-test any renderSurfaces and any layer clipRects that are active. - while (currentLayer) { - if (currentLayer->renderSurface() && !pointHitsRect(viewportPoint, currentLayer->renderSurface()->screenSpaceTransform(), currentLayer->renderSurface()->contentRect())) - return true; - - // Note that drawableContentRects are actually in targetSurface space, so the transform we - // have to provide is the target surface's screenSpaceTransform. - CCLayerImpl* renderTarget = currentLayer->renderTarget(); - if (layerClipsSubtree(currentLayer) && !pointHitsRect(viewportPoint, renderTarget->renderSurface()->screenSpaceTransform(), currentLayer->drawableContentRect())) - return true; - - currentLayer = currentLayer->parent(); - } - - // If we have finished walking all ancestors without having already exited, then the point is not clipped by any ancestors. - return false; -} - -CCLayerImpl* CCLayerTreeHostCommon::findLayerThatIsHitByPoint(const IntPoint& viewportPoint, std::vector& renderSurfaceLayerList) -{ - CCLayerImpl* foundLayer = 0; - - typedef CCLayerIterator, CCRenderSurface, CCLayerIteratorActions::FrontToBack> CCLayerIteratorType; - CCLayerIteratorType end = CCLayerIteratorType::end(&renderSurfaceLayerList); - - for (CCLayerIteratorType it = CCLayerIteratorType::begin(&renderSurfaceLayerList); it != end; ++it) { - // We don't want to consider renderSurfaces for hit testing. - if (!it.representsItself()) - continue; - - CCLayerImpl* currentLayer = (*it); - - FloatRect contentRect(FloatPoint::zero(), currentLayer->contentBounds()); - if (!pointHitsRect(viewportPoint, currentLayer->screenSpaceTransform(), contentRect)) - continue; - - // At this point, we think the point does hit the layer, but we need to walk up - // the parents to ensure that the layer was not clipped in such a way that the - // hit point actually should not hit the layer. - if (pointIsClippedBySurfaceOrClipRect(viewportPoint, currentLayer)) - continue; - - foundLayer = currentLayer; - break; - } - - // This can potentially return 0, which means the viewportPoint did not successfully hit test any layers, not even the root layer. - return foundLayer; -} - -} // namespace cc diff --git a/cc/CCLayerTreeHostCommon.h b/cc/CCLayerTreeHostCommon.h index 01dc41e..4fcd6b0 100644 --- a/cc/CCLayerTreeHostCommon.h +++ b/cc/CCLayerTreeHostCommon.h @@ -1,96 +1,6 @@ -// Copyright 2011 The Chromium Authors. All rights reserved. +// Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CCLayerTreeHostCommon_h -#define CCLayerTreeHostCommon_h - -#include "base/memory/ref_counted.h" -#include "cc/scoped_ptr_vector.h" -#include "IntRect.h" -#include "IntSize.h" -#include -#include - -namespace cc { - -class CCLayerImpl; -class CCLayerSorter; -class LayerChromium; - -class CCLayerTreeHostCommon { -public: - static IntRect calculateVisibleRect(const IntRect& targetSurfaceRect, const IntRect& layerBoundRect, const WebKit::WebTransformationMatrix&); - - static void calculateDrawTransforms(LayerChromium* rootLayer, const IntSize& deviceViewportSize, float deviceScaleFactor, int maxTextureSize, std::vector >& renderSurfaceLayerList); - static void calculateDrawTransforms(CCLayerImpl* rootLayer, const IntSize& deviceViewportSize, float deviceScaleFactor, CCLayerSorter*, int maxTextureSize, std::vector& renderSurfaceLayerList); - - // Performs hit testing for a given renderSurfaceLayerList. - static CCLayerImpl* findLayerThatIsHitByPoint(const IntPoint& viewportPoint, std::vector& renderSurfaceLayerList); - - template static bool renderSurfaceContributesToTarget(LayerType*, int targetSurfaceLayerID); - - // Returns a layer with the given id if one exists in the subtree starting - // from the given root layer (including mask and replica layers). - template static LayerType* findLayerInSubtree(LayerType* rootLayer, int layerId); - - static LayerChromium* getChildAsRawPtr(const std::vector >& children, size_t index) - { - return children[index].get(); - } - - static CCLayerImpl* getChildAsRawPtr(const ScopedPtrVector& children, size_t index) - { - return children[index]; - } - - struct ScrollUpdateInfo { - int layerId; - IntSize scrollDelta; - }; -}; - -struct CCScrollAndScaleSet { - CCScrollAndScaleSet(); - ~CCScrollAndScaleSet(); - - Vector scrolls; - float pageScaleDelta; -}; - -template -bool CCLayerTreeHostCommon::renderSurfaceContributesToTarget(LayerType* layer, int targetSurfaceLayerID) -{ - // A layer will either contribute its own content, or its render surface's content, to - // the target surface. The layer contributes its surface's content when both the - // following are true: - // (1) The layer actually has a renderSurface, and - // (2) The layer's renderSurface is not the same as the targetSurface. - // - // Otherwise, the layer just contributes itself to the target surface. - - return layer->renderSurface() && layer->id() != targetSurfaceLayerID; -} - -template -LayerType* CCLayerTreeHostCommon::findLayerInSubtree(LayerType* rootLayer, int layerId) -{ - if (rootLayer->id() == layerId) - return rootLayer; - - if (rootLayer->maskLayer() && rootLayer->maskLayer()->id() == layerId) - return rootLayer->maskLayer(); - - if (rootLayer->replicaLayer() && rootLayer->replicaLayer()->id() == layerId) - return rootLayer->replicaLayer(); - - for (size_t i = 0; i < rootLayer->children().size(); ++i) { - if (LayerType* found = findLayerInSubtree(getChildAsRawPtr(rootLayer->children(), i), layerId)) - return found; - } - return 0; -} - -} // namespace cc - -#endif +// Temporary forwarding header +#include "cc/layer_tree_host_common.h" diff --git a/cc/CCLayerTreeHostImpl.cpp b/cc/CCLayerTreeHostImpl.cpp deleted file mode 100644 index bc50697..0000000 --- a/cc/CCLayerTreeHostImpl.cpp +++ /dev/null @@ -1,1462 +0,0 @@ -// Copyright 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "config.h" - -#include "CCLayerTreeHostImpl.h" - -#include "base/basictypes.h" -#include "CCAppendQuadsData.h" -#include "CCDamageTracker.h" -#include "CCDebugRectHistory.h" -#include "CCDelayBasedTimeSource.h" -#include "CCFontAtlas.h" -#include "CCFrameRateCounter.h" -#include "CCHeadsUpDisplayLayerImpl.h" -#include "CCLayerIterator.h" -#include "CCLayerTreeHost.h" -#include "CCLayerTreeHostCommon.h" -#include "CCMathUtil.h" -#include "CCOverdrawMetrics.h" -#include "CCPageScaleAnimation.h" -#include "CCPrioritizedTextureManager.h" -#include "CCRenderPassDrawQuad.h" -#include "CCRendererGL.h" -#include "CCRendererSoftware.h" -#include "CCRenderingStats.h" -#include "CCScrollbarAnimationController.h" -#include "CCScrollbarLayerImpl.h" -#include "CCSettings.h" -#include "CCSingleThreadProxy.h" -#include "TextureUploader.h" -#include "TraceEvent.h" -#include -#include - -using WebKit::WebTransformationMatrix; - -namespace { - -void didVisibilityChange(cc::CCLayerTreeHostImpl* id, bool visible) -{ - if (visible) { - TRACE_EVENT_ASYNC_BEGIN1("webkit", "CCLayerTreeHostImpl::setVisible", id, "CCLayerTreeHostImpl", id); - return; - } - - TRACE_EVENT_ASYNC_END0("webkit", "CCLayerTreeHostImpl::setVisible", id); -} - -} // namespace - -namespace cc { - -CCPinchZoomViewport::CCPinchZoomViewport() - : m_pageScaleFactor(1) - , m_pageScaleDelta(1) - , m_sentPageScaleDelta(1) - , m_minPageScaleFactor(0) - , m_maxPageScaleFactor(0) -{ -} - -float CCPinchZoomViewport::totalPageScaleFactor() const -{ - return m_pageScaleFactor * m_pageScaleDelta; -} - -void CCPinchZoomViewport::setPageScaleDelta(float delta) -{ - // Clamp to the current min/max limits. - float totalPageScaleFactor = m_pageScaleFactor * delta; - if (m_minPageScaleFactor && totalPageScaleFactor < m_minPageScaleFactor) - delta = m_minPageScaleFactor / m_pageScaleFactor; - else if (m_maxPageScaleFactor && totalPageScaleFactor > m_maxPageScaleFactor) - delta = m_maxPageScaleFactor / m_pageScaleFactor; - - if (delta == m_pageScaleDelta) - return; - - m_pageScaleDelta = delta; -} - -bool CCPinchZoomViewport::setPageScaleFactorAndLimits(float pageScaleFactor, float minPageScaleFactor, float maxPageScaleFactor) -{ - ASSERT(pageScaleFactor); - - if (m_sentPageScaleDelta == 1 && pageScaleFactor == m_pageScaleFactor && minPageScaleFactor == m_minPageScaleFactor && maxPageScaleFactor == m_maxPageScaleFactor) - return false; - - m_minPageScaleFactor = minPageScaleFactor; - m_maxPageScaleFactor = maxPageScaleFactor; - - m_pageScaleFactor = pageScaleFactor; - return true; -} - -FloatRect CCPinchZoomViewport::bounds() const -{ - FloatSize scaledViewportSize = m_layoutViewportSize; - scaledViewportSize.scale(1 / totalPageScaleFactor()); - - FloatRect bounds(FloatPoint(0, 0), scaledViewportSize); - bounds.setLocation(m_pinchViewportScrollDelta); - - return bounds; -} - -FloatSize CCPinchZoomViewport::applyScroll(FloatSize& delta) -{ - FloatSize overflow; - FloatRect pinchedBounds = bounds(); - - pinchedBounds.move(delta); - if (pinchedBounds.x() < 0) { - overflow.setWidth(pinchedBounds.x()); - pinchedBounds.setX(0); - } - - if (pinchedBounds.y() < 0) { - overflow.setHeight(pinchedBounds.y()); - pinchedBounds.setY(0); - } - - if (pinchedBounds.maxX() > m_layoutViewportSize.width()) { - overflow.setWidth( - pinchedBounds.maxX() - m_layoutViewportSize.width()); - pinchedBounds.move( - m_layoutViewportSize.width() - pinchedBounds.maxX(), 0); - } - - if (pinchedBounds.maxY() > m_layoutViewportSize.height()) { - overflow.setHeight( - pinchedBounds.maxY() - m_layoutViewportSize.height()); - pinchedBounds.move( - 0, m_layoutViewportSize.height() - pinchedBounds.maxY()); - } - m_pinchViewportScrollDelta = pinchedBounds.location(); - - return overflow; -} - -WebTransformationMatrix CCPinchZoomViewport::implTransform() const -{ - WebTransformationMatrix transform; - transform.scale(m_pageScaleDelta); - - // If the pinch state is applied in the impl, then push it to the - // impl transform, otherwise the scale is handled by WebCore. - if (CCSettings::pageScalePinchZoomEnabled()) { - transform.scale(m_pageScaleFactor); - transform.translate(-m_pinchViewportScrollDelta.x(), - -m_pinchViewportScrollDelta.y()); - } - - return transform; -} - -class CCLayerTreeHostImplTimeSourceAdapter : public CCTimeSourceClient { -public: - static PassOwnPtr create(CCLayerTreeHostImpl* layerTreeHostImpl, PassRefPtr timeSource) - { - return adoptPtr(new CCLayerTreeHostImplTimeSourceAdapter(layerTreeHostImpl, timeSource)); - } - virtual ~CCLayerTreeHostImplTimeSourceAdapter() - { - m_timeSource->setClient(0); - m_timeSource->setActive(false); - } - - virtual void onTimerTick() OVERRIDE - { - // FIXME: We require that animate be called on the impl thread. This - // avoids asserts in single threaded mode. Ideally background ticking - // would be handled by the proxy/scheduler and this could be removed. - DebugScopedSetImplThread impl; - - m_layerTreeHostImpl->animate(monotonicallyIncreasingTime(), currentTime()); - } - - void setActive(bool active) - { - if (active != m_timeSource->active()) - m_timeSource->setActive(active); - } - -private: - CCLayerTreeHostImplTimeSourceAdapter(CCLayerTreeHostImpl* layerTreeHostImpl, PassRefPtr timeSource) - : m_layerTreeHostImpl(layerTreeHostImpl) - , m_timeSource(timeSource) - { - m_timeSource->setClient(this); - } - - CCLayerTreeHostImpl* m_layerTreeHostImpl; - RefPtr m_timeSource; - - DISALLOW_COPY_AND_ASSIGN(CCLayerTreeHostImplTimeSourceAdapter); -}; - -CCLayerTreeHostImpl::FrameData::FrameData() -{ -} - -CCLayerTreeHostImpl::FrameData::~FrameData() -{ -} - -scoped_ptr CCLayerTreeHostImpl::create(const CCLayerTreeSettings& settings, CCLayerTreeHostImplClient* client) -{ - return make_scoped_ptr(new CCLayerTreeHostImpl(settings, client)); -} - -CCLayerTreeHostImpl::CCLayerTreeHostImpl(const CCLayerTreeSettings& settings, CCLayerTreeHostImplClient* client) - : m_client(client) - , m_sourceFrameNumber(-1) - , m_rootScrollLayerImpl(0) - , m_currentlyScrollingLayerImpl(0) - , m_hudLayerImpl(0) - , m_scrollingLayerIdFromPreviousTree(-1) - , m_scrollDeltaIsInScreenSpace(false) - , m_settings(settings) - , m_deviceScaleFactor(1) - , m_visible(true) - , m_contentsTexturesPurged(false) - , m_memoryAllocationLimitBytes(CCPrioritizedTextureManager::defaultMemoryAllocationLimit()) - , m_backgroundColor(0) - , m_hasTransparentBackground(false) - , m_needsAnimateLayers(false) - , m_pinchGestureActive(false) - , m_fpsCounter(CCFrameRateCounter::create()) - , m_debugRectHistory(CCDebugRectHistory::create()) - , m_numImplThreadScrolls(0) - , m_numMainThreadScrolls(0) -{ - ASSERT(CCProxy::isImplThread()); - didVisibilityChange(this, m_visible); -} - -CCLayerTreeHostImpl::~CCLayerTreeHostImpl() -{ - ASSERT(CCProxy::isImplThread()); - TRACE_EVENT0("cc", "CCLayerTreeHostImpl::~CCLayerTreeHostImpl()"); - - if (m_rootLayerImpl) - clearRenderSurfaces(); -} - -void CCLayerTreeHostImpl::beginCommit() -{ -} - -void CCLayerTreeHostImpl::commitComplete() -{ - TRACE_EVENT0("cc", "CCLayerTreeHostImpl::commitComplete"); - // Recompute max scroll position; must be after layer content bounds are - // updated. - updateMaxScrollPosition(); -} - -bool CCLayerTreeHostImpl::canDraw() -{ - // Note: If you are changing this function or any other function that might - // affect the result of canDraw, make sure to call m_client->onCanDrawStateChanged - // in the proper places and update the notifyIfCanDrawChanged test. - - if (!m_rootLayerImpl) { - TRACE_EVENT_INSTANT0("cc", "CCLayerTreeHostImpl::canDraw no root layer"); - return false; - } - if (deviceViewportSize().isEmpty()) { - TRACE_EVENT_INSTANT0("cc", "CCLayerTreeHostImpl::canDraw empty viewport"); - return false; - } - if (!m_renderer) { - TRACE_EVENT_INSTANT0("cc", "CCLayerTreeHostImpl::canDraw no renderer"); - return false; - } - if (m_contentsTexturesPurged) { - TRACE_EVENT_INSTANT0("cc", "CCLayerTreeHostImpl::canDraw contents textures purged"); - return false; - } - return true; -} - -CCGraphicsContext* CCLayerTreeHostImpl::context() const -{ - return m_context.get(); -} - -void CCLayerTreeHostImpl::animate(double monotonicTime, double wallClockTime) -{ - animatePageScale(monotonicTime); - animateLayers(monotonicTime, wallClockTime); - animateScrollbars(monotonicTime); -} - -void CCLayerTreeHostImpl::startPageScaleAnimation(const IntSize& targetPosition, bool anchorPoint, float pageScale, double startTime, double duration) -{ - if (!m_rootScrollLayerImpl) - return; - - IntSize scrollTotal = flooredIntSize(m_rootScrollLayerImpl->scrollPosition() + m_rootScrollLayerImpl->scrollDelta()); - scrollTotal.scale(m_pinchZoomViewport.pageScaleDelta()); - float scaleTotal = m_pinchZoomViewport.totalPageScaleFactor(); - IntSize scaledContentSize = contentSize(); - scaledContentSize.scale(m_pinchZoomViewport.pageScaleDelta()); - - m_pageScaleAnimation = CCPageScaleAnimation::create(scrollTotal, scaleTotal, m_deviceViewportSize, scaledContentSize, startTime); - - if (anchorPoint) { - IntSize windowAnchor(targetPosition); - windowAnchor.scale(scaleTotal / pageScale); - windowAnchor -= scrollTotal; - m_pageScaleAnimation->zoomWithAnchor(windowAnchor, pageScale, duration); - } else - m_pageScaleAnimation->zoomTo(targetPosition, pageScale, duration); - - m_client->setNeedsRedrawOnImplThread(); - m_client->setNeedsCommitOnImplThread(); -} - -void CCLayerTreeHostImpl::scheduleAnimation() -{ - m_client->setNeedsRedrawOnImplThread(); -} - -void CCLayerTreeHostImpl::trackDamageForAllSurfaces(CCLayerImpl* rootDrawLayer, const CCLayerList& renderSurfaceLayerList) -{ - // For now, we use damage tracking to compute a global scissor. To do this, we must - // compute all damage tracking before drawing anything, so that we know the root - // damage rect. The root damage rect is then used to scissor each surface. - - for (int surfaceIndex = renderSurfaceLayerList.size() - 1; surfaceIndex >= 0 ; --surfaceIndex) { - CCLayerImpl* renderSurfaceLayer = renderSurfaceLayerList[surfaceIndex]; - CCRenderSurface* renderSurface = renderSurfaceLayer->renderSurface(); - ASSERT(renderSurface); - renderSurface->damageTracker()->updateDamageTrackingState(renderSurface->layerList(), renderSurfaceLayer->id(), renderSurface->surfacePropertyChangedOnlyFromDescendant(), renderSurface->contentRect(), renderSurfaceLayer->maskLayer(), renderSurfaceLayer->filters()); - } -} - -void CCLayerTreeHostImpl::updateRootScrollLayerImplTransform() -{ - if (m_rootScrollLayerImpl) { - m_rootScrollLayerImpl->setImplTransform(implTransform()); - } -} - -void CCLayerTreeHostImpl::calculateRenderSurfaceLayerList(CCLayerList& renderSurfaceLayerList) -{ - ASSERT(renderSurfaceLayerList.empty()); - ASSERT(m_rootLayerImpl); - ASSERT(m_renderer); // For maxTextureSize. - - { - updateRootScrollLayerImplTransform(); - - TRACE_EVENT0("cc", "CCLayerTreeHostImpl::calcDrawEtc"); - CCLayerTreeHostCommon::calculateDrawTransforms(m_rootLayerImpl.get(), deviceViewportSize(), m_deviceScaleFactor, &m_layerSorter, rendererCapabilities().maxTextureSize, renderSurfaceLayerList); - - trackDamageForAllSurfaces(m_rootLayerImpl.get(), renderSurfaceLayerList); - } -} - -void CCLayerTreeHostImpl::FrameData::appendRenderPass(scoped_ptr renderPass) -{ - CCRenderPass* pass = renderPass.get(); - renderPasses.push_back(pass); - renderPassesById.set(pass->id(), renderPass.Pass()); -} - -bool CCLayerTreeHostImpl::calculateRenderPasses(FrameData& frame) -{ - ASSERT(frame.renderPasses.empty()); - - calculateRenderSurfaceLayerList(*frame.renderSurfaceLayerList); - - TRACE_EVENT1("cc", "CCLayerTreeHostImpl::calculateRenderPasses", "renderSurfaceLayerList.size()", static_cast(frame.renderSurfaceLayerList->size())); - - // Create the render passes in dependency order. - for (int surfaceIndex = frame.renderSurfaceLayerList->size() - 1; surfaceIndex >= 0 ; --surfaceIndex) { - CCLayerImpl* renderSurfaceLayer = (*frame.renderSurfaceLayerList)[surfaceIndex]; - renderSurfaceLayer->renderSurface()->appendRenderPasses(frame); - } - - bool recordMetricsForFrame = true; // FIXME: In the future, disable this when about:tracing is off. - CCOcclusionTrackerImpl occlusionTracker(m_rootLayerImpl->renderSurface()->contentRect(), recordMetricsForFrame); - occlusionTracker.setMinimumTrackingSize(m_settings.minimumOcclusionTrackingSize); - - if (settings().showOccludingRects) - occlusionTracker.setOccludingScreenSpaceRectsContainer(&frame.occludingScreenSpaceRects); - - // Add quads to the Render passes in FrontToBack order to allow for testing occlusion and performing culling during the tree walk. - typedef CCLayerIterator, CCRenderSurface, CCLayerIteratorActions::FrontToBack> CCLayerIteratorType; - - // Typically when we are missing a texture and use a checkerboard quad, we still draw the frame. However when the layer being - // checkerboarded is moving due to an impl-animation, we drop the frame to avoid flashing due to the texture suddenly appearing - // in the future. - bool drawFrame = true; - - CCLayerIteratorType end = CCLayerIteratorType::end(frame.renderSurfaceLayerList); - for (CCLayerIteratorType it = CCLayerIteratorType::begin(frame.renderSurfaceLayerList); it != end; ++it) { - CCRenderPass::Id targetRenderPassId = it.targetRenderSurfaceLayer()->renderSurface()->renderPassId(); - CCRenderPass* targetRenderPass = frame.renderPassesById.get(targetRenderPassId); - - occlusionTracker.enterLayer(it); - - CCAppendQuadsData appendQuadsData(targetRenderPass->id()); - - if (it.representsContributingRenderSurface()) { - CCRenderPass::Id contributingRenderPassId = it->renderSurface()->renderPassId(); - CCRenderPass* contributingRenderPass = frame.renderPassesById.get(contributingRenderPassId); - targetRenderPass->appendQuadsForRenderSurfaceLayer(*it, contributingRenderPass, &occlusionTracker, appendQuadsData); - } else if (it.representsItself() && !it->visibleContentRect().isEmpty()) { - bool hasOcclusionFromOutsideTargetSurface; - if (occlusionTracker.occluded(*it, it->visibleContentRect(), &hasOcclusionFromOutsideTargetSurface)) - appendQuadsData.hadOcclusionFromOutsideTargetSurface |= hasOcclusionFromOutsideTargetSurface; - else { - it->willDraw(m_resourceProvider.get()); - frame.willDrawLayers.push_back(*it); - - if (it->hasContributingDelegatedRenderPasses()) { - CCRenderPass::Id contributingRenderPassId = it->firstContributingRenderPassId(); - while (frame.renderPassesById.contains(contributingRenderPassId)) { - CCRenderPass* renderPass = frame.renderPassesById.get(contributingRenderPassId); - - CCAppendQuadsData appendQuadsData(renderPass->id()); - renderPass->appendQuadsForLayer(*it, &occlusionTracker, appendQuadsData); - - contributingRenderPassId = it->nextContributingRenderPassId(contributingRenderPassId); - } - } - - targetRenderPass->appendQuadsForLayer(*it, &occlusionTracker, appendQuadsData); - } - } - - if (appendQuadsData.hadOcclusionFromOutsideTargetSurface) - targetRenderPass->setHasOcclusionFromOutsideTargetSurface(true); - - if (appendQuadsData.hadMissingTiles) { - bool layerHasAnimatingTransform = it->screenSpaceTransformIsAnimating() || it->drawTransformIsAnimating(); - if (layerHasAnimatingTransform || CCSettings::jankInsteadOfCheckerboard()) - drawFrame = false; - } - - occlusionTracker.leaveLayer(it); - } - -#if !ASSERT_DISABLED - for (size_t i = 0; i < frame.renderPasses.size(); ++i) { - for (size_t j = 0; j < frame.renderPasses[i]->quadList().size(); ++j) - ASSERT(frame.renderPasses[i]->quadList()[j]->sharedQuadStateId() >= 0); - ASSERT(frame.renderPassesById.contains(frame.renderPasses[i]->id())); - } -#endif - - if (!m_hasTransparentBackground) { - frame.renderPasses.back()->setHasTransparentBackground(false); - frame.renderPasses.back()->appendQuadsToFillScreen(m_rootLayerImpl.get(), m_backgroundColor, occlusionTracker); - } - - if (drawFrame) - occlusionTracker.overdrawMetrics().recordMetrics(this); - - removeRenderPasses(CullRenderPassesWithNoQuads(), frame); - m_renderer->decideRenderPassAllocationsForFrame(frame.renderPasses); - removeRenderPasses(CullRenderPassesWithCachedTextures(*m_renderer), frame); - - return drawFrame; -} - -void CCLayerTreeHostImpl::animateLayersRecursive(CCLayerImpl* current, double monotonicTime, double wallClockTime, CCAnimationEventsVector* events, bool& didAnimate, bool& needsAnimateLayers) -{ - bool subtreeNeedsAnimateLayers = false; - - CCLayerAnimationController* currentController = current->layerAnimationController(); - - bool hadActiveAnimation = currentController->hasActiveAnimation(); - currentController->animate(monotonicTime, events); - bool startedAnimation = events->size() > 0; - - // We animated if we either ticked a running animation, or started a new animation. - if (hadActiveAnimation || startedAnimation) - didAnimate = true; - - // If the current controller still has an active animation, we must continue animating layers. - if (currentController->hasActiveAnimation()) - subtreeNeedsAnimateLayers = true; - - for (size_t i = 0; i < current->children().size(); ++i) { - bool childNeedsAnimateLayers = false; - animateLayersRecursive(current->children()[i], monotonicTime, wallClockTime, events, didAnimate, childNeedsAnimateLayers); - if (childNeedsAnimateLayers) - subtreeNeedsAnimateLayers = true; - } - - needsAnimateLayers = subtreeNeedsAnimateLayers; -} - -void CCLayerTreeHostImpl::setBackgroundTickingEnabled(bool enabled) -{ - // Lazily create the timeSource adapter so that we can vary the interval for testing. - if (!m_timeSourceClientAdapter) - m_timeSourceClientAdapter = CCLayerTreeHostImplTimeSourceAdapter::create(this, CCDelayBasedTimeSource::create(lowFrequencyAnimationInterval(), CCProxy::currentThread())); - - m_timeSourceClientAdapter->setActive(enabled); -} - -IntSize CCLayerTreeHostImpl::contentSize() const -{ - // TODO(aelias): Hardcoding the first child here is weird. Think of - // a cleaner way to get the contentBounds on the Impl side. - if (!m_rootScrollLayerImpl || m_rootScrollLayerImpl->children().isEmpty()) - return IntSize(); - return m_rootScrollLayerImpl->children()[0]->contentBounds(); -} - -static inline CCRenderPass* findRenderPassById(CCRenderPass::Id renderPassId, const CCLayerTreeHostImpl::FrameData& frame) -{ - CCRenderPassIdHashMap::const_iterator it = frame.renderPassesById.find(renderPassId); - ASSERT(it != frame.renderPassesById.end()); - return it->second; -} - -static void removeRenderPassesRecursive(CCRenderPass::Id removeRenderPassId, CCLayerTreeHostImpl::FrameData& frame) -{ - CCRenderPass* removeRenderPass = findRenderPassById(removeRenderPassId, frame); - CCRenderPassList& renderPasses = frame.renderPasses; - CCRenderPassList::iterator toRemove = std::find(renderPasses.begin(), renderPasses.end(), removeRenderPass); - - // The pass was already removed by another quad - probably the original, and we are the replica. - if (toRemove == renderPasses.end()) - return; - - const CCRenderPass* removedPass = *toRemove; - frame.renderPasses.erase(toRemove); - - // Now follow up for all RenderPass quads and remove their RenderPasses recursively. - const CCQuadList& quadList = removedPass->quadList(); - CCQuadList::constBackToFrontIterator quadListIterator = quadList.backToFrontBegin(); - for (; quadListIterator != quadList.backToFrontEnd(); ++quadListIterator) { - CCDrawQuad* currentQuad = (*quadListIterator); - if (currentQuad->material() != CCDrawQuad::RenderPass) - continue; - - CCRenderPass::Id nextRemoveRenderPassId = CCRenderPassDrawQuad::materialCast(currentQuad)->renderPassId(); - removeRenderPassesRecursive(nextRemoveRenderPassId, frame); - } -} - -bool CCLayerTreeHostImpl::CullRenderPassesWithCachedTextures::shouldRemoveRenderPass(const CCRenderPassDrawQuad& quad, const FrameData&) const -{ - return quad.contentsChangedSinceLastFrame().isEmpty() && m_renderer.haveCachedResourcesForRenderPassId(quad.renderPassId()); -} - -bool CCLayerTreeHostImpl::CullRenderPassesWithNoQuads::shouldRemoveRenderPass(const CCRenderPassDrawQuad& quad, const FrameData& frame) const -{ - const CCRenderPass* renderPass = findRenderPassById(quad.renderPassId(), frame); - const CCRenderPassList& renderPasses = frame.renderPasses; - CCRenderPassList::const_iterator foundPass = std::find(renderPasses.begin(), renderPasses.end(), renderPass); - - bool renderPassAlreadyRemoved = foundPass == renderPasses.end(); - if (renderPassAlreadyRemoved) - return false; - - // If any quad or RenderPass draws into this RenderPass, then keep it. - const CCQuadList& quadList = (*foundPass)->quadList(); - for (CCQuadList::constBackToFrontIterator quadListIterator = quadList.backToFrontBegin(); quadListIterator != quadList.backToFrontEnd(); ++quadListIterator) { - CCDrawQuad* currentQuad = *quadListIterator; - - if (currentQuad->material() != CCDrawQuad::RenderPass) - return false; - - const CCRenderPass* contributingPass = findRenderPassById(CCRenderPassDrawQuad::materialCast(currentQuad)->renderPassId(), frame); - CCRenderPassList::const_iterator foundContributingPass = std::find(renderPasses.begin(), renderPasses.end(), contributingPass); - if (foundContributingPass != renderPasses.end()) - return false; - } - return true; -} - -// Defined for linking tests. -template void CCLayerTreeHostImpl::removeRenderPasses(CullRenderPassesWithCachedTextures, FrameData&); -template void CCLayerTreeHostImpl::removeRenderPasses(CullRenderPassesWithNoQuads, FrameData&); - -// static -template -void CCLayerTreeHostImpl::removeRenderPasses(RenderPassCuller culler, FrameData& frame) -{ - for (size_t it = culler.renderPassListBegin(frame.renderPasses); it != culler.renderPassListEnd(frame.renderPasses); it = culler.renderPassListNext(it)) { - const CCRenderPass* currentPass = frame.renderPasses[it]; - const CCQuadList& quadList = currentPass->quadList(); - CCQuadList::constBackToFrontIterator quadListIterator = quadList.backToFrontBegin(); - - for (; quadListIterator != quadList.backToFrontEnd(); ++quadListIterator) { - CCDrawQuad* currentQuad = *quadListIterator; - - if (currentQuad->material() != CCDrawQuad::RenderPass) - continue; - - CCRenderPassDrawQuad* renderPassQuad = static_cast(currentQuad); - if (!culler.shouldRemoveRenderPass(*renderPassQuad, frame)) - continue; - - // We are changing the vector in the middle of iteration. Because we - // delete render passes that draw into the current pass, we are - // guaranteed that any data from the iterator to the end will not - // change. So, capture the iterator position from the end of the - // list, and restore it after the change. - int positionFromEnd = frame.renderPasses.size() - it; - removeRenderPassesRecursive(renderPassQuad->renderPassId(), frame); - it = frame.renderPasses.size() - positionFromEnd; - ASSERT(it >= 0); - } - } -} - -bool CCLayerTreeHostImpl::prepareToDraw(FrameData& frame) -{ - TRACE_EVENT0("cc", "CCLayerTreeHostImpl::prepareToDraw"); - ASSERT(canDraw()); - - frame.renderSurfaceLayerList = &m_renderSurfaceLayerList; - frame.renderPasses.clear(); - frame.renderPassesById.clear(); - frame.renderSurfaceLayerList->clear(); - frame.willDrawLayers.clear(); - - if (!calculateRenderPasses(frame)) - return false; - - // If we return true, then we expect drawLayers() to be called before this function is called again. - return true; -} - -void CCLayerTreeHostImpl::releaseContentsTextures() -{ - if (m_contentsTexturesPurged) - return; - m_client->releaseContentsTexturesOnImplThread(); - setContentsTexturesPurged(); - m_client->setNeedsCommitOnImplThread(); - m_client->onCanDrawStateChanged(canDraw()); -} - -void CCLayerTreeHostImpl::setMemoryAllocationLimitBytes(size_t bytes) -{ - if (m_memoryAllocationLimitBytes == bytes) - return; - m_memoryAllocationLimitBytes = bytes; - - ASSERT(bytes); - m_client->setNeedsCommitOnImplThread(); -} - -void CCLayerTreeHostImpl::onVSyncParametersChanged(double monotonicTimebase, double intervalInSeconds) -{ - m_client->onVSyncParametersChanged(monotonicTimebase, intervalInSeconds); -} - -void CCLayerTreeHostImpl::drawLayers(const FrameData& frame) -{ - TRACE_EVENT0("cc", "CCLayerTreeHostImpl::drawLayers"); - ASSERT(canDraw()); - ASSERT(!frame.renderPasses.empty()); - - // FIXME: use the frame begin time from the overall compositor scheduler. - // This value is currently inaccessible because it is up in Chromium's - // RenderWidget. - m_fpsCounter->markBeginningOfFrame(currentTime()); - - if (m_settings.showDebugRects()) - m_debugRectHistory->saveDebugRectsForCurrentFrame(m_rootLayerImpl.get(), *frame.renderSurfaceLayerList, frame.occludingScreenSpaceRects, settings()); - - // Because the contents of the HUD depend on everything else in the frame, the contents - // of its texture are updated as the last thing before the frame is drawn. - if (m_hudLayerImpl) - m_hudLayerImpl->updateHudTexture(m_resourceProvider.get()); - - m_renderer->drawFrame(frame.renderPasses, frame.renderPassesById); - - // Once a RenderPass has been drawn, its damage should be cleared in - // case the RenderPass will be reused next frame. - for (unsigned int i = 0; i < frame.renderPasses.size(); i++) - frame.renderPasses[i]->setDamageRect(FloatRect()); - - // The next frame should start by assuming nothing has changed, and changes are noted as they occur. - for (unsigned int i = 0; i < frame.renderSurfaceLayerList->size(); i++) - (*frame.renderSurfaceLayerList)[i]->renderSurface()->damageTracker()->didDrawDamagedArea(); - m_rootLayerImpl->resetAllChangeTrackingForSubtree(); -} - -void CCLayerTreeHostImpl::didDrawAllLayers(const FrameData& frame) -{ - for (size_t i = 0; i < frame.willDrawLayers.size(); ++i) - frame.willDrawLayers[i]->didDraw(m_resourceProvider.get()); - - // Once all layers have been drawn, pending texture uploads should no - // longer block future uploads. - m_resourceProvider->textureUploader()->markPendingUploadsAsNonBlocking(); -} - -void CCLayerTreeHostImpl::finishAllRendering() -{ - if (m_renderer) - m_renderer->finish(); -} - -bool CCLayerTreeHostImpl::isContextLost() -{ - return m_renderer && m_renderer->isContextLost(); -} - -const RendererCapabilities& CCLayerTreeHostImpl::rendererCapabilities() const -{ - return m_renderer->capabilities(); -} - -bool CCLayerTreeHostImpl::swapBuffers() -{ - ASSERT(m_renderer); - - m_fpsCounter->markEndOfFrame(); - return m_renderer->swapBuffers(); -} - -const IntSize& CCLayerTreeHostImpl::deviceViewportSize() const -{ - return m_deviceViewportSize; -} - -const CCLayerTreeSettings& CCLayerTreeHostImpl::settings() const -{ - return m_settings; -} - -void CCLayerTreeHostImpl::didLoseContext() -{ - m_client->didLoseContextOnImplThread(); -} - -void CCLayerTreeHostImpl::onSwapBuffersComplete() -{ - m_client->onSwapBuffersCompleteOnImplThread(); -} - -void CCLayerTreeHostImpl::readback(void* pixels, const IntRect& rect) -{ - ASSERT(m_renderer); - m_renderer->getFramebufferPixels(pixels, rect); -} - -static CCLayerImpl* findRootScrollLayer(CCLayerImpl* layer) -{ - if (!layer) - return 0; - - if (layer->scrollable()) - return layer; - - for (size_t i = 0; i < layer->children().size(); ++i) { - CCLayerImpl* found = findRootScrollLayer(layer->children()[i]); - if (found) - return found; - } - - return 0; -} - -// Content layers can be either directly scrollable or contained in an outer -// scrolling layer which applies the scroll transform. Given a content layer, -// this function returns the associated scroll layer if any. -static CCLayerImpl* findScrollLayerForContentLayer(CCLayerImpl* layerImpl) -{ - if (!layerImpl) - return 0; - - if (layerImpl->scrollable()) - return layerImpl; - - if (layerImpl->drawsContent() && layerImpl->parent() && layerImpl->parent()->scrollable()) - return layerImpl->parent(); - - return 0; -} - -void CCLayerTreeHostImpl::setRootLayer(scoped_ptr layer) -{ - m_rootLayerImpl = layer.Pass(); - m_rootScrollLayerImpl = findRootScrollLayer(m_rootLayerImpl.get()); - m_currentlyScrollingLayerImpl = 0; - - if (m_rootLayerImpl && m_scrollingLayerIdFromPreviousTree != -1) - m_currentlyScrollingLayerImpl = CCLayerTreeHostCommon::findLayerInSubtree(m_rootLayerImpl.get(), m_scrollingLayerIdFromPreviousTree); - - m_scrollingLayerIdFromPreviousTree = -1; - - m_client->onCanDrawStateChanged(canDraw()); -} - -scoped_ptr CCLayerTreeHostImpl::detachLayerTree() -{ - // Clear all data structures that have direct references to the layer tree. - m_scrollingLayerIdFromPreviousTree = m_currentlyScrollingLayerImpl ? m_currentlyScrollingLayerImpl->id() : -1; - m_currentlyScrollingLayerImpl = 0; - m_renderSurfaceLayerList.clear(); - - return m_rootLayerImpl.Pass(); -} - -void CCLayerTreeHostImpl::setVisible(bool visible) -{ - ASSERT(CCProxy::isImplThread()); - - if (m_visible == visible) - return; - m_visible = visible; - didVisibilityChange(this, m_visible); - - if (!m_renderer) - return; - - m_renderer->setVisible(visible); - - setBackgroundTickingEnabled(!m_visible && m_needsAnimateLayers); -} - -bool CCLayerTreeHostImpl::initializeRenderer(scoped_ptr context) -{ - // Since we will create a new resource provider, we cannot continue to use - // the old resources (i.e. renderSurfaces and texture IDs). Clear them - // before we destroy the old resource provider. - if (m_rootLayerImpl) { - clearRenderSurfaces(); - sendDidLoseContextRecursive(m_rootLayerImpl.get()); - } - // Note: order is important here. - m_renderer.clear(); - m_resourceProvider.clear(); - m_context.reset(); - - if (!context->bindToClient(this)) - return false; - - OwnPtr resourceProvider = CCResourceProvider::create(context.get()); - if (!resourceProvider) - return false; - - if (context->context3D()) - m_renderer = CCRendererGL::create(this, resourceProvider.get()); - else if (context->softwareDevice()) - m_renderer = CCRendererSoftware::create(this, resourceProvider.get(), context->softwareDevice()); - if (!m_renderer) - return false; - - m_resourceProvider = resourceProvider.release(); - m_context = context.Pass(); - - if (!m_visible) - m_renderer->setVisible(m_visible); - - m_client->onCanDrawStateChanged(canDraw()); - - return true; -} - -void CCLayerTreeHostImpl::setContentsTexturesPurged() -{ - m_contentsTexturesPurged = true; - m_client->onCanDrawStateChanged(canDraw()); -} - -void CCLayerTreeHostImpl::resetContentsTexturesPurged() -{ - m_contentsTexturesPurged = false; - m_client->onCanDrawStateChanged(canDraw()); -} - -void CCLayerTreeHostImpl::setViewportSize(const IntSize& layoutViewportSize, const IntSize& deviceViewportSize) -{ - if (layoutViewportSize == m_layoutViewportSize && deviceViewportSize == m_deviceViewportSize) - return; - - m_layoutViewportSize = layoutViewportSize; - m_deviceViewportSize = deviceViewportSize; - - m_pinchZoomViewport.setLayoutViewportSize(FloatSize(layoutViewportSize)); - - updateMaxScrollPosition(); - - if (m_renderer) - m_renderer->viewportChanged(); - - m_client->onCanDrawStateChanged(canDraw()); -} - -static void adjustScrollsForPageScaleChange(CCLayerImpl* layerImpl, float pageScaleChange) -{ - if (!layerImpl) - return; - - if (layerImpl->scrollable()) { - // We need to convert impl-side scroll deltas to pageScale space. - FloatSize scrollDelta = layerImpl->scrollDelta(); - scrollDelta.scale(pageScaleChange); - layerImpl->setScrollDelta(scrollDelta); - } - - for (size_t i = 0; i < layerImpl->children().size(); ++i) - adjustScrollsForPageScaleChange(layerImpl->children()[i], pageScaleChange); -} - -void CCLayerTreeHostImpl::setDeviceScaleFactor(float deviceScaleFactor) -{ - if (deviceScaleFactor == m_deviceScaleFactor) - return; - m_deviceScaleFactor = deviceScaleFactor; - - updateMaxScrollPosition(); -} - -float CCLayerTreeHostImpl::pageScaleFactor() const -{ - return m_pinchZoomViewport.pageScaleFactor(); -} - -void CCLayerTreeHostImpl::setPageScaleFactorAndLimits(float pageScaleFactor, float minPageScaleFactor, float maxPageScaleFactor) -{ - if (!pageScaleFactor) - return; - - float pageScaleChange = pageScaleFactor / m_pinchZoomViewport.pageScaleFactor(); - m_pinchZoomViewport.setPageScaleFactorAndLimits(pageScaleFactor, minPageScaleFactor, maxPageScaleFactor); - - if (!CCSettings::pageScalePinchZoomEnabled()) { - if (pageScaleChange != 1) - adjustScrollsForPageScaleChange(m_rootScrollLayerImpl, pageScaleChange); - } - - // Clamp delta to limits and refresh display matrix. - setPageScaleDelta(m_pinchZoomViewport.pageScaleDelta() / m_pinchZoomViewport.sentPageScaleDelta()); - m_pinchZoomViewport.setSentPageScaleDelta(1); -} - -void CCLayerTreeHostImpl::setPageScaleDelta(float delta) -{ - m_pinchZoomViewport.setPageScaleDelta(delta); - - updateMaxScrollPosition(); -} - -void CCLayerTreeHostImpl::updateMaxScrollPosition() -{ - if (!m_rootScrollLayerImpl || !m_rootScrollLayerImpl->children().size()) - return; - - FloatSize viewBounds = m_deviceViewportSize; - if (CCLayerImpl* clipLayer = m_rootScrollLayerImpl->parent()) { - // Compensate for non-overlay scrollbars. - if (clipLayer->masksToBounds()) { - viewBounds = clipLayer->bounds(); - viewBounds.scale(m_deviceScaleFactor); - } - } - - IntSize contentBounds = contentSize(); - if (CCSettings::pageScalePinchZoomEnabled()) { - // Pinch with pageScale scrolls entirely in layout space. contentSize - // returns the bounds including the page scale factor, so calculate the - // pre page-scale layout size here. - float pageScaleFactor = m_pinchZoomViewport.pageScaleFactor(); - contentBounds.setWidth(contentBounds.width() / pageScaleFactor); - contentBounds.setHeight(contentBounds.height() / pageScaleFactor); - } else { - viewBounds.scale(1 / m_pinchZoomViewport.pageScaleDelta()); - } - - IntSize maxScroll = contentBounds - expandedIntSize(viewBounds); - maxScroll.scale(1 / m_deviceScaleFactor); - - // The viewport may be larger than the contents in some cases, such as - // having a vertical scrollbar but no horizontal overflow. - maxScroll.clampNegativeToZero(); - - m_rootScrollLayerImpl->setMaxScrollPosition(maxScroll); -} - -void CCLayerTreeHostImpl::setNeedsRedraw() -{ - m_client->setNeedsRedrawOnImplThread(); -} - -bool CCLayerTreeHostImpl::ensureRenderSurfaceLayerList() -{ - if (!m_rootLayerImpl) - return false; - if (!m_renderer) - return false; - - // We need both a non-empty render surface layer list and a root render - // surface to be able to iterate over the visible layers. - if (m_renderSurfaceLayerList.size() && m_rootLayerImpl->renderSurface()) - return true; - - // If we are called after setRootLayer() but before prepareToDraw(), we need - // to recalculate the visible layers. This prevents being unable to scroll - // during part of a commit. - m_renderSurfaceLayerList.clear(); - calculateRenderSurfaceLayerList(m_renderSurfaceLayerList); - - return m_renderSurfaceLayerList.size(); -} - -CCInputHandlerClient::ScrollStatus CCLayerTreeHostImpl::scrollBegin(const IntPoint& viewportPoint, CCInputHandlerClient::ScrollInputType type) -{ - TRACE_EVENT0("cc", "CCLayerTreeHostImpl::scrollBegin"); - - ASSERT(!m_currentlyScrollingLayerImpl); - clearCurrentlyScrollingLayer(); - - if (!ensureRenderSurfaceLayerList()) - return ScrollIgnored; - - IntPoint deviceViewportPoint = viewportPoint; - deviceViewportPoint.scale(m_deviceScaleFactor, m_deviceScaleFactor); - - // First find out which layer was hit from the saved list of visible layers - // in the most recent frame. - CCLayerImpl* layerImpl = CCLayerTreeHostCommon::findLayerThatIsHitByPoint(viewportPoint, m_renderSurfaceLayerList); - - // Walk up the hierarchy and look for a scrollable layer. - CCLayerImpl* potentiallyScrollingLayerImpl = 0; - for (; layerImpl; layerImpl = layerImpl->parent()) { - // The content layer can also block attempts to scroll outside the main thread. - if (layerImpl->tryScroll(deviceViewportPoint, type) == ScrollOnMainThread) { - m_numMainThreadScrolls++; - return ScrollOnMainThread; - } - - CCLayerImpl* scrollLayerImpl = findScrollLayerForContentLayer(layerImpl); - if (!scrollLayerImpl) - continue; - - ScrollStatus status = scrollLayerImpl->tryScroll(viewportPoint, type); - - // If any layer wants to divert the scroll event to the main thread, abort. - if (status == ScrollOnMainThread) { - m_numMainThreadScrolls++; - return ScrollOnMainThread; - } - - if (status == ScrollStarted && !potentiallyScrollingLayerImpl) - potentiallyScrollingLayerImpl = scrollLayerImpl; - } - - if (potentiallyScrollingLayerImpl) { - m_currentlyScrollingLayerImpl = potentiallyScrollingLayerImpl; - // Gesture events need to be transformed from screen coordinates to local layer coordinates - // so that the scrolling contents exactly follow the user's finger. In contrast, wheel - // events are already in local layer coordinates so we can just apply them directly. - m_scrollDeltaIsInScreenSpace = (type == Gesture); - m_numImplThreadScrolls++; - return ScrollStarted; - } - return ScrollIgnored; -} - -static FloatSize scrollLayerWithScreenSpaceDelta(CCPinchZoomViewport* viewport, CCLayerImpl& layerImpl, const FloatPoint& screenSpacePoint, const FloatSize& screenSpaceDelta) -{ - // Layers with non-invertible screen space transforms should not have passed the scroll hit - // test in the first place. - ASSERT(layerImpl.screenSpaceTransform().isInvertible()); - WebTransformationMatrix inverseScreenSpaceTransform = layerImpl.screenSpaceTransform().inverse(); - - // First project the scroll start and end points to local layer space to find the scroll delta - // in layer coordinates. - bool startClipped, endClipped; - FloatPoint screenSpaceEndPoint = screenSpacePoint + screenSpaceDelta; - FloatPoint localStartPoint = CCMathUtil::projectPoint(inverseScreenSpaceTransform, screenSpacePoint, startClipped); - FloatPoint localEndPoint = CCMathUtil::projectPoint(inverseScreenSpaceTransform, screenSpaceEndPoint, endClipped); - - // In general scroll point coordinates should not get clipped. - ASSERT(!startClipped); - ASSERT(!endClipped); - if (startClipped || endClipped) - return FloatSize(); - - // Apply the scroll delta. - FloatSize previousDelta(layerImpl.scrollDelta()); - FloatSize unscrolled = layerImpl.scrollBy(localEndPoint - localStartPoint); - - if (viewport) - viewport->applyScroll(unscrolled); - - // Calculate the applied scroll delta in screen space coordinates. - FloatPoint actualLocalEndPoint = localStartPoint + layerImpl.scrollDelta() - previousDelta; - FloatPoint actualScreenSpaceEndPoint = CCMathUtil::mapPoint(layerImpl.screenSpaceTransform(), actualLocalEndPoint, endClipped); - ASSERT(!endClipped); - if (endClipped) - return FloatSize(); - return actualScreenSpaceEndPoint - screenSpacePoint; -} - -static FloatSize scrollLayerWithLocalDelta(CCLayerImpl& layerImpl, const FloatSize& localDelta) -{ - FloatSize previousDelta(layerImpl.scrollDelta()); - layerImpl.scrollBy(localDelta); - return layerImpl.scrollDelta() - previousDelta; -} - -void CCLayerTreeHostImpl::scrollBy(const IntPoint& viewportPoint, const IntSize& scrollDelta) -{ - TRACE_EVENT0("cc", "CCLayerTreeHostImpl::scrollBy"); - if (!m_currentlyScrollingLayerImpl) - return; - - FloatSize pendingDelta(scrollDelta); - - pendingDelta.scale(m_deviceScaleFactor); - - for (CCLayerImpl* layerImpl = m_currentlyScrollingLayerImpl; layerImpl; layerImpl = layerImpl->parent()) { - if (!layerImpl->scrollable()) - continue; - - CCPinchZoomViewport* viewport = layerImpl == m_rootScrollLayerImpl ? &m_pinchZoomViewport : 0; - FloatSize appliedDelta; - if (m_scrollDeltaIsInScreenSpace) - appliedDelta = scrollLayerWithScreenSpaceDelta(viewport, *layerImpl, viewportPoint, pendingDelta); - else - appliedDelta = scrollLayerWithLocalDelta(*layerImpl, pendingDelta); - - // If the layer wasn't able to move, try the next one in the hierarchy. - float moveThresholdSquared = 0.1f * 0.1f; - if (appliedDelta.diagonalLengthSquared() < moveThresholdSquared) - continue; - - // If the applied delta is within 45 degrees of the input delta, bail out to make it easier - // to scroll just one layer in one direction without affecting any of its parents. - float angleThreshold = 45; - if (CCMathUtil::smallestAngleBetweenVectors(appliedDelta, pendingDelta) < angleThreshold) { - pendingDelta = FloatSize(); - break; - } - - // Allow further movement only on an axis perpendicular to the direction in which the layer - // moved. - FloatSize perpendicularAxis(-appliedDelta.height(), appliedDelta.width()); - pendingDelta = CCMathUtil::projectVector(pendingDelta, perpendicularAxis); - - if (flooredIntSize(pendingDelta).isZero()) - break; - } - - if (!scrollDelta.isZero() && flooredIntSize(pendingDelta).isEmpty()) { - m_client->setNeedsCommitOnImplThread(); - m_client->setNeedsRedrawOnImplThread(); - } -} - -void CCLayerTreeHostImpl::clearCurrentlyScrollingLayer() -{ - m_currentlyScrollingLayerImpl = 0; - m_scrollingLayerIdFromPreviousTree = -1; -} - -void CCLayerTreeHostImpl::scrollEnd() -{ - clearCurrentlyScrollingLayer(); -} - -void CCLayerTreeHostImpl::pinchGestureBegin() -{ - m_pinchGestureActive = true; - m_previousPinchAnchor = IntPoint(); - - if (m_rootScrollLayerImpl && m_rootScrollLayerImpl->scrollbarAnimationController()) - m_rootScrollLayerImpl->scrollbarAnimationController()->didPinchGestureBegin(); -} - -void CCLayerTreeHostImpl::pinchGestureUpdate(float magnifyDelta, - const IntPoint& anchor) -{ - TRACE_EVENT0("cc", "CCLayerTreeHostImpl::pinchGestureUpdate"); - - if (!m_rootScrollLayerImpl) - return; - - if (m_previousPinchAnchor == IntPoint::zero()) - m_previousPinchAnchor = anchor; - - // Keep the center-of-pinch anchor specified by (x, y) in a stable - // position over the course of the magnify. - float pageScaleDelta = m_pinchZoomViewport.pageScaleDelta(); - FloatPoint previousScaleAnchor(m_previousPinchAnchor.x() / pageScaleDelta, - m_previousPinchAnchor.y() / pageScaleDelta); - setPageScaleDelta(pageScaleDelta * magnifyDelta); - pageScaleDelta = m_pinchZoomViewport.pageScaleDelta(); - FloatPoint newScaleAnchor(anchor.x() / pageScaleDelta, anchor.y() / pageScaleDelta); - FloatSize move = previousScaleAnchor - newScaleAnchor; - - m_previousPinchAnchor = anchor; - - if (CCSettings::pageScalePinchZoomEnabled()) { - // Compute the application of the delta with respect to the current page zoom of the page. - move.scale(1 / (m_pinchZoomViewport.pageScaleFactor() * m_deviceScaleFactor)); - } - - FloatSize scrollOverflow = CCSettings::pageScalePinchZoomEnabled() ? m_pinchZoomViewport.applyScroll(move) : move; - m_rootScrollLayerImpl->scrollBy(roundedIntSize(scrollOverflow)); - - if (m_rootScrollLayerImpl->scrollbarAnimationController()) - m_rootScrollLayerImpl->scrollbarAnimationController()->didPinchGestureUpdate(); - - m_client->setNeedsCommitOnImplThread(); - m_client->setNeedsRedrawOnImplThread(); -} - -void CCLayerTreeHostImpl::pinchGestureEnd() -{ - m_pinchGestureActive = false; - - if (m_rootScrollLayerImpl && m_rootScrollLayerImpl->scrollbarAnimationController()) - m_rootScrollLayerImpl->scrollbarAnimationController()->didPinchGestureEnd(); - - m_client->setNeedsCommitOnImplThread(); -} - -void CCLayerTreeHostImpl::computeDoubleTapZoomDeltas(CCScrollAndScaleSet* scrollInfo) -{ - float pageScale = m_pageScaleAnimation->finalPageScale(); - IntSize scrollOffset = m_pageScaleAnimation->finalScrollOffset(); - scrollOffset.scale(m_pinchZoomViewport.pageScaleFactor() / pageScale); - makeScrollAndScaleSet(scrollInfo, scrollOffset, pageScale); -} - -void CCLayerTreeHostImpl::computePinchZoomDeltas(CCScrollAndScaleSet* scrollInfo) -{ - if (!m_rootScrollLayerImpl) - return; - - // Only send fake scroll/zoom deltas if we're pinch zooming out by a - // significant amount. This also ensures only one fake delta set will be - // sent. - const float pinchZoomOutSensitivity = 0.95f; - if (m_pinchZoomViewport.pageScaleDelta() > pinchZoomOutSensitivity) - return; - - // Compute where the scroll offset/page scale would be if fully pinch-zoomed - // out from the anchor point. - IntSize scrollBegin = flooredIntSize(m_rootScrollLayerImpl->scrollPosition() + m_rootScrollLayerImpl->scrollDelta()); - scrollBegin.scale(m_pinchZoomViewport.pageScaleDelta()); - float scaleBegin = m_pinchZoomViewport.totalPageScaleFactor(); - float pageScaleDeltaToSend = m_pinchZoomViewport.minPageScaleFactor() / m_pinchZoomViewport.pageScaleFactor(); - FloatSize scaledContentsSize = contentSize(); - scaledContentsSize.scale(pageScaleDeltaToSend); - - FloatSize anchor = toSize(m_previousPinchAnchor); - FloatSize scrollEnd = scrollBegin + anchor; - scrollEnd.scale(m_pinchZoomViewport.minPageScaleFactor() / scaleBegin); - scrollEnd -= anchor; - scrollEnd = scrollEnd.shrunkTo(roundedIntSize(scaledContentsSize - m_deviceViewportSize)).expandedTo(FloatSize(0, 0)); - scrollEnd.scale(1 / pageScaleDeltaToSend); - scrollEnd.scale(m_deviceScaleFactor); - - makeScrollAndScaleSet(scrollInfo, roundedIntSize(scrollEnd), m_pinchZoomViewport.minPageScaleFactor()); -} - -void CCLayerTreeHostImpl::makeScrollAndScaleSet(CCScrollAndScaleSet* scrollInfo, const IntSize& scrollOffset, float pageScale) -{ - if (!m_rootScrollLayerImpl) - return; - - CCLayerTreeHostCommon::ScrollUpdateInfo scroll; - scroll.layerId = m_rootScrollLayerImpl->id(); - scroll.scrollDelta = scrollOffset - toSize(m_rootScrollLayerImpl->scrollPosition()); - scrollInfo->scrolls.append(scroll); - m_rootScrollLayerImpl->setSentScrollDelta(scroll.scrollDelta); - scrollInfo->pageScaleDelta = pageScale / m_pinchZoomViewport.pageScaleFactor(); - m_pinchZoomViewport.setSentPageScaleDelta(scrollInfo->pageScaleDelta); -} - -static void collectScrollDeltas(CCScrollAndScaleSet* scrollInfo, CCLayerImpl* layerImpl) -{ - if (!layerImpl) - return; - - if (!layerImpl->scrollDelta().isZero()) { - IntSize scrollDelta = flooredIntSize(layerImpl->scrollDelta()); - CCLayerTreeHostCommon::ScrollUpdateInfo scroll; - scroll.layerId = layerImpl->id(); - scroll.scrollDelta = scrollDelta; - scrollInfo->scrolls.append(scroll); - layerImpl->setSentScrollDelta(scrollDelta); - } - - for (size_t i = 0; i < layerImpl->children().size(); ++i) - collectScrollDeltas(scrollInfo, layerImpl->children()[i]); -} - -scoped_ptr CCLayerTreeHostImpl::processScrollDeltas() -{ - scoped_ptr scrollInfo(new CCScrollAndScaleSet()); - - if (m_pinchGestureActive || m_pageScaleAnimation) { - scrollInfo->pageScaleDelta = 1; - m_pinchZoomViewport.setSentPageScaleDelta(1); - // FIXME(aelias): Make these painting optimizations compatible with - // compositor-side scaling. - if (!CCSettings::pageScalePinchZoomEnabled()) { - if (m_pinchGestureActive) - computePinchZoomDeltas(scrollInfo.get()); - else if (m_pageScaleAnimation.get()) - computeDoubleTapZoomDeltas(scrollInfo.get()); - } - return scrollInfo.Pass(); - } - - collectScrollDeltas(scrollInfo.get(), m_rootLayerImpl.get()); - scrollInfo->pageScaleDelta = m_pinchZoomViewport.pageScaleDelta(); - m_pinchZoomViewport.setSentPageScaleDelta(scrollInfo->pageScaleDelta); - - return scrollInfo.Pass(); -} - -WebTransformationMatrix CCLayerTreeHostImpl::implTransform() const -{ - return m_pinchZoomViewport.implTransform(); -} - -void CCLayerTreeHostImpl::setFullRootLayerDamage() -{ - if (m_rootLayerImpl) { - CCRenderSurface* renderSurface = m_rootLayerImpl->renderSurface(); - if (renderSurface) - renderSurface->damageTracker()->forceFullDamageNextUpdate(); - } -} - -void CCLayerTreeHostImpl::animatePageScale(double monotonicTime) -{ - if (!m_pageScaleAnimation || !m_rootScrollLayerImpl) - return; - - IntSize scrollTotal = flooredIntSize(m_rootScrollLayerImpl->scrollPosition() + m_rootScrollLayerImpl->scrollDelta()); - - setPageScaleDelta(m_pageScaleAnimation->pageScaleAtTime(monotonicTime) / m_pinchZoomViewport.pageScaleFactor()); - IntSize nextScroll = m_pageScaleAnimation->scrollOffsetAtTime(monotonicTime); - nextScroll.scale(1 / m_pinchZoomViewport.pageScaleDelta()); - m_rootScrollLayerImpl->scrollBy(nextScroll - scrollTotal); - m_client->setNeedsRedrawOnImplThread(); - - if (m_pageScaleAnimation->isAnimationCompleteAtTime(monotonicTime)) { - m_pageScaleAnimation.clear(); - m_client->setNeedsCommitOnImplThread(); - } -} - -void CCLayerTreeHostImpl::animateLayers(double monotonicTime, double wallClockTime) -{ - if (!CCSettings::acceleratedAnimationEnabled() || !m_needsAnimateLayers || !m_rootLayerImpl) - return; - - TRACE_EVENT0("cc", "CCLayerTreeHostImpl::animateLayers"); - - scoped_ptr events(make_scoped_ptr(new CCAnimationEventsVector)); - - bool didAnimate = false; - animateLayersRecursive(m_rootLayerImpl.get(), monotonicTime, wallClockTime, events.get(), didAnimate, m_needsAnimateLayers); - - if (!events->empty()) - m_client->postAnimationEventsToMainThreadOnImplThread(events.Pass(), wallClockTime); - - if (didAnimate) - m_client->setNeedsRedrawOnImplThread(); - - setBackgroundTickingEnabled(!m_visible && m_needsAnimateLayers); -} - -base::TimeDelta CCLayerTreeHostImpl::lowFrequencyAnimationInterval() const -{ - return base::TimeDelta::FromSeconds(1); -} - -void CCLayerTreeHostImpl::sendDidLoseContextRecursive(CCLayerImpl* current) -{ - ASSERT(current); - current->didLoseContext(); - if (current->maskLayer()) - sendDidLoseContextRecursive(current->maskLayer()); - if (current->replicaLayer()) - sendDidLoseContextRecursive(current->replicaLayer()); - for (size_t i = 0; i < current->children().size(); ++i) - sendDidLoseContextRecursive(current->children()[i]); -} - -static void clearRenderSurfacesOnCCLayerImplRecursive(CCLayerImpl* current) -{ - ASSERT(current); - for (size_t i = 0; i < current->children().size(); ++i) - clearRenderSurfacesOnCCLayerImplRecursive(current->children()[i]); - current->clearRenderSurface(); -} - -void CCLayerTreeHostImpl::clearRenderSurfaces() -{ - clearRenderSurfacesOnCCLayerImplRecursive(m_rootLayerImpl.get()); - m_renderSurfaceLayerList.clear(); -} - -std::string CCLayerTreeHostImpl::layerTreeAsText() const -{ - std::string str; - if (m_rootLayerImpl) { - str = m_rootLayerImpl->layerTreeAsText(); - str += "RenderSurfaces:\n"; - dumpRenderSurfaces(&str, 1, m_rootLayerImpl.get()); - } - return str; -} - -void CCLayerTreeHostImpl::dumpRenderSurfaces(std::string* str, int indent, const CCLayerImpl* layer) const -{ - if (layer->renderSurface()) - layer->renderSurface()->dumpSurface(str, indent); - - for (size_t i = 0; i < layer->children().size(); ++i) - dumpRenderSurfaces(str, indent, layer->children()[i]); -} - -int CCLayerTreeHostImpl::sourceAnimationFrameNumber() const -{ - return fpsCounter()->currentFrameNumber(); -} - -void CCLayerTreeHostImpl::renderingStats(CCRenderingStats* stats) const -{ - stats->numFramesSentToScreen = fpsCounter()->currentFrameNumber(); - stats->droppedFrameCount = fpsCounter()->droppedFrameCount(); - stats->numImplThreadScrolls = m_numImplThreadScrolls; - stats->numMainThreadScrolls = m_numMainThreadScrolls; -} - -void CCLayerTreeHostImpl::animateScrollbars(double monotonicTime) -{ - animateScrollbarsRecursive(m_rootLayerImpl.get(), monotonicTime); -} - -void CCLayerTreeHostImpl::animateScrollbarsRecursive(CCLayerImpl* layer, double monotonicTime) -{ - if (!layer) - return; - - CCScrollbarAnimationController* scrollbarController = layer->scrollbarAnimationController(); - if (scrollbarController && scrollbarController->animate(monotonicTime)) - m_client->setNeedsRedrawOnImplThread(); - - for (size_t i = 0; i < layer->children().size(); ++i) - animateScrollbarsRecursive(layer->children()[i], monotonicTime); -} - -} // namespace cc diff --git a/cc/CCLayerTreeHostImpl.h b/cc/CCLayerTreeHostImpl.h index 297f619..714a528 100644 --- a/cc/CCLayerTreeHostImpl.h +++ b/cc/CCLayerTreeHostImpl.h @@ -1,356 +1,6 @@ -// Copyright 2011 The Chromium Authors. All rights reserved. +// Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CCLayerTreeHostImpl_h -#define CCLayerTreeHostImpl_h - -#include "base/basictypes.h" -#include "base/time.h" -#include "CCAnimationEvents.h" -#include "CCInputHandler.h" -#include "CCLayerSorter.h" -#include "CCRenderPass.h" -#include "CCRenderPassSink.h" -#include "CCRenderer.h" -#include "SkColor.h" -#include -#include -#include - -namespace cc { - -class CCCompletionEvent; -class CCDebugRectHistory; -class CCFrameRateCounter; -class CCHeadsUpDisplayLayerImpl; -class CCLayerImpl; -class CCLayerTreeHostImplTimeSourceAdapter; -class CCPageScaleAnimation; -class CCRenderPassDrawQuad; -class CCResourceProvider; -struct RendererCapabilities; -struct CCRenderingStats; - -// CCLayerTreeHost->CCProxy callback interface. -class CCLayerTreeHostImplClient { -public: - virtual void didLoseContextOnImplThread() = 0; - virtual void onSwapBuffersCompleteOnImplThread() = 0; - virtual void onVSyncParametersChanged(double monotonicTimebase, double intervalInSeconds) = 0; - virtual void onCanDrawStateChanged(bool canDraw) = 0; - virtual void setNeedsRedrawOnImplThread() = 0; - virtual void setNeedsCommitOnImplThread() = 0; - virtual void postAnimationEventsToMainThreadOnImplThread(scoped_ptr, double wallClockTime) = 0; - virtual void releaseContentsTexturesOnImplThread() = 0; -}; - -// CCPinchZoomViewport models the bounds and offset of the viewport that is used during a pinch-zoom operation. -// It tracks the layout-space dimensions of the viewport before any applied scale, and then tracks the layout-space -// coordinates of the viewport respecting the pinch settings. -class CCPinchZoomViewport { -public: - CCPinchZoomViewport(); - - float totalPageScaleFactor() const; - - void setPageScaleFactor(float factor) { m_pageScaleFactor = factor; } - float pageScaleFactor() const { return m_pageScaleFactor; } - - void setPageScaleDelta(float delta); - float pageScaleDelta() const { return m_pageScaleDelta; } - - float minPageScaleFactor() const { return m_minPageScaleFactor; } - float maxPageScaleFactor() const { return m_maxPageScaleFactor; } - - void setSentPageScaleDelta(float delta) { m_sentPageScaleDelta = delta; } - float sentPageScaleDelta() const { return m_sentPageScaleDelta; } - - // Returns true if the passed parameters were different from those previously - // cached. - bool setPageScaleFactorAndLimits(float pageScaleFactor, - float minPageScaleFactor, - float maxPageScaleFactor); - - // Returns the bounds and offset of the scaled and translated viewport to use for pinch-zoom. - FloatRect bounds() const; - const FloatPoint& scrollDelta() const { return m_pinchViewportScrollDelta; } - - void setLayoutViewportSize(const FloatSize& size) { m_layoutViewportSize = size; } - - // Apply the scroll offset in layout space to the offset of the pinch-zoom viewport. The viewport cannot be - // scrolled outside of the layout viewport bounds. Returns the component of the scroll that is un-applied due to - // this constraint. - FloatSize applyScroll(FloatSize&); - - WebKit::WebTransformationMatrix implTransform() const; - -private: - float m_pageScaleFactor; - float m_pageScaleDelta; - float m_sentPageScaleDelta; - float m_maxPageScaleFactor; - float m_minPageScaleFactor; - - FloatPoint m_pinchViewportScrollDelta; - FloatSize m_layoutViewportSize; -}; - -// CCLayerTreeHostImpl owns the CCLayerImpl tree as well as associated rendering state -class CCLayerTreeHostImpl : public CCInputHandlerClient, - public CCRendererClient, - public WebKit::WebCompositorOutputSurfaceClient { - typedef std::vector CCLayerList; - -public: - static scoped_ptr create(const CCLayerTreeSettings&, CCLayerTreeHostImplClient*); - virtual ~CCLayerTreeHostImpl(); - - // CCInputHandlerClient implementation - virtual CCInputHandlerClient::ScrollStatus scrollBegin(const IntPoint&, CCInputHandlerClient::ScrollInputType) OVERRIDE; - virtual void scrollBy(const IntPoint&, const IntSize&) OVERRIDE; - virtual void scrollEnd() OVERRIDE; - virtual void pinchGestureBegin() OVERRIDE; - virtual void pinchGestureUpdate(float, const IntPoint&) OVERRIDE; - virtual void pinchGestureEnd() OVERRIDE; - virtual void startPageScaleAnimation(const IntSize& targetPosition, bool anchorPoint, float pageScale, double startTime, double duration) OVERRIDE; - virtual void scheduleAnimation() OVERRIDE; - - struct FrameData : public CCRenderPassSink { - FrameData(); - ~FrameData(); - - Vector occludingScreenSpaceRects; - CCRenderPassList renderPasses; - CCRenderPassIdHashMap renderPassesById; - CCLayerList* renderSurfaceLayerList; - CCLayerList willDrawLayers; - - // CCRenderPassSink implementation. - virtual void appendRenderPass(scoped_ptr) OVERRIDE; - }; - - // Virtual for testing. - virtual void beginCommit(); - virtual void commitComplete(); - virtual void animate(double monotonicTime, double wallClockTime); - - // Returns false if problems occured preparing the frame, and we should try - // to avoid displaying the frame. If prepareToDraw is called, - // didDrawAllLayers must also be called, regardless of whether drawLayers is - // called between the two. - virtual bool prepareToDraw(FrameData&); - virtual void drawLayers(const FrameData&); - // Must be called if and only if prepareToDraw was called. - void didDrawAllLayers(const FrameData&); - - // CCRendererClient implementation - virtual const IntSize& deviceViewportSize() const OVERRIDE; - virtual const CCLayerTreeSettings& settings() const OVERRIDE; - virtual void didLoseContext() OVERRIDE; - virtual void onSwapBuffersComplete() OVERRIDE; - virtual void setFullRootLayerDamage() OVERRIDE; - virtual void releaseContentsTextures() OVERRIDE; - virtual void setMemoryAllocationLimitBytes(size_t) OVERRIDE; - - // WebCompositorOutputSurfaceClient implementation. - virtual void onVSyncParametersChanged(double monotonicTimebase, double intervalInSeconds) OVERRIDE; - - // Implementation - bool canDraw(); - CCGraphicsContext* context() const; - - std::string layerTreeAsText() const; - - void finishAllRendering(); - int sourceAnimationFrameNumber() const; - - bool initializeRenderer(scoped_ptr); - bool isContextLost(); - CCRenderer* renderer() { return m_renderer.get(); } - const RendererCapabilities& rendererCapabilities() const; - - bool swapBuffers(); - - void readback(void* pixels, const IntRect&); - - void setRootLayer(scoped_ptr); - CCLayerImpl* rootLayer() { return m_rootLayerImpl.get(); } - - void setHudLayer(CCHeadsUpDisplayLayerImpl* layerImpl) { m_hudLayerImpl = layerImpl; } - CCHeadsUpDisplayLayerImpl* hudLayer() { return m_hudLayerImpl; } - - // Release ownership of the current layer tree and replace it with an empty - // tree. Returns the root layer of the detached tree. - scoped_ptr detachLayerTree(); - - CCLayerImpl* rootScrollLayer() const { return m_rootScrollLayerImpl; } - - bool visible() const { return m_visible; } - void setVisible(bool); - - int sourceFrameNumber() const { return m_sourceFrameNumber; } - void setSourceFrameNumber(int frameNumber) { m_sourceFrameNumber = frameNumber; } - - bool contentsTexturesPurged() const { return m_contentsTexturesPurged; } - void setContentsTexturesPurged(); - void resetContentsTexturesPurged(); - size_t memoryAllocationLimitBytes() const { return m_memoryAllocationLimitBytes; } - - void setViewportSize(const IntSize& layoutViewportSize, const IntSize& deviceViewportSize); - const IntSize& layoutViewportSize() const { return m_layoutViewportSize; } - - float deviceScaleFactor() const { return m_deviceScaleFactor; } - void setDeviceScaleFactor(float); - - float pageScaleFactor() const; - void setPageScaleFactorAndLimits(float pageScaleFactor, float minPageScaleFactor, float maxPageScaleFactor); - - scoped_ptr processScrollDeltas(); - WebKit::WebTransformationMatrix implTransform() const; - - void startPageScaleAnimation(const IntSize& tragetPosition, bool useAnchor, float scale, double durationSec); - - SkColor backgroundColor() const { return m_backgroundColor; } - void setBackgroundColor(SkColor color) { m_backgroundColor = color; } - - bool hasTransparentBackground() const { return m_hasTransparentBackground; } - void setHasTransparentBackground(bool transparent) { m_hasTransparentBackground = transparent; } - - bool needsAnimateLayers() const { return m_needsAnimateLayers; } - void setNeedsAnimateLayers() { m_needsAnimateLayers = true; } - - void setNeedsRedraw(); - - void renderingStats(CCRenderingStats*) const; - - void updateRootScrollLayerImplTransform(); - - CCFrameRateCounter* fpsCounter() const { return m_fpsCounter.get(); } - CCDebugRectHistory* debugRectHistory() const { return m_debugRectHistory.get(); } - CCResourceProvider* resourceProvider() const { return m_resourceProvider.get(); } - - class CullRenderPassesWithCachedTextures { - public: - bool shouldRemoveRenderPass(const CCRenderPassDrawQuad&, const FrameData&) const; - - // Iterates from the root first, in order to remove the surfaces closest - // to the root with cached textures, and all surfaces that draw into - // them. - size_t renderPassListBegin(const CCRenderPassList& list) const { return list.size() - 1; } - size_t renderPassListEnd(const CCRenderPassList&) const { return 0 - 1; } - size_t renderPassListNext(size_t it) const { return it - 1; } - - CullRenderPassesWithCachedTextures(CCRenderer& renderer) : m_renderer(renderer) { } - private: - CCRenderer& m_renderer; - }; - - class CullRenderPassesWithNoQuads { - public: - bool shouldRemoveRenderPass(const CCRenderPassDrawQuad&, const FrameData&) const; - - // Iterates in draw order, so that when a surface is removed, and its - // target becomes empty, then its target can be removed also. - size_t renderPassListBegin(const CCRenderPassList&) const { return 0; } - size_t renderPassListEnd(const CCRenderPassList& list) const { return list.size(); } - size_t renderPassListNext(size_t it) const { return it + 1; } - }; - - template - static void removeRenderPasses(RenderPassCuller, FrameData&); - -protected: - CCLayerTreeHostImpl(const CCLayerTreeSettings&, CCLayerTreeHostImplClient*); - - void animatePageScale(double monotonicTime); - void animateScrollbars(double monotonicTime); - - // Exposed for testing. - void calculateRenderSurfaceLayerList(CCLayerList&); - - // Virtual for testing. - virtual void animateLayers(double monotonicTime, double wallClockTime); - - // Virtual for testing. - virtual base::TimeDelta lowFrequencyAnimationInterval() const; - - CCLayerTreeHostImplClient* m_client; - int m_sourceFrameNumber; - -private: - void computeDoubleTapZoomDeltas(CCScrollAndScaleSet* scrollInfo); - void computePinchZoomDeltas(CCScrollAndScaleSet* scrollInfo); - void makeScrollAndScaleSet(CCScrollAndScaleSet* scrollInfo, const IntSize& scrollOffset, float pageScale); - - void setPageScaleDelta(float); - void updateMaxScrollPosition(); - void trackDamageForAllSurfaces(CCLayerImpl* rootDrawLayer, const CCLayerList& renderSurfaceLayerList); - - // Returns false if the frame should not be displayed. This function should - // only be called from prepareToDraw, as didDrawAllLayers must be called - // if this helper function is called. - bool calculateRenderPasses(FrameData&); - void animateLayersRecursive(CCLayerImpl*, double monotonicTime, double wallClockTime, CCAnimationEventsVector*, bool& didAnimate, bool& needsAnimateLayers); - void setBackgroundTickingEnabled(bool); - IntSize contentSize() const; - - void sendDidLoseContextRecursive(CCLayerImpl*); - void clearRenderSurfaces(); - bool ensureRenderSurfaceLayerList(); - void clearCurrentlyScrollingLayer(); - - void animateScrollbarsRecursive(CCLayerImpl*, double monotonicTime); - - void dumpRenderSurfaces(std::string*, int indent, const CCLayerImpl*) const; - - scoped_ptr m_context; - OwnPtr m_resourceProvider; - OwnPtr m_renderer; - scoped_ptr m_rootLayerImpl; - CCLayerImpl* m_rootScrollLayerImpl; - CCLayerImpl* m_currentlyScrollingLayerImpl; - CCHeadsUpDisplayLayerImpl* m_hudLayerImpl; - int m_scrollingLayerIdFromPreviousTree; - bool m_scrollDeltaIsInScreenSpace; - CCLayerTreeSettings m_settings; - IntSize m_layoutViewportSize; - IntSize m_deviceViewportSize; - float m_deviceScaleFactor; - bool m_visible; - bool m_contentsTexturesPurged; - size_t m_memoryAllocationLimitBytes; - - SkColor m_backgroundColor; - bool m_hasTransparentBackground; - - // If this is true, it is necessary to traverse the layer tree ticking the animators. - bool m_needsAnimateLayers; - bool m_pinchGestureActive; - IntPoint m_previousPinchAnchor; - - OwnPtr m_pageScaleAnimation; - - // This is used for ticking animations slowly when hidden. - OwnPtr m_timeSourceClientAdapter; - - CCLayerSorter m_layerSorter; - - // List of visible layers for the most recently prepared frame. Used for - // rendering and input event hit testing. - CCLayerList m_renderSurfaceLayerList; - - CCPinchZoomViewport m_pinchZoomViewport; - - OwnPtr m_fpsCounter; - OwnPtr m_debugRectHistory; - - size_t m_numImplThreadScrolls; - size_t m_numMainThreadScrolls; - - DISALLOW_COPY_AND_ASSIGN(CCLayerTreeHostImpl); -}; - -}; - -#endif +// Temporary forwarding header +#include "cc/layer_tree_host_impl.h" diff --git a/cc/CCMathUtil.cpp b/cc/CCMathUtil.cpp deleted file mode 100644 index d90eb09..0000000 --- a/cc/CCMathUtil.cpp +++ /dev/null @@ -1,379 +0,0 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "config.h" - -#include "CCMathUtil.h" - -#include "FloatPoint.h" -#include "FloatQuad.h" -#include "IntRect.h" -#include - -using WebKit::WebTransformationMatrix; - -namespace cc { - -static HomogeneousCoordinate projectHomogeneousPoint(const WebTransformationMatrix& transform, const FloatPoint& p) -{ - // In this case, the layer we are trying to project onto is perpendicular to ray - // (point p and z-axis direction) that we are trying to project. This happens when the - // layer is rotated so that it is infinitesimally thin, or when it is co-planar with - // the camera origin -- i.e. when the layer is invisible anyway. - if (!transform.m33()) - return HomogeneousCoordinate(0, 0, 0, 1); - - double x = p.x(); - double y = p.y(); - double z = -(transform.m13() * x + transform.m23() * y + transform.m43()) / transform.m33(); - // implicit definition of w = 1; - - double outX = x * transform.m11() + y * transform.m21() + z * transform.m31() + transform.m41(); - double outY = x * transform.m12() + y * transform.m22() + z * transform.m32() + transform.m42(); - double outZ = x * transform.m13() + y * transform.m23() + z * transform.m33() + transform.m43(); - double outW = x * transform.m14() + y * transform.m24() + z * transform.m34() + transform.m44(); - - return HomogeneousCoordinate(outX, outY, outZ, outW); -} - -static HomogeneousCoordinate mapHomogeneousPoint(const WebTransformationMatrix& transform, const FloatPoint3D& p) -{ - double x = p.x(); - double y = p.y(); - double z = p.z(); - // implicit definition of w = 1; - - double outX = x * transform.m11() + y * transform.m21() + z * transform.m31() + transform.m41(); - double outY = x * transform.m12() + y * transform.m22() + z * transform.m32() + transform.m42(); - double outZ = x * transform.m13() + y * transform.m23() + z * transform.m33() + transform.m43(); - double outW = x * transform.m14() + y * transform.m24() + z * transform.m34() + transform.m44(); - - return HomogeneousCoordinate(outX, outY, outZ, outW); -} - -static HomogeneousCoordinate computeClippedPointForEdge(const HomogeneousCoordinate& h1, const HomogeneousCoordinate& h2) -{ - // Points h1 and h2 form a line in 4d, and any point on that line can be represented - // as an interpolation between h1 and h2: - // p = (1-t) h1 + (t) h2 - // - // We want to compute point p such that p.w == epsilon, where epsilon is a small - // non-zero number. (but the smaller the number is, the higher the risk of overflow) - // To do this, we solve for t in the following equation: - // p.w = epsilon = (1-t) * h1.w + (t) * h2.w - // - // Once paramter t is known, the rest of p can be computed via p = (1-t) h1 + (t) h2. - - // Technically this is a special case of the following assertion, but its a good idea to keep it an explicit sanity check here. - ASSERT(h2.w != h1.w); - // Exactly one of h1 or h2 (but not both) must be on the negative side of the w plane when this is called. - ASSERT(h1.shouldBeClipped() ^ h2.shouldBeClipped()); - - double w = 0.00001; // or any positive non-zero small epsilon - - double t = (w - h1.w) / (h2.w - h1.w); - - double x = (1-t) * h1.x + t * h2.x; - double y = (1-t) * h1.y + t * h2.y; - double z = (1-t) * h1.z + t * h2.z; - - return HomogeneousCoordinate(x, y, z, w); -} - -static inline void expandBoundsToIncludePoint(float& xmin, float& xmax, float& ymin, float& ymax, const FloatPoint& p) -{ - xmin = std::min(p.x(), xmin); - xmax = std::max(p.x(), xmax); - ymin = std::min(p.y(), ymin); - ymax = std::max(p.y(), ymax); -} - -static inline void addVertexToClippedQuad(const FloatPoint& newVertex, FloatPoint clippedQuad[8], int& numVerticesInClippedQuad) -{ - clippedQuad[numVerticesInClippedQuad] = newVertex; - numVerticesInClippedQuad++; -} - -IntRect CCMathUtil::mapClippedRect(const WebTransformationMatrix& transform, const IntRect& srcRect) -{ - return enclosingIntRect(mapClippedRect(transform, FloatRect(srcRect))); -} - -FloatRect CCMathUtil::mapClippedRect(const WebTransformationMatrix& transform, const FloatRect& srcRect) -{ - if (transform.isIdentityOrTranslation()) { - FloatRect mappedRect(srcRect); - mappedRect.move(static_cast(transform.m41()), static_cast(transform.m42())); - return mappedRect; - } - - // Apply the transform, but retain the result in homogeneous coordinates. - FloatQuad q = FloatQuad(FloatRect(srcRect)); - HomogeneousCoordinate h1 = mapHomogeneousPoint(transform, q.p1()); - HomogeneousCoordinate h2 = mapHomogeneousPoint(transform, q.p2()); - HomogeneousCoordinate h3 = mapHomogeneousPoint(transform, q.p3()); - HomogeneousCoordinate h4 = mapHomogeneousPoint(transform, q.p4()); - - return computeEnclosingClippedRect(h1, h2, h3, h4); -} - -FloatRect CCMathUtil::projectClippedRect(const WebTransformationMatrix& transform, const FloatRect& srcRect) -{ - // Perform the projection, but retain the result in homogeneous coordinates. - FloatQuad q = FloatQuad(FloatRect(srcRect)); - HomogeneousCoordinate h1 = projectHomogeneousPoint(transform, q.p1()); - HomogeneousCoordinate h2 = projectHomogeneousPoint(transform, q.p2()); - HomogeneousCoordinate h3 = projectHomogeneousPoint(transform, q.p3()); - HomogeneousCoordinate h4 = projectHomogeneousPoint(transform, q.p4()); - - return computeEnclosingClippedRect(h1, h2, h3, h4); -} - -void CCMathUtil::mapClippedQuad(const WebTransformationMatrix& transform, const FloatQuad& srcQuad, FloatPoint clippedQuad[8], int& numVerticesInClippedQuad) -{ - HomogeneousCoordinate h1 = mapHomogeneousPoint(transform, srcQuad.p1()); - HomogeneousCoordinate h2 = mapHomogeneousPoint(transform, srcQuad.p2()); - HomogeneousCoordinate h3 = mapHomogeneousPoint(transform, srcQuad.p3()); - HomogeneousCoordinate h4 = mapHomogeneousPoint(transform, srcQuad.p4()); - - // The order of adding the vertices to the array is chosen so that clockwise / counter-clockwise orientation is retained. - - numVerticesInClippedQuad = 0; - - if (!h1.shouldBeClipped()) - addVertexToClippedQuad(h1.cartesianPoint2d(), clippedQuad, numVerticesInClippedQuad); - - if (h1.shouldBeClipped() ^ h2.shouldBeClipped()) - addVertexToClippedQuad(computeClippedPointForEdge(h1, h2).cartesianPoint2d(), clippedQuad, numVerticesInClippedQuad); - - if (!h2.shouldBeClipped()) - addVertexToClippedQuad(h2.cartesianPoint2d(), clippedQuad, numVerticesInClippedQuad); - - if (h2.shouldBeClipped() ^ h3.shouldBeClipped()) - addVertexToClippedQuad(computeClippedPointForEdge(h2, h3).cartesianPoint2d(), clippedQuad, numVerticesInClippedQuad); - - if (!h3.shouldBeClipped()) - addVertexToClippedQuad(h3.cartesianPoint2d(), clippedQuad, numVerticesInClippedQuad); - - if (h3.shouldBeClipped() ^ h4.shouldBeClipped()) - addVertexToClippedQuad(computeClippedPointForEdge(h3, h4).cartesianPoint2d(), clippedQuad, numVerticesInClippedQuad); - - if (!h4.shouldBeClipped()) - addVertexToClippedQuad(h4.cartesianPoint2d(), clippedQuad, numVerticesInClippedQuad); - - if (h4.shouldBeClipped() ^ h1.shouldBeClipped()) - addVertexToClippedQuad(computeClippedPointForEdge(h4, h1).cartesianPoint2d(), clippedQuad, numVerticesInClippedQuad); - - ASSERT(numVerticesInClippedQuad <= 8); -} - -FloatRect CCMathUtil::computeEnclosingRectOfVertices(FloatPoint vertices[], int numVertices) -{ - if (numVertices < 2) - return FloatRect(); - - float xmin = std::numeric_limits::max(); - float xmax = -std::numeric_limits::max(); - float ymin = std::numeric_limits::max(); - float ymax = -std::numeric_limits::max(); - - for (int i = 0; i < numVertices; ++i) - expandBoundsToIncludePoint(xmin, xmax, ymin, ymax, vertices[i]); - - return FloatRect(FloatPoint(xmin, ymin), FloatSize(xmax - xmin, ymax - ymin)); -} - -FloatRect CCMathUtil::computeEnclosingClippedRect(const HomogeneousCoordinate& h1, const HomogeneousCoordinate& h2, const HomogeneousCoordinate& h3, const HomogeneousCoordinate& h4) -{ - // This function performs clipping as necessary and computes the enclosing 2d - // FloatRect of the vertices. Doing these two steps simultaneously allows us to avoid - // the overhead of storing an unknown number of clipped vertices. - - // If no vertices on the quad are clipped, then we can simply return the enclosing rect directly. - bool somethingClipped = h1.shouldBeClipped() || h2.shouldBeClipped() || h3.shouldBeClipped() || h4.shouldBeClipped(); - if (!somethingClipped) { - FloatQuad mappedQuad = FloatQuad(h1.cartesianPoint2d(), h2.cartesianPoint2d(), h3.cartesianPoint2d(), h4.cartesianPoint2d()); - return mappedQuad.boundingBox(); - } - - bool everythingClipped = h1.shouldBeClipped() && h2.shouldBeClipped() && h3.shouldBeClipped() && h4.shouldBeClipped(); - if (everythingClipped) - return FloatRect(); - - - float xmin = std::numeric_limits::max(); - float xmax = -std::numeric_limits::max(); - float ymin = std::numeric_limits::max(); - float ymax = -std::numeric_limits::max(); - - if (!h1.shouldBeClipped()) - expandBoundsToIncludePoint(xmin, xmax, ymin, ymax, h1.cartesianPoint2d()); - - if (h1.shouldBeClipped() ^ h2.shouldBeClipped()) - expandBoundsToIncludePoint(xmin, xmax, ymin, ymax, computeClippedPointForEdge(h1, h2).cartesianPoint2d()); - - if (!h2.shouldBeClipped()) - expandBoundsToIncludePoint(xmin, xmax, ymin, ymax, h2.cartesianPoint2d()); - - if (h2.shouldBeClipped() ^ h3.shouldBeClipped()) - expandBoundsToIncludePoint(xmin, xmax, ymin, ymax, computeClippedPointForEdge(h2, h3).cartesianPoint2d()); - - if (!h3.shouldBeClipped()) - expandBoundsToIncludePoint(xmin, xmax, ymin, ymax, h3.cartesianPoint2d()); - - if (h3.shouldBeClipped() ^ h4.shouldBeClipped()) - expandBoundsToIncludePoint(xmin, xmax, ymin, ymax, computeClippedPointForEdge(h3, h4).cartesianPoint2d()); - - if (!h4.shouldBeClipped()) - expandBoundsToIncludePoint(xmin, xmax, ymin, ymax, h4.cartesianPoint2d()); - - if (h4.shouldBeClipped() ^ h1.shouldBeClipped()) - expandBoundsToIncludePoint(xmin, xmax, ymin, ymax, computeClippedPointForEdge(h4, h1).cartesianPoint2d()); - - return FloatRect(FloatPoint(xmin, ymin), FloatSize(xmax - xmin, ymax - ymin)); -} - -FloatQuad CCMathUtil::mapQuad(const WebTransformationMatrix& transform, const FloatQuad& q, bool& clipped) -{ - if (transform.isIdentityOrTranslation()) { - FloatQuad mappedQuad(q); - mappedQuad.move(static_cast(transform.m41()), static_cast(transform.m42())); - clipped = false; - return mappedQuad; - } - - HomogeneousCoordinate h1 = mapHomogeneousPoint(transform, q.p1()); - HomogeneousCoordinate h2 = mapHomogeneousPoint(transform, q.p2()); - HomogeneousCoordinate h3 = mapHomogeneousPoint(transform, q.p3()); - HomogeneousCoordinate h4 = mapHomogeneousPoint(transform, q.p4()); - - clipped = h1.shouldBeClipped() || h2.shouldBeClipped() || h3.shouldBeClipped() || h4.shouldBeClipped(); - - // Result will be invalid if clipped == true. But, compute it anyway just in case, to emulate existing behavior. - return FloatQuad(h1.cartesianPoint2d(), h2.cartesianPoint2d(), h3.cartesianPoint2d(), h4.cartesianPoint2d()); -} - -FloatPoint CCMathUtil::mapPoint(const WebTransformationMatrix& transform, const FloatPoint& p, bool& clipped) -{ - HomogeneousCoordinate h = mapHomogeneousPoint(transform, p); - - if (h.w > 0) { - clipped = false; - return h.cartesianPoint2d(); - } - - // The cartesian coordinates will be invalid after dividing by w. - clipped = true; - - // Avoid dividing by w if w == 0. - if (!h.w) - return FloatPoint(); - - // This return value will be invalid because clipped == true, but (1) users of this - // code should be ignoring the return value when clipped == true anyway, and (2) this - // behavior is more consistent with existing behavior of WebKit transforms if the user - // really does not ignore the return value. - return h.cartesianPoint2d(); -} - -FloatPoint3D CCMathUtil::mapPoint(const WebTransformationMatrix& transform, const FloatPoint3D& p, bool& clipped) -{ - HomogeneousCoordinate h = mapHomogeneousPoint(transform, p); - - if (h.w > 0) { - clipped = false; - return h.cartesianPoint3d(); - } - - // The cartesian coordinates will be invalid after dividing by w. - clipped = true; - - // Avoid dividing by w if w == 0. - if (!h.w) - return FloatPoint3D(); - - // This return value will be invalid because clipped == true, but (1) users of this - // code should be ignoring the return value when clipped == true anyway, and (2) this - // behavior is more consistent with existing behavior of WebKit transforms if the user - // really does not ignore the return value. - return h.cartesianPoint3d(); -} - -FloatQuad CCMathUtil::projectQuad(const WebTransformationMatrix& transform, const FloatQuad& q, bool& clipped) -{ - FloatQuad projectedQuad; - bool clippedPoint; - projectedQuad.setP1(projectPoint(transform, q.p1(), clippedPoint)); - clipped = clippedPoint; - projectedQuad.setP2(projectPoint(transform, q.p2(), clippedPoint)); - clipped |= clippedPoint; - projectedQuad.setP3(projectPoint(transform, q.p3(), clippedPoint)); - clipped |= clippedPoint; - projectedQuad.setP4(projectPoint(transform, q.p4(), clippedPoint)); - clipped |= clippedPoint; - - return projectedQuad; -} - -FloatPoint CCMathUtil::projectPoint(const WebTransformationMatrix& transform, const FloatPoint& p, bool& clipped) -{ - HomogeneousCoordinate h = projectHomogeneousPoint(transform, p); - - if (h.w > 0) { - // The cartesian coordinates will be valid in this case. - clipped = false; - return h.cartesianPoint2d(); - } - - // The cartesian coordinates will be invalid after dividing by w. - clipped = true; - - // Avoid dividing by w if w == 0. - if (!h.w) - return FloatPoint(); - - // This return value will be invalid because clipped == true, but (1) users of this - // code should be ignoring the return value when clipped == true anyway, and (2) this - // behavior is more consistent with existing behavior of WebKit transforms if the user - // really does not ignore the return value. - return h.cartesianPoint2d(); -} - -void CCMathUtil::flattenTransformTo2d(WebTransformationMatrix& transform) -{ - // Set both the 3rd row and 3rd column to (0, 0, 1, 0). - // - // One useful interpretation of doing this operation: - // - For x and y values, the new transform behaves effectively like an orthographic - // projection was added to the matrix sequence. - // - For z values, the new transform overrides any effect that the transform had on - // z, and instead it preserves the z value for any points that are transformed. - // - Because of linearity of transforms, this flattened transform also preserves the - // effect that any subsequent (post-multiplied) transforms would have on z values. - // - transform.setM13(0); - transform.setM23(0); - transform.setM31(0); - transform.setM32(0); - transform.setM33(1); - transform.setM34(0); - transform.setM43(0); -} - -float CCMathUtil::smallestAngleBetweenVectors(const FloatSize& v1, const FloatSize& v2) -{ - float dotProduct = (v1.width() * v2.width() + v1.height() * v2.height()) / (v1.diagonalLength() * v2.diagonalLength()); - // Clamp to compensate for rounding errors. - dotProduct = std::max(-1.f, std::min(1.f, dotProduct)); - return rad2deg(acosf(dotProduct)); -} - -FloatSize CCMathUtil::projectVector(const FloatSize& source, const FloatSize& destination) -{ - float sourceDotDestination = source.width() * destination.width() + source.height() * destination.height(); - float projectedLength = sourceDotDestination / destination.diagonalLengthSquared(); - return FloatSize(projectedLength * destination.width(), projectedLength * destination.height()); -} - -} // namespace cc diff --git a/cc/CCMathUtil.h b/cc/CCMathUtil.h index ed3848e..945ffe8 100644 --- a/cc/CCMathUtil.h +++ b/cc/CCMathUtil.h @@ -2,106 +2,5 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CCMathUtil_h -#define CCMathUtil_h - -#include "FloatPoint.h" -#include "FloatPoint3D.h" - -namespace WebKit { -class WebTransformationMatrix; -} - -namespace cc { - -class IntRect; -class FloatRect; -class FloatQuad; - -struct HomogeneousCoordinate { - HomogeneousCoordinate(double newX, double newY, double newZ, double newW) - : x(newX) - , y(newY) - , z(newZ) - , w(newW) - { - } - - bool shouldBeClipped() const - { - return w <= 0; - } - - FloatPoint cartesianPoint2d() const - { - if (w == 1) - return FloatPoint(x, y); - - // For now, because this code is used privately only by CCMathUtil, it should never be called when w == 0, and we do not yet need to handle that case. - ASSERT(w); - double invW = 1.0 / w; - return FloatPoint(x * invW, y * invW); - } - - FloatPoint3D cartesianPoint3d() const - { - if (w == 1) - return FloatPoint3D(x, y, z); - - // For now, because this code is used privately only by CCMathUtil, it should never be called when w == 0, and we do not yet need to handle that case. - ASSERT(w); - double invW = 1.0 / w; - return FloatPoint3D(x * invW, y * invW, z * invW); - } - - double x; - double y; - double z; - double w; -}; - -class CCMathUtil { -public: - - // Background: WebTransformationMatrix code in WebCore does not do the right thing in - // mapRect / mapQuad / projectQuad when there is a perspective projection that causes - // one of the transformed vertices to go to w < 0. In those cases, it is necessary to - // perform clipping in homogeneous coordinates, after applying the transform, before - // dividing-by-w to convert to cartesian coordinates. - // - // These functions return the axis-aligned rect that encloses the correctly clipped, - // transformed polygon. - static IntRect mapClippedRect(const WebKit::WebTransformationMatrix&, const IntRect&); - static FloatRect mapClippedRect(const WebKit::WebTransformationMatrix&, const FloatRect&); - static FloatRect projectClippedRect(const WebKit::WebTransformationMatrix&, const FloatRect&); - - // Returns an array of vertices that represent the clipped polygon. After returning, indexes from - // 0 to numVerticesInClippedQuad are valid in the clippedQuad array. Note that - // numVerticesInClippedQuad may be zero, which means the entire quad was clipped, and - // none of the vertices in the array are valid. - static void mapClippedQuad(const WebKit::WebTransformationMatrix&, const FloatQuad& srcQuad, FloatPoint clippedQuad[8], int& numVerticesInClippedQuad); - - static FloatRect computeEnclosingRectOfVertices(FloatPoint vertices[], int numVertices); - static FloatRect computeEnclosingClippedRect(const HomogeneousCoordinate& h1, const HomogeneousCoordinate& h2, const HomogeneousCoordinate& h3, const HomogeneousCoordinate& h4); - - // NOTE: These functions do not do correct clipping against w = 0 plane, but they - // correctly detect the clipped condition via the boolean clipped. - static FloatQuad mapQuad(const WebKit::WebTransformationMatrix&, const FloatQuad&, bool& clipped); - static FloatPoint mapPoint(const WebKit::WebTransformationMatrix&, const FloatPoint&, bool& clipped); - static FloatPoint3D mapPoint(const WebKit::WebTransformationMatrix&, const FloatPoint3D&, bool& clipped); - static FloatQuad projectQuad(const WebKit::WebTransformationMatrix&, const FloatQuad&, bool& clipped); - static FloatPoint projectPoint(const WebKit::WebTransformationMatrix&, const FloatPoint&, bool& clipped); - - static void flattenTransformTo2d(WebKit::WebTransformationMatrix&); - - // Returns the smallest angle between the given two vectors in degrees. Neither vector is - // assumed to be normalized. - static float smallestAngleBetweenVectors(const FloatSize&, const FloatSize&); - - // Projects the |source| vector onto |destination|. Neither vector is assumed to be normalized. - static FloatSize projectVector(const FloatSize& source, const FloatSize& destination); -}; - -} // namespace cc - -#endif // #define CCMathUtil_h +// Temporary forwarding header +#include "cc/math_util.h" diff --git a/cc/CCOcclusionTracker.cpp b/cc/CCOcclusionTracker.cpp deleted file mode 100644 index bedb80c..0000000 --- a/cc/CCOcclusionTracker.cpp +++ /dev/null @@ -1,482 +0,0 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "config.h" - -#if USE(ACCELERATED_COMPOSITING) - -#include "CCOcclusionTracker.h" - -#include "CCLayerImpl.h" -#include "CCMathUtil.h" -#include "CCOverdrawMetrics.h" -#include "LayerChromium.h" -#include - -using namespace std; -using WebKit::WebTransformationMatrix; - -namespace cc { - -template -CCOcclusionTrackerBase::CCOcclusionTrackerBase(IntRect rootTargetRect, bool recordMetricsForFrame) - : m_rootTargetRect(rootTargetRect) - , m_overdrawMetrics(CCOverdrawMetrics::create(recordMetricsForFrame)) - , m_occludingScreenSpaceRects(0) -{ -} - -template -void CCOcclusionTrackerBase::enterLayer(const CCLayerIteratorPosition& layerIterator) -{ - LayerType* renderTarget = layerIterator.targetRenderSurfaceLayer; - - if (layerIterator.representsItself) - enterRenderTarget(renderTarget); - else if (layerIterator.representsTargetRenderSurface) - finishedRenderTarget(renderTarget); -} - -template -void CCOcclusionTrackerBase::leaveLayer(const CCLayerIteratorPosition& layerIterator) -{ - LayerType* renderTarget = layerIterator.targetRenderSurfaceLayer; - - if (layerIterator.representsItself) - markOccludedBehindLayer(layerIterator.currentLayer); - else if (layerIterator.representsContributingRenderSurface) - leaveToRenderTarget(renderTarget); -} - -template -void CCOcclusionTrackerBase::enterRenderTarget(const LayerType* newTarget) -{ - if (!m_stack.isEmpty() && m_stack.last().target == newTarget) - return; - - const LayerType* oldTarget = m_stack.isEmpty() ? 0 : m_stack.last().target; - const RenderSurfaceType* oldAncestorThatMovesPixels = !oldTarget ? 0 : oldTarget->renderSurface()->nearestAncestorThatMovesPixels(); - const RenderSurfaceType* newAncestorThatMovesPixels = newTarget->renderSurface()->nearestAncestorThatMovesPixels(); - - m_stack.append(StackObject(newTarget)); - - // We copy the screen occlusion into the new RenderSurface subtree, but we never copy in the - // target occlusion, since we are looking at a new RenderSurface target. - - // If we are entering a subtree that is going to move pixels around, then the occlusion we've computed - // so far won't apply to the pixels we're drawing here in the same way. We discard the occlusion thus - // far to be safe, and ensure we don't cull any pixels that are moved such that they become visible. - bool enteringSubtreeThatMovesPixels = newAncestorThatMovesPixels && newAncestorThatMovesPixels != oldAncestorThatMovesPixels; - - bool copyScreenOcclusionForward = m_stack.size() > 1 && !enteringSubtreeThatMovesPixels; - if (copyScreenOcclusionForward) { - int lastIndex = m_stack.size() - 1; - m_stack[lastIndex].occlusionInScreen = m_stack[lastIndex - 1].occlusionInScreen; - } -} - -static inline bool layerOpacityKnown(const LayerChromium* layer) { return !layer->drawOpacityIsAnimating(); } -static inline bool layerOpacityKnown(const CCLayerImpl*) { return true; } -static inline bool layerTransformsToTargetKnown(const LayerChromium* layer) { return !layer->drawTransformIsAnimating(); } -static inline bool layerTransformsToTargetKnown(const CCLayerImpl*) { return true; } -static inline bool layerTransformsToScreenKnown(const LayerChromium* layer) { return !layer->screenSpaceTransformIsAnimating(); } -static inline bool layerTransformsToScreenKnown(const CCLayerImpl*) { return true; } - -static inline bool surfaceOpacityKnown(const RenderSurfaceChromium* surface) { return !surface->drawOpacityIsAnimating(); } -static inline bool surfaceOpacityKnown(const CCRenderSurface*) { return true; } -static inline bool surfaceTransformsToTargetKnown(const RenderSurfaceChromium* surface) { return !surface->targetSurfaceTransformsAreAnimating(); } -static inline bool surfaceTransformsToTargetKnown(const CCRenderSurface*) { return true; } -static inline bool surfaceTransformsToScreenKnown(const RenderSurfaceChromium* surface) { return !surface->screenSpaceTransformsAreAnimating(); } -static inline bool surfaceTransformsToScreenKnown(const CCRenderSurface*) { return true; } - -static inline bool layerIsInUnsorted3dRenderingContext(const LayerChromium* layer) { return layer->parent() && layer->parent()->preserves3D(); } -static inline bool layerIsInUnsorted3dRenderingContext(const CCLayerImpl*) { return false; } - -template -void CCOcclusionTrackerBase::finishedRenderTarget(const LayerType* finishedTarget) -{ - // Make sure we know about the target surface. - enterRenderTarget(finishedTarget); - - RenderSurfaceType* surface = finishedTarget->renderSurface(); - - // If the occlusion within the surface can not be applied to things outside of the surface's subtree, then clear the occlusion here so it won't be used. - if (finishedTarget->maskLayer() || !surfaceOpacityKnown(surface) || surface->drawOpacity() < 1 || finishedTarget->filters().hasFilterThatAffectsOpacity()) { - m_stack.last().occlusionInScreen = Region(); - m_stack.last().occlusionInTarget = Region(); - } else { - if (!surfaceTransformsToTargetKnown(surface)) - m_stack.last().occlusionInTarget = Region(); - if (!surfaceTransformsToScreenKnown(surface)) - m_stack.last().occlusionInScreen = Region(); - } -} - -template -static inline Region transformSurfaceOpaqueRegion(const RenderSurfaceType* surface, const Region& region, const WebTransformationMatrix& transform) -{ - // Verify that rects within the |surface| will remain rects in its target surface after applying |transform|. If this is true, then - // apply |transform| to each rect within |region| in order to transform the entire Region. - - bool clipped; - FloatQuad transformedBoundsQuad = CCMathUtil::mapQuad(transform, FloatQuad(region.bounds()), clipped); - // FIXME: Find a rect interior to each transformed quad. - if (clipped || !transformedBoundsQuad.isRectilinear()) - return Region(); - - Region transformedRegion; - - Vector rects = region.rects(); - for (size_t i = 0; i < rects.size(); ++i) { - // We've already checked for clipping in the mapQuad call above, these calls should not clip anything further. - IntRect transformedRect = enclosedIntRect(CCMathUtil::mapClippedRect(transform, FloatRect(rects[i]))); - if (!surface->clipRect().isEmpty()) - transformedRect.intersect(surface->clipRect()); - transformedRegion.unite(transformedRect); - } - return transformedRegion; -} - -static inline void reduceOcclusion(const IntRect& affectedArea, const IntRect& expandedPixel, Region& occlusion) -{ - if (affectedArea.isEmpty()) - return; - - Region affectedOcclusion = intersect(occlusion, affectedArea); - Vector affectedOcclusionRects = affectedOcclusion.rects(); - - occlusion.subtract(affectedArea); - for (size_t j = 0; j < affectedOcclusionRects.size(); ++j) { - WebCore::IntRect& occlusionRect = affectedOcclusionRects[j]; - - // Shrink the rect by expanding the non-opaque pixels outside the rect. - - // The expandedPixel is the IntRect for a single pixel after being - // expanded by filters on the layer. The original pixel would be - // IntRect(0, 0, 1, 1), and the expanded pixel is the rect, relative - // to this original rect, that the original pixel can influence after - // being filtered. - // To convert the expandedPixel IntRect back to filter outsets: - // x = -leftOutset - // width = leftOutset + rightOutset - // maxX = x + width = -leftOutset + leftOutset + rightOutset = rightOutset - - // The leftOutset of the filters moves pixels on the right side of - // the occlusionRect into it, shrinking its right edge. - int shrinkLeft = occlusionRect.x() == affectedArea.x() ? 0 : expandedPixel.maxX(); - int shrinkTop = occlusionRect.y() == affectedArea.y() ? 0 : expandedPixel.maxY(); - int shrinkRight = occlusionRect.maxX() == affectedArea.maxX() ? 0 : -expandedPixel.x(); - int shrinkBottom = occlusionRect.maxY() == affectedArea.maxY() ? 0 : -expandedPixel.y(); - - occlusionRect.move(shrinkLeft, shrinkTop); - occlusionRect.contract(shrinkLeft + shrinkRight, shrinkTop + shrinkBottom); - - occlusion.unite(occlusionRect); - } -} - -template -static void reduceOcclusionBelowSurface(LayerType* contributingLayer, const IntRect& surfaceRect, const WebTransformationMatrix& surfaceTransform, LayerType* renderTarget, Region& occlusionInTarget, Region& occlusionInScreen) -{ - if (surfaceRect.isEmpty()) - return; - - IntRect boundsInTarget = enclosingIntRect(CCMathUtil::mapClippedRect(surfaceTransform, FloatRect(surfaceRect))); - if (!contributingLayer->renderSurface()->clipRect().isEmpty()) - boundsInTarget.intersect(contributingLayer->renderSurface()->clipRect()); - - int outsetTop, outsetRight, outsetBottom, outsetLeft; - contributingLayer->backgroundFilters().getOutsets(outsetTop, outsetRight, outsetBottom, outsetLeft); - - // The filter can move pixels from outside of the clip, so allow affectedArea to expand outside the clip. - boundsInTarget.move(-outsetLeft, -outsetTop); - boundsInTarget.expand(outsetLeft + outsetRight, outsetTop + outsetBottom); - - IntRect boundsInScreen = enclosingIntRect(CCMathUtil::mapClippedRect(renderTarget->renderSurface()->screenSpaceTransform(), FloatRect(boundsInTarget))); - - IntRect filterOutsetsInTarget(-outsetLeft, -outsetTop, outsetLeft + outsetRight, outsetTop + outsetBottom); - IntRect filterOutsetsInScreen = enclosingIntRect(CCMathUtil::mapClippedRect(renderTarget->renderSurface()->screenSpaceTransform(), FloatRect(filterOutsetsInTarget))); - - reduceOcclusion(boundsInTarget, filterOutsetsInTarget, occlusionInTarget); - reduceOcclusion(boundsInScreen, filterOutsetsInScreen, occlusionInScreen); -} - -template -void CCOcclusionTrackerBase::leaveToRenderTarget(const LayerType* newTarget) -{ - int lastIndex = m_stack.size() - 1; - bool surfaceWillBeAtTopAfterPop = m_stack.size() > 1 && m_stack[lastIndex - 1].target == newTarget; - - // We merge the screen occlusion from the current RenderSurface subtree out to its parent target RenderSurface. - // The target occlusion can be merged out as well but needs to be transformed to the new target. - - const LayerType* oldTarget = m_stack[lastIndex].target; - const RenderSurfaceType* oldSurface = oldTarget->renderSurface(); - Region oldTargetOcclusionInNewTarget = transformSurfaceOpaqueRegion(oldSurface, m_stack[lastIndex].occlusionInTarget, oldSurface->drawTransform()); - if (oldTarget->hasReplica() && !oldTarget->replicaHasMask()) - oldTargetOcclusionInNewTarget.unite(transformSurfaceOpaqueRegion(oldSurface, m_stack[lastIndex].occlusionInTarget, oldSurface->replicaDrawTransform())); - - IntRect unoccludedSurfaceRect; - IntRect unoccludedReplicaRect; - if (oldTarget->backgroundFilters().hasFilterThatMovesPixels()) { - unoccludedSurfaceRect = unoccludedContributingSurfaceContentRect(oldTarget, false, oldSurface->contentRect()); - if (oldTarget->hasReplica()) - unoccludedReplicaRect = unoccludedContributingSurfaceContentRect(oldTarget, true, oldSurface->contentRect()); - } - - if (surfaceWillBeAtTopAfterPop) { - // Merge the top of the stack down. - m_stack[lastIndex - 1].occlusionInScreen.unite(m_stack[lastIndex].occlusionInScreen); - m_stack[lastIndex - 1].occlusionInTarget.unite(oldTargetOcclusionInNewTarget); - m_stack.removeLast(); - } else { - // Replace the top of the stack with the new pushed surface. Copy the occluded screen region to the top. - m_stack.last().target = newTarget; - m_stack.last().occlusionInTarget = oldTargetOcclusionInNewTarget; - } - - if (oldTarget->backgroundFilters().hasFilterThatMovesPixels()) { - reduceOcclusionBelowSurface(oldTarget, unoccludedSurfaceRect, oldSurface->drawTransform(), newTarget, m_stack.last().occlusionInTarget, m_stack.last().occlusionInScreen); - if (oldTarget->hasReplica()) - reduceOcclusionBelowSurface(oldTarget, unoccludedReplicaRect, oldSurface->replicaDrawTransform(), newTarget, m_stack.last().occlusionInTarget, m_stack.last().occlusionInScreen); - } -} - -// FIXME: Remove usePaintTracking when paint tracking is on for paint culling. -template -static inline void addOcclusionBehindLayer(Region& region, const LayerType* layer, const WebTransformationMatrix& transform, const Region& opaqueContents, const IntRect& clipRectInTarget, const IntSize& minimumTrackingSize, Vector* occludingScreenSpaceRects) -{ - ASSERT(layer->visibleContentRect().contains(opaqueContents.bounds())); - - bool clipped; - FloatQuad visibleTransformedQuad = CCMathUtil::mapQuad(transform, FloatQuad(layer->visibleContentRect()), clipped); - // FIXME: Find a rect interior to each transformed quad. - if (clipped || !visibleTransformedQuad.isRectilinear()) - return; - - Vector contentRects = opaqueContents.rects(); - for (size_t i = 0; i < contentRects.size(); ++i) { - // We've already checked for clipping in the mapQuad call above, these calls should not clip anything further. - IntRect transformedRect = enclosedIntRect(CCMathUtil::mapClippedRect(transform, FloatRect(contentRects[i]))); - transformedRect.intersect(clipRectInTarget); - if (transformedRect.width() >= minimumTrackingSize.width() || transformedRect.height() >= minimumTrackingSize.height()) { - if (occludingScreenSpaceRects) - occludingScreenSpaceRects->append(transformedRect); - region.unite(transformedRect); - } - } -} - -template -void CCOcclusionTrackerBase::markOccludedBehindLayer(const LayerType* layer) -{ - ASSERT(!m_stack.isEmpty()); - ASSERT(layer->renderTarget() == m_stack.last().target); - if (m_stack.isEmpty()) - return; - - if (!layerOpacityKnown(layer) || layer->drawOpacity() < 1) - return; - - if (layerIsInUnsorted3dRenderingContext(layer)) - return; - - Region opaqueContents = layer->visibleContentOpaqueRegion(); - if (opaqueContents.isEmpty()) - return; - - IntRect clipRectInTarget = layerClipRectInTarget(layer); - if (layerTransformsToTargetKnown(layer)) - addOcclusionBehindLayer(m_stack.last().occlusionInTarget, layer, layer->drawTransform(), opaqueContents, clipRectInTarget, m_minimumTrackingSize, 0); - - // We must clip the occlusion within the layer's clipRectInTarget within screen space as well. If the clip rect can't be moved to screen space and - // remain rectilinear, then we don't add any occlusion in screen space. - - if (layerTransformsToScreenKnown(layer)) { - WebTransformationMatrix targetToScreenTransform = m_stack.last().target->renderSurface()->screenSpaceTransform(); - bool clipped; - FloatQuad clipQuadInScreen = CCMathUtil::mapQuad(targetToScreenTransform, FloatQuad(FloatRect(clipRectInTarget)), clipped); - // FIXME: Find a rect interior to the transformed clip quad. - if (clipped || !clipQuadInScreen.isRectilinear()) - return; - IntRect clipRectInScreen = intersection(m_rootTargetRect, enclosedIntRect(clipQuadInScreen.boundingBox())); - addOcclusionBehindLayer(m_stack.last().occlusionInScreen, layer, layer->screenSpaceTransform(), opaqueContents, clipRectInScreen, m_minimumTrackingSize, m_occludingScreenSpaceRects); - } -} - -static inline bool testContentRectOccluded(const IntRect& contentRect, const WebTransformationMatrix& contentSpaceTransform, const IntRect& clipRectInTarget, const Region& occlusion) -{ - FloatRect transformedRect = CCMathUtil::mapClippedRect(contentSpaceTransform, FloatRect(contentRect)); - // Take the enclosingIntRect, as we want to include partial pixels in the test. - IntRect targetRect = intersection(enclosingIntRect(transformedRect), clipRectInTarget); - return targetRect.isEmpty() || occlusion.contains(targetRect); -} - -template -bool CCOcclusionTrackerBase::occluded(const LayerType* layer, const IntRect& contentRect, bool* hasOcclusionFromOutsideTargetSurface) const -{ - if (hasOcclusionFromOutsideTargetSurface) - *hasOcclusionFromOutsideTargetSurface = false; - - ASSERT(!m_stack.isEmpty()); - if (m_stack.isEmpty()) - return false; - if (contentRect.isEmpty()) - return true; - - ASSERT(layer->renderTarget() == m_stack.last().target); - - if (layerTransformsToTargetKnown(layer) && testContentRectOccluded(contentRect, layer->drawTransform(), layerClipRectInTarget(layer), m_stack.last().occlusionInTarget)) - return true; - - if (layerTransformsToScreenKnown(layer) && testContentRectOccluded(contentRect, layer->screenSpaceTransform(), m_rootTargetRect, m_stack.last().occlusionInScreen)) { - if (hasOcclusionFromOutsideTargetSurface) - *hasOcclusionFromOutsideTargetSurface = true; - return true; - } - - return false; -} - -// Determines what portion of rect, if any, is unoccluded (not occluded by region). If -// the resulting unoccluded region is not rectangular, we return a rect containing it. -static inline IntRect rectSubtractRegion(const IntRect& rect, const Region& region) -{ - Region rectRegion(rect); - rectRegion.subtract(region); - return rectRegion.bounds(); -} - -static inline IntRect computeUnoccludedContentRect(const IntRect& contentRect, const WebTransformationMatrix& contentSpaceTransform, const IntRect& clipRectInTarget, const Region& occlusion) -{ - if (!contentSpaceTransform.isInvertible()) - return contentRect; - - // Take the enclosingIntRect at each step, as we want to contain any unoccluded partial pixels in the resulting IntRect. - FloatRect transformedRect = CCMathUtil::mapClippedRect(contentSpaceTransform, FloatRect(contentRect)); - IntRect shrunkRect = rectSubtractRegion(intersection(enclosingIntRect(transformedRect), clipRectInTarget), occlusion); - IntRect unoccludedRect = enclosingIntRect(CCMathUtil::projectClippedRect(contentSpaceTransform.inverse(), FloatRect(shrunkRect))); - // The rect back in content space is a bounding box and may extend outside of the original contentRect, so clamp it to the contentRectBounds. - return intersection(unoccludedRect, contentRect); -} - -template -IntRect CCOcclusionTrackerBase::unoccludedContentRect(const LayerType* layer, const IntRect& contentRect, bool* hasOcclusionFromOutsideTargetSurface) const -{ - ASSERT(!m_stack.isEmpty()); - if (m_stack.isEmpty()) - return contentRect; - if (contentRect.isEmpty()) - return contentRect; - - ASSERT(layer->renderTarget() == m_stack.last().target); - - // We want to return a rect that contains all the visible parts of |contentRect| in both screen space and in the target surface. - // So we find the visible parts of |contentRect| in each space, and take the intersection. - - IntRect unoccludedInScreen = contentRect; - if (layerTransformsToScreenKnown(layer)) - unoccludedInScreen = computeUnoccludedContentRect(contentRect, layer->screenSpaceTransform(), m_rootTargetRect, m_stack.last().occlusionInScreen); - - IntRect unoccludedInTarget = contentRect; - if (layerTransformsToTargetKnown(layer)) - unoccludedInTarget = computeUnoccludedContentRect(contentRect, layer->drawTransform(), layerClipRectInTarget(layer), m_stack.last().occlusionInTarget); - - if (hasOcclusionFromOutsideTargetSurface) - *hasOcclusionFromOutsideTargetSurface = (intersection(unoccludedInScreen, unoccludedInTarget) != unoccludedInTarget); - - return intersection(unoccludedInScreen, unoccludedInTarget); -} - -template -IntRect CCOcclusionTrackerBase::unoccludedContributingSurfaceContentRect(const LayerType* layer, bool forReplica, const IntRect& contentRect, bool* hasOcclusionFromOutsideTargetSurface) const -{ - ASSERT(!m_stack.isEmpty()); - // The layer is a contributing renderTarget so it should have a surface. - ASSERT(layer->renderSurface()); - // The layer is a contributing renderTarget so its target should be itself. - ASSERT(layer->renderTarget() == layer); - // The layer should not be the root, else what is is contributing to? - ASSERT(layer->parent()); - // This should be called while the layer is still considered the current target in the occlusion tracker. - ASSERT(layer == m_stack.last().target); - - if (contentRect.isEmpty()) - return contentRect; - - RenderSurfaceType* surface = layer->renderSurface(); - - IntRect surfaceClipRect = surface->clipRect(); - if (surfaceClipRect.isEmpty()) { - LayerType* contributingSurfaceRenderTarget = layer->parent()->renderTarget(); - surfaceClipRect = intersection(contributingSurfaceRenderTarget->renderSurface()->contentRect(), enclosingIntRect(surface->drawableContentRect())); - } - - // A contributing surface doesn't get occluded by things inside its own surface, so only things outside the surface can occlude it. That occlusion is - // found just below the top of the stack (if it exists). - bool hasOcclusion = m_stack.size() > 1; - - const WebTransformationMatrix& transformToScreen = forReplica ? surface->replicaScreenSpaceTransform() : surface->screenSpaceTransform(); - const WebTransformationMatrix& transformToTarget = forReplica ? surface->replicaDrawTransform() : surface->drawTransform(); - - IntRect unoccludedInScreen = contentRect; - if (surfaceTransformsToScreenKnown(surface)) { - if (hasOcclusion) { - const StackObject& secondLast = m_stack[m_stack.size() - 2]; - unoccludedInScreen = computeUnoccludedContentRect(contentRect, transformToScreen, m_rootTargetRect, secondLast.occlusionInScreen); - } else - unoccludedInScreen = computeUnoccludedContentRect(contentRect, transformToScreen, m_rootTargetRect, Region()); - } - - IntRect unoccludedInTarget = contentRect; - if (surfaceTransformsToTargetKnown(surface)) { - if (hasOcclusion) { - const StackObject& secondLast = m_stack[m_stack.size() - 2]; - unoccludedInTarget = computeUnoccludedContentRect(contentRect, transformToTarget, surfaceClipRect, secondLast.occlusionInTarget); - } else - unoccludedInTarget = computeUnoccludedContentRect(contentRect, transformToTarget, surfaceClipRect, Region()); - } - - if (hasOcclusionFromOutsideTargetSurface) - *hasOcclusionFromOutsideTargetSurface = (intersection(unoccludedInScreen, unoccludedInTarget) != unoccludedInTarget); - - return intersection(unoccludedInScreen, unoccludedInTarget); -} - -template -IntRect CCOcclusionTrackerBase::layerClipRectInTarget(const LayerType* layer) const -{ - // FIXME: we could remove this helper function, but unit tests currently override this - // function, and they need to be verified/adjusted before this can be removed. - return layer->drawableContentRect(); -} - -// Declare the possible functions here for the linker. -template CCOcclusionTrackerBase::CCOcclusionTrackerBase(IntRect rootTargetRect, bool recordMetricsForFrame); -template void CCOcclusionTrackerBase::enterLayer(const CCLayerIteratorPosition&); -template void CCOcclusionTrackerBase::leaveLayer(const CCLayerIteratorPosition&); -template void CCOcclusionTrackerBase::enterRenderTarget(const LayerChromium* newTarget); -template void CCOcclusionTrackerBase::finishedRenderTarget(const LayerChromium* finishedTarget); -template void CCOcclusionTrackerBase::leaveToRenderTarget(const LayerChromium* newTarget); -template void CCOcclusionTrackerBase::markOccludedBehindLayer(const LayerChromium*); -template bool CCOcclusionTrackerBase::occluded(const LayerChromium*, const IntRect& contentRect, bool* hasOcclusionFromOutsideTargetSurface) const; -template IntRect CCOcclusionTrackerBase::unoccludedContentRect(const LayerChromium*, const IntRect& contentRect, bool* hasOcclusionFromOutsideTargetSurface) const; -template IntRect CCOcclusionTrackerBase::unoccludedContributingSurfaceContentRect(const LayerChromium*, bool forReplica, const IntRect& contentRect, bool* hasOcclusionFromOutsideTargetSurface) const; -template IntRect CCOcclusionTrackerBase::layerClipRectInTarget(const LayerChromium*) const; - -template CCOcclusionTrackerBase::CCOcclusionTrackerBase(IntRect rootTargetRect, bool recordMetricsForFrame); -template void CCOcclusionTrackerBase::enterLayer(const CCLayerIteratorPosition&); -template void CCOcclusionTrackerBase::leaveLayer(const CCLayerIteratorPosition&); -template void CCOcclusionTrackerBase::enterRenderTarget(const CCLayerImpl* newTarget); -template void CCOcclusionTrackerBase::finishedRenderTarget(const CCLayerImpl* finishedTarget); -template void CCOcclusionTrackerBase::leaveToRenderTarget(const CCLayerImpl* newTarget); -template void CCOcclusionTrackerBase::markOccludedBehindLayer(const CCLayerImpl*); -template bool CCOcclusionTrackerBase::occluded(const CCLayerImpl*, const IntRect& contentRect, bool* hasOcclusionFromOutsideTargetSurface) const; -template IntRect CCOcclusionTrackerBase::unoccludedContentRect(const CCLayerImpl*, const IntRect& contentRect, bool* hasOcclusionFromOutsideTargetSurface) const; -template IntRect CCOcclusionTrackerBase::unoccludedContributingSurfaceContentRect(const CCLayerImpl*, bool forReplica, const IntRect& contentRect, bool* hasOcclusionFromOutsideTargetSurface) const; -template IntRect CCOcclusionTrackerBase::layerClipRectInTarget(const CCLayerImpl*) const; - - -} // namespace cc -#endif // USE(ACCELERATED_COMPOSITING) diff --git a/cc/CCOcclusionTracker.h b/cc/CCOcclusionTracker.h index c2526cd..b7c8ce0 100644 --- a/cc/CCOcclusionTracker.h +++ b/cc/CCOcclusionTracker.h @@ -2,104 +2,5 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CCOcclusionTracker_h -#define CCOcclusionTracker_h - -#include "base/basictypes.h" -#include "CCLayerIterator.h" -#include "FloatQuad.h" -#include "Region.h" - -namespace cc { -class CCOverdrawMetrics; -class CCLayerImpl; -class CCRenderSurface; -class LayerChromium; -class RenderSurfaceChromium; - -// This class is used to track occlusion of layers while traversing them in a front-to-back order. As each layer is visited, one of the -// methods in this class is called to notify it about the current target surface. -// Then, occlusion in the content space of the current layer may be queried, via methods such as occluded() and unoccludedContentRect(). -// If the current layer owns a RenderSurface, then occlusion on that RenderSurface may also be queried via surfaceOccluded() and surfaceUnoccludedContentRect(). -// Finally, once finished with the layer, occlusion behind the layer should be marked by calling markOccludedBehindLayer(). -template -class CCOcclusionTrackerBase { -public: - CCOcclusionTrackerBase(IntRect rootTargetRect, bool recordMetricsForFrame); - - // Called at the beginning of each step in the CCLayerIterator's front-to-back traversal. - void enterLayer(const CCLayerIteratorPosition&); - // Called at the end of each step in the CCLayerIterator's front-to-back traversal. - void leaveLayer(const CCLayerIteratorPosition&); - - // Returns true if the given rect in content space for the layer is fully occluded in either screen space or the layer's target surface. - bool occluded(const LayerType*, const IntRect& contentRect, bool* hasOcclusionFromOutsideTargetSurface = 0) const; - // Gives an unoccluded sub-rect of |contentRect| in the content space of the layer. Used when considering occlusion for a layer that paints/draws something. - IntRect unoccludedContentRect(const LayerType*, const IntRect& contentRect, bool* hasOcclusionFromOutsideTargetSurface = 0) const; - - // Gives an unoccluded sub-rect of |contentRect| in the content space of the renderTarget owned by the layer. - // Used when considering occlusion for a contributing surface that is rendering into another target. - IntRect unoccludedContributingSurfaceContentRect(const LayerType*, bool forReplica, const IntRect& contentRect, bool* hasOcclusionFromOutsideTargetSurface = 0) const; - - // Report operations for recording overdraw metrics. - CCOverdrawMetrics& overdrawMetrics() const { return *m_overdrawMetrics.get(); } - - // Gives the region of the screen that is not occluded by something opaque. - Region computeVisibleRegionInScreen() const { return subtract(Region(m_rootTargetRect), m_stack.last().occlusionInScreen); } - - void setMinimumTrackingSize(const IntSize& size) { m_minimumTrackingSize = size; } - - // The following is used for visualization purposes. - void setOccludingScreenSpaceRectsContainer(Vector* rects) { m_occludingScreenSpaceRects = rects; } - -protected: - struct StackObject { - StackObject() : target(0) { } - StackObject(const LayerType* target) : target(target) { } - const LayerType* target; - Region occlusionInScreen; - Region occlusionInTarget; - }; - - // The stack holds occluded regions for subtrees in the RenderSurface-Layer tree, so that when we leave a subtree we may - // apply a mask to it, but not to the parts outside the subtree. - // - The first time we see a new subtree under a target, we add that target to the top of the stack. This can happen as a layer representing itself, or as a target surface. - // - When we visit a target surface, we apply its mask to its subtree, which is at the top of the stack. - // - When we visit a layer representing itself, we add its occlusion to the current subtree, which is at the top of the stack. - // - When we visit a layer representing a contributing surface, the current target will never be the top of the stack since we just came from the contributing surface. - // We merge the occlusion at the top of the stack with the new current subtree. This new target is pushed onto the stack if not already there. - Vector m_stack; - - // Allow tests to override this. - virtual IntRect layerClipRectInTarget(const LayerType*) const; - -private: - // Called when visiting a layer representing itself. If the target was not already current, then this indicates we have entered a new surface subtree. - void enterRenderTarget(const LayerType* newTarget); - - // Called when visiting a layer representing a target surface. This indicates we have visited all the layers within the surface, and we may - // perform any surface-wide operations. - void finishedRenderTarget(const LayerType* finishedTarget); - - // Called when visiting a layer representing a contributing surface. This indicates that we are leaving our current surface, and - // entering the new one. We then perform any operations required for merging results from the child subtree into its parent. - void leaveToRenderTarget(const LayerType* newTarget); - - // Add the layer's occlusion to the tracked state. - void markOccludedBehindLayer(const LayerType*); - - IntRect m_rootTargetRect; - OwnPtr m_overdrawMetrics; - IntSize m_minimumTrackingSize; - - // This is used for visualizing the occlusion tracking process. - Vector* m_occludingScreenSpaceRects; - - DISALLOW_COPY_AND_ASSIGN(CCOcclusionTrackerBase); -}; - -typedef CCOcclusionTrackerBase CCOcclusionTracker; -typedef CCOcclusionTrackerBase CCOcclusionTrackerImpl; - -} -#endif // CCOcclusionTracker_h +// Temporary forwarding header +#include "cc/occlusion_tracker.h" diff --git a/cc/CCOverdrawMetrics.cpp b/cc/CCOverdrawMetrics.cpp deleted file mode 100644 index 4eba7d3..0000000 --- a/cc/CCOverdrawMetrics.cpp +++ /dev/null @@ -1,190 +0,0 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "config.h" - -#if USE(ACCELERATED_COMPOSITING) - -#include "CCOverdrawMetrics.h" - -#include "CCLayerTreeHost.h" -#include "CCLayerTreeHostImpl.h" -#include "CCMathUtil.h" -#include "FloatQuad.h" -#include "IntRect.h" -#include "TraceEvent.h" -#include -#include - -using WebKit::WebTransformationMatrix; - -namespace cc { - -CCOverdrawMetrics::CCOverdrawMetrics(bool recordMetricsForFrame) - : m_recordMetricsForFrame(recordMetricsForFrame) - , m_pixelsPainted(0) - , m_pixelsUploadedOpaque(0) - , m_pixelsUploadedTranslucent(0) - , m_tilesCulledForUpload(0) - , m_contentsTextureUseBytes(0) - , m_renderSurfaceTextureUseBytes(0) - , m_pixelsDrawnOpaque(0) - , m_pixelsDrawnTranslucent(0) - , m_pixelsCulledForDrawing(0) -{ -} - -static inline float wedgeProduct(const FloatPoint& p1, const FloatPoint& p2) -{ - return p1.x() * p2.y() - p1.y() * p2.x(); -} - -// Calculates area of an arbitrary convex polygon with up to 8 points. -static inline float polygonArea(const FloatPoint points[8], int numPoints) -{ - if (numPoints < 3) - return 0; - - float area = 0; - for (int i = 0; i < numPoints; ++i) - area += wedgeProduct(points[i], points[(i+1)%numPoints]); - return fabs(0.5f * area); -} - -// Takes a given quad, maps it by the given transformation, and gives the area of the resulting polygon. -static inline float areaOfMappedQuad(const WebTransformationMatrix& transform, const FloatQuad& quad) -{ - FloatPoint clippedQuad[8]; - int numVerticesInClippedQuad = 0; - CCMathUtil::mapClippedQuad(transform, quad, clippedQuad, numVerticesInClippedQuad); - return polygonArea(clippedQuad, numVerticesInClippedQuad); -} - -void CCOverdrawMetrics::didPaint(const IntRect& paintedRect) -{ - if (!m_recordMetricsForFrame) - return; - - m_pixelsPainted += static_cast(paintedRect.width()) * paintedRect.height(); -} - -void CCOverdrawMetrics::didCullTileForUpload() -{ - if (m_recordMetricsForFrame) - ++m_tilesCulledForUpload; -} - -void CCOverdrawMetrics::didUpload(const WebTransformationMatrix& transformToTarget, const IntRect& uploadRect, const IntRect& opaqueRect) -{ - if (!m_recordMetricsForFrame) - return; - - float uploadArea = areaOfMappedQuad(transformToTarget, FloatQuad(uploadRect)); - float uploadOpaqueArea = areaOfMappedQuad(transformToTarget, FloatQuad(intersection(opaqueRect, uploadRect))); - - m_pixelsUploadedOpaque += uploadOpaqueArea; - m_pixelsUploadedTranslucent += uploadArea - uploadOpaqueArea; -} - -void CCOverdrawMetrics::didUseContentsTextureMemoryBytes(size_t contentsTextureUseBytes) -{ - if (!m_recordMetricsForFrame) - return; - - m_contentsTextureUseBytes += contentsTextureUseBytes; -} - -void CCOverdrawMetrics::didUseRenderSurfaceTextureMemoryBytes(size_t renderSurfaceUseBytes) -{ - if (!m_recordMetricsForFrame) - return; - - m_renderSurfaceTextureUseBytes += renderSurfaceUseBytes; -} - -void CCOverdrawMetrics::didCullForDrawing(const WebTransformationMatrix& transformToTarget, const IntRect& beforeCullRect, const IntRect& afterCullRect) -{ - if (!m_recordMetricsForFrame) - return; - - float beforeCullArea = areaOfMappedQuad(transformToTarget, FloatQuad(beforeCullRect)); - float afterCullArea = areaOfMappedQuad(transformToTarget, FloatQuad(afterCullRect)); - - m_pixelsCulledForDrawing += beforeCullArea - afterCullArea; -} - -void CCOverdrawMetrics::didDraw(const WebTransformationMatrix& transformToTarget, const IntRect& afterCullRect, const IntRect& opaqueRect) -{ - if (!m_recordMetricsForFrame) - return; - - float afterCullArea = areaOfMappedQuad(transformToTarget, FloatQuad(afterCullRect)); - float afterCullOpaqueArea = areaOfMappedQuad(transformToTarget, FloatQuad(intersection(opaqueRect, afterCullRect))); - - m_pixelsDrawnOpaque += afterCullOpaqueArea; - m_pixelsDrawnTranslucent += afterCullArea - afterCullOpaqueArea; -} - -void CCOverdrawMetrics::recordMetrics(const CCLayerTreeHost* layerTreeHost) const -{ - if (m_recordMetricsForFrame) - recordMetricsInternal(UpdateAndCommit, layerTreeHost); -} - -void CCOverdrawMetrics::recordMetrics(const CCLayerTreeHostImpl* layerTreeHost) const -{ - if (m_recordMetricsForFrame) - recordMetricsInternal(DrawingToScreen, layerTreeHost); -} - -template -void CCOverdrawMetrics::recordMetricsInternal(MetricsType metricsType, const LayerTreeHostType* layerTreeHost) const -{ - // This gives approximately 10x the percentage of pixels to fill the viewport once. - float normalization = 1000.f / (layerTreeHost->deviceViewportSize().width() * layerTreeHost->deviceViewportSize().height()); - // This gives approximately 100x the percentage of tiles to fill the viewport once, if all tiles were 256x256. - float tileNormalization = 10000.f / (layerTreeHost->deviceViewportSize().width() / 256.f * layerTreeHost->deviceViewportSize().height() / 256.f); - // This gives approximately 10x the percentage of bytes to fill the viewport once, assuming 4 bytes per pixel. - float byteNormalization = normalization / 4; - - switch (metricsType) { - case DrawingToScreen: - WebKit::Platform::current()->histogramCustomCounts("Renderer4.pixelCountOpaque_Draw", static_cast(normalization * m_pixelsDrawnOpaque), 100, 1000000, 50); - WebKit::Platform::current()->histogramCustomCounts("Renderer4.pixelCountTranslucent_Draw", static_cast(normalization * m_pixelsDrawnTranslucent), 100, 1000000, 50); - WebKit::Platform::current()->histogramCustomCounts("Renderer4.pixelCountCulled_Draw", static_cast(normalization * m_pixelsCulledForDrawing), 100, 1000000, 50); - - { - TRACE_COUNTER_ID1("cc", "DrawPixelsCulled", layerTreeHost, m_pixelsCulledForDrawing); - TRACE_EVENT2("cc", "CCOverdrawMetrics", "PixelsDrawnOpaque", m_pixelsDrawnOpaque, "PixelsDrawnTranslucent", m_pixelsDrawnTranslucent); - } - break; - case UpdateAndCommit: - WebKit::Platform::current()->histogramCustomCounts("Renderer4.pixelCountPainted", static_cast(normalization * m_pixelsPainted), 100, 1000000, 50); - WebKit::Platform::current()->histogramCustomCounts("Renderer4.pixelCountOpaque_Upload", static_cast(normalization * m_pixelsUploadedOpaque), 100, 1000000, 50); - WebKit::Platform::current()->histogramCustomCounts("Renderer4.pixelCountTranslucent_Upload", static_cast(normalization * m_pixelsUploadedTranslucent), 100, 1000000, 50); - WebKit::Platform::current()->histogramCustomCounts("Renderer4.tileCountCulled_Upload", static_cast(tileNormalization * m_tilesCulledForUpload), 100, 10000000, 50); - WebKit::Platform::current()->histogramCustomCounts("Renderer4.renderSurfaceTextureBytes_ViewportScaled", static_cast(byteNormalization * m_renderSurfaceTextureUseBytes), 10, 1000000, 50); - WebKit::Platform::current()->histogramCustomCounts("Renderer4.renderSurfaceTextureBytes_Unscaled", static_cast(m_renderSurfaceTextureUseBytes / 1000), 1000, 100000000, 50); - WebKit::Platform::current()->histogramCustomCounts("Renderer4.contentsTextureBytes_ViewportScaled", static_cast(byteNormalization * m_contentsTextureUseBytes), 10, 1000000, 50); - WebKit::Platform::current()->histogramCustomCounts("Renderer4.contentsTextureBytes_Unscaled", static_cast(m_contentsTextureUseBytes / 1000), 1000, 100000000, 50); - - { - TRACE_COUNTER_ID1("cc", "UploadTilesCulled", layerTreeHost, m_tilesCulledForUpload); - TRACE_EVENT2("cc", "CCOverdrawMetrics", "PixelsUploadedOpaque", m_pixelsUploadedOpaque, "PixelsUploadedTranslucent", m_pixelsUploadedTranslucent); - } - { - // This must be in a different scope than the TRACE_EVENT2 above. - TRACE_EVENT1("cc", "CCOverdrawPaintMetrics", "PixelsPainted", m_pixelsPainted); - } - { - // This must be in a different scope than the TRACE_EVENTs above. - TRACE_EVENT2("cc", "CCOverdrawPaintMetrics", "ContentsTextureBytes", m_contentsTextureUseBytes, "RenderSurfaceTextureBytes", m_renderSurfaceTextureUseBytes); - } - break; - } -} - -} // namespace cc - -#endif diff --git a/cc/CCOverdrawMetrics.h b/cc/CCOverdrawMetrics.h index b907a64..94a1788 100644 --- a/cc/CCOverdrawMetrics.h +++ b/cc/CCOverdrawMetrics.h @@ -2,96 +2,5 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CCOverdrawMetrics_h -#define CCOverdrawMetrics_h - -#include - -namespace WebKit { -class WebTransformationMatrix; -} - -namespace cc { -class IntRect; -class CCLayerTreeHost; -class CCLayerTreeHostImpl; - -// FIXME: compute overdraw metrics only occasionally, not every frame. -class CCOverdrawMetrics { -public: - static PassOwnPtr create(bool recordMetricsForFrame) { return adoptPtr(new CCOverdrawMetrics(recordMetricsForFrame)); } - - // These methods are used for saving metrics during update/commit. - - // Record pixels painted by WebKit into the texture updater, but does not mean the pixels were rasterized in main memory. - void didPaint(const IntRect& paintedRect); - // Records that an invalid tile was culled and did not need to be painted/uploaded, and did not contribute to other tiles needing to be painted. - void didCullTileForUpload(); - // Records pixels that were uploaded to texture memory. - void didUpload(const WebKit::WebTransformationMatrix& transformToTarget, const IntRect& uploadRect, const IntRect& opaqueRect); - // Record contents texture(s) behind present using the given number of bytes. - void didUseContentsTextureMemoryBytes(size_t contentsTextureUseBytes); - // Record RenderSurface texture(s) being present using the given number of bytes. - void didUseRenderSurfaceTextureMemoryBytes(size_t renderSurfaceUseBytes); - - // These methods are used for saving metrics during draw. - - // Record pixels that were not drawn to screen. - void didCullForDrawing(const WebKit::WebTransformationMatrix& transformToTarget, const IntRect& beforeCullRect, const IntRect& afterCullRect); - // Record pixels that were drawn to screen. - void didDraw(const WebKit::WebTransformationMatrix& transformToTarget, const IntRect& afterCullRect, const IntRect& opaqueRect); - - void recordMetrics(const CCLayerTreeHost*) const; - void recordMetrics(const CCLayerTreeHostImpl*) const; - - // Accessors for tests. - float pixelsDrawnOpaque() const { return m_pixelsDrawnOpaque; } - float pixelsDrawnTranslucent() const { return m_pixelsDrawnTranslucent; } - float pixelsCulledForDrawing() const { return m_pixelsCulledForDrawing; } - float pixelsPainted() const { return m_pixelsPainted; } - float pixelsUploadedOpaque() const { return m_pixelsUploadedOpaque; } - float pixelsUploadedTranslucent() const { return m_pixelsUploadedTranslucent; } - int tilesCulledForUpload() const { return m_tilesCulledForUpload; } - -private: - enum MetricsType { - UpdateAndCommit, - DrawingToScreen - }; - - explicit CCOverdrawMetrics(bool recordMetricsForFrame); - - template - void recordMetricsInternal(MetricsType, const LayerTreeHostType*) const; - - // When false this class is a giant no-op. - bool m_recordMetricsForFrame; - - // These values are used for saving metrics during update/commit. - - // Count of pixels that were painted due to invalidation. - float m_pixelsPainted; - // Count of pixels uploaded to textures and known to be opaque. - float m_pixelsUploadedOpaque; - // Count of pixels uploaded to textures and not known to be opaque. - float m_pixelsUploadedTranslucent; - // Count of tiles that were invalidated but not uploaded. - int m_tilesCulledForUpload; - // Count the number of bytes in contents textures. - unsigned long long m_contentsTextureUseBytes; - // Count the number of bytes in RenderSurface textures. - unsigned long long m_renderSurfaceTextureUseBytes; - - // These values are used for saving metrics during draw. - - // Count of pixels that are opaque (and thus occlude). Ideally this is no more than wiewport width x height. - float m_pixelsDrawnOpaque; - // Count of pixels that are possibly translucent, and cannot occlude. - float m_pixelsDrawnTranslucent; - // Count of pixels not drawn as they are occluded by somthing opaque. - float m_pixelsCulledForDrawing; -}; - -} // namespace cc - -#endif +// Temporary forwarding header +#include "cc/overdraw_metrics.h" diff --git a/cc/CCPageScaleAnimation.cpp b/cc/CCPageScaleAnimation.cpp deleted file mode 100644 index 12dda09..0000000 --- a/cc/CCPageScaleAnimation.cpp +++ /dev/null @@ -1,159 +0,0 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "config.h" - -#include "CCPageScaleAnimation.h" - -#include "FloatRect.h" -#include "FloatSize.h" - -#include - -namespace cc { - -PassOwnPtr CCPageScaleAnimation::create(const IntSize& scrollStart, float pageScaleStart, const IntSize& windowSize, const IntSize& contentSize, double startTime) -{ - return adoptPtr(new CCPageScaleAnimation(scrollStart, pageScaleStart, windowSize, contentSize, startTime)); -} - - -CCPageScaleAnimation::CCPageScaleAnimation(const IntSize& scrollStart, float pageScaleStart, const IntSize& windowSize, const IntSize& contentSize, double startTime) - : m_scrollStart(scrollStart) - , m_pageScaleStart(pageScaleStart) - , m_windowSize(windowSize) - , m_contentSize(contentSize) - , m_anchorMode(false) - , m_scrollEnd(scrollStart) - , m_pageScaleEnd(pageScaleStart) - , m_startTime(startTime) - , m_duration(0) -{ -} - -void CCPageScaleAnimation::zoomTo(const IntSize& finalScroll, float finalPageScale, double duration) -{ - if (m_pageScaleStart != finalPageScale) { - // For uniform-looking zooming, infer the anchor (point that remains in - // place throughout the zoom) from the start and end rects. - FloatRect startRect(IntPoint(m_scrollStart), m_windowSize); - FloatRect endRect(IntPoint(finalScroll), m_windowSize); - endRect.scale(m_pageScaleStart / finalPageScale); - - // The anchor is the point which is at the same ratio of the sides of - // both startRect and endRect. For example, a zoom-in double-tap to a - // perfectly centered rect will have anchor ratios (0.5, 0.5), while one - // to a rect touching the bottom-right of the screen will have anchor - // ratios (1.0, 1.0). In other words, it obeys the equations: - // anchorX = start_width * ratioX + start_x - // anchorX = end_width * ratioX + end_x - // anchorY = start_height * ratioY + start_y - // anchorY = end_height * ratioY + end_y - // where both anchor{x,y} and ratio{x,y} begin as unknowns. Solving - // for the ratios, we get the following formulas: - float ratioX = (startRect.x() - endRect.x()) / (endRect.width() - startRect.width()); - float ratioY = (startRect.y() - endRect.y()) / (endRect.height() - startRect.height()); - - IntSize anchor(m_windowSize.width() * ratioX, m_windowSize.height() * ratioY); - zoomWithAnchor(anchor, finalPageScale, duration); - } else { - // If this is a pure translation, then there exists no anchor. Linearly - // interpolate the scroll offset instead. - m_scrollEnd = finalScroll; - m_pageScaleEnd = finalPageScale; - m_duration = duration; - m_anchorMode = false; - } -} - -void CCPageScaleAnimation::zoomWithAnchor(const IntSize& anchor, float finalPageScale, double duration) -{ - m_scrollEnd = m_scrollStart + anchor; - m_scrollEnd.scale(finalPageScale / m_pageScaleStart); - m_scrollEnd -= anchor; - - m_scrollEnd.clampNegativeToZero(); - FloatSize scaledContentSize(m_contentSize); - scaledContentSize.scale(finalPageScale / m_pageScaleStart); - IntSize maxScrollPosition = roundedIntSize(scaledContentSize - m_windowSize); - m_scrollEnd = m_scrollEnd.shrunkTo(maxScrollPosition); - - m_anchor = anchor; - m_pageScaleEnd = finalPageScale; - m_duration = duration; - m_anchorMode = true; -} - -IntSize CCPageScaleAnimation::scrollOffsetAtTime(double time) const -{ - return scrollOffsetAtRatio(progressRatioForTime(time)); -} - -float CCPageScaleAnimation::pageScaleAtTime(double time) const -{ - return pageScaleAtRatio(progressRatioForTime(time)); -} - -bool CCPageScaleAnimation::isAnimationCompleteAtTime(double time) const -{ - return time >= endTime(); -} - -float CCPageScaleAnimation::progressRatioForTime(double time) const -{ - if (isAnimationCompleteAtTime(time)) - return 1; - - return (time - m_startTime) / m_duration; -} - -IntSize CCPageScaleAnimation::scrollOffsetAtRatio(float ratio) const -{ - if (ratio <= 0) - return m_scrollStart; - if (ratio >= 1) - return m_scrollEnd; - - float currentPageScale = pageScaleAtRatio(ratio); - IntSize currentScrollOffset; - if (m_anchorMode) { - // Keep the anchor stable on the screen at the current scale. - IntSize documentAnchor = m_scrollStart + m_anchor; - documentAnchor.scale(currentPageScale / m_pageScaleStart); - currentScrollOffset = documentAnchor - m_anchor; - } else { - // First move both scroll offsets to the current coordinate space. - FloatSize scaledStartScroll(m_scrollStart); - scaledStartScroll.scale(currentPageScale / m_pageScaleStart); - FloatSize scaledEndScroll(m_scrollEnd); - scaledEndScroll.scale(currentPageScale / m_pageScaleEnd); - - // Linearly interpolate between them. - FloatSize delta = scaledEndScroll - scaledStartScroll; - delta.scale(ratio); - currentScrollOffset = roundedIntSize(scaledStartScroll + delta); - } - - return currentScrollOffset; -} - -float CCPageScaleAnimation::pageScaleAtRatio(float ratio) const -{ - if (ratio <= 0) - return m_pageScaleStart; - if (ratio >= 1) - return m_pageScaleEnd; - - // Linearly interpolate the magnitude in log scale. - // Log scale is needed to maintain the appearance of uniform zoom. For - // example, if we zoom from 0.5 to 4.0 in 3 seconds, then we should - // be zooming by 2x every second. - float diff = m_pageScaleEnd / m_pageScaleStart; - float logDiff = log(diff); - logDiff *= ratio; - diff = exp(logDiff); - return m_pageScaleStart * diff; -} - -} // namespace cc diff --git a/cc/CCPageScaleAnimation.h b/cc/CCPageScaleAnimation.h index f597026..1c59d7d 100644 --- a/cc/CCPageScaleAnimation.h +++ b/cc/CCPageScaleAnimation.h @@ -1,74 +1,6 @@ -// Copyright 2011 The Chromium Authors. All rights reserved. +// Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CCPageScaleAnimation_h -#define CCPageScaleAnimation_h - -#include "IntSize.h" -#include - -namespace cc { - -// A small helper class that does the math for zoom animations, primarily for -// double-tap zoom. Initialize it with starting and ending scroll/page scale -// positions and an animation length time, then call ...AtTime() at every frame -// to obtain the current interpolated position. -class CCPageScaleAnimation { -public: - // Construct with the starting page scale and scroll offset (which is in - // pageScaleStart space). The window size is the user-viewable area - // in pixels. - static PassOwnPtr create(const IntSize& scrollStart, float pageScaleStart, const IntSize& windowSize, const IntSize& contentSize, double startTime); - - // The following methods initialize the animation. Call one of them - // immediately after construction to set the final scroll and page scale. - - // Zoom while explicitly specifying the top-left scroll position. The - // scroll offset is in finalPageScale coordinates. - void zoomTo(const IntSize& finalScroll, float finalPageScale, double duration); - - // Zoom based on a specified onscreen anchor, which will remain at the same - // position on the screen throughout the animation. The anchor is in local - // space relative to scrollStart. - void zoomWithAnchor(const IntSize& anchor, float finalPageScale, double duration); - - // Call these functions while the animation is in progress to output the - // current state. - IntSize scrollOffsetAtTime(double time) const; - float pageScaleAtTime(double time) const; - bool isAnimationCompleteAtTime(double time) const; - - // The following methods return state which is invariant throughout the - // course of the animation. - double startTime() const { return m_startTime; } - double duration() const { return m_duration; } - double endTime() const { return m_startTime + m_duration; } - const IntSize& finalScrollOffset() const { return m_scrollEnd; } - float finalPageScale() const { return m_pageScaleEnd; } - -protected: - CCPageScaleAnimation(const IntSize& scrollStart, float pageScaleStart, const IntSize& windowSize, const IntSize& contentSize, double startTime); - -private: - float progressRatioForTime(double time) const; - IntSize scrollOffsetAtRatio(float ratio) const; - float pageScaleAtRatio(float ratio) const; - - IntSize m_scrollStart; - float m_pageScaleStart; - IntSize m_windowSize; - IntSize m_contentSize; - - bool m_anchorMode; - IntSize m_anchor; - IntSize m_scrollEnd; - float m_pageScaleEnd; - - double m_startTime; - double m_duration; -}; - -} // namespace cc - -#endif +// Temporary forwarding header +#include "cc/page_scale_animation.h" diff --git a/cc/CCPrioritizedTexture.cpp b/cc/CCPrioritizedTexture.cpp deleted file mode 100644 index 2940e92..0000000 --- a/cc/CCPrioritizedTexture.cpp +++ /dev/null @@ -1,180 +0,0 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "config.h" - -#include "CCPrioritizedTexture.h" - -#include "CCPrioritizedTextureManager.h" -#include "CCPriorityCalculator.h" -#include "CCProxy.h" -#include - -using namespace std; - -namespace cc { - -CCPrioritizedTexture::CCPrioritizedTexture(CCPrioritizedTextureManager* manager, IntSize size, GC3Denum format) - : m_size(size) - , m_format(format) - , m_bytes(0) - , m_priority(CCPriorityCalculator::lowestPriority()) - , m_isAbovePriorityCutoff(false) - , m_isSelfManaged(false) - , m_backing(0) - , m_manager(0) -{ - // m_manager is set in registerTexture() so validity can be checked. - ASSERT(format || size.isEmpty()); - if (format) - m_bytes = CCTexture::memorySizeBytes(size, format); - if (manager) - manager->registerTexture(this); -} - -CCPrioritizedTexture::~CCPrioritizedTexture() -{ - if (m_manager) - m_manager->unregisterTexture(this); -} - -void CCPrioritizedTexture::setTextureManager(CCPrioritizedTextureManager* manager) -{ - if (m_manager == manager) - return; - if (m_manager) - m_manager->unregisterTexture(this); - if (manager) - manager->registerTexture(this); -} - -void CCPrioritizedTexture::setDimensions(IntSize size, GC3Denum format) -{ - if (m_format != format || m_size != size) { - m_isAbovePriorityCutoff = false; - m_format = format; - m_size = size; - m_bytes = CCTexture::memorySizeBytes(size, format); - ASSERT(m_manager || !m_backing); - if (m_manager) - m_manager->returnBackingTexture(this); - } -} - -bool CCPrioritizedTexture::requestLate() -{ - if (!m_manager) - return false; - return m_manager->requestLate(this); -} - -bool CCPrioritizedTexture::backingResourceWasEvicted() const -{ - return m_backing ? m_backing->resourceHasBeenDeleted() : false; -} - -void CCPrioritizedTexture::acquireBackingTexture(CCResourceProvider* resourceProvider) -{ - ASSERT(m_isAbovePriorityCutoff); - if (m_isAbovePriorityCutoff) - m_manager->acquireBackingTextureIfNeeded(this, resourceProvider); -} - -CCResourceProvider::ResourceId CCPrioritizedTexture::resourceId() const -{ - if (m_backing) - return m_backing->id(); - return 0; -} - -void CCPrioritizedTexture::upload(CCResourceProvider* resourceProvider, - const uint8_t* image, const IntRect& imageRect, - const IntRect& sourceRect, const IntSize& destOffset) -{ - ASSERT(m_isAbovePriorityCutoff); - if (m_isAbovePriorityCutoff) - acquireBackingTexture(resourceProvider); - ASSERT(m_backing); - resourceProvider->upload(resourceId(), image, imageRect, sourceRect, destOffset); -} - -void CCPrioritizedTexture::link(Backing* backing) -{ - ASSERT(backing); - ASSERT(!backing->m_owner); - ASSERT(!m_backing); - - m_backing = backing; - m_backing->m_owner = this; -} - -void CCPrioritizedTexture::unlink() -{ - ASSERT(m_backing); - ASSERT(m_backing->m_owner == this); - - m_backing->m_owner = 0; - m_backing = 0; -} - -void CCPrioritizedTexture::setToSelfManagedMemoryPlaceholder(size_t bytes) -{ - setDimensions(IntSize(), GraphicsContext3D::RGBA); - setIsSelfManaged(true); - m_bytes = bytes; -} - -CCPrioritizedTexture::Backing::Backing(unsigned id, CCResourceProvider* resourceProvider, IntSize size, GC3Denum format) - : CCTexture(id, size, format) - , m_owner(0) - , m_priorityAtLastPriorityUpdate(CCPriorityCalculator::lowestPriority()) - , m_ownerExistedAtLastPriorityUpdate(false) - , m_wasAbovePriorityCutoffAtLastPriorityUpdate(false) - , m_resourceHasBeenDeleted(false) -#ifndef NDEBUG - , m_resourceProvider(resourceProvider) -#endif -{ -} - -CCPrioritizedTexture::Backing::~Backing() -{ - ASSERT(!m_owner); - ASSERT(m_resourceHasBeenDeleted); -} - -void CCPrioritizedTexture::Backing::deleteResource(CCResourceProvider* resourceProvider) -{ - ASSERT(CCProxy::isImplThread()); - ASSERT(!m_resourceHasBeenDeleted); -#ifndef NDEBUG - ASSERT(resourceProvider == m_resourceProvider); -#endif - - resourceProvider->deleteResource(id()); - setId(0); - m_resourceHasBeenDeleted = true; -} - -bool CCPrioritizedTexture::Backing::resourceHasBeenDeleted() const -{ - ASSERT(CCProxy::isImplThread()); - return m_resourceHasBeenDeleted; -} - -void CCPrioritizedTexture::Backing::updatePriority() -{ - ASSERT(CCProxy::isImplThread() && CCProxy::isMainThreadBlocked()); - if (m_owner) { - m_ownerExistedAtLastPriorityUpdate = true; - m_priorityAtLastPriorityUpdate = m_owner->requestPriority(); - m_wasAbovePriorityCutoffAtLastPriorityUpdate = m_owner->isAbovePriorityCutoff(); - } else { - m_ownerExistedAtLastPriorityUpdate = false; - m_priorityAtLastPriorityUpdate = CCPriorityCalculator::lowestPriority(); - m_wasAbovePriorityCutoffAtLastPriorityUpdate = false; - } -} - -} // namespace cc diff --git a/cc/CCPrioritizedTexture.h b/cc/CCPrioritizedTexture.h index 3196867..19fdca2 100644 --- a/cc/CCPrioritizedTexture.h +++ b/cc/CCPrioritizedTexture.h @@ -2,141 +2,5 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CCPrioritizedTexture_h -#define CCPrioritizedTexture_h - -#include "base/basictypes.h" -#include "base/memory/scoped_ptr.h" -#include "CCPriorityCalculator.h" -#include "CCResourceProvider.h" -#include "CCTexture.h" -#include "GraphicsContext3D.h" -#include "IntRect.h" -#include "IntSize.h" - -namespace cc { - -class CCPrioritizedTextureManager; - -class CCPrioritizedTexture { -public: - static scoped_ptr create(CCPrioritizedTextureManager* manager, IntSize size, GC3Denum format) - { - return make_scoped_ptr(new CCPrioritizedTexture(manager, size, format)); - } - static scoped_ptr create(CCPrioritizedTextureManager* manager) - { - return make_scoped_ptr(new CCPrioritizedTexture(manager, IntSize(), 0)); - } - ~CCPrioritizedTexture(); - - // Texture properties. Changing these causes the backing texture to be lost. - // Setting these to the same value is a no-op. - void setTextureManager(CCPrioritizedTextureManager*); - CCPrioritizedTextureManager* textureManager() { return m_manager; } - void setDimensions(IntSize, GC3Denum format); - GC3Denum format() const { return m_format; } - IntSize size() const { return m_size; } - size_t bytes() const { return m_bytes; } - - // Set priority for the requested texture. - void setRequestPriority(int priority) { m_priority = priority; } - int requestPriority() const { return m_priority; } - - // After CCPrioritizedTexture::prioritizeTextures() is called, this returns - // if the the request succeeded and this texture can be acquired for use. - bool canAcquireBackingTexture() const { return m_isAbovePriorityCutoff; } - - // This returns whether we still have a backing texture. This can continue - // to be true even after canAcquireBackingTexture() becomes false. In this - // case the texture can be used but shouldn't be updated since it will get - // taken away "soon". - bool haveBackingTexture() const { return !!backing(); } - - bool backingResourceWasEvicted() const; - - // If canAcquireBackingTexture() is true acquireBackingTexture() will acquire - // a backing texture for use. Call this whenever the texture is actually needed. - void acquireBackingTexture(CCResourceProvider*); - - // FIXME: Request late is really a hack for when we are totally out of memory - // (all textures are visible) but we can still squeeze into the limit - // by not painting occluded textures. In this case the manager - // refuses all visible textures and requestLate() will enable - // canAcquireBackingTexture() on a call-order basis. We might want to - // just remove this in the future (carefully) and just make sure we don't - // regress OOMs situations. - bool requestLate(); - - // Uploads pixels into the backing resource. This functions will aquire the backing if needed. - void upload(CCResourceProvider*, const uint8_t* image, const IntRect& imageRect, const IntRect& sourceRect, const IntSize& destOffset); - - CCResourceProvider::ResourceId resourceId() const; - - // Self-managed textures are accounted for when prioritizing other textures, - // but they are not allocated/recycled/deleted, so this needs to be done - // externally. canAcquireBackingTexture() indicates if the texture would have - // been allowed given its priority. - void setIsSelfManaged(bool isSelfManaged) { m_isSelfManaged = isSelfManaged; } - bool isSelfManaged() { return m_isSelfManaged; } - void setToSelfManagedMemoryPlaceholder(size_t bytes); - -private: - friend class CCPrioritizedTextureManager; - friend class CCPrioritizedTextureTest; - - class Backing : public CCTexture { - public: - Backing(unsigned id, CCResourceProvider*, IntSize, GC3Denum format); - ~Backing(); - void updatePriority(); - - CCPrioritizedTexture* owner() { return m_owner; } - bool hadOwnerAtLastPriorityUpdate() const { return m_ownerExistedAtLastPriorityUpdate; } - int requestPriorityAtLastPriorityUpdate() const { return m_priorityAtLastPriorityUpdate; } - bool wasAbovePriorityCutoffAtLastPriorityUpdate() const { return m_wasAbovePriorityCutoffAtLastPriorityUpdate; } - - void deleteResource(CCResourceProvider*); - bool resourceHasBeenDeleted() const; - - private: - friend class CCPrioritizedTexture; - CCPrioritizedTexture* m_owner; - int m_priorityAtLastPriorityUpdate; - bool m_ownerExistedAtLastPriorityUpdate; - bool m_wasAbovePriorityCutoffAtLastPriorityUpdate; - bool m_resourceHasBeenDeleted; -#ifndef NDEBUG - CCResourceProvider* m_resourceProvider; -#endif - - DISALLOW_COPY_AND_ASSIGN(Backing); - }; - - CCPrioritizedTexture(CCPrioritizedTextureManager*, IntSize, GC3Denum format); - - bool isAbovePriorityCutoff() { return m_isAbovePriorityCutoff; } - void setAbovePriorityCutoff(bool isAbovePriorityCutoff) { m_isAbovePriorityCutoff = isAbovePriorityCutoff; } - void setManagerInternal(CCPrioritizedTextureManager* manager) { m_manager = manager; } - - Backing* backing() const { return m_backing; } - void link(Backing*); - void unlink(); - - IntSize m_size; - GC3Denum m_format; - size_t m_bytes; - - int m_priority; - bool m_isAbovePriorityCutoff; - bool m_isSelfManaged; - - Backing* m_backing; - CCPrioritizedTextureManager* m_manager; - - DISALLOW_COPY_AND_ASSIGN(CCPrioritizedTexture); -}; - -} // namespace cc - -#endif +// Temporary forwarding header +#include "cc/prioritized_texture.h" diff --git a/cc/CCPrioritizedTextureManager.cpp b/cc/CCPrioritizedTextureManager.cpp deleted file mode 100644 index a609548..0000000 --- a/cc/CCPrioritizedTextureManager.cpp +++ /dev/null @@ -1,410 +0,0 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "config.h" - -#include "CCPrioritizedTextureManager.h" - -#include "base/stl_util.h" -#include "CCPrioritizedTexture.h" -#include "CCPriorityCalculator.h" -#include "CCProxy.h" -#include "TraceEvent.h" -#include - -using namespace std; - -namespace cc { - -CCPrioritizedTextureManager::CCPrioritizedTextureManager(size_t maxMemoryLimitBytes, int, int pool) - : m_maxMemoryLimitBytes(maxMemoryLimitBytes) - , m_memoryUseBytes(0) - , m_memoryAboveCutoffBytes(0) - , m_memoryAvailableBytes(0) - , m_pool(pool) - , m_needsUpdateBackingsPrioritites(false) -{ -} - -CCPrioritizedTextureManager::~CCPrioritizedTextureManager() -{ - while (m_textures.size() > 0) - unregisterTexture(*m_textures.begin()); - - deleteEvictedBackings(); - - // Each remaining backing is a leaked opengl texture. There should be none. - ASSERT(m_backings.isEmpty()); -} - -void CCPrioritizedTextureManager::prioritizeTextures() -{ - TRACE_EVENT0("cc", "CCPrioritizedTextureManager::prioritizeTextures"); - ASSERT(CCProxy::isMainThread()); - - // Sorting textures in this function could be replaced by a slightly - // modified O(n) quick-select to partition textures rather than - // sort them (if performance of the sort becomes an issue). - - TextureVector& sortedTextures = m_tempTextureVector; - sortedTextures.clear(); - - // Copy all textures into a vector and sort them. - for (TextureSet::iterator it = m_textures.begin(); it != m_textures.end(); ++it) - sortedTextures.append(*it); - std::sort(sortedTextures.begin(), sortedTextures.end(), compareTextures); - - m_memoryAvailableBytes = m_maxMemoryLimitBytes; - m_priorityCutoff = CCPriorityCalculator::lowestPriority(); - size_t memoryBytes = 0; - for (TextureVector::iterator it = sortedTextures.begin(); it != sortedTextures.end(); ++it) { - if ((*it)->requestPriority() == CCPriorityCalculator::lowestPriority()) - break; - - if ((*it)->isSelfManaged()) { - // Account for self-managed memory immediately by reducing the memory - // available (since it never gets acquired). - size_t newMemoryBytes = memoryBytes + (*it)->bytes(); - if (newMemoryBytes > m_memoryAvailableBytes) { - m_priorityCutoff = (*it)->requestPriority(); - m_memoryAvailableBytes = memoryBytes; - break; - } - m_memoryAvailableBytes -= (*it)->bytes(); - } else { - size_t newMemoryBytes = memoryBytes + (*it)->bytes(); - if (newMemoryBytes > m_memoryAvailableBytes) { - m_priorityCutoff = (*it)->requestPriority(); - break; - } - memoryBytes = newMemoryBytes; - } - } - - // Only allow textures if they are higher than the cutoff. All textures - // of the same priority are accepted or rejected together, rather than - // being partially allowed randomly. - m_memoryAboveCutoffBytes = 0; - for (TextureVector::iterator it = sortedTextures.begin(); it != sortedTextures.end(); ++it) { - bool isAbovePriorityCutoff = CCPriorityCalculator::priorityIsHigher((*it)->requestPriority(), m_priorityCutoff); - (*it)->setAbovePriorityCutoff(isAbovePriorityCutoff); - if (isAbovePriorityCutoff && !(*it)->isSelfManaged()) - m_memoryAboveCutoffBytes += (*it)->bytes(); - } - sortedTextures.clear(); - - m_needsUpdateBackingsPrioritites = true; - - ASSERT(m_memoryAboveCutoffBytes <= m_memoryAvailableBytes); - ASSERT(memoryAboveCutoffBytes() <= maxMemoryLimitBytes()); -} - -void CCPrioritizedTextureManager::updateBackingsPriorities() -{ - TRACE_EVENT0("cc", "CCPrioritizedTextureManager::updateBackingsPriorities"); - ASSERT(CCProxy::isImplThread() && CCProxy::isMainThreadBlocked()); - - if (!m_needsUpdateBackingsPrioritites) - return; - -#if !ASSERT_DISABLED - assertInvariants(); -#endif - - // Update backings' priorities and put backings in eviction/recycling order. - BackingVector& sortedBackings = m_tempBackingVector; - sortedBackings.clear(); - for (BackingSet::iterator it = m_backings.begin(); it != m_backings.end(); ++it) { - (*it)->updatePriority(); - sortedBackings.append(*it); - } - std::sort(sortedBackings.begin(), sortedBackings.end(), compareBackings); - - for (BackingVector::iterator it = sortedBackings.begin(); it != sortedBackings.end(); ++it) { - m_backings.remove(*it); - m_backings.add(*it); - } - sortedBackings.clear(); - m_needsUpdateBackingsPrioritites = false; - -#if !ASSERT_DISABLED - assertInvariants(); -#endif -} - -void CCPrioritizedTextureManager::clearPriorities() -{ - ASSERT(CCProxy::isMainThread()); - for (TextureSet::iterator it = m_textures.begin(); it != m_textures.end(); ++it) { - // FIXME: We should remove this and just set all priorities to - // CCPriorityCalculator::lowestPriority() once we have priorities - // for all textures (we can't currently calculate distances for - // off-screen textures). - (*it)->setRequestPriority(CCPriorityCalculator::lingeringPriority((*it)->requestPriority())); - } -} - -bool CCPrioritizedTextureManager::requestLate(CCPrioritizedTexture* texture) -{ - ASSERT(CCProxy::isMainThread()); - - // This is already above cutoff, so don't double count it's memory below. - if (texture->isAbovePriorityCutoff()) - return true; - - if (CCPriorityCalculator::priorityIsLower(texture->requestPriority(), m_priorityCutoff)) - return false; - - size_t newMemoryBytes = m_memoryAboveCutoffBytes + texture->bytes(); - if (newMemoryBytes > m_memoryAvailableBytes) - return false; - - m_memoryAboveCutoffBytes = newMemoryBytes; - texture->setAbovePriorityCutoff(true); - m_needsUpdateBackingsPrioritites = true; - return true; -} - -void CCPrioritizedTextureManager::acquireBackingTextureIfNeeded(CCPrioritizedTexture* texture, CCResourceProvider* resourceProvider) -{ - ASSERT(CCProxy::isImplThread() && CCProxy::isMainThreadBlocked()); - ASSERT(!texture->isSelfManaged()); - ASSERT(texture->isAbovePriorityCutoff()); - if (texture->backing() || !texture->isAbovePriorityCutoff()) - return; - - // Make sure that the backings list is up to date and sorted before traversing it. - updateBackingsPriorities(); - - // Find a backing below, by either recycling or allocating. - CCPrioritizedTexture::Backing* backing = 0; - - // First try to recycle - for (BackingSet::iterator it = m_backings.begin(); it != m_backings.end(); ++it) { - if ((*it)->hadOwnerAtLastPriorityUpdate() && (*it)->wasAbovePriorityCutoffAtLastPriorityUpdate()) - break; - if ((*it)->size() == texture->size() && (*it)->format() == texture->format()) { - backing = (*it); - break; - } - } - - // Otherwise reduce memory and just allocate a new backing texures. - if (!backing) { - evictBackingsToReduceMemory(m_memoryAvailableBytes - texture->bytes(), RespectManagerPriorityCutoff, resourceProvider); - backing = createBacking(texture->size(), texture->format(), resourceProvider); - } - - // Move the used backing texture to the end of the eviction list. - if (backing->owner()) - backing->owner()->unlink(); - texture->link(backing); - m_backings.remove(backing); - m_backings.add(backing); - - // Update the backing's priority from its new owner. - backing->updatePriority(); -} - -void CCPrioritizedTextureManager::evictBackingsToReduceMemory(size_t limitBytes, EvictionPriorityPolicy evictionPolicy, CCResourceProvider* resourceProvider) -{ - ASSERT(CCProxy::isImplThread()); - if (memoryUseBytes() <= limitBytes) - return; - - // Destroy backings until we are below the limit, - // or until all backings remaining are above the cutoff. - while (memoryUseBytes() > limitBytes && m_backings.size() > 0) { - CCPrioritizedTexture::Backing* backing = *m_backings.begin(); - if (evictionPolicy == RespectManagerPriorityCutoff) - if (backing->hadOwnerAtLastPriorityUpdate() && backing->wasAbovePriorityCutoffAtLastPriorityUpdate()) - break; - evictBackingResource(backing, resourceProvider); - } -} - -void CCPrioritizedTextureManager::reduceMemory(CCResourceProvider* resourceProvider) -{ - ASSERT(CCProxy::isImplThread() && CCProxy::isMainThreadBlocked()); - - // Make sure that the backings list is up to date and sorted before traversing it. - updateBackingsPriorities(); - - evictBackingsToReduceMemory(m_memoryAvailableBytes, RespectManagerPriorityCutoff, resourceProvider); - ASSERT(memoryUseBytes() <= maxMemoryLimitBytes()); - - // We currently collect backings from deleted textures for later recycling. - // However, if we do that forever we will always use the max limit even if - // we really need very little memory. This should probably be solved by reducing the - // limit externally, but until then this just does some "clean up" of unused - // backing textures (any more than 10%). - size_t wastedMemory = 0; - for (BackingSet::iterator it = m_backings.begin(); it != m_backings.end(); ++it) { - if ((*it)->owner()) - break; - wastedMemory += (*it)->bytes(); - } - size_t tenPercentOfMemory = m_memoryAvailableBytes / 10; - if (wastedMemory > tenPercentOfMemory) - evictBackingsToReduceMemory(memoryUseBytes() - (wastedMemory - tenPercentOfMemory), RespectManagerPriorityCutoff, resourceProvider); - - deleteEvictedBackings(); -} - -void CCPrioritizedTextureManager::clearAllMemory(CCResourceProvider* resourceProvider) -{ - ASSERT(CCProxy::isImplThread() && CCProxy::isMainThreadBlocked()); - ASSERT(resourceProvider); - evictBackingsToReduceMemory(0, DoNotRespectManagerPriorityCutoff, resourceProvider); - deleteEvictedBackings(); -} - -void CCPrioritizedTextureManager::reduceMemoryOnImplThread(size_t limitBytes, CCResourceProvider* resourceProvider) -{ - ASSERT(CCProxy::isImplThread()); - ASSERT(resourceProvider); - evictBackingsToReduceMemory(limitBytes, DoNotRespectManagerPriorityCutoff, resourceProvider); -} - -void CCPrioritizedTextureManager::getEvictedBackings(BackingVector& evictedBackings) -{ - ASSERT(CCProxy::isImplThread()); - evictedBackings.clear(); - evictedBackings.append(m_evictedBackings); -} - -void CCPrioritizedTextureManager::unlinkEvictedBackings(const BackingVector& evictedBackings) -{ - ASSERT(CCProxy::isMainThread()); - for (BackingVector::const_iterator it = evictedBackings.begin(); it != evictedBackings.end(); ++it) { - CCPrioritizedTexture::Backing* backing = (*it); - if (backing->owner()) - backing->owner()->unlink(); - } -} - -bool CCPrioritizedTextureManager::deleteEvictedBackings() -{ - ASSERT(CCProxy::isMainThread() || (CCProxy::isImplThread() && CCProxy::isMainThreadBlocked())); - bool linkedEvictedBackingsExisted = false; - for (BackingVector::const_iterator it = m_evictedBackings.begin(); it != m_evictedBackings.end(); ++it) { - CCPrioritizedTexture::Backing* backing = (*it); - if (backing->owner()) { - linkedEvictedBackingsExisted = true; - backing->owner()->unlink(); - } - delete backing; - } - m_evictedBackings.clear(); - return linkedEvictedBackingsExisted; -} - -void CCPrioritizedTextureManager::registerTexture(CCPrioritizedTexture* texture) -{ - ASSERT(CCProxy::isMainThread()); - ASSERT(texture); - ASSERT(!texture->textureManager()); - ASSERT(!texture->backing()); - ASSERT(!ContainsKey(m_textures, texture)); - - texture->setManagerInternal(this); - m_textures.insert(texture); - -} - -void CCPrioritizedTextureManager::unregisterTexture(CCPrioritizedTexture* texture) -{ - ASSERT(CCProxy::isMainThread() || (CCProxy::isImplThread() && CCProxy::isMainThreadBlocked())); - ASSERT(texture); - ASSERT(ContainsKey(m_textures, texture)); - - returnBackingTexture(texture); - texture->setManagerInternal(0); - m_textures.erase(texture); - texture->setAbovePriorityCutoff(false); -} - -void CCPrioritizedTextureManager::returnBackingTexture(CCPrioritizedTexture* texture) -{ - ASSERT(CCProxy::isMainThread() || (CCProxy::isImplThread() && CCProxy::isMainThreadBlocked())); - if (texture->backing()) { - texture->unlink(); - m_needsUpdateBackingsPrioritites = true; - } -} - -CCPrioritizedTexture::Backing* CCPrioritizedTextureManager::createBacking(IntSize size, GC3Denum format, CCResourceProvider* resourceProvider) -{ - ASSERT(CCProxy::isImplThread() && CCProxy::isMainThreadBlocked()); - ASSERT(resourceProvider); - CCResourceProvider::ResourceId resourceId = resourceProvider->createResource(m_pool, size, format, CCResourceProvider::TextureUsageAny); - CCPrioritizedTexture::Backing* backing = new CCPrioritizedTexture::Backing(resourceId, resourceProvider, size, format); - m_memoryUseBytes += backing->bytes(); - // Put backing texture at the front for eviction, since it isn't in use yet. - m_backings.insertBefore(m_backings.begin(), backing); - return backing; -} - -void CCPrioritizedTextureManager::evictBackingResource(CCPrioritizedTexture::Backing* backing, CCResourceProvider* resourceProvider) -{ - ASSERT(CCProxy::isImplThread()); - ASSERT(backing); - ASSERT(resourceProvider); - ASSERT(m_backings.find(backing) != m_backings.end()); - - // Note that we create a backing and its resource at the same time, but we - // delete the backing structure and its resource in two steps. This is because - // we can delete the resource while the main thread is running, but we cannot - // unlink backings while the main thread is running. - backing->deleteResource(resourceProvider); - m_memoryUseBytes -= backing->bytes(); - m_backings.remove(backing); - m_evictedBackings.append(backing); -} - -#if !ASSERT_DISABLED -void CCPrioritizedTextureManager::assertInvariants() -{ - ASSERT(CCProxy::isImplThread() && CCProxy::isMainThreadBlocked()); - - // If we hit any of these asserts, there is a bug in this class. To see - // where the bug is, call this function at the beginning and end of - // every public function. - - // Backings/textures must be doubly-linked and only to other backings/textures in this manager. - for (BackingSet::iterator it = m_backings.begin(); it != m_backings.end(); ++it) { - if ((*it)->owner()) { - ASSERT(ContainsKey(m_textures, (*it)->owner())); - ASSERT((*it)->owner()->backing() == (*it)); - } - } - for (TextureSet::iterator it = m_textures.begin(); it != m_textures.end(); ++it) { - if ((*it)->backing()) { - ASSERT(m_backings.find((*it)->backing()) != m_backings.end()); - ASSERT((*it)->backing()->owner() == (*it)); - } - } - - // At all times, backings that can be evicted must always come before - // backings that can't be evicted in the backing texture list (otherwise - // reduceMemory will not find all textures available for eviction/recycling). - bool reachedOwned = false; - bool reachedAboveCutoff = false; - for (BackingSet::iterator it = m_backings.begin(); it != m_backings.end(); ++it) { - if ((*it)->hadOwnerAtLastPriorityUpdate()) - reachedOwned = true; - if ((*it)->wasAbovePriorityCutoffAtLastPriorityUpdate()) - reachedAboveCutoff = true; - if (reachedOwned) - ASSERT((*it)->hadOwnerAtLastPriorityUpdate()); - if (reachedAboveCutoff) { - ASSERT((*it)->hadOwnerAtLastPriorityUpdate() && (*it)->wasAbovePriorityCutoffAtLastPriorityUpdate()); - ASSERT(reachedOwned); - } - } -} -#endif - - -} // namespace cc diff --git a/cc/CCPrioritizedTextureManager.h b/cc/CCPrioritizedTextureManager.h index 1b3b1ed..cfeb804 100644 --- a/cc/CCPrioritizedTextureManager.h +++ b/cc/CCPrioritizedTextureManager.h @@ -2,158 +2,5 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CCPrioritizedTextureManager_h -#define CCPrioritizedTextureManager_h - -#include "base/basictypes.h" -#include "base/hash_tables.h" -#include "base/memory/scoped_ptr.h" -#include "CCPrioritizedTexture.h" -#include "CCPriorityCalculator.h" -#include "CCTexture.h" -#include "GraphicsContext3D.h" -#include "IntRect.h" -#include "IntSize.h" -#include -#include - -#if defined(COMPILER_GCC) -namespace BASE_HASH_NAMESPACE { -template<> -struct hash { - size_t operator()(cc::CCPrioritizedTexture* ptr) const { - return hash()(reinterpret_cast(ptr)); - } -}; -} // namespace BASE_HASH_NAMESPACE -#endif // COMPILER - -namespace cc { - -class CCPriorityCalculator; - -class CCPrioritizedTextureManager { -public: - static scoped_ptr create(size_t maxMemoryLimitBytes, int maxTextureSize, int pool) - { - return make_scoped_ptr(new CCPrioritizedTextureManager(maxMemoryLimitBytes, maxTextureSize, pool)); - } - scoped_ptr createTexture(IntSize size, GC3Denum format) - { - return make_scoped_ptr(new CCPrioritizedTexture(this, size, format)); - } - ~CCPrioritizedTextureManager(); - - typedef Vector BackingVector; - - // FIXME (http://crbug.com/137094): This 64MB default is a straggler from the - // old texture manager and is just to give us a default memory allocation before - // we get a callback from the GPU memory manager. We should probaby either: - // - wait for the callback before rendering anything instead - // - push this into the GPU memory manager somehow. - static size_t defaultMemoryAllocationLimit() { return 64 * 1024 * 1024; } - - // memoryUseBytes() describes the number of bytes used by existing allocated textures. - // memoryAboveCutoffBytes() describes the number of bytes that would be used if all - // textures that are above the cutoff were allocated. - // memoryUseBytes() <= memoryAboveCutoffBytes() should always be true. - size_t memoryUseBytes() const { return m_memoryUseBytes; } - size_t memoryAboveCutoffBytes() const { return m_memoryAboveCutoffBytes; } - size_t memoryForSelfManagedTextures() const { return m_maxMemoryLimitBytes - m_memoryAvailableBytes; } - - void setMaxMemoryLimitBytes(size_t bytes) { m_maxMemoryLimitBytes = bytes; } - size_t maxMemoryLimitBytes() const { return m_maxMemoryLimitBytes; } - - void prioritizeTextures(); - void clearPriorities(); - - void reduceMemoryOnImplThread(size_t limitBytes, CCResourceProvider*); - bool evictedBackingsExist() const { return !m_evictedBackings.isEmpty(); } - void getEvictedBackings(BackingVector& evictedBackings); - void unlinkEvictedBackings(const BackingVector& evictedBackings); - // Deletes all evicted backings, unlinking them from their owning textures if needed. - // Returns true if this function unlinked any backings from their owning texture while - // destroying them. - bool deleteEvictedBackings(); - - bool requestLate(CCPrioritizedTexture*); - - void reduceMemory(CCResourceProvider*); - void clearAllMemory(CCResourceProvider*); - - void acquireBackingTextureIfNeeded(CCPrioritizedTexture*, CCResourceProvider*); - - void registerTexture(CCPrioritizedTexture*); - void unregisterTexture(CCPrioritizedTexture*); - void returnBackingTexture(CCPrioritizedTexture*); - -private: - friend class CCPrioritizedTextureTest; - - enum EvictionPriorityPolicy { - RespectManagerPriorityCutoff, - DoNotRespectManagerPriorityCutoff, - }; - - // Compare textures. Highest priority first. - static inline bool compareTextures(CCPrioritizedTexture* a, CCPrioritizedTexture* b) - { - if (a->requestPriority() == b->requestPriority()) - return a < b; - return CCPriorityCalculator::priorityIsHigher(a->requestPriority(), b->requestPriority()); - } - // Compare backings. Lowest priority first. - static inline bool compareBackings(CCPrioritizedTexture::Backing* a, CCPrioritizedTexture::Backing* b) - { - int priorityA = a->requestPriorityAtLastPriorityUpdate(); - int priorityB = b->requestPriorityAtLastPriorityUpdate(); - if (priorityA != priorityB) - return CCPriorityCalculator::priorityIsLower(priorityA, priorityB); - bool aboveCutoffA = a->wasAbovePriorityCutoffAtLastPriorityUpdate(); - bool aboveCutoffB = b->wasAbovePriorityCutoffAtLastPriorityUpdate(); - if (!aboveCutoffA && aboveCutoffB) - return true; - if (aboveCutoffA && !aboveCutoffB) - return false; - return a < b; - } - - CCPrioritizedTextureManager(size_t maxMemoryLimitBytes, int maxTextureSize, int pool); - - void updateBackingsPriorities(); - void evictBackingsToReduceMemory(size_t limitBytes, EvictionPriorityPolicy, CCResourceProvider*); - CCPrioritizedTexture::Backing* createBacking(IntSize, GC3Denum format, CCResourceProvider*); - void evictBackingResource(CCPrioritizedTexture::Backing*, CCResourceProvider*); - -#if !ASSERT_DISABLED - void assertInvariants(); -#endif - - size_t m_maxMemoryLimitBytes; - unsigned m_priorityCutoff; - size_t m_memoryUseBytes; - size_t m_memoryAboveCutoffBytes; - size_t m_memoryAvailableBytes; - int m_pool; - - typedef base::hash_set TextureSet; - typedef ListHashSet BackingSet; - typedef Vector TextureVector; - - TextureSet m_textures; - BackingSet m_backings; - BackingVector m_evictedBackings; - - TextureVector m_tempTextureVector; - BackingVector m_tempBackingVector; - - // Set by the main thread when it adjust priorities in such a way that - // the m_backings array's view of priorities is now out of date. - bool m_needsUpdateBackingsPrioritites; - - DISALLOW_COPY_AND_ASSIGN(CCPrioritizedTextureManager); -}; - -} // namespace cc - -#endif +// Temporary forwarding header +#include "cc/prioritized_texture_manager.h" diff --git a/cc/CCPriorityCalculator.cpp b/cc/CCPriorityCalculator.cpp deleted file mode 100644 index 055520c..0000000 --- a/cc/CCPriorityCalculator.cpp +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "config.h" - -#include "CCPriorityCalculator.h" - -using namespace std; - -namespace cc { - -static const int uiDrawsToRootSurfacePriority = -1; -static const int visibleDrawsToRootSurfacePriority = 0; -static const int renderSurfacesPriority = 1; -static const int uiDoesNotDrawToRootSurfacePriority = 2; -static const int visibleDoesNotDrawToRootSurfacePriority = 3; - -// The lower digits are how far from being visible the texture is, -// in pixels. -static const int notVisibleBasePriority = 1000000; -static const int notVisibleLimitPriority = 1900000; - -// Small animated layers are treated as though they are 512 pixels -// from being visible. -static const int smallAnimatedLayerPriority = notVisibleBasePriority + 512; - -static const int lingeringBasePriority = 2000000; -static const int lingeringLimitPriority = 2900000; - -// static -int CCPriorityCalculator::uiPriority(bool drawsToRootSurface) -{ - return drawsToRootSurface ? uiDrawsToRootSurfacePriority : uiDoesNotDrawToRootSurfacePriority; -} - -// static -int CCPriorityCalculator::visiblePriority(bool drawsToRootSurface) -{ - return drawsToRootSurface ? visibleDrawsToRootSurfacePriority : visibleDoesNotDrawToRootSurfacePriority; -} - -// static -int CCPriorityCalculator::renderSurfacePriority() -{ - return renderSurfacesPriority; -} - -// static -int CCPriorityCalculator::lingeringPriority(int previousPriority) -{ - // FIXME: We should remove this once we have priorities for all - // textures (we can't currently calculate distances for - // off-screen textures). - return min(lingeringLimitPriority, - max(lingeringBasePriority, previousPriority + 1)); -} - -namespace { -int manhattanDistance(const IntRect& a, const IntRect& b) -{ - IntRect c = unionRect(a, b); - int x = max(0, c.width() - a.width() - b.width() + 1); - int y = max(0, c.height() - a.height() - b.height() + 1); - return (x + y); -} -} - -// static -int CCPriorityCalculator::priorityFromDistance(const IntRect& visibleRect, const IntRect& textureRect, bool drawsToRootSurface) -{ - int distance = manhattanDistance(visibleRect, textureRect); - if (!distance) - return visiblePriority(drawsToRootSurface); - return min(notVisibleLimitPriority, notVisibleBasePriority + distance); -} - -// static -int CCPriorityCalculator::smallAnimatedLayerMinPriority() -{ - return smallAnimatedLayerPriority; -} - -} // cc diff --git a/cc/CCPriorityCalculator.h b/cc/CCPriorityCalculator.h index 45f2e64..973da9f 100644 --- a/cc/CCPriorityCalculator.h +++ b/cc/CCPriorityCalculator.h @@ -1,32 +1,6 @@ -// Copyright 2010 The Chromium Authors. All rights reserved. +// Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CCPriorityCalculator_h -#define CCPriorityCalculator_h - -#include "GraphicsContext3D.h" -#include "IntRect.h" -#include "IntSize.h" - -namespace cc { - -class CCPriorityCalculator { -public: - static int uiPriority(bool drawsToRootSurface); - static int visiblePriority(bool drawsToRootSurface); - static int renderSurfacePriority(); - static int lingeringPriority(int previousPriority); - static int priorityFromDistance(const IntRect& visibleRect, const IntRect& textureRect, bool drawsToRootSurface); - static int smallAnimatedLayerMinPriority(); - - static inline int highestPriority() { return std::numeric_limits::min(); } - static inline int lowestPriority() { return std::numeric_limits::max(); } - static inline bool priorityIsLower(int a, int b) { return a > b; } - static inline bool priorityIsHigher(int a, int b) { return a < b; } - static inline bool maxPriority(int a, int b) { return priorityIsHigher(a, b) ? a : b; } -}; - -} - -#endif +// Temporary forwarding header +#include "cc/priority_calculator.h" diff --git a/cc/CCProxy.cpp b/cc/CCProxy.cpp deleted file mode 100644 index bc5ae69..0000000 --- a/cc/CCProxy.cpp +++ /dev/null @@ -1,105 +0,0 @@ -// Copyright 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "config.h" - -#include "CCProxy.h" - -#include "CCThreadTask.h" - -using namespace WTF; - -namespace cc { - -namespace { -#ifndef NDEBUG -bool implThreadIsOverridden = false; -bool s_isMainThreadBlocked = false; -base::PlatformThreadId threadIDOverridenToBeImplThread; -#endif -CCThread* s_mainThread = 0; -CCThread* s_implThread = 0; -} - -void CCProxy::setMainThread(CCThread* thread) -{ - s_mainThread = thread; -} - -CCThread* CCProxy::mainThread() -{ - return s_mainThread; -} - -bool CCProxy::hasImplThread() -{ - return s_implThread; -} - -void CCProxy::setImplThread(CCThread* thread) -{ - s_implThread = thread; -} - -CCThread* CCProxy::implThread() -{ - return s_implThread; -} - -CCThread* CCProxy::currentThread() -{ - base::PlatformThreadId currentThreadIdentifier = base::PlatformThread::CurrentId(); - if (s_mainThread && s_mainThread->threadID() == currentThreadIdentifier) - return s_mainThread; - if (s_implThread && s_implThread->threadID() == currentThreadIdentifier) - return s_implThread; - return 0; -} - -#ifndef NDEBUG -bool CCProxy::isMainThread() -{ - ASSERT(s_mainThread); - if (implThreadIsOverridden && base::PlatformThread::CurrentId() == threadIDOverridenToBeImplThread) - return false; - return base::PlatformThread::CurrentId() == s_mainThread->threadID(); -} - -bool CCProxy::isImplThread() -{ - base::PlatformThreadId implThreadID = s_implThread ? s_implThread->threadID() : 0; - if (implThreadIsOverridden && base::PlatformThread::CurrentId() == threadIDOverridenToBeImplThread) - return true; - return base::PlatformThread::CurrentId() == implThreadID; -} - -void CCProxy::setCurrentThreadIsImplThread(bool isImplThread) -{ - implThreadIsOverridden = isImplThread; - if (isImplThread) - threadIDOverridenToBeImplThread = base::PlatformThread::CurrentId(); -} - -bool CCProxy::isMainThreadBlocked() -{ - return s_isMainThreadBlocked; -} - -void CCProxy::setMainThreadBlocked(bool isMainThreadBlocked) -{ - s_isMainThreadBlocked = isMainThreadBlocked; -} -#endif - -CCProxy::CCProxy() -{ - ASSERT(isMainThread()); -} - -CCProxy::~CCProxy() -{ - ASSERT(isMainThread()); -} - -} diff --git a/cc/CCProxy.h b/cc/CCProxy.h index 30a62cc..012f06f 100644 --- a/cc/CCProxy.h +++ b/cc/CCProxy.h @@ -1,129 +1,6 @@ -// Copyright 2011 The Chromium Authors. All rights reserved. +// Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CCProxy_h -#define CCProxy_h - -#include "base/basictypes.h" -#include -#include -#include - -namespace cc { - -class CCThread; -class IntRect; -class IntSize; -struct CCRenderingStats; -struct RendererCapabilities; - -// Abstract class responsible for proxying commands from the main-thread side of -// the compositor over to the compositor implementation. -class CCProxy { -public: - static void setMainThread(CCThread*); - static CCThread* mainThread(); - - static bool hasImplThread(); - static void setImplThread(CCThread*); - static CCThread* implThread(); - - // Returns 0 if the current thread is neither the main thread nor the impl thread. - static CCThread* currentThread(); - - virtual ~CCProxy(); - - virtual bool compositeAndReadback(void *pixels, const IntRect&) = 0; - - virtual void startPageScaleAnimation(const IntSize& targetPosition, bool useAnchor, float scale, double durationSec) = 0; - - virtual void finishAllRendering() = 0; - - virtual bool isStarted() const = 0; - - // Attempts to initialize a context to use for rendering. Returns false if the context could not be created. - // The context will not be used and no frames may be produced until initializeRenderer() is called. - virtual bool initializeContext() = 0; - - // Indicates that the compositing surface associated with our context is ready to use. - virtual void setSurfaceReady() = 0; - - virtual void setVisible(bool) = 0; - - // Attempts to initialize the layer renderer. Returns false if the context isn't usable for compositing. - virtual bool initializeRenderer() = 0; - - // Attempts to recreate the context and layer renderer after a context lost. Returns false if the renderer couldn't be - // reinitialized. - virtual bool recreateContext() = 0; - - virtual void renderingStats(CCRenderingStats*) = 0; - - virtual const RendererCapabilities& rendererCapabilities() const = 0; - - virtual void setNeedsAnimate() = 0; - virtual void setNeedsCommit() = 0; - virtual void setNeedsRedraw() = 0; - - virtual void didAddAnimation() = 0; - - virtual bool commitRequested() const = 0; - - virtual void start() = 0; // Must be called before using the proxy. - virtual void stop() = 0; // Must be called before deleting the proxy. - - // Forces 3D commands on all contexts to wait for all previous SwapBuffers to finish before executing in the GPU - // process. - virtual void forceSerializeOnSwapBuffers() = 0; - - // Maximum number of sub-region texture updates supported for each commit. - virtual size_t maxPartialTextureUpdates() const = 0; - - virtual void acquireLayerTextures() = 0; - - // Debug hooks -#ifndef NDEBUG - static bool isMainThread(); - static bool isImplThread(); - static bool isMainThreadBlocked(); - static void setMainThreadBlocked(bool); -#endif - - // Testing hooks - virtual void loseContext() = 0; - -#ifndef NDEBUG - static void setCurrentThreadIsImplThread(bool); -#endif - -protected: - CCProxy(); - friend class DebugScopedSetImplThread; - friend class DebugScopedSetMainThreadBlocked; - -private: - DISALLOW_COPY_AND_ASSIGN(CCProxy); -}; - -class DebugScopedSetMainThreadBlocked { -public: - DebugScopedSetMainThreadBlocked() - { -#if !ASSERT_DISABLED - ASSERT(!CCProxy::isMainThreadBlocked()); - CCProxy::setMainThreadBlocked(true); -#endif - } - ~DebugScopedSetMainThreadBlocked() - { -#if !ASSERT_DISABLED - ASSERT(CCProxy::isMainThreadBlocked()); - CCProxy::setMainThreadBlocked(false); -#endif - } -}; - -} - -#endif +// Temporary forwarding header +#include "cc/proxy.h" diff --git a/cc/CCQuadCuller.cpp b/cc/CCQuadCuller.cpp deleted file mode 100644 index 8955a98..0000000 --- a/cc/CCQuadCuller.cpp +++ /dev/null @@ -1,94 +0,0 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "config.h" - -#if USE(ACCELERATED_COMPOSITING) - -#include "CCQuadCuller.h" - -#include "CCAppendQuadsData.h" -#include "CCDebugBorderDrawQuad.h" -#include "CCLayerImpl.h" -#include "CCOcclusionTracker.h" -#include "CCOverdrawMetrics.h" -#include "CCRenderPass.h" -#include "Region.h" -#include "SkColor.h" -#include - -using namespace std; - -namespace cc { - -static const int debugTileBorderWidth = 1; -static const int debugTileBorderAlpha = 120; -static const int debugTileBorderColorRed = 160; -static const int debugTileBorderColorGreen = 100; -static const int debugTileBorderColorBlue = 0; - -CCQuadCuller::CCQuadCuller(CCQuadList& quadList, CCSharedQuadStateList& sharedQuadStateList, CCLayerImpl* layer, const CCOcclusionTrackerImpl* occlusionTracker, bool showCullingWithDebugBorderQuads, bool forSurface) - : m_quadList(quadList) - , m_sharedQuadStateList(sharedQuadStateList) - , m_currentSharedQuadState(0) - , m_layer(layer) - , m_occlusionTracker(occlusionTracker) - , m_showCullingWithDebugBorderQuads(showCullingWithDebugBorderQuads) - , m_forSurface(forSurface) -{ -} - -CCSharedQuadState* CCQuadCuller::useSharedQuadState(scoped_ptr sharedQuadState) -{ - sharedQuadState->id = m_sharedQuadStateList.size(); - - // FIXME: If all quads are culled for the sharedQuadState, we can drop it from the list. - m_currentSharedQuadState = sharedQuadState.get(); - m_sharedQuadStateList.append(sharedQuadState.Pass()); - return m_currentSharedQuadState; -} - -static inline bool appendQuadInternal(scoped_ptr drawQuad, const IntRect& culledRect, CCQuadList& quadList, const CCOcclusionTrackerImpl& occlusionTracker, bool createDebugBorderQuads) -{ - bool keepQuad = !culledRect.isEmpty(); - if (keepQuad) - drawQuad->setQuadVisibleRect(culledRect); - - occlusionTracker.overdrawMetrics().didCullForDrawing(drawQuad->quadTransform(), drawQuad->quadRect(), culledRect); - occlusionTracker.overdrawMetrics().didDraw(drawQuad->quadTransform(), culledRect, drawQuad->opaqueRect()); - - if (keepQuad) { - if (createDebugBorderQuads && !drawQuad->isDebugQuad() && drawQuad->quadVisibleRect() != drawQuad->quadRect()) { - SkColor borderColor = SkColorSetARGB(debugTileBorderAlpha, debugTileBorderColorRed, debugTileBorderColorGreen, debugTileBorderColorBlue); - quadList.append(CCDebugBorderDrawQuad::create(drawQuad->sharedQuadState(), drawQuad->quadVisibleRect(), borderColor, debugTileBorderWidth).PassAs()); - } - - // Pass the quad after we're done using it. - quadList.append(drawQuad.Pass()); - } - return keepQuad; -} - -bool CCQuadCuller::append(scoped_ptr drawQuad, CCAppendQuadsData& appendQuadsData) -{ - ASSERT(drawQuad->sharedQuadState() == m_currentSharedQuadState); - ASSERT(drawQuad->sharedQuadStateId() == m_currentSharedQuadState->id); - ASSERT(!m_sharedQuadStateList.isEmpty()); - ASSERT(m_sharedQuadStateList.last() == m_currentSharedQuadState); - - IntRect culledRect; - bool hasOcclusionFromOutsideTargetSurface; - - if (m_forSurface) - culledRect = m_occlusionTracker->unoccludedContributingSurfaceContentRect(m_layer, false, drawQuad->quadRect(), &hasOcclusionFromOutsideTargetSurface); - else - culledRect = m_occlusionTracker->unoccludedContentRect(m_layer, drawQuad->quadRect(), &hasOcclusionFromOutsideTargetSurface); - - appendQuadsData.hadOcclusionFromOutsideTargetSurface |= hasOcclusionFromOutsideTargetSurface; - - return appendQuadInternal(drawQuad.Pass(), culledRect, m_quadList, *m_occlusionTracker, m_showCullingWithDebugBorderQuads); -} - -} // namespace cc -#endif // USE(ACCELERATED_COMPOSITING) diff --git a/cc/CCQuadCuller.h b/cc/CCQuadCuller.h index b3927cc..097fb78 100644 --- a/cc/CCQuadCuller.h +++ b/cc/CCQuadCuller.h @@ -2,36 +2,5 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CCQuadCuller_h -#define CCQuadCuller_h - -#include "CCQuadSink.h" -#include "CCRenderPass.h" - -namespace cc { -class CCLayerImpl; -class CCRenderSurface; -template -class CCOcclusionTrackerBase; - -class CCQuadCuller : public CCQuadSink { -public: - CCQuadCuller(CCQuadList&, CCSharedQuadStateList&, CCLayerImpl*, const CCOcclusionTrackerBase*, bool showCullingWithDebugBorderQuads, bool forSurface); - virtual ~CCQuadCuller() { } - - // CCQuadSink implementation. - virtual CCSharedQuadState* useSharedQuadState(scoped_ptr) OVERRIDE; - virtual bool append(scoped_ptr, CCAppendQuadsData&) OVERRIDE; - -private: - CCQuadList& m_quadList; - CCSharedQuadStateList& m_sharedQuadStateList; - CCSharedQuadState* m_currentSharedQuadState; - CCLayerImpl* m_layer; - const CCOcclusionTrackerBase* m_occlusionTracker; - bool m_showCullingWithDebugBorderQuads; - bool m_forSurface; -}; - -} -#endif // CCQuadCuller_h +// Temporary forwarding header +#include "cc/quad_culler.h" diff --git a/cc/CCQuadSink.h b/cc/CCQuadSink.h index 06d31b0..a503c6c 100644 --- a/cc/CCQuadSink.h +++ b/cc/CCQuadSink.h @@ -2,29 +2,5 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CCQuadSink_h -#define CCQuadSink_h - -#include "base/memory/scoped_ptr.h" - -namespace cc { - -class CCDrawQuad; - -struct CCAppendQuadsData; -struct CCSharedQuadState; - -class CCQuadSink { -public: - virtual ~CCQuadSink() { } - - // Call this to add a SharedQuadState before appending quads that refer to it. Returns a pointer - // to the given SharedQuadState for convenience, that can be set on the quads to append. - virtual CCSharedQuadState* useSharedQuadState(scoped_ptr) = 0; - - // Returns true if the quad is added to the list, and false if the quad is entirely culled. - virtual bool append(scoped_ptr passDrawQuad, CCAppendQuadsData&) = 0; -}; - -} -#endif // CCQuadCuller_h +// Temporary forwarding header +#include "cc/quad_sink.h" diff --git a/cc/CCRenderPass.cpp b/cc/CCRenderPass.cpp deleted file mode 100644 index 513bd8b..0000000 --- a/cc/CCRenderPass.cpp +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "config.h" - -#include "CCRenderPass.h" - -#include "CCLayerImpl.h" -#include "CCMathUtil.h" -#include "CCOcclusionTracker.h" -#include "CCQuadCuller.h" -#include "CCSharedQuadState.h" -#include "CCSolidColorDrawQuad.h" - -using WebKit::WebTransformationMatrix; - -namespace cc { - -scoped_ptr CCRenderPass::create(Id id, IntRect outputRect, const WebKit::WebTransformationMatrix& transformToRootTarget) -{ - return make_scoped_ptr(new CCRenderPass(id, outputRect, transformToRootTarget)); -} - -CCRenderPass::CCRenderPass(Id id, IntRect outputRect, const WebKit::WebTransformationMatrix& transformToRootTarget) - : m_id(id) - , m_transformToRootTarget(transformToRootTarget) - , m_outputRect(outputRect) - , m_hasTransparentBackground(true) - , m_hasOcclusionFromOutsideTargetSurface(false) -{ - ASSERT(id.layerId > 0); - ASSERT(id.index >= 0); -} - -CCRenderPass::~CCRenderPass() -{ -} - -scoped_ptr CCRenderPass::copy(Id newId) const -{ - ASSERT(newId != m_id); - - scoped_ptr copyPass(create(newId, m_outputRect, m_transformToRootTarget)); - copyPass->setDamageRect(m_damageRect); - copyPass->setHasTransparentBackground(m_hasTransparentBackground); - copyPass->setHasOcclusionFromOutsideTargetSurface(m_hasOcclusionFromOutsideTargetSurface); - copyPass->setFilters(m_filters); - copyPass->setBackgroundFilters(m_backgroundFilters); - return copyPass.Pass(); -} - -void CCRenderPass::appendQuadsForLayer(CCLayerImpl* layer, CCOcclusionTrackerImpl* occlusionTracker, CCAppendQuadsData& appendQuadsData) -{ - const bool forSurface = false; - CCQuadCuller quadCuller(m_quadList, m_sharedQuadStateList, layer, occlusionTracker, layer->hasDebugBorders(), forSurface); - - layer->appendQuads(quadCuller, appendQuadsData); -} - -void CCRenderPass::appendQuadsForRenderSurfaceLayer(CCLayerImpl* layer, const CCRenderPass* contributingRenderPass, CCOcclusionTrackerImpl* occlusionTracker, CCAppendQuadsData& appendQuadsData) -{ - const bool forSurface = true; - CCQuadCuller quadCuller(m_quadList, m_sharedQuadStateList, layer, occlusionTracker, layer->hasDebugBorders(), forSurface); - - bool isReplica = false; - layer->renderSurface()->appendQuads(quadCuller, appendQuadsData, isReplica, contributingRenderPass->id()); - - // Add replica after the surface so that it appears below the surface. - if (layer->hasReplica()) { - isReplica = true; - layer->renderSurface()->appendQuads(quadCuller, appendQuadsData, isReplica, contributingRenderPass->id()); - } -} - -void CCRenderPass::appendQuadsToFillScreen(CCLayerImpl* rootLayer, SkColor screenBackgroundColor, const CCOcclusionTrackerImpl& occlusionTracker) -{ - if (!rootLayer || !screenBackgroundColor) - return; - - Region fillRegion = occlusionTracker.computeVisibleRegionInScreen(); - if (fillRegion.isEmpty()) - return; - - bool forSurface = false; - CCQuadCuller quadCuller(m_quadList, m_sharedQuadStateList, rootLayer, &occlusionTracker, rootLayer->hasDebugBorders(), forSurface); - - // Manually create the quad state for the gutter quads, as the root layer - // doesn't have any bounds and so can't generate this itself. - // FIXME: Make the gutter quads generated by the solid color layer (make it smarter about generating quads to fill unoccluded areas). - IntRect rootTargetRect = rootLayer->renderSurface()->contentRect(); - float opacity = 1; - bool opaque = true; - CCSharedQuadState* sharedQuadState = quadCuller.useSharedQuadState(CCSharedQuadState::create(rootLayer->drawTransform(), rootTargetRect, rootTargetRect, opacity, opaque)); - ASSERT(rootLayer->screenSpaceTransform().isInvertible()); - WebTransformationMatrix transformToLayerSpace = rootLayer->screenSpaceTransform().inverse(); - Vector fillRects = fillRegion.rects(); - for (size_t i = 0; i < fillRects.size(); ++i) { - // The root layer transform is composed of translations and scales only, no perspective, so mapping is sufficient. - IntRect layerRect = CCMathUtil::mapClippedRect(transformToLayerSpace, cc::IntRect(fillRects[i])); - // Skip the quad culler and just append the quads directly to avoid occlusion checks. - m_quadList.append(CCSolidColorDrawQuad::create(sharedQuadState, layerRect, screenBackgroundColor).PassAs()); - } -} - -} // namespace cc diff --git a/cc/CCRenderPass.h b/cc/CCRenderPass.h index cdfa958..ab2ae64 100644 --- a/cc/CCRenderPass.h +++ b/cc/CCRenderPass.h @@ -1,140 +1,6 @@ -// Copyright 2011 The Chromium Authors. All rights reserved. +// Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CCRenderPass_h -#define CCRenderPass_h - -#include "base/basictypes.h" -#include "cc/hash_pair.h" -#include "cc/scoped_ptr_hash_map.h" -#include "cc/scoped_ptr_vector.h" -#include "CCDrawQuad.h" -#include "CCSharedQuadState.h" -#include "FloatRect.h" -#include "SkColor.h" -#include -#include -#include - -namespace cc { - -class CCLayerImpl; -template -class CCOcclusionTrackerBase; -class CCRenderSurface; - -struct CCAppendQuadsData; - -typedef CCOcclusionTrackerBase CCOcclusionTrackerImpl; - -// A list of CCDrawQuad objects, sorted internally in front-to-back order. -class CCQuadList : public ScopedPtrVector { -public: - typedef reverse_iterator backToFrontIterator; - typedef const_reverse_iterator constBackToFrontIterator; - - inline backToFrontIterator backToFrontBegin() { return rbegin(); } - inline backToFrontIterator backToFrontEnd() { return rend(); } - inline constBackToFrontIterator backToFrontBegin() const { return rbegin(); } - inline constBackToFrontIterator backToFrontEnd() const { return rend(); } -}; - -typedef ScopedPtrVector CCSharedQuadStateList; - -class CCRenderPass { -public: - ~CCRenderPass(); - - struct Id { - int layerId; - int index; - - Id(int layerId, int index) - : layerId(layerId) - , index(index) - { - } - - bool operator==(const Id& other) const { return layerId == other.layerId && index == other.index; } - bool operator!=(const Id& other) const { return !(*this == other); } - bool operator<(const Id& other) const { return layerId < other.layerId || (layerId == other.layerId && index < other.index); } - }; - - static scoped_ptr create(Id, IntRect outputRect, const WebKit::WebTransformationMatrix& transformToRootTarget); - - // A shallow copy of the render pass, which does not include its quads. - scoped_ptr copy(Id newId) const; - - void appendQuadsForLayer(CCLayerImpl*, CCOcclusionTrackerImpl*, CCAppendQuadsData&); - void appendQuadsForRenderSurfaceLayer(CCLayerImpl*, const CCRenderPass* contributingRenderPass, CCOcclusionTrackerImpl*, CCAppendQuadsData&); - void appendQuadsToFillScreen(CCLayerImpl* rootLayer, SkColor screenBackgroundColor, const CCOcclusionTrackerImpl&); - - const CCQuadList& quadList() const { return m_quadList; } - - Id id() const { return m_id; } - - // FIXME: Modify this transform when merging the RenderPass into a parent compositor. - // Transforms from quad's original content space to the root target's content space. - const WebKit::WebTransformationMatrix& transformToRootTarget() const { return m_transformToRootTarget; } - - // This denotes the bounds in physical pixels of the output generated by this RenderPass. - const IntRect& outputRect() const { return m_outputRect; } - - FloatRect damageRect() const { return m_damageRect; } - void setDamageRect(FloatRect rect) { m_damageRect = rect; } - - const WebKit::WebFilterOperations& filters() const { return m_filters; } - void setFilters(const WebKit::WebFilterOperations& filters) { m_filters = filters; } - - const WebKit::WebFilterOperations& backgroundFilters() const { return m_backgroundFilters; } - void setBackgroundFilters(const WebKit::WebFilterOperations& filters) { m_backgroundFilters = filters; } - - bool hasTransparentBackground() const { return m_hasTransparentBackground; } - void setHasTransparentBackground(bool transparent) { m_hasTransparentBackground = transparent; } - - bool hasOcclusionFromOutsideTargetSurface() const { return m_hasOcclusionFromOutsideTargetSurface; } - void setHasOcclusionFromOutsideTargetSurface(bool hasOcclusionFromOutsideTargetSurface) { m_hasOcclusionFromOutsideTargetSurface = hasOcclusionFromOutsideTargetSurface; } -protected: - CCRenderPass(Id, IntRect outputRect, const WebKit::WebTransformationMatrix& transformToRootTarget); - - Id m_id; - CCQuadList m_quadList; - CCSharedQuadStateList m_sharedQuadStateList; - WebKit::WebTransformationMatrix m_transformToRootTarget; - IntRect m_outputRect; - FloatRect m_damageRect; - bool m_hasTransparentBackground; - bool m_hasOcclusionFromOutsideTargetSurface; - WebKit::WebFilterOperations m_filters; - WebKit::WebFilterOperations m_backgroundFilters; - - DISALLOW_COPY_AND_ASSIGN(CCRenderPass); -}; - -} // namespace cc - -namespace BASE_HASH_NAMESPACE { -#if defined(COMPILER_MSVC) -template<> -inline size_t hash_value(const cc::CCRenderPass::Id& key) { - return hash_value >(std::pair(key.layerId, key.index)); -} -#elif defined(COMPILER_GCC) -template<> -struct hash { - size_t operator()(cc::CCRenderPass::Id key) const { - return hash >()(std::pair(key.layerId, key.index)); - } -}; -#else -#error define a hash function for your compiler -#endif // COMPILER -} - -namespace cc { -typedef std::vector CCRenderPassList; -typedef ScopedPtrHashMap CCRenderPassIdHashMap; -} // namespace cc - -#endif +// Temporary forwarding header +#include "cc/render_pass.h" diff --git a/cc/CCRenderPassDrawQuad.cpp b/cc/CCRenderPassDrawQuad.cpp deleted file mode 100644 index 9e385c6..0000000 --- a/cc/CCRenderPassDrawQuad.cpp +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "config.h" - -#include "CCRenderPassDrawQuad.h" - -namespace cc { - -scoped_ptr CCRenderPassDrawQuad::create(const CCSharedQuadState* sharedQuadState, const IntRect& quadRect, CCRenderPass::Id renderPassId, bool isReplica, const CCResourceProvider::ResourceId maskResourceId, const IntRect& contentsChangedSinceLastFrame, float maskTexCoordScaleX, float maskTexCoordScaleY, float maskTexCoordOffsetX, float maskTexCoordOffsetY) -{ - return make_scoped_ptr(new CCRenderPassDrawQuad(sharedQuadState, quadRect, renderPassId, isReplica, maskResourceId, contentsChangedSinceLastFrame, maskTexCoordScaleX, maskTexCoordScaleY, maskTexCoordOffsetX, maskTexCoordOffsetY)); -} - -CCRenderPassDrawQuad::CCRenderPassDrawQuad(const CCSharedQuadState* sharedQuadState, const IntRect& quadRect, CCRenderPass::Id renderPassId, bool isReplica, CCResourceProvider::ResourceId maskResourceId, const IntRect& contentsChangedSinceLastFrame, float maskTexCoordScaleX, float maskTexCoordScaleY, float maskTexCoordOffsetX, float maskTexCoordOffsetY) - : CCDrawQuad(sharedQuadState, CCDrawQuad::RenderPass, quadRect) - , m_renderPassId(renderPassId) - , m_isReplica(isReplica) - , m_maskResourceId(maskResourceId) - , m_contentsChangedSinceLastFrame(contentsChangedSinceLastFrame) - , m_maskTexCoordScaleX(maskTexCoordScaleX) - , m_maskTexCoordScaleY(maskTexCoordScaleY) - , m_maskTexCoordOffsetX(maskTexCoordOffsetX) - , m_maskTexCoordOffsetY(maskTexCoordOffsetY) -{ - ASSERT(m_renderPassId.layerId > 0); - ASSERT(m_renderPassId.index >= 0); -} - -const CCRenderPassDrawQuad* CCRenderPassDrawQuad::materialCast(const CCDrawQuad* quad) -{ - ASSERT(quad->material() == CCDrawQuad::RenderPass); - return static_cast(quad); -} - -scoped_ptr CCRenderPassDrawQuad::copy(const CCSharedQuadState* copiedSharedQuadState, CCRenderPass::Id copiedRenderPassId) const -{ - unsigned bytes = size(); - ASSERT(bytes); - - scoped_ptr copyQuad(reinterpret_cast(new char[bytes])); - memcpy(copyQuad.get(), this, bytes); - copyQuad->setSharedQuadState(copiedSharedQuadState); - copyQuad->m_renderPassId = copiedRenderPassId; - - return copyQuad.Pass(); -} - -} // namespace cc diff --git a/cc/CCRenderPassDrawQuad.h b/cc/CCRenderPassDrawQuad.h index 99222d9..d665960 100644 --- a/cc/CCRenderPassDrawQuad.h +++ b/cc/CCRenderPassDrawQuad.h @@ -1,51 +1,6 @@ -// Copyright 2011 The Chromium Authors. All rights reserved. +// Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CCRenderPassDrawQuad_h -#define CCRenderPassDrawQuad_h - -#include "base/basictypes.h" -#include "base/memory/scoped_ptr.h" -#include "CCDrawQuad.h" -#include "CCRenderPass.h" -#include "CCResourceProvider.h" -#include "IntRect.h" - -namespace cc { - -class CCRenderPassDrawQuad : public CCDrawQuad { -public: - static scoped_ptr create(const CCSharedQuadState*, const IntRect&, CCRenderPass::Id renderPassId, bool isReplica, CCResourceProvider::ResourceId maskResourceId, const IntRect& contentsChangedSinceLastFrame, float maskTexCoordScaleX, float maskTexCoordScaleY, float maskTexCoordOffsetX, float maskTexCoordOffsetY); - - CCRenderPass::Id renderPassId() const { return m_renderPassId; } - bool isReplica() const { return m_isReplica; } - CCResourceProvider::ResourceId maskResourceId() const { return m_maskResourceId; } - const IntRect& contentsChangedSinceLastFrame() const { return m_contentsChangedSinceLastFrame; } - - static const CCRenderPassDrawQuad* materialCast(const CCDrawQuad*); - float maskTexCoordScaleX() const { return m_maskTexCoordScaleX; } - float maskTexCoordScaleY() const { return m_maskTexCoordScaleY; } - float maskTexCoordOffsetX() const { return m_maskTexCoordOffsetX; } - float maskTexCoordOffsetY() const { return m_maskTexCoordOffsetY; } - - scoped_ptr copy(const CCSharedQuadState* copiedSharedQuadState, CCRenderPass::Id copiedRenderPassId) const; - -private: - CCRenderPassDrawQuad(const CCSharedQuadState*, const IntRect&, CCRenderPass::Id renderPassId, bool isReplica, CCResourceProvider::ResourceId maskResourceId, const IntRect& contentsChangedSinceLastFrame, float maskTexCoordScaleX, float maskTexCoordScaleY, float maskTexCoordOffsetX, float maskTexCoordOffsetY); - - CCRenderPass::Id m_renderPassId; - bool m_isReplica; - CCResourceProvider::ResourceId m_maskResourceId; - IntRect m_contentsChangedSinceLastFrame; - float m_maskTexCoordScaleX; - float m_maskTexCoordScaleY; - float m_maskTexCoordOffsetX; - float m_maskTexCoordOffsetY; - - DISALLOW_COPY_AND_ASSIGN(CCRenderPassDrawQuad); -}; - -} - -#endif +// Temporary forwarding header +#include "cc/render_pass_draw_quad.h" diff --git a/cc/CCRenderPassSink.h b/cc/CCRenderPassSink.h index f3bac1d..6f8bf64 100644 --- a/cc/CCRenderPassSink.h +++ b/cc/CCRenderPassSink.h @@ -2,19 +2,5 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CCRenderPassSink_h -#define CCRenderPassSink_h - -#include "base/memory/scoped_ptr.h" - -namespace cc { - -class CCRenderPass; - -class CCRenderPassSink { -public: - virtual void appendRenderPass(scoped_ptr) = 0; -}; - -} -#endif // CCRenderPassSink_h +// Temporary forwarding header +#include "cc/render_pass_sink.h" diff --git a/cc/CCRenderSurface.cpp b/cc/CCRenderSurface.cpp deleted file mode 100644 index f10c83b..0000000 --- a/cc/CCRenderSurface.cpp +++ /dev/null @@ -1,253 +0,0 @@ -// Copyright 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "config.h" - -#if USE(ACCELERATED_COMPOSITING) - -#include "CCRenderSurface.h" - -#include "base/stringprintf.h" -#include "CCDamageTracker.h" -#include "CCDebugBorderDrawQuad.h" -#include "CCDelegatedRendererLayerImpl.h" -#include "CCLayerImpl.h" -#include "CCMathUtil.h" -#include "CCQuadSink.h" -#include "CCRenderPass.h" -#include "CCRenderPassDrawQuad.h" -#include "CCRenderPassSink.h" -#include "CCSharedQuadState.h" -#include - -using WebKit::WebTransformationMatrix; - -namespace cc { - -static const int debugSurfaceBorderWidth = 2; -static const int debugSurfaceBorderAlpha = 100; -static const int debugSurfaceBorderColorRed = 0; -static const int debugSurfaceBorderColorGreen = 0; -static const int debugSurfaceBorderColorBlue = 255; -static const int debugReplicaBorderColorRed = 160; -static const int debugReplicaBorderColorGreen = 0; -static const int debugReplicaBorderColorBlue = 255; - -CCRenderSurface::CCRenderSurface(CCLayerImpl* owningLayer) - : m_owningLayer(owningLayer) - , m_surfacePropertyChanged(false) - , m_drawOpacity(1) - , m_drawOpacityIsAnimating(false) - , m_targetSurfaceTransformsAreAnimating(false) - , m_screenSpaceTransformsAreAnimating(false) - , m_nearestAncestorThatMovesPixels(0) - , m_targetRenderSurfaceLayerIndexHistory(0) - , m_currentLayerIndexHistory(0) -{ - m_damageTracker = CCDamageTracker::create(); -} - -CCRenderSurface::~CCRenderSurface() -{ -} - -FloatRect CCRenderSurface::drawableContentRect() const -{ - FloatRect drawableContentRect = CCMathUtil::mapClippedRect(m_drawTransform, m_contentRect); - if (m_owningLayer->hasReplica()) - drawableContentRect.unite(CCMathUtil::mapClippedRect(m_replicaDrawTransform, m_contentRect)); - - return drawableContentRect; -} - -std::string CCRenderSurface::name() const -{ - return base::StringPrintf("RenderSurface(id=%i,owner=%s)", m_owningLayer->id(), m_owningLayer->debugName().data()); -} - -static std::string indentString(int indent) -{ - std::string str; - for (int i = 0; i != indent; ++i) - str.append(" "); - return str; -} - -void CCRenderSurface::dumpSurface(std::string* str, int indent) const -{ - std::string indentStr = indentString(indent); - str->append(indentStr); - base::StringAppendF(str, "%s\n", name().data()); - - indentStr.append(" "); - str->append(indentStr); - base::StringAppendF(str, "contentRect: (%d, %d, %d, %d)\n", m_contentRect.x(), m_contentRect.y(), m_contentRect.width(), m_contentRect.height()); - - str->append(indentStr); - base::StringAppendF(str, "drawTransform: %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f\n", - m_drawTransform.m11(), m_drawTransform.m12(), m_drawTransform.m13(), m_drawTransform.m14(), - m_drawTransform.m21(), m_drawTransform.m22(), m_drawTransform.m23(), m_drawTransform.m24(), - m_drawTransform.m31(), m_drawTransform.m32(), m_drawTransform.m33(), m_drawTransform.m34(), - m_drawTransform.m41(), m_drawTransform.m42(), m_drawTransform.m43(), m_drawTransform.m44()); - - str->append(indentStr); - base::StringAppendF(str, "damageRect is pos(%f, %f), size(%f, %f)\n", - m_damageTracker->currentDamageRect().x(), m_damageTracker->currentDamageRect().y(), - m_damageTracker->currentDamageRect().width(), m_damageTracker->currentDamageRect().height()); -} - -int CCRenderSurface::owningLayerId() const -{ - return m_owningLayer ? m_owningLayer->id() : 0; -} - - -void CCRenderSurface::setClipRect(const IntRect& clipRect) -{ - if (m_clipRect == clipRect) - return; - - m_surfacePropertyChanged = true; - m_clipRect = clipRect; -} - -bool CCRenderSurface::contentsChanged() const -{ - return !m_damageTracker->currentDamageRect().isEmpty(); -} - -void CCRenderSurface::setContentRect(const IntRect& contentRect) -{ - if (m_contentRect == contentRect) - return; - - m_surfacePropertyChanged = true; - m_contentRect = contentRect; -} - -bool CCRenderSurface::surfacePropertyChanged() const -{ - // Surface property changes are tracked as follows: - // - // - m_surfacePropertyChanged is flagged when the clipRect or contentRect change. As - // of now, these are the only two properties that can be affected by descendant layers. - // - // - all other property changes come from the owning layer (or some ancestor layer - // that propagates its change to the owning layer). - // - ASSERT(m_owningLayer); - return m_surfacePropertyChanged || m_owningLayer->layerPropertyChanged(); -} - -bool CCRenderSurface::surfacePropertyChangedOnlyFromDescendant() const -{ - return m_surfacePropertyChanged && !m_owningLayer->layerPropertyChanged(); -} - -void CCRenderSurface::addContributingDelegatedRenderPassLayer(CCLayerImpl* layer) -{ - ASSERT(std::find(m_layerList.begin(), m_layerList.end(), layer) != m_layerList.end()); - CCDelegatedRendererLayerImpl* delegatedRendererLayer = static_cast(layer); - m_contributingDelegatedRenderPassLayerList.push_back(delegatedRendererLayer); -} - -void CCRenderSurface::clearLayerLists() -{ - m_layerList.clear(); - m_contributingDelegatedRenderPassLayerList.clear(); -} - -static inline IntRect computeClippedRectInTarget(const CCLayerImpl* owningLayer) -{ - ASSERT(owningLayer->parent()); - - const CCLayerImpl* renderTarget = owningLayer->parent()->renderTarget(); - const CCRenderSurface* self = owningLayer->renderSurface(); - - IntRect clippedRectInTarget = self->clipRect(); - if (owningLayer->backgroundFilters().hasFilterThatMovesPixels()) { - // If the layer has background filters that move pixels, we cannot scissor as tightly. - // FIXME: this should be able to be a tighter scissor, perhaps expanded by the filter outsets? - clippedRectInTarget = renderTarget->renderSurface()->contentRect(); - } else if (clippedRectInTarget.isEmpty()) { - // For surfaces, empty clipRect means that the surface does not clip anything. - clippedRectInTarget = enclosingIntRect(intersection(renderTarget->renderSurface()->contentRect(), self->drawableContentRect())); - } else - clippedRectInTarget.intersect(enclosingIntRect(self->drawableContentRect())); - return clippedRectInTarget; -} - -CCRenderPass::Id CCRenderSurface::renderPassId() -{ - int layerId = m_owningLayer->id(); - int subId = 0; - ASSERT(layerId > 0); - return CCRenderPass::Id(layerId, subId); -} - -void CCRenderSurface::appendRenderPasses(CCRenderPassSink& passSink) -{ - for (size_t i = 0; i < m_contributingDelegatedRenderPassLayerList.size(); ++i) - m_contributingDelegatedRenderPassLayerList[i]->appendContributingRenderPasses(passSink); - - scoped_ptr pass = CCRenderPass::create(renderPassId(), m_contentRect, m_screenSpaceTransform); - pass->setDamageRect(m_damageTracker->currentDamageRect()); - pass->setFilters(m_owningLayer->filters()); - pass->setBackgroundFilters(m_owningLayer->backgroundFilters()); - passSink.appendRenderPass(pass.Pass()); -} - -void CCRenderSurface::appendQuads(CCQuadSink& quadSink, CCAppendQuadsData& appendQuadsData, bool forReplica, CCRenderPass::Id renderPassId) -{ - ASSERT(!forReplica || m_owningLayer->hasReplica()); - - IntRect clippedRectInTarget = computeClippedRectInTarget(m_owningLayer); - bool isOpaque = false; - const WebTransformationMatrix& drawTransform = forReplica ? m_replicaDrawTransform : m_drawTransform; - CCSharedQuadState* sharedQuadState = quadSink.useSharedQuadState(CCSharedQuadState::create(drawTransform, m_contentRect, clippedRectInTarget, m_drawOpacity, isOpaque).Pass()); - - if (m_owningLayer->hasDebugBorders()) { - int red = forReplica ? debugReplicaBorderColorRed : debugSurfaceBorderColorRed; - int green = forReplica ? debugReplicaBorderColorGreen : debugSurfaceBorderColorGreen; - int blue = forReplica ? debugReplicaBorderColorBlue : debugSurfaceBorderColorBlue; - SkColor color = SkColorSetARGB(debugSurfaceBorderAlpha, red, green, blue); - quadSink.append(CCDebugBorderDrawQuad::create(sharedQuadState, contentRect(), color, debugSurfaceBorderWidth).PassAs(), appendQuadsData); - } - - // FIXME: By using the same RenderSurface for both the content and its reflection, - // it's currently not possible to apply a separate mask to the reflection layer - // or correctly handle opacity in reflections (opacity must be applied after drawing - // both the layer and its reflection). The solution is to introduce yet another RenderSurface - // to draw the layer and its reflection in. For now we only apply a separate reflection - // mask if the contents don't have a mask of their own. - CCLayerImpl* maskLayer = m_owningLayer->maskLayer(); - if (maskLayer && (!maskLayer->drawsContent() || maskLayer->bounds().isEmpty())) - maskLayer = 0; - - if (!maskLayer && forReplica) { - maskLayer = m_owningLayer->replicaLayer()->maskLayer(); - if (maskLayer && (!maskLayer->drawsContent() || maskLayer->bounds().isEmpty())) - maskLayer = 0; - } - - float maskTexCoordScaleX = 1; - float maskTexCoordScaleY = 1; - float maskTexCoordOffsetX = 1; - float maskTexCoordOffsetY = 1; - if (maskLayer) { - maskTexCoordScaleX = static_cast(contentRect().width()) / maskLayer->contentBounds().width(); - maskTexCoordScaleY = static_cast(contentRect().height()) / maskLayer->contentBounds().height(); - maskTexCoordOffsetX = static_cast(contentRect().x()) / contentRect().width() * maskTexCoordScaleX; - maskTexCoordOffsetY = static_cast(contentRect().y()) / contentRect().height() * maskTexCoordScaleY; - } - - CCResourceProvider::ResourceId maskResourceId = maskLayer ? maskLayer->contentsResourceId() : 0; - IntRect contentsChangedSinceLastFrame = contentsChanged() ? m_contentRect : IntRect(); - - quadSink.append(CCRenderPassDrawQuad::create(sharedQuadState, contentRect(), renderPassId, forReplica, maskResourceId, contentsChangedSinceLastFrame, - maskTexCoordScaleX, maskTexCoordScaleY, maskTexCoordOffsetX, maskTexCoordOffsetY).PassAs(), appendQuadsData); -} - -} -#endif // USE(ACCELERATED_COMPOSITING) diff --git a/cc/CCRenderSurface.h b/cc/CCRenderSurface.h index afdf062..7747efd 100644 --- a/cc/CCRenderSurface.h +++ b/cc/CCRenderSurface.h @@ -1,132 +1,6 @@ -// Copyright 2011 The Chromium Authors. All rights reserved. +// Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CCRenderSurface_h -#define CCRenderSurface_h - -#if USE(ACCELERATED_COMPOSITING) - -#include "base/basictypes.h" -#include "base/memory/scoped_ptr.h" -#include "CCRenderPass.h" -#include "CCSharedQuadState.h" -#include "FloatRect.h" -#include "IntRect.h" -#include - -namespace cc { - -class CCDamageTracker; -class CCDelegatedRendererLayerImpl; -class CCQuadSink; -class CCRenderPassSink; -class CCLayerImpl; - -struct CCAppendQuadsData; - -class CCRenderSurface { -public: - explicit CCRenderSurface(CCLayerImpl*); - virtual ~CCRenderSurface(); - - std::string name() const; - void dumpSurface(std::string*, int indent) const; - - FloatPoint contentRectCenter() const { return FloatRect(m_contentRect).center(); } - - // Returns the rect that encloses the RenderSurface including any reflection. - FloatRect drawableContentRect() const; - - float drawOpacity() const { return m_drawOpacity; } - void setDrawOpacity(float opacity) { m_drawOpacity = opacity; } - - void setNearestAncestorThatMovesPixels(CCRenderSurface* surface) { m_nearestAncestorThatMovesPixels = surface; } - const CCRenderSurface* nearestAncestorThatMovesPixels() const { return m_nearestAncestorThatMovesPixels; } - - bool drawOpacityIsAnimating() const { return m_drawOpacityIsAnimating; } - void setDrawOpacityIsAnimating(bool drawOpacityIsAnimating) { m_drawOpacityIsAnimating = drawOpacityIsAnimating; } - - void setDrawTransform(const WebKit::WebTransformationMatrix& drawTransform) { m_drawTransform = drawTransform; } - const WebKit::WebTransformationMatrix& drawTransform() const { return m_drawTransform; } - - void setScreenSpaceTransform(const WebKit::WebTransformationMatrix& screenSpaceTransform) { m_screenSpaceTransform = screenSpaceTransform; } - const WebKit::WebTransformationMatrix& screenSpaceTransform() const { return m_screenSpaceTransform; } - - void setReplicaDrawTransform(const WebKit::WebTransformationMatrix& replicaDrawTransform) { m_replicaDrawTransform = replicaDrawTransform; } - const WebKit::WebTransformationMatrix& replicaDrawTransform() const { return m_replicaDrawTransform; } - - void setReplicaScreenSpaceTransform(const WebKit::WebTransformationMatrix& replicaScreenSpaceTransform) { m_replicaScreenSpaceTransform = replicaScreenSpaceTransform; } - const WebKit::WebTransformationMatrix& replicaScreenSpaceTransform() const { return m_replicaScreenSpaceTransform; } - - bool targetSurfaceTransformsAreAnimating() const { return m_targetSurfaceTransformsAreAnimating; } - void setTargetSurfaceTransformsAreAnimating(bool animating) { m_targetSurfaceTransformsAreAnimating = animating; } - bool screenSpaceTransformsAreAnimating() const { return m_screenSpaceTransformsAreAnimating; } - void setScreenSpaceTransformsAreAnimating(bool animating) { m_screenSpaceTransformsAreAnimating = animating; } - - void setClipRect(const IntRect&); - const IntRect& clipRect() const { return m_clipRect; } - - bool contentsChanged() const; - - void setContentRect(const IntRect&); - const IntRect& contentRect() const { return m_contentRect; } - - std::vector& layerList() { return m_layerList; } - void addContributingDelegatedRenderPassLayer(CCLayerImpl*); - void clearLayerLists(); - - int owningLayerId() const; - - void resetPropertyChangedFlag() { m_surfacePropertyChanged = false; } - bool surfacePropertyChanged() const; - bool surfacePropertyChangedOnlyFromDescendant() const; - - CCDamageTracker* damageTracker() const { return m_damageTracker.get(); } - - CCRenderPass::Id renderPassId(); - - void appendRenderPasses(CCRenderPassSink&); - void appendQuads(CCQuadSink&, CCAppendQuadsData&, bool forReplica, CCRenderPass::Id renderPassId); - -private: - CCLayerImpl* m_owningLayer; - - // Uses this surface's space. - IntRect m_contentRect; - bool m_surfacePropertyChanged; - - float m_drawOpacity; - bool m_drawOpacityIsAnimating; - WebKit::WebTransformationMatrix m_drawTransform; - WebKit::WebTransformationMatrix m_screenSpaceTransform; - WebKit::WebTransformationMatrix m_replicaDrawTransform; - WebKit::WebTransformationMatrix m_replicaScreenSpaceTransform; - bool m_targetSurfaceTransformsAreAnimating; - bool m_screenSpaceTransformsAreAnimating; - - // Uses the space of the surface's target surface. - IntRect m_clipRect; - - std::vector m_layerList; - std::vector m_contributingDelegatedRenderPassLayerList; - - // The nearest ancestor target surface that will contain the contents of this surface, and that is going - // to move pixels within the surface (such as with a blur). This can point to itself. - CCRenderSurface* m_nearestAncestorThatMovesPixels; - - scoped_ptr m_damageTracker; - - // For CCLayerIteratorActions - int m_targetRenderSurfaceLayerIndexHistory; - int m_currentLayerIndexHistory; - - friend struct CCLayerIteratorActions; - - DISALLOW_COPY_AND_ASSIGN(CCRenderSurface); -}; - -} -#endif // USE(ACCELERATED_COMPOSITING) - -#endif +// Temporary forwarding header +#include "cc/render_surface_impl.h" diff --git a/cc/CCRenderSurfaceFilters.cpp b/cc/CCRenderSurfaceFilters.cpp deleted file mode 100644 index 40344c6..0000000 --- a/cc/CCRenderSurfaceFilters.cpp +++ /dev/null @@ -1,446 +0,0 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "config.h" - -#if USE(ACCELERATED_COMPOSITING) - -#include "CCRenderSurfaceFilters.h" - -#include "FloatSize.h" -#include "SkBlurImageFilter.h" -#include "SkCanvas.h" -#include "SkColorMatrixFilter.h" -#include "SkGpuDevice.h" -#include "SkGrPixelRef.h" -#include "SkMagnifierImageFilter.h" -#include -#include -#include -#include - -using namespace cc; - -namespace { - -void getBrightnessMatrix(float amount, SkScalar matrix[20]) -{ - memset(matrix, 0, 20 * sizeof(SkScalar)); - // Old implementation, a la the draft spec, a straight-up scale, - // representing - // (See http://dvcs.w3.org/hg/FXTF/raw-file/tip/filters/index.html#brightnessEquivalent) - // matrix[0] = matrix[6] = matrix[12] = amount; - // matrix[18] = 1; - // New implementation, a translation in color space, representing - // - // (See https://www.w3.org/Bugs/Public/show_bug.cgi?id=15647) - matrix[0] = matrix[6] = matrix[12] = matrix[18] = 1; - matrix[4] = matrix[9] = matrix[14] = amount * 255; -} - -void getContrastMatrix(float amount, SkScalar matrix[20]) -{ - memset(matrix, 0, 20 * sizeof(SkScalar)); - matrix[0] = matrix[6] = matrix[12] = amount; - matrix[4] = matrix[9] = matrix[14] = (-0.5f * amount + 0.5f) * 255; - matrix[18] = 1; -} - -void getSaturateMatrix(float amount, SkScalar matrix[20]) -{ - // Note, these values are computed to ensure matrixNeedsClamping is false - // for amount in [0..1] - matrix[0] = 0.213f + 0.787f * amount; - matrix[1] = 0.715f - 0.715f * amount; - matrix[2] = 1.f - (matrix[0] + matrix[1]); - matrix[3] = matrix[4] = 0; - matrix[5] = 0.213f - 0.213f * amount; - matrix[6] = 0.715f + 0.285f * amount; - matrix[7] = 1.f - (matrix[5] + matrix[6]); - matrix[8] = matrix[9] = 0; - matrix[10] = 0.213f - 0.213f * amount; - matrix[11] = 0.715f - 0.715f * amount; - matrix[12] = 1.f - (matrix[10] + matrix[11]); - matrix[13] = matrix[14] = 0; - matrix[15] = matrix[16] = matrix[17] = matrix[19] = 0; - matrix[18] = 1; -} - -void getHueRotateMatrix(float hue, SkScalar matrix[20]) -{ - float cosHue = cosf(hue * piFloat / 180); - float sinHue = sinf(hue * piFloat / 180); - matrix[0] = 0.213f + cosHue * 0.787f - sinHue * 0.213f; - matrix[1] = 0.715f - cosHue * 0.715f - sinHue * 0.715f; - matrix[2] = 0.072f - cosHue * 0.072f + sinHue * 0.928f; - matrix[3] = matrix[4] = 0; - matrix[5] = 0.213f - cosHue * 0.213f + sinHue * 0.143f; - matrix[6] = 0.715f + cosHue * 0.285f + sinHue * 0.140f; - matrix[7] = 0.072f - cosHue * 0.072f - sinHue * 0.283f; - matrix[8] = matrix[9] = 0; - matrix[10] = 0.213f - cosHue * 0.213f - sinHue * 0.787f; - matrix[11] = 0.715f - cosHue * 0.715f + sinHue * 0.715f; - matrix[12] = 0.072f + cosHue * 0.928f + sinHue * 0.072f; - matrix[13] = matrix[14] = 0; - matrix[15] = matrix[16] = matrix[17] = 0; - matrix[18] = 1; - matrix[19] = 0; -} - -void getInvertMatrix(float amount, SkScalar matrix[20]) -{ - memset(matrix, 0, 20 * sizeof(SkScalar)); - matrix[0] = matrix[6] = matrix[12] = 1 - 2 * amount; - matrix[4] = matrix[9] = matrix[14] = amount * 255; - matrix[18] = 1; -} - -void getOpacityMatrix(float amount, SkScalar matrix[20]) -{ - memset(matrix, 0, 20 * sizeof(SkScalar)); - matrix[0] = matrix[6] = matrix[12] = 1; - matrix[18] = amount; -} - -void getGrayscaleMatrix(float amount, SkScalar matrix[20]) -{ - // Note, these values are computed to ensure matrixNeedsClamping is false - // for amount in [0..1] - matrix[0] = 0.2126f + 0.7874f * amount; - matrix[1] = 0.7152f - 0.7152f * amount; - matrix[2] = 1.f - (matrix[0] + matrix[1]); - matrix[3] = matrix[4] = 0; - - matrix[5] = 0.2126f - 0.2126f * amount; - matrix[6] = 0.7152f + 0.2848f * amount; - matrix[7] = 1.f - (matrix[5] + matrix[6]); - matrix[8] = matrix[9] = 0; - - matrix[10] = 0.2126f - 0.2126f * amount; - matrix[11] = 0.7152f - 0.7152f * amount; - matrix[12] = 1.f - (matrix[10] + matrix[11]); - matrix[13] = matrix[14] = 0; - - matrix[15] = matrix[16] = matrix[17] = matrix[19] = 0; - matrix[18] = 1; -} - -void getSepiaMatrix(float amount, SkScalar matrix[20]) -{ - matrix[0] = 0.393f + 0.607f * amount; - matrix[1] = 0.769f - 0.769f * amount; - matrix[2] = 0.189f - 0.189f * amount; - matrix[3] = matrix[4] = 0; - - matrix[5] = 0.349f - 0.349f * amount; - matrix[6] = 0.686f + 0.314f * amount; - matrix[7] = 0.168f - 0.168f * amount; - matrix[8] = matrix[9] = 0; - - matrix[10] = 0.272f - 0.272f * amount; - matrix[11] = 0.534f - 0.534f * amount; - matrix[12] = 0.131f + 0.869f * amount; - matrix[13] = matrix[14] = 0; - - matrix[15] = matrix[16] = matrix[17] = matrix[19] = 0; - matrix[18] = 1; -} - -// The 5x4 matrix is really a "compressed" version of a 5x5 matrix that'd have -// (0 0 0 0 1) as a last row, and that would be applied to a 5-vector extended -// from the 4-vector color with a 1. -void multColorMatrix(SkScalar a[20], SkScalar b[20], SkScalar out[20]) -{ - for (int j = 0; j < 4; ++j) { - for (int i = 0; i < 5; ++i) { - out[i+j*5] = i == 4 ? a[4+j*5] : 0; - for (int k = 0; k < 4; ++k) - out[i+j*5] += a[k+j*5] * b[i+k*5]; - } - } -} - -// To detect if we need to apply clamping after applying a matrix, we check if -// any output component might go outside of [0, 255] for any combination of -// input components in [0..255]. -// Each output component is an affine transformation of the input component, so -// the minimum and maximum values are for any combination of minimum or maximum -// values of input components (i.e. 0 or 255). -// E.g. if R' = x*R + y*G + z*B + w*A + t -// Then the maximum value will be for R=255 if x>0 or R=0 if x<0, and the -// minimum value will be for R=0 if x>0 or R=255 if x<0. -// Same goes for all components. -bool componentNeedsClamping(SkScalar row[5]) -{ - SkScalar maxValue = row[4] / 255; - SkScalar minValue = row[4] / 255; - for (int i = 0; i < 4; ++i) { - if (row[i] > 0) - maxValue += row[i]; - else - minValue += row[i]; - } - return (maxValue > 1) || (minValue < 0); -} - -bool matrixNeedsClamping(SkScalar matrix[20]) -{ - return componentNeedsClamping(matrix) - || componentNeedsClamping(matrix+5) - || componentNeedsClamping(matrix+10) - || componentNeedsClamping(matrix+15); -} - -bool getColorMatrix(const WebKit::WebFilterOperation& op, SkScalar matrix[20]) -{ - switch (op.type()) { - case WebKit::WebFilterOperation::FilterTypeBrightness: { - getBrightnessMatrix(op.amount(), matrix); - return true; - } - case WebKit::WebFilterOperation::FilterTypeContrast: { - getContrastMatrix(op.amount(), matrix); - return true; - } - case WebKit::WebFilterOperation::FilterTypeGrayscale: { - getGrayscaleMatrix(1 - op.amount(), matrix); - return true; - } - case WebKit::WebFilterOperation::FilterTypeSepia: { - getSepiaMatrix(1 - op.amount(), matrix); - return true; - } - case WebKit::WebFilterOperation::FilterTypeSaturate: { - getSaturateMatrix(op.amount(), matrix); - return true; - } - case WebKit::WebFilterOperation::FilterTypeHueRotate: { - getHueRotateMatrix(op.amount(), matrix); - return true; - } - case WebKit::WebFilterOperation::FilterTypeInvert: { - getInvertMatrix(op.amount(), matrix); - return true; - } - case WebKit::WebFilterOperation::FilterTypeOpacity: { - getOpacityMatrix(op.amount(), matrix); - return true; - } - case WebKit::WebFilterOperation::FilterTypeColorMatrix: { - memcpy(matrix, op.matrix(), sizeof(SkScalar[20])); - return true; - } - default: - return false; - } -} - -class FilterBufferState { -public: - FilterBufferState(GrContext* grContext, const FloatSize& size, unsigned textureId) - : m_grContext(grContext) - , m_currentTexture(0) - { - // Wrap the source texture in a Ganesh platform texture. - GrPlatformTextureDesc platformTextureDescription; - platformTextureDescription.fWidth = size.width(); - platformTextureDescription.fHeight = size.height(); - platformTextureDescription.fConfig = kSkia8888_GrPixelConfig; - platformTextureDescription.fTextureHandle = textureId; - SkAutoTUnref texture(grContext->createPlatformTexture(platformTextureDescription)); - // Place the platform texture inside an SkBitmap. - m_source.setConfig(SkBitmap::kARGB_8888_Config, size.width(), size.height()); - m_source.setPixelRef(new SkGrPixelRef(texture.get()))->unref(); - } - - ~FilterBufferState() { } - - bool init(int filterCount) - { - int scratchCount = std::min(2, filterCount); - GrTextureDesc desc; - desc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit; - desc.fSampleCnt = 0; - desc.fWidth = m_source.width(); - desc.fHeight = m_source.height(); - desc.fConfig = kSkia8888_GrPixelConfig; - for (int i = 0; i < scratchCount; ++i) { - GrAutoScratchTexture scratchTexture(m_grContext, desc, GrContext::kExact_ScratchTexMatch); - m_scratchTextures[i].reset(scratchTexture.detach()); - if (!m_scratchTextures[i].get()) - return false; - } - return true; - } - - SkCanvas* canvas() - { - if (!m_canvas.get()) - createCanvas(); - return m_canvas.get(); - } - - const SkBitmap& source() { return m_source; } - - void swap() - { - m_canvas->flush(); - m_canvas.reset(0); - m_device.reset(0); - - m_source.setPixelRef(new SkGrPixelRef(m_scratchTextures[m_currentTexture].get()))->unref(); - m_currentTexture = 1 - m_currentTexture; - } - -private: - void createCanvas() - { - ASSERT(m_scratchTextures[m_currentTexture].get()); - m_device.reset(new SkGpuDevice(m_grContext, m_scratchTextures[m_currentTexture].get())); - m_canvas.reset(new SkCanvas(m_device.get())); - m_canvas->clear(0x0); - } - - GrContext* m_grContext; - SkBitmap m_source; - SkAutoTUnref m_scratchTextures[2]; - int m_currentTexture; - SkAutoTUnref m_device; - SkAutoTUnref m_canvas; -}; - -} - -namespace cc { - -WebKit::WebFilterOperations CCRenderSurfaceFilters::optimize(const WebKit::WebFilterOperations& filters) -{ - WebKit::WebFilterOperations newList; - - SkScalar accumulatedColorMatrix[20]; - bool haveAccumulatedColorMatrix = false; - for (unsigned i = 0; i < filters.size(); ++i) { - const WebKit::WebFilterOperation& op = filters.at(i); - - // If the filter is a color matrix, we may be able to combine it with - // following filter(s) that also are color matrices. - SkScalar matrix[20]; - if (getColorMatrix(op, matrix)) { - if (haveAccumulatedColorMatrix) { - SkScalar newMatrix[20]; - multColorMatrix(matrix, accumulatedColorMatrix, newMatrix); - memcpy(accumulatedColorMatrix, newMatrix, sizeof(accumulatedColorMatrix)); - } else { - memcpy(accumulatedColorMatrix, matrix, sizeof(accumulatedColorMatrix)); - haveAccumulatedColorMatrix = true; - } - - // We can only combine matrices if clamping of color components - // would have no effect. - if (!matrixNeedsClamping(accumulatedColorMatrix)) - continue; - } - - if (haveAccumulatedColorMatrix) - newList.append(WebKit::WebFilterOperation::createColorMatrixFilter(accumulatedColorMatrix)); - haveAccumulatedColorMatrix = false; - - switch (op.type()) { - case WebKit::WebFilterOperation::FilterTypeBlur: - case WebKit::WebFilterOperation::FilterTypeDropShadow: - case WebKit::WebFilterOperation::FilterTypeZoom: - newList.append(op); - break; - case WebKit::WebFilterOperation::FilterTypeBrightness: - case WebKit::WebFilterOperation::FilterTypeContrast: - case WebKit::WebFilterOperation::FilterTypeGrayscale: - case WebKit::WebFilterOperation::FilterTypeSepia: - case WebKit::WebFilterOperation::FilterTypeSaturate: - case WebKit::WebFilterOperation::FilterTypeHueRotate: - case WebKit::WebFilterOperation::FilterTypeInvert: - case WebKit::WebFilterOperation::FilterTypeOpacity: - case WebKit::WebFilterOperation::FilterTypeColorMatrix: - break; - } - } - if (haveAccumulatedColorMatrix) - newList.append(WebKit::WebFilterOperation::createColorMatrixFilter(accumulatedColorMatrix)); - return newList; -} - -SkBitmap CCRenderSurfaceFilters::apply(const WebKit::WebFilterOperations& filters, unsigned textureId, const FloatSize& size, WebKit::WebGraphicsContext3D* context3D, GrContext* grContext) -{ - if (!context3D || !grContext) - return SkBitmap(); - - WebKit::WebFilterOperations optimizedFilters = optimize(filters); - FilterBufferState state(grContext, size, textureId); - if (!state.init(optimizedFilters.size())) - return SkBitmap(); - - for (unsigned i = 0; i < optimizedFilters.size(); ++i) { - const WebKit::WebFilterOperation& op = optimizedFilters.at(i); - SkCanvas* canvas = state.canvas(); - switch (op.type()) { - case WebKit::WebFilterOperation::FilterTypeColorMatrix: { - SkPaint paint; - paint.setColorFilter(new SkColorMatrixFilter(op.matrix()))->unref(); - canvas->drawBitmap(state.source(), 0, 0, &paint); - break; - } - case WebKit::WebFilterOperation::FilterTypeBlur: { - float stdDeviation = op.amount(); - SkAutoTUnref filter(new SkBlurImageFilter(stdDeviation, stdDeviation)); - SkPaint paint; - paint.setImageFilter(filter.get()); - canvas->drawSprite(state.source(), 0, 0, &paint); - break; - } - case WebKit::WebFilterOperation::FilterTypeDropShadow: { - SkAutoTUnref blurFilter(new SkBlurImageFilter(op.amount(), op.amount())); - SkAutoTUnref colorFilter(SkColorFilter::CreateModeFilter(op.dropShadowColor(), SkXfermode::kSrcIn_Mode)); - SkPaint paint; - paint.setImageFilter(blurFilter.get()); - paint.setColorFilter(colorFilter.get()); - paint.setXfermodeMode(SkXfermode::kSrcOver_Mode); - canvas->saveLayer(0, &paint); - canvas->drawBitmap(state.source(), op.dropShadowOffset().x, -op.dropShadowOffset().y); - canvas->restore(); - canvas->drawBitmap(state.source(), 0, 0); - break; - } - case WebKit::WebFilterOperation::FilterTypeZoom: { - SkPaint paint; - SkAutoTUnref zoomFilter( - new SkMagnifierImageFilter( - SkRect::MakeXYWH(op.zoomRect().x, - op.zoomRect().y, - op.zoomRect().width, - op.zoomRect().height), - op.amount())); - paint.setImageFilter(zoomFilter.get()); - canvas->saveLayer(0, &paint); - canvas->drawBitmap(state.source(), 0, 0); - canvas->restore(); - break; - } - case WebKit::WebFilterOperation::FilterTypeBrightness: - case WebKit::WebFilterOperation::FilterTypeContrast: - case WebKit::WebFilterOperation::FilterTypeGrayscale: - case WebKit::WebFilterOperation::FilterTypeSepia: - case WebKit::WebFilterOperation::FilterTypeSaturate: - case WebKit::WebFilterOperation::FilterTypeHueRotate: - case WebKit::WebFilterOperation::FilterTypeInvert: - case WebKit::WebFilterOperation::FilterTypeOpacity: - ASSERT_NOT_REACHED(); - break; - } - state.swap(); - } - context3D->flush(); - return state.source(); -} - -} -#endif // USE(ACCELERATED_COMPOSITING) diff --git a/cc/CCRenderSurfaceFilters.h b/cc/CCRenderSurfaceFilters.h index cd199b5..f102a22 100644 --- a/cc/CCRenderSurfaceFilters.h +++ b/cc/CCRenderSurfaceFilters.h @@ -2,33 +2,5 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. - -#ifndef CCRenderSurfaceFilters_h -#define CCRenderSurfaceFilters_h - -#if USE(ACCELERATED_COMPOSITING) - -class GrContext; -class SkBitmap; - -namespace WebKit { -class WebFilterOperations; -class WebGraphicsContext3D; -} - -namespace cc { -class FloatSize; - -class CCRenderSurfaceFilters { -public: - static SkBitmap apply(const WebKit::WebFilterOperations& filters, unsigned textureId, const FloatSize&, WebKit::WebGraphicsContext3D*, GrContext*); - static WebKit::WebFilterOperations optimize(const WebKit::WebFilterOperations& filters); - -private: - CCRenderSurfaceFilters(); -}; - -} -#endif // USE(ACCELERATED_COMPOSITING) - -#endif +// Temporary forwarding header +#include "cc/render_surface_filters.h" diff --git a/cc/CCRenderer.cpp b/cc/CCRenderer.cpp deleted file mode 100644 index 69c04df..0000000 --- a/cc/CCRenderer.cpp +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "config.h" - -#include "CCRenderer.h" - -namespace cc { - -bool CCRenderer::haveCachedResourcesForRenderPassId(CCRenderPass::Id) const -{ - return false; -} - -bool CCRenderer::isContextLost() -{ - return false; -} - -} diff --git a/cc/CCRenderer.h b/cc/CCRenderer.h index 740ba0b..3e37b7f 100644 --- a/cc/CCRenderer.h +++ b/cc/CCRenderer.h @@ -2,83 +2,5 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CCRenderer_h -#define CCRenderer_h - -#include "base/basictypes.h" -#include "CCLayerTreeHost.h" -#include "CCRenderPass.h" -#include "FloatQuad.h" -#include "IntRect.h" -#include - -namespace cc { - -class CCScopedTexture; - -class CCRendererClient { -public: - virtual const IntSize& deviceViewportSize() const = 0; - virtual const CCLayerTreeSettings& settings() const = 0; - virtual void didLoseContext() = 0; - virtual void onSwapBuffersComplete() = 0; - virtual void releaseContentsTextures() = 0; - virtual void setFullRootLayerDamage() = 0; - virtual void setMemoryAllocationLimitBytes(size_t) = 0; -protected: - virtual ~CCRendererClient() { } -}; - -class CCRenderer { -public: - // This enum defines the various resource pools for the CCResourceProvider - // where textures get allocated. - enum ResourcePool { - ImplPool = 1, // This pool is for textures that get allocated on the impl thread (e.g. RenderSurfaces). - ContentPool // This pool is for textures that get allocated on the main thread (e.g. tiles). - }; - - virtual ~CCRenderer() { } - - virtual const RendererCapabilities& capabilities() const = 0; - - const CCLayerTreeSettings& settings() const { return m_client->settings(); } - - const IntSize& viewportSize() { return m_client->deviceViewportSize(); } - int viewportWidth() { return viewportSize().width(); } - int viewportHeight() { return viewportSize().height(); } - - virtual void viewportChanged() { } - - virtual void decideRenderPassAllocationsForFrame(const CCRenderPassList&) { } - virtual bool haveCachedResourcesForRenderPassId(CCRenderPass::Id) const; - - virtual void drawFrame(const CCRenderPassList&, const CCRenderPassIdHashMap&) = 0; - - // waits for rendering to finish - virtual void finish() = 0; - - virtual void doNoOp() { } - // puts backbuffer onscreen - virtual bool swapBuffers() = 0; - - virtual void getFramebufferPixels(void *pixels, const IntRect&) = 0; - - virtual bool isContextLost(); - - virtual void setVisible(bool) = 0; - -protected: - explicit CCRenderer(CCRendererClient* client) - : m_client(client) - { - } - - CCRendererClient* m_client; - - DISALLOW_COPY_AND_ASSIGN(CCRenderer); -}; - -} - -#endif // CCRenderer_h +// Temporary forwarding header +#include "cc/renderer.h" diff --git a/cc/CCRendererGL.cpp b/cc/CCRendererGL.cpp deleted file mode 100644 index f28cc50..0000000 --- a/cc/CCRendererGL.cpp +++ /dev/null @@ -1,1530 +0,0 @@ -// Copyright 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - - -#include "config.h" - -#if USE(ACCELERATED_COMPOSITING) -#include "CCRendererGL.h" - -#include "CCDamageTracker.h" -#include "CCLayerQuad.h" -#include "CCMathUtil.h" -#include "CCProxy.h" -#include "CCRenderPass.h" -#include "CCRenderSurfaceFilters.h" -#include "CCScopedTexture.h" -#include "CCSettings.h" -#include "CCSingleThreadProxy.h" -#include "CCVideoLayerImpl.h" -#include "Extensions3D.h" -#include "FloatQuad.h" -#include "GeometryBinding.h" -#include "GrTexture.h" -#include "NotImplemented.h" -#include "PlatformColor.h" -#include "SkBitmap.h" -#include "SkColor.h" -#include "TraceEvent.h" -#ifdef LOG -#undef LOG -#endif -#include "base/string_split.h" -#include "base/string_util.h" -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace std; -using WebKit::WebGraphicsContext3D; -using WebKit::WebGraphicsMemoryAllocation; -using WebKit::WebSharedGraphicsContext3D; -using WebKit::WebTransformationMatrix; - -namespace cc { - -namespace { - -bool needsIOSurfaceReadbackWorkaround() -{ -#if OS(DARWIN) - return true; -#else - return false; -#endif -} - -} // anonymous namespace - -PassOwnPtr CCRendererGL::create(CCRendererClient* client, CCResourceProvider* resourceProvider) -{ - OwnPtr renderer(adoptPtr(new CCRendererGL(client, resourceProvider))); - if (!renderer->initialize()) - return nullptr; - - return renderer.release(); -} - -CCRendererGL::CCRendererGL(CCRendererClient* client, - CCResourceProvider* resourceProvider) - : CCDirectRenderer(client, resourceProvider) - , m_offscreenFramebufferId(0) - , m_sharedGeometryQuad(FloatRect(-0.5f, -0.5f, 1.0f, 1.0f)) - , m_context(resourceProvider->graphicsContext3D()) - , m_isViewportChanged(false) - , m_isFramebufferDiscarded(false) - , m_isUsingBindUniform(false) - , m_visible(true) -{ - ASSERT(m_context); -} - -bool CCRendererGL::initialize() -{ - if (!m_context->makeContextCurrent()) - return false; - - m_context->setContextLostCallback(this); - m_context->pushGroupMarkerEXT("CompositorContext"); - - std::string extensionsString = UTF16ToASCII(m_context->getString(GraphicsContext3D::EXTENSIONS)); - std::vector extensionsList; - base::SplitString(extensionsString, ' ', &extensionsList); - std::set extensions(extensionsList.begin(), extensionsList.end()); - - if (settings().acceleratePainting && extensions.count("GL_EXT_texture_format_BGRA8888") - && extensions.count("GL_EXT_read_format_bgra")) - m_capabilities.usingAcceleratedPainting = true; - else - m_capabilities.usingAcceleratedPainting = false; - - - m_capabilities.contextHasCachedFrontBuffer = extensions.count("GL_CHROMIUM_front_buffer_cached"); - - m_capabilities.usingPartialSwap = CCSettings::partialSwapEnabled() && extensions.count("GL_CHROMIUM_post_sub_buffer"); - - // Use the swapBuffers callback only with the threaded proxy. - if (CCProxy::hasImplThread()) - m_capabilities.usingSwapCompleteCallback = extensions.count("GL_CHROMIUM_swapbuffers_complete_callback"); - if (m_capabilities.usingSwapCompleteCallback) - m_context->setSwapBuffersCompleteCallbackCHROMIUM(this); - - m_capabilities.usingSetVisibility = extensions.count("GL_CHROMIUM_set_visibility"); - - if (extensions.count("GL_CHROMIUM_iosurface")) - ASSERT(extensions.count("GL_ARB_texture_rectangle")); - - m_capabilities.usingGpuMemoryManager = extensions.count("GL_CHROMIUM_gpu_memory_manager"); - if (m_capabilities.usingGpuMemoryManager) - m_context->setMemoryAllocationChangedCallbackCHROMIUM(this); - - m_capabilities.usingDiscardFramebuffer = extensions.count("GL_CHROMIUM_discard_framebuffer"); - - m_capabilities.usingEglImage = extensions.count("GL_OES_EGL_image_external"); - - GLC(m_context, m_context->getIntegerv(GraphicsContext3D::MAX_TEXTURE_SIZE, &m_capabilities.maxTextureSize)); - m_capabilities.bestTextureFormat = PlatformColor::bestTextureFormat(m_context, extensions.count("GL_EXT_texture_format_BGRA8888")); - - m_isUsingBindUniform = extensions.count("GL_CHROMIUM_bind_uniform_location"); - - if (!initializeSharedObjects()) - return false; - - // Make sure the viewport and context gets initialized, even if it is to zero. - viewportChanged(); - return true; -} - -CCRendererGL::~CCRendererGL() -{ - ASSERT(CCProxy::isImplThread()); - m_context->setSwapBuffersCompleteCallbackCHROMIUM(0); - m_context->setMemoryAllocationChangedCallbackCHROMIUM(0); - m_context->setContextLostCallback(0); - cleanupSharedObjects(); -} - -const RendererCapabilities& CCRendererGL::capabilities() const -{ - return m_capabilities; -} - -WebGraphicsContext3D* CCRendererGL::context() -{ - return m_context; -} - -void CCRendererGL::debugGLCall(WebGraphicsContext3D* context, const char* command, const char* file, int line) -{ - unsigned long error = context->getError(); - if (error != GraphicsContext3D::NO_ERROR) - LOG_ERROR("GL command failed: File: %s\n\tLine %d\n\tcommand: %s, error %x\n", file, line, command, static_cast(error)); -} - -void CCRendererGL::setVisible(bool visible) -{ - if (m_visible == visible) - return; - m_visible = visible; - - // TODO: Replace setVisibilityCHROMIUM with an extension to explicitly manage front/backbuffers - // crbug.com/116049 - if (m_capabilities.usingSetVisibility) - m_context->setVisibilityCHROMIUM(visible); -} - -void CCRendererGL::releaseRenderPassTextures() -{ - m_renderPassTextures.clear(); -} - -void CCRendererGL::viewportChanged() -{ - m_isViewportChanged = true; -} - -void CCRendererGL::clearFramebuffer(DrawingFrame& frame) -{ - // On DEBUG builds, opaque render passes are cleared to blue to easily see regions that were not drawn on the screen. - if (frame.currentRenderPass->hasTransparentBackground()) - GLC(m_context, m_context->clearColor(0, 0, 0, 0)); - else - GLC(m_context, m_context->clearColor(0, 0, 1, 1)); - -#if defined(NDEBUG) - if (frame.currentRenderPass->hasTransparentBackground()) -#endif - m_context->clear(GraphicsContext3D::COLOR_BUFFER_BIT); -} - -void CCRendererGL::beginDrawingFrame(DrawingFrame& frame) -{ - // FIXME: Remove this once framebuffer is automatically recreated on first use - ensureFramebuffer(); - - if (viewportSize().isEmpty()) - return; - - TRACE_EVENT0("cc", "CCRendererGL::drawLayers"); - if (m_isViewportChanged) { - // Only reshape when we know we are going to draw. Otherwise, the reshape - // can leave the window at the wrong size if we never draw and the proper - // viewport size is never set. - m_isViewportChanged = false; - m_context->reshape(viewportWidth(), viewportHeight()); - } - - makeContextCurrent(); - // Bind the common vertex attributes used for drawing all the layers. - m_sharedGeometry->prepareForDraw(); - - GLC(m_context, m_context->disable(GraphicsContext3D::DEPTH_TEST)); - GLC(m_context, m_context->disable(GraphicsContext3D::CULL_FACE)); - GLC(m_context, m_context->colorMask(true, true, true, true)); - GLC(m_context, m_context->enable(GraphicsContext3D::BLEND)); - GLC(m_context, m_context->blendFunc(GraphicsContext3D::ONE, GraphicsContext3D::ONE_MINUS_SRC_ALPHA)); -} - -void CCRendererGL::doNoOp() -{ - GLC(m_context, m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, 0)); - GLC(m_context, m_context->flush()); -} - -void CCRendererGL::drawQuad(DrawingFrame& frame, const CCDrawQuad* quad) -{ - if (quad->needsBlending()) - GLC(m_context, m_context->enable(GraphicsContext3D::BLEND)); - else - GLC(m_context, m_context->disable(GraphicsContext3D::BLEND)); - - switch (quad->material()) { - case CCDrawQuad::Invalid: - ASSERT_NOT_REACHED(); - break; - case CCDrawQuad::Checkerboard: - drawCheckerboardQuad(frame, CCCheckerboardDrawQuad::materialCast(quad)); - break; - case CCDrawQuad::DebugBorder: - drawDebugBorderQuad(frame, CCDebugBorderDrawQuad::materialCast(quad)); - break; - case CCDrawQuad::IOSurfaceContent: - drawIOSurfaceQuad(frame, CCIOSurfaceDrawQuad::materialCast(quad)); - break; - case CCDrawQuad::RenderPass: - drawRenderPassQuad(frame, CCRenderPassDrawQuad::materialCast(quad)); - break; - case CCDrawQuad::SolidColor: - drawSolidColorQuad(frame, CCSolidColorDrawQuad::materialCast(quad)); - break; - case CCDrawQuad::StreamVideoContent: - drawStreamVideoQuad(frame, CCStreamVideoDrawQuad::materialCast(quad)); - break; - case CCDrawQuad::TextureContent: - drawTextureQuad(frame, CCTextureDrawQuad::materialCast(quad)); - break; - case CCDrawQuad::TiledContent: - drawTileQuad(frame, CCTileDrawQuad::materialCast(quad)); - break; - case CCDrawQuad::YUVVideoContent: - drawYUVVideoQuad(frame, CCYUVVideoDrawQuad::materialCast(quad)); - break; - } -} - -void CCRendererGL::drawCheckerboardQuad(const DrawingFrame& frame, const CCCheckerboardDrawQuad* quad) -{ - const TileCheckerboardProgram* program = tileCheckerboardProgram(); - ASSERT(program && program->initialized()); - GLC(context(), context()->useProgram(program->program())); - - SkColor color = quad->color(); - GLC(context(), context()->uniform4f(program->fragmentShader().colorLocation(), SkColorGetR(color) / 255.0, SkColorGetG(color) / 255.0, SkColorGetB(color) / 255.0, 1)); - - const int checkerboardWidth = 16; - float frequency = 1.0 / checkerboardWidth; - - IntRect tileRect = quad->quadRect(); - float texOffsetX = tileRect.x() % checkerboardWidth; - float texOffsetY = tileRect.y() % checkerboardWidth; - float texScaleX = tileRect.width(); - float texScaleY = tileRect.height(); - GLC(context(), context()->uniform4f(program->fragmentShader().texTransformLocation(), texOffsetX, texOffsetY, texScaleX, texScaleY)); - - GLC(context(), context()->uniform1f(program->fragmentShader().frequencyLocation(), frequency)); - - setShaderOpacity(quad->opacity(), program->fragmentShader().alphaLocation()); - drawQuadGeometry(frame, quad->quadTransform(), quad->quadRect(), program->vertexShader().matrixLocation()); -} - -void CCRendererGL::drawDebugBorderQuad(const DrawingFrame& frame, const CCDebugBorderDrawQuad* quad) -{ - static float glMatrix[16]; - const SolidColorProgram* program = solidColorProgram(); - ASSERT(program && program->initialized()); - GLC(context(), context()->useProgram(program->program())); - - // Use the full quadRect for debug quads to not move the edges based on partial swaps. - const IntRect& layerRect = quad->quadRect(); - WebTransformationMatrix renderMatrix = quad->quadTransform(); - renderMatrix.translate(0.5 * layerRect.width() + layerRect.x(), 0.5 * layerRect.height() + layerRect.y()); - renderMatrix.scaleNonUniform(layerRect.width(), layerRect.height()); - CCRendererGL::toGLMatrix(&glMatrix[0], frame.projectionMatrix * renderMatrix); - GLC(context(), context()->uniformMatrix4fv(program->vertexShader().matrixLocation(), 1, false, &glMatrix[0])); - - SkColor color = quad->color(); - float alpha = SkColorGetA(color) / 255.0; - - GLC(context(), context()->uniform4f(program->fragmentShader().colorLocation(), (SkColorGetR(color) / 255.0) * alpha, (SkColorGetG(color) / 255.0) * alpha, (SkColorGetB(color) / 255.0) * alpha, alpha)); - - GLC(context(), context()->lineWidth(quad->width())); - - // The indices for the line are stored in the same array as the triangle indices. - GLC(context(), context()->drawElements(GraphicsContext3D::LINE_LOOP, 4, GraphicsContext3D::UNSIGNED_SHORT, 6 * sizeof(unsigned short))); -} - -static inline SkBitmap applyFilters(CCRendererGL* renderer, const WebKit::WebFilterOperations& filters, CCScopedTexture* sourceTexture) -{ - if (filters.isEmpty()) - return SkBitmap(); - - WebGraphicsContext3D* filterContext = CCProxy::hasImplThread() ? WebSharedGraphicsContext3D::compositorThreadContext() : WebSharedGraphicsContext3D::mainThreadContext(); - GrContext* filterGrContext = CCProxy::hasImplThread() ? WebSharedGraphicsContext3D::compositorThreadGrContext() : WebSharedGraphicsContext3D::mainThreadGrContext(); - - if (!filterContext || !filterGrContext) - return SkBitmap(); - - renderer->context()->flush(); - - CCResourceProvider::ScopedWriteLockGL lock(renderer->resourceProvider(), sourceTexture->id()); - SkBitmap source = CCRenderSurfaceFilters::apply(filters, lock.textureId(), sourceTexture->size(), filterContext, filterGrContext); - return source; -} - -PassOwnPtr CCRendererGL::drawBackgroundFilters(DrawingFrame& frame, const CCRenderPassDrawQuad* quad, const WebKit::WebFilterOperations& filters, const WebTransformationMatrix& contentsDeviceTransform) -{ - // This method draws a background filter, which applies a filter to any pixels behind the quad and seen through its background. - // The algorithm works as follows: - // 1. Compute a bounding box around the pixels that will be visible through the quad. - // 2. Read the pixels in the bounding box into a buffer R. - // 3. Apply the background filter to R, so that it is applied in the pixels' coordinate space. - // 4. Apply the quad's inverse transform to map the pixels in R into the quad's content space. This implicitly - // clips R by the content bounds of the quad since the destination texture has bounds matching the quad's content. - // 5. Draw the background texture for the contents using the same transform as used to draw the contents itself. This is done - // without blending to replace the current background pixels with the new filtered background. - // 6. Draw the contents of the quad over drop of the new background with blending, as per usual. The filtered background - // pixels will show through any non-opaque pixels in this draws. - // - // Pixel copies in this algorithm occur at steps 2, 3, 4, and 5. - - // FIXME: When this algorithm changes, update CCLayerTreeHost::prioritizeTextures() accordingly. - - if (filters.isEmpty()) - return nullptr; - - // FIXME: We only allow background filters on an opaque render surface because other surfaces may contain - // translucent pixels, and the contents behind those translucent pixels wouldn't have the filter applied. - if (frame.currentRenderPass->hasTransparentBackground()) - return nullptr; - ASSERT(!frame.currentTexture); - - // FIXME: Do a single readback for both the surface and replica and cache the filtered results (once filter textures are not reused). - IntRect deviceRect = enclosingIntRect(CCMathUtil::mapClippedRect(contentsDeviceTransform, sharedGeometryQuad().boundingBox())); - - int top, right, bottom, left; - filters.getOutsets(top, right, bottom, left); - deviceRect.move(-left, -top); - deviceRect.expand(left + right, top + bottom); - - deviceRect.intersect(frame.currentRenderPass->outputRect()); - - OwnPtr deviceBackgroundTexture = CCScopedTexture::create(m_resourceProvider); - if (!getFramebufferTexture(deviceBackgroundTexture.get(), deviceRect)) - return nullptr; - - SkBitmap filteredDeviceBackground = applyFilters(this, filters, deviceBackgroundTexture.get()); - if (!filteredDeviceBackground.getTexture()) - return nullptr; - - GrTexture* texture = reinterpret_cast(filteredDeviceBackground.getTexture()); - int filteredDeviceBackgroundTextureId = texture->getTextureHandle(); - - OwnPtr backgroundTexture = CCScopedTexture::create(m_resourceProvider); - if (!backgroundTexture->allocate(CCRenderer::ImplPool, quad->quadRect().size(), GraphicsContext3D::RGBA, CCResourceProvider::TextureUsageFramebuffer)) - return nullptr; - - const CCRenderPass* targetRenderPass = frame.currentRenderPass; - bool usingBackgroundTexture = useScopedTexture(frame, backgroundTexture.get(), quad->quadRect()); - - if (usingBackgroundTexture) { - // Copy the readback pixels from device to the background texture for the surface. - WebTransformationMatrix deviceToFramebufferTransform; - deviceToFramebufferTransform.translate(quad->quadRect().width() / 2.0, quad->quadRect().height() / 2.0); - deviceToFramebufferTransform.scale3d(quad->quadRect().width(), quad->quadRect().height(), 1); - deviceToFramebufferTransform.multiply(contentsDeviceTransform.inverse()); - copyTextureToFramebuffer(frame, filteredDeviceBackgroundTextureId, deviceRect, deviceToFramebufferTransform); - } - - useRenderPass(frame, targetRenderPass); - - if (!usingBackgroundTexture) - return nullptr; - return backgroundTexture.release(); -} - -void CCRendererGL::drawRenderPassQuad(DrawingFrame& frame, const CCRenderPassDrawQuad* quad) -{ - CachedTexture* contentsTexture = m_renderPassTextures.get(quad->renderPassId()); - if (!contentsTexture || !contentsTexture->id()) - return; - - const CCRenderPass* renderPass = frame.renderPassesById->get(quad->renderPassId()); - ASSERT(renderPass); - if (!renderPass) - return; - - WebTransformationMatrix renderMatrix = quad->quadTransform(); - renderMatrix.translate(0.5 * quad->quadRect().width() + quad->quadRect().x(), 0.5 * quad->quadRect().height() + quad->quadRect().y()); - WebTransformationMatrix deviceMatrix = renderMatrix; - deviceMatrix.scaleNonUniform(quad->quadRect().width(), quad->quadRect().height()); - WebTransformationMatrix contentsDeviceTransform = WebTransformationMatrix(frame.windowMatrix * frame.projectionMatrix * deviceMatrix).to2dTransform(); - - // Can only draw surface if device matrix is invertible. - if (!contentsDeviceTransform.isInvertible()) - return; - - OwnPtr backgroundTexture = drawBackgroundFilters(frame, quad, renderPass->backgroundFilters(), contentsDeviceTransform); - - // FIXME: Cache this value so that we don't have to do it for both the surface and its replica. - // Apply filters to the contents texture. - SkBitmap filterBitmap = applyFilters(this, renderPass->filters(), contentsTexture); - OwnPtr contentsResourceLock; - unsigned contentsTextureId = 0; - if (filterBitmap.getTexture()) { - GrTexture* texture = reinterpret_cast(filterBitmap.getTexture()); - contentsTextureId = texture->getTextureHandle(); - } else { - contentsResourceLock = adoptPtr(new CCResourceProvider::ScopedReadLockGL(m_resourceProvider, contentsTexture->id())); - contentsTextureId = contentsResourceLock->textureId(); - } - - // Draw the background texture if there is one. - if (backgroundTexture) { - ASSERT(backgroundTexture->size() == quad->quadRect().size()); - CCResourceProvider::ScopedReadLockGL lock(m_resourceProvider, backgroundTexture->id()); - copyTextureToFramebuffer(frame, lock.textureId(), quad->quadRect(), quad->quadTransform()); - } - - bool clipped = false; - FloatQuad deviceQuad = CCMathUtil::mapQuad(contentsDeviceTransform, sharedGeometryQuad(), clipped); - ASSERT(!clipped); - CCLayerQuad deviceLayerBounds = CCLayerQuad(FloatQuad(deviceQuad.boundingBox())); - CCLayerQuad deviceLayerEdges = CCLayerQuad(deviceQuad); - - // Use anti-aliasing programs only when necessary. - bool useAA = (!deviceQuad.isRectilinear() || !deviceQuad.boundingBox().isExpressibleAsIntRect()); - if (useAA) { - deviceLayerBounds.inflateAntiAliasingDistance(); - deviceLayerEdges.inflateAntiAliasingDistance(); - } - - OwnPtr maskResourceLock; - unsigned maskTextureId = 0; - if (quad->maskResourceId()) { - maskResourceLock = adoptPtr(new CCResourceProvider::ScopedReadLockGL(m_resourceProvider, quad->maskResourceId())); - maskTextureId = maskResourceLock->textureId(); - } - - // FIXME: use the backgroundTexture and blend the background in with this draw instead of having a separate copy of the background texture. - - GLC(context(), context()->activeTexture(GraphicsContext3D::TEXTURE0)); - context()->bindTexture(GraphicsContext3D::TEXTURE_2D, contentsTextureId); - - int shaderQuadLocation = -1; - int shaderEdgeLocation = -1; - int shaderMaskSamplerLocation = -1; - int shaderMaskTexCoordScaleLocation = -1; - int shaderMaskTexCoordOffsetLocation = -1; - int shaderMatrixLocation = -1; - int shaderAlphaLocation = -1; - if (useAA && maskTextureId) { - const RenderPassMaskProgramAA* program = renderPassMaskProgramAA(); - GLC(context(), context()->useProgram(program->program())); - GLC(context(), context()->uniform1i(program->fragmentShader().samplerLocation(), 0)); - - shaderQuadLocation = program->vertexShader().pointLocation(); - shaderEdgeLocation = program->fragmentShader().edgeLocation(); - shaderMaskSamplerLocation = program->fragmentShader().maskSamplerLocation(); - shaderMaskTexCoordScaleLocation = program->fragmentShader().maskTexCoordScaleLocation(); - shaderMaskTexCoordOffsetLocation = program->fragmentShader().maskTexCoordOffsetLocation(); - shaderMatrixLocation = program->vertexShader().matrixLocation(); - shaderAlphaLocation = program->fragmentShader().alphaLocation(); - } else if (!useAA && maskTextureId) { - const RenderPassMaskProgram* program = renderPassMaskProgram(); - GLC(context(), context()->useProgram(program->program())); - GLC(context(), context()->uniform1i(program->fragmentShader().samplerLocation(), 0)); - - shaderMaskSamplerLocation = program->fragmentShader().maskSamplerLocation(); - shaderMaskTexCoordScaleLocation = program->fragmentShader().maskTexCoordScaleLocation(); - shaderMaskTexCoordOffsetLocation = program->fragmentShader().maskTexCoordOffsetLocation(); - shaderMatrixLocation = program->vertexShader().matrixLocation(); - shaderAlphaLocation = program->fragmentShader().alphaLocation(); - } else if (useAA && !maskTextureId) { - const RenderPassProgramAA* program = renderPassProgramAA(); - GLC(context(), context()->useProgram(program->program())); - GLC(context(), context()->uniform1i(program->fragmentShader().samplerLocation(), 0)); - - shaderQuadLocation = program->vertexShader().pointLocation(); - shaderEdgeLocation = program->fragmentShader().edgeLocation(); - shaderMatrixLocation = program->vertexShader().matrixLocation(); - shaderAlphaLocation = program->fragmentShader().alphaLocation(); - } else { - const RenderPassProgram* program = renderPassProgram(); - GLC(context(), context()->useProgram(program->program())); - GLC(context(), context()->uniform1i(program->fragmentShader().samplerLocation(), 0)); - - shaderMatrixLocation = program->vertexShader().matrixLocation(); - shaderAlphaLocation = program->fragmentShader().alphaLocation(); - } - - if (shaderMaskSamplerLocation != -1) { - ASSERT(shaderMaskTexCoordScaleLocation != 1); - ASSERT(shaderMaskTexCoordOffsetLocation != 1); - GLC(context(), context()->activeTexture(GraphicsContext3D::TEXTURE1)); - GLC(context(), context()->uniform1i(shaderMaskSamplerLocation, 1)); - GLC(context(), context()->uniform2f(shaderMaskTexCoordScaleLocation, quad->maskTexCoordScaleX(), quad->maskTexCoordScaleY())); - GLC(context(), context()->uniform2f(shaderMaskTexCoordOffsetLocation, quad->maskTexCoordOffsetX(), quad->maskTexCoordOffsetY())); - context()->bindTexture(GraphicsContext3D::TEXTURE_2D, maskTextureId); - GLC(context(), context()->activeTexture(GraphicsContext3D::TEXTURE0)); - } - - if (shaderEdgeLocation != -1) { - float edge[24]; - deviceLayerEdges.toFloatArray(edge); - deviceLayerBounds.toFloatArray(&edge[12]); - GLC(context(), context()->uniform3fv(shaderEdgeLocation, 8, edge)); - } - - // Map device space quad to surface space. contentsDeviceTransform has no 3d component since it was generated with to2dTransform() so we don't need to project. - FloatQuad surfaceQuad = CCMathUtil::mapQuad(contentsDeviceTransform.inverse(), deviceLayerEdges.floatQuad(), clipped); - ASSERT(!clipped); - - setShaderOpacity(quad->opacity(), shaderAlphaLocation); - setShaderFloatQuad(surfaceQuad, shaderQuadLocation); - drawQuadGeometry(frame, quad->quadTransform(), quad->quadRect(), shaderMatrixLocation); -} - -void CCRendererGL::drawSolidColorQuad(const DrawingFrame& frame, const CCSolidColorDrawQuad* quad) -{ - const SolidColorProgram* program = solidColorProgram(); - GLC(context(), context()->useProgram(program->program())); - - SkColor color = quad->color(); - float opacity = quad->opacity(); - float alpha = (SkColorGetA(color) / 255.0) * opacity; - - GLC(context(), context()->uniform4f(program->fragmentShader().colorLocation(), (SkColorGetR(color) / 255.0) * alpha, (SkColorGetG(color) / 255.0) * alpha, (SkColorGetB(color) / 255.0) * alpha, alpha)); - - drawQuadGeometry(frame, quad->quadTransform(), quad->quadRect(), program->vertexShader().matrixLocation()); -} - -struct TileProgramUniforms { - unsigned program; - unsigned samplerLocation; - unsigned vertexTexTransformLocation; - unsigned fragmentTexTransformLocation; - unsigned edgeLocation; - unsigned matrixLocation; - unsigned alphaLocation; - unsigned pointLocation; -}; - -template -static void tileUniformLocation(T program, TileProgramUniforms& uniforms) -{ - uniforms.program = program->program(); - uniforms.vertexTexTransformLocation = program->vertexShader().vertexTexTransformLocation(); - uniforms.matrixLocation = program->vertexShader().matrixLocation(); - uniforms.pointLocation = program->vertexShader().pointLocation(); - - uniforms.samplerLocation = program->fragmentShader().samplerLocation(); - uniforms.alphaLocation = program->fragmentShader().alphaLocation(); - uniforms.fragmentTexTransformLocation = program->fragmentShader().fragmentTexTransformLocation(); - uniforms.edgeLocation = program->fragmentShader().edgeLocation(); -} - -void CCRendererGL::drawTileQuad(const DrawingFrame& frame, const CCTileDrawQuad* quad) -{ - IntRect tileRect = quad->quadVisibleRect(); - - FloatRect clampRect(tileRect); - // Clamp texture coordinates to avoid sampling outside the layer - // by deflating the tile region half a texel or half a texel - // minus epsilon for one pixel layers. The resulting clamp region - // is mapped to the unit square by the vertex shader and mapped - // back to normalized texture coordinates by the fragment shader - // after being clamped to 0-1 range. - const float epsilon = 1 / 1024.0f; - float clampX = min(0.5, clampRect.width() / 2.0 - epsilon); - float clampY = min(0.5, clampRect.height() / 2.0 - epsilon); - clampRect.inflateX(-clampX); - clampRect.inflateY(-clampY); - FloatSize clampOffset = clampRect.minXMinYCorner() - FloatRect(tileRect).minXMinYCorner(); - - FloatPoint textureOffset = quad->textureOffset() + clampOffset + - IntPoint(tileRect.location() - quad->quadRect().location()); - - // Map clamping rectangle to unit square. - float vertexTexTranslateX = -clampRect.x() / clampRect.width(); - float vertexTexTranslateY = -clampRect.y() / clampRect.height(); - float vertexTexScaleX = tileRect.width() / clampRect.width(); - float vertexTexScaleY = tileRect.height() / clampRect.height(); - - // Map to normalized texture coordinates. - const IntSize& textureSize = quad->textureSize(); - float fragmentTexTranslateX = textureOffset.x() / textureSize.width(); - float fragmentTexTranslateY = textureOffset.y() / textureSize.height(); - float fragmentTexScaleX = clampRect.width() / textureSize.width(); - float fragmentTexScaleY = clampRect.height() / textureSize.height(); - - - FloatQuad localQuad; - WebTransformationMatrix deviceTransform = WebTransformationMatrix(frame.windowMatrix * frame.projectionMatrix * quad->quadTransform()).to2dTransform(); - if (!deviceTransform.isInvertible()) - return; - - bool clipped = false; - FloatQuad deviceLayerQuad = CCMathUtil::mapQuad(deviceTransform, FloatQuad(quad->visibleContentRect()), clipped); - ASSERT(!clipped); - - TileProgramUniforms uniforms; - // For now, we simply skip anti-aliasing with the quad is clipped. This only happens - // on perspective transformed layers that go partially behind the camera. - if (quad->isAntialiased() && !clipped) { - if (quad->swizzleContents()) - tileUniformLocation(tileProgramSwizzleAA(), uniforms); - else - tileUniformLocation(tileProgramAA(), uniforms); - } else { - if (quad->needsBlending()) { - if (quad->swizzleContents()) - tileUniformLocation(tileProgramSwizzle(), uniforms); - else - tileUniformLocation(tileProgram(), uniforms); - } else { - if (quad->swizzleContents()) - tileUniformLocation(tileProgramSwizzleOpaque(), uniforms); - else - tileUniformLocation(tileProgramOpaque(), uniforms); - } - } - - GLC(context(), context()->useProgram(uniforms.program)); - GLC(context(), context()->uniform1i(uniforms.samplerLocation, 0)); - GLC(context(), context()->activeTexture(GraphicsContext3D::TEXTURE0)); - CCResourceProvider::ScopedReadLockGL quadResourceLock(m_resourceProvider, quad->resourceId()); - GLC(context(), context()->bindTexture(GraphicsContext3D::TEXTURE_2D, quadResourceLock.textureId())); - GLC(context(), context()->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, quad->textureFilter())); - GLC(context(), context()->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, quad->textureFilter())); - - bool useAA = !clipped && quad->isAntialiased(); - if (useAA) { - CCLayerQuad deviceLayerBounds = CCLayerQuad(FloatQuad(deviceLayerQuad.boundingBox())); - deviceLayerBounds.inflateAntiAliasingDistance(); - - CCLayerQuad deviceLayerEdges = CCLayerQuad(deviceLayerQuad); - deviceLayerEdges.inflateAntiAliasingDistance(); - - float edge[24]; - deviceLayerEdges.toFloatArray(edge); - deviceLayerBounds.toFloatArray(&edge[12]); - GLC(context(), context()->uniform3fv(uniforms.edgeLocation, 8, edge)); - - GLC(context(), context()->uniform4f(uniforms.vertexTexTransformLocation, vertexTexTranslateX, vertexTexTranslateY, vertexTexScaleX, vertexTexScaleY)); - GLC(context(), context()->uniform4f(uniforms.fragmentTexTransformLocation, fragmentTexTranslateX, fragmentTexTranslateY, fragmentTexScaleX, fragmentTexScaleY)); - - FloatPoint bottomRight(tileRect.maxX(), tileRect.maxY()); - FloatPoint bottomLeft(tileRect.x(), tileRect.maxY()); - FloatPoint topLeft(tileRect.x(), tileRect.y()); - FloatPoint topRight(tileRect.maxX(), tileRect.y()); - - // Map points to device space. - bottomRight = CCMathUtil::mapPoint(deviceTransform, bottomRight, clipped); - ASSERT(!clipped); - bottomLeft = CCMathUtil::mapPoint(deviceTransform, bottomLeft, clipped); - ASSERT(!clipped); - topLeft = CCMathUtil::mapPoint(deviceTransform, topLeft, clipped); - ASSERT(!clipped); - topRight = CCMathUtil::mapPoint(deviceTransform, topRight, clipped); - ASSERT(!clipped); - - CCLayerQuad::Edge bottomEdge(bottomRight, bottomLeft); - CCLayerQuad::Edge leftEdge(bottomLeft, topLeft); - CCLayerQuad::Edge topEdge(topLeft, topRight); - CCLayerQuad::Edge rightEdge(topRight, bottomRight); - - // Only apply anti-aliasing to edges not clipped by culling or scissoring. - if (quad->topEdgeAA() && tileRect.y() == quad->quadRect().y()) - topEdge = deviceLayerEdges.top(); - if (quad->leftEdgeAA() && tileRect.x() == quad->quadRect().x()) - leftEdge = deviceLayerEdges.left(); - if (quad->rightEdgeAA() && tileRect.maxX() == quad->quadRect().maxX()) - rightEdge = deviceLayerEdges.right(); - if (quad->bottomEdgeAA() && tileRect.maxY() == quad->quadRect().maxY()) - bottomEdge = deviceLayerEdges.bottom(); - - float sign = FloatQuad(tileRect).isCounterclockwise() ? -1 : 1; - bottomEdge.scale(sign); - leftEdge.scale(sign); - topEdge.scale(sign); - rightEdge.scale(sign); - - // Create device space quad. - CCLayerQuad deviceQuad(leftEdge, topEdge, rightEdge, bottomEdge); - - // Map device space quad to local space. contentsDeviceTransform has no 3d component since it was generated with to2dTransform() so we don't need to project. - WebTransformationMatrix inverseDeviceTransform = deviceTransform.inverse(); - localQuad = CCMathUtil::mapQuad(inverseDeviceTransform, deviceQuad.floatQuad(), clipped); - - // We should not ASSERT(!clipped) here, because anti-aliasing inflation may cause deviceQuad to become - // clipped. To our knowledge this scenario does not need to be handled differently than the unclipped case. - } else { - // Move fragment shader transform to vertex shader. We can do this while - // still producing correct results as fragmentTexTransformLocation - // should always be non-negative when tiles are transformed in a way - // that could result in sampling outside the layer. - vertexTexScaleX *= fragmentTexScaleX; - vertexTexScaleY *= fragmentTexScaleY; - vertexTexTranslateX *= fragmentTexScaleX; - vertexTexTranslateY *= fragmentTexScaleY; - vertexTexTranslateX += fragmentTexTranslateX; - vertexTexTranslateY += fragmentTexTranslateY; - - GLC(context(), context()->uniform4f(uniforms.vertexTexTransformLocation, vertexTexTranslateX, vertexTexTranslateY, vertexTexScaleX, vertexTexScaleY)); - - localQuad = FloatRect(tileRect); - } - - // Normalize to tileRect. - localQuad.scale(1.0f / tileRect.width(), 1.0f / tileRect.height()); - - setShaderOpacity(quad->opacity(), uniforms.alphaLocation); - setShaderFloatQuad(localQuad, uniforms.pointLocation); - - // The tile quad shader behaves differently compared to all other shaders. - // The transform and vertex data are used to figure out the extents that the - // un-antialiased quad should have and which vertex this is and the float - // quad passed in via uniform is the actual geometry that gets used to draw - // it. This is why this centered rect is used and not the original quadRect. - FloatRect centeredRect(FloatPoint(-0.5 * tileRect.width(), -0.5 * tileRect.height()), tileRect.size()); - drawQuadGeometry(frame, quad->quadTransform(), centeredRect, uniforms.matrixLocation); -} - -void CCRendererGL::drawYUVVideoQuad(const DrawingFrame& frame, const CCYUVVideoDrawQuad* quad) -{ - const VideoYUVProgram* program = videoYUVProgram(); - ASSERT(program && program->initialized()); - - const CCVideoLayerImpl::FramePlane& yPlane = quad->yPlane(); - const CCVideoLayerImpl::FramePlane& uPlane = quad->uPlane(); - const CCVideoLayerImpl::FramePlane& vPlane = quad->vPlane(); - - CCResourceProvider::ScopedReadLockGL yPlaneLock(m_resourceProvider, yPlane.resourceId); - CCResourceProvider::ScopedReadLockGL uPlaneLock(m_resourceProvider, uPlane.resourceId); - CCResourceProvider::ScopedReadLockGL vPlaneLock(m_resourceProvider, vPlane.resourceId); - GLC(context(), context()->activeTexture(GraphicsContext3D::TEXTURE1)); - GLC(context(), context()->bindTexture(GraphicsContext3D::TEXTURE_2D, yPlaneLock.textureId())); - GLC(context(), context()->activeTexture(GraphicsContext3D::TEXTURE2)); - GLC(context(), context()->bindTexture(GraphicsContext3D::TEXTURE_2D, uPlaneLock.textureId())); - GLC(context(), context()->activeTexture(GraphicsContext3D::TEXTURE3)); - GLC(context(), context()->bindTexture(GraphicsContext3D::TEXTURE_2D, vPlaneLock.textureId())); - - GLC(context(), context()->useProgram(program->program())); - - float yWidthScaleFactor = static_cast(yPlane.visibleSize.width()) / yPlane.size.width(); - // Arbitrarily take the u sizes because u and v dimensions are identical. - float uvWidthScaleFactor = static_cast(uPlane.visibleSize.width()) / uPlane.size.width(); - GLC(context(), context()->uniform1f(program->vertexShader().yWidthScaleFactorLocation(), yWidthScaleFactor)); - GLC(context(), context()->uniform1f(program->vertexShader().uvWidthScaleFactorLocation(), uvWidthScaleFactor)); - - GLC(context(), context()->uniform1i(program->fragmentShader().yTextureLocation(), 1)); - GLC(context(), context()->uniform1i(program->fragmentShader().uTextureLocation(), 2)); - GLC(context(), context()->uniform1i(program->fragmentShader().vTextureLocation(), 3)); - - // These values are magic numbers that are used in the transformation from YUV to RGB color values. - // They are taken from the following webpage: http://www.fourcc.org/fccyvrgb.php - float yuv2RGB[9] = { - 1.164f, 1.164f, 1.164f, - 0.f, -.391f, 2.018f, - 1.596f, -.813f, 0.f, - }; - GLC(context(), context()->uniformMatrix3fv(program->fragmentShader().ccMatrixLocation(), 1, 0, yuv2RGB)); - - // These values map to 16, 128, and 128 respectively, and are computed - // as a fraction over 256 (e.g. 16 / 256 = 0.0625). - // They are used in the YUV to RGBA conversion formula: - // Y - 16 : Gives 16 values of head and footroom for overshooting - // U - 128 : Turns unsigned U into signed U [-128,127] - // V - 128 : Turns unsigned V into signed V [-128,127] - float yuvAdjust[3] = { - -0.0625f, - -0.5f, - -0.5f, - }; - GLC(context(), context()->uniform3fv(program->fragmentShader().yuvAdjLocation(), 1, yuvAdjust)); - - setShaderOpacity(quad->opacity(), program->fragmentShader().alphaLocation()); - drawQuadGeometry(frame, quad->quadTransform(), quad->quadRect(), program->vertexShader().matrixLocation()); - - // Reset active texture back to texture 0. - GLC(context(), context()->activeTexture(GraphicsContext3D::TEXTURE0)); -} - -void CCRendererGL::drawStreamVideoQuad(const DrawingFrame& frame, const CCStreamVideoDrawQuad* quad) -{ - static float glMatrix[16]; - - ASSERT(m_capabilities.usingEglImage); - - const VideoStreamTextureProgram* program = videoStreamTextureProgram(); - GLC(context(), context()->useProgram(program->program())); - - toGLMatrix(&glMatrix[0], quad->matrix()); - GLC(context(), context()->uniformMatrix4fv(program->vertexShader().texMatrixLocation(), 1, false, glMatrix)); - - GLC(context(), context()->activeTexture(GraphicsContext3D::TEXTURE0)); - GLC(context(), context()->bindTexture(Extensions3DChromium::GL_TEXTURE_EXTERNAL_OES, quad->textureId())); - - GLC(context(), context()->uniform1i(program->fragmentShader().samplerLocation(), 0)); - - setShaderOpacity(quad->opacity(), program->fragmentShader().alphaLocation()); - drawQuadGeometry(frame, quad->quadTransform(), quad->quadRect(), program->vertexShader().matrixLocation()); -} - -struct TextureProgramBinding { - template void set(Program* program) - { - ASSERT(program && program->initialized()); - programId = program->program(); - samplerLocation = program->fragmentShader().samplerLocation(); - matrixLocation = program->vertexShader().matrixLocation(); - alphaLocation = program->fragmentShader().alphaLocation(); - } - int programId; - int samplerLocation; - int matrixLocation; - int alphaLocation; -}; - -struct TexTransformTextureProgramBinding : TextureProgramBinding { - template void set(Program* program) - { - TextureProgramBinding::set(program); - texTransformLocation = program->vertexShader().texTransformLocation(); - } - int texTransformLocation; -}; - -void CCRendererGL::drawTextureQuad(const DrawingFrame& frame, const CCTextureDrawQuad* quad) -{ - ASSERT(CCProxy::isImplThread()); - - TexTransformTextureProgramBinding binding; - if (quad->flipped()) - binding.set(textureProgramFlip()); - else - binding.set(textureProgram()); - GLC(context(), context()->useProgram(binding.programId)); - GLC(context(), context()->uniform1i(binding.samplerLocation, 0)); - const FloatRect& uvRect = quad->uvRect(); - GLC(context(), context()->uniform4f(binding.texTransformLocation, uvRect.x(), uvRect.y(), uvRect.width(), uvRect.height())); - - GLC(context(), context()->activeTexture(GraphicsContext3D::TEXTURE0)); - CCResourceProvider::ScopedReadLockGL quadResourceLock(m_resourceProvider, quad->resourceId()); - GLC(context(), context()->bindTexture(GraphicsContext3D::TEXTURE_2D, quadResourceLock.textureId())); - - // FIXME: setting the texture parameters every time is redundant. Move this code somewhere - // where it will only happen once per texture. - GLC(context(), context()->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR)); - GLC(context(), context()->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR)); - GLC(context(), context()->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE)); - GLC(context(), context()->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE)); - - if (!quad->premultipliedAlpha()) { - // As it turns out, the premultiplied alpha blending function (ONE, ONE_MINUS_SRC_ALPHA) - // will never cause the alpha channel to be set to anything less than 1.0 if it is - // initialized to that value! Therefore, premultipliedAlpha being false is the first - // situation we can generally see an alpha channel less than 1.0 coming out of the - // compositor. This is causing platform differences in some layout tests (see - // https://bugs.webkit.org/show_bug.cgi?id=82412), so in this situation, use a separate - // blend function for the alpha channel to avoid modifying it. Don't use colorMask for this - // as it has performance implications on some platforms. - GLC(context(), context()->blendFuncSeparate(GraphicsContext3D::SRC_ALPHA, GraphicsContext3D::ONE_MINUS_SRC_ALPHA, GraphicsContext3D::ZERO, GraphicsContext3D::ONE)); - } - - setShaderOpacity(quad->opacity(), binding.alphaLocation); - drawQuadGeometry(frame, quad->quadTransform(), quad->quadRect(), binding.matrixLocation); - - if (!quad->premultipliedAlpha()) - GLC(m_context, m_context->blendFunc(GraphicsContext3D::ONE, GraphicsContext3D::ONE_MINUS_SRC_ALPHA)); -} - -void CCRendererGL::drawIOSurfaceQuad(const DrawingFrame& frame, const CCIOSurfaceDrawQuad* quad) -{ - ASSERT(CCProxy::isImplThread()); - TexTransformTextureProgramBinding binding; - binding.set(textureIOSurfaceProgram()); - - GLC(context(), context()->useProgram(binding.programId)); - GLC(context(), context()->uniform1i(binding.samplerLocation, 0)); - if (quad->orientation() == CCIOSurfaceDrawQuad::Flipped) - GLC(context(), context()->uniform4f(binding.texTransformLocation, 0, quad->ioSurfaceSize().height(), quad->ioSurfaceSize().width(), quad->ioSurfaceSize().height() * -1.0)); - else - GLC(context(), context()->uniform4f(binding.texTransformLocation, 0, 0, quad->ioSurfaceSize().width(), quad->ioSurfaceSize().height())); - - GLC(context(), context()->activeTexture(GraphicsContext3D::TEXTURE0)); - GLC(context(), context()->bindTexture(Extensions3D::TEXTURE_RECTANGLE_ARB, quad->ioSurfaceTextureId())); - - setShaderOpacity(quad->opacity(), binding.alphaLocation); - drawQuadGeometry(frame, quad->quadTransform(), quad->quadRect(), binding.matrixLocation); - - GLC(context(), context()->bindTexture(Extensions3D::TEXTURE_RECTANGLE_ARB, 0)); -} - -void CCRendererGL::finishDrawingFrame(DrawingFrame& frame) -{ - m_currentFramebufferLock.clear(); - m_swapBufferRect.unite(enclosingIntRect(frame.rootDamageRect)); - - GLC(m_context, m_context->disable(GraphicsContext3D::SCISSOR_TEST)); - GLC(m_context, m_context->disable(GraphicsContext3D::BLEND)); -} - -bool CCRendererGL::flippedFramebuffer() const -{ - return true; -} - -void CCRendererGL::toGLMatrix(float* flattened, const WebTransformationMatrix& m) -{ - flattened[0] = m.m11(); - flattened[1] = m.m12(); - flattened[2] = m.m13(); - flattened[3] = m.m14(); - flattened[4] = m.m21(); - flattened[5] = m.m22(); - flattened[6] = m.m23(); - flattened[7] = m.m24(); - flattened[8] = m.m31(); - flattened[9] = m.m32(); - flattened[10] = m.m33(); - flattened[11] = m.m34(); - flattened[12] = m.m41(); - flattened[13] = m.m42(); - flattened[14] = m.m43(); - flattened[15] = m.m44(); -} - -void CCRendererGL::setShaderFloatQuad(const FloatQuad& quad, int quadLocation) -{ - if (quadLocation == -1) - return; - - float point[8]; - point[0] = quad.p1().x(); - point[1] = quad.p1().y(); - point[2] = quad.p2().x(); - point[3] = quad.p2().y(); - point[4] = quad.p3().x(); - point[5] = quad.p3().y(); - point[6] = quad.p4().x(); - point[7] = quad.p4().y(); - GLC(m_context, m_context->uniform2fv(quadLocation, 4, point)); -} - -void CCRendererGL::setShaderOpacity(float opacity, int alphaLocation) -{ - if (alphaLocation != -1) - GLC(m_context, m_context->uniform1f(alphaLocation, opacity)); -} - -void CCRendererGL::drawQuadGeometry(const DrawingFrame& frame, const WebKit::WebTransformationMatrix& drawTransform, const FloatRect& quadRect, int matrixLocation) -{ - WebTransformationMatrix quadRectMatrix; - quadRectTransform(&quadRectMatrix, drawTransform, quadRect); - static float glMatrix[16]; - toGLMatrix(&glMatrix[0], frame.projectionMatrix * quadRectMatrix); - GLC(m_context, m_context->uniformMatrix4fv(matrixLocation, 1, false, &glMatrix[0])); - - GLC(m_context, m_context->drawElements(GraphicsContext3D::TRIANGLES, 6, GraphicsContext3D::UNSIGNED_SHORT, 0)); -} - -void CCRendererGL::copyTextureToFramebuffer(const DrawingFrame& frame, int textureId, const IntRect& rect, const WebTransformationMatrix& drawMatrix) -{ - const RenderPassProgram* program = renderPassProgram(); - - GLC(context(), context()->activeTexture(GraphicsContext3D::TEXTURE0)); - GLC(context(), context()->bindTexture(GraphicsContext3D::TEXTURE_2D, textureId)); - GLC(context(), context()->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR)); - GLC(context(), context()->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR)); - GLC(context(), context()->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE)); - GLC(context(), context()->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE)); - - GLC(context(), context()->useProgram(program->program())); - GLC(context(), context()->uniform1i(program->fragmentShader().samplerLocation(), 0)); - setShaderOpacity(1, program->fragmentShader().alphaLocation()); - drawQuadGeometry(frame, drawMatrix, rect, program->vertexShader().matrixLocation()); -} - -void CCRendererGL::finish() -{ - TRACE_EVENT0("cc", "CCRendererGL::finish"); - m_context->finish(); -} - -bool CCRendererGL::swapBuffers() -{ - ASSERT(m_visible); - ASSERT(!m_isFramebufferDiscarded); - - TRACE_EVENT0("cc", "CCRendererGL::swapBuffers"); - // We're done! Time to swapbuffers! - - if (m_capabilities.usingPartialSwap) { - // If supported, we can save significant bandwidth by only swapping the damaged/scissored region (clamped to the viewport) - m_swapBufferRect.intersect(IntRect(IntPoint(), viewportSize())); - int flippedYPosOfRectBottom = viewportHeight() - m_swapBufferRect.y() - m_swapBufferRect.height(); - m_context->postSubBufferCHROMIUM(m_swapBufferRect.x(), flippedYPosOfRectBottom, m_swapBufferRect.width(), m_swapBufferRect.height()); - } else { - // Note that currently this has the same effect as swapBuffers; we should - // consider exposing a different entry point on WebGraphicsContext3D. - m_context->prepareTexture(); - } - - m_swapBufferRect = IntRect(); - - return true; -} - -void CCRendererGL::onSwapBuffersComplete() -{ - m_client->onSwapBuffersComplete(); -} - -void CCRendererGL::onMemoryAllocationChanged(WebGraphicsMemoryAllocation allocation) -{ - // FIXME: This is called on the main thread in single threaded mode, but we expect it on the impl thread. - if (!CCProxy::hasImplThread()) { - ASSERT(CCProxy::isMainThread()); - DebugScopedSetImplThread impl; - onMemoryAllocationChangedOnImplThread(allocation); - } else { - ASSERT(CCProxy::isImplThread()); - onMemoryAllocationChangedOnImplThread(allocation); - } -} - -void CCRendererGL::onMemoryAllocationChangedOnImplThread(WebKit::WebGraphicsMemoryAllocation allocation) -{ - if (m_visible && !allocation.gpuResourceSizeInBytes) - return; - - if (!allocation.suggestHaveBackbuffer && !m_visible) - discardFramebuffer(); - - if (!allocation.gpuResourceSizeInBytes) { - releaseRenderPassTextures(); - m_client->releaseContentsTextures(); - GLC(m_context, m_context->flush()); - } else - m_client->setMemoryAllocationLimitBytes(allocation.gpuResourceSizeInBytes); -} - -void CCRendererGL::discardFramebuffer() -{ - if (m_isFramebufferDiscarded) - return; - - if (!m_capabilities.usingDiscardFramebuffer) - return; - - // FIXME: Update attachments argument to appropriate values once they are no longer ignored. - m_context->discardFramebufferEXT(GraphicsContext3D::TEXTURE_2D, 0, 0); - m_isFramebufferDiscarded = true; - - // Damage tracker needs a full reset every time framebuffer is discarded. - m_client->setFullRootLayerDamage(); -} - -void CCRendererGL::ensureFramebuffer() -{ - if (!m_isFramebufferDiscarded) - return; - - if (!m_capabilities.usingDiscardFramebuffer) - return; - - m_context->ensureFramebufferCHROMIUM(); - m_isFramebufferDiscarded = false; -} - -void CCRendererGL::onContextLost() -{ - m_client->didLoseContext(); -} - - -void CCRendererGL::getFramebufferPixels(void *pixels, const IntRect& rect) -{ - ASSERT(rect.maxX() <= viewportWidth() && rect.maxY() <= viewportHeight()); - - if (!pixels) - return; - - makeContextCurrent(); - - bool doWorkaround = needsIOSurfaceReadbackWorkaround(); - - Platform3DObject temporaryTexture = 0; - Platform3DObject temporaryFBO = 0; - - if (doWorkaround) { - // On Mac OS X, calling glReadPixels against an FBO whose color attachment is an - // IOSurface-backed texture causes corruption of future glReadPixels calls, even those on - // different OpenGL contexts. It is believed that this is the root cause of top crasher - // http://crbug.com/99393. - - temporaryTexture = m_context->createTexture(); - GLC(m_context, m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, temporaryTexture)); - GLC(m_context, m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR)); - GLC(m_context, m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR)); - GLC(m_context, m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE)); - GLC(m_context, m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE)); - // Copy the contents of the current (IOSurface-backed) framebuffer into a temporary texture. - GLC(m_context, m_context->copyTexImage2D(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::RGBA, 0, 0, viewportSize().width(), viewportSize().height(), 0)); - temporaryFBO = m_context->createFramebuffer(); - // Attach this texture to an FBO, and perform the readback from that FBO. - GLC(m_context, m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, temporaryFBO)); - GLC(m_context, m_context->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE_2D, temporaryTexture, 0)); - - ASSERT(m_context->checkFramebufferStatus(GraphicsContext3D::FRAMEBUFFER) == GraphicsContext3D::FRAMEBUFFER_COMPLETE); - } - - OwnArrayPtr srcPixels = adoptArrayPtr(new uint8_t[rect.width() * rect.height() * 4]); - GLC(m_context, m_context->readPixels(rect.x(), viewportSize().height() - rect.maxY(), rect.width(), rect.height(), - GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, srcPixels.get())); - - uint8_t* destPixels = static_cast(pixels); - size_t rowBytes = rect.width() * 4; - int numRows = rect.height(); - size_t totalBytes = numRows * rowBytes; - for (size_t destY = 0; destY < totalBytes; destY += rowBytes) { - // Flip Y axis. - size_t srcY = totalBytes - destY - rowBytes; - // Swizzle BGRA -> RGBA. - for (size_t x = 0; x < rowBytes; x += 4) { - destPixels[destY + (x+0)] = srcPixels.get()[srcY + (x+2)]; - destPixels[destY + (x+1)] = srcPixels.get()[srcY + (x+1)]; - destPixels[destY + (x+2)] = srcPixels.get()[srcY + (x+0)]; - destPixels[destY + (x+3)] = srcPixels.get()[srcY + (x+3)]; - } - } - - if (doWorkaround) { - // Clean up. - GLC(m_context, m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, 0)); - GLC(m_context, m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, 0)); - GLC(m_context, m_context->deleteFramebuffer(temporaryFBO)); - GLC(m_context, m_context->deleteTexture(temporaryTexture)); - } - - if (!m_visible) { - TRACE_EVENT0("cc", "CCRendererGL::getFramebufferPixels dropping resources after readback"); - discardFramebuffer(); - releaseRenderPassTextures(); - m_client->releaseContentsTextures(); - GLC(m_context, m_context->flush()); - } -} - -bool CCRendererGL::getFramebufferTexture(CCScopedTexture* texture, const IntRect& deviceRect) -{ - ASSERT(!texture->id() || (texture->size() == deviceRect.size() && texture->format() == GraphicsContext3D::RGB)); - - if (!texture->id() && !texture->allocate(CCRenderer::ImplPool, deviceRect.size(), GraphicsContext3D::RGB, CCResourceProvider::TextureUsageAny)) - return false; - - CCResourceProvider::ScopedWriteLockGL lock(m_resourceProvider, texture->id()); - GLC(m_context, m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, lock.textureId())); - GLC(m_context, m_context->copyTexImage2D(GraphicsContext3D::TEXTURE_2D, 0, texture->format(), - deviceRect.x(), deviceRect.y(), deviceRect.width(), deviceRect.height(), 0)); - return true; -} - -bool CCRendererGL::useScopedTexture(DrawingFrame& frame, const CCScopedTexture* texture, const IntRect& viewportRect) -{ - ASSERT(texture->id()); - frame.currentRenderPass = 0; - frame.currentTexture = texture; - - return bindFramebufferToTexture(frame, texture, viewportRect); -} - -void CCRendererGL::bindFramebufferToOutputSurface(DrawingFrame& frame) -{ - m_currentFramebufferLock.clear(); - GLC(m_context, m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, 0)); -} - -bool CCRendererGL::bindFramebufferToTexture(DrawingFrame& frame, const CCScopedTexture* texture, const IntRect& framebufferRect) -{ - ASSERT(texture->id()); - - GLC(m_context, m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_offscreenFramebufferId)); - m_currentFramebufferLock = adoptPtr(new CCResourceProvider::ScopedWriteLockGL(m_resourceProvider, texture->id())); - unsigned textureId = m_currentFramebufferLock->textureId(); - GLC(m_context, m_context->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE_2D, textureId, 0)); - -#if !defined ( NDEBUG ) - if (m_context->checkFramebufferStatus(GraphicsContext3D::FRAMEBUFFER) != GraphicsContext3D::FRAMEBUFFER_COMPLETE) { - ASSERT_NOT_REACHED(); - return false; - } -#endif - - initializeMatrices(frame, framebufferRect, false); - setDrawViewportSize(framebufferRect.size()); - - return true; -} - -void CCRendererGL::enableScissorTestRect(const IntRect& scissorRect) -{ - GLC(m_context, m_context->enable(GraphicsContext3D::SCISSOR_TEST)); - GLC(m_context, m_context->scissor(scissorRect.x(), scissorRect.y(), scissorRect.width(), scissorRect.height())); -} - -void CCRendererGL::disableScissorTest() -{ - GLC(m_context, m_context->disable(GraphicsContext3D::SCISSOR_TEST)); -} - -void CCRendererGL::setDrawViewportSize(const IntSize& viewportSize) -{ - GLC(m_context, m_context->viewport(0, 0, viewportSize.width(), viewportSize.height())); -} - -bool CCRendererGL::makeContextCurrent() -{ - return m_context->makeContextCurrent(); -} - -bool CCRendererGL::initializeSharedObjects() -{ - TRACE_EVENT0("cc", "CCRendererGL::initializeSharedObjects"); - makeContextCurrent(); - - // Create an FBO for doing offscreen rendering. - GLC(m_context, m_offscreenFramebufferId = m_context->createFramebuffer()); - - // We will always need these programs to render, so create the programs eagerly so that the shader compilation can - // start while we do other work. Other programs are created lazily on first access. - m_sharedGeometry = adoptPtr(new GeometryBinding(m_context, quadVertexRect())); - m_renderPassProgram = adoptPtr(new RenderPassProgram(m_context)); - m_tileProgram = adoptPtr(new TileProgram(m_context)); - m_tileProgramOpaque = adoptPtr(new TileProgramOpaque(m_context)); - - GLC(m_context, m_context->flush()); - - return true; -} - -const CCRendererGL::TileCheckerboardProgram* CCRendererGL::tileCheckerboardProgram() -{ - if (!m_tileCheckerboardProgram) - m_tileCheckerboardProgram = adoptPtr(new TileCheckerboardProgram(m_context)); - if (!m_tileCheckerboardProgram->initialized()) { - TRACE_EVENT0("cc", "CCRendererGL::checkerboardProgram::initalize"); - m_tileCheckerboardProgram->initialize(m_context, m_isUsingBindUniform); - } - return m_tileCheckerboardProgram.get(); -} - -const CCRendererGL::SolidColorProgram* CCRendererGL::solidColorProgram() -{ - if (!m_solidColorProgram) - m_solidColorProgram = adoptPtr(new SolidColorProgram(m_context)); - if (!m_solidColorProgram->initialized()) { - TRACE_EVENT0("cc", "CCRendererGL::solidColorProgram::initialize"); - m_solidColorProgram->initialize(m_context, m_isUsingBindUniform); - } - return m_solidColorProgram.get(); -} - -const CCRendererGL::RenderPassProgram* CCRendererGL::renderPassProgram() -{ - ASSERT(m_renderPassProgram); - if (!m_renderPassProgram->initialized()) { - TRACE_EVENT0("cc", "CCRendererGL::renderPassProgram::initialize"); - m_renderPassProgram->initialize(m_context, m_isUsingBindUniform); - } - return m_renderPassProgram.get(); -} - -const CCRendererGL::RenderPassProgramAA* CCRendererGL::renderPassProgramAA() -{ - if (!m_renderPassProgramAA) - m_renderPassProgramAA = adoptPtr(new RenderPassProgramAA(m_context)); - if (!m_renderPassProgramAA->initialized()) { - TRACE_EVENT0("cc", "CCRendererGL::renderPassProgramAA::initialize"); - m_renderPassProgramAA->initialize(m_context, m_isUsingBindUniform); - } - return m_renderPassProgramAA.get(); -} - -const CCRendererGL::RenderPassMaskProgram* CCRendererGL::renderPassMaskProgram() -{ - if (!m_renderPassMaskProgram) - m_renderPassMaskProgram = adoptPtr(new RenderPassMaskProgram(m_context)); - if (!m_renderPassMaskProgram->initialized()) { - TRACE_EVENT0("cc", "CCRendererGL::renderPassMaskProgram::initialize"); - m_renderPassMaskProgram->initialize(m_context, m_isUsingBindUniform); - } - return m_renderPassMaskProgram.get(); -} - -const CCRendererGL::RenderPassMaskProgramAA* CCRendererGL::renderPassMaskProgramAA() -{ - if (!m_renderPassMaskProgramAA) - m_renderPassMaskProgramAA = adoptPtr(new RenderPassMaskProgramAA(m_context)); - if (!m_renderPassMaskProgramAA->initialized()) { - TRACE_EVENT0("cc", "CCRendererGL::renderPassMaskProgramAA::initialize"); - m_renderPassMaskProgramAA->initialize(m_context, m_isUsingBindUniform); - } - return m_renderPassMaskProgramAA.get(); -} - -const CCRendererGL::TileProgram* CCRendererGL::tileProgram() -{ - ASSERT(m_tileProgram); - if (!m_tileProgram->initialized()) { - TRACE_EVENT0("cc", "CCRendererGL::tileProgram::initialize"); - m_tileProgram->initialize(m_context, m_isUsingBindUniform); - } - return m_tileProgram.get(); -} - -const CCRendererGL::TileProgramOpaque* CCRendererGL::tileProgramOpaque() -{ - ASSERT(m_tileProgramOpaque); - if (!m_tileProgramOpaque->initialized()) { - TRACE_EVENT0("cc", "CCRendererGL::tileProgramOpaque::initialize"); - m_tileProgramOpaque->initialize(m_context, m_isUsingBindUniform); - } - return m_tileProgramOpaque.get(); -} - -const CCRendererGL::TileProgramAA* CCRendererGL::tileProgramAA() -{ - if (!m_tileProgramAA) - m_tileProgramAA = adoptPtr(new TileProgramAA(m_context)); - if (!m_tileProgramAA->initialized()) { - TRACE_EVENT0("cc", "CCRendererGL::tileProgramAA::initialize"); - m_tileProgramAA->initialize(m_context, m_isUsingBindUniform); - } - return m_tileProgramAA.get(); -} - -const CCRendererGL::TileProgramSwizzle* CCRendererGL::tileProgramSwizzle() -{ - if (!m_tileProgramSwizzle) - m_tileProgramSwizzle = adoptPtr(new TileProgramSwizzle(m_context)); - if (!m_tileProgramSwizzle->initialized()) { - TRACE_EVENT0("cc", "CCRendererGL::tileProgramSwizzle::initialize"); - m_tileProgramSwizzle->initialize(m_context, m_isUsingBindUniform); - } - return m_tileProgramSwizzle.get(); -} - -const CCRendererGL::TileProgramSwizzleOpaque* CCRendererGL::tileProgramSwizzleOpaque() -{ - if (!m_tileProgramSwizzleOpaque) - m_tileProgramSwizzleOpaque = adoptPtr(new TileProgramSwizzleOpaque(m_context)); - if (!m_tileProgramSwizzleOpaque->initialized()) { - TRACE_EVENT0("cc", "CCRendererGL::tileProgramSwizzleOpaque::initialize"); - m_tileProgramSwizzleOpaque->initialize(m_context, m_isUsingBindUniform); - } - return m_tileProgramSwizzleOpaque.get(); -} - -const CCRendererGL::TileProgramSwizzleAA* CCRendererGL::tileProgramSwizzleAA() -{ - if (!m_tileProgramSwizzleAA) - m_tileProgramSwizzleAA = adoptPtr(new TileProgramSwizzleAA(m_context)); - if (!m_tileProgramSwizzleAA->initialized()) { - TRACE_EVENT0("cc", "CCRendererGL::tileProgramSwizzleAA::initialize"); - m_tileProgramSwizzleAA->initialize(m_context, m_isUsingBindUniform); - } - return m_tileProgramSwizzleAA.get(); -} - -const CCRendererGL::TextureProgram* CCRendererGL::textureProgram() -{ - if (!m_textureProgram) - m_textureProgram = adoptPtr(new TextureProgram(m_context)); - if (!m_textureProgram->initialized()) { - TRACE_EVENT0("cc", "CCRendererGL::textureProgram::initialize"); - m_textureProgram->initialize(m_context, m_isUsingBindUniform); - } - return m_textureProgram.get(); -} - -const CCRendererGL::TextureProgramFlip* CCRendererGL::textureProgramFlip() -{ - if (!m_textureProgramFlip) - m_textureProgramFlip = adoptPtr(new TextureProgramFlip(m_context)); - if (!m_textureProgramFlip->initialized()) { - TRACE_EVENT0("cc", "CCRendererGL::textureProgramFlip::initialize"); - m_textureProgramFlip->initialize(m_context, m_isUsingBindUniform); - } - return m_textureProgramFlip.get(); -} - -const CCRendererGL::TextureIOSurfaceProgram* CCRendererGL::textureIOSurfaceProgram() -{ - if (!m_textureIOSurfaceProgram) - m_textureIOSurfaceProgram = adoptPtr(new TextureIOSurfaceProgram(m_context)); - if (!m_textureIOSurfaceProgram->initialized()) { - TRACE_EVENT0("cc", "CCRendererGL::textureIOSurfaceProgram::initialize"); - m_textureIOSurfaceProgram->initialize(m_context, m_isUsingBindUniform); - } - return m_textureIOSurfaceProgram.get(); -} - -const CCRendererGL::VideoYUVProgram* CCRendererGL::videoYUVProgram() -{ - if (!m_videoYUVProgram) - m_videoYUVProgram = adoptPtr(new VideoYUVProgram(m_context)); - if (!m_videoYUVProgram->initialized()) { - TRACE_EVENT0("cc", "CCRendererGL::videoYUVProgram::initialize"); - m_videoYUVProgram->initialize(m_context, m_isUsingBindUniform); - } - return m_videoYUVProgram.get(); -} - -const CCRendererGL::VideoStreamTextureProgram* CCRendererGL::videoStreamTextureProgram() -{ - if (!m_videoStreamTextureProgram) - m_videoStreamTextureProgram = adoptPtr(new VideoStreamTextureProgram(m_context)); - if (!m_videoStreamTextureProgram->initialized()) { - TRACE_EVENT0("cc", "CCRendererGL::streamTextureProgram::initialize"); - m_videoStreamTextureProgram->initialize(m_context, m_isUsingBindUniform); - } - return m_videoStreamTextureProgram.get(); -} - -void CCRendererGL::cleanupSharedObjects() -{ - makeContextCurrent(); - - m_sharedGeometry.clear(); - - if (m_tileProgram) - m_tileProgram->cleanup(m_context); - if (m_tileProgramOpaque) - m_tileProgramOpaque->cleanup(m_context); - if (m_tileProgramSwizzle) - m_tileProgramSwizzle->cleanup(m_context); - if (m_tileProgramSwizzleOpaque) - m_tileProgramSwizzleOpaque->cleanup(m_context); - if (m_tileProgramAA) - m_tileProgramAA->cleanup(m_context); - if (m_tileProgramSwizzleAA) - m_tileProgramSwizzleAA->cleanup(m_context); - if (m_tileCheckerboardProgram) - m_tileCheckerboardProgram->cleanup(m_context); - - if (m_renderPassMaskProgram) - m_renderPassMaskProgram->cleanup(m_context); - if (m_renderPassProgram) - m_renderPassProgram->cleanup(m_context); - if (m_renderPassMaskProgramAA) - m_renderPassMaskProgramAA->cleanup(m_context); - if (m_renderPassProgramAA) - m_renderPassProgramAA->cleanup(m_context); - - if (m_textureProgram) - m_textureProgram->cleanup(m_context); - if (m_textureProgramFlip) - m_textureProgramFlip->cleanup(m_context); - if (m_textureIOSurfaceProgram) - m_textureIOSurfaceProgram->cleanup(m_context); - - if (m_videoYUVProgram) - m_videoYUVProgram->cleanup(m_context); - if (m_videoStreamTextureProgram) - m_videoStreamTextureProgram->cleanup(m_context); - - if (m_solidColorProgram) - m_solidColorProgram->cleanup(m_context); - - if (m_offscreenFramebufferId) - GLC(m_context, m_context->deleteFramebuffer(m_offscreenFramebufferId)); - - releaseRenderPassTextures(); -} - -bool CCRendererGL::isContextLost() -{ - return (m_context->getGraphicsResetStatusARB() != GraphicsContext3D::NO_ERROR); -} - -} // namespace cc - -#endif // USE(ACCELERATED_COMPOSITING) diff --git a/cc/CCRendererGL.h b/cc/CCRendererGL.h index a5f2c4f..a4458d6 100644 --- a/cc/CCRendererGL.h +++ b/cc/CCRendererGL.h @@ -1,240 +1,6 @@ -// Copyright 2010 The Chromium Authors. All rights reserved. +// Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. - -#ifndef CCRendererGL_h -#define CCRendererGL_h - -#if USE(ACCELERATED_COMPOSITING) - -#include "base/basictypes.h" -#include "CCCheckerboardDrawQuad.h" -#include "CCDebugBorderDrawQuad.h" -#include "CCDirectRenderer.h" -#include "CCIOSurfaceDrawQuad.h" -#include "CCRenderPassDrawQuad.h" -#include "CCRenderer.h" -#include "CCSolidColorDrawQuad.h" -#include "CCStreamVideoDrawQuad.h" -#include "CCTextureDrawQuad.h" -#include "CCTileDrawQuad.h" -#include "CCYUVVideoDrawQuad.h" -#include "Extensions3DChromium.h" -#include - -namespace WebKit { -class WebGraphicsContext3D; -} - -namespace cc { - -class CCScopedTexture; -class GeometryBinding; -class ScopedEnsureFramebufferAllocation; - -// Class that handles drawing of composited render layers using GL. -class CCRendererGL : public CCDirectRenderer, - public WebKit::WebGraphicsContext3D::WebGraphicsSwapBuffersCompleteCallbackCHROMIUM, - public WebKit::WebGraphicsContext3D::WebGraphicsMemoryAllocationChangedCallbackCHROMIUM , - public WebKit::WebGraphicsContext3D::WebGraphicsContextLostCallback { -public: - static PassOwnPtr create(CCRendererClient*, CCResourceProvider*); - - virtual ~CCRendererGL(); - - virtual const RendererCapabilities& capabilities() const OVERRIDE; - - WebKit::WebGraphicsContext3D* context(); - - virtual void viewportChanged() OVERRIDE; - - const FloatQuad& sharedGeometryQuad() const { return m_sharedGeometryQuad; } - - // waits for rendering to finish - virtual void finish() OVERRIDE; - - virtual void doNoOp() OVERRIDE; - // puts backbuffer onscreen - virtual bool swapBuffers() OVERRIDE; - - static void debugGLCall(WebKit::WebGraphicsContext3D*, const char* command, const char* file, int line); - - const GeometryBinding* sharedGeometry() const { return m_sharedGeometry.get(); } - - virtual void getFramebufferPixels(void *pixels, const IntRect&) OVERRIDE; - bool getFramebufferTexture(CCScopedTexture*, const IntRect& deviceRect); - - virtual bool isContextLost() OVERRIDE; - - virtual void setVisible(bool) OVERRIDE; - -protected: - CCRendererGL(CCRendererClient*, CCResourceProvider*); - - bool isFramebufferDiscarded() const { return m_isFramebufferDiscarded; } - bool initialize(); - - void releaseRenderPassTextures(); - - virtual void bindFramebufferToOutputSurface(DrawingFrame&) OVERRIDE; - virtual bool bindFramebufferToTexture(DrawingFrame&, const CCScopedTexture*, const IntRect& framebufferRect) OVERRIDE; - virtual void setDrawViewportSize(const IntSize&) OVERRIDE; - virtual void enableScissorTestRect(const IntRect& scissorRect) OVERRIDE; - virtual void disableScissorTest() OVERRIDE; - virtual void clearFramebuffer(DrawingFrame&) OVERRIDE; - virtual void drawQuad(DrawingFrame&, const CCDrawQuad*) OVERRIDE; - virtual void beginDrawingFrame(DrawingFrame&) OVERRIDE; - virtual void finishDrawingFrame(DrawingFrame&) OVERRIDE; - virtual bool flippedFramebuffer() const OVERRIDE; - -private: - static void toGLMatrix(float*, const WebKit::WebTransformationMatrix&); - - void drawCheckerboardQuad(const DrawingFrame&, const CCCheckerboardDrawQuad*); - void drawDebugBorderQuad(const DrawingFrame&, const CCDebugBorderDrawQuad*); - PassOwnPtr drawBackgroundFilters(DrawingFrame&, const CCRenderPassDrawQuad*, const WebKit::WebFilterOperations&, const WebKit::WebTransformationMatrix& deviceTransform); - void drawRenderPassQuad(DrawingFrame&, const CCRenderPassDrawQuad*); - void drawSolidColorQuad(const DrawingFrame&, const CCSolidColorDrawQuad*); - void drawStreamVideoQuad(const DrawingFrame&, const CCStreamVideoDrawQuad*); - void drawTextureQuad(const DrawingFrame&, const CCTextureDrawQuad*); - void drawIOSurfaceQuad(const DrawingFrame&, const CCIOSurfaceDrawQuad*); - void drawTileQuad(const DrawingFrame&, const CCTileDrawQuad*); - void drawYUVVideoQuad(const DrawingFrame&, const CCYUVVideoDrawQuad*); - - void setShaderOpacity(float opacity, int alphaLocation); - void setShaderFloatQuad(const FloatQuad&, int quadLocation); - void drawQuadGeometry(const DrawingFrame&, const WebKit::WebTransformationMatrix& drawTransform, const FloatRect& quadRect, int matrixLocation); - - void copyTextureToFramebuffer(const DrawingFrame&, int textureId, const IntRect&, const WebKit::WebTransformationMatrix& drawMatrix); - - bool useScopedTexture(DrawingFrame&, const CCScopedTexture*, const IntRect& viewportRect); - - bool makeContextCurrent(); - - bool initializeSharedObjects(); - void cleanupSharedObjects(); - - // WebKit::WebGraphicsContext3D::WebGraphicsSwapBuffersCompleteCallbackCHROMIUM implementation. - virtual void onSwapBuffersComplete() OVERRIDE; - - // WebKit::WebGraphicsContext3D::WebGraphicsMemoryAllocationChangedCallbackCHROMIUM implementation. - virtual void onMemoryAllocationChanged(WebKit::WebGraphicsMemoryAllocation) OVERRIDE; - void onMemoryAllocationChangedOnImplThread(WebKit::WebGraphicsMemoryAllocation); - void discardFramebuffer(); - void ensureFramebuffer(); - - // WebGraphicsContext3D::WebGraphicsContextLostCallback implementation. - virtual void onContextLost() OVERRIDE; - - RendererCapabilities m_capabilities; - - unsigned m_offscreenFramebufferId; - - OwnPtr m_sharedGeometry; - FloatQuad m_sharedGeometryQuad; - - // This block of bindings defines all of the programs used by the compositor itself. - - // Tiled layer shaders. - typedef ProgramBinding TileProgram; - typedef ProgramBinding TileProgramAA; - typedef ProgramBinding TileProgramSwizzleAA; - typedef ProgramBinding TileProgramOpaque; - typedef ProgramBinding TileProgramSwizzle; - typedef ProgramBinding TileProgramSwizzleOpaque; - typedef ProgramBinding TileCheckerboardProgram; - - // Render surface shaders. - typedef ProgramBinding RenderPassProgram; - typedef ProgramBinding RenderPassMaskProgram; - typedef ProgramBinding RenderPassProgramAA; - typedef ProgramBinding RenderPassMaskProgramAA; - - // Texture shaders. - typedef ProgramBinding TextureProgram; - typedef ProgramBinding TextureProgramFlip; - typedef ProgramBinding TextureIOSurfaceProgram; - - // Video shaders. - typedef ProgramBinding VideoStreamTextureProgram; - typedef ProgramBinding VideoYUVProgram; - - // Special purpose / effects shaders. - typedef ProgramBinding SolidColorProgram; - - const TileProgram* tileProgram(); - const TileProgramOpaque* tileProgramOpaque(); - const TileProgramAA* tileProgramAA(); - const TileProgramSwizzle* tileProgramSwizzle(); - const TileProgramSwizzleOpaque* tileProgramSwizzleOpaque(); - const TileProgramSwizzleAA* tileProgramSwizzleAA(); - const TileCheckerboardProgram* tileCheckerboardProgram(); - - const RenderPassProgram* renderPassProgram(); - const RenderPassProgramAA* renderPassProgramAA(); - const RenderPassMaskProgram* renderPassMaskProgram(); - const RenderPassMaskProgramAA* renderPassMaskProgramAA(); - - const TextureProgram* textureProgram(); - const TextureProgramFlip* textureProgramFlip(); - const TextureIOSurfaceProgram* textureIOSurfaceProgram(); - - const VideoYUVProgram* videoYUVProgram(); - const VideoStreamTextureProgram* videoStreamTextureProgram(); - - const SolidColorProgram* solidColorProgram(); - - OwnPtr m_tileProgram; - OwnPtr m_tileProgramOpaque; - OwnPtr m_tileProgramAA; - OwnPtr m_tileProgramSwizzle; - OwnPtr m_tileProgramSwizzleOpaque; - OwnPtr m_tileProgramSwizzleAA; - OwnPtr m_tileCheckerboardProgram; - - OwnPtr m_renderPassProgram; - OwnPtr m_renderPassProgramAA; - OwnPtr m_renderPassMaskProgram; - OwnPtr m_renderPassMaskProgramAA; - - OwnPtr m_textureProgram; - OwnPtr m_textureProgramFlip; - OwnPtr m_textureIOSurfaceProgram; - - OwnPtr m_videoYUVProgram; - OwnPtr m_videoStreamTextureProgram; - - OwnPtr m_solidColorProgram; - - WebKit::WebGraphicsContext3D* m_context; - - IntRect m_swapBufferRect; - bool m_isViewportChanged; - bool m_isFramebufferDiscarded; - bool m_isUsingBindUniform; - bool m_visible; - - OwnPtr m_currentFramebufferLock; - - DISALLOW_COPY_AND_ASSIGN(CCRendererGL); -}; - - -// Setting DEBUG_GL_CALLS to 1 will call glGetError() after almost every GL -// call made by the compositor. Useful for debugging rendering issues but -// will significantly degrade performance. -#define DEBUG_GL_CALLS 0 - -#if DEBUG_GL_CALLS && !defined ( NDEBUG ) -#define GLC(context, x) (x, CCRendererGL::debugGLCall(&*context, #x, __FILE__, __LINE__)) -#else -#define GLC(context, x) (x) -#endif - - -} - -#endif // USE(ACCELERATED_COMPOSITING) - -#endif +// Temporary forwarding header +#include "cc/gl_renderer.h" diff --git a/cc/CCRendererSoftware.cpp b/cc/CCRendererSoftware.cpp deleted file mode 100644 index e833780..0000000 --- a/cc/CCRendererSoftware.cpp +++ /dev/null @@ -1,279 +0,0 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "config.h" - -#include "CCRendererSoftware.h" - -#include "CCDebugBorderDrawQuad.h" -#include "CCSolidColorDrawQuad.h" -#include "CCTextureDrawQuad.h" -#include "CCTileDrawQuad.h" -#include "SkCanvas.h" -#include "SkColor.h" -#include "SkMatrix.h" -#include "SkPixelRef.h" -#include -#include -#include -#include - -using WebKit::WebCompositorSoftwareOutputDevice; -using WebKit::WebImage; -using WebKit::WebSize; -using WebKit::WebTransformationMatrix; - -namespace cc { - -namespace { - -SkRect toSkRect(const FloatRect& rect) -{ - return SkRect::MakeXYWH(rect.x(), rect.y(), rect.width(), rect.height()); -} - -SkIRect toSkIRect(const IntRect& rect) -{ - return SkIRect::MakeXYWH(rect.x(), rect.y(), rect.width(), rect.height()); -} - -void toSkMatrix(SkMatrix* flattened, const WebTransformationMatrix& m) -{ - // Convert from 4x4 to 3x3 by dropping the third row and column. - flattened->set(0, m.m11()); - flattened->set(1, m.m21()); - flattened->set(2, m.m41()); - flattened->set(3, m.m12()); - flattened->set(4, m.m22()); - flattened->set(5, m.m42()); - flattened->set(6, m.m14()); - flattened->set(7, m.m24()); - flattened->set(8, m.m44()); -} - -} // anonymous namespace - -PassOwnPtr CCRendererSoftware::create(CCRendererClient* client, CCResourceProvider* resourceProvider, WebCompositorSoftwareOutputDevice* outputDevice) -{ - return adoptPtr(new CCRendererSoftware(client, resourceProvider, outputDevice)); -} - -CCRendererSoftware::CCRendererSoftware(CCRendererClient* client, CCResourceProvider* resourceProvider, WebCompositorSoftwareOutputDevice* outputDevice) - : CCDirectRenderer(client, resourceProvider) - , m_visible(true) - , m_outputDevice(outputDevice) - , m_skCurrentCanvas(0) -{ - m_resourceProvider->setDefaultResourceType(CCResourceProvider::Bitmap); - - m_capabilities.maxTextureSize = INT_MAX; - m_capabilities.bestTextureFormat = GraphicsContext3D::RGBA; - m_capabilities.contextHasCachedFrontBuffer = true; - m_capabilities.usingSetVisibility = true; - - viewportChanged(); -} - -CCRendererSoftware::~CCRendererSoftware() -{ -} - -const RendererCapabilities& CCRendererSoftware::capabilities() const -{ - return m_capabilities; -} - -void CCRendererSoftware::viewportChanged() -{ - m_outputDevice->didChangeViewportSize(WebSize(viewportSize().width(), viewportSize().height())); -} - -void CCRendererSoftware::beginDrawingFrame(DrawingFrame& frame) -{ - m_skRootCanvas = adoptPtr(new SkCanvas(m_outputDevice->lock(true)->getSkBitmap())); -} - -void CCRendererSoftware::finishDrawingFrame(DrawingFrame& frame) -{ - m_currentFramebufferLock.clear(); - m_skCurrentCanvas = 0; - m_skRootCanvas.clear(); - m_outputDevice->unlock(); -} - -bool CCRendererSoftware::flippedFramebuffer() const -{ - return false; -} - -void CCRendererSoftware::finish() -{ -} - -void CCRendererSoftware::bindFramebufferToOutputSurface(DrawingFrame& frame) -{ - m_currentFramebufferLock.clear(); - m_skCurrentCanvas = m_skRootCanvas.get(); -} - -bool CCRendererSoftware::bindFramebufferToTexture(DrawingFrame& frame, const CCScopedTexture* texture, const IntRect& framebufferRect) -{ - m_currentFramebufferLock = adoptPtr(new CCResourceProvider::ScopedWriteLockSoftware(m_resourceProvider, texture->id())); - m_skCurrentCanvas = m_currentFramebufferLock->skCanvas(); - initializeMatrices(frame, framebufferRect, false); - setDrawViewportSize(framebufferRect.size()); - - return true; -} - -void CCRendererSoftware::enableScissorTestRect(const IntRect& scissorRect) -{ - m_skCurrentCanvas->clipRect(toSkRect(scissorRect), SkRegion::kReplace_Op); -} - -void CCRendererSoftware::disableScissorTest() -{ - IntRect canvasRect(IntPoint(), viewportSize()); - m_skCurrentCanvas->clipRect(toSkRect(canvasRect), SkRegion::kReplace_Op); -} - -void CCRendererSoftware::clearFramebuffer(DrawingFrame& frame) -{ - m_skCurrentCanvas->clear(SK_ColorGREEN); -} - -void CCRendererSoftware::setDrawViewportSize(const IntSize& viewportSize) -{ -} - -bool CCRendererSoftware::isSoftwareResource(CCResourceProvider::ResourceId id) const -{ - switch (m_resourceProvider->resourceType(id)) { - case CCResourceProvider::GLTexture: - return false; - case CCResourceProvider::Bitmap: - return true; - } - - CRASH(); - return false; -} - -void CCRendererSoftware::drawQuad(DrawingFrame& frame, const CCDrawQuad* quad) -{ - WebTransformationMatrix quadRectMatrix; - quadRectTransform(&quadRectMatrix, quad->quadTransform(), quad->quadRect()); - WebTransformationMatrix windowMatrix = frame.windowMatrix * frame.projectionMatrix * quadRectMatrix; - SkMatrix skWindowMatrix; - toSkMatrix(&skWindowMatrix, windowMatrix); - m_skCurrentCanvas->setMatrix(skWindowMatrix); - - m_skCurrentPaint.reset(); - if (quad->needsBlending()) - m_skCurrentPaint.setAlpha(quad->opacity() * 255); - else - m_skCurrentPaint.setXfermodeMode(SkXfermode::kSrc_Mode); - - switch (quad->material()) { - case CCDrawQuad::DebugBorder: - drawDebugBorderQuad(frame, CCDebugBorderDrawQuad::materialCast(quad)); - break; - case CCDrawQuad::SolidColor: - drawSolidColorQuad(frame, CCSolidColorDrawQuad::materialCast(quad)); - break; - case CCDrawQuad::TextureContent: - drawTextureQuad(frame, CCTextureDrawQuad::materialCast(quad)); - break; - case CCDrawQuad::TiledContent: - drawTileQuad(frame, CCTileDrawQuad::materialCast(quad)); - break; - default: - drawUnsupportedQuad(frame, quad); - break; - } - - m_skCurrentCanvas->resetMatrix(); -} - -void CCRendererSoftware::drawDebugBorderQuad(const DrawingFrame& frame, const CCDebugBorderDrawQuad* quad) -{ - // We need to apply the matrix manually to have pixel-sized stroke width. - SkPoint vertices[4]; - toSkRect(quadVertexRect()).toQuad(vertices); - SkPoint transformedVertices[4]; - m_skCurrentCanvas->getTotalMatrix().mapPoints(transformedVertices, vertices, 4); - m_skCurrentCanvas->resetMatrix(); - - m_skCurrentPaint.setColor(quad->color()); - m_skCurrentPaint.setAlpha(quad->opacity() * SkColorGetA(quad->color())); - m_skCurrentPaint.setStyle(SkPaint::kStroke_Style); - m_skCurrentPaint.setStrokeWidth(quad->width()); - m_skCurrentCanvas->drawPoints(SkCanvas::kPolygon_PointMode, 4, transformedVertices, m_skCurrentPaint); -} - -void CCRendererSoftware::drawSolidColorQuad(const DrawingFrame& frame, const CCSolidColorDrawQuad* quad) -{ - m_skCurrentPaint.setColor(quad->color()); - m_skCurrentPaint.setAlpha(quad->opacity() * SkColorGetA(quad->color())); - m_skCurrentCanvas->drawRect(toSkRect(quadVertexRect()), m_skCurrentPaint); -} - -void CCRendererSoftware::drawTextureQuad(const DrawingFrame& frame, const CCTextureDrawQuad* quad) -{ - if (!isSoftwareResource(quad->resourceId())) { - drawUnsupportedQuad(frame, quad); - return; - } - - // FIXME: Add support for non-premultiplied alpha. - CCResourceProvider::ScopedReadLockSoftware quadResourceLock(m_resourceProvider, quad->resourceId()); - FloatRect uvRect = quad->uvRect(); - uvRect.scale(quad->quadRect().width(), quad->quadRect().height()); - SkIRect skUvRect = toSkIRect(enclosingIntRect(uvRect)); - if (quad->flipped()) - m_skCurrentCanvas->scale(1, -1); - m_skCurrentCanvas->drawBitmapRect(*quadResourceLock.skBitmap(), &skUvRect, toSkRect(quadVertexRect()), &m_skCurrentPaint); -} - -void CCRendererSoftware::drawTileQuad(const DrawingFrame& frame, const CCTileDrawQuad* quad) -{ - ASSERT(isSoftwareResource(quad->resourceId())); - CCResourceProvider::ScopedReadLockSoftware quadResourceLock(m_resourceProvider, quad->resourceId()); - - SkIRect uvRect = toSkIRect(IntRect(quad->textureOffset(), quad->quadRect().size())); - m_skCurrentCanvas->drawBitmapRect(*quadResourceLock.skBitmap(), &uvRect, toSkRect(quadVertexRect()), &m_skCurrentPaint); -} - -void CCRendererSoftware::drawUnsupportedQuad(const DrawingFrame& frame, const CCDrawQuad* quad) -{ - m_skCurrentPaint.setColor(SK_ColorMAGENTA); - m_skCurrentPaint.setAlpha(quad->opacity() * 255); - m_skCurrentCanvas->drawRect(toSkRect(quadVertexRect()), m_skCurrentPaint); -} - -bool CCRendererSoftware::swapBuffers() -{ - if (CCProxy::hasImplThread()) - m_client->onSwapBuffersComplete(); - return true; -} - -void CCRendererSoftware::getFramebufferPixels(void *pixels, const IntRect& rect) -{ - SkBitmap fullBitmap = m_outputDevice->lock(false)->getSkBitmap(); - SkBitmap subsetBitmap; - SkIRect invertRect = SkIRect::MakeXYWH(rect.x(), viewportSize().height() - rect.maxY(), rect.width(), rect.height()); - fullBitmap.extractSubset(&subsetBitmap, invertRect); - subsetBitmap.copyPixelsTo(pixels, rect.width() * rect.height() * 4, rect.width() * 4); - m_outputDevice->unlock(); -} - -void CCRendererSoftware::setVisible(bool visible) -{ - if (m_visible == visible) - return; - m_visible = visible; -} - -} diff --git a/cc/CCRendererSoftware.h b/cc/CCRendererSoftware.h index 2ad688f..827aa21 100644 --- a/cc/CCRendererSoftware.h +++ b/cc/CCRendererSoftware.h @@ -2,75 +2,5 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CCRendererSoftware_h -#define CCRendererSoftware_h - -#include "base/basictypes.h" -#include "CCDirectRenderer.h" -#include "CCLayerTreeHost.h" -#include - -namespace cc { - -class CCDebugBorderDrawQuad; -class CCRendererClient; -class CCResourceProvider; -class CCSolidColorDrawQuad; -class CCTextureDrawQuad; -class CCTileDrawQuad; - -class CCRendererSoftware : public CCDirectRenderer { -public: - static PassOwnPtr create(CCRendererClient*, CCResourceProvider*, WebKit::WebCompositorSoftwareOutputDevice*); - virtual ~CCRendererSoftware(); - - virtual const RendererCapabilities& capabilities() const OVERRIDE; - - virtual void viewportChanged() OVERRIDE; - - virtual void finish() OVERRIDE; - - virtual bool swapBuffers() OVERRIDE; - - virtual void getFramebufferPixels(void *pixels, const IntRect&) OVERRIDE; - - virtual void setVisible(bool) OVERRIDE; - -protected: - virtual void bindFramebufferToOutputSurface(DrawingFrame&) OVERRIDE; - virtual bool bindFramebufferToTexture(DrawingFrame&, const CCScopedTexture*, const IntRect& framebufferRect) OVERRIDE; - virtual void setDrawViewportSize(const IntSize&) OVERRIDE; - virtual void enableScissorTestRect(const IntRect& scissorRect) OVERRIDE; - virtual void disableScissorTest() OVERRIDE; - virtual void clearFramebuffer(DrawingFrame&) OVERRIDE; - virtual void drawQuad(DrawingFrame&, const CCDrawQuad*) OVERRIDE; - virtual void beginDrawingFrame(DrawingFrame&) OVERRIDE; - virtual void finishDrawingFrame(DrawingFrame&) OVERRIDE; - virtual bool flippedFramebuffer() const OVERRIDE; - -private: - CCRendererSoftware(CCRendererClient*, CCResourceProvider*, WebKit::WebCompositorSoftwareOutputDevice*); - - bool isSoftwareResource(CCResourceProvider::ResourceId) const; - - void drawDebugBorderQuad(const DrawingFrame&, const CCDebugBorderDrawQuad*); - void drawSolidColorQuad(const DrawingFrame&, const CCSolidColorDrawQuad*); - void drawTextureQuad(const DrawingFrame&, const CCTextureDrawQuad*); - void drawTileQuad(const DrawingFrame&, const CCTileDrawQuad*); - void drawUnsupportedQuad(const DrawingFrame&, const CCDrawQuad*); - - RendererCapabilities m_capabilities; - bool m_visible; - - WebKit::WebCompositorSoftwareOutputDevice* m_outputDevice; - OwnPtr m_skRootCanvas; - SkCanvas* m_skCurrentCanvas; - SkPaint m_skCurrentPaint; - OwnPtr m_currentFramebufferLock; - - DISALLOW_COPY_AND_ASSIGN(CCRendererSoftware); -}; - -} - -#endif +// Temporary forwarding header +#include "cc/software_renderer.h" diff --git a/cc/CCRenderingStats.h b/cc/CCRenderingStats.h index fb178a8..d95e987 100644 --- a/cc/CCRenderingStats.h +++ b/cc/CCRenderingStats.h @@ -2,37 +2,5 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CCRenderingStats_h -#define CCRenderingStats_h - -namespace cc { - -struct CCRenderingStats { - // FIXME: Rename these to animationFrameCount and screenFrameCount, crbug.com/138641. - int numAnimationFrames; - int numFramesSentToScreen; - int droppedFrameCount; - double totalPaintTimeInSeconds; - double totalRasterizeTimeInSeconds; - double totalCommitTimeInSeconds; - size_t totalCommitCount; - size_t numImplThreadScrolls; - size_t numMainThreadScrolls; - - CCRenderingStats() - : numAnimationFrames(0) - , numFramesSentToScreen(0) - , droppedFrameCount(0) - , totalPaintTimeInSeconds(0) - , totalRasterizeTimeInSeconds(0) - , totalCommitTimeInSeconds(0) - , totalCommitCount(0) - , numImplThreadScrolls(0) - , numMainThreadScrolls(0) - { - } -}; - -} - -#endif +// Temporary forwarding header +#include "cc/rendering_stats.h" diff --git a/cc/CCResourceProvider.cpp b/cc/CCResourceProvider.cpp deleted file mode 100644 index 29ca7d4..0000000 --- a/cc/CCResourceProvider.cpp +++ /dev/null @@ -1,708 +0,0 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "config.h" - -#include "CCResourceProvider.h" -#ifdef LOG -#undef LOG -#endif - -#include - -#include "base/debug/alias.h" -#include "base/hash_tables.h" -#include "base/stl_util.h" -#include "base/string_split.h" -#include "base/string_util.h" -#include "CCProxy.h" -#include "CCRendererGL.h" // For the GLC() macro. -#include "Extensions3DChromium.h" -#include "IntRect.h" -#include "LayerTextureSubImage.h" -#include "ThrottledTextureUploader.h" -#include "UnthrottledTextureUploader.h" -#include - -using WebKit::WebGraphicsContext3D; - -namespace cc { - -static GC3Denum textureToStorageFormat(GC3Denum textureFormat) -{ - GC3Denum storageFormat = Extensions3D::RGBA8_OES; - switch (textureFormat) { - case GraphicsContext3D::RGBA: - break; - case Extensions3D::BGRA_EXT: - storageFormat = Extensions3DChromium::BGRA8_EXT; - break; - default: - ASSERT_NOT_REACHED(); - break; - } - - return storageFormat; -} - -static bool isTextureFormatSupportedForStorage(GC3Denum format) -{ - return (format == GraphicsContext3D::RGBA || format == Extensions3D::BGRA_EXT); -} - -CCResourceProvider::TransferableResourceList::TransferableResourceList() -{ -} - -CCResourceProvider::TransferableResourceList::~TransferableResourceList() -{ -} - -CCResourceProvider::Resource::Resource() - : glId(0) - , pixels(0) - , pool(0) - , lockForReadCount(0) - , lockedForWrite(false) - , external(false) - , exported(false) - , size() - , format(0) - , type(static_cast(0)) -{ -} - -CCResourceProvider::Resource::Resource(unsigned textureId, int pool, const IntSize& size, GC3Denum format) - : glId(textureId) - , pixels(0) - , pool(pool) - , lockForReadCount(0) - , lockedForWrite(false) - , external(false) - , exported(false) - , size(size) - , format(format) - , type(GLTexture) -{ -} - -CCResourceProvider::Resource::Resource(uint8_t* pixels, int pool, const IntSize& size, GC3Denum format) - : glId(0) - , pixels(pixels) - , pool(pool) - , lockForReadCount(0) - , lockedForWrite(false) - , external(false) - , exported(false) - , size(size) - , format(format) - , type(Bitmap) -{ -} - -CCResourceProvider::Child::Child() -{ -} - -CCResourceProvider::Child::~Child() -{ -} - -PassOwnPtr CCResourceProvider::create(CCGraphicsContext* context) -{ - OwnPtr resourceProvider(adoptPtr(new CCResourceProvider(context))); - if (!resourceProvider->initialize()) - return nullptr; - return resourceProvider.release(); -} - -CCResourceProvider::~CCResourceProvider() -{ - WebGraphicsContext3D* context3d = m_context->context3D(); - if (!context3d || !context3d->makeContextCurrent()) - return; - m_textureUploader.clear(); - m_textureCopier.clear(); -} - -WebGraphicsContext3D* CCResourceProvider::graphicsContext3D() -{ - ASSERT(CCProxy::isImplThread()); - return m_context->context3D(); -} - -bool CCResourceProvider::inUseByConsumer(ResourceId id) -{ - ASSERT(CCProxy::isImplThread()); - ResourceMap::iterator it = m_resources.find(id); - CHECK(it != m_resources.end()); -#if WTF_NEW_HASHMAP_ITERATORS_INTERFACE - Resource* resource = &it->value; -#else - Resource* resource = &it->second; -#endif - return !!resource->lockForReadCount || resource->exported; -} - -CCResourceProvider::ResourceId CCResourceProvider::createResource(int pool, const IntSize& size, GC3Denum format, TextureUsageHint hint) -{ - switch (m_defaultResourceType) { - case GLTexture: - return createGLTexture(pool, size, format, hint); - case Bitmap: - ASSERT(format == GraphicsContext3D::RGBA); - return createBitmap(pool, size); - } - - CRASH(); - return 0; -} - -CCResourceProvider::ResourceId CCResourceProvider::createGLTexture(int pool, const IntSize& size, GC3Denum format, TextureUsageHint hint) -{ - ASSERT(CCProxy::isImplThread()); - unsigned textureId = 0; - WebGraphicsContext3D* context3d = m_context->context3D(); - ASSERT(context3d); - GLC(context3d, textureId = context3d->createTexture()); - GLC(context3d, context3d->bindTexture(GraphicsContext3D::TEXTURE_2D, textureId)); - GLC(context3d, context3d->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR)); - GLC(context3d, context3d->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR)); - GLC(context3d, context3d->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE)); - GLC(context3d, context3d->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE)); - - if (m_useTextureUsageHint && hint == TextureUsageFramebuffer) - GLC(context3d, context3d->texParameteri(GraphicsContext3D::TEXTURE_2D, Extensions3DChromium::GL_TEXTURE_USAGE_ANGLE, Extensions3DChromium::GL_FRAMEBUFFER_ATTACHMENT_ANGLE)); - if (m_useTextureStorageExt && isTextureFormatSupportedForStorage(format)) { - GC3Denum storageFormat = textureToStorageFormat(format); - GLC(context3d, context3d->texStorage2DEXT(GraphicsContext3D::TEXTURE_2D, 1, storageFormat, size.width(), size.height())); - } else - GLC(context3d, context3d->texImage2D(GraphicsContext3D::TEXTURE_2D, 0, format, size.width(), size.height(), 0, format, GraphicsContext3D::UNSIGNED_BYTE, 0)); - ResourceId id = m_nextId++; - Resource resource(textureId, pool, size, format); - m_resources.add(id, resource); - return id; -} - -CCResourceProvider::ResourceId CCResourceProvider::createBitmap(int pool, const IntSize& size) -{ - ASSERT(CCProxy::isImplThread()); - - uint8_t* pixels = new uint8_t[size.width() * size.height() * 4]; - - ResourceId id = m_nextId++; - Resource resource(pixels, pool, size, GraphicsContext3D::RGBA); - m_resources.add(id, resource); - return id; -} - -CCResourceProvider::ResourceId CCResourceProvider::createResourceFromExternalTexture(unsigned textureId) -{ - ASSERT(CCProxy::isImplThread()); - ASSERT(m_context->context3D()); - ResourceId id = m_nextId++; - Resource resource(textureId, 0, IntSize(), 0); - resource.external = true; - m_resources.add(id, resource); - return id; -} - -void CCResourceProvider::deleteResource(ResourceId id) -{ - ASSERT(CCProxy::isImplThread()); - ResourceMap::iterator it = m_resources.find(id); - CHECK(it != m_resources.end()); -#if WTF_NEW_HASHMAP_ITERATORS_INTERFACE - Resource* resource = &it->value; -#else - Resource* resource = &it->second; -#endif - ASSERT(!resource->lockedForWrite); - ASSERT(!resource->lockForReadCount); - - if (resource->glId && !resource->external) { - WebGraphicsContext3D* context3d = m_context->context3D(); - ASSERT(context3d); - GLC(context3d, context3d->deleteTexture(resource->glId)); - } - if (resource->pixels) - delete resource->pixels; - - m_resources.remove(it); -} - -void CCResourceProvider::deleteOwnedResources(int pool) -{ - ASSERT(CCProxy::isImplThread()); - ResourceIdArray toDelete; - for (ResourceMap::iterator it = m_resources.begin(); it != m_resources.end(); ++it) { -#if WTF_NEW_HASHMAP_ITERATORS_INTERFACE - if (it->value.pool == pool && !it->value.external) - toDelete.append(it->key); -#else - if (it->second.pool == pool && !it->second.external) - toDelete.append(it->first); -#endif - } - for (ResourceIdArray::iterator it = toDelete.begin(); it != toDelete.end(); ++it) - deleteResource(*it); -} - -CCResourceProvider::ResourceType CCResourceProvider::resourceType(ResourceId id) -{ - ResourceMap::iterator it = m_resources.find(id); - CHECK(it != m_resources.end()); -#if WTF_NEW_HASHMAP_ITERATORS_INTERFACE - Resource* resource = &it->value; -#else - Resource* resource = &it->second; -#endif - return resource->type; -} - -void CCResourceProvider::upload(ResourceId id, const uint8_t* image, const IntRect& imageRect, const IntRect& sourceRect, const IntSize& destOffset) -{ - ASSERT(CCProxy::isImplThread()); - ResourceMap::iterator it = m_resources.find(id); - CHECK(it != m_resources.end()); -#if WTF_NEW_HASHMAP_ITERATORS_INTERFACE - Resource* resource = &it->value; -#else - Resource* resource = &it->second; -#endif - ASSERT(!resource->lockedForWrite); - ASSERT(!resource->lockForReadCount); - ASSERT(!resource->external); - - if (resource->glId) { - WebGraphicsContext3D* context3d = m_context->context3D(); - ASSERT(context3d); - ASSERT(m_texSubImage.get()); - context3d->bindTexture(GraphicsContext3D::TEXTURE_2D, resource->glId); - m_texSubImage->upload(image, imageRect, sourceRect, destOffset, resource->format, context3d); - } - - if (resource->pixels) { - SkBitmap srcFull; - srcFull.setConfig(SkBitmap::kARGB_8888_Config, imageRect.width(), imageRect.height()); - srcFull.setPixels(const_cast(image)); - SkBitmap srcSubset; - SkIRect skSourceRect = SkIRect::MakeXYWH(sourceRect.x(), sourceRect.y(), sourceRect.width(), sourceRect.height()); - skSourceRect.offset(-imageRect.x(), -imageRect.y()); - srcFull.extractSubset(&srcSubset, skSourceRect); - - ScopedWriteLockSoftware lock(this, id); - SkCanvas* dest = lock.skCanvas(); - dest->writePixels(srcSubset, destOffset.width(), destOffset.height()); - } -} - -void CCResourceProvider::flush() -{ - ASSERT(CCProxy::isImplThread()); - WebGraphicsContext3D* context3d = m_context->context3D(); - if (context3d) - context3d->flush(); -} - -bool CCResourceProvider::shallowFlushIfSupported() -{ - ASSERT(CCProxy::isImplThread()); - WebGraphicsContext3D* context3d = m_context->context3D(); - if (!context3d || !m_useShallowFlush) - return false; - - context3d->shallowFlushCHROMIUM(); - return true; -} - -const CCResourceProvider::Resource* CCResourceProvider::lockForRead(ResourceId id) -{ - ASSERT(CCProxy::isImplThread()); - ResourceMap::iterator it = m_resources.find(id); - CHECK(it != m_resources.end()); - -#if WTF_NEW_HASHMAP_ITERATORS_INTERFACE - Resource* resource = &it->value; -#else - Resource* resource = &it->second; -#endif - ASSERT(!resource->lockedForWrite); - resource->lockForReadCount++; - return resource; -} - -void CCResourceProvider::unlockForRead(ResourceId id) -{ - ASSERT(CCProxy::isImplThread()); - ResourceMap::iterator it = m_resources.find(id); - CHECK(it != m_resources.end()); -#if WTF_NEW_HASHMAP_ITERATORS_INTERFACE - Resource* resource = &it->value; -#else - Resource* resource = &it->second; -#endif - ASSERT(resource->lockForReadCount > 0); - resource->lockForReadCount--; -} - -const CCResourceProvider::Resource* CCResourceProvider::lockForWrite(ResourceId id) -{ - ASSERT(CCProxy::isImplThread()); - ResourceMap::iterator it = m_resources.find(id); - CHECK(it != m_resources.end()); -#if WTF_NEW_HASHMAP_ITERATORS_INTERFACE - Resource* resource = &it->value; -#else - Resource* resource = &it->second; -#endif - ASSERT(!resource->lockedForWrite); - ASSERT(!resource->lockForReadCount); - ASSERT(!resource->external); - resource->lockedForWrite = true; - return resource; -} - -void CCResourceProvider::unlockForWrite(ResourceId id) -{ - ASSERT(CCProxy::isImplThread()); - ResourceMap::iterator it = m_resources.find(id); - CHECK(it != m_resources.end()); -#if WTF_NEW_HASHMAP_ITERATORS_INTERFACE - Resource* resource = &it->value; -#else - Resource* resource = &it->second; -#endif - ASSERT(resource->lockedForWrite); - ASSERT(!resource->external); - resource->lockedForWrite = false; -} - -CCResourceProvider::ScopedReadLockGL::ScopedReadLockGL(CCResourceProvider* resourceProvider, CCResourceProvider::ResourceId resourceId) - : m_resourceProvider(resourceProvider) - , m_resourceId(resourceId) - , m_textureId(resourceProvider->lockForRead(resourceId)->glId) -{ - ASSERT(m_textureId); -} - -CCResourceProvider::ScopedReadLockGL::~ScopedReadLockGL() -{ - m_resourceProvider->unlockForRead(m_resourceId); -} - -CCResourceProvider::ScopedWriteLockGL::ScopedWriteLockGL(CCResourceProvider* resourceProvider, CCResourceProvider::ResourceId resourceId) - : m_resourceProvider(resourceProvider) - , m_resourceId(resourceId) - , m_textureId(resourceProvider->lockForWrite(resourceId)->glId) -{ - ASSERT(m_textureId); -} - -CCResourceProvider::ScopedWriteLockGL::~ScopedWriteLockGL() -{ - m_resourceProvider->unlockForWrite(m_resourceId); -} - -void CCResourceProvider::populateSkBitmapWithResource(SkBitmap* skBitmap, const Resource* resource) -{ - ASSERT(resource->pixels); - ASSERT(resource->format == GraphicsContext3D::RGBA); - skBitmap->setConfig(SkBitmap::kARGB_8888_Config, resource->size.width(), resource->size.height()); - skBitmap->setPixels(resource->pixels); -} - -CCResourceProvider::ScopedReadLockSoftware::ScopedReadLockSoftware(CCResourceProvider* resourceProvider, CCResourceProvider::ResourceId resourceId) - : m_resourceProvider(resourceProvider) - , m_resourceId(resourceId) -{ - CCResourceProvider::populateSkBitmapWithResource(&m_skBitmap, resourceProvider->lockForRead(resourceId)); -} - -CCResourceProvider::ScopedReadLockSoftware::~ScopedReadLockSoftware() -{ - m_resourceProvider->unlockForRead(m_resourceId); -} - -CCResourceProvider::ScopedWriteLockSoftware::ScopedWriteLockSoftware(CCResourceProvider* resourceProvider, CCResourceProvider::ResourceId resourceId) - : m_resourceProvider(resourceProvider) - , m_resourceId(resourceId) -{ - CCResourceProvider::populateSkBitmapWithResource(&m_skBitmap, resourceProvider->lockForWrite(resourceId)); - m_skCanvas = adoptPtr(new SkCanvas(m_skBitmap)); -} - -CCResourceProvider::ScopedWriteLockSoftware::~ScopedWriteLockSoftware() -{ - m_resourceProvider->unlockForWrite(m_resourceId); -} - -CCResourceProvider::CCResourceProvider(CCGraphicsContext* context) - : m_context(context) - , m_nextId(1) - , m_nextChild(1) - , m_defaultResourceType(GLTexture) - , m_useTextureStorageExt(false) - , m_useTextureUsageHint(false) - , m_useShallowFlush(false) - , m_maxTextureSize(0) -{ -} - -bool CCResourceProvider::initialize() -{ - ASSERT(CCProxy::isImplThread()); - WebGraphicsContext3D* context3d = m_context->context3D(); - if (!context3d) { - m_maxTextureSize = INT_MAX / 2; - m_textureUploader = UnthrottledTextureUploader::create(); - return true; - } - if (!context3d->makeContextCurrent()) - return false; - - std::string extensionsString = UTF16ToASCII(context3d->getString(GraphicsContext3D::EXTENSIONS)); - std::vector extensions; - base::SplitString(extensionsString, ' ', &extensions); - bool useMapSub = false; - bool useBindUniform = false; - for (size_t i = 0; i < extensions.size(); ++i) { - if (extensions[i] == "GL_EXT_texture_storage") - m_useTextureStorageExt = true; - else if (extensions[i] == "GL_ANGLE_texture_usage") - m_useTextureUsageHint = true; - else if (extensions[i] == "GL_CHROMIUM_map_sub") - useMapSub = true; - else if (extensions[i] == "GL_CHROMIUM_shallow_flush") - m_useShallowFlush = true; - else if (extensions[i] == "GL_CHROMIUM_bind_uniform_location") - useBindUniform = true; - } - - m_texSubImage = adoptPtr(new LayerTextureSubImage(useMapSub)); - m_textureCopier = AcceleratedTextureCopier::create(context3d, useBindUniform); - - m_textureUploader = ThrottledTextureUploader::create(context3d); - GLC(context3d, context3d->getIntegerv(GraphicsContext3D::MAX_TEXTURE_SIZE, &m_maxTextureSize)); - return true; -} - -int CCResourceProvider::createChild(int pool) -{ - ASSERT(CCProxy::isImplThread()); - Child childInfo; - childInfo.pool = pool; - int child = m_nextChild++; - m_children.add(child, childInfo); - return child; -} - -void CCResourceProvider::destroyChild(int child) -{ - ASSERT(CCProxy::isImplThread()); - ChildMap::iterator it = m_children.find(child); - ASSERT(it != m_children.end()); -#if WTF_NEW_HASHMAP_ITERATORS_INTERFACE - deleteOwnedResources(it->value.pool); -#else - deleteOwnedResources(it->second.pool); -#endif - m_children.remove(it); - trimMailboxDeque(); -} - -const CCResourceProvider::ResourceIdMap& CCResourceProvider::getChildToParentMap(int child) const -{ - ASSERT(CCProxy::isImplThread()); - ChildMap::const_iterator it = m_children.find(child); - ASSERT(it != m_children.end()); -#if WTF_NEW_HASHMAP_ITERATORS_INTERFACE - return it->value.childToParentMap; -#else - return it->second.childToParentMap; -#endif -} - -CCResourceProvider::TransferableResourceList CCResourceProvider::prepareSendToParent(const ResourceIdArray& resources) -{ - ASSERT(CCProxy::isImplThread()); - TransferableResourceList list; - list.syncPoint = 0; - WebGraphicsContext3D* context3d = m_context->context3D(); - if (!context3d || !context3d->makeContextCurrent()) { - // FIXME: Implement this path for software compositing. - return list; - } - for (ResourceIdArray::const_iterator it = resources.begin(); it != resources.end(); ++it) { - TransferableResource resource; - if (transferResource(context3d, *it, &resource)) { -#if WTF_NEW_HASHMAP_ITERATORS_INTERFACE - m_resources.find(*it)->value.exported = true; -#else - m_resources.find(*it)->second.exported = true; -#endif - list.resources.append(resource); - } - } - if (list.resources.size()) - list.syncPoint = context3d->insertSyncPoint(); - return list; -} - -CCResourceProvider::TransferableResourceList CCResourceProvider::prepareSendToChild(int child, const ResourceIdArray& resources) -{ - ASSERT(CCProxy::isImplThread()); - TransferableResourceList list; - list.syncPoint = 0; - WebGraphicsContext3D* context3d = m_context->context3D(); - if (!context3d || !context3d->makeContextCurrent()) { - // FIXME: Implement this path for software compositing. - return list; - } -#if WTF_NEW_HASHMAP_ITERATORS_INTERFACE - Child& childInfo = m_children.find(child)->value; -#else - Child& childInfo = m_children.find(child)->second; -#endif - for (ResourceIdArray::const_iterator it = resources.begin(); it != resources.end(); ++it) { - TransferableResource resource; - if (!transferResource(context3d, *it, &resource)) - ASSERT_NOT_REACHED(); - resource.id = childInfo.parentToChildMap.get(*it); - childInfo.parentToChildMap.remove(*it); - childInfo.childToParentMap.remove(resource.id); - list.resources.append(resource); - deleteResource(*it); - } - if (list.resources.size()) - list.syncPoint = context3d->insertSyncPoint(); - return list; -} - -void CCResourceProvider::receiveFromChild(int child, const TransferableResourceList& resources) -{ - ASSERT(CCProxy::isImplThread()); - WebGraphicsContext3D* context3d = m_context->context3D(); - if (!context3d || !context3d->makeContextCurrent()) { - // FIXME: Implement this path for software compositing. - return; - } - if (resources.syncPoint) { - // NOTE: If the parent is a browser and the child a renderer, the parent - // is not supposed to have its context wait, because that could induce - // deadlocks and/or security issues. The caller is responsible for - // waiting asynchronously, and resetting syncPoint before calling this. - // However if the parent is a renderer (e.g. browser tag), it may be ok - // (and is simpler) to wait. - GLC(context3d, context3d->waitSyncPoint(resources.syncPoint)); - } -#if WTF_NEW_HASHMAP_ITERATORS_INTERFACE - Child& childInfo = m_children.find(child)->value; -#else - Child& childInfo = m_children.find(child)->second; -#endif - for (Vector::const_iterator it = resources.resources.begin(); it != resources.resources.end(); ++it) { - unsigned textureId; - GLC(context3d, textureId = context3d->createTexture()); - GLC(context3d, context3d->bindTexture(GraphicsContext3D::TEXTURE_2D, textureId)); - GLC(context3d, context3d->consumeTextureCHROMIUM(GraphicsContext3D::TEXTURE_2D, it->mailbox.name)); - ResourceId id = m_nextId++; - Resource resource(textureId, childInfo.pool, it->size, it->format); - m_resources.add(id, resource); - m_mailboxes.append(it->mailbox); - childInfo.parentToChildMap.add(id, it->id); - childInfo.childToParentMap.add(it->id, id); - } -} - -void CCResourceProvider::receiveFromParent(const TransferableResourceList& resources) -{ - ASSERT(CCProxy::isImplThread()); - WebGraphicsContext3D* context3d = m_context->context3D(); - if (!context3d || !context3d->makeContextCurrent()) { - // FIXME: Implement this path for software compositing. - return; - } - if (resources.syncPoint) - GLC(context3d, context3d->waitSyncPoint(resources.syncPoint)); - for (Vector::const_iterator it = resources.resources.begin(); it != resources.resources.end(); ++it) { -#if WTF_NEW_HASHMAP_ITERATORS_INTERFACE - Resource* resource = &m_resources.find(it->id)->value; -#else - Resource* resource = &m_resources.find(it->id)->second; -#endif - ASSERT(resource->exported); - resource->exported = false; - GLC(context3d, context3d->bindTexture(GraphicsContext3D::TEXTURE_2D, resource->glId)); - GLC(context3d, context3d->consumeTextureCHROMIUM(GraphicsContext3D::TEXTURE_2D, it->mailbox.name)); - m_mailboxes.append(it->mailbox); - } -} - -bool CCResourceProvider::transferResource(WebGraphicsContext3D* context, ResourceId id, TransferableResource* resource) -{ - ASSERT(CCProxy::isImplThread()); - ResourceMap::const_iterator it = m_resources.find(id); - CHECK(it != m_resources.end()); -#if WTF_NEW_HASHMAP_ITERATORS_INTERFACE - const Resource* source = &it->value; -#else - const Resource* source = &it->second; -#endif - ASSERT(!source->lockedForWrite); - ASSERT(!source->lockForReadCount); - ASSERT(!source->external); - if (source->exported) - return false; - resource->id = id; - resource->format = source->format; - resource->size = source->size; - if (!m_mailboxes.isEmpty()) - resource->mailbox = m_mailboxes.takeFirst(); - else - GLC(context, context->genMailboxCHROMIUM(resource->mailbox.name)); - GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, source->glId)); - GLC(context, context->produceTextureCHROMIUM(GraphicsContext3D::TEXTURE_2D, resource->mailbox.name)); - return true; -} - -void CCResourceProvider::trimMailboxDeque() -{ - // Trim the mailbox deque to the maximum number of resources we may need to - // send. - // If we have a parent, any non-external resource not already transfered is - // eligible to be sent to the parent. Otherwise, all resources belonging to - // a child might need to be sent back to the child. - size_t maxMailboxCount = 0; - if (m_context->capabilities().hasParentCompositor) { - for (ResourceMap::iterator it = m_resources.begin(); it != m_resources.end(); ++it) { -#if WTF_NEW_HASHMAP_ITERATORS_INTERFACE - if (!it->value.exported && !it->value.external) -#else - if (!it->second.exported && !it->second.external) -#endif - ++maxMailboxCount; - } - } else { - base::hash_set childPoolSet; - for (ChildMap::iterator it = m_children.begin(); it != m_children.end(); ++it) -#if WTF_NEW_HASHMAP_ITERATORS_INTERFACE - childPoolSet.insert(it->value.pool); -#else - childPoolSet.insert(it->second.pool); -#endif - for (ResourceMap::iterator it = m_resources.begin(); it != m_resources.end(); ++it) { -#if WTF_NEW_HASHMAP_ITERATORS_INTERFACE - if (ContainsKey(childPoolSet, it->value.pool)) -#else - if (ContainsKey(childPoolSet, it->second.pool)) -#endif - ++maxMailboxCount; - } - } - while (m_mailboxes.size() > maxMailboxCount) - m_mailboxes.removeFirst(); -} - -} diff --git a/cc/CCResourceProvider.h b/cc/CCResourceProvider.h index f515c11..be760bb 100644 --- a/cc/CCResourceProvider.h +++ b/cc/CCResourceProvider.h @@ -2,274 +2,5 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CCResourceProvider_h -#define CCResourceProvider_h - -#include "base/basictypes.h" -#include "CCGraphicsContext.h" -#include "GraphicsContext3D.h" -#include "IntSize.h" -#include "SkBitmap.h" -#include "SkCanvas.h" -#include "TextureCopier.h" -#include -#include -#include -#include -#include -#include -#include - -namespace WebKit { -class WebGraphicsContext3D; -} - -namespace cc { - -class IntRect; -class LayerTextureSubImage; -class TextureCopier; -class TextureUploader; - -// Thread-safety notes: this class is not thread-safe and can only be called -// from the thread it was created on (in practice, the compositor thread). -class CCResourceProvider { -public: - typedef unsigned ResourceId; - typedef Vector ResourceIdArray; - typedef HashMap ResourceIdMap; - enum TextureUsageHint { TextureUsageAny, TextureUsageFramebuffer }; - enum ResourceType { - GLTexture = 1, - Bitmap, - }; - struct Mailbox { - GC3Dbyte name[64]; - }; - struct TransferableResource { - unsigned id; - GC3Denum format; - IntSize size; - Mailbox mailbox; - }; - typedef Vector TransferableResourceArray; - struct TransferableResourceList { - TransferableResourceList(); - ~TransferableResourceList(); - - TransferableResourceArray resources; - unsigned syncPoint; - }; - - static PassOwnPtr create(CCGraphicsContext*); - - virtual ~CCResourceProvider(); - - WebKit::WebGraphicsContext3D* graphicsContext3D(); - TextureUploader* textureUploader() const { return m_textureUploader.get(); } - TextureCopier* textureCopier() const { return m_textureCopier.get(); } - int maxTextureSize() const { return m_maxTextureSize; } - unsigned numResources() const { return m_resources.size(); } - - // Checks whether a resource is in use by a consumer. - bool inUseByConsumer(ResourceId); - - - // Producer interface. - - void setDefaultResourceType(ResourceType type) { m_defaultResourceType = type; } - ResourceType defaultResourceType() const { return m_defaultResourceType; } - ResourceType resourceType(ResourceId); - - // Creates a resource of the default resource type. - ResourceId createResource(int pool, const IntSize&, GC3Denum format, TextureUsageHint); - - // You can also explicitly create a specific resource type. - ResourceId createGLTexture(int pool, const IntSize&, GC3Denum format, TextureUsageHint); - ResourceId createBitmap(int pool, const IntSize&); - // Wraps an external texture into a GL resource. - ResourceId createResourceFromExternalTexture(unsigned textureId); - - void deleteResource(ResourceId); - - // Deletes all resources owned by a given pool. - void deleteOwnedResources(int pool); - - // Upload data from image, copying sourceRect (in image) into destRect (in the resource). - void upload(ResourceId, const uint8_t* image, const IntRect& imageRect, const IntRect& sourceRect, const IntSize& destOffset); - - // Flush all context operations, kicking uploads and ensuring ordering with - // respect to other contexts. - void flush(); - - // Only flush the command buffer if supported. - // Returns true if the shallow flush occurred, false otherwise. - bool shallowFlushIfSupported(); - - // Creates accounting for a child, and associate it with a pool. Resources - // transfered from that child will go to that pool. Returns a child ID. - int createChild(int pool); - - // Destroys accounting for the child, deleting all resources from that pool. - void destroyChild(int child); - - // Gets the child->parent resource ID map. - const ResourceIdMap& getChildToParentMap(int child) const; - - // Prepares resources to be transfered to the parent, moving them to - // mailboxes and serializing meta-data into TransferableResources. - // Resources are not removed from the CCResourceProvider, but are markes as - // "in use". - TransferableResourceList prepareSendToParent(const ResourceIdArray&); - - // Prepares resources to be transfered back to the child, moving them to - // mailboxes and serializing meta-data into TransferableResources. - // Resources are removed from the CCResourceProvider. Note: the resource IDs - // passed are in the parent namespace and will be translated to the child - // namespace when returned. - TransferableResourceList prepareSendToChild(int child, const ResourceIdArray&); - - // Receives resources from a child, moving them from mailboxes. Resource IDs - // passed are in the child namespace, and will be translated to the parent - // namespace, added to the child->parent map. - // NOTE: if the syncPoint filed in TransferableResourceList is set, this - // will wait on it. - void receiveFromChild(int child, const TransferableResourceList&); - - // Receives resources from the parent, moving them from mailboxes. Resource IDs - // passed are in the child namespace. - // NOTE: if the syncPoint filed in TransferableResourceList is set, this - // will wait on it. - void receiveFromParent(const TransferableResourceList&); - - // Only for testing - size_t mailboxCount() const { return m_mailboxes.size(); } - - // The following lock classes are part of the CCResourceProvider API and are - // needed to read and write the resource contents. The user must ensure - // that they only use GL locks on GL resources, etc, and this is enforced - // by assertions. - class ScopedReadLockGL { - public: - ScopedReadLockGL(CCResourceProvider*, CCResourceProvider::ResourceId); - ~ScopedReadLockGL(); - - unsigned textureId() const { return m_textureId; } - - private: - CCResourceProvider* m_resourceProvider; - CCResourceProvider::ResourceId m_resourceId; - unsigned m_textureId; - - DISALLOW_COPY_AND_ASSIGN(ScopedReadLockGL); - }; - - class ScopedWriteLockGL { - public: - ScopedWriteLockGL(CCResourceProvider*, CCResourceProvider::ResourceId); - ~ScopedWriteLockGL(); - - unsigned textureId() const { return m_textureId; } - - private: - CCResourceProvider* m_resourceProvider; - CCResourceProvider::ResourceId m_resourceId; - unsigned m_textureId; - - DISALLOW_COPY_AND_ASSIGN(ScopedWriteLockGL); - }; - - class ScopedReadLockSoftware { - public: - ScopedReadLockSoftware(CCResourceProvider*, CCResourceProvider::ResourceId); - ~ScopedReadLockSoftware(); - - const SkBitmap* skBitmap() const { return &m_skBitmap; } - - private: - CCResourceProvider* m_resourceProvider; - CCResourceProvider::ResourceId m_resourceId; - SkBitmap m_skBitmap; - - DISALLOW_COPY_AND_ASSIGN(ScopedReadLockSoftware); - }; - - class ScopedWriteLockSoftware { - public: - ScopedWriteLockSoftware(CCResourceProvider*, CCResourceProvider::ResourceId); - ~ScopedWriteLockSoftware(); - - SkCanvas* skCanvas() { return m_skCanvas.get(); } - - private: - CCResourceProvider* m_resourceProvider; - CCResourceProvider::ResourceId m_resourceId; - SkBitmap m_skBitmap; - OwnPtr m_skCanvas; - - DISALLOW_COPY_AND_ASSIGN(ScopedWriteLockSoftware); - }; - -private: - struct Resource { - Resource(); - Resource(unsigned textureId, int pool, const IntSize& size, GC3Denum format); - Resource(uint8_t* pixels, int pool, const IntSize& size, GC3Denum format); - - unsigned glId; - uint8_t* pixels; - int pool; - int lockForReadCount; - bool lockedForWrite; - bool external; - bool exported; - IntSize size; - GC3Denum format; - ResourceType type; - }; - typedef HashMap ResourceMap; - struct Child { - Child(); - ~Child(); - - int pool; - ResourceIdMap childToParentMap; - ResourceIdMap parentToChildMap; - }; - typedef HashMap ChildMap; - - explicit CCResourceProvider(CCGraphicsContext*); - bool initialize(); - - const Resource* lockForRead(ResourceId); - void unlockForRead(ResourceId); - const Resource* lockForWrite(ResourceId); - void unlockForWrite(ResourceId); - static void populateSkBitmapWithResource(SkBitmap*, const Resource*); - - bool transferResource(WebKit::WebGraphicsContext3D*, ResourceId, TransferableResource*); - void trimMailboxDeque(); - - CCGraphicsContext* m_context; - ResourceId m_nextId; - ResourceMap m_resources; - int m_nextChild; - ChildMap m_children; - - Deque m_mailboxes; - - ResourceType m_defaultResourceType; - bool m_useTextureStorageExt; - bool m_useTextureUsageHint; - bool m_useShallowFlush; - OwnPtr m_texSubImage; - OwnPtr m_textureUploader; - OwnPtr m_textureCopier; - int m_maxTextureSize; - - DISALLOW_COPY_AND_ASSIGN(CCResourceProvider); -}; - -} - -#endif +// Temporary forwarding header +#include "cc/resource_provider.h" diff --git a/cc/CCScheduler.cpp b/cc/CCScheduler.cpp deleted file mode 100644 index 869cd19..0000000 --- a/cc/CCScheduler.cpp +++ /dev/null @@ -1,192 +0,0 @@ -// Copyright 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "config.h" - -#include "CCScheduler.h" - -#include "TraceEvent.h" -#include - -namespace cc { - -CCScheduler::CCScheduler(CCSchedulerClient* client, scoped_ptr frameRateController) - : m_client(client) - , m_frameRateController(frameRateController.Pass()) - , m_insideProcessScheduledActions(false) -{ - ASSERT(m_client); - m_frameRateController->setClient(this); - ASSERT(!m_stateMachine.vsyncCallbackNeeded()); -} - -CCScheduler::~CCScheduler() -{ - m_frameRateController->setActive(false); -} - -void CCScheduler::setCanBeginFrame(bool can) -{ - m_stateMachine.setCanBeginFrame(can); - processScheduledActions(); -} - -void CCScheduler::setVisible(bool visible) -{ - m_stateMachine.setVisible(visible); - processScheduledActions(); -} - -void CCScheduler::setCanDraw(bool canDraw) -{ - m_stateMachine.setCanDraw(canDraw); - processScheduledActions(); -} - -void CCScheduler::setNeedsCommit() -{ - m_stateMachine.setNeedsCommit(); - processScheduledActions(); -} - -void CCScheduler::setNeedsForcedCommit() -{ - m_stateMachine.setNeedsForcedCommit(); - processScheduledActions(); -} - -void CCScheduler::setNeedsRedraw() -{ - m_stateMachine.setNeedsRedraw(); - processScheduledActions(); -} - -void CCScheduler::setNeedsForcedRedraw() -{ - m_stateMachine.setNeedsForcedRedraw(); - processScheduledActions(); -} - -void CCScheduler::setMainThreadNeedsLayerTextures() -{ - m_stateMachine.setMainThreadNeedsLayerTextures(); - processScheduledActions(); -} - -void CCScheduler::beginFrameComplete() -{ - TRACE_EVENT0("cc", "CCScheduler::beginFrameComplete"); - m_stateMachine.beginFrameComplete(); - processScheduledActions(); -} - -void CCScheduler::beginFrameAborted() -{ - TRACE_EVENT0("cc", "CCScheduler::beginFrameAborted"); - m_stateMachine.beginFrameAborted(); - processScheduledActions(); -} - -void CCScheduler::setMaxFramesPending(int maxFramesPending) -{ - m_frameRateController->setMaxFramesPending(maxFramesPending); -} - -void CCScheduler::setSwapBuffersCompleteSupported(bool supported) -{ - m_frameRateController->setSwapBuffersCompleteSupported(supported); -} - -void CCScheduler::didSwapBuffersComplete() -{ - TRACE_EVENT0("cc", "CCScheduler::didSwapBuffersComplete"); - m_frameRateController->didFinishFrame(); -} - -void CCScheduler::didLoseContext() -{ - TRACE_EVENT0("cc", "CCScheduler::didLoseContext"); - m_frameRateController->didAbortAllPendingFrames(); - m_stateMachine.didLoseContext(); - processScheduledActions(); -} - -void CCScheduler::didRecreateContext() -{ - TRACE_EVENT0("cc", "CCScheduler::didRecreateContext"); - m_stateMachine.didRecreateContext(); - processScheduledActions(); -} - -void CCScheduler::setTimebaseAndInterval(base::TimeTicks timebase, base::TimeDelta interval) -{ - m_frameRateController->setTimebaseAndInterval(timebase, interval); -} - -base::TimeTicks CCScheduler::anticipatedDrawTime() -{ - return m_frameRateController->nextTickTime(); -} - -void CCScheduler::vsyncTick(bool throttled) -{ - TRACE_EVENT1("cc", "CCScheduler::vsyncTick", "throttled", throttled); - if (!throttled) - m_stateMachine.didEnterVSync(); - processScheduledActions(); - if (!throttled) - m_stateMachine.didLeaveVSync(); -} - -void CCScheduler::processScheduledActions() -{ - // We do not allow processScheduledActions to be recursive. - // The top-level call will iteratively execute the next action for us anyway. - if (m_insideProcessScheduledActions) - return; - - AutoReset markInside(&m_insideProcessScheduledActions, true); - - CCSchedulerStateMachine::Action action = m_stateMachine.nextAction(); - while (action != CCSchedulerStateMachine::ACTION_NONE) { - m_stateMachine.updateState(action); - TRACE_EVENT1("cc", "CCScheduler::processScheduledActions()", "action", action); - - switch (action) { - case CCSchedulerStateMachine::ACTION_NONE: - break; - case CCSchedulerStateMachine::ACTION_BEGIN_FRAME: - m_client->scheduledActionBeginFrame(); - break; - case CCSchedulerStateMachine::ACTION_COMMIT: - m_client->scheduledActionCommit(); - break; - case CCSchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE: { - CCScheduledActionDrawAndSwapResult result = m_client->scheduledActionDrawAndSwapIfPossible(); - m_stateMachine.didDrawIfPossibleCompleted(result.didDraw); - if (result.didSwap) - m_frameRateController->didBeginFrame(); - break; - } - case CCSchedulerStateMachine::ACTION_DRAW_FORCED: { - CCScheduledActionDrawAndSwapResult result = m_client->scheduledActionDrawAndSwapForced(); - if (result.didSwap) - m_frameRateController->didBeginFrame(); - break; - } case CCSchedulerStateMachine::ACTION_BEGIN_CONTEXT_RECREATION: - m_client->scheduledActionBeginContextRecreation(); - break; - case CCSchedulerStateMachine::ACTION_ACQUIRE_LAYER_TEXTURES_FOR_MAIN_THREAD: - m_client->scheduledActionAcquireLayerTexturesForMainThread(); - break; - } - action = m_stateMachine.nextAction(); - } - - // Activate or deactivate the frame rate controller. - m_frameRateController->setActive(m_stateMachine.vsyncCallbackNeeded()); - m_client->didAnticipatedDrawTimeChange(m_frameRateController->nextTickTime()); -} - -} // namespace cc diff --git a/cc/CCScheduler.h b/cc/CCScheduler.h index 1b48307..7032779 100644 --- a/cc/CCScheduler.h +++ b/cc/CCScheduler.h @@ -1,109 +1,6 @@ -// Copyright 2011 The Chromium Authors. All rights reserved. +// Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CCScheduler_h -#define CCScheduler_h - -#include "base/basictypes.h" -#include "base/memory/scoped_ptr.h" -#include "base/time.h" -#include "CCFrameRateController.h" -#include "CCSchedulerStateMachine.h" -#include - -namespace cc { - -class CCThread; - -struct CCScheduledActionDrawAndSwapResult { - CCScheduledActionDrawAndSwapResult() - : didDraw(false) - , didSwap(false) - { - } - CCScheduledActionDrawAndSwapResult(bool didDraw, bool didSwap) - : didDraw(didDraw) - , didSwap(didSwap) - { - } - bool didDraw; - bool didSwap; -}; - -class CCSchedulerClient { -public: - virtual void scheduledActionBeginFrame() = 0; - virtual CCScheduledActionDrawAndSwapResult scheduledActionDrawAndSwapIfPossible() = 0; - virtual CCScheduledActionDrawAndSwapResult scheduledActionDrawAndSwapForced() = 0; - virtual void scheduledActionCommit() = 0; - virtual void scheduledActionBeginContextRecreation() = 0; - virtual void scheduledActionAcquireLayerTexturesForMainThread() = 0; - virtual void didAnticipatedDrawTimeChange(base::TimeTicks) = 0; - -protected: - virtual ~CCSchedulerClient() { } -}; - -class CCScheduler : CCFrameRateControllerClient { -public: - static PassOwnPtr create(CCSchedulerClient* client, scoped_ptr frameRateController) - { - return adoptPtr(new CCScheduler(client, frameRateController.Pass())); - } - - virtual ~CCScheduler(); - - void setCanBeginFrame(bool); - - void setVisible(bool); - void setCanDraw(bool); - - void setNeedsCommit(); - - // Like setNeedsCommit(), but ensures a commit will definitely happen even if we are not visible. - void setNeedsForcedCommit(); - - void setNeedsRedraw(); - - void setMainThreadNeedsLayerTextures(); - - // Like setNeedsRedraw(), but ensures the draw will definitely happen even if we are not visible. - void setNeedsForcedRedraw(); - - void beginFrameComplete(); - void beginFrameAborted(); - - void setMaxFramesPending(int); - void setSwapBuffersCompleteSupported(bool); - void didSwapBuffersComplete(); - - void didLoseContext(); - void didRecreateContext(); - - bool commitPending() const { return m_stateMachine.commitPending(); } - bool redrawPending() const { return m_stateMachine.redrawPending(); } - - void setTimebaseAndInterval(base::TimeTicks timebase, base::TimeDelta interval); - - base::TimeTicks anticipatedDrawTime(); - - // CCFrameRateControllerClient implementation - virtual void vsyncTick(bool throttled) OVERRIDE; - -private: - CCScheduler(CCSchedulerClient*, scoped_ptr); - - void processScheduledActions(); - - CCSchedulerClient* m_client; - scoped_ptr m_frameRateController; - CCSchedulerStateMachine m_stateMachine; - bool m_insideProcessScheduledActions; - - DISALLOW_COPY_AND_ASSIGN(CCScheduler); -}; - -} // namespace cc - -#endif // CCScheduler_h +// Temporary forwarding header +#include "cc/scheduler.h" diff --git a/cc/CCSchedulerStateMachine.cpp b/cc/CCSchedulerStateMachine.cpp deleted file mode 100644 index 3eaf5cd..0000000 --- a/cc/CCSchedulerStateMachine.cpp +++ /dev/null @@ -1,317 +0,0 @@ -// Copyright 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "config.h" - -#include "CCSchedulerStateMachine.h" -#include "base/stringprintf.h" - - -namespace cc { - -CCSchedulerStateMachine::CCSchedulerStateMachine() - : m_commitState(COMMIT_STATE_IDLE) - , m_currentFrameNumber(0) - , m_lastFrameNumberWhereDrawWasCalled(-1) - , m_consecutiveFailedDraws(0) - , m_maximumNumberOfFailedDrawsBeforeDrawIsForced(3) - , m_needsRedraw(false) - , m_needsForcedRedraw(false) - , m_needsForcedRedrawAfterNextCommit(false) - , m_needsCommit(false) - , m_needsForcedCommit(false) - , m_mainThreadNeedsLayerTextures(false) - , m_insideVSync(false) - , m_visible(false) - , m_canBeginFrame(false) - , m_canDraw(false) - , m_drawIfPossibleFailed(false) - , m_textureState(LAYER_TEXTURE_STATE_UNLOCKED) - , m_contextState(CONTEXT_ACTIVE) -{ -} - -std::string CCSchedulerStateMachine::toString() -{ - std::string str; - base::StringAppendF(&str, "m_commitState = %d; ", m_commitState); - base::StringAppendF(&str, "m_currentFrameNumber = %d; ", m_currentFrameNumber); - base::StringAppendF(&str, "m_lastFrameNumberWhereDrawWasCalled = %d; ", m_lastFrameNumberWhereDrawWasCalled); - base::StringAppendF(&str, "m_consecutiveFailedDraws = %d; ", m_consecutiveFailedDraws); - base::StringAppendF(&str, "m_maximumNumberOfFailedDrawsBeforeDrawIsForced = %d; ", m_maximumNumberOfFailedDrawsBeforeDrawIsForced); - base::StringAppendF(&str, "m_needsRedraw = %d; ", m_needsRedraw); - base::StringAppendF(&str, "m_needsForcedRedraw = %d; ", m_needsForcedRedraw); - base::StringAppendF(&str, "m_needsForcedRedrawAfterNextCommit = %d; ", m_needsForcedRedrawAfterNextCommit); - base::StringAppendF(&str, "m_needsCommit = %d; ", m_needsCommit); - base::StringAppendF(&str, "m_needsForcedCommit = %d; ", m_needsForcedCommit); - base::StringAppendF(&str, "m_mainThreadNeedsLayerTextures = %d; ", m_mainThreadNeedsLayerTextures); - base::StringAppendF(&str, "m_insideVSync = %d; ", m_insideVSync); - base::StringAppendF(&str, "m_visible = %d; ", m_visible); - base::StringAppendF(&str, "m_canBeginFrame = %d; ", m_canBeginFrame); - base::StringAppendF(&str, "m_canDraw = %d; ", m_canDraw); - base::StringAppendF(&str, "m_drawIfPossibleFailed = %d; ", m_drawIfPossibleFailed); - base::StringAppendF(&str, "m_textureState = %d; ", m_textureState); - base::StringAppendF(&str, "m_contextState = %d; ", m_contextState); - return str; -} - -bool CCSchedulerStateMachine::hasDrawnThisFrame() const -{ - return m_currentFrameNumber == m_lastFrameNumberWhereDrawWasCalled; -} - -bool CCSchedulerStateMachine::drawSuspendedUntilCommit() const -{ - if (!m_canDraw) - return true; - if (!m_visible) - return true; - if (m_textureState == LAYER_TEXTURE_STATE_ACQUIRED_BY_MAIN_THREAD) - return true; - return false; -} - -bool CCSchedulerStateMachine::scheduledToDraw() const -{ - if (!m_needsRedraw) - return false; - if (drawSuspendedUntilCommit()) - return false; - return true; -} - -bool CCSchedulerStateMachine::shouldDraw() const -{ - if (m_needsForcedRedraw) - return true; - - if (!scheduledToDraw()) - return false; - if (!m_insideVSync) - return false; - if (hasDrawnThisFrame()) - return false; - if (m_contextState != CONTEXT_ACTIVE) - return false; - return true; -} - -bool CCSchedulerStateMachine::shouldAcquireLayerTexturesForMainThread() const -{ - if (!m_mainThreadNeedsLayerTextures) - return false; - if (m_textureState == LAYER_TEXTURE_STATE_UNLOCKED) - return true; - ASSERT(m_textureState == LAYER_TEXTURE_STATE_ACQUIRED_BY_IMPL_THREAD); - // Transfer the lock from impl thread to main thread immediately if the - // impl thread is not even scheduled to draw. Guards against deadlocking. - if (!scheduledToDraw()) - return true; - if (!vsyncCallbackNeeded()) - return true; - return false; -} - -CCSchedulerStateMachine::Action CCSchedulerStateMachine::nextAction() const -{ - if (shouldAcquireLayerTexturesForMainThread()) - return ACTION_ACQUIRE_LAYER_TEXTURES_FOR_MAIN_THREAD; - switch (m_commitState) { - case COMMIT_STATE_IDLE: - if (m_contextState != CONTEXT_ACTIVE && m_needsForcedRedraw) - return ACTION_DRAW_FORCED; - if (m_contextState != CONTEXT_ACTIVE && m_needsForcedCommit) - return ACTION_BEGIN_FRAME; - if (m_contextState == CONTEXT_LOST) - return ACTION_BEGIN_CONTEXT_RECREATION; - if (m_contextState == CONTEXT_RECREATING) - return ACTION_NONE; - if (shouldDraw()) - return m_needsForcedRedraw ? ACTION_DRAW_FORCED : ACTION_DRAW_IF_POSSIBLE; - if (m_needsCommit && ((m_visible && m_canBeginFrame) || m_needsForcedCommit)) - return ACTION_BEGIN_FRAME; - return ACTION_NONE; - - case COMMIT_STATE_FRAME_IN_PROGRESS: - if (shouldDraw()) - return m_needsForcedRedraw ? ACTION_DRAW_FORCED : ACTION_DRAW_IF_POSSIBLE; - return ACTION_NONE; - - case COMMIT_STATE_READY_TO_COMMIT: - return ACTION_COMMIT; - - case COMMIT_STATE_WAITING_FOR_FIRST_DRAW: - if (shouldDraw() || m_contextState == CONTEXT_LOST) - return m_needsForcedRedraw ? ACTION_DRAW_FORCED : ACTION_DRAW_IF_POSSIBLE; - // COMMIT_STATE_WAITING_FOR_FIRST_DRAW wants to enforce a draw. If m_canDraw is false - // or textures are not available, proceed to the next step (similar as in COMMIT_STATE_IDLE). - bool canCommit = m_visible || m_needsForcedCommit; - if (m_needsCommit && canCommit && drawSuspendedUntilCommit()) - return ACTION_BEGIN_FRAME; - return ACTION_NONE; - } - ASSERT_NOT_REACHED(); - return ACTION_NONE; -} - -void CCSchedulerStateMachine::updateState(Action action) -{ - switch (action) { - case ACTION_NONE: - return; - - case ACTION_BEGIN_FRAME: - ASSERT(m_visible || m_needsForcedCommit); - m_commitState = COMMIT_STATE_FRAME_IN_PROGRESS; - m_needsCommit = false; - m_needsForcedCommit = false; - return; - - case ACTION_COMMIT: - m_commitState = COMMIT_STATE_WAITING_FOR_FIRST_DRAW; - m_needsRedraw = true; - if (m_drawIfPossibleFailed) - m_lastFrameNumberWhereDrawWasCalled = -1; - - if (m_needsForcedRedrawAfterNextCommit) { - m_needsForcedRedrawAfterNextCommit = false; - m_needsForcedRedraw = true; - } - - m_textureState = LAYER_TEXTURE_STATE_ACQUIRED_BY_IMPL_THREAD; - return; - - case ACTION_DRAW_FORCED: - case ACTION_DRAW_IF_POSSIBLE: - m_needsRedraw = false; - m_needsForcedRedraw = false; - m_drawIfPossibleFailed = false; - if (m_insideVSync) - m_lastFrameNumberWhereDrawWasCalled = m_currentFrameNumber; - if (m_commitState == COMMIT_STATE_WAITING_FOR_FIRST_DRAW) - m_commitState = COMMIT_STATE_IDLE; - if (m_textureState == LAYER_TEXTURE_STATE_ACQUIRED_BY_IMPL_THREAD) - m_textureState = LAYER_TEXTURE_STATE_UNLOCKED; - return; - - case ACTION_BEGIN_CONTEXT_RECREATION: - ASSERT(m_commitState == COMMIT_STATE_IDLE); - ASSERT(m_contextState == CONTEXT_LOST); - m_contextState = CONTEXT_RECREATING; - return; - - case ACTION_ACQUIRE_LAYER_TEXTURES_FOR_MAIN_THREAD: - m_textureState = LAYER_TEXTURE_STATE_ACQUIRED_BY_MAIN_THREAD; - m_mainThreadNeedsLayerTextures = false; - if (m_commitState != COMMIT_STATE_FRAME_IN_PROGRESS) - m_needsCommit = true; - return; - } -} - -void CCSchedulerStateMachine::setMainThreadNeedsLayerTextures() -{ - ASSERT(!m_mainThreadNeedsLayerTextures); - ASSERT(m_textureState != LAYER_TEXTURE_STATE_ACQUIRED_BY_MAIN_THREAD); - m_mainThreadNeedsLayerTextures = true; -} - -bool CCSchedulerStateMachine::vsyncCallbackNeeded() const -{ - // If we can't draw, don't tick until we are notified that we can draw again. - if (!m_canDraw) - return false; - - if (m_needsForcedRedraw) - return true; - - return m_needsRedraw && m_visible && m_contextState == CONTEXT_ACTIVE; -} - -void CCSchedulerStateMachine::didEnterVSync() -{ - m_insideVSync = true; -} - -void CCSchedulerStateMachine::didLeaveVSync() -{ - m_currentFrameNumber++; - m_insideVSync = false; -} - -void CCSchedulerStateMachine::setVisible(bool visible) -{ - m_visible = visible; -} - -void CCSchedulerStateMachine::setNeedsRedraw() -{ - m_needsRedraw = true; -} - -void CCSchedulerStateMachine::setNeedsForcedRedraw() -{ - m_needsForcedRedraw = true; -} - -void CCSchedulerStateMachine::didDrawIfPossibleCompleted(bool success) -{ - m_drawIfPossibleFailed = !success; - if (m_drawIfPossibleFailed) { - m_needsRedraw = true; - m_needsCommit = true; - m_consecutiveFailedDraws++; - if (m_consecutiveFailedDraws >= m_maximumNumberOfFailedDrawsBeforeDrawIsForced) { - m_consecutiveFailedDraws = 0; - // We need to force a draw, but it doesn't make sense to do this until - // we've committed and have new textures. - m_needsForcedRedrawAfterNextCommit = true; - } - } else - m_consecutiveFailedDraws = 0; -} - -void CCSchedulerStateMachine::setNeedsCommit() -{ - m_needsCommit = true; -} - -void CCSchedulerStateMachine::setNeedsForcedCommit() -{ - m_needsForcedCommit = true; -} - -void CCSchedulerStateMachine::beginFrameComplete() -{ - ASSERT(m_commitState == COMMIT_STATE_FRAME_IN_PROGRESS); - m_commitState = COMMIT_STATE_READY_TO_COMMIT; -} - -void CCSchedulerStateMachine::beginFrameAborted() -{ - ASSERT(m_commitState == COMMIT_STATE_FRAME_IN_PROGRESS); - m_commitState = COMMIT_STATE_IDLE; - setNeedsCommit(); -} - -void CCSchedulerStateMachine::didLoseContext() -{ - if (m_contextState == CONTEXT_LOST || m_contextState == CONTEXT_RECREATING) - return; - m_contextState = CONTEXT_LOST; -} - -void CCSchedulerStateMachine::didRecreateContext() -{ - ASSERT(m_contextState == CONTEXT_RECREATING); - m_contextState = CONTEXT_ACTIVE; - setNeedsCommit(); -} - -void CCSchedulerStateMachine::setMaximumNumberOfFailedDrawsBeforeDrawIsForced(int numDraws) -{ - m_maximumNumberOfFailedDrawsBeforeDrawIsForced = numDraws; -} - -} diff --git a/cc/CCSchedulerStateMachine.h b/cc/CCSchedulerStateMachine.h index 092231f..a585284 100644 --- a/cc/CCSchedulerStateMachine.h +++ b/cc/CCSchedulerStateMachine.h @@ -1,161 +1,6 @@ -// Copyright 2011 The Chromium Authors. All rights reserved. +// Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CCSchedulerStateMachine_h -#define CCSchedulerStateMachine_h - -#include - -#include "base/basictypes.h" - -namespace cc { - -// The CCSchedulerStateMachine decides how to coordinate main thread activites -// like painting/running javascript with rendering and input activities on the -// impl thread. -// -// The state machine tracks internal state but is also influenced by external state. -// Internal state includes things like whether a frame has been requested, while -// external state includes things like the current time being near to the vblank time. -// -// The scheduler seperates "what to do next" from the updating of its internal state to -// make testing cleaner. -class CCSchedulerStateMachine { -public: - CCSchedulerStateMachine(); - - enum CommitState { - COMMIT_STATE_IDLE, - COMMIT_STATE_FRAME_IN_PROGRESS, - COMMIT_STATE_READY_TO_COMMIT, - COMMIT_STATE_WAITING_FOR_FIRST_DRAW, - }; - - enum TextureState { - LAYER_TEXTURE_STATE_UNLOCKED, - LAYER_TEXTURE_STATE_ACQUIRED_BY_MAIN_THREAD, - LAYER_TEXTURE_STATE_ACQUIRED_BY_IMPL_THREAD, - }; - - enum ContextState { - CONTEXT_ACTIVE, - CONTEXT_LOST, - CONTEXT_RECREATING, - }; - - bool commitPending() const - { - return m_commitState != COMMIT_STATE_IDLE; - } - - bool redrawPending() const { return m_needsRedraw; } - - enum Action { - ACTION_NONE, - ACTION_BEGIN_FRAME, - ACTION_COMMIT, - ACTION_DRAW_IF_POSSIBLE, - ACTION_DRAW_FORCED, - ACTION_BEGIN_CONTEXT_RECREATION, - ACTION_ACQUIRE_LAYER_TEXTURES_FOR_MAIN_THREAD, - }; - Action nextAction() const; - void updateState(Action); - - // Indicates whether the scheduler needs a vsync callback in order to make - // progress. - bool vsyncCallbackNeeded() const; - - // Indicates that the system has entered and left a vsync callback. - // The scheduler will not draw more than once in a given vsync callback. - void didEnterVSync(); - void didLeaveVSync(); - - // Indicates whether the LayerTreeHostImpl is visible. - void setVisible(bool); - - // Indicates that a redraw is required, either due to the impl tree changing - // or the screen being damaged and simply needing redisplay. - void setNeedsRedraw(); - - // As setNeedsRedraw(), but ensures the draw will definitely happen even if - // we are not visible. - void setNeedsForcedRedraw(); - - // Indicates whether ACTION_DRAW_IF_POSSIBLE drew to the screen or not. - void didDrawIfPossibleCompleted(bool success); - - // Indicates that a new commit flow needs to be performed, either to pull - // updates from the main thread to the impl, or to push deltas from the impl - // thread to main. - void setNeedsCommit(); - - // As setNeedsCommit(), but ensures the beginFrame will definitely happen even if - // we are not visible. - void setNeedsForcedCommit(); - - // Call this only in response to receiving an ACTION_BEGIN_FRAME - // from nextState. Indicates that all painting is complete. - void beginFrameComplete(); - - // Call this only in response to receiving an ACTION_BEGIN_FRAME - // from nextState if the client rejects the beginFrame message. - void beginFrameAborted(); - - // Request exclusive access to the textures that back single buffered - // layers on behalf of the main thread. Upon acqusition, - // ACTION_DRAW_IF_POSSIBLE will not draw until the main thread releases the - // textures to the impl thread by committing the layers. - void setMainThreadNeedsLayerTextures(); - - // Indicates whether we can successfully begin a frame at this time. - void setCanBeginFrame(bool can) { m_canBeginFrame = can; } - - // Indicates whether drawing would, at this time, make sense. - // canDraw can be used to supress flashes or checkerboarding - // when such behavior would be undesirable. - void setCanDraw(bool can) { m_canDraw = can; } - - void didLoseContext(); - void didRecreateContext(); - - // Exposed for testing purposes. - void setMaximumNumberOfFailedDrawsBeforeDrawIsForced(int); - - std::string toString(); - -protected: - bool shouldDrawForced() const; - bool drawSuspendedUntilCommit() const; - bool scheduledToDraw() const; - bool shouldDraw() const; - bool shouldAcquireLayerTexturesForMainThread() const; - bool hasDrawnThisFrame() const; - - CommitState m_commitState; - - int m_currentFrameNumber; - int m_lastFrameNumberWhereDrawWasCalled; - int m_consecutiveFailedDraws; - int m_maximumNumberOfFailedDrawsBeforeDrawIsForced; - bool m_needsRedraw; - bool m_needsForcedRedraw; - bool m_needsForcedRedrawAfterNextCommit; - bool m_needsCommit; - bool m_needsForcedCommit; - bool m_mainThreadNeedsLayerTextures; - bool m_insideVSync; - bool m_visible; - bool m_canBeginFrame; - bool m_canDraw; - bool m_drawIfPossibleFailed; - TextureState m_textureState; - ContextState m_contextState; - - DISALLOW_COPY_AND_ASSIGN(CCSchedulerStateMachine); -}; - -} - -#endif // CCSchedulerStateMachine_h +// Temporary forwarding header +#include "cc/scheduler_state_machine.h" diff --git a/cc/CCScopedTexture.cpp b/cc/CCScopedTexture.cpp deleted file mode 100644 index d43ebe3..0000000 --- a/cc/CCScopedTexture.cpp +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "config.h" - -#include "CCScopedTexture.h" - -namespace cc { - -CCScopedTexture::CCScopedTexture(CCResourceProvider* resourceProvider) - : m_resourceProvider(resourceProvider) -{ - ASSERT(m_resourceProvider); -} - -CCScopedTexture::~CCScopedTexture() -{ - free(); -} - -bool CCScopedTexture::allocate(int pool, const IntSize& size, GC3Denum format, CCResourceProvider::TextureUsageHint hint) -{ - ASSERT(!id()); - ASSERT(!size.isEmpty()); - - setDimensions(size, format); - setId(m_resourceProvider->createResource(pool, size, format, hint)); - -#if !ASSERT_DISABLED - m_allocateThreadIdentifier = base::PlatformThread::CurrentId(); -#endif - - return id(); -} - -void CCScopedTexture::free() -{ - if (id()) { - ASSERT(m_allocateThreadIdentifier == base::PlatformThread::CurrentId()); - m_resourceProvider->deleteResource(id()); - } - setId(0); -} - -void CCScopedTexture::leak() -{ - setId(0); -} - -} diff --git a/cc/CCScopedTexture.h b/cc/CCScopedTexture.h index a5b615c..faa11f5 100644 --- a/cc/CCScopedTexture.h +++ b/cc/CCScopedTexture.h @@ -2,45 +2,5 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CCScopedTexture_h -#define CCScopedTexture_h - -#include "base/basictypes.h" -#include "CCTexture.h" - -#if !ASSERT_DISABLED -#include "base/threading/platform_thread.h" -#endif - -namespace cc { - -class CCScopedTexture : protected CCTexture { -public: - static PassOwnPtr create(CCResourceProvider* resourceProvider) { return adoptPtr(new CCScopedTexture(resourceProvider)); } - virtual ~CCScopedTexture(); - - using CCTexture::id; - using CCTexture::size; - using CCTexture::format; - using CCTexture::bytes; - - bool allocate(int pool, const IntSize&, GC3Denum format, CCResourceProvider::TextureUsageHint); - void free(); - void leak(); - -protected: - explicit CCScopedTexture(CCResourceProvider*); - -private: - CCResourceProvider* m_resourceProvider; - -#if !ASSERT_DISABLED - base::PlatformThreadId m_allocateThreadIdentifier; -#endif - - DISALLOW_COPY_AND_ASSIGN(CCScopedTexture); -}; - -} - -#endif +// Temporary forwarding header +#include "cc/scoped_texture.h" diff --git a/cc/CCScopedThreadProxy.cpp b/cc/CCScopedThreadProxy.cpp deleted file mode 100644 index c2f1b13..0000000 --- a/cc/CCScopedThreadProxy.cpp +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "config.h" - -#include "CCScopedThreadProxy.h" - -namespace cc { - -CCScopedThreadProxy::CCScopedThreadProxy(CCThread* targetThread) - : m_targetThread(targetThread) - , m_shutdown(false) -{ -} - -CCScopedThreadProxy::~CCScopedThreadProxy() -{ -} - -} diff --git a/cc/CCScopedThreadProxy.h b/cc/CCScopedThreadProxy.h index 802046d..20a6b07 100644 --- a/cc/CCScopedThreadProxy.h +++ b/cc/CCScopedThreadProxy.h @@ -1,74 +1,6 @@ -// Copyright 2011 The Chromium Authors. All rights reserved. +// Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CCScopedThreadProxy_h -#define CCScopedThreadProxy_h - -#include "CCThreadTask.h" -#include "base/threading/platform_thread.h" -#include -#include -#include - -namespace cc { - -// This class is a proxy used to post tasks to an target thread from any other thread. The proxy may be shut down at -// any point from the target thread after which no more tasks posted to the proxy will run. In other words, all -// tasks posted via a proxy are scoped to the lifecycle of the proxy. Use this when posting tasks to an object that -// might die with tasks in flight. -// -// The proxy must be created and shut down from the target thread, tasks may be posted from any thread. -// -// Implementation note: Unlike ScopedRunnableMethodFactory in Chromium, pending tasks are not cancelled by actually -// destroying the proxy. Instead each pending task holds a reference to the proxy to avoid maintaining an explicit -// list of outstanding tasks. -class CCScopedThreadProxy : public ThreadSafeRefCounted { -public: - static PassRefPtr create(CCThread* targetThread) - { - ASSERT(base::PlatformThread::CurrentId() == targetThread->threadID()); - return adoptRef(new CCScopedThreadProxy(targetThread)); - } - - ~CCScopedThreadProxy(); - - // Can be called from any thread. Posts a task to the target thread that runs unless - // shutdown() is called before it runs. - void postTask(PassOwnPtr task) - { - ref(); - m_targetThread->postTask(createCCThreadTask(this, &CCScopedThreadProxy::runTaskIfNotShutdown, task)); - } - - void shutdown() - { - ASSERT(base::PlatformThread::CurrentId() == m_targetThread->threadID()); - ASSERT(!m_shutdown); - m_shutdown = true; - } - -private: - explicit CCScopedThreadProxy(CCThread* targetThread); - - void runTaskIfNotShutdown(PassOwnPtr popTask) - { - OwnPtr task = popTask; - // If our shutdown flag is set, it's possible that m_targetThread has already been destroyed so don't - // touch it. - if (m_shutdown) { - deref(); - return; - } - ASSERT(base::PlatformThread::CurrentId() == m_targetThread->threadID()); - task->performTask(); - deref(); - } - - CCThread* m_targetThread; - bool m_shutdown; // Only accessed on the target thread -}; - -} - -#endif +// Temporary forwarding header +#include "cc/scoped_thread_proxy.h" diff --git a/cc/CCScrollbarAnimationController.cpp b/cc/CCScrollbarAnimationController.cpp deleted file mode 100644 index 89f74cb..0000000 --- a/cc/CCScrollbarAnimationController.cpp +++ /dev/null @@ -1,97 +0,0 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "config.h" - -#include "CCScrollbarAnimationController.h" - -#include "CCScrollbarLayerImpl.h" -#include - -#if OS(ANDROID) -#include "CCScrollbarAnimationControllerLinearFade.h" -#endif - -namespace cc { - -#if OS(ANDROID) -PassOwnPtr CCScrollbarAnimationController::create(CCLayerImpl* scrollLayer) -{ - static const double fadeoutDelay = 0.3; - static const double fadeoutLength = 0.3; - return CCScrollbarAnimationControllerLinearFade::create(scrollLayer, fadeoutDelay, fadeoutLength); -} -#else -PassOwnPtr CCScrollbarAnimationController::create(CCLayerImpl* scrollLayer) -{ - return adoptPtr(new CCScrollbarAnimationController(scrollLayer)); -} -#endif - -CCScrollbarAnimationController::CCScrollbarAnimationController(CCLayerImpl* scrollLayer) - : m_horizontalScrollbarLayer(0) - , m_verticalScrollbarLayer(0) -{ - CCScrollbarAnimationController::updateScrollOffsetAtTime(scrollLayer, 0); -} - -CCScrollbarAnimationController::~CCScrollbarAnimationController() -{ -} - -bool CCScrollbarAnimationController::animate(double) -{ - return false; -} - -void CCScrollbarAnimationController::didPinchGestureBegin() -{ - didPinchGestureBeginAtTime(monotonicallyIncreasingTime()); -} - -void CCScrollbarAnimationController::didPinchGestureUpdate() -{ - didPinchGestureUpdateAtTime(monotonicallyIncreasingTime()); -} - -void CCScrollbarAnimationController::didPinchGestureEnd() -{ - didPinchGestureEndAtTime(monotonicallyIncreasingTime()); -} - -void CCScrollbarAnimationController::updateScrollOffset(CCLayerImpl* scrollLayer) -{ - updateScrollOffsetAtTime(scrollLayer, monotonicallyIncreasingTime()); -} - -IntSize CCScrollbarAnimationController::getScrollLayerBounds(const CCLayerImpl* scrollLayer) -{ - if (!scrollLayer->children().size()) - return IntSize(); - // Copy & paste from CCLayerTreeHostImpl... - // FIXME: Hardcoding the first child here is weird. Think of - // a cleaner way to get the contentBounds on the Impl side. - return scrollLayer->children()[0]->bounds(); -} - -void CCScrollbarAnimationController::updateScrollOffsetAtTime(CCLayerImpl* scrollLayer, double) -{ - m_currentPos = scrollLayer->scrollPosition() + scrollLayer->scrollDelta(); - m_totalSize = getScrollLayerBounds(scrollLayer); - m_maximum = scrollLayer->maxScrollPosition(); - - if (m_horizontalScrollbarLayer) { - m_horizontalScrollbarLayer->setCurrentPos(m_currentPos.x()); - m_horizontalScrollbarLayer->setTotalSize(m_totalSize.width()); - m_horizontalScrollbarLayer->setMaximum(m_maximum.width()); - } - - if (m_verticalScrollbarLayer) { - m_verticalScrollbarLayer->setCurrentPos(m_currentPos.y()); - m_verticalScrollbarLayer->setTotalSize(m_totalSize.height()); - m_verticalScrollbarLayer->setMaximum(m_maximum.height()); - } -} - -} // namespace cc diff --git a/cc/CCScrollbarAnimationController.h b/cc/CCScrollbarAnimationController.h index bb387d7..584c8dc 100644 --- a/cc/CCScrollbarAnimationController.h +++ b/cc/CCScrollbarAnimationController.h @@ -2,63 +2,5 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CCScrollbarAnimationController_h -#define CCScrollbarAnimationController_h - -#include "FloatPoint.h" -#include "IntSize.h" -#include - -namespace cc { - -class CCLayerImpl; -class CCScrollbarLayerImpl; - -// This abstract class represents the compositor-side analogy of ScrollbarAnimator. -// Individual platforms should subclass it to provide specialized implementation. -class CCScrollbarAnimationController { -public: - // Implemented by subclass. - static PassOwnPtr create(CCLayerImpl* scrollLayer); - - virtual ~CCScrollbarAnimationController(); - - virtual bool animate(double monotonicTime); - void didPinchGestureBegin(); - void didPinchGestureUpdate(); - void didPinchGestureEnd(); - void updateScrollOffset(CCLayerImpl* scrollLayer); - - void setHorizontalScrollbarLayer(CCScrollbarLayerImpl* layer) { m_horizontalScrollbarLayer = layer; } - CCScrollbarLayerImpl* horizontalScrollbarLayer() const { return m_horizontalScrollbarLayer; } - - void setVerticalScrollbarLayer(CCScrollbarLayerImpl* layer) { m_verticalScrollbarLayer = layer; } - CCScrollbarLayerImpl* verticalScrollbarLayer() const { return m_verticalScrollbarLayer; } - - FloatPoint currentPos() const { return m_currentPos; } - IntSize totalSize() const { return m_totalSize; } - IntSize maximum() const { return m_maximum; } - - virtual void didPinchGestureBeginAtTime(double monotonicTime) { } - virtual void didPinchGestureUpdateAtTime(double monotonicTime) { } - virtual void didPinchGestureEndAtTime(double monotonicTime) { } - virtual void updateScrollOffsetAtTime(CCLayerImpl* scrollLayer, double monotonicTime); - -protected: - explicit CCScrollbarAnimationController(CCLayerImpl* scrollLayer); - -private: - static IntSize getScrollLayerBounds(const CCLayerImpl*); - - // Beware of dangling pointer. Always update these during tree synchronization. - CCScrollbarLayerImpl* m_horizontalScrollbarLayer; - CCScrollbarLayerImpl* m_verticalScrollbarLayer; - - FloatPoint m_currentPos; - IntSize m_totalSize; - IntSize m_maximum; -}; - -} // namespace cc - -#endif // CCScrollbarAnimationController_h +// Temporary forwarding header +#include "cc/scrollbar_animation_controller.h" diff --git a/cc/CCScrollbarAnimationControllerLinearFade.cpp b/cc/CCScrollbarAnimationControllerLinearFade.cpp deleted file mode 100644 index 95ad198..0000000 --- a/cc/CCScrollbarAnimationControllerLinearFade.cpp +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "config.h" - -#include "CCScrollbarAnimationControllerLinearFade.h" - -#include "CCScrollbarLayerImpl.h" - -namespace cc { - -PassOwnPtr CCScrollbarAnimationControllerLinearFade::create(CCLayerImpl* scrollLayer, double fadeoutDelay, double fadeoutLength) -{ - return adoptPtr(new CCScrollbarAnimationControllerLinearFade(scrollLayer, fadeoutDelay, fadeoutLength)); -} - -CCScrollbarAnimationControllerLinearFade::CCScrollbarAnimationControllerLinearFade(CCLayerImpl* scrollLayer, double fadeoutDelay, double fadeoutLength) - : CCScrollbarAnimationController(scrollLayer) - , m_lastAwakenTime(-100000000) // arbitrary invalid timestamp - , m_pinchGestureInEffect(false) - , m_fadeoutDelay(fadeoutDelay) - , m_fadeoutLength(fadeoutLength) -{ -} - -CCScrollbarAnimationControllerLinearFade::~CCScrollbarAnimationControllerLinearFade() -{ -} - -bool CCScrollbarAnimationControllerLinearFade::animate(double monotonicTime) -{ - float opacity = opacityAtTime(monotonicTime); - if (horizontalScrollbarLayer()) - horizontalScrollbarLayer()->setOpacity(opacity); - if (verticalScrollbarLayer()) - verticalScrollbarLayer()->setOpacity(opacity); - return opacity; -} - -void CCScrollbarAnimationControllerLinearFade::didPinchGestureUpdateAtTime(double) -{ - m_pinchGestureInEffect = true; -} - -void CCScrollbarAnimationControllerLinearFade::didPinchGestureEndAtTime(double monotonicTime) -{ - m_pinchGestureInEffect = false; - m_lastAwakenTime = monotonicTime; -} - -void CCScrollbarAnimationControllerLinearFade::updateScrollOffsetAtTime(CCLayerImpl* scrollLayer, double monotonicTime) -{ - FloatPoint previousPos = currentPos(); - CCScrollbarAnimationController::updateScrollOffsetAtTime(scrollLayer, monotonicTime); - - if (previousPos == currentPos()) - return; - - m_lastAwakenTime = monotonicTime; -} - -float CCScrollbarAnimationControllerLinearFade::opacityAtTime(double monotonicTime) -{ - if (m_pinchGestureInEffect) - return 1; - - double delta = monotonicTime - m_lastAwakenTime; - - if (delta <= m_fadeoutDelay) - return 1; - if (delta < m_fadeoutDelay + m_fadeoutLength) - return (m_fadeoutDelay + m_fadeoutLength - delta) / m_fadeoutLength; - return 0; -} - -} // namespace cc diff --git a/cc/CCScrollbarAnimationControllerLinearFade.h b/cc/CCScrollbarAnimationControllerLinearFade.h index 749dca5..7ce0e02 100644 --- a/cc/CCScrollbarAnimationControllerLinearFade.h +++ b/cc/CCScrollbarAnimationControllerLinearFade.h @@ -2,38 +2,5 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CCScrollbarAnimationControllerLinearFade_h -#define CCScrollbarAnimationControllerLinearFade_h - -#include "CCScrollbarAnimationController.h" - -namespace cc { - -class CCScrollbarAnimationControllerLinearFade : public CCScrollbarAnimationController { -public: - static PassOwnPtr create(CCLayerImpl* scrollLayer, double fadeoutDelay, double fadeoutLength); - - virtual ~CCScrollbarAnimationControllerLinearFade(); - - virtual bool animate(double monotonicTime) OVERRIDE; - - virtual void didPinchGestureUpdateAtTime(double monotonicTime) OVERRIDE; - virtual void didPinchGestureEndAtTime(double monotonicTime) OVERRIDE; - virtual void updateScrollOffsetAtTime(CCLayerImpl* scrollLayer, double monotonicTime) OVERRIDE; - -protected: - CCScrollbarAnimationControllerLinearFade(CCLayerImpl* scrollLayer, double fadeoutDelay, double fadeoutLength); - -private: - float opacityAtTime(double monotonicTime); - - double m_lastAwakenTime; - bool m_pinchGestureInEffect; - - double m_fadeoutDelay; - double m_fadeoutLength; -}; - -} // namespace cc - -#endif // CCScrollbarAnimationControllerLinearFade_h +// Temporary forwarding header +#include "cc/scrollbar_animation_controller_linear_fade.h" diff --git a/cc/CCScrollbarGeometryFixedThumb.cpp b/cc/CCScrollbarGeometryFixedThumb.cpp deleted file mode 100644 index dc55829..0000000 --- a/cc/CCScrollbarGeometryFixedThumb.cpp +++ /dev/null @@ -1,94 +0,0 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "config.h" - -#include "CCScrollbarGeometryFixedThumb.h" - -#include -#include -#include - -using WebKit::WebRect; -using WebKit::WebScrollbar; -using WebKit::WebScrollbarThemeGeometry; - -namespace cc { - -PassOwnPtr CCScrollbarGeometryFixedThumb::create(PassOwnPtr geometry) -{ - return adoptPtr(new CCScrollbarGeometryFixedThumb(geometry)); -} - -CCScrollbarGeometryFixedThumb::~CCScrollbarGeometryFixedThumb() -{ -} - -void CCScrollbarGeometryFixedThumb::update(WebScrollbar* scrollbar) -{ - int length = CCScrollbarGeometryStub::thumbLength(scrollbar); - - if (scrollbar->orientation() == WebScrollbar::Horizontal) - m_thumbSize = IntSize(length, scrollbar->size().height); - else - m_thumbSize = IntSize(scrollbar->size().width, length); -} - -WebScrollbarThemeGeometry* CCScrollbarGeometryFixedThumb::clone() const -{ - CCScrollbarGeometryFixedThumb* geometry = new CCScrollbarGeometryFixedThumb(adoptPtr(CCScrollbarGeometryStub::clone())); - geometry->m_thumbSize = m_thumbSize; - return geometry; -} - -int CCScrollbarGeometryFixedThumb::thumbLength(WebScrollbar* scrollbar) -{ - if (scrollbar->orientation() == WebScrollbar::Horizontal) - return m_thumbSize.width(); - return m_thumbSize.height(); -} - -int CCScrollbarGeometryFixedThumb::thumbPosition(WebScrollbar* scrollbar) -{ - if (scrollbar->enabled()) { - float size = scrollbar->maximum(); - if (!size) - return 1; - int value = std::min(std::max(0, scrollbar->value()), scrollbar->maximum()); - float pos = (trackLength(scrollbar) - thumbLength(scrollbar)) * value / size; - return static_cast(floorf((pos < 1 && pos > 0) ? 1 : pos)); - } - return 0; -} -void CCScrollbarGeometryFixedThumb::splitTrack(WebScrollbar* scrollbar, const WebRect& unconstrainedTrackRect, WebRect& beforeThumbRect, WebRect& thumbRect, WebRect& afterThumbRect) -{ - // This is a reimplementation of ScrollbarThemeComposite::splitTrack. - // Because the WebScrollbarThemeGeometry functions call down to native - // ScrollbarThemeComposite code which uses ScrollbarThemeComposite virtual - // helpers, there's no way to override a helper like thumbLength from - // the WebScrollbarThemeGeometry level. So, these three functions - // (splitTrack, thumbPosition, thumbLength) are copied here so that the - // WebScrollbarThemeGeometry helper functions are used instead and - // a fixed size thumbLength can be used. - - WebRect trackRect = constrainTrackRectToTrackPieces(scrollbar, unconstrainedTrackRect); - int thickness = scrollbar->orientation() == WebScrollbar::Horizontal ? scrollbar->size().height : scrollbar->size().width; - int thumbPos = thumbPosition(scrollbar); - if (scrollbar->orientation() == WebScrollbar::Horizontal) { - thumbRect = WebRect(trackRect.x + thumbPos, trackRect.y + (trackRect.height - thickness) / 2, thumbLength(scrollbar), thickness); - beforeThumbRect = WebRect(trackRect.x, trackRect.y, thumbPos + thumbRect.width / 2, trackRect.height); - afterThumbRect = WebRect(trackRect.x + beforeThumbRect.width, trackRect.y, trackRect.x + trackRect.width - beforeThumbRect.x - beforeThumbRect.width, trackRect.height); - } else { - thumbRect = WebRect(trackRect.x + (trackRect.width - thickness) / 2, trackRect.y + thumbPos, thickness, thumbLength(scrollbar)); - beforeThumbRect = WebRect(trackRect.x, trackRect.y, trackRect.width, thumbPos + thumbRect.height / 2); - afterThumbRect = WebRect(trackRect.x, trackRect.y + beforeThumbRect.height, trackRect.width, trackRect.y + trackRect.height - beforeThumbRect.y - beforeThumbRect.height); - } -} - -CCScrollbarGeometryFixedThumb::CCScrollbarGeometryFixedThumb(PassOwnPtr geometry) - : CCScrollbarGeometryStub(geometry) -{ -} - -} diff --git a/cc/CCScrollbarGeometryFixedThumb.h b/cc/CCScrollbarGeometryFixedThumb.h index fe0db12..e19a679 100644 --- a/cc/CCScrollbarGeometryFixedThumb.h +++ b/cc/CCScrollbarGeometryFixedThumb.h @@ -2,38 +2,5 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CCScrollbarGeometryFixedThumb_h -#define CCScrollbarGeometryFixedThumb_h - -#include "CCScrollbarGeometryStub.h" -#include "IntSize.h" - -namespace cc { - -// This scrollbar geometry class behaves exactly like a normal geometry except -// it always returns a fixed thumb length. This allows a page to zoom (changing -// the total size of the scrollable area, changing the thumb length) while not -// requiring the thumb resource to be repainted. -class CCScrollbarGeometryFixedThumb : public CCScrollbarGeometryStub { -public: - static PassOwnPtr create(PassOwnPtr); - virtual ~CCScrollbarGeometryFixedThumb(); - - // Update thumb length from scrollbar - void update(WebKit::WebScrollbar*); - - // WebScrollbarThemeGeometry interface - virtual WebKit::WebScrollbarThemeGeometry* clone() const OVERRIDE; - virtual int thumbLength(WebKit::WebScrollbar*) OVERRIDE; - virtual int thumbPosition(WebKit::WebScrollbar*) OVERRIDE; - virtual void splitTrack(WebKit::WebScrollbar*, const WebKit::WebRect& track, WebKit::WebRect& startTrack, WebKit::WebRect& thumb, WebKit::WebRect& endTrack) OVERRIDE; - -private: - explicit CCScrollbarGeometryFixedThumb(PassOwnPtr); - - IntSize m_thumbSize; -}; - -} - -#endif +// Temporary forwarding header +#include "cc/scrollbar_geometry_fixed_thumb.h" diff --git a/cc/CCScrollbarGeometryStub.cpp b/cc/CCScrollbarGeometryStub.cpp deleted file mode 100644 index 7be7b15..0000000 --- a/cc/CCScrollbarGeometryStub.cpp +++ /dev/null @@ -1,109 +0,0 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "config.h" - -#include "CCScrollbarGeometryStub.h" - -using WebKit::WebRect; -using WebKit::WebScrollbar; -using WebKit::WebScrollbarThemeGeometry; - -namespace cc { - -CCScrollbarGeometryStub::CCScrollbarGeometryStub(PassOwnPtr geometry) - : m_geometry(geometry) -{ -} - -CCScrollbarGeometryStub::~CCScrollbarGeometryStub() -{ -} - -WebScrollbarThemeGeometry* CCScrollbarGeometryStub::clone() const -{ - return m_geometry->clone(); -} - -int CCScrollbarGeometryStub::thumbPosition(WebScrollbar* scrollbar) -{ - return m_geometry->thumbPosition(scrollbar); -} - -int CCScrollbarGeometryStub::thumbLength(WebScrollbar* scrollbar) -{ - return m_geometry->thumbLength(scrollbar); -} - -int CCScrollbarGeometryStub::trackPosition(WebScrollbar* scrollbar) -{ - return m_geometry->trackPosition(scrollbar); -} - -int CCScrollbarGeometryStub::trackLength(WebScrollbar* scrollbar) -{ - return m_geometry->trackLength(scrollbar); -} - -bool CCScrollbarGeometryStub::hasButtons(WebScrollbar* scrollbar) -{ - return m_geometry->hasButtons(scrollbar); -} - -bool CCScrollbarGeometryStub::hasThumb(WebScrollbar* scrollbar) -{ - return m_geometry->hasThumb(scrollbar); -} - -WebRect CCScrollbarGeometryStub::trackRect(WebScrollbar* scrollbar) -{ - return m_geometry->trackRect(scrollbar); -} - -WebRect CCScrollbarGeometryStub::thumbRect(WebScrollbar* scrollbar) -{ - return m_geometry->thumbRect(scrollbar); -} - -int CCScrollbarGeometryStub::minimumThumbLength(WebScrollbar* scrollbar) -{ - return m_geometry->minimumThumbLength(scrollbar); -} - -int CCScrollbarGeometryStub::scrollbarThickness(WebScrollbar* scrollbar) -{ - return m_geometry->scrollbarThickness(scrollbar); -} - -WebRect CCScrollbarGeometryStub::backButtonStartRect(WebScrollbar* scrollbar) -{ - return m_geometry->backButtonStartRect(scrollbar); -} - -WebRect CCScrollbarGeometryStub::backButtonEndRect(WebScrollbar* scrollbar) -{ - return m_geometry->backButtonEndRect(scrollbar); -} - -WebRect CCScrollbarGeometryStub::forwardButtonStartRect(WebScrollbar* scrollbar) -{ - return m_geometry->forwardButtonStartRect(scrollbar); -} - -WebRect CCScrollbarGeometryStub::forwardButtonEndRect(WebScrollbar* scrollbar) -{ - return m_geometry->forwardButtonEndRect(scrollbar); -} - -WebRect CCScrollbarGeometryStub::constrainTrackRectToTrackPieces(WebScrollbar* scrollbar, const WebRect& rect) -{ - return m_geometry->constrainTrackRectToTrackPieces(scrollbar, rect); -} - -void CCScrollbarGeometryStub::splitTrack(WebScrollbar* scrollbar, const WebRect& unconstrainedTrackRect, WebRect& beforeThumbRect, WebRect& thumbRect, WebRect& afterThumbRect) -{ - m_geometry->splitTrack(scrollbar, unconstrainedTrackRect, beforeThumbRect, thumbRect, afterThumbRect); -} - -} diff --git a/cc/CCScrollbarGeometryStub.h b/cc/CCScrollbarGeometryStub.h index 0d23a4e..3d0d81a5 100644 --- a/cc/CCScrollbarGeometryStub.h +++ b/cc/CCScrollbarGeometryStub.h @@ -2,51 +2,5 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CCScrollbarGeometryStub_h -#define CCScrollbarGeometryStub_h - -#include -#include -#include - -namespace cc { - -// This subclass wraps an existing scrollbar geometry class so that -// another class can derive from it and override specific functions, while -// passing through the remaining ones. -class CCScrollbarGeometryStub : public WebKit::WebScrollbarThemeGeometry { -public: - virtual ~CCScrollbarGeometryStub(); - - // Allow derived classes to update themselves from a scrollbar. - void update(WebKit::WebScrollbar*) { } - - // WebScrollbarThemeGeometry interface - virtual WebKit::WebScrollbarThemeGeometry* clone() const OVERRIDE; - virtual int thumbPosition(WebKit::WebScrollbar*) OVERRIDE; - virtual int thumbLength(WebKit::WebScrollbar*) OVERRIDE; - virtual int trackPosition(WebKit::WebScrollbar*) OVERRIDE; - virtual int trackLength(WebKit::WebScrollbar*) OVERRIDE; - virtual bool hasButtons(WebKit::WebScrollbar*) OVERRIDE; - virtual bool hasThumb(WebKit::WebScrollbar*) OVERRIDE; - virtual WebKit::WebRect trackRect(WebKit::WebScrollbar*) OVERRIDE; - virtual WebKit::WebRect thumbRect(WebKit::WebScrollbar*) OVERRIDE; - virtual int minimumThumbLength(WebKit::WebScrollbar*) OVERRIDE; - virtual int scrollbarThickness(WebKit::WebScrollbar*) OVERRIDE; - virtual WebKit::WebRect backButtonStartRect(WebKit::WebScrollbar*) OVERRIDE; - virtual WebKit::WebRect backButtonEndRect(WebKit::WebScrollbar*) OVERRIDE; - virtual WebKit::WebRect forwardButtonStartRect(WebKit::WebScrollbar*) OVERRIDE; - virtual WebKit::WebRect forwardButtonEndRect(WebKit::WebScrollbar*) OVERRIDE; - virtual WebKit::WebRect constrainTrackRectToTrackPieces(WebKit::WebScrollbar*, const WebKit::WebRect&) OVERRIDE; - virtual void splitTrack(WebKit::WebScrollbar*, const WebKit::WebRect& track, WebKit::WebRect& startTrack, WebKit::WebRect& thumb, WebKit::WebRect& endTrack) OVERRIDE; - -protected: - explicit CCScrollbarGeometryStub(PassOwnPtr); - -private: - OwnPtr m_geometry; -}; - -} - -#endif +// Temporary forwarding header +#include "cc/scrollbar_geometry_stub.h" diff --git a/cc/CCScrollbarLayerImpl.cpp b/cc/CCScrollbarLayerImpl.cpp deleted file mode 100644 index 8a832e7..0000000 --- a/cc/CCScrollbarLayerImpl.cpp +++ /dev/null @@ -1,206 +0,0 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "config.h" - -#if USE(ACCELERATED_COMPOSITING) - -#include "CCScrollbarLayerImpl.h" - -#include "CCQuadSink.h" -#include "CCScrollbarAnimationController.h" -#include "CCTextureDrawQuad.h" - -using WebKit::WebRect; -using WebKit::WebScrollbar; - -namespace cc { - -scoped_ptr CCScrollbarLayerImpl::create(int id) -{ - return make_scoped_ptr(new CCScrollbarLayerImpl(id)); -} - -CCScrollbarLayerImpl::CCScrollbarLayerImpl(int id) - : CCLayerImpl(id) - , m_scrollbar(this) - , m_backTrackResourceId(0) - , m_foreTrackResourceId(0) - , m_thumbResourceId(0) - , m_scrollbarOverlayStyle(WebScrollbar::ScrollbarOverlayStyleDefault) - , m_orientation(WebScrollbar::Horizontal) - , m_controlSize(WebScrollbar::RegularScrollbar) - , m_pressedPart(WebScrollbar::NoPart) - , m_hoveredPart(WebScrollbar::NoPart) - , m_isScrollableAreaActive(false) - , m_isScrollViewScrollbar(false) - , m_enabled(false) - , m_isCustomScrollbar(false) - , m_isOverlayScrollbar(false) -{ -} - -CCScrollbarLayerImpl::~CCScrollbarLayerImpl() -{ -} - -void CCScrollbarLayerImpl::setScrollbarGeometry(PassOwnPtr geometry) -{ - m_geometry = geometry; -} - -void CCScrollbarLayerImpl::setScrollbarData(WebScrollbar* scrollbar) -{ - m_scrollbarOverlayStyle = scrollbar->scrollbarOverlayStyle(); - m_orientation = scrollbar->orientation(); - m_controlSize = scrollbar->controlSize(); - m_pressedPart = scrollbar->pressedPart(); - m_hoveredPart = scrollbar->hoveredPart(); - m_isScrollableAreaActive = scrollbar->isScrollableAreaActive(); - m_isScrollViewScrollbar = scrollbar->isScrollViewScrollbar(); - m_enabled = scrollbar->enabled(); - m_isCustomScrollbar = scrollbar->isCustomScrollbar(); - m_isOverlayScrollbar = scrollbar->isOverlay(); - - scrollbar->getTickmarks(m_tickmarks); - - m_geometry->update(scrollbar); -} - -static FloatRect toUVRect(const WebRect& r, const IntRect& bounds) -{ - return FloatRect(static_cast(r.x) / bounds.width(), static_cast(r.y) / bounds.height(), - static_cast(r.width) / bounds.width(), static_cast(r.height) / bounds.height()); -} - -void CCScrollbarLayerImpl::appendQuads(CCQuadSink& quadSink, CCAppendQuadsData& appendQuadsData) -{ - bool premultipledAlpha = false; - bool flipped = false; - FloatRect uvRect(0, 0, 1, 1); - IntRect boundsRect(IntPoint(), bounds()); - IntRect contentBoundsRect(IntPoint(), contentBounds()); - - CCSharedQuadState* sharedQuadState = quadSink.useSharedQuadState(createSharedQuadState()); - appendDebugBorderQuad(quadSink, sharedQuadState, appendQuadsData); - - WebRect thumbRect, backTrackRect, foreTrackRect; - m_geometry->splitTrack(&m_scrollbar, m_geometry->trackRect(&m_scrollbar), backTrackRect, thumbRect, foreTrackRect); - if (!m_geometry->hasThumb(&m_scrollbar)) - thumbRect = WebRect(); - - if (m_thumbResourceId && !thumbRect.isEmpty()) { - scoped_ptr quad = CCTextureDrawQuad::create(sharedQuadState, layerRectToContentRect(thumbRect), m_thumbResourceId, premultipledAlpha, uvRect, flipped); - quad->setNeedsBlending(); - quadSink.append(quad.PassAs(), appendQuadsData); - } - - if (!m_backTrackResourceId) - return; - - // We only paint the track in two parts if we were given a texture for the forward track part. - if (m_foreTrackResourceId && !foreTrackRect.isEmpty()) - quadSink.append(CCTextureDrawQuad::create(sharedQuadState, layerRectToContentRect(foreTrackRect), m_foreTrackResourceId, premultipledAlpha, toUVRect(foreTrackRect, boundsRect), flipped).PassAs(), appendQuadsData); - - // Order matters here: since the back track texture is being drawn to the entire contents rect, we must append it after the thumb and - // fore track quads. The back track texture contains (and displays) the buttons. - if (!contentBoundsRect.isEmpty()) - quadSink.append(CCTextureDrawQuad::create(sharedQuadState, IntRect(contentBoundsRect), m_backTrackResourceId, premultipledAlpha, uvRect, flipped).PassAs(), appendQuadsData); -} - -void CCScrollbarLayerImpl::didLoseContext() -{ - m_backTrackResourceId = 0; - m_foreTrackResourceId = 0; - m_thumbResourceId = 0; -} - -bool CCScrollbarLayerImpl::CCScrollbar::isOverlay() const -{ - return m_owner->m_isOverlayScrollbar; -} - -int CCScrollbarLayerImpl::CCScrollbar::value() const -{ - return m_owner->m_currentPos; -} - -WebKit::WebPoint CCScrollbarLayerImpl::CCScrollbar::location() const -{ - return WebKit::WebPoint(); -} - -WebKit::WebSize CCScrollbarLayerImpl::CCScrollbar::size() const -{ - return WebKit::WebSize(m_owner->bounds().width(), m_owner->bounds().height()); -} - -bool CCScrollbarLayerImpl::CCScrollbar::enabled() const -{ - return m_owner->m_enabled; -} - -int CCScrollbarLayerImpl::CCScrollbar::maximum() const -{ - return m_owner->m_maximum; -} - -int CCScrollbarLayerImpl::CCScrollbar::totalSize() const -{ - return m_owner->m_totalSize; -} - -bool CCScrollbarLayerImpl::CCScrollbar::isScrollViewScrollbar() const -{ - return m_owner->m_isScrollViewScrollbar; -} - -bool CCScrollbarLayerImpl::CCScrollbar::isScrollableAreaActive() const -{ - return m_owner->m_isScrollableAreaActive; -} - -void CCScrollbarLayerImpl::CCScrollbar::getTickmarks(WebKit::WebVector& tickmarks) const -{ - tickmarks = m_owner->m_tickmarks; -} - -WebScrollbar::ScrollbarControlSize CCScrollbarLayerImpl::CCScrollbar::controlSize() const -{ - return m_owner->m_controlSize; -} - -WebScrollbar::ScrollbarPart CCScrollbarLayerImpl::CCScrollbar::pressedPart() const -{ - return m_owner->m_pressedPart; -} - -WebScrollbar::ScrollbarPart CCScrollbarLayerImpl::CCScrollbar::hoveredPart() const -{ - return m_owner->m_hoveredPart; -} - -WebScrollbar::ScrollbarOverlayStyle CCScrollbarLayerImpl::CCScrollbar::scrollbarOverlayStyle() const -{ - return m_owner->m_scrollbarOverlayStyle; -} - -WebScrollbar::Orientation CCScrollbarLayerImpl::CCScrollbar::orientation() const -{ - return m_owner->m_orientation; -} - -bool CCScrollbarLayerImpl::CCScrollbar::isCustomScrollbar() const -{ - return m_owner->m_isCustomScrollbar; -} - -const char* CCScrollbarLayerImpl::layerTypeAsString() const -{ - return "ScrollbarLayer"; -} - -} - -#endif // USE(ACCELERATED_COMPOSITING) diff --git a/cc/CCScrollbarLayerImpl.h b/cc/CCScrollbarLayerImpl.h index e7cf584..69fd3c4 100644 --- a/cc/CCScrollbarLayerImpl.h +++ b/cc/CCScrollbarLayerImpl.h @@ -2,111 +2,5 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CCScrollbarLayerImpl_h -#define CCScrollbarLayerImpl_h - -#if USE(ACCELERATED_COMPOSITING) - -#include "CCLayerImpl.h" -#include "CCScrollbarGeometryFixedThumb.h" -#include -#include -#include - -namespace cc { - -class ScrollView; - -class CCScrollbarLayerImpl : public CCLayerImpl { -public: - static scoped_ptr create(int id); - virtual ~CCScrollbarLayerImpl(); - - CCScrollbarGeometryFixedThumb* scrollbarGeometry() const { return m_geometry.get(); } - void setScrollbarGeometry(PassOwnPtr); - void setScrollbarData(WebKit::WebScrollbar*); - - void setBackTrackResourceId(CCResourceProvider::ResourceId id) { m_backTrackResourceId = id; } - void setForeTrackResourceId(CCResourceProvider::ResourceId id) { m_foreTrackResourceId = id; } - void setThumbResourceId(CCResourceProvider::ResourceId id) { m_thumbResourceId = id; } - - float currentPos() const { return m_currentPos; } - void setCurrentPos(float currentPos) { m_currentPos = currentPos; } - - int totalSize() const { return m_totalSize; } - void setTotalSize(int totalSize) { m_totalSize = totalSize; } - - int maximum() const { return m_maximum; } - void setMaximum(int maximum) { m_maximum = maximum; } - - WebKit::WebScrollbar::Orientation orientation() const { return m_orientation; } - - virtual void appendQuads(CCQuadSink&, CCAppendQuadsData&) OVERRIDE; - - virtual void didLoseContext() OVERRIDE; - -protected: - explicit CCScrollbarLayerImpl(int id); - -private: - // nested class only to avoid namespace problem - class CCScrollbar : public WebKit::WebScrollbar { - public: - explicit CCScrollbar(CCScrollbarLayerImpl* owner) : m_owner(owner) { } - - // WebScrollbar implementation - virtual bool isOverlay() const; - virtual int value() const; - virtual WebKit::WebPoint location() const; - virtual WebKit::WebSize size() const; - virtual bool enabled() const; - virtual int maximum() const; - virtual int totalSize() const; - virtual bool isScrollViewScrollbar() const; - virtual bool isScrollableAreaActive() const; - virtual void getTickmarks(WebKit::WebVector& tickmarks) const; - virtual WebScrollbar::ScrollbarControlSize controlSize() const; - virtual WebScrollbar::ScrollbarPart pressedPart() const; - virtual WebScrollbar::ScrollbarPart hoveredPart() const; - virtual WebScrollbar::ScrollbarOverlayStyle scrollbarOverlayStyle() const; - virtual WebScrollbar::Orientation orientation() const; - virtual bool isCustomScrollbar() const; - - private: - CCScrollbarLayerImpl* m_owner; - - }; - - virtual const char* layerTypeAsString() const OVERRIDE; - - CCScrollbar m_scrollbar; - - CCResourceProvider::ResourceId m_backTrackResourceId; - CCResourceProvider::ResourceId m_foreTrackResourceId; - CCResourceProvider::ResourceId m_thumbResourceId; - - OwnPtr m_geometry; - - // Data to implement CCScrollbar - WebKit::WebScrollbar::ScrollbarOverlayStyle m_scrollbarOverlayStyle; - WebKit::WebVector m_tickmarks; - WebKit::WebScrollbar::Orientation m_orientation; - WebKit::WebScrollbar::ScrollbarControlSize m_controlSize; - WebKit::WebScrollbar::ScrollbarPart m_pressedPart; - WebKit::WebScrollbar::ScrollbarPart m_hoveredPart; - - float m_currentPos; - int m_totalSize; - int m_maximum; - - bool m_isScrollableAreaActive; - bool m_isScrollViewScrollbar; - bool m_enabled; - bool m_isCustomScrollbar; - bool m_isOverlayScrollbar; -}; - -} -#endif // USE(ACCELERATED_COMPOSITING) - -#endif +// Temporary forwarding header +#include "cc/scrollbar_layer_impl.h" diff --git a/cc/CCSettings.cpp b/cc/CCSettings.cpp deleted file mode 100644 index cfdc258..0000000 --- a/cc/CCSettings.cpp +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "config.h" - -#include "base/command_line.h" -#include "CCSettings.h" -#include "cc/switches.h" - -namespace { -static bool s_perTilePaintingEnabled = false; -static bool s_partialSwapEnabled = false; -static bool s_acceleratedAnimationEnabled = false; -static bool s_pageScalePinchZoomEnabled = false; -} // namespace - -namespace cc { - -bool CCSettings::perTilePaintingEnabled() { return s_perTilePaintingEnabled; } -void CCSettings::setPerTilePaintingEnabled(bool enabled) { s_perTilePaintingEnabled = enabled; } - -bool CCSettings::partialSwapEnabled() { return s_partialSwapEnabled; } -void CCSettings::setPartialSwapEnabled(bool enabled) { s_partialSwapEnabled = enabled; } - -bool CCSettings::acceleratedAnimationEnabled() { return s_acceleratedAnimationEnabled; } -void CCSettings::setAcceleratedAnimationEnabled(bool enabled) { s_acceleratedAnimationEnabled = enabled; } - -bool CCSettings::pageScalePinchZoomEnabled() { return s_pageScalePinchZoomEnabled; } -void CCSettings::setPageScalePinchZoomEnabled(bool enabled) { s_pageScalePinchZoomEnabled = enabled; } - -bool CCSettings::jankInsteadOfCheckerboard() -{ - return CommandLine::ForCurrentProcess()->HasSwitch(switches::kJankInsteadOfCheckerboard); -} - -bool CCSettings::backgroundColorInsteadOfCheckerboard() -{ - return CommandLine::ForCurrentProcess()->HasSwitch(switches::kBackgroundColorInsteadOfCheckerboard); -} - -void CCSettings::reset() -{ - s_perTilePaintingEnabled = false; - s_partialSwapEnabled = false; - s_acceleratedAnimationEnabled = false; - s_pageScalePinchZoomEnabled = false; -} - -} // namespace cc diff --git a/cc/CCSettings.h b/cc/CCSettings.h index cde48ca..af2de40 100644 --- a/cc/CCSettings.h +++ b/cc/CCSettings.h @@ -2,39 +2,5 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CCSettings_h -#define CCSettings_h - -#include "IntSize.h" - -namespace cc { - -// This file is for settings that apply to all compositors. Add settings to -// CCLayerTreeSettings if a ui and renderer compositor might not want the same -// setting. - -class CCSettings { -public: - static bool perTilePaintingEnabled(); - static bool partialSwapEnabled(); - static bool acceleratedAnimationEnabled(); - static bool pageScalePinchZoomEnabled(); - - static bool jankInsteadOfCheckerboard(); - static bool backgroundColorInsteadOfCheckerboard(); - - // These setters should only be used on the main thread before the layer - // renderer is initialized. - static void setPerTilePaintingEnabled(bool); - static void setPartialSwapEnabled(bool); - static void setAcceleratedAnimationEnabled(bool); - static void setPageScalePinchZoomEnabled(bool); - - // These settings are meant to be set only once, and only read thereafter. - // This function is only for resetting settings in tests. - static void reset(); -}; - -} // namespace cc - -#endif // CCSettings_h +// Temporary forwarding header +#include "cc/settings.h" diff --git a/cc/CCSharedQuadState.cpp b/cc/CCSharedQuadState.cpp deleted file mode 100644 index ede07a5..0000000 --- a/cc/CCSharedQuadState.cpp +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "config.h" - -#include "CCSharedQuadState.h" - -#include "FloatQuad.h" - -namespace cc { - -scoped_ptr CCSharedQuadState::create(const WebKit::WebTransformationMatrix& quadTransform, const IntRect& visibleContentRect, const IntRect& clippedRectInTarget, float opacity, bool opaque) -{ - return make_scoped_ptr(new CCSharedQuadState(quadTransform, visibleContentRect, clippedRectInTarget, opacity, opaque)); -} - -CCSharedQuadState::CCSharedQuadState(const WebKit::WebTransformationMatrix& quadTransform, const IntRect& visibleContentRect, const IntRect& clippedRectInTarget, float opacity, bool opaque) - : id(-1) - , quadTransform(quadTransform) - , visibleContentRect(visibleContentRect) - , clippedRectInTarget(clippedRectInTarget) - , opacity(opacity) - , opaque(opaque) -{ -} - -scoped_ptr CCSharedQuadState::copy() const -{ - scoped_ptr copiedState(create(quadTransform, visibleContentRect, clippedRectInTarget, opacity, opaque)); - copiedState->id = id; - return copiedState.Pass(); -} - -} // namespace cc diff --git a/cc/CCSharedQuadState.h b/cc/CCSharedQuadState.h index 0f5e386..c5d50d8 100644 --- a/cc/CCSharedQuadState.h +++ b/cc/CCSharedQuadState.h @@ -2,32 +2,5 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CCSharedQuadState_h -#define CCSharedQuadState_h - -#include "IntRect.h" -#include "base/memory/scoped_ptr.h" -#include - -namespace cc { - -struct CCSharedQuadState { - int id; - - // Transforms from quad's original content space to its target content space. - WebKit::WebTransformationMatrix quadTransform; - // This rect lives in the content space for the quad's originating layer. - IntRect visibleContentRect; - IntRect clippedRectInTarget; - float opacity; - bool opaque; - - static scoped_ptr create(const WebKit::WebTransformationMatrix& quadTransform, const IntRect& visibleContentRect, const IntRect& clippedRectInTarget, float opacity, bool opaque); - CCSharedQuadState(const WebKit::WebTransformationMatrix& quadTransform, const IntRect& visibleContentRect, const IntRect& clippedRectInTarget, float opacity, bool opaque); - - scoped_ptr copy() const; -}; - -} - -#endif +// Temporary forwarding header +#include "cc/shared_quad_state.h" diff --git a/cc/CCSingleThreadProxy.cpp b/cc/CCSingleThreadProxy.cpp deleted file mode 100644 index 7f89cf5..0000000 --- a/cc/CCSingleThreadProxy.cpp +++ /dev/null @@ -1,385 +0,0 @@ -// Copyright 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "config.h" - -#include "CCSingleThreadProxy.h" - -#include "CCDrawQuad.h" -#include "CCGraphicsContext.h" -#include "CCLayerTreeHost.h" -#include "CCTextureUpdateController.h" -#include "CCTimer.h" -#include "TraceEvent.h" -#include - -using namespace WTF; - -namespace cc { - -scoped_ptr CCSingleThreadProxy::create(CCLayerTreeHost* layerTreeHost) -{ - return make_scoped_ptr(new CCSingleThreadProxy(layerTreeHost)).PassAs(); -} - -CCSingleThreadProxy::CCSingleThreadProxy(CCLayerTreeHost* layerTreeHost) - : m_layerTreeHost(layerTreeHost) - , m_contextLost(false) - , m_rendererInitialized(false) - , m_nextFrameIsNewlyCommittedFrame(false) - , m_totalCommitCount(0) -{ - TRACE_EVENT0("cc", "CCSingleThreadProxy::CCSingleThreadProxy"); - ASSERT(CCProxy::isMainThread()); -} - -void CCSingleThreadProxy::start() -{ - DebugScopedSetImplThread impl; - m_layerTreeHostImpl = m_layerTreeHost->createLayerTreeHostImpl(this); -} - -CCSingleThreadProxy::~CCSingleThreadProxy() -{ - TRACE_EVENT0("cc", "CCSingleThreadProxy::~CCSingleThreadProxy"); - ASSERT(CCProxy::isMainThread()); - ASSERT(!m_layerTreeHostImpl.get() && !m_layerTreeHost); // make sure stop() got called. -} - -bool CCSingleThreadProxy::compositeAndReadback(void *pixels, const IntRect& rect) -{ - TRACE_EVENT0("cc", "CCSingleThreadProxy::compositeAndReadback"); - ASSERT(CCProxy::isMainThread()); - - if (!commitAndComposite()) - return false; - - m_layerTreeHostImpl->readback(pixels, rect); - - if (m_layerTreeHostImpl->isContextLost()) - return false; - - m_layerTreeHostImpl->swapBuffers(); - didSwapFrame(); - - return true; -} - -void CCSingleThreadProxy::startPageScaleAnimation(const IntSize& targetPosition, bool useAnchor, float scale, double duration) -{ - m_layerTreeHostImpl->startPageScaleAnimation(targetPosition, useAnchor, scale, monotonicallyIncreasingTime(), duration); -} - -void CCSingleThreadProxy::finishAllRendering() -{ - ASSERT(CCProxy::isMainThread()); - { - DebugScopedSetImplThread impl; - m_layerTreeHostImpl->finishAllRendering(); - } -} - -bool CCSingleThreadProxy::isStarted() const -{ - ASSERT(CCProxy::isMainThread()); - return m_layerTreeHostImpl.get(); -} - -bool CCSingleThreadProxy::initializeContext() -{ - ASSERT(CCProxy::isMainThread()); - scoped_ptr context = m_layerTreeHost->createContext(); - if (!context.get()) - return false; - m_contextBeforeInitialization = context.Pass(); - return true; -} - -void CCSingleThreadProxy::setSurfaceReady() -{ - // Scheduling is controlled by the embedder in the single thread case, so nothing to do. -} - -void CCSingleThreadProxy::setVisible(bool visible) -{ - DebugScopedSetImplThread impl; - m_layerTreeHostImpl->setVisible(visible); -} - -bool CCSingleThreadProxy::initializeRenderer() -{ - ASSERT(CCProxy::isMainThread()); - ASSERT(m_contextBeforeInitialization.get()); - { - DebugScopedSetImplThread impl; - bool ok = m_layerTreeHostImpl->initializeRenderer(m_contextBeforeInitialization.Pass()); - if (ok) { - m_rendererInitialized = true; - m_RendererCapabilitiesForMainThread = m_layerTreeHostImpl->rendererCapabilities(); - } - - return ok; - } -} - -bool CCSingleThreadProxy::recreateContext() -{ - TRACE_EVENT0("cc", "CCSingleThreadProxy::recreateContext"); - ASSERT(CCProxy::isMainThread()); - ASSERT(m_contextLost); - - scoped_ptr context = m_layerTreeHost->createContext(); - if (!context.get()) - return false; - - bool initialized; - { - DebugScopedSetMainThreadBlocked mainThreadBlocked; - DebugScopedSetImplThread impl; - if (!m_layerTreeHostImpl->contentsTexturesPurged()) - m_layerTreeHost->deleteContentsTexturesOnImplThread(m_layerTreeHostImpl->resourceProvider()); - initialized = m_layerTreeHostImpl->initializeRenderer(context.Pass()); - if (initialized) { - m_RendererCapabilitiesForMainThread = m_layerTreeHostImpl->rendererCapabilities(); - } - } - - if (initialized) - m_contextLost = false; - - return initialized; -} - -void CCSingleThreadProxy::renderingStats(CCRenderingStats* stats) -{ - stats->totalCommitTimeInSeconds = m_totalCommitTime.InSecondsF(); - stats->totalCommitCount = m_totalCommitCount; - m_layerTreeHostImpl->renderingStats(stats); -} - -const RendererCapabilities& CCSingleThreadProxy::rendererCapabilities() const -{ - ASSERT(m_rendererInitialized); - // Note: this gets called during the commit by the "impl" thread - return m_RendererCapabilitiesForMainThread; -} - -void CCSingleThreadProxy::loseContext() -{ - ASSERT(CCProxy::isMainThread()); - m_layerTreeHost->didLoseContext(); - m_contextLost = true; -} - -void CCSingleThreadProxy::setNeedsAnimate() -{ - // CCThread-only feature - ASSERT_NOT_REACHED(); -} - -void CCSingleThreadProxy::doCommit(PassOwnPtr queue) -{ - ASSERT(CCProxy::isMainThread()); - // Commit immediately - { - DebugScopedSetMainThreadBlocked mainThreadBlocked; - DebugScopedSetImplThread impl; - - base::TimeTicks startTime = base::TimeTicks::HighResNow(); - m_layerTreeHostImpl->beginCommit(); - - m_layerTreeHost->beginCommitOnImplThread(m_layerTreeHostImpl.get()); - - OwnPtr updateController = - CCTextureUpdateController::create( - NULL, - CCProxy::mainThread(), - queue, - m_layerTreeHostImpl->resourceProvider(), - m_layerTreeHostImpl->resourceProvider()->textureUploader()); - updateController->finalize(); - - m_layerTreeHost->finishCommitOnImplThread(m_layerTreeHostImpl.get()); - - m_layerTreeHostImpl->commitComplete(); - -#if !ASSERT_DISABLED - // In the single-threaded case, the scroll deltas should never be - // touched on the impl layer tree. - scoped_ptr scrollInfo = m_layerTreeHostImpl->processScrollDeltas(); - ASSERT(!scrollInfo->scrolls.size()); -#endif - - base::TimeTicks endTime = base::TimeTicks::HighResNow(); - m_totalCommitTime += endTime - startTime; - m_totalCommitCount++; - } - m_layerTreeHost->commitComplete(); - m_nextFrameIsNewlyCommittedFrame = true; -} - -void CCSingleThreadProxy::setNeedsCommit() -{ - ASSERT(CCProxy::isMainThread()); - m_layerTreeHost->scheduleComposite(); -} - -void CCSingleThreadProxy::setNeedsRedraw() -{ - // FIXME: Once we move render_widget scheduling into this class, we can - // treat redraw requests more efficiently than commitAndRedraw requests. - m_layerTreeHostImpl->setFullRootLayerDamage(); - setNeedsCommit(); -} - -bool CCSingleThreadProxy::commitRequested() const -{ - return false; -} - -void CCSingleThreadProxy::didAddAnimation() -{ -} - -size_t CCSingleThreadProxy::maxPartialTextureUpdates() const -{ - return std::numeric_limits::max(); -} - -void CCSingleThreadProxy::stop() -{ - TRACE_EVENT0("cc", "CCSingleThreadProxy::stop"); - ASSERT(CCProxy::isMainThread()); - { - DebugScopedSetMainThreadBlocked mainThreadBlocked; - DebugScopedSetImplThread impl; - - if (!m_layerTreeHostImpl->contentsTexturesPurged()) - m_layerTreeHost->deleteContentsTexturesOnImplThread(m_layerTreeHostImpl->resourceProvider()); - m_layerTreeHostImpl.reset(); - } - m_layerTreeHost = 0; -} - -void CCSingleThreadProxy::setNeedsRedrawOnImplThread() -{ - m_layerTreeHost->scheduleComposite(); -} - -void CCSingleThreadProxy::setNeedsCommitOnImplThread() -{ - m_layerTreeHost->scheduleComposite(); -} - -void CCSingleThreadProxy::postAnimationEventsToMainThreadOnImplThread(scoped_ptr events, double wallClockTime) -{ - ASSERT(CCProxy::isImplThread()); - DebugScopedSetMainThread main; - m_layerTreeHost->setAnimationEvents(events.Pass(), wallClockTime); -} - -void CCSingleThreadProxy::releaseContentsTexturesOnImplThread() -{ - ASSERT(isImplThread()); - m_layerTreeHost->reduceContentsTexturesMemoryOnImplThread(0, m_layerTreeHostImpl->resourceProvider()); -} - -// Called by the legacy scheduling path (e.g. where render_widget does the scheduling) -void CCSingleThreadProxy::compositeImmediately() -{ - if (commitAndComposite()) { - m_layerTreeHostImpl->swapBuffers(); - didSwapFrame(); - } -} - -void CCSingleThreadProxy::forceSerializeOnSwapBuffers() -{ - { - DebugScopedSetImplThread impl; - if (m_rendererInitialized) - m_layerTreeHostImpl->renderer()->doNoOp(); - } -} - -void CCSingleThreadProxy::onSwapBuffersCompleteOnImplThread() -{ - ASSERT_NOT_REACHED(); -} - -bool CCSingleThreadProxy::commitAndComposite() -{ - ASSERT(CCProxy::isMainThread()); - - if (!m_layerTreeHost->initializeRendererIfNeeded()) - return false; - - // Unlink any texture backings that were deleted - CCPrioritizedTextureManager::BackingVector evictedContentsTexturesBackings; - { - DebugScopedSetImplThread implThread; - m_layerTreeHost->getEvictedContentTexturesBackings(evictedContentsTexturesBackings); - } - m_layerTreeHost->unlinkEvictedContentTexturesBackings(evictedContentsTexturesBackings); - { - DebugScopedSetImplThreadAndMainThreadBlocked implAndMainBlocked; - m_layerTreeHost->deleteEvictedContentTexturesBackings(); - } - - OwnPtr queue = adoptPtr(new CCTextureUpdateQueue); - m_layerTreeHost->updateLayers(*(queue.get()), m_layerTreeHostImpl->memoryAllocationLimitBytes()); - - if (m_layerTreeHostImpl->contentsTexturesPurged()) - m_layerTreeHostImpl->resetContentsTexturesPurged(); - - m_layerTreeHost->willCommit(); - doCommit(queue.release()); - bool result = doComposite(); - m_layerTreeHost->didBeginFrame(); - return result; -} - -bool CCSingleThreadProxy::doComposite() -{ - ASSERT(!m_contextLost); - { - DebugScopedSetImplThread impl; - - if (!m_layerTreeHostImpl->visible()) - return false; - - double monotonicTime = monotonicallyIncreasingTime(); - double wallClockTime = currentTime(); - m_layerTreeHostImpl->animate(monotonicTime, wallClockTime); - - // We guard prepareToDraw() with canDraw() because it always returns a valid frame, so can only - // be used when such a frame is possible. Since drawLayers() depends on the result of - // prepareToDraw(), it is guarded on canDraw() as well. - if (!m_layerTreeHostImpl->canDraw()) - return false; - - CCLayerTreeHostImpl::FrameData frame; - m_layerTreeHostImpl->prepareToDraw(frame); - m_layerTreeHostImpl->drawLayers(frame); - m_layerTreeHostImpl->didDrawAllLayers(frame); - } - - if (m_layerTreeHostImpl->isContextLost()) { - m_contextLost = true; - m_layerTreeHost->didLoseContext(); - return false; - } - - return true; -} - -void CCSingleThreadProxy::didSwapFrame() -{ - if (m_nextFrameIsNewlyCommittedFrame) { - m_nextFrameIsNewlyCommittedFrame = false; - m_layerTreeHost->didCommitAndDrawFrame(); - } -} - -} diff --git a/cc/CCSingleThreadProxy.h b/cc/CCSingleThreadProxy.h index 979dbb3..4a6f21e 100644 --- a/cc/CCSingleThreadProxy.h +++ b/cc/CCSingleThreadProxy.h @@ -1,134 +1,6 @@ -// Copyright 2011 The Chromium Authors. All rights reserved. +// Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CCSingleThreadProxy_h -#define CCSingleThreadProxy_h - -#include "CCAnimationEvents.h" -#include "CCLayerTreeHostImpl.h" -#include "CCProxy.h" -#include -#include - -namespace cc { - -class CCLayerTreeHost; - -class CCSingleThreadProxy : public CCProxy, CCLayerTreeHostImplClient { -public: - static scoped_ptr create(CCLayerTreeHost*); - virtual ~CCSingleThreadProxy(); - - // CCProxy implementation - virtual bool compositeAndReadback(void *pixels, const IntRect&) OVERRIDE; - virtual void startPageScaleAnimation(const IntSize& targetPosition, bool useAnchor, float scale, double duration) OVERRIDE; - virtual void finishAllRendering() OVERRIDE; - virtual bool isStarted() const OVERRIDE; - virtual bool initializeContext() OVERRIDE; - virtual void setSurfaceReady() OVERRIDE; - virtual void setVisible(bool) OVERRIDE; - virtual bool initializeRenderer() OVERRIDE; - virtual bool recreateContext() OVERRIDE; - virtual void renderingStats(CCRenderingStats*) OVERRIDE; - virtual const RendererCapabilities& rendererCapabilities() const OVERRIDE; - virtual void loseContext() OVERRIDE; - virtual void setNeedsAnimate() OVERRIDE; - virtual void setNeedsCommit() OVERRIDE; - virtual void setNeedsRedraw() OVERRIDE; - virtual bool commitRequested() const OVERRIDE; - virtual void didAddAnimation() OVERRIDE; - virtual void start() OVERRIDE; - virtual void stop() OVERRIDE; - virtual size_t maxPartialTextureUpdates() const OVERRIDE; - virtual void acquireLayerTextures() OVERRIDE { } - virtual void forceSerializeOnSwapBuffers() OVERRIDE; - - // CCLayerTreeHostImplClient implementation - virtual void didLoseContextOnImplThread() OVERRIDE { } - virtual void onSwapBuffersCompleteOnImplThread() OVERRIDE; - virtual void onVSyncParametersChanged(double monotonicTimebase, double intervalInSeconds) OVERRIDE { } - virtual void onCanDrawStateChanged(bool canDraw) OVERRIDE { } - virtual void setNeedsRedrawOnImplThread() OVERRIDE; - virtual void setNeedsCommitOnImplThread() OVERRIDE; - virtual void postAnimationEventsToMainThreadOnImplThread(scoped_ptr, double wallClockTime) OVERRIDE; - virtual void releaseContentsTexturesOnImplThread() OVERRIDE; - - // Called by the legacy path where RenderWidget does the scheduling. - void compositeImmediately(); - -private: - explicit CCSingleThreadProxy(CCLayerTreeHost*); - - bool commitAndComposite(); - void doCommit(PassOwnPtr); - bool doComposite(); - void didSwapFrame(); - - // Accessed on main thread only. - CCLayerTreeHost* m_layerTreeHost; - bool m_contextLost; - - // Holds on to the context between initializeContext() and initializeRenderer() calls. Shouldn't - // be used for anything else. - scoped_ptr m_contextBeforeInitialization; - - // Used on the CCThread, but checked on main thread during initialization/shutdown. - scoped_ptr m_layerTreeHostImpl; - bool m_rendererInitialized; - RendererCapabilities m_RendererCapabilitiesForMainThread; - - bool m_nextFrameIsNewlyCommittedFrame; - - base::TimeDelta m_totalCommitTime; - size_t m_totalCommitCount; -}; - -// For use in the single-threaded case. In debug builds, it pretends that the -// code is running on the impl thread to satisfy assertion checks. -class DebugScopedSetImplThread { -public: - DebugScopedSetImplThread() - { -#if !ASSERT_DISABLED - CCProxy::setCurrentThreadIsImplThread(true); -#endif - } - ~DebugScopedSetImplThread() - { -#if !ASSERT_DISABLED - CCProxy::setCurrentThreadIsImplThread(false); -#endif - } -}; - -// For use in the single-threaded case. In debug builds, it pretends that the -// code is running on the main thread to satisfy assertion checks. -class DebugScopedSetMainThread { -public: - DebugScopedSetMainThread() - { -#if !ASSERT_DISABLED - CCProxy::setCurrentThreadIsImplThread(false); -#endif - } - ~DebugScopedSetMainThread() - { -#if !ASSERT_DISABLED - CCProxy::setCurrentThreadIsImplThread(true); -#endif - } -}; - -// For use in the single-threaded case. In debug builds, it pretends that the -// code is running on the impl thread and that the main thread is blocked to -// satisfy assertion checks -class DebugScopedSetImplThreadAndMainThreadBlocked { -private: - DebugScopedSetImplThread m_implThread; - DebugScopedSetMainThreadBlocked m_mainThreadBlocked; -}; - -} // namespace cc - -#endif +// Temporary forwarding header +#include "cc/single_thread_proxy.h" diff --git a/cc/CCSolidColorDrawQuad.cpp b/cc/CCSolidColorDrawQuad.cpp deleted file mode 100644 index 157acd9..0000000 --- a/cc/CCSolidColorDrawQuad.cpp +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "config.h" - -#include "CCSolidColorDrawQuad.h" - -namespace cc { - -scoped_ptr CCSolidColorDrawQuad::create(const CCSharedQuadState* sharedQuadState, const IntRect& quadRect, SkColor color) -{ - return make_scoped_ptr(new CCSolidColorDrawQuad(sharedQuadState, quadRect, color)); -} - -CCSolidColorDrawQuad::CCSolidColorDrawQuad(const CCSharedQuadState* sharedQuadState, const IntRect& quadRect, SkColor color) - : CCDrawQuad(sharedQuadState, CCDrawQuad::SolidColor, quadRect) - , m_color(color) -{ - if (SkColorGetA(m_color) < 255) - m_quadOpaque = false; - else - m_opaqueRect = quadRect; -} - -const CCSolidColorDrawQuad* CCSolidColorDrawQuad::materialCast(const CCDrawQuad* quad) -{ - ASSERT(quad->material() == CCDrawQuad::SolidColor); - return static_cast(quad); -} - -} // namespacec cc diff --git a/cc/CCSolidColorDrawQuad.h b/cc/CCSolidColorDrawQuad.h index 6825612..ca00bc9 100644 --- a/cc/CCSolidColorDrawQuad.h +++ b/cc/CCSolidColorDrawQuad.h @@ -2,32 +2,5 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CCSolidColorDrawQuad_h -#define CCSolidColorDrawQuad_h - -#include "CCDrawQuad.h" -#include "SkColor.h" -#include "base/memory/scoped_ptr.h" - -namespace cc { - -#pragma pack(push, 4) - -class CCSolidColorDrawQuad : public CCDrawQuad { -public: - static scoped_ptr create(const CCSharedQuadState*, const IntRect&, SkColor); - - SkColor color() const { return m_color; }; - - static const CCSolidColorDrawQuad* materialCast(const CCDrawQuad*); -private: - CCSolidColorDrawQuad(const CCSharedQuadState*, const IntRect&, SkColor); - - SkColor m_color; -}; - -#pragma pack(pop) - -} - -#endif +// Temporary forwarding header +#include "cc/solid_color_draw_quad.h" diff --git a/cc/CCSolidColorLayerImpl.cpp b/cc/CCSolidColorLayerImpl.cpp deleted file mode 100644 index abf8d48..0000000 --- a/cc/CCSolidColorLayerImpl.cpp +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "config.h" - -#if USE(ACCELERATED_COMPOSITING) - -#include "CCSolidColorLayerImpl.h" - -#include "CCQuadSink.h" -#include "CCSolidColorDrawQuad.h" -#include - -using namespace std; -using WebKit::WebTransformationMatrix; - -namespace cc { - -CCSolidColorLayerImpl::CCSolidColorLayerImpl(int id) - : CCLayerImpl(id) - , m_tileSize(256) -{ -} - -CCSolidColorLayerImpl::~CCSolidColorLayerImpl() -{ -} - -void CCSolidColorLayerImpl::appendQuads(CCQuadSink& quadSink, CCAppendQuadsData& appendQuadsData) -{ - CCSharedQuadState* sharedQuadState = quadSink.useSharedQuadState(createSharedQuadState()); - appendDebugBorderQuad(quadSink, sharedQuadState, appendQuadsData); - - // We create a series of smaller quads instead of just one large one so that the - // culler can reduce the total pixels drawn. - int width = contentBounds().width(); - int height = contentBounds().height(); - for (int x = 0; x < width; x += m_tileSize) { - for (int y = 0; y < height; y += m_tileSize) { - IntRect solidTileRect(x, y, min(width - x, m_tileSize), min(height - y, m_tileSize)); - quadSink.append(CCSolidColorDrawQuad::create(sharedQuadState, solidTileRect, backgroundColor()).PassAs(), appendQuadsData); - } - } -} - -const char* CCSolidColorLayerImpl::layerTypeAsString() const -{ - return "SolidColorLayer"; -} - -} // namespace cc -#endif // USE(ACCELERATED_COMPOSITING) diff --git a/cc/CCSolidColorLayerImpl.h b/cc/CCSolidColorLayerImpl.h index 72beb25..b763bf7 100644 --- a/cc/CCSolidColorLayerImpl.h +++ b/cc/CCSolidColorLayerImpl.h @@ -2,33 +2,5 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CCSolidColorLayerImpl_h -#define CCSolidColorLayerImpl_h - -#include "CCLayerImpl.h" -#include - -namespace cc { - -class CCSolidColorLayerImpl : public CCLayerImpl { -public: - static scoped_ptr create(int id) - { - return make_scoped_ptr(new CCSolidColorLayerImpl(id)); - } - virtual ~CCSolidColorLayerImpl(); - - virtual void appendQuads(CCQuadSink&, CCAppendQuadsData&) OVERRIDE; - -protected: - explicit CCSolidColorLayerImpl(int id); - -private: - virtual const char* layerTypeAsString() const OVERRIDE; - - const int m_tileSize; -}; - -} - -#endif // CCSolidColorLayerImpl_h +// Temporary forwarding header +#include "cc/solid_color_layer_impl.h" diff --git a/cc/CCStreamVideoDrawQuad.cpp b/cc/CCStreamVideoDrawQuad.cpp deleted file mode 100644 index e92d98a..0000000 --- a/cc/CCStreamVideoDrawQuad.cpp +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "config.h" - -#include "CCStreamVideoDrawQuad.h" - -namespace cc { - -scoped_ptr CCStreamVideoDrawQuad::create(const CCSharedQuadState* sharedQuadState, const IntRect& quadRect, unsigned textureId, const WebKit::WebTransformationMatrix& matrix) -{ - return make_scoped_ptr(new CCStreamVideoDrawQuad(sharedQuadState, quadRect, textureId, matrix)); -} - -CCStreamVideoDrawQuad::CCStreamVideoDrawQuad(const CCSharedQuadState* sharedQuadState, const IntRect& quadRect, unsigned textureId, const WebKit::WebTransformationMatrix& matrix) - : CCDrawQuad(sharedQuadState, CCDrawQuad::StreamVideoContent, quadRect) - , m_textureId(textureId) - , m_matrix(matrix) -{ -} - -const CCStreamVideoDrawQuad* CCStreamVideoDrawQuad::materialCast(const CCDrawQuad* quad) -{ - ASSERT(quad->material() == CCDrawQuad::StreamVideoContent); - return static_cast(quad); -} - -} // namespace cc diff --git a/cc/CCStreamVideoDrawQuad.h b/cc/CCStreamVideoDrawQuad.h index 6a1b6c4..fb996bfa 100644 --- a/cc/CCStreamVideoDrawQuad.h +++ b/cc/CCStreamVideoDrawQuad.h @@ -2,34 +2,5 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CCStreamVideoDrawQuad_h -#define CCStreamVideoDrawQuad_h - -#include "CCDrawQuad.h" -#include "base/memory/scoped_ptr.h" -#include - -namespace cc { - -#pragma pack(push, 4) - -class CCStreamVideoDrawQuad : public CCDrawQuad { -public: - static scoped_ptr create(const CCSharedQuadState*, const IntRect&, unsigned textureId, const WebKit::WebTransformationMatrix&); - - unsigned textureId() const { return m_textureId; } - const WebKit::WebTransformationMatrix& matrix() const { return m_matrix; } - - static const CCStreamVideoDrawQuad* materialCast(const CCDrawQuad*); -private: - CCStreamVideoDrawQuad(const CCSharedQuadState*, const IntRect&, unsigned textureId, const WebKit::WebTransformationMatrix&); - - unsigned m_textureId; - WebKit::WebTransformationMatrix m_matrix; -}; - -#pragma pack(pop) - -} - -#endif +// Temporary forwarding header +#include "cc/stream_video_draw_quad.h" diff --git a/cc/CCTexture.cpp b/cc/CCTexture.cpp deleted file mode 100644 index add8429..0000000 --- a/cc/CCTexture.cpp +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "config.h" - -#include "CCTexture.h" - -namespace cc { - -void CCTexture::setDimensions(const IntSize& size, GC3Denum format) -{ - m_size = size; - m_format = format; -} - -size_t CCTexture::bytes() const -{ - if (m_size.isEmpty()) - return 0u; - - return memorySizeBytes(m_size, m_format); -} - -size_t CCTexture::memorySizeBytes(const IntSize& size, GC3Denum format) -{ - unsigned int componentsPerPixel = 4; - unsigned int bytesPerComponent = 1; - return componentsPerPixel * bytesPerComponent * size.width() * size.height(); -} - -} diff --git a/cc/CCTexture.h b/cc/CCTexture.h index 8d0def3..4f798d0 100644 --- a/cc/CCTexture.h +++ b/cc/CCTexture.h @@ -2,41 +2,5 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CCTexture_h -#define CCTexture_h - -#include "CCResourceProvider.h" -#include "CCTexture.h" -#include "GraphicsContext3D.h" -#include "IntSize.h" - -namespace cc { - -class CCTexture { -public: - CCTexture() : m_id(0) { } - CCTexture(unsigned id, IntSize size, GC3Denum format) - : m_id(id) - , m_size(size) - , m_format(format) { } - - CCResourceProvider::ResourceId id() const { return m_id; } - const IntSize& size() const { return m_size; } - GC3Denum format() const { return m_format; } - - void setId(CCResourceProvider::ResourceId id) { m_id = id; } - void setDimensions(const IntSize&, GC3Denum format); - - size_t bytes() const; - - static size_t memorySizeBytes(const IntSize&, GC3Denum format); - -private: - CCResourceProvider::ResourceId m_id; - IntSize m_size; - GC3Denum m_format; -}; - -} - -#endif +// Temporary forwarding header +#include "cc/texture.h" diff --git a/cc/CCTextureDrawQuad.cpp b/cc/CCTextureDrawQuad.cpp deleted file mode 100644 index db985ad..0000000 --- a/cc/CCTextureDrawQuad.cpp +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "config.h" - -#include "CCTextureDrawQuad.h" - -namespace cc { - -scoped_ptr CCTextureDrawQuad::create(const CCSharedQuadState* sharedQuadState, const IntRect& quadRect, unsigned resourceId, bool premultipliedAlpha, const FloatRect& uvRect, bool flipped) -{ - return make_scoped_ptr(new CCTextureDrawQuad(sharedQuadState, quadRect, resourceId, premultipliedAlpha, uvRect, flipped)); -} - -CCTextureDrawQuad::CCTextureDrawQuad(const CCSharedQuadState* sharedQuadState, const IntRect& quadRect, unsigned resourceId, bool premultipliedAlpha, const FloatRect& uvRect, bool flipped) - : CCDrawQuad(sharedQuadState, CCDrawQuad::TextureContent, quadRect) - , m_resourceId(resourceId) - , m_premultipliedAlpha(premultipliedAlpha) - , m_uvRect(uvRect) - , m_flipped(flipped) -{ -} - -void CCTextureDrawQuad::setNeedsBlending() -{ - m_needsBlending = true; -} - -const CCTextureDrawQuad* CCTextureDrawQuad::materialCast(const CCDrawQuad* quad) -{ - ASSERT(quad->material() == CCDrawQuad::TextureContent); - return static_cast(quad); -} - -} diff --git a/cc/CCTextureDrawQuad.h b/cc/CCTextureDrawQuad.h index daa600f..2ad6600 100644 --- a/cc/CCTextureDrawQuad.h +++ b/cc/CCTextureDrawQuad.h @@ -2,40 +2,5 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CCTextureDrawQuad_h -#define CCTextureDrawQuad_h - -#include "CCDrawQuad.h" -#include "FloatRect.h" -#include "base/memory/scoped_ptr.h" - -namespace cc { - -#pragma pack(push, 4) - -class CCTextureDrawQuad : public CCDrawQuad { -public: - static scoped_ptr create(const CCSharedQuadState*, const IntRect&, unsigned resourceId, bool premultipliedAlpha, const FloatRect& uvRect, bool flipped); - FloatRect uvRect() const { return m_uvRect; } - - unsigned resourceId() const { return m_resourceId; } - bool premultipliedAlpha() const { return m_premultipliedAlpha; } - bool flipped() const { return m_flipped; } - - void setNeedsBlending(); - - static const CCTextureDrawQuad* materialCast(const CCDrawQuad*); -private: - CCTextureDrawQuad(const CCSharedQuadState*, const IntRect&, unsigned resourceId, bool premultipliedAlpha, const FloatRect& uvRect, bool flipped); - - unsigned m_resourceId; - bool m_premultipliedAlpha; - FloatRect m_uvRect; - bool m_flipped; -}; - -#pragma pack(pop) - -} - -#endif +// Temporary forwarding header +#include "cc/texture_draw_quad.h" diff --git a/cc/CCTextureLayerImpl.cpp b/cc/CCTextureLayerImpl.cpp deleted file mode 100644 index 441265f..0000000 --- a/cc/CCTextureLayerImpl.cpp +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "config.h" - -#if USE(ACCELERATED_COMPOSITING) - -#include "CCTextureLayerImpl.h" - -#include "base/stringprintf.h" -#include "CCQuadSink.h" -#include "CCRenderer.h" -#include "CCTextureDrawQuad.h" - -namespace cc { - -CCTextureLayerImpl::CCTextureLayerImpl(int id) - : CCLayerImpl(id) - , m_textureId(0) - , m_externalTextureResource(0) - , m_premultipliedAlpha(true) - , m_flipped(true) - , m_uvRect(0, 0, 1, 1) -{ -} - -CCTextureLayerImpl::~CCTextureLayerImpl() -{ -} - -void CCTextureLayerImpl::willDraw(CCResourceProvider* resourceProvider) -{ - if (!m_textureId) - return; - ASSERT(!m_externalTextureResource); - m_externalTextureResource = resourceProvider->createResourceFromExternalTexture(m_textureId); -} - -void CCTextureLayerImpl::appendQuads(CCQuadSink& quadSink, CCAppendQuadsData& appendQuadsData) -{ - if (!m_externalTextureResource) - return; - - CCSharedQuadState* sharedQuadState = quadSink.useSharedQuadState(createSharedQuadState()); - appendDebugBorderQuad(quadSink, sharedQuadState, appendQuadsData); - - IntRect quadRect(IntPoint(), contentBounds()); - quadSink.append(CCTextureDrawQuad::create(sharedQuadState, quadRect, m_externalTextureResource, m_premultipliedAlpha, m_uvRect, m_flipped).PassAs(), appendQuadsData); -} - -void CCTextureLayerImpl::didDraw(CCResourceProvider* resourceProvider) -{ - if (!m_externalTextureResource) - return; - // FIXME: the following assert will not be true when sending resources to a - // parent compositor. A synchronization scheme (double-buffering or - // pipelining of updates) for the client will need to exist to solve this. - ASSERT(!resourceProvider->inUseByConsumer(m_externalTextureResource)); - resourceProvider->deleteResource(m_externalTextureResource); - m_externalTextureResource = 0; -} - -void CCTextureLayerImpl::dumpLayerProperties(std::string* str, int indent) const -{ - str->append(indentString(indent)); - base::StringAppendF(str, "texture layer texture id: %u premultiplied: %d\n", m_textureId, m_premultipliedAlpha); - CCLayerImpl::dumpLayerProperties(str, indent); -} - -void CCTextureLayerImpl::didLoseContext() -{ - m_textureId = 0; - m_externalTextureResource = 0; -} - -const char* CCTextureLayerImpl::layerTypeAsString() const -{ - return "TextureLayer"; -} - -} - -#endif // USE(ACCELERATED_COMPOSITING) diff --git a/cc/CCTextureLayerImpl.h b/cc/CCTextureLayerImpl.h index ff88ff3..8b05959 100644 --- a/cc/CCTextureLayerImpl.h +++ b/cc/CCTextureLayerImpl.h @@ -2,47 +2,5 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CCTextureLayerImpl_h -#define CCTextureLayerImpl_h - -#include "CCLayerImpl.h" - -namespace cc { - -class CCTextureLayerImpl : public CCLayerImpl { -public: - static scoped_ptr create(int id) - { - return make_scoped_ptr(new CCTextureLayerImpl(id)); - } - virtual ~CCTextureLayerImpl(); - - virtual void willDraw(CCResourceProvider*) OVERRIDE; - virtual void appendQuads(CCQuadSink&, CCAppendQuadsData&) OVERRIDE; - virtual void didDraw(CCResourceProvider*) OVERRIDE; - - virtual void didLoseContext() OVERRIDE; - - virtual void dumpLayerProperties(std::string*, int indent) const OVERRIDE; - - unsigned textureId() const { return m_textureId; } - void setTextureId(unsigned id) { m_textureId = id; } - void setPremultipliedAlpha(bool premultipliedAlpha) { m_premultipliedAlpha = premultipliedAlpha; } - void setFlipped(bool flipped) { m_flipped = flipped; } - void setUVRect(const FloatRect& rect) { m_uvRect = rect; } - -private: - explicit CCTextureLayerImpl(int); - - virtual const char* layerTypeAsString() const OVERRIDE; - - unsigned m_textureId; - CCResourceProvider::ResourceId m_externalTextureResource; - bool m_premultipliedAlpha; - bool m_flipped; - FloatRect m_uvRect; -}; - -} - -#endif // CCTextureLayerImpl_h +// Temporary forwarding header +#include "cc/texture_layer_impl.h" diff --git a/cc/CCTextureUpdateController.cpp b/cc/CCTextureUpdateController.cpp deleted file mode 100644 index 200948d..0000000 --- a/cc/CCTextureUpdateController.cpp +++ /dev/null @@ -1,197 +0,0 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "config.h" - -#include "CCTextureUpdateController.h" - -#include "GraphicsContext3D.h" -#include "TextureCopier.h" -#include "TextureUploader.h" -#include "TraceEvent.h" -#include -#include - -namespace { - -// Number of partial updates we allow. -static const size_t partialTextureUpdatesMax = 12; - -// Measured in seconds. -static const double textureUpdateTickRate = 0.004; - -// Measured in seconds. -static const double uploaderBusyTickRate = 0.001; - -// Flush interval when performing texture uploads. -static const int textureUploadFlushPeriod = 4; - -// Number of blocking update intervals to allow. -static const size_t maxBlockingUpdateIntervals = 4; - -} // anonymous namespace - -namespace cc { - -size_t CCTextureUpdateController::maxPartialTextureUpdates() -{ - return partialTextureUpdatesMax; -} - -size_t CCTextureUpdateController::maxFullUpdatesPerTick(TextureUploader* uploader) -{ - double texturesPerSecond = uploader->estimatedTexturesPerSecond(); - size_t texturesPerTick = floor(textureUpdateTickRate * texturesPerSecond); - return texturesPerTick ? texturesPerTick : 1; -} - -CCTextureUpdateController::CCTextureUpdateController(CCTextureUpdateControllerClient* client, CCThread* thread, PassOwnPtr queue, CCResourceProvider* resourceProvider, TextureUploader* uploader) - : m_client(client) - , m_timer(adoptPtr(new CCTimer(thread, this))) - , m_queue(queue) - , m_resourceProvider(resourceProvider) - , m_uploader(uploader) - , m_textureUpdatesPerTick(maxFullUpdatesPerTick(uploader)) - , m_firstUpdateAttempt(true) -{ -} - -CCTextureUpdateController::~CCTextureUpdateController() -{ -} - -void CCTextureUpdateController::performMoreUpdates( - base::TimeTicks timeLimit) -{ - m_timeLimit = timeLimit; - - // Update already in progress. - if (m_timer->isActive()) - return; - - // Call updateMoreTexturesNow() directly unless it's the first update - // attempt. This ensures that we empty the update queue in a finite - // amount of time. - if (m_firstUpdateAttempt) { - // Post a 0-delay task when no updates were left. When it runs, - // readyToFinalizeTextureUpdates() will be called. - if (!updateMoreTexturesIfEnoughTimeRemaining()) - m_timer->startOneShot(0); - - m_firstUpdateAttempt = false; - } else - updateMoreTexturesNow(); -} - -void CCTextureUpdateController::discardUploadsToEvictedResources() -{ - m_queue->clearUploadsToEvictedResources(); -} - -void CCTextureUpdateController::finalize() -{ - size_t uploadCount = 0; - while (m_queue->fullUploadSize()) { - if (!(uploadCount % textureUploadFlushPeriod) && uploadCount) - m_resourceProvider->shallowFlushIfSupported(); - - m_uploader->uploadTexture( - m_resourceProvider, m_queue->takeFirstFullUpload()); - uploadCount++; - } - - while (m_queue->partialUploadSize()) { - if (!(uploadCount % textureUploadFlushPeriod) && uploadCount) - m_resourceProvider->shallowFlushIfSupported(); - - m_uploader->uploadTexture( - m_resourceProvider, m_queue->takeFirstPartialUpload()); - uploadCount++; - } - - if (uploadCount) - m_resourceProvider->shallowFlushIfSupported(); - - if (m_queue->copySize()) { - TextureCopier* copier = m_resourceProvider->textureCopier(); - while (m_queue->copySize()) - copier->copyTexture(m_queue->takeFirstCopy()); - - // If we've performed any texture copies, we need to insert a flush - // here into the compositor context before letting the main thread - // proceed as it may make draw calls to the source texture of one of - // our copy operations. - copier->flush(); - } -} - -void CCTextureUpdateController::onTimerFired() -{ - if (!updateMoreTexturesIfEnoughTimeRemaining()) - m_client->readyToFinalizeTextureUpdates(); -} - -base::TimeTicks CCTextureUpdateController::now() const -{ - return base::TimeTicks::Now(); -} - -base::TimeDelta CCTextureUpdateController::updateMoreTexturesTime() const -{ - return base::TimeDelta::FromMilliseconds(textureUpdateTickRate * 1000); -} - -size_t CCTextureUpdateController::updateMoreTexturesSize() const -{ - return m_textureUpdatesPerTick; -} - -size_t CCTextureUpdateController::maxBlockingUpdates() const -{ - return updateMoreTexturesSize() * maxBlockingUpdateIntervals; -} - -bool CCTextureUpdateController::updateMoreTexturesIfEnoughTimeRemaining() -{ - // Blocking uploads will increase when we're too aggressive in our upload - // time estimate. We use a different timeout here to prevent unnecessary - // amounts of idle time when blocking uploads have reached the max. - if (m_uploader->numBlockingUploads() >= maxBlockingUpdates()) { - m_timer->startOneShot(uploaderBusyTickRate); - return true; - } - - if (!m_queue->fullUploadSize()) - return false; - - bool hasTimeRemaining = m_timeLimit.is_null() || - this->now() < m_timeLimit - updateMoreTexturesTime(); - if (hasTimeRemaining) - updateMoreTexturesNow(); - - return true; -} - -void CCTextureUpdateController::updateMoreTexturesNow() -{ - size_t uploads = std::min( - m_queue->fullUploadSize(), updateMoreTexturesSize()); - m_timer->startOneShot( - updateMoreTexturesTime().InSecondsF() / updateMoreTexturesSize() * - uploads); - - if (!uploads) - return; - - size_t uploadCount = 0; - while (m_queue->fullUploadSize() && uploadCount < uploads) { - if (!(uploadCount % textureUploadFlushPeriod) && uploadCount) - m_resourceProvider->shallowFlushIfSupported(); - m_uploader->uploadTexture(m_resourceProvider, m_queue->takeFirstFullUpload()); - uploadCount++; - } - m_resourceProvider->shallowFlushIfSupported(); -} - -} diff --git a/cc/CCTextureUpdateController.h b/cc/CCTextureUpdateController.h index 74bb8ca..9c00820 100644 --- a/cc/CCTextureUpdateController.h +++ b/cc/CCTextureUpdateController.h @@ -2,76 +2,5 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CCTextureUpdateController_h -#define CCTextureUpdateController_h - -#include "base/basictypes.h" -#include "base/time.h" -#include "CCTextureUpdateQueue.h" -#include "CCTimer.h" -#include - -namespace cc { - -class TextureUploader; - -class CCTextureUpdateControllerClient { -public: - virtual void readyToFinalizeTextureUpdates() = 0; - -protected: - virtual ~CCTextureUpdateControllerClient() { } -}; - -class CCTextureUpdateController : public CCTimerClient { -public: - static PassOwnPtr create(CCTextureUpdateControllerClient* client, CCThread* thread, PassOwnPtr queue, CCResourceProvider* resourceProvider, TextureUploader* uploader) - { - return adoptPtr(new CCTextureUpdateController(client, thread, queue, resourceProvider, uploader)); - } - static size_t maxPartialTextureUpdates(); - - virtual ~CCTextureUpdateController(); - - // Discard uploads to textures that were evicted on the impl thread. - void discardUploadsToEvictedResources(); - - void performMoreUpdates(base::TimeTicks timeLimit); - void finalize(); - - // CCTimerClient implementation. - virtual void onTimerFired() OVERRIDE; - - // Virtual for testing. - virtual base::TimeTicks now() const; - virtual base::TimeDelta updateMoreTexturesTime() const; - virtual size_t updateMoreTexturesSize() const; - -protected: - CCTextureUpdateController(CCTextureUpdateControllerClient*, CCThread*, PassOwnPtr, CCResourceProvider*, TextureUploader*); - - static size_t maxFullUpdatesPerTick(TextureUploader*); - - size_t maxBlockingUpdates() const; - - // This returns true when there were textures left to update. - bool updateMoreTexturesIfEnoughTimeRemaining(); - void updateMoreTexturesNow(); - - CCTextureUpdateControllerClient* m_client; - OwnPtr m_timer; - OwnPtr m_queue; - bool m_contentsTexturesPurged; - CCResourceProvider* m_resourceProvider; - TextureUploader* m_uploader; - base::TimeTicks m_timeLimit; - size_t m_textureUpdatesPerTick; - bool m_firstUpdateAttempt; - -private: - DISALLOW_COPY_AND_ASSIGN(CCTextureUpdateController); -}; - -} - -#endif // CCTextureUpdateController_h +// Temporary forwarding header +#include "cc/texture_update_controller.h" diff --git a/cc/CCTextureUpdateQueue.cpp b/cc/CCTextureUpdateQueue.cpp deleted file mode 100644 index b5ebdf5..0000000 --- a/cc/CCTextureUpdateQueue.cpp +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "config.h" - -#if USE(ACCELERATED_COMPOSITING) - -#include "CCTextureUpdateQueue.h" - -namespace cc { - -CCTextureUpdateQueue::CCTextureUpdateQueue() -{ -} - -CCTextureUpdateQueue::~CCTextureUpdateQueue() -{ -} - -void CCTextureUpdateQueue::appendFullUpload(TextureUploader::Parameters upload) -{ - m_fullEntries.append(upload); -} - -void CCTextureUpdateQueue::appendPartialUpload(TextureUploader::Parameters upload) -{ - m_partialEntries.append(upload); -} - -void CCTextureUpdateQueue::appendCopy(TextureCopier::Parameters copy) -{ - m_copyEntries.append(copy); -} - -void CCTextureUpdateQueue::clearUploadsToEvictedResources() -{ - clearUploadsToEvictedResources(m_fullEntries); - clearUploadsToEvictedResources(m_partialEntries); -} - -void CCTextureUpdateQueue::clearUploadsToEvictedResources(Deque& entryQueue) -{ - Deque temp; - entryQueue.swap(temp); - while (temp.size()) { - TextureUploader::Parameters upload = temp.takeFirst(); - if (!upload.texture->backingResourceWasEvicted()) - entryQueue.append(upload); - } -} - -TextureUploader::Parameters CCTextureUpdateQueue::takeFirstFullUpload() -{ - return m_fullEntries.takeFirst(); -} - -TextureUploader::Parameters CCTextureUpdateQueue::takeFirstPartialUpload() -{ - return m_partialEntries.takeFirst(); -} - -TextureCopier::Parameters CCTextureUpdateQueue::takeFirstCopy() -{ - return m_copyEntries.takeFirst(); -} - -bool CCTextureUpdateQueue::hasMoreUpdates() const -{ - return m_fullEntries.size() || m_partialEntries.size() || m_copyEntries.size(); -} - -} - -#endif // USE(ACCELERATED_COMPOSITING) diff --git a/cc/CCTextureUpdateQueue.h b/cc/CCTextureUpdateQueue.h index 4cf29338..b3ead95 100644 --- a/cc/CCTextureUpdateQueue.h +++ b/cc/CCTextureUpdateQueue.h @@ -2,46 +2,5 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CCTextureUpdateQueue_h -#define CCTextureUpdateQueue_h - -#include "base/basictypes.h" -#include "TextureCopier.h" -#include "TextureUploader.h" -#include - -namespace cc { - -class CCTextureUpdateQueue { -public: - CCTextureUpdateQueue(); - virtual ~CCTextureUpdateQueue(); - - void appendFullUpload(TextureUploader::Parameters); - void appendPartialUpload(TextureUploader::Parameters); - void appendCopy(TextureCopier::Parameters); - - void clearUploadsToEvictedResources(); - - TextureUploader::Parameters takeFirstFullUpload(); - TextureUploader::Parameters takeFirstPartialUpload(); - TextureCopier::Parameters takeFirstCopy(); - - size_t fullUploadSize() const { return m_fullEntries.size(); } - size_t partialUploadSize() const { return m_partialEntries.size(); } - size_t copySize() const { return m_copyEntries.size(); } - - bool hasMoreUpdates() const; - -private: - void clearUploadsToEvictedResources(Deque& entryQueue); - Deque m_fullEntries; - Deque m_partialEntries; - Deque m_copyEntries; - - DISALLOW_COPY_AND_ASSIGN(CCTextureUpdateQueue); -}; - -} - -#endif // CCTextureUpdateQueue_h +// Temporary forwarding header +#include "cc/texture_update_queue.h" diff --git a/cc/CCThread.h b/cc/CCThread.h index 1ac4946..aaa3579 100644 --- a/cc/CCThread.h +++ b/cc/CCThread.h @@ -1,43 +1,6 @@ -// Copyright 2011 The Chromium Authors. All rights reserved. +// Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CCThread_h -#define CCThread_h - -#include "base/basictypes.h" -#include "base/threading/platform_thread.h" -#include - -namespace cc { - -// CCThread provides basic infrastructure for messaging with the compositor in a -// platform-neutral way. -class CCThread { -public: - virtual ~CCThread() { } - - class Task { - public: - virtual ~Task() { } - virtual void performTask() = 0; - void* instance() const { return m_instance; } - protected: - Task(void* instance) : m_instance(instance) { } - void* m_instance; - private: - DISALLOW_COPY_AND_ASSIGN(Task); - }; - - // Executes the task on context's thread asynchronously. - virtual void postTask(PassOwnPtr) = 0; - - // Executes the task after the specified delay. - virtual void postDelayedTask(PassOwnPtr, long long delayMs) = 0; - - virtual base::PlatformThreadId threadID() const = 0; -}; - -} - -#endif +// Temporary forwarding header +#include "cc/thread.h" diff --git a/cc/CCThreadProxy.cpp b/cc/CCThreadProxy.cpp deleted file mode 100644 index 1d3f2d3..0000000 --- a/cc/CCThreadProxy.cpp +++ /dev/null @@ -1,957 +0,0 @@ -// Copyright 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "config.h" - -#include "CCThreadProxy.h" - -#include "CCDelayBasedTimeSource.h" -#include "CCDrawQuad.h" -#include "CCFrameRateController.h" -#include "CCGraphicsContext.h" -#include "CCInputHandler.h" -#include "CCLayerTreeHost.h" -#include "CCScheduler.h" -#include "CCScopedThreadProxy.h" -#include "CCThreadTask.h" -#include "TraceEvent.h" -#include -#include - -using namespace WTF; -using WebKit::WebSharedGraphicsContext3D; - -namespace { - -// Measured in seconds. -const double contextRecreationTickRate = 0.03; - -} // namespace - -namespace cc { - -scoped_ptr CCThreadProxy::create(CCLayerTreeHost* layerTreeHost) -{ - return make_scoped_ptr(new CCThreadProxy(layerTreeHost)).PassAs(); -} - -CCThreadProxy::CCThreadProxy(CCLayerTreeHost* layerTreeHost) - : m_animateRequested(false) - , m_commitRequested(false) - , m_commitRequestSentToImplThread(false) - , m_forcedCommitRequested(false) - , m_layerTreeHost(layerTreeHost) - , m_rendererInitialized(false) - , m_started(false) - , m_texturesAcquired(true) - , m_inCompositeAndReadback(false) - , m_mainThreadProxy(CCScopedThreadProxy::create(CCProxy::mainThread())) - , m_beginFrameCompletionEventOnImplThread(0) - , m_readbackRequestOnImplThread(0) - , m_commitCompletionEventOnImplThread(0) - , m_textureAcquisitionCompletionEventOnImplThread(0) - , m_resetContentsTexturesPurgedAfterCommitOnImplThread(false) - , m_nextFrameIsNewlyCommittedFrameOnImplThread(false) - , m_renderVSyncEnabled(layerTreeHost->settings().renderVSyncEnabled) - , m_totalCommitCount(0) -{ - TRACE_EVENT0("cc", "CCThreadProxy::CCThreadProxy"); - ASSERT(isMainThread()); -} - -CCThreadProxy::~CCThreadProxy() -{ - TRACE_EVENT0("cc", "CCThreadProxy::~CCThreadProxy"); - ASSERT(isMainThread()); - ASSERT(!m_started); -} - -bool CCThreadProxy::compositeAndReadback(void *pixels, const IntRect& rect) -{ - TRACE_EVENT0("cc", "CCThreadPRoxy::compositeAndReadback"); - ASSERT(isMainThread()); - ASSERT(m_layerTreeHost); - - if (!m_layerTreeHost->initializeRendererIfNeeded()) { - TRACE_EVENT0("cc", "compositeAndReadback_EarlyOut_LR_Uninitialized"); - return false; - } - - - // Perform a synchronous commit. - { - DebugScopedSetMainThreadBlocked mainThreadBlocked; - CCCompletionEvent beginFrameCompletion; - CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::forceBeginFrameOnImplThread, &beginFrameCompletion)); - beginFrameCompletion.wait(); - } - m_inCompositeAndReadback = true; - beginFrame(); - m_inCompositeAndReadback = false; - - // Perform a synchronous readback. - ReadbackRequest request; - request.rect = rect; - request.pixels = pixels; - { - DebugScopedSetMainThreadBlocked mainThreadBlocked; - CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::requestReadbackOnImplThread, &request)); - request.completion.wait(); - } - return request.success; -} - -void CCThreadProxy::requestReadbackOnImplThread(ReadbackRequest* request) -{ - ASSERT(CCProxy::isImplThread()); - ASSERT(!m_readbackRequestOnImplThread); - if (!m_layerTreeHostImpl.get()) { - request->success = false; - request->completion.signal(); - return; - } - - m_readbackRequestOnImplThread = request; - m_schedulerOnImplThread->setNeedsRedraw(); - m_schedulerOnImplThread->setNeedsForcedRedraw(); -} - -void CCThreadProxy::startPageScaleAnimation(const IntSize& targetPosition, bool useAnchor, float scale, double duration) -{ - ASSERT(CCProxy::isMainThread()); - CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::requestStartPageScaleAnimationOnImplThread, targetPosition, useAnchor, scale, duration)); -} - -void CCThreadProxy::requestStartPageScaleAnimationOnImplThread(IntSize targetPosition, bool useAnchor, float scale, double duration) -{ - ASSERT(CCProxy::isImplThread()); - if (m_layerTreeHostImpl.get()) - m_layerTreeHostImpl->startPageScaleAnimation(targetPosition, useAnchor, scale, monotonicallyIncreasingTime(), duration); -} - -void CCThreadProxy::finishAllRendering() -{ - ASSERT(CCProxy::isMainThread()); - - // Make sure all GL drawing is finished on the impl thread. - DebugScopedSetMainThreadBlocked mainThreadBlocked; - CCCompletionEvent completion; - CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::finishAllRenderingOnImplThread, &completion)); - completion.wait(); -} - -bool CCThreadProxy::isStarted() const -{ - ASSERT(CCProxy::isMainThread()); - return m_started; -} - -bool CCThreadProxy::initializeContext() -{ - TRACE_EVENT0("cc", "CCThreadProxy::initializeContext"); - scoped_ptr context = m_layerTreeHost->createContext(); - if (!context.get()) - return false; - - CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::initializeContextOnImplThread, - context.release())); - return true; -} - -void CCThreadProxy::setSurfaceReady() -{ - TRACE_EVENT0("cc", "CCThreadProxy::setSurfaceReady"); - CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::setSurfaceReadyOnImplThread)); -} - -void CCThreadProxy::setSurfaceReadyOnImplThread() -{ - TRACE_EVENT0("cc", "CCThreadProxy::setSurfaceReadyOnImplThread"); - m_schedulerOnImplThread->setCanBeginFrame(true); -} - -void CCThreadProxy::setVisible(bool visible) -{ - TRACE_EVENT0("cc", "CCThreadProxy::setVisible"); - DebugScopedSetMainThreadBlocked mainThreadBlocked; - CCCompletionEvent completion; - CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::setVisibleOnImplThread, &completion, visible)); - completion.wait(); -} - -void CCThreadProxy::setVisibleOnImplThread(CCCompletionEvent* completion, bool visible) -{ - TRACE_EVENT0("cc", "CCThreadProxy::setVisibleOnImplThread"); - m_layerTreeHostImpl->setVisible(visible); - m_schedulerOnImplThread->setVisible(visible); - completion->signal(); -} - -bool CCThreadProxy::initializeRenderer() -{ - TRACE_EVENT0("cc", "CCThreadProxy::initializeRenderer"); - // Make a blocking call to initializeRendererOnImplThread. The results of that call - // are pushed into the initializeSucceeded and capabilities local variables. - CCCompletionEvent completion; - bool initializeSucceeded = false; - RendererCapabilities capabilities; - DebugScopedSetMainThreadBlocked mainThreadBlocked; - CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::initializeRendererOnImplThread, - &completion, - &initializeSucceeded, - &capabilities)); - completion.wait(); - - if (initializeSucceeded) { - m_rendererInitialized = true; - m_RendererCapabilitiesMainThreadCopy = capabilities; - } - return initializeSucceeded; -} - -bool CCThreadProxy::recreateContext() -{ - TRACE_EVENT0("cc", "CCThreadProxy::recreateContext"); - ASSERT(isMainThread()); - - // Try to create the context. - scoped_ptr context = m_layerTreeHost->createContext(); - if (!context.get()) - return false; - if (m_layerTreeHost->needsSharedContext()) - if (!WebSharedGraphicsContext3D::createCompositorThreadContext()) - return false; - - // Make a blocking call to recreateContextOnImplThread. The results of that - // call are pushed into the recreateSucceeded and capabilities local - // variables. - CCCompletionEvent completion; - bool recreateSucceeded = false; - RendererCapabilities capabilities; - DebugScopedSetMainThreadBlocked mainThreadBlocked; - CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::recreateContextOnImplThread, - &completion, - context.release(), - &recreateSucceeded, - &capabilities)); - completion.wait(); - - if (recreateSucceeded) - m_RendererCapabilitiesMainThreadCopy = capabilities; - return recreateSucceeded; -} - -void CCThreadProxy::renderingStats(CCRenderingStats* stats) -{ - ASSERT(isMainThread()); - - DebugScopedSetMainThreadBlocked mainThreadBlocked; - CCCompletionEvent completion; - CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::renderingStatsOnImplThread, - &completion, - stats)); - stats->totalCommitTimeInSeconds = m_totalCommitTime.InSecondsF(); - stats->totalCommitCount = m_totalCommitCount; - - completion.wait(); -} - -const RendererCapabilities& CCThreadProxy::rendererCapabilities() const -{ - ASSERT(m_rendererInitialized); - return m_RendererCapabilitiesMainThreadCopy; -} - -void CCThreadProxy::loseContext() -{ - CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::didLoseContextOnImplThread)); -} - -void CCThreadProxy::setNeedsAnimate() -{ - ASSERT(isMainThread()); - if (m_animateRequested) - return; - - TRACE_EVENT0("cc", "CCThreadProxy::setNeedsAnimate"); - m_animateRequested = true; - - if (m_commitRequestSentToImplThread) - return; - m_commitRequestSentToImplThread = true; - CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::setNeedsCommitOnImplThread)); -} - -void CCThreadProxy::setNeedsCommit() -{ - ASSERT(isMainThread()); - if (m_commitRequested) - return; - TRACE_EVENT0("cc", "CCThreadProxy::setNeedsCommit"); - m_commitRequested = true; - - if (m_commitRequestSentToImplThread) - return; - m_commitRequestSentToImplThread = true; - CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::setNeedsCommitOnImplThread)); -} - -void CCThreadProxy::didLoseContextOnImplThread() -{ - ASSERT(isImplThread()); - TRACE_EVENT0("cc", "CCThreadProxy::didLoseContextOnImplThread"); - m_schedulerOnImplThread->didLoseContext(); -} - -void CCThreadProxy::onSwapBuffersCompleteOnImplThread() -{ - ASSERT(isImplThread()); - TRACE_EVENT0("cc", "CCThreadProxy::onSwapBuffersCompleteOnImplThread"); - m_schedulerOnImplThread->didSwapBuffersComplete(); - m_mainThreadProxy->postTask(createCCThreadTask(this, &CCThreadProxy::didCompleteSwapBuffers)); -} - -void CCThreadProxy::onVSyncParametersChanged(double monotonicTimebase, double intervalInSeconds) -{ - ASSERT(isImplThread()); - TRACE_EVENT2("cc", "CCThreadProxy::onVSyncParametersChanged", "monotonicTimebase", monotonicTimebase, "intervalInSeconds", intervalInSeconds); - base::TimeTicks timebase = base::TimeTicks::FromInternalValue(monotonicTimebase * base::Time::kMicrosecondsPerSecond); - base::TimeDelta interval = base::TimeDelta::FromMicroseconds(intervalInSeconds * base::Time::kMicrosecondsPerSecond); - m_schedulerOnImplThread->setTimebaseAndInterval(timebase, interval); -} - -void CCThreadProxy::onCanDrawStateChanged(bool canDraw) -{ - ASSERT(isImplThread()); - TRACE_EVENT1("cc", "CCThreadProxy::onCanDrawStateChanged", "canDraw", canDraw); - m_schedulerOnImplThread->setCanDraw(canDraw); -} - -void CCThreadProxy::setNeedsCommitOnImplThread() -{ - ASSERT(isImplThread()); - TRACE_EVENT0("cc", "CCThreadProxy::setNeedsCommitOnImplThread"); - m_schedulerOnImplThread->setNeedsCommit(); -} - -void CCThreadProxy::setNeedsForcedCommitOnImplThread() -{ - ASSERT(isImplThread()); - TRACE_EVENT0("cc", "CCThreadProxy::setNeedsForcedCommitOnImplThread"); - m_schedulerOnImplThread->setNeedsCommit(); - m_schedulerOnImplThread->setNeedsForcedCommit(); -} - -void CCThreadProxy::postAnimationEventsToMainThreadOnImplThread(scoped_ptr events, double wallClockTime) -{ - ASSERT(isImplThread()); - TRACE_EVENT0("cc", "CCThreadProxy::postAnimationEventsToMainThreadOnImplThread"); - m_mainThreadProxy->postTask(createCCThreadTask(this, &CCThreadProxy::setAnimationEvents, events.release(), wallClockTime)); -} - -void CCThreadProxy::releaseContentsTexturesOnImplThread() -{ - ASSERT(isImplThread()); - - m_layerTreeHost->reduceContentsTexturesMemoryOnImplThread(0, m_layerTreeHostImpl->resourceProvider()); - - // Make sure that we get a new commit before drawing again. - m_resetContentsTexturesPurgedAfterCommitOnImplThread = false; - // The texture upload queue may reference textures that were just purged, clear - // them from the queue. - if (m_currentTextureUpdateControllerOnImplThread.get() && m_layerTreeHost->evictedContentsTexturesBackingsExist()) - m_currentTextureUpdateControllerOnImplThread->discardUploadsToEvictedResources(); -} - -void CCThreadProxy::setNeedsRedraw() -{ - ASSERT(isMainThread()); - TRACE_EVENT0("cc", "CCThreadProxy::setNeedsRedraw"); - CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::setFullRootLayerDamageOnImplThread)); - CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::setNeedsRedrawOnImplThread)); -} - -bool CCThreadProxy::commitRequested() const -{ - ASSERT(isMainThread()); - return m_commitRequested; -} - -void CCThreadProxy::setNeedsRedrawOnImplThread() -{ - ASSERT(isImplThread()); - TRACE_EVENT0("cc", "CCThreadProxy::setNeedsRedrawOnImplThread"); - m_schedulerOnImplThread->setNeedsRedraw(); -} - -void CCThreadProxy::start() -{ - ASSERT(isMainThread()); - ASSERT(CCProxy::implThread()); - // Create LayerTreeHostImpl. - DebugScopedSetMainThreadBlocked mainThreadBlocked; - CCCompletionEvent completion; - scoped_ptr handler = m_layerTreeHost->createInputHandler(); - CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::initializeImplOnImplThread, &completion, handler.release())); - completion.wait(); - - m_started = true; -} - -void CCThreadProxy::stop() -{ - TRACE_EVENT0("cc", "CCThreadProxy::stop"); - ASSERT(isMainThread()); - ASSERT(m_started); - - // Synchronously deletes the impl. - { - DebugScopedSetMainThreadBlocked mainThreadBlocked; - - CCCompletionEvent completion; - CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::layerTreeHostClosedOnImplThread, &completion)); - completion.wait(); - } - - m_mainThreadProxy->shutdown(); // Stop running tasks posted to us. - - ASSERT(!m_layerTreeHostImpl.get()); // verify that the impl deleted. - m_layerTreeHost = 0; - m_started = false; -} - -void CCThreadProxy::forceSerializeOnSwapBuffers() -{ - DebugScopedSetMainThreadBlocked mainThreadBlocked; - CCCompletionEvent completion; - CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::forceSerializeOnSwapBuffersOnImplThread, &completion)); - completion.wait(); -} - -void CCThreadProxy::forceSerializeOnSwapBuffersOnImplThread(CCCompletionEvent* completion) -{ - if (m_rendererInitialized) - m_layerTreeHostImpl->renderer()->doNoOp(); - completion->signal(); -} - - -void CCThreadProxy::finishAllRenderingOnImplThread(CCCompletionEvent* completion) -{ - TRACE_EVENT0("cc", "CCThreadProxy::finishAllRenderingOnImplThread"); - ASSERT(isImplThread()); - m_layerTreeHostImpl->finishAllRendering(); - completion->signal(); -} - -void CCThreadProxy::forceBeginFrameOnImplThread(CCCompletionEvent* completion) -{ - TRACE_EVENT0("cc", "CCThreadProxy::forceBeginFrameOnImplThread"); - ASSERT(!m_beginFrameCompletionEventOnImplThread); - - if (m_schedulerOnImplThread->commitPending()) { - completion->signal(); - return; - } - - m_beginFrameCompletionEventOnImplThread = completion; - setNeedsForcedCommitOnImplThread(); -} - -void CCThreadProxy::scheduledActionBeginFrame() -{ - TRACE_EVENT0("cc", "CCThreadProxy::scheduledActionBeginFrame"); - ASSERT(!m_pendingBeginFrameRequest); - m_pendingBeginFrameRequest = adoptPtr(new BeginFrameAndCommitState()); - m_pendingBeginFrameRequest->monotonicFrameBeginTime = monotonicallyIncreasingTime(); - m_pendingBeginFrameRequest->scrollInfo = m_layerTreeHostImpl->processScrollDeltas(); - m_pendingBeginFrameRequest->implTransform = m_layerTreeHostImpl->implTransform(); - m_pendingBeginFrameRequest->memoryAllocationLimitBytes = m_layerTreeHostImpl->memoryAllocationLimitBytes(); - m_layerTreeHost->getEvictedContentTexturesBackings(m_pendingBeginFrameRequest->evictedContentsTexturesBackings); - - m_mainThreadProxy->postTask(createCCThreadTask(this, &CCThreadProxy::beginFrame)); - - if (m_beginFrameCompletionEventOnImplThread) { - m_beginFrameCompletionEventOnImplThread->signal(); - m_beginFrameCompletionEventOnImplThread = 0; - } -} - -void CCThreadProxy::beginFrame() -{ - TRACE_EVENT0("cc", "CCThreadProxy::beginFrame"); - ASSERT(isMainThread()); - if (!m_layerTreeHost) - return; - - if (!m_pendingBeginFrameRequest) { - TRACE_EVENT0("cc", "EarlyOut_StaleBeginFrameMessage"); - return; - } - - if (m_layerTreeHost->needsSharedContext() && !WebSharedGraphicsContext3D::haveCompositorThreadContext()) - WebSharedGraphicsContext3D::createCompositorThreadContext(); - - OwnPtr request(m_pendingBeginFrameRequest.release()); - - // Do not notify the impl thread of commit requests that occur during - // the apply/animate/layout part of the beginFrameAndCommit process since - // those commit requests will get painted immediately. Once we have done - // the paint, m_commitRequested will be set to false to allow new commit - // requests to be scheduled. - m_commitRequested = true; - m_commitRequestSentToImplThread = true; - - // On the other hand, the animationRequested flag needs to be cleared - // here so that any animation requests generated by the apply or animate - // callbacks will trigger another frame. - m_animateRequested = false; - - // FIXME: technically, scroll deltas need to be applied for dropped commits as well. - // Re-do the commit flow so that we don't send the scrollInfo on the BFAC message. - m_layerTreeHost->applyScrollAndScale(*request->scrollInfo); - m_layerTreeHost->setImplTransform(request->implTransform); - - if (!m_inCompositeAndReadback && !m_layerTreeHost->visible()) { - m_commitRequested = false; - m_commitRequestSentToImplThread = false; - m_forcedCommitRequested = false; - - TRACE_EVENT0("cc", "EarlyOut_NotVisible"); - CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::beginFrameAbortedOnImplThread)); - return; - } - - m_layerTreeHost->willBeginFrame(); - - m_layerTreeHost->updateAnimations(request->monotonicFrameBeginTime); - m_layerTreeHost->layout(); - - // Clear the commit flag after updating animations and layout here --- objects that only - // layout when painted will trigger another setNeedsCommit inside - // updateLayers. - m_commitRequested = false; - m_commitRequestSentToImplThread = false; - m_forcedCommitRequested = false; - - if (!m_layerTreeHost->initializeRendererIfNeeded()) { - TRACE_EVENT0("cc", "EarlyOut_InitializeFailed"); - return; - } - - m_layerTreeHost->unlinkEvictedContentTexturesBackings(request->evictedContentsTexturesBackings); - - OwnPtr queue = adoptPtr(new CCTextureUpdateQueue); - m_layerTreeHost->updateLayers(*(queue.get()), request->memoryAllocationLimitBytes); - - // Once single buffered layers are committed, they cannot be modified until - // they are drawn by the impl thread. - m_texturesAcquired = false; - - m_layerTreeHost->willCommit(); - // Before applying scrolls and calling animate, we set m_animateRequested to - // false. If it is true now, it means setNeedAnimate was called again, but - // during a state when m_commitRequestSentToImplThread = true. We need to - // force that call to happen again now so that the commit request is sent to - // the impl thread. - if (m_animateRequested) { - // Forces setNeedsAnimate to consider posting a commit task. - m_animateRequested = false; - setNeedsAnimate(); - } - - // Notify the impl thread that the beginFrame has completed. This will - // begin the commit process, which is blocking from the main thread's - // point of view, but asynchronously performed on the impl thread, - // coordinated by the CCScheduler. - { - TRACE_EVENT0("cc", "commit"); - - DebugScopedSetMainThreadBlocked mainThreadBlocked; - - base::TimeTicks startTime = base::TimeTicks::HighResNow(); - CCCompletionEvent completion; - CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::beginFrameCompleteOnImplThread, &completion, queue.release())); - completion.wait(); - base::TimeTicks endTime = base::TimeTicks::HighResNow(); - - m_totalCommitTime += endTime - startTime; - m_totalCommitCount++; - } - - m_layerTreeHost->commitComplete(); - m_layerTreeHost->didBeginFrame(); -} - -void CCThreadProxy::beginFrameCompleteOnImplThread(CCCompletionEvent* completion, PassOwnPtr queue) -{ - TRACE_EVENT0("cc", "CCThreadProxy::beginFrameCompleteOnImplThread"); - ASSERT(!m_commitCompletionEventOnImplThread); - ASSERT(isImplThread() && isMainThreadBlocked()); - ASSERT(m_schedulerOnImplThread); - ASSERT(m_schedulerOnImplThread->commitPending()); - - if (!m_layerTreeHostImpl.get()) { - TRACE_EVENT0("cc", "EarlyOut_NoLayerTree"); - completion->signal(); - return; - } - - // Clear any uploads we were making to textures linked to evicted - // resources - if (m_layerTreeHost->evictedContentsTexturesBackingsExist()) - queue->clearUploadsToEvictedResources(); - - // If we unlinked evicted textures on the main thread, delete them now. - if (m_layerTreeHost->deleteEvictedContentTexturesBackings()) { - // Deleting the evicted textures' backings resulted in some textures in the - // layer tree being invalidated (unliked from their backings). Kick off - // another commit to fill them again. - setNeedsCommitOnImplThread(); - } else { - // The layer tree does not reference evicted textures, so mark that we - // can draw this tree once this commit is complete. - if (m_layerTreeHostImpl->contentsTexturesPurged()) - m_resetContentsTexturesPurgedAfterCommitOnImplThread = true; - } - - m_currentTextureUpdateControllerOnImplThread = CCTextureUpdateController::create(this, CCProxy::implThread(), queue, m_layerTreeHostImpl->resourceProvider(), m_layerTreeHostImpl->resourceProvider()->textureUploader()); - m_currentTextureUpdateControllerOnImplThread->performMoreUpdates( - m_schedulerOnImplThread->anticipatedDrawTime()); - - m_commitCompletionEventOnImplThread = completion; -} - -void CCThreadProxy::beginFrameAbortedOnImplThread() -{ - TRACE_EVENT0("cc", "CCThreadProxy::beginFrameAbortedOnImplThread"); - ASSERT(isImplThread()); - ASSERT(m_schedulerOnImplThread); - ASSERT(m_schedulerOnImplThread->commitPending()); - - m_schedulerOnImplThread->beginFrameAborted(); -} - -void CCThreadProxy::scheduledActionCommit() -{ - TRACE_EVENT0("cc", "CCThreadProxy::scheduledActionCommit"); - ASSERT(isImplThread()); - ASSERT(m_commitCompletionEventOnImplThread); - ASSERT(m_currentTextureUpdateControllerOnImplThread); - - // Complete all remaining texture updates. - m_currentTextureUpdateControllerOnImplThread->finalize(); - m_currentTextureUpdateControllerOnImplThread.clear(); - - m_layerTreeHostImpl->beginCommit(); - - m_layerTreeHost->beginCommitOnImplThread(m_layerTreeHostImpl.get()); - m_layerTreeHost->finishCommitOnImplThread(m_layerTreeHostImpl.get()); - - if (m_resetContentsTexturesPurgedAfterCommitOnImplThread) { - m_resetContentsTexturesPurgedAfterCommitOnImplThread = false; - m_layerTreeHostImpl->resetContentsTexturesPurged(); - } - - m_layerTreeHostImpl->commitComplete(); - - m_nextFrameIsNewlyCommittedFrameOnImplThread = true; - - m_commitCompletionEventOnImplThread->signal(); - m_commitCompletionEventOnImplThread = 0; - - // SetVisible kicks off the next scheduler action, so this must be last. - m_schedulerOnImplThread->setVisible(m_layerTreeHostImpl->visible()); -} - -void CCThreadProxy::scheduledActionBeginContextRecreation() -{ - ASSERT(isImplThread()); - m_mainThreadProxy->postTask(createCCThreadTask(this, &CCThreadProxy::beginContextRecreation)); -} - -CCScheduledActionDrawAndSwapResult CCThreadProxy::scheduledActionDrawAndSwapInternal(bool forcedDraw) -{ - TRACE_EVENT0("cc", "CCThreadProxy::scheduledActionDrawAndSwap"); - CCScheduledActionDrawAndSwapResult result; - result.didDraw = false; - result.didSwap = false; - ASSERT(isImplThread()); - ASSERT(m_layerTreeHostImpl.get()); - if (!m_layerTreeHostImpl.get()) - return result; - - ASSERT(m_layerTreeHostImpl->renderer()); - if (!m_layerTreeHostImpl->renderer()) - return result; - - // FIXME: compute the frame display time more intelligently - double monotonicTime = monotonicallyIncreasingTime(); - double wallClockTime = currentTime(); - - if (m_inputHandlerOnImplThread.get()) - m_inputHandlerOnImplThread->animate(monotonicTime); - m_layerTreeHostImpl->animate(monotonicTime, wallClockTime); - - // This method is called on a forced draw, regardless of whether we are able to produce a frame, - // as the calling site on main thread is blocked until its request completes, and we signal - // completion here. If canDraw() is false, we will indicate success=false to the caller, but we - // must still signal completion to avoid deadlock. - - // We guard prepareToDraw() with canDraw() because it always returns a valid frame, so can only - // be used when such a frame is possible. Since drawLayers() depends on the result of - // prepareToDraw(), it is guarded on canDraw() as well. - - CCLayerTreeHostImpl::FrameData frame; - bool drawFrame = m_layerTreeHostImpl->canDraw() && (m_layerTreeHostImpl->prepareToDraw(frame) || forcedDraw); - if (drawFrame) { - m_layerTreeHostImpl->drawLayers(frame); - result.didDraw = true; - } - m_layerTreeHostImpl->didDrawAllLayers(frame); - - // Check for a pending compositeAndReadback. - if (m_readbackRequestOnImplThread) { - m_readbackRequestOnImplThread->success = false; - if (drawFrame) { - m_layerTreeHostImpl->readback(m_readbackRequestOnImplThread->pixels, m_readbackRequestOnImplThread->rect); - m_readbackRequestOnImplThread->success = !m_layerTreeHostImpl->isContextLost(); - } - m_readbackRequestOnImplThread->completion.signal(); - m_readbackRequestOnImplThread = 0; - } else if (drawFrame) - result.didSwap = m_layerTreeHostImpl->swapBuffers(); - - // Tell the main thread that the the newly-commited frame was drawn. - if (m_nextFrameIsNewlyCommittedFrameOnImplThread) { - m_nextFrameIsNewlyCommittedFrameOnImplThread = false; - m_mainThreadProxy->postTask(createCCThreadTask(this, &CCThreadProxy::didCommitAndDrawFrame)); - } - - return result; -} - -void CCThreadProxy::acquireLayerTextures() -{ - // Called when the main thread needs to modify a layer texture that is used - // directly by the compositor. - // This method will block until the next compositor draw if there is a - // previously committed frame that is still undrawn. This is necessary to - // ensure that the main thread does not monopolize access to the textures. - ASSERT(isMainThread()); - - if (m_texturesAcquired) - return; - - TRACE_EVENT0("cc", "CCThreadProxy::acquireLayerTextures"); - DebugScopedSetMainThreadBlocked mainThreadBlocked; - CCCompletionEvent completion; - CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::acquireLayerTexturesForMainThreadOnImplThread, &completion)); - completion.wait(); // Block until it is safe to write to layer textures from the main thread. - - m_texturesAcquired = true; -} - -void CCThreadProxy::acquireLayerTexturesForMainThreadOnImplThread(CCCompletionEvent* completion) -{ - ASSERT(isImplThread()); - ASSERT(!m_textureAcquisitionCompletionEventOnImplThread); - - m_textureAcquisitionCompletionEventOnImplThread = completion; - m_schedulerOnImplThread->setMainThreadNeedsLayerTextures(); -} - -void CCThreadProxy::scheduledActionAcquireLayerTexturesForMainThread() -{ - ASSERT(m_textureAcquisitionCompletionEventOnImplThread); - m_textureAcquisitionCompletionEventOnImplThread->signal(); - m_textureAcquisitionCompletionEventOnImplThread = 0; -} - -CCScheduledActionDrawAndSwapResult CCThreadProxy::scheduledActionDrawAndSwapIfPossible() -{ - return scheduledActionDrawAndSwapInternal(false); -} - -CCScheduledActionDrawAndSwapResult CCThreadProxy::scheduledActionDrawAndSwapForced() -{ - return scheduledActionDrawAndSwapInternal(true); -} - -void CCThreadProxy::didAnticipatedDrawTimeChange(base::TimeTicks time) -{ - if (!m_currentTextureUpdateControllerOnImplThread) - return; - - m_currentTextureUpdateControllerOnImplThread->performMoreUpdates(time); -} - -void CCThreadProxy::readyToFinalizeTextureUpdates() -{ - ASSERT(isImplThread()); - m_schedulerOnImplThread->beginFrameComplete(); -} - -void CCThreadProxy::didCommitAndDrawFrame() -{ - ASSERT(isMainThread()); - if (!m_layerTreeHost) - return; - m_layerTreeHost->didCommitAndDrawFrame(); -} - -void CCThreadProxy::didCompleteSwapBuffers() -{ - ASSERT(isMainThread()); - if (!m_layerTreeHost) - return; - m_layerTreeHost->didCompleteSwapBuffers(); -} - -void CCThreadProxy::setAnimationEvents(CCAnimationEventsVector* passed_events, double wallClockTime) -{ - scoped_ptr events(make_scoped_ptr(passed_events)); - - TRACE_EVENT0("cc", "CCThreadProxy::setAnimationEvents"); - ASSERT(isMainThread()); - if (!m_layerTreeHost) - return; - m_layerTreeHost->setAnimationEvents(events.Pass(), wallClockTime); -} - -class CCThreadProxyContextRecreationTimer : public CCTimer, CCTimerClient { -public: - static PassOwnPtr create(CCThreadProxy* proxy) { return adoptPtr(new CCThreadProxyContextRecreationTimer(proxy)); } - - virtual void onTimerFired() OVERRIDE - { - m_proxy->tryToRecreateContext(); - } - -private: - explicit CCThreadProxyContextRecreationTimer(CCThreadProxy* proxy) - : CCTimer(CCProxy::mainThread(), this) - , m_proxy(proxy) - { - } - - CCThreadProxy* m_proxy; -}; - -void CCThreadProxy::beginContextRecreation() -{ - TRACE_EVENT0("cc", "CCThreadProxy::beginContextRecreation"); - ASSERT(isMainThread()); - ASSERT(!m_contextRecreationTimer); - m_contextRecreationTimer = CCThreadProxyContextRecreationTimer::create(this); - m_layerTreeHost->didLoseContext(); - m_contextRecreationTimer->startOneShot(contextRecreationTickRate); -} - -void CCThreadProxy::tryToRecreateContext() -{ - ASSERT(isMainThread()); - ASSERT(m_layerTreeHost); - CCLayerTreeHost::RecreateResult result = m_layerTreeHost->recreateContext(); - if (result == CCLayerTreeHost::RecreateFailedButTryAgain) - m_contextRecreationTimer->startOneShot(contextRecreationTickRate); - else if (result == CCLayerTreeHost::RecreateSucceeded) - m_contextRecreationTimer.clear(); -} - -void CCThreadProxy::initializeImplOnImplThread(CCCompletionEvent* completion, CCInputHandler* handler) -{ - TRACE_EVENT0("cc", "CCThreadProxy::initializeImplOnImplThread"); - ASSERT(isImplThread()); - m_layerTreeHostImpl = m_layerTreeHost->createLayerTreeHostImpl(this); - const base::TimeDelta displayRefreshInterval = base::TimeDelta::FromMicroseconds(base::Time::kMicrosecondsPerSecond / 60); - scoped_ptr frameRateController; - if (m_renderVSyncEnabled) - frameRateController.reset(new CCFrameRateController(CCDelayBasedTimeSource::create(displayRefreshInterval, CCProxy::implThread()))); - else - frameRateController.reset(new CCFrameRateController(CCProxy::implThread())); - m_schedulerOnImplThread = CCScheduler::create(this, frameRateController.Pass()); - m_schedulerOnImplThread->setVisible(m_layerTreeHostImpl->visible()); - - m_inputHandlerOnImplThread = scoped_ptr(handler); - if (m_inputHandlerOnImplThread.get()) - m_inputHandlerOnImplThread->bindToClient(m_layerTreeHostImpl.get()); - - completion->signal(); -} - -void CCThreadProxy::initializeContextOnImplThread(CCGraphicsContext* context) -{ - TRACE_EVENT0("cc", "CCThreadProxy::initializeContextOnImplThread"); - ASSERT(isImplThread()); - m_contextBeforeInitializationOnImplThread = scoped_ptr(context).Pass(); -} - -void CCThreadProxy::initializeRendererOnImplThread(CCCompletionEvent* completion, bool* initializeSucceeded, RendererCapabilities* capabilities) -{ - TRACE_EVENT0("cc", "CCThreadProxy::initializeRendererOnImplThread"); - ASSERT(isImplThread()); - ASSERT(m_contextBeforeInitializationOnImplThread.get()); - *initializeSucceeded = m_layerTreeHostImpl->initializeRenderer(m_contextBeforeInitializationOnImplThread.Pass()); - if (*initializeSucceeded) { - *capabilities = m_layerTreeHostImpl->rendererCapabilities(); - m_schedulerOnImplThread->setSwapBuffersCompleteSupported( - capabilities->usingSwapCompleteCallback); - } - - completion->signal(); -} - -void CCThreadProxy::layerTreeHostClosedOnImplThread(CCCompletionEvent* completion) -{ - TRACE_EVENT0("cc", "CCThreadProxy::layerTreeHostClosedOnImplThread"); - ASSERT(isImplThread()); - m_layerTreeHost->deleteContentsTexturesOnImplThread(m_layerTreeHostImpl->resourceProvider()); - m_inputHandlerOnImplThread.reset(); - m_layerTreeHostImpl.reset(); - m_schedulerOnImplThread.clear(); - completion->signal(); -} - -void CCThreadProxy::setFullRootLayerDamageOnImplThread() -{ - ASSERT(isImplThread()); - m_layerTreeHostImpl->setFullRootLayerDamage(); -} - -size_t CCThreadProxy::maxPartialTextureUpdates() const -{ - return CCTextureUpdateController::maxPartialTextureUpdates(); -} - -void CCThreadProxy::recreateContextOnImplThread(CCCompletionEvent* completion, CCGraphicsContext* contextPtr, bool* recreateSucceeded, RendererCapabilities* capabilities) -{ - TRACE_EVENT0("cc", "CCThreadProxy::recreateContextOnImplThread"); - ASSERT(isImplThread()); - m_layerTreeHost->deleteContentsTexturesOnImplThread(m_layerTreeHostImpl->resourceProvider()); - *recreateSucceeded = m_layerTreeHostImpl->initializeRenderer(scoped_ptr(contextPtr).Pass()); - if (*recreateSucceeded) { - *capabilities = m_layerTreeHostImpl->rendererCapabilities(); - m_schedulerOnImplThread->didRecreateContext(); - } - completion->signal(); -} - -void CCThreadProxy::renderingStatsOnImplThread(CCCompletionEvent* completion, CCRenderingStats* stats) -{ - ASSERT(isImplThread()); - m_layerTreeHostImpl->renderingStats(stats); - completion->signal(); -} - -CCThreadProxy::BeginFrameAndCommitState::BeginFrameAndCommitState() - : monotonicFrameBeginTime(0) -{ -} - -CCThreadProxy::BeginFrameAndCommitState::~BeginFrameAndCommitState() -{ -} - -} // namespace cc diff --git a/cc/CCThreadProxy.h b/cc/CCThreadProxy.h index a6ea6ac..04899c0 100644 --- a/cc/CCThreadProxy.h +++ b/cc/CCThreadProxy.h @@ -1,185 +1,6 @@ -// Copyright 2011 The Chromium Authors. All rights reserved. +// Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CCThreadProxy_h -#define CCThreadProxy_h - -#include "CCAnimationEvents.h" -#include "CCCompletionEvent.h" -#include "CCLayerTreeHostImpl.h" -#include "CCProxy.h" -#include "CCScheduler.h" -#include "CCTextureUpdateController.h" -#include -#include - -namespace cc { - -class CCInputHandler; -class CCLayerTreeHost; -class CCScheduler; -class CCScopedThreadProxy; -class CCTextureUpdateQueue; -class CCThread; -class CCThreadProxyContextRecreationTimer; - -class CCThreadProxy : public CCProxy, CCLayerTreeHostImplClient, CCSchedulerClient, CCTextureUpdateControllerClient { -public: - static scoped_ptr create(CCLayerTreeHost*); - - virtual ~CCThreadProxy(); - - // CCProxy implementation - virtual bool compositeAndReadback(void *pixels, const IntRect&) OVERRIDE; - virtual void startPageScaleAnimation(const IntSize& targetPosition, bool useAnchor, float scale, double duration) OVERRIDE; - virtual void finishAllRendering() OVERRIDE; - virtual bool isStarted() const OVERRIDE; - virtual bool initializeContext() OVERRIDE; - virtual void setSurfaceReady() OVERRIDE; - virtual void setVisible(bool) OVERRIDE; - virtual bool initializeRenderer() OVERRIDE; - virtual bool recreateContext() OVERRIDE; - virtual void renderingStats(CCRenderingStats*) OVERRIDE; - virtual const RendererCapabilities& rendererCapabilities() const OVERRIDE; - virtual void loseContext() OVERRIDE; - virtual void setNeedsAnimate() OVERRIDE; - virtual void setNeedsCommit() OVERRIDE; - virtual void setNeedsRedraw() OVERRIDE; - virtual bool commitRequested() const OVERRIDE; - virtual void didAddAnimation() OVERRIDE { } - virtual void start() OVERRIDE; - virtual void stop() OVERRIDE; - virtual size_t maxPartialTextureUpdates() const OVERRIDE; - virtual void acquireLayerTextures() OVERRIDE; - virtual void forceSerializeOnSwapBuffers() OVERRIDE; - - // CCLayerTreeHostImplClient implementation - virtual void didLoseContextOnImplThread() OVERRIDE; - virtual void onSwapBuffersCompleteOnImplThread() OVERRIDE; - virtual void onVSyncParametersChanged(double monotonicTimebase, double intervalInSeconds) OVERRIDE; - virtual void onCanDrawStateChanged(bool canDraw) OVERRIDE; - virtual void setNeedsRedrawOnImplThread() OVERRIDE; - virtual void setNeedsCommitOnImplThread() OVERRIDE; - virtual void postAnimationEventsToMainThreadOnImplThread(scoped_ptr, double wallClockTime) OVERRIDE; - virtual void releaseContentsTexturesOnImplThread() OVERRIDE; - - // CCSchedulerClient implementation - virtual void scheduledActionBeginFrame() OVERRIDE; - virtual CCScheduledActionDrawAndSwapResult scheduledActionDrawAndSwapIfPossible() OVERRIDE; - virtual CCScheduledActionDrawAndSwapResult scheduledActionDrawAndSwapForced() OVERRIDE; - virtual void scheduledActionCommit() OVERRIDE; - virtual void scheduledActionBeginContextRecreation() OVERRIDE; - virtual void scheduledActionAcquireLayerTexturesForMainThread() OVERRIDE; - virtual void didAnticipatedDrawTimeChange(base::TimeTicks) OVERRIDE; - - // CCTextureUpdateControllerClient implementation - virtual void readyToFinalizeTextureUpdates() OVERRIDE; - -private: - explicit CCThreadProxy(CCLayerTreeHost*); - friend class CCThreadProxyContextRecreationTimer; - - // Set on impl thread, read on main thread. - struct BeginFrameAndCommitState { - BeginFrameAndCommitState(); - ~BeginFrameAndCommitState(); - - double monotonicFrameBeginTime; - scoped_ptr scrollInfo; - WebKit::WebTransformationMatrix implTransform; - CCPrioritizedTextureManager::BackingVector evictedContentsTexturesBackings; - size_t memoryAllocationLimitBytes; - }; - OwnPtr m_pendingBeginFrameRequest; - - // Called on main thread - void beginFrame(); - void didCommitAndDrawFrame(); - void didCompleteSwapBuffers(); - void setAnimationEvents(CCAnimationEventsVector*, double wallClockTime); - void beginContextRecreation(); - void tryToRecreateContext(); - - // Called on impl thread - struct ReadbackRequest { - CCCompletionEvent completion; - bool success; - void* pixels; - IntRect rect; - }; - void forceBeginFrameOnImplThread(CCCompletionEvent*); - void beginFrameCompleteOnImplThread(CCCompletionEvent*, PassOwnPtr); - void beginFrameAbortedOnImplThread(); - void requestReadbackOnImplThread(ReadbackRequest*); - void requestStartPageScaleAnimationOnImplThread(IntSize targetPosition, bool useAnchor, float scale, double durationSec); - void finishAllRenderingOnImplThread(CCCompletionEvent*); - void initializeImplOnImplThread(CCCompletionEvent*, CCInputHandler*); - void setSurfaceReadyOnImplThread(); - void setVisibleOnImplThread(CCCompletionEvent*, bool); - void initializeContextOnImplThread(CCGraphicsContext*); - void initializeRendererOnImplThread(CCCompletionEvent*, bool* initializeSucceeded, RendererCapabilities*); - void layerTreeHostClosedOnImplThread(CCCompletionEvent*); - void setFullRootLayerDamageOnImplThread(); - void acquireLayerTexturesForMainThreadOnImplThread(CCCompletionEvent*); - void recreateContextOnImplThread(CCCompletionEvent*, CCGraphicsContext*, bool* recreateSucceeded, RendererCapabilities*); - void renderingStatsOnImplThread(CCCompletionEvent*, CCRenderingStats*); - CCScheduledActionDrawAndSwapResult scheduledActionDrawAndSwapInternal(bool forcedDraw); - void forceSerializeOnSwapBuffersOnImplThread(CCCompletionEvent*); - void setNeedsForcedCommitOnImplThread(); - - // Accessed on main thread only. - bool m_animateRequested; // Set only when setNeedsAnimate is called. - bool m_commitRequested; // Set only when setNeedsCommit is called. - bool m_commitRequestSentToImplThread; // Set by setNeedsCommit and setNeedsAnimate. - bool m_forcedCommitRequested; - OwnPtr m_contextRecreationTimer; - CCLayerTreeHost* m_layerTreeHost; - bool m_rendererInitialized; - RendererCapabilities m_RendererCapabilitiesMainThreadCopy; - bool m_started; - bool m_texturesAcquired; - bool m_inCompositeAndReadback; - - scoped_ptr m_layerTreeHostImpl; - - scoped_ptr m_inputHandlerOnImplThread; - - OwnPtr m_schedulerOnImplThread; - - RefPtr m_mainThreadProxy; - - // Holds on to the context we might use for compositing in between initializeContext() - // and initializeRenderer() calls. - scoped_ptr m_contextBeforeInitializationOnImplThread; - - // Set when the main thread is waiting on a scheduledActionBeginFrame to be issued. - CCCompletionEvent* m_beginFrameCompletionEventOnImplThread; - - // Set when the main thread is waiting on a readback. - ReadbackRequest* m_readbackRequestOnImplThread; - - // Set when the main thread is waiting on a commit to complete. - CCCompletionEvent* m_commitCompletionEventOnImplThread; - - // Set when the main thread is waiting on layers to be drawn. - CCCompletionEvent* m_textureAcquisitionCompletionEventOnImplThread; - - OwnPtr m_currentTextureUpdateControllerOnImplThread; - - // Set when we need to reset the contentsTexturesPurged flag after the - // commit. - bool m_resetContentsTexturesPurgedAfterCommitOnImplThread; - - // Set when the next draw should post didCommitAndDrawFrame to the main thread. - bool m_nextFrameIsNewlyCommittedFrameOnImplThread; - - bool m_renderVSyncEnabled; - - base::TimeDelta m_totalCommitTime; - size_t m_totalCommitCount; -}; - -} - -#endif +// Temporary forwarding header +#include "cc/thread_proxy.h" diff --git a/cc/CCThreadTask.h b/cc/CCThreadTask.h index 25c5509..561156b7 100644 --- a/cc/CCThreadTask.h +++ b/cc/CCThreadTask.h @@ -1,305 +1,6 @@ -// Copyright 2011 The Chromium Authors. All rights reserved. +// Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CCThreadTask_h -#define CCThreadTask_h -#include "CCThread.h" -#include -#include - -namespace cc { - -template -class CCThreadTask0 : public CCThread::Task { -public: - typedef void (T::*Method)(); - typedef CCThreadTask0 CCThreadTaskImpl; - - static PassOwnPtr create(T* instance, Method method) - { - return adoptPtr(new CCThreadTaskImpl(instance, method)); - } - -private: - CCThreadTask0(T* instance, Method method) - : CCThread::Task(instance) - , m_method(method) - { - } - - virtual void performTask() OVERRIDE - { - (*static_cast(instance()).*m_method)(); - } - -private: - Method m_method; -}; - -template -class CCThreadTask1 : public CCThread::Task { -public: - typedef void (T::*Method)(MP1); - typedef CCThreadTask1 CCThreadTaskImpl; - - static PassOwnPtr create(T* instance, Method method, P1 parameter1) - { - return adoptPtr(new CCThreadTaskImpl(instance, method, parameter1)); - } - -private: - CCThreadTask1(T* instance, Method method, P1 parameter1) - : CCThread::Task(instance) - , m_method(method) - , m_parameter1(parameter1) - { - } - - virtual void performTask() OVERRIDE - { - (*static_cast(instance()).*m_method)(m_parameter1); - } - -private: - Method m_method; - P1 m_parameter1; -}; - -template -class CCThreadTask2 : public CCThread::Task { -public: - typedef void (T::*Method)(MP1, MP2); - typedef CCThreadTask2 CCThreadTaskImpl; - - static PassOwnPtr create(T* instance, Method method, P1 parameter1, P2 parameter2) - { - return adoptPtr(new CCThreadTaskImpl(instance, method, parameter1, parameter2)); - } - -private: - CCThreadTask2(T* instance, Method method, P1 parameter1, P2 parameter2) - : CCThread::Task(instance) - , m_method(method) - , m_parameter1(parameter1) - , m_parameter2(parameter2) - { - } - - virtual void performTask() OVERRIDE - { - (*static_cast(instance()).*m_method)(m_parameter1, m_parameter2); - } - -private: - Method m_method; - P1 m_parameter1; - P2 m_parameter2; -}; - -template -class CCThreadTask3 : public CCThread::Task { -public: - typedef void (T::*Method)(MP1, MP2, MP3); - typedef CCThreadTask3 CCThreadTaskImpl; - - static PassOwnPtr create(T* instance, Method method, P1 parameter1, P2 parameter2, P3 parameter3) - { - return adoptPtr(new CCThreadTaskImpl(instance, method, parameter1, parameter2, parameter3)); - } - -private: - CCThreadTask3(T* instance, Method method, P1 parameter1, P2 parameter2, P3 parameter3) - : CCThread::Task(instance) - , m_method(method) - , m_parameter1(parameter1) - , m_parameter2(parameter2) - , m_parameter3(parameter3) - { - } - - virtual void performTask() OVERRIDE - { - (*static_cast(instance()).*m_method)(m_parameter1, m_parameter2, m_parameter3); - } - -private: - Method m_method; - P1 m_parameter1; - P2 m_parameter2; - P3 m_parameter3; -}; - - -template -class CCThreadTask4 : public CCThread::Task { -public: - typedef void (T::*Method)(MP1, MP2, MP3, MP4); - typedef CCThreadTask4 CCThreadTaskImpl; - - static PassOwnPtr create(T* instance, Method method, P1 parameter1, P2 parameter2, P3 parameter3, P4 parameter4) - { - return adoptPtr(new CCThreadTaskImpl(instance, method, parameter1, parameter2, parameter3, parameter4)); - } - -private: - CCThreadTask4(T* instance, Method method, P1 parameter1, P2 parameter2, P3 parameter3, P4 parameter4) - : CCThread::Task(instance) - , m_method(method) - , m_parameter1(parameter1) - , m_parameter2(parameter2) - , m_parameter3(parameter3) - , m_parameter4(parameter4) - { - } - - virtual void performTask() OVERRIDE - { - (*static_cast(instance()).*m_method)(m_parameter1, m_parameter2, m_parameter3, m_parameter4); - } - -private: - Method m_method; - P1 m_parameter1; - P2 m_parameter2; - P3 m_parameter3; - P4 m_parameter4; -}; - -template -class CCThreadTask5 : public CCThread::Task { -public: - typedef void (T::*Method)(MP1, MP2, MP3, MP4, MP5); - typedef CCThreadTask5 CCThreadTaskImpl; - - static PassOwnPtr create(T* instance, Method method, P1 parameter1, P2 parameter2, P3 parameter3, P4 parameter4, P5 parameter5) - { - return adoptPtr(new CCThreadTaskImpl(instance, method, parameter1, parameter2, parameter3, parameter4, parameter5)); - } - -private: - CCThreadTask5(T* instance, Method method, P1 parameter1, P2 parameter2, P3 parameter3, P4 parameter4, P5 parameter5) - : CCThread::Task(instance) - , m_method(method) - , m_parameter1(parameter1) - , m_parameter2(parameter2) - , m_parameter3(parameter3) - , m_parameter4(parameter4) - , m_parameter5(parameter5) - { - } - - virtual void performTask() OVERRIDE - { - (*static_cast(instance()).*m_method)(m_parameter1, m_parameter2, m_parameter3, m_parameter4, m_parameter5); - } - -private: - Method m_method; - P1 m_parameter1; - P2 m_parameter2; - P3 m_parameter3; - P4 m_parameter4; - P5 m_parameter5; -}; - -template -PassOwnPtr createCCThreadTask( - T* const callee, - void (T::*method)()); - -template -PassOwnPtr createCCThreadTask( - T* const callee, - void (T::*method)()) -{ - return CCThreadTask0::create( - callee, - method); -} - -template -PassOwnPtr createCCThreadTask( - T* const callee, - void (T::*method)(MP1), - const P1& parameter1) -{ - return CCThreadTask1::create( - callee, - method, - parameter1); -} - -template -PassOwnPtr createCCThreadTask( - T* const callee, - void (T::*method)(MP1, MP2), - const P1& parameter1, - const P2& parameter2) -{ - return CCThreadTask2::create( - callee, - method, - parameter1, - parameter2); -} - -template -PassOwnPtr createCCThreadTask( - T* const callee, - void (T::*method)(MP1, MP2, MP3), - const P1& parameter1, - const P2& parameter2, - const P3& parameter3) -{ - return CCThreadTask3::create( - callee, - method, - parameter1, - parameter2, - parameter3); -} - -template -PassOwnPtr createCCThreadTask( - T* const callee, - void (T::*method)(MP1, MP2, MP3, MP4), - const P1& parameter1, - const P2& parameter2, - const P3& parameter3, - const P4& parameter4) -{ - return CCThreadTask4::create( - callee, - method, - parameter1, - parameter2, - parameter3, - parameter4); - -} - -template -PassOwnPtr createCCThreadTask( - T* const callee, - void (T::*method)(MP1, MP2, MP3, MP4, MP5), - const P1& parameter1, - const P2& parameter2, - const P3& parameter3, - const P4& parameter4, - const P5& parameter5) -{ - return CCThreadTask5::create( - callee, - method, - parameter1, - parameter2, - parameter3, - parameter4, - parameter5); - -} - -} // namespace cc - -#endif // CCThreadTask_h +// Temporary forwarding header +#include "cc/thread_task.h" diff --git a/cc/CCTileDrawQuad.cpp b/cc/CCTileDrawQuad.cpp deleted file mode 100644 index a5ac33d..0000000 --- a/cc/CCTileDrawQuad.cpp +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "config.h" - -#include "CCTileDrawQuad.h" - -namespace cc { - -scoped_ptr CCTileDrawQuad::create(const CCSharedQuadState* sharedQuadState, const IntRect& quadRect, const IntRect& opaqueRect, unsigned resourceId, const IntPoint& textureOffset, const IntSize& textureSize, GC3Dint textureFilter, bool swizzleContents, bool leftEdgeAA, bool topEdgeAA, bool rightEdgeAA, bool bottomEdgeAA) -{ - return make_scoped_ptr(new CCTileDrawQuad(sharedQuadState, quadRect, opaqueRect, resourceId, textureOffset, textureSize, textureFilter, swizzleContents, leftEdgeAA, topEdgeAA, rightEdgeAA, bottomEdgeAA)); -} - -CCTileDrawQuad::CCTileDrawQuad(const CCSharedQuadState* sharedQuadState, const IntRect& quadRect, const IntRect& opaqueRect, unsigned resourceId, const IntPoint& textureOffset, const IntSize& textureSize, GC3Dint textureFilter, bool swizzleContents, bool leftEdgeAA, bool topEdgeAA, bool rightEdgeAA, bool bottomEdgeAA) - : CCDrawQuad(sharedQuadState, CCDrawQuad::TiledContent, quadRect) - , m_resourceId(resourceId) - , m_textureOffset(textureOffset) - , m_textureSize(textureSize) - , m_textureFilter(textureFilter) - , m_swizzleContents(swizzleContents) - , m_leftEdgeAA(leftEdgeAA) - , m_topEdgeAA(topEdgeAA) - , m_rightEdgeAA(rightEdgeAA) - , m_bottomEdgeAA(bottomEdgeAA) -{ - if (isAntialiased()) - m_needsBlending = true; - m_opaqueRect = opaqueRect; -} - -const CCTileDrawQuad* CCTileDrawQuad::materialCast(const CCDrawQuad* quad) -{ - ASSERT(quad->material() == CCDrawQuad::TiledContent); - return static_cast(quad); -} - -} diff --git a/cc/CCTileDrawQuad.h b/cc/CCTileDrawQuad.h index 21a98cf..584c439 100644 --- a/cc/CCTileDrawQuad.h +++ b/cc/CCTileDrawQuad.h @@ -2,53 +2,5 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CCTileDrawQuad_h -#define CCTileDrawQuad_h - -#include "CCDrawQuad.h" -#include "GraphicsTypes3D.h" -#include "IntPoint.h" -#include "IntSize.h" -#include "base/memory/scoped_ptr.h" - -namespace cc { - -#pragma pack(push, 4) - -class CCTileDrawQuad : public CCDrawQuad { -public: - static scoped_ptr create(const CCSharedQuadState*, const IntRect& quadRect, const IntRect& opaqueRect, unsigned resourceId, const IntPoint& textureOffset, const IntSize& textureSize, GC3Dint textureFilter, bool swizzleContents, bool leftEdgeAA, bool topEdgeAA, bool rightEdgeAA, bool bottomEdgeAA); - - unsigned resourceId() const { return m_resourceId; } - IntPoint textureOffset() const { return m_textureOffset; } - IntSize textureSize() const { return m_textureSize; } - GC3Dint textureFilter() const { return m_textureFilter; } - bool swizzleContents() const { return m_swizzleContents; } - - bool leftEdgeAA() const { return m_leftEdgeAA; } - bool topEdgeAA() const { return m_topEdgeAA; } - bool rightEdgeAA() const { return m_rightEdgeAA; } - bool bottomEdgeAA() const { return m_bottomEdgeAA; } - - bool isAntialiased() const { return leftEdgeAA() || topEdgeAA() || rightEdgeAA() || bottomEdgeAA(); } - - static const CCTileDrawQuad* materialCast(const CCDrawQuad*); -private: - CCTileDrawQuad(const CCSharedQuadState*, const IntRect& quadRect, const IntRect& opaqueRect, unsigned resourceId, const IntPoint& textureOffset, const IntSize& textureSize, GC3Dint textureFilter, bool swizzleContents, bool leftEdgeAA, bool topEdgeAA, bool rightEdgeAA, bool bottomEdgeAA); - - unsigned m_resourceId; - IntPoint m_textureOffset; - IntSize m_textureSize; - GC3Dint m_textureFilter; - bool m_swizzleContents; - bool m_leftEdgeAA; - bool m_topEdgeAA; - bool m_rightEdgeAA; - bool m_bottomEdgeAA; -}; - -#pragma pack(pop) - -} - -#endif +// Temporary forwarding header +#include "cc/tile_draw_quad.h" diff --git a/cc/CCTiledLayerImpl.cpp b/cc/CCTiledLayerImpl.cpp deleted file mode 100644 index faa8ef8..0000000 --- a/cc/CCTiledLayerImpl.cpp +++ /dev/null @@ -1,253 +0,0 @@ -// Copyright 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "config.h" - -#if USE(ACCELERATED_COMPOSITING) - -#include "CCTiledLayerImpl.h" - -#include "base/basictypes.h" -#include "base/stringprintf.h" -#include "CCAppendQuadsData.h" -#include "CCCheckerboardDrawQuad.h" -#include "CCDebugBorderDrawQuad.h" -#include "CCLayerTilingData.h" -#include "CCMathUtil.h" -#include "CCQuadSink.h" -#include "CCSolidColorDrawQuad.h" -#include "CCTileDrawQuad.h" -#include "FloatQuad.h" -#include "GraphicsContext3D.h" -#include "SkColor.h" - -using namespace std; -using WebKit::WebTransformationMatrix; - -namespace cc { - -static const int debugTileBorderWidth = 1; -static const int debugTileBorderAlpha = 100; -static const int debugTileBorderColorRed = 80; -static const int debugTileBorderColorGreen = 200; -static const int debugTileBorderColorBlue = 200; -static const int debugTileBorderMissingTileColorRed = 255; -static const int debugTileBorderMissingTileColorGreen = 0; -static const int debugTileBorderMissingTileColorBlue = 0; - -static const int defaultCheckerboardColorRed = 241; -static const int defaultCheckerboardColorGreen = 241; -static const int defaultCheckerboardColorBlue = 241; -static const int debugTileEvictedCheckerboardColorRed = 255; -static const int debugTileEvictedCheckerboardColorGreen = 200; -static const int debugTileEvictedCheckerboardColorBlue = 200; -static const int debugTileInvalidatedCheckerboardColorRed = 128; -static const int debugTileInvalidatedCheckerboardColorGreen = 200; -static const int debugTileInvalidatedCheckerboardColorBlue = 245; - -class DrawableTile : public CCLayerTilingData::Tile { -public: - static PassOwnPtr create() { return adoptPtr(new DrawableTile()); } - - CCResourceProvider::ResourceId resourceId() const { return m_resourceId; } - void setResourceId(CCResourceProvider::ResourceId resourceId) { m_resourceId = resourceId; } - -private: - DrawableTile() : m_resourceId(0) { } - - CCResourceProvider::ResourceId m_resourceId; - - DISALLOW_COPY_AND_ASSIGN(DrawableTile); -}; - -CCTiledLayerImpl::CCTiledLayerImpl(int id) - : CCLayerImpl(id) - , m_skipsDraw(true) - , m_contentsSwizzled(false) -{ -} - -CCTiledLayerImpl::~CCTiledLayerImpl() -{ -} - -CCResourceProvider::ResourceId CCTiledLayerImpl::contentsResourceId() const -{ - // This function is only valid for single texture layers, e.g. masks. - ASSERT(m_tiler); - ASSERT(m_tiler->numTilesX() == 1); - ASSERT(m_tiler->numTilesY() == 1); - - DrawableTile* tile = tileAt(0, 0); - CCResourceProvider::ResourceId resourceId = tile ? tile->resourceId() : 0; - return resourceId; -} - -void CCTiledLayerImpl::dumpLayerProperties(std::string* str, int indent) const -{ - str->append(indentString(indent)); - base::StringAppendF(str, "skipsDraw: %d\n", (!m_tiler || m_skipsDraw)); - CCLayerImpl::dumpLayerProperties(str, indent); -} - -bool CCTiledLayerImpl::hasTileAt(int i, int j) const -{ - return m_tiler->tileAt(i, j); -} - -bool CCTiledLayerImpl::hasResourceIdForTileAt(int i, int j) const -{ - return hasTileAt(i, j) && tileAt(i, j)->resourceId(); -} - -DrawableTile* CCTiledLayerImpl::tileAt(int i, int j) const -{ - return static_cast(m_tiler->tileAt(i, j)); -} - -DrawableTile* CCTiledLayerImpl::createTile(int i, int j) -{ - OwnPtr tile(DrawableTile::create()); - DrawableTile* addedTile = tile.get(); - m_tiler->addTile(tile.release(), i, j); - return addedTile; -} - -void CCTiledLayerImpl::appendQuads(CCQuadSink& quadSink, CCAppendQuadsData& appendQuadsData) -{ - const IntRect& contentRect = visibleContentRect(); - - if (!m_tiler || m_tiler->hasEmptyBounds() || contentRect.isEmpty()) - return; - - CCSharedQuadState* sharedQuadState = quadSink.useSharedQuadState(createSharedQuadState()); - appendDebugBorderQuad(quadSink, sharedQuadState, appendQuadsData); - - int left, top, right, bottom; - m_tiler->contentRectToTileIndices(contentRect, left, top, right, bottom); - - if (hasDebugBorders()) { - for (int j = top; j <= bottom; ++j) { - for (int i = left; i <= right; ++i) { - DrawableTile* tile = tileAt(i, j); - IntRect tileRect = m_tiler->tileBounds(i, j); - SkColor borderColor; - - if (m_skipsDraw || !tile || !tile->resourceId()) - borderColor = SkColorSetARGB(debugTileBorderAlpha, debugTileBorderMissingTileColorRed, debugTileBorderMissingTileColorGreen, debugTileBorderMissingTileColorBlue); - else - borderColor = SkColorSetARGB(debugTileBorderAlpha, debugTileBorderColorRed, debugTileBorderColorGreen, debugTileBorderColorBlue); - quadSink.append(CCDebugBorderDrawQuad::create(sharedQuadState, tileRect, borderColor, debugTileBorderWidth).PassAs(), appendQuadsData); - } - } - } - - if (m_skipsDraw) - return; - - for (int j = top; j <= bottom; ++j) { - for (int i = left; i <= right; ++i) { - DrawableTile* tile = tileAt(i, j); - IntRect tileRect = m_tiler->tileBounds(i, j); - IntRect displayRect = tileRect; - tileRect.intersect(contentRect); - - // Skip empty tiles. - if (tileRect.isEmpty()) - continue; - - if (!tile || !tile->resourceId()) { - if (drawCheckerboardForMissingTiles()) { - SkColor defaultColor = SkColorSetRGB(defaultCheckerboardColorRed, defaultCheckerboardColorGreen, defaultCheckerboardColorBlue); - SkColor evictedColor = SkColorSetRGB(debugTileEvictedCheckerboardColorRed, debugTileEvictedCheckerboardColorGreen, debugTileEvictedCheckerboardColorBlue); - SkColor invalidatedColor = SkColorSetRGB(debugTileInvalidatedCheckerboardColorRed, debugTileEvictedCheckerboardColorGreen, debugTileEvictedCheckerboardColorBlue); - - SkColor checkerColor; - if (hasDebugBorders()) - checkerColor = tile ? invalidatedColor : evictedColor; - else - checkerColor = defaultColor; - - appendQuadsData.hadMissingTiles |= quadSink.append(CCCheckerboardDrawQuad::create(sharedQuadState, tileRect, checkerColor).PassAs(), appendQuadsData); - } else - appendQuadsData.hadMissingTiles |= quadSink.append(CCSolidColorDrawQuad::create(sharedQuadState, tileRect, backgroundColor()).PassAs(), appendQuadsData); - continue; - } - - IntRect tileOpaqueRect = tile->opaqueRect(); - tileOpaqueRect.intersect(contentRect); - - // Keep track of how the top left has moved, so the texture can be - // offset the same amount. - IntSize displayOffset = tileRect.minXMinYCorner() - displayRect.minXMinYCorner(); - IntPoint textureOffset = m_tiler->textureOffset(i, j) + displayOffset; - float tileWidth = static_cast(m_tiler->tileSize().width()); - float tileHeight = static_cast(m_tiler->tileSize().height()); - IntSize textureSize(tileWidth, tileHeight); - - bool clipped = false; - FloatQuad visibleContentInTargetQuad = CCMathUtil::mapQuad(drawTransform(), FloatQuad(visibleContentRect()), clipped); - bool isAxisAlignedInTarget = !clipped && visibleContentInTargetQuad.isRectilinear(); - bool useAA = m_tiler->hasBorderTexels() && !isAxisAlignedInTarget; - - bool leftEdgeAA = !i && useAA; - bool topEdgeAA = !j && useAA; - bool rightEdgeAA = i == m_tiler->numTilesX() - 1 && useAA; - bool bottomEdgeAA = j == m_tiler->numTilesY() - 1 && useAA; - - const GC3Dint textureFilter = m_tiler->hasBorderTexels() ? GraphicsContext3D::LINEAR : GraphicsContext3D::NEAREST; - quadSink.append(CCTileDrawQuad::create(sharedQuadState, tileRect, tileOpaqueRect, tile->resourceId(), textureOffset, textureSize, textureFilter, contentsSwizzled(), leftEdgeAA, topEdgeAA, rightEdgeAA, bottomEdgeAA).PassAs(), appendQuadsData); - } - } -} - -void CCTiledLayerImpl::setTilingData(const CCLayerTilingData& tiler) -{ - if (m_tiler) - m_tiler->reset(); - else - m_tiler = CCLayerTilingData::create(tiler.tileSize(), tiler.hasBorderTexels() ? CCLayerTilingData::HasBorderTexels : CCLayerTilingData::NoBorderTexels); - *m_tiler = tiler; -} - -void CCTiledLayerImpl::pushTileProperties(int i, int j, CCResourceProvider::ResourceId resourceId, const IntRect& opaqueRect) -{ - DrawableTile* tile = tileAt(i, j); - if (!tile) - tile = createTile(i, j); - tile->setResourceId(resourceId); - tile->setOpaqueRect(opaqueRect); -} - -void CCTiledLayerImpl::pushInvalidTile(int i, int j) -{ - DrawableTile* tile = tileAt(i, j); - if (!tile) - tile = createTile(i, j); - tile->setResourceId(0); - tile->setOpaqueRect(IntRect()); -} - -Region CCTiledLayerImpl::visibleContentOpaqueRegion() const -{ - if (m_skipsDraw) - return Region(); - if (contentsOpaque()) - return visibleContentRect(); - return m_tiler->opaqueRegionInContentRect(visibleContentRect()); -} - -void CCTiledLayerImpl::didLoseContext() -{ - m_tiler->reset(); -} - -const char* CCTiledLayerImpl::layerTypeAsString() const -{ - return "ContentLayer"; -} - -} // namespace cc - -#endif // USE(ACCELERATED_COMPOSITING) diff --git a/cc/CCTiledLayerImpl.h b/cc/CCTiledLayerImpl.h index 2d6803d..b9726e2 100644 --- a/cc/CCTiledLayerImpl.h +++ b/cc/CCTiledLayerImpl.h @@ -1,62 +1,6 @@ -// Copyright 2011 The Chromium Authors. All rights reserved. +// Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CCTiledLayerImpl_h -#define CCTiledLayerImpl_h - -#include "CCLayerImpl.h" -#include - -namespace cc { - -class CCLayerTilingData; -class DrawableTile; - -class CCTiledLayerImpl : public CCLayerImpl { -public: - static scoped_ptr create(int id) - { - return make_scoped_ptr(new CCTiledLayerImpl(id)); - } - virtual ~CCTiledLayerImpl(); - - virtual void appendQuads(CCQuadSink&, CCAppendQuadsData&) OVERRIDE; - - virtual CCResourceProvider::ResourceId contentsResourceId() const OVERRIDE; - - virtual void dumpLayerProperties(std::string*, int indent) const OVERRIDE; - - void setSkipsDraw(bool skipsDraw) { m_skipsDraw = skipsDraw; } - void setTilingData(const CCLayerTilingData& tiler); - void pushTileProperties(int, int, CCResourceProvider::ResourceId, const IntRect& opaqueRect); - void pushInvalidTile(int, int); - - void setContentsSwizzled(bool contentsSwizzled) { m_contentsSwizzled = contentsSwizzled; } - bool contentsSwizzled() const { return m_contentsSwizzled; } - - virtual Region visibleContentOpaqueRegion() const OVERRIDE; - virtual void didLoseContext() OVERRIDE; - -protected: - explicit CCTiledLayerImpl(int id); - // Exposed for testing. - bool hasTileAt(int, int) const; - bool hasResourceIdForTileAt(int, int) const; - -private: - - virtual const char* layerTypeAsString() const OVERRIDE; - - DrawableTile* tileAt(int, int) const; - DrawableTile* createTile(int, int); - - bool m_skipsDraw; - bool m_contentsSwizzled; - - OwnPtr m_tiler; -}; - -} - -#endif // CCTiledLayerImpl_h +// Temporary forwarding header +#include "cc/tiled_layer_impl.h" diff --git a/cc/CCTimeSource.h b/cc/CCTimeSource.h index 6f24d35..e0fa624 100644 --- a/cc/CCTimeSource.h +++ b/cc/CCTimeSource.h @@ -1,40 +1,6 @@ -// Copyright 2011 The Chromium Authors. All rights reserved. +// Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CCTimeSource_h -#define CCTimeSource_h - -#include "base/time.h" -#include - -namespace cc { - -class CCThread; - -class CCTimeSourceClient { -public: - virtual void onTimerTick() = 0; - -protected: - virtual ~CCTimeSourceClient() { } -}; - -// An generic interface for getting a reliably-ticking timesource of -// a specified rate. -// -// Be sure to call setActive(false) before releasing your reference to the -// timer, or it will keep on ticking! -class CCTimeSource : public RefCounted { -public: - virtual ~CCTimeSource() { } - virtual void setClient(CCTimeSourceClient*) = 0; - virtual void setActive(bool) = 0; - virtual bool active() const = 0; - virtual void setTimebaseAndInterval(base::TimeTicks timebase, base::TimeDelta interval) = 0; - virtual base::TimeTicks lastTickTime() = 0; - virtual base::TimeTicks nextTickTime() = 0; -}; - -} -#endif // CCSmoothedTimer_h +// Temporary forwarding header +#include "cc/time_source.h" diff --git a/cc/CCTimer.cpp b/cc/CCTimer.cpp deleted file mode 100644 index 089c12b..0000000 --- a/cc/CCTimer.cpp +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "config.h" - -#include "CCTimer.h" - -#include "base/compiler_specific.h" -#include "CCThread.h" - -namespace cc { - -class CCTimerTask : public CCThread::Task { -public: - explicit CCTimerTask(CCTimer* timer) - : CCThread::Task(0) - , m_timer(timer) - { - } - - virtual ~CCTimerTask() - { - if (!m_timer) - return; - - ASSERT(m_timer->m_task == this); - m_timer->stop(); - } - - virtual void performTask() OVERRIDE - { - if (!m_timer) - return; - - CCTimerClient* client = m_timer->m_client; - - m_timer->stop(); - if (client) - client->onTimerFired(); - } - -private: - friend class CCTimer; - - CCTimer* m_timer; // null if cancelled -}; - -CCTimer::CCTimer(CCThread* thread, CCTimerClient* client) - : m_client(client) - , m_thread(thread) - , m_task(0) -{ -} - -CCTimer::~CCTimer() -{ - stop(); -} - -void CCTimer::startOneShot(double intervalSeconds) -{ - stop(); - - m_task = new CCTimerTask(this); - - // The thread expects delays in milliseconds. - m_thread->postDelayedTask(adoptPtr(m_task), intervalSeconds * 1000.0); -} - -void CCTimer::stop() -{ - if (!m_task) - return; - - m_task->m_timer = 0; - m_task = 0; -} - -} // namespace cc diff --git a/cc/CCTimer.h b/cc/CCTimer.h index 9424aef..5dee85a 100644 --- a/cc/CCTimer.h +++ b/cc/CCTimer.h @@ -1,41 +1,6 @@ -// Copyright 2011 The Chromium Authors. All rights reserved. +// Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CCTimer_h -#define CCTimer_h - -namespace cc { - -class CCThread; -class CCTimerTask; - -class CCTimerClient { -public: - virtual ~CCTimerClient() { } - - virtual void onTimerFired() = 0; -}; - -class CCTimer { -public: - CCTimer(CCThread*, CCTimerClient*); - ~CCTimer(); - - // If a previous task is pending, it will be replaced with the new one. - void startOneShot(double intervalSeconds); - void stop(); - - bool isActive() const { return m_task; } - -private: - friend class CCTimerTask; - - CCTimerClient* m_client; - CCThread* m_thread; - CCTimerTask* m_task; // weak pointer -}; - -} // namespace cc - -#endif +// Temporary forwarding header +#include "cc/timer.h" diff --git a/cc/CCTimingFunction.cpp b/cc/CCTimingFunction.cpp deleted file mode 100644 index 3a4ecd4..0000000 --- a/cc/CCTimingFunction.cpp +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "config.h" - -#include "CCTimingFunction.h" - -namespace { -const double epsilon = 1e-6; -} // namespace - -namespace cc { - -CCTimingFunction::CCTimingFunction() -{ -} - -CCTimingFunction::~CCTimingFunction() -{ -} - -double CCTimingFunction::duration() const -{ - return 1.0; -} - -scoped_ptr CCCubicBezierTimingFunction::create(double x1, double y1, double x2, double y2) -{ - return make_scoped_ptr(new CCCubicBezierTimingFunction(x1, y1, x2, y2)); -} - -CCCubicBezierTimingFunction::CCCubicBezierTimingFunction(double x1, double y1, double x2, double y2) - : m_curve(x1, y1, x2, y2) -{ -} - -CCCubicBezierTimingFunction::~CCCubicBezierTimingFunction() -{ -} - -float CCCubicBezierTimingFunction::getValue(double x) const -{ - UnitBezier temp(m_curve); - return static_cast(temp.solve(x, epsilon)); -} - -scoped_ptr CCCubicBezierTimingFunction::clone() const -{ - return make_scoped_ptr(new CCCubicBezierTimingFunction(*this)).PassAs(); -} - -// These numbers come from http://www.w3.org/TR/css3-transitions/#transition-timing-function_tag. -scoped_ptr CCEaseTimingFunction::create() -{ - return CCCubicBezierTimingFunction::create(0.25, 0.1, 0.25, 1).PassAs(); -} - -scoped_ptr CCEaseInTimingFunction::create() -{ - return CCCubicBezierTimingFunction::create(0.42, 0, 1.0, 1).PassAs(); -} - -scoped_ptr CCEaseOutTimingFunction::create() -{ - return CCCubicBezierTimingFunction::create(0, 0, 0.58, 1).PassAs(); -} - -scoped_ptr CCEaseInOutTimingFunction::create() -{ - return CCCubicBezierTimingFunction::create(0.42, 0, 0.58, 1).PassAs(); -} - -} // namespace cc diff --git a/cc/CCTimingFunction.h b/cc/CCTimingFunction.h index 993ab87..82dd931 100644 --- a/cc/CCTimingFunction.h +++ b/cc/CCTimingFunction.h @@ -2,61 +2,5 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CCTimingFunction_h -#define CCTimingFunction_h - -#include "CCAnimationCurve.h" -#include "UnitBezier.h" - -namespace cc { - -// See http://www.w3.org/TR/css3-transitions/. -class CCTimingFunction : public CCFloatAnimationCurve { -public: - virtual ~CCTimingFunction(); - - // Partial implementation of CCFloatAnimationCurve. - virtual double duration() const OVERRIDE; - -protected: - CCTimingFunction(); -}; - -class CCCubicBezierTimingFunction : public CCTimingFunction { -public: - static scoped_ptr create(double x1, double y1, double x2, double y2); - virtual ~CCCubicBezierTimingFunction(); - - // Partial implementation of CCFloatAnimationCurve. - virtual float getValue(double time) const OVERRIDE; - virtual scoped_ptr clone() const OVERRIDE; - -protected: - CCCubicBezierTimingFunction(double x1, double y1, double x2, double y2); - - UnitBezier m_curve; -}; - -class CCEaseTimingFunction { -public: - static scoped_ptr create(); -}; - -class CCEaseInTimingFunction { -public: - static scoped_ptr create(); -}; - -class CCEaseOutTimingFunction { -public: - static scoped_ptr create(); -}; - -class CCEaseInOutTimingFunction { -public: - static scoped_ptr create(); -}; - -} // namespace cc - -#endif // CCTimingFunction_h +// Temporary forwarding header +#include "cc/timing_function.h" diff --git a/cc/CCVideoLayerImpl.cpp b/cc/CCVideoLayerImpl.cpp deleted file mode 100644 index d1fb412..0000000 --- a/cc/CCVideoLayerImpl.cpp +++ /dev/null @@ -1,391 +0,0 @@ -// Copyright 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "config.h" - -#if USE(ACCELERATED_COMPOSITING) - -#include "CCVideoLayerImpl.h" - -#include "CCIOSurfaceDrawQuad.h" -#include "CCLayerTreeHostImpl.h" -#include "CCProxy.h" -#include "CCQuadSink.h" -#include "CCResourceProvider.h" -#include "CCStreamVideoDrawQuad.h" -#include "CCTextureDrawQuad.h" -#include "CCYUVVideoDrawQuad.h" -#include "Extensions3DChromium.h" -#include "GraphicsContext3D.h" -#include "NotImplemented.h" -#include - -namespace cc { - -CCVideoLayerImpl::CCVideoLayerImpl(int id, WebKit::WebVideoFrameProvider* provider) - : CCLayerImpl(id) - , m_provider(provider) - , m_frame(0) - , m_externalTextureResource(0) -{ - // This matrix is the default transformation for stream textures, and flips on the Y axis. - m_streamTextureMatrix = WebKit::WebTransformationMatrix( - 1, 0, 0, 0, - 0, -1, 0, 0, - 0, 0, 1, 0, - 0, 1, 0, 1); - - // This only happens during a commit on the compositor thread while the main - // thread is blocked. That makes this a thread-safe call to set the video - // frame provider client that does not require a lock. The same is true of - // the call in the destructor. - ASSERT(CCProxy::isMainThreadBlocked()); - m_provider->setVideoFrameProviderClient(this); -} - -CCVideoLayerImpl::~CCVideoLayerImpl() -{ - // See comment in constructor for why this doesn't need a lock. - ASSERT(CCProxy::isMainThreadBlocked()); - if (m_provider) { - m_provider->setVideoFrameProviderClient(0); - m_provider = 0; - } - freePlaneData(layerTreeHostImpl()->resourceProvider()); - -#if !ASSERT_DISABLED - for (unsigned i = 0; i < WebKit::WebVideoFrame::maxPlanes; ++i) - ASSERT(!m_framePlanes[i].resourceId); - ASSERT(!m_externalTextureResource); -#endif -} - -void CCVideoLayerImpl::stopUsingProvider() -{ - // Block the provider from shutting down until this client is done - // using the frame. - MutexLocker locker(m_providerMutex); - ASSERT(!m_frame); - m_provider = 0; -} - -// Convert WebKit::WebVideoFrame::Format to GraphicsContext3D's format enum values. -static GC3Denum convertVFCFormatToGC3DFormat(const WebKit::WebVideoFrame& frame) -{ - switch (frame.format()) { - case WebKit::WebVideoFrame::FormatYV12: - case WebKit::WebVideoFrame::FormatYV16: - return GraphicsContext3D::LUMINANCE; - case WebKit::WebVideoFrame::FormatNativeTexture: - return frame.textureTarget(); - case WebKit::WebVideoFrame::FormatInvalid: - case WebKit::WebVideoFrame::FormatRGB32: - case WebKit::WebVideoFrame::FormatEmpty: - case WebKit::WebVideoFrame::FormatI420: - notImplemented(); - } - return GraphicsContext3D::INVALID_VALUE; -} - -void CCVideoLayerImpl::willDraw(CCResourceProvider* resourceProvider) -{ - ASSERT(CCProxy::isImplThread()); - CCLayerImpl::willDraw(resourceProvider); - - // Explicitly lock and unlock the provider mutex so it can be held from - // willDraw to didDraw. Since the compositor thread is in the middle of - // drawing, the layer will not be destroyed before didDraw is called. - // Therefore, the only thing that will prevent this lock from being released - // is the GPU process locking it. As the GPU process can't cause the - // destruction of the provider (calling stopUsingProvider), holding this - // lock should not cause a deadlock. - m_providerMutex.lock(); - - willDrawInternal(resourceProvider); - freeUnusedPlaneData(resourceProvider); - - if (!m_frame) - m_providerMutex.unlock(); -} - -void CCVideoLayerImpl::willDrawInternal(CCResourceProvider* resourceProvider) -{ - ASSERT(CCProxy::isImplThread()); - ASSERT(!m_externalTextureResource); - - if (!m_provider) { - m_frame = 0; - return; - } - - m_frame = m_provider->getCurrentFrame(); - - if (!m_frame) - return; - - m_format = convertVFCFormatToGC3DFormat(*m_frame); - - if (m_format == GraphicsContext3D::INVALID_VALUE) { - m_provider->putCurrentFrame(m_frame); - m_frame = 0; - return; - } - - if (m_frame->planes() > WebKit::WebVideoFrame::maxPlanes) { - m_provider->putCurrentFrame(m_frame); - m_frame = 0; - return; - } - - if (!allocatePlaneData(resourceProvider)) { - m_provider->putCurrentFrame(m_frame); - m_frame = 0; - return; - } - - if (!copyPlaneData(resourceProvider)) { - m_provider->putCurrentFrame(m_frame); - m_frame = 0; - return; - } - - if (m_format == GraphicsContext3D::TEXTURE_2D) - m_externalTextureResource = resourceProvider->createResourceFromExternalTexture(m_frame->textureId()); -} - -void CCVideoLayerImpl::appendQuads(CCQuadSink& quadSink, CCAppendQuadsData& appendQuadsData) -{ - ASSERT(CCProxy::isImplThread()); - - if (!m_frame) - return; - - CCSharedQuadState* sharedQuadState = quadSink.useSharedQuadState(createSharedQuadState()); - appendDebugBorderQuad(quadSink, sharedQuadState, appendQuadsData); - - // FIXME: When we pass quads out of process, we need to double-buffer, or - // otherwise synchonize use of all textures in the quad. - - IntRect quadRect(IntPoint(), contentBounds()); - - switch (m_format) { - case GraphicsContext3D::LUMINANCE: { - // YUV software decoder. - const FramePlane& yPlane = m_framePlanes[WebKit::WebVideoFrame::yPlane]; - const FramePlane& uPlane = m_framePlanes[WebKit::WebVideoFrame::uPlane]; - const FramePlane& vPlane = m_framePlanes[WebKit::WebVideoFrame::vPlane]; - scoped_ptr yuvVideoQuad = CCYUVVideoDrawQuad::create(sharedQuadState, quadRect, yPlane, uPlane, vPlane); - quadSink.append(yuvVideoQuad.PassAs(), appendQuadsData); - break; - } - case GraphicsContext3D::RGBA: { - // RGBA software decoder. - const FramePlane& plane = m_framePlanes[WebKit::WebVideoFrame::rgbPlane]; - float widthScaleFactor = static_cast(plane.visibleSize.width()) / plane.size.width(); - - bool premultipliedAlpha = true; - FloatRect uvRect(0, 0, widthScaleFactor, 1); - bool flipped = false; - scoped_ptr textureQuad = CCTextureDrawQuad::create(sharedQuadState, quadRect, plane.resourceId, premultipliedAlpha, uvRect, flipped); - quadSink.append(textureQuad.PassAs(), appendQuadsData); - break; - } - case GraphicsContext3D::TEXTURE_2D: { - // NativeTexture hardware decoder. - bool premultipliedAlpha = true; - FloatRect uvRect(0, 0, 1, 1); - bool flipped = false; - scoped_ptr textureQuad = CCTextureDrawQuad::create(sharedQuadState, quadRect, m_externalTextureResource, premultipliedAlpha, uvRect, flipped); - quadSink.append(textureQuad.PassAs(), appendQuadsData); - break; - } - case Extensions3D::TEXTURE_RECTANGLE_ARB: { - IntSize textureSize(m_frame->width(), m_frame->height()); - scoped_ptr ioSurfaceQuad = CCIOSurfaceDrawQuad::create(sharedQuadState, quadRect, textureSize, m_frame->textureId(), CCIOSurfaceDrawQuad::Unflipped); - quadSink.append(ioSurfaceQuad.PassAs(), appendQuadsData); - break; - } - case Extensions3DChromium::GL_TEXTURE_EXTERNAL_OES: { - // StreamTexture hardware decoder. - scoped_ptr streamVideoQuad = CCStreamVideoDrawQuad::create(sharedQuadState, quadRect, m_frame->textureId(), m_streamTextureMatrix); - quadSink.append(streamVideoQuad.PassAs(), appendQuadsData); - break; - } - default: - CRASH(); // Someone updated convertVFCFormatToGC3DFormat above but update this! - } -} - -void CCVideoLayerImpl::didDraw(CCResourceProvider* resourceProvider) -{ - ASSERT(CCProxy::isImplThread()); - CCLayerImpl::didDraw(resourceProvider); - - if (!m_frame) - return; - - if (m_format == GraphicsContext3D::TEXTURE_2D) { - ASSERT(m_externalTextureResource); - // FIXME: the following assert will not be true when sending resources to a - // parent compositor. We will probably need to hold on to m_frame for - // longer, and have several "current frames" in the pipeline. - ASSERT(!resourceProvider->inUseByConsumer(m_externalTextureResource)); - resourceProvider->deleteResource(m_externalTextureResource); - m_externalTextureResource = 0; - } - - m_provider->putCurrentFrame(m_frame); - m_frame = 0; - - m_providerMutex.unlock(); -} - -static int videoFrameDimension(int originalDimension, unsigned plane, int format) -{ - if (format == WebKit::WebVideoFrame::FormatYV12 && plane != WebKit::WebVideoFrame::yPlane) - return originalDimension / 2; - return originalDimension; -} - -static bool hasPaddingBytes(const WebKit::WebVideoFrame& frame, unsigned plane) -{ - return frame.stride(plane) > videoFrameDimension(frame.width(), plane, frame.format()); -} - -IntSize CCVideoLayerImpl::computeVisibleSize(const WebKit::WebVideoFrame& frame, unsigned plane) -{ - int visibleWidth = videoFrameDimension(frame.width(), plane, frame.format()); - int originalWidth = visibleWidth; - int visibleHeight = videoFrameDimension(frame.height(), plane, frame.format()); - - // When there are dead pixels at the edge of the texture, decrease - // the frame width by 1 to prevent the rightmost pixels from - // interpolating with the dead pixels. - if (hasPaddingBytes(frame, plane)) - --visibleWidth; - - // In YV12, every 2x2 square of Y values corresponds to one U and - // one V value. If we decrease the width of the UV plane, we must decrease the - // width of the Y texture by 2 for proper alignment. This must happen - // always, even if Y's texture does not have padding bytes. - if (plane == WebKit::WebVideoFrame::yPlane && frame.format() == WebKit::WebVideoFrame::FormatYV12) { - if (hasPaddingBytes(frame, WebKit::WebVideoFrame::uPlane)) - visibleWidth = originalWidth - 2; - } - - return IntSize(visibleWidth, visibleHeight); -} - -bool CCVideoLayerImpl::FramePlane::allocateData(CCResourceProvider* resourceProvider) -{ - if (resourceId) - return true; - - resourceId = resourceProvider->createResource(CCRenderer::ImplPool, size, format, CCResourceProvider::TextureUsageAny); - return resourceId; -} - -void CCVideoLayerImpl::FramePlane::freeData(CCResourceProvider* resourceProvider) -{ - if (!resourceId) - return; - - resourceProvider->deleteResource(resourceId); - resourceId = 0; -} - -bool CCVideoLayerImpl::allocatePlaneData(CCResourceProvider* resourceProvider) -{ - int maxTextureSize = resourceProvider->maxTextureSize(); - for (unsigned planeIndex = 0; planeIndex < m_frame->planes(); ++planeIndex) { - CCVideoLayerImpl::FramePlane& plane = m_framePlanes[planeIndex]; - - IntSize requiredTextureSize(m_frame->stride(planeIndex), videoFrameDimension(m_frame->height(), planeIndex, m_frame->format())); - // FIXME: Remove the test against maxTextureSize when tiled layers are implemented. - if (requiredTextureSize.isZero() || requiredTextureSize.width() > maxTextureSize || requiredTextureSize.height() > maxTextureSize) - return false; - - if (plane.size != requiredTextureSize || plane.format != m_format) { - plane.freeData(resourceProvider); - plane.size = requiredTextureSize; - plane.format = m_format; - } - - if (!plane.resourceId) { - if (!plane.allocateData(resourceProvider)) - return false; - plane.visibleSize = computeVisibleSize(*m_frame, planeIndex); - } - } - return true; -} - -bool CCVideoLayerImpl::copyPlaneData(CCResourceProvider* resourceProvider) -{ - size_t softwarePlaneCount = m_frame->planes(); - if (!softwarePlaneCount) - return true; - - for (size_t softwarePlaneIndex = 0; softwarePlaneIndex < softwarePlaneCount; ++softwarePlaneIndex) { - CCVideoLayerImpl::FramePlane& plane = m_framePlanes[softwarePlaneIndex]; - const uint8_t* softwarePlanePixels = static_cast(m_frame->data(softwarePlaneIndex)); - IntRect planeRect(IntPoint(), plane.size); - resourceProvider->upload(plane.resourceId, softwarePlanePixels, planeRect, planeRect, IntSize()); - } - return true; -} - -void CCVideoLayerImpl::freePlaneData(CCResourceProvider* resourceProvider) -{ - for (unsigned i = 0; i < WebKit::WebVideoFrame::maxPlanes; ++i) - m_framePlanes[i].freeData(resourceProvider); -} - -void CCVideoLayerImpl::freeUnusedPlaneData(CCResourceProvider* resourceProvider) -{ - unsigned firstUnusedPlane = m_frame ? m_frame->planes() : 0; - for (unsigned i = firstUnusedPlane; i < WebKit::WebVideoFrame::maxPlanes; ++i) - m_framePlanes[i].freeData(resourceProvider); -} - -void CCVideoLayerImpl::didReceiveFrame() -{ - setNeedsRedraw(); -} - -void CCVideoLayerImpl::didUpdateMatrix(const float matrix[16]) -{ - m_streamTextureMatrix = WebKit::WebTransformationMatrix( - 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]); - setNeedsRedraw(); -} - -void CCVideoLayerImpl::didLoseContext() -{ - freePlaneData(layerTreeHostImpl()->resourceProvider()); -} - -void CCVideoLayerImpl::setNeedsRedraw() -{ - layerTreeHostImpl()->setNeedsRedraw(); -} - -void CCVideoLayerImpl::dumpLayerProperties(std::string* str, int indent) const -{ - str->append(indentString(indent)); - str->append("video layer\n"); - CCLayerImpl::dumpLayerProperties(str, indent); -} - -const char* CCVideoLayerImpl::layerTypeAsString() const -{ - return "VideoLayer"; -} - -} - -#endif // USE(ACCELERATED_COMPOSITING) diff --git a/cc/CCVideoLayerImpl.h b/cc/CCVideoLayerImpl.h index b254e8c..f147549 100644 --- a/cc/CCVideoLayerImpl.h +++ b/cc/CCVideoLayerImpl.h @@ -2,88 +2,5 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CCVideoLayerImpl_h -#define CCVideoLayerImpl_h - -#include "CCLayerImpl.h" -#include "GraphicsContext3D.h" -#include "IntSize.h" -#include -#include - -namespace WebKit { -class WebVideoFrame; -} - -namespace cc { - -class CCLayerTreeHostImpl; -class CCVideoLayerImpl; - -class CCVideoLayerImpl : public CCLayerImpl - , public WebKit::WebVideoFrameProvider::Client { -public: - static scoped_ptr create(int id, WebKit::WebVideoFrameProvider* provider) - { - return make_scoped_ptr(new CCVideoLayerImpl(id, provider)); - } - virtual ~CCVideoLayerImpl(); - - virtual void willDraw(CCResourceProvider*) OVERRIDE; - virtual void appendQuads(CCQuadSink&, CCAppendQuadsData&) OVERRIDE; - virtual void didDraw(CCResourceProvider*) OVERRIDE; - - virtual void dumpLayerProperties(std::string*, int indent) const OVERRIDE; - - Mutex& providerMutex() { return m_providerMutex; } - - // WebKit::WebVideoFrameProvider::Client implementation. - virtual void stopUsingProvider(); // Callable on any thread. - virtual void didReceiveFrame(); // Callable on impl thread. - virtual void didUpdateMatrix(const float*); // Callable on impl thread. - - virtual void didLoseContext() OVERRIDE; - - void setNeedsRedraw(); - - struct FramePlane { - CCResourceProvider::ResourceId resourceId; - IntSize size; - GC3Denum format; - IntSize visibleSize; - - FramePlane() : resourceId(0) { } - - bool allocateData(CCResourceProvider*); - void freeData(CCResourceProvider*); - }; - -private: - CCVideoLayerImpl(int, WebKit::WebVideoFrameProvider*); - - static IntSize computeVisibleSize(const WebKit::WebVideoFrame&, unsigned plane); - virtual const char* layerTypeAsString() const OVERRIDE; - - void willDrawInternal(CCResourceProvider*); - bool allocatePlaneData(CCResourceProvider*); - bool copyPlaneData(CCResourceProvider*); - void freePlaneData(CCResourceProvider*); - void freeUnusedPlaneData(CCResourceProvider*); - - // Guards the destruction of m_provider and the frame that it provides - Mutex m_providerMutex; - WebKit::WebVideoFrameProvider* m_provider; - - WebKit::WebTransformationMatrix m_streamTextureMatrix; - - WebKit::WebVideoFrame* m_frame; - GC3Denum m_format; - CCResourceProvider::ResourceId m_externalTextureResource; - - // Each index in this array corresponds to a plane in WebKit::WebVideoFrame. - FramePlane m_framePlanes[WebKit::WebVideoFrame::maxPlanes]; -}; - -} - -#endif // CCVideoLayerImpl_h +// Temporary forwarding header +#include "cc/video_layer_impl.h" diff --git a/cc/CCYUVVideoDrawQuad.cpp b/cc/CCYUVVideoDrawQuad.cpp deleted file mode 100644 index 41d5490..0000000 --- a/cc/CCYUVVideoDrawQuad.cpp +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "config.h" - -#include "CCYUVVideoDrawQuad.h" - -namespace cc { - -scoped_ptr CCYUVVideoDrawQuad::create(const CCSharedQuadState* sharedQuadState, const IntRect& quadRect, const CCVideoLayerImpl::FramePlane& yPlane, const CCVideoLayerImpl::FramePlane& uPlane, const CCVideoLayerImpl::FramePlane& vPlane) -{ - return make_scoped_ptr(new CCYUVVideoDrawQuad(sharedQuadState, quadRect, yPlane, uPlane, vPlane)); -} - -CCYUVVideoDrawQuad::CCYUVVideoDrawQuad(const CCSharedQuadState* sharedQuadState, const IntRect& quadRect, const CCVideoLayerImpl::FramePlane& yPlane, const CCVideoLayerImpl::FramePlane& uPlane, const CCVideoLayerImpl::FramePlane& vPlane) - : CCDrawQuad(sharedQuadState, CCDrawQuad::YUVVideoContent, quadRect) - , m_yPlane(yPlane) - , m_uPlane(uPlane) - , m_vPlane(vPlane) -{ -} - -const CCYUVVideoDrawQuad* CCYUVVideoDrawQuad::materialCast(const CCDrawQuad* quad) -{ - ASSERT(quad->material() == CCDrawQuad::YUVVideoContent); - return static_cast(quad); -} - -} // namespace cc diff --git a/cc/CCYUVVideoDrawQuad.h b/cc/CCYUVVideoDrawQuad.h index 5d574b7b..ebdd1e5 100644 --- a/cc/CCYUVVideoDrawQuad.h +++ b/cc/CCYUVVideoDrawQuad.h @@ -2,35 +2,5 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CCYUVVideoDrawQuad_h -#define CCYUVVideoDrawQuad_h - -#include "base/basictypes.h" -#include "base/memory/scoped_ptr.h" -#include "CCDrawQuad.h" -#include "CCVideoLayerImpl.h" - -namespace cc { - -class CCYUVVideoDrawQuad : public CCDrawQuad { -public: - static scoped_ptr create(const CCSharedQuadState*, const IntRect&, const CCVideoLayerImpl::FramePlane& yPlane, const CCVideoLayerImpl::FramePlane& uPlane, const CCVideoLayerImpl::FramePlane& vPlane); - - const CCVideoLayerImpl::FramePlane& yPlane() const { return m_yPlane; } - const CCVideoLayerImpl::FramePlane& uPlane() const { return m_uPlane; } - const CCVideoLayerImpl::FramePlane& vPlane() const { return m_vPlane; } - - static const CCYUVVideoDrawQuad* materialCast(const CCDrawQuad*); -private: - CCYUVVideoDrawQuad(const CCSharedQuadState*, const IntRect&, const CCVideoLayerImpl::FramePlane& yPlane, const CCVideoLayerImpl::FramePlane& uPlane, const CCVideoLayerImpl::FramePlane& vPlane); - - CCVideoLayerImpl::FramePlane m_yPlane; - CCVideoLayerImpl::FramePlane m_uPlane; - CCVideoLayerImpl::FramePlane m_vPlane; - - DISALLOW_COPY_AND_ASSIGN(CCYUVVideoDrawQuad); -}; - -} - -#endif +// Temporary forwarding header +#include "cc/yuv_video_draw_quad.h" diff --git a/cc/CanvasLayerTextureUpdater.cpp b/cc/CanvasLayerTextureUpdater.cpp deleted file mode 100644 index eae5d16a..0000000 --- a/cc/CanvasLayerTextureUpdater.cpp +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - - -#include "config.h" - -#if USE(ACCELERATED_COMPOSITING) - -#include "CanvasLayerTextureUpdater.h" - -#include "CCRenderingStats.h" -#include "FloatRect.h" -#include "LayerPainterChromium.h" -#include "SkCanvas.h" -#include "SkPaint.h" -#include "SkRect.h" -#include "SkiaUtils.h" -#include "TraceEvent.h" -#include - -namespace cc { - -CanvasLayerTextureUpdater::CanvasLayerTextureUpdater(PassOwnPtr painter) - : m_painter(painter) -{ -} - -CanvasLayerTextureUpdater::~CanvasLayerTextureUpdater() -{ -} - -void CanvasLayerTextureUpdater::paintContents(SkCanvas* canvas, const IntRect& contentRect, float contentsWidthScale, float contentsHeightScale, IntRect& resultingOpaqueRect, CCRenderingStats& stats) -{ - TRACE_EVENT0("cc", "CanvasLayerTextureUpdater::paintContents"); - canvas->save(); - canvas->translate(CCFloatToSkScalar(-contentRect.x()), CCFloatToSkScalar(-contentRect.y())); - - IntRect layerRect = contentRect; - - if (contentsWidthScale != 1 || contentsHeightScale != 1) { - canvas->scale(CCFloatToSkScalar(contentsWidthScale), CCFloatToSkScalar(contentsHeightScale)); - - FloatRect rect = contentRect; - rect.scale(1 / contentsWidthScale, 1 / contentsHeightScale); - layerRect = enclosingIntRect(rect); - } - - SkPaint paint; - paint.setAntiAlias(false); - paint.setXfermodeMode(SkXfermode::kClear_Mode); - SkRect layerSkRect = SkRect::MakeXYWH(layerRect.x(), layerRect.y(), layerRect.width(), layerRect.height()); - canvas->drawRect(layerSkRect, paint); - canvas->clipRect(layerSkRect); - - FloatRect opaqueLayerRect; - double paintBeginTime = monotonicallyIncreasingTime(); - m_painter->paint(canvas, layerRect, opaqueLayerRect); - stats.totalPaintTimeInSeconds += monotonicallyIncreasingTime() - paintBeginTime; - canvas->restore(); - - FloatRect opaqueContentRect = opaqueLayerRect; - opaqueContentRect.scale(contentsWidthScale, contentsHeightScale); - resultingOpaqueRect = enclosedIntRect(opaqueContentRect); - - m_contentRect = contentRect; -} - -} // namespace cc -#endif // USE(ACCELERATED_COMPOSITING) diff --git a/cc/CanvasLayerTextureUpdater.h b/cc/CanvasLayerTextureUpdater.h index c8bb9b0..cb14510 100644 --- a/cc/CanvasLayerTextureUpdater.h +++ b/cc/CanvasLayerTextureUpdater.h @@ -1,39 +1,6 @@ -// Copyright 2011 The Chromium Authors. All rights reserved. +// Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. - -#ifndef CanvasLayerTextureUpdater_h -#define CanvasLayerTextureUpdater_h - -#if USE(ACCELERATED_COMPOSITING) - -#include "LayerTextureUpdater.h" - -class SkCanvas; - -namespace cc { - -class LayerPainterChromium; - -// Base class for BitmapCanvasLayerTextureUpdater and -// SkPictureCanvasLayerTextureUpdater that reduces code duplication between -// their respective paintContents implementations. -class CanvasLayerTextureUpdater : public LayerTextureUpdater { -public: - virtual ~CanvasLayerTextureUpdater(); - -protected: - explicit CanvasLayerTextureUpdater(PassOwnPtr); - - void paintContents(SkCanvas*, const IntRect& contentRect, float contentsWidthScale, float contentsHeightScale, IntRect& resultingOpaqueRect, CCRenderingStats&); - const IntRect& contentRect() const { return m_contentRect; } - -private: - IntRect m_contentRect; - OwnPtr m_painter; -}; - -} // namespace cc -#endif // USE(ACCELERATED_COMPOSITING) -#endif // CanvasLayerTextureUpdater_h +// Temporary forwarding header +#include "cc/canvas_layer_texture_updater.h" diff --git a/cc/ContentLayerChromium.cpp b/cc/ContentLayerChromium.cpp deleted file mode 100644 index ee8277b..0000000 --- a/cc/ContentLayerChromium.cpp +++ /dev/null @@ -1,113 +0,0 @@ -// Copyright 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "config.h" - -#if USE(ACCELERATED_COMPOSITING) - -#include "ContentLayerChromium.h" - -#include "base/time.h" -#include "BitmapCanvasLayerTextureUpdater.h" -#include "BitmapSkPictureCanvasLayerTextureUpdater.h" -#include "CCLayerTreeHost.h" -#include "CCSettings.h" -#include "ContentLayerChromiumClient.h" -#include "FrameBufferSkPictureCanvasLayerTextureUpdater.h" -#include "LayerPainterChromium.h" -#include - -namespace cc { - -ContentLayerPainter::ContentLayerPainter(ContentLayerChromiumClient* client) - : m_client(client) -{ -} - -PassOwnPtr ContentLayerPainter::create(ContentLayerChromiumClient* client) -{ - return adoptPtr(new ContentLayerPainter(client)); -} - -void ContentLayerPainter::paint(SkCanvas* canvas, const IntRect& contentRect, FloatRect& opaque) -{ - base::TimeTicks paintStart = base::TimeTicks::HighResNow(); - m_client->paintContents(canvas, contentRect, opaque); - base::TimeTicks paintEnd = base::TimeTicks::HighResNow(); - double pixelsPerSec = (contentRect.width() * contentRect.height()) / (paintEnd - paintStart).InSecondsF(); - WebKit::Platform::current()->histogramCustomCounts("Renderer4.AccelContentPaintDurationMS", (paintEnd - paintStart).InMillisecondsF(), 0, 120, 30); - WebKit::Platform::current()->histogramCustomCounts("Renderer4.AccelContentPaintMegapixPerSecond", pixelsPerSec / 1000000, 10, 210, 30); -} - -scoped_refptr ContentLayerChromium::create(ContentLayerChromiumClient* client) -{ - return make_scoped_refptr(new ContentLayerChromium(client)); -} - -ContentLayerChromium::ContentLayerChromium(ContentLayerChromiumClient* client) - : TiledLayerChromium() - , m_client(client) -{ -} - -ContentLayerChromium::~ContentLayerChromium() -{ -} - -bool ContentLayerChromium::drawsContent() const -{ - return TiledLayerChromium::drawsContent() && m_client; -} - -void ContentLayerChromium::setTexturePriorities(const CCPriorityCalculator& priorityCalc) -{ - // Update the tile data before creating all the layer's tiles. - updateTileSizeAndTilingOption(); - - TiledLayerChromium::setTexturePriorities(priorityCalc); -} - -void ContentLayerChromium::update(CCTextureUpdateQueue& queue, const CCOcclusionTracker* occlusion, CCRenderingStats& stats) -{ - createTextureUpdaterIfNeeded(); - TiledLayerChromium::update(queue, occlusion, stats); - m_needsDisplay = false; -} - -bool ContentLayerChromium::needMoreUpdates() -{ - return needsIdlePaint(); -} - -LayerTextureUpdater* ContentLayerChromium::textureUpdater() const -{ - return m_textureUpdater.get(); -} - -void ContentLayerChromium::createTextureUpdaterIfNeeded() -{ - if (m_textureUpdater) - return; - if (layerTreeHost()->settings().acceleratePainting) - m_textureUpdater = FrameBufferSkPictureCanvasLayerTextureUpdater::create(ContentLayerPainter::create(m_client)); - else if (CCSettings::perTilePaintingEnabled()) - m_textureUpdater = BitmapSkPictureCanvasLayerTextureUpdater::create(ContentLayerPainter::create(m_client)); - else - m_textureUpdater = BitmapCanvasLayerTextureUpdater::create(ContentLayerPainter::create(m_client)); - m_textureUpdater->setOpaque(contentsOpaque()); - - GC3Denum textureFormat = layerTreeHost()->rendererCapabilities().bestTextureFormat; - setTextureFormat(textureFormat); - setSampledTexelFormat(textureUpdater()->sampledTexelFormat(textureFormat)); -} - -void ContentLayerChromium::setContentsOpaque(bool opaque) -{ - LayerChromium::setContentsOpaque(opaque); - if (m_textureUpdater) - m_textureUpdater->setOpaque(opaque); -} - -} -#endif // USE(ACCELERATED_COMPOSITING) diff --git a/cc/ContentLayerChromium.h b/cc/ContentLayerChromium.h index b8ac462..687dbd4 100644 --- a/cc/ContentLayerChromium.h +++ b/cc/ContentLayerChromium.h @@ -1,67 +1,6 @@ -// Copyright 2010 The Chromium Authors. All rights reserved. +// Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. - -#ifndef ContentLayerChromium_h -#define ContentLayerChromium_h - -#if USE(ACCELERATED_COMPOSITING) - -#include "base/basictypes.h" -#include "LayerPainterChromium.h" -#include "TiledLayerChromium.h" - -class SkCanvas; - -namespace cc { - -class ContentLayerChromiumClient; -class FloatRect; -class IntRect; -class LayerTextureUpdater; - -class ContentLayerPainter : public LayerPainterChromium { -public: - static PassOwnPtr create(ContentLayerChromiumClient*); - - virtual void paint(SkCanvas*, const IntRect& contentRect, FloatRect& opaque) OVERRIDE; - -private: - explicit ContentLayerPainter(ContentLayerChromiumClient*); - - ContentLayerChromiumClient* m_client; - - DISALLOW_COPY_AND_ASSIGN(ContentLayerPainter); -}; - -// A layer that renders its contents into an SkCanvas. -class ContentLayerChromium : public TiledLayerChromium { -public: - static scoped_refptr create(ContentLayerChromiumClient*); - - void clearClient() { m_client = 0; } - - virtual bool drawsContent() const OVERRIDE; - virtual void setTexturePriorities(const CCPriorityCalculator&) OVERRIDE; - virtual void update(CCTextureUpdateQueue&, const CCOcclusionTracker*, CCRenderingStats&) OVERRIDE; - virtual bool needMoreUpdates() OVERRIDE; - - virtual void setContentsOpaque(bool) OVERRIDE; - -protected: - explicit ContentLayerChromium(ContentLayerChromiumClient*); - virtual ~ContentLayerChromium(); - -private: - virtual LayerTextureUpdater* textureUpdater() const OVERRIDE; - virtual void createTextureUpdaterIfNeeded() OVERRIDE; - - ContentLayerChromiumClient* m_client; - RefPtr m_textureUpdater; -}; - -} -#endif // USE(ACCELERATED_COMPOSITING) - -#endif +// Temporary forwarding header +#include "cc/content_layer.h" diff --git a/cc/ContentLayerChromiumClient.h b/cc/ContentLayerChromiumClient.h index 54a9267..2bfb52a 100644 --- a/cc/ContentLayerChromiumClient.h +++ b/cc/ContentLayerChromiumClient.h @@ -2,23 +2,5 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef ContentLayerChromiumClient_h -#define ContentLayerChromiumClient_h - -class SkCanvas; - -namespace cc { -class FloatRect; -class IntRect; - -class ContentLayerChromiumClient { -public: - virtual void paintContents(SkCanvas*, const IntRect& clip, FloatRect& opaque) = 0; - -protected: - virtual ~ContentLayerChromiumClient() { } -}; - -} - -#endif // ContentLayerChromiumClient_h +// Temporary forwarding header +#include "cc/content_layer_client.h" diff --git a/cc/DelegatedRendererLayerChromium.cpp b/cc/DelegatedRendererLayerChromium.cpp deleted file mode 100644 index 721630d..0000000 --- a/cc/DelegatedRendererLayerChromium.cpp +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "config.h" -#include "DelegatedRendererLayerChromium.h" - -#include "CCDelegatedRendererLayerImpl.h" - -namespace cc { - -scoped_refptr DelegatedRendererLayerChromium::create() -{ - return scoped_refptr(new DelegatedRendererLayerChromium()); -} - -DelegatedRendererLayerChromium::DelegatedRendererLayerChromium() - : LayerChromium() -{ - setIsDrawable(true); - setMasksToBounds(true); -} - -DelegatedRendererLayerChromium::~DelegatedRendererLayerChromium() -{ -} - -scoped_ptr DelegatedRendererLayerChromium::createCCLayerImpl() -{ - return CCDelegatedRendererLayerImpl::create(m_layerId).PassAs(); -} - -} diff --git a/cc/DelegatedRendererLayerChromium.h b/cc/DelegatedRendererLayerChromium.h index c7f8d2c..1b7e4e2 100644 --- a/cc/DelegatedRendererLayerChromium.h +++ b/cc/DelegatedRendererLayerChromium.h @@ -2,25 +2,5 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef DelegatedRendererLayerChromium_h -#define DelegatedRendererLayerChromium_h - -#include "LayerChromium.h" - -namespace cc { - -class DelegatedRendererLayerChromium : public LayerChromium { -public: - static scoped_refptr create(); - - virtual scoped_ptr createCCLayerImpl() OVERRIDE; - -protected: - DelegatedRendererLayerChromium(); - -private: - virtual ~DelegatedRendererLayerChromium(); -}; - -} -#endif +// Temporary forwarding header +#include "cc/delegated_renderer_layer.h" diff --git a/cc/FrameBufferSkPictureCanvasLayerTextureUpdater.cpp b/cc/FrameBufferSkPictureCanvasLayerTextureUpdater.cpp deleted file mode 100644 index adfcd07..0000000 --- a/cc/FrameBufferSkPictureCanvasLayerTextureUpdater.cpp +++ /dev/null @@ -1,119 +0,0 @@ -// Copyright 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - - -#include "config.h" - -#if USE(ACCELERATED_COMPOSITING) - -#include "FrameBufferSkPictureCanvasLayerTextureUpdater.h" - -#include "CCProxy.h" -#include "LayerPainterChromium.h" -#include "SkCanvas.h" -#include "SkGpuDevice.h" -#include -#include - -using WebKit::WebGraphicsContext3D; -using WebKit::WebSharedGraphicsContext3D; - -namespace cc { - -static PassOwnPtr createAcceleratedCanvas(GrContext* grContext, - IntSize canvasSize, - unsigned textureId) -{ - GrPlatformTextureDesc textureDesc; - textureDesc.fFlags = kRenderTarget_GrPlatformTextureFlag; - textureDesc.fWidth = canvasSize.width(); - textureDesc.fHeight = canvasSize.height(); - textureDesc.fConfig = kSkia8888_GrPixelConfig; - textureDesc.fTextureHandle = textureId; - SkAutoTUnref target(grContext->createPlatformTexture(textureDesc)); - SkAutoTUnref device(new SkGpuDevice(grContext, target.get())); - return adoptPtr(new SkCanvas(device.get())); -} - -FrameBufferSkPictureCanvasLayerTextureUpdater::Texture::Texture(FrameBufferSkPictureCanvasLayerTextureUpdater* textureUpdater, scoped_ptr texture) - : LayerTextureUpdater::Texture(texture.Pass()) - , m_textureUpdater(textureUpdater) -{ -} - -FrameBufferSkPictureCanvasLayerTextureUpdater::Texture::~Texture() -{ -} - -void FrameBufferSkPictureCanvasLayerTextureUpdater::Texture::updateRect(CCResourceProvider* resourceProvider, const IntRect& sourceRect, const IntSize& destOffset) -{ - WebGraphicsContext3D* sharedContext = CCProxy::hasImplThread() ? WebSharedGraphicsContext3D::compositorThreadContext() : WebSharedGraphicsContext3D::mainThreadContext(); - GrContext* sharedGrContext = CCProxy::hasImplThread() ? WebSharedGraphicsContext3D::compositorThreadGrContext() : WebSharedGraphicsContext3D::mainThreadGrContext(); - if (!sharedContext || !sharedGrContext) - return; - textureUpdater()->updateTextureRect(sharedContext, sharedGrContext, resourceProvider, texture(), sourceRect, destOffset); -} - -PassRefPtr FrameBufferSkPictureCanvasLayerTextureUpdater::create(PassOwnPtr painter) -{ - return adoptRef(new FrameBufferSkPictureCanvasLayerTextureUpdater(painter)); -} - -FrameBufferSkPictureCanvasLayerTextureUpdater::FrameBufferSkPictureCanvasLayerTextureUpdater(PassOwnPtr painter) - : SkPictureCanvasLayerTextureUpdater(painter) -{ -} - -FrameBufferSkPictureCanvasLayerTextureUpdater::~FrameBufferSkPictureCanvasLayerTextureUpdater() -{ -} - -PassOwnPtr FrameBufferSkPictureCanvasLayerTextureUpdater::createTexture(CCPrioritizedTextureManager* manager) -{ - return adoptPtr(new Texture(this, CCPrioritizedTexture::create(manager))); -} - -LayerTextureUpdater::SampledTexelFormat FrameBufferSkPictureCanvasLayerTextureUpdater::sampledTexelFormat(GC3Denum textureFormat) -{ - // Here we directly render to the texture, so the component order is always correct. - return LayerTextureUpdater::SampledTexelFormatRGBA; -} - -void FrameBufferSkPictureCanvasLayerTextureUpdater::updateTextureRect(WebGraphicsContext3D* context, GrContext* grContext, CCResourceProvider* resourceProvider, CCPrioritizedTexture* texture, const IntRect& sourceRect, const IntSize& destOffset) -{ - texture->acquireBackingTexture(resourceProvider); - // Flush the context in which the backing texture is created so that it - // is available in other shared contexts. It is important to do here - // because the backing texture is created in one context while it is - // being written to in another. - resourceProvider->flush(); - CCResourceProvider::ScopedWriteLockGL lock(resourceProvider, texture->resourceId()); - - // Make sure ganesh uses the correct GL context. - context->makeContextCurrent(); - // Create an accelerated canvas to draw on. - OwnPtr canvas = createAcceleratedCanvas(grContext, texture->size(), lock.textureId()); - - // The compositor expects the textures to be upside-down so it can flip - // the final composited image. Ganesh renders the image upright so we - // need to do a y-flip. - canvas->translate(0.0, texture->size().height()); - canvas->scale(1.0, -1.0); - // Clip to the destination on the texture that must be updated. - canvas->clipRect(SkRect::MakeXYWH(destOffset.width(), destOffset.height(), sourceRect.width(), sourceRect.height())); - // Translate the origin of contentRect to that of destRect. - // Note that destRect is defined relative to sourceRect. - canvas->translate(contentRect().x() - sourceRect.x() + destOffset.width(), - contentRect().y() - sourceRect.y() + destOffset.height()); - drawPicture(canvas.get()); - - // Flush ganesh context so that all the rendered stuff appears on the texture. - grContext->flush(); - - // Flush the GL context so rendering results from this context are visible in the compositor's context. - context->flush(); -} - -} // namespace cc -#endif // USE(ACCELERATED_COMPOSITING) diff --git a/cc/FrameBufferSkPictureCanvasLayerTextureUpdater.h b/cc/FrameBufferSkPictureCanvasLayerTextureUpdater.h index 79093f2..78c4b33 100644 --- a/cc/FrameBufferSkPictureCanvasLayerTextureUpdater.h +++ b/cc/FrameBufferSkPictureCanvasLayerTextureUpdater.h @@ -1,52 +1,6 @@ -// Copyright 2011 The Chromium Authors. All rights reserved. +// Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. - -#ifndef FrameBufferSkPictureCanvasLayerTextureUpdater_h -#define FrameBufferSkPictureCanvasLayerTextureUpdater_h - -#if USE(ACCELERATED_COMPOSITING) - -#include "SkPictureCanvasLayerTextureUpdater.h" - -class GrContext; - -namespace WebKit { -class WebGraphicsContext3D; -class WebSharedGraphicsContext3D; -} - -namespace cc { - -// This class records the contentRect into an SkPicture, then uses accelerated -// drawing to update the texture. The accelerated drawing goes to an -// intermediate framebuffer and then is copied to the destination texture once done. -class FrameBufferSkPictureCanvasLayerTextureUpdater : public SkPictureCanvasLayerTextureUpdater { -public: - class Texture : public LayerTextureUpdater::Texture { - public: - Texture(FrameBufferSkPictureCanvasLayerTextureUpdater*, scoped_ptr); - virtual ~Texture(); - - virtual void updateRect(CCResourceProvider*, const IntRect& sourceRect, const IntSize& destOffset) OVERRIDE; - - private: - FrameBufferSkPictureCanvasLayerTextureUpdater* textureUpdater() { return m_textureUpdater; } - - FrameBufferSkPictureCanvasLayerTextureUpdater* m_textureUpdater; - }; - - static PassRefPtr create(PassOwnPtr); - virtual ~FrameBufferSkPictureCanvasLayerTextureUpdater(); - - virtual PassOwnPtr createTexture(CCPrioritizedTextureManager*) OVERRIDE; - virtual SampledTexelFormat sampledTexelFormat(GC3Denum textureFormat) OVERRIDE; - void updateTextureRect(WebKit::WebGraphicsContext3D*, GrContext*, CCResourceProvider*, CCPrioritizedTexture*, const IntRect& sourceRect, const IntSize& destOffset); - -private: - explicit FrameBufferSkPictureCanvasLayerTextureUpdater(PassOwnPtr); -}; -} // namespace cc -#endif // USE(ACCELERATED_COMPOSITING) -#endif // FrameBufferSkPictureCanvasLayerTextureUpdater_h +// Temporary forwarding header +#include "cc/frame_buffer_skpicture_canvas_layer_texture_updater.h" diff --git a/cc/GeometryBinding.cpp b/cc/GeometryBinding.cpp deleted file mode 100644 index bac1059..0000000 --- a/cc/GeometryBinding.cpp +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "config.h" - -#if USE(ACCELERATED_COMPOSITING) - -#include "GeometryBinding.h" - -#include "CCRendererGL.h" // For the GLC() macro. -#include "GraphicsContext3D.h" -#include - -namespace cc { - -GeometryBinding::GeometryBinding(WebKit::WebGraphicsContext3D* context, const FloatRect& quadVertexRect) - : m_context(context) - , m_quadVerticesVbo(0) - , m_quadElementsVbo(0) - , m_initialized(false) -{ - // Vertex positions and texture coordinates for the 4 corners of a 1x1 quad. - float vertices[] = { quadVertexRect.x(), quadVertexRect.maxY(), 0.0f, 0.0f, 1.0f, - quadVertexRect.x(), quadVertexRect.y(), 0.0f, 0.0f, 0.0f, - quadVertexRect.maxX(), quadVertexRect.y(), 0.0f, 1.0f, 0.0f, - quadVertexRect.maxX(), quadVertexRect.maxY(), 0.0f, 1.0f, 1.0f }; - uint16_t indices[] = { 0, 1, 2, 0, 2, 3, // The two triangles that make up the layer quad. - 0, 1, 2, 3}; // A line path for drawing the layer border. - - GLC(m_context, m_quadVerticesVbo = m_context->createBuffer()); - GLC(m_context, m_quadElementsVbo = m_context->createBuffer()); - GLC(m_context, m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, m_quadVerticesVbo)); - GLC(m_context, m_context->bufferData(GraphicsContext3D::ARRAY_BUFFER, sizeof(vertices), vertices, GraphicsContext3D::STATIC_DRAW)); - GLC(m_context, m_context->bindBuffer(GraphicsContext3D::ELEMENT_ARRAY_BUFFER, m_quadElementsVbo)); - GLC(m_context, m_context->bufferData(GraphicsContext3D::ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GraphicsContext3D::STATIC_DRAW)); - - m_initialized = true; -} - -GeometryBinding::~GeometryBinding() -{ - GLC(m_context, m_context->deleteBuffer(m_quadVerticesVbo)); - GLC(m_context, m_context->deleteBuffer(m_quadElementsVbo)); -} - -void GeometryBinding::prepareForDraw() -{ - GLC(m_context, m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, quadVerticesVbo())); - GLC(m_context, m_context->bindBuffer(GraphicsContext3D::ELEMENT_ARRAY_BUFFER, quadElementsVbo())); - unsigned offset = 0; - GLC(m_context, m_context->vertexAttribPointer(positionAttribLocation(), 3, GraphicsContext3D::FLOAT, false, 5 * sizeof(float), offset)); - offset += 3 * sizeof(float); - GLC(m_context, m_context->vertexAttribPointer(texCoordAttribLocation(), 2, GraphicsContext3D::FLOAT, false, 5 * sizeof(float), offset)); - GLC(m_context, m_context->enableVertexAttribArray(positionAttribLocation())); - GLC(m_context, m_context->enableVertexAttribArray(texCoordAttribLocation())); -} - -} // namespace cc - -#endif // USE(ACCELERATED_COMPOSITING) diff --git a/cc/GeometryBinding.h b/cc/GeometryBinding.h index f0b6e72..9af39a8 100644 --- a/cc/GeometryBinding.h +++ b/cc/GeometryBinding.h @@ -1,48 +1,6 @@ -// Copyright 2011 The Chromium Authors. All rights reserved. +// Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef GeometryBinding_h -#define GeometryBinding_h - -#include "FloatRect.h" - -#if USE(ACCELERATED_COMPOSITING) - -namespace WebKit { -class WebGraphicsContext3D; -} - -namespace cc { - -class GeometryBinding { -public: - GeometryBinding(WebKit::WebGraphicsContext3D*, const FloatRect& quadVertexRect); - ~GeometryBinding(); - - bool initialized() const { return m_initialized; } - - WebKit::WebGraphicsContext3D* context() const { return m_context; } - unsigned quadVerticesVbo() const { return m_quadVerticesVbo; } - unsigned quadElementsVbo() const { return m_quadElementsVbo; } - - void prepareForDraw(); - - // All layer shaders share the same attribute locations for the vertex - // positions and texture coordinates. This allows switching shaders without - // rebinding attribute arrays. - static int positionAttribLocation() { return 0; } - static int texCoordAttribLocation() { return 1; } - -private: - WebKit::WebGraphicsContext3D* m_context; - unsigned m_quadVerticesVbo; - unsigned m_quadElementsVbo; - bool m_initialized; -}; - -} // namespace cc - -#endif // USE(ACCELERATED_COMPOSITING) - -#endif +// Temporary forwarding header +#include "cc/geometry_binding.h" diff --git a/cc/HeadsUpDisplayLayerChromium.cpp b/cc/HeadsUpDisplayLayerChromium.cpp deleted file mode 100644 index 743593c..0000000 --- a/cc/HeadsUpDisplayLayerChromium.cpp +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "config.h" - -#include "HeadsUpDisplayLayerChromium.h" - -#include "CCHeadsUpDisplayLayerImpl.h" -#include "CCLayerTreeHost.h" -#include "TraceEvent.h" - -namespace cc { - -scoped_refptr HeadsUpDisplayLayerChromium::create() -{ - return make_scoped_refptr(new HeadsUpDisplayLayerChromium()); -} - -HeadsUpDisplayLayerChromium::HeadsUpDisplayLayerChromium() - : LayerChromium() -{ - - setBounds(IntSize(512, 128)); -} - -HeadsUpDisplayLayerChromium::~HeadsUpDisplayLayerChromium() -{ -} - -void HeadsUpDisplayLayerChromium::update(CCTextureUpdateQueue&, const CCOcclusionTracker*, CCRenderingStats&) -{ - const CCLayerTreeSettings& settings = layerTreeHost()->settings(); - int maxTextureSize = layerTreeHost()->rendererCapabilities().maxTextureSize; - - IntSize bounds; - if (settings.showPlatformLayerTree || settings.showDebugRects()) { - bounds.setWidth(std::min(maxTextureSize, layerTreeHost()->deviceViewportSize().width())); - bounds.setHeight(std::min(maxTextureSize, layerTreeHost()->deviceViewportSize().height())); - } else { - bounds.setWidth(512); - bounds.setHeight(128); - } - - setBounds(bounds); -} - -bool HeadsUpDisplayLayerChromium::drawsContent() const -{ - return true; -} - -void HeadsUpDisplayLayerChromium::setFontAtlas(scoped_ptr fontAtlas) -{ - m_fontAtlas = fontAtlas.Pass(); - setNeedsCommit(); -} - -scoped_ptr HeadsUpDisplayLayerChromium::createCCLayerImpl() -{ - return CCHeadsUpDisplayLayerImpl::create(m_layerId).PassAs(); -} - -void HeadsUpDisplayLayerChromium::pushPropertiesTo(CCLayerImpl* layerImpl) -{ - LayerChromium::pushPropertiesTo(layerImpl); - - if (!m_fontAtlas.get()) - return; - - CCHeadsUpDisplayLayerImpl* hudLayerImpl = static_cast(layerImpl); - hudLayerImpl->setFontAtlas(m_fontAtlas.Pass()); -} - -} diff --git a/cc/HeadsUpDisplayLayerChromium.h b/cc/HeadsUpDisplayLayerChromium.h index cd2627e..3d7a138 100644 --- a/cc/HeadsUpDisplayLayerChromium.h +++ b/cc/HeadsUpDisplayLayerChromium.h @@ -2,37 +2,5 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef HeadsUpDisplayLayerChromium_h -#define HeadsUpDisplayLayerChromium_h - -#include "base/memory/scoped_ptr.h" -#include "CCFontAtlas.h" -#include "IntSize.h" -#include "LayerChromium.h" - -namespace cc { - -class HeadsUpDisplayLayerChromium : public LayerChromium { -public: - static scoped_refptr create(); - - virtual void update(CCTextureUpdateQueue&, const CCOcclusionTracker*, CCRenderingStats&) OVERRIDE; - virtual bool drawsContent() const OVERRIDE; - - void setFontAtlas(scoped_ptr); - - virtual scoped_ptr createCCLayerImpl() OVERRIDE; - virtual void pushPropertiesTo(CCLayerImpl*) OVERRIDE; - -protected: - HeadsUpDisplayLayerChromium(); - -private: - virtual ~HeadsUpDisplayLayerChromium(); - - scoped_ptr m_fontAtlas; -}; - -} // namespace cc - -#endif +// Temporary forwarding header +#include "cc/heads_up_display_layer.h" diff --git a/cc/IOSurfaceLayerChromium.cpp b/cc/IOSurfaceLayerChromium.cpp deleted file mode 100644 index fe6d39a..0000000 --- a/cc/IOSurfaceLayerChromium.cpp +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "config.h" - -#if USE(ACCELERATED_COMPOSITING) - -#include "IOSurfaceLayerChromium.h" - -#include "CCIOSurfaceLayerImpl.h" - -namespace cc { - -scoped_refptr IOSurfaceLayerChromium::create() -{ - return make_scoped_refptr(new IOSurfaceLayerChromium()); -} - -IOSurfaceLayerChromium::IOSurfaceLayerChromium() - : LayerChromium() - , m_ioSurfaceId(0) -{ -} - -IOSurfaceLayerChromium::~IOSurfaceLayerChromium() -{ -} - -void IOSurfaceLayerChromium::setIOSurfaceProperties(uint32_t ioSurfaceId, const IntSize& size) -{ - m_ioSurfaceId = ioSurfaceId; - m_ioSurfaceSize = size; - setNeedsCommit(); -} - -scoped_ptr IOSurfaceLayerChromium::createCCLayerImpl() -{ - return CCIOSurfaceLayerImpl::create(m_layerId).PassAs(); -} - -bool IOSurfaceLayerChromium::drawsContent() const -{ - return m_ioSurfaceId && LayerChromium::drawsContent(); -} - -void IOSurfaceLayerChromium::pushPropertiesTo(CCLayerImpl* layer) -{ - LayerChromium::pushPropertiesTo(layer); - - CCIOSurfaceLayerImpl* textureLayer = static_cast(layer); - textureLayer->setIOSurfaceProperties(m_ioSurfaceId, m_ioSurfaceSize); -} - -} -#endif // USE(ACCELERATED_COMPOSITING) diff --git a/cc/IOSurfaceLayerChromium.h b/cc/IOSurfaceLayerChromium.h index f9c4b5f..085ec98 100644 --- a/cc/IOSurfaceLayerChromium.h +++ b/cc/IOSurfaceLayerChromium.h @@ -2,37 +2,5 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. - -#ifndef IOSurfaceLayerChromium_h -#define IOSurfaceLayerChromium_h - -#if USE(ACCELERATED_COMPOSITING) - -#include "LayerChromium.h" - -namespace cc { - -class IOSurfaceLayerChromium : public LayerChromium { -public: - static scoped_refptr create(); - - void setIOSurfaceProperties(uint32_t ioSurfaceId, const IntSize&); - - virtual scoped_ptr createCCLayerImpl() OVERRIDE; - virtual bool drawsContent() const OVERRIDE; - virtual void pushPropertiesTo(CCLayerImpl*) OVERRIDE; - -protected: - IOSurfaceLayerChromium(); - -private: - virtual ~IOSurfaceLayerChromium(); - - uint32_t m_ioSurfaceId; - IntSize m_ioSurfaceSize; -}; - -} -#endif // USE(ACCELERATED_COMPOSITING) - -#endif +// Temporary forwarding header +#include "cc/io_surface_layer.h" diff --git a/cc/ImageLayerChromium.cpp b/cc/ImageLayerChromium.cpp deleted file mode 100644 index c98796b..0000000 --- a/cc/ImageLayerChromium.cpp +++ /dev/null @@ -1,163 +0,0 @@ -// Copyright 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "config.h" - -#if USE(ACCELERATED_COMPOSITING) - -#include "ImageLayerChromium.h" - -#include "base/compiler_specific.h" -#include "CCLayerTreeHost.h" -#include "LayerTextureUpdater.h" -#include "PlatformColor.h" - -namespace cc { - -class ImageLayerTextureUpdater : public LayerTextureUpdater { -public: - class Texture : public LayerTextureUpdater::Texture { - public: - Texture(ImageLayerTextureUpdater* textureUpdater, scoped_ptr texture) - : LayerTextureUpdater::Texture(texture.Pass()) - , m_textureUpdater(textureUpdater) - { - } - - virtual void updateRect(CCResourceProvider* resourceProvider, const IntRect& sourceRect, const IntSize& destOffset) OVERRIDE - { - textureUpdater()->updateTextureRect(resourceProvider, texture(), sourceRect, destOffset); - } - - private: - ImageLayerTextureUpdater* textureUpdater() { return m_textureUpdater; } - - ImageLayerTextureUpdater* m_textureUpdater; - }; - - static PassRefPtr create() - { - return adoptRef(new ImageLayerTextureUpdater()); - } - - virtual ~ImageLayerTextureUpdater() { } - - virtual PassOwnPtr createTexture( - CCPrioritizedTextureManager* manager) OVERRIDE - { - return adoptPtr(new Texture(this, CCPrioritizedTexture::create(manager))); - } - - virtual SampledTexelFormat sampledTexelFormat(GC3Denum textureFormat) OVERRIDE - { - return PlatformColor::sameComponentOrder(textureFormat) ? - LayerTextureUpdater::SampledTexelFormatRGBA : LayerTextureUpdater::SampledTexelFormatBGRA; - } - - void updateTextureRect(CCResourceProvider* resourceProvider, CCPrioritizedTexture* texture, const IntRect& sourceRect, const IntSize& destOffset) - { - // Source rect should never go outside the image pixels, even if this - // is requested because the texture extends outside the image. - IntRect clippedSourceRect = sourceRect; - IntRect imageRect = IntRect(0, 0, m_bitmap.width(), m_bitmap.height()); - clippedSourceRect.intersect(imageRect); - - IntSize clippedDestOffset = destOffset + IntSize(clippedSourceRect.location() - sourceRect.location()); - - SkAutoLockPixels lock(m_bitmap); - texture->upload(resourceProvider, static_cast(m_bitmap.getPixels()), imageRect, clippedSourceRect, clippedDestOffset); - } - - void setBitmap(const SkBitmap& bitmap) - { - m_bitmap = bitmap; - } - -private: - ImageLayerTextureUpdater() { } - - SkBitmap m_bitmap; -}; - -scoped_refptr ImageLayerChromium::create() -{ - return make_scoped_refptr(new ImageLayerChromium()); -} - -ImageLayerChromium::ImageLayerChromium() - : TiledLayerChromium() -{ -} - -ImageLayerChromium::~ImageLayerChromium() -{ -} - -void ImageLayerChromium::setBitmap(const SkBitmap& bitmap) -{ - // setBitmap() currently gets called whenever there is any - // style change that affects the layer even if that change doesn't - // affect the actual contents of the image (e.g. a CSS animation). - // With this check in place we avoid unecessary texture uploads. - if (bitmap.pixelRef() && bitmap.pixelRef() == m_bitmap.pixelRef()) - return; - - m_bitmap = bitmap; - setNeedsDisplay(); -} - -void ImageLayerChromium::setTexturePriorities(const CCPriorityCalculator& priorityCalc) -{ - // Update the tile data before creating all the layer's tiles. - updateTileSizeAndTilingOption(); - - TiledLayerChromium::setTexturePriorities(priorityCalc); -} - -void ImageLayerChromium::update(CCTextureUpdateQueue& queue, const CCOcclusionTracker* occlusion, CCRenderingStats& stats) -{ - createTextureUpdaterIfNeeded(); - if (m_needsDisplay) { - m_textureUpdater->setBitmap(m_bitmap); - updateTileSizeAndTilingOption(); - invalidateContentRect(IntRect(IntPoint(), contentBounds())); - m_needsDisplay = false; - } - TiledLayerChromium::update(queue, occlusion, stats); -} - -void ImageLayerChromium::createTextureUpdaterIfNeeded() -{ - if (m_textureUpdater) - return; - - m_textureUpdater = ImageLayerTextureUpdater::create(); - GC3Denum textureFormat = layerTreeHost()->rendererCapabilities().bestTextureFormat; - setTextureFormat(textureFormat); - setSampledTexelFormat(textureUpdater()->sampledTexelFormat(textureFormat)); -} - -LayerTextureUpdater* ImageLayerChromium::textureUpdater() const -{ - return m_textureUpdater.get(); -} - -IntSize ImageLayerChromium::contentBounds() const -{ - return IntSize(m_bitmap.width(), m_bitmap.height()); -} - -bool ImageLayerChromium::drawsContent() const -{ - return !m_bitmap.isNull() && TiledLayerChromium::drawsContent(); -} - -bool ImageLayerChromium::needsContentsScale() const -{ - // Contents scale is not need for image layer because this can be done in compositor more efficiently. - return false; -} - -} -#endif // USE(ACCELERATED_COMPOSITING) diff --git a/cc/ImageLayerChromium.h b/cc/ImageLayerChromium.h index 12ac397..7b7e0c7 100644 --- a/cc/ImageLayerChromium.h +++ b/cc/ImageLayerChromium.h @@ -1,48 +1,6 @@ -// Copyright 2010 The Chromium Authors. All rights reserved. +// Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. - -#ifndef ImageLayerChromium_h -#define ImageLayerChromium_h - -#if USE(ACCELERATED_COMPOSITING) - -#include "ContentLayerChromium.h" -#include "SkBitmap.h" - -namespace cc { - -class ImageLayerTextureUpdater; - -// A Layer that contains only an Image element. -class ImageLayerChromium : public TiledLayerChromium { -public: - static scoped_refptr create(); - - virtual bool drawsContent() const OVERRIDE; - virtual void setTexturePriorities(const CCPriorityCalculator&) OVERRIDE; - virtual void update(CCTextureUpdateQueue&, const CCOcclusionTracker*, CCRenderingStats&) OVERRIDE; - virtual bool needsContentsScale() const OVERRIDE; - - void setBitmap(const SkBitmap& image); - -private: - ImageLayerChromium(); - virtual ~ImageLayerChromium(); - - void setTilingOption(TilingOption); - - virtual LayerTextureUpdater* textureUpdater() const OVERRIDE; - virtual void createTextureUpdaterIfNeeded() OVERRIDE; - virtual IntSize contentBounds() const OVERRIDE; - - SkBitmap m_bitmap; - - RefPtr m_textureUpdater; -}; - -} -#endif // USE(ACCELERATED_COMPOSITING) - -#endif +// Temporary forwarding header +#include "cc/image_layer.h" diff --git a/cc/LayerChromium.cpp b/cc/LayerChromium.cpp deleted file mode 100644 index dc3bd67..0000000 --- a/cc/LayerChromium.cpp +++ /dev/null @@ -1,799 +0,0 @@ -// Copyright 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "config.h" - -#if USE(ACCELERATED_COMPOSITING) -#include "LayerChromium.h" - -#include "CCActiveAnimation.h" -#include "CCAnimationEvents.h" -#include "CCLayerAnimationController.h" -#include "CCLayerImpl.h" -#include "CCLayerTreeHost.h" -#include "CCSettings.h" -#include -#include -#include - -using namespace std; -using WebKit::WebTransformationMatrix; - -namespace cc { - -static int s_nextLayerId = 1; - -scoped_refptr LayerChromium::create() -{ - return make_scoped_refptr(new LayerChromium()); -} - -LayerChromium::LayerChromium() - : m_needsDisplay(false) - , m_stackingOrderChanged(false) - , m_layerId(s_nextLayerId++) - , m_parent(0) - , m_layerTreeHost(0) - , m_layerAnimationController(CCLayerAnimationController::create(this)) - , m_scrollable(false) - , m_shouldScrollOnMainThread(false) - , m_haveWheelEventHandlers(false) - , m_nonFastScrollableRegionChanged(false) - , m_anchorPoint(0.5, 0.5) - , m_backgroundColor(0) - , m_debugBorderColor(0) - , m_debugBorderWidth(0) - , m_opacity(1.0) - , m_anchorPointZ(0) - , m_isContainerForFixedPositionLayers(false) - , m_fixedToContainerLayer(false) - , m_isDrawable(false) - , m_masksToBounds(false) - , m_contentsOpaque(false) - , m_doubleSided(true) - , m_useLCDText(false) - , m_preserves3D(false) - , m_useParentBackfaceVisibility(false) - , m_drawCheckerboardForMissingTiles(false) - , m_forceRenderSurface(false) - , m_replicaLayer(0) - , m_drawOpacity(0) - , m_drawOpacityIsAnimating(false) - , m_renderTarget(0) - , m_drawTransformIsAnimating(false) - , m_screenSpaceTransformIsAnimating(false) - , m_contentsScale(1.0) - , m_boundsContainPageScale(false) - , m_layerAnimationDelegate(0) - , m_layerScrollClient(0) -{ - if (m_layerId < 0) { - s_nextLayerId = 1; - m_layerId = s_nextLayerId++; - } -} - -LayerChromium::~LayerChromium() -{ - // Our parent should be holding a reference to us so there should be no - // way for us to be destroyed while we still have a parent. - ASSERT(!parent()); - - // Remove the parent reference from all children. - removeAllChildren(); -} - -void LayerChromium::setUseLCDText(bool useLCDText) -{ - m_useLCDText = useLCDText; -} - -void LayerChromium::setLayerTreeHost(CCLayerTreeHost* host) -{ - if (m_layerTreeHost == host) - return; - - m_layerTreeHost = host; - - for (size_t i = 0; i < m_children.size(); ++i) - m_children[i]->setLayerTreeHost(host); - - if (m_maskLayer) - m_maskLayer->setLayerTreeHost(host); - if (m_replicaLayer) - m_replicaLayer->setLayerTreeHost(host); - - // If this layer already has active animations, the host needs to be notified. - if (host && m_layerAnimationController->hasActiveAnimation()) - host->didAddAnimation(); -} - -void LayerChromium::setNeedsCommit() -{ - if (m_layerTreeHost) - m_layerTreeHost->setNeedsCommit(); -} - -IntRect LayerChromium::layerRectToContentRect(const WebKit::WebRect& layerRect) -{ - float widthScale = static_cast(contentBounds().width()) / bounds().width(); - float heightScale = static_cast(contentBounds().height()) / bounds().height(); - FloatRect contentRect(layerRect.x, layerRect.y, layerRect.width, layerRect.height); - contentRect.scale(widthScale, heightScale); - return enclosingIntRect(contentRect); -} - -void LayerChromium::setParent(LayerChromium* layer) -{ - ASSERT(!layer || !layer->hasAncestor(this)); - m_parent = layer; - setLayerTreeHost(m_parent ? m_parent->layerTreeHost() : 0); -} - -bool LayerChromium::hasAncestor(LayerChromium* ancestor) const -{ - for (LayerChromium* layer = parent(); layer; layer = layer->parent()) { - if (layer == ancestor) - return true; - } - return false; -} - -void LayerChromium::addChild(scoped_refptr child) -{ - insertChild(child, numChildren()); -} - -void LayerChromium::insertChild(scoped_refptr child, size_t index) -{ - index = min(index, m_children.size()); - child->removeFromParent(); - child->setParent(this); - child->m_stackingOrderChanged = true; - - LayerList::iterator iter = m_children.begin(); - m_children.insert(iter + index, child); - setNeedsCommit(); -} - -void LayerChromium::removeFromParent() -{ - if (m_parent) - m_parent->removeChild(this); -} - -void LayerChromium::removeChild(LayerChromium* child) -{ - for (LayerList::iterator iter = m_children.begin(); iter != m_children.end(); ++iter) - { - if (*iter != child) - continue; - - child->setParent(0); - m_children.erase(iter); - setNeedsCommit(); - return; - } -} - -void LayerChromium::replaceChild(LayerChromium* reference, scoped_refptr newLayer) -{ - ASSERT_ARG(reference, reference); - ASSERT_ARG(reference, reference->parent() == this); - - if (reference == newLayer) - return; - - int referenceIndex = indexOfChild(reference); - if (referenceIndex == -1) { - ASSERT_NOT_REACHED(); - return; - } - - reference->removeFromParent(); - - if (newLayer) { - newLayer->removeFromParent(); - insertChild(newLayer, referenceIndex); - } -} - -int LayerChromium::indexOfChild(const LayerChromium* reference) -{ - for (size_t i = 0; i < m_children.size(); i++) { - if (m_children[i] == reference) - return i; - } - return -1; -} - -void LayerChromium::setBounds(const IntSize& size) -{ - if (bounds() == size) - return; - - bool firstResize = bounds().isEmpty() && !size.isEmpty(); - - m_bounds = size; - - if (firstResize) - setNeedsDisplay(); - else - setNeedsCommit(); -} - -LayerChromium* LayerChromium::rootLayer() -{ - LayerChromium* layer = this; - while (layer->parent()) - layer = layer->parent(); - return layer; -} - -void LayerChromium::removeAllChildren() -{ - while (m_children.size()) { - LayerChromium* layer = m_children[0].get(); - ASSERT(layer->parent()); - layer->removeFromParent(); - } -} - -void LayerChromium::setChildren(const LayerList& children) -{ - if (children == m_children) - return; - - removeAllChildren(); - size_t listSize = children.size(); - for (size_t i = 0; i < listSize; i++) - addChild(children[i]); -} - -void LayerChromium::setAnchorPoint(const FloatPoint& anchorPoint) -{ - if (m_anchorPoint == anchorPoint) - return; - m_anchorPoint = anchorPoint; - setNeedsCommit(); -} - -void LayerChromium::setAnchorPointZ(float anchorPointZ) -{ - if (m_anchorPointZ == anchorPointZ) - return; - m_anchorPointZ = anchorPointZ; - setNeedsCommit(); -} - -void LayerChromium::setBackgroundColor(SkColor backgroundColor) -{ - if (m_backgroundColor == backgroundColor) - return; - m_backgroundColor = backgroundColor; - setNeedsCommit(); -} - -IntSize LayerChromium::contentBounds() const -{ - return bounds(); -} - -void LayerChromium::setMasksToBounds(bool masksToBounds) -{ - if (m_masksToBounds == masksToBounds) - return; - m_masksToBounds = masksToBounds; - setNeedsCommit(); -} - -void LayerChromium::setMaskLayer(LayerChromium* maskLayer) -{ - if (m_maskLayer == maskLayer) - return; - if (m_maskLayer) - m_maskLayer->setLayerTreeHost(0); - m_maskLayer = maskLayer; - if (m_maskLayer) { - m_maskLayer->setLayerTreeHost(m_layerTreeHost); - m_maskLayer->setIsMask(true); - } - setNeedsCommit(); -} - -void LayerChromium::setReplicaLayer(LayerChromium* layer) -{ - if (m_replicaLayer == layer) - return; - if (m_replicaLayer) - m_replicaLayer->setLayerTreeHost(0); - m_replicaLayer = layer; - if (m_replicaLayer) - m_replicaLayer->setLayerTreeHost(m_layerTreeHost); - setNeedsCommit(); -} - -void LayerChromium::setFilters(const WebKit::WebFilterOperations& filters) -{ - if (m_filters == filters) - return; - m_filters = filters; - setNeedsCommit(); - if (!filters.isEmpty()) - CCLayerTreeHost::setNeedsFilterContext(true); -} - -void LayerChromium::setBackgroundFilters(const WebKit::WebFilterOperations& backgroundFilters) -{ - if (m_backgroundFilters == backgroundFilters) - return; - m_backgroundFilters = backgroundFilters; - setNeedsCommit(); - if (!backgroundFilters.isEmpty()) - CCLayerTreeHost::setNeedsFilterContext(true); -} - -bool LayerChromium::needsDisplay() const -{ - return m_needsDisplay; -} - -void LayerChromium::setOpacity(float opacity) -{ - if (m_opacity == opacity) - return; - m_opacity = opacity; - setNeedsCommit(); -} - -bool LayerChromium::opacityIsAnimating() const -{ - return m_layerAnimationController->isAnimatingProperty(CCActiveAnimation::Opacity); -} - -void LayerChromium::setContentsOpaque(bool opaque) -{ - if (m_contentsOpaque == opaque) - return; - m_contentsOpaque = opaque; - setNeedsDisplay(); -} - -void LayerChromium::setPosition(const FloatPoint& position) -{ - if (m_position == position) - return; - m_position = position; - setNeedsCommit(); -} - -void LayerChromium::setSublayerTransform(const WebTransformationMatrix& sublayerTransform) -{ - if (m_sublayerTransform == sublayerTransform) - return; - m_sublayerTransform = sublayerTransform; - setNeedsCommit(); -} - -void LayerChromium::setTransform(const WebTransformationMatrix& transform) -{ - if (m_transform == transform) - return; - m_transform = transform; - setNeedsCommit(); -} - -bool LayerChromium::transformIsAnimating() const -{ - return m_layerAnimationController->isAnimatingProperty(CCActiveAnimation::Transform); -} - -void LayerChromium::setScrollPosition(const IntPoint& scrollPosition) -{ - if (m_scrollPosition == scrollPosition) - return; - m_scrollPosition = scrollPosition; - if (m_layerScrollClient) - m_layerScrollClient->didScroll(); - setNeedsCommit(); -} - -void LayerChromium::setMaxScrollPosition(const IntSize& maxScrollPosition) -{ - if (m_maxScrollPosition == maxScrollPosition) - return; - m_maxScrollPosition = maxScrollPosition; - setNeedsCommit(); -} - -void LayerChromium::setScrollable(bool scrollable) -{ - if (m_scrollable == scrollable) - return; - m_scrollable = scrollable; - setNeedsCommit(); -} - -void LayerChromium::setShouldScrollOnMainThread(bool shouldScrollOnMainThread) -{ - if (m_shouldScrollOnMainThread == shouldScrollOnMainThread) - return; - m_shouldScrollOnMainThread = shouldScrollOnMainThread; - setNeedsCommit(); -} - -void LayerChromium::setHaveWheelEventHandlers(bool haveWheelEventHandlers) -{ - if (m_haveWheelEventHandlers == haveWheelEventHandlers) - return; - m_haveWheelEventHandlers = haveWheelEventHandlers; - setNeedsCommit(); -} - -void LayerChromium::setNonFastScrollableRegion(const Region& region) -{ - if (m_nonFastScrollableRegion == region) - return; - m_nonFastScrollableRegion = region; - m_nonFastScrollableRegionChanged = true; - setNeedsCommit(); -} - -void LayerChromium::setDrawCheckerboardForMissingTiles(bool checkerboard) -{ - if (m_drawCheckerboardForMissingTiles == checkerboard) - return; - m_drawCheckerboardForMissingTiles = checkerboard; - setNeedsCommit(); -} - -void LayerChromium::setForceRenderSurface(bool force) -{ - if (m_forceRenderSurface == force) - return; - m_forceRenderSurface = force; - setNeedsCommit(); -} - -void LayerChromium::setImplTransform(const WebTransformationMatrix& transform) -{ - if (m_implTransform == transform) - return; - m_implTransform = transform; - setNeedsCommit(); -} - -void LayerChromium::setDoubleSided(bool doubleSided) -{ - if (m_doubleSided == doubleSided) - return; - m_doubleSided = doubleSided; - setNeedsCommit(); -} - -void LayerChromium::setIsDrawable(bool isDrawable) -{ - if (m_isDrawable == isDrawable) - return; - - m_isDrawable = isDrawable; - setNeedsCommit(); -} - -LayerChromium* LayerChromium::parent() const -{ - return m_parent; -} - -void LayerChromium::setNeedsDisplayRect(const FloatRect& dirtyRect) -{ - m_updateRect.unite(dirtyRect); - - // Simply mark the contents as dirty. For non-root layers, the call to - // setNeedsCommit will schedule a fresh compositing pass. - // For the root layer, setNeedsCommit has no effect. - if (!dirtyRect.isEmpty()) - m_needsDisplay = true; - - setNeedsCommit(); -} - -bool LayerChromium::descendantIsFixedToContainerLayer() const -{ - for (size_t i = 0; i < m_children.size(); ++i) { - if (m_children[i]->fixedToContainerLayer() || m_children[i]->descendantIsFixedToContainerLayer()) - return true; - } - return false; -} - -void LayerChromium::setIsContainerForFixedPositionLayers(bool isContainerForFixedPositionLayers) -{ - if (m_isContainerForFixedPositionLayers == isContainerForFixedPositionLayers) - return; - m_isContainerForFixedPositionLayers = isContainerForFixedPositionLayers; - - if (m_layerTreeHost && m_layerTreeHost->commitRequested()) - return; - - // Only request a commit if we have a fixed positioned descendant. - if (descendantIsFixedToContainerLayer()) - setNeedsCommit(); -} - -void LayerChromium::setFixedToContainerLayer(bool fixedToContainerLayer) -{ - if (m_fixedToContainerLayer == fixedToContainerLayer) - return; - m_fixedToContainerLayer = fixedToContainerLayer; - setNeedsCommit(); -} - -void LayerChromium::pushPropertiesTo(CCLayerImpl* layer) -{ - layer->setAnchorPoint(m_anchorPoint); - layer->setAnchorPointZ(m_anchorPointZ); - layer->setBackgroundColor(m_backgroundColor); - layer->setBounds(m_bounds); - layer->setContentBounds(contentBounds()); - layer->setDebugBorderColor(m_debugBorderColor); - layer->setDebugBorderWidth(m_debugBorderWidth); - layer->setDebugName(m_debugName); - layer->setDoubleSided(m_doubleSided); - layer->setDrawCheckerboardForMissingTiles(m_drawCheckerboardForMissingTiles); - layer->setForceRenderSurface(m_forceRenderSurface); - layer->setDrawsContent(drawsContent()); - layer->setFilters(filters()); - layer->setBackgroundFilters(backgroundFilters()); - layer->setUseLCDText(m_useLCDText); - layer->setMasksToBounds(m_masksToBounds); - layer->setScrollable(m_scrollable); - layer->setShouldScrollOnMainThread(m_shouldScrollOnMainThread); - layer->setHaveWheelEventHandlers(m_haveWheelEventHandlers); - // Copying a Region is more expensive than most layer properties, since it involves copying two Vectors that may be - // arbitrarily large depending on page content, so we only push the property if it's changed. - if (m_nonFastScrollableRegionChanged) { - layer->setNonFastScrollableRegion(m_nonFastScrollableRegion); - m_nonFastScrollableRegionChanged = false; - } - layer->setContentsOpaque(m_contentsOpaque); - if (!opacityIsAnimating()) - layer->setOpacity(m_opacity); - layer->setPosition(m_position); - layer->setIsContainerForFixedPositionLayers(m_isContainerForFixedPositionLayers); - layer->setFixedToContainerLayer(m_fixedToContainerLayer); - layer->setPreserves3D(preserves3D()); - layer->setUseParentBackfaceVisibility(m_useParentBackfaceVisibility); - layer->setScrollPosition(m_scrollPosition); - layer->setMaxScrollPosition(m_maxScrollPosition); - layer->setSublayerTransform(m_sublayerTransform); - if (!transformIsAnimating()) - layer->setTransform(m_transform); - - // If the main thread commits multiple times before the impl thread actually draws, then damage tracking - // will become incorrect if we simply clobber the updateRect here. The CCLayerImpl's updateRect needs to - // accumulate (i.e. union) any update changes that have occurred on the main thread. - m_updateRect.uniteIfNonZero(layer->updateRect()); - layer->setUpdateRect(m_updateRect); - - layer->setScrollDelta(layer->scrollDelta() - layer->sentScrollDelta()); - layer->setSentScrollDelta(IntSize()); - - layer->setStackingOrderChanged(m_stackingOrderChanged); - - if (maskLayer()) - maskLayer()->pushPropertiesTo(layer->maskLayer()); - if (replicaLayer()) - replicaLayer()->pushPropertiesTo(layer->replicaLayer()); - - m_layerAnimationController->pushAnimationUpdatesTo(layer->layerAnimationController()); - - // Reset any state that should be cleared for the next update. - m_stackingOrderChanged = false; - m_updateRect = FloatRect(); -} - -scoped_ptr LayerChromium::createCCLayerImpl() -{ - return CCLayerImpl::create(m_layerId); -} - -bool LayerChromium::drawsContent() const -{ - return m_isDrawable; -} - -bool LayerChromium::needMoreUpdates() -{ - return false; -} - -bool LayerChromium::needsContentsScale() const -{ - return false; -} - -void LayerChromium::setDebugBorderColor(SkColor color) -{ - m_debugBorderColor = color; - setNeedsCommit(); -} - -void LayerChromium::setDebugBorderWidth(float width) -{ - m_debugBorderWidth = width; - setNeedsCommit(); -} - -void LayerChromium::setDebugName(const std::string& debugName) -{ - m_debugName = debugName; - setNeedsCommit(); -} - -void LayerChromium::setContentsScale(float contentsScale) -{ - if (!needsContentsScale() || m_contentsScale == contentsScale) - return; - m_contentsScale = contentsScale; - - setNeedsDisplay(); -} - -void LayerChromium::setBoundsContainPageScale(bool boundsContainPageScale) -{ - for (size_t i = 0; i < m_children.size(); ++i) - m_children[i]->setBoundsContainPageScale(boundsContainPageScale); - - if (boundsContainPageScale == m_boundsContainPageScale) - return; - - m_boundsContainPageScale = boundsContainPageScale; - setNeedsDisplay(); -} - -void LayerChromium::createRenderSurface() -{ - ASSERT(!m_renderSurface); - m_renderSurface = make_scoped_ptr(new RenderSurfaceChromium(this)); - setRenderTarget(this); -} - -bool LayerChromium::descendantDrawsContent() -{ - for (size_t i = 0; i < m_children.size(); ++i) { - if (m_children[i]->drawsContent() || m_children[i]->descendantDrawsContent()) - return true; - } - return false; -} - -int LayerChromium::id() const -{ - return m_layerId; -} - -float LayerChromium::opacity() const -{ - return m_opacity; -} - -void LayerChromium::setOpacityFromAnimation(float opacity) -{ - // This is called due to an ongoing accelerated animation. Since this animation is - // also being run on the impl thread, there is no need to request a commit to push - // this value over, so set the value directly rather than calling setOpacity. - m_opacity = opacity; -} - -const WebKit::WebTransformationMatrix& LayerChromium::transform() const -{ - return m_transform; -} - -void LayerChromium::setTransformFromAnimation(const WebTransformationMatrix& transform) -{ - // This is called due to an ongoing accelerated animation. Since this animation is - // also being run on the impl thread, there is no need to request a commit to push - // this value over, so set this value directly rather than calling setTransform. - m_transform = transform; -} - -bool LayerChromium::addAnimation(scoped_ptr animation) -{ - // WebCore currently assumes that accelerated animations will start soon - // after the animation is added. However we cannot guarantee that if we do - // not have a layerTreeHost that will setNeedsCommit(). - if (!m_layerTreeHost) - return false; - - if (!CCSettings::acceleratedAnimationEnabled()) - return false; - - m_layerAnimationController->addAnimation(animation.Pass()); - if (m_layerTreeHost) { - m_layerTreeHost->didAddAnimation(); - setNeedsCommit(); - } - return true; -} - -void LayerChromium::pauseAnimation(int animationId, double timeOffset) -{ - m_layerAnimationController->pauseAnimation(animationId, timeOffset); - setNeedsCommit(); -} - -void LayerChromium::removeAnimation(int animationId) -{ - m_layerAnimationController->removeAnimation(animationId); - setNeedsCommit(); -} - -void LayerChromium::suspendAnimations(double monotonicTime) -{ - m_layerAnimationController->suspendAnimations(monotonicTime); - setNeedsCommit(); -} - -void LayerChromium::resumeAnimations(double monotonicTime) -{ - m_layerAnimationController->resumeAnimations(monotonicTime); - setNeedsCommit(); -} - -void LayerChromium::setLayerAnimationController(scoped_ptr layerAnimationController) -{ - m_layerAnimationController = layerAnimationController.Pass(); - if (m_layerAnimationController) { - m_layerAnimationController->setClient(this); - m_layerAnimationController->setForceSync(); - } - setNeedsCommit(); -} - -scoped_ptr LayerChromium::releaseLayerAnimationController() -{ - scoped_ptr toReturn = m_layerAnimationController.Pass(); - m_layerAnimationController = CCLayerAnimationController::create(this); - return toReturn.Pass(); -} - -bool LayerChromium::hasActiveAnimation() const -{ - return m_layerAnimationController->hasActiveAnimation(); -} - -void LayerChromium::notifyAnimationStarted(const CCAnimationEvent& event, double wallClockTime) -{ - m_layerAnimationController->notifyAnimationStarted(event); - if (m_layerAnimationDelegate) - m_layerAnimationDelegate->notifyAnimationStarted(wallClockTime); -} - -void LayerChromium::notifyAnimationFinished(double wallClockTime) -{ - if (m_layerAnimationDelegate) - m_layerAnimationDelegate->notifyAnimationFinished(wallClockTime); -} - -Region LayerChromium::visibleContentOpaqueRegion() const -{ - if (contentsOpaque()) - return visibleContentRect(); - return Region(); -} - -ScrollbarLayerChromium* LayerChromium::toScrollbarLayerChromium() -{ - return 0; -} - -void sortLayers(std::vector >::iterator, std::vector >::iterator, void*) -{ - // Currently we don't use z-order to decide what to paint, so there's no need to actually sort LayerChromiums. -} - -} -#endif // USE(ACCELERATED_COMPOSITING) diff --git a/cc/LayerChromium.h b/cc/LayerChromium.h index a87caa0..ea56428 100644 --- a/cc/LayerChromium.h +++ b/cc/LayerChromium.h @@ -1,390 +1,6 @@ -// Copyright 2010 The Chromium Authors. All rights reserved. +// Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. - -#ifndef LayerChromium_h -#define LayerChromium_h - -#if USE(ACCELERATED_COMPOSITING) - -#include "base/memory/ref_counted.h" -#include "CCLayerAnimationController.h" -#include "CCOcclusionTracker.h" -#include "FloatPoint.h" -#include "Region.h" -#include "RenderSurfaceChromium.h" -#include "SkColor.h" -#include -#include -#include -#include - -namespace WebKit { -class WebAnimationDelegate; -class WebLayerScrollClient; -} - -namespace cc { - -class CCActiveAnimation; -struct CCAnimationEvent; -class CCLayerAnimationDelegate; -class CCLayerImpl; -class CCLayerTreeHost; -class CCPriorityCalculator; -class CCTextureUpdateQueue; -class ScrollbarLayerChromium; -struct CCAnimationEvent; -struct CCRenderingStats; - -// Base class for composited layers. Special layer types are derived from -// this class. -class LayerChromium : public base::RefCounted, public CCLayerAnimationControllerClient { -public: - typedef std::vector > LayerList; - - static scoped_refptr create(); - - // CCLayerAnimationControllerClient implementation - virtual int id() const OVERRIDE; - virtual void setOpacityFromAnimation(float) OVERRIDE; - virtual float opacity() const OVERRIDE; - virtual void setTransformFromAnimation(const WebKit::WebTransformationMatrix&) OVERRIDE; - // A layer's transform operates layer space. That is, entirely in logical, - // non-page-scaled pixels (that is, they have page zoom baked in, but not page scale). - // The root layer is a special case -- it operates in physical pixels. - virtual const WebKit::WebTransformationMatrix& transform() const OVERRIDE; - - LayerChromium* rootLayer(); - LayerChromium* parent() const; - void addChild(scoped_refptr); - void insertChild(scoped_refptr, size_t index); - void replaceChild(LayerChromium* reference, scoped_refptr newLayer); - void removeFromParent(); - void removeAllChildren(); - void setChildren(const LayerList&); - - const LayerList& children() const { return m_children; } - - void setAnchorPoint(const FloatPoint&); - FloatPoint anchorPoint() const { return m_anchorPoint; } - - void setAnchorPointZ(float); - float anchorPointZ() const { return m_anchorPointZ; } - - void setBackgroundColor(SkColor); - SkColor backgroundColor() const { return m_backgroundColor; } - - // A layer's bounds are in logical, non-page-scaled pixels (however, the - // root layer's bounds are in physical pixels). - void setBounds(const IntSize&); - const IntSize& bounds() const { return m_bounds; } - virtual IntSize contentBounds() const; - - void setMasksToBounds(bool); - bool masksToBounds() const { return m_masksToBounds; } - - void setMaskLayer(LayerChromium*); - LayerChromium* maskLayer() const { return m_maskLayer.get(); } - - virtual void setNeedsDisplayRect(const FloatRect& dirtyRect); - void setNeedsDisplay() { setNeedsDisplayRect(FloatRect(FloatPoint(), bounds())); } - virtual bool needsDisplay() const; - - void setOpacity(float); - bool opacityIsAnimating() const; - - void setFilters(const WebKit::WebFilterOperations&); - const WebKit::WebFilterOperations& filters() const { return m_filters; } - - // Background filters are filters applied to what is behind this layer, when they are viewed through non-opaque - // regions in this layer. They are used through the WebLayer interface, and are not exposed to HTML. - void setBackgroundFilters(const WebKit::WebFilterOperations&); - const WebKit::WebFilterOperations& backgroundFilters() const { return m_backgroundFilters; } - - virtual void setContentsOpaque(bool); - bool contentsOpaque() const { return m_contentsOpaque; } - - void setPosition(const FloatPoint&); - FloatPoint position() const { return m_position; } - - void setIsContainerForFixedPositionLayers(bool); - bool isContainerForFixedPositionLayers() const { return m_isContainerForFixedPositionLayers; } - - void setFixedToContainerLayer(bool); - bool fixedToContainerLayer() const { return m_fixedToContainerLayer; } - - void setSublayerTransform(const WebKit::WebTransformationMatrix&); - const WebKit::WebTransformationMatrix& sublayerTransform() const { return m_sublayerTransform; } - - void setTransform(const WebKit::WebTransformationMatrix&); - bool transformIsAnimating() const; - - const IntRect& visibleContentRect() const { return m_visibleContentRect; } - void setVisibleContentRect(const IntRect& visibleContentRect) { m_visibleContentRect = visibleContentRect; } - - void setScrollPosition(const IntPoint&); - const IntPoint& scrollPosition() const { return m_scrollPosition; } - - void setMaxScrollPosition(const IntSize&); - const IntSize& maxScrollPosition() const { return m_maxScrollPosition; } - - void setScrollable(bool); - bool scrollable() const { return m_scrollable; } - - void setShouldScrollOnMainThread(bool); - bool shouldScrollOnMainThread() const { return m_shouldScrollOnMainThread; } - - void setHaveWheelEventHandlers(bool); - bool haveWheelEventHandlers() const { return m_haveWheelEventHandlers; } - - void setNonFastScrollableRegion(const Region&); - void setNonFastScrollableRegionChanged() { m_nonFastScrollableRegionChanged = true; } - const Region& nonFastScrollableRegion() const { return m_nonFastScrollableRegion; } - - void setLayerScrollClient(WebKit::WebLayerScrollClient* layerScrollClient) { m_layerScrollClient = layerScrollClient; } - - void setDrawCheckerboardForMissingTiles(bool); - bool drawCheckerboardForMissingTiles() const { return m_drawCheckerboardForMissingTiles; } - - bool forceRenderSurface() const { return m_forceRenderSurface; } - void setForceRenderSurface(bool); - - IntSize scrollDelta() const { return IntSize(); } - - void setImplTransform(const WebKit::WebTransformationMatrix&); - const WebKit::WebTransformationMatrix& implTransform() const { return m_implTransform; } - - void setDoubleSided(bool); - bool doubleSided() const { return m_doubleSided; } - - void setPreserves3D(bool preserve3D) { m_preserves3D = preserve3D; } - bool preserves3D() const { return m_preserves3D; } - - void setUseParentBackfaceVisibility(bool useParentBackfaceVisibility) { m_useParentBackfaceVisibility = useParentBackfaceVisibility; } - bool useParentBackfaceVisibility() const { return m_useParentBackfaceVisibility; } - - virtual void setUseLCDText(bool); - bool useLCDText() const { return m_useLCDText; } - - virtual void setLayerTreeHost(CCLayerTreeHost*); - - bool hasContributingDelegatedRenderPasses() const { return false; } - - void setIsDrawable(bool); - - void setReplicaLayer(LayerChromium*); - LayerChromium* replicaLayer() const { return m_replicaLayer.get(); } - - bool hasMask() const { return m_maskLayer; } - bool hasReplica() const { return m_replicaLayer; } - bool replicaHasMask() const { return m_replicaLayer && (m_maskLayer || m_replicaLayer->m_maskLayer); } - - // These methods typically need to be overwritten by derived classes. - virtual bool drawsContent() const; - virtual void update(CCTextureUpdateQueue&, const CCOcclusionTracker*, CCRenderingStats&) { } - virtual bool needMoreUpdates(); - virtual void setIsMask(bool) { } - virtual void bindContentsTexture() { } - virtual bool needsContentsScale() const; - - void setDebugBorderColor(SkColor); - void setDebugBorderWidth(float); - void setDebugName(const std::string&); - - virtual void pushPropertiesTo(CCLayerImpl*); - - void clearRenderSurface() { m_renderSurface.reset(); } - RenderSurfaceChromium* renderSurface() const { return m_renderSurface.get(); } - void createRenderSurface(); - - float drawOpacity() const { return m_drawOpacity; } - void setDrawOpacity(float opacity) { m_drawOpacity = opacity; } - - bool drawOpacityIsAnimating() const { return m_drawOpacityIsAnimating; } - void setDrawOpacityIsAnimating(bool drawOpacityIsAnimating) { m_drawOpacityIsAnimating = drawOpacityIsAnimating; } - - LayerChromium* renderTarget() const { ASSERT(!m_renderTarget || m_renderTarget->renderSurface()); return m_renderTarget; } - void setRenderTarget(LayerChromium* target) { m_renderTarget = target; } - - bool drawTransformIsAnimating() const { return m_drawTransformIsAnimating; } - void setDrawTransformIsAnimating(bool animating) { m_drawTransformIsAnimating = animating; } - bool screenSpaceTransformIsAnimating() const { return m_screenSpaceTransformIsAnimating; } - void setScreenSpaceTransformIsAnimating(bool animating) { m_screenSpaceTransformIsAnimating = animating; } - - // This moves from layer space, with origin in the center to target space with origin in the top left. - // That is, it converts from logical, non-page-scaled, to target pixels (and if the target is the - // root render surface, then this converts to physical pixels). - const WebKit::WebTransformationMatrix& drawTransform() const { return m_drawTransform; } - void setDrawTransform(const WebKit::WebTransformationMatrix& matrix) { m_drawTransform = matrix; } - // This moves from content space, with origin the top left to screen space with origin in the top left. - // It converts logical, non-page-scaled pixels to physical pixels. - const WebKit::WebTransformationMatrix& screenSpaceTransform() const { return m_screenSpaceTransform; } - void setScreenSpaceTransform(const WebKit::WebTransformationMatrix& matrix) { m_screenSpaceTransform = matrix; } - const IntRect& drawableContentRect() const { return m_drawableContentRect; } - void setDrawableContentRect(const IntRect& rect) { m_drawableContentRect = rect; } - // The contentsScale converts from logical, non-page-scaled pixels to target pixels. - // The contentsScale is 1 for the root layer as it is already in physical pixels. - float contentsScale() const { return m_contentsScale; } - void setContentsScale(float); - - // When true, the layer's contents are not scaled by the current page scale factor. - // setBoundsContainPageScale recursively sets the value on all child layers. - void setBoundsContainPageScale(bool); - bool boundsContainPageScale() const { return m_boundsContainPageScale; } - - // Returns true if any of the layer's descendants has content to draw. - bool descendantDrawsContent(); - - CCLayerTreeHost* layerTreeHost() const { return m_layerTreeHost; } - - // Set the priority of all desired textures in this layer. - virtual void setTexturePriorities(const CCPriorityCalculator&) { } - - bool addAnimation(scoped_ptr); - void pauseAnimation(int animationId, double timeOffset); - void removeAnimation(int animationId); - - void suspendAnimations(double monotonicTime); - void resumeAnimations(double monotonicTime); - - CCLayerAnimationController* layerAnimationController() { return m_layerAnimationController.get(); } - void setLayerAnimationController(scoped_ptr); - scoped_ptr releaseLayerAnimationController(); - - void setLayerAnimationDelegate(WebKit::WebAnimationDelegate* layerAnimationDelegate) { m_layerAnimationDelegate = layerAnimationDelegate; } - - bool hasActiveAnimation() const; - - virtual void notifyAnimationStarted(const CCAnimationEvent&, double wallClockTime); - virtual void notifyAnimationFinished(double wallClockTime); - - virtual Region visibleContentOpaqueRegion() const; - - virtual ScrollbarLayerChromium* toScrollbarLayerChromium(); - -protected: - friend class CCLayerImpl; - friend class TreeSynchronizer; - virtual ~LayerChromium(); - - LayerChromium(); - - void setNeedsCommit(); - - IntRect layerRectToContentRect(const WebKit::WebRect& layerRect); - - // This flag is set when layer need repainting/updating. - bool m_needsDisplay; - - // Tracks whether this layer may have changed stacking order with its siblings. - bool m_stackingOrderChanged; - - // The update rect is the region of the compositor resource that was actually updated by the compositor. - // For layers that may do updating outside the compositor's control (i.e. plugin layers), this information - // is not available and the update rect will remain empty. - // Note this rect is in layer space (not content space). - FloatRect m_updateRect; - - scoped_refptr m_maskLayer; - - // Constructs a CCLayerImpl of the correct runtime type for this LayerChromium type. - virtual scoped_ptr createCCLayerImpl(); - int m_layerId; - -private: - friend class base::RefCounted; - - void setParent(LayerChromium*); - bool hasAncestor(LayerChromium*) const; - bool descendantIsFixedToContainerLayer() const; - - size_t numChildren() const { return m_children.size(); } - - // Returns the index of the child or -1 if not found. - int indexOfChild(const LayerChromium*); - - // This should only be called from removeFromParent. - void removeChild(LayerChromium*); - - LayerList m_children; - LayerChromium* m_parent; - - // LayerChromium instances have a weak pointer to their CCLayerTreeHost. - // This pointer value is nil when a LayerChromium is not in a tree and is - // updated via setLayerTreeHost() if a layer moves between trees. - CCLayerTreeHost* m_layerTreeHost; - - scoped_ptr m_layerAnimationController; - - // Layer properties. - IntSize m_bounds; - - // Uses layer's content space. - IntRect m_visibleContentRect; - - IntPoint m_scrollPosition; - IntSize m_maxScrollPosition; - bool m_scrollable; - bool m_shouldScrollOnMainThread; - bool m_haveWheelEventHandlers; - Region m_nonFastScrollableRegion; - bool m_nonFastScrollableRegionChanged; - FloatPoint m_position; - FloatPoint m_anchorPoint; - SkColor m_backgroundColor; - SkColor m_debugBorderColor; - float m_debugBorderWidth; - std::string m_debugName; - float m_opacity; - WebKit::WebFilterOperations m_filters; - WebKit::WebFilterOperations m_backgroundFilters; - float m_anchorPointZ; - bool m_isContainerForFixedPositionLayers; - bool m_fixedToContainerLayer; - bool m_isDrawable; - bool m_masksToBounds; - bool m_contentsOpaque; - bool m_doubleSided; - bool m_useLCDText; - bool m_preserves3D; - bool m_useParentBackfaceVisibility; - bool m_drawCheckerboardForMissingTiles; - bool m_forceRenderSurface; - - WebKit::WebTransformationMatrix m_transform; - WebKit::WebTransformationMatrix m_sublayerTransform; - - // Replica layer used for reflections. - scoped_refptr m_replicaLayer; - - // Transient properties. - scoped_ptr m_renderSurface; - float m_drawOpacity; - bool m_drawOpacityIsAnimating; - - LayerChromium* m_renderTarget; - - WebKit::WebTransformationMatrix m_drawTransform; - WebKit::WebTransformationMatrix m_screenSpaceTransform; - bool m_drawTransformIsAnimating; - bool m_screenSpaceTransformIsAnimating; - - // Uses target surface space. - IntRect m_drawableContentRect; - float m_contentsScale; - bool m_boundsContainPageScale; - - WebKit::WebTransformationMatrix m_implTransform; - - WebKit::WebAnimationDelegate* m_layerAnimationDelegate; - WebKit::WebLayerScrollClient* m_layerScrollClient; -}; - -void sortLayers(std::vector >::iterator, std::vector >::iterator, void*); - -} -#endif // USE(ACCELERATED_COMPOSITING) - -#endif +// Temporary forwarding header +#include "cc/layer.h" diff --git a/cc/LayerPainterChromium.h b/cc/LayerPainterChromium.h index d552382..67987d9 100644 --- a/cc/LayerPainterChromium.h +++ b/cc/LayerPainterChromium.h @@ -1,26 +1,6 @@ -// Copyright 2011 The Chromium Authors. All rights reserved. +// Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. - -#ifndef LayerPainterChromium_h -#define LayerPainterChromium_h - -#if USE(ACCELERATED_COMPOSITING) - -class SkCanvas; - -namespace cc { - -class FloatRect; -class IntRect; - -class LayerPainterChromium { -public: - virtual ~LayerPainterChromium() { } - virtual void paint(SkCanvas*, const IntRect& contentRect, FloatRect& opaque) = 0; -}; - -} // namespace cc -#endif // USE(ACCELERATED_COMPOSITING) -#endif // LayerPainterChromium_h +// Temporary forwarding header +#include "cc/layer_painter.h" diff --git a/cc/LayerTextureSubImage.cpp b/cc/LayerTextureSubImage.cpp deleted file mode 100644 index 60f5311..0000000 --- a/cc/LayerTextureSubImage.cpp +++ /dev/null @@ -1,117 +0,0 @@ -// Copyright 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "config.h" - -#if USE(ACCELERATED_COMPOSITING) - -#include "LayerTextureSubImage.h" - -#include "CCRendererGL.h" // For the GLC() macro. -#include "GraphicsContext3D.h" -#include "Extensions3DChromium.h" -#include "TraceEvent.h" -#include - -using WebKit::WebGraphicsContext3D; - -namespace cc { - -LayerTextureSubImage::LayerTextureSubImage(bool useMapTexSubImage) - : m_useMapTexSubImage(useMapTexSubImage) - , m_subImageSize(0) -{ -} - -LayerTextureSubImage::~LayerTextureSubImage() -{ -} - -void LayerTextureSubImage::upload(const uint8_t* image, const IntRect& imageRect, - const IntRect& sourceRect, const IntSize& destOffset, - GC3Denum format, WebGraphicsContext3D* context) -{ - if (m_useMapTexSubImage) - uploadWithMapTexSubImage(image, imageRect, sourceRect, destOffset, format, context); - else - uploadWithTexSubImage(image, imageRect, sourceRect, destOffset, format, context); -} - -void LayerTextureSubImage::uploadWithTexSubImage(const uint8_t* image, const IntRect& imageRect, - const IntRect& sourceRect, const IntSize& destOffset, - GC3Denum format, WebGraphicsContext3D* context) -{ - TRACE_EVENT0("cc", "LayerTextureSubImage::uploadWithTexSubImage"); - - // Offset from image-rect to source-rect. - IntPoint offset(sourceRect.x() - imageRect.x(), sourceRect.y() - imageRect.y()); - - const uint8_t* pixelSource; - if (imageRect.width() == sourceRect.width() && !offset.x()) - pixelSource = &image[4 * offset.y() * imageRect.width()]; - else { - size_t neededSize = 4 * sourceRect.width() * sourceRect.height(); - if (m_subImageSize < neededSize) { - m_subImage = adoptArrayPtr(new uint8_t[neededSize]); - m_subImageSize = neededSize; - } - // Strides not equal, so do a row-by-row memcpy from the - // paint results into a temp buffer for uploading. - for (int row = 0; row < sourceRect.height(); ++row) - memcpy(&m_subImage[sourceRect.width() * 4 * row], - &image[4 * (offset.x() + (offset.y() + row) * imageRect.width())], - sourceRect.width() * 4); - - pixelSource = &m_subImage[0]; - } - - GLC(context, context->texSubImage2D(GraphicsContext3D::TEXTURE_2D, 0, destOffset.width(), destOffset.height(), sourceRect.width(), sourceRect.height(), format, GraphicsContext3D::UNSIGNED_BYTE, pixelSource)); -} - -void LayerTextureSubImage::uploadWithMapTexSubImage(const uint8_t* image, const IntRect& imageRect, - const IntRect& sourceRect, const IntSize& destOffset, - GC3Denum format, WebGraphicsContext3D* context) -{ - TRACE_EVENT0("cc", "LayerTextureSubImage::uploadWithMapTexSubImage"); - // Offset from image-rect to source-rect. - IntPoint offset(sourceRect.x() - imageRect.x(), sourceRect.y() - imageRect.y()); - - // Upload tile data via a mapped transfer buffer - uint8_t* pixelDest = static_cast(context->mapTexSubImage2DCHROMIUM(GraphicsContext3D::TEXTURE_2D, 0, destOffset.width(), destOffset.height(), sourceRect.width(), sourceRect.height(), format, GraphicsContext3D::UNSIGNED_BYTE, Extensions3DChromium::WRITE_ONLY)); - - if (!pixelDest) { - uploadWithTexSubImage(image, imageRect, sourceRect, destOffset, format, context); - return; - } - - unsigned int componentsPerPixel = 0; - switch (format) { - case GraphicsContext3D::RGBA: - case Extensions3D::BGRA_EXT: - componentsPerPixel = 4; - break; - case GraphicsContext3D::LUMINANCE: - componentsPerPixel = 1; - break; - default: - ASSERT_NOT_REACHED(); - } - unsigned int bytesPerComponent = 1; - - if (imageRect.width() == sourceRect.width() && !offset.x()) - memcpy(pixelDest, &image[offset.y() * imageRect.width() * componentsPerPixel * bytesPerComponent], imageRect.width() * sourceRect.height() * componentsPerPixel * bytesPerComponent); - else { - // Strides not equal, so do a row-by-row memcpy from the - // paint results into the pixelDest - for (int row = 0; row < sourceRect.height(); ++row) - memcpy(&pixelDest[sourceRect.width() * row * componentsPerPixel * bytesPerComponent], - &image[4 * (offset.x() + (offset.y() + row) * imageRect.width())], - sourceRect.width() * componentsPerPixel * bytesPerComponent); - } - GLC(context, context->unmapTexSubImage2DCHROMIUM(pixelDest)); -} - -} // namespace cc - -#endif // USE(ACCELERATED_COMPOSITING) diff --git a/cc/LayerTextureSubImage.h b/cc/LayerTextureSubImage.h index 2c6cc14..3efbf6a 100644 --- a/cc/LayerTextureSubImage.h +++ b/cc/LayerTextureSubImage.h @@ -1,46 +1,6 @@ -// Copyright 2011 The Chromium Authors. All rights reserved. +// Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. - -#ifndef LayerTextureSubImage_h -#define LayerTextureSubImage_h - -#if USE(ACCELERATED_COMPOSITING) - -#include "GraphicsTypes3D.h" -#include "IntRect.h" -#include "IntSize.h" -#include - -namespace WebKit { -class WebGraphicsContext3D; -} - -namespace cc { - -class LayerTextureSubImage { -public: - explicit LayerTextureSubImage(bool useMapSubForUpload); - ~LayerTextureSubImage(); - - void upload(const uint8_t* image, const IntRect& imageRect, - const IntRect& sourceRect, const IntSize& destOffset, - GC3Denum format, WebKit::WebGraphicsContext3D*); - -private: - void uploadWithTexSubImage(const uint8_t* image, const IntRect& imageRect, - const IntRect& sourceRect, const IntSize& destOffset, - GC3Denum format, WebKit::WebGraphicsContext3D*); - void uploadWithMapTexSubImage(const uint8_t* image, const IntRect& imageRect, - const IntRect& sourceRect, const IntSize& destOffset, - GC3Denum format, WebKit::WebGraphicsContext3D*); - - bool m_useMapTexSubImage; - size_t m_subImageSize; - OwnArrayPtr m_subImage; -}; - -} // namespace cc -#endif // USE(ACCELERATED_COMPOSITING) -#endif // LayerTextureSubImage_h +// Temporary forwarding header +#include "cc/layer_texture_sub_image.h" diff --git a/cc/LayerTextureUpdater.cpp b/cc/LayerTextureUpdater.cpp deleted file mode 100644 index d4e708f..0000000 --- a/cc/LayerTextureUpdater.cpp +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "config.h" - -#include "LayerTextureUpdater.h" - -namespace cc { - -LayerTextureUpdater::Texture::Texture(scoped_ptr texture) - : m_texture(texture.Pass()) -{ -} - -LayerTextureUpdater::Texture::~Texture() -{ -} - -bool LayerTextureUpdater::Texture::backingResourceWasEvicted() const -{ - return m_texture->backingResourceWasEvicted(); -} - -} diff --git a/cc/LayerTextureUpdater.h b/cc/LayerTextureUpdater.h index 89fc520..74bd00e 100644 --- a/cc/LayerTextureUpdater.h +++ b/cc/LayerTextureUpdater.h @@ -1,69 +1,6 @@ -// Copyright 2011 The Chromium Authors. All rights reserved. +// Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. - -#ifndef LayerTextureUpdater_h -#define LayerTextureUpdater_h - -#if USE(ACCELERATED_COMPOSITING) - -#include "CCPrioritizedTexture.h" -#include "GraphicsTypes3D.h" -#include - -namespace cc { - -class IntRect; -class IntSize; -class TextureManager; -struct CCRenderingStats; - -class LayerTextureUpdater : public RefCounted { -public: - // Allows texture uploaders to store per-tile resources. - class Texture { - public: - virtual ~Texture(); - - CCPrioritizedTexture* texture() { return m_texture.get(); } - void swapTextureWith(scoped_ptr& texture) { m_texture.swap(texture); } - virtual void prepareRect(const IntRect& /* sourceRect */, CCRenderingStats&) { } - virtual void updateRect(CCResourceProvider*, const IntRect& sourceRect, const IntSize& destOffset) = 0; - virtual bool backingResourceWasEvicted() const; - protected: - explicit Texture(scoped_ptr texture); - - private: - scoped_ptr m_texture; - }; - - LayerTextureUpdater() - { - turnOffVerifier(); // In the component build we don't have WTF threading initialized in this DLL so the thread verifier explodes. - } - - virtual ~LayerTextureUpdater() { } - - enum SampledTexelFormat { - SampledTexelFormatRGBA, - SampledTexelFormatBGRA, - SampledTexelFormatInvalid, - }; - virtual PassOwnPtr createTexture(CCPrioritizedTextureManager*) = 0; - // Returns the format of the texel uploaded by this interface. - // This format should not be confused by texture internal format. - // This format specifies the component order in the sampled texel. - // If the format is TexelFormatBGRA, vec4.x is blue and vec4.z is red. - virtual SampledTexelFormat sampledTexelFormat(GC3Denum textureFormat) = 0; - // The |resultingOpaqueRect| gives back a region of the layer that was painted opaque. If the layer is marked opaque in the updater, - // then this region should be ignored in preference for the entire layer's area. - virtual void prepareToUpdate(const IntRect& contentRect, const IntSize& tileSize, float contentsWidthScale, float contentsHeightScale, IntRect& resultingOpaqueRect, CCRenderingStats&) { } - - // Set true by the layer when it is known that the entire output is going to be opaque. - virtual void setOpaque(bool) { } -}; - -} // namespace cc -#endif // USE(ACCELERATED_COMPOSITING) -#endif // LayerTextureUpdater_h +// Temporary forwarding header +#include "cc/layer_texture_updater.h" diff --git a/cc/PlatformColor.h b/cc/PlatformColor.h index 61ffd31..24690aa 100644 --- a/cc/PlatformColor.h +++ b/cc/PlatformColor.h @@ -1,58 +1,6 @@ -// Copyright 2011 The Chromium Authors. All rights reserved. +// Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef PlatformColor_h -#define PlatformColor_h - -#include "Extensions3D.h" -#include "GraphicsContext3D.h" -#include "SkTypes.h" -#include - -namespace cc { - -class PlatformColor { -public: - static GraphicsContext3D::SourceDataFormat format() - { - return SK_B32_SHIFT ? GraphicsContext3D::SourceFormatRGBA8 : GraphicsContext3D::SourceFormatBGRA8; - } - - // Returns the most efficient texture format for this platform. - static GC3Denum bestTextureFormat(WebKit::WebGraphicsContext3D* context, bool supportsBGRA8888) - { - GC3Denum textureFormat = GraphicsContext3D::RGBA; - switch (format()) { - case GraphicsContext3D::SourceFormatRGBA8: - break; - case GraphicsContext3D::SourceFormatBGRA8: - if (supportsBGRA8888) - textureFormat = Extensions3D::BGRA_EXT; - break; - default: - ASSERT_NOT_REACHED(); - break; - } - return textureFormat; - } - - // Return true if the given texture format has the same component order - // as the color on this platform. - static bool sameComponentOrder(GC3Denum textureFormat) - { - switch (format()) { - case GraphicsContext3D::SourceFormatRGBA8: - return textureFormat == GraphicsContext3D::RGBA; - case GraphicsContext3D::SourceFormatBGRA8: - return textureFormat == Extensions3D::BGRA_EXT; - default: - ASSERT_NOT_REACHED(); - return false; - } - } -}; - -} // namespace cc - -#endif +// Temporary forwarding header +#include "cc/platform_color.h" diff --git a/cc/ProgramBinding.cpp b/cc/ProgramBinding.cpp deleted file mode 100644 index 27d5226..0000000 --- a/cc/ProgramBinding.cpp +++ /dev/null @@ -1,147 +0,0 @@ -// Copyright 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "config.h" - -#if USE(ACCELERATED_COMPOSITING) - -#include "ProgramBinding.h" - -#include "CCRendererGL.h" // For the GLC() macro. -#include "GeometryBinding.h" -#include "GraphicsContext3D.h" -#include "TraceEvent.h" -#include - -using WebKit::WebGraphicsContext3D; - -namespace cc { - -ProgramBindingBase::ProgramBindingBase() - : m_program(0) - , m_vertexShaderId(0) - , m_fragmentShaderId(0) - , m_initialized(false) -{ -} - -ProgramBindingBase::~ProgramBindingBase() -{ - // If you hit these asserts, you initialized but forgot to call cleanup(). - ASSERT(!m_program); - ASSERT(!m_vertexShaderId); - ASSERT(!m_fragmentShaderId); - ASSERT(!m_initialized); -} - -static bool contextLost(WebGraphicsContext3D* context) -{ - return (context->getGraphicsResetStatusARB() != GraphicsContext3D::NO_ERROR); -} - - -void ProgramBindingBase::init(WebGraphicsContext3D* context, const std::string& vertexShader, const std::string& fragmentShader) -{ - TRACE_EVENT0("cc", "ProgramBindingBase::init"); - m_vertexShaderId = loadShader(context, GraphicsContext3D::VERTEX_SHADER, vertexShader); - if (!m_vertexShaderId) { - if (!contextLost(context)) - LOG_ERROR("Failed to create vertex shader"); - return; - } - - m_fragmentShaderId = loadShader(context, GraphicsContext3D::FRAGMENT_SHADER, fragmentShader); - if (!m_fragmentShaderId) { - GLC(context, context->deleteShader(m_vertexShaderId)); - m_vertexShaderId = 0; - if (!contextLost(context)) - LOG_ERROR("Failed to create fragment shader"); - return; - } - - m_program = createShaderProgram(context, m_vertexShaderId, m_fragmentShaderId); - ASSERT(m_program || contextLost(context)); -} - -void ProgramBindingBase::link(WebGraphicsContext3D* context) -{ - GLC(context, context->linkProgram(m_program)); - cleanupShaders(context); -#ifndef NDEBUG - int linked = 0; - GLC(context, context->getProgramiv(m_program, GraphicsContext3D::LINK_STATUS, &linked)); - if (!linked) { - if (!contextLost(context)) - LOG_ERROR("Failed to link shader program"); - GLC(context, context->deleteProgram(m_program)); - return; - } -#endif -} - -void ProgramBindingBase::cleanup(WebGraphicsContext3D* context) -{ - m_initialized = false; - if (!m_program) - return; - - ASSERT(context); - GLC(context, context->deleteProgram(m_program)); - m_program = 0; - - cleanupShaders(context); -} - -unsigned ProgramBindingBase::loadShader(WebGraphicsContext3D* context, unsigned type, const std::string& shaderSource) -{ - unsigned shader = context->createShader(type); - if (!shader) - return 0; - GLC(context, context->shaderSource(shader, shaderSource.data())); - GLC(context, context->compileShader(shader)); -#ifndef NDEBUG - int compiled = 0; - GLC(context, context->getShaderiv(shader, GraphicsContext3D::COMPILE_STATUS, &compiled)); - if (!compiled) { - GLC(context, context->deleteShader(shader)); - return 0; - } -#endif - return shader; -} - -unsigned ProgramBindingBase::createShaderProgram(WebGraphicsContext3D* context, unsigned vertexShader, unsigned fragmentShader) -{ - unsigned programObject = context->createProgram(); - if (!programObject) { - if (!contextLost(context)) - LOG_ERROR("Failed to create shader program"); - return 0; - } - - GLC(context, context->attachShader(programObject, vertexShader)); - GLC(context, context->attachShader(programObject, fragmentShader)); - - // Bind the common attrib locations. - GLC(context, context->bindAttribLocation(programObject, GeometryBinding::positionAttribLocation(), "a_position")); - GLC(context, context->bindAttribLocation(programObject, GeometryBinding::texCoordAttribLocation(), "a_texCoord")); - - return programObject; -} - -void ProgramBindingBase::cleanupShaders(WebGraphicsContext3D* context) -{ - if (m_vertexShaderId) { - GLC(context, context->deleteShader(m_vertexShaderId)); - m_vertexShaderId = 0; - } - if (m_fragmentShaderId) { - GLC(context, context->deleteShader(m_fragmentShaderId)); - m_fragmentShaderId = 0; - } -} - -} // namespace cc - -#endif // USE(ACCELERATED_COMPOSITING) diff --git a/cc/ProgramBinding.h b/cc/ProgramBinding.h index 9f0d067..f44ed18 100644 --- a/cc/ProgramBinding.h +++ b/cc/ProgramBinding.h @@ -1,84 +1,6 @@ -// Copyright 2011 The Chromium Authors. All rights reserved. +// Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef ProgramBinding_h -#define ProgramBinding_h - -#if USE(ACCELERATED_COMPOSITING) - -#include - -namespace WebKit { -class WebGraphicsContext3D; -} - -namespace cc { - -class ProgramBindingBase { -public: - ProgramBindingBase(); - ~ProgramBindingBase(); - - void init(WebKit::WebGraphicsContext3D*, const std::string& vertexShader, const std::string& fragmentShader); - void link(WebKit::WebGraphicsContext3D*); - void cleanup(WebKit::WebGraphicsContext3D*); - - unsigned program() const { ASSERT(m_initialized); return m_program; } - bool initialized() const { return m_initialized; } - -protected: - - unsigned loadShader(WebKit::WebGraphicsContext3D*, unsigned type, const std::string& shaderSource); - unsigned createShaderProgram(WebKit::WebGraphicsContext3D*, unsigned vertexShader, unsigned fragmentShader); - void cleanupShaders(WebKit::WebGraphicsContext3D*); - - unsigned m_program; - unsigned m_vertexShaderId; - unsigned m_fragmentShaderId; - bool m_initialized; -}; - -template -class ProgramBinding : public ProgramBindingBase { -public: - explicit ProgramBinding(WebKit::WebGraphicsContext3D* context) - { - ProgramBindingBase::init(context, m_vertexShader.getShaderString(), m_fragmentShader.getShaderString()); - } - - void initialize(WebKit::WebGraphicsContext3D* context, bool usingBindUniform) - { - ASSERT(context); - ASSERT(m_program); - ASSERT(!m_initialized); - - // Need to bind uniforms before linking - if (!usingBindUniform) - link(context); - - int baseUniformIndex = 0; - m_vertexShader.init(context, m_program, usingBindUniform, &baseUniformIndex); - m_fragmentShader.init(context, m_program, usingBindUniform, &baseUniformIndex); - - // Link after binding uniforms - if (usingBindUniform) - link(context); - - m_initialized = true; - } - - const VertexShader& vertexShader() const { return m_vertexShader; } - const FragmentShader& fragmentShader() const { return m_fragmentShader; } - -private: - - VertexShader m_vertexShader; - FragmentShader m_fragmentShader; -}; - -} // namespace cc - -#endif // USE(ACCELERATED_COMPOSITING) - -#endif +// Temporary forwarding header +#include "cc/program_binding.h" diff --git a/cc/RateLimiter.cpp b/cc/RateLimiter.cpp deleted file mode 100644 index a521525..0000000 --- a/cc/RateLimiter.cpp +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "config.h" - -#if USE(ACCELERATED_COMPOSITING) -#include "RateLimiter.h" - -#include "CCProxy.h" -#include "CCThread.h" -#include "TraceEvent.h" -#include -#include - -namespace cc { - -class RateLimiter::Task : public CCThread::Task { -public: - static PassOwnPtr create(RateLimiter* rateLimiter) - { - return adoptPtr(new Task(rateLimiter)); - } - virtual ~Task() { } - -private: - explicit Task(RateLimiter* rateLimiter) - : CCThread::Task(this) - , m_rateLimiter(rateLimiter) - { - } - - virtual void performTask() OVERRIDE - { - m_rateLimiter->rateLimitContext(); - } - - scoped_refptr m_rateLimiter; -}; - -scoped_refptr RateLimiter::create(WebKit::WebGraphicsContext3D* context, RateLimiterClient *client) -{ - return make_scoped_refptr(new RateLimiter(context, client)); -} - -RateLimiter::RateLimiter(WebKit::WebGraphicsContext3D* context, RateLimiterClient *client) - : m_context(context) - , m_active(false) - , m_client(client) -{ - ASSERT(context); -} - -RateLimiter::~RateLimiter() -{ -} - -void RateLimiter::start() -{ - if (m_active) - return; - - TRACE_EVENT0("cc", "RateLimiter::start"); - m_active = true; - CCProxy::mainThread()->postTask(RateLimiter::Task::create(this)); -} - -void RateLimiter::stop() -{ - TRACE_EVENT0("cc", "RateLimiter::stop"); - m_client = 0; -} - -void RateLimiter::rateLimitContext() -{ - if (!m_client) - return; - - TRACE_EVENT0("cc", "RateLimiter::rateLimitContext"); - - m_active = false; - m_client->rateLimit(); - m_context->rateLimitOffscreenContextCHROMIUM(); -} - -} -#endif // USE(ACCELERATED_COMPOSITING) diff --git a/cc/RateLimiter.h b/cc/RateLimiter.h index 7b48d74..90c7f54 100644 --- a/cc/RateLimiter.h +++ b/cc/RateLimiter.h @@ -1,53 +1,6 @@ -// Copyright 2011 The Chromium Authors. All rights reserved. +// Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef RateLimiter_h -#define RateLimiter_h - -#if USE(ACCELERATED_COMPOSITING) - -#include "base/memory/ref_counted.h" - -namespace WebKit { -class WebGraphicsContext3D; -} - -namespace cc { - -class RateLimiterClient { -public: - virtual void rateLimit() = 0; -}; - -// A RateLimiter can be used to make sure that a single context does not dominate all execution time. -// To use, construct a RateLimiter class around the context and call start() whenever calls are made on the -// context outside of normal flow control. RateLimiter will block if the context is too far ahead of the -// compositor. -class RateLimiter : public base::RefCounted { -public: - static scoped_refptr create(WebKit::WebGraphicsContext3D*, RateLimiterClient*); - - void start(); - - // Context and client will not be accessed after stop(). - void stop(); - -private: - RateLimiter(WebKit::WebGraphicsContext3D*, RateLimiterClient*); - ~RateLimiter(); - friend class base::RefCounted; - - class Task; - friend class Task; - void rateLimitContext(); - - WebKit::WebGraphicsContext3D* m_context; - bool m_active; - RateLimiterClient *m_client; -}; - -} -#endif // USE(ACCELERATED_COMPOSITING) - -#endif +// Temporary forwarding header +#include "cc/rate_limiter.h" diff --git a/cc/RenderSurfaceChromium.cpp b/cc/RenderSurfaceChromium.cpp deleted file mode 100644 index 320a3d8..0000000 --- a/cc/RenderSurfaceChromium.cpp +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "config.h" - -#if USE(ACCELERATED_COMPOSITING) - -#include "RenderSurfaceChromium.h" - -#include "CCMathUtil.h" -#include "LayerChromium.h" -#include - -using WebKit::WebTransformationMatrix; - -namespace cc { - -RenderSurfaceChromium::RenderSurfaceChromium(LayerChromium* owningLayer) - : m_owningLayer(owningLayer) - , m_drawOpacity(1) - , m_drawOpacityIsAnimating(false) - , m_targetSurfaceTransformsAreAnimating(false) - , m_screenSpaceTransformsAreAnimating(false) - , m_nearestAncestorThatMovesPixels(0) -{ -} - -RenderSurfaceChromium::~RenderSurfaceChromium() -{ -} - -FloatRect RenderSurfaceChromium::drawableContentRect() const -{ - FloatRect drawableContentRect = CCMathUtil::mapClippedRect(m_drawTransform, m_contentRect); - if (m_owningLayer->hasReplica()) - drawableContentRect.unite(CCMathUtil::mapClippedRect(m_replicaDrawTransform, m_contentRect)); - return drawableContentRect; -} - -} -#endif // USE(ACCELERATED_COMPOSITING) diff --git a/cc/RenderSurfaceChromium.h b/cc/RenderSurfaceChromium.h index 67ed626..a7a9147 100644 --- a/cc/RenderSurfaceChromium.h +++ b/cc/RenderSurfaceChromium.h @@ -1,107 +1,6 @@ -// Copyright 2010 The Chromium Authors. All rights reserved. +// Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. - -#ifndef RenderSurfaceChromium_h -#define RenderSurfaceChromium_h - -#if USE(ACCELERATED_COMPOSITING) - -#include "base/basictypes.h" -#include "base/memory/ref_counted.h" -#include "FloatRect.h" -#include "IntRect.h" -#include -#include - -namespace cc { - -class LayerChromium; - -class RenderSurfaceChromium { -public: - explicit RenderSurfaceChromium(LayerChromium*); - ~RenderSurfaceChromium(); - - // Returns the rect that encloses the RenderSurface including any reflection. - FloatRect drawableContentRect() const; - - const IntRect& contentRect() const { return m_contentRect; } - void setContentRect(const IntRect& contentRect) { m_contentRect = contentRect; } - - float drawOpacity() const { return m_drawOpacity; } - void setDrawOpacity(float drawOpacity) { m_drawOpacity = drawOpacity; } - - bool drawOpacityIsAnimating() const { return m_drawOpacityIsAnimating; } - void setDrawOpacityIsAnimating(bool drawOpacityIsAnimating) { m_drawOpacityIsAnimating = drawOpacityIsAnimating; } - - // This goes from content space with the origin in the center of the rect being transformed to the target space with the origin in the top left of the - // rect being transformed. Position the rect so that the origin is in the center of it before applying this transform. - const WebKit::WebTransformationMatrix& drawTransform() const { return m_drawTransform; } - void setDrawTransform(const WebKit::WebTransformationMatrix& drawTransform) { m_drawTransform = drawTransform; } - - const WebKit::WebTransformationMatrix& screenSpaceTransform() const { return m_screenSpaceTransform; } - void setScreenSpaceTransform(const WebKit::WebTransformationMatrix& screenSpaceTransform) { m_screenSpaceTransform = screenSpaceTransform; } - - const WebKit::WebTransformationMatrix& replicaDrawTransform() const { return m_replicaDrawTransform; } - void setReplicaDrawTransform(const WebKit::WebTransformationMatrix& replicaDrawTransform) { m_replicaDrawTransform = replicaDrawTransform; } - - const WebKit::WebTransformationMatrix& replicaScreenSpaceTransform() const { return m_replicaScreenSpaceTransform; } - void setReplicaScreenSpaceTransform(const WebKit::WebTransformationMatrix& replicaScreenSpaceTransform) { m_replicaScreenSpaceTransform = replicaScreenSpaceTransform; } - - bool targetSurfaceTransformsAreAnimating() const { return m_targetSurfaceTransformsAreAnimating; } - void setTargetSurfaceTransformsAreAnimating(bool animating) { m_targetSurfaceTransformsAreAnimating = animating; } - bool screenSpaceTransformsAreAnimating() const { return m_screenSpaceTransformsAreAnimating; } - void setScreenSpaceTransformsAreAnimating(bool animating) { m_screenSpaceTransformsAreAnimating = animating; } - - const IntRect& clipRect() const { return m_clipRect; } - void setClipRect(const IntRect& clipRect) { m_clipRect = clipRect; } - - typedef std::vector > LayerList; - LayerList& layerList() { return m_layerList; } - // A no-op since DelegatedRendererLayers on the main thread don't have any - // RenderPasses so they can't contribute to a surface. - void addContributingDelegatedRenderPassLayer(LayerChromium*) { } - void clearLayerLists() { m_layerList.clear(); } - - void setNearestAncestorThatMovesPixels(RenderSurfaceChromium* surface) { m_nearestAncestorThatMovesPixels = surface; } - const RenderSurfaceChromium* nearestAncestorThatMovesPixels() const { return m_nearestAncestorThatMovesPixels; } - -private: - friend struct CCLayerIteratorActions; - - LayerChromium* m_owningLayer; - - // Uses this surface's space. - IntRect m_contentRect; - - float m_drawOpacity; - bool m_drawOpacityIsAnimating; - WebKit::WebTransformationMatrix m_drawTransform; - WebKit::WebTransformationMatrix m_screenSpaceTransform; - WebKit::WebTransformationMatrix m_replicaDrawTransform; - WebKit::WebTransformationMatrix m_replicaScreenSpaceTransform; - bool m_targetSurfaceTransformsAreAnimating; - bool m_screenSpaceTransformsAreAnimating; - - // Uses the space of the surface's target surface. - IntRect m_clipRect; - - LayerList m_layerList; - - // The nearest ancestor target surface that will contain the contents of this surface, and that is going - // to move pixels within the surface (such as with a blur). This can point to itself. - RenderSurfaceChromium* m_nearestAncestorThatMovesPixels; - - // For CCLayerIteratorActions - int m_targetRenderSurfaceLayerIndexHistory; - int m_currentLayerIndexHistory; - - DISALLOW_COPY_AND_ASSIGN(RenderSurfaceChromium); -}; - -} -#endif // USE(ACCELERATED_COMPOSITING) - -#endif +// Temporary forwarding header +#include "cc/render_surface.h" diff --git a/cc/ScrollbarLayerChromium.cpp b/cc/ScrollbarLayerChromium.cpp deleted file mode 100644 index 4259b7b..0000000 --- a/cc/ScrollbarLayerChromium.cpp +++ /dev/null @@ -1,290 +0,0 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "config.h" - -#if USE(ACCELERATED_COMPOSITING) - -#include "ScrollbarLayerChromium.h" - -#include "base/basictypes.h" -#include "CCLayerTreeHost.h" -#include "CCScrollbarLayerImpl.h" -#include "CCTextureUpdateQueue.h" -#include "LayerPainterChromium.h" -#include "TraceEvent.h" -#include - -using WebKit::WebRect; - -namespace cc { - -scoped_ptr ScrollbarLayerChromium::createCCLayerImpl() -{ - return CCScrollbarLayerImpl::create(id()).PassAs(); -} - -scoped_refptr ScrollbarLayerChromium::create(PassOwnPtr scrollbar, WebKit::WebScrollbarThemePainter painter, PassOwnPtr geometry, int scrollLayerId) -{ - return make_scoped_refptr(new ScrollbarLayerChromium(scrollbar, painter, geometry, scrollLayerId)); -} - -ScrollbarLayerChromium::ScrollbarLayerChromium(PassOwnPtr scrollbar, WebKit::WebScrollbarThemePainter painter, PassOwnPtr geometry, int scrollLayerId) - : m_scrollbar(scrollbar) - , m_painter(painter) - , m_geometry(geometry) - , m_scrollLayerId(scrollLayerId) - , m_textureFormat(GraphicsContext3D::INVALID_ENUM) -{ -} - -ScrollbarLayerChromium::~ScrollbarLayerChromium() -{ -} - -void ScrollbarLayerChromium::pushPropertiesTo(CCLayerImpl* layer) -{ - LayerChromium::pushPropertiesTo(layer); - - CCScrollbarLayerImpl* scrollbarLayer = static_cast(layer); - - if (!scrollbarLayer->scrollbarGeometry()) - scrollbarLayer->setScrollbarGeometry(CCScrollbarGeometryFixedThumb::create(adoptPtr(m_geometry->clone()))); - - scrollbarLayer->setScrollbarData(m_scrollbar.get()); - - if (m_backTrack && m_backTrack->texture()->haveBackingTexture()) - scrollbarLayer->setBackTrackResourceId(m_backTrack->texture()->resourceId()); - else - scrollbarLayer->setBackTrackResourceId(0); - - if (m_foreTrack && m_foreTrack->texture()->haveBackingTexture()) - scrollbarLayer->setForeTrackResourceId(m_foreTrack->texture()->resourceId()); - else - scrollbarLayer->setForeTrackResourceId(0); - - if (m_thumb && m_thumb->texture()->haveBackingTexture()) - scrollbarLayer->setThumbResourceId(m_thumb->texture()->resourceId()); - else - scrollbarLayer->setThumbResourceId(0); -} - -ScrollbarLayerChromium* ScrollbarLayerChromium::toScrollbarLayerChromium() -{ - return this; -} - -class ScrollbarBackgroundPainter : public LayerPainterChromium { -public: - static PassOwnPtr create(WebKit::WebScrollbar* scrollbar, WebKit::WebScrollbarThemePainter painter, WebKit::WebScrollbarThemeGeometry* geometry, WebKit::WebScrollbar::ScrollbarPart trackPart) - { - return adoptPtr(new ScrollbarBackgroundPainter(scrollbar, painter, geometry, trackPart)); - } - - virtual void paint(SkCanvas* skCanvas, const IntRect& contentRect, FloatRect&) OVERRIDE - { - WebKit::WebCanvas* canvas = skCanvas; - // The following is a simplification of ScrollbarThemeComposite::paint. - WebKit::WebRect contentWebRect(contentRect.x(), contentRect.y(), contentRect.width(), contentRect.height()); - m_painter.paintScrollbarBackground(canvas, contentWebRect); - - if (m_geometry->hasButtons(m_scrollbar)) { - WebRect backButtonStartPaintRect = m_geometry->backButtonStartRect(m_scrollbar); - m_painter.paintBackButtonStart(canvas, backButtonStartPaintRect); - - WebRect backButtonEndPaintRect = m_geometry->backButtonEndRect(m_scrollbar); - m_painter.paintBackButtonEnd(canvas, backButtonEndPaintRect); - - WebRect forwardButtonStartPaintRect = m_geometry->forwardButtonStartRect(m_scrollbar); - m_painter.paintForwardButtonStart(canvas, forwardButtonStartPaintRect); - - WebRect forwardButtonEndPaintRect = m_geometry->forwardButtonEndRect(m_scrollbar); - m_painter.paintForwardButtonEnd(canvas, forwardButtonEndPaintRect); - } - - WebRect trackPaintRect = m_geometry->trackRect(m_scrollbar); - m_painter.paintTrackBackground(canvas, trackPaintRect); - - bool thumbPresent = m_geometry->hasThumb(m_scrollbar); - if (thumbPresent) { - if (m_trackPart == WebKit::WebScrollbar::ForwardTrackPart) - m_painter.paintForwardTrackPart(canvas, trackPaintRect); - else - m_painter.paintBackTrackPart(canvas, trackPaintRect); - } - - m_painter.paintTickmarks(canvas, trackPaintRect); - } -private: - ScrollbarBackgroundPainter(WebKit::WebScrollbar* scrollbar, WebKit::WebScrollbarThemePainter painter, WebKit::WebScrollbarThemeGeometry* geometry, WebKit::WebScrollbar::ScrollbarPart trackPart) - : m_scrollbar(scrollbar) - , m_painter(painter) - , m_geometry(geometry) - , m_trackPart(trackPart) - { - } - - WebKit::WebScrollbar* m_scrollbar; - WebKit::WebScrollbarThemePainter m_painter; - WebKit::WebScrollbarThemeGeometry* m_geometry; - WebKit::WebScrollbar::ScrollbarPart m_trackPart; - - DISALLOW_COPY_AND_ASSIGN(ScrollbarBackgroundPainter); -}; - -bool ScrollbarLayerChromium::needsContentsScale() const -{ - return true; -} - -IntSize ScrollbarLayerChromium::contentBounds() const -{ - return IntSize(lroundf(bounds().width() * contentsScale()), lroundf(bounds().height() * contentsScale())); -} - -class ScrollbarThumbPainter : public LayerPainterChromium { -public: - static PassOwnPtr create(WebKit::WebScrollbar* scrollbar, WebKit::WebScrollbarThemePainter painter, WebKit::WebScrollbarThemeGeometry* geometry) - { - return adoptPtr(new ScrollbarThumbPainter(scrollbar, painter, geometry)); - } - - virtual void paint(SkCanvas* skCanvas, const IntRect& contentRect, FloatRect& opaque) OVERRIDE - { - WebKit::WebCanvas* canvas = skCanvas; - - // Consider the thumb to be at the origin when painting. - WebRect thumbRect = m_geometry->thumbRect(m_scrollbar); - thumbRect.x = 0; - thumbRect.y = 0; - m_painter.paintThumb(canvas, thumbRect); - } - -private: - ScrollbarThumbPainter(WebKit::WebScrollbar* scrollbar, WebKit::WebScrollbarThemePainter painter, WebKit::WebScrollbarThemeGeometry* geometry) - : m_scrollbar(scrollbar) - , m_painter(painter) - , m_geometry(geometry) - { - } - - WebKit::WebScrollbar* m_scrollbar; - WebKit::WebScrollbarThemePainter m_painter; - WebKit::WebScrollbarThemeGeometry* m_geometry; - - DISALLOW_COPY_AND_ASSIGN(ScrollbarThumbPainter); -}; - -void ScrollbarLayerChromium::setLayerTreeHost(CCLayerTreeHost* host) -{ - if (!host || host != layerTreeHost()) { - m_backTrackUpdater.clear(); - m_backTrack.clear(); - m_thumbUpdater.clear(); - m_thumb.clear(); - } - - LayerChromium::setLayerTreeHost(host); -} - -void ScrollbarLayerChromium::createTextureUpdaterIfNeeded() -{ - m_textureFormat = layerTreeHost()->rendererCapabilities().bestTextureFormat; - - if (!m_backTrackUpdater) - m_backTrackUpdater = CachingBitmapCanvasLayerTextureUpdater::Create(ScrollbarBackgroundPainter::create(m_scrollbar.get(), m_painter, m_geometry.get(), WebKit::WebScrollbar::BackTrackPart)); - if (!m_backTrack) - m_backTrack = m_backTrackUpdater->createTexture(layerTreeHost()->contentsTextureManager()); - - // Only create two-part track if we think the two parts could be different in appearance. - if (m_scrollbar->isCustomScrollbar()) { - if (!m_foreTrackUpdater) - m_foreTrackUpdater = CachingBitmapCanvasLayerTextureUpdater::Create(ScrollbarBackgroundPainter::create(m_scrollbar.get(), m_painter, m_geometry.get(), WebKit::WebScrollbar::ForwardTrackPart)); - if (!m_foreTrack) - m_foreTrack = m_foreTrackUpdater->createTexture(layerTreeHost()->contentsTextureManager()); - } - - if (!m_thumbUpdater) - m_thumbUpdater = CachingBitmapCanvasLayerTextureUpdater::Create(ScrollbarThumbPainter::create(m_scrollbar.get(), m_painter, m_geometry.get())); - if (!m_thumb) - m_thumb = m_thumbUpdater->createTexture(layerTreeHost()->contentsTextureManager()); -} - -void ScrollbarLayerChromium::updatePart(CachingBitmapCanvasLayerTextureUpdater* painter, LayerTextureUpdater::Texture* texture, const IntRect& rect, CCTextureUpdateQueue& queue, CCRenderingStats& stats) -{ - // Skip painting and uploading if there are no invalidations and - // we already have valid texture data. - if (texture->texture()->haveBackingTexture() - && texture->texture()->size() == rect.size() - && m_updateRect.isEmpty()) - return; - - // We should always have enough memory for UI. - ASSERT(texture->texture()->canAcquireBackingTexture()); - if (!texture->texture()->canAcquireBackingTexture()) - return; - - // Paint and upload the entire part. - float widthScale = static_cast(contentBounds().width()) / bounds().width(); - float heightScale = static_cast(contentBounds().height()) / bounds().height(); - IntRect paintedOpaqueRect; - painter->prepareToUpdate(rect, rect.size(), widthScale, heightScale, paintedOpaqueRect, stats); - if (!painter->pixelsDidChange() && texture->texture()->haveBackingTexture()) { - TRACE_EVENT_INSTANT0("cc","ScrollbarLayerChromium::updatePart no texture upload needed"); - return; - } - - texture->prepareRect(rect, stats); - - IntSize destOffset(0, 0); - TextureUploader::Parameters upload = { texture, rect, destOffset }; - queue.appendFullUpload(upload); -} - - -void ScrollbarLayerChromium::setTexturePriorities(const CCPriorityCalculator&) -{ - if (contentBounds().isEmpty()) - return; - - createTextureUpdaterIfNeeded(); - - bool drawsToRoot = !renderTarget()->parent(); - if (m_backTrack) { - m_backTrack->texture()->setDimensions(contentBounds(), m_textureFormat); - m_backTrack->texture()->setRequestPriority(CCPriorityCalculator::uiPriority(drawsToRoot)); - } - if (m_foreTrack) { - m_foreTrack->texture()->setDimensions(contentBounds(), m_textureFormat); - m_foreTrack->texture()->setRequestPriority(CCPriorityCalculator::uiPriority(drawsToRoot)); - } - if (m_thumb) { - IntSize thumbSize = layerRectToContentRect(m_geometry->thumbRect(m_scrollbar.get())).size(); - m_thumb->texture()->setDimensions(thumbSize, m_textureFormat); - m_thumb->texture()->setRequestPriority(CCPriorityCalculator::uiPriority(drawsToRoot)); - } -} - -void ScrollbarLayerChromium::update(CCTextureUpdateQueue& queue, const CCOcclusionTracker*, CCRenderingStats& stats) -{ - if (contentBounds().isEmpty()) - return; - - createTextureUpdaterIfNeeded(); - - IntPoint scrollbarOrigin(m_scrollbar->location().x, m_scrollbar->location().y); - IntRect contentRect = layerRectToContentRect(WebKit::WebRect(scrollbarOrigin.x(), scrollbarOrigin.y(), bounds().width(), bounds().height())); - updatePart(m_backTrackUpdater.get(), m_backTrack.get(), contentRect, queue, stats); - if (m_foreTrack && m_foreTrackUpdater) - updatePart(m_foreTrackUpdater.get(), m_foreTrack.get(), contentRect, queue, stats); - - // Consider the thumb to be at the origin when painting. - WebKit::WebRect thumbRect = m_geometry->thumbRect(m_scrollbar.get()); - IntRect originThumbRect = layerRectToContentRect(WebKit::WebRect(0, 0, thumbRect.width, thumbRect.height)); - if (!originThumbRect.isEmpty()) - updatePart(m_thumbUpdater.get(), m_thumb.get(), originThumbRect, queue, stats); -} - -} -#endif // USE(ACCELERATED_COMPOSITING) diff --git a/cc/ScrollbarLayerChromium.h b/cc/ScrollbarLayerChromium.h index 5c7cc5c..1e7384a 100644 --- a/cc/ScrollbarLayerChromium.h +++ b/cc/ScrollbarLayerChromium.h @@ -2,69 +2,5 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. - -#ifndef ScrollbarLayerChromium_h -#define ScrollbarLayerChromium_h - -#if USE(ACCELERATED_COMPOSITING) - -#include "LayerChromium.h" -#include "caching_bitmap_canvas_layer_texture_updater.h" -#include -#include -#include - -namespace cc { - -class Scrollbar; -class ScrollbarThemeComposite; -class CCTextureUpdateQueue; - -class ScrollbarLayerChromium : public LayerChromium { -public: - virtual scoped_ptr createCCLayerImpl() OVERRIDE; - - static scoped_refptr create(PassOwnPtr, WebKit::WebScrollbarThemePainter, PassOwnPtr, int scrollLayerId); - - // LayerChromium interface - virtual bool needsContentsScale() const OVERRIDE; - virtual IntSize contentBounds() const OVERRIDE; - virtual void setTexturePriorities(const CCPriorityCalculator&) OVERRIDE; - virtual void update(CCTextureUpdateQueue&, const CCOcclusionTracker*, CCRenderingStats&) OVERRIDE; - virtual void setLayerTreeHost(CCLayerTreeHost*) OVERRIDE; - virtual void pushPropertiesTo(CCLayerImpl*) OVERRIDE; - - int scrollLayerId() const { return m_scrollLayerId; } - void setScrollLayerId(int id) { m_scrollLayerId = id; } - - virtual ScrollbarLayerChromium* toScrollbarLayerChromium() OVERRIDE; - -protected: - ScrollbarLayerChromium(PassOwnPtr, WebKit::WebScrollbarThemePainter, PassOwnPtr, int scrollLayerId); - virtual ~ScrollbarLayerChromium(); - -private: - void updatePart(CachingBitmapCanvasLayerTextureUpdater*, LayerTextureUpdater::Texture*, const IntRect&, CCTextureUpdateQueue&, CCRenderingStats&); - void createTextureUpdaterIfNeeded(); - - OwnPtr m_scrollbar; - WebKit::WebScrollbarThemePainter m_painter; - OwnPtr m_geometry; - int m_scrollLayerId; - - GC3Denum m_textureFormat; - - RefPtr m_backTrackUpdater; - RefPtr m_foreTrackUpdater; - RefPtr m_thumbUpdater; - - // All the parts of the scrollbar except the thumb - OwnPtr m_backTrack; - OwnPtr m_foreTrack; - OwnPtr m_thumb; -}; - -} -#endif // USE(ACCELERATED_COMPOSITING) - -#endif +// Temporary forwarding header +#include "cc/scrollbar_layer.h" diff --git a/cc/ShaderChromium.cpp b/cc/ShaderChromium.cpp deleted file mode 100644 index cf485c1..0000000 --- a/cc/ShaderChromium.cpp +++ /dev/null @@ -1,888 +0,0 @@ -// Copyright 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "config.h" - -#if USE(ACCELERATED_COMPOSITING) - -#include "ShaderChromium.h" - -#include -#include - -#define SHADER0(Src) #Src -#define SHADER(Src) SHADER0(Src) - -using WebKit::WebGraphicsContext3D; - -namespace cc { - -namespace { - -static void getProgramUniformLocations(WebGraphicsContext3D* context, unsigned program, const char** shaderUniforms, size_t count, size_t maxLocations, int* locations, bool usingBindUniform, int* baseUniformIndex) -{ - for (size_t uniformIndex = 0; uniformIndex < count; uniformIndex ++) { - ASSERT(uniformIndex < maxLocations); - - if (usingBindUniform) { - locations[uniformIndex] = (*baseUniformIndex)++; - context->bindUniformLocationCHROMIUM(program, locations[uniformIndex], shaderUniforms[uniformIndex]); - } else - locations[uniformIndex] = context->getUniformLocation(program, shaderUniforms[uniformIndex]); - } -} - -} - -VertexShaderPosTex::VertexShaderPosTex() - : m_matrixLocation(-1) -{ -} - -void VertexShaderPosTex::init(WebGraphicsContext3D* context, unsigned program, bool usingBindUniform, int* baseUniformIndex) -{ - static const char* shaderUniforms[] = { - "matrix", - }; - int locations[1]; - - getProgramUniformLocations(context, program, shaderUniforms, WTF_ARRAY_LENGTH(shaderUniforms), WTF_ARRAY_LENGTH(locations), locations, usingBindUniform, baseUniformIndex); - - m_matrixLocation = locations[0]; - ASSERT(m_matrixLocation != -1); -} - -std::string VertexShaderPosTex::getShaderString() const -{ - return SHADER( - attribute vec4 a_position; - attribute vec2 a_texCoord; - uniform mat4 matrix; - varying vec2 v_texCoord; - void main() - { - gl_Position = matrix * a_position; - v_texCoord = a_texCoord; - } - ); -} - -VertexShaderPosTexYUVStretch::VertexShaderPosTexYUVStretch() - : m_matrixLocation(-1) - , m_yWidthScaleFactorLocation(-1) - , m_uvWidthScaleFactorLocation(-1) -{ -} - -void VertexShaderPosTexYUVStretch::init(WebGraphicsContext3D* context, unsigned program, bool usingBindUniform, int* baseUniformIndex) -{ - static const char* shaderUniforms[] = { - "matrix", - "y_widthScaleFactor", - "uv_widthScaleFactor", - }; - int locations[3]; - - getProgramUniformLocations(context, program, shaderUniforms, WTF_ARRAY_LENGTH(shaderUniforms), WTF_ARRAY_LENGTH(locations), locations, usingBindUniform, baseUniformIndex); - - m_matrixLocation = locations[0]; - m_yWidthScaleFactorLocation = locations[1]; - m_uvWidthScaleFactorLocation = locations[2]; - ASSERT(m_matrixLocation != -1 && m_yWidthScaleFactorLocation != -1 && m_uvWidthScaleFactorLocation != -1); -} - -std::string VertexShaderPosTexYUVStretch::getShaderString() const -{ - return SHADER( - precision mediump float; - attribute vec4 a_position; - attribute vec2 a_texCoord; - uniform mat4 matrix; - varying vec2 y_texCoord; - varying vec2 uv_texCoord; - uniform float y_widthScaleFactor; - uniform float uv_widthScaleFactor; - void main() - { - gl_Position = matrix * a_position; - y_texCoord = vec2(y_widthScaleFactor * a_texCoord.x, a_texCoord.y); - uv_texCoord = vec2(uv_widthScaleFactor * a_texCoord.x, a_texCoord.y); - } - ); -} - -VertexShaderPos::VertexShaderPos() - : m_matrixLocation(-1) -{ -} - -void VertexShaderPos::init(WebGraphicsContext3D* context, unsigned program, bool usingBindUniform, int* baseUniformIndex) -{ - static const char* shaderUniforms[] = { - "matrix", - }; - int locations[1]; - - getProgramUniformLocations(context, program, shaderUniforms, WTF_ARRAY_LENGTH(shaderUniforms), WTF_ARRAY_LENGTH(locations), locations, usingBindUniform, baseUniformIndex); - - m_matrixLocation = locations[0]; - ASSERT(m_matrixLocation != -1); -} - -std::string VertexShaderPos::getShaderString() const -{ - return SHADER( - attribute vec4 a_position; - uniform mat4 matrix; - void main() - { - gl_Position = matrix * a_position; - } - ); -} - -VertexShaderPosTexTransform::VertexShaderPosTexTransform() - : m_matrixLocation(-1) - , m_texTransformLocation(-1) -{ -} - -void VertexShaderPosTexTransform::init(WebGraphicsContext3D* context, unsigned program, bool usingBindUniform, int* baseUniformIndex) -{ - static const char* shaderUniforms[] = { - "matrix", - "texTransform", - }; - int locations[2]; - - getProgramUniformLocations(context, program, shaderUniforms, WTF_ARRAY_LENGTH(shaderUniforms), WTF_ARRAY_LENGTH(locations), locations, usingBindUniform, baseUniformIndex); - - m_matrixLocation = locations[0]; - m_texTransformLocation = locations[1]; - ASSERT(m_matrixLocation != -1 && m_texTransformLocation != -1); -} - -std::string VertexShaderPosTexTransform::getShaderString() const -{ - return SHADER( - attribute vec4 a_position; - attribute vec2 a_texCoord; - uniform mat4 matrix; - uniform vec4 texTransform; - varying vec2 v_texCoord; - void main() - { - gl_Position = matrix * a_position; - v_texCoord = a_texCoord * texTransform.zw + texTransform.xy; - } - ); -} - -VertexShaderQuad::VertexShaderQuad() - : m_matrixLocation(-1) - , m_pointLocation(-1) -{ -} - -std::string VertexShaderPosTexIdentity::getShaderString() const -{ - return SHADER( - attribute vec4 a_position; - varying vec2 v_texCoord; - void main() - { - gl_Position = a_position; - v_texCoord = (a_position.xy + vec2(1.0)) * 0.5; - } - ); -} - -void VertexShaderQuad::init(WebGraphicsContext3D* context, unsigned program, bool usingBindUniform, int* baseUniformIndex) -{ - static const char* shaderUniforms[] = { - "matrix", - "point", - }; - int locations[2]; - - getProgramUniformLocations(context, program, shaderUniforms, WTF_ARRAY_LENGTH(shaderUniforms), WTF_ARRAY_LENGTH(locations), locations, usingBindUniform, baseUniformIndex); - - m_matrixLocation = locations[0]; - m_pointLocation = locations[1]; - ASSERT(m_matrixLocation != -1 && m_pointLocation != -1); -} - -std::string VertexShaderQuad::getShaderString() const -{ - return SHADER( - attribute vec4 a_position; - attribute vec2 a_texCoord; - uniform mat4 matrix; - uniform vec2 point[4]; - varying vec2 v_texCoord; - void main() - { - vec2 complement = abs(a_texCoord - 1.0); - vec4 pos = vec4(0.0, 0.0, a_position.z, a_position.w); - pos.xy += (complement.x * complement.y) * point[0]; - pos.xy += (a_texCoord.x * complement.y) * point[1]; - pos.xy += (a_texCoord.x * a_texCoord.y) * point[2]; - pos.xy += (complement.x * a_texCoord.y) * point[3]; - gl_Position = matrix * pos; - v_texCoord = pos.xy + vec2(0.5); - } - ); -} - -VertexShaderTile::VertexShaderTile() - : m_matrixLocation(-1) - , m_pointLocation(-1) - , m_vertexTexTransformLocation(-1) -{ -} - -void VertexShaderTile::init(WebGraphicsContext3D* context, unsigned program, bool usingBindUniform, int* baseUniformIndex) -{ - static const char* shaderUniforms[] = { - "matrix", - "point", - "vertexTexTransform", - }; - int locations[3]; - - getProgramUniformLocations(context, program, shaderUniforms, WTF_ARRAY_LENGTH(shaderUniforms), WTF_ARRAY_LENGTH(locations), locations, usingBindUniform, baseUniformIndex); - - m_matrixLocation = locations[0]; - m_pointLocation = locations[1]; - m_vertexTexTransformLocation = locations[2]; - ASSERT(m_matrixLocation != -1 && m_pointLocation != -1 && m_vertexTexTransformLocation != -1); -} - -std::string VertexShaderTile::getShaderString() const -{ - return SHADER( - attribute vec4 a_position; - attribute vec2 a_texCoord; - uniform mat4 matrix; - uniform vec2 point[4]; - uniform vec4 vertexTexTransform; - varying vec2 v_texCoord; - void main() - { - vec2 complement = abs(a_texCoord - 1.0); - vec4 pos = vec4(0.0, 0.0, a_position.z, a_position.w); - pos.xy += (complement.x * complement.y) * point[0]; - pos.xy += (a_texCoord.x * complement.y) * point[1]; - pos.xy += (a_texCoord.x * a_texCoord.y) * point[2]; - pos.xy += (complement.x * a_texCoord.y) * point[3]; - gl_Position = matrix * pos; - v_texCoord = pos.xy * vertexTexTransform.zw + vertexTexTransform.xy; - } - ); -} - -VertexShaderVideoTransform::VertexShaderVideoTransform() - : m_matrixLocation(-1) - , m_texMatrixLocation(-1) -{ -} - -bool VertexShaderVideoTransform::init(WebGraphicsContext3D* context, unsigned program, bool usingBindUniform, int* baseUniformIndex) -{ - static const char* shaderUniforms[] = { - "matrix", - "texMatrix", - }; - int locations[2]; - - getProgramUniformLocations(context, program, shaderUniforms, WTF_ARRAY_LENGTH(shaderUniforms), WTF_ARRAY_LENGTH(locations), locations, usingBindUniform, baseUniformIndex); - - m_matrixLocation = locations[0]; - m_texMatrixLocation = locations[1]; - return m_matrixLocation != -1 && m_texMatrixLocation != -1; -} - -std::string VertexShaderVideoTransform::getShaderString() const -{ - return SHADER( - attribute vec4 a_position; - attribute vec2 a_texCoord; - uniform mat4 matrix; - uniform mat4 texMatrix; - varying vec2 v_texCoord; - void main() - { - gl_Position = matrix * a_position; - v_texCoord = vec2(texMatrix * vec4(a_texCoord.x, 1.0 - a_texCoord.y, 0.0, 1.0)); - } - ); -} - -FragmentTexAlphaBinding::FragmentTexAlphaBinding() - : m_samplerLocation(-1) - , m_alphaLocation(-1) -{ -} - -void FragmentTexAlphaBinding::init(WebGraphicsContext3D* context, unsigned program, bool usingBindUniform, int* baseUniformIndex) -{ - static const char* shaderUniforms[] = { - "s_texture", - "alpha", - }; - int locations[2]; - - getProgramUniformLocations(context, program, shaderUniforms, WTF_ARRAY_LENGTH(shaderUniforms), WTF_ARRAY_LENGTH(locations), locations, usingBindUniform, baseUniformIndex); - - m_samplerLocation = locations[0]; - m_alphaLocation = locations[1]; - ASSERT(m_samplerLocation != -1 && m_alphaLocation != -1); -} - -FragmentTexOpaqueBinding::FragmentTexOpaqueBinding() - : m_samplerLocation(-1) -{ -} - -void FragmentTexOpaqueBinding::init(WebGraphicsContext3D* context, unsigned program, bool usingBindUniform, int* baseUniformIndex) -{ - static const char* shaderUniforms[] = { - "s_texture", - }; - int locations[1]; - - getProgramUniformLocations(context, program, shaderUniforms, WTF_ARRAY_LENGTH(shaderUniforms), WTF_ARRAY_LENGTH(locations), locations, usingBindUniform, baseUniformIndex); - - m_samplerLocation = locations[0]; - ASSERT(m_samplerLocation != -1); -} - -std::string FragmentShaderRGBATexFlipAlpha::getShaderString() const -{ - return SHADER( - precision mediump float; - varying vec2 v_texCoord; - uniform sampler2D s_texture; - uniform float alpha; - void main() - { - vec4 texColor = texture2D(s_texture, vec2(v_texCoord.x, 1.0 - v_texCoord.y)); - gl_FragColor = vec4(texColor.x, texColor.y, texColor.z, texColor.w) * alpha; - } - ); -} - -bool FragmentShaderOESImageExternal::init(WebGraphicsContext3D* context, unsigned program, bool usingBindUniform, int* baseUniformIndex) -{ - static const char* shaderUniforms[] = { - "s_texture", - }; - int locations[1]; - - getProgramUniformLocations(context, program, shaderUniforms, WTF_ARRAY_LENGTH(shaderUniforms), WTF_ARRAY_LENGTH(locations), locations, usingBindUniform, baseUniformIndex); - - m_samplerLocation = locations[0]; - return m_samplerLocation != -1; -} - -std::string FragmentShaderOESImageExternal::getShaderString() const -{ - // Cannot use the SHADER() macro because of the '#' char - return "#extension GL_OES_EGL_image_external : require \n" - "precision mediump float;\n" - "varying vec2 v_texCoord;\n" - "uniform samplerExternalOES s_texture;\n" - "void main()\n" - "{\n" - " vec4 texColor = texture2D(s_texture, v_texCoord);\n" - " gl_FragColor = vec4(texColor.x, texColor.y, texColor.z, texColor.w);\n" - "}\n"; -} - -std::string FragmentShaderRGBATexAlpha::getShaderString() const -{ - return SHADER( - precision mediump float; - varying vec2 v_texCoord; - uniform sampler2D s_texture; - uniform float alpha; - void main() - { - vec4 texColor = texture2D(s_texture, v_texCoord); - gl_FragColor = texColor * alpha; - } - ); -} - -std::string FragmentShaderRGBATexRectFlipAlpha::getShaderString() const -{ - // This must be paired with VertexShaderPosTexTransform to pick up the texTransform uniform. - // The necessary #extension preprocessing directive breaks the SHADER and SHADER0 macros. - return "#extension GL_ARB_texture_rectangle : require\n" - "precision mediump float;\n" - "varying vec2 v_texCoord;\n" - "uniform vec4 texTransform;\n" - "uniform sampler2DRect s_texture;\n" - "uniform float alpha;\n" - "void main()\n" - "{\n" - " vec4 texColor = texture2DRect(s_texture, vec2(v_texCoord.x, texTransform.w - v_texCoord.y));\n" - " gl_FragColor = vec4(texColor.x, texColor.y, texColor.z, texColor.w) * alpha;\n" - "}\n"; -} - -std::string FragmentShaderRGBATexRectAlpha::getShaderString() const -{ - return "#extension GL_ARB_texture_rectangle : require\n" - "precision mediump float;\n" - "varying vec2 v_texCoord;\n" - "uniform sampler2DRect s_texture;\n" - "uniform float alpha;\n" - "void main()\n" - "{\n" - " vec4 texColor = texture2DRect(s_texture, v_texCoord);\n" - " gl_FragColor = texColor * alpha;\n" - "}\n"; -} - -std::string FragmentShaderRGBATexOpaque::getShaderString() const -{ - return SHADER( - precision mediump float; - varying vec2 v_texCoord; - uniform sampler2D s_texture; - void main() - { - vec4 texColor = texture2D(s_texture, v_texCoord); - gl_FragColor = vec4(texColor.rgb, 1.0); - } - ); -} - -std::string FragmentShaderRGBATex::getShaderString() const -{ - return SHADER( - precision mediump float; - varying vec2 v_texCoord; - uniform sampler2D s_texture; - void main() - { - gl_FragColor = texture2D(s_texture, v_texCoord); - } - ); -} - -std::string FragmentShaderRGBATexSwizzleAlpha::getShaderString() const -{ - return SHADER( - precision mediump float; - varying vec2 v_texCoord; - uniform sampler2D s_texture; - uniform float alpha; - void main() - { - vec4 texColor = texture2D(s_texture, v_texCoord); - gl_FragColor = vec4(texColor.z, texColor.y, texColor.x, texColor.w) * alpha; - } - ); -} - -std::string FragmentShaderRGBATexSwizzleOpaque::getShaderString() const -{ - return SHADER( - precision mediump float; - varying vec2 v_texCoord; - uniform sampler2D s_texture; - void main() - { - vec4 texColor = texture2D(s_texture, v_texCoord); - gl_FragColor = vec4(texColor.z, texColor.y, texColor.x, 1.0); - } - ); -} - -FragmentShaderRGBATexAlphaAA::FragmentShaderRGBATexAlphaAA() - : m_samplerLocation(-1) - , m_alphaLocation(-1) - , m_edgeLocation(-1) -{ -} - -void FragmentShaderRGBATexAlphaAA::init(WebGraphicsContext3D* context, unsigned program, bool usingBindUniform, int* baseUniformIndex) -{ - static const char* shaderUniforms[] = { - "s_texture", - "alpha", - "edge", - }; - int locations[3]; - - getProgramUniformLocations(context, program, shaderUniforms, WTF_ARRAY_LENGTH(shaderUniforms), WTF_ARRAY_LENGTH(locations), locations, usingBindUniform, baseUniformIndex); - - m_samplerLocation = locations[0]; - m_alphaLocation = locations[1]; - m_edgeLocation = locations[2]; - ASSERT(m_samplerLocation != -1 && m_alphaLocation != -1 && m_edgeLocation != -1); -} - -std::string FragmentShaderRGBATexAlphaAA::getShaderString() const -{ - return SHADER( - precision mediump float; - varying vec2 v_texCoord; - uniform sampler2D s_texture; - uniform float alpha; - uniform vec3 edge[8]; - void main() - { - vec4 texColor = texture2D(s_texture, v_texCoord); - vec3 pos = vec3(gl_FragCoord.xy, 1); - float a0 = clamp(dot(edge[0], pos), 0.0, 1.0); - float a1 = clamp(dot(edge[1], pos), 0.0, 1.0); - float a2 = clamp(dot(edge[2], pos), 0.0, 1.0); - float a3 = clamp(dot(edge[3], pos), 0.0, 1.0); - float a4 = clamp(dot(edge[4], pos), 0.0, 1.0); - float a5 = clamp(dot(edge[5], pos), 0.0, 1.0); - float a6 = clamp(dot(edge[6], pos), 0.0, 1.0); - float a7 = clamp(dot(edge[7], pos), 0.0, 1.0); - gl_FragColor = texColor * alpha * min(min(a0, a2) * min(a1, a3), min(a4, a6) * min(a5, a7)); - } - ); -} - -FragmentTexClampAlphaAABinding::FragmentTexClampAlphaAABinding() - : m_samplerLocation(-1) - , m_alphaLocation(-1) - , m_fragmentTexTransformLocation(-1) - , m_edgeLocation(-1) -{ -} - -void FragmentTexClampAlphaAABinding::init(WebGraphicsContext3D* context, unsigned program, bool usingBindUniform, int* baseUniformIndex) -{ - static const char* shaderUniforms[] = { - "s_texture", - "alpha", - "fragmentTexTransform", - "edge", - }; - int locations[4]; - - getProgramUniformLocations(context, program, shaderUniforms, WTF_ARRAY_LENGTH(shaderUniforms), WTF_ARRAY_LENGTH(locations), locations, usingBindUniform, baseUniformIndex); - - m_samplerLocation = locations[0]; - m_alphaLocation = locations[1]; - m_fragmentTexTransformLocation = locations[2]; - m_edgeLocation = locations[3]; - ASSERT(m_samplerLocation != -1 && m_alphaLocation != -1 && m_fragmentTexTransformLocation != -1 && m_edgeLocation != -1); -} - -std::string FragmentShaderRGBATexClampAlphaAA::getShaderString() const -{ - return SHADER( - precision mediump float; - varying vec2 v_texCoord; - uniform sampler2D s_texture; - uniform float alpha; - uniform vec4 fragmentTexTransform; - uniform vec3 edge[8]; - void main() - { - vec2 texCoord = clamp(v_texCoord, 0.0, 1.0) * fragmentTexTransform.zw + fragmentTexTransform.xy; - vec4 texColor = texture2D(s_texture, texCoord); - vec3 pos = vec3(gl_FragCoord.xy, 1); - float a0 = clamp(dot(edge[0], pos), 0.0, 1.0); - float a1 = clamp(dot(edge[1], pos), 0.0, 1.0); - float a2 = clamp(dot(edge[2], pos), 0.0, 1.0); - float a3 = clamp(dot(edge[3], pos), 0.0, 1.0); - float a4 = clamp(dot(edge[4], pos), 0.0, 1.0); - float a5 = clamp(dot(edge[5], pos), 0.0, 1.0); - float a6 = clamp(dot(edge[6], pos), 0.0, 1.0); - float a7 = clamp(dot(edge[7], pos), 0.0, 1.0); - gl_FragColor = texColor * alpha * min(min(a0, a2) * min(a1, a3), min(a4, a6) * min(a5, a7)); - } - ); -} - -std::string FragmentShaderRGBATexClampSwizzleAlphaAA::getShaderString() const -{ - return SHADER( - precision mediump float; - varying vec2 v_texCoord; - uniform sampler2D s_texture; - uniform float alpha; - uniform vec4 fragmentTexTransform; - uniform vec3 edge[8]; - void main() - { - vec2 texCoord = clamp(v_texCoord, 0.0, 1.0) * fragmentTexTransform.zw + fragmentTexTransform.xy; - vec4 texColor = texture2D(s_texture, texCoord); - vec3 pos = vec3(gl_FragCoord.xy, 1); - float a0 = clamp(dot(edge[0], pos), 0.0, 1.0); - float a1 = clamp(dot(edge[1], pos), 0.0, 1.0); - float a2 = clamp(dot(edge[2], pos), 0.0, 1.0); - float a3 = clamp(dot(edge[3], pos), 0.0, 1.0); - float a4 = clamp(dot(edge[4], pos), 0.0, 1.0); - float a5 = clamp(dot(edge[5], pos), 0.0, 1.0); - float a6 = clamp(dot(edge[6], pos), 0.0, 1.0); - float a7 = clamp(dot(edge[7], pos), 0.0, 1.0); - gl_FragColor = vec4(texColor.z, texColor.y, texColor.x, texColor.w) * alpha * min(min(a0, a2) * min(a1, a3), min(a4, a6) * min(a5, a7)); - } - ); -} - -FragmentShaderRGBATexAlphaMask::FragmentShaderRGBATexAlphaMask() - : m_samplerLocation(-1) - , m_maskSamplerLocation(-1) - , m_alphaLocation(-1) - , m_maskTexCoordScaleLocation(-1) -{ -} - -void FragmentShaderRGBATexAlphaMask::init(WebGraphicsContext3D* context, unsigned program, bool usingBindUniform, int* baseUniformIndex) -{ - static const char* shaderUniforms[] = { - "s_texture", - "s_mask", - "alpha", - "maskTexCoordScale", - "maskTexCoordOffset", - }; - int locations[5]; - - getProgramUniformLocations(context, program, shaderUniforms, WTF_ARRAY_LENGTH(shaderUniforms), WTF_ARRAY_LENGTH(locations), locations, usingBindUniform, baseUniformIndex); - - m_samplerLocation = locations[0]; - m_maskSamplerLocation = locations[1]; - m_alphaLocation = locations[2]; - m_maskTexCoordScaleLocation = locations[3]; - m_maskTexCoordOffsetLocation = locations[4]; - ASSERT(m_samplerLocation != -1 && m_maskSamplerLocation != -1 && m_alphaLocation != -1); -} - -std::string FragmentShaderRGBATexAlphaMask::getShaderString() const -{ - return SHADER( - precision mediump float; - varying vec2 v_texCoord; - uniform sampler2D s_texture; - uniform sampler2D s_mask; - uniform vec2 maskTexCoordScale; - uniform vec2 maskTexCoordOffset; - uniform float alpha; - void main() - { - vec4 texColor = texture2D(s_texture, v_texCoord); - vec2 maskTexCoord = vec2(maskTexCoordOffset.x + v_texCoord.x * maskTexCoordScale.x, maskTexCoordOffset.y + v_texCoord.y * maskTexCoordScale.y); - vec4 maskColor = texture2D(s_mask, maskTexCoord); - gl_FragColor = vec4(texColor.x, texColor.y, texColor.z, texColor.w) * alpha * maskColor.w; - } - ); -} - -FragmentShaderRGBATexAlphaMaskAA::FragmentShaderRGBATexAlphaMaskAA() - : m_samplerLocation(-1) - , m_maskSamplerLocation(-1) - , m_alphaLocation(-1) - , m_edgeLocation(-1) - , m_maskTexCoordScaleLocation(-1) -{ -} - -void FragmentShaderRGBATexAlphaMaskAA::init(WebGraphicsContext3D* context, unsigned program, bool usingBindUniform, int* baseUniformIndex) -{ - static const char* shaderUniforms[] = { - "s_texture", - "s_mask", - "alpha", - "edge", - "maskTexCoordScale", - "maskTexCoordOffset", - }; - int locations[6]; - - getProgramUniformLocations(context, program, shaderUniforms, WTF_ARRAY_LENGTH(shaderUniforms), WTF_ARRAY_LENGTH(locations), locations, usingBindUniform, baseUniformIndex); - - m_samplerLocation = locations[0]; - m_maskSamplerLocation = locations[1]; - m_alphaLocation = locations[2]; - m_edgeLocation = locations[3]; - m_maskTexCoordScaleLocation = locations[4]; - m_maskTexCoordOffsetLocation = locations[5]; - ASSERT(m_samplerLocation != -1 && m_maskSamplerLocation != -1 && m_alphaLocation != -1 && m_edgeLocation != -1); -} - -std::string FragmentShaderRGBATexAlphaMaskAA::getShaderString() const -{ - return SHADER( - precision mediump float; - varying vec2 v_texCoord; - uniform sampler2D s_texture; - uniform sampler2D s_mask; - uniform vec2 maskTexCoordScale; - uniform vec2 maskTexCoordOffset; - uniform float alpha; - uniform vec3 edge[8]; - void main() - { - vec4 texColor = texture2D(s_texture, v_texCoord); - vec2 maskTexCoord = vec2(maskTexCoordOffset.x + v_texCoord.x * maskTexCoordScale.x, maskTexCoordOffset.y + v_texCoord.y * maskTexCoordScale.y); - vec4 maskColor = texture2D(s_mask, maskTexCoord); - vec3 pos = vec3(gl_FragCoord.xy, 1); - float a0 = clamp(dot(edge[0], pos), 0.0, 1.0); - float a1 = clamp(dot(edge[1], pos), 0.0, 1.0); - float a2 = clamp(dot(edge[2], pos), 0.0, 1.0); - float a3 = clamp(dot(edge[3], pos), 0.0, 1.0); - float a4 = clamp(dot(edge[4], pos), 0.0, 1.0); - float a5 = clamp(dot(edge[5], pos), 0.0, 1.0); - float a6 = clamp(dot(edge[6], pos), 0.0, 1.0); - float a7 = clamp(dot(edge[7], pos), 0.0, 1.0); - gl_FragColor = vec4(texColor.x, texColor.y, texColor.z, texColor.w) * alpha * maskColor.w * min(min(a0, a2) * min(a1, a3), min(a4, a6) * min(a5, a7)); - } - ); -} - -FragmentShaderYUVVideo::FragmentShaderYUVVideo() - : m_yTextureLocation(-1) - , m_uTextureLocation(-1) - , m_vTextureLocation(-1) - , m_alphaLocation(-1) - , m_ccMatrixLocation(-1) - , m_yuvAdjLocation(-1) -{ -} - -void FragmentShaderYUVVideo::init(WebGraphicsContext3D* context, unsigned program, bool usingBindUniform, int* baseUniformIndex) -{ - static const char* shaderUniforms[] = { - "y_texture", - "u_texture", - "v_texture", - "alpha", - "cc_matrix", - "yuv_adj", - }; - int locations[6]; - - getProgramUniformLocations(context, program, shaderUniforms, WTF_ARRAY_LENGTH(shaderUniforms), WTF_ARRAY_LENGTH(locations), locations, usingBindUniform, baseUniformIndex); - - m_yTextureLocation = locations[0]; - m_uTextureLocation = locations[1]; - m_vTextureLocation = locations[2]; - m_alphaLocation = locations[3]; - m_ccMatrixLocation = locations[4]; - m_yuvAdjLocation = locations[5]; - - ASSERT(m_yTextureLocation != -1 && m_uTextureLocation != -1 && m_vTextureLocation != -1 - && m_alphaLocation != -1 && m_ccMatrixLocation != -1 && m_yuvAdjLocation != -1); -} - -std::string FragmentShaderYUVVideo::getShaderString() const -{ - return SHADER( - precision mediump float; - precision mediump int; - varying vec2 y_texCoord; - varying vec2 uv_texCoord; - uniform sampler2D y_texture; - uniform sampler2D u_texture; - uniform sampler2D v_texture; - uniform float alpha; - uniform vec3 yuv_adj; - uniform mat3 cc_matrix; - void main() - { - float y_raw = texture2D(y_texture, y_texCoord).x; - float u_unsigned = texture2D(u_texture, uv_texCoord).x; - float v_unsigned = texture2D(v_texture, uv_texCoord).x; - vec3 yuv = vec3(y_raw, u_unsigned, v_unsigned) + yuv_adj; - vec3 rgb = cc_matrix * yuv; - gl_FragColor = vec4(rgb, float(1)) * alpha; - } - ); -} - -FragmentShaderColor::FragmentShaderColor() - : m_colorLocation(-1) -{ -} - -void FragmentShaderColor::init(WebGraphicsContext3D* context, unsigned program, bool usingBindUniform, int* baseUniformIndex) -{ - static const char* shaderUniforms[] = { - "color", - }; - int locations[1]; - - getProgramUniformLocations(context, program, shaderUniforms, WTF_ARRAY_LENGTH(shaderUniforms), WTF_ARRAY_LENGTH(locations), locations, usingBindUniform, baseUniformIndex); - - m_colorLocation = locations[0]; - ASSERT(m_colorLocation != -1); -} - -std::string FragmentShaderColor::getShaderString() const -{ - return SHADER( - precision mediump float; - uniform vec4 color; - void main() - { - gl_FragColor = color; - } - ); -} - -FragmentShaderCheckerboard::FragmentShaderCheckerboard() - : m_alphaLocation(-1) - , m_texTransformLocation(-1) - , m_frequencyLocation(-1) -{ -} - -void FragmentShaderCheckerboard::init(WebGraphicsContext3D* context, unsigned program, bool usingBindUniform, int* baseUniformIndex) -{ - static const char* shaderUniforms[] = { - "alpha", - "texTransform", - "frequency", - "color", - }; - int locations[4]; - - getProgramUniformLocations(context, program, shaderUniforms, WTF_ARRAY_LENGTH(shaderUniforms), WTF_ARRAY_LENGTH(locations), locations, usingBindUniform, baseUniformIndex); - - m_alphaLocation = locations[0]; - m_texTransformLocation = locations[1]; - m_frequencyLocation = locations[2]; - m_colorLocation = locations[3]; - ASSERT(m_alphaLocation != -1 && m_texTransformLocation != -1 && m_frequencyLocation != -1 && m_colorLocation != -1); -} - -std::string FragmentShaderCheckerboard::getShaderString() const -{ - // Shader based on Example 13-17 of "OpenGL ES 2.0 Programming Guide" - // by Munshi, Ginsburg, Shreiner. - return SHADER( - precision mediump float; - precision mediump int; - varying vec2 v_texCoord; - uniform float alpha; - uniform float frequency; - uniform vec4 texTransform; - uniform vec4 color; - void main() - { - vec4 color1 = vec4(1.0, 1.0, 1.0, 1.0); - vec4 color2 = color; - vec2 texCoord = clamp(v_texCoord, 0.0, 1.0) * texTransform.zw + texTransform.xy; - vec2 coord = mod(floor(texCoord * frequency * 2.0), 2.0); - float picker = abs(coord.x - coord.y); - gl_FragColor = mix(color1, color2, picker) * alpha; - } - ); -} - -} // namespace cc - -#endif // USE(ACCELERATED_COMPOSITING) diff --git a/cc/ShaderChromium.h b/cc/ShaderChromium.h index 2518382..5170597 100644 --- a/cc/ShaderChromium.h +++ b/cc/ShaderChromium.h @@ -1,353 +1,6 @@ -// Copyright 2011 The Chromium Authors. All rights reserved. +// Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef ShaderChromium_h -#define ShaderChromium_h - -#if USE(ACCELERATED_COMPOSITING) - -#include "SkColorPriv.h" -#include - -namespace WebKit { -class WebGraphicsContext3D; -} - -namespace cc { - -class VertexShaderPosTex { -public: - VertexShaderPosTex(); - - void init(WebKit::WebGraphicsContext3D*, unsigned program, bool usingBindUniform, int* baseUniformIndex); - std::string getShaderString() const; - - int matrixLocation() const { return m_matrixLocation; } - -private: - int m_matrixLocation; -}; - -class VertexShaderPosTexYUVStretch { -public: - VertexShaderPosTexYUVStretch(); - - void init(WebKit::WebGraphicsContext3D*, unsigned program, bool usingBindUniform, int* baseUniformIndex); - std::string getShaderString() const; - - int matrixLocation() const { return m_matrixLocation; } - int yWidthScaleFactorLocation() const { return m_yWidthScaleFactorLocation; } - int uvWidthScaleFactorLocation() const { return m_uvWidthScaleFactorLocation; } - -private: - int m_matrixLocation; - int m_yWidthScaleFactorLocation; - int m_uvWidthScaleFactorLocation; -}; - -class VertexShaderPos { -public: - VertexShaderPos(); - - void init(WebKit::WebGraphicsContext3D*, unsigned program, bool usingBindUniform, int* baseUniformIndex); - std::string getShaderString() const; - - int matrixLocation() const { return m_matrixLocation; } - -private: - int m_matrixLocation; -}; - -class VertexShaderPosTexIdentity { -public: - void init(WebKit::WebGraphicsContext3D*, unsigned program, bool usingBindUniform, int* baseUniformIndex) { } - std::string getShaderString() const; -}; - -class VertexShaderPosTexTransform { -public: - VertexShaderPosTexTransform(); - - void init(WebKit::WebGraphicsContext3D*, unsigned program, bool usingBindUniform, int* baseUniformIndex); - std::string getShaderString() const; - - int matrixLocation() const { return m_matrixLocation; } - int texTransformLocation() const { return m_texTransformLocation; } - -private: - int m_matrixLocation; - int m_texTransformLocation; -}; - -class VertexShaderQuad { -public: - VertexShaderQuad(); - - void init(WebKit::WebGraphicsContext3D*, unsigned program, bool usingBindUniform, int* baseUniformIndex); - std::string getShaderString() const; - - int matrixLocation() const { return m_matrixLocation; } - int pointLocation() const { return m_pointLocation; } - -private: - int m_matrixLocation; - int m_pointLocation; -}; - -class VertexShaderTile { -public: - VertexShaderTile(); - - void init(WebKit::WebGraphicsContext3D*, unsigned program, bool usingBindUniform, int* baseUniformIndex); - std::string getShaderString() const; - - int matrixLocation() const { return m_matrixLocation; } - int pointLocation() const { return m_pointLocation; } - int vertexTexTransformLocation() const { return m_vertexTexTransformLocation; } - -private: - int m_matrixLocation; - int m_pointLocation; - int m_vertexTexTransformLocation; -}; - -class VertexShaderVideoTransform { -public: - VertexShaderVideoTransform(); - - bool init(WebKit::WebGraphicsContext3D*, unsigned program, bool usingBindUniform, int* baseUniformIndex); - std::string getShaderString() const; - - int matrixLocation() const { return m_matrixLocation; } - int texMatrixLocation() const { return m_texMatrixLocation; } - -private: - int m_matrixLocation; - int m_texMatrixLocation; -}; - -class FragmentTexAlphaBinding { -public: - FragmentTexAlphaBinding(); - - void init(WebKit::WebGraphicsContext3D*, unsigned program, bool usingBindUniform, int* baseUniformIndex); - int alphaLocation() const { return m_alphaLocation; } - int edgeLocation() const { return -1; } - int fragmentTexTransformLocation() const { return -1; } - int samplerLocation() const { return m_samplerLocation; } - -private: - int m_samplerLocation; - int m_alphaLocation; -}; - -class FragmentTexOpaqueBinding { -public: - FragmentTexOpaqueBinding(); - - void init(WebKit::WebGraphicsContext3D*, unsigned program, bool usingBindUniform, int* baseUniformIndex); - int alphaLocation() const { return -1; } - int edgeLocation() const { return -1; } - int fragmentTexTransformLocation() const { return -1; } - int samplerLocation() const { return m_samplerLocation; } - -private: - int m_samplerLocation; -}; - -class FragmentShaderRGBATexFlipAlpha : public FragmentTexAlphaBinding { -public: - std::string getShaderString() const; -}; - -class FragmentShaderRGBATexAlpha : public FragmentTexAlphaBinding { -public: - std::string getShaderString() const; -}; - -class FragmentShaderRGBATexRectFlipAlpha : public FragmentTexAlphaBinding { -public: - std::string getShaderString() const; -}; - -class FragmentShaderRGBATexRectAlpha : public FragmentTexAlphaBinding { -public: - std::string getShaderString() const; -}; - -class FragmentShaderRGBATexOpaque : public FragmentTexOpaqueBinding { -public: - std::string getShaderString() const; -}; - -class FragmentShaderRGBATex : public FragmentTexOpaqueBinding { -public: - std::string getShaderString() const; -}; - -// Swizzles the red and blue component of sampled texel with alpha. -class FragmentShaderRGBATexSwizzleAlpha : public FragmentTexAlphaBinding { -public: - std::string getShaderString() const; -}; - -// Swizzles the red and blue component of sampled texel without alpha. -class FragmentShaderRGBATexSwizzleOpaque : public FragmentTexOpaqueBinding { -public: - std::string getShaderString() const; -}; - -// Fragment shader for external textures. -class FragmentShaderOESImageExternal : public FragmentTexAlphaBinding { -public: - std::string getShaderString() const; - bool init(WebKit::WebGraphicsContext3D*, unsigned program, bool usingBindUniform, int* baseUniformIndex); -private: - int m_samplerLocation; -}; - -class FragmentShaderRGBATexAlphaAA { -public: - FragmentShaderRGBATexAlphaAA(); - - void init(WebKit::WebGraphicsContext3D*, unsigned program, bool usingBindUniform, int* baseUniformIndex); - std::string getShaderString() const; - - int alphaLocation() const { return m_alphaLocation; } - int samplerLocation() const { return m_samplerLocation; } - int edgeLocation() const { return m_edgeLocation; } - -private: - int m_samplerLocation; - int m_alphaLocation; - int m_edgeLocation; -}; - -class FragmentTexClampAlphaAABinding { -public: - FragmentTexClampAlphaAABinding(); - - void init(WebKit::WebGraphicsContext3D*, unsigned program, bool usingBindUniform, int* baseUniformIndex); - int alphaLocation() const { return m_alphaLocation; } - int samplerLocation() const { return m_samplerLocation; } - int fragmentTexTransformLocation() const { return m_fragmentTexTransformLocation; } - int edgeLocation() const { return m_edgeLocation; } - -private: - int m_samplerLocation; - int m_alphaLocation; - int m_fragmentTexTransformLocation; - int m_edgeLocation; -}; - -class FragmentShaderRGBATexClampAlphaAA : public FragmentTexClampAlphaAABinding { -public: - std::string getShaderString() const; -}; - -// Swizzles the red and blue component of sampled texel. -class FragmentShaderRGBATexClampSwizzleAlphaAA : public FragmentTexClampAlphaAABinding { -public: - std::string getShaderString() const; -}; - -class FragmentShaderRGBATexAlphaMask { -public: - FragmentShaderRGBATexAlphaMask(); - std::string getShaderString() const; - - void init(WebKit::WebGraphicsContext3D*, unsigned program, bool usingBindUniform, int* baseUniformIndex); - int alphaLocation() const { return m_alphaLocation; } - int samplerLocation() const { return m_samplerLocation; } - int maskSamplerLocation() const { return m_maskSamplerLocation; } - int maskTexCoordScaleLocation() const { return m_maskTexCoordScaleLocation; } - int maskTexCoordOffsetLocation() const { return m_maskTexCoordOffsetLocation; } - -private: - int m_samplerLocation; - int m_maskSamplerLocation; - int m_alphaLocation; - int m_maskTexCoordScaleLocation; - int m_maskTexCoordOffsetLocation; -}; - -class FragmentShaderRGBATexAlphaMaskAA { -public: - FragmentShaderRGBATexAlphaMaskAA(); - std::string getShaderString() const; - - void init(WebKit::WebGraphicsContext3D*, unsigned program, bool usingBindUniform, int* baseUniformIndex); - int alphaLocation() const { return m_alphaLocation; } - int samplerLocation() const { return m_samplerLocation; } - int maskSamplerLocation() const { return m_maskSamplerLocation; } - int edgeLocation() const { return m_edgeLocation; } - int maskTexCoordScaleLocation() const { return m_maskTexCoordScaleLocation; } - int maskTexCoordOffsetLocation() const { return m_maskTexCoordOffsetLocation; } - -private: - int m_samplerLocation; - int m_maskSamplerLocation; - int m_alphaLocation; - int m_edgeLocation; - int m_maskTexCoordScaleLocation; - int m_maskTexCoordOffsetLocation; -}; - -class FragmentShaderYUVVideo { -public: - FragmentShaderYUVVideo(); - std::string getShaderString() const; - - void init(WebKit::WebGraphicsContext3D*, unsigned program, bool usingBindUniform, int* baseUniformIndex); - - int yTextureLocation() const { return m_yTextureLocation; } - int uTextureLocation() const { return m_uTextureLocation; } - int vTextureLocation() const { return m_vTextureLocation; } - int alphaLocation() const { return m_alphaLocation; } - int ccMatrixLocation() const { return m_ccMatrixLocation; } - int yuvAdjLocation() const { return m_yuvAdjLocation; } - -private: - int m_yTextureLocation; - int m_uTextureLocation; - int m_vTextureLocation; - int m_alphaLocation; - int m_ccMatrixLocation; - int m_yuvAdjLocation; -}; - -class FragmentShaderColor { -public: - FragmentShaderColor(); - std::string getShaderString() const; - - void init(WebKit::WebGraphicsContext3D*, unsigned program, bool usingBindUniform, int* baseUniformIndex); - int colorLocation() const { return m_colorLocation; } - -private: - int m_colorLocation; -}; - -class FragmentShaderCheckerboard { -public: - FragmentShaderCheckerboard(); - std::string getShaderString() const; - - void init(WebKit::WebGraphicsContext3D*, unsigned program, bool usingBindUniform, int* baseUniformIndex); - int alphaLocation() const { return m_alphaLocation; } - int texTransformLocation() const { return m_texTransformLocation; } - int frequencyLocation() const { return m_frequencyLocation; } - int colorLocation() const { return m_colorLocation; } -private: - int m_alphaLocation; - int m_texTransformLocation; - int m_frequencyLocation; - int m_colorLocation; -}; - -} // namespace cc - -#endif // USE(ACCELERATED_COMPOSITING) - -#endif +// Temporary forwarding header +#include "cc/shader.h" diff --git a/cc/SkPictureCanvasLayerTextureUpdater.cpp b/cc/SkPictureCanvasLayerTextureUpdater.cpp deleted file mode 100644 index 62026d7..0000000 --- a/cc/SkPictureCanvasLayerTextureUpdater.cpp +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - - -#include "config.h" - -#if USE(ACCELERATED_COMPOSITING) - -#include "SkPictureCanvasLayerTextureUpdater.h" - -#include "LayerPainterChromium.h" -#include "SkCanvas.h" -#include "TraceEvent.h" - -namespace cc { - -SkPictureCanvasLayerTextureUpdater::SkPictureCanvasLayerTextureUpdater(PassOwnPtr painter) - : CanvasLayerTextureUpdater(painter) - , m_layerIsOpaque(false) -{ -} - -SkPictureCanvasLayerTextureUpdater::~SkPictureCanvasLayerTextureUpdater() -{ -} - -void SkPictureCanvasLayerTextureUpdater::prepareToUpdate(const IntRect& contentRect, const IntSize&, float contentsWidthScale, float contentsHeightScale, IntRect& resultingOpaqueRect, CCRenderingStats& stats) -{ - SkCanvas* canvas = m_picture.beginRecording(contentRect.width(), contentRect.height()); - paintContents(canvas, contentRect, contentsWidthScale, contentsHeightScale, resultingOpaqueRect, stats); - m_picture.endRecording(); -} - -void SkPictureCanvasLayerTextureUpdater::drawPicture(SkCanvas* canvas) -{ - TRACE_EVENT0("cc", "SkPictureCanvasLayerTextureUpdater::drawPicture"); - canvas->drawPicture(m_picture); -} - -void SkPictureCanvasLayerTextureUpdater::setOpaque(bool opaque) -{ - m_layerIsOpaque = opaque; -} - -} // namespace cc -#endif // USE(ACCELERATED_COMPOSITING) diff --git a/cc/SkPictureCanvasLayerTextureUpdater.h b/cc/SkPictureCanvasLayerTextureUpdater.h index fd9bb5f..8d3d49e 100644 --- a/cc/SkPictureCanvasLayerTextureUpdater.h +++ b/cc/SkPictureCanvasLayerTextureUpdater.h @@ -1,48 +1,6 @@ -// Copyright 2011 The Chromium Authors. All rights reserved. +// Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. - -#ifndef SkPictureCanvasLayerTextureUpdater_h -#define SkPictureCanvasLayerTextureUpdater_h - -#if USE(ACCELERATED_COMPOSITING) - -#include "CanvasLayerTextureUpdater.h" -#include "SkPicture.h" - -class SkCanvas; - -namespace cc { - -class LayerPainterChromium; - -// This class records the contentRect into an SkPicture. Subclasses, provide -// different implementations of tile updating based on this recorded picture. -// The BitmapSkPictureCanvasLayerTextureUpdater and -// FrameBufferSkPictureCanvasLayerTextureUpdater are two examples of such -// implementations. -class SkPictureCanvasLayerTextureUpdater : public CanvasLayerTextureUpdater { -public: - virtual ~SkPictureCanvasLayerTextureUpdater(); - - virtual void setOpaque(bool) OVERRIDE; - -protected: - explicit SkPictureCanvasLayerTextureUpdater(PassOwnPtr); - - virtual void prepareToUpdate(const IntRect& contentRect, const IntSize& tileSize, float contentsWidthScale, float contentsHeightScale, IntRect& resultingOpaqueRect, CCRenderingStats&) OVERRIDE; - void drawPicture(SkCanvas*); - - bool layerIsOpaque() const { return m_layerIsOpaque; } - -private: - // Recording canvas. - SkPicture m_picture; - // True when it is known that all output pixels will be opaque. - bool m_layerIsOpaque; -}; - -} // namespace cc -#endif // USE(ACCELERATED_COMPOSITING) -#endif // SkPictureCanvasLayerTextureUpdater_h +// Temporary forwarding header +#include "cc/skpicture_canvas_layer_texture_updater.h" diff --git a/cc/SolidColorLayerChromium.cpp b/cc/SolidColorLayerChromium.cpp deleted file mode 100644 index d5c0b42..0000000 --- a/cc/SolidColorLayerChromium.cpp +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "config.h" - -#if USE(ACCELERATED_COMPOSITING) - -#include "SolidColorLayerChromium.h" - -#include "CCSolidColorLayerImpl.h" - -namespace cc { - -scoped_ptr SolidColorLayerChromium::createCCLayerImpl() -{ - return CCSolidColorLayerImpl::create(id()).PassAs(); -} - -scoped_refptr SolidColorLayerChromium::create() -{ - return make_scoped_refptr(new SolidColorLayerChromium()); -} - -SolidColorLayerChromium::SolidColorLayerChromium() - : LayerChromium() -{ -} - -SolidColorLayerChromium::~SolidColorLayerChromium() -{ -} - -} // namespace cc - -#endif // USE(ACCELERATED_COMPOSITING) diff --git a/cc/SolidColorLayerChromium.h b/cc/SolidColorLayerChromium.h index 9123484..a60d376 100644 --- a/cc/SolidColorLayerChromium.h +++ b/cc/SolidColorLayerChromium.h @@ -2,32 +2,5 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. - -#ifndef SolidColorLayerChromium_h -#define SolidColorLayerChromium_h - -#if USE(ACCELERATED_COMPOSITING) - -#include "LayerChromium.h" - -namespace cc { - -// A Layer that renders a solid color. The color is specified by using -// setBackgroundColor() on the base class. -class SolidColorLayerChromium : public LayerChromium { -public: - static scoped_refptr create(); - - virtual scoped_ptr createCCLayerImpl() OVERRIDE; - -protected: - SolidColorLayerChromium(); - -private: - virtual ~SolidColorLayerChromium(); -}; - -} -#endif // USE(ACCELERATED_COMPOSITING) - -#endif +// Temporary forwarding header +#include "cc/solid_color_layer.h" diff --git a/cc/TextureCopier.cpp b/cc/TextureCopier.cpp deleted file mode 100644 index b0db144..0000000 --- a/cc/TextureCopier.cpp +++ /dev/null @@ -1,101 +0,0 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "config.h" - -#include "TextureCopier.h" - -#include "CCRendererGL.h" // For the GLC() macro. -#include "GraphicsContext3D.h" -#include "TraceEvent.h" -#include - -namespace cc { - -#if USE(ACCELERATED_COMPOSITING) -AcceleratedTextureCopier::AcceleratedTextureCopier(WebKit::WebGraphicsContext3D* context, bool usingBindUniforms) - : m_context(context) - , m_usingBindUniforms(usingBindUniforms) -{ - ASSERT(m_context); - GLC(m_context, m_fbo = m_context->createFramebuffer()); - GLC(m_context, m_positionBuffer = m_context->createBuffer()); - - static const float kPositions[4][4] = { - {-1, -1, 0, 1}, - { 1, -1, 0, 1}, - { 1, 1, 0, 1}, - {-1, 1, 0, 1} - }; - - GLC(m_context, m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, m_positionBuffer)); - GLC(m_context, m_context->bufferData(GraphicsContext3D::ARRAY_BUFFER, sizeof(kPositions), kPositions, GraphicsContext3D::STATIC_DRAW)); - GLC(m_context, m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, 0)); - - m_blitProgram = adoptPtr(new BlitProgram(m_context)); -} - -AcceleratedTextureCopier::~AcceleratedTextureCopier() -{ - if (m_blitProgram) - m_blitProgram->cleanup(m_context); - if (m_positionBuffer) - GLC(m_context, m_context->deleteBuffer(m_positionBuffer)); - if (m_fbo) - GLC(m_context, m_context->deleteFramebuffer(m_fbo)); -} - -void AcceleratedTextureCopier::copyTexture(Parameters parameters) -{ - TRACE_EVENT0("cc", "TextureCopier::copyTexture"); - - // Note: this code does not restore the viewport, bound program, 2D texture, framebuffer, buffer or blend enable. - GLC(m_context, m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_fbo)); - GLC(m_context, m_context->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE_2D, parameters.destTexture, 0)); - -#if OS(ANDROID) - // Clear destination to improve performance on tiling GPUs. - // TODO: Use EXT_discard_framebuffer or skip clearing if it isn't available. - GLC(m_context, m_context->clear(GraphicsContext3D::COLOR_BUFFER_BIT)); -#endif - - GLC(m_context, m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, parameters.sourceTexture)); - GLC(m_context, m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::NEAREST)); - GLC(m_context, m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::NEAREST)); - - if (!m_blitProgram->initialized()) - m_blitProgram->initialize(m_context, m_usingBindUniforms); - - // TODO: Use EXT_framebuffer_blit if available. - GLC(m_context, m_context->useProgram(m_blitProgram->program())); - - const int kPositionAttribute = 0; - GLC(m_context, m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, m_positionBuffer)); - GLC(m_context, m_context->vertexAttribPointer(kPositionAttribute, 4, GraphicsContext3D::FLOAT, false, 0, 0)); - GLC(m_context, m_context->enableVertexAttribArray(kPositionAttribute)); - GLC(m_context, m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, 0)); - - GLC(m_context, m_context->viewport(0, 0, parameters.size.width(), parameters.size.height())); - GLC(m_context, m_context->disable(GraphicsContext3D::BLEND)); - GLC(m_context, m_context->drawArrays(GraphicsContext3D::TRIANGLE_FAN, 0, 4)); - - GLC(m_context, m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR)); - GLC(m_context, m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR)); - GLC(m_context, m_context->disableVertexAttribArray(kPositionAttribute)); - - GLC(m_context, m_context->useProgram(0)); - - GLC(m_context, m_context->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE_2D, 0, 0)); - GLC(m_context, m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, 0)); - GLC(m_context, m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, 0)); -} - -void AcceleratedTextureCopier::flush() -{ - GLC(m_context, m_context->flush()); -} - -} - -#endif // USE(ACCELERATED_COMPOSITING) diff --git a/cc/TextureCopier.h b/cc/TextureCopier.h index ba8d7bf..de210fe 100644 --- a/cc/TextureCopier.h +++ b/cc/TextureCopier.h @@ -2,69 +2,5 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef TextureCopier_h -#define TextureCopier_h - -#include "base/basictypes.h" -#include "GraphicsContext3D.h" -#include "ProgramBinding.h" -#include "ShaderChromium.h" -#include -#include - -namespace WebKit { -class WebGraphicsContext3D; -} - -namespace cc { -class IntSize; - -class TextureCopier { -public: - struct Parameters { - unsigned sourceTexture; - unsigned destTexture; - IntSize size; - }; - // Copy the base level contents of |sourceTexture| to |destTexture|. Both texture objects - // must be complete and have a base level of |size| dimensions. The color formats do not need - // to match, but |destTexture| must have a renderable format. - virtual void copyTexture(Parameters) = 0; - virtual void flush() = 0; - - virtual ~TextureCopier() { } -}; - -#if USE(ACCELERATED_COMPOSITING) - -class AcceleratedTextureCopier : public TextureCopier { -public: - static PassOwnPtr create(WebKit::WebGraphicsContext3D* context, bool usingBindUniforms) - { - return adoptPtr(new AcceleratedTextureCopier(context, usingBindUniforms)); - } - virtual ~AcceleratedTextureCopier(); - - virtual void copyTexture(Parameters) OVERRIDE; - virtual void flush() OVERRIDE; - -protected: - AcceleratedTextureCopier(WebKit::WebGraphicsContext3D*, bool usingBindUniforms); - -private: - typedef ProgramBinding BlitProgram; - - WebKit::WebGraphicsContext3D* m_context; - Platform3DObject m_fbo; - Platform3DObject m_positionBuffer; - OwnPtr m_blitProgram; - bool m_usingBindUniforms; - - DISALLOW_COPY_AND_ASSIGN(AcceleratedTextureCopier); -}; - -#endif // USE(ACCELERATED_COMPOSITING) - -} - -#endif +// Temporary forwarding header +#include "cc/texture_copier.h" diff --git a/cc/TextureLayerChromium.cpp b/cc/TextureLayerChromium.cpp deleted file mode 100644 index e1b4851..0000000 --- a/cc/TextureLayerChromium.cpp +++ /dev/null @@ -1,135 +0,0 @@ -// Copyright 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "config.h" - -#if USE(ACCELERATED_COMPOSITING) - -#include "TextureLayerChromium.h" - -#include "CCLayerTreeHost.h" -#include "CCTextureLayerImpl.h" -#include "GraphicsContext3D.h" -#include "TextureLayerChromiumClient.h" -#include - -namespace cc { - -scoped_refptr TextureLayerChromium::create(TextureLayerChromiumClient* client) -{ - return scoped_refptr(new TextureLayerChromium(client)); -} - -TextureLayerChromium::TextureLayerChromium(TextureLayerChromiumClient* client) - : LayerChromium() - , m_client(client) - , m_flipped(true) - , m_uvRect(0, 0, 1, 1) - , m_premultipliedAlpha(true) - , m_rateLimitContext(false) - , m_contextLost(false) - , m_textureId(0) -{ -} - -TextureLayerChromium::~TextureLayerChromium() -{ - if (layerTreeHost()) { - if (m_textureId) - layerTreeHost()->acquireLayerTextures(); - if (m_rateLimitContext && m_client) - layerTreeHost()->stopRateLimiter(m_client->context()); - } -} - -scoped_ptr TextureLayerChromium::createCCLayerImpl() -{ - return CCTextureLayerImpl::create(m_layerId).PassAs(); -} - -void TextureLayerChromium::setFlipped(bool flipped) -{ - m_flipped = flipped; - setNeedsCommit(); -} - -void TextureLayerChromium::setUVRect(const FloatRect& rect) -{ - m_uvRect = rect; - setNeedsCommit(); -} - -void TextureLayerChromium::setPremultipliedAlpha(bool premultipliedAlpha) -{ - m_premultipliedAlpha = premultipliedAlpha; - setNeedsCommit(); -} - -void TextureLayerChromium::setRateLimitContext(bool rateLimit) -{ - if (!rateLimit && m_rateLimitContext && m_client && layerTreeHost()) - layerTreeHost()->stopRateLimiter(m_client->context()); - - m_rateLimitContext = rateLimit; -} - -void TextureLayerChromium::setTextureId(unsigned id) -{ - if (m_textureId == id) - return; - if (m_textureId && layerTreeHost()) - layerTreeHost()->acquireLayerTextures(); - m_textureId = id; - setNeedsCommit(); -} - -void TextureLayerChromium::willModifyTexture() -{ - if (layerTreeHost()) - layerTreeHost()->acquireLayerTextures(); -} - -void TextureLayerChromium::setNeedsDisplayRect(const FloatRect& dirtyRect) -{ - LayerChromium::setNeedsDisplayRect(dirtyRect); - - if (m_rateLimitContext && m_client && layerTreeHost()) - layerTreeHost()->startRateLimiter(m_client->context()); -} - -void TextureLayerChromium::setLayerTreeHost(CCLayerTreeHost* host) -{ - if (m_textureId && layerTreeHost() && host != layerTreeHost()) - layerTreeHost()->acquireLayerTextures(); - LayerChromium::setLayerTreeHost(host); -} - -bool TextureLayerChromium::drawsContent() const -{ - return (m_client || m_textureId) && !m_contextLost && LayerChromium::drawsContent(); -} - -void TextureLayerChromium::update(CCTextureUpdateQueue& queue, const CCOcclusionTracker*, CCRenderingStats&) -{ - if (m_client) { - m_textureId = m_client->prepareTexture(queue); - m_contextLost = m_client->context()->getGraphicsResetStatusARB() != GraphicsContext3D::NO_ERROR; - } - - m_needsDisplay = false; -} - -void TextureLayerChromium::pushPropertiesTo(CCLayerImpl* layer) -{ - LayerChromium::pushPropertiesTo(layer); - - CCTextureLayerImpl* textureLayer = static_cast(layer); - textureLayer->setFlipped(m_flipped); - textureLayer->setUVRect(m_uvRect); - textureLayer->setPremultipliedAlpha(m_premultipliedAlpha); - textureLayer->setTextureId(m_textureId); -} - -} -#endif // USE(ACCELERATED_COMPOSITING) diff --git a/cc/TextureLayerChromium.h b/cc/TextureLayerChromium.h index 124f845..620c2d5 100644 --- a/cc/TextureLayerChromium.h +++ b/cc/TextureLayerChromium.h @@ -1,77 +1,6 @@ -// Copyright 2010 The Chromium Authors. All rights reserved. +// Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef TextureLayerChromium_h -#define TextureLayerChromium_h - -#if USE(ACCELERATED_COMPOSITING) - -#include "LayerChromium.h" - -namespace WebKit { -class WebGraphicsContext3D; -} - -namespace cc { - -class TextureLayerChromiumClient; - -// A Layer containing a the rendered output of a plugin instance. -class TextureLayerChromium : public LayerChromium { -public: - // If this texture layer requires special preparation logic for each frame driven by - // the compositor, pass in a non-nil client. Pass in a nil client pointer if texture updates - // are driven by an external process. - static scoped_refptr create(TextureLayerChromiumClient*); - - void clearClient() { m_client = 0; } - - virtual scoped_ptr createCCLayerImpl() OVERRIDE; - - // Sets whether this texture should be Y-flipped at draw time. Defaults to true. - void setFlipped(bool); - - // Sets a UV transform to be used at draw time. Defaults to (0, 0, 1, 1). - void setUVRect(const FloatRect&); - - // Sets whether the alpha channel is premultiplied or unpremultiplied. Defaults to true. - void setPremultipliedAlpha(bool); - - // Sets whether this context should rate limit on damage to prevent too many frames from - // being queued up before the compositor gets a chance to run. Requires a non-nil client. - // Defaults to false. - void setRateLimitContext(bool); - - // Code path for plugins which supply their own texture ID. - void setTextureId(unsigned); - - void willModifyTexture(); - - virtual void setNeedsDisplayRect(const FloatRect&) OVERRIDE; - - virtual void setLayerTreeHost(CCLayerTreeHost*) OVERRIDE; - virtual bool drawsContent() const OVERRIDE; - virtual void update(CCTextureUpdateQueue&, const CCOcclusionTracker*, CCRenderingStats&) OVERRIDE; - virtual void pushPropertiesTo(CCLayerImpl*) OVERRIDE; - -protected: - explicit TextureLayerChromium(TextureLayerChromiumClient*); - virtual ~TextureLayerChromium(); - -private: - TextureLayerChromiumClient* m_client; - - bool m_flipped; - FloatRect m_uvRect; - bool m_premultipliedAlpha; - bool m_rateLimitContext; - bool m_contextLost; - - unsigned m_textureId; -}; - -} -#endif // USE(ACCELERATED_COMPOSITING) - -#endif +// Temporary forwarding header +#include "cc/texture_layer.h" diff --git a/cc/TextureLayerChromiumClient.h b/cc/TextureLayerChromiumClient.h index 4edbe9f..bec4fa5 100644 --- a/cc/TextureLayerChromiumClient.h +++ b/cc/TextureLayerChromiumClient.h @@ -2,30 +2,5 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef TextureLayerChromiumClient_h -#define TextureLayerChromiumClient_h - -namespace WebKit { -class WebGraphicsContext3D; -} - -namespace cc { -class CCTextureUpdateQueue; - -class TextureLayerChromiumClient { -public: - // Called to prepare this layer's texture for compositing. The client may queue a texture - // upload or copy on the CCTextureUpdateQueue. - // Returns the texture ID to be used for compositing. - virtual unsigned prepareTexture(CCTextureUpdateQueue&) = 0; - - // Returns the context that is providing the texture. Used for rate limiting and detecting lost context. - virtual WebKit::WebGraphicsContext3D* context() = 0; - -protected: - virtual ~TextureLayerChromiumClient() { } -}; - -} - -#endif // TextureLayerChromiumClient_h +// Temporary forwarding header +#include "cc/texture_layer_client.h" diff --git a/cc/TextureUploader.h b/cc/TextureUploader.h index 5505204..0cf73f7 100644 --- a/cc/TextureUploader.h +++ b/cc/TextureUploader.h @@ -2,31 +2,5 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef TextureUploader_h -#define TextureUploader_h - -#include "LayerTextureUpdater.h" - -namespace cc { - -class TextureUploader { -public: - struct Parameters { - LayerTextureUpdater::Texture* texture; - IntRect sourceRect; - IntSize destOffset; - }; - - virtual ~TextureUploader() { } - - virtual size_t numBlockingUploads() = 0; - virtual void markPendingUploadsAsNonBlocking() = 0; - - // Returns our throughput on the GPU process - virtual double estimatedTexturesPerSecond() = 0; - virtual void uploadTexture(CCResourceProvider*, Parameters) = 0; -}; - -} - -#endif +// Temporary forwarding header +#include "cc/texture_uploader.h" diff --git a/cc/ThrottledTextureUploader.cpp b/cc/ThrottledTextureUploader.cpp deleted file mode 100644 index 179f2b6..0000000 --- a/cc/ThrottledTextureUploader.cpp +++ /dev/null @@ -1,186 +0,0 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "config.h" -#include "ThrottledTextureUploader.h" - -#include "Extensions3DChromium.h" -#include "TraceEvent.h" -#include -#include -#include -#include - -namespace { - -// How many previous uploads to use when predicting future throughput. -static const size_t uploadHistorySize = 100; - -// Global estimated number of textures per second to maintain estimates across -// subsequent instances of ThrottledTextureUploader. -// More than one thread will not access this variable, so we do not need to synchronize access. -static double estimatedTexturesPerSecondGlobal = 48.0 * 60.0; - -} // anonymous namespace - -namespace cc { - -ThrottledTextureUploader::Query::Query(WebKit::WebGraphicsContext3D* context) - : m_context(context) - , m_queryId(0) - , m_value(0) - , m_hasValue(false) - , m_isNonBlocking(false) -{ - m_queryId = m_context->createQueryEXT(); -} - -ThrottledTextureUploader::Query::~Query() -{ - m_context->deleteQueryEXT(m_queryId); -} - -void ThrottledTextureUploader::Query::begin() -{ - m_hasValue = false; - m_isNonBlocking = false; - m_context->beginQueryEXT(Extensions3DChromium::COMMANDS_ISSUED_CHROMIUM, m_queryId); -} - -void ThrottledTextureUploader::Query::end() -{ - m_context->endQueryEXT(Extensions3DChromium::COMMANDS_ISSUED_CHROMIUM); -} - -bool ThrottledTextureUploader::Query::isPending() -{ - unsigned available = 1; - m_context->getQueryObjectuivEXT(m_queryId, Extensions3DChromium::QUERY_RESULT_AVAILABLE_EXT, &available); - return !available; -} - -void ThrottledTextureUploader::Query::wait() -{ - value(); - return; -} - -unsigned ThrottledTextureUploader::Query::value() -{ - if (!m_hasValue) { - m_context->getQueryObjectuivEXT(m_queryId, Extensions3DChromium::QUERY_RESULT_EXT, &m_value); - m_hasValue = true; - } - return m_value; -} - -void ThrottledTextureUploader::Query::markAsNonBlocking() -{ - m_isNonBlocking = true; -} - -bool ThrottledTextureUploader::Query::isNonBlocking() -{ - return m_isNonBlocking; -} - -ThrottledTextureUploader::ThrottledTextureUploader(WebKit::WebGraphicsContext3D* context) - : m_context(context) - , m_texturesPerSecondHistory(uploadHistorySize, estimatedTexturesPerSecondGlobal) - , m_numBlockingTextureUploads(0) -{ -} - -ThrottledTextureUploader::~ThrottledTextureUploader() -{ -} - -size_t ThrottledTextureUploader::numBlockingUploads() -{ - processQueries(); - return m_numBlockingTextureUploads; -} - -void ThrottledTextureUploader::markPendingUploadsAsNonBlocking() -{ - for (Deque >::iterator it = m_pendingQueries.begin(); - it != m_pendingQueries.end(); ++it) { - if (it->get()->isNonBlocking()) - continue; - - m_numBlockingTextureUploads--; - it->get()->markAsNonBlocking(); - } - - ASSERT(!m_numBlockingTextureUploads); -} - -double ThrottledTextureUploader::estimatedTexturesPerSecond() -{ - processQueries(); - - // The history should never be empty because we initialize all elements with an estimate. - ASSERT(m_texturesPerSecondHistory.size() == uploadHistorySize); - - // Sort the history and use the median as our estimate. - std::vector sortedHistory(m_texturesPerSecondHistory.begin(), - m_texturesPerSecondHistory.end()); - std::sort(sortedHistory.begin(), sortedHistory.end()); - - estimatedTexturesPerSecondGlobal = sortedHistory[sortedHistory.size() * 2 / 3]; - TRACE_COUNTER1("cc", "estimatedTexturesPerSecond", estimatedTexturesPerSecondGlobal); - return estimatedTexturesPerSecondGlobal; -} - -void ThrottledTextureUploader::beginQuery() -{ - if (m_availableQueries.isEmpty()) - m_availableQueries.append(Query::create(m_context)); - - m_availableQueries.first()->begin(); -} - -void ThrottledTextureUploader::endQuery() -{ - m_availableQueries.first()->end(); - m_pendingQueries.append(m_availableQueries.takeFirst()); - m_numBlockingTextureUploads++; -} - -void ThrottledTextureUploader::uploadTexture(CCResourceProvider* resourceProvider, Parameters upload) -{ - bool isFullUpload = upload.destOffset.isZero() && - upload.sourceRect.size() == upload.texture->texture()->size(); - - if (isFullUpload) - beginQuery(); - - upload.texture->updateRect(resourceProvider, upload.sourceRect, upload.destOffset); - - if (isFullUpload) - endQuery(); -} - -void ThrottledTextureUploader::processQueries() -{ - while (!m_pendingQueries.isEmpty()) { - if (m_pendingQueries.first()->isPending()) - break; - - unsigned usElapsed = m_pendingQueries.first()->value(); - WebKit::Platform::current()->histogramCustomCounts("Renderer4.TextureGpuUploadTimeUS", usElapsed, 0, 100000, 50); - - if (!m_pendingQueries.first()->isNonBlocking()) - m_numBlockingTextureUploads--; - - // Remove the oldest values from our history and insert the new one - double texturesPerSecond = 1.0 / (usElapsed * 1e-6); - m_texturesPerSecondHistory.pop_back(); - m_texturesPerSecondHistory.push_front(texturesPerSecond); - - m_availableQueries.append(m_pendingQueries.takeFirst()); - } -} - -} diff --git a/cc/ThrottledTextureUploader.h b/cc/ThrottledTextureUploader.h index f517401..f839d24 100644 --- a/cc/ThrottledTextureUploader.h +++ b/cc/ThrottledTextureUploader.h @@ -2,75 +2,5 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef ThrottledTextureUploader_h -#define ThrottledTextureUploader_h - -#include "TextureUploader.h" - -#include "base/basictypes.h" -#include -#include - -namespace WebKit { -class WebGraphicsContext3D; -} - -namespace cc { - -class ThrottledTextureUploader : public TextureUploader { -public: - static PassOwnPtr create(WebKit::WebGraphicsContext3D* context) - { - return adoptPtr(new ThrottledTextureUploader(context)); - } - virtual ~ThrottledTextureUploader(); - - virtual size_t numBlockingUploads() OVERRIDE; - virtual void markPendingUploadsAsNonBlocking() OVERRIDE; - virtual double estimatedTexturesPerSecond() OVERRIDE; - virtual void uploadTexture(CCResourceProvider*, Parameters) OVERRIDE; - -private: - class Query { - public: - static PassOwnPtr create(WebKit::WebGraphicsContext3D* context) { return adoptPtr(new Query(context)); } - - virtual ~Query(); - - void begin(); - void end(); - bool isPending(); - void wait(); - unsigned value(); - size_t texturesUploaded(); - void markAsNonBlocking(); - bool isNonBlocking(); - - private: - explicit Query(WebKit::WebGraphicsContext3D*); - - WebKit::WebGraphicsContext3D* m_context; - unsigned m_queryId; - unsigned m_value; - bool m_hasValue; - bool m_isNonBlocking; - }; - - ThrottledTextureUploader(WebKit::WebGraphicsContext3D*); - - void beginQuery(); - void endQuery(); - void processQueries(); - - WebKit::WebGraphicsContext3D* m_context; - Deque > m_pendingQueries; - Deque > m_availableQueries; - std::deque m_texturesPerSecondHistory; - size_t m_numBlockingTextureUploads; - - DISALLOW_COPY_AND_ASSIGN(ThrottledTextureUploader); -}; - -} - -#endif +// Temporary forwarding header +#include "cc/throttled_texture_uploader.h" diff --git a/cc/TiledLayerChromium.cpp b/cc/TiledLayerChromium.cpp deleted file mode 100644 index f2219e6..0000000 --- a/cc/TiledLayerChromium.cpp +++ /dev/null @@ -1,820 +0,0 @@ -// Copyright 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "config.h" - -#if USE(ACCELERATED_COMPOSITING) - -#include "base/basictypes.h" -#include "TiledLayerChromium.h" - -#include "CCLayerImpl.h" -#include "CCLayerTreeHost.h" -#include "CCOverdrawMetrics.h" -#include "CCTextureUpdateQueue.h" -#include "CCTiledLayerImpl.h" -#include "GraphicsContext3D.h" -#include "Region.h" -#include -#include - -using namespace std; -using WebKit::WebTransformationMatrix; - -namespace cc { - -class UpdatableTile : public CCLayerTilingData::Tile { -public: - static PassOwnPtr create(PassOwnPtr texture) - { - return adoptPtr(new UpdatableTile(texture)); - } - - LayerTextureUpdater::Texture* texture() { return m_texture.get(); } - CCPrioritizedTexture* managedTexture() { return m_texture->texture(); } - - bool isDirty() const { return !dirtyRect.isEmpty(); } - - // Reset update state for the current frame. This should occur before painting - // for all layers. Since painting one layer can invalidate another layer - // after it has already painted, mark all non-dirty tiles as valid before painting - // such that invalidations during painting won't prevent them from being pushed. - void resetUpdateState() - { - updateRect = IntRect(); - occluded = false; - partialUpdate = false; - validForFrame = !isDirty(); - } - - // This promises to update the tile and therefore also guarantees the tile - // will be valid for this frame. dirtyRect is copied into updateRect so - // we can continue to track re-entrant invalidations that occur during painting. - void markForUpdate() - { - validForFrame = true; - updateRect = dirtyRect; - dirtyRect = IntRect(); - } - - IntRect dirtyRect; - IntRect updateRect; - bool partialUpdate; - bool validForFrame; - bool occluded; - bool isInUseOnImpl; -private: - explicit UpdatableTile(PassOwnPtr texture) - : partialUpdate(false) - , validForFrame(false) - , occluded(false) - , isInUseOnImpl(false) - , m_texture(texture) - { - } - - OwnPtr m_texture; - - DISALLOW_COPY_AND_ASSIGN(UpdatableTile); -}; - -TiledLayerChromium::TiledLayerChromium() - : LayerChromium() - , m_textureFormat(GraphicsContext3D::INVALID_ENUM) - , m_skipsDraw(false) - , m_failedUpdate(false) - , m_sampledTexelFormat(LayerTextureUpdater::SampledTexelFormatInvalid) - , m_tilingOption(AutoTile) -{ - m_tiler = CCLayerTilingData::create(IntSize(), CCLayerTilingData::HasBorderTexels); -} - -TiledLayerChromium::~TiledLayerChromium() -{ -} - -scoped_ptr TiledLayerChromium::createCCLayerImpl() -{ - return CCTiledLayerImpl::create(id()).PassAs(); -} - -void TiledLayerChromium::updateTileSizeAndTilingOption() -{ - ASSERT(layerTreeHost()); - - const IntSize& defaultTileSize = layerTreeHost()->settings().defaultTileSize; - const IntSize& maxUntiledLayerSize = layerTreeHost()->settings().maxUntiledLayerSize; - int layerWidth = contentBounds().width(); - int layerHeight = contentBounds().height(); - - const IntSize tileSize(min(defaultTileSize.width(), layerWidth), min(defaultTileSize.height(), layerHeight)); - - // Tile if both dimensions large, or any one dimension large and the other - // extends into a second tile but the total layer area isn't larger than that - // of the largest possible untiled layer. This heuristic allows for long skinny layers - // (e.g. scrollbars) that are Nx1 tiles to minimize wasted texture space but still avoids - // creating very large tiles. - const bool anyDimensionLarge = layerWidth > maxUntiledLayerSize.width() || layerHeight > maxUntiledLayerSize.height(); - const bool anyDimensionOneTile = (layerWidth <= defaultTileSize.width() || layerHeight <= defaultTileSize.height()) - && (layerWidth * layerHeight) <= (maxUntiledLayerSize.width() * maxUntiledLayerSize.height()); - const bool autoTiled = anyDimensionLarge && !anyDimensionOneTile; - - bool isTiled; - if (m_tilingOption == AlwaysTile) - isTiled = true; - else if (m_tilingOption == NeverTile) - isTiled = false; - else - isTiled = autoTiled; - - IntSize requestedSize = isTiled ? tileSize : contentBounds(); - const int maxSize = layerTreeHost()->rendererCapabilities().maxTextureSize; - IntSize clampedSize = requestedSize.shrunkTo(IntSize(maxSize, maxSize)); - setTileSize(clampedSize); -} - -void TiledLayerChromium::updateBounds() -{ - IntSize oldBounds = m_tiler->bounds(); - IntSize newBounds = contentBounds(); - if (oldBounds == newBounds) - return; - m_tiler->setBounds(newBounds); - - // Invalidate any areas that the new bounds exposes. - Region oldRegion(IntRect(IntPoint(), oldBounds)); - Region newRegion(IntRect(IntPoint(), newBounds)); - newRegion.subtract(oldRegion); - Vector rects = newRegion.rects(); - for (size_t i = 0; i < rects.size(); ++i) - invalidateContentRect(rects[i]); -} - -void TiledLayerChromium::setTileSize(const IntSize& size) -{ - m_tiler->setTileSize(size); -} - -void TiledLayerChromium::setBorderTexelOption(CCLayerTilingData::BorderTexelOption borderTexelOption) -{ - m_tiler->setBorderTexelOption(borderTexelOption); -} - -bool TiledLayerChromium::drawsContent() const -{ - if (!LayerChromium::drawsContent()) - return false; - - bool hasMoreThanOneTile = m_tiler->numTilesX() > 1 || m_tiler->numTilesY() > 1; - if (m_tilingOption == NeverTile && hasMoreThanOneTile) - return false; - - return true; -} - -bool TiledLayerChromium::needsContentsScale() const -{ - return true; -} - -IntSize TiledLayerChromium::contentBounds() const -{ - return IntSize(lroundf(bounds().width() * contentsScale()), lroundf(bounds().height() * contentsScale())); -} - -void TiledLayerChromium::setTilingOption(TilingOption tilingOption) -{ - m_tilingOption = tilingOption; -} - -void TiledLayerChromium::setIsMask(bool isMask) -{ - setTilingOption(isMask ? NeverTile : AutoTile); -} - -void TiledLayerChromium::pushPropertiesTo(CCLayerImpl* layer) -{ - LayerChromium::pushPropertiesTo(layer); - - CCTiledLayerImpl* tiledLayer = static_cast(layer); - - tiledLayer->setSkipsDraw(m_skipsDraw); - tiledLayer->setContentsSwizzled(m_sampledTexelFormat != LayerTextureUpdater::SampledTexelFormatRGBA); - tiledLayer->setTilingData(*m_tiler); - Vector invalidTiles; - - for (CCLayerTilingData::TileMap::const_iterator iter = m_tiler->tiles().begin(); iter != m_tiler->tiles().end(); ++iter) { -#if WTF_NEW_HASHMAP_ITERATORS_INTERFACE - int i = iter->key.first; - int j = iter->key.second; - UpdatableTile* tile = static_cast(iter->value.get()); -#else - int i = iter->first.first; - int j = iter->first.second; - UpdatableTile* tile = static_cast(iter->second.get()); -#endif - // FIXME: This should not ever be null. - if (!tile) - continue; - - tile->isInUseOnImpl = false; - - if (!tile->managedTexture()->haveBackingTexture()) { - // Evicted tiles get deleted from both layers - invalidTiles.append(tile); - continue; - } - - if (!tile->validForFrame) { - // Invalidated tiles are set so they can get different debug colors. - tiledLayer->pushInvalidTile(i, j); - continue; - } - - tiledLayer->pushTileProperties(i, j, tile->managedTexture()->resourceId(), tile->opaqueRect()); - tile->isInUseOnImpl = true; - } - for (Vector::const_iterator iter = invalidTiles.begin(); iter != invalidTiles.end(); ++iter) - m_tiler->takeTile((*iter)->i(), (*iter)->j()); -} - -CCPrioritizedTextureManager* TiledLayerChromium::textureManager() const -{ - if (!layerTreeHost()) - return 0; - return layerTreeHost()->contentsTextureManager(); -} - -void TiledLayerChromium::setLayerTreeHost(CCLayerTreeHost* host) -{ - if (host && host != layerTreeHost()) { - for (CCLayerTilingData::TileMap::const_iterator iter = m_tiler->tiles().begin(); iter != m_tiler->tiles().end(); ++iter) { -#if WTF_NEW_HASHMAP_ITERATORS_INTERFACE - UpdatableTile* tile = static_cast(iter->value.get()); -#else - UpdatableTile* tile = static_cast(iter->second.get()); -#endif - // FIXME: This should not ever be null. - if (!tile) - continue; - tile->managedTexture()->setTextureManager(host->contentsTextureManager()); - } - } - LayerChromium::setLayerTreeHost(host); -} - -UpdatableTile* TiledLayerChromium::tileAt(int i, int j) const -{ - return static_cast(m_tiler->tileAt(i, j)); -} - -UpdatableTile* TiledLayerChromium::createTile(int i, int j) -{ - createTextureUpdaterIfNeeded(); - - OwnPtr tile(UpdatableTile::create(textureUpdater()->createTexture(textureManager()))); - tile->managedTexture()->setDimensions(m_tiler->tileSize(), m_textureFormat); - - UpdatableTile* addedTile = tile.get(); - m_tiler->addTile(tile.release(), i, j); - - addedTile->dirtyRect = m_tiler->tileRect(addedTile); - - // Temporary diagnostic crash. - if (!addedTile) - CRASH(); - if (!tileAt(i, j)) - CRASH(); - - return addedTile; -} - -void TiledLayerChromium::setNeedsDisplayRect(const FloatRect& dirtyRect) -{ - float contentsWidthScale = static_cast(contentBounds().width()) / bounds().width(); - float contentsHeightScale = static_cast(contentBounds().height()) / bounds().height(); - FloatRect scaledDirtyRect(dirtyRect); - scaledDirtyRect.scale(contentsWidthScale, contentsHeightScale); - IntRect dirty = enclosingIntRect(scaledDirtyRect); - invalidateContentRect(dirty); - LayerChromium::setNeedsDisplayRect(dirtyRect); -} - -void TiledLayerChromium::setUseLCDText(bool useLCDText) -{ - LayerChromium::setUseLCDText(useLCDText); - - CCLayerTilingData::BorderTexelOption borderTexelOption; -#if OS(ANDROID) - // Always want border texels and GL_LINEAR due to pinch zoom. - borderTexelOption = CCLayerTilingData::HasBorderTexels; -#else - borderTexelOption = useLCDText ? CCLayerTilingData::NoBorderTexels : CCLayerTilingData::HasBorderTexels; -#endif - setBorderTexelOption(borderTexelOption); -} - -void TiledLayerChromium::invalidateContentRect(const IntRect& contentRect) -{ - updateBounds(); - if (m_tiler->isEmpty() || contentRect.isEmpty() || m_skipsDraw) - return; - - for (CCLayerTilingData::TileMap::const_iterator iter = m_tiler->tiles().begin(); iter != m_tiler->tiles().end(); ++iter) { -#if WTF_NEW_HASHMAP_ITERATORS_INTERFACE - UpdatableTile* tile = static_cast(iter->value.get()); -#else - UpdatableTile* tile = static_cast(iter->second.get()); -#endif - ASSERT(tile); - // FIXME: This should not ever be null. - if (!tile) - continue; - IntRect bound = m_tiler->tileRect(tile); - bound.intersect(contentRect); - tile->dirtyRect.unite(bound); - } -} - -// Returns true if tile is dirty and only part of it needs to be updated. -bool TiledLayerChromium::tileOnlyNeedsPartialUpdate(UpdatableTile* tile) -{ - return !tile->dirtyRect.contains(m_tiler->tileRect(tile)); -} - -// Dirty tiles with valid textures needs buffered update to guarantee that -// we don't modify textures currently used for drawing by the impl thread. -bool TiledLayerChromium::tileNeedsBufferedUpdate(UpdatableTile* tile) -{ - if (!tile->managedTexture()->haveBackingTexture()) - return false; - - if (!tile->isDirty()) - return false; - - if (!tile->isInUseOnImpl) - return false; - - return true; -} - - -bool TiledLayerChromium::updateTiles(int left, int top, int right, int bottom, CCTextureUpdateQueue& queue, const CCOcclusionTracker* occlusion, CCRenderingStats& stats, bool& didPaint) -{ - didPaint = false; - createTextureUpdaterIfNeeded(); - - bool ignoreOcclusions = !occlusion; - if (!haveTexturesForTiles(left, top, right, bottom, ignoreOcclusions)) { - m_failedUpdate = true; - return false; - } - - IntRect paintRect = markTilesForUpdate(left, top, right, bottom, ignoreOcclusions); - - if (occlusion) - occlusion->overdrawMetrics().didPaint(paintRect); - - if (paintRect.isEmpty()) - return true; - - didPaint = true; - updateTileTextures(paintRect, left, top, right, bottom, queue, occlusion, stats); - return true; -} - -void TiledLayerChromium::markOcclusionsAndRequestTextures(int left, int top, int right, int bottom, const CCOcclusionTracker* occlusion) -{ - // There is some difficult dependancies between occlusions, recording occlusion metrics - // and requesting memory so those are encapsulated in this function: - // - We only want to call requestLate on unoccluded textures (to preserve - // memory for other layers when near OOM). - // - We only want to record occlusion metrics if all memory requests succeed. - - int occludedTileCount = 0; - bool succeeded = true; - for (int j = top; j <= bottom; ++j) { - for (int i = left; i <= right; ++i) { - UpdatableTile* tile = tileAt(i, j); - ASSERT(tile); // Did setTexturePriorities get skipped? - // FIXME: This should not ever be null. - if (!tile) - continue; - ASSERT(!tile->occluded); // Did resetUpdateState get skipped? Are we doing more than one occlusion pass? - IntRect visibleTileRect = intersection(m_tiler->tileBounds(i, j), visibleContentRect()); - if (occlusion && occlusion->occluded(this, visibleTileRect)) { - tile->occluded = true; - occludedTileCount++; - } else { - succeeded &= tile->managedTexture()->requestLate(); - } - } - } - - if (!succeeded) - return; - - // FIXME: Remove the loop and just pass the count! - for (int i = 0; i < occludedTileCount; i++) - occlusion->overdrawMetrics().didCullTileForUpload(); -} - -bool TiledLayerChromium::haveTexturesForTiles(int left, int top, int right, int bottom, bool ignoreOcclusions) -{ - for (int j = top; j <= bottom; ++j) { - for (int i = left; i <= right; ++i) { - UpdatableTile* tile = tileAt(i, j); - ASSERT(tile); // Did setTexturePriorites get skipped? - // FIXME: This should not ever be null. - if (!tile) - continue; - - // Ensure the entire tile is dirty if we don't have the texture. - if (!tile->managedTexture()->haveBackingTexture()) - tile->dirtyRect = m_tiler->tileRect(tile); - - // If using occlusion and the visible region of the tile is occluded, - // don't reserve a texture or update the tile. - if (tile->occluded && !ignoreOcclusions) - continue; - - if (!tile->managedTexture()->canAcquireBackingTexture()) - return false; - } - } - return true; -} - -IntRect TiledLayerChromium::markTilesForUpdate(int left, int top, int right, int bottom, bool ignoreOcclusions) -{ - IntRect paintRect; - for (int j = top; j <= bottom; ++j) { - for (int i = left; i <= right; ++i) { - UpdatableTile* tile = tileAt(i, j); - ASSERT(tile); // Did setTexturePriorites get skipped? - // FIXME: This should not ever be null. - if (!tile) - continue; - if (tile->occluded && !ignoreOcclusions) - continue; - paintRect.unite(tile->dirtyRect); - tile->markForUpdate(); - } - } - return paintRect; -} - -void TiledLayerChromium::updateTileTextures(const IntRect& paintRect, int left, int top, int right, int bottom, CCTextureUpdateQueue& queue, const CCOcclusionTracker* occlusion, CCRenderingStats& stats) -{ - // The updateRect should be in layer space. So we have to convert the paintRect from content space to layer space. - m_updateRect = FloatRect(paintRect); - float widthScale = bounds().width() / static_cast(contentBounds().width()); - float heightScale = bounds().height() / static_cast(contentBounds().height()); - m_updateRect.scale(widthScale, heightScale); - - // Calling prepareToUpdate() calls into WebKit to paint, which may have the side - // effect of disabling compositing, which causes our reference to the texture updater to be deleted. - // However, we can't free the memory backing the SkCanvas until the paint finishes, - // so we grab a local reference here to hold the updater alive until the paint completes. - RefPtr protector(textureUpdater()); - IntRect paintedOpaqueRect; - textureUpdater()->prepareToUpdate(paintRect, m_tiler->tileSize(), 1 / widthScale, 1 / heightScale, paintedOpaqueRect, stats); - - for (int j = top; j <= bottom; ++j) { - for (int i = left; i <= right; ++i) { - UpdatableTile* tile = tileAt(i, j); - ASSERT(tile); // Did setTexturePriorites get skipped? - // FIXME: This should not ever be null. - if (!tile) - continue; - - IntRect tileRect = m_tiler->tileBounds(i, j); - - // Use updateRect as the above loop copied the dirty rect for this frame to updateRect. - const IntRect& dirtyRect = tile->updateRect; - if (dirtyRect.isEmpty()) - continue; - - // Save what was painted opaque in the tile. Keep the old area if the paint didn't touch it, and didn't paint some - // other part of the tile opaque. - IntRect tilePaintedRect = intersection(tileRect, paintRect); - IntRect tilePaintedOpaqueRect = intersection(tileRect, paintedOpaqueRect); - if (!tilePaintedRect.isEmpty()) { - IntRect paintInsideTileOpaqueRect = intersection(tile->opaqueRect(), tilePaintedRect); - bool paintInsideTileOpaqueRectIsNonOpaque = !tilePaintedOpaqueRect.contains(paintInsideTileOpaqueRect); - bool opaquePaintNotInsideTileOpaqueRect = !tilePaintedOpaqueRect.isEmpty() && !tile->opaqueRect().contains(tilePaintedOpaqueRect); - - if (paintInsideTileOpaqueRectIsNonOpaque || opaquePaintNotInsideTileOpaqueRect) - tile->setOpaqueRect(tilePaintedOpaqueRect); - } - - // sourceRect starts as a full-sized tile with border texels included. - IntRect sourceRect = m_tiler->tileRect(tile); - sourceRect.intersect(dirtyRect); - // Paint rect not guaranteed to line up on tile boundaries, so - // make sure that sourceRect doesn't extend outside of it. - sourceRect.intersect(paintRect); - - tile->updateRect = sourceRect; - - if (sourceRect.isEmpty()) - continue; - - tile->texture()->prepareRect(sourceRect, stats); - if (occlusion) - occlusion->overdrawMetrics().didUpload(WebTransformationMatrix(), sourceRect, tile->opaqueRect()); - - const IntPoint anchor = m_tiler->tileRect(tile).location(); - - // Calculate tile-space rectangle to upload into. - IntSize destOffset(sourceRect.x() - anchor.x(), sourceRect.y() - anchor.y()); - if (destOffset.width() < 0) - CRASH(); - if (destOffset.height() < 0) - CRASH(); - - // Offset from paint rectangle to this tile's dirty rectangle. - IntPoint paintOffset(sourceRect.x() - paintRect.x(), sourceRect.y() - paintRect.y()); - if (paintOffset.x() < 0) - CRASH(); - if (paintOffset.y() < 0) - CRASH(); - if (paintOffset.x() + sourceRect.width() > paintRect.width()) - CRASH(); - if (paintOffset.y() + sourceRect.height() > paintRect.height()) - CRASH(); - - TextureUploader::Parameters upload = { tile->texture(), sourceRect, destOffset }; - if (tile->partialUpdate) - queue.appendPartialUpload(upload); - else - queue.appendFullUpload(upload); - } - } -} - -namespace { -// This picks a small animated layer to be anything less than one viewport. This -// is specifically for page transitions which are viewport-sized layers. The extra -// 64 pixels is due to these layers being slightly larger than the viewport in some cases. -bool isSmallAnimatedLayer(TiledLayerChromium* layer) -{ - if (!layer->drawTransformIsAnimating() && !layer->screenSpaceTransformIsAnimating()) - return false; - IntSize viewportSize = layer->layerTreeHost() ? layer->layerTreeHost()->deviceViewportSize() : IntSize(); - IntRect contentRect(IntPoint::zero(), layer->contentBounds()); - return contentRect.width() <= viewportSize.width() + 64 - && contentRect.height() <= viewportSize.height() + 64; -} - -// FIXME: Remove this and make this based on distance once distance can be calculated -// for offscreen layers. For now, prioritize all small animated layers after 512 -// pixels of pre-painting. -void setPriorityForTexture(const IntRect& visibleRect, - const IntRect& tileRect, - bool drawsToRoot, - bool isSmallAnimatedLayer, - CCPrioritizedTexture* texture) -{ - int priority = CCPriorityCalculator::lowestPriority(); - if (!visibleRect.isEmpty()) - priority = CCPriorityCalculator::priorityFromDistance(visibleRect, tileRect, drawsToRoot); - if (isSmallAnimatedLayer) - priority = CCPriorityCalculator::maxPriority(priority, CCPriorityCalculator::smallAnimatedLayerMinPriority()); - if (priority != CCPriorityCalculator::lowestPriority()) - texture->setRequestPriority(priority); -} -} - -void TiledLayerChromium::setTexturePriorities(const CCPriorityCalculator& priorityCalc) -{ - updateBounds(); - resetUpdateState(); - - if (m_tiler->hasEmptyBounds()) - return; - - bool drawsToRoot = !renderTarget()->parent(); - bool smallAnimatedLayer = isSmallAnimatedLayer(this); - - // Minimally create the tiles in the desired pre-paint rect. - IntRect createTilesRect = idlePaintRect(); - if (!createTilesRect.isEmpty()) { - int left, top, right, bottom; - m_tiler->contentRectToTileIndices(createTilesRect, left, top, right, bottom); - for (int j = top; j <= bottom; ++j) { - for (int i = left; i <= right; ++i) { - if (!tileAt(i, j)) - createTile(i, j); - } - } - } - - // Also, minimally create all tiles for small animated layers and also - // double-buffer them since we have limited their size to be reasonable. - IntRect doubleBufferedRect = visibleContentRect(); - if (smallAnimatedLayer) - doubleBufferedRect = IntRect(IntPoint::zero(), contentBounds()); - - // Create additional textures for double-buffered updates when needed. - // These textures must stay alive while the updated textures are incrementally - // uploaded, swapped atomically via pushProperties, and finally deleted - // after the commit is complete, after which they can be recycled. - if (!doubleBufferedRect.isEmpty()) { - int left, top, right, bottom; - m_tiler->contentRectToTileIndices(doubleBufferedRect, left, top, right, bottom); - for (int j = top; j <= bottom; ++j) { - for (int i = left; i <= right; ++i) { - UpdatableTile* tile = tileAt(i, j); - if (!tile) - tile = createTile(i, j); - // We need an additional texture if the tile needs a buffered-update and it's not a partial update. - // FIXME: Decide if partial update should be allowed based on cost - // of update. https://bugs.webkit.org/show_bug.cgi?id=77376 - if (!layerTreeHost() || !layerTreeHost()->bufferedUpdates() || !tileNeedsBufferedUpdate(tile)) - continue; - if (tileOnlyNeedsPartialUpdate(tile) && layerTreeHost()->requestPartialTextureUpdate()) { - tile->partialUpdate = true; - continue; - } - - IntRect tileRect = m_tiler->tileRect(tile); - tile->dirtyRect = tileRect; - LayerTextureUpdater::Texture* backBuffer = tile->texture(); - setPriorityForTexture(visibleContentRect(), tile->dirtyRect, drawsToRoot, smallAnimatedLayer, backBuffer->texture()); - scoped_ptr frontBuffer = CCPrioritizedTexture::create(backBuffer->texture()->textureManager(), - backBuffer->texture()->size(), - backBuffer->texture()->format()); - // Swap backBuffer into frontBuffer and add it to delete after commit queue. - backBuffer->swapTextureWith(frontBuffer); - layerTreeHost()->deleteTextureAfterCommit(frontBuffer.Pass()); - } - } - } - - // Now update priorities on all tiles we have in the layer, no matter where they are. - for (CCLayerTilingData::TileMap::const_iterator iter = m_tiler->tiles().begin(); iter != m_tiler->tiles().end(); ++iter) { -#if WTF_NEW_HASHMAP_ITERATORS_INTERFACE - UpdatableTile* tile = static_cast(iter->value.get()); -#else - UpdatableTile* tile = static_cast(iter->second.get()); -#endif - // FIXME: This should not ever be null. - if (!tile) - continue; - IntRect tileRect = m_tiler->tileRect(tile); - setPriorityForTexture(visibleContentRect(), tileRect, drawsToRoot, smallAnimatedLayer, tile->managedTexture()); - } -} - -Region TiledLayerChromium::visibleContentOpaqueRegion() const -{ - if (m_skipsDraw) - return Region(); - if (contentsOpaque()) - return visibleContentRect(); - return m_tiler->opaqueRegionInContentRect(visibleContentRect()); -} - -void TiledLayerChromium::resetUpdateState() -{ - m_skipsDraw = false; - m_failedUpdate = false; - - CCLayerTilingData::TileMap::const_iterator end = m_tiler->tiles().end(); - for (CCLayerTilingData::TileMap::const_iterator iter = m_tiler->tiles().begin(); iter != end; ++iter) { -#if WTF_NEW_HASHMAP_ITERATORS_INTERFACE - UpdatableTile* tile = static_cast(iter->value.get()); -#else - UpdatableTile* tile = static_cast(iter->second.get()); -#endif - // FIXME: This should not ever be null. - if (!tile) - continue; - tile->resetUpdateState(); - } -} - -void TiledLayerChromium::update(CCTextureUpdateQueue& queue, const CCOcclusionTracker* occlusion, CCRenderingStats& stats) -{ - ASSERT(!m_skipsDraw && !m_failedUpdate); // Did resetUpdateState get skipped? - updateBounds(); - if (m_tiler->hasEmptyBounds() || !drawsContent()) - return; - - bool didPaint = false; - - // Animation pre-paint. If the layer is small, try to paint it all - // immediately whether or not it is occluded, to avoid paint/upload - // hiccups while it is animating. - if (isSmallAnimatedLayer(this)) { - int left, top, right, bottom; - m_tiler->contentRectToTileIndices(IntRect(IntPoint::zero(), contentBounds()), left, top, right, bottom); - updateTiles(left, top, right, bottom, queue, 0, stats, didPaint); - if (didPaint) - return; - // This was an attempt to paint the entire layer so if we fail it's okay, - // just fallback on painting visible etc. below. - m_failedUpdate = false; - } - - if (visibleContentRect().isEmpty()) - return; - - // Visible painting. First occlude visible tiles and paint the non-occluded tiles. - int left, top, right, bottom; - m_tiler->contentRectToTileIndices(visibleContentRect(), left, top, right, bottom); - markOcclusionsAndRequestTextures(left, top, right, bottom, occlusion); - m_skipsDraw = !updateTiles(left, top, right, bottom, queue, occlusion, stats, didPaint); - if (m_skipsDraw) - m_tiler->reset(); - if (m_skipsDraw || didPaint) - return; - - // If we have already painting everything visible. Do some pre-painting while idle. - IntRect idlePaintContentRect = idlePaintRect(); - if (idlePaintContentRect.isEmpty()) - return; - - // Prepaint anything that was occluded but inside the layer's visible region. - if (!updateTiles(left, top, right, bottom, queue, 0, stats, didPaint) || didPaint) - return; - - int prepaintLeft, prepaintTop, prepaintRight, prepaintBottom; - m_tiler->contentRectToTileIndices(idlePaintContentRect, prepaintLeft, prepaintTop, prepaintRight, prepaintBottom); - - // Then expand outwards from the visible area until we find a dirty row or column to update. - while (left > prepaintLeft || top > prepaintTop || right < prepaintRight || bottom < prepaintBottom) { - if (bottom < prepaintBottom) { - ++bottom; - if (!updateTiles(left, bottom, right, bottom, queue, 0, stats, didPaint) || didPaint) - return; - } - if (top > prepaintTop) { - --top; - if (!updateTiles(left, top, right, top, queue, 0, stats, didPaint) || didPaint) - return; - } - if (left > prepaintLeft) { - --left; - if (!updateTiles(left, top, left, bottom, queue, 0, stats, didPaint) || didPaint) - return; - } - if (right < prepaintRight) { - ++right; - if (!updateTiles(right, top, right, bottom, queue, 0, stats, didPaint) || didPaint) - return; - } - } -} - -bool TiledLayerChromium::needsIdlePaint() -{ - // Don't trigger more paints if we failed (as we'll just fail again). - if (m_failedUpdate || visibleContentRect().isEmpty() || m_tiler->hasEmptyBounds() || !drawsContent()) - return false; - - IntRect idlePaintContentRect = idlePaintRect(); - if (idlePaintContentRect.isEmpty()) - return false; - - int left, top, right, bottom; - m_tiler->contentRectToTileIndices(idlePaintContentRect, left, top, right, bottom); - - for (int j = top; j <= bottom; ++j) { - for (int i = left; i <= right; ++i) { - UpdatableTile* tile = tileAt(i, j); - ASSERT(tile); // Did setTexturePriorities get skipped? - if (!tile) - continue; - - bool updated = !tile->updateRect.isEmpty(); - bool canAcquire = tile->managedTexture()->canAcquireBackingTexture(); - bool dirty = tile->isDirty() || !tile->managedTexture()->haveBackingTexture(); - if (!updated && canAcquire && dirty) - return true; - } - } - return false; -} - -IntRect TiledLayerChromium::idlePaintRect() -{ - // Don't inflate an empty rect. - if (visibleContentRect().isEmpty()) - return IntRect(); - - // FIXME: This can be made a lot larger now! We should increase - // this slowly while insuring it doesn't cause any perf issues. - IntRect prepaintRect = visibleContentRect(); - prepaintRect.inflateX(m_tiler->tileSize().width()); - prepaintRect.inflateY(m_tiler->tileSize().height() * 2); - IntRect contentRect(IntPoint::zero(), contentBounds()); - prepaintRect.intersect(contentRect); - - return prepaintRect; -} - -} -#endif // USE(ACCELERATED_COMPOSITING) diff --git a/cc/TiledLayerChromium.h b/cc/TiledLayerChromium.h index 3c27382..cdf7868 100644 --- a/cc/TiledLayerChromium.h +++ b/cc/TiledLayerChromium.h @@ -1,105 +1,6 @@ -// Copyright 2011 The Chromium Authors. All rights reserved. +// Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef TiledLayerChromium_h -#define TiledLayerChromium_h - -#if USE(ACCELERATED_COMPOSITING) - -#include "CCLayerTilingData.h" -#include "LayerChromium.h" -#include "LayerTextureUpdater.h" - -namespace cc { -class UpdatableTile; - -class TiledLayerChromium : public LayerChromium { -public: - enum TilingOption { AlwaysTile, NeverTile, AutoTile }; - - virtual void setIsMask(bool) OVERRIDE; - - virtual void pushPropertiesTo(CCLayerImpl*) OVERRIDE; - - virtual bool drawsContent() const OVERRIDE; - virtual bool needsContentsScale() const OVERRIDE; - - virtual IntSize contentBounds() const OVERRIDE; - - virtual void setNeedsDisplayRect(const FloatRect&) OVERRIDE; - - virtual void setUseLCDText(bool) OVERRIDE; - - virtual void setLayerTreeHost(CCLayerTreeHost*) OVERRIDE; - - virtual void setTexturePriorities(const CCPriorityCalculator&) OVERRIDE; - - virtual Region visibleContentOpaqueRegion() const OVERRIDE; - - virtual void update(CCTextureUpdateQueue&, const CCOcclusionTracker*, CCRenderingStats&) OVERRIDE; - -protected: - TiledLayerChromium(); - virtual ~TiledLayerChromium(); - - void updateTileSizeAndTilingOption(); - void updateBounds(); - - // Exposed to subclasses for testing. - void setTileSize(const IntSize&); - void setTextureFormat(GC3Denum textureFormat) { m_textureFormat = textureFormat; } - void setBorderTexelOption(CCLayerTilingData::BorderTexelOption); - void setSampledTexelFormat(LayerTextureUpdater::SampledTexelFormat sampledTexelFormat) { m_sampledTexelFormat = sampledTexelFormat; } - size_t numPaintedTiles() { return m_tiler->tiles().size(); } - - virtual LayerTextureUpdater* textureUpdater() const = 0; - virtual void createTextureUpdaterIfNeeded() = 0; - - // Set invalidations to be potentially repainted during update(). - void invalidateContentRect(const IntRect& contentRect); - - // Reset state on tiles that will be used for updating the layer. - void resetUpdateState(); - - // After preparing an update, returns true if more painting is needed. - bool needsIdlePaint(); - IntRect idlePaintRect(); - - bool skipsDraw() const { return m_skipsDraw; } - - // Virtual for testing - virtual CCPrioritizedTextureManager* textureManager() const; - -private: - virtual scoped_ptr createCCLayerImpl() OVERRIDE; - - void createTilerIfNeeded(); - void setTilingOption(TilingOption); - - bool tileOnlyNeedsPartialUpdate(UpdatableTile*); - bool tileNeedsBufferedUpdate(UpdatableTile*); - - void markOcclusionsAndRequestTextures(int left, int top, int right, int bottom, const CCOcclusionTracker*); - - bool updateTiles(int left, int top, int right, int bottom, CCTextureUpdateQueue&, const CCOcclusionTracker*, CCRenderingStats&, bool& didPaint); - bool haveTexturesForTiles(int left, int top, int right, int bottom, bool ignoreOcclusions); - IntRect markTilesForUpdate(int left, int top, int right, int bottom, bool ignoreOcclusions); - void updateTileTextures(const IntRect& paintRect, int left, int top, int right, int bottom, CCTextureUpdateQueue&, const CCOcclusionTracker*, CCRenderingStats&); - - UpdatableTile* tileAt(int, int) const; - UpdatableTile* createTile(int, int); - - GC3Denum m_textureFormat; - bool m_skipsDraw; - bool m_failedUpdate; - LayerTextureUpdater::SampledTexelFormat m_sampledTexelFormat; - - TilingOption m_tilingOption; - OwnPtr m_tiler; -}; - -} -#endif // USE(ACCELERATED_COMPOSITING) - -#endif +// Temporary forwarding header +#include "cc/tiled_layer.h" diff --git a/cc/TreeSynchronizer.cpp b/cc/TreeSynchronizer.cpp deleted file mode 100644 index b7e76bb..0000000 --- a/cc/TreeSynchronizer.cpp +++ /dev/null @@ -1,112 +0,0 @@ -// Copyright 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "config.h" - -#include "TreeSynchronizer.h" - -#include "CCLayerImpl.h" -#include "CCScrollbarAnimationController.h" -#include "CCScrollbarLayerImpl.h" -#include "LayerChromium.h" -#include "ScrollbarLayerChromium.h" - -namespace cc { - -scoped_ptr TreeSynchronizer::synchronizeTrees(LayerChromium* layerChromiumRoot, scoped_ptr oldCCLayerImplRoot, CCLayerTreeHostImpl* hostImpl) -{ - ScopedPtrCCLayerImplMap oldLayers; - RawPtrCCLayerImplMap newLayers; - - collectExistingCCLayerImplRecursive(oldLayers, oldCCLayerImplRoot.Pass()); - - scoped_ptr newTree = synchronizeTreeRecursive(newLayers, oldLayers, layerChromiumRoot, hostImpl); - - updateScrollbarLayerPointersRecursive(newLayers, layerChromiumRoot); - - return newTree.Pass(); -} - -void TreeSynchronizer::collectExistingCCLayerImplRecursive(ScopedPtrCCLayerImplMap& oldLayers, scoped_ptr ccLayerImpl) -{ - if (!ccLayerImpl) - return; - - ScopedPtrVector& children = ccLayerImpl->m_children; - for (size_t i = 0; i < children.size(); ++i) - collectExistingCCLayerImplRecursive(oldLayers, children.take(i)); - - collectExistingCCLayerImplRecursive(oldLayers, ccLayerImpl->m_maskLayer.Pass()); - collectExistingCCLayerImplRecursive(oldLayers, ccLayerImpl->m_replicaLayer.Pass()); - - int id = ccLayerImpl->id(); - oldLayers.set(id, ccLayerImpl.Pass()); -} - -scoped_ptr TreeSynchronizer::reuseOrCreateCCLayerImpl(RawPtrCCLayerImplMap& newLayers, ScopedPtrCCLayerImplMap& oldLayers, LayerChromium* layer) -{ - scoped_ptr ccLayerImpl = oldLayers.take(layer->id()); - - if (!ccLayerImpl) - ccLayerImpl = layer->createCCLayerImpl(); - - newLayers[layer->id()] = ccLayerImpl.get(); - return ccLayerImpl.Pass(); -} - -scoped_ptr TreeSynchronizer::synchronizeTreeRecursive(RawPtrCCLayerImplMap& newLayers, ScopedPtrCCLayerImplMap& oldLayers, LayerChromium* layer, CCLayerTreeHostImpl* hostImpl) -{ - if (!layer) - return scoped_ptr(); - - scoped_ptr ccLayerImpl = reuseOrCreateCCLayerImpl(newLayers, oldLayers, layer); - - ccLayerImpl->clearChildList(); - const std::vector >& children = layer->children(); - for (size_t i = 0; i < children.size(); ++i) - ccLayerImpl->addChild(synchronizeTreeRecursive(newLayers, oldLayers, children[i].get(), hostImpl)); - - ccLayerImpl->setMaskLayer(synchronizeTreeRecursive(newLayers, oldLayers, layer->maskLayer(), hostImpl)); - ccLayerImpl->setReplicaLayer(synchronizeTreeRecursive(newLayers, oldLayers, layer->replicaLayer(), hostImpl)); - - layer->pushPropertiesTo(ccLayerImpl.get()); - ccLayerImpl->setLayerTreeHostImpl(hostImpl); - - // Remove all dangling pointers. The pointers will be setup later in updateScrollbarLayerPointersRecursive phase - if (CCScrollbarAnimationController* scrollbarController = ccLayerImpl->scrollbarAnimationController()) { - scrollbarController->setHorizontalScrollbarLayer(0); - scrollbarController->setVerticalScrollbarLayer(0); - } - - return ccLayerImpl.Pass(); -} - -void TreeSynchronizer::updateScrollbarLayerPointersRecursive(const RawPtrCCLayerImplMap& newLayers, LayerChromium* layer) -{ - if (!layer) - return; - - const std::vector >& children = layer->children(); - for (size_t i = 0; i < children.size(); ++i) - updateScrollbarLayerPointersRecursive(newLayers, children[i].get()); - - ScrollbarLayerChromium* scrollbarLayer = layer->toScrollbarLayerChromium(); - if (!scrollbarLayer) - return; - - RawPtrCCLayerImplMap::const_iterator iter = newLayers.find(scrollbarLayer->id()); - CCScrollbarLayerImpl* ccScrollbarLayerImpl = iter != newLayers.end() ? static_cast(iter->second) : NULL; - iter = newLayers.find(scrollbarLayer->scrollLayerId()); - CCLayerImpl* ccScrollLayerImpl = iter != newLayers.end() ? iter->second : NULL; - - ASSERT(ccScrollbarLayerImpl); - ASSERT(ccScrollLayerImpl); - - if (ccScrollbarLayerImpl->orientation() == WebKit::WebScrollbar::Horizontal) - ccScrollLayerImpl->setHorizontalScrollbarLayer(ccScrollbarLayerImpl); - else - ccScrollLayerImpl->setVerticalScrollbarLayer(ccScrollbarLayerImpl); -} - -} // namespace cc diff --git a/cc/TreeSynchronizer.h b/cc/TreeSynchronizer.h index 2609841..f6e56c1 100644 --- a/cc/TreeSynchronizer.h +++ b/cc/TreeSynchronizer.h @@ -1,41 +1,6 @@ -// Copyright 2011 The Chromium Authors. All rights reserved. +// Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef TreeSynchronizer_h -#define TreeSynchronizer_h - -#include "base/basictypes.h" -#include "base/memory/scoped_ptr.h" -#include "cc/scoped_ptr_hash_map.h" - -namespace cc { - -class CCLayerImpl; -class CCLayerTreeHostImpl; -class LayerChromium; - -class TreeSynchronizer { -public: - // Accepts a LayerChromium tree and returns a reference to a CCLayerImpl tree that duplicates the structure - // of the LayerChromium tree, reusing the CCLayerImpls in the tree provided by oldCCLayerImplRoot if possible. - static scoped_ptr synchronizeTrees(LayerChromium* layerRoot, scoped_ptr oldCCLayerImplRoot, CCLayerTreeHostImpl*); - -private: - TreeSynchronizer(); // Not instantiable. - - typedef ScopedPtrHashMap ScopedPtrCCLayerImplMap; - typedef base::hash_map RawPtrCCLayerImplMap; - - // Declared as static member functions so they can access functions on LayerChromium as a friend class. - static scoped_ptr reuseOrCreateCCLayerImpl(RawPtrCCLayerImplMap& newLayers, ScopedPtrCCLayerImplMap& oldLayers, LayerChromium*); - static void collectExistingCCLayerImplRecursive(ScopedPtrCCLayerImplMap& oldLayers, scoped_ptr); - static scoped_ptr synchronizeTreeRecursive(RawPtrCCLayerImplMap& newLayers, ScopedPtrCCLayerImplMap& oldLayers, LayerChromium*, CCLayerTreeHostImpl*); - static void updateScrollbarLayerPointersRecursive(const RawPtrCCLayerImplMap& newLayers, LayerChromium*); - - DISALLOW_COPY_AND_ASSIGN(TreeSynchronizer); -}; - -} // namespace cc - -#endif // TreeSynchronizer_h +// Temporary forwarding header +#include "cc/tree_synchronizer.h" diff --git a/cc/UnthrottledTextureUploader.cpp b/cc/UnthrottledTextureUploader.cpp deleted file mode 100644 index 82b4337..0000000 --- a/cc/UnthrottledTextureUploader.cpp +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "config.h" - -#include "UnthrottledTextureUploader.h" - -namespace cc { - -size_t UnthrottledTextureUploader::numBlockingUploads() -{ - return 0; -} - -void UnthrottledTextureUploader::markPendingUploadsAsNonBlocking() -{ -} - -double UnthrottledTextureUploader::estimatedTexturesPerSecond() -{ - return std::numeric_limits::max(); -} - -void UnthrottledTextureUploader::uploadTexture(CCResourceProvider* resourceProvider, Parameters upload) -{ - upload.texture->updateRect(resourceProvider, upload.sourceRect, upload.destOffset); -} - -} diff --git a/cc/UnthrottledTextureUploader.h b/cc/UnthrottledTextureUploader.h index bc0822a..6df0878 100644 --- a/cc/UnthrottledTextureUploader.h +++ b/cc/UnthrottledTextureUploader.h @@ -2,35 +2,5 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UnthrottledTextureUploader_h -#define UnthrottledTextureUploader_h - -#include "base/basictypes.h" -#include "CCResourceProvider.h" -#include "TextureUploader.h" - -namespace cc { - -class UnthrottledTextureUploader : public TextureUploader { -public: - static PassOwnPtr create() - { - return adoptPtr(new UnthrottledTextureUploader()); - } - virtual ~UnthrottledTextureUploader() { } - - virtual size_t numBlockingUploads() OVERRIDE; - virtual void markPendingUploadsAsNonBlocking() OVERRIDE; - virtual double estimatedTexturesPerSecond() OVERRIDE; - virtual void uploadTexture(CCResourceProvider* resourceProvider, Parameters upload) OVERRIDE; - -protected: - UnthrottledTextureUploader() { } - -private: - DISALLOW_COPY_AND_ASSIGN(UnthrottledTextureUploader); -}; - -} - -#endif +// Temporary forwarding header +#include "cc/unthrottled_texture_uploader.h" diff --git a/cc/VideoLayerChromium.cpp b/cc/VideoLayerChromium.cpp deleted file mode 100644 index e210473..0000000 --- a/cc/VideoLayerChromium.cpp +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "config.h" - -#if USE(ACCELERATED_COMPOSITING) -#include "VideoLayerChromium.h" - -#include "CCVideoLayerImpl.h" - -namespace cc { - -scoped_refptr VideoLayerChromium::create(WebKit::WebVideoFrameProvider* provider) -{ - return make_scoped_refptr(new VideoLayerChromium(provider)); -} - -VideoLayerChromium::VideoLayerChromium(WebKit::WebVideoFrameProvider* provider) - : LayerChromium() - , m_provider(provider) -{ - ASSERT(m_provider); -} - -VideoLayerChromium::~VideoLayerChromium() -{ -} - -scoped_ptr VideoLayerChromium::createCCLayerImpl() -{ - return CCVideoLayerImpl::create(m_layerId, m_provider).PassAs(); -} - -} // namespace cc - -#endif // USE(ACCELERATED_COMPOSITING) diff --git a/cc/VideoLayerChromium.h b/cc/VideoLayerChromium.h index 92b5e13..2d2179e 100644 --- a/cc/VideoLayerChromium.h +++ b/cc/VideoLayerChromium.h @@ -1,39 +1,6 @@ -// Copyright 2010 The Chromium Authors. All rights reserved. +// Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. - -#ifndef VideoLayerChromium_h -#define VideoLayerChromium_h - -#if USE(ACCELERATED_COMPOSITING) - -#include "LayerChromium.h" - -namespace WebKit { -class WebVideoFrameProvider; -} - -namespace cc { - -class CCVideoLayerImpl; - -// A Layer that contains a Video element. -class VideoLayerChromium : public LayerChromium { -public: - static scoped_refptr create(WebKit::WebVideoFrameProvider*); - - virtual scoped_ptr createCCLayerImpl() OVERRIDE; - -private: - explicit VideoLayerChromium(WebKit::WebVideoFrameProvider*); - virtual ~VideoLayerChromium(); - - // This pointer is only for passing to CCVideoLayerImpl's constructor. It should never be dereferenced by this class. - WebKit::WebVideoFrameProvider* m_provider; -}; - -} -#endif // USE(ACCELERATED_COMPOSITING) - -#endif +// Temporary forwarding header +#include "cc/video_layer.h" diff --git a/cc/active_animation.cc b/cc/active_animation.cc new file mode 100644 index 0000000..b1817d1 --- /dev/null +++ b/cc/active_animation.cc @@ -0,0 +1,212 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#include "CCActiveAnimation.h" + +#include "CCAnimationCurve.h" +#include "TraceEvent.h" +#ifdef LOG +#undef LOG +#endif +#include "base/string_util.h" +#include + +namespace { + +// This should match the RunState enum. +static const char* const s_runStateNames[] = { + "WaitingForNextTick", + "WaitingForTargetAvailability", + "WaitingForStartTime", + "WaitingForDeletion", + "Running", + "Paused", + "Finished", + "Aborted" +}; + +COMPILE_ASSERT(static_cast(cc::CCActiveAnimation::RunStateEnumSize) == arraysize(s_runStateNames), RunState_names_match_enum); + +// This should match the TargetProperty enum. +static const char* const s_targetPropertyNames[] = { + "Transform", + "Opacity" +}; + +COMPILE_ASSERT(static_cast(cc::CCActiveAnimation::TargetPropertyEnumSize) == arraysize(s_targetPropertyNames), TargetProperty_names_match_enum); + +} // namespace + +namespace cc { + +scoped_ptr CCActiveAnimation::create(scoped_ptr curve, int animationId, int groupId, TargetProperty targetProperty) +{ + return make_scoped_ptr(new CCActiveAnimation(curve.Pass(), animationId, groupId, targetProperty)); +} + +CCActiveAnimation::CCActiveAnimation(scoped_ptr curve, int animationId, int groupId, TargetProperty targetProperty) + : m_curve(curve.Pass()) + , m_id(animationId) + , m_group(groupId) + , m_targetProperty(targetProperty) + , m_runState(WaitingForTargetAvailability) + , m_iterations(1) + , m_startTime(0) + , m_alternatesDirection(false) + , m_timeOffset(0) + , m_needsSynchronizedStartTime(false) + , m_suspended(false) + , m_pauseTime(0) + , m_totalPausedTime(0) + , m_isControllingInstance(false) +{ +} + +CCActiveAnimation::~CCActiveAnimation() +{ + if (m_runState == Running || m_runState == Paused) + setRunState(Aborted, 0); +} + +void CCActiveAnimation::setRunState(RunState runState, double monotonicTime) +{ + if (m_suspended) + return; + + char nameBuffer[256]; + base::snprintf(nameBuffer, sizeof(nameBuffer), "%s-%d%s", s_targetPropertyNames[m_targetProperty], m_group, m_isControllingInstance ? "(impl)" : ""); + + bool isWaitingToStart = m_runState == WaitingForNextTick + || m_runState == WaitingForTargetAvailability + || m_runState == WaitingForStartTime; + + if (isWaitingToStart && runState == Running) + TRACE_EVENT_ASYNC_BEGIN1("cc", "CCActiveAnimation", this, "Name", TRACE_STR_COPY(nameBuffer)); + + bool wasFinished = isFinished(); + + const char* oldRunStateName = s_runStateNames[m_runState]; + + if (runState == Running && m_runState == Paused) + m_totalPausedTime += monotonicTime - m_pauseTime; + else if (runState == Paused) + m_pauseTime = monotonicTime; + m_runState = runState; + + const char* newRunStateName = s_runStateNames[runState]; + + if (!wasFinished && isFinished()) + TRACE_EVENT_ASYNC_END0("cc", "CCActiveAnimation", this); + + char stateBuffer[256]; + base::snprintf(stateBuffer, sizeof(stateBuffer), "%s->%s", oldRunStateName, newRunStateName); + + TRACE_EVENT_INSTANT2("cc", "CCLayerAnimationController::setRunState", "Name", TRACE_STR_COPY(nameBuffer), "State", TRACE_STR_COPY(stateBuffer)); +} + +void CCActiveAnimation::suspend(double monotonicTime) +{ + setRunState(Paused, monotonicTime); + m_suspended = true; +} + +void CCActiveAnimation::resume(double monotonicTime) +{ + m_suspended = false; + setRunState(Running, monotonicTime); +} + +bool CCActiveAnimation::isFinishedAt(double monotonicTime) const +{ + if (isFinished()) + return true; + + if (m_needsSynchronizedStartTime) + return false; + + return m_runState == Running + && m_iterations >= 0 + && m_iterations * m_curve->duration() <= monotonicTime - startTime() - m_totalPausedTime; +} + +double CCActiveAnimation::trimTimeToCurrentIteration(double monotonicTime) const +{ + double trimmed = monotonicTime + m_timeOffset; + + // If we're paused, time is 'stuck' at the pause time. + if (m_runState == Paused) + trimmed = m_pauseTime; + + // Returned time should always be relative to the start time and should subtract + // all time spent paused. + trimmed -= m_startTime + m_totalPausedTime; + + // Zero is always the start of the animation. + if (trimmed <= 0) + return 0; + + // Always return zero if we have no iterations. + if (!m_iterations) + return 0; + + // Don't attempt to trim if we have no duration. + if (m_curve->duration() <= 0) + return 0; + + // If less than an iteration duration, just return trimmed. + if (trimmed < m_curve->duration()) + return trimmed; + + // If greater than or equal to the total duration, return iteration duration. + if (m_iterations >= 0 && trimmed >= m_curve->duration() * m_iterations) { + if (m_alternatesDirection && !(m_iterations % 2)) + return 0; + return m_curve->duration(); + } + + // We need to know the current iteration if we're alternating. + int iteration = static_cast(trimmed / m_curve->duration()); + + // Calculate x where trimmed = x + n * m_curve->duration() for some positive integer n. + trimmed = fmod(trimmed, m_curve->duration()); + + // If we're alternating and on an odd iteration, reverse the direction. + if (m_alternatesDirection && iteration % 2 == 1) + return m_curve->duration() - trimmed; + + return trimmed; +} + +scoped_ptr CCActiveAnimation::clone(InstanceType instanceType) const +{ + return cloneAndInitialize(instanceType, m_runState, m_startTime); +} + +scoped_ptr CCActiveAnimation::cloneAndInitialize(InstanceType instanceType, RunState initialRunState, double startTime) const +{ + scoped_ptr toReturn(new CCActiveAnimation(m_curve->clone(), m_id, m_group, m_targetProperty)); + toReturn->m_runState = initialRunState; + toReturn->m_iterations = m_iterations; + toReturn->m_startTime = startTime; + toReturn->m_pauseTime = m_pauseTime; + toReturn->m_totalPausedTime = m_totalPausedTime; + toReturn->m_timeOffset = m_timeOffset; + toReturn->m_alternatesDirection = m_alternatesDirection; + toReturn->m_isControllingInstance = instanceType == ControllingInstance; + return toReturn.Pass(); +} + +void CCActiveAnimation::pushPropertiesTo(CCActiveAnimation* other) const +{ + // Currently, we only push changes due to pausing and resuming animations on the main thread. + if (m_runState == CCActiveAnimation::Paused || other->m_runState == CCActiveAnimation::Paused) { + other->m_runState = m_runState; + other->m_pauseTime = m_pauseTime; + other->m_totalPausedTime = m_totalPausedTime; + } +} + +} // namespace cc diff --git a/cc/active_animation.h b/cc/active_animation.h index 638cbb2..b8d3607 100644 --- a/cc/active_animation.h +++ b/cc/active_animation.h @@ -1,3 +1,161 @@ // Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CCActiveAnimation_h +#define CCActiveAnimation_h + +#include "base/basictypes.h" +#include "base/memory/scoped_ptr.h" + +namespace cc { + +class CCAnimationCurve; + +// A CCActiveAnimation, contains all the state required to play a CCAnimationCurve. +// Specifically, the affected property, the run state (paused, finished, etc.), +// loop count, last pause time, and the total time spent paused. +class CCActiveAnimation { +public: + // Animations begin in one of the 'waiting' states. Animations waiting for the next tick + // will start the next time the controller animates. Animations waiting for target + // availibility will run as soon as their target property is free (and all the animations + // animating with it are also able to run). Animations waiting for their start time to + // come have be scheduled to run at a particular point in time. When this time arrives, + // the controller will move the animations into the Running state. Running animations + // may toggle between Running and Paused, and may be stopped by moving into either the + // Aborted or Finished states. A Finished animation was allowed to run to completion, but + // an Aborted animation was not. + enum RunState { + WaitingForNextTick = 0, + WaitingForTargetAvailability, + WaitingForStartTime, + WaitingForDeletion, + Running, + Paused, + Finished, + Aborted, + // This sentinel must be last. + RunStateEnumSize + }; + + enum TargetProperty { + Transform = 0, + Opacity, + // This sentinel must be last. + TargetPropertyEnumSize + }; + + static scoped_ptr create(scoped_ptr, int animationId, int groupId, TargetProperty); + + virtual ~CCActiveAnimation(); + + int id() const { return m_id; } + int group() const { return m_group; } + TargetProperty targetProperty() const { return m_targetProperty; } + + RunState runState() const { return m_runState; } + void setRunState(RunState, double monotonicTime); + + // This is the number of times that the animation will play. If this + // value is zero the animation will not play. If it is negative, then + // the animation will loop indefinitely. + int iterations() const { return m_iterations; } + void setIterations(int n) { m_iterations = n; } + + double startTime() const { return m_startTime; } + void setStartTime(double monotonicTime) { m_startTime = monotonicTime; } + bool hasSetStartTime() const { return m_startTime; } + + double timeOffset() const { return m_timeOffset; } + void setTimeOffset(double monotonicTime) { m_timeOffset = monotonicTime; } + + void suspend(double monotonicTime); + void resume(double monotonicTime); + + // If alternatesDirection is true, on odd numbered iterations we reverse the curve. + bool alternatesDirection() const { return m_alternatesDirection; } + void setAlternatesDirection(bool alternates) { m_alternatesDirection = alternates; } + + bool isFinishedAt(double monotonicTime) const; + bool isFinished() const { return m_runState == Finished + || m_runState == Aborted + || m_runState == WaitingForDeletion; } + + CCAnimationCurve* curve() { return m_curve.get(); } + const CCAnimationCurve* curve() const { return m_curve.get(); } + + // If this is true, even if the animation is running, it will not be tickable until + // it is given a start time. This is true for animations running on the main thread. + bool needsSynchronizedStartTime() const { return m_needsSynchronizedStartTime; } + void setNeedsSynchronizedStartTime(bool needsSynchronizedStartTime) { m_needsSynchronizedStartTime = needsSynchronizedStartTime; } + + // Takes the given absolute time, and using the start time and the number + // of iterations, returns the relative time in the current iteration. + double trimTimeToCurrentIteration(double monotonicTime) const; + + enum InstanceType { + ControllingInstance = 0, + NonControllingInstance + }; + + scoped_ptr clone(InstanceType) const; + scoped_ptr cloneAndInitialize(InstanceType, RunState initialRunState, double startTime) const; + bool isControllingInstance() const { return m_isControllingInstance; } + + void pushPropertiesTo(CCActiveAnimation*) const; + +private: + CCActiveAnimation(scoped_ptr, int animationId, int groupId, TargetProperty); + + scoped_ptr m_curve; + + // IDs are not necessarily unique. + int m_id; + + // Animations that must be run together are called 'grouped' and have the same group id + // Grouped animations are guaranteed to start at the same time and no other animations + // may animate any of the group's target properties until all animations in the + // group have finished animating. Note: an active animation's group id and target + // property uniquely identify that animation. + int m_group; + + TargetProperty m_targetProperty; + RunState m_runState; + int m_iterations; + double m_startTime; + bool m_alternatesDirection; + + // The time offset effectively pushes the start of the animation back in time. This is + // used for resuming paused animations -- an animation is added with a non-zero time + // offset, causing the animation to skip ahead to the desired point in time. + double m_timeOffset; + + bool m_needsSynchronizedStartTime; + + // When an animation is suspended, it behaves as if it is paused and it also ignores + // all run state changes until it is resumed. This is used for testing purposes. + bool m_suspended; + + // These are used in trimTimeToCurrentIteration to account for time + // spent while paused. This is not included in AnimationState since it + // there is absolutely no need for clients of this controller to know + // about these values. + double m_pauseTime; + double m_totalPausedTime; + + // Animations lead dual lives. An active animation will be conceptually owned by + // two controllers, one on the impl thread and one on the main. In reality, there + // will be two separate CCActiveAnimation instances for the same animation. They + // will have the same group id and the same target property (these two values + // uniquely identify an animation). The instance on the impl thread is the instance + // that ultimately controls the values of the animating layer and so we will refer + // to it as the 'controlling instance'. + bool m_isControllingInstance; + + DISALLOW_COPY_AND_ASSIGN(CCActiveAnimation); +}; + +} // namespace cc + +#endif // CCActiveAnimation_h diff --git a/cc/animation_curve.cc b/cc/animation_curve.cc new file mode 100644 index 0000000..7cd0158 --- /dev/null +++ b/cc/animation_curve.cc @@ -0,0 +1,33 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#include "CCAnimationCurve.h" + +namespace cc { + +const CCFloatAnimationCurve* CCAnimationCurve::toFloatAnimationCurve() const +{ + ASSERT(type() == CCAnimationCurve::Float); + return static_cast(this); +} + +CCAnimationCurve::Type CCFloatAnimationCurve::type() const +{ + return Float; +} + +const CCTransformAnimationCurve* CCAnimationCurve::toTransformAnimationCurve() const +{ + ASSERT(type() == CCAnimationCurve::Transform); + return static_cast(this); +} + +CCAnimationCurve::Type CCTransformAnimationCurve::type() const +{ + return Transform; +} + +} // namespace cc diff --git a/cc/animation_curve.h b/cc/animation_curve.h index 638cbb2..7ed6e7a 100644 --- a/cc/animation_curve.h +++ b/cc/animation_curve.h @@ -1,3 +1,56 @@ // Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CCAnimationCurve_h +#define CCAnimationCurve_h + +#include "base/memory/scoped_ptr.h" +#include + +namespace cc { + +class CCFloatAnimationCurve; +class CCTransformAnimationCurve; +class IntSize; +class TransformOperations; + +// An animation curve is a function that returns a value given a time. +// There are currently only two types of curve, float and transform. +class CCAnimationCurve { +public: + enum Type { Float, Transform }; + + virtual ~CCAnimationCurve() { } + + virtual double duration() const = 0; + virtual Type type() const = 0; + virtual scoped_ptr clone() const = 0; + + const CCFloatAnimationCurve* toFloatAnimationCurve() const; + const CCTransformAnimationCurve* toTransformAnimationCurve() const; +}; + +class CCFloatAnimationCurve : public CCAnimationCurve { +public: + virtual ~CCFloatAnimationCurve() { } + + virtual float getValue(double t) const = 0; + + // Partial CCAnimation implementation. + virtual Type type() const OVERRIDE; +}; + +class CCTransformAnimationCurve : public CCAnimationCurve { +public: + virtual ~CCTransformAnimationCurve() { } + + virtual WebKit::WebTransformationMatrix getValue(double t) const = 0; + + // Partial CCAnimation implementation. + virtual Type type() const OVERRIDE; +}; + +} // namespace cc + +#endif // CCAnimation_h diff --git a/cc/animation_events.h b/cc/animation_events.h index 638cbb2..5e86ef7 100644 --- a/cc/animation_events.h +++ b/cc/animation_events.h @@ -1,3 +1,37 @@ // Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CCAnimationEvents_h +#define CCAnimationEvents_h + +#include + +#include "CCActiveAnimation.h" + +namespace cc { + +struct CCAnimationEvent { + enum Type { Started, Finished }; + + CCAnimationEvent(Type type, int layerId, int groupId, CCActiveAnimation::TargetProperty targetProperty, double monotonicTime) + : type(type) + , layerId(layerId) + , groupId(groupId) + , targetProperty(targetProperty) + , monotonicTime(monotonicTime) + { + } + + Type type; + int layerId; + int groupId; + CCActiveAnimation::TargetProperty targetProperty; + double monotonicTime; +}; + +typedef std::vector CCAnimationEventsVector; + +} // namespace cc + +#endif // CCAnimationEvents_h diff --git a/cc/append_quads_data.h b/cc/append_quads_data.h index 638cbb2..b086de0 100644 --- a/cc/append_quads_data.h +++ b/cc/append_quads_data.h @@ -1,3 +1,36 @@ // Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CCAppendQuadsData_h +#define CCAppendQuadsData_h + +#include "CCRenderPass.h" + +namespace cc { + +struct CCAppendQuadsData { + CCAppendQuadsData() + : hadOcclusionFromOutsideTargetSurface(false) + , hadMissingTiles(false) + , renderPassId(0, 0) + { + } + + explicit CCAppendQuadsData(CCRenderPass::Id renderPassId) + : hadOcclusionFromOutsideTargetSurface(false) + , hadMissingTiles(false) + , renderPassId(renderPassId) + { + } + + // Set by the QuadCuller. + bool hadOcclusionFromOutsideTargetSurface; + // Set by the layer appending quads. + bool hadMissingTiles; + // Given to the layer appending quads. + const CCRenderPass::Id renderPassId; +}; + +} +#endif // CCCCAppendQuadsData_h diff --git a/cc/bitmap_canvas_layer_texture_updater.cc b/cc/bitmap_canvas_layer_texture_updater.cc new file mode 100644 index 0000000..3231b7d --- /dev/null +++ b/cc/bitmap_canvas_layer_texture_updater.cc @@ -0,0 +1,89 @@ +// Copyright 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + +#include "config.h" + +#if USE(ACCELERATED_COMPOSITING) + +#include "BitmapCanvasLayerTextureUpdater.h" + +#include "LayerPainterChromium.h" +#include "PlatformColor.h" +#include "skia/ext/platform_canvas.h" + +namespace cc { + +BitmapCanvasLayerTextureUpdater::Texture::Texture(BitmapCanvasLayerTextureUpdater* textureUpdater, scoped_ptr texture) + : LayerTextureUpdater::Texture(texture.Pass()) + , m_textureUpdater(textureUpdater) +{ +} + +BitmapCanvasLayerTextureUpdater::Texture::~Texture() +{ +} + +void BitmapCanvasLayerTextureUpdater::Texture::updateRect(CCResourceProvider* resourceProvider, const IntRect& sourceRect, const IntSize& destOffset) +{ + textureUpdater()->updateTextureRect(resourceProvider, texture(), sourceRect, destOffset); +} + +PassRefPtr BitmapCanvasLayerTextureUpdater::create(PassOwnPtr painter) +{ + return adoptRef(new BitmapCanvasLayerTextureUpdater(painter)); +} + +BitmapCanvasLayerTextureUpdater::BitmapCanvasLayerTextureUpdater(PassOwnPtr painter) + : CanvasLayerTextureUpdater(painter) + , m_opaque(false) +{ +} + +BitmapCanvasLayerTextureUpdater::~BitmapCanvasLayerTextureUpdater() +{ +} + +PassOwnPtr BitmapCanvasLayerTextureUpdater::createTexture(CCPrioritizedTextureManager* manager) +{ + return adoptPtr(new Texture(this, CCPrioritizedTexture::create(manager))); +} + +LayerTextureUpdater::SampledTexelFormat BitmapCanvasLayerTextureUpdater::sampledTexelFormat(GC3Denum textureFormat) +{ + // The component order may be bgra if we uploaded bgra pixels to rgba textures. + return PlatformColor::sameComponentOrder(textureFormat) ? + LayerTextureUpdater::SampledTexelFormatRGBA : LayerTextureUpdater::SampledTexelFormatBGRA; +} + +void BitmapCanvasLayerTextureUpdater::prepareToUpdate(const IntRect& contentRect, const IntSize& tileSize, float contentsWidthScale, float contentsHeightScale, IntRect& resultingOpaqueRect, CCRenderingStats& stats) +{ + if (m_canvasSize != contentRect.size()) { + m_canvasSize = contentRect.size(); + m_canvas = adoptPtr(skia::CreateBitmapCanvas(m_canvasSize.width(), m_canvasSize.height(), m_opaque)); + } + + paintContents(m_canvas.get(), contentRect, contentsWidthScale, contentsHeightScale, resultingOpaqueRect, stats); +} + +void BitmapCanvasLayerTextureUpdater::updateTextureRect(CCResourceProvider* resourceProvider, CCPrioritizedTexture* texture, const IntRect& sourceRect, const IntSize& destOffset) +{ + const SkBitmap& bitmap = m_canvas->getDevice()->accessBitmap(false); + bitmap.lockPixels(); + + texture->upload(resourceProvider, static_cast(bitmap.getPixels()), contentRect(), sourceRect, destOffset); + bitmap.unlockPixels(); +} + +void BitmapCanvasLayerTextureUpdater::setOpaque(bool opaque) +{ + if (opaque != m_opaque) { + m_canvas.clear(); + m_canvasSize = IntSize(); + } + m_opaque = opaque; +} + +} // namespace cc +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/cc/bitmap_canvas_layer_texture_updater.h b/cc/bitmap_canvas_layer_texture_updater.h index 638cbb2..8cf4e25 100644 --- a/cc/bitmap_canvas_layer_texture_updater.h +++ b/cc/bitmap_canvas_layer_texture_updater.h @@ -1,3 +1,57 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. +// Copyright 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + + +#ifndef BitmapCanvasLayerTextureUpdater_h +#define BitmapCanvasLayerTextureUpdater_h + +#if USE(ACCELERATED_COMPOSITING) + +#include "CanvasLayerTextureUpdater.h" + +class SkCanvas; + +namespace cc { + +class LayerPainterChromium; + +// This class rasterizes the contentRect into a skia bitmap canvas. It then updates +// textures by copying from the canvas into the texture, using MapSubImage if +// possible. +class BitmapCanvasLayerTextureUpdater : public CanvasLayerTextureUpdater { +public: + class Texture : public LayerTextureUpdater::Texture { + public: + Texture(BitmapCanvasLayerTextureUpdater*, scoped_ptr); + virtual ~Texture(); + + virtual void updateRect(CCResourceProvider*, const IntRect& sourceRect, const IntSize& destOffset) OVERRIDE; + + private: + BitmapCanvasLayerTextureUpdater* textureUpdater() { return m_textureUpdater; } + + BitmapCanvasLayerTextureUpdater* m_textureUpdater; + }; + + static PassRefPtr create(PassOwnPtr); + virtual ~BitmapCanvasLayerTextureUpdater(); + + virtual PassOwnPtr createTexture(CCPrioritizedTextureManager*) OVERRIDE; + virtual SampledTexelFormat sampledTexelFormat(GC3Denum textureFormat) OVERRIDE; + virtual void prepareToUpdate(const IntRect& contentRect, const IntSize& tileSize, float contentsWidthScale, float contentsHeightScale, IntRect& resultingOpaqueRect, CCRenderingStats&) OVERRIDE; + void updateTextureRect(CCResourceProvider*, CCPrioritizedTexture*, const IntRect& sourceRect, const IntSize& destOffset); + + virtual void setOpaque(bool) OVERRIDE; + +protected: + explicit BitmapCanvasLayerTextureUpdater(PassOwnPtr); + + OwnPtr m_canvas; + IntSize m_canvasSize; + bool m_opaque; +}; + +} // namespace cc +#endif // USE(ACCELERATED_COMPOSITING) +#endif // BitmapCanvasLayerTextureUpdater_h diff --git a/cc/bitmap_skpicture_canvas_layer_texture_updater.cc b/cc/bitmap_skpicture_canvas_layer_texture_updater.cc new file mode 100644 index 0000000..93c8483 --- /dev/null +++ b/cc/bitmap_skpicture_canvas_layer_texture_updater.cc @@ -0,0 +1,84 @@ +// Copyright 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + +#include "config.h" + +#if USE(ACCELERATED_COMPOSITING) + +#include "BitmapSkPictureCanvasLayerTextureUpdater.h" + +#include "CCRenderingStats.h" +#include "LayerPainterChromium.h" +#include "PlatformColor.h" +#include "SkCanvas.h" +#include "SkDevice.h" +#include + +namespace cc { + +BitmapSkPictureCanvasLayerTextureUpdater::Texture::Texture(BitmapSkPictureCanvasLayerTextureUpdater* textureUpdater, scoped_ptr texture) + : CanvasLayerTextureUpdater::Texture(texture.Pass()) + , m_textureUpdater(textureUpdater) +{ +} + +void BitmapSkPictureCanvasLayerTextureUpdater::Texture::prepareRect(const IntRect& sourceRect, CCRenderingStats& stats) +{ + m_bitmap.setConfig(SkBitmap::kARGB_8888_Config, sourceRect.width(), sourceRect.height()); + m_bitmap.allocPixels(); + m_bitmap.setIsOpaque(m_textureUpdater->layerIsOpaque()); + SkDevice device(m_bitmap); + SkCanvas canvas(&device); + double paintBeginTime = monotonicallyIncreasingTime(); + textureUpdater()->paintContentsRect(&canvas, sourceRect, stats); + stats.totalPaintTimeInSeconds += monotonicallyIncreasingTime() - paintBeginTime; +} + +void BitmapSkPictureCanvasLayerTextureUpdater::Texture::updateRect(CCResourceProvider* resourceProvider, const IntRect& sourceRect, const IntSize& destOffset) +{ + m_bitmap.lockPixels(); + texture()->upload(resourceProvider, static_cast(m_bitmap.getPixels()), sourceRect, sourceRect, destOffset); + m_bitmap.unlockPixels(); + m_bitmap.reset(); +} + +PassRefPtr BitmapSkPictureCanvasLayerTextureUpdater::create(PassOwnPtr painter) +{ + return adoptRef(new BitmapSkPictureCanvasLayerTextureUpdater(painter)); +} + +BitmapSkPictureCanvasLayerTextureUpdater::BitmapSkPictureCanvasLayerTextureUpdater(PassOwnPtr painter) + : SkPictureCanvasLayerTextureUpdater(painter) +{ +} + +BitmapSkPictureCanvasLayerTextureUpdater::~BitmapSkPictureCanvasLayerTextureUpdater() +{ +} + +PassOwnPtr BitmapSkPictureCanvasLayerTextureUpdater::createTexture(CCPrioritizedTextureManager* manager) +{ + return adoptPtr(new Texture(this, CCPrioritizedTexture::create(manager))); +} + +LayerTextureUpdater::SampledTexelFormat BitmapSkPictureCanvasLayerTextureUpdater::sampledTexelFormat(GC3Denum textureFormat) +{ + // The component order may be bgra if we uploaded bgra pixels to rgba textures. + return PlatformColor::sameComponentOrder(textureFormat) ? + LayerTextureUpdater::SampledTexelFormatRGBA : LayerTextureUpdater::SampledTexelFormatBGRA; +} + +void BitmapSkPictureCanvasLayerTextureUpdater::paintContentsRect(SkCanvas* canvas, const IntRect& sourceRect, CCRenderingStats& stats) +{ + // Translate the origin of contentRect to that of sourceRect. + canvas->translate(contentRect().x() - sourceRect.x(), + contentRect().y() - sourceRect.y()); + double rasterizeBeginTime = monotonicallyIncreasingTime(); + drawPicture(canvas); + stats.totalRasterizeTimeInSeconds += monotonicallyIncreasingTime() - rasterizeBeginTime; +} + +} // namespace cc +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/cc/bitmap_skpicture_canvas_layer_texture_updater.h b/cc/bitmap_skpicture_canvas_layer_texture_updater.h index 638cbb2..140f9be 100644 --- a/cc/bitmap_skpicture_canvas_layer_texture_updater.h +++ b/cc/bitmap_skpicture_canvas_layer_texture_updater.h @@ -1,3 +1,45 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. +// Copyright 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + + +#ifndef BitmapSkPictureCanvasLayerTextureUpdater_h +#define BitmapSkPictureCanvasLayerTextureUpdater_h + +#if USE(ACCELERATED_COMPOSITING) +#include "SkBitmap.h" +#include "SkPictureCanvasLayerTextureUpdater.h" + +namespace cc { + +// This class records the contentRect into an SkPicture, then software rasterizes +// the SkPicture into bitmaps for each tile. This implements CCSettings::perTilePainting. +class BitmapSkPictureCanvasLayerTextureUpdater : public SkPictureCanvasLayerTextureUpdater { +public: + class Texture : public CanvasLayerTextureUpdater::Texture { + public: + Texture(BitmapSkPictureCanvasLayerTextureUpdater*, scoped_ptr); + + virtual void prepareRect(const IntRect& sourceRect, CCRenderingStats&) OVERRIDE; + virtual void updateRect(CCResourceProvider*, const IntRect& sourceRect, const IntSize& destOffset) OVERRIDE; + + private: + BitmapSkPictureCanvasLayerTextureUpdater* textureUpdater() { return m_textureUpdater; } + + SkBitmap m_bitmap; + BitmapSkPictureCanvasLayerTextureUpdater* m_textureUpdater; + }; + + static PassRefPtr create(PassOwnPtr); + virtual ~BitmapSkPictureCanvasLayerTextureUpdater(); + + virtual PassOwnPtr createTexture(CCPrioritizedTextureManager*) OVERRIDE; + virtual SampledTexelFormat sampledTexelFormat(GC3Denum textureFormat) OVERRIDE; + void paintContentsRect(SkCanvas*, const IntRect& sourceRect, CCRenderingStats&); + +private: + explicit BitmapSkPictureCanvasLayerTextureUpdater(PassOwnPtr); +}; +} // namespace cc +#endif // USE(ACCELERATED_COMPOSITING) +#endif // BitmapSkPictureCanvasLayerTextureUpdater_h diff --git a/cc/canvas_layer_texture_updater.cc b/cc/canvas_layer_texture_updater.cc new file mode 100644 index 0000000..eae5d16a --- /dev/null +++ b/cc/canvas_layer_texture_updater.cc @@ -0,0 +1,70 @@ +// Copyright 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + +#include "config.h" + +#if USE(ACCELERATED_COMPOSITING) + +#include "CanvasLayerTextureUpdater.h" + +#include "CCRenderingStats.h" +#include "FloatRect.h" +#include "LayerPainterChromium.h" +#include "SkCanvas.h" +#include "SkPaint.h" +#include "SkRect.h" +#include "SkiaUtils.h" +#include "TraceEvent.h" +#include + +namespace cc { + +CanvasLayerTextureUpdater::CanvasLayerTextureUpdater(PassOwnPtr painter) + : m_painter(painter) +{ +} + +CanvasLayerTextureUpdater::~CanvasLayerTextureUpdater() +{ +} + +void CanvasLayerTextureUpdater::paintContents(SkCanvas* canvas, const IntRect& contentRect, float contentsWidthScale, float contentsHeightScale, IntRect& resultingOpaqueRect, CCRenderingStats& stats) +{ + TRACE_EVENT0("cc", "CanvasLayerTextureUpdater::paintContents"); + canvas->save(); + canvas->translate(CCFloatToSkScalar(-contentRect.x()), CCFloatToSkScalar(-contentRect.y())); + + IntRect layerRect = contentRect; + + if (contentsWidthScale != 1 || contentsHeightScale != 1) { + canvas->scale(CCFloatToSkScalar(contentsWidthScale), CCFloatToSkScalar(contentsHeightScale)); + + FloatRect rect = contentRect; + rect.scale(1 / contentsWidthScale, 1 / contentsHeightScale); + layerRect = enclosingIntRect(rect); + } + + SkPaint paint; + paint.setAntiAlias(false); + paint.setXfermodeMode(SkXfermode::kClear_Mode); + SkRect layerSkRect = SkRect::MakeXYWH(layerRect.x(), layerRect.y(), layerRect.width(), layerRect.height()); + canvas->drawRect(layerSkRect, paint); + canvas->clipRect(layerSkRect); + + FloatRect opaqueLayerRect; + double paintBeginTime = monotonicallyIncreasingTime(); + m_painter->paint(canvas, layerRect, opaqueLayerRect); + stats.totalPaintTimeInSeconds += monotonicallyIncreasingTime() - paintBeginTime; + canvas->restore(); + + FloatRect opaqueContentRect = opaqueLayerRect; + opaqueContentRect.scale(contentsWidthScale, contentsHeightScale); + resultingOpaqueRect = enclosedIntRect(opaqueContentRect); + + m_contentRect = contentRect; +} + +} // namespace cc +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/cc/canvas_layer_texture_updater.h b/cc/canvas_layer_texture_updater.h index 638cbb2..c8bb9b0 100644 --- a/cc/canvas_layer_texture_updater.h +++ b/cc/canvas_layer_texture_updater.h @@ -1,3 +1,39 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. +// Copyright 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + + +#ifndef CanvasLayerTextureUpdater_h +#define CanvasLayerTextureUpdater_h + +#if USE(ACCELERATED_COMPOSITING) + +#include "LayerTextureUpdater.h" + +class SkCanvas; + +namespace cc { + +class LayerPainterChromium; + +// Base class for BitmapCanvasLayerTextureUpdater and +// SkPictureCanvasLayerTextureUpdater that reduces code duplication between +// their respective paintContents implementations. +class CanvasLayerTextureUpdater : public LayerTextureUpdater { +public: + virtual ~CanvasLayerTextureUpdater(); + +protected: + explicit CanvasLayerTextureUpdater(PassOwnPtr); + + void paintContents(SkCanvas*, const IntRect& contentRect, float contentsWidthScale, float contentsHeightScale, IntRect& resultingOpaqueRect, CCRenderingStats&); + const IntRect& contentRect() const { return m_contentRect; } + +private: + IntRect m_contentRect; + OwnPtr m_painter; +}; + +} // namespace cc +#endif // USE(ACCELERATED_COMPOSITING) +#endif // CanvasLayerTextureUpdater_h diff --git a/cc/cc.gyp b/cc/cc.gyp index 264021e..be5b960 100644 --- a/cc/cc.gyp +++ b/cc/cc.gyp @@ -11,220 +11,220 @@ 'own_ptr_vector.h', 'scoped_ptr_hash_map.h', 'scoped_ptr_vector.h', - 'BitmapCanvasLayerTextureUpdater.cpp', + 'bitmap_canvas_layer_texture_updater.cc', 'BitmapCanvasLayerTextureUpdater.h', - 'BitmapSkPictureCanvasLayerTextureUpdater.cpp', + 'bitmap_skpicture_canvas_layer_texture_updater.cc', 'BitmapSkPictureCanvasLayerTextureUpdater.h', 'caching_bitmap_canvas_layer_texture_updater.cc', 'caching_bitmap_canvas_layer_texture_updater.h', - 'CCActiveAnimation.cpp', + 'active_animation.cc', 'CCActiveAnimation.h', 'CCAppendQuadsData.h', - 'CCAnimationCurve.cpp', + 'animation_curve.cc', 'CCAnimationCurve.h', 'CCAnimationEvents.h', - 'CCCheckerboardDrawQuad.cpp', + 'checkerboard_draw_quad.cc', 'CCCheckerboardDrawQuad.h', 'CCCompletionEvent.h', - 'CCDamageTracker.cpp', + 'damage_tracker.cc', 'CCDamageTracker.h', - 'CCDebugBorderDrawQuad.cpp', + 'debug_border_draw_quad.cc', 'CCDebugBorderDrawQuad.h', - 'CCDebugRectHistory.cpp', + 'debug_rect_history.cc', 'CCDebugRectHistory.h', - 'CCDelayBasedTimeSource.cpp', + 'delay_based_time_source.cc', 'CCDelayBasedTimeSource.h', - 'CCDelegatedRendererLayerImpl.cpp', + 'delegated_renderer_layer_impl.cc', 'CCDelegatedRendererLayerImpl.h', - 'CCDirectRenderer.cpp', + 'direct_renderer.cc', 'CCDirectRenderer.h', - 'CCDrawQuad.cpp', + 'draw_quad.cc', 'CCDrawQuad.h', - 'CCFontAtlas.cpp', + 'font_atlas.cc', 'CCFontAtlas.h', - 'CCFrameRateController.cpp', + 'frame_rate_controller.cc', 'CCFrameRateController.h', - 'CCFrameRateCounter.cpp', + 'frame_rate_counter.cc', 'CCFrameRateCounter.h', 'CCGraphicsContext.h', - 'CCHeadsUpDisplayLayerImpl.cpp', + 'heads_up_display_layer_impl.cc', 'CCHeadsUpDisplayLayerImpl.h', - 'CCIOSurfaceDrawQuad.cpp', + 'io_surface_draw_quad.cc', 'CCIOSurfaceDrawQuad.h', - 'CCIOSurfaceLayerImpl.cpp', + 'io_surface_layer_impl.cc', 'CCIOSurfaceLayerImpl.h', 'CCInputHandler.h', - 'CCKeyframedAnimationCurve.cpp', + 'keyframed_animation_curve.cc', 'CCKeyframedAnimationCurve.h', - 'CCLayerAnimationController.cpp', + 'layer_animation_controller.cc', 'CCLayerAnimationController.h', - 'CCLayerImpl.cpp', + 'layer_impl.cc', 'CCLayerImpl.h', - 'CCLayerIterator.cpp', + 'layer_iterator.cc', 'CCLayerIterator.h', - 'CCLayerQuad.cpp', + 'layer_quad.cc', 'CCLayerQuad.h', - 'CCLayerSorter.cpp', + 'layer_sorter.cc', 'CCLayerSorter.h', - 'CCLayerTilingData.cpp', + 'layer_tiling_data.cc', 'CCLayerTilingData.h', - 'CCLayerTreeHost.cpp', + 'layer_tree_host.cc', 'CCLayerTreeHost.h', 'CCLayerTreeHostClient.h', - 'CCLayerTreeHostCommon.cpp', + 'layer_tree_host_common.cc', 'CCLayerTreeHostCommon.h', - 'CCLayerTreeHostImpl.cpp', + 'layer_tree_host_impl.cc', 'CCLayerTreeHostImpl.h', - 'CCMathUtil.cpp', + 'math_util.cc', 'CCMathUtil.h', - 'CCOcclusionTracker.cpp', + 'occlusion_tracker.cc', 'CCOcclusionTracker.h', - 'CCOverdrawMetrics.cpp', + 'overdraw_metrics.cc', 'CCOverdrawMetrics.h', - 'CCPageScaleAnimation.cpp', + 'page_scale_animation.cc', 'CCPageScaleAnimation.h', - 'CCPrioritizedTexture.cpp', + 'prioritized_texture.cc', 'CCPrioritizedTexture.h', - 'CCPrioritizedTextureManager.cpp', + 'prioritized_texture_manager.cc', 'CCPrioritizedTextureManager.h', - 'CCPriorityCalculator.cpp', + 'priority_calculator.cc', 'CCPriorityCalculator.h', - 'CCProxy.cpp', + 'proxy.cc', 'CCProxy.h', - 'CCQuadCuller.cpp', + 'quad_culler.cc', 'CCQuadCuller.h', 'CCQuadSink.h', - 'CCRenderPass.cpp', + 'render_pass.cc', 'CCRenderPass.h', - 'CCRenderPassDrawQuad.cpp', + 'render_pass_draw_quad.cc', 'CCRenderPassDrawQuad.h', 'CCRenderPassSink.h', - 'CCRenderSurface.cpp', + 'render_surface_impl.cc', 'CCRenderSurface.h', - 'CCRenderSurfaceFilters.cpp', + 'render_surface_filters.cc', 'CCRenderSurfaceFilters.h', - 'CCRenderer.cpp', + 'renderer.cc', 'CCRenderer.h', - 'CCRendererGL.cpp', + 'gl_renderer.cc', 'CCRendererGL.h', - 'CCRendererSoftware.cpp', + 'software_renderer.cc', 'CCRendererSoftware.h', 'CCRenderingStats.h', - 'CCResourceProvider.cpp', + 'resource_provider.cc', 'CCResourceProvider.h', - 'CCScheduler.cpp', + 'scheduler.cc', 'CCScheduler.h', - 'CCSchedulerStateMachine.cpp', + 'scheduler_state_machine.cc', 'CCSchedulerStateMachine.h', - 'CCScopedTexture.cpp', + 'scoped_texture.cc', 'CCScopedTexture.h', - 'CCScopedThreadProxy.cpp', + 'scoped_thread_proxy.cc', 'CCScopedThreadProxy.h', - 'CCScrollbarAnimationController.cpp', + 'scrollbar_animation_controller.cc', 'CCScrollbarAnimationController.h', - 'CCScrollbarAnimationControllerLinearFade.cpp', + 'scrollbar_animation_controller_linear_fade.cc', 'CCScrollbarAnimationControllerLinearFade.h', - 'CCScrollbarLayerImpl.cpp', + 'scrollbar_layer_impl.cc', 'CCScrollbarLayerImpl.h', - 'CCScrollbarGeometryFixedThumb.cpp', + 'scrollbar_geometry_fixed_thumb.cc', 'CCScrollbarGeometryFixedThumb.h', - 'CCScrollbarGeometryStub.cpp', + 'scrollbar_geometry_stub.cc', 'CCScrollbarGeometryStub.h', - 'CCSettings.cpp', + 'settings.cc', 'CCSettings.h', - 'CCSharedQuadState.cpp', + 'shared_quad_state.cc', 'CCSharedQuadState.h', - 'CCSingleThreadProxy.cpp', + 'single_thread_proxy.cc', 'CCSingleThreadProxy.h', - 'CCSolidColorDrawQuad.cpp', + 'solid_color_draw_quad.cc', 'CCSolidColorDrawQuad.h', - 'CCSolidColorLayerImpl.cpp', + 'solid_color_layer_impl.cc', 'CCSolidColorLayerImpl.h', - 'CCStreamVideoDrawQuad.cpp', + 'stream_video_draw_quad.cc', 'CCStreamVideoDrawQuad.h', - 'CCTexture.cpp', + 'texture.cc', 'CCTexture.h', - 'CCTextureDrawQuad.cpp', + 'texture_draw_quad.cc', 'CCTextureDrawQuad.h', - 'CCTextureLayerImpl.cpp', + 'texture_layer_impl.cc', 'CCTextureLayerImpl.h', - 'CCTextureUpdateController.cpp', + 'texture_update_controller.cc', 'CCTextureUpdateController.h', - 'CCTextureUpdateQueue.cpp', + 'texture_update_queue.cc', 'CCTextureUpdateQueue.h', 'CCThread.h', - 'CCThreadProxy.cpp', + 'thread_proxy.cc', 'CCThreadProxy.h', 'CCThreadTask.h', - 'CCTileDrawQuad.cpp', + 'tile_draw_quad.cc', 'CCTileDrawQuad.h', - 'CCTiledLayerImpl.cpp', + 'tiled_layer_impl.cc', 'CCTiledLayerImpl.h', 'CCTimeSource.h', - 'CCTimer.cpp', + 'timer.cc', 'CCTimer.h', - 'CCTimingFunction.cpp', + 'timing_function.cc', 'CCTimingFunction.h', - 'CCVideoLayerImpl.cpp', + 'video_layer_impl.cc', 'CCVideoLayerImpl.h', - 'CCYUVVideoDrawQuad.cpp', + 'yuv_video_draw_quad.cc', 'CCYUVVideoDrawQuad.h', - 'CanvasLayerTextureUpdater.cpp', + 'canvas_layer_texture_updater.cc', 'CanvasLayerTextureUpdater.h', - 'ContentLayerChromium.cpp', + 'content_layer.cc', 'ContentLayerChromium.h', 'ContentLayerChromiumClient.h', - 'DelegatedRendererLayerChromium.cpp', + 'delegated_renderer_layer.cc', 'DelegatedRendererLayerChromium.h', - 'FrameBufferSkPictureCanvasLayerTextureUpdater.cpp', + 'frame_buffer_skpicture_canvas_layer_texture_updater.cc', 'FrameBufferSkPictureCanvasLayerTextureUpdater.h', - 'GeometryBinding.cpp', + 'geometry_binding.cc', 'GeometryBinding.h', - 'HeadsUpDisplayLayerChromium.cpp', + 'heads_up_display_layer.cc', 'HeadsUpDisplayLayerChromium.h', - 'IOSurfaceLayerChromium.cpp', + 'io_surface_layer.cc', 'IOSurfaceLayerChromium.h', - 'ImageLayerChromium.cpp', + 'image_layer.cc', 'ImageLayerChromium.h', - 'LayerChromium.cpp', + 'layer.cc', 'LayerChromium.h', 'LayerPainterChromium.h', - 'LayerTextureSubImage.cpp', + 'layer_texture_sub_image.cc', 'LayerTextureSubImage.h', - 'LayerTextureUpdater.cpp', + 'layer_texture_updater.cc', 'LayerTextureUpdater.h', 'PlatformColor.h', - 'ProgramBinding.cpp', + 'program_binding.cc', 'ProgramBinding.h', - 'RateLimiter.cpp', + 'rate_limiter.cc', 'RateLimiter.h', - 'RenderSurfaceChromium.cpp', + 'render_surface.cc', 'RenderSurfaceChromium.h', - 'ScrollbarLayerChromium.cpp', + 'scrollbar_layer.cc', 'ScrollbarLayerChromium.h', - 'ShaderChromium.cpp', + 'shader.cc', 'ShaderChromium.h', - 'SkPictureCanvasLayerTextureUpdater.cpp', + 'skpicture_canvas_layer_texture_updater.cc', 'SkPictureCanvasLayerTextureUpdater.h', - 'SolidColorLayerChromium.cpp', + 'solid_color_layer.cc', 'SolidColorLayerChromium.h', 'switches.cc', 'switches.h', - 'TextureCopier.cpp', + 'texture_copier.cc', 'TextureCopier.h', - 'TextureLayerChromium.cpp', + 'texture_layer.cc', 'TextureLayerChromium.h', 'TextureLayerChromiumClient.h', 'TextureUploader.h', - 'ThrottledTextureUploader.cpp', + 'throttled_texture_uploader.cc', 'ThrottledTextureUploader.h', - 'UnthrottledTextureUploader.cpp', + 'unthrottled_texture_uploader.cc', 'UnthrottledTextureUploader.h', - 'TiledLayerChromium.cpp', + 'tiled_layer.cc', 'TiledLayerChromium.h', - 'TreeSynchronizer.cpp', + 'tree_synchronizer.cc', 'TreeSynchronizer.h', - 'VideoLayerChromium.cpp', + 'video_layer.cc', 'VideoLayerChromium.h', 'bitmap_canvas_layer_texture_updater.h', diff --git a/cc/checkerboard_draw_quad.cc b/cc/checkerboard_draw_quad.cc new file mode 100644 index 0000000..f1b34a3 --- /dev/null +++ b/cc/checkerboard_draw_quad.cc @@ -0,0 +1,28 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#include "CCCheckerboardDrawQuad.h" + +namespace cc { + +scoped_ptr CCCheckerboardDrawQuad::create(const CCSharedQuadState* sharedQuadState, const IntRect& quadRect, SkColor color) +{ + return make_scoped_ptr(new CCCheckerboardDrawQuad(sharedQuadState, quadRect, color)); +} + +CCCheckerboardDrawQuad::CCCheckerboardDrawQuad(const CCSharedQuadState* sharedQuadState, const IntRect& quadRect, SkColor color) + : CCDrawQuad(sharedQuadState, CCDrawQuad::Checkerboard, quadRect) + , m_color(color) +{ +} + +const CCCheckerboardDrawQuad* CCCheckerboardDrawQuad::materialCast(const CCDrawQuad* quad) +{ + ASSERT(quad->material() == CCDrawQuad::Checkerboard); + return static_cast(quad); +} + +} // namespace cc diff --git a/cc/checkerboard_draw_quad.h b/cc/checkerboard_draw_quad.h index 638cbb2..1ef147f 100644 --- a/cc/checkerboard_draw_quad.h +++ b/cc/checkerboard_draw_quad.h @@ -1,3 +1,33 @@ // Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CCCheckerboardDrawQuad_h +#define CCCheckerboardDrawQuad_h + +#include "CCDrawQuad.h" +#include "base/memory/scoped_ptr.h" +#include "SkColor.h" + +namespace cc { + +#pragma pack(push, 4) + +class CCCheckerboardDrawQuad : public CCDrawQuad { +public: + static scoped_ptr create(const CCSharedQuadState*, const IntRect&, SkColor); + + SkColor color() const { return m_color; }; + + static const CCCheckerboardDrawQuad* materialCast(const CCDrawQuad*); +private: + CCCheckerboardDrawQuad(const CCSharedQuadState*, const IntRect&, SkColor); + + SkColor m_color; +}; + +#pragma pack(pop) + +} + +#endif diff --git a/cc/completion_event.h b/cc/completion_event.h index 638cbb2..462e4ba 100644 --- a/cc/completion_event.h +++ b/cc/completion_event.h @@ -1,3 +1,62 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. +// Copyright 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CCCompletionEvent_h +#define CCCompletionEvent_h + +#include "base/synchronization/waitable_event.h" + +namespace cc { + +// Used for making blocking calls from one thread to another. Use only when +// absolutely certain that doing-so will not lead to a deadlock. +// +// It is safe to destroy this object as soon as wait() returns. +class CCCompletionEvent { +public: + CCCompletionEvent() + : m_event(false /* manual_reset */, false /* initially_signaled */) + { +#ifndef NDEBUG + m_waited = false; + m_signaled = false; +#endif + } + + ~CCCompletionEvent() + { + ASSERT(m_waited); + ASSERT(m_signaled); + } + + void wait() + { + ASSERT(!m_waited); +#ifndef NDEBUG + m_waited = true; +#endif + m_event.Wait(); + } + + void signal() + { + ASSERT(!m_signaled); +#ifndef NDEBUG + m_signaled = true; +#endif + m_event.Signal(); + } + +private: + base::WaitableEvent m_event; +#ifndef NDEBUG + // Used to assert that wait() and signal() are each called exactly once. + bool m_waited; + bool m_signaled; +#endif +}; + +} + +#endif diff --git a/cc/content_layer.cc b/cc/content_layer.cc new file mode 100644 index 0000000..ee8277b --- /dev/null +++ b/cc/content_layer.cc @@ -0,0 +1,113 @@ +// Copyright 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#if USE(ACCELERATED_COMPOSITING) + +#include "ContentLayerChromium.h" + +#include "base/time.h" +#include "BitmapCanvasLayerTextureUpdater.h" +#include "BitmapSkPictureCanvasLayerTextureUpdater.h" +#include "CCLayerTreeHost.h" +#include "CCSettings.h" +#include "ContentLayerChromiumClient.h" +#include "FrameBufferSkPictureCanvasLayerTextureUpdater.h" +#include "LayerPainterChromium.h" +#include + +namespace cc { + +ContentLayerPainter::ContentLayerPainter(ContentLayerChromiumClient* client) + : m_client(client) +{ +} + +PassOwnPtr ContentLayerPainter::create(ContentLayerChromiumClient* client) +{ + return adoptPtr(new ContentLayerPainter(client)); +} + +void ContentLayerPainter::paint(SkCanvas* canvas, const IntRect& contentRect, FloatRect& opaque) +{ + base::TimeTicks paintStart = base::TimeTicks::HighResNow(); + m_client->paintContents(canvas, contentRect, opaque); + base::TimeTicks paintEnd = base::TimeTicks::HighResNow(); + double pixelsPerSec = (contentRect.width() * contentRect.height()) / (paintEnd - paintStart).InSecondsF(); + WebKit::Platform::current()->histogramCustomCounts("Renderer4.AccelContentPaintDurationMS", (paintEnd - paintStart).InMillisecondsF(), 0, 120, 30); + WebKit::Platform::current()->histogramCustomCounts("Renderer4.AccelContentPaintMegapixPerSecond", pixelsPerSec / 1000000, 10, 210, 30); +} + +scoped_refptr ContentLayerChromium::create(ContentLayerChromiumClient* client) +{ + return make_scoped_refptr(new ContentLayerChromium(client)); +} + +ContentLayerChromium::ContentLayerChromium(ContentLayerChromiumClient* client) + : TiledLayerChromium() + , m_client(client) +{ +} + +ContentLayerChromium::~ContentLayerChromium() +{ +} + +bool ContentLayerChromium::drawsContent() const +{ + return TiledLayerChromium::drawsContent() && m_client; +} + +void ContentLayerChromium::setTexturePriorities(const CCPriorityCalculator& priorityCalc) +{ + // Update the tile data before creating all the layer's tiles. + updateTileSizeAndTilingOption(); + + TiledLayerChromium::setTexturePriorities(priorityCalc); +} + +void ContentLayerChromium::update(CCTextureUpdateQueue& queue, const CCOcclusionTracker* occlusion, CCRenderingStats& stats) +{ + createTextureUpdaterIfNeeded(); + TiledLayerChromium::update(queue, occlusion, stats); + m_needsDisplay = false; +} + +bool ContentLayerChromium::needMoreUpdates() +{ + return needsIdlePaint(); +} + +LayerTextureUpdater* ContentLayerChromium::textureUpdater() const +{ + return m_textureUpdater.get(); +} + +void ContentLayerChromium::createTextureUpdaterIfNeeded() +{ + if (m_textureUpdater) + return; + if (layerTreeHost()->settings().acceleratePainting) + m_textureUpdater = FrameBufferSkPictureCanvasLayerTextureUpdater::create(ContentLayerPainter::create(m_client)); + else if (CCSettings::perTilePaintingEnabled()) + m_textureUpdater = BitmapSkPictureCanvasLayerTextureUpdater::create(ContentLayerPainter::create(m_client)); + else + m_textureUpdater = BitmapCanvasLayerTextureUpdater::create(ContentLayerPainter::create(m_client)); + m_textureUpdater->setOpaque(contentsOpaque()); + + GC3Denum textureFormat = layerTreeHost()->rendererCapabilities().bestTextureFormat; + setTextureFormat(textureFormat); + setSampledTexelFormat(textureUpdater()->sampledTexelFormat(textureFormat)); +} + +void ContentLayerChromium::setContentsOpaque(bool opaque) +{ + LayerChromium::setContentsOpaque(opaque); + if (m_textureUpdater) + m_textureUpdater->setOpaque(opaque); +} + +} +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/cc/content_layer.h b/cc/content_layer.h index 638cbb2..b8ac462 100644 --- a/cc/content_layer.h +++ b/cc/content_layer.h @@ -1,3 +1,67 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. +// Copyright 2010 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + + +#ifndef ContentLayerChromium_h +#define ContentLayerChromium_h + +#if USE(ACCELERATED_COMPOSITING) + +#include "base/basictypes.h" +#include "LayerPainterChromium.h" +#include "TiledLayerChromium.h" + +class SkCanvas; + +namespace cc { + +class ContentLayerChromiumClient; +class FloatRect; +class IntRect; +class LayerTextureUpdater; + +class ContentLayerPainter : public LayerPainterChromium { +public: + static PassOwnPtr create(ContentLayerChromiumClient*); + + virtual void paint(SkCanvas*, const IntRect& contentRect, FloatRect& opaque) OVERRIDE; + +private: + explicit ContentLayerPainter(ContentLayerChromiumClient*); + + ContentLayerChromiumClient* m_client; + + DISALLOW_COPY_AND_ASSIGN(ContentLayerPainter); +}; + +// A layer that renders its contents into an SkCanvas. +class ContentLayerChromium : public TiledLayerChromium { +public: + static scoped_refptr create(ContentLayerChromiumClient*); + + void clearClient() { m_client = 0; } + + virtual bool drawsContent() const OVERRIDE; + virtual void setTexturePriorities(const CCPriorityCalculator&) OVERRIDE; + virtual void update(CCTextureUpdateQueue&, const CCOcclusionTracker*, CCRenderingStats&) OVERRIDE; + virtual bool needMoreUpdates() OVERRIDE; + + virtual void setContentsOpaque(bool) OVERRIDE; + +protected: + explicit ContentLayerChromium(ContentLayerChromiumClient*); + virtual ~ContentLayerChromium(); + +private: + virtual LayerTextureUpdater* textureUpdater() const OVERRIDE; + virtual void createTextureUpdaterIfNeeded() OVERRIDE; + + ContentLayerChromiumClient* m_client; + RefPtr m_textureUpdater; +}; + +} +#endif // USE(ACCELERATED_COMPOSITING) + +#endif diff --git a/cc/content_layer_client.h b/cc/content_layer_client.h index 638cbb2..54a9267 100644 --- a/cc/content_layer_client.h +++ b/cc/content_layer_client.h @@ -1,3 +1,24 @@ // Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef ContentLayerChromiumClient_h +#define ContentLayerChromiumClient_h + +class SkCanvas; + +namespace cc { +class FloatRect; +class IntRect; + +class ContentLayerChromiumClient { +public: + virtual void paintContents(SkCanvas*, const IntRect& clip, FloatRect& opaque) = 0; + +protected: + virtual ~ContentLayerChromiumClient() { } +}; + +} + +#endif // ContentLayerChromiumClient_h diff --git a/cc/damage_tracker.cc b/cc/damage_tracker.cc new file mode 100644 index 0000000..bd1c31f --- /dev/null +++ b/cc/damage_tracker.cc @@ -0,0 +1,349 @@ +// Copyright 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#if USE(ACCELERATED_COMPOSITING) + +#include "CCDamageTracker.h" + +#include "CCLayerImpl.h" +#include "CCLayerTreeHostCommon.h" +#include "CCMathUtil.h" +#include "CCRenderSurface.h" +#include + +using WebKit::WebTransformationMatrix; + +namespace cc { + +scoped_ptr CCDamageTracker::create() +{ + return make_scoped_ptr(new CCDamageTracker()); +} + +CCDamageTracker::CCDamageTracker() + : m_forceFullDamageNextUpdate(false), + m_currentRectHistory(new RectMap), + m_nextRectHistory(new RectMap) +{ +} + +CCDamageTracker::~CCDamageTracker() +{ +} + +static inline void expandRectWithFilters(FloatRect& rect, const WebKit::WebFilterOperations& filters) +{ + int top, right, bottom, left; + filters.getOutsets(top, right, bottom, left); + rect.move(-left, -top); + rect.expand(left + right, top + bottom); +} + +static inline void expandDamageRectInsideRectWithFilters(FloatRect& damageRect, const FloatRect& preFilterRect, const WebKit::WebFilterOperations& filters) +{ + FloatRect expandedDamageRect = damageRect; + expandRectWithFilters(expandedDamageRect, filters); + FloatRect filterRect = preFilterRect; + expandRectWithFilters(filterRect, filters); + + expandedDamageRect.intersect(filterRect); + damageRect.unite(expandedDamageRect); +} + +void CCDamageTracker::updateDamageTrackingState(const std::vector& layerList, int targetSurfaceLayerID, bool targetSurfacePropertyChangedOnlyFromDescendant, const IntRect& targetSurfaceContentRect, CCLayerImpl* targetSurfaceMaskLayer, const WebKit::WebFilterOperations& filters) +{ + // + // This function computes the "damage rect" of a target surface, and updates the state + // that is used to correctly track damage across frames. The damage rect is the region + // of the surface that may have changed and needs to be redrawn. This can be used to + // scissor what is actually drawn, to save GPU computation and bandwidth. + // + // The surface's damage rect is computed as the union of all possible changes that + // have happened to the surface since the last frame was drawn. This includes: + // - any changes for existing layers/surfaces that contribute to the target surface + // - layers/surfaces that existed in the previous frame, but no longer exist. + // + // The basic algorithm for computing the damage region is as follows: + // + // 1. compute damage caused by changes in active/new layers + // for each layer in the layerList: + // if the layer is actually a renderSurface: + // add the surface's damage to our target surface. + // else + // add the layer's damage to the target surface. + // + // 2. compute damage caused by the target surface's mask, if it exists. + // + // 3. compute damage caused by old layers/surfaces that no longer exist + // for each leftover layer: + // add the old layer/surface bounds to the target surface damage. + // + // 4. combine all partial damage rects to get the full damage rect. + // + // Additional important points: + // + // - This algorithm is implicitly recursive; it assumes that descendant surfaces have + // already computed their damage. + // + // - Changes to layers/surfaces indicate "damage" to the target surface; If a layer is + // not changed, it does NOT mean that the layer can skip drawing. All layers that + // overlap the damaged region still need to be drawn. For example, if a layer + // changed its opacity, then layers underneath must be re-drawn as well, even if + // they did not change. + // + // - If a layer/surface property changed, the old bounds and new bounds may overlap... + // i.e. some of the exposed region may not actually be exposing anything. But this + // does not artificially inflate the damage rect. If the layer changed, its entire + // old bounds would always need to be redrawn, regardless of how much it overlaps + // with the layer's new bounds, which also need to be entirely redrawn. + // + // - See comments in the rest of the code to see what exactly is considered a "change" + // in a layer/surface. + // + // - To correctly manage exposed rects, two RectMaps are maintained: + // + // 1. The "current" map contains all the layer bounds that contributed to the + // previous frame (even outside the previous damaged area). If a layer changes + // or does not exist anymore, those regions are then exposed and damage the + // target surface. As the algorithm progresses, entries are removed from the + // map until it has only leftover layers that no longer exist. + // + // 2. The "next" map starts out empty, and as the algorithm progresses, every + // layer/surface that contributes to the surface is added to the map. + // + // 3. After the damage rect is computed, the two maps are swapped, so that the + // damage tracker is ready for the next frame. + // + + // These functions cannot be bypassed with early-exits, even if we know what the + // damage will be for this frame, because we need to update the damage tracker state + // to correctly track the next frame. + FloatRect damageFromActiveLayers = trackDamageFromActiveLayers(layerList, targetSurfaceLayerID); + FloatRect damageFromSurfaceMask = trackDamageFromSurfaceMask(targetSurfaceMaskLayer); + FloatRect damageFromLeftoverRects = trackDamageFromLeftoverRects(); + + FloatRect damageRectForThisUpdate; + + if (m_forceFullDamageNextUpdate || targetSurfacePropertyChangedOnlyFromDescendant) { + damageRectForThisUpdate = targetSurfaceContentRect; + m_forceFullDamageNextUpdate = false; + } else { + // FIXME: can we clamp this damage to the surface's content rect? (affects performance, but not correctness) + damageRectForThisUpdate = damageFromActiveLayers; + damageRectForThisUpdate.uniteIfNonZero(damageFromSurfaceMask); + damageRectForThisUpdate.uniteIfNonZero(damageFromLeftoverRects); + + if (filters.hasFilterThatMovesPixels()) + expandRectWithFilters(damageRectForThisUpdate, filters); + } + + // Damage accumulates until we are notified that we actually did draw on that frame. + m_currentDamageRect.uniteIfNonZero(damageRectForThisUpdate); + + // The next history map becomes the current map for the next frame. Note this must + // happen every frame to correctly track changes, even if damage accumulates over + // multiple frames before actually being drawn. + swap(m_currentRectHistory, m_nextRectHistory); +} + +FloatRect CCDamageTracker::removeRectFromCurrentFrame(int layerID, bool& layerIsNew) +{ + layerIsNew = !m_currentRectHistory->contains(layerID); + + // take() will remove the entry from the map, or if not found, return a default (empty) rect. + return m_currentRectHistory->take(layerID); +} + +void CCDamageTracker::saveRectForNextFrame(int layerID, const FloatRect& targetSpaceRect) +{ + // This layer should not yet exist in next frame's history. + ASSERT(layerID > 0); + ASSERT(m_nextRectHistory->find(layerID) == m_nextRectHistory->end()); + m_nextRectHistory->set(layerID, targetSpaceRect); +} + +FloatRect CCDamageTracker::trackDamageFromActiveLayers(const std::vector& layerList, int targetSurfaceLayerID) +{ + FloatRect damageRect = FloatRect(); + + for (unsigned layerIndex = 0; layerIndex < layerList.size(); ++layerIndex) { + // Visit layers in back-to-front order. + CCLayerImpl* layer = layerList[layerIndex]; + + if (CCLayerTreeHostCommon::renderSurfaceContributesToTarget(layer, targetSurfaceLayerID)) + extendDamageForRenderSurface(layer, damageRect); + else + extendDamageForLayer(layer, damageRect); + } + + return damageRect; +} + +FloatRect CCDamageTracker::trackDamageFromSurfaceMask(CCLayerImpl* targetSurfaceMaskLayer) +{ + FloatRect damageRect = FloatRect(); + + if (!targetSurfaceMaskLayer) + return damageRect; + + // Currently, if there is any change to the mask, we choose to damage the entire + // surface. This could potentially be optimized later, but it is not expected to be a + // common case. + if (targetSurfaceMaskLayer->layerPropertyChanged() || !targetSurfaceMaskLayer->updateRect().isEmpty()) + damageRect = FloatRect(FloatPoint::zero(), FloatSize(targetSurfaceMaskLayer->bounds())); + + return damageRect; +} + +FloatRect CCDamageTracker::trackDamageFromLeftoverRects() +{ + // After computing damage for all active layers, any leftover items in the current + // rect history correspond to layers/surfaces that no longer exist. So, these regions + // are now exposed on the target surface. + + FloatRect damageRect = FloatRect(); + + for (RectMap::iterator it = m_currentRectHistory->begin(); it != m_currentRectHistory->end(); ++it) +#if WTF_NEW_HASHMAP_ITERATORS_INTERFACE + damageRect.unite(it->value); +#else + damageRect.unite(it->second); +#endif + + m_currentRectHistory->clear(); + + return damageRect; +} + +static bool layerNeedsToRedrawOntoItsTargetSurface(CCLayerImpl* layer) +{ + // If the layer does NOT own a surface but has SurfacePropertyChanged, + // this means that its target surface is affected and needs to be redrawn. + // However, if the layer DOES own a surface, then the SurfacePropertyChanged + // flag should not be used here, because that flag represents whether the + // layer's surface has changed. + if (layer->renderSurface()) + return layer->layerPropertyChanged(); + return layer->layerPropertyChanged() || layer->layerSurfacePropertyChanged(); +} + +void CCDamageTracker::extendDamageForLayer(CCLayerImpl* layer, FloatRect& targetDamageRect) +{ + // There are two ways that a layer can damage a region of the target surface: + // 1. Property change (e.g. opacity, position, transforms): + // - the entire region of the layer itself damages the surface. + // - the old layer region also damages the surface, because this region is now exposed. + // - note that in many cases the old and new layer rects may overlap, which is fine. + // + // 2. Repaint/update: If a region of the layer that was repainted/updated, that + // region damages the surface. + // + // Property changes take priority over update rects. + // + // This method is called when we want to consider how a layer contributes to its + // targetRenderSurface, even if that layer owns the targetRenderSurface itself. + // To consider how a layer's targetSurface contributes to the ancestorSurface, + // extendDamageForRenderSurface() must be called instead. + + bool layerIsNew = false; + FloatRect oldRectInTargetSpace = removeRectFromCurrentFrame(layer->id(), layerIsNew); + + FloatRect rectInTargetSpace = CCMathUtil::mapClippedRect(layer->drawTransform(), FloatRect(FloatPoint::zero(), layer->contentBounds())); + saveRectForNextFrame(layer->id(), rectInTargetSpace); + + if (layerIsNew || layerNeedsToRedrawOntoItsTargetSurface(layer)) { + // If a layer is new or has changed, then its entire layer rect affects the target surface. + targetDamageRect.uniteIfNonZero(rectInTargetSpace); + + // The layer's old region is now exposed on the target surface, too. + // Note oldRectInTargetSpace is already in target space. + targetDamageRect.uniteIfNonZero(oldRectInTargetSpace); + } else if (!layer->updateRect().isEmpty()) { + // If the layer properties havent changed, then the the target surface is only + // affected by the layer's update area, which could be empty. + FloatRect updateContentRect = layer->updateRect(); + float widthScale = layer->contentBounds().width() / static_cast(layer->bounds().width()); + float heightScale = layer->contentBounds().height() / static_cast(layer->bounds().height()); + updateContentRect.scale(widthScale, heightScale); + + FloatRect updateRectInTargetSpace = CCMathUtil::mapClippedRect(layer->drawTransform(), updateContentRect); + targetDamageRect.uniteIfNonZero(updateRectInTargetSpace); + } +} + +void CCDamageTracker::extendDamageForRenderSurface(CCLayerImpl* layer, FloatRect& targetDamageRect) +{ + // There are two ways a "descendant surface" can damage regions of the "target surface": + // 1. Property change: + // - a surface's geometry can change because of + // - changes to descendants (i.e. the subtree) that affect the surface's content rect + // - changes to ancestor layers that propagate their property changes to their entire subtree. + // - just like layers, both the old surface rect and new surface rect will + // damage the target surface in this case. + // + // 2. Damage rect: This surface may have been damaged by its own layerList as well, and that damage + // should propagate to the target surface. + // + + CCRenderSurface* renderSurface = layer->renderSurface(); + + bool surfaceIsNew = false; + FloatRect oldSurfaceRect = removeRectFromCurrentFrame(layer->id(), surfaceIsNew); + + FloatRect surfaceRectInTargetSpace = renderSurface->drawableContentRect(); // already includes replica if it exists. + saveRectForNextFrame(layer->id(), surfaceRectInTargetSpace); + + FloatRect damageRectInLocalSpace; + if (surfaceIsNew || renderSurface->surfacePropertyChanged() || layer->layerSurfacePropertyChanged()) { + // The entire surface contributes damage. + damageRectInLocalSpace = renderSurface->contentRect(); + + // The surface's old region is now exposed on the target surface, too. + targetDamageRect.uniteIfNonZero(oldSurfaceRect); + } else { + // Only the surface's damageRect will damage the target surface. + damageRectInLocalSpace = renderSurface->damageTracker()->currentDamageRect(); + } + + // If there was damage, transform it to target space, and possibly contribute its reflection if needed. + if (!damageRectInLocalSpace.isEmpty()) { + const WebTransformationMatrix& drawTransform = renderSurface->drawTransform(); + FloatRect damageRectInTargetSpace = CCMathUtil::mapClippedRect(drawTransform, damageRectInLocalSpace); + targetDamageRect.uniteIfNonZero(damageRectInTargetSpace); + + if (layer->replicaLayer()) { + const WebTransformationMatrix& replicaDrawTransform = renderSurface->replicaDrawTransform(); + targetDamageRect.uniteIfNonZero(CCMathUtil::mapClippedRect(replicaDrawTransform, damageRectInLocalSpace)); + } + } + + // If there was damage on the replica's mask, then the target surface receives that damage as well. + if (layer->replicaLayer() && layer->replicaLayer()->maskLayer()) { + CCLayerImpl* replicaMaskLayer = layer->replicaLayer()->maskLayer(); + + bool replicaIsNew = false; + removeRectFromCurrentFrame(replicaMaskLayer->id(), replicaIsNew); + + const WebTransformationMatrix& replicaDrawTransform = renderSurface->replicaDrawTransform(); + FloatRect replicaMaskLayerRect = CCMathUtil::mapClippedRect(replicaDrawTransform, FloatRect(FloatPoint::zero(), FloatSize(replicaMaskLayer->bounds().width(), replicaMaskLayer->bounds().height()))); + saveRectForNextFrame(replicaMaskLayer->id(), replicaMaskLayerRect); + + // In the current implementation, a change in the replica mask damages the entire replica region. + if (replicaIsNew || replicaMaskLayer->layerPropertyChanged() || !replicaMaskLayer->updateRect().isEmpty()) + targetDamageRect.uniteIfNonZero(replicaMaskLayerRect); + } + + // If the layer has a background filter, this may cause pixels in our surface to be expanded, so we will need to expand any damage + // at or below this layer. We expand the damage from this layer too, as we need to readback those pixels from the surface with only + // the contents of layers below this one in them. This means we need to redraw any pixels in the surface being used for the blur in + // this layer this frame. + if (layer->backgroundFilters().hasFilterThatMovesPixels()) + expandDamageRectInsideRectWithFilters(targetDamageRect, surfaceRectInTargetSpace, layer->backgroundFilters()); +} + +} // namespace cc + +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/cc/damage_tracker.h b/cc/damage_tracker.h index 638cbb2..c7550a2 100644 --- a/cc/damage_tracker.h +++ b/cc/damage_tracker.h @@ -1,3 +1,63 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. +// Copyright 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CCDamageTracker_h +#define CCDamageTracker_h + +#include "base/memory/scoped_ptr.h" +#include "FloatRect.h" +#include +#include +#include + +namespace WebKit { +class WebFilterOperations; +} + +namespace cc { + +class CCLayerImpl; +class CCRenderSurface; + +// Computes the region where pixels have actually changed on a RenderSurface. This region is used +// to scissor what is actually drawn to the screen to save GPU computation and bandwidth. +class CCDamageTracker { +public: + static scoped_ptr create(); + ~CCDamageTracker(); + + void didDrawDamagedArea() { m_currentDamageRect = FloatRect(); } + void forceFullDamageNextUpdate() { m_forceFullDamageNextUpdate = true; } + void updateDamageTrackingState(const std::vector& layerList, int targetSurfaceLayerID, bool targetSurfacePropertyChangedOnlyFromDescendant, const IntRect& targetSurfaceContentRect, CCLayerImpl* targetSurfaceMaskLayer, const WebKit::WebFilterOperations&); + + const FloatRect& currentDamageRect() { return m_currentDamageRect; } + +private: + CCDamageTracker(); + + FloatRect trackDamageFromActiveLayers(const std::vector& layerList, int targetSurfaceLayerID); + FloatRect trackDamageFromSurfaceMask(CCLayerImpl* targetSurfaceMaskLayer); + FloatRect trackDamageFromLeftoverRects(); + + FloatRect removeRectFromCurrentFrame(int layerID, bool& layerIsNew); + void saveRectForNextFrame(int layerID, const FloatRect& targetSpaceRect); + + // These helper functions are used only in trackDamageFromActiveLayers(). + void extendDamageForLayer(CCLayerImpl*, FloatRect& targetDamageRect); + void extendDamageForRenderSurface(CCLayerImpl*, FloatRect& targetDamageRect); + + // To correctly track exposed regions, two hashtables of rects are maintained. + // The "current" map is used to compute exposed regions of the current frame, while + // the "next" map is used to collect layer rects that are used in the next frame. + typedef HashMap RectMap; + scoped_ptr m_currentRectHistory; + scoped_ptr m_nextRectHistory; + + FloatRect m_currentDamageRect; + bool m_forceFullDamageNextUpdate; +}; + +} // namespace cc + +#endif // CCDamageTracker_h diff --git a/cc/debug_border_draw_quad.cc b/cc/debug_border_draw_quad.cc new file mode 100644 index 0000000..aabf9e2 --- /dev/null +++ b/cc/debug_border_draw_quad.cc @@ -0,0 +1,32 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#include "CCDebugBorderDrawQuad.h" + +namespace cc { + +scoped_ptr CCDebugBorderDrawQuad::create(const CCSharedQuadState* sharedQuadState, const IntRect& quadRect, SkColor color, int width) +{ + return make_scoped_ptr(new CCDebugBorderDrawQuad(sharedQuadState, quadRect, color, width)); +} + +CCDebugBorderDrawQuad::CCDebugBorderDrawQuad(const CCSharedQuadState* sharedQuadState, const IntRect& quadRect, SkColor color, int width) + : CCDrawQuad(sharedQuadState, CCDrawQuad::DebugBorder, quadRect) + , m_color(color) + , m_width(width) +{ + m_quadOpaque = false; + if (SkColorGetA(m_color) < 255) + m_needsBlending = true; +} + +const CCDebugBorderDrawQuad* CCDebugBorderDrawQuad::materialCast(const CCDrawQuad* quad) +{ + ASSERT(quad->material() == CCDrawQuad::DebugBorder); + return static_cast(quad); +} + +} // namespace cc diff --git a/cc/debug_border_draw_quad.h b/cc/debug_border_draw_quad.h index 638cbb2..fbba1c6 100644 --- a/cc/debug_border_draw_quad.h +++ b/cc/debug_border_draw_quad.h @@ -1,3 +1,35 @@ // Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CCDebugBorderDrawQuad_h +#define CCDebugBorderDrawQuad_h + +#include "CCDrawQuad.h" +#include "SkColor.h" +#include "base/memory/scoped_ptr.h" + +namespace cc { + +#pragma pack(push, 4) + +class CCDebugBorderDrawQuad : public CCDrawQuad { +public: + static scoped_ptr create(const CCSharedQuadState*, const IntRect&, SkColor, int width); + + SkColor color() const { return m_color; }; + int width() const { return m_width; } + + static const CCDebugBorderDrawQuad* materialCast(const CCDrawQuad*); +private: + CCDebugBorderDrawQuad(const CCSharedQuadState*, const IntRect&, SkColor, int width); + + SkColor m_color; + int m_width; +}; + +#pragma pack(pop) + +} + +#endif diff --git a/cc/debug_rect_history.cc b/cc/debug_rect_history.cc new file mode 100644 index 0000000..7f3c2ea --- /dev/null +++ b/cc/debug_rect_history.cc @@ -0,0 +1,120 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#if USE(ACCELERATED_COMPOSITING) +#include "CCDebugRectHistory.h" + +#include "CCDamageTracker.h" +#include "CCLayerImpl.h" +#include "CCLayerTreeHost.h" +#include "CCMathUtil.h" + +namespace cc { + +CCDebugRectHistory::CCDebugRectHistory() +{ +} + +CCDebugRectHistory::~CCDebugRectHistory() +{ +} + +void CCDebugRectHistory::saveDebugRectsForCurrentFrame(CCLayerImpl* rootLayer, const std::vector& renderSurfaceLayerList, const Vector& occludingScreenSpaceRects, const CCLayerTreeSettings& settings) +{ + // For now, clear all rects from previous frames. In the future we may want to store + // all debug rects for a history of many frames. + m_debugRects.clear(); + + if (settings.showPaintRects) + savePaintRects(rootLayer); + + if (settings.showPropertyChangedRects) + savePropertyChangedRects(renderSurfaceLayerList); + + if (settings.showSurfaceDamageRects) + saveSurfaceDamageRects(renderSurfaceLayerList); + + if (settings.showScreenSpaceRects) + saveScreenSpaceRects(renderSurfaceLayerList); + + if (settings.showOccludingRects) + saveOccludingRects(occludingScreenSpaceRects); +} + + +void CCDebugRectHistory::savePaintRects(CCLayerImpl* layer) +{ + // We would like to visualize where any layer's paint rect (update rect) has changed, + // regardless of whether this layer is skipped for actual drawing or not. Therefore + // we traverse recursively over all layers, not just the render surface list. + + if (!layer->updateRect().isEmpty() && layer->drawsContent()) { + FloatRect updateContentRect = layer->updateRect(); + updateContentRect.scale(layer->contentBounds().width() / static_cast(layer->bounds().width()), layer->contentBounds().height() / static_cast(layer->bounds().height())); + m_debugRects.append(CCDebugRect(PaintRectType, CCMathUtil::mapClippedRect(layer->screenSpaceTransform(), updateContentRect))); + } + + for (unsigned i = 0; i < layer->children().size(); ++i) + savePaintRects(layer->children()[i]); +} + +void CCDebugRectHistory::savePropertyChangedRects(const std::vector& renderSurfaceLayerList) +{ + for (int surfaceIndex = renderSurfaceLayerList.size() - 1; surfaceIndex >= 0 ; --surfaceIndex) { + CCLayerImpl* renderSurfaceLayer = renderSurfaceLayerList[surfaceIndex]; + CCRenderSurface* renderSurface = renderSurfaceLayer->renderSurface(); + ASSERT(renderSurface); + + const std::vector& layerList = renderSurface->layerList(); + for (unsigned layerIndex = 0; layerIndex < layerList.size(); ++layerIndex) { + CCLayerImpl* layer = layerList[layerIndex]; + + if (CCLayerTreeHostCommon::renderSurfaceContributesToTarget(layer, renderSurfaceLayer->id())) + continue; + + if (layer->layerIsAlwaysDamaged()) + continue; + + if (layer->layerPropertyChanged() || layer->layerSurfacePropertyChanged()) + m_debugRects.append(CCDebugRect(PropertyChangedRectType, CCMathUtil::mapClippedRect(layer->screenSpaceTransform(), FloatRect(FloatPoint::zero(), layer->contentBounds())))); + } + } +} + +void CCDebugRectHistory::saveSurfaceDamageRects(const std::vector& renderSurfaceLayerList) +{ + for (int surfaceIndex = renderSurfaceLayerList.size() - 1; surfaceIndex >= 0 ; --surfaceIndex) { + CCLayerImpl* renderSurfaceLayer = renderSurfaceLayerList[surfaceIndex]; + CCRenderSurface* renderSurface = renderSurfaceLayer->renderSurface(); + ASSERT(renderSurface); + + m_debugRects.append(CCDebugRect(SurfaceDamageRectType, CCMathUtil::mapClippedRect(renderSurface->screenSpaceTransform(), renderSurface->damageTracker()->currentDamageRect()))); + } +} + +void CCDebugRectHistory::saveScreenSpaceRects(const std::vector& renderSurfaceLayerList) +{ + for (int surfaceIndex = renderSurfaceLayerList.size() - 1; surfaceIndex >= 0 ; --surfaceIndex) { + CCLayerImpl* renderSurfaceLayer = renderSurfaceLayerList[surfaceIndex]; + CCRenderSurface* renderSurface = renderSurfaceLayer->renderSurface(); + ASSERT(renderSurface); + + m_debugRects.append(CCDebugRect(ScreenSpaceRectType, CCMathUtil::mapClippedRect(renderSurface->screenSpaceTransform(), renderSurface->contentRect()))); + + if (renderSurfaceLayer->replicaLayer()) + m_debugRects.append(CCDebugRect(ReplicaScreenSpaceRectType, CCMathUtil::mapClippedRect(renderSurface->replicaScreenSpaceTransform(), renderSurface->contentRect()))); + } +} + +void CCDebugRectHistory::saveOccludingRects(const Vector& occludingRects) +{ + for (size_t i = 0; i < occludingRects.size(); ++i) + m_debugRects.append(CCDebugRect(OccludingRectType, occludingRects[i])); +} + +} // namespace cc + +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/cc/debug_rect_history.h b/cc/debug_rect_history.h index 638cbb2..1b03f34 100644 --- a/cc/debug_rect_history.h +++ b/cc/debug_rect_history.h @@ -1,3 +1,87 @@ // Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CCDebugRectHistory_h +#define CCDebugRectHistory_h + +#if USE(ACCELERATED_COMPOSITING) + +#include "base/basictypes.h" +#include "FloatRect.h" +#include "IntRect.h" +#include +#include +#include + +namespace cc { + +class CCLayerImpl; +struct CCLayerTreeSettings; + +// There are currently six types of debug rects: +// +// - Paint rects (update rects): regions of a layer that needed to be re-uploaded to the +// texture resource; in most cases implying that they had to be repainted, too. +// +// - Property-changed rects: enclosing bounds of layers that cause changes to the screen +// even if the layer did not change internally. (For example, if the layer's opacity or +// position changes.) +// +// - Surface damage rects: the aggregate damage on a target surface that is caused by all +// layers and surfaces that contribute to it. This includes (1) paint rects, (2) property- +// changed rects, and (3) newly exposed areas. +// +// - Screen space rects: this is the region the contents occupy in screen space. +// +// - Replica screen space rects: this is the region the replica's contents occupy in screen space. +// +// - Occluding rects: these are the regions that contribute to the occluded region. +// +enum DebugRectType { PaintRectType, PropertyChangedRectType, SurfaceDamageRectType, ScreenSpaceRectType, ReplicaScreenSpaceRectType, OccludingRectType }; + +struct CCDebugRect { + CCDebugRect(DebugRectType newType, FloatRect newRect) + : type(newType) + , rect(newRect) { } + + DebugRectType type; + FloatRect rect; +}; + +// This class maintains a history of rects of various types that can be used +// for debugging purposes. The overhead of collecting rects is performed only if +// the appropriate CCLayerTreeSettings are enabled. +class CCDebugRectHistory { +public: + static PassOwnPtr create() + { + return adoptPtr(new CCDebugRectHistory()); + } + + ~CCDebugRectHistory(); + + // Note: Saving debug rects must happen before layers' change tracking is reset. + void saveDebugRectsForCurrentFrame(CCLayerImpl* rootLayer, const std::vector& renderSurfaceLayerList, const Vector& occludingScreenSpaceRects, const CCLayerTreeSettings&); + + const Vector& debugRects() { return m_debugRects; } + +private: + CCDebugRectHistory(); + + void savePaintRects(CCLayerImpl*); + void savePropertyChangedRects(const std::vector& renderSurfaceLayerList); + void saveSurfaceDamageRects(const std::vector& renderSurfaceLayerList); + void saveScreenSpaceRects(const std::vector& renderSurfaceLayerList); + void saveOccludingRects(const Vector& occludingScreenSpaceRects); + + Vector m_debugRects; + + DISALLOW_COPY_AND_ASSIGN(CCDebugRectHistory); +}; + +} // namespace cc + +#endif // USE(ACCELERATED_COMPOSITING) + +#endif diff --git a/cc/delay_based_time_source.cc b/cc/delay_based_time_source.cc new file mode 100644 index 0000000..6e34a07 --- /dev/null +++ b/cc/delay_based_time_source.cc @@ -0,0 +1,232 @@ +// Copyright 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#include "CCDelayBasedTimeSource.h" + +#include "TraceEvent.h" +#include +#include +#include + +namespace cc { + +namespace { + +// doubleTickThreshold prevents ticks from running within the specified fraction of an interval. +// This helps account for jitter in the timebase as well as quick timer reactivation. +const double doubleTickThreshold = 0.25; + +// intervalChangeThreshold is the fraction of the interval that will trigger an immediate interval change. +// phaseChangeThreshold is the fraction of the interval that will trigger an immediate phase change. +// If the changes are within the thresholds, the change will take place on the next tick. +// If either change is outside the thresholds, the next tick will be canceled and reissued immediately. +const double intervalChangeThreshold = 0.25; +const double phaseChangeThreshold = 0.25; + +} + + +PassRefPtr CCDelayBasedTimeSource::create(base::TimeDelta interval, CCThread* thread) +{ + return adoptRef(new CCDelayBasedTimeSource(interval, thread)); +} + +CCDelayBasedTimeSource::CCDelayBasedTimeSource(base::TimeDelta interval, CCThread* thread) + : m_client(0) + , m_hasTickTarget(false) + , m_currentParameters(interval, base::TimeTicks()) + , m_nextParameters(interval, base::TimeTicks()) + , m_state(STATE_INACTIVE) + , m_timer(thread, this) +{ + turnOffVerifier(); +} + +CCDelayBasedTimeSource::~CCDelayBasedTimeSource() +{ +} + +void CCDelayBasedTimeSource::setActive(bool active) +{ + TRACE_EVENT1("cc", "CCDelayBasedTimeSource::setActive", "active", active); + if (!active) { + m_state = STATE_INACTIVE; + m_timer.stop(); + return; + } + + if (m_state == STATE_STARTING || m_state == STATE_ACTIVE) + return; + + if (!m_hasTickTarget) { + // Becoming active the first time is deferred: we post a 0-delay task. When + // it runs, we use that to establish the timebase, become truly active, and + // fire the first tick. + m_state = STATE_STARTING; + m_timer.startOneShot(0); + return; + } + + m_state = STATE_ACTIVE; + + postNextTickTask(now()); +} + +bool CCDelayBasedTimeSource::active() const +{ + return m_state != STATE_INACTIVE; +} + +base::TimeTicks CCDelayBasedTimeSource::lastTickTime() +{ + return m_lastTickTime; +} + +base::TimeTicks CCDelayBasedTimeSource::nextTickTime() +{ + return active() ? m_currentParameters.tickTarget : base::TimeTicks(); +} + +void CCDelayBasedTimeSource::onTimerFired() +{ + ASSERT(m_state != STATE_INACTIVE); + + base::TimeTicks now = this->now(); + m_lastTickTime = now; + + if (m_state == STATE_STARTING) { + setTimebaseAndInterval(now, m_currentParameters.interval); + m_state = STATE_ACTIVE; + } + + postNextTickTask(now); + + // Fire the tick + if (m_client) + m_client->onTimerTick(); +} + +void CCDelayBasedTimeSource::setClient(CCTimeSourceClient* client) +{ + m_client = client; +} + +void CCDelayBasedTimeSource::setTimebaseAndInterval(base::TimeTicks timebase, base::TimeDelta interval) +{ + m_nextParameters.interval = interval; + m_nextParameters.tickTarget = timebase; + m_hasTickTarget = true; + + if (m_state != STATE_ACTIVE) { + // If we aren't active, there's no need to reset the timer. + return; + } + + // If the change in interval is larger than the change threshold, + // request an immediate reset. + double intervalDelta = std::abs((interval - m_currentParameters.interval).InSecondsF()); + double intervalChange = intervalDelta / interval.InSecondsF(); + if (intervalChange > intervalChangeThreshold) { + setActive(false); + setActive(true); + return; + } + + // If the change in phase is greater than the change threshold in either + // direction, request an immediate reset. This logic might result in a false + // negative if there is a simultaneous small change in the interval and the + // fmod just happens to return something near zero. Assuming the timebase + // is very recent though, which it should be, we'll still be ok because the + // old clock and new clock just happen to line up. + double targetDelta = std::abs((timebase - m_currentParameters.tickTarget).InSecondsF()); + double phaseChange = fmod(targetDelta, interval.InSecondsF()) / interval.InSecondsF(); + if (phaseChange > phaseChangeThreshold && phaseChange < (1.0 - phaseChangeThreshold)) { + setActive(false); + setActive(true); + return; + } +} + +base::TimeTicks CCDelayBasedTimeSource::now() const +{ + return base::TimeTicks::Now(); +} + +// This code tries to achieve an average tick rate as close to m_interval as possible. +// To do this, it has to deal with a few basic issues: +// 1. postDelayedTask can delay only at a millisecond granularity. So, 16.666 has to +// posted as 16 or 17. +// 2. A delayed task may come back a bit late (a few ms), or really late (frames later) +// +// The basic idea with this scheduler here is to keep track of where we *want* to run in +// m_tickTarget. We update this with the exact interval. +// +// Then, when we post our task, we take the floor of (m_tickTarget and now()). If we +// started at now=0, and 60FPs (all times in milliseconds): +// now=0 target=16.667 postDelayedTask(16) +// +// When our callback runs, we figure out how far off we were from that goal. Because of the flooring +// operation, and assuming our timer runs exactly when it should, this yields: +// now=16 target=16.667 +// +// Since we can't post a 0.667 ms task to get to now=16, we just treat this as a tick. Then, +// we update target to be 33.333. We now post another task based on the difference between our target +// and now: +// now=16 tickTarget=16.667 newTarget=33.333 --> postDelayedTask(floor(33.333 - 16)) --> postDelayedTask(17) +// +// Over time, with no late tasks, this leads to us posting tasks like this: +// now=0 tickTarget=0 newTarget=16.667 --> tick(), postDelayedTask(16) +// now=16 tickTarget=16.667 newTarget=33.333 --> tick(), postDelayedTask(17) +// now=33 tickTarget=33.333 newTarget=50.000 --> tick(), postDelayedTask(17) +// now=50 tickTarget=50.000 newTarget=66.667 --> tick(), postDelayedTask(16) +// +// We treat delays in tasks differently depending on the amount of delay we encounter. Suppose we +// posted a task with a target=16.667: +// Case 1: late but not unrecoverably-so +// now=18 tickTarget=16.667 +// +// Case 2: so late we obviously missed the tick +// now=25.0 tickTarget=16.667 +// +// We treat the first case as a tick anyway, and assume the delay was +// unusual. Thus, we compute the newTarget based on the old timebase: +// now=18 tickTarget=16.667 newTarget=33.333 --> tick(), postDelayedTask(floor(33.333-18)) --> postDelayedTask(15) +// This brings us back to 18+15 = 33, which was where we would have been if the task hadn't been late. +// +// For the really late delay, we we move to the next logical tick. The timebase is not reset. +// now=37 tickTarget=16.667 newTarget=50.000 --> tick(), postDelayedTask(floor(50.000-37)) --> postDelayedTask(13) +base::TimeTicks CCDelayBasedTimeSource::nextTickTarget(base::TimeTicks now) +{ + base::TimeDelta newInterval = m_nextParameters.interval; + int intervalsElapsed = static_cast(floor((now - m_nextParameters.tickTarget).InSecondsF() / newInterval.InSecondsF())); + base::TimeTicks lastEffectiveTick = m_nextParameters.tickTarget + newInterval * intervalsElapsed; + base::TimeTicks newTickTarget = lastEffectiveTick + newInterval; + ASSERT(newTickTarget > now); + + // Avoid double ticks when: + // 1) Turning off the timer and turning it right back on. + // 2) Jittery data is passed to setTimebaseAndInterval(). + if (newTickTarget - m_lastTickTime <= newInterval / static_cast(1.0 / doubleTickThreshold)) + newTickTarget += newInterval; + + return newTickTarget; +} + +void CCDelayBasedTimeSource::postNextTickTask(base::TimeTicks now) +{ + base::TimeTicks newTickTarget = nextTickTarget(now); + + // Post another task *before* the tick and update state + base::TimeDelta delay = newTickTarget - now; + ASSERT(delay.InMillisecondsF() <= + m_nextParameters.interval.InMillisecondsF() * (1.0 + doubleTickThreshold)); + m_timer.startOneShot(delay.InSecondsF()); + + m_nextParameters.tickTarget = newTickTarget; + m_currentParameters = m_nextParameters; +} + +} diff --git a/cc/delay_based_time_source.h b/cc/delay_based_time_source.h index 638cbb2..bf183f7 100644 --- a/cc/delay_based_time_source.h +++ b/cc/delay_based_time_source.h @@ -1,3 +1,79 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. +// Copyright 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CCDelayBasedTimeSource_h +#define CCDelayBasedTimeSource_h + +#include "CCTimeSource.h" +#include "CCTimer.h" +#include + +namespace cc { + +class CCThread; + +// This timer implements a time source that achieves the specified interval +// in face of millisecond-precision delayed callbacks and random queueing delays. +class CCDelayBasedTimeSource : public CCTimeSource, CCTimerClient { +public: + static PassRefPtr create(base::TimeDelta interval, CCThread*); + + virtual ~CCDelayBasedTimeSource(); + + virtual void setClient(CCTimeSourceClient* client) OVERRIDE; + + // CCTimeSource implementation + virtual void setTimebaseAndInterval(base::TimeTicks timebase, base::TimeDelta interval) OVERRIDE; + + virtual void setActive(bool) OVERRIDE; + virtual bool active() const OVERRIDE; + + // Get the last and next tick times. nextTimeTime() returns null when + // inactive. + virtual base::TimeTicks lastTickTime() OVERRIDE; + virtual base::TimeTicks nextTickTime() OVERRIDE; + + // CCTimerClient implementation. + virtual void onTimerFired() OVERRIDE; + + // Virtual for testing. + virtual base::TimeTicks now() const; + +protected: + CCDelayBasedTimeSource(base::TimeDelta interval, CCThread*); + base::TimeTicks nextTickTarget(base::TimeTicks now); + void postNextTickTask(base::TimeTicks now); + + enum State { + STATE_INACTIVE, + STATE_STARTING, + STATE_ACTIVE, + }; + + struct Parameters { + Parameters(base::TimeDelta interval, base::TimeTicks tickTarget) + : interval(interval), tickTarget(tickTarget) + { } + base::TimeDelta interval; + base::TimeTicks tickTarget; + }; + + CCTimeSourceClient* m_client; + bool m_hasTickTarget; + base::TimeTicks m_lastTickTime; + + // m_currentParameters should only be written by postNextTickTask. + // m_nextParameters will take effect on the next call to postNextTickTask. + // Maintaining a pending set of parameters allows nextTickTime() to always + // reflect the actual time we expect onTimerFired to be called. + Parameters m_currentParameters; + Parameters m_nextParameters; + + State m_state; + CCThread* m_thread; + CCTimer m_timer; +}; + +} +#endif // CCDelayBasedTimeSource_h diff --git a/cc/delegated_renderer_layer.cc b/cc/delegated_renderer_layer.cc new file mode 100644 index 0000000..721630d --- /dev/null +++ b/cc/delegated_renderer_layer.cc @@ -0,0 +1,33 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "DelegatedRendererLayerChromium.h" + +#include "CCDelegatedRendererLayerImpl.h" + +namespace cc { + +scoped_refptr DelegatedRendererLayerChromium::create() +{ + return scoped_refptr(new DelegatedRendererLayerChromium()); +} + +DelegatedRendererLayerChromium::DelegatedRendererLayerChromium() + : LayerChromium() +{ + setIsDrawable(true); + setMasksToBounds(true); +} + +DelegatedRendererLayerChromium::~DelegatedRendererLayerChromium() +{ +} + +scoped_ptr DelegatedRendererLayerChromium::createCCLayerImpl() +{ + return CCDelegatedRendererLayerImpl::create(m_layerId).PassAs(); +} + +} diff --git a/cc/delegated_renderer_layer.h b/cc/delegated_renderer_layer.h index 638cbb2..c7f8d2c 100644 --- a/cc/delegated_renderer_layer.h +++ b/cc/delegated_renderer_layer.h @@ -1,3 +1,26 @@ // Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef DelegatedRendererLayerChromium_h +#define DelegatedRendererLayerChromium_h + +#include "LayerChromium.h" + +namespace cc { + +class DelegatedRendererLayerChromium : public LayerChromium { +public: + static scoped_refptr create(); + + virtual scoped_ptr createCCLayerImpl() OVERRIDE; + +protected: + DelegatedRendererLayerChromium(); + +private: + virtual ~DelegatedRendererLayerChromium(); +}; + +} +#endif diff --git a/cc/delegated_renderer_layer_impl.cc b/cc/delegated_renderer_layer_impl.cc new file mode 100644 index 0000000..02d5698 --- /dev/null +++ b/cc/delegated_renderer_layer_impl.cc @@ -0,0 +1,185 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#include "CCDelegatedRendererLayerImpl.h" + +#include "CCAppendQuadsData.h" +#include "CCQuadSink.h" +#include "CCMathUtil.h" +#include "CCRenderPassDrawQuad.h" +#include "CCRenderPassSink.h" + +namespace cc { + +CCDelegatedRendererLayerImpl::CCDelegatedRendererLayerImpl(int id) + : CCLayerImpl(id) +{ +} + +CCDelegatedRendererLayerImpl::~CCDelegatedRendererLayerImpl() +{ + clearRenderPasses(); +} + +bool CCDelegatedRendererLayerImpl::descendantDrawsContent() +{ + // FIXME: This could possibly return false even though there are some + // quads present as they could all be from a single layer (or set of + // layers without children). If this happens, then make a test that + // ensures the opacity is being changed on quads in the root RenderPass + // when this layer doesn't own a RenderSurface. + return !m_renderPassesInDrawOrder.isEmpty(); +} + +bool CCDelegatedRendererLayerImpl::hasContributingDelegatedRenderPasses() const +{ + // The root RenderPass for the layer is merged with its target + // RenderPass in each frame. So we only have extra RenderPasses + // to merge when we have a non-root RenderPass present. + return m_renderPassesInDrawOrder.size() > 1; +} + +void CCDelegatedRendererLayerImpl::setRenderPasses(ScopedPtrVector& renderPassesInDrawOrder) +{ + FloatRect oldRootDamage; + if (!m_renderPassesInDrawOrder.isEmpty()) + oldRootDamage = m_renderPassesInDrawOrder.last()->damageRect(); + + clearRenderPasses(); + + for (size_t i = 0; i < renderPassesInDrawOrder.size(); ++i) { + m_renderPassesIndexById.insert(std::pair(renderPassesInDrawOrder[i]->id(), i)); + m_renderPassesInDrawOrder.append(renderPassesInDrawOrder.take(i)); + } + renderPassesInDrawOrder.clear(); + + if (!m_renderPassesInDrawOrder.isEmpty()) { + FloatRect newRootDamage = m_renderPassesInDrawOrder.last()->damageRect(); + m_renderPassesInDrawOrder.last()->setDamageRect(unionRect(oldRootDamage, newRootDamage)); + } +} + +void CCDelegatedRendererLayerImpl::clearRenderPasses() +{ + // FIXME: Release the resources back to the nested compositor. + m_renderPassesIndexById.clear(); + m_renderPassesInDrawOrder.clear(); +} + +void CCDelegatedRendererLayerImpl::didLoseContext() +{ + clearRenderPasses(); +} + +static inline int indexToId(int index) { return index + 1; } +static inline int idToIndex(int id) { return id - 1; } + +CCRenderPass::Id CCDelegatedRendererLayerImpl::firstContributingRenderPassId() const +{ + return CCRenderPass::Id(id(), indexToId(0)); +} + +CCRenderPass::Id CCDelegatedRendererLayerImpl::nextContributingRenderPassId(CCRenderPass::Id previous) const +{ + return CCRenderPass::Id(previous.layerId, previous.index + 1); +} + +CCRenderPass::Id CCDelegatedRendererLayerImpl::convertDelegatedRenderPassId(CCRenderPass::Id delegatedRenderPassId) const +{ + base::hash_map::const_iterator it = m_renderPassesIndexById.find(delegatedRenderPassId); + ASSERT(it != m_renderPassesIndexById.end()); + unsigned delegatedRenderPassIndex = it->second; + return CCRenderPass::Id(id(), indexToId(delegatedRenderPassIndex)); +} + +void CCDelegatedRendererLayerImpl::appendContributingRenderPasses(CCRenderPassSink& renderPassSink) +{ + ASSERT(hasContributingDelegatedRenderPasses()); + + for (size_t i = 0; i < m_renderPassesInDrawOrder.size() - 1; ++i) { + CCRenderPass::Id outputRenderPassId = convertDelegatedRenderPassId(m_renderPassesInDrawOrder[i]->id()); + + // Don't clash with the RenderPass we generate if we own a RenderSurface. + ASSERT(outputRenderPassId.index > 0); + + renderPassSink.appendRenderPass(m_renderPassesInDrawOrder[i]->copy(outputRenderPassId)); + } +} + +void CCDelegatedRendererLayerImpl::appendQuads(CCQuadSink& quadSink, CCAppendQuadsData& appendQuadsData) +{ + if (m_renderPassesInDrawOrder.isEmpty()) + return; + + CCRenderPass::Id targetRenderPassId = appendQuadsData.renderPassId; + + // If the index of the renderPassId is 0, then it is a renderPass generated for a layer + // in this compositor, not the delegated renderer. Then we want to merge our root renderPass with + // the target renderPass. Otherwise, it is some renderPass which we added from the delegated + // renderer. + bool shouldMergeRootRenderPassWithTarget = !targetRenderPassId.index; + if (shouldMergeRootRenderPassWithTarget) { + // Verify that the renderPass we are appending to is created our renderTarget. + ASSERT(targetRenderPassId.layerId == renderTarget()->id()); + + CCRenderPass* rootDelegatedRenderPass = m_renderPassesInDrawOrder.last(); + appendRenderPassQuads(quadSink, appendQuadsData, rootDelegatedRenderPass); + } else { + // Verify that the renderPass we are appending to was created by us. + ASSERT(targetRenderPassId.layerId == id()); + + int renderPassIndex = idToIndex(targetRenderPassId.index); + CCRenderPass* delegatedRenderPass = m_renderPassesInDrawOrder[renderPassIndex]; + appendRenderPassQuads(quadSink, appendQuadsData, delegatedRenderPass); + } +} + +void CCDelegatedRendererLayerImpl::appendRenderPassQuads(CCQuadSink& quadSink, CCAppendQuadsData& appendQuadsData, CCRenderPass* delegatedRenderPass) const +{ + const CCSharedQuadState* currentSharedQuadState = 0; + CCSharedQuadState* copiedSharedQuadState = 0; + for (size_t i = 0; i < delegatedRenderPass->quadList().size(); ++i) { + CCDrawQuad* quad = delegatedRenderPass->quadList()[i]; + + if (quad->sharedQuadState() != currentSharedQuadState) { + currentSharedQuadState = quad->sharedQuadState(); + copiedSharedQuadState = quadSink.useSharedQuadState(currentSharedQuadState->copy()); + bool targetIsFromDelegatedRendererLayer = appendQuadsData.renderPassId.layerId == id(); + if (!targetIsFromDelegatedRendererLayer) { + // Should be the root render pass. + ASSERT(delegatedRenderPass == m_renderPassesInDrawOrder.last()); + // This layer must be drawing to a renderTarget other than itself. + ASSERT(renderTarget() != this); + + copiedSharedQuadState->clippedRectInTarget = CCMathUtil::mapClippedRect(drawTransform(), copiedSharedQuadState->clippedRectInTarget); + copiedSharedQuadState->quadTransform = copiedSharedQuadState->quadTransform * drawTransform(); + copiedSharedQuadState->opacity *= drawOpacity(); + } + } + ASSERT(copiedSharedQuadState); + + scoped_ptr copyQuad; + if (quad->material() != CCDrawQuad::RenderPass) + copyQuad = quad->copy(copiedSharedQuadState); + else { + CCRenderPass::Id contributingDelegatedRenderPassId = CCRenderPassDrawQuad::materialCast(quad)->renderPassId(); + CCRenderPass::Id contributingRenderPassId = convertDelegatedRenderPassId(contributingDelegatedRenderPassId); + ASSERT(contributingRenderPassId != appendQuadsData.renderPassId); + + copyQuad = CCRenderPassDrawQuad::materialCast(quad)->copy(copiedSharedQuadState, contributingRenderPassId).PassAs(); + } + ASSERT(copyQuad.get()); + + quadSink.append(copyQuad.Pass(), appendQuadsData); + } +} + +const char* CCDelegatedRendererLayerImpl::layerTypeAsString() const +{ + return "DelegatedRendererLayer"; +} + +} diff --git a/cc/delegated_renderer_layer_impl.h b/cc/delegated_renderer_layer_impl.h index 638cbb2..4ed842e 100644 --- a/cc/delegated_renderer_layer_impl.h +++ b/cc/delegated_renderer_layer_impl.h @@ -1,3 +1,50 @@ // Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CCDelegatedRendererLayerImpl_h +#define CCDelegatedRendererLayerImpl_h + +#include "CCLayerImpl.h" +#include "cc/scoped_ptr_vector.h" + +namespace cc { + +class CCDelegatedRendererLayerImpl : public CCLayerImpl { +public: + static scoped_ptr create(int id) { return make_scoped_ptr(new CCDelegatedRendererLayerImpl(id)); } + virtual ~CCDelegatedRendererLayerImpl(); + + virtual bool descendantDrawsContent() OVERRIDE; + virtual bool hasContributingDelegatedRenderPasses() const OVERRIDE; + + // This gives ownership of the RenderPasses to the layer. + void setRenderPasses(ScopedPtrVector&); + void clearRenderPasses(); + + virtual void didLoseContext() OVERRIDE; + + virtual CCRenderPass::Id firstContributingRenderPassId() const OVERRIDE; + virtual CCRenderPass::Id nextContributingRenderPassId(CCRenderPass::Id) const OVERRIDE; + + void appendContributingRenderPasses(CCRenderPassSink&); + virtual void appendQuads(CCQuadSink&, CCAppendQuadsData&) OVERRIDE; + +private: + explicit CCDelegatedRendererLayerImpl(int); + + CCRenderPass::Id convertDelegatedRenderPassId(CCRenderPass::Id delegatedRenderPassId) const; + + void appendRenderPassQuads(CCQuadSink&, CCAppendQuadsData&, CCRenderPass* fromDelegatedRenderPass) const; + + PassOwnPtr createCopyOfQuad(const CCDrawQuad*); + + virtual const char* layerTypeAsString() const OVERRIDE; + + ScopedPtrVector m_renderPassesInDrawOrder; + base::hash_map m_renderPassesIndexById; +}; + +} + +#endif // CCDelegatedRendererLayerImpl_h diff --git a/cc/direct_renderer.cc b/cc/direct_renderer.cc new file mode 100644 index 0000000..23fa1d3 --- /dev/null +++ b/cc/direct_renderer.cc @@ -0,0 +1,237 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#include "CCDirectRenderer.h" + +#include "CCMathUtil.h" +#include +#include + +using WebKit::WebTransformationMatrix; + +static WebTransformationMatrix orthoProjectionMatrix(float left, float right, float bottom, float top) +{ + // Use the standard formula to map the clipping frustum to the cube from + // [-1, -1, -1] to [1, 1, 1]. + float deltaX = right - left; + float deltaY = top - bottom; + WebTransformationMatrix proj; + if (!deltaX || !deltaY) + return proj; + proj.setM11(2.0f / deltaX); + proj.setM41(-(right + left) / deltaX); + proj.setM22(2.0f / deltaY); + proj.setM42(-(top + bottom) / deltaY); + + // Z component of vertices is always set to zero as we don't use the depth buffer + // while drawing. + proj.setM33(0); + + return proj; +} + +static WebTransformationMatrix windowMatrix(int x, int y, int width, int height) +{ + WebTransformationMatrix canvas; + + // Map to window position and scale up to pixel coordinates. + canvas.translate3d(x, y, 0); + canvas.scale3d(width, height, 0); + + // Map from ([-1, -1] to [1, 1]) -> ([0, 0] to [1, 1]) + canvas.translate3d(0.5, 0.5, 0.5); + canvas.scale3d(0.5, 0.5, 0.5); + + return canvas; +} + +namespace cc { + +CCDirectRenderer::DrawingFrame::DrawingFrame() + : rootRenderPass(0) + , currentRenderPass(0) + , currentTexture(0) + , flippedY(false) +{ +} + +CCDirectRenderer::DrawingFrame::~DrawingFrame() +{ +} + +// +// static +FloatRect CCDirectRenderer::quadVertexRect() +{ + return FloatRect(-0.5, -0.5, 1, 1); +} + +// static +void CCDirectRenderer::quadRectTransform(WebKit::WebTransformationMatrix* quadRectTransform, const WebKit::WebTransformationMatrix& quadTransform, const FloatRect& quadRect) +{ + *quadRectTransform = quadTransform; + quadRectTransform->translate(0.5 * quadRect.width() + quadRect.x(), 0.5 * quadRect.height() + quadRect.y()); + quadRectTransform->scaleNonUniform(quadRect.width(), quadRect.height()); +} + +// static +void CCDirectRenderer::initializeMatrices(DrawingFrame& frame, const IntRect& drawRect, bool flipY) +{ + if (flipY) + frame.projectionMatrix = orthoProjectionMatrix(drawRect.x(), drawRect.maxX(), drawRect.maxY(), drawRect.y()); + else + frame.projectionMatrix = orthoProjectionMatrix(drawRect.x(), drawRect.maxX(), drawRect.y(), drawRect.maxY()); + frame.windowMatrix = windowMatrix(0, 0, drawRect.width(), drawRect.height()); + frame.flippedY = flipY; +} + +// static +IntRect CCDirectRenderer::moveScissorToWindowSpace(const DrawingFrame& frame, FloatRect scissorRect) +{ + IntRect scissorRectInCanvasSpace = enclosingIntRect(scissorRect); + // The scissor coordinates must be supplied in viewport space so we need to offset + // by the relative position of the top left corner of the current render pass. + IntRect framebufferOutputRect = frame.currentRenderPass->outputRect(); + scissorRectInCanvasSpace.setX(scissorRectInCanvasSpace.x() - framebufferOutputRect.x()); + if (frame.flippedY && !frame.currentTexture) + scissorRectInCanvasSpace.setY(framebufferOutputRect.height() - (scissorRectInCanvasSpace.maxY() - framebufferOutputRect.y())); + else + scissorRectInCanvasSpace.setY(scissorRectInCanvasSpace.y() - framebufferOutputRect.y()); + return scissorRectInCanvasSpace; +} + +CCDirectRenderer::CCDirectRenderer(CCRendererClient* client, CCResourceProvider* resourceProvider) + : CCRenderer(client) + , m_resourceProvider(resourceProvider) +{ +} + +CCDirectRenderer::~CCDirectRenderer() +{ +} + +void CCDirectRenderer::decideRenderPassAllocationsForFrame(const CCRenderPassList& renderPassesInDrawOrder) +{ + base::hash_map renderPassesInFrame; + for (size_t i = 0; i < renderPassesInDrawOrder.size(); ++i) + renderPassesInFrame.insert(std::pair(renderPassesInDrawOrder[i]->id(), renderPassesInDrawOrder[i])); + + std::vector passesToDelete; + ScopedPtrHashMap::const_iterator passIterator; + for (passIterator = m_renderPassTextures.begin(); passIterator != m_renderPassTextures.end(); ++passIterator) { + base::hash_map::const_iterator it = renderPassesInFrame.find(passIterator->first); + if (it == renderPassesInFrame.end()) { + passesToDelete.push_back(passIterator->first); + continue; + } + + const CCRenderPass* renderPassInFrame = it->second; + const IntSize& requiredSize = renderPassTextureSize(renderPassInFrame); + GC3Denum requiredFormat = renderPassTextureFormat(renderPassInFrame); + CachedTexture* texture = passIterator->second; + ASSERT(texture); + + if (texture->id() && (texture->size() != requiredSize || texture->format() != requiredFormat)) + texture->free(); + } + + // Delete RenderPass textures from the previous frame that will not be used again. + for (size_t i = 0; i < passesToDelete.size(); ++i) + m_renderPassTextures.erase(passesToDelete[i]); + + for (size_t i = 0; i < renderPassesInDrawOrder.size(); ++i) { + if (!m_renderPassTextures.contains(renderPassesInDrawOrder[i]->id())) { + scoped_ptr texture = CachedTexture::create(m_resourceProvider); + m_renderPassTextures.set(renderPassesInDrawOrder[i]->id(), texture.Pass()); + } + } +} + +void CCDirectRenderer::drawFrame(const CCRenderPassList& renderPassesInDrawOrder, const CCRenderPassIdHashMap& renderPassesById) +{ + const CCRenderPass* rootRenderPass = renderPassesInDrawOrder.back(); + ASSERT(rootRenderPass); + + DrawingFrame frame; + frame.renderPassesById = &renderPassesById; + frame.rootRenderPass = rootRenderPass; + frame.rootDamageRect = capabilities().usingPartialSwap ? rootRenderPass->damageRect() : rootRenderPass->outputRect(); + frame.rootDamageRect.intersect(IntRect(IntPoint::zero(), viewportSize())); + + beginDrawingFrame(frame); + for (size_t i = 0; i < renderPassesInDrawOrder.size(); ++i) + drawRenderPass(frame, renderPassesInDrawOrder[i]); + finishDrawingFrame(frame); +} + +void CCDirectRenderer::drawRenderPass(DrawingFrame& frame, const CCRenderPass* renderPass) +{ + if (!useRenderPass(frame, renderPass)) + return; + + frame.scissorRectInRenderPassSpace = frame.currentRenderPass->outputRect(); + if (frame.rootDamageRect != frame.rootRenderPass->outputRect()) { + WebTransformationMatrix inverseTransformToRoot = frame.currentRenderPass->transformToRootTarget().inverse(); + frame.scissorRectInRenderPassSpace.intersect(CCMathUtil::projectClippedRect(inverseTransformToRoot, frame.rootDamageRect)); + } + + enableScissorTestRect(moveScissorToWindowSpace(frame, frame.scissorRectInRenderPassSpace)); + clearFramebuffer(frame); + + const CCQuadList& quadList = renderPass->quadList(); + for (CCQuadList::constBackToFrontIterator it = quadList.backToFrontBegin(); it != quadList.backToFrontEnd(); ++it) { + FloatRect quadScissorRect = frame.scissorRectInRenderPassSpace; + quadScissorRect.intersect((*it)->clippedRectInTarget()); + if (!quadScissorRect.isEmpty()) { + enableScissorTestRect(moveScissorToWindowSpace(frame, quadScissorRect)); + drawQuad(frame, *it); + } + } + + CachedTexture* texture = m_renderPassTextures.get(renderPass->id()); + if (texture) + texture->setIsComplete(!renderPass->hasOcclusionFromOutsideTargetSurface()); +} + +bool CCDirectRenderer::useRenderPass(DrawingFrame& frame, const CCRenderPass* renderPass) +{ + frame.currentRenderPass = renderPass; + frame.currentTexture = 0; + + if (renderPass == frame.rootRenderPass) { + bindFramebufferToOutputSurface(frame); + initializeMatrices(frame, renderPass->outputRect(), flippedFramebuffer()); + setDrawViewportSize(renderPass->outputRect().size()); + return true; + } + + CachedTexture* texture = m_renderPassTextures.get(renderPass->id()); + ASSERT(texture); + if (!texture->id() && !texture->allocate(CCRenderer::ImplPool, renderPassTextureSize(renderPass), renderPassTextureFormat(renderPass), CCResourceProvider::TextureUsageFramebuffer)) + return false; + + return bindFramebufferToTexture(frame, texture, renderPass->outputRect()); +} + +bool CCDirectRenderer::haveCachedResourcesForRenderPassId(CCRenderPass::Id id) const +{ + CachedTexture* texture = m_renderPassTextures.get(id); + return texture && texture->id() && texture->isComplete(); +} + +// static +IntSize CCDirectRenderer::renderPassTextureSize(const CCRenderPass* pass) +{ + return pass->outputRect().size(); +} + +// static +GC3Denum CCDirectRenderer::renderPassTextureFormat(const CCRenderPass*) +{ + return GraphicsContext3D::RGBA; +} + +} diff --git a/cc/direct_renderer.h b/cc/direct_renderer.h index 638cbb2..73e6dc6 100644 --- a/cc/direct_renderer.h +++ b/cc/direct_renderer.h @@ -1,3 +1,105 @@ // Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CCDirectRenderer_h +#define CCDirectRenderer_h + +#include "base/basictypes.h" +#include "CCRenderer.h" +#include "CCResourceProvider.h" +#include "CCScopedTexture.h" + +namespace cc { + +class CCResourceProvider; + +// This is the base class for code shared between the GL and software +// renderer implementations. "Direct" refers to the fact that it does not +// delegate rendering to another compositor. +class CCDirectRenderer : public CCRenderer { +public: + virtual ~CCDirectRenderer(); + + CCResourceProvider* resourceProvider() const { return m_resourceProvider; } + + virtual void decideRenderPassAllocationsForFrame(const CCRenderPassList& renderPassesInDrawOrder) OVERRIDE; + virtual bool haveCachedResourcesForRenderPassId(CCRenderPass::Id) const OVERRIDE; + virtual void drawFrame(const CCRenderPassList& renderPassesInDrawOrder, const CCRenderPassIdHashMap& renderPassesById) OVERRIDE; + +protected: + CCDirectRenderer(CCRendererClient* client, CCResourceProvider* resourceProvider); + + struct DrawingFrame { + DrawingFrame(); + ~DrawingFrame(); + + const CCRenderPassIdHashMap* renderPassesById; + const CCRenderPass* rootRenderPass; + const CCRenderPass* currentRenderPass; + const CCScopedTexture* currentTexture; + + FloatRect rootDamageRect; + + WebKit::WebTransformationMatrix projectionMatrix; + WebKit::WebTransformationMatrix windowMatrix; + bool flippedY; + FloatRect scissorRectInRenderPassSpace; + }; + + class CachedTexture : public CCScopedTexture { + public: + static scoped_ptr create(CCResourceProvider* resourceProvider) { + return make_scoped_ptr(new CachedTexture(resourceProvider)); + } + virtual ~CachedTexture() {} + + bool isComplete() const { return m_isComplete; } + void setIsComplete(bool isComplete) { m_isComplete = isComplete; } + + protected: + explicit CachedTexture(CCResourceProvider* resourceProvider) + : CCScopedTexture(resourceProvider) + , m_isComplete(false) + { + } + + private: + bool m_isComplete; + + DISALLOW_COPY_AND_ASSIGN(CachedTexture); + }; + + static FloatRect quadVertexRect(); + static void quadRectTransform(WebKit::WebTransformationMatrix* quadRectTransform, const WebKit::WebTransformationMatrix& quadTransform, const FloatRect& quadRect); + static void initializeMatrices(DrawingFrame&, const IntRect& drawRect, bool flipY); + static IntRect moveScissorToWindowSpace(const DrawingFrame&, FloatRect scissorRect); + + bool haveCachedResources(CCRenderPass::Id) const; + static IntSize renderPassTextureSize(const CCRenderPass*); + static GC3Denum renderPassTextureFormat(const CCRenderPass*); + + void drawRenderPass(DrawingFrame&, const CCRenderPass*); + bool useRenderPass(DrawingFrame&, const CCRenderPass*); + + virtual void bindFramebufferToOutputSurface(DrawingFrame&) = 0; + virtual bool bindFramebufferToTexture(DrawingFrame&, const CCScopedTexture*, const IntRect& framebufferRect) = 0; + virtual void setDrawViewportSize(const IntSize&) = 0; + virtual void enableScissorTestRect(const IntRect& scissorRect) = 0; + virtual void disableScissorTest() = 0; + virtual void clearFramebuffer(DrawingFrame&) = 0; + virtual void drawQuad(DrawingFrame&, const CCDrawQuad*) = 0; + virtual void beginDrawingFrame(DrawingFrame&) = 0; + virtual void finishDrawingFrame(DrawingFrame&) = 0; + virtual bool flippedFramebuffer() const = 0; + + ScopedPtrHashMap m_renderPassTextures; + CCResourceProvider* m_resourceProvider; + +private: + DISALLOW_COPY_AND_ASSIGN(CCDirectRenderer); +}; + +} // namespace cc + +#endif // CCDirectRenderer_h diff --git a/cc/draw_quad.cc b/cc/draw_quad.cc new file mode 100644 index 0000000..b88eac6 --- /dev/null +++ b/cc/draw_quad.cc @@ -0,0 +1,100 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "CCDrawQuad.h" + +#include "CCCheckerboardDrawQuad.h" +#include "CCDebugBorderDrawQuad.h" +#include "CCIOSurfaceDrawQuad.h" +#include "CCRenderPassDrawQuad.h" +#include "CCSolidColorDrawQuad.h" +#include "CCStreamVideoDrawQuad.h" +#include "CCTextureDrawQuad.h" +#include "CCTileDrawQuad.h" +#include "CCYUVVideoDrawQuad.h" +#include "IntRect.h" + +namespace cc { + +CCDrawQuad::CCDrawQuad(const CCSharedQuadState* sharedQuadState, Material material, const IntRect& quadRect) + : m_sharedQuadState(sharedQuadState) + , m_sharedQuadStateId(sharedQuadState->id) + , m_material(material) + , m_quadRect(quadRect) + , m_quadVisibleRect(quadRect) + , m_quadOpaque(true) + , m_needsBlending(false) +{ + ASSERT(m_sharedQuadState); + ASSERT(m_material != Invalid); +} + +IntRect CCDrawQuad::opaqueRect() const +{ + if (opacity() != 1) + return IntRect(); + if (m_sharedQuadState->opaque && m_quadOpaque) + return m_quadRect; + return m_opaqueRect; +} + +void CCDrawQuad::setQuadVisibleRect(const IntRect& quadVisibleRect) +{ + IntRect intersection = quadVisibleRect; + intersection.intersect(m_quadRect); + m_quadVisibleRect = intersection; +} + +unsigned CCDrawQuad::size() const +{ + switch (material()) { + case Checkerboard: + return sizeof(CCCheckerboardDrawQuad); + case DebugBorder: + return sizeof(CCDebugBorderDrawQuad); + case IOSurfaceContent: + return sizeof(CCIOSurfaceDrawQuad); + case TextureContent: + return sizeof(CCTextureDrawQuad); + case SolidColor: + return sizeof(CCSolidColorDrawQuad); + case TiledContent: + return sizeof(CCTileDrawQuad); + case StreamVideoContent: + return sizeof(CCStreamVideoDrawQuad); + case RenderPass: + return sizeof(CCRenderPassDrawQuad); + case YUVVideoContent: + return sizeof(CCYUVVideoDrawQuad); + case Invalid: + break; + } + + CRASH(); + return sizeof(CCDrawQuad); +} + +scoped_ptr CCDrawQuad::copy(const CCSharedQuadState* copiedSharedQuadState) const +{ + // RenderPass quads have their own copy() method. + ASSERT(material() != RenderPass); + + unsigned bytes = size(); + ASSERT(bytes); + + scoped_ptr copyQuad(reinterpret_cast(new char[bytes])); + memcpy(copyQuad.get(), this, bytes); + copyQuad->setSharedQuadState(copiedSharedQuadState); + + return copyQuad.Pass(); +} + +void CCDrawQuad::setSharedQuadState(const CCSharedQuadState* sharedQuadState) +{ + m_sharedQuadState = sharedQuadState; + m_sharedQuadStateId = sharedQuadState->id; +} + +} diff --git a/cc/draw_quad.h b/cc/draw_quad.h index 638cbb2..05a6906 100644 --- a/cc/draw_quad.h +++ b/cc/draw_quad.h @@ -1,3 +1,96 @@ // Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CCDrawQuad_h +#define CCDrawQuad_h + +#include "CCSharedQuadState.h" + +namespace cc { + +// WARNING! All CCXYZDrawQuad classes must remain PODs (plain old data). +// They are intended to be "serializable" by copying their raw bytes, so they +// must not contain any non-bit-copyable member variables! +// +// Furthermore, the class members need to be packed so they are aligned +// properly and don't have paddings/gaps, otherwise memory check tools +// like Valgrind will complain about uninitialized memory usage when +// transferring these classes over the wire. +#pragma pack(push, 4) + +// CCDrawQuad is a bag of data used for drawing a quad. Because different +// materials need different bits of per-quad data to render, classes that derive +// from CCDrawQuad store additional data in their derived instance. The Material +// enum is used to "safely" downcast to the derived class. +class CCDrawQuad { +public: + enum Material { + Invalid, + Checkerboard, + DebugBorder, + IOSurfaceContent, + RenderPass, + TextureContent, + SolidColor, + TiledContent, + YUVVideoContent, + StreamVideoContent, + }; + + IntRect quadRect() const { return m_quadRect; } + const WebKit::WebTransformationMatrix& quadTransform() const { return m_sharedQuadState->quadTransform; } + IntRect visibleContentRect() const { return m_sharedQuadState->visibleContentRect; } + IntRect clippedRectInTarget() const { return m_sharedQuadState->clippedRectInTarget; } + float opacity() const { return m_sharedQuadState->opacity; } + // For the purposes of blending, what part of the contents of this quad are opaque? + IntRect opaqueRect() const; + bool needsBlending() const { return m_needsBlending || !opaqueRect().contains(m_quadVisibleRect); } + + // Allows changing the rect that gets drawn to make it smaller. Parameter passed + // in will be clipped to quadRect(). + void setQuadVisibleRect(const IntRect&); + IntRect quadVisibleRect() const { return m_quadVisibleRect; } + bool isDebugQuad() const { return m_material == DebugBorder; } + + Material material() const { return m_material; } + + // Returns transfer size of this object based on the derived class (by + // looking at the material type). + unsigned size() const; + + scoped_ptr copy(const CCSharedQuadState* copiedSharedQuadState) const; + + const CCSharedQuadState* sharedQuadState() const { return m_sharedQuadState; } + int sharedQuadStateId() const { return m_sharedQuadStateId; } + void setSharedQuadState(const CCSharedQuadState*); + +protected: + CCDrawQuad(const CCSharedQuadState*, Material, const IntRect&); + + // Stores state common to a large bundle of quads; kept separate for memory + // efficiency. There is special treatment to reconstruct these pointers + // during serialization. + const CCSharedQuadState* m_sharedQuadState; + int m_sharedQuadStateId; + + Material m_material; + IntRect m_quadRect; + IntRect m_quadVisibleRect; + + // By default, the shared quad state determines whether or not this quad is + // opaque or needs blending. Derived classes can override with these + // variables. + bool m_quadOpaque; + bool m_needsBlending; + + // Be default, this rect is empty. It is used when the shared quad state and above + // variables determine that the quad is not fully opaque but may be partially opaque. + IntRect m_opaqueRect; +}; + +#pragma pack(pop) + +} + +#endif diff --git a/cc/font_atlas.cc b/cc/font_atlas.cc new file mode 100644 index 0000000..8be8b63 --- /dev/null +++ b/cc/font_atlas.cc @@ -0,0 +1,73 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#if USE(ACCELERATED_COMPOSITING) +#include "CCFontAtlas.h" + +#include "base/string_split.h" +#include "ui/gfx/point.h" +#include "CCProxy.h" +#include "SkCanvas.h" +#include + +namespace cc { + +using namespace std; + +CCFontAtlas::CCFontAtlas(SkBitmap bitmap, IntRect asciiToRectTable[128], int fontHeight) + : m_atlas(bitmap) + , m_fontHeight(fontHeight) +{ + for (size_t i = 0; i < 128; ++i) + m_asciiToRectTable[i] = asciiToRectTable[i]; +} + +CCFontAtlas::~CCFontAtlas() +{ +} + +void CCFontAtlas::drawText(SkCanvas* canvas, const SkPaint& paint, const std::string& text, const gfx::Point& destPosition, const IntSize& clip) const +{ + ASSERT(CCProxy::isImplThread()); + + std::vector lines; + base::SplitString(text, '\n', &lines); + + gfx::Point position = destPosition; + for (size_t i = 0; i < lines.size(); ++i) { + drawOneLineOfTextInternal(canvas, paint, lines[i], position); + position.set_y(position.y() + m_fontHeight); + if (position.y() > clip.height()) + return; + } +} + +void CCFontAtlas::drawOneLineOfTextInternal(SkCanvas* canvas, const SkPaint& paint, const std::string& textLine, const gfx::Point& destPosition) const +{ + ASSERT(CCProxy::isImplThread()); + + gfx::Point position = destPosition; + for (unsigned i = 0; i < textLine.length(); ++i) { + // If the ASCII code is out of bounds, then index 0 is used, which is just a plain rectangle glyph. + int asciiIndex = (textLine[i] < 128) ? textLine[i] : 0; + IntRect glyphBounds = m_asciiToRectTable[asciiIndex]; + SkIRect source = SkIRect::MakeXYWH(glyphBounds.x(), glyphBounds.y(), glyphBounds.width(), glyphBounds.height()); + canvas->drawBitmapRect(m_atlas, &source, SkRect::MakeXYWH(position.x(), position.y(), glyphBounds.width(), glyphBounds.height()), &paint); + position.set_x(position.x() + glyphBounds.width()); + } +} + +void CCFontAtlas::drawDebugAtlas(SkCanvas* canvas, const gfx::Point& destPosition) const +{ + ASSERT(CCProxy::isImplThread()); + + SkIRect source = SkIRect::MakeWH(m_atlas.width(), m_atlas.height()); + canvas->drawBitmapRect(m_atlas, &source, SkRect::MakeXYWH(destPosition.x(), destPosition.y(), m_atlas.width(), m_atlas.height())); +} + +} // namespace cc + +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/cc/font_atlas.h b/cc/font_atlas.h index 638cbb2..2881ee9 100644 --- a/cc/font_atlas.h +++ b/cc/font_atlas.h @@ -1,3 +1,70 @@ // Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CCFontAtlas_h +#define CCFontAtlas_h + +#if USE(ACCELERATED_COMPOSITING) + +#include + +#include "base/basictypes.h" +#include "base/memory/scoped_ptr.h" +#include "IntRect.h" +#include "SkBitmap.h" + +class SkCanvas; + +namespace gfx { +class Point; +} + +namespace cc { + +class Color; +class FontDescription; +class GraphicsContext; +class IntSize; + +// This class provides basic ability to draw text onto the heads-up display. +class CCFontAtlas { +public: + static scoped_ptr create(SkBitmap bitmap, IntRect asciiToRectTable[128], int fontHeight) + { + return make_scoped_ptr(new CCFontAtlas(bitmap, asciiToRectTable, fontHeight)); + } + ~CCFontAtlas(); + + // Draws multiple lines of text where each line of text is separated by '\n'. + // - Correct glyphs will be drawn for ASCII codes in the range 32-127; any characters + // outside that range will be displayed as a default rectangle glyph. + // - IntSize clip is used to avoid wasting time drawing things that are outside the + // target canvas bounds. + // - Should only be called only on the impl thread. + void drawText(SkCanvas*, const SkPaint&, const std::string& text, const gfx::Point& destPosition, const IntSize& clip) const; + + // Draws the entire atlas at the specified position, just for debugging purposes. + void drawDebugAtlas(SkCanvas*, const gfx::Point& destPosition) const; + +private: + CCFontAtlas(SkBitmap, IntRect asciiToRectTable[128], int fontHeight); + + void drawOneLineOfTextInternal(SkCanvas*, const SkPaint&, const std::string&, const gfx::Point& destPosition) const; + + // The actual texture atlas containing all the pre-rendered glyphs. + SkBitmap m_atlas; + + // The look-up tables mapping ascii characters to their IntRect locations on the atlas. + IntRect m_asciiToRectTable[128]; + + int m_fontHeight; + + DISALLOW_COPY_AND_ASSIGN(CCFontAtlas); +}; + +} // namespace cc + +#endif // USE(ACCELERATED_COMPOSITING) + +#endif diff --git a/cc/frame_buffer_skpicture_canvas_layer_texture_updater.cc b/cc/frame_buffer_skpicture_canvas_layer_texture_updater.cc new file mode 100644 index 0000000..adfcd07 --- /dev/null +++ b/cc/frame_buffer_skpicture_canvas_layer_texture_updater.cc @@ -0,0 +1,119 @@ +// Copyright 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + +#include "config.h" + +#if USE(ACCELERATED_COMPOSITING) + +#include "FrameBufferSkPictureCanvasLayerTextureUpdater.h" + +#include "CCProxy.h" +#include "LayerPainterChromium.h" +#include "SkCanvas.h" +#include "SkGpuDevice.h" +#include +#include + +using WebKit::WebGraphicsContext3D; +using WebKit::WebSharedGraphicsContext3D; + +namespace cc { + +static PassOwnPtr createAcceleratedCanvas(GrContext* grContext, + IntSize canvasSize, + unsigned textureId) +{ + GrPlatformTextureDesc textureDesc; + textureDesc.fFlags = kRenderTarget_GrPlatformTextureFlag; + textureDesc.fWidth = canvasSize.width(); + textureDesc.fHeight = canvasSize.height(); + textureDesc.fConfig = kSkia8888_GrPixelConfig; + textureDesc.fTextureHandle = textureId; + SkAutoTUnref target(grContext->createPlatformTexture(textureDesc)); + SkAutoTUnref device(new SkGpuDevice(grContext, target.get())); + return adoptPtr(new SkCanvas(device.get())); +} + +FrameBufferSkPictureCanvasLayerTextureUpdater::Texture::Texture(FrameBufferSkPictureCanvasLayerTextureUpdater* textureUpdater, scoped_ptr texture) + : LayerTextureUpdater::Texture(texture.Pass()) + , m_textureUpdater(textureUpdater) +{ +} + +FrameBufferSkPictureCanvasLayerTextureUpdater::Texture::~Texture() +{ +} + +void FrameBufferSkPictureCanvasLayerTextureUpdater::Texture::updateRect(CCResourceProvider* resourceProvider, const IntRect& sourceRect, const IntSize& destOffset) +{ + WebGraphicsContext3D* sharedContext = CCProxy::hasImplThread() ? WebSharedGraphicsContext3D::compositorThreadContext() : WebSharedGraphicsContext3D::mainThreadContext(); + GrContext* sharedGrContext = CCProxy::hasImplThread() ? WebSharedGraphicsContext3D::compositorThreadGrContext() : WebSharedGraphicsContext3D::mainThreadGrContext(); + if (!sharedContext || !sharedGrContext) + return; + textureUpdater()->updateTextureRect(sharedContext, sharedGrContext, resourceProvider, texture(), sourceRect, destOffset); +} + +PassRefPtr FrameBufferSkPictureCanvasLayerTextureUpdater::create(PassOwnPtr painter) +{ + return adoptRef(new FrameBufferSkPictureCanvasLayerTextureUpdater(painter)); +} + +FrameBufferSkPictureCanvasLayerTextureUpdater::FrameBufferSkPictureCanvasLayerTextureUpdater(PassOwnPtr painter) + : SkPictureCanvasLayerTextureUpdater(painter) +{ +} + +FrameBufferSkPictureCanvasLayerTextureUpdater::~FrameBufferSkPictureCanvasLayerTextureUpdater() +{ +} + +PassOwnPtr FrameBufferSkPictureCanvasLayerTextureUpdater::createTexture(CCPrioritizedTextureManager* manager) +{ + return adoptPtr(new Texture(this, CCPrioritizedTexture::create(manager))); +} + +LayerTextureUpdater::SampledTexelFormat FrameBufferSkPictureCanvasLayerTextureUpdater::sampledTexelFormat(GC3Denum textureFormat) +{ + // Here we directly render to the texture, so the component order is always correct. + return LayerTextureUpdater::SampledTexelFormatRGBA; +} + +void FrameBufferSkPictureCanvasLayerTextureUpdater::updateTextureRect(WebGraphicsContext3D* context, GrContext* grContext, CCResourceProvider* resourceProvider, CCPrioritizedTexture* texture, const IntRect& sourceRect, const IntSize& destOffset) +{ + texture->acquireBackingTexture(resourceProvider); + // Flush the context in which the backing texture is created so that it + // is available in other shared contexts. It is important to do here + // because the backing texture is created in one context while it is + // being written to in another. + resourceProvider->flush(); + CCResourceProvider::ScopedWriteLockGL lock(resourceProvider, texture->resourceId()); + + // Make sure ganesh uses the correct GL context. + context->makeContextCurrent(); + // Create an accelerated canvas to draw on. + OwnPtr canvas = createAcceleratedCanvas(grContext, texture->size(), lock.textureId()); + + // The compositor expects the textures to be upside-down so it can flip + // the final composited image. Ganesh renders the image upright so we + // need to do a y-flip. + canvas->translate(0.0, texture->size().height()); + canvas->scale(1.0, -1.0); + // Clip to the destination on the texture that must be updated. + canvas->clipRect(SkRect::MakeXYWH(destOffset.width(), destOffset.height(), sourceRect.width(), sourceRect.height())); + // Translate the origin of contentRect to that of destRect. + // Note that destRect is defined relative to sourceRect. + canvas->translate(contentRect().x() - sourceRect.x() + destOffset.width(), + contentRect().y() - sourceRect.y() + destOffset.height()); + drawPicture(canvas.get()); + + // Flush ganesh context so that all the rendered stuff appears on the texture. + grContext->flush(); + + // Flush the GL context so rendering results from this context are visible in the compositor's context. + context->flush(); +} + +} // namespace cc +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/cc/frame_buffer_skpicture_canvas_layer_texture_updater.h b/cc/frame_buffer_skpicture_canvas_layer_texture_updater.h index 638cbb2..79093f2 100644 --- a/cc/frame_buffer_skpicture_canvas_layer_texture_updater.h +++ b/cc/frame_buffer_skpicture_canvas_layer_texture_updater.h @@ -1,3 +1,52 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. +// Copyright 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + + +#ifndef FrameBufferSkPictureCanvasLayerTextureUpdater_h +#define FrameBufferSkPictureCanvasLayerTextureUpdater_h + +#if USE(ACCELERATED_COMPOSITING) + +#include "SkPictureCanvasLayerTextureUpdater.h" + +class GrContext; + +namespace WebKit { +class WebGraphicsContext3D; +class WebSharedGraphicsContext3D; +} + +namespace cc { + +// This class records the contentRect into an SkPicture, then uses accelerated +// drawing to update the texture. The accelerated drawing goes to an +// intermediate framebuffer and then is copied to the destination texture once done. +class FrameBufferSkPictureCanvasLayerTextureUpdater : public SkPictureCanvasLayerTextureUpdater { +public: + class Texture : public LayerTextureUpdater::Texture { + public: + Texture(FrameBufferSkPictureCanvasLayerTextureUpdater*, scoped_ptr); + virtual ~Texture(); + + virtual void updateRect(CCResourceProvider*, const IntRect& sourceRect, const IntSize& destOffset) OVERRIDE; + + private: + FrameBufferSkPictureCanvasLayerTextureUpdater* textureUpdater() { return m_textureUpdater; } + + FrameBufferSkPictureCanvasLayerTextureUpdater* m_textureUpdater; + }; + + static PassRefPtr create(PassOwnPtr); + virtual ~FrameBufferSkPictureCanvasLayerTextureUpdater(); + + virtual PassOwnPtr createTexture(CCPrioritizedTextureManager*) OVERRIDE; + virtual SampledTexelFormat sampledTexelFormat(GC3Denum textureFormat) OVERRIDE; + void updateTextureRect(WebKit::WebGraphicsContext3D*, GrContext*, CCResourceProvider*, CCPrioritizedTexture*, const IntRect& sourceRect, const IntSize& destOffset); + +private: + explicit FrameBufferSkPictureCanvasLayerTextureUpdater(PassOwnPtr); +}; +} // namespace cc +#endif // USE(ACCELERATED_COMPOSITING) +#endif // FrameBufferSkPictureCanvasLayerTextureUpdater_h diff --git a/cc/frame_rate_controller.cc b/cc/frame_rate_controller.cc new file mode 100644 index 0000000..c996ebd --- /dev/null +++ b/cc/frame_rate_controller.cc @@ -0,0 +1,161 @@ +// Copyright 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#include "CCFrameRateController.h" + +#include "CCDelayBasedTimeSource.h" +#include "CCTimeSource.h" +#include "TraceEvent.h" +#include + +namespace { + +// This will be the maximum number of pending frames unless +// CCFrameRateController::setMaxFramesPending is called. +const int defaultMaxFramesPending = 2; + +} // namespace + +namespace cc { + +class CCFrameRateControllerTimeSourceAdapter : public CCTimeSourceClient { +public: + static scoped_ptr create(CCFrameRateController* frameRateController) { + return make_scoped_ptr(new CCFrameRateControllerTimeSourceAdapter(frameRateController)); + } + virtual ~CCFrameRateControllerTimeSourceAdapter() {} + + virtual void onTimerTick() OVERRIDE { + m_frameRateController->onTimerTick(); + } + +private: + explicit CCFrameRateControllerTimeSourceAdapter(CCFrameRateController* frameRateController) + : m_frameRateController(frameRateController) {} + + CCFrameRateController* m_frameRateController; +}; + +CCFrameRateController::CCFrameRateController(PassRefPtr timer) + : m_client(0) + , m_numFramesPending(0) + , m_maxFramesPending(defaultMaxFramesPending) + , m_timeSource(timer) + , m_active(false) + , m_swapBuffersCompleteSupported(true) + , m_isTimeSourceThrottling(true) +{ + m_timeSourceClientAdapter = CCFrameRateControllerTimeSourceAdapter::create(this); + m_timeSource->setClient(m_timeSourceClientAdapter.get()); +} + +CCFrameRateController::CCFrameRateController(CCThread* thread) + : m_client(0) + , m_numFramesPending(0) + , m_maxFramesPending(defaultMaxFramesPending) + , m_active(false) + , m_swapBuffersCompleteSupported(true) + , m_isTimeSourceThrottling(false) + , m_manualTicker(new CCTimer(thread, this)) +{ +} + +CCFrameRateController::~CCFrameRateController() +{ + if (m_isTimeSourceThrottling) + m_timeSource->setActive(false); +} + +void CCFrameRateController::setActive(bool active) +{ + if (m_active == active) + return; + TRACE_EVENT1("cc", "CCFrameRateController::setActive", "active", active); + m_active = active; + + if (m_isTimeSourceThrottling) + m_timeSource->setActive(active); + else { + if (active) + postManualTick(); + else + m_manualTicker->stop(); + } +} + +void CCFrameRateController::setMaxFramesPending(int maxFramesPending) +{ + ASSERT(maxFramesPending > 0); + m_maxFramesPending = maxFramesPending; +} + +void CCFrameRateController::setTimebaseAndInterval(base::TimeTicks timebase, base::TimeDelta interval) +{ + if (m_isTimeSourceThrottling) + m_timeSource->setTimebaseAndInterval(timebase, interval); +} + +void CCFrameRateController::setSwapBuffersCompleteSupported(bool supported) +{ + m_swapBuffersCompleteSupported = supported; +} + +void CCFrameRateController::onTimerTick() +{ + ASSERT(m_active); + + // Check if we have too many frames in flight. + bool throttled = m_numFramesPending >= m_maxFramesPending; + + if (m_client) + m_client->vsyncTick(throttled); + + if (m_swapBuffersCompleteSupported && !m_isTimeSourceThrottling && m_numFramesPending < m_maxFramesPending) + postManualTick(); +} + +void CCFrameRateController::postManualTick() +{ + if (m_active) + m_manualTicker->startOneShot(0); +} + +void CCFrameRateController::onTimerFired() +{ + onTimerTick(); +} + +void CCFrameRateController::didBeginFrame() +{ + if (m_swapBuffersCompleteSupported) + m_numFramesPending++; + else if (!m_isTimeSourceThrottling) + postManualTick(); +} + +void CCFrameRateController::didFinishFrame() +{ + ASSERT(m_swapBuffersCompleteSupported); + + m_numFramesPending--; + if (!m_isTimeSourceThrottling) + postManualTick(); +} + +void CCFrameRateController::didAbortAllPendingFrames() +{ + m_numFramesPending = 0; +} + +base::TimeTicks CCFrameRateController::nextTickTime() +{ + if (m_isTimeSourceThrottling) + return m_timeSource->nextTickTime(); + + return base::TimeTicks(); +} + +} diff --git a/cc/frame_rate_controller.h b/cc/frame_rate_controller.h index 638cbb2..2aeeae1 100644 --- a/cc/frame_rate_controller.h +++ b/cc/frame_rate_controller.h @@ -1,3 +1,82 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. +// Copyright 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CCFrameRateController_h +#define CCFrameRateController_h + +#include "base/memory/scoped_ptr.h" +#include "base/time.h" +#include "CCTimer.h" +#include +#include + +namespace cc { + +class CCThread; +class CCTimeSource; + +class CCFrameRateControllerClient { +public: + // Throttled is true when we have a maximum number of frames pending. + virtual void vsyncTick(bool throttled) = 0; + +protected: + virtual ~CCFrameRateControllerClient() {} +}; + +class CCFrameRateControllerTimeSourceAdapter; + +class CCFrameRateController : public CCTimerClient { +public: + explicit CCFrameRateController(PassRefPtr); + // Alternate form of CCFrameRateController with unthrottled frame-rate. + explicit CCFrameRateController(CCThread*); + virtual ~CCFrameRateController(); + + void setClient(CCFrameRateControllerClient* client) { m_client = client; } + + void setActive(bool); + + // Use the following methods to adjust target frame rate. + // + // Multiple frames can be in-progress, but for every didBeginFrame, a + // didFinishFrame should be posted. + // + // If the rendering pipeline crashes, call didAbortAllPendingFrames. + void didBeginFrame(); + void didFinishFrame(); + void didAbortAllPendingFrames(); + void setMaxFramesPending(int); // 0 for unlimited. + + // This returns null for unthrottled frame-rate. + base::TimeTicks nextTickTime(); + + void setTimebaseAndInterval(base::TimeTicks timebase, base::TimeDelta interval); + void setSwapBuffersCompleteSupported(bool); + +protected: + friend class CCFrameRateControllerTimeSourceAdapter; + void onTimerTick(); + + void postManualTick(); + + // CCTimerClient implementation (used for unthrottled frame-rate). + virtual void onTimerFired() OVERRIDE; + + CCFrameRateControllerClient* m_client; + int m_numFramesPending; + int m_maxFramesPending; + RefPtr m_timeSource; + scoped_ptr m_timeSourceClientAdapter; + bool m_active; + bool m_swapBuffersCompleteSupported; + + // Members for unthrottled frame-rate. + bool m_isTimeSourceThrottling; + scoped_ptr m_manualTicker; +}; + +} // namespace cc + +#endif // CCFrameRateController_h diff --git a/cc/frame_rate_counter.cc b/cc/frame_rate_counter.cc new file mode 100644 index 0000000..80074ed --- /dev/null +++ b/cc/frame_rate_counter.cc @@ -0,0 +1,132 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#if USE(ACCELERATED_COMPOSITING) +#include "CCFrameRateCounter.h" + +#include + +#include "CCProxy.h" +#include +#include + +namespace cc { + +const double CCFrameRateCounter::kFrameTooFast = 1.0 / 70.0; // measured in seconds +const double CCFrameRateCounter::kFrameTooSlow = 1.0 / 12.0; +const double CCFrameRateCounter::kDroppedFrameTime = 1.0 / 50.0; + +// safeMod works on -1, returning m-1 in that case. +static inline int safeMod(int number, int modulus) +{ + return (number + modulus) % modulus; +} + +inline double CCFrameRateCounter::frameInterval(int frameNumber) const +{ + return m_timeStampHistory[frameIndex(frameNumber)] - + m_timeStampHistory[frameIndex(frameNumber - 1)]; +} + +inline int CCFrameRateCounter::frameIndex(int frameNumber) const +{ + return safeMod(frameNumber, kTimeStampHistorySize); +} + +CCFrameRateCounter::CCFrameRateCounter() + : m_currentFrameNumber(1) + , m_droppedFrameCount(0) +{ + m_timeStampHistory[0] = currentTime(); + m_timeStampHistory[1] = m_timeStampHistory[0]; + for (int i = 2; i < kTimeStampHistorySize; i++) + m_timeStampHistory[i] = 0; +} + +void CCFrameRateCounter::markBeginningOfFrame(double timestamp) +{ + m_timeStampHistory[frameIndex(m_currentFrameNumber)] = timestamp; + double frameIntervalSeconds = frameInterval(m_currentFrameNumber); + + if (CCProxy::hasImplThread() && m_currentFrameNumber > 0) { + double drawDelayMs = frameIntervalSeconds * 1000.0; + WebKit::Platform::current()->histogramCustomCounts("Renderer4.CompositorThreadImplDrawDelay", static_cast(drawDelayMs), 1, 120, 60); + } + + if (!isBadFrameInterval(frameIntervalSeconds) && frameIntervalSeconds > kDroppedFrameTime) + ++m_droppedFrameCount; +} + +void CCFrameRateCounter::markEndOfFrame() +{ + m_currentFrameNumber += 1; +} + +bool CCFrameRateCounter::isBadFrameInterval(double intervalBetweenConsecutiveFrames) const +{ + bool schedulerAllowsDoubleFrames = !CCProxy::hasImplThread(); + bool intervalTooFast = schedulerAllowsDoubleFrames && intervalBetweenConsecutiveFrames < kFrameTooFast; + bool intervalTooSlow = intervalBetweenConsecutiveFrames > kFrameTooSlow; + return intervalTooFast || intervalTooSlow; +} + +bool CCFrameRateCounter::isBadFrame(int frameNumber) const +{ + return isBadFrameInterval(frameInterval(frameNumber)); +} + +void CCFrameRateCounter::getAverageFPSAndStandardDeviation(double& averageFPS, double& standardDeviation) const +{ + int frame = m_currentFrameNumber - 1; + averageFPS = 0; + int averageFPSCount = 0; + double fpsVarianceNumerator = 0; + + // Walk backwards through the samples looking for a run of good frame + // timings from which to compute the mean and standard deviation. + // + // Slow frames occur just because the user is inactive, and should be + // ignored. Fast frames are ignored if the scheduler is in single-thread + // mode in order to represent the true frame rate in spite of the fact that + // the first few swapbuffers happen instantly which skews the statistics + // too much for short lived animations. + // + // isBadFrame encapsulates the frame too slow/frame too fast logic. + while (1) { + if (!isBadFrame(frame)) { + averageFPSCount++; + double secForLastFrame = m_timeStampHistory[frameIndex(frame)] - + m_timeStampHistory[frameIndex(frame - 1)]; + double x = 1.0 / secForLastFrame; + double deltaFromAverage = x - averageFPS; + // Change with caution - numerics. http://en.wikipedia.org/wiki/Standard_deviation + averageFPS = averageFPS + deltaFromAverage / averageFPSCount; + fpsVarianceNumerator = fpsVarianceNumerator + deltaFromAverage * (x - averageFPS); + } + if (averageFPSCount && isBadFrame(frame)) { + // We've gathered a run of good samples, so stop. + break; + } + --frame; + if (frameIndex(frame) == frameIndex(m_currentFrameNumber) || frame < 0) { + // We've gone through all available historical data, so stop. + break; + } + } + + standardDeviation = sqrt(fpsVarianceNumerator / averageFPSCount); +} + +double CCFrameRateCounter::timeStampOfRecentFrame(int n) +{ + ASSERT(n >= 0 && n < kTimeStampHistorySize); + int desiredIndex = (frameIndex(m_currentFrameNumber) + n) % kTimeStampHistorySize; + return m_timeStampHistory[desiredIndex]; +} + +} // namespace cc + +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/cc/frame_rate_counter.h b/cc/frame_rate_counter.h index 638cbb2..76b4224 100644 --- a/cc/frame_rate_counter.h +++ b/cc/frame_rate_counter.h @@ -1,3 +1,72 @@ // Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CCFrameRateCounter_h +#define CCFrameRateCounter_h + +#if USE(ACCELERATED_COMPOSITING) + +#include "base/basictypes.h" +#include + +namespace cc { + +// This class maintains a history of timestamps, and provides functionality to +// intelligently compute average frames per second (and standard deviation). +class CCFrameRateCounter { +public: + static PassOwnPtr create() + { + return adoptPtr(new CCFrameRateCounter()); + } + + void markBeginningOfFrame(double timestamp); + void markEndOfFrame(); + int currentFrameNumber() const { return m_currentFrameNumber; } + void getAverageFPSAndStandardDeviation(double& averageFPS, double& standardDeviation) const; + int timeStampHistorySize() const { return kTimeStampHistorySize; } + + // n = 0 returns the oldest frame retained in the history, + // while n = timeStampHistorySize() - 1 returns the timestamp most recent frame. + double timeStampOfRecentFrame(int /* n */); + + // This is a heuristic that can be used to ignore frames in a reasonable way. Returns + // true if the given frame interval is too fast or too slow, based on constant thresholds. + bool isBadFrameInterval(double intervalBetweenConsecutiveFrames) const; + + int droppedFrameCount() const { return m_droppedFrameCount; } + +private: + CCFrameRateCounter(); + + double frameInterval(int frameNumber) const; + int frameIndex(int frameNumber) const; + bool isBadFrame(int frameNumber) const; + + // Two thresholds (measured in seconds) that describe what is considered to be a "no-op frame" that should not be counted. + // - if the frame is too fast, then given our compositor implementation, the frame probably was a no-op and did not draw. + // - if the frame is too slow, then there is probably not animating content, so we should not pollute the average. + static const double kFrameTooFast; + static const double kFrameTooSlow; + + // If a frame takes longer than this threshold (measured in seconds) then we + // (naively) assume that it missed a screen refresh; that is, we dropped a frame. + // FIXME: Determine this threshold based on monitor refresh rate, crbug.com/138642. + static const double kDroppedFrameTime; + + static const int kTimeStampHistorySize = 120; + + int m_currentFrameNumber; + double m_timeStampHistory[kTimeStampHistorySize]; + + int m_droppedFrameCount; + + DISALLOW_COPY_AND_ASSIGN(CCFrameRateCounter); +}; + +} // namespace cc + +#endif // USE(ACCELERATED_COMPOSITING) + +#endif diff --git a/cc/geometry_binding.cc b/cc/geometry_binding.cc new file mode 100644 index 0000000..bac1059 --- /dev/null +++ b/cc/geometry_binding.cc @@ -0,0 +1,61 @@ +// Copyright 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#if USE(ACCELERATED_COMPOSITING) + +#include "GeometryBinding.h" + +#include "CCRendererGL.h" // For the GLC() macro. +#include "GraphicsContext3D.h" +#include + +namespace cc { + +GeometryBinding::GeometryBinding(WebKit::WebGraphicsContext3D* context, const FloatRect& quadVertexRect) + : m_context(context) + , m_quadVerticesVbo(0) + , m_quadElementsVbo(0) + , m_initialized(false) +{ + // Vertex positions and texture coordinates for the 4 corners of a 1x1 quad. + float vertices[] = { quadVertexRect.x(), quadVertexRect.maxY(), 0.0f, 0.0f, 1.0f, + quadVertexRect.x(), quadVertexRect.y(), 0.0f, 0.0f, 0.0f, + quadVertexRect.maxX(), quadVertexRect.y(), 0.0f, 1.0f, 0.0f, + quadVertexRect.maxX(), quadVertexRect.maxY(), 0.0f, 1.0f, 1.0f }; + uint16_t indices[] = { 0, 1, 2, 0, 2, 3, // The two triangles that make up the layer quad. + 0, 1, 2, 3}; // A line path for drawing the layer border. + + GLC(m_context, m_quadVerticesVbo = m_context->createBuffer()); + GLC(m_context, m_quadElementsVbo = m_context->createBuffer()); + GLC(m_context, m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, m_quadVerticesVbo)); + GLC(m_context, m_context->bufferData(GraphicsContext3D::ARRAY_BUFFER, sizeof(vertices), vertices, GraphicsContext3D::STATIC_DRAW)); + GLC(m_context, m_context->bindBuffer(GraphicsContext3D::ELEMENT_ARRAY_BUFFER, m_quadElementsVbo)); + GLC(m_context, m_context->bufferData(GraphicsContext3D::ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GraphicsContext3D::STATIC_DRAW)); + + m_initialized = true; +} + +GeometryBinding::~GeometryBinding() +{ + GLC(m_context, m_context->deleteBuffer(m_quadVerticesVbo)); + GLC(m_context, m_context->deleteBuffer(m_quadElementsVbo)); +} + +void GeometryBinding::prepareForDraw() +{ + GLC(m_context, m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, quadVerticesVbo())); + GLC(m_context, m_context->bindBuffer(GraphicsContext3D::ELEMENT_ARRAY_BUFFER, quadElementsVbo())); + unsigned offset = 0; + GLC(m_context, m_context->vertexAttribPointer(positionAttribLocation(), 3, GraphicsContext3D::FLOAT, false, 5 * sizeof(float), offset)); + offset += 3 * sizeof(float); + GLC(m_context, m_context->vertexAttribPointer(texCoordAttribLocation(), 2, GraphicsContext3D::FLOAT, false, 5 * sizeof(float), offset)); + GLC(m_context, m_context->enableVertexAttribArray(positionAttribLocation())); + GLC(m_context, m_context->enableVertexAttribArray(texCoordAttribLocation())); +} + +} // namespace cc + +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/cc/geometry_binding.h b/cc/geometry_binding.h index 638cbb2..f0b6e72 100644 --- a/cc/geometry_binding.h +++ b/cc/geometry_binding.h @@ -1,3 +1,48 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. +// Copyright 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef GeometryBinding_h +#define GeometryBinding_h + +#include "FloatRect.h" + +#if USE(ACCELERATED_COMPOSITING) + +namespace WebKit { +class WebGraphicsContext3D; +} + +namespace cc { + +class GeometryBinding { +public: + GeometryBinding(WebKit::WebGraphicsContext3D*, const FloatRect& quadVertexRect); + ~GeometryBinding(); + + bool initialized() const { return m_initialized; } + + WebKit::WebGraphicsContext3D* context() const { return m_context; } + unsigned quadVerticesVbo() const { return m_quadVerticesVbo; } + unsigned quadElementsVbo() const { return m_quadElementsVbo; } + + void prepareForDraw(); + + // All layer shaders share the same attribute locations for the vertex + // positions and texture coordinates. This allows switching shaders without + // rebinding attribute arrays. + static int positionAttribLocation() { return 0; } + static int texCoordAttribLocation() { return 1; } + +private: + WebKit::WebGraphicsContext3D* m_context; + unsigned m_quadVerticesVbo; + unsigned m_quadElementsVbo; + bool m_initialized; +}; + +} // namespace cc + +#endif // USE(ACCELERATED_COMPOSITING) + +#endif diff --git a/cc/gl_renderer.cc b/cc/gl_renderer.cc new file mode 100644 index 0000000..f28cc50 --- /dev/null +++ b/cc/gl_renderer.cc @@ -0,0 +1,1530 @@ +// Copyright 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + +#include "config.h" + +#if USE(ACCELERATED_COMPOSITING) +#include "CCRendererGL.h" + +#include "CCDamageTracker.h" +#include "CCLayerQuad.h" +#include "CCMathUtil.h" +#include "CCProxy.h" +#include "CCRenderPass.h" +#include "CCRenderSurfaceFilters.h" +#include "CCScopedTexture.h" +#include "CCSettings.h" +#include "CCSingleThreadProxy.h" +#include "CCVideoLayerImpl.h" +#include "Extensions3D.h" +#include "FloatQuad.h" +#include "GeometryBinding.h" +#include "GrTexture.h" +#include "NotImplemented.h" +#include "PlatformColor.h" +#include "SkBitmap.h" +#include "SkColor.h" +#include "TraceEvent.h" +#ifdef LOG +#undef LOG +#endif +#include "base/string_split.h" +#include "base/string_util.h" +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; +using WebKit::WebGraphicsContext3D; +using WebKit::WebGraphicsMemoryAllocation; +using WebKit::WebSharedGraphicsContext3D; +using WebKit::WebTransformationMatrix; + +namespace cc { + +namespace { + +bool needsIOSurfaceReadbackWorkaround() +{ +#if OS(DARWIN) + return true; +#else + return false; +#endif +} + +} // anonymous namespace + +PassOwnPtr CCRendererGL::create(CCRendererClient* client, CCResourceProvider* resourceProvider) +{ + OwnPtr renderer(adoptPtr(new CCRendererGL(client, resourceProvider))); + if (!renderer->initialize()) + return nullptr; + + return renderer.release(); +} + +CCRendererGL::CCRendererGL(CCRendererClient* client, + CCResourceProvider* resourceProvider) + : CCDirectRenderer(client, resourceProvider) + , m_offscreenFramebufferId(0) + , m_sharedGeometryQuad(FloatRect(-0.5f, -0.5f, 1.0f, 1.0f)) + , m_context(resourceProvider->graphicsContext3D()) + , m_isViewportChanged(false) + , m_isFramebufferDiscarded(false) + , m_isUsingBindUniform(false) + , m_visible(true) +{ + ASSERT(m_context); +} + +bool CCRendererGL::initialize() +{ + if (!m_context->makeContextCurrent()) + return false; + + m_context->setContextLostCallback(this); + m_context->pushGroupMarkerEXT("CompositorContext"); + + std::string extensionsString = UTF16ToASCII(m_context->getString(GraphicsContext3D::EXTENSIONS)); + std::vector extensionsList; + base::SplitString(extensionsString, ' ', &extensionsList); + std::set extensions(extensionsList.begin(), extensionsList.end()); + + if (settings().acceleratePainting && extensions.count("GL_EXT_texture_format_BGRA8888") + && extensions.count("GL_EXT_read_format_bgra")) + m_capabilities.usingAcceleratedPainting = true; + else + m_capabilities.usingAcceleratedPainting = false; + + + m_capabilities.contextHasCachedFrontBuffer = extensions.count("GL_CHROMIUM_front_buffer_cached"); + + m_capabilities.usingPartialSwap = CCSettings::partialSwapEnabled() && extensions.count("GL_CHROMIUM_post_sub_buffer"); + + // Use the swapBuffers callback only with the threaded proxy. + if (CCProxy::hasImplThread()) + m_capabilities.usingSwapCompleteCallback = extensions.count("GL_CHROMIUM_swapbuffers_complete_callback"); + if (m_capabilities.usingSwapCompleteCallback) + m_context->setSwapBuffersCompleteCallbackCHROMIUM(this); + + m_capabilities.usingSetVisibility = extensions.count("GL_CHROMIUM_set_visibility"); + + if (extensions.count("GL_CHROMIUM_iosurface")) + ASSERT(extensions.count("GL_ARB_texture_rectangle")); + + m_capabilities.usingGpuMemoryManager = extensions.count("GL_CHROMIUM_gpu_memory_manager"); + if (m_capabilities.usingGpuMemoryManager) + m_context->setMemoryAllocationChangedCallbackCHROMIUM(this); + + m_capabilities.usingDiscardFramebuffer = extensions.count("GL_CHROMIUM_discard_framebuffer"); + + m_capabilities.usingEglImage = extensions.count("GL_OES_EGL_image_external"); + + GLC(m_context, m_context->getIntegerv(GraphicsContext3D::MAX_TEXTURE_SIZE, &m_capabilities.maxTextureSize)); + m_capabilities.bestTextureFormat = PlatformColor::bestTextureFormat(m_context, extensions.count("GL_EXT_texture_format_BGRA8888")); + + m_isUsingBindUniform = extensions.count("GL_CHROMIUM_bind_uniform_location"); + + if (!initializeSharedObjects()) + return false; + + // Make sure the viewport and context gets initialized, even if it is to zero. + viewportChanged(); + return true; +} + +CCRendererGL::~CCRendererGL() +{ + ASSERT(CCProxy::isImplThread()); + m_context->setSwapBuffersCompleteCallbackCHROMIUM(0); + m_context->setMemoryAllocationChangedCallbackCHROMIUM(0); + m_context->setContextLostCallback(0); + cleanupSharedObjects(); +} + +const RendererCapabilities& CCRendererGL::capabilities() const +{ + return m_capabilities; +} + +WebGraphicsContext3D* CCRendererGL::context() +{ + return m_context; +} + +void CCRendererGL::debugGLCall(WebGraphicsContext3D* context, const char* command, const char* file, int line) +{ + unsigned long error = context->getError(); + if (error != GraphicsContext3D::NO_ERROR) + LOG_ERROR("GL command failed: File: %s\n\tLine %d\n\tcommand: %s, error %x\n", file, line, command, static_cast(error)); +} + +void CCRendererGL::setVisible(bool visible) +{ + if (m_visible == visible) + return; + m_visible = visible; + + // TODO: Replace setVisibilityCHROMIUM with an extension to explicitly manage front/backbuffers + // crbug.com/116049 + if (m_capabilities.usingSetVisibility) + m_context->setVisibilityCHROMIUM(visible); +} + +void CCRendererGL::releaseRenderPassTextures() +{ + m_renderPassTextures.clear(); +} + +void CCRendererGL::viewportChanged() +{ + m_isViewportChanged = true; +} + +void CCRendererGL::clearFramebuffer(DrawingFrame& frame) +{ + // On DEBUG builds, opaque render passes are cleared to blue to easily see regions that were not drawn on the screen. + if (frame.currentRenderPass->hasTransparentBackground()) + GLC(m_context, m_context->clearColor(0, 0, 0, 0)); + else + GLC(m_context, m_context->clearColor(0, 0, 1, 1)); + +#if defined(NDEBUG) + if (frame.currentRenderPass->hasTransparentBackground()) +#endif + m_context->clear(GraphicsContext3D::COLOR_BUFFER_BIT); +} + +void CCRendererGL::beginDrawingFrame(DrawingFrame& frame) +{ + // FIXME: Remove this once framebuffer is automatically recreated on first use + ensureFramebuffer(); + + if (viewportSize().isEmpty()) + return; + + TRACE_EVENT0("cc", "CCRendererGL::drawLayers"); + if (m_isViewportChanged) { + // Only reshape when we know we are going to draw. Otherwise, the reshape + // can leave the window at the wrong size if we never draw and the proper + // viewport size is never set. + m_isViewportChanged = false; + m_context->reshape(viewportWidth(), viewportHeight()); + } + + makeContextCurrent(); + // Bind the common vertex attributes used for drawing all the layers. + m_sharedGeometry->prepareForDraw(); + + GLC(m_context, m_context->disable(GraphicsContext3D::DEPTH_TEST)); + GLC(m_context, m_context->disable(GraphicsContext3D::CULL_FACE)); + GLC(m_context, m_context->colorMask(true, true, true, true)); + GLC(m_context, m_context->enable(GraphicsContext3D::BLEND)); + GLC(m_context, m_context->blendFunc(GraphicsContext3D::ONE, GraphicsContext3D::ONE_MINUS_SRC_ALPHA)); +} + +void CCRendererGL::doNoOp() +{ + GLC(m_context, m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, 0)); + GLC(m_context, m_context->flush()); +} + +void CCRendererGL::drawQuad(DrawingFrame& frame, const CCDrawQuad* quad) +{ + if (quad->needsBlending()) + GLC(m_context, m_context->enable(GraphicsContext3D::BLEND)); + else + GLC(m_context, m_context->disable(GraphicsContext3D::BLEND)); + + switch (quad->material()) { + case CCDrawQuad::Invalid: + ASSERT_NOT_REACHED(); + break; + case CCDrawQuad::Checkerboard: + drawCheckerboardQuad(frame, CCCheckerboardDrawQuad::materialCast(quad)); + break; + case CCDrawQuad::DebugBorder: + drawDebugBorderQuad(frame, CCDebugBorderDrawQuad::materialCast(quad)); + break; + case CCDrawQuad::IOSurfaceContent: + drawIOSurfaceQuad(frame, CCIOSurfaceDrawQuad::materialCast(quad)); + break; + case CCDrawQuad::RenderPass: + drawRenderPassQuad(frame, CCRenderPassDrawQuad::materialCast(quad)); + break; + case CCDrawQuad::SolidColor: + drawSolidColorQuad(frame, CCSolidColorDrawQuad::materialCast(quad)); + break; + case CCDrawQuad::StreamVideoContent: + drawStreamVideoQuad(frame, CCStreamVideoDrawQuad::materialCast(quad)); + break; + case CCDrawQuad::TextureContent: + drawTextureQuad(frame, CCTextureDrawQuad::materialCast(quad)); + break; + case CCDrawQuad::TiledContent: + drawTileQuad(frame, CCTileDrawQuad::materialCast(quad)); + break; + case CCDrawQuad::YUVVideoContent: + drawYUVVideoQuad(frame, CCYUVVideoDrawQuad::materialCast(quad)); + break; + } +} + +void CCRendererGL::drawCheckerboardQuad(const DrawingFrame& frame, const CCCheckerboardDrawQuad* quad) +{ + const TileCheckerboardProgram* program = tileCheckerboardProgram(); + ASSERT(program && program->initialized()); + GLC(context(), context()->useProgram(program->program())); + + SkColor color = quad->color(); + GLC(context(), context()->uniform4f(program->fragmentShader().colorLocation(), SkColorGetR(color) / 255.0, SkColorGetG(color) / 255.0, SkColorGetB(color) / 255.0, 1)); + + const int checkerboardWidth = 16; + float frequency = 1.0 / checkerboardWidth; + + IntRect tileRect = quad->quadRect(); + float texOffsetX = tileRect.x() % checkerboardWidth; + float texOffsetY = tileRect.y() % checkerboardWidth; + float texScaleX = tileRect.width(); + float texScaleY = tileRect.height(); + GLC(context(), context()->uniform4f(program->fragmentShader().texTransformLocation(), texOffsetX, texOffsetY, texScaleX, texScaleY)); + + GLC(context(), context()->uniform1f(program->fragmentShader().frequencyLocation(), frequency)); + + setShaderOpacity(quad->opacity(), program->fragmentShader().alphaLocation()); + drawQuadGeometry(frame, quad->quadTransform(), quad->quadRect(), program->vertexShader().matrixLocation()); +} + +void CCRendererGL::drawDebugBorderQuad(const DrawingFrame& frame, const CCDebugBorderDrawQuad* quad) +{ + static float glMatrix[16]; + const SolidColorProgram* program = solidColorProgram(); + ASSERT(program && program->initialized()); + GLC(context(), context()->useProgram(program->program())); + + // Use the full quadRect for debug quads to not move the edges based on partial swaps. + const IntRect& layerRect = quad->quadRect(); + WebTransformationMatrix renderMatrix = quad->quadTransform(); + renderMatrix.translate(0.5 * layerRect.width() + layerRect.x(), 0.5 * layerRect.height() + layerRect.y()); + renderMatrix.scaleNonUniform(layerRect.width(), layerRect.height()); + CCRendererGL::toGLMatrix(&glMatrix[0], frame.projectionMatrix * renderMatrix); + GLC(context(), context()->uniformMatrix4fv(program->vertexShader().matrixLocation(), 1, false, &glMatrix[0])); + + SkColor color = quad->color(); + float alpha = SkColorGetA(color) / 255.0; + + GLC(context(), context()->uniform4f(program->fragmentShader().colorLocation(), (SkColorGetR(color) / 255.0) * alpha, (SkColorGetG(color) / 255.0) * alpha, (SkColorGetB(color) / 255.0) * alpha, alpha)); + + GLC(context(), context()->lineWidth(quad->width())); + + // The indices for the line are stored in the same array as the triangle indices. + GLC(context(), context()->drawElements(GraphicsContext3D::LINE_LOOP, 4, GraphicsContext3D::UNSIGNED_SHORT, 6 * sizeof(unsigned short))); +} + +static inline SkBitmap applyFilters(CCRendererGL* renderer, const WebKit::WebFilterOperations& filters, CCScopedTexture* sourceTexture) +{ + if (filters.isEmpty()) + return SkBitmap(); + + WebGraphicsContext3D* filterContext = CCProxy::hasImplThread() ? WebSharedGraphicsContext3D::compositorThreadContext() : WebSharedGraphicsContext3D::mainThreadContext(); + GrContext* filterGrContext = CCProxy::hasImplThread() ? WebSharedGraphicsContext3D::compositorThreadGrContext() : WebSharedGraphicsContext3D::mainThreadGrContext(); + + if (!filterContext || !filterGrContext) + return SkBitmap(); + + renderer->context()->flush(); + + CCResourceProvider::ScopedWriteLockGL lock(renderer->resourceProvider(), sourceTexture->id()); + SkBitmap source = CCRenderSurfaceFilters::apply(filters, lock.textureId(), sourceTexture->size(), filterContext, filterGrContext); + return source; +} + +PassOwnPtr CCRendererGL::drawBackgroundFilters(DrawingFrame& frame, const CCRenderPassDrawQuad* quad, const WebKit::WebFilterOperations& filters, const WebTransformationMatrix& contentsDeviceTransform) +{ + // This method draws a background filter, which applies a filter to any pixels behind the quad and seen through its background. + // The algorithm works as follows: + // 1. Compute a bounding box around the pixels that will be visible through the quad. + // 2. Read the pixels in the bounding box into a buffer R. + // 3. Apply the background filter to R, so that it is applied in the pixels' coordinate space. + // 4. Apply the quad's inverse transform to map the pixels in R into the quad's content space. This implicitly + // clips R by the content bounds of the quad since the destination texture has bounds matching the quad's content. + // 5. Draw the background texture for the contents using the same transform as used to draw the contents itself. This is done + // without blending to replace the current background pixels with the new filtered background. + // 6. Draw the contents of the quad over drop of the new background with blending, as per usual. The filtered background + // pixels will show through any non-opaque pixels in this draws. + // + // Pixel copies in this algorithm occur at steps 2, 3, 4, and 5. + + // FIXME: When this algorithm changes, update CCLayerTreeHost::prioritizeTextures() accordingly. + + if (filters.isEmpty()) + return nullptr; + + // FIXME: We only allow background filters on an opaque render surface because other surfaces may contain + // translucent pixels, and the contents behind those translucent pixels wouldn't have the filter applied. + if (frame.currentRenderPass->hasTransparentBackground()) + return nullptr; + ASSERT(!frame.currentTexture); + + // FIXME: Do a single readback for both the surface and replica and cache the filtered results (once filter textures are not reused). + IntRect deviceRect = enclosingIntRect(CCMathUtil::mapClippedRect(contentsDeviceTransform, sharedGeometryQuad().boundingBox())); + + int top, right, bottom, left; + filters.getOutsets(top, right, bottom, left); + deviceRect.move(-left, -top); + deviceRect.expand(left + right, top + bottom); + + deviceRect.intersect(frame.currentRenderPass->outputRect()); + + OwnPtr deviceBackgroundTexture = CCScopedTexture::create(m_resourceProvider); + if (!getFramebufferTexture(deviceBackgroundTexture.get(), deviceRect)) + return nullptr; + + SkBitmap filteredDeviceBackground = applyFilters(this, filters, deviceBackgroundTexture.get()); + if (!filteredDeviceBackground.getTexture()) + return nullptr; + + GrTexture* texture = reinterpret_cast(filteredDeviceBackground.getTexture()); + int filteredDeviceBackgroundTextureId = texture->getTextureHandle(); + + OwnPtr backgroundTexture = CCScopedTexture::create(m_resourceProvider); + if (!backgroundTexture->allocate(CCRenderer::ImplPool, quad->quadRect().size(), GraphicsContext3D::RGBA, CCResourceProvider::TextureUsageFramebuffer)) + return nullptr; + + const CCRenderPass* targetRenderPass = frame.currentRenderPass; + bool usingBackgroundTexture = useScopedTexture(frame, backgroundTexture.get(), quad->quadRect()); + + if (usingBackgroundTexture) { + // Copy the readback pixels from device to the background texture for the surface. + WebTransformationMatrix deviceToFramebufferTransform; + deviceToFramebufferTransform.translate(quad->quadRect().width() / 2.0, quad->quadRect().height() / 2.0); + deviceToFramebufferTransform.scale3d(quad->quadRect().width(), quad->quadRect().height(), 1); + deviceToFramebufferTransform.multiply(contentsDeviceTransform.inverse()); + copyTextureToFramebuffer(frame, filteredDeviceBackgroundTextureId, deviceRect, deviceToFramebufferTransform); + } + + useRenderPass(frame, targetRenderPass); + + if (!usingBackgroundTexture) + return nullptr; + return backgroundTexture.release(); +} + +void CCRendererGL::drawRenderPassQuad(DrawingFrame& frame, const CCRenderPassDrawQuad* quad) +{ + CachedTexture* contentsTexture = m_renderPassTextures.get(quad->renderPassId()); + if (!contentsTexture || !contentsTexture->id()) + return; + + const CCRenderPass* renderPass = frame.renderPassesById->get(quad->renderPassId()); + ASSERT(renderPass); + if (!renderPass) + return; + + WebTransformationMatrix renderMatrix = quad->quadTransform(); + renderMatrix.translate(0.5 * quad->quadRect().width() + quad->quadRect().x(), 0.5 * quad->quadRect().height() + quad->quadRect().y()); + WebTransformationMatrix deviceMatrix = renderMatrix; + deviceMatrix.scaleNonUniform(quad->quadRect().width(), quad->quadRect().height()); + WebTransformationMatrix contentsDeviceTransform = WebTransformationMatrix(frame.windowMatrix * frame.projectionMatrix * deviceMatrix).to2dTransform(); + + // Can only draw surface if device matrix is invertible. + if (!contentsDeviceTransform.isInvertible()) + return; + + OwnPtr backgroundTexture = drawBackgroundFilters(frame, quad, renderPass->backgroundFilters(), contentsDeviceTransform); + + // FIXME: Cache this value so that we don't have to do it for both the surface and its replica. + // Apply filters to the contents texture. + SkBitmap filterBitmap = applyFilters(this, renderPass->filters(), contentsTexture); + OwnPtr contentsResourceLock; + unsigned contentsTextureId = 0; + if (filterBitmap.getTexture()) { + GrTexture* texture = reinterpret_cast(filterBitmap.getTexture()); + contentsTextureId = texture->getTextureHandle(); + } else { + contentsResourceLock = adoptPtr(new CCResourceProvider::ScopedReadLockGL(m_resourceProvider, contentsTexture->id())); + contentsTextureId = contentsResourceLock->textureId(); + } + + // Draw the background texture if there is one. + if (backgroundTexture) { + ASSERT(backgroundTexture->size() == quad->quadRect().size()); + CCResourceProvider::ScopedReadLockGL lock(m_resourceProvider, backgroundTexture->id()); + copyTextureToFramebuffer(frame, lock.textureId(), quad->quadRect(), quad->quadTransform()); + } + + bool clipped = false; + FloatQuad deviceQuad = CCMathUtil::mapQuad(contentsDeviceTransform, sharedGeometryQuad(), clipped); + ASSERT(!clipped); + CCLayerQuad deviceLayerBounds = CCLayerQuad(FloatQuad(deviceQuad.boundingBox())); + CCLayerQuad deviceLayerEdges = CCLayerQuad(deviceQuad); + + // Use anti-aliasing programs only when necessary. + bool useAA = (!deviceQuad.isRectilinear() || !deviceQuad.boundingBox().isExpressibleAsIntRect()); + if (useAA) { + deviceLayerBounds.inflateAntiAliasingDistance(); + deviceLayerEdges.inflateAntiAliasingDistance(); + } + + OwnPtr maskResourceLock; + unsigned maskTextureId = 0; + if (quad->maskResourceId()) { + maskResourceLock = adoptPtr(new CCResourceProvider::ScopedReadLockGL(m_resourceProvider, quad->maskResourceId())); + maskTextureId = maskResourceLock->textureId(); + } + + // FIXME: use the backgroundTexture and blend the background in with this draw instead of having a separate copy of the background texture. + + GLC(context(), context()->activeTexture(GraphicsContext3D::TEXTURE0)); + context()->bindTexture(GraphicsContext3D::TEXTURE_2D, contentsTextureId); + + int shaderQuadLocation = -1; + int shaderEdgeLocation = -1; + int shaderMaskSamplerLocation = -1; + int shaderMaskTexCoordScaleLocation = -1; + int shaderMaskTexCoordOffsetLocation = -1; + int shaderMatrixLocation = -1; + int shaderAlphaLocation = -1; + if (useAA && maskTextureId) { + const RenderPassMaskProgramAA* program = renderPassMaskProgramAA(); + GLC(context(), context()->useProgram(program->program())); + GLC(context(), context()->uniform1i(program->fragmentShader().samplerLocation(), 0)); + + shaderQuadLocation = program->vertexShader().pointLocation(); + shaderEdgeLocation = program->fragmentShader().edgeLocation(); + shaderMaskSamplerLocation = program->fragmentShader().maskSamplerLocation(); + shaderMaskTexCoordScaleLocation = program->fragmentShader().maskTexCoordScaleLocation(); + shaderMaskTexCoordOffsetLocation = program->fragmentShader().maskTexCoordOffsetLocation(); + shaderMatrixLocation = program->vertexShader().matrixLocation(); + shaderAlphaLocation = program->fragmentShader().alphaLocation(); + } else if (!useAA && maskTextureId) { + const RenderPassMaskProgram* program = renderPassMaskProgram(); + GLC(context(), context()->useProgram(program->program())); + GLC(context(), context()->uniform1i(program->fragmentShader().samplerLocation(), 0)); + + shaderMaskSamplerLocation = program->fragmentShader().maskSamplerLocation(); + shaderMaskTexCoordScaleLocation = program->fragmentShader().maskTexCoordScaleLocation(); + shaderMaskTexCoordOffsetLocation = program->fragmentShader().maskTexCoordOffsetLocation(); + shaderMatrixLocation = program->vertexShader().matrixLocation(); + shaderAlphaLocation = program->fragmentShader().alphaLocation(); + } else if (useAA && !maskTextureId) { + const RenderPassProgramAA* program = renderPassProgramAA(); + GLC(context(), context()->useProgram(program->program())); + GLC(context(), context()->uniform1i(program->fragmentShader().samplerLocation(), 0)); + + shaderQuadLocation = program->vertexShader().pointLocation(); + shaderEdgeLocation = program->fragmentShader().edgeLocation(); + shaderMatrixLocation = program->vertexShader().matrixLocation(); + shaderAlphaLocation = program->fragmentShader().alphaLocation(); + } else { + const RenderPassProgram* program = renderPassProgram(); + GLC(context(), context()->useProgram(program->program())); + GLC(context(), context()->uniform1i(program->fragmentShader().samplerLocation(), 0)); + + shaderMatrixLocation = program->vertexShader().matrixLocation(); + shaderAlphaLocation = program->fragmentShader().alphaLocation(); + } + + if (shaderMaskSamplerLocation != -1) { + ASSERT(shaderMaskTexCoordScaleLocation != 1); + ASSERT(shaderMaskTexCoordOffsetLocation != 1); + GLC(context(), context()->activeTexture(GraphicsContext3D::TEXTURE1)); + GLC(context(), context()->uniform1i(shaderMaskSamplerLocation, 1)); + GLC(context(), context()->uniform2f(shaderMaskTexCoordScaleLocation, quad->maskTexCoordScaleX(), quad->maskTexCoordScaleY())); + GLC(context(), context()->uniform2f(shaderMaskTexCoordOffsetLocation, quad->maskTexCoordOffsetX(), quad->maskTexCoordOffsetY())); + context()->bindTexture(GraphicsContext3D::TEXTURE_2D, maskTextureId); + GLC(context(), context()->activeTexture(GraphicsContext3D::TEXTURE0)); + } + + if (shaderEdgeLocation != -1) { + float edge[24]; + deviceLayerEdges.toFloatArray(edge); + deviceLayerBounds.toFloatArray(&edge[12]); + GLC(context(), context()->uniform3fv(shaderEdgeLocation, 8, edge)); + } + + // Map device space quad to surface space. contentsDeviceTransform has no 3d component since it was generated with to2dTransform() so we don't need to project. + FloatQuad surfaceQuad = CCMathUtil::mapQuad(contentsDeviceTransform.inverse(), deviceLayerEdges.floatQuad(), clipped); + ASSERT(!clipped); + + setShaderOpacity(quad->opacity(), shaderAlphaLocation); + setShaderFloatQuad(surfaceQuad, shaderQuadLocation); + drawQuadGeometry(frame, quad->quadTransform(), quad->quadRect(), shaderMatrixLocation); +} + +void CCRendererGL::drawSolidColorQuad(const DrawingFrame& frame, const CCSolidColorDrawQuad* quad) +{ + const SolidColorProgram* program = solidColorProgram(); + GLC(context(), context()->useProgram(program->program())); + + SkColor color = quad->color(); + float opacity = quad->opacity(); + float alpha = (SkColorGetA(color) / 255.0) * opacity; + + GLC(context(), context()->uniform4f(program->fragmentShader().colorLocation(), (SkColorGetR(color) / 255.0) * alpha, (SkColorGetG(color) / 255.0) * alpha, (SkColorGetB(color) / 255.0) * alpha, alpha)); + + drawQuadGeometry(frame, quad->quadTransform(), quad->quadRect(), program->vertexShader().matrixLocation()); +} + +struct TileProgramUniforms { + unsigned program; + unsigned samplerLocation; + unsigned vertexTexTransformLocation; + unsigned fragmentTexTransformLocation; + unsigned edgeLocation; + unsigned matrixLocation; + unsigned alphaLocation; + unsigned pointLocation; +}; + +template +static void tileUniformLocation(T program, TileProgramUniforms& uniforms) +{ + uniforms.program = program->program(); + uniforms.vertexTexTransformLocation = program->vertexShader().vertexTexTransformLocation(); + uniforms.matrixLocation = program->vertexShader().matrixLocation(); + uniforms.pointLocation = program->vertexShader().pointLocation(); + + uniforms.samplerLocation = program->fragmentShader().samplerLocation(); + uniforms.alphaLocation = program->fragmentShader().alphaLocation(); + uniforms.fragmentTexTransformLocation = program->fragmentShader().fragmentTexTransformLocation(); + uniforms.edgeLocation = program->fragmentShader().edgeLocation(); +} + +void CCRendererGL::drawTileQuad(const DrawingFrame& frame, const CCTileDrawQuad* quad) +{ + IntRect tileRect = quad->quadVisibleRect(); + + FloatRect clampRect(tileRect); + // Clamp texture coordinates to avoid sampling outside the layer + // by deflating the tile region half a texel or half a texel + // minus epsilon for one pixel layers. The resulting clamp region + // is mapped to the unit square by the vertex shader and mapped + // back to normalized texture coordinates by the fragment shader + // after being clamped to 0-1 range. + const float epsilon = 1 / 1024.0f; + float clampX = min(0.5, clampRect.width() / 2.0 - epsilon); + float clampY = min(0.5, clampRect.height() / 2.0 - epsilon); + clampRect.inflateX(-clampX); + clampRect.inflateY(-clampY); + FloatSize clampOffset = clampRect.minXMinYCorner() - FloatRect(tileRect).minXMinYCorner(); + + FloatPoint textureOffset = quad->textureOffset() + clampOffset + + IntPoint(tileRect.location() - quad->quadRect().location()); + + // Map clamping rectangle to unit square. + float vertexTexTranslateX = -clampRect.x() / clampRect.width(); + float vertexTexTranslateY = -clampRect.y() / clampRect.height(); + float vertexTexScaleX = tileRect.width() / clampRect.width(); + float vertexTexScaleY = tileRect.height() / clampRect.height(); + + // Map to normalized texture coordinates. + const IntSize& textureSize = quad->textureSize(); + float fragmentTexTranslateX = textureOffset.x() / textureSize.width(); + float fragmentTexTranslateY = textureOffset.y() / textureSize.height(); + float fragmentTexScaleX = clampRect.width() / textureSize.width(); + float fragmentTexScaleY = clampRect.height() / textureSize.height(); + + + FloatQuad localQuad; + WebTransformationMatrix deviceTransform = WebTransformationMatrix(frame.windowMatrix * frame.projectionMatrix * quad->quadTransform()).to2dTransform(); + if (!deviceTransform.isInvertible()) + return; + + bool clipped = false; + FloatQuad deviceLayerQuad = CCMathUtil::mapQuad(deviceTransform, FloatQuad(quad->visibleContentRect()), clipped); + ASSERT(!clipped); + + TileProgramUniforms uniforms; + // For now, we simply skip anti-aliasing with the quad is clipped. This only happens + // on perspective transformed layers that go partially behind the camera. + if (quad->isAntialiased() && !clipped) { + if (quad->swizzleContents()) + tileUniformLocation(tileProgramSwizzleAA(), uniforms); + else + tileUniformLocation(tileProgramAA(), uniforms); + } else { + if (quad->needsBlending()) { + if (quad->swizzleContents()) + tileUniformLocation(tileProgramSwizzle(), uniforms); + else + tileUniformLocation(tileProgram(), uniforms); + } else { + if (quad->swizzleContents()) + tileUniformLocation(tileProgramSwizzleOpaque(), uniforms); + else + tileUniformLocation(tileProgramOpaque(), uniforms); + } + } + + GLC(context(), context()->useProgram(uniforms.program)); + GLC(context(), context()->uniform1i(uniforms.samplerLocation, 0)); + GLC(context(), context()->activeTexture(GraphicsContext3D::TEXTURE0)); + CCResourceProvider::ScopedReadLockGL quadResourceLock(m_resourceProvider, quad->resourceId()); + GLC(context(), context()->bindTexture(GraphicsContext3D::TEXTURE_2D, quadResourceLock.textureId())); + GLC(context(), context()->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, quad->textureFilter())); + GLC(context(), context()->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, quad->textureFilter())); + + bool useAA = !clipped && quad->isAntialiased(); + if (useAA) { + CCLayerQuad deviceLayerBounds = CCLayerQuad(FloatQuad(deviceLayerQuad.boundingBox())); + deviceLayerBounds.inflateAntiAliasingDistance(); + + CCLayerQuad deviceLayerEdges = CCLayerQuad(deviceLayerQuad); + deviceLayerEdges.inflateAntiAliasingDistance(); + + float edge[24]; + deviceLayerEdges.toFloatArray(edge); + deviceLayerBounds.toFloatArray(&edge[12]); + GLC(context(), context()->uniform3fv(uniforms.edgeLocation, 8, edge)); + + GLC(context(), context()->uniform4f(uniforms.vertexTexTransformLocation, vertexTexTranslateX, vertexTexTranslateY, vertexTexScaleX, vertexTexScaleY)); + GLC(context(), context()->uniform4f(uniforms.fragmentTexTransformLocation, fragmentTexTranslateX, fragmentTexTranslateY, fragmentTexScaleX, fragmentTexScaleY)); + + FloatPoint bottomRight(tileRect.maxX(), tileRect.maxY()); + FloatPoint bottomLeft(tileRect.x(), tileRect.maxY()); + FloatPoint topLeft(tileRect.x(), tileRect.y()); + FloatPoint topRight(tileRect.maxX(), tileRect.y()); + + // Map points to device space. + bottomRight = CCMathUtil::mapPoint(deviceTransform, bottomRight, clipped); + ASSERT(!clipped); + bottomLeft = CCMathUtil::mapPoint(deviceTransform, bottomLeft, clipped); + ASSERT(!clipped); + topLeft = CCMathUtil::mapPoint(deviceTransform, topLeft, clipped); + ASSERT(!clipped); + topRight = CCMathUtil::mapPoint(deviceTransform, topRight, clipped); + ASSERT(!clipped); + + CCLayerQuad::Edge bottomEdge(bottomRight, bottomLeft); + CCLayerQuad::Edge leftEdge(bottomLeft, topLeft); + CCLayerQuad::Edge topEdge(topLeft, topRight); + CCLayerQuad::Edge rightEdge(topRight, bottomRight); + + // Only apply anti-aliasing to edges not clipped by culling or scissoring. + if (quad->topEdgeAA() && tileRect.y() == quad->quadRect().y()) + topEdge = deviceLayerEdges.top(); + if (quad->leftEdgeAA() && tileRect.x() == quad->quadRect().x()) + leftEdge = deviceLayerEdges.left(); + if (quad->rightEdgeAA() && tileRect.maxX() == quad->quadRect().maxX()) + rightEdge = deviceLayerEdges.right(); + if (quad->bottomEdgeAA() && tileRect.maxY() == quad->quadRect().maxY()) + bottomEdge = deviceLayerEdges.bottom(); + + float sign = FloatQuad(tileRect).isCounterclockwise() ? -1 : 1; + bottomEdge.scale(sign); + leftEdge.scale(sign); + topEdge.scale(sign); + rightEdge.scale(sign); + + // Create device space quad. + CCLayerQuad deviceQuad(leftEdge, topEdge, rightEdge, bottomEdge); + + // Map device space quad to local space. contentsDeviceTransform has no 3d component since it was generated with to2dTransform() so we don't need to project. + WebTransformationMatrix inverseDeviceTransform = deviceTransform.inverse(); + localQuad = CCMathUtil::mapQuad(inverseDeviceTransform, deviceQuad.floatQuad(), clipped); + + // We should not ASSERT(!clipped) here, because anti-aliasing inflation may cause deviceQuad to become + // clipped. To our knowledge this scenario does not need to be handled differently than the unclipped case. + } else { + // Move fragment shader transform to vertex shader. We can do this while + // still producing correct results as fragmentTexTransformLocation + // should always be non-negative when tiles are transformed in a way + // that could result in sampling outside the layer. + vertexTexScaleX *= fragmentTexScaleX; + vertexTexScaleY *= fragmentTexScaleY; + vertexTexTranslateX *= fragmentTexScaleX; + vertexTexTranslateY *= fragmentTexScaleY; + vertexTexTranslateX += fragmentTexTranslateX; + vertexTexTranslateY += fragmentTexTranslateY; + + GLC(context(), context()->uniform4f(uniforms.vertexTexTransformLocation, vertexTexTranslateX, vertexTexTranslateY, vertexTexScaleX, vertexTexScaleY)); + + localQuad = FloatRect(tileRect); + } + + // Normalize to tileRect. + localQuad.scale(1.0f / tileRect.width(), 1.0f / tileRect.height()); + + setShaderOpacity(quad->opacity(), uniforms.alphaLocation); + setShaderFloatQuad(localQuad, uniforms.pointLocation); + + // The tile quad shader behaves differently compared to all other shaders. + // The transform and vertex data are used to figure out the extents that the + // un-antialiased quad should have and which vertex this is and the float + // quad passed in via uniform is the actual geometry that gets used to draw + // it. This is why this centered rect is used and not the original quadRect. + FloatRect centeredRect(FloatPoint(-0.5 * tileRect.width(), -0.5 * tileRect.height()), tileRect.size()); + drawQuadGeometry(frame, quad->quadTransform(), centeredRect, uniforms.matrixLocation); +} + +void CCRendererGL::drawYUVVideoQuad(const DrawingFrame& frame, const CCYUVVideoDrawQuad* quad) +{ + const VideoYUVProgram* program = videoYUVProgram(); + ASSERT(program && program->initialized()); + + const CCVideoLayerImpl::FramePlane& yPlane = quad->yPlane(); + const CCVideoLayerImpl::FramePlane& uPlane = quad->uPlane(); + const CCVideoLayerImpl::FramePlane& vPlane = quad->vPlane(); + + CCResourceProvider::ScopedReadLockGL yPlaneLock(m_resourceProvider, yPlane.resourceId); + CCResourceProvider::ScopedReadLockGL uPlaneLock(m_resourceProvider, uPlane.resourceId); + CCResourceProvider::ScopedReadLockGL vPlaneLock(m_resourceProvider, vPlane.resourceId); + GLC(context(), context()->activeTexture(GraphicsContext3D::TEXTURE1)); + GLC(context(), context()->bindTexture(GraphicsContext3D::TEXTURE_2D, yPlaneLock.textureId())); + GLC(context(), context()->activeTexture(GraphicsContext3D::TEXTURE2)); + GLC(context(), context()->bindTexture(GraphicsContext3D::TEXTURE_2D, uPlaneLock.textureId())); + GLC(context(), context()->activeTexture(GraphicsContext3D::TEXTURE3)); + GLC(context(), context()->bindTexture(GraphicsContext3D::TEXTURE_2D, vPlaneLock.textureId())); + + GLC(context(), context()->useProgram(program->program())); + + float yWidthScaleFactor = static_cast(yPlane.visibleSize.width()) / yPlane.size.width(); + // Arbitrarily take the u sizes because u and v dimensions are identical. + float uvWidthScaleFactor = static_cast(uPlane.visibleSize.width()) / uPlane.size.width(); + GLC(context(), context()->uniform1f(program->vertexShader().yWidthScaleFactorLocation(), yWidthScaleFactor)); + GLC(context(), context()->uniform1f(program->vertexShader().uvWidthScaleFactorLocation(), uvWidthScaleFactor)); + + GLC(context(), context()->uniform1i(program->fragmentShader().yTextureLocation(), 1)); + GLC(context(), context()->uniform1i(program->fragmentShader().uTextureLocation(), 2)); + GLC(context(), context()->uniform1i(program->fragmentShader().vTextureLocation(), 3)); + + // These values are magic numbers that are used in the transformation from YUV to RGB color values. + // They are taken from the following webpage: http://www.fourcc.org/fccyvrgb.php + float yuv2RGB[9] = { + 1.164f, 1.164f, 1.164f, + 0.f, -.391f, 2.018f, + 1.596f, -.813f, 0.f, + }; + GLC(context(), context()->uniformMatrix3fv(program->fragmentShader().ccMatrixLocation(), 1, 0, yuv2RGB)); + + // These values map to 16, 128, and 128 respectively, and are computed + // as a fraction over 256 (e.g. 16 / 256 = 0.0625). + // They are used in the YUV to RGBA conversion formula: + // Y - 16 : Gives 16 values of head and footroom for overshooting + // U - 128 : Turns unsigned U into signed U [-128,127] + // V - 128 : Turns unsigned V into signed V [-128,127] + float yuvAdjust[3] = { + -0.0625f, + -0.5f, + -0.5f, + }; + GLC(context(), context()->uniform3fv(program->fragmentShader().yuvAdjLocation(), 1, yuvAdjust)); + + setShaderOpacity(quad->opacity(), program->fragmentShader().alphaLocation()); + drawQuadGeometry(frame, quad->quadTransform(), quad->quadRect(), program->vertexShader().matrixLocation()); + + // Reset active texture back to texture 0. + GLC(context(), context()->activeTexture(GraphicsContext3D::TEXTURE0)); +} + +void CCRendererGL::drawStreamVideoQuad(const DrawingFrame& frame, const CCStreamVideoDrawQuad* quad) +{ + static float glMatrix[16]; + + ASSERT(m_capabilities.usingEglImage); + + const VideoStreamTextureProgram* program = videoStreamTextureProgram(); + GLC(context(), context()->useProgram(program->program())); + + toGLMatrix(&glMatrix[0], quad->matrix()); + GLC(context(), context()->uniformMatrix4fv(program->vertexShader().texMatrixLocation(), 1, false, glMatrix)); + + GLC(context(), context()->activeTexture(GraphicsContext3D::TEXTURE0)); + GLC(context(), context()->bindTexture(Extensions3DChromium::GL_TEXTURE_EXTERNAL_OES, quad->textureId())); + + GLC(context(), context()->uniform1i(program->fragmentShader().samplerLocation(), 0)); + + setShaderOpacity(quad->opacity(), program->fragmentShader().alphaLocation()); + drawQuadGeometry(frame, quad->quadTransform(), quad->quadRect(), program->vertexShader().matrixLocation()); +} + +struct TextureProgramBinding { + template void set(Program* program) + { + ASSERT(program && program->initialized()); + programId = program->program(); + samplerLocation = program->fragmentShader().samplerLocation(); + matrixLocation = program->vertexShader().matrixLocation(); + alphaLocation = program->fragmentShader().alphaLocation(); + } + int programId; + int samplerLocation; + int matrixLocation; + int alphaLocation; +}; + +struct TexTransformTextureProgramBinding : TextureProgramBinding { + template void set(Program* program) + { + TextureProgramBinding::set(program); + texTransformLocation = program->vertexShader().texTransformLocation(); + } + int texTransformLocation; +}; + +void CCRendererGL::drawTextureQuad(const DrawingFrame& frame, const CCTextureDrawQuad* quad) +{ + ASSERT(CCProxy::isImplThread()); + + TexTransformTextureProgramBinding binding; + if (quad->flipped()) + binding.set(textureProgramFlip()); + else + binding.set(textureProgram()); + GLC(context(), context()->useProgram(binding.programId)); + GLC(context(), context()->uniform1i(binding.samplerLocation, 0)); + const FloatRect& uvRect = quad->uvRect(); + GLC(context(), context()->uniform4f(binding.texTransformLocation, uvRect.x(), uvRect.y(), uvRect.width(), uvRect.height())); + + GLC(context(), context()->activeTexture(GraphicsContext3D::TEXTURE0)); + CCResourceProvider::ScopedReadLockGL quadResourceLock(m_resourceProvider, quad->resourceId()); + GLC(context(), context()->bindTexture(GraphicsContext3D::TEXTURE_2D, quadResourceLock.textureId())); + + // FIXME: setting the texture parameters every time is redundant. Move this code somewhere + // where it will only happen once per texture. + GLC(context(), context()->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR)); + GLC(context(), context()->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR)); + GLC(context(), context()->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE)); + GLC(context(), context()->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE)); + + if (!quad->premultipliedAlpha()) { + // As it turns out, the premultiplied alpha blending function (ONE, ONE_MINUS_SRC_ALPHA) + // will never cause the alpha channel to be set to anything less than 1.0 if it is + // initialized to that value! Therefore, premultipliedAlpha being false is the first + // situation we can generally see an alpha channel less than 1.0 coming out of the + // compositor. This is causing platform differences in some layout tests (see + // https://bugs.webkit.org/show_bug.cgi?id=82412), so in this situation, use a separate + // blend function for the alpha channel to avoid modifying it. Don't use colorMask for this + // as it has performance implications on some platforms. + GLC(context(), context()->blendFuncSeparate(GraphicsContext3D::SRC_ALPHA, GraphicsContext3D::ONE_MINUS_SRC_ALPHA, GraphicsContext3D::ZERO, GraphicsContext3D::ONE)); + } + + setShaderOpacity(quad->opacity(), binding.alphaLocation); + drawQuadGeometry(frame, quad->quadTransform(), quad->quadRect(), binding.matrixLocation); + + if (!quad->premultipliedAlpha()) + GLC(m_context, m_context->blendFunc(GraphicsContext3D::ONE, GraphicsContext3D::ONE_MINUS_SRC_ALPHA)); +} + +void CCRendererGL::drawIOSurfaceQuad(const DrawingFrame& frame, const CCIOSurfaceDrawQuad* quad) +{ + ASSERT(CCProxy::isImplThread()); + TexTransformTextureProgramBinding binding; + binding.set(textureIOSurfaceProgram()); + + GLC(context(), context()->useProgram(binding.programId)); + GLC(context(), context()->uniform1i(binding.samplerLocation, 0)); + if (quad->orientation() == CCIOSurfaceDrawQuad::Flipped) + GLC(context(), context()->uniform4f(binding.texTransformLocation, 0, quad->ioSurfaceSize().height(), quad->ioSurfaceSize().width(), quad->ioSurfaceSize().height() * -1.0)); + else + GLC(context(), context()->uniform4f(binding.texTransformLocation, 0, 0, quad->ioSurfaceSize().width(), quad->ioSurfaceSize().height())); + + GLC(context(), context()->activeTexture(GraphicsContext3D::TEXTURE0)); + GLC(context(), context()->bindTexture(Extensions3D::TEXTURE_RECTANGLE_ARB, quad->ioSurfaceTextureId())); + + setShaderOpacity(quad->opacity(), binding.alphaLocation); + drawQuadGeometry(frame, quad->quadTransform(), quad->quadRect(), binding.matrixLocation); + + GLC(context(), context()->bindTexture(Extensions3D::TEXTURE_RECTANGLE_ARB, 0)); +} + +void CCRendererGL::finishDrawingFrame(DrawingFrame& frame) +{ + m_currentFramebufferLock.clear(); + m_swapBufferRect.unite(enclosingIntRect(frame.rootDamageRect)); + + GLC(m_context, m_context->disable(GraphicsContext3D::SCISSOR_TEST)); + GLC(m_context, m_context->disable(GraphicsContext3D::BLEND)); +} + +bool CCRendererGL::flippedFramebuffer() const +{ + return true; +} + +void CCRendererGL::toGLMatrix(float* flattened, const WebTransformationMatrix& m) +{ + flattened[0] = m.m11(); + flattened[1] = m.m12(); + flattened[2] = m.m13(); + flattened[3] = m.m14(); + flattened[4] = m.m21(); + flattened[5] = m.m22(); + flattened[6] = m.m23(); + flattened[7] = m.m24(); + flattened[8] = m.m31(); + flattened[9] = m.m32(); + flattened[10] = m.m33(); + flattened[11] = m.m34(); + flattened[12] = m.m41(); + flattened[13] = m.m42(); + flattened[14] = m.m43(); + flattened[15] = m.m44(); +} + +void CCRendererGL::setShaderFloatQuad(const FloatQuad& quad, int quadLocation) +{ + if (quadLocation == -1) + return; + + float point[8]; + point[0] = quad.p1().x(); + point[1] = quad.p1().y(); + point[2] = quad.p2().x(); + point[3] = quad.p2().y(); + point[4] = quad.p3().x(); + point[5] = quad.p3().y(); + point[6] = quad.p4().x(); + point[7] = quad.p4().y(); + GLC(m_context, m_context->uniform2fv(quadLocation, 4, point)); +} + +void CCRendererGL::setShaderOpacity(float opacity, int alphaLocation) +{ + if (alphaLocation != -1) + GLC(m_context, m_context->uniform1f(alphaLocation, opacity)); +} + +void CCRendererGL::drawQuadGeometry(const DrawingFrame& frame, const WebKit::WebTransformationMatrix& drawTransform, const FloatRect& quadRect, int matrixLocation) +{ + WebTransformationMatrix quadRectMatrix; + quadRectTransform(&quadRectMatrix, drawTransform, quadRect); + static float glMatrix[16]; + toGLMatrix(&glMatrix[0], frame.projectionMatrix * quadRectMatrix); + GLC(m_context, m_context->uniformMatrix4fv(matrixLocation, 1, false, &glMatrix[0])); + + GLC(m_context, m_context->drawElements(GraphicsContext3D::TRIANGLES, 6, GraphicsContext3D::UNSIGNED_SHORT, 0)); +} + +void CCRendererGL::copyTextureToFramebuffer(const DrawingFrame& frame, int textureId, const IntRect& rect, const WebTransformationMatrix& drawMatrix) +{ + const RenderPassProgram* program = renderPassProgram(); + + GLC(context(), context()->activeTexture(GraphicsContext3D::TEXTURE0)); + GLC(context(), context()->bindTexture(GraphicsContext3D::TEXTURE_2D, textureId)); + GLC(context(), context()->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR)); + GLC(context(), context()->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR)); + GLC(context(), context()->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE)); + GLC(context(), context()->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE)); + + GLC(context(), context()->useProgram(program->program())); + GLC(context(), context()->uniform1i(program->fragmentShader().samplerLocation(), 0)); + setShaderOpacity(1, program->fragmentShader().alphaLocation()); + drawQuadGeometry(frame, drawMatrix, rect, program->vertexShader().matrixLocation()); +} + +void CCRendererGL::finish() +{ + TRACE_EVENT0("cc", "CCRendererGL::finish"); + m_context->finish(); +} + +bool CCRendererGL::swapBuffers() +{ + ASSERT(m_visible); + ASSERT(!m_isFramebufferDiscarded); + + TRACE_EVENT0("cc", "CCRendererGL::swapBuffers"); + // We're done! Time to swapbuffers! + + if (m_capabilities.usingPartialSwap) { + // If supported, we can save significant bandwidth by only swapping the damaged/scissored region (clamped to the viewport) + m_swapBufferRect.intersect(IntRect(IntPoint(), viewportSize())); + int flippedYPosOfRectBottom = viewportHeight() - m_swapBufferRect.y() - m_swapBufferRect.height(); + m_context->postSubBufferCHROMIUM(m_swapBufferRect.x(), flippedYPosOfRectBottom, m_swapBufferRect.width(), m_swapBufferRect.height()); + } else { + // Note that currently this has the same effect as swapBuffers; we should + // consider exposing a different entry point on WebGraphicsContext3D. + m_context->prepareTexture(); + } + + m_swapBufferRect = IntRect(); + + return true; +} + +void CCRendererGL::onSwapBuffersComplete() +{ + m_client->onSwapBuffersComplete(); +} + +void CCRendererGL::onMemoryAllocationChanged(WebGraphicsMemoryAllocation allocation) +{ + // FIXME: This is called on the main thread in single threaded mode, but we expect it on the impl thread. + if (!CCProxy::hasImplThread()) { + ASSERT(CCProxy::isMainThread()); + DebugScopedSetImplThread impl; + onMemoryAllocationChangedOnImplThread(allocation); + } else { + ASSERT(CCProxy::isImplThread()); + onMemoryAllocationChangedOnImplThread(allocation); + } +} + +void CCRendererGL::onMemoryAllocationChangedOnImplThread(WebKit::WebGraphicsMemoryAllocation allocation) +{ + if (m_visible && !allocation.gpuResourceSizeInBytes) + return; + + if (!allocation.suggestHaveBackbuffer && !m_visible) + discardFramebuffer(); + + if (!allocation.gpuResourceSizeInBytes) { + releaseRenderPassTextures(); + m_client->releaseContentsTextures(); + GLC(m_context, m_context->flush()); + } else + m_client->setMemoryAllocationLimitBytes(allocation.gpuResourceSizeInBytes); +} + +void CCRendererGL::discardFramebuffer() +{ + if (m_isFramebufferDiscarded) + return; + + if (!m_capabilities.usingDiscardFramebuffer) + return; + + // FIXME: Update attachments argument to appropriate values once they are no longer ignored. + m_context->discardFramebufferEXT(GraphicsContext3D::TEXTURE_2D, 0, 0); + m_isFramebufferDiscarded = true; + + // Damage tracker needs a full reset every time framebuffer is discarded. + m_client->setFullRootLayerDamage(); +} + +void CCRendererGL::ensureFramebuffer() +{ + if (!m_isFramebufferDiscarded) + return; + + if (!m_capabilities.usingDiscardFramebuffer) + return; + + m_context->ensureFramebufferCHROMIUM(); + m_isFramebufferDiscarded = false; +} + +void CCRendererGL::onContextLost() +{ + m_client->didLoseContext(); +} + + +void CCRendererGL::getFramebufferPixels(void *pixels, const IntRect& rect) +{ + ASSERT(rect.maxX() <= viewportWidth() && rect.maxY() <= viewportHeight()); + + if (!pixels) + return; + + makeContextCurrent(); + + bool doWorkaround = needsIOSurfaceReadbackWorkaround(); + + Platform3DObject temporaryTexture = 0; + Platform3DObject temporaryFBO = 0; + + if (doWorkaround) { + // On Mac OS X, calling glReadPixels against an FBO whose color attachment is an + // IOSurface-backed texture causes corruption of future glReadPixels calls, even those on + // different OpenGL contexts. It is believed that this is the root cause of top crasher + // http://crbug.com/99393. + + temporaryTexture = m_context->createTexture(); + GLC(m_context, m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, temporaryTexture)); + GLC(m_context, m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR)); + GLC(m_context, m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR)); + GLC(m_context, m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE)); + GLC(m_context, m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE)); + // Copy the contents of the current (IOSurface-backed) framebuffer into a temporary texture. + GLC(m_context, m_context->copyTexImage2D(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::RGBA, 0, 0, viewportSize().width(), viewportSize().height(), 0)); + temporaryFBO = m_context->createFramebuffer(); + // Attach this texture to an FBO, and perform the readback from that FBO. + GLC(m_context, m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, temporaryFBO)); + GLC(m_context, m_context->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE_2D, temporaryTexture, 0)); + + ASSERT(m_context->checkFramebufferStatus(GraphicsContext3D::FRAMEBUFFER) == GraphicsContext3D::FRAMEBUFFER_COMPLETE); + } + + OwnArrayPtr srcPixels = adoptArrayPtr(new uint8_t[rect.width() * rect.height() * 4]); + GLC(m_context, m_context->readPixels(rect.x(), viewportSize().height() - rect.maxY(), rect.width(), rect.height(), + GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, srcPixels.get())); + + uint8_t* destPixels = static_cast(pixels); + size_t rowBytes = rect.width() * 4; + int numRows = rect.height(); + size_t totalBytes = numRows * rowBytes; + for (size_t destY = 0; destY < totalBytes; destY += rowBytes) { + // Flip Y axis. + size_t srcY = totalBytes - destY - rowBytes; + // Swizzle BGRA -> RGBA. + for (size_t x = 0; x < rowBytes; x += 4) { + destPixels[destY + (x+0)] = srcPixels.get()[srcY + (x+2)]; + destPixels[destY + (x+1)] = srcPixels.get()[srcY + (x+1)]; + destPixels[destY + (x+2)] = srcPixels.get()[srcY + (x+0)]; + destPixels[destY + (x+3)] = srcPixels.get()[srcY + (x+3)]; + } + } + + if (doWorkaround) { + // Clean up. + GLC(m_context, m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, 0)); + GLC(m_context, m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, 0)); + GLC(m_context, m_context->deleteFramebuffer(temporaryFBO)); + GLC(m_context, m_context->deleteTexture(temporaryTexture)); + } + + if (!m_visible) { + TRACE_EVENT0("cc", "CCRendererGL::getFramebufferPixels dropping resources after readback"); + discardFramebuffer(); + releaseRenderPassTextures(); + m_client->releaseContentsTextures(); + GLC(m_context, m_context->flush()); + } +} + +bool CCRendererGL::getFramebufferTexture(CCScopedTexture* texture, const IntRect& deviceRect) +{ + ASSERT(!texture->id() || (texture->size() == deviceRect.size() && texture->format() == GraphicsContext3D::RGB)); + + if (!texture->id() && !texture->allocate(CCRenderer::ImplPool, deviceRect.size(), GraphicsContext3D::RGB, CCResourceProvider::TextureUsageAny)) + return false; + + CCResourceProvider::ScopedWriteLockGL lock(m_resourceProvider, texture->id()); + GLC(m_context, m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, lock.textureId())); + GLC(m_context, m_context->copyTexImage2D(GraphicsContext3D::TEXTURE_2D, 0, texture->format(), + deviceRect.x(), deviceRect.y(), deviceRect.width(), deviceRect.height(), 0)); + return true; +} + +bool CCRendererGL::useScopedTexture(DrawingFrame& frame, const CCScopedTexture* texture, const IntRect& viewportRect) +{ + ASSERT(texture->id()); + frame.currentRenderPass = 0; + frame.currentTexture = texture; + + return bindFramebufferToTexture(frame, texture, viewportRect); +} + +void CCRendererGL::bindFramebufferToOutputSurface(DrawingFrame& frame) +{ + m_currentFramebufferLock.clear(); + GLC(m_context, m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, 0)); +} + +bool CCRendererGL::bindFramebufferToTexture(DrawingFrame& frame, const CCScopedTexture* texture, const IntRect& framebufferRect) +{ + ASSERT(texture->id()); + + GLC(m_context, m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_offscreenFramebufferId)); + m_currentFramebufferLock = adoptPtr(new CCResourceProvider::ScopedWriteLockGL(m_resourceProvider, texture->id())); + unsigned textureId = m_currentFramebufferLock->textureId(); + GLC(m_context, m_context->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE_2D, textureId, 0)); + +#if !defined ( NDEBUG ) + if (m_context->checkFramebufferStatus(GraphicsContext3D::FRAMEBUFFER) != GraphicsContext3D::FRAMEBUFFER_COMPLETE) { + ASSERT_NOT_REACHED(); + return false; + } +#endif + + initializeMatrices(frame, framebufferRect, false); + setDrawViewportSize(framebufferRect.size()); + + return true; +} + +void CCRendererGL::enableScissorTestRect(const IntRect& scissorRect) +{ + GLC(m_context, m_context->enable(GraphicsContext3D::SCISSOR_TEST)); + GLC(m_context, m_context->scissor(scissorRect.x(), scissorRect.y(), scissorRect.width(), scissorRect.height())); +} + +void CCRendererGL::disableScissorTest() +{ + GLC(m_context, m_context->disable(GraphicsContext3D::SCISSOR_TEST)); +} + +void CCRendererGL::setDrawViewportSize(const IntSize& viewportSize) +{ + GLC(m_context, m_context->viewport(0, 0, viewportSize.width(), viewportSize.height())); +} + +bool CCRendererGL::makeContextCurrent() +{ + return m_context->makeContextCurrent(); +} + +bool CCRendererGL::initializeSharedObjects() +{ + TRACE_EVENT0("cc", "CCRendererGL::initializeSharedObjects"); + makeContextCurrent(); + + // Create an FBO for doing offscreen rendering. + GLC(m_context, m_offscreenFramebufferId = m_context->createFramebuffer()); + + // We will always need these programs to render, so create the programs eagerly so that the shader compilation can + // start while we do other work. Other programs are created lazily on first access. + m_sharedGeometry = adoptPtr(new GeometryBinding(m_context, quadVertexRect())); + m_renderPassProgram = adoptPtr(new RenderPassProgram(m_context)); + m_tileProgram = adoptPtr(new TileProgram(m_context)); + m_tileProgramOpaque = adoptPtr(new TileProgramOpaque(m_context)); + + GLC(m_context, m_context->flush()); + + return true; +} + +const CCRendererGL::TileCheckerboardProgram* CCRendererGL::tileCheckerboardProgram() +{ + if (!m_tileCheckerboardProgram) + m_tileCheckerboardProgram = adoptPtr(new TileCheckerboardProgram(m_context)); + if (!m_tileCheckerboardProgram->initialized()) { + TRACE_EVENT0("cc", "CCRendererGL::checkerboardProgram::initalize"); + m_tileCheckerboardProgram->initialize(m_context, m_isUsingBindUniform); + } + return m_tileCheckerboardProgram.get(); +} + +const CCRendererGL::SolidColorProgram* CCRendererGL::solidColorProgram() +{ + if (!m_solidColorProgram) + m_solidColorProgram = adoptPtr(new SolidColorProgram(m_context)); + if (!m_solidColorProgram->initialized()) { + TRACE_EVENT0("cc", "CCRendererGL::solidColorProgram::initialize"); + m_solidColorProgram->initialize(m_context, m_isUsingBindUniform); + } + return m_solidColorProgram.get(); +} + +const CCRendererGL::RenderPassProgram* CCRendererGL::renderPassProgram() +{ + ASSERT(m_renderPassProgram); + if (!m_renderPassProgram->initialized()) { + TRACE_EVENT0("cc", "CCRendererGL::renderPassProgram::initialize"); + m_renderPassProgram->initialize(m_context, m_isUsingBindUniform); + } + return m_renderPassProgram.get(); +} + +const CCRendererGL::RenderPassProgramAA* CCRendererGL::renderPassProgramAA() +{ + if (!m_renderPassProgramAA) + m_renderPassProgramAA = adoptPtr(new RenderPassProgramAA(m_context)); + if (!m_renderPassProgramAA->initialized()) { + TRACE_EVENT0("cc", "CCRendererGL::renderPassProgramAA::initialize"); + m_renderPassProgramAA->initialize(m_context, m_isUsingBindUniform); + } + return m_renderPassProgramAA.get(); +} + +const CCRendererGL::RenderPassMaskProgram* CCRendererGL::renderPassMaskProgram() +{ + if (!m_renderPassMaskProgram) + m_renderPassMaskProgram = adoptPtr(new RenderPassMaskProgram(m_context)); + if (!m_renderPassMaskProgram->initialized()) { + TRACE_EVENT0("cc", "CCRendererGL::renderPassMaskProgram::initialize"); + m_renderPassMaskProgram->initialize(m_context, m_isUsingBindUniform); + } + return m_renderPassMaskProgram.get(); +} + +const CCRendererGL::RenderPassMaskProgramAA* CCRendererGL::renderPassMaskProgramAA() +{ + if (!m_renderPassMaskProgramAA) + m_renderPassMaskProgramAA = adoptPtr(new RenderPassMaskProgramAA(m_context)); + if (!m_renderPassMaskProgramAA->initialized()) { + TRACE_EVENT0("cc", "CCRendererGL::renderPassMaskProgramAA::initialize"); + m_renderPassMaskProgramAA->initialize(m_context, m_isUsingBindUniform); + } + return m_renderPassMaskProgramAA.get(); +} + +const CCRendererGL::TileProgram* CCRendererGL::tileProgram() +{ + ASSERT(m_tileProgram); + if (!m_tileProgram->initialized()) { + TRACE_EVENT0("cc", "CCRendererGL::tileProgram::initialize"); + m_tileProgram->initialize(m_context, m_isUsingBindUniform); + } + return m_tileProgram.get(); +} + +const CCRendererGL::TileProgramOpaque* CCRendererGL::tileProgramOpaque() +{ + ASSERT(m_tileProgramOpaque); + if (!m_tileProgramOpaque->initialized()) { + TRACE_EVENT0("cc", "CCRendererGL::tileProgramOpaque::initialize"); + m_tileProgramOpaque->initialize(m_context, m_isUsingBindUniform); + } + return m_tileProgramOpaque.get(); +} + +const CCRendererGL::TileProgramAA* CCRendererGL::tileProgramAA() +{ + if (!m_tileProgramAA) + m_tileProgramAA = adoptPtr(new TileProgramAA(m_context)); + if (!m_tileProgramAA->initialized()) { + TRACE_EVENT0("cc", "CCRendererGL::tileProgramAA::initialize"); + m_tileProgramAA->initialize(m_context, m_isUsingBindUniform); + } + return m_tileProgramAA.get(); +} + +const CCRendererGL::TileProgramSwizzle* CCRendererGL::tileProgramSwizzle() +{ + if (!m_tileProgramSwizzle) + m_tileProgramSwizzle = adoptPtr(new TileProgramSwizzle(m_context)); + if (!m_tileProgramSwizzle->initialized()) { + TRACE_EVENT0("cc", "CCRendererGL::tileProgramSwizzle::initialize"); + m_tileProgramSwizzle->initialize(m_context, m_isUsingBindUniform); + } + return m_tileProgramSwizzle.get(); +} + +const CCRendererGL::TileProgramSwizzleOpaque* CCRendererGL::tileProgramSwizzleOpaque() +{ + if (!m_tileProgramSwizzleOpaque) + m_tileProgramSwizzleOpaque = adoptPtr(new TileProgramSwizzleOpaque(m_context)); + if (!m_tileProgramSwizzleOpaque->initialized()) { + TRACE_EVENT0("cc", "CCRendererGL::tileProgramSwizzleOpaque::initialize"); + m_tileProgramSwizzleOpaque->initialize(m_context, m_isUsingBindUniform); + } + return m_tileProgramSwizzleOpaque.get(); +} + +const CCRendererGL::TileProgramSwizzleAA* CCRendererGL::tileProgramSwizzleAA() +{ + if (!m_tileProgramSwizzleAA) + m_tileProgramSwizzleAA = adoptPtr(new TileProgramSwizzleAA(m_context)); + if (!m_tileProgramSwizzleAA->initialized()) { + TRACE_EVENT0("cc", "CCRendererGL::tileProgramSwizzleAA::initialize"); + m_tileProgramSwizzleAA->initialize(m_context, m_isUsingBindUniform); + } + return m_tileProgramSwizzleAA.get(); +} + +const CCRendererGL::TextureProgram* CCRendererGL::textureProgram() +{ + if (!m_textureProgram) + m_textureProgram = adoptPtr(new TextureProgram(m_context)); + if (!m_textureProgram->initialized()) { + TRACE_EVENT0("cc", "CCRendererGL::textureProgram::initialize"); + m_textureProgram->initialize(m_context, m_isUsingBindUniform); + } + return m_textureProgram.get(); +} + +const CCRendererGL::TextureProgramFlip* CCRendererGL::textureProgramFlip() +{ + if (!m_textureProgramFlip) + m_textureProgramFlip = adoptPtr(new TextureProgramFlip(m_context)); + if (!m_textureProgramFlip->initialized()) { + TRACE_EVENT0("cc", "CCRendererGL::textureProgramFlip::initialize"); + m_textureProgramFlip->initialize(m_context, m_isUsingBindUniform); + } + return m_textureProgramFlip.get(); +} + +const CCRendererGL::TextureIOSurfaceProgram* CCRendererGL::textureIOSurfaceProgram() +{ + if (!m_textureIOSurfaceProgram) + m_textureIOSurfaceProgram = adoptPtr(new TextureIOSurfaceProgram(m_context)); + if (!m_textureIOSurfaceProgram->initialized()) { + TRACE_EVENT0("cc", "CCRendererGL::textureIOSurfaceProgram::initialize"); + m_textureIOSurfaceProgram->initialize(m_context, m_isUsingBindUniform); + } + return m_textureIOSurfaceProgram.get(); +} + +const CCRendererGL::VideoYUVProgram* CCRendererGL::videoYUVProgram() +{ + if (!m_videoYUVProgram) + m_videoYUVProgram = adoptPtr(new VideoYUVProgram(m_context)); + if (!m_videoYUVProgram->initialized()) { + TRACE_EVENT0("cc", "CCRendererGL::videoYUVProgram::initialize"); + m_videoYUVProgram->initialize(m_context, m_isUsingBindUniform); + } + return m_videoYUVProgram.get(); +} + +const CCRendererGL::VideoStreamTextureProgram* CCRendererGL::videoStreamTextureProgram() +{ + if (!m_videoStreamTextureProgram) + m_videoStreamTextureProgram = adoptPtr(new VideoStreamTextureProgram(m_context)); + if (!m_videoStreamTextureProgram->initialized()) { + TRACE_EVENT0("cc", "CCRendererGL::streamTextureProgram::initialize"); + m_videoStreamTextureProgram->initialize(m_context, m_isUsingBindUniform); + } + return m_videoStreamTextureProgram.get(); +} + +void CCRendererGL::cleanupSharedObjects() +{ + makeContextCurrent(); + + m_sharedGeometry.clear(); + + if (m_tileProgram) + m_tileProgram->cleanup(m_context); + if (m_tileProgramOpaque) + m_tileProgramOpaque->cleanup(m_context); + if (m_tileProgramSwizzle) + m_tileProgramSwizzle->cleanup(m_context); + if (m_tileProgramSwizzleOpaque) + m_tileProgramSwizzleOpaque->cleanup(m_context); + if (m_tileProgramAA) + m_tileProgramAA->cleanup(m_context); + if (m_tileProgramSwizzleAA) + m_tileProgramSwizzleAA->cleanup(m_context); + if (m_tileCheckerboardProgram) + m_tileCheckerboardProgram->cleanup(m_context); + + if (m_renderPassMaskProgram) + m_renderPassMaskProgram->cleanup(m_context); + if (m_renderPassProgram) + m_renderPassProgram->cleanup(m_context); + if (m_renderPassMaskProgramAA) + m_renderPassMaskProgramAA->cleanup(m_context); + if (m_renderPassProgramAA) + m_renderPassProgramAA->cleanup(m_context); + + if (m_textureProgram) + m_textureProgram->cleanup(m_context); + if (m_textureProgramFlip) + m_textureProgramFlip->cleanup(m_context); + if (m_textureIOSurfaceProgram) + m_textureIOSurfaceProgram->cleanup(m_context); + + if (m_videoYUVProgram) + m_videoYUVProgram->cleanup(m_context); + if (m_videoStreamTextureProgram) + m_videoStreamTextureProgram->cleanup(m_context); + + if (m_solidColorProgram) + m_solidColorProgram->cleanup(m_context); + + if (m_offscreenFramebufferId) + GLC(m_context, m_context->deleteFramebuffer(m_offscreenFramebufferId)); + + releaseRenderPassTextures(); +} + +bool CCRendererGL::isContextLost() +{ + return (m_context->getGraphicsResetStatusARB() != GraphicsContext3D::NO_ERROR); +} + +} // namespace cc + +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/cc/gl_renderer.h b/cc/gl_renderer.h index 638cbb2..a5f2c4f 100644 --- a/cc/gl_renderer.h +++ b/cc/gl_renderer.h @@ -1,3 +1,240 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. +// Copyright 2010 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + + +#ifndef CCRendererGL_h +#define CCRendererGL_h + +#if USE(ACCELERATED_COMPOSITING) + +#include "base/basictypes.h" +#include "CCCheckerboardDrawQuad.h" +#include "CCDebugBorderDrawQuad.h" +#include "CCDirectRenderer.h" +#include "CCIOSurfaceDrawQuad.h" +#include "CCRenderPassDrawQuad.h" +#include "CCRenderer.h" +#include "CCSolidColorDrawQuad.h" +#include "CCStreamVideoDrawQuad.h" +#include "CCTextureDrawQuad.h" +#include "CCTileDrawQuad.h" +#include "CCYUVVideoDrawQuad.h" +#include "Extensions3DChromium.h" +#include + +namespace WebKit { +class WebGraphicsContext3D; +} + +namespace cc { + +class CCScopedTexture; +class GeometryBinding; +class ScopedEnsureFramebufferAllocation; + +// Class that handles drawing of composited render layers using GL. +class CCRendererGL : public CCDirectRenderer, + public WebKit::WebGraphicsContext3D::WebGraphicsSwapBuffersCompleteCallbackCHROMIUM, + public WebKit::WebGraphicsContext3D::WebGraphicsMemoryAllocationChangedCallbackCHROMIUM , + public WebKit::WebGraphicsContext3D::WebGraphicsContextLostCallback { +public: + static PassOwnPtr create(CCRendererClient*, CCResourceProvider*); + + virtual ~CCRendererGL(); + + virtual const RendererCapabilities& capabilities() const OVERRIDE; + + WebKit::WebGraphicsContext3D* context(); + + virtual void viewportChanged() OVERRIDE; + + const FloatQuad& sharedGeometryQuad() const { return m_sharedGeometryQuad; } + + // waits for rendering to finish + virtual void finish() OVERRIDE; + + virtual void doNoOp() OVERRIDE; + // puts backbuffer onscreen + virtual bool swapBuffers() OVERRIDE; + + static void debugGLCall(WebKit::WebGraphicsContext3D*, const char* command, const char* file, int line); + + const GeometryBinding* sharedGeometry() const { return m_sharedGeometry.get(); } + + virtual void getFramebufferPixels(void *pixels, const IntRect&) OVERRIDE; + bool getFramebufferTexture(CCScopedTexture*, const IntRect& deviceRect); + + virtual bool isContextLost() OVERRIDE; + + virtual void setVisible(bool) OVERRIDE; + +protected: + CCRendererGL(CCRendererClient*, CCResourceProvider*); + + bool isFramebufferDiscarded() const { return m_isFramebufferDiscarded; } + bool initialize(); + + void releaseRenderPassTextures(); + + virtual void bindFramebufferToOutputSurface(DrawingFrame&) OVERRIDE; + virtual bool bindFramebufferToTexture(DrawingFrame&, const CCScopedTexture*, const IntRect& framebufferRect) OVERRIDE; + virtual void setDrawViewportSize(const IntSize&) OVERRIDE; + virtual void enableScissorTestRect(const IntRect& scissorRect) OVERRIDE; + virtual void disableScissorTest() OVERRIDE; + virtual void clearFramebuffer(DrawingFrame&) OVERRIDE; + virtual void drawQuad(DrawingFrame&, const CCDrawQuad*) OVERRIDE; + virtual void beginDrawingFrame(DrawingFrame&) OVERRIDE; + virtual void finishDrawingFrame(DrawingFrame&) OVERRIDE; + virtual bool flippedFramebuffer() const OVERRIDE; + +private: + static void toGLMatrix(float*, const WebKit::WebTransformationMatrix&); + + void drawCheckerboardQuad(const DrawingFrame&, const CCCheckerboardDrawQuad*); + void drawDebugBorderQuad(const DrawingFrame&, const CCDebugBorderDrawQuad*); + PassOwnPtr drawBackgroundFilters(DrawingFrame&, const CCRenderPassDrawQuad*, const WebKit::WebFilterOperations&, const WebKit::WebTransformationMatrix& deviceTransform); + void drawRenderPassQuad(DrawingFrame&, const CCRenderPassDrawQuad*); + void drawSolidColorQuad(const DrawingFrame&, const CCSolidColorDrawQuad*); + void drawStreamVideoQuad(const DrawingFrame&, const CCStreamVideoDrawQuad*); + void drawTextureQuad(const DrawingFrame&, const CCTextureDrawQuad*); + void drawIOSurfaceQuad(const DrawingFrame&, const CCIOSurfaceDrawQuad*); + void drawTileQuad(const DrawingFrame&, const CCTileDrawQuad*); + void drawYUVVideoQuad(const DrawingFrame&, const CCYUVVideoDrawQuad*); + + void setShaderOpacity(float opacity, int alphaLocation); + void setShaderFloatQuad(const FloatQuad&, int quadLocation); + void drawQuadGeometry(const DrawingFrame&, const WebKit::WebTransformationMatrix& drawTransform, const FloatRect& quadRect, int matrixLocation); + + void copyTextureToFramebuffer(const DrawingFrame&, int textureId, const IntRect&, const WebKit::WebTransformationMatrix& drawMatrix); + + bool useScopedTexture(DrawingFrame&, const CCScopedTexture*, const IntRect& viewportRect); + + bool makeContextCurrent(); + + bool initializeSharedObjects(); + void cleanupSharedObjects(); + + // WebKit::WebGraphicsContext3D::WebGraphicsSwapBuffersCompleteCallbackCHROMIUM implementation. + virtual void onSwapBuffersComplete() OVERRIDE; + + // WebKit::WebGraphicsContext3D::WebGraphicsMemoryAllocationChangedCallbackCHROMIUM implementation. + virtual void onMemoryAllocationChanged(WebKit::WebGraphicsMemoryAllocation) OVERRIDE; + void onMemoryAllocationChangedOnImplThread(WebKit::WebGraphicsMemoryAllocation); + void discardFramebuffer(); + void ensureFramebuffer(); + + // WebGraphicsContext3D::WebGraphicsContextLostCallback implementation. + virtual void onContextLost() OVERRIDE; + + RendererCapabilities m_capabilities; + + unsigned m_offscreenFramebufferId; + + OwnPtr m_sharedGeometry; + FloatQuad m_sharedGeometryQuad; + + // This block of bindings defines all of the programs used by the compositor itself. + + // Tiled layer shaders. + typedef ProgramBinding TileProgram; + typedef ProgramBinding TileProgramAA; + typedef ProgramBinding TileProgramSwizzleAA; + typedef ProgramBinding TileProgramOpaque; + typedef ProgramBinding TileProgramSwizzle; + typedef ProgramBinding TileProgramSwizzleOpaque; + typedef ProgramBinding TileCheckerboardProgram; + + // Render surface shaders. + typedef ProgramBinding RenderPassProgram; + typedef ProgramBinding RenderPassMaskProgram; + typedef ProgramBinding RenderPassProgramAA; + typedef ProgramBinding RenderPassMaskProgramAA; + + // Texture shaders. + typedef ProgramBinding TextureProgram; + typedef ProgramBinding TextureProgramFlip; + typedef ProgramBinding TextureIOSurfaceProgram; + + // Video shaders. + typedef ProgramBinding VideoStreamTextureProgram; + typedef ProgramBinding VideoYUVProgram; + + // Special purpose / effects shaders. + typedef ProgramBinding SolidColorProgram; + + const TileProgram* tileProgram(); + const TileProgramOpaque* tileProgramOpaque(); + const TileProgramAA* tileProgramAA(); + const TileProgramSwizzle* tileProgramSwizzle(); + const TileProgramSwizzleOpaque* tileProgramSwizzleOpaque(); + const TileProgramSwizzleAA* tileProgramSwizzleAA(); + const TileCheckerboardProgram* tileCheckerboardProgram(); + + const RenderPassProgram* renderPassProgram(); + const RenderPassProgramAA* renderPassProgramAA(); + const RenderPassMaskProgram* renderPassMaskProgram(); + const RenderPassMaskProgramAA* renderPassMaskProgramAA(); + + const TextureProgram* textureProgram(); + const TextureProgramFlip* textureProgramFlip(); + const TextureIOSurfaceProgram* textureIOSurfaceProgram(); + + const VideoYUVProgram* videoYUVProgram(); + const VideoStreamTextureProgram* videoStreamTextureProgram(); + + const SolidColorProgram* solidColorProgram(); + + OwnPtr m_tileProgram; + OwnPtr m_tileProgramOpaque; + OwnPtr m_tileProgramAA; + OwnPtr m_tileProgramSwizzle; + OwnPtr m_tileProgramSwizzleOpaque; + OwnPtr m_tileProgramSwizzleAA; + OwnPtr m_tileCheckerboardProgram; + + OwnPtr m_renderPassProgram; + OwnPtr m_renderPassProgramAA; + OwnPtr m_renderPassMaskProgram; + OwnPtr m_renderPassMaskProgramAA; + + OwnPtr m_textureProgram; + OwnPtr m_textureProgramFlip; + OwnPtr m_textureIOSurfaceProgram; + + OwnPtr m_videoYUVProgram; + OwnPtr m_videoStreamTextureProgram; + + OwnPtr m_solidColorProgram; + + WebKit::WebGraphicsContext3D* m_context; + + IntRect m_swapBufferRect; + bool m_isViewportChanged; + bool m_isFramebufferDiscarded; + bool m_isUsingBindUniform; + bool m_visible; + + OwnPtr m_currentFramebufferLock; + + DISALLOW_COPY_AND_ASSIGN(CCRendererGL); +}; + + +// Setting DEBUG_GL_CALLS to 1 will call glGetError() after almost every GL +// call made by the compositor. Useful for debugging rendering issues but +// will significantly degrade performance. +#define DEBUG_GL_CALLS 0 + +#if DEBUG_GL_CALLS && !defined ( NDEBUG ) +#define GLC(context, x) (x, CCRendererGL::debugGLCall(&*context, #x, __FILE__, __LINE__)) +#else +#define GLC(context, x) (x) +#endif + + +} + +#endif // USE(ACCELERATED_COMPOSITING) + +#endif diff --git a/cc/graphics_context.h b/cc/graphics_context.h index 638cbb2..6eb5b34 100644 --- a/cc/graphics_context.h +++ b/cc/graphics_context.h @@ -1,3 +1,18 @@ // Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CCGraphicsContext_h +#define CCGraphicsContext_h + +#include +#include + +namespace cc { + +// FIXME: rename fully to CCOutputSurface. +typedef WebKit::WebCompositorOutputSurface CCGraphicsContext; + +} // namespace cc + +#endif // CCGraphicsContext_h diff --git a/cc/heads_up_display_layer.cc b/cc/heads_up_display_layer.cc new file mode 100644 index 0000000..743593c --- /dev/null +++ b/cc/heads_up_display_layer.cc @@ -0,0 +1,75 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#include "HeadsUpDisplayLayerChromium.h" + +#include "CCHeadsUpDisplayLayerImpl.h" +#include "CCLayerTreeHost.h" +#include "TraceEvent.h" + +namespace cc { + +scoped_refptr HeadsUpDisplayLayerChromium::create() +{ + return make_scoped_refptr(new HeadsUpDisplayLayerChromium()); +} + +HeadsUpDisplayLayerChromium::HeadsUpDisplayLayerChromium() + : LayerChromium() +{ + + setBounds(IntSize(512, 128)); +} + +HeadsUpDisplayLayerChromium::~HeadsUpDisplayLayerChromium() +{ +} + +void HeadsUpDisplayLayerChromium::update(CCTextureUpdateQueue&, const CCOcclusionTracker*, CCRenderingStats&) +{ + const CCLayerTreeSettings& settings = layerTreeHost()->settings(); + int maxTextureSize = layerTreeHost()->rendererCapabilities().maxTextureSize; + + IntSize bounds; + if (settings.showPlatformLayerTree || settings.showDebugRects()) { + bounds.setWidth(std::min(maxTextureSize, layerTreeHost()->deviceViewportSize().width())); + bounds.setHeight(std::min(maxTextureSize, layerTreeHost()->deviceViewportSize().height())); + } else { + bounds.setWidth(512); + bounds.setHeight(128); + } + + setBounds(bounds); +} + +bool HeadsUpDisplayLayerChromium::drawsContent() const +{ + return true; +} + +void HeadsUpDisplayLayerChromium::setFontAtlas(scoped_ptr fontAtlas) +{ + m_fontAtlas = fontAtlas.Pass(); + setNeedsCommit(); +} + +scoped_ptr HeadsUpDisplayLayerChromium::createCCLayerImpl() +{ + return CCHeadsUpDisplayLayerImpl::create(m_layerId).PassAs(); +} + +void HeadsUpDisplayLayerChromium::pushPropertiesTo(CCLayerImpl* layerImpl) +{ + LayerChromium::pushPropertiesTo(layerImpl); + + if (!m_fontAtlas.get()) + return; + + CCHeadsUpDisplayLayerImpl* hudLayerImpl = static_cast(layerImpl); + hudLayerImpl->setFontAtlas(m_fontAtlas.Pass()); +} + +} diff --git a/cc/heads_up_display_layer.h b/cc/heads_up_display_layer.h index 638cbb2..cd2627e 100644 --- a/cc/heads_up_display_layer.h +++ b/cc/heads_up_display_layer.h @@ -1,3 +1,38 @@ // Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef HeadsUpDisplayLayerChromium_h +#define HeadsUpDisplayLayerChromium_h + +#include "base/memory/scoped_ptr.h" +#include "CCFontAtlas.h" +#include "IntSize.h" +#include "LayerChromium.h" + +namespace cc { + +class HeadsUpDisplayLayerChromium : public LayerChromium { +public: + static scoped_refptr create(); + + virtual void update(CCTextureUpdateQueue&, const CCOcclusionTracker*, CCRenderingStats&) OVERRIDE; + virtual bool drawsContent() const OVERRIDE; + + void setFontAtlas(scoped_ptr); + + virtual scoped_ptr createCCLayerImpl() OVERRIDE; + virtual void pushPropertiesTo(CCLayerImpl*) OVERRIDE; + +protected: + HeadsUpDisplayLayerChromium(); + +private: + virtual ~HeadsUpDisplayLayerChromium(); + + scoped_ptr m_fontAtlas; +}; + +} // namespace cc + +#endif diff --git a/cc/heads_up_display_layer_impl.cc b/cc/heads_up_display_layer_impl.cc new file mode 100644 index 0000000..58a490e --- /dev/null +++ b/cc/heads_up_display_layer_impl.cc @@ -0,0 +1,296 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#include "CCHeadsUpDisplayLayerImpl.h" + +#include "base/stringprintf.h" +#include "ui/gfx/point.h" +#include "CCDebugRectHistory.h" +#include "CCFontAtlas.h" +#include "CCFrameRateCounter.h" +#include "CCLayerTreeHostImpl.h" +#include "CCQuadSink.h" +#include "CCTextureDrawQuad.h" +#include "Extensions3DChromium.h" +#include "GraphicsContext3D.h" +#include "SkBitmap.h" +#include "SkColorMatrixFilter.h" +#include "SkPaint.h" +#include "skia/ext/platform_canvas.h" + +namespace cc { + +static inline SkPaint createPaint() +{ + // The SkCanvas is in RGBA but the shader is expecting BGRA, so we need to + // swizzle our colors when drawing to the SkCanvas. + SkColorMatrix swizzleMatrix; + for (int i = 0; i < 20; ++i) + swizzleMatrix.fMat[i] = 0; + swizzleMatrix.fMat[0 + 5 * 2] = 1; + swizzleMatrix.fMat[1 + 5 * 1] = 1; + swizzleMatrix.fMat[2 + 5 * 0] = 1; + swizzleMatrix.fMat[3 + 5 * 3] = 1; + + SkPaint paint; + paint.setColorFilter(new SkColorMatrixFilter(swizzleMatrix))->unref(); + return paint; +} + +CCHeadsUpDisplayLayerImpl::CCHeadsUpDisplayLayerImpl(int id) + : CCLayerImpl(id) +{ +} + +CCHeadsUpDisplayLayerImpl::~CCHeadsUpDisplayLayerImpl() +{ +} + +void CCHeadsUpDisplayLayerImpl::setFontAtlas(scoped_ptr fontAtlas) +{ + m_fontAtlas = fontAtlas.Pass(); +} + +void CCHeadsUpDisplayLayerImpl::willDraw(CCResourceProvider* resourceProvider) +{ + CCLayerImpl::willDraw(resourceProvider); + + if (!m_hudTexture) + m_hudTexture = CCScopedTexture::create(resourceProvider); + + // FIXME: Scale the HUD by deviceScale to make it more friendly under high DPI. + + if (m_hudTexture->size() != bounds()) + m_hudTexture->free(); + + if (!m_hudTexture->id()) + m_hudTexture->allocate(CCRenderer::ImplPool, bounds(), GraphicsContext3D::RGBA, CCResourceProvider::TextureUsageAny); +} + +void CCHeadsUpDisplayLayerImpl::appendQuads(CCQuadSink& quadSink, CCAppendQuadsData& appendQuadsData) +{ + if (!m_hudTexture->id()) + return; + + CCSharedQuadState* sharedQuadState = quadSink.useSharedQuadState(createSharedQuadState()); + + IntRect quadRect(IntPoint(), bounds()); + bool premultipliedAlpha = true; + FloatRect uvRect(0, 0, 1, 1); + bool flipped = false; + quadSink.append(CCTextureDrawQuad::create(sharedQuadState, quadRect, m_hudTexture->id(), premultipliedAlpha, uvRect, flipped).PassAs(), appendQuadsData); +} + +void CCHeadsUpDisplayLayerImpl::updateHudTexture(CCResourceProvider* resourceProvider) +{ + if (!m_hudTexture->id()) + return; + + SkISize canvasSize; + if (m_hudCanvas) + canvasSize = m_hudCanvas->getDeviceSize(); + else + canvasSize.set(0, 0); + + if (canvasSize.fWidth != bounds().width() || canvasSize.fHeight != bounds().height() || !m_hudCanvas) + m_hudCanvas = adoptPtr(skia::CreateBitmapCanvas(bounds().width(), bounds().height(), false /* opaque */)); + + m_hudCanvas->clear(SkColorSetARGB(0, 0, 0, 0)); + drawHudContents(m_hudCanvas.get()); + + const SkBitmap* bitmap = &m_hudCanvas->getDevice()->accessBitmap(false); + SkAutoLockPixels locker(*bitmap); + + IntRect layerRect(IntPoint(), bounds()); + ASSERT(bitmap->config() == SkBitmap::kARGB_8888_Config); + resourceProvider->upload(m_hudTexture->id(), static_cast(bitmap->getPixels()), layerRect, layerRect, IntSize()); +} + +void CCHeadsUpDisplayLayerImpl::didDraw(CCResourceProvider* resourceProvider) +{ + CCLayerImpl::didDraw(resourceProvider); + + if (!m_hudTexture->id()) + return; + + // FIXME: the following assert will not be true when sending resources to a + // parent compositor. We will probably need to hold on to m_hudTexture for + // longer, and have several HUD textures in the pipeline. + ASSERT(!resourceProvider->inUseByConsumer(m_hudTexture->id())); +} + +void CCHeadsUpDisplayLayerImpl::didLoseContext() +{ + m_hudTexture.clear(); +} + +bool CCHeadsUpDisplayLayerImpl::layerIsAlwaysDamaged() const +{ + return true; +} + +void CCHeadsUpDisplayLayerImpl::drawHudContents(SkCanvas* canvas) +{ + const CCLayerTreeSettings& settings = layerTreeHostImpl()->settings(); + + if (settings.showPlatformLayerTree) { + SkPaint paint = createPaint(); + paint.setColor(SkColorSetARGB(192, 0, 0, 0)); + canvas->drawRect(SkRect::MakeXYWH(0, 0, bounds().width(), bounds().height()), paint); + } + + int fpsCounterHeight = 40; + int fpsCounterTop = 2; + int platformLayerTreeTop; + + if (settings.showFPSCounter) + platformLayerTreeTop = fpsCounterTop + fpsCounterHeight; + else + platformLayerTreeTop = 0; + + if (settings.showFPSCounter) + drawFPSCounter(canvas, layerTreeHostImpl()->fpsCounter(), fpsCounterTop, fpsCounterHeight); + + if (settings.showPlatformLayerTree && m_fontAtlas.get()) { + std::string layerTree = layerTreeHostImpl()->layerTreeAsText(); + m_fontAtlas->drawText(canvas, createPaint(), layerTree, gfx::Point(2, platformLayerTreeTop), bounds()); + } + + if (settings.showDebugRects()) + drawDebugRects(canvas, layerTreeHostImpl()->debugRectHistory()); +} + +void CCHeadsUpDisplayLayerImpl::drawFPSCounter(SkCanvas* canvas, CCFrameRateCounter* fpsCounter, int top, int height) +{ + float textWidth = 170; // so text fits on linux. + float graphWidth = fpsCounter->timeStampHistorySize(); + + // Draw the FPS text. + drawFPSCounterText(canvas, fpsCounter, top, textWidth, height); + + // Draw FPS graph. + const double loFPS = 0; + const double hiFPS = 80; + SkPaint paint = createPaint(); + paint.setColor(SkColorSetRGB(154, 205, 50)); + canvas->drawRect(SkRect::MakeXYWH(2 + textWidth, top, graphWidth, height / 2), paint); + + paint.setColor(SkColorSetRGB(255, 250, 205)); + canvas->drawRect(SkRect::MakeXYWH(2 + textWidth, top + height / 2, graphWidth, height / 2), paint); + + int graphLeft = static_cast(textWidth + 3); + int x = 0; + double h = static_cast(height - 2); + SkPath path; + for (int i = 0; i < fpsCounter->timeStampHistorySize() - 1; ++i) { + int j = i + 1; + double delta = fpsCounter->timeStampOfRecentFrame(j) - fpsCounter->timeStampOfRecentFrame(i); + + // Skip plotting this particular instantaneous frame rate if it is not likely to have been valid. + if (fpsCounter->isBadFrameInterval(delta)) { + x += 1; + continue; + } + + double fps = 1.0 / delta; + + // Clamp the FPS to the range we want to plot visually. + double p = 1 - ((fps - loFPS) / (hiFPS - loFPS)); + if (p < 0) + p = 0; + if (p > 1) + p = 1; + + // Plot this data point. + SkPoint cur = SkPoint::Make(graphLeft + x, 1 + top + p*h); + if (path.isEmpty()) + path.moveTo(cur); + else + path.lineTo(cur); + x += 1; + } + paint.setColor(SK_ColorRED); + paint.setStyle(SkPaint::kStroke_Style); + paint.setStrokeWidth(1); + paint.setAntiAlias(true); + canvas->drawPath(path, paint); +} + +void CCHeadsUpDisplayLayerImpl::drawFPSCounterText(SkCanvas* canvas, CCFrameRateCounter* fpsCounter, int top, int width, int height) +{ + double averageFPS, stdDeviation; + fpsCounter->getAverageFPSAndStandardDeviation(averageFPS, stdDeviation); + + // Draw background. + SkPaint paint = createPaint(); + paint.setColor(SK_ColorBLACK); + canvas->drawRect(SkRect::MakeXYWH(2, top, width, height), paint); + + // Draw FPS text. + if (m_fontAtlas.get()) + m_fontAtlas->drawText(canvas, createPaint(), base::StringPrintf("FPS: %4.1f +/- %3.1f", averageFPS, stdDeviation), gfx::Point(10, height / 3), IntSize(width, height)); +} + +void CCHeadsUpDisplayLayerImpl::drawDebugRects(SkCanvas* canvas, CCDebugRectHistory* debugRectHistory) +{ + const Vector& debugRects = debugRectHistory->debugRects(); + + for (size_t i = 0; i < debugRects.size(); ++i) { + SkColor strokeColor = 0; + SkColor fillColor = 0; + + switch (debugRects[i].type) { + case PaintRectType: + // Paint rects in red + strokeColor = SkColorSetARGB(255, 255, 0, 0); + fillColor = SkColorSetARGB(30, 255, 0, 0); + break; + case PropertyChangedRectType: + // Property-changed rects in blue + strokeColor = SkColorSetARGB(255, 255, 0, 0); + fillColor = SkColorSetARGB(30, 0, 0, 255); + break; + case SurfaceDamageRectType: + // Surface damage rects in yellow-orange + strokeColor = SkColorSetARGB(255, 200, 100, 0); + fillColor = SkColorSetARGB(30, 200, 100, 0); + break; + case ReplicaScreenSpaceRectType: + // Screen space rects in green. + strokeColor = SkColorSetARGB(255, 100, 200, 0); + fillColor = SkColorSetARGB(30, 100, 200, 0); + break; + case ScreenSpaceRectType: + // Screen space rects in purple. + strokeColor = SkColorSetARGB(255, 100, 0, 200); + fillColor = SkColorSetARGB(10, 100, 0, 200); + break; + case OccludingRectType: + // Occluding rects in a reddish color. + strokeColor = SkColorSetARGB(255, 200, 0, 100); + fillColor = SkColorSetARGB(10, 200, 0, 100); + break; + } + + const FloatRect& rect = debugRects[i].rect; + SkRect skRect = SkRect::MakeXYWH(rect.x(), rect.y(), rect.width(), rect.height()); + SkPaint paint = createPaint(); + paint.setColor(fillColor); + canvas->drawRect(skRect, paint); + + paint.setColor(strokeColor); + paint.setStyle(SkPaint::kStroke_Style); + paint.setStrokeWidth(2); + canvas->drawRect(skRect, paint); + } +} + +const char* CCHeadsUpDisplayLayerImpl::layerTypeAsString() const +{ + return "HeadsUpDisplayLayer"; +} + +} diff --git a/cc/heads_up_display_layer_impl.h b/cc/heads_up_display_layer_impl.h index 638cbb2..47e7cfe 100644 --- a/cc/heads_up_display_layer_impl.h +++ b/cc/heads_up_display_layer_impl.h @@ -1,3 +1,57 @@ // Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CCHeadsUpDisplayLayerImpl_h +#define CCHeadsUpDisplayLayerImpl_h + +#include "base/memory/scoped_ptr.h" +#include "CCFontAtlas.h" +#include "CCLayerImpl.h" +#include "CCScopedTexture.h" + +class SkCanvas; + +namespace cc { + +class CCDebugRectHistory; +class CCFontAtlas; +class CCFrameRateCounter; + +class CCHeadsUpDisplayLayerImpl : public CCLayerImpl { +public: + static scoped_ptr create(int id) + { + return make_scoped_ptr(new CCHeadsUpDisplayLayerImpl(id)); + } + virtual ~CCHeadsUpDisplayLayerImpl(); + + void setFontAtlas(scoped_ptr); + + virtual void willDraw(CCResourceProvider*) OVERRIDE; + virtual void appendQuads(CCQuadSink&, CCAppendQuadsData&) OVERRIDE; + void updateHudTexture(CCResourceProvider*); + virtual void didDraw(CCResourceProvider*) OVERRIDE; + + virtual void didLoseContext() OVERRIDE; + + virtual bool layerIsAlwaysDamaged() const OVERRIDE; + +private: + explicit CCHeadsUpDisplayLayerImpl(int); + + virtual const char* layerTypeAsString() const OVERRIDE; + + void drawHudContents(SkCanvas*); + void drawFPSCounter(SkCanvas*, CCFrameRateCounter*, int top, int height); + void drawFPSCounterText(SkCanvas*, CCFrameRateCounter*, int top, int width, int height); + void drawDebugRects(SkCanvas*, CCDebugRectHistory*); + + scoped_ptr m_fontAtlas; + OwnPtr m_hudTexture; + OwnPtr m_hudCanvas; +}; + +} // namespace cc + +#endif // CCHeadsUpDisplayLayerImpl_h diff --git a/cc/image_layer.cc b/cc/image_layer.cc new file mode 100644 index 0000000..c98796b --- /dev/null +++ b/cc/image_layer.cc @@ -0,0 +1,163 @@ +// Copyright 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#if USE(ACCELERATED_COMPOSITING) + +#include "ImageLayerChromium.h" + +#include "base/compiler_specific.h" +#include "CCLayerTreeHost.h" +#include "LayerTextureUpdater.h" +#include "PlatformColor.h" + +namespace cc { + +class ImageLayerTextureUpdater : public LayerTextureUpdater { +public: + class Texture : public LayerTextureUpdater::Texture { + public: + Texture(ImageLayerTextureUpdater* textureUpdater, scoped_ptr texture) + : LayerTextureUpdater::Texture(texture.Pass()) + , m_textureUpdater(textureUpdater) + { + } + + virtual void updateRect(CCResourceProvider* resourceProvider, const IntRect& sourceRect, const IntSize& destOffset) OVERRIDE + { + textureUpdater()->updateTextureRect(resourceProvider, texture(), sourceRect, destOffset); + } + + private: + ImageLayerTextureUpdater* textureUpdater() { return m_textureUpdater; } + + ImageLayerTextureUpdater* m_textureUpdater; + }; + + static PassRefPtr create() + { + return adoptRef(new ImageLayerTextureUpdater()); + } + + virtual ~ImageLayerTextureUpdater() { } + + virtual PassOwnPtr createTexture( + CCPrioritizedTextureManager* manager) OVERRIDE + { + return adoptPtr(new Texture(this, CCPrioritizedTexture::create(manager))); + } + + virtual SampledTexelFormat sampledTexelFormat(GC3Denum textureFormat) OVERRIDE + { + return PlatformColor::sameComponentOrder(textureFormat) ? + LayerTextureUpdater::SampledTexelFormatRGBA : LayerTextureUpdater::SampledTexelFormatBGRA; + } + + void updateTextureRect(CCResourceProvider* resourceProvider, CCPrioritizedTexture* texture, const IntRect& sourceRect, const IntSize& destOffset) + { + // Source rect should never go outside the image pixels, even if this + // is requested because the texture extends outside the image. + IntRect clippedSourceRect = sourceRect; + IntRect imageRect = IntRect(0, 0, m_bitmap.width(), m_bitmap.height()); + clippedSourceRect.intersect(imageRect); + + IntSize clippedDestOffset = destOffset + IntSize(clippedSourceRect.location() - sourceRect.location()); + + SkAutoLockPixels lock(m_bitmap); + texture->upload(resourceProvider, static_cast(m_bitmap.getPixels()), imageRect, clippedSourceRect, clippedDestOffset); + } + + void setBitmap(const SkBitmap& bitmap) + { + m_bitmap = bitmap; + } + +private: + ImageLayerTextureUpdater() { } + + SkBitmap m_bitmap; +}; + +scoped_refptr ImageLayerChromium::create() +{ + return make_scoped_refptr(new ImageLayerChromium()); +} + +ImageLayerChromium::ImageLayerChromium() + : TiledLayerChromium() +{ +} + +ImageLayerChromium::~ImageLayerChromium() +{ +} + +void ImageLayerChromium::setBitmap(const SkBitmap& bitmap) +{ + // setBitmap() currently gets called whenever there is any + // style change that affects the layer even if that change doesn't + // affect the actual contents of the image (e.g. a CSS animation). + // With this check in place we avoid unecessary texture uploads. + if (bitmap.pixelRef() && bitmap.pixelRef() == m_bitmap.pixelRef()) + return; + + m_bitmap = bitmap; + setNeedsDisplay(); +} + +void ImageLayerChromium::setTexturePriorities(const CCPriorityCalculator& priorityCalc) +{ + // Update the tile data before creating all the layer's tiles. + updateTileSizeAndTilingOption(); + + TiledLayerChromium::setTexturePriorities(priorityCalc); +} + +void ImageLayerChromium::update(CCTextureUpdateQueue& queue, const CCOcclusionTracker* occlusion, CCRenderingStats& stats) +{ + createTextureUpdaterIfNeeded(); + if (m_needsDisplay) { + m_textureUpdater->setBitmap(m_bitmap); + updateTileSizeAndTilingOption(); + invalidateContentRect(IntRect(IntPoint(), contentBounds())); + m_needsDisplay = false; + } + TiledLayerChromium::update(queue, occlusion, stats); +} + +void ImageLayerChromium::createTextureUpdaterIfNeeded() +{ + if (m_textureUpdater) + return; + + m_textureUpdater = ImageLayerTextureUpdater::create(); + GC3Denum textureFormat = layerTreeHost()->rendererCapabilities().bestTextureFormat; + setTextureFormat(textureFormat); + setSampledTexelFormat(textureUpdater()->sampledTexelFormat(textureFormat)); +} + +LayerTextureUpdater* ImageLayerChromium::textureUpdater() const +{ + return m_textureUpdater.get(); +} + +IntSize ImageLayerChromium::contentBounds() const +{ + return IntSize(m_bitmap.width(), m_bitmap.height()); +} + +bool ImageLayerChromium::drawsContent() const +{ + return !m_bitmap.isNull() && TiledLayerChromium::drawsContent(); +} + +bool ImageLayerChromium::needsContentsScale() const +{ + // Contents scale is not need for image layer because this can be done in compositor more efficiently. + return false; +} + +} +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/cc/image_layer.h b/cc/image_layer.h index 638cbb2..12ac397 100644 --- a/cc/image_layer.h +++ b/cc/image_layer.h @@ -1,3 +1,48 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. +// Copyright 2010 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + + +#ifndef ImageLayerChromium_h +#define ImageLayerChromium_h + +#if USE(ACCELERATED_COMPOSITING) + +#include "ContentLayerChromium.h" +#include "SkBitmap.h" + +namespace cc { + +class ImageLayerTextureUpdater; + +// A Layer that contains only an Image element. +class ImageLayerChromium : public TiledLayerChromium { +public: + static scoped_refptr create(); + + virtual bool drawsContent() const OVERRIDE; + virtual void setTexturePriorities(const CCPriorityCalculator&) OVERRIDE; + virtual void update(CCTextureUpdateQueue&, const CCOcclusionTracker*, CCRenderingStats&) OVERRIDE; + virtual bool needsContentsScale() const OVERRIDE; + + void setBitmap(const SkBitmap& image); + +private: + ImageLayerChromium(); + virtual ~ImageLayerChromium(); + + void setTilingOption(TilingOption); + + virtual LayerTextureUpdater* textureUpdater() const OVERRIDE; + virtual void createTextureUpdaterIfNeeded() OVERRIDE; + virtual IntSize contentBounds() const OVERRIDE; + + SkBitmap m_bitmap; + + RefPtr m_textureUpdater; +}; + +} +#endif // USE(ACCELERATED_COMPOSITING) + +#endif diff --git a/cc/input_handler.h b/cc/input_handler.h index 638cbb2..7188cab 100644 --- a/cc/input_handler.h +++ b/cc/input_handler.h @@ -1,3 +1,83 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. +// Copyright 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CCInputHandler_h +#define CCInputHandler_h + +#include "base/basictypes.h" +#include + +namespace cc { + +class IntPoint; +class IntSize; + +// The CCInputHandler is a way for the embedders to interact with +// the impl thread side of the compositor implementation. +// +// There is one CCInputHandler for every CCLayerTreeHost. It is +// created on the main thread and used only on the impl thread. +// +// The CCInputHandler is constructed with a CCInputHandlerClient, which is the +// interface by which the handler can manipulate the LayerTree. +class CCInputHandlerClient { +public: + enum ScrollStatus { ScrollOnMainThread, ScrollStarted, ScrollIgnored }; + enum ScrollInputType { Gesture, Wheel }; + + // Selects a layer to be scrolled at a given point in window coordinates. + // Returns ScrollStarted if the layer at the coordinates can be scrolled, + // ScrollOnMainThread if the scroll event should instead be delegated to the + // main thread, or ScrollIgnored if there is nothing to be scrolled at the + // given coordinates. + virtual ScrollStatus scrollBegin(const IntPoint&, ScrollInputType) = 0; + + // Scroll the selected layer starting at the given window coordinate. If + // there is no room to move the layer in the requested direction, its first + // ancestor layer that can be scrolled will be moved instead. Should only be + // called if scrollBegin() returned ScrollStarted. + virtual void scrollBy(const IntPoint&, const IntSize&) = 0; + + // Stop scrolling the selected layer. Should only be called if scrollBegin() + // returned ScrollStarted. + virtual void scrollEnd() = 0; + + virtual void pinchGestureBegin() = 0; + virtual void pinchGestureUpdate(float magnifyDelta, const IntPoint& anchor) = 0; + virtual void pinchGestureEnd() = 0; + + virtual void startPageScaleAnimation(const IntSize& targetPosition, + bool anchorPoint, + float pageScale, + double startTime, + double duration) = 0; + + // Request another callback to CCInputHandler::animate(). + virtual void scheduleAnimation() = 0; + +protected: + CCInputHandlerClient() { } + virtual ~CCInputHandlerClient() { } + +private: + DISALLOW_COPY_AND_ASSIGN(CCInputHandlerClient); +}; + +class CCInputHandler { +public: + virtual ~CCInputHandler() { } + + virtual void bindToClient(CCInputHandlerClient*) = 0; + virtual void animate(double monotonicTime) = 0; + +protected: + CCInputHandler() { } + +private: + DISALLOW_COPY_AND_ASSIGN(CCInputHandler); +}; + +} + +#endif diff --git a/cc/io_surface_draw_quad.cc b/cc/io_surface_draw_quad.cc new file mode 100644 index 0000000..5d50043 --- /dev/null +++ b/cc/io_surface_draw_quad.cc @@ -0,0 +1,30 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#include "CCIOSurfaceDrawQuad.h" + +namespace cc { + +scoped_ptr CCIOSurfaceDrawQuad::create(const CCSharedQuadState* sharedQuadState, const IntRect& quadRect, const IntSize& ioSurfaceSize, unsigned ioSurfaceTextureId, Orientation orientation) +{ + return make_scoped_ptr(new CCIOSurfaceDrawQuad(sharedQuadState, quadRect, ioSurfaceSize, ioSurfaceTextureId, orientation)); +} + +CCIOSurfaceDrawQuad::CCIOSurfaceDrawQuad(const CCSharedQuadState* sharedQuadState, const IntRect& quadRect, const IntSize& ioSurfaceSize, unsigned ioSurfaceTextureId, Orientation orientation) + : CCDrawQuad(sharedQuadState, CCDrawQuad::IOSurfaceContent, quadRect) + , m_ioSurfaceSize(ioSurfaceSize) + , m_ioSurfaceTextureId(ioSurfaceTextureId) + , m_orientation(orientation) +{ +} + +const CCIOSurfaceDrawQuad* CCIOSurfaceDrawQuad::materialCast(const CCDrawQuad* quad) +{ + ASSERT(quad->material() == CCDrawQuad::IOSurfaceContent); + return static_cast(quad); +} + +} // namespace cc diff --git a/cc/io_surface_draw_quad.h b/cc/io_surface_draw_quad.h index 638cbb2..bb5b028 100644 --- a/cc/io_surface_draw_quad.h +++ b/cc/io_surface_draw_quad.h @@ -1,3 +1,42 @@ // Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CCIOSurfaceDrawQuad_h +#define CCIOSurfaceDrawQuad_h + +#include "CCDrawQuad.h" +#include "IntSize.h" +#include "base/memory/scoped_ptr.h" + +namespace cc { + +#pragma pack(push, 4) + +class CCIOSurfaceDrawQuad : public CCDrawQuad { +public: + enum Orientation { + Flipped, + Unflipped + }; + + static scoped_ptr create(const CCSharedQuadState*, const IntRect&, const IntSize& ioSurfaceSize, unsigned ioSurfaceTextureId, Orientation); + + IntSize ioSurfaceSize() const { return m_ioSurfaceSize; } + unsigned ioSurfaceTextureId() const { return m_ioSurfaceTextureId; } + Orientation orientation() const { return m_orientation; } + + static const CCIOSurfaceDrawQuad* materialCast(const CCDrawQuad*); +private: + CCIOSurfaceDrawQuad(const CCSharedQuadState*, const IntRect&, const IntSize& ioSurfaceSize, unsigned ioSurfaceTextureId, Orientation); + + IntSize m_ioSurfaceSize; + unsigned m_ioSurfaceTextureId; + Orientation m_orientation; +}; + +#pragma pack(pop) + +} + +#endif diff --git a/cc/io_surface_layer.cc b/cc/io_surface_layer.cc new file mode 100644 index 0000000..fe6d39a --- /dev/null +++ b/cc/io_surface_layer.cc @@ -0,0 +1,56 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#if USE(ACCELERATED_COMPOSITING) + +#include "IOSurfaceLayerChromium.h" + +#include "CCIOSurfaceLayerImpl.h" + +namespace cc { + +scoped_refptr IOSurfaceLayerChromium::create() +{ + return make_scoped_refptr(new IOSurfaceLayerChromium()); +} + +IOSurfaceLayerChromium::IOSurfaceLayerChromium() + : LayerChromium() + , m_ioSurfaceId(0) +{ +} + +IOSurfaceLayerChromium::~IOSurfaceLayerChromium() +{ +} + +void IOSurfaceLayerChromium::setIOSurfaceProperties(uint32_t ioSurfaceId, const IntSize& size) +{ + m_ioSurfaceId = ioSurfaceId; + m_ioSurfaceSize = size; + setNeedsCommit(); +} + +scoped_ptr IOSurfaceLayerChromium::createCCLayerImpl() +{ + return CCIOSurfaceLayerImpl::create(m_layerId).PassAs(); +} + +bool IOSurfaceLayerChromium::drawsContent() const +{ + return m_ioSurfaceId && LayerChromium::drawsContent(); +} + +void IOSurfaceLayerChromium::pushPropertiesTo(CCLayerImpl* layer) +{ + LayerChromium::pushPropertiesTo(layer); + + CCIOSurfaceLayerImpl* textureLayer = static_cast(layer); + textureLayer->setIOSurfaceProperties(m_ioSurfaceId, m_ioSurfaceSize); +} + +} +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/cc/io_surface_layer.h b/cc/io_surface_layer.h index 638cbb2..f9c4b5f 100644 --- a/cc/io_surface_layer.h +++ b/cc/io_surface_layer.h @@ -1,3 +1,38 @@ // Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + + +#ifndef IOSurfaceLayerChromium_h +#define IOSurfaceLayerChromium_h + +#if USE(ACCELERATED_COMPOSITING) + +#include "LayerChromium.h" + +namespace cc { + +class IOSurfaceLayerChromium : public LayerChromium { +public: + static scoped_refptr create(); + + void setIOSurfaceProperties(uint32_t ioSurfaceId, const IntSize&); + + virtual scoped_ptr createCCLayerImpl() OVERRIDE; + virtual bool drawsContent() const OVERRIDE; + virtual void pushPropertiesTo(CCLayerImpl*) OVERRIDE; + +protected: + IOSurfaceLayerChromium(); + +private: + virtual ~IOSurfaceLayerChromium(); + + uint32_t m_ioSurfaceId; + IntSize m_ioSurfaceSize; +}; + +} +#endif // USE(ACCELERATED_COMPOSITING) + +#endif diff --git a/cc/io_surface_layer_impl.cc b/cc/io_surface_layer_impl.cc new file mode 100644 index 0000000..689a003 --- /dev/null +++ b/cc/io_surface_layer_impl.cc @@ -0,0 +1,118 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#if USE(ACCELERATED_COMPOSITING) + +#include "CCIOSurfaceLayerImpl.h" + +#include "base/stringprintf.h" +#include "CCGraphicsContext.h" +#include "CCIOSurfaceDrawQuad.h" +#include "CCLayerTreeHostImpl.h" +#include "CCQuadSink.h" +#include "CCRendererGL.h" // For the GLC() macro. +#include "Extensions3D.h" +#include + +namespace cc { + +CCIOSurfaceLayerImpl::CCIOSurfaceLayerImpl(int id) + : CCLayerImpl(id) + , m_ioSurfaceId(0) + , m_ioSurfaceChanged(false) + , m_ioSurfaceTextureId(0) +{ +} + +CCIOSurfaceLayerImpl::~CCIOSurfaceLayerImpl() +{ + if (!m_ioSurfaceTextureId) + return; + + CCGraphicsContext* context = layerTreeHostImpl()->context(); + // FIXME: Implement this path for software compositing. + WebKit::WebGraphicsContext3D* context3d = context->context3D(); + if (context3d) + context3d->deleteTexture(m_ioSurfaceTextureId); +} + +void CCIOSurfaceLayerImpl::willDraw(CCResourceProvider* resourceProvider) +{ + CCLayerImpl::willDraw(resourceProvider); + + if (m_ioSurfaceChanged) { + WebKit::WebGraphicsContext3D* context3d = resourceProvider->graphicsContext3D(); + if (!context3d) { + // FIXME: Implement this path for software compositing. + return; + } + + // FIXME: Do this in a way that we can track memory usage. + if (!m_ioSurfaceTextureId) + m_ioSurfaceTextureId = context3d->createTexture(); + + GLC(context3d, context3d->activeTexture(GraphicsContext3D::TEXTURE0)); + GLC(context3d, context3d->bindTexture(Extensions3D::TEXTURE_RECTANGLE_ARB, m_ioSurfaceTextureId)); + GLC(context3d, context3d->texParameteri(Extensions3D::TEXTURE_RECTANGLE_ARB, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR)); + GLC(context3d, context3d->texParameteri(Extensions3D::TEXTURE_RECTANGLE_ARB, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR)); + GLC(context3d, context3d->texParameteri(Extensions3D::TEXTURE_RECTANGLE_ARB, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE)); + GLC(context3d, context3d->texParameteri(Extensions3D::TEXTURE_RECTANGLE_ARB, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE)); + context3d->texImageIOSurface2DCHROMIUM(Extensions3D::TEXTURE_RECTANGLE_ARB, + m_ioSurfaceSize.width(), + m_ioSurfaceSize.height(), + m_ioSurfaceId, + 0); + // Do not check for error conditions. texImageIOSurface2DCHROMIUM is supposed to hold on to + // the last good IOSurface if the new one is already closed. This is only a possibility + // during live resizing of plugins. However, it seems that this is not sufficient to + // completely guard against garbage being drawn. If this is found to be a significant issue, + // it may be necessary to explicitly tell the embedder when to free the surfaces it has + // allocated. + m_ioSurfaceChanged = false; + } +} + +void CCIOSurfaceLayerImpl::appendQuads(CCQuadSink& quadSink, CCAppendQuadsData& appendQuadsData) +{ + CCSharedQuadState* sharedQuadState = quadSink.useSharedQuadState(createSharedQuadState()); + appendDebugBorderQuad(quadSink, sharedQuadState, appendQuadsData); + + IntRect quadRect(IntPoint(), contentBounds()); + quadSink.append(CCIOSurfaceDrawQuad::create(sharedQuadState, quadRect, m_ioSurfaceSize, m_ioSurfaceTextureId, CCIOSurfaceDrawQuad::Flipped).PassAs(), appendQuadsData); +} + +void CCIOSurfaceLayerImpl::dumpLayerProperties(std::string* str, int indent) const +{ + str->append(indentString(indent)); + base::StringAppendF(str, "iosurface id: %u texture id: %u\n", m_ioSurfaceId, m_ioSurfaceTextureId); + CCLayerImpl::dumpLayerProperties(str, indent); +} + +void CCIOSurfaceLayerImpl::didLoseContext() +{ + // We don't have a valid texture ID in the new context; however, + // the IOSurface is still valid. + m_ioSurfaceTextureId = 0; + m_ioSurfaceChanged = true; +} + +void CCIOSurfaceLayerImpl::setIOSurfaceProperties(unsigned ioSurfaceId, const IntSize& size) +{ + if (m_ioSurfaceId != ioSurfaceId) + m_ioSurfaceChanged = true; + + m_ioSurfaceId = ioSurfaceId; + m_ioSurfaceSize = size; +} + +const char* CCIOSurfaceLayerImpl::layerTypeAsString() const +{ + return "IOSurfaceLayer"; +} + +} + +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/cc/io_surface_layer_impl.h b/cc/io_surface_layer_impl.h index 638cbb2..238e27e 100644 --- a/cc/io_surface_layer_impl.h +++ b/cc/io_surface_layer_impl.h @@ -1,3 +1,43 @@ // Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CCIOSurfaceLayerImpl_h +#define CCIOSurfaceLayerImpl_h + +#include "CCLayerImpl.h" +#include "IntSize.h" + +namespace cc { + +class CCIOSurfaceLayerImpl : public CCLayerImpl { +public: + static scoped_ptr create(int id) + { + return make_scoped_ptr(new CCIOSurfaceLayerImpl(id)); + } + virtual ~CCIOSurfaceLayerImpl(); + + void setIOSurfaceProperties(unsigned ioSurfaceId, const IntSize&); + + virtual void appendQuads(CCQuadSink&, CCAppendQuadsData&) OVERRIDE; + + virtual void willDraw(CCResourceProvider*) OVERRIDE; + virtual void didLoseContext() OVERRIDE; + + virtual void dumpLayerProperties(std::string*, int indent) const OVERRIDE; + +private: + explicit CCIOSurfaceLayerImpl(int); + + virtual const char* layerTypeAsString() const OVERRIDE; + + unsigned m_ioSurfaceId; + IntSize m_ioSurfaceSize; + bool m_ioSurfaceChanged; + unsigned m_ioSurfaceTextureId; +}; + +} + +#endif // CCIOSurfaceLayerImpl_h diff --git a/cc/keyframed_animation_curve.cc b/cc/keyframed_animation_curve.cc new file mode 100644 index 0000000..a6b368e --- /dev/null +++ b/cc/keyframed_animation_curve.cc @@ -0,0 +1,223 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#include "CCKeyframedAnimationCurve.h" + +using WebKit::WebTransformationMatrix; + +namespace cc { + +namespace { + +template +void insertKeyframe(scoped_ptr keyframe, ScopedPtrVector& keyframes) +{ + // Usually, the keyframes will be added in order, so this loop would be unnecessary and + // we should skip it if possible. + if (!keyframes.isEmpty() && keyframe->time() < keyframes.last()->time()) { + for (size_t i = 0; i < keyframes.size(); ++i) { + if (keyframe->time() < keyframes[i]->time()) { + keyframes.insert(i, keyframe.Pass()); + return; + } + } + } + + keyframes.append(keyframe.Pass()); +} + +scoped_ptr cloneTimingFunction(const CCTimingFunction* timingFunction) +{ + ASSERT(timingFunction); + scoped_ptr curve(timingFunction->clone()); + return scoped_ptr(static_cast(curve.release())); +} + +} // namespace + +CCKeyframe::CCKeyframe(double time, scoped_ptr timingFunction) + : m_time(time) + , m_timingFunction(timingFunction.Pass()) +{ +} + +CCKeyframe::~CCKeyframe() +{ +} + +double CCKeyframe::time() const +{ + return m_time; +} + +const CCTimingFunction* CCKeyframe::timingFunction() const +{ + return m_timingFunction.get(); +} + +scoped_ptr CCFloatKeyframe::create(double time, float value, scoped_ptr timingFunction) +{ + return make_scoped_ptr(new CCFloatKeyframe(time, value, timingFunction.Pass())); +} + +CCFloatKeyframe::CCFloatKeyframe(double time, float value, scoped_ptr timingFunction) + : CCKeyframe(time, timingFunction.Pass()) + , m_value(value) +{ +} + +CCFloatKeyframe::~CCFloatKeyframe() +{ +} + +float CCFloatKeyframe::value() const +{ + return m_value; +} + +scoped_ptr CCFloatKeyframe::clone() const +{ + scoped_ptr func; + if (timingFunction()) + func = cloneTimingFunction(timingFunction()); + return CCFloatKeyframe::create(time(), value(), func.Pass()); +} + +scoped_ptr CCTransformKeyframe::create(double time, const WebKit::WebTransformOperations& value, scoped_ptr timingFunction) +{ + return make_scoped_ptr(new CCTransformKeyframe(time, value, timingFunction.Pass())); +} + +CCTransformKeyframe::CCTransformKeyframe(double time, const WebKit::WebTransformOperations& value, scoped_ptr timingFunction) + : CCKeyframe(time, timingFunction.Pass()) + , m_value(value) +{ +} + +CCTransformKeyframe::~CCTransformKeyframe() +{ +} + +const WebKit::WebTransformOperations& CCTransformKeyframe::value() const +{ + return m_value; +} + +scoped_ptr CCTransformKeyframe::clone() const +{ + scoped_ptr func; + if (timingFunction()) + func = cloneTimingFunction(timingFunction()); + return CCTransformKeyframe::create(time(), value(), func.Pass()); +} + +scoped_ptr CCKeyframedFloatAnimationCurve::create() +{ + return make_scoped_ptr(new CCKeyframedFloatAnimationCurve); +} + +CCKeyframedFloatAnimationCurve::CCKeyframedFloatAnimationCurve() +{ +} + +CCKeyframedFloatAnimationCurve::~CCKeyframedFloatAnimationCurve() +{ +} + +void CCKeyframedFloatAnimationCurve::addKeyframe(scoped_ptr keyframe) +{ + insertKeyframe(keyframe.Pass(), m_keyframes); +} + +double CCKeyframedFloatAnimationCurve::duration() const +{ + return m_keyframes.last()->time() - m_keyframes.first()->time(); +} + +scoped_ptr CCKeyframedFloatAnimationCurve::clone() const +{ + scoped_ptr toReturn(CCKeyframedFloatAnimationCurve::create()); + for (size_t i = 0; i < m_keyframes.size(); ++i) + toReturn->addKeyframe(m_keyframes[i]->clone()); + return toReturn.PassAs(); +} + +float CCKeyframedFloatAnimationCurve::getValue(double t) const +{ + if (t <= m_keyframes.first()->time()) + return m_keyframes.first()->value(); + + if (t >= m_keyframes.last()->time()) + return m_keyframes.last()->value(); + + size_t i = 0; + for (; i < m_keyframes.size() - 1; ++i) { + if (t < m_keyframes[i+1]->time()) + break; + } + + float progress = static_cast((t - m_keyframes[i]->time()) / (m_keyframes[i+1]->time() - m_keyframes[i]->time())); + + if (m_keyframes[i]->timingFunction()) + progress = m_keyframes[i]->timingFunction()->getValue(progress); + + return m_keyframes[i]->value() + (m_keyframes[i+1]->value() - m_keyframes[i]->value()) * progress; +} + +scoped_ptr CCKeyframedTransformAnimationCurve::create() +{ + return make_scoped_ptr(new CCKeyframedTransformAnimationCurve); +} + +CCKeyframedTransformAnimationCurve::CCKeyframedTransformAnimationCurve() +{ +} + +CCKeyframedTransformAnimationCurve::~CCKeyframedTransformAnimationCurve() +{ +} + +void CCKeyframedTransformAnimationCurve::addKeyframe(scoped_ptr keyframe) +{ + insertKeyframe(keyframe.Pass(), m_keyframes); +} + +double CCKeyframedTransformAnimationCurve::duration() const +{ + return m_keyframes.last()->time() - m_keyframes.first()->time(); +} + +scoped_ptr CCKeyframedTransformAnimationCurve::clone() const +{ + scoped_ptr toReturn(CCKeyframedTransformAnimationCurve::create()); + for (size_t i = 0; i < m_keyframes.size(); ++i) + toReturn->addKeyframe(m_keyframes[i]->clone()); + return toReturn.PassAs(); +} + +WebTransformationMatrix CCKeyframedTransformAnimationCurve::getValue(double t) const +{ + if (t <= m_keyframes.first()->time()) + return m_keyframes.first()->value().apply(); + + if (t >= m_keyframes.last()->time()) + return m_keyframes.last()->value().apply(); + + size_t i = 0; + for (; i < m_keyframes.size() - 1; ++i) { + if (t < m_keyframes[i+1]->time()) + break; + } + + double progress = (t - m_keyframes[i]->time()) / (m_keyframes[i+1]->time() - m_keyframes[i]->time()); + + if (m_keyframes[i]->timingFunction()) + progress = m_keyframes[i]->timingFunction()->getValue(progress); + + return m_keyframes[i+1]->value().blend(m_keyframes[i]->value(), progress); +} + +} // namespace cc diff --git a/cc/keyframed_animation_curve.h b/cc/keyframed_animation_curve.h index 638cbb2..066e5c6 100644 --- a/cc/keyframed_animation_curve.h +++ b/cc/keyframed_animation_curve.h @@ -1,3 +1,109 @@ // Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CCKeyframedAnimationCurve_h +#define CCKeyframedAnimationCurve_h + +#include "CCAnimationCurve.h" +#include "CCTimingFunction.h" +#include "scoped_ptr_vector.h" +#include + +namespace cc { + +class CCKeyframe { +public: + double time() const; + const CCTimingFunction* timingFunction() const; + +protected: + CCKeyframe(double time, scoped_ptr); + virtual ~CCKeyframe(); + +private: + double m_time; + scoped_ptr m_timingFunction; +}; + +class CCFloatKeyframe : public CCKeyframe { +public: + static scoped_ptr create(double time, float value, scoped_ptr); + virtual ~CCFloatKeyframe(); + + float value() const; + + scoped_ptr clone() const; + +private: + CCFloatKeyframe(double time, float value, scoped_ptr); + + float m_value; +}; + +class CCTransformKeyframe : public CCKeyframe { +public: + static scoped_ptr create(double time, const WebKit::WebTransformOperations& value, scoped_ptr); + virtual ~CCTransformKeyframe(); + + const WebKit::WebTransformOperations& value() const; + + scoped_ptr clone() const; + +private: + CCTransformKeyframe(double time, const WebKit::WebTransformOperations& value, scoped_ptr); + + WebKit::WebTransformOperations m_value; +}; + +class CCKeyframedFloatAnimationCurve : public CCFloatAnimationCurve { +public: + // It is required that the keyframes be sorted by time. + static scoped_ptr create(); + + virtual ~CCKeyframedFloatAnimationCurve(); + + void addKeyframe(scoped_ptr); + + // CCAnimationCurve implementation + virtual double duration() const OVERRIDE; + virtual scoped_ptr clone() const OVERRIDE; + + // CCFloatAnimationCurve implementation + virtual float getValue(double t) const OVERRIDE; + +private: + CCKeyframedFloatAnimationCurve(); + + // Always sorted in order of increasing time. No two keyframes have the + // same time. + ScopedPtrVector m_keyframes; +}; + +class CCKeyframedTransformAnimationCurve : public CCTransformAnimationCurve { +public: + // It is required that the keyframes be sorted by time. + static scoped_ptr create(); + + virtual ~CCKeyframedTransformAnimationCurve(); + + void addKeyframe(scoped_ptr); + + // CCAnimationCurve implementation + virtual double duration() const OVERRIDE; + virtual scoped_ptr clone() const OVERRIDE; + + // CCTransformAnimationCurve implementation + virtual WebKit::WebTransformationMatrix getValue(double t) const OVERRIDE; + +private: + CCKeyframedTransformAnimationCurve(); + + // Always sorted in order of increasing time. No two keyframes have the + // same time. + ScopedPtrVector m_keyframes; +}; + +} // namespace cc + +#endif // CCKeyframedAnimationCurve_h diff --git a/cc/layer.cc b/cc/layer.cc new file mode 100644 index 0000000..dc3bd67 --- /dev/null +++ b/cc/layer.cc @@ -0,0 +1,799 @@ +// Copyright 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#if USE(ACCELERATED_COMPOSITING) +#include "LayerChromium.h" + +#include "CCActiveAnimation.h" +#include "CCAnimationEvents.h" +#include "CCLayerAnimationController.h" +#include "CCLayerImpl.h" +#include "CCLayerTreeHost.h" +#include "CCSettings.h" +#include +#include +#include + +using namespace std; +using WebKit::WebTransformationMatrix; + +namespace cc { + +static int s_nextLayerId = 1; + +scoped_refptr LayerChromium::create() +{ + return make_scoped_refptr(new LayerChromium()); +} + +LayerChromium::LayerChromium() + : m_needsDisplay(false) + , m_stackingOrderChanged(false) + , m_layerId(s_nextLayerId++) + , m_parent(0) + , m_layerTreeHost(0) + , m_layerAnimationController(CCLayerAnimationController::create(this)) + , m_scrollable(false) + , m_shouldScrollOnMainThread(false) + , m_haveWheelEventHandlers(false) + , m_nonFastScrollableRegionChanged(false) + , m_anchorPoint(0.5, 0.5) + , m_backgroundColor(0) + , m_debugBorderColor(0) + , m_debugBorderWidth(0) + , m_opacity(1.0) + , m_anchorPointZ(0) + , m_isContainerForFixedPositionLayers(false) + , m_fixedToContainerLayer(false) + , m_isDrawable(false) + , m_masksToBounds(false) + , m_contentsOpaque(false) + , m_doubleSided(true) + , m_useLCDText(false) + , m_preserves3D(false) + , m_useParentBackfaceVisibility(false) + , m_drawCheckerboardForMissingTiles(false) + , m_forceRenderSurface(false) + , m_replicaLayer(0) + , m_drawOpacity(0) + , m_drawOpacityIsAnimating(false) + , m_renderTarget(0) + , m_drawTransformIsAnimating(false) + , m_screenSpaceTransformIsAnimating(false) + , m_contentsScale(1.0) + , m_boundsContainPageScale(false) + , m_layerAnimationDelegate(0) + , m_layerScrollClient(0) +{ + if (m_layerId < 0) { + s_nextLayerId = 1; + m_layerId = s_nextLayerId++; + } +} + +LayerChromium::~LayerChromium() +{ + // Our parent should be holding a reference to us so there should be no + // way for us to be destroyed while we still have a parent. + ASSERT(!parent()); + + // Remove the parent reference from all children. + removeAllChildren(); +} + +void LayerChromium::setUseLCDText(bool useLCDText) +{ + m_useLCDText = useLCDText; +} + +void LayerChromium::setLayerTreeHost(CCLayerTreeHost* host) +{ + if (m_layerTreeHost == host) + return; + + m_layerTreeHost = host; + + for (size_t i = 0; i < m_children.size(); ++i) + m_children[i]->setLayerTreeHost(host); + + if (m_maskLayer) + m_maskLayer->setLayerTreeHost(host); + if (m_replicaLayer) + m_replicaLayer->setLayerTreeHost(host); + + // If this layer already has active animations, the host needs to be notified. + if (host && m_layerAnimationController->hasActiveAnimation()) + host->didAddAnimation(); +} + +void LayerChromium::setNeedsCommit() +{ + if (m_layerTreeHost) + m_layerTreeHost->setNeedsCommit(); +} + +IntRect LayerChromium::layerRectToContentRect(const WebKit::WebRect& layerRect) +{ + float widthScale = static_cast(contentBounds().width()) / bounds().width(); + float heightScale = static_cast(contentBounds().height()) / bounds().height(); + FloatRect contentRect(layerRect.x, layerRect.y, layerRect.width, layerRect.height); + contentRect.scale(widthScale, heightScale); + return enclosingIntRect(contentRect); +} + +void LayerChromium::setParent(LayerChromium* layer) +{ + ASSERT(!layer || !layer->hasAncestor(this)); + m_parent = layer; + setLayerTreeHost(m_parent ? m_parent->layerTreeHost() : 0); +} + +bool LayerChromium::hasAncestor(LayerChromium* ancestor) const +{ + for (LayerChromium* layer = parent(); layer; layer = layer->parent()) { + if (layer == ancestor) + return true; + } + return false; +} + +void LayerChromium::addChild(scoped_refptr child) +{ + insertChild(child, numChildren()); +} + +void LayerChromium::insertChild(scoped_refptr child, size_t index) +{ + index = min(index, m_children.size()); + child->removeFromParent(); + child->setParent(this); + child->m_stackingOrderChanged = true; + + LayerList::iterator iter = m_children.begin(); + m_children.insert(iter + index, child); + setNeedsCommit(); +} + +void LayerChromium::removeFromParent() +{ + if (m_parent) + m_parent->removeChild(this); +} + +void LayerChromium::removeChild(LayerChromium* child) +{ + for (LayerList::iterator iter = m_children.begin(); iter != m_children.end(); ++iter) + { + if (*iter != child) + continue; + + child->setParent(0); + m_children.erase(iter); + setNeedsCommit(); + return; + } +} + +void LayerChromium::replaceChild(LayerChromium* reference, scoped_refptr newLayer) +{ + ASSERT_ARG(reference, reference); + ASSERT_ARG(reference, reference->parent() == this); + + if (reference == newLayer) + return; + + int referenceIndex = indexOfChild(reference); + if (referenceIndex == -1) { + ASSERT_NOT_REACHED(); + return; + } + + reference->removeFromParent(); + + if (newLayer) { + newLayer->removeFromParent(); + insertChild(newLayer, referenceIndex); + } +} + +int LayerChromium::indexOfChild(const LayerChromium* reference) +{ + for (size_t i = 0; i < m_children.size(); i++) { + if (m_children[i] == reference) + return i; + } + return -1; +} + +void LayerChromium::setBounds(const IntSize& size) +{ + if (bounds() == size) + return; + + bool firstResize = bounds().isEmpty() && !size.isEmpty(); + + m_bounds = size; + + if (firstResize) + setNeedsDisplay(); + else + setNeedsCommit(); +} + +LayerChromium* LayerChromium::rootLayer() +{ + LayerChromium* layer = this; + while (layer->parent()) + layer = layer->parent(); + return layer; +} + +void LayerChromium::removeAllChildren() +{ + while (m_children.size()) { + LayerChromium* layer = m_children[0].get(); + ASSERT(layer->parent()); + layer->removeFromParent(); + } +} + +void LayerChromium::setChildren(const LayerList& children) +{ + if (children == m_children) + return; + + removeAllChildren(); + size_t listSize = children.size(); + for (size_t i = 0; i < listSize; i++) + addChild(children[i]); +} + +void LayerChromium::setAnchorPoint(const FloatPoint& anchorPoint) +{ + if (m_anchorPoint == anchorPoint) + return; + m_anchorPoint = anchorPoint; + setNeedsCommit(); +} + +void LayerChromium::setAnchorPointZ(float anchorPointZ) +{ + if (m_anchorPointZ == anchorPointZ) + return; + m_anchorPointZ = anchorPointZ; + setNeedsCommit(); +} + +void LayerChromium::setBackgroundColor(SkColor backgroundColor) +{ + if (m_backgroundColor == backgroundColor) + return; + m_backgroundColor = backgroundColor; + setNeedsCommit(); +} + +IntSize LayerChromium::contentBounds() const +{ + return bounds(); +} + +void LayerChromium::setMasksToBounds(bool masksToBounds) +{ + if (m_masksToBounds == masksToBounds) + return; + m_masksToBounds = masksToBounds; + setNeedsCommit(); +} + +void LayerChromium::setMaskLayer(LayerChromium* maskLayer) +{ + if (m_maskLayer == maskLayer) + return; + if (m_maskLayer) + m_maskLayer->setLayerTreeHost(0); + m_maskLayer = maskLayer; + if (m_maskLayer) { + m_maskLayer->setLayerTreeHost(m_layerTreeHost); + m_maskLayer->setIsMask(true); + } + setNeedsCommit(); +} + +void LayerChromium::setReplicaLayer(LayerChromium* layer) +{ + if (m_replicaLayer == layer) + return; + if (m_replicaLayer) + m_replicaLayer->setLayerTreeHost(0); + m_replicaLayer = layer; + if (m_replicaLayer) + m_replicaLayer->setLayerTreeHost(m_layerTreeHost); + setNeedsCommit(); +} + +void LayerChromium::setFilters(const WebKit::WebFilterOperations& filters) +{ + if (m_filters == filters) + return; + m_filters = filters; + setNeedsCommit(); + if (!filters.isEmpty()) + CCLayerTreeHost::setNeedsFilterContext(true); +} + +void LayerChromium::setBackgroundFilters(const WebKit::WebFilterOperations& backgroundFilters) +{ + if (m_backgroundFilters == backgroundFilters) + return; + m_backgroundFilters = backgroundFilters; + setNeedsCommit(); + if (!backgroundFilters.isEmpty()) + CCLayerTreeHost::setNeedsFilterContext(true); +} + +bool LayerChromium::needsDisplay() const +{ + return m_needsDisplay; +} + +void LayerChromium::setOpacity(float opacity) +{ + if (m_opacity == opacity) + return; + m_opacity = opacity; + setNeedsCommit(); +} + +bool LayerChromium::opacityIsAnimating() const +{ + return m_layerAnimationController->isAnimatingProperty(CCActiveAnimation::Opacity); +} + +void LayerChromium::setContentsOpaque(bool opaque) +{ + if (m_contentsOpaque == opaque) + return; + m_contentsOpaque = opaque; + setNeedsDisplay(); +} + +void LayerChromium::setPosition(const FloatPoint& position) +{ + if (m_position == position) + return; + m_position = position; + setNeedsCommit(); +} + +void LayerChromium::setSublayerTransform(const WebTransformationMatrix& sublayerTransform) +{ + if (m_sublayerTransform == sublayerTransform) + return; + m_sublayerTransform = sublayerTransform; + setNeedsCommit(); +} + +void LayerChromium::setTransform(const WebTransformationMatrix& transform) +{ + if (m_transform == transform) + return; + m_transform = transform; + setNeedsCommit(); +} + +bool LayerChromium::transformIsAnimating() const +{ + return m_layerAnimationController->isAnimatingProperty(CCActiveAnimation::Transform); +} + +void LayerChromium::setScrollPosition(const IntPoint& scrollPosition) +{ + if (m_scrollPosition == scrollPosition) + return; + m_scrollPosition = scrollPosition; + if (m_layerScrollClient) + m_layerScrollClient->didScroll(); + setNeedsCommit(); +} + +void LayerChromium::setMaxScrollPosition(const IntSize& maxScrollPosition) +{ + if (m_maxScrollPosition == maxScrollPosition) + return; + m_maxScrollPosition = maxScrollPosition; + setNeedsCommit(); +} + +void LayerChromium::setScrollable(bool scrollable) +{ + if (m_scrollable == scrollable) + return; + m_scrollable = scrollable; + setNeedsCommit(); +} + +void LayerChromium::setShouldScrollOnMainThread(bool shouldScrollOnMainThread) +{ + if (m_shouldScrollOnMainThread == shouldScrollOnMainThread) + return; + m_shouldScrollOnMainThread = shouldScrollOnMainThread; + setNeedsCommit(); +} + +void LayerChromium::setHaveWheelEventHandlers(bool haveWheelEventHandlers) +{ + if (m_haveWheelEventHandlers == haveWheelEventHandlers) + return; + m_haveWheelEventHandlers = haveWheelEventHandlers; + setNeedsCommit(); +} + +void LayerChromium::setNonFastScrollableRegion(const Region& region) +{ + if (m_nonFastScrollableRegion == region) + return; + m_nonFastScrollableRegion = region; + m_nonFastScrollableRegionChanged = true; + setNeedsCommit(); +} + +void LayerChromium::setDrawCheckerboardForMissingTiles(bool checkerboard) +{ + if (m_drawCheckerboardForMissingTiles == checkerboard) + return; + m_drawCheckerboardForMissingTiles = checkerboard; + setNeedsCommit(); +} + +void LayerChromium::setForceRenderSurface(bool force) +{ + if (m_forceRenderSurface == force) + return; + m_forceRenderSurface = force; + setNeedsCommit(); +} + +void LayerChromium::setImplTransform(const WebTransformationMatrix& transform) +{ + if (m_implTransform == transform) + return; + m_implTransform = transform; + setNeedsCommit(); +} + +void LayerChromium::setDoubleSided(bool doubleSided) +{ + if (m_doubleSided == doubleSided) + return; + m_doubleSided = doubleSided; + setNeedsCommit(); +} + +void LayerChromium::setIsDrawable(bool isDrawable) +{ + if (m_isDrawable == isDrawable) + return; + + m_isDrawable = isDrawable; + setNeedsCommit(); +} + +LayerChromium* LayerChromium::parent() const +{ + return m_parent; +} + +void LayerChromium::setNeedsDisplayRect(const FloatRect& dirtyRect) +{ + m_updateRect.unite(dirtyRect); + + // Simply mark the contents as dirty. For non-root layers, the call to + // setNeedsCommit will schedule a fresh compositing pass. + // For the root layer, setNeedsCommit has no effect. + if (!dirtyRect.isEmpty()) + m_needsDisplay = true; + + setNeedsCommit(); +} + +bool LayerChromium::descendantIsFixedToContainerLayer() const +{ + for (size_t i = 0; i < m_children.size(); ++i) { + if (m_children[i]->fixedToContainerLayer() || m_children[i]->descendantIsFixedToContainerLayer()) + return true; + } + return false; +} + +void LayerChromium::setIsContainerForFixedPositionLayers(bool isContainerForFixedPositionLayers) +{ + if (m_isContainerForFixedPositionLayers == isContainerForFixedPositionLayers) + return; + m_isContainerForFixedPositionLayers = isContainerForFixedPositionLayers; + + if (m_layerTreeHost && m_layerTreeHost->commitRequested()) + return; + + // Only request a commit if we have a fixed positioned descendant. + if (descendantIsFixedToContainerLayer()) + setNeedsCommit(); +} + +void LayerChromium::setFixedToContainerLayer(bool fixedToContainerLayer) +{ + if (m_fixedToContainerLayer == fixedToContainerLayer) + return; + m_fixedToContainerLayer = fixedToContainerLayer; + setNeedsCommit(); +} + +void LayerChromium::pushPropertiesTo(CCLayerImpl* layer) +{ + layer->setAnchorPoint(m_anchorPoint); + layer->setAnchorPointZ(m_anchorPointZ); + layer->setBackgroundColor(m_backgroundColor); + layer->setBounds(m_bounds); + layer->setContentBounds(contentBounds()); + layer->setDebugBorderColor(m_debugBorderColor); + layer->setDebugBorderWidth(m_debugBorderWidth); + layer->setDebugName(m_debugName); + layer->setDoubleSided(m_doubleSided); + layer->setDrawCheckerboardForMissingTiles(m_drawCheckerboardForMissingTiles); + layer->setForceRenderSurface(m_forceRenderSurface); + layer->setDrawsContent(drawsContent()); + layer->setFilters(filters()); + layer->setBackgroundFilters(backgroundFilters()); + layer->setUseLCDText(m_useLCDText); + layer->setMasksToBounds(m_masksToBounds); + layer->setScrollable(m_scrollable); + layer->setShouldScrollOnMainThread(m_shouldScrollOnMainThread); + layer->setHaveWheelEventHandlers(m_haveWheelEventHandlers); + // Copying a Region is more expensive than most layer properties, since it involves copying two Vectors that may be + // arbitrarily large depending on page content, so we only push the property if it's changed. + if (m_nonFastScrollableRegionChanged) { + layer->setNonFastScrollableRegion(m_nonFastScrollableRegion); + m_nonFastScrollableRegionChanged = false; + } + layer->setContentsOpaque(m_contentsOpaque); + if (!opacityIsAnimating()) + layer->setOpacity(m_opacity); + layer->setPosition(m_position); + layer->setIsContainerForFixedPositionLayers(m_isContainerForFixedPositionLayers); + layer->setFixedToContainerLayer(m_fixedToContainerLayer); + layer->setPreserves3D(preserves3D()); + layer->setUseParentBackfaceVisibility(m_useParentBackfaceVisibility); + layer->setScrollPosition(m_scrollPosition); + layer->setMaxScrollPosition(m_maxScrollPosition); + layer->setSublayerTransform(m_sublayerTransform); + if (!transformIsAnimating()) + layer->setTransform(m_transform); + + // If the main thread commits multiple times before the impl thread actually draws, then damage tracking + // will become incorrect if we simply clobber the updateRect here. The CCLayerImpl's updateRect needs to + // accumulate (i.e. union) any update changes that have occurred on the main thread. + m_updateRect.uniteIfNonZero(layer->updateRect()); + layer->setUpdateRect(m_updateRect); + + layer->setScrollDelta(layer->scrollDelta() - layer->sentScrollDelta()); + layer->setSentScrollDelta(IntSize()); + + layer->setStackingOrderChanged(m_stackingOrderChanged); + + if (maskLayer()) + maskLayer()->pushPropertiesTo(layer->maskLayer()); + if (replicaLayer()) + replicaLayer()->pushPropertiesTo(layer->replicaLayer()); + + m_layerAnimationController->pushAnimationUpdatesTo(layer->layerAnimationController()); + + // Reset any state that should be cleared for the next update. + m_stackingOrderChanged = false; + m_updateRect = FloatRect(); +} + +scoped_ptr LayerChromium::createCCLayerImpl() +{ + return CCLayerImpl::create(m_layerId); +} + +bool LayerChromium::drawsContent() const +{ + return m_isDrawable; +} + +bool LayerChromium::needMoreUpdates() +{ + return false; +} + +bool LayerChromium::needsContentsScale() const +{ + return false; +} + +void LayerChromium::setDebugBorderColor(SkColor color) +{ + m_debugBorderColor = color; + setNeedsCommit(); +} + +void LayerChromium::setDebugBorderWidth(float width) +{ + m_debugBorderWidth = width; + setNeedsCommit(); +} + +void LayerChromium::setDebugName(const std::string& debugName) +{ + m_debugName = debugName; + setNeedsCommit(); +} + +void LayerChromium::setContentsScale(float contentsScale) +{ + if (!needsContentsScale() || m_contentsScale == contentsScale) + return; + m_contentsScale = contentsScale; + + setNeedsDisplay(); +} + +void LayerChromium::setBoundsContainPageScale(bool boundsContainPageScale) +{ + for (size_t i = 0; i < m_children.size(); ++i) + m_children[i]->setBoundsContainPageScale(boundsContainPageScale); + + if (boundsContainPageScale == m_boundsContainPageScale) + return; + + m_boundsContainPageScale = boundsContainPageScale; + setNeedsDisplay(); +} + +void LayerChromium::createRenderSurface() +{ + ASSERT(!m_renderSurface); + m_renderSurface = make_scoped_ptr(new RenderSurfaceChromium(this)); + setRenderTarget(this); +} + +bool LayerChromium::descendantDrawsContent() +{ + for (size_t i = 0; i < m_children.size(); ++i) { + if (m_children[i]->drawsContent() || m_children[i]->descendantDrawsContent()) + return true; + } + return false; +} + +int LayerChromium::id() const +{ + return m_layerId; +} + +float LayerChromium::opacity() const +{ + return m_opacity; +} + +void LayerChromium::setOpacityFromAnimation(float opacity) +{ + // This is called due to an ongoing accelerated animation. Since this animation is + // also being run on the impl thread, there is no need to request a commit to push + // this value over, so set the value directly rather than calling setOpacity. + m_opacity = opacity; +} + +const WebKit::WebTransformationMatrix& LayerChromium::transform() const +{ + return m_transform; +} + +void LayerChromium::setTransformFromAnimation(const WebTransformationMatrix& transform) +{ + // This is called due to an ongoing accelerated animation. Since this animation is + // also being run on the impl thread, there is no need to request a commit to push + // this value over, so set this value directly rather than calling setTransform. + m_transform = transform; +} + +bool LayerChromium::addAnimation(scoped_ptr animation) +{ + // WebCore currently assumes that accelerated animations will start soon + // after the animation is added. However we cannot guarantee that if we do + // not have a layerTreeHost that will setNeedsCommit(). + if (!m_layerTreeHost) + return false; + + if (!CCSettings::acceleratedAnimationEnabled()) + return false; + + m_layerAnimationController->addAnimation(animation.Pass()); + if (m_layerTreeHost) { + m_layerTreeHost->didAddAnimation(); + setNeedsCommit(); + } + return true; +} + +void LayerChromium::pauseAnimation(int animationId, double timeOffset) +{ + m_layerAnimationController->pauseAnimation(animationId, timeOffset); + setNeedsCommit(); +} + +void LayerChromium::removeAnimation(int animationId) +{ + m_layerAnimationController->removeAnimation(animationId); + setNeedsCommit(); +} + +void LayerChromium::suspendAnimations(double monotonicTime) +{ + m_layerAnimationController->suspendAnimations(monotonicTime); + setNeedsCommit(); +} + +void LayerChromium::resumeAnimations(double monotonicTime) +{ + m_layerAnimationController->resumeAnimations(monotonicTime); + setNeedsCommit(); +} + +void LayerChromium::setLayerAnimationController(scoped_ptr layerAnimationController) +{ + m_layerAnimationController = layerAnimationController.Pass(); + if (m_layerAnimationController) { + m_layerAnimationController->setClient(this); + m_layerAnimationController->setForceSync(); + } + setNeedsCommit(); +} + +scoped_ptr LayerChromium::releaseLayerAnimationController() +{ + scoped_ptr toReturn = m_layerAnimationController.Pass(); + m_layerAnimationController = CCLayerAnimationController::create(this); + return toReturn.Pass(); +} + +bool LayerChromium::hasActiveAnimation() const +{ + return m_layerAnimationController->hasActiveAnimation(); +} + +void LayerChromium::notifyAnimationStarted(const CCAnimationEvent& event, double wallClockTime) +{ + m_layerAnimationController->notifyAnimationStarted(event); + if (m_layerAnimationDelegate) + m_layerAnimationDelegate->notifyAnimationStarted(wallClockTime); +} + +void LayerChromium::notifyAnimationFinished(double wallClockTime) +{ + if (m_layerAnimationDelegate) + m_layerAnimationDelegate->notifyAnimationFinished(wallClockTime); +} + +Region LayerChromium::visibleContentOpaqueRegion() const +{ + if (contentsOpaque()) + return visibleContentRect(); + return Region(); +} + +ScrollbarLayerChromium* LayerChromium::toScrollbarLayerChromium() +{ + return 0; +} + +void sortLayers(std::vector >::iterator, std::vector >::iterator, void*) +{ + // Currently we don't use z-order to decide what to paint, so there's no need to actually sort LayerChromiums. +} + +} +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/cc/layer.h b/cc/layer.h index 638cbb2..a87caa0 100644 --- a/cc/layer.h +++ b/cc/layer.h @@ -1,3 +1,390 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. +// Copyright 2010 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + + +#ifndef LayerChromium_h +#define LayerChromium_h + +#if USE(ACCELERATED_COMPOSITING) + +#include "base/memory/ref_counted.h" +#include "CCLayerAnimationController.h" +#include "CCOcclusionTracker.h" +#include "FloatPoint.h" +#include "Region.h" +#include "RenderSurfaceChromium.h" +#include "SkColor.h" +#include +#include +#include +#include + +namespace WebKit { +class WebAnimationDelegate; +class WebLayerScrollClient; +} + +namespace cc { + +class CCActiveAnimation; +struct CCAnimationEvent; +class CCLayerAnimationDelegate; +class CCLayerImpl; +class CCLayerTreeHost; +class CCPriorityCalculator; +class CCTextureUpdateQueue; +class ScrollbarLayerChromium; +struct CCAnimationEvent; +struct CCRenderingStats; + +// Base class for composited layers. Special layer types are derived from +// this class. +class LayerChromium : public base::RefCounted, public CCLayerAnimationControllerClient { +public: + typedef std::vector > LayerList; + + static scoped_refptr create(); + + // CCLayerAnimationControllerClient implementation + virtual int id() const OVERRIDE; + virtual void setOpacityFromAnimation(float) OVERRIDE; + virtual float opacity() const OVERRIDE; + virtual void setTransformFromAnimation(const WebKit::WebTransformationMatrix&) OVERRIDE; + // A layer's transform operates layer space. That is, entirely in logical, + // non-page-scaled pixels (that is, they have page zoom baked in, but not page scale). + // The root layer is a special case -- it operates in physical pixels. + virtual const WebKit::WebTransformationMatrix& transform() const OVERRIDE; + + LayerChromium* rootLayer(); + LayerChromium* parent() const; + void addChild(scoped_refptr); + void insertChild(scoped_refptr, size_t index); + void replaceChild(LayerChromium* reference, scoped_refptr newLayer); + void removeFromParent(); + void removeAllChildren(); + void setChildren(const LayerList&); + + const LayerList& children() const { return m_children; } + + void setAnchorPoint(const FloatPoint&); + FloatPoint anchorPoint() const { return m_anchorPoint; } + + void setAnchorPointZ(float); + float anchorPointZ() const { return m_anchorPointZ; } + + void setBackgroundColor(SkColor); + SkColor backgroundColor() const { return m_backgroundColor; } + + // A layer's bounds are in logical, non-page-scaled pixels (however, the + // root layer's bounds are in physical pixels). + void setBounds(const IntSize&); + const IntSize& bounds() const { return m_bounds; } + virtual IntSize contentBounds() const; + + void setMasksToBounds(bool); + bool masksToBounds() const { return m_masksToBounds; } + + void setMaskLayer(LayerChromium*); + LayerChromium* maskLayer() const { return m_maskLayer.get(); } + + virtual void setNeedsDisplayRect(const FloatRect& dirtyRect); + void setNeedsDisplay() { setNeedsDisplayRect(FloatRect(FloatPoint(), bounds())); } + virtual bool needsDisplay() const; + + void setOpacity(float); + bool opacityIsAnimating() const; + + void setFilters(const WebKit::WebFilterOperations&); + const WebKit::WebFilterOperations& filters() const { return m_filters; } + + // Background filters are filters applied to what is behind this layer, when they are viewed through non-opaque + // regions in this layer. They are used through the WebLayer interface, and are not exposed to HTML. + void setBackgroundFilters(const WebKit::WebFilterOperations&); + const WebKit::WebFilterOperations& backgroundFilters() const { return m_backgroundFilters; } + + virtual void setContentsOpaque(bool); + bool contentsOpaque() const { return m_contentsOpaque; } + + void setPosition(const FloatPoint&); + FloatPoint position() const { return m_position; } + + void setIsContainerForFixedPositionLayers(bool); + bool isContainerForFixedPositionLayers() const { return m_isContainerForFixedPositionLayers; } + + void setFixedToContainerLayer(bool); + bool fixedToContainerLayer() const { return m_fixedToContainerLayer; } + + void setSublayerTransform(const WebKit::WebTransformationMatrix&); + const WebKit::WebTransformationMatrix& sublayerTransform() const { return m_sublayerTransform; } + + void setTransform(const WebKit::WebTransformationMatrix&); + bool transformIsAnimating() const; + + const IntRect& visibleContentRect() const { return m_visibleContentRect; } + void setVisibleContentRect(const IntRect& visibleContentRect) { m_visibleContentRect = visibleContentRect; } + + void setScrollPosition(const IntPoint&); + const IntPoint& scrollPosition() const { return m_scrollPosition; } + + void setMaxScrollPosition(const IntSize&); + const IntSize& maxScrollPosition() const { return m_maxScrollPosition; } + + void setScrollable(bool); + bool scrollable() const { return m_scrollable; } + + void setShouldScrollOnMainThread(bool); + bool shouldScrollOnMainThread() const { return m_shouldScrollOnMainThread; } + + void setHaveWheelEventHandlers(bool); + bool haveWheelEventHandlers() const { return m_haveWheelEventHandlers; } + + void setNonFastScrollableRegion(const Region&); + void setNonFastScrollableRegionChanged() { m_nonFastScrollableRegionChanged = true; } + const Region& nonFastScrollableRegion() const { return m_nonFastScrollableRegion; } + + void setLayerScrollClient(WebKit::WebLayerScrollClient* layerScrollClient) { m_layerScrollClient = layerScrollClient; } + + void setDrawCheckerboardForMissingTiles(bool); + bool drawCheckerboardForMissingTiles() const { return m_drawCheckerboardForMissingTiles; } + + bool forceRenderSurface() const { return m_forceRenderSurface; } + void setForceRenderSurface(bool); + + IntSize scrollDelta() const { return IntSize(); } + + void setImplTransform(const WebKit::WebTransformationMatrix&); + const WebKit::WebTransformationMatrix& implTransform() const { return m_implTransform; } + + void setDoubleSided(bool); + bool doubleSided() const { return m_doubleSided; } + + void setPreserves3D(bool preserve3D) { m_preserves3D = preserve3D; } + bool preserves3D() const { return m_preserves3D; } + + void setUseParentBackfaceVisibility(bool useParentBackfaceVisibility) { m_useParentBackfaceVisibility = useParentBackfaceVisibility; } + bool useParentBackfaceVisibility() const { return m_useParentBackfaceVisibility; } + + virtual void setUseLCDText(bool); + bool useLCDText() const { return m_useLCDText; } + + virtual void setLayerTreeHost(CCLayerTreeHost*); + + bool hasContributingDelegatedRenderPasses() const { return false; } + + void setIsDrawable(bool); + + void setReplicaLayer(LayerChromium*); + LayerChromium* replicaLayer() const { return m_replicaLayer.get(); } + + bool hasMask() const { return m_maskLayer; } + bool hasReplica() const { return m_replicaLayer; } + bool replicaHasMask() const { return m_replicaLayer && (m_maskLayer || m_replicaLayer->m_maskLayer); } + + // These methods typically need to be overwritten by derived classes. + virtual bool drawsContent() const; + virtual void update(CCTextureUpdateQueue&, const CCOcclusionTracker*, CCRenderingStats&) { } + virtual bool needMoreUpdates(); + virtual void setIsMask(bool) { } + virtual void bindContentsTexture() { } + virtual bool needsContentsScale() const; + + void setDebugBorderColor(SkColor); + void setDebugBorderWidth(float); + void setDebugName(const std::string&); + + virtual void pushPropertiesTo(CCLayerImpl*); + + void clearRenderSurface() { m_renderSurface.reset(); } + RenderSurfaceChromium* renderSurface() const { return m_renderSurface.get(); } + void createRenderSurface(); + + float drawOpacity() const { return m_drawOpacity; } + void setDrawOpacity(float opacity) { m_drawOpacity = opacity; } + + bool drawOpacityIsAnimating() const { return m_drawOpacityIsAnimating; } + void setDrawOpacityIsAnimating(bool drawOpacityIsAnimating) { m_drawOpacityIsAnimating = drawOpacityIsAnimating; } + + LayerChromium* renderTarget() const { ASSERT(!m_renderTarget || m_renderTarget->renderSurface()); return m_renderTarget; } + void setRenderTarget(LayerChromium* target) { m_renderTarget = target; } + + bool drawTransformIsAnimating() const { return m_drawTransformIsAnimating; } + void setDrawTransformIsAnimating(bool animating) { m_drawTransformIsAnimating = animating; } + bool screenSpaceTransformIsAnimating() const { return m_screenSpaceTransformIsAnimating; } + void setScreenSpaceTransformIsAnimating(bool animating) { m_screenSpaceTransformIsAnimating = animating; } + + // This moves from layer space, with origin in the center to target space with origin in the top left. + // That is, it converts from logical, non-page-scaled, to target pixels (and if the target is the + // root render surface, then this converts to physical pixels). + const WebKit::WebTransformationMatrix& drawTransform() const { return m_drawTransform; } + void setDrawTransform(const WebKit::WebTransformationMatrix& matrix) { m_drawTransform = matrix; } + // This moves from content space, with origin the top left to screen space with origin in the top left. + // It converts logical, non-page-scaled pixels to physical pixels. + const WebKit::WebTransformationMatrix& screenSpaceTransform() const { return m_screenSpaceTransform; } + void setScreenSpaceTransform(const WebKit::WebTransformationMatrix& matrix) { m_screenSpaceTransform = matrix; } + const IntRect& drawableContentRect() const { return m_drawableContentRect; } + void setDrawableContentRect(const IntRect& rect) { m_drawableContentRect = rect; } + // The contentsScale converts from logical, non-page-scaled pixels to target pixels. + // The contentsScale is 1 for the root layer as it is already in physical pixels. + float contentsScale() const { return m_contentsScale; } + void setContentsScale(float); + + // When true, the layer's contents are not scaled by the current page scale factor. + // setBoundsContainPageScale recursively sets the value on all child layers. + void setBoundsContainPageScale(bool); + bool boundsContainPageScale() const { return m_boundsContainPageScale; } + + // Returns true if any of the layer's descendants has content to draw. + bool descendantDrawsContent(); + + CCLayerTreeHost* layerTreeHost() const { return m_layerTreeHost; } + + // Set the priority of all desired textures in this layer. + virtual void setTexturePriorities(const CCPriorityCalculator&) { } + + bool addAnimation(scoped_ptr); + void pauseAnimation(int animationId, double timeOffset); + void removeAnimation(int animationId); + + void suspendAnimations(double monotonicTime); + void resumeAnimations(double monotonicTime); + + CCLayerAnimationController* layerAnimationController() { return m_layerAnimationController.get(); } + void setLayerAnimationController(scoped_ptr); + scoped_ptr releaseLayerAnimationController(); + + void setLayerAnimationDelegate(WebKit::WebAnimationDelegate* layerAnimationDelegate) { m_layerAnimationDelegate = layerAnimationDelegate; } + + bool hasActiveAnimation() const; + + virtual void notifyAnimationStarted(const CCAnimationEvent&, double wallClockTime); + virtual void notifyAnimationFinished(double wallClockTime); + + virtual Region visibleContentOpaqueRegion() const; + + virtual ScrollbarLayerChromium* toScrollbarLayerChromium(); + +protected: + friend class CCLayerImpl; + friend class TreeSynchronizer; + virtual ~LayerChromium(); + + LayerChromium(); + + void setNeedsCommit(); + + IntRect layerRectToContentRect(const WebKit::WebRect& layerRect); + + // This flag is set when layer need repainting/updating. + bool m_needsDisplay; + + // Tracks whether this layer may have changed stacking order with its siblings. + bool m_stackingOrderChanged; + + // The update rect is the region of the compositor resource that was actually updated by the compositor. + // For layers that may do updating outside the compositor's control (i.e. plugin layers), this information + // is not available and the update rect will remain empty. + // Note this rect is in layer space (not content space). + FloatRect m_updateRect; + + scoped_refptr m_maskLayer; + + // Constructs a CCLayerImpl of the correct runtime type for this LayerChromium type. + virtual scoped_ptr createCCLayerImpl(); + int m_layerId; + +private: + friend class base::RefCounted; + + void setParent(LayerChromium*); + bool hasAncestor(LayerChromium*) const; + bool descendantIsFixedToContainerLayer() const; + + size_t numChildren() const { return m_children.size(); } + + // Returns the index of the child or -1 if not found. + int indexOfChild(const LayerChromium*); + + // This should only be called from removeFromParent. + void removeChild(LayerChromium*); + + LayerList m_children; + LayerChromium* m_parent; + + // LayerChromium instances have a weak pointer to their CCLayerTreeHost. + // This pointer value is nil when a LayerChromium is not in a tree and is + // updated via setLayerTreeHost() if a layer moves between trees. + CCLayerTreeHost* m_layerTreeHost; + + scoped_ptr m_layerAnimationController; + + // Layer properties. + IntSize m_bounds; + + // Uses layer's content space. + IntRect m_visibleContentRect; + + IntPoint m_scrollPosition; + IntSize m_maxScrollPosition; + bool m_scrollable; + bool m_shouldScrollOnMainThread; + bool m_haveWheelEventHandlers; + Region m_nonFastScrollableRegion; + bool m_nonFastScrollableRegionChanged; + FloatPoint m_position; + FloatPoint m_anchorPoint; + SkColor m_backgroundColor; + SkColor m_debugBorderColor; + float m_debugBorderWidth; + std::string m_debugName; + float m_opacity; + WebKit::WebFilterOperations m_filters; + WebKit::WebFilterOperations m_backgroundFilters; + float m_anchorPointZ; + bool m_isContainerForFixedPositionLayers; + bool m_fixedToContainerLayer; + bool m_isDrawable; + bool m_masksToBounds; + bool m_contentsOpaque; + bool m_doubleSided; + bool m_useLCDText; + bool m_preserves3D; + bool m_useParentBackfaceVisibility; + bool m_drawCheckerboardForMissingTiles; + bool m_forceRenderSurface; + + WebKit::WebTransformationMatrix m_transform; + WebKit::WebTransformationMatrix m_sublayerTransform; + + // Replica layer used for reflections. + scoped_refptr m_replicaLayer; + + // Transient properties. + scoped_ptr m_renderSurface; + float m_drawOpacity; + bool m_drawOpacityIsAnimating; + + LayerChromium* m_renderTarget; + + WebKit::WebTransformationMatrix m_drawTransform; + WebKit::WebTransformationMatrix m_screenSpaceTransform; + bool m_drawTransformIsAnimating; + bool m_screenSpaceTransformIsAnimating; + + // Uses target surface space. + IntRect m_drawableContentRect; + float m_contentsScale; + bool m_boundsContainPageScale; + + WebKit::WebTransformationMatrix m_implTransform; + + WebKit::WebAnimationDelegate* m_layerAnimationDelegate; + WebKit::WebLayerScrollClient* m_layerScrollClient; +}; + +void sortLayers(std::vector >::iterator, std::vector >::iterator, void*); + +} +#endif // USE(ACCELERATED_COMPOSITING) + +#endif diff --git a/cc/layer_animation_controller.cc b/cc/layer_animation_controller.cc new file mode 100644 index 0000000..2025db8 --- /dev/null +++ b/cc/layer_animation_controller.cc @@ -0,0 +1,407 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#include "CCLayerAnimationController.h" + +#include "CCActiveAnimation.h" +#include "CCKeyframedAnimationCurve.h" +#include +#include +#include + +using WebKit::WebTransformationMatrix; + +namespace cc { + +CCLayerAnimationController::CCLayerAnimationController(CCLayerAnimationControllerClient* client) + : m_forceSync(false) + , m_client(client) +{ +} + +CCLayerAnimationController::~CCLayerAnimationController() +{ +} + +scoped_ptr CCLayerAnimationController::create(CCLayerAnimationControllerClient* client) +{ + return make_scoped_ptr(new CCLayerAnimationController(client)); +} + +void CCLayerAnimationController::pauseAnimation(int animationId, double timeOffset) +{ + for (size_t i = 0; i < m_activeAnimations.size(); ++i) { + if (m_activeAnimations[i]->id() == animationId) + m_activeAnimations[i]->setRunState(CCActiveAnimation::Paused, timeOffset + m_activeAnimations[i]->startTime()); + } +} + +void CCLayerAnimationController::removeAnimation(int animationId) +{ + for (size_t i = 0; i < m_activeAnimations.size();) { + if (m_activeAnimations[i]->id() == animationId) + m_activeAnimations.remove(i); + else + i++; + } +} + +void CCLayerAnimationController::removeAnimation(int animationId, CCActiveAnimation::TargetProperty targetProperty) +{ + for (size_t i = 0; i < m_activeAnimations.size();) { + if (m_activeAnimations[i]->id() == animationId && m_activeAnimations[i]->targetProperty() == targetProperty) + m_activeAnimations.remove(i); + else + i++; + } +} + +// According to render layer backing, these are for testing only. +void CCLayerAnimationController::suspendAnimations(double monotonicTime) +{ + for (size_t i = 0; i < m_activeAnimations.size(); ++i) { + if (!m_activeAnimations[i]->isFinished()) + m_activeAnimations[i]->setRunState(CCActiveAnimation::Paused, monotonicTime); + } +} + +// Looking at GraphicsLayerCA, this appears to be the analog to suspendAnimations, which is for testing. +void CCLayerAnimationController::resumeAnimations(double monotonicTime) +{ + for (size_t i = 0; i < m_activeAnimations.size(); ++i) { + if (m_activeAnimations[i]->runState() == CCActiveAnimation::Paused) + m_activeAnimations[i]->setRunState(CCActiveAnimation::Running, monotonicTime); + } +} + +// Ensures that the list of active animations on the main thread and the impl thread +// are kept in sync. +void CCLayerAnimationController::pushAnimationUpdatesTo(CCLayerAnimationController* controllerImpl) +{ + if (m_forceSync) { + replaceImplThreadAnimations(controllerImpl); + m_forceSync = false; + } else { + purgeAnimationsMarkedForDeletion(); + pushNewAnimationsToImplThread(controllerImpl); + + // Remove finished impl side animations only after pushing, + // and only after the animations are deleted on the main thread + // this insures we will never push an animation twice. + removeAnimationsCompletedOnMainThread(controllerImpl); + + pushPropertiesToImplThread(controllerImpl); + } +} + +void CCLayerAnimationController::animate(double monotonicTime, CCAnimationEventsVector* events) +{ + startAnimationsWaitingForNextTick(monotonicTime, events); + startAnimationsWaitingForStartTime(monotonicTime, events); + startAnimationsWaitingForTargetAvailability(monotonicTime, events); + resolveConflicts(monotonicTime); + tickAnimations(monotonicTime); + markAnimationsForDeletion(monotonicTime, events); + startAnimationsWaitingForTargetAvailability(monotonicTime, events); +} + +void CCLayerAnimationController::addAnimation(scoped_ptr animation) +{ + m_activeAnimations.append(animation.Pass()); +} + +CCActiveAnimation* CCLayerAnimationController::getActiveAnimation(int groupId, CCActiveAnimation::TargetProperty targetProperty) const +{ + for (size_t i = 0; i < m_activeAnimations.size(); ++i) + if (m_activeAnimations[i]->group() == groupId && m_activeAnimations[i]->targetProperty() == targetProperty) + return m_activeAnimations[i]; + return 0; +} + +CCActiveAnimation* CCLayerAnimationController::getActiveAnimation(CCActiveAnimation::TargetProperty targetProperty) const +{ + for (size_t i = 0; i < m_activeAnimations.size(); ++i) { + size_t index = m_activeAnimations.size() - i - 1; + if (m_activeAnimations[index]->targetProperty() == targetProperty) + return m_activeAnimations[index]; + } + return 0; +} + +bool CCLayerAnimationController::hasActiveAnimation() const +{ + for (size_t i = 0; i < m_activeAnimations.size(); ++i) { + if (!m_activeAnimations[i]->isFinished()) + return true; + } + return false; +} + +bool CCLayerAnimationController::isAnimatingProperty(CCActiveAnimation::TargetProperty targetProperty) const +{ + for (size_t i = 0; i < m_activeAnimations.size(); ++i) { + if (m_activeAnimations[i]->runState() != CCActiveAnimation::Finished && m_activeAnimations[i]->runState() != CCActiveAnimation::Aborted && m_activeAnimations[i]->targetProperty() == targetProperty) + return true; + } + return false; +} + +void CCLayerAnimationController::notifyAnimationStarted(const CCAnimationEvent& event) +{ + for (size_t i = 0; i < m_activeAnimations.size(); ++i) { + if (m_activeAnimations[i]->group() == event.groupId && m_activeAnimations[i]->targetProperty() == event.targetProperty && m_activeAnimations[i]->needsSynchronizedStartTime()) { + m_activeAnimations[i]->setNeedsSynchronizedStartTime(false); + m_activeAnimations[i]->setStartTime(event.monotonicTime); + return; + } + } +} + +void CCLayerAnimationController::setClient(CCLayerAnimationControllerClient* client) +{ + m_client = client; +} + +void CCLayerAnimationController::pushNewAnimationsToImplThread(CCLayerAnimationController* controllerImpl) const +{ + // Any new animations owned by the main thread's controller are cloned and adde to the impl thread's controller. + for (size_t i = 0; i < m_activeAnimations.size(); ++i) { + // If the animation is already running on the impl thread, there is no need to copy it over. + if (controllerImpl->getActiveAnimation(m_activeAnimations[i]->group(), m_activeAnimations[i]->targetProperty())) + continue; + + // If the animation is not running on the impl thread, it does not necessarily mean that it needs + // to be copied over and started; it may have already finished. In this case, the impl thread animation + // will have already notified that it has started and the main thread animation will no longer need + // a synchronized start time. + if (!m_activeAnimations[i]->needsSynchronizedStartTime()) + continue; + + // The new animation should be set to run as soon as possible. + CCActiveAnimation::RunState initialRunState = CCActiveAnimation::WaitingForTargetAvailability; + double startTime = 0; + scoped_ptr toAdd(m_activeAnimations[i]->cloneAndInitialize(CCActiveAnimation::ControllingInstance, initialRunState, startTime)); + ASSERT(!toAdd->needsSynchronizedStartTime()); + controllerImpl->addAnimation(toAdd.Pass()); + } +} + +void CCLayerAnimationController::removeAnimationsCompletedOnMainThread(CCLayerAnimationController* controllerImpl) const +{ + // Delete all impl thread animations for which there is no corresponding main thread animation. + // Each iteration, controller->m_activeAnimations.size() is decremented or i is incremented + // guaranteeing progress towards loop termination. + for (size_t i = 0; i < controllerImpl->m_activeAnimations.size();) { + CCActiveAnimation* current = getActiveAnimation(controllerImpl->m_activeAnimations[i]->group(), controllerImpl->m_activeAnimations[i]->targetProperty()); + if (!current) + controllerImpl->m_activeAnimations.remove(i); + else + i++; + } +} + +void CCLayerAnimationController::pushPropertiesToImplThread(CCLayerAnimationController* controllerImpl) const +{ + for (size_t i = 0; i < m_activeAnimations.size(); ++i) { + CCActiveAnimation* currentImpl = controllerImpl->getActiveAnimation(m_activeAnimations[i]->group(), m_activeAnimations[i]->targetProperty()); + if (currentImpl) + m_activeAnimations[i]->pushPropertiesTo(currentImpl); + } +} + +void CCLayerAnimationController::startAnimationsWaitingForNextTick(double monotonicTime, CCAnimationEventsVector* events) +{ + for (size_t i = 0; i < m_activeAnimations.size(); ++i) { + if (m_activeAnimations[i]->runState() == CCActiveAnimation::WaitingForNextTick) { + m_activeAnimations[i]->setRunState(CCActiveAnimation::Running, monotonicTime); + if (!m_activeAnimations[i]->hasSetStartTime()) + m_activeAnimations[i]->setStartTime(monotonicTime); + if (events) + events->push_back(CCAnimationEvent(CCAnimationEvent::Started, m_client->id(), m_activeAnimations[i]->group(), m_activeAnimations[i]->targetProperty(), monotonicTime)); + } + } +} + +void CCLayerAnimationController::startAnimationsWaitingForStartTime(double monotonicTime, CCAnimationEventsVector* events) +{ + for (size_t i = 0; i < m_activeAnimations.size(); ++i) { + if (m_activeAnimations[i]->runState() == CCActiveAnimation::WaitingForStartTime && m_activeAnimations[i]->startTime() <= monotonicTime) { + m_activeAnimations[i]->setRunState(CCActiveAnimation::Running, monotonicTime); + if (events) + events->push_back(CCAnimationEvent(CCAnimationEvent::Started, m_client->id(), m_activeAnimations[i]->group(), m_activeAnimations[i]->targetProperty(), monotonicTime)); + } + } +} + +void CCLayerAnimationController::startAnimationsWaitingForTargetAvailability(double monotonicTime, CCAnimationEventsVector* events) +{ + // First collect running properties. + TargetProperties blockedProperties; + for (size_t i = 0; i < m_activeAnimations.size(); ++i) { + if (m_activeAnimations[i]->runState() == CCActiveAnimation::Running || m_activeAnimations[i]->runState() == CCActiveAnimation::Finished) + blockedProperties.insert(m_activeAnimations[i]->targetProperty()); + } + + for (size_t i = 0; i < m_activeAnimations.size(); ++i) { + if (m_activeAnimations[i]->runState() == CCActiveAnimation::WaitingForTargetAvailability) { + // Collect all properties for animations with the same group id (they should all also be in the list of animations). + TargetProperties enqueuedProperties; + enqueuedProperties.insert(m_activeAnimations[i]->targetProperty()); + for (size_t j = i + 1; j < m_activeAnimations.size(); ++j) { + if (m_activeAnimations[i]->group() == m_activeAnimations[j]->group()) + enqueuedProperties.insert(m_activeAnimations[j]->targetProperty()); + } + + // Check to see if intersection of the list of properties affected by the group and the list of currently + // blocked properties is null. In any case, the group's target properties need to be added to the list + // of blocked properties. + bool nullIntersection = true; + for (TargetProperties::iterator pIter = enqueuedProperties.begin(); pIter != enqueuedProperties.end(); ++pIter) { + if (!blockedProperties.insert(*pIter).second) + nullIntersection = false; + } + + // If the intersection is null, then we are free to start the animations in the group. + if (nullIntersection) { + m_activeAnimations[i]->setRunState(CCActiveAnimation::Running, monotonicTime); + if (!m_activeAnimations[i]->hasSetStartTime()) + m_activeAnimations[i]->setStartTime(monotonicTime); + if (events) + events->push_back(CCAnimationEvent(CCAnimationEvent::Started, m_client->id(), m_activeAnimations[i]->group(), m_activeAnimations[i]->targetProperty(), monotonicTime)); + for (size_t j = i + 1; j < m_activeAnimations.size(); ++j) { + if (m_activeAnimations[i]->group() == m_activeAnimations[j]->group()) { + m_activeAnimations[j]->setRunState(CCActiveAnimation::Running, monotonicTime); + if (!m_activeAnimations[j]->hasSetStartTime()) + m_activeAnimations[j]->setStartTime(monotonicTime); + } + } + } + } + } +} + +void CCLayerAnimationController::resolveConflicts(double monotonicTime) +{ + // Find any animations that are animating the same property and resolve the + // confict. We could eventually blend, but for now we'll just abort the + // previous animation (where 'previous' means: (1) has a prior start time or + // (2) has an equal start time, but was added to the queue earlier, i.e., + // has a lower index in m_activeAnimations). + for (size_t i = 0; i < m_activeAnimations.size(); ++i) { + if (m_activeAnimations[i]->runState() == CCActiveAnimation::Running) { + for (size_t j = i + 1; j < m_activeAnimations.size(); ++j) { + if (m_activeAnimations[j]->runState() == CCActiveAnimation::Running && m_activeAnimations[i]->targetProperty() == m_activeAnimations[j]->targetProperty()) { + if (m_activeAnimations[i]->startTime() > m_activeAnimations[j]->startTime()) + m_activeAnimations[j]->setRunState(CCActiveAnimation::Aborted, monotonicTime); + else + m_activeAnimations[i]->setRunState(CCActiveAnimation::Aborted, monotonicTime); + } + } + } + } +} + +void CCLayerAnimationController::markAnimationsForDeletion(double monotonicTime, CCAnimationEventsVector* events) +{ + for (size_t i = 0; i < m_activeAnimations.size(); i++) { + int groupId = m_activeAnimations[i]->group(); + bool allAnimsWithSameIdAreFinished = false; + // If an animation is finished, and not already marked for deletion, + // Find out if all other animations in the same group are also finished. + if (m_activeAnimations[i]->isFinished()) { + allAnimsWithSameIdAreFinished = true; + for (size_t j = 0; j < m_activeAnimations.size(); ++j) { + if (groupId == m_activeAnimations[j]->group() && !m_activeAnimations[j]->isFinished()) { + allAnimsWithSameIdAreFinished = false; + break; + } + } + } + if (allAnimsWithSameIdAreFinished) { + // We now need to remove all animations with the same group id as groupId + // (and send along animation finished notifications, if necessary). + for (size_t j = i; j < m_activeAnimations.size(); j++) { + if (groupId == m_activeAnimations[j]->group()) { + if (events) + events->push_back(CCAnimationEvent(CCAnimationEvent::Finished, m_client->id(), m_activeAnimations[j]->group(), m_activeAnimations[j]->targetProperty(), monotonicTime)); + m_activeAnimations[j]->setRunState(CCActiveAnimation::WaitingForDeletion, monotonicTime); + } + } + } + } +} + +void CCLayerAnimationController::purgeAnimationsMarkedForDeletion() +{ + for (size_t i = 0; i < m_activeAnimations.size();) { + if (m_activeAnimations[i]->runState() == CCActiveAnimation::WaitingForDeletion) + m_activeAnimations.remove(i); + else + i++; + } +} + +void CCLayerAnimationController::replaceImplThreadAnimations(CCLayerAnimationController* controllerImpl) const +{ + controllerImpl->m_activeAnimations.clear(); + for (size_t i = 0; i < m_activeAnimations.size(); ++i) { + scoped_ptr toAdd; + if (m_activeAnimations[i]->needsSynchronizedStartTime()) { + // We haven't received an animation started notification yet, so it + // is important that we add it in a 'waiting' and not 'running' state. + CCActiveAnimation::RunState initialRunState = CCActiveAnimation::WaitingForTargetAvailability; + double startTime = 0; + toAdd = m_activeAnimations[i]->cloneAndInitialize(CCActiveAnimation::ControllingInstance, initialRunState, startTime).Pass(); + } else + toAdd = m_activeAnimations[i]->clone(CCActiveAnimation::ControllingInstance).Pass(); + + controllerImpl->addAnimation(toAdd.Pass()); + } +} + +void CCLayerAnimationController::tickAnimations(double monotonicTime) +{ + for (size_t i = 0; i < m_activeAnimations.size(); ++i) { + if (m_activeAnimations[i]->runState() == CCActiveAnimation::Running || m_activeAnimations[i]->runState() == CCActiveAnimation::Paused) { + double trimmed = m_activeAnimations[i]->trimTimeToCurrentIteration(monotonicTime); + + // Animation assumes its initial value until it gets the synchronized start time + // from the impl thread and can start ticking. + if (m_activeAnimations[i]->needsSynchronizedStartTime()) + trimmed = 0; + + switch (m_activeAnimations[i]->targetProperty()) { + + case CCActiveAnimation::Transform: { + const CCTransformAnimationCurve* transformAnimationCurve = m_activeAnimations[i]->curve()->toTransformAnimationCurve(); + const WebTransformationMatrix matrix = transformAnimationCurve->getValue(trimmed); + if (m_activeAnimations[i]->isFinishedAt(monotonicTime)) + m_activeAnimations[i]->setRunState(CCActiveAnimation::Finished, monotonicTime); + + m_client->setTransformFromAnimation(matrix); + break; + } + + case CCActiveAnimation::Opacity: { + const CCFloatAnimationCurve* floatAnimationCurve = m_activeAnimations[i]->curve()->toFloatAnimationCurve(); + const float opacity = floatAnimationCurve->getValue(trimmed); + if (m_activeAnimations[i]->isFinishedAt(monotonicTime)) + m_activeAnimations[i]->setRunState(CCActiveAnimation::Finished, monotonicTime); + + m_client->setOpacityFromAnimation(opacity); + break; + } + + // Do nothing for sentinel value. + case CCActiveAnimation::TargetPropertyEnumSize: + ASSERT_NOT_REACHED(); + + } + } + } +} + +} // namespace cc diff --git a/cc/layer_animation_controller.h b/cc/layer_animation_controller.h index 638cbb2..2fdb91c 100644 --- a/cc/layer_animation_controller.h +++ b/cc/layer_animation_controller.h @@ -1,3 +1,112 @@ // Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CCLayerAnimationController_h +#define CCLayerAnimationController_h + +#include "CCAnimationEvents.h" + +#include "base/basictypes.h" +#include "base/hash_tables.h" +#include "base/memory/scoped_ptr.h" +#include "cc/scoped_ptr_vector.h" + +namespace WebKit { +class WebTransformationMatrix; +} + +namespace cc { + +class Animation; +class IntSize; +class KeyframeValueList; + +class CCLayerAnimationControllerClient { +public: + virtual ~CCLayerAnimationControllerClient() { } + + virtual int id() const = 0; + virtual void setOpacityFromAnimation(float) = 0; + virtual float opacity() const = 0; + virtual void setTransformFromAnimation(const WebKit::WebTransformationMatrix&) = 0; + virtual const WebKit::WebTransformationMatrix& transform() const = 0; +}; + +class CCLayerAnimationController { +public: + static scoped_ptr create(CCLayerAnimationControllerClient*); + + virtual ~CCLayerAnimationController(); + + // These methods are virtual for testing. + virtual void addAnimation(scoped_ptr); + virtual void pauseAnimation(int animationId, double timeOffset); + virtual void removeAnimation(int animationId); + virtual void removeAnimation(int animationId, CCActiveAnimation::TargetProperty); + virtual void suspendAnimations(double monotonicTime); + virtual void resumeAnimations(double monotonicTime); + + // Ensures that the list of active animations on the main thread and the impl thread + // are kept in sync. This function does not take ownership of the impl thread controller. + virtual void pushAnimationUpdatesTo(CCLayerAnimationController*); + + void animate(double monotonicTime, CCAnimationEventsVector*); + + // Returns the active animation in the given group, animating the given property, if such an + // animation exists. + CCActiveAnimation* getActiveAnimation(int groupId, CCActiveAnimation::TargetProperty) const; + + // Returns the active animation animating the given property that is either running, or is + // next to run, if such an animation exists. + CCActiveAnimation* getActiveAnimation(CCActiveAnimation::TargetProperty) const; + + // Returns true if there are any animations that have neither finished nor aborted. + bool hasActiveAnimation() const; + + // Returns true if there is an animation currently animating the given property, or + // if there is an animation scheduled to animate this property in the future. + bool isAnimatingProperty(CCActiveAnimation::TargetProperty) const; + + // This is called in response to an animation being started on the impl thread. This + // function updates the corresponding main thread animation's start time. + void notifyAnimationStarted(const CCAnimationEvent&); + + // If a sync is forced, then the next time animation updates are pushed to the impl + // thread, all animations will be transferred. + void setForceSync() { m_forceSync = true; } + + void setClient(CCLayerAnimationControllerClient*); + +protected: + explicit CCLayerAnimationController(CCLayerAnimationControllerClient*); + +private: + typedef base::hash_set TargetProperties; + + void pushNewAnimationsToImplThread(CCLayerAnimationController*) const; + void removeAnimationsCompletedOnMainThread(CCLayerAnimationController*) const; + void pushPropertiesToImplThread(CCLayerAnimationController*) const; + void replaceImplThreadAnimations(CCLayerAnimationController*) const; + + void startAnimationsWaitingForNextTick(double monotonicTime, CCAnimationEventsVector*); + void startAnimationsWaitingForStartTime(double monotonicTime, CCAnimationEventsVector*); + void startAnimationsWaitingForTargetAvailability(double monotonicTime, CCAnimationEventsVector*); + void resolveConflicts(double monotonicTime); + void markAnimationsForDeletion(double monotonicTime, CCAnimationEventsVector*); + void purgeAnimationsMarkedForDeletion(); + + void tickAnimations(double monotonicTime); + + // If this is true, we force a sync to the impl thread. + bool m_forceSync; + + CCLayerAnimationControllerClient* m_client; + ScopedPtrVector m_activeAnimations; + + DISALLOW_COPY_AND_ASSIGN(CCLayerAnimationController); +}; + +} // namespace cc + +#endif // CCLayerAnimationController_h diff --git a/cc/layer_impl.cc b/cc/layer_impl.cc new file mode 100644 index 0000000..16c9356 --- /dev/null +++ b/cc/layer_impl.cc @@ -0,0 +1,685 @@ +// Copyright 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#if USE(ACCELERATED_COMPOSITING) + +#include "CCLayerImpl.h" + +#include "base/stringprintf.h" +#include "CCDebugBorderDrawQuad.h" +#include "CCLayerSorter.h" +#include "CCMathUtil.h" +#include "CCProxy.h" +#include "CCQuadSink.h" +#include "CCScrollbarAnimationController.h" +#include "CCSettings.h" +#include "TraceEvent.h" + +using WebKit::WebTransformationMatrix; + +namespace cc { + +CCLayerImpl::CCLayerImpl(int id) + : m_parent(0) + , m_maskLayerId(-1) + , m_replicaLayerId(-1) + , m_layerId(id) + , m_layerTreeHostImpl(0) + , m_anchorPoint(0.5, 0.5) + , m_anchorPointZ(0) + , m_scrollable(false) + , m_shouldScrollOnMainThread(false) + , m_haveWheelEventHandlers(false) + , m_backgroundColor(0) + , m_doubleSided(true) + , m_layerPropertyChanged(false) + , m_layerSurfacePropertyChanged(false) + , m_masksToBounds(false) + , m_contentsOpaque(false) + , m_opacity(1.0) + , m_preserves3D(false) + , m_useParentBackfaceVisibility(false) + , m_drawCheckerboardForMissingTiles(false) + , m_useLCDText(false) + , m_drawsContent(false) + , m_forceRenderSurface(false) + , m_isContainerForFixedPositionLayers(false) + , m_fixedToContainerLayer(false) + , m_renderTarget(0) + , m_drawDepth(0) + , m_drawOpacity(0) + , m_drawOpacityIsAnimating(false) + , m_debugBorderColor(0) + , m_debugBorderWidth(0) + , m_drawTransformIsAnimating(false) + , m_screenSpaceTransformIsAnimating(false) +#ifndef NDEBUG + , m_betweenWillDrawAndDidDraw(false) +#endif + , m_layerAnimationController(CCLayerAnimationController::create(this)) +{ + ASSERT(CCProxy::isImplThread()); + ASSERT(m_layerId > 0); +} + +CCLayerImpl::~CCLayerImpl() +{ + ASSERT(CCProxy::isImplThread()); +#ifndef NDEBUG + ASSERT(!m_betweenWillDrawAndDidDraw); +#endif +} + +void CCLayerImpl::addChild(scoped_ptr child) +{ + child->setParent(this); + m_children.append(child.Pass()); +} + +void CCLayerImpl::removeFromParent() +{ + if (!m_parent) + return; + + CCLayerImpl* parent = m_parent; + m_parent = 0; + + for (size_t i = 0; i < parent->m_children.size(); ++i) { + if (parent->m_children[i] == this) { + parent->m_children.remove(i); + return; + } + } +} + +void CCLayerImpl::removeAllChildren() +{ + while (m_children.size()) + m_children[0]->removeFromParent(); +} + +void CCLayerImpl::clearChildList() +{ + m_children.clear(); +} + +void CCLayerImpl::createRenderSurface() +{ + ASSERT(!m_renderSurface); + m_renderSurface = adoptPtr(new CCRenderSurface(this)); + setRenderTarget(this); +} + +bool CCLayerImpl::descendantDrawsContent() +{ + for (size_t i = 0; i < m_children.size(); ++i) { + if (m_children[i]->drawsContent() || m_children[i]->descendantDrawsContent()) + return true; + } + return false; +} + +scoped_ptr CCLayerImpl::createSharedQuadState() const +{ + return CCSharedQuadState::create(m_drawTransform, m_visibleContentRect, m_drawableContentRect, m_drawOpacity, m_contentsOpaque); +} + +void CCLayerImpl::willDraw(CCResourceProvider*) +{ +#ifndef NDEBUG + // willDraw/didDraw must be matched. + ASSERT(!m_betweenWillDrawAndDidDraw); + m_betweenWillDrawAndDidDraw = true; +#endif +} + +void CCLayerImpl::didDraw(CCResourceProvider*) +{ +#ifndef NDEBUG + ASSERT(m_betweenWillDrawAndDidDraw); + m_betweenWillDrawAndDidDraw = false; +#endif +} + +void CCLayerImpl::appendDebugBorderQuad(CCQuadSink& quadList, const CCSharedQuadState* sharedQuadState, CCAppendQuadsData& appendQuadsData) const +{ + if (!hasDebugBorders()) + return; + + IntRect contentRect(IntPoint(), contentBounds()); + quadList.append(CCDebugBorderDrawQuad::create(sharedQuadState, contentRect, debugBorderColor(), debugBorderWidth()).PassAs(), appendQuadsData); +} + +bool CCLayerImpl::hasContributingDelegatedRenderPasses() const +{ + return false; +} + +CCRenderPass::Id CCLayerImpl::firstContributingRenderPassId() const +{ + return CCRenderPass::Id(0, 0); +} + +CCRenderPass::Id CCLayerImpl::nextContributingRenderPassId(CCRenderPass::Id) const +{ + return CCRenderPass::Id(0, 0); +} + +CCResourceProvider::ResourceId CCLayerImpl::contentsResourceId() const +{ + ASSERT_NOT_REACHED(); + return 0; +} + +FloatSize CCLayerImpl::scrollBy(const FloatSize& scroll) +{ + IntSize minDelta = -toSize(m_scrollPosition); + IntSize maxDelta = m_maxScrollPosition - toSize(m_scrollPosition); + // Clamp newDelta so that position + delta stays within scroll bounds. + FloatSize newDelta = (m_scrollDelta + scroll).expandedTo(minDelta).shrunkTo(maxDelta); + FloatSize unscrolled = m_scrollDelta + scroll - newDelta; + + if (m_scrollDelta == newDelta) + return unscrolled; + + m_scrollDelta = newDelta; + if (m_scrollbarAnimationController) + m_scrollbarAnimationController->updateScrollOffset(this); + noteLayerPropertyChangedForSubtree(); + + return unscrolled; +} + +CCInputHandlerClient::ScrollStatus CCLayerImpl::tryScroll(const IntPoint& viewportPoint, CCInputHandlerClient::ScrollInputType type) const +{ + if (shouldScrollOnMainThread()) { + TRACE_EVENT0("cc", "CCLayerImpl::tryScroll: Failed shouldScrollOnMainThread"); + return CCInputHandlerClient::ScrollOnMainThread; + } + + if (!screenSpaceTransform().isInvertible()) { + TRACE_EVENT0("cc", "CCLayerImpl::tryScroll: Ignored nonInvertibleTransform"); + return CCInputHandlerClient::ScrollIgnored; + } + + if (!nonFastScrollableRegion().isEmpty()) { + bool clipped = false; + FloatPoint hitTestPointInLocalSpace = CCMathUtil::projectPoint(screenSpaceTransform().inverse(), FloatPoint(viewportPoint), clipped); + if (!clipped && nonFastScrollableRegion().contains(flooredIntPoint(hitTestPointInLocalSpace))) { + TRACE_EVENT0("cc", "CCLayerImpl::tryScroll: Failed nonFastScrollableRegion"); + return CCInputHandlerClient::ScrollOnMainThread; + } + } + + if (type == CCInputHandlerClient::Wheel && haveWheelEventHandlers()) { + TRACE_EVENT0("cc", "CCLayerImpl::tryScroll: Failed wheelEventHandlers"); + return CCInputHandlerClient::ScrollOnMainThread; + } + + if (!scrollable()) { + TRACE_EVENT0("cc", "CCLayerImpl::tryScroll: Ignored not scrollable"); + return CCInputHandlerClient::ScrollIgnored; + } + + return CCInputHandlerClient::ScrollStarted; +} + +bool CCLayerImpl::drawCheckerboardForMissingTiles() const +{ + return m_drawCheckerboardForMissingTiles && !CCSettings::backgroundColorInsteadOfCheckerboard(); +} + +IntRect CCLayerImpl::layerRectToContentRect(const WebKit::WebRect& layerRect) +{ + float widthScale = static_cast(contentBounds().width()) / bounds().width(); + float heightScale = static_cast(contentBounds().height()) / bounds().height(); + FloatRect contentRect(layerRect.x, layerRect.y, layerRect.width, layerRect.height); + contentRect.scale(widthScale, heightScale); + return enclosingIntRect(contentRect); +} + +std::string CCLayerImpl::indentString(int indent) +{ + std::string str; + for (int i = 0; i != indent; ++i) + str.append(" "); + return str; +} + +void CCLayerImpl::dumpLayerProperties(std::string* str, int indent) const +{ + std::string indentStr = indentString(indent); + str->append(indentStr); + base::StringAppendF(str, "layer ID: %d\n", m_layerId); + + str->append(indentStr); + base::StringAppendF(str, "bounds: %d, %d\n", bounds().width(), bounds().height()); + + if (m_renderTarget) { + str->append(indentStr); + base::StringAppendF(str, "renderTarget: %d\n", m_renderTarget->m_layerId); + } + + str->append(indentStr); + base::StringAppendF(str, "drawTransform: %f, %f, %f, %f // %f, %f, %f, %f // %f, %f, %f, %f // %f, %f, %f, %f\n", + m_drawTransform.m11(), m_drawTransform.m12(), m_drawTransform.m13(), m_drawTransform.m14(), + m_drawTransform.m21(), m_drawTransform.m22(), m_drawTransform.m23(), m_drawTransform.m24(), + m_drawTransform.m31(), m_drawTransform.m32(), m_drawTransform.m33(), m_drawTransform.m34(), + m_drawTransform.m41(), m_drawTransform.m42(), m_drawTransform.m43(), m_drawTransform.m44()); + + str->append(indentStr); + base::StringAppendF(str, "drawsContent: %s\n", m_drawsContent ? "yes" : "no"); +} + +void sortLayers(std::vector::iterator first, std::vector::iterator end, CCLayerSorter* layerSorter) +{ + TRACE_EVENT0("cc", "CCLayerImpl::sortLayers"); + layerSorter->sort(first, end); +} + +std::string CCLayerImpl::layerTreeAsText() const +{ + std::string str; + dumpLayer(&str, 0); + return str; +} + +void CCLayerImpl::dumpLayer(std::string* str, int indent) const +{ + str->append(indentString(indent)); + base::StringAppendF(str, "%s(%s)\n", layerTypeAsString(), m_debugName.data()); + dumpLayerProperties(str, indent+2); + if (m_replicaLayer) { + str->append(indentString(indent+2)); + str->append("Replica:\n"); + m_replicaLayer->dumpLayer(str, indent+3); + } + if (m_maskLayer) { + str->append(indentString(indent+2)); + str->append("Mask:\n"); + m_maskLayer->dumpLayer(str, indent+3); + } + for (size_t i = 0; i < m_children.size(); ++i) + m_children[i]->dumpLayer(str, indent+1); +} + +void CCLayerImpl::setStackingOrderChanged(bool stackingOrderChanged) +{ + // We don't need to store this flag; we only need to track that the change occurred. + if (stackingOrderChanged) + noteLayerPropertyChangedForSubtree(); +} + +bool CCLayerImpl::layerSurfacePropertyChanged() const +{ + if (m_layerSurfacePropertyChanged) + return true; + + // If this layer's surface property hasn't changed, we want to see if + // some layer above us has changed this property. This is done for the + // case when such parent layer does not draw content, and therefore will + // not be traversed by the damage tracker. We need to make sure that + // property change on such layer will be caught by its descendants. + CCLayerImpl* current = this->m_parent; + while (current && !current->m_renderSurface) { + if (current->m_layerSurfacePropertyChanged) + return true; + current = current->m_parent; + } + + return false; +} + +void CCLayerImpl::noteLayerPropertyChangedForSubtree() +{ + m_layerPropertyChanged = true; + noteLayerPropertyChangedForDescendants(); +} + +void CCLayerImpl::noteLayerPropertyChangedForDescendants() +{ + for (size_t i = 0; i < m_children.size(); ++i) + m_children[i]->noteLayerPropertyChangedForSubtree(); +} + +const char* CCLayerImpl::layerTypeAsString() const +{ + return "LayerChromium"; +} + +void CCLayerImpl::resetAllChangeTrackingForSubtree() +{ + m_layerPropertyChanged = false; + m_layerSurfacePropertyChanged = false; + + m_updateRect = FloatRect(); + + if (m_renderSurface) + m_renderSurface->resetPropertyChangedFlag(); + + if (m_maskLayer) + m_maskLayer->resetAllChangeTrackingForSubtree(); + + if (m_replicaLayer) + m_replicaLayer->resetAllChangeTrackingForSubtree(); // also resets the replica mask, if it exists. + + for (size_t i = 0; i < m_children.size(); ++i) + m_children[i]->resetAllChangeTrackingForSubtree(); +} + +bool CCLayerImpl::layerIsAlwaysDamaged() const +{ + return false; +} + +int CCLayerImpl::id() const +{ + return m_layerId; +} + +float CCLayerImpl::opacity() const +{ + return m_opacity; +} + +void CCLayerImpl::setOpacityFromAnimation(float opacity) +{ + setOpacity(opacity); +} + +const WebKit::WebTransformationMatrix& CCLayerImpl::transform() const +{ + return m_transform; +} + +void CCLayerImpl::setTransformFromAnimation(const WebTransformationMatrix& transform) +{ + setTransform(transform); +} + +void CCLayerImpl::setBounds(const IntSize& bounds) +{ + if (m_bounds == bounds) + return; + + m_bounds = bounds; + + if (masksToBounds()) + noteLayerPropertyChangedForSubtree(); + else + m_layerPropertyChanged = true; +} + +void CCLayerImpl::setMaskLayer(scoped_ptr maskLayer) +{ + m_maskLayer = maskLayer.Pass(); + + int newLayerId = m_maskLayer ? m_maskLayer->id() : -1; + if (newLayerId == m_maskLayerId) + return; + + m_maskLayerId = newLayerId; + noteLayerPropertyChangedForSubtree(); +} + +void CCLayerImpl::setReplicaLayer(scoped_ptr replicaLayer) +{ + m_replicaLayer = replicaLayer.Pass(); + + int newLayerId = m_replicaLayer ? m_replicaLayer->id() : -1; + if (newLayerId == m_replicaLayerId) + return; + + m_replicaLayerId = newLayerId; + noteLayerPropertyChangedForSubtree(); +} + +void CCLayerImpl::setDrawsContent(bool drawsContent) +{ + if (m_drawsContent == drawsContent) + return; + + m_drawsContent = drawsContent; + m_layerPropertyChanged = true; +} + +void CCLayerImpl::setAnchorPoint(const FloatPoint& anchorPoint) +{ + if (m_anchorPoint == anchorPoint) + return; + + m_anchorPoint = anchorPoint; + noteLayerPropertyChangedForSubtree(); +} + +void CCLayerImpl::setAnchorPointZ(float anchorPointZ) +{ + if (m_anchorPointZ == anchorPointZ) + return; + + m_anchorPointZ = anchorPointZ; + noteLayerPropertyChangedForSubtree(); +} + +void CCLayerImpl::setBackgroundColor(SkColor backgroundColor) +{ + if (m_backgroundColor == backgroundColor) + return; + + m_backgroundColor = backgroundColor; + m_layerPropertyChanged = true; +} + +void CCLayerImpl::setFilters(const WebKit::WebFilterOperations& filters) +{ + if (m_filters == filters) + return; + + m_filters = filters; + noteLayerPropertyChangedForSubtree(); +} + +void CCLayerImpl::setBackgroundFilters(const WebKit::WebFilterOperations& backgroundFilters) +{ + if (m_backgroundFilters == backgroundFilters) + return; + + m_backgroundFilters = backgroundFilters; + m_layerPropertyChanged = true; +} + +void CCLayerImpl::setMasksToBounds(bool masksToBounds) +{ + if (m_masksToBounds == masksToBounds) + return; + + m_masksToBounds = masksToBounds; + noteLayerPropertyChangedForSubtree(); +} + +void CCLayerImpl::setContentsOpaque(bool opaque) +{ + if (m_contentsOpaque == opaque) + return; + + m_contentsOpaque = opaque; + noteLayerPropertyChangedForSubtree(); +} + +void CCLayerImpl::setOpacity(float opacity) +{ + if (m_opacity == opacity) + return; + + m_opacity = opacity; + m_layerSurfacePropertyChanged = true; +} + +bool CCLayerImpl::opacityIsAnimating() const +{ + return m_layerAnimationController->isAnimatingProperty(CCActiveAnimation::Opacity); +} + +void CCLayerImpl::setPosition(const FloatPoint& position) +{ + if (m_position == position) + return; + + m_position = position; + noteLayerPropertyChangedForSubtree(); +} + +void CCLayerImpl::setPreserves3D(bool preserves3D) +{ + if (m_preserves3D == preserves3D) + return; + + m_preserves3D = preserves3D; + noteLayerPropertyChangedForSubtree(); +} + +void CCLayerImpl::setSublayerTransform(const WebTransformationMatrix& sublayerTransform) +{ + if (m_sublayerTransform == sublayerTransform) + return; + + m_sublayerTransform = sublayerTransform; + // sublayer transform does not affect the current layer; it affects only its children. + noteLayerPropertyChangedForDescendants(); +} + +void CCLayerImpl::setTransform(const WebTransformationMatrix& transform) +{ + if (m_transform == transform) + return; + + m_transform = transform; + m_layerSurfacePropertyChanged = true; +} + +bool CCLayerImpl::transformIsAnimating() const +{ + return m_layerAnimationController->isAnimatingProperty(CCActiveAnimation::Transform); +} + +void CCLayerImpl::setDebugBorderColor(SkColor debugBorderColor) +{ + if (m_debugBorderColor == debugBorderColor) + return; + + m_debugBorderColor = debugBorderColor; + m_layerPropertyChanged = true; +} + +void CCLayerImpl::setDebugBorderWidth(float debugBorderWidth) +{ + if (m_debugBorderWidth == debugBorderWidth) + return; + + m_debugBorderWidth = debugBorderWidth; + m_layerPropertyChanged = true; +} + +bool CCLayerImpl::hasDebugBorders() const +{ + return SkColorGetA(m_debugBorderColor) && debugBorderWidth() > 0; +} + +void CCLayerImpl::setContentBounds(const IntSize& contentBounds) +{ + if (m_contentBounds == contentBounds) + return; + + m_contentBounds = contentBounds; + m_layerPropertyChanged = true; +} + +void CCLayerImpl::setScrollPosition(const IntPoint& scrollPosition) +{ + if (m_scrollPosition == scrollPosition) + return; + + m_scrollPosition = scrollPosition; + noteLayerPropertyChangedForSubtree(); +} + +void CCLayerImpl::setScrollDelta(const FloatSize& scrollDelta) +{ + if (m_scrollDelta == scrollDelta) + return; + + m_scrollDelta = scrollDelta; + noteLayerPropertyChangedForSubtree(); +} + +void CCLayerImpl::setImplTransform(const WebKit::WebTransformationMatrix& transform) +{ + if (m_implTransform == transform) + return; + + m_implTransform = transform; + noteLayerPropertyChangedForSubtree(); +} + +void CCLayerImpl::setDoubleSided(bool doubleSided) +{ + if (m_doubleSided == doubleSided) + return; + + m_doubleSided = doubleSided; + noteLayerPropertyChangedForSubtree(); +} + +Region CCLayerImpl::visibleContentOpaqueRegion() const +{ + if (contentsOpaque()) + return visibleContentRect(); + return Region(); +} + +void CCLayerImpl::didLoseContext() +{ +} + +void CCLayerImpl::setMaxScrollPosition(const IntSize& maxScrollPosition) +{ + m_maxScrollPosition = maxScrollPosition; + + if (!m_scrollbarAnimationController) + return; + m_scrollbarAnimationController->updateScrollOffset(this); +} + +CCScrollbarLayerImpl* CCLayerImpl::horizontalScrollbarLayer() const +{ + return m_scrollbarAnimationController ? m_scrollbarAnimationController->horizontalScrollbarLayer() : 0; +} + +void CCLayerImpl::setHorizontalScrollbarLayer(CCScrollbarLayerImpl* scrollbarLayer) +{ + if (!m_scrollbarAnimationController) + m_scrollbarAnimationController = CCScrollbarAnimationController::create(this); + m_scrollbarAnimationController->setHorizontalScrollbarLayer(scrollbarLayer); + m_scrollbarAnimationController->updateScrollOffset(this); +} + +CCScrollbarLayerImpl* CCLayerImpl::verticalScrollbarLayer() const +{ + return m_scrollbarAnimationController ? m_scrollbarAnimationController->verticalScrollbarLayer() : 0; +} + +void CCLayerImpl::setVerticalScrollbarLayer(CCScrollbarLayerImpl* scrollbarLayer) +{ + if (!m_scrollbarAnimationController) + m_scrollbarAnimationController = CCScrollbarAnimationController::create(this); + m_scrollbarAnimationController->setVerticalScrollbarLayer(scrollbarLayer); + m_scrollbarAnimationController->updateScrollOffset(this); +} + +} + + +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/cc/layer_impl.h b/cc/layer_impl.h index 638cbb2..e34ccc8 100644 --- a/cc/layer_impl.h +++ b/cc/layer_impl.h @@ -1,3 +1,399 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. +// Copyright 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CCLayerImpl_h +#define CCLayerImpl_h + +#include "base/memory/scoped_ptr.h" +#include "cc/scoped_ptr_vector.h" +#include "CCInputHandler.h" +#include "CCLayerAnimationController.h" +#include "CCRenderPass.h" +#include "CCRenderSurface.h" +#include "CCResourceProvider.h" +#include "CCSharedQuadState.h" +#include "FloatRect.h" +#include "IntRect.h" +#include "Region.h" +#include "SkColor.h" +#include +#include +#include +#include + +namespace cc { + +class CCLayerSorter; +class CCLayerTreeHostImpl; +class CCQuadSink; +class CCRenderer; +class CCScrollbarAnimationController; +class CCScrollbarLayerImpl; +class LayerChromium; + +struct CCAppendQuadsData; + +class CCLayerImpl : public CCLayerAnimationControllerClient { +public: + static scoped_ptr create(int id) + { + return make_scoped_ptr(new CCLayerImpl(id)); + } + + virtual ~CCLayerImpl(); + + // CCLayerAnimationControllerClient implementation. + virtual int id() const OVERRIDE; + virtual void setOpacityFromAnimation(float) OVERRIDE; + virtual float opacity() const OVERRIDE; + virtual void setTransformFromAnimation(const WebKit::WebTransformationMatrix&) OVERRIDE; + virtual const WebKit::WebTransformationMatrix& transform() const OVERRIDE; + + // Tree structure. + CCLayerImpl* parent() const { return m_parent; } + const ScopedPtrVector& children() const { return m_children; } + void addChild(scoped_ptr); + void removeFromParent(); + void removeAllChildren(); + + void setMaskLayer(scoped_ptr); + CCLayerImpl* maskLayer() const { return m_maskLayer.get(); } + + void setReplicaLayer(scoped_ptr); + CCLayerImpl* replicaLayer() const { return m_replicaLayer.get(); } + + bool hasMask() const { return m_maskLayer; } + bool hasReplica() const { return m_replicaLayer; } + bool replicaHasMask() const { return m_replicaLayer && (m_maskLayer || m_replicaLayer->m_maskLayer); } + + CCLayerTreeHostImpl* layerTreeHostImpl() const { return m_layerTreeHostImpl; } + void setLayerTreeHostImpl(CCLayerTreeHostImpl* hostImpl) { m_layerTreeHostImpl = hostImpl; } + + scoped_ptr createSharedQuadState() const; + // willDraw must be called before appendQuads. If willDraw is called, + // didDraw is guaranteed to be called before another willDraw or before + // the layer is destroyed. To enforce this, any class that overrides + // willDraw/didDraw must call the base class version. + virtual void willDraw(CCResourceProvider*); + virtual void appendQuads(CCQuadSink&, CCAppendQuadsData&) { } + virtual void didDraw(CCResourceProvider*); + + virtual CCResourceProvider::ResourceId contentsResourceId() const; + + virtual bool hasContributingDelegatedRenderPasses() const; + virtual CCRenderPass::Id firstContributingRenderPassId() const; + virtual CCRenderPass::Id nextContributingRenderPassId(CCRenderPass::Id) const; + + // Returns true if this layer has content to draw. + void setDrawsContent(bool); + bool drawsContent() const { return m_drawsContent; } + + bool forceRenderSurface() const { return m_forceRenderSurface; } + void setForceRenderSurface(bool force) { m_forceRenderSurface = force; } + + // Returns true if any of the layer's descendants has content to draw. + virtual bool descendantDrawsContent(); + + void setAnchorPoint(const FloatPoint&); + const FloatPoint& anchorPoint() const { return m_anchorPoint; } + + void setAnchorPointZ(float); + float anchorPointZ() const { return m_anchorPointZ; } + + void setBackgroundColor(SkColor); + SkColor backgroundColor() const { return m_backgroundColor; } + + void setFilters(const WebKit::WebFilterOperations&); + const WebKit::WebFilterOperations& filters() const { return m_filters; } + + void setBackgroundFilters(const WebKit::WebFilterOperations&); + const WebKit::WebFilterOperations& backgroundFilters() const { return m_backgroundFilters; } + + void setMasksToBounds(bool); + bool masksToBounds() const { return m_masksToBounds; } + + void setContentsOpaque(bool); + bool contentsOpaque() const { return m_contentsOpaque; } + + void setOpacity(float); + bool opacityIsAnimating() const; + + void setPosition(const FloatPoint&); + const FloatPoint& position() const { return m_position; } + + void setIsContainerForFixedPositionLayers(bool isContainerForFixedPositionLayers) { m_isContainerForFixedPositionLayers = isContainerForFixedPositionLayers; } + bool isContainerForFixedPositionLayers() const { return m_isContainerForFixedPositionLayers; } + + void setFixedToContainerLayer(bool fixedToContainerLayer = true) { m_fixedToContainerLayer = fixedToContainerLayer;} + bool fixedToContainerLayer() const { return m_fixedToContainerLayer; } + + void setPreserves3D(bool); + bool preserves3D() const { return m_preserves3D; } + + void setUseParentBackfaceVisibility(bool useParentBackfaceVisibility) { m_useParentBackfaceVisibility = useParentBackfaceVisibility; } + bool useParentBackfaceVisibility() const { return m_useParentBackfaceVisibility; } + + void setUseLCDText(bool useLCDText) { m_useLCDText = useLCDText; } + bool useLCDText() const { return m_useLCDText; } + + void setSublayerTransform(const WebKit::WebTransformationMatrix&); + const WebKit::WebTransformationMatrix& sublayerTransform() const { return m_sublayerTransform; } + + // Debug layer border - visual effect only, do not change geometry/clipping/etc. + void setDebugBorderColor(SkColor); + SkColor debugBorderColor() const { return m_debugBorderColor; } + void setDebugBorderWidth(float); + float debugBorderWidth() const { return m_debugBorderWidth; } + bool hasDebugBorders() const; + + // Debug layer name. + void setDebugName(const std::string& debugName) { m_debugName = debugName; } + std::string debugName() const { return m_debugName; } + + CCRenderSurface* renderSurface() const { return m_renderSurface.get(); } + void createRenderSurface(); + void clearRenderSurface() { m_renderSurface.clear(); } + + float drawOpacity() const { return m_drawOpacity; } + void setDrawOpacity(float opacity) { m_drawOpacity = opacity; } + + bool drawOpacityIsAnimating() const { return m_drawOpacityIsAnimating; } + void setDrawOpacityIsAnimating(bool drawOpacityIsAnimating) { m_drawOpacityIsAnimating = drawOpacityIsAnimating; } + + CCLayerImpl* renderTarget() const { ASSERT(!m_renderTarget || m_renderTarget->renderSurface()); return m_renderTarget; } + void setRenderTarget(CCLayerImpl* target) { m_renderTarget = target; } + + void setBounds(const IntSize&); + const IntSize& bounds() const { return m_bounds; } + + const IntSize& contentBounds() const { return m_contentBounds; } + void setContentBounds(const IntSize&); + + const IntPoint& scrollPosition() const { return m_scrollPosition; } + void setScrollPosition(const IntPoint&); + + const IntSize& maxScrollPosition() const {return m_maxScrollPosition; } + void setMaxScrollPosition(const IntSize&); + + const FloatSize& scrollDelta() const { return m_scrollDelta; } + void setScrollDelta(const FloatSize&); + + const WebKit::WebTransformationMatrix& implTransform() const { return m_implTransform; } + void setImplTransform(const WebKit::WebTransformationMatrix& transform); + + const IntSize& sentScrollDelta() const { return m_sentScrollDelta; } + void setSentScrollDelta(const IntSize& sentScrollDelta) { m_sentScrollDelta = sentScrollDelta; } + + // Returns the delta of the scroll that was outside of the bounds of the initial scroll + FloatSize scrollBy(const FloatSize& scroll); + + bool scrollable() const { return m_scrollable; } + void setScrollable(bool scrollable) { m_scrollable = scrollable; } + + bool shouldScrollOnMainThread() const { return m_shouldScrollOnMainThread; } + void setShouldScrollOnMainThread(bool shouldScrollOnMainThread) { m_shouldScrollOnMainThread = shouldScrollOnMainThread; } + + bool haveWheelEventHandlers() const { return m_haveWheelEventHandlers; } + void setHaveWheelEventHandlers(bool haveWheelEventHandlers) { m_haveWheelEventHandlers = haveWheelEventHandlers; } + + const Region& nonFastScrollableRegion() const { return m_nonFastScrollableRegion; } + void setNonFastScrollableRegion(const Region& region) { m_nonFastScrollableRegion = region; } + + void setDrawCheckerboardForMissingTiles(bool checkerboard) { m_drawCheckerboardForMissingTiles = checkerboard; } + bool drawCheckerboardForMissingTiles() const; + + CCInputHandlerClient::ScrollStatus tryScroll(const IntPoint& viewportPoint, CCInputHandlerClient::ScrollInputType) const; + + const IntRect& visibleContentRect() const { return m_visibleContentRect; } + void setVisibleContentRect(const IntRect& visibleContentRect) { m_visibleContentRect = visibleContentRect; } + + bool doubleSided() const { return m_doubleSided; } + void setDoubleSided(bool); + + void setTransform(const WebKit::WebTransformationMatrix&); + bool transformIsAnimating() const; + + const WebKit::WebTransformationMatrix& drawTransform() const { return m_drawTransform; } + void setDrawTransform(const WebKit::WebTransformationMatrix& matrix) { m_drawTransform = matrix; } + const WebKit::WebTransformationMatrix& screenSpaceTransform() const { return m_screenSpaceTransform; } + void setScreenSpaceTransform(const WebKit::WebTransformationMatrix& matrix) { m_screenSpaceTransform = matrix; } + + bool drawTransformIsAnimating() const { return m_drawTransformIsAnimating; } + void setDrawTransformIsAnimating(bool animating) { m_drawTransformIsAnimating = animating; } + bool screenSpaceTransformIsAnimating() const { return m_screenSpaceTransformIsAnimating; } + void setScreenSpaceTransformIsAnimating(bool animating) { m_screenSpaceTransformIsAnimating = animating; } + + const IntRect& drawableContentRect() const { return m_drawableContentRect; } + void setDrawableContentRect(const IntRect& rect) { m_drawableContentRect = rect; } + const FloatRect& updateRect() const { return m_updateRect; } + void setUpdateRect(const FloatRect& updateRect) { m_updateRect = updateRect; } + + std::string layerTreeAsText() const; + + void setStackingOrderChanged(bool); + + bool layerPropertyChanged() const { return m_layerPropertyChanged || layerIsAlwaysDamaged(); } + bool layerSurfacePropertyChanged() const; + + void resetAllChangeTrackingForSubtree(); + + virtual bool layerIsAlwaysDamaged() const; + + CCLayerAnimationController* layerAnimationController() { return m_layerAnimationController.get(); } + + virtual Region visibleContentOpaqueRegion() const; + + // Indicates that the context previously used to render this layer + // was lost and that a new one has been created. Won't be called + // until the new context has been created successfully. + virtual void didLoseContext(); + + CCScrollbarAnimationController* scrollbarAnimationController() const { return m_scrollbarAnimationController.get(); } + + CCScrollbarLayerImpl* horizontalScrollbarLayer() const; + void setHorizontalScrollbarLayer(CCScrollbarLayerImpl*); + + CCScrollbarLayerImpl* verticalScrollbarLayer() const; + void setVerticalScrollbarLayer(CCScrollbarLayerImpl*); + +protected: + explicit CCLayerImpl(int); + + void appendDebugBorderQuad(CCQuadSink&, const CCSharedQuadState*, CCAppendQuadsData&) const; + + IntRect layerRectToContentRect(const WebKit::WebRect& layerRect); + + virtual void dumpLayerProperties(std::string*, int indent) const; + static std::string indentString(int indent); + +private: + void setParent(CCLayerImpl* parent) { m_parent = parent; } + friend class TreeSynchronizer; + void clearChildList(); // Warning: This does not preserve tree structure invariants and so is only exposed to the tree synchronizer. + + void noteLayerPropertyChangedForSubtree(); + + // Note carefully this does not affect the current layer. + void noteLayerPropertyChangedForDescendants(); + + virtual const char* layerTypeAsString() const; + + void dumpLayer(std::string*, int indent) const; + + // Properties internal to CCLayerImpl + CCLayerImpl* m_parent; + ScopedPtrVector m_children; + // m_maskLayer can be temporarily stolen during tree sync, we need this ID to confirm newly assigned layer is still the previous one + int m_maskLayerId; + scoped_ptr m_maskLayer; + int m_replicaLayerId; // ditto + scoped_ptr m_replicaLayer; + int m_layerId; + CCLayerTreeHostImpl* m_layerTreeHostImpl; + + // Properties synchronized from the associated LayerChromium. + FloatPoint m_anchorPoint; + float m_anchorPointZ; + IntSize m_bounds; + IntSize m_contentBounds; + IntPoint m_scrollPosition; + bool m_scrollable; + bool m_shouldScrollOnMainThread; + bool m_haveWheelEventHandlers; + Region m_nonFastScrollableRegion; + SkColor m_backgroundColor; + + // Whether the "back" of this layer should draw. + bool m_doubleSided; + + // Tracks if drawing-related properties have changed since last redraw. + bool m_layerPropertyChanged; + + // Indicates that a property has changed on this layer that would not + // affect the pixels on its target surface, but would require redrawing + // but would require redrawing the targetSurface onto its ancestor targetSurface. + // For layers that do not own a surface this flag acts as m_layerPropertyChanged. + bool m_layerSurfacePropertyChanged; + + // Uses layer's content space. + IntRect m_visibleContentRect; + bool m_masksToBounds; + bool m_contentsOpaque; + float m_opacity; + FloatPoint m_position; + bool m_preserves3D; + bool m_useParentBackfaceVisibility; + bool m_drawCheckerboardForMissingTiles; + WebKit::WebTransformationMatrix m_sublayerTransform; + WebKit::WebTransformationMatrix m_transform; + bool m_useLCDText; + + bool m_drawsContent; + bool m_forceRenderSurface; + + // Set for the layer that other layers are fixed to. + bool m_isContainerForFixedPositionLayers; + // This is true if the layer should be fixed to the closest ancestor container. + bool m_fixedToContainerLayer; + + FloatSize m_scrollDelta; + IntSize m_sentScrollDelta; + IntSize m_maxScrollPosition; + WebKit::WebTransformationMatrix m_implTransform; + + // The layer whose coordinate space this layer draws into. This can be + // either the same layer (m_renderTarget == this) or an ancestor of this + // layer. + CCLayerImpl* m_renderTarget; + + // The global depth value of the center of the layer. This value is used + // to sort layers from back to front. + float m_drawDepth; + float m_drawOpacity; + bool m_drawOpacityIsAnimating; + + // Debug borders. + SkColor m_debugBorderColor; + float m_debugBorderWidth; + + // Debug layer name. + std::string m_debugName; + + WebKit::WebFilterOperations m_filters; + WebKit::WebFilterOperations m_backgroundFilters; + + WebKit::WebTransformationMatrix m_drawTransform; + WebKit::WebTransformationMatrix m_screenSpaceTransform; + bool m_drawTransformIsAnimating; + bool m_screenSpaceTransformIsAnimating; + +#ifndef NDEBUG + bool m_betweenWillDrawAndDidDraw; +#endif + + // Render surface associated with this layer. The layer and its descendants + // will render to this surface. + OwnPtr m_renderSurface; + + // Hierarchical bounding rect containing the layer and its descendants. + // Uses target surface's space. + IntRect m_drawableContentRect; + + // Rect indicating what was repainted/updated during update. + // Note that plugin layers bypass this and leave it empty. + // Uses layer's content space. + FloatRect m_updateRect; + + // Manages animations for this layer. + scoped_ptr m_layerAnimationController; + + // Manages scrollbars for this layer + OwnPtr m_scrollbarAnimationController; +}; + +void sortLayers(std::vector::iterator first, std::vector::iterator end, CCLayerSorter*); + +} + +#endif // CCLayerImpl_h diff --git a/cc/layer_iterator.cc b/cc/layer_iterator.cc new file mode 100644 index 0000000..71fde80 --- /dev/null +++ b/cc/layer_iterator.cc @@ -0,0 +1,153 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#if USE(ACCELERATED_COMPOSITING) + +#include "CCLayerIterator.h" + +#include "CCLayerImpl.h" +#include "CCRenderSurface.h" +#include "LayerChromium.h" +#include "RenderSurfaceChromium.h" + +namespace cc { + +template +void CCLayerIteratorActions::BackToFront::begin(CCLayerIterator& it) +{ + it.m_targetRenderSurfaceLayerIndex = 0; + it.m_currentLayerIndex = CCLayerIteratorValue::LayerIndexRepresentingTargetRenderSurface; + + m_highestTargetRenderSurfaceLayer = 0; +} + +template +void CCLayerIteratorActions::BackToFront::end(CCLayerIterator& it) +{ + it.m_targetRenderSurfaceLayerIndex = CCLayerIteratorValue::InvalidTargetRenderSurfaceLayerIndex; + it.m_currentLayerIndex = 0; +} + +template +void CCLayerIteratorActions::BackToFront::next(CCLayerIterator& it) +{ + // If the current layer has a RS, move to its layer list. Otherwise, visit the next layer in the current RS layer list. + if (it.currentLayerRepresentsContributingRenderSurface()) { + // Save our position in the childLayer list for the RenderSurface, then jump to the next RenderSurface. Save where we + // came from in the next RenderSurface so we can get back to it. + it.targetRenderSurface()->m_currentLayerIndexHistory = it.m_currentLayerIndex; + int previousTargetRenderSurfaceLayer = it.m_targetRenderSurfaceLayerIndex; + + it.m_targetRenderSurfaceLayerIndex = ++m_highestTargetRenderSurfaceLayer; + it.m_currentLayerIndex = CCLayerIteratorValue::LayerIndexRepresentingTargetRenderSurface; + + it.targetRenderSurface()->m_targetRenderSurfaceLayerIndexHistory = previousTargetRenderSurfaceLayer; + } else { + ++it.m_currentLayerIndex; + + int targetRenderSurfaceNumChildren = it.targetRenderSurfaceChildren().size(); + while (it.m_currentLayerIndex == targetRenderSurfaceNumChildren) { + // Jump back to the previous RenderSurface, and get back the position where we were in that list, and move to the next position there. + if (!it.m_targetRenderSurfaceLayerIndex) { + // End of the list + it.m_targetRenderSurfaceLayerIndex = CCLayerIteratorValue::InvalidTargetRenderSurfaceLayerIndex; + it.m_currentLayerIndex = 0; + return; + } + it.m_targetRenderSurfaceLayerIndex = it.targetRenderSurface()->m_targetRenderSurfaceLayerIndexHistory; + it.m_currentLayerIndex = it.targetRenderSurface()->m_currentLayerIndexHistory + 1; + + targetRenderSurfaceNumChildren = it.targetRenderSurfaceChildren().size(); + } + } +} + +template +void CCLayerIteratorActions::FrontToBack::begin(CCLayerIterator& it) +{ + it.m_targetRenderSurfaceLayerIndex = 0; + it.m_currentLayerIndex = it.targetRenderSurfaceChildren().size() - 1; + goToHighestInSubtree(it); +} + +template +void CCLayerIteratorActions::FrontToBack::end(CCLayerIterator& it) +{ + it.m_targetRenderSurfaceLayerIndex = CCLayerIteratorValue::InvalidTargetRenderSurfaceLayerIndex; + it.m_currentLayerIndex = 0; +} + +template +void CCLayerIteratorActions::FrontToBack::next(CCLayerIterator& it) +{ + // Moves to the previous layer in the current RS layer list. Then we check if the + // new current layer has its own RS, in which case there are things in that RS layer list that are higher, so + // we find the highest layer in that subtree. + // If we move back past the front of the list, we jump up to the previous RS layer list, picking up again where we + // had previously recursed into the current RS layer list. + + if (!it.currentLayerRepresentsTargetRenderSurface()) { + // Subtracting one here will eventually cause the current layer to become that layer + // representing the target render surface. + --it.m_currentLayerIndex; + goToHighestInSubtree(it); + } else { + while (it.currentLayerRepresentsTargetRenderSurface()) { + if (!it.m_targetRenderSurfaceLayerIndex) { + // End of the list + it.m_targetRenderSurfaceLayerIndex = CCLayerIteratorValue::InvalidTargetRenderSurfaceLayerIndex; + it.m_currentLayerIndex = 0; + return; + } + it.m_targetRenderSurfaceLayerIndex = it.targetRenderSurface()->m_targetRenderSurfaceLayerIndexHistory; + it.m_currentLayerIndex = it.targetRenderSurface()->m_currentLayerIndexHistory; + } + } +} + +template +void CCLayerIteratorActions::FrontToBack::goToHighestInSubtree(CCLayerIterator& it) +{ + if (it.currentLayerRepresentsTargetRenderSurface()) + return; + while (it.currentLayerRepresentsContributingRenderSurface()) { + // Save where we were in the current target surface, move to the next one, and save the target surface that we + // came from there so we can go back to it. + it.targetRenderSurface()->m_currentLayerIndexHistory = it.m_currentLayerIndex; + int previousTargetRenderSurfaceLayer = it.m_targetRenderSurfaceLayerIndex; + + for (LayerType* layer = it.currentLayer(); it.targetRenderSurfaceLayer() != layer; ++it.m_targetRenderSurfaceLayerIndex) { } + it.m_currentLayerIndex = it.targetRenderSurfaceChildren().size() - 1; + + it.targetRenderSurface()->m_targetRenderSurfaceLayerIndexHistory = previousTargetRenderSurfaceLayer; + } +} + +typedef std::vector > LayerChromiumList; +typedef std::vector CCLayerImplList; + +// Declare each of the above functions for LayerChromium and CCLayerImpl classes so that they are linked. +template void CCLayerIteratorActions::BackToFront::begin(CCLayerIterator &); +template void CCLayerIteratorActions::BackToFront::end(CCLayerIterator&); +template void CCLayerIteratorActions::BackToFront::next(CCLayerIterator&); + +template void CCLayerIteratorActions::BackToFront::begin(CCLayerIterator&); +template void CCLayerIteratorActions::BackToFront::end(CCLayerIterator&); +template void CCLayerIteratorActions::BackToFront::next(CCLayerIterator&); + +template void CCLayerIteratorActions::FrontToBack::next(CCLayerIterator&); +template void CCLayerIteratorActions::FrontToBack::end(CCLayerIterator&); +template void CCLayerIteratorActions::FrontToBack::begin(CCLayerIterator&); +template void CCLayerIteratorActions::FrontToBack::goToHighestInSubtree(CCLayerIterator&); + +template void CCLayerIteratorActions::FrontToBack::next(CCLayerIterator&); +template void CCLayerIteratorActions::FrontToBack::end(CCLayerIterator&); +template void CCLayerIteratorActions::FrontToBack::begin(CCLayerIterator&); +template void CCLayerIteratorActions::FrontToBack::goToHighestInSubtree(CCLayerIterator&); + +} // namespace cc + +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/cc/layer_iterator.h b/cc/layer_iterator.h index 638cbb2..4d36080 100644 --- a/cc/layer_iterator.h +++ b/cc/layer_iterator.h @@ -1,3 +1,208 @@ // Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CCLayerIterator_h +#define CCLayerIterator_h + +#include "CCLayerTreeHostCommon.h" + +#include "base/memory/ref_counted.h" + +namespace cc { + +// These classes provide means to iterate over the RenderSurface-Layer tree. + +// Example code follows, for a tree of LayerChromium/RenderSurfaceChromium objects. See below for details. +// +// void doStuffOnLayers(const std::vector >& renderSurfaceLayerList) +// { +// typedef CCLayerIterator CCLayerIteratorType; +// +// CCLayerIteratorType end = CCLayerIteratorType::end(&renderSurfaceLayerList); +// for (CCLayerIteratorType it = CCLayerIteratorType::begin(&renderSurfaceLayerList); it != end; ++it) { +// // Only one of these will be true +// if (it.representsTargetRenderSurface()) +// foo(*it); // *it is a layer representing a target RenderSurface +// if (it.representsContributingRenderSurface()) +// bar(*it); // *it is a layer representing a RenderSurface that contributes to the layer's target RenderSurface +// if (it.representsItself()) +// baz(*it); // *it is a layer representing itself, as it contributes to its own target RenderSurface +// } +// } + +// A RenderSurface R may be referred to in one of two different contexts. One RenderSurface is "current" at any time, for +// whatever operation is being performed. This current surface is referred to as a target surface. For example, when R is +// being painted it would be the target surface. Once R has been painted, its contents may be included into another +// surface S. While S is considered the target surface when it is being painted, R is called a contributing surface +// in this context as it contributes to the content of the target surface S. +// +// The iterator's current position in the tree always points to some layer. The state of the iterator indicates the role of the +// layer, and will be one of the following three states. A single layer L will appear in the iteration process in at least one, +// and possibly all, of these states. +// 1. Representing the target surface: The iterator in this state, pointing at layer L, indicates that the target RenderSurface +// is now the surface owned by L. This will occur exactly once for each RenderSurface in the tree. +// 2. Representing a contributing surface: The iterator in this state, pointing at layer L, refers to the RenderSurface owned +// by L as a contributing surface, without changing the current target RenderSurface. +// 3. Representing itself: The iterator in this state, pointing at layer L, refers to the layer itself, as a child of the +// current target RenderSurface. +// +// The BackToFront iterator will return a layer representing the target surface before returning layers representing themselves +// as children of the current target surface. Whereas the FrontToBack ordering will iterate over children layers of a surface +// before the layer representing the surface as a target surface. +// +// To use the iterators: +// +// Create a stepping iterator and end iterator by calling CCLayerIterator::begin() and CCLayerIterator::end() and passing in the +// list of layers owning target RenderSurfaces. Step through the tree by incrementing the stepping iterator while it is != to +// the end iterator. At each step the iterator knows what the layer is representing, and you can query the iterator to decide +// what actions to perform with the layer given what it represents. + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +// Non-templated constants +struct CCLayerIteratorValue { + static const int InvalidTargetRenderSurfaceLayerIndex = -1; + // This must be -1 since the iterator action code assumes that this value can be + // reached by subtracting one from the position of the first layer in the current + // target surface's child layer list, which is 0. + static const int LayerIndexRepresentingTargetRenderSurface = -1; +}; + +// The position of a layer iterator that is independent of its many template types. +template +struct CCLayerIteratorPosition { + bool representsTargetRenderSurface; + bool representsContributingRenderSurface; + bool representsItself; + LayerType* targetRenderSurfaceLayer; + LayerType* currentLayer; +}; + +// An iterator class for walking over layers in the RenderSurface-Layer tree. +template +class CCLayerIterator { + typedef CCLayerIterator CCLayerIteratorType; + +public: + CCLayerIterator() : m_renderSurfaceLayerList(0) { } + + static CCLayerIteratorType begin(const LayerList* renderSurfaceLayerList) { return CCLayerIteratorType(renderSurfaceLayerList, true); } + static CCLayerIteratorType end(const LayerList* renderSurfaceLayerList) { return CCLayerIteratorType(renderSurfaceLayerList, false); } + + CCLayerIteratorType& operator++() { m_actions.next(*this); return *this; } + bool operator==(const CCLayerIterator& other) const + { + return m_targetRenderSurfaceLayerIndex == other.m_targetRenderSurfaceLayerIndex + && m_currentLayerIndex == other.m_currentLayerIndex; + } + bool operator!=(const CCLayerIteratorType& other) const { return !(*this == other); } + + LayerType* operator->() const { return currentLayer(); } + LayerType* operator*() const { return currentLayer(); } + + bool representsTargetRenderSurface() const { return currentLayerRepresentsTargetRenderSurface(); } + bool representsContributingRenderSurface() const { return !representsTargetRenderSurface() && currentLayerRepresentsContributingRenderSurface(); } + bool representsItself() const { return !representsTargetRenderSurface() && !representsContributingRenderSurface(); } + + LayerType* targetRenderSurfaceLayer() const { return getRawPtr((*m_renderSurfaceLayerList)[m_targetRenderSurfaceLayerIndex]); } + + operator const CCLayerIteratorPosition() const + { + CCLayerIteratorPosition position; + position.representsTargetRenderSurface = representsTargetRenderSurface(); + position.representsContributingRenderSurface = representsContributingRenderSurface(); + position.representsItself = representsItself(); + position.targetRenderSurfaceLayer = targetRenderSurfaceLayer(); + position.currentLayer = currentLayer(); + return position; + } + +private: + CCLayerIterator(const LayerList* renderSurfaceLayerList, bool start) + : m_renderSurfaceLayerList(renderSurfaceLayerList) + , m_targetRenderSurfaceLayerIndex(0) + { + for (size_t i = 0; i < renderSurfaceLayerList->size(); ++i) { + if (!(*renderSurfaceLayerList)[i]->renderSurface()) { + ASSERT_NOT_REACHED(); + m_actions.end(*this); + return; + } + } + + if (start && !renderSurfaceLayerList->empty()) + m_actions.begin(*this); + else + m_actions.end(*this); + } + + inline static LayerChromium* getRawPtr(const scoped_refptr& ptr) { return ptr.get(); } + inline static CCLayerImpl* getRawPtr(CCLayerImpl* ptr) { return ptr; } + + inline LayerType* currentLayer() const { return currentLayerRepresentsTargetRenderSurface() ? targetRenderSurfaceLayer() : getRawPtr(targetRenderSurfaceChildren()[m_currentLayerIndex]); } + + inline bool currentLayerRepresentsContributingRenderSurface() const { return CCLayerTreeHostCommon::renderSurfaceContributesToTarget(currentLayer(), targetRenderSurfaceLayer()->id()); } + inline bool currentLayerRepresentsTargetRenderSurface() const { return m_currentLayerIndex == CCLayerIteratorValue::LayerIndexRepresentingTargetRenderSurface; } + + inline RenderSurfaceType* targetRenderSurface() const { return targetRenderSurfaceLayer()->renderSurface(); } + inline const LayerList& targetRenderSurfaceChildren() const { return targetRenderSurface()->layerList(); } + + IteratorActionType m_actions; + const LayerList* m_renderSurfaceLayerList; + + // The iterator's current position. + + // A position in the renderSurfaceLayerList. This points to a layer which owns the current target surface. + // This is a value from 0 to n-1 (n = size of renderSurfaceLayerList = number of surfaces). A value outside of + // this range (for example, CCLayerIteratorValue::InvalidTargetRenderSurfaceLayerIndex) is used to + // indicate a position outside the bounds of the tree. + int m_targetRenderSurfaceLayerIndex; + // A position in the list of layers that are children of the current target surface. When pointing to one of + // these layers, this is a value from 0 to n-1 (n = number of children). Since the iterator must also stop at + // the layers representing the target surface, this is done by setting the currentLayerIndex to a value of + // CCLayerIteratorValue::LayerRepresentingTargetRenderSurface. + int m_currentLayerIndex; + + friend struct CCLayerIteratorActions; +}; + +// Orderings for iterating over the RenderSurface-Layer tree. +struct CCLayerIteratorActions { + // Walks layers sorted by z-order from back to front. + class BackToFront { + public: + template + void begin(CCLayerIterator&); + + template + void end(CCLayerIterator&); + + template + void next(CCLayerIterator&); + + private: + int m_highestTargetRenderSurfaceLayer; + }; + + // Walks layers sorted by z-order from front to back + class FrontToBack { + public: + template + void begin(CCLayerIterator&); + + template + void end(CCLayerIterator&); + + template + void next(CCLayerIterator&); + + private: + template + void goToHighestInSubtree(CCLayerIterator&); + }; +}; + +} // namespace cc + +#endif diff --git a/cc/layer_painter.h b/cc/layer_painter.h index 638cbb2..d552382 100644 --- a/cc/layer_painter.h +++ b/cc/layer_painter.h @@ -1,3 +1,26 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. +// Copyright 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + + +#ifndef LayerPainterChromium_h +#define LayerPainterChromium_h + +#if USE(ACCELERATED_COMPOSITING) + +class SkCanvas; + +namespace cc { + +class FloatRect; +class IntRect; + +class LayerPainterChromium { +public: + virtual ~LayerPainterChromium() { } + virtual void paint(SkCanvas*, const IntRect& contentRect, FloatRect& opaque) = 0; +}; + +} // namespace cc +#endif // USE(ACCELERATED_COMPOSITING) +#endif // LayerPainterChromium_h diff --git a/cc/layer_quad.cc b/cc/layer_quad.cc new file mode 100644 index 0000000..9642622 --- /dev/null +++ b/cc/layer_quad.cc @@ -0,0 +1,74 @@ +// Copyright 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + +#include "config.h" + +#if USE(ACCELERATED_COMPOSITING) + +#include "CCLayerQuad.h" + +namespace cc { + +CCLayerQuad::Edge::Edge(const FloatPoint& p, const FloatPoint& q) +{ + ASSERT(p != q); + + FloatPoint tangent(p.y() - q.y(), q.x() - p.x()); + float cross2 = p.x() * q.y() - q.x() * p.y(); + + set(tangent.x(), tangent.y(), cross2); + scale(1.0f / tangent.length()); +} + +CCLayerQuad::CCLayerQuad(const FloatQuad& quad) +{ + // Create edges. + m_left = Edge(quad.p4(), quad.p1()); + m_right = Edge(quad.p2(), quad.p3()); + m_top = Edge(quad.p1(), quad.p2()); + m_bottom = Edge(quad.p3(), quad.p4()); + + float sign = quad.isCounterclockwise() ? -1 : 1; + m_left.scale(sign); + m_right.scale(sign); + m_top.scale(sign); + m_bottom.scale(sign); +} + +CCLayerQuad::CCLayerQuad(const Edge& left, const Edge& top, const Edge& right, const Edge& bottom) + : m_left(left) + , m_top(top) + , m_right(right) + , m_bottom(bottom) +{ +} + +FloatQuad CCLayerQuad::floatQuad() const +{ + return FloatQuad(m_left.intersect(m_top), + m_top.intersect(m_right), + m_right.intersect(m_bottom), + m_bottom.intersect(m_left)); +} + +void CCLayerQuad::toFloatArray(float flattened[12]) const +{ + flattened[0] = m_left.x(); + flattened[1] = m_left.y(); + flattened[2] = m_left.z(); + flattened[3] = m_top.x(); + flattened[4] = m_top.y(); + flattened[5] = m_top.z(); + flattened[6] = m_right.x(); + flattened[7] = m_right.y(); + flattened[8] = m_right.z(); + flattened[9] = m_bottom.x(); + flattened[10] = m_bottom.y(); + flattened[11] = m_bottom.z(); +} + +} // namespace cc + +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/cc/layer_quad.h b/cc/layer_quad.h index 638cbb2..8be296f 100644 --- a/cc/layer_quad.h +++ b/cc/layer_quad.h @@ -1,3 +1,106 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. +// Copyright 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + + +#ifndef CCLayerQuad_h +#define CCLayerQuad_h + +#if USE(ACCELERATED_COMPOSITING) + +#include "FloatPoint3D.h" +#include "FloatQuad.h" + +static const float kAntiAliasingInflateDistance = 0.5f; + +namespace cc { + +class CCLayerQuad { +public: + class Edge { + public: + Edge() + : m_x(0) + , m_y(0) + , m_z(0) + { + } + Edge(const FloatPoint&, const FloatPoint&); + + float x() const { return m_x; } + float y() const { return m_y; } + float z() const { return m_z; } + + void setX(float x) { m_x = x; } + void setY(float y) { m_y = y; } + void setZ(float z) { m_z = z; } + void set(float x, float y, float z) + { + m_x = x; + m_y = y; + m_z = z; + } + + void moveX(float dx) { m_x += dx; } + void moveY(float dy) { m_y += dy; } + void moveZ(float dz) { m_z += dz; } + void move(float dx, float dy, float dz) + { + m_x += dx; + m_y += dy; + m_z += dz; + } + + void scaleX(float sx) { m_x *= sx; } + void scaleY(float sy) { m_y *= sy; } + void scaleZ(float sz) { m_z *= sz; } + void scale(float sx, float sy, float sz) + { + m_x *= sx; + m_y *= sy; + m_z *= sz; + } + void scale(float s) { scale(s, s, s); } + + FloatPoint intersect(const Edge& e) const + { + return FloatPoint( + (y() * e.z() - e.y() * z()) / (x() * e.y() - e.x() * y()), + (x() * e.z() - e.x() * z()) / (e.x() * y() - x() * e.y())); + } + + private: + float m_x; + float m_y; + float m_z; + }; + + CCLayerQuad(const Edge& left, const Edge& top, const Edge& right, const Edge& bottom); + CCLayerQuad(const FloatQuad&); + + Edge left() const { return m_left; } + Edge top() const { return m_top; } + Edge right() const { return m_right; } + Edge bottom() const { return m_bottom; } + + void inflateX(float dx) { m_left.moveZ(dx); m_right.moveZ(dx); } + void inflateY(float dy) { m_top.moveZ(dy); m_bottom.moveZ(dy); } + void inflate(float d) { inflateX(d); inflateY(d); } + void inflateAntiAliasingDistance() { inflate(kAntiAliasingInflateDistance); } + + FloatQuad floatQuad() const; + + void toFloatArray(float[12]) const; + +private: + Edge m_left; + Edge m_top; + Edge m_right; + Edge m_bottom; +}; + +} + +#endif // USE(ACCELERATED_COMPOSITING) + +#endif diff --git a/cc/layer_sorter.cc b/cc/layer_sorter.cc new file mode 100644 index 0000000..cf85777 --- /dev/null +++ b/cc/layer_sorter.cc @@ -0,0 +1,445 @@ +// Copyright 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#include "CCLayerSorter.h" + +#include "CCMathUtil.h" +#include "CCRenderSurface.h" +#include +#include +#include + +using namespace std; +using WebKit::WebTransformationMatrix; + +#define LOG_CHANNEL_PREFIX Log +#define SHOW_DEBUG_LOG 0 + +#if !defined( NDEBUG ) +#if SHOW_DEBUG_LOG +static WTFLogChannel LogCCLayerSorter = { 0x00000000, "", WTFLogChannelOn }; +#else +static WTFLogChannel LogCCLayerSorter = { 0x00000000, "", WTFLogChannelOff }; +#endif +#endif + +namespace cc { + +inline static float perpProduct(const FloatSize& u, const FloatSize& v) +{ + return u.width() * v.height() - u.height() * v.width(); +} + +// Tests if two edges defined by their endpoints (a,b) and (c,d) intersect. Returns true and the +// point of intersection if they do and false otherwise. +static bool edgeEdgeTest(const FloatPoint& a, const FloatPoint& b, const FloatPoint& c, const FloatPoint& d, FloatPoint& r) +{ + FloatSize u = b - a; + FloatSize v = d - c; + FloatSize w = a - c; + + float denom = perpProduct(u, v); + + // If denom == 0 then the edges are parallel. While they could be overlapping + // we don't bother to check here as the we'll find their intersections from the + // corner to quad tests. + if (!denom) + return false; + + float s = perpProduct(v, w) / denom; + if (s < 0 || s > 1) + return false; + + float t = perpProduct(u, w) / denom; + if (t < 0 || t > 1) + return false; + + u.scale(s); + r = a + u; + return true; +} + +CCLayerSorter::GraphNode::GraphNode(CCLayerImpl* cclayer) + : layer(cclayer) + , incomingEdgeWeight(0) +{ +} + +CCLayerSorter::GraphNode::~GraphNode() +{ +} + +CCLayerSorter::CCLayerSorter() + : m_zRange(0) +{ +} + +CCLayerSorter::~CCLayerSorter() +{ +} + +// Checks whether layer "a" draws on top of layer "b". The weight value returned is an indication of +// the maximum z-depth difference between the layers or zero if the layers are found to be intesecting +// (some features are in front and some are behind). +CCLayerSorter::ABCompareResult CCLayerSorter::checkOverlap(LayerShape* a, LayerShape* b, float zThreshold, float& weight) +{ + weight = 0; + + // Early out if the projected bounds don't overlap. + if (!a->projectedBounds.intersects(b->projectedBounds)) + return None; + + FloatPoint aPoints[4] = {a->projectedQuad.p1(), a->projectedQuad.p2(), a->projectedQuad.p3(), a->projectedQuad.p4() }; + FloatPoint bPoints[4] = {b->projectedQuad.p1(), b->projectedQuad.p2(), b->projectedQuad.p3(), b->projectedQuad.p4() }; + + // Make a list of points that inside both layer quad projections. + Vector overlapPoints; + + // Check all four corners of one layer against the other layer's quad. + for (int i = 0; i < 4; ++i) { + if (a->projectedQuad.containsPoint(bPoints[i])) + overlapPoints.append(bPoints[i]); + if (b->projectedQuad.containsPoint(aPoints[i])) + overlapPoints.append(aPoints[i]); + } + + // Check all the edges of one layer for intersection with the other layer's edges. + FloatPoint r; + for (int ea = 0; ea < 4; ++ea) + for (int eb = 0; eb < 4; ++eb) + if (edgeEdgeTest(aPoints[ea], aPoints[(ea + 1) % 4], + bPoints[eb], bPoints[(eb + 1) % 4], + r)) + overlapPoints.append(r); + + if (!overlapPoints.size()) + return None; + + // Check the corresponding layer depth value for all overlap points to determine + // which layer is in front. + float maxPositive = 0; + float maxNegative = 0; + for (unsigned o = 0; o < overlapPoints.size(); o++) { + float za = a->layerZFromProjectedPoint(overlapPoints[o]); + float zb = b->layerZFromProjectedPoint(overlapPoints[o]); + + float diff = za - zb; + if (diff > maxPositive) + maxPositive = diff; + if (diff < maxNegative) + maxNegative = diff; + } + + float maxDiff = (fabsf(maxPositive) > fabsf(maxNegative) ? maxPositive : maxNegative); + + // If the results are inconsistent (and the z difference substantial to rule out + // numerical errors) then the layers are intersecting. We will still return an + // order based on the maximum depth difference but with an edge weight of zero + // these layers will get priority if a graph cycle is present and needs to be broken. + if (maxPositive > zThreshold && maxNegative < -zThreshold) + weight = 0; + else + weight = fabsf(maxDiff); + + // Maintain relative order if the layers have the same depth at all intersection points. + if (maxDiff <= 0) + return ABeforeB; + + return BBeforeA; +} + +CCLayerSorter::LayerShape::LayerShape() +{ +} + +CCLayerSorter::LayerShape::LayerShape(float width, float height, const WebTransformationMatrix& drawTransform) +{ + FloatQuad layerQuad(FloatRect(0, 0, width, height)); + + // Compute the projection of the layer quad onto the z = 0 plane. + + FloatPoint clippedQuad[8]; + int numVerticesInClippedQuad; + CCMathUtil::mapClippedQuad(drawTransform, layerQuad, clippedQuad, numVerticesInClippedQuad); + + if (numVerticesInClippedQuad < 3) { + projectedBounds = FloatRect(); + return; + } + + projectedBounds = CCMathUtil::computeEnclosingRectOfVertices(clippedQuad, numVerticesInClippedQuad); + + // NOTE: it will require very significant refactoring and overhead to deal with + // generalized polygons or multiple quads per layer here. For the sake of layer + // sorting it is equally correct to take a subsection of the polygon that can be made + // into a quad. This will only be incorrect in the case of intersecting layers, which + // are not supported yet anyway. + projectedQuad.setP1(clippedQuad[0]); + projectedQuad.setP2(clippedQuad[1]); + projectedQuad.setP3(clippedQuad[2]); + if (numVerticesInClippedQuad >= 4) + projectedQuad.setP4(clippedQuad[3]); + else + projectedQuad.setP4(clippedQuad[2]); // this will be a degenerate quad that is actually a triangle. + + // Compute the normal of the layer's plane. + bool clipped = false; + FloatPoint3D c1 = CCMathUtil::mapPoint(drawTransform, FloatPoint3D(0, 0, 0), clipped); + FloatPoint3D c2 = CCMathUtil::mapPoint(drawTransform, FloatPoint3D(0, 1, 0), clipped); + FloatPoint3D c3 = CCMathUtil::mapPoint(drawTransform, FloatPoint3D(1, 0, 0), clipped); + // FIXME: Deal with clipping. + FloatPoint3D c12 = c2 - c1; + FloatPoint3D c13 = c3 - c1; + layerNormal = c13.cross(c12); + + transformOrigin = c1; +} + +// Returns the Z coordinate of a point on the layer that projects +// to point p which lies on the z = 0 plane. It does it by computing the +// intersection of a line starting from p along the Z axis and the plane +// of the layer. +float CCLayerSorter::LayerShape::layerZFromProjectedPoint(const FloatPoint& p) const +{ + const FloatPoint3D zAxis(0, 0, 1); + FloatPoint3D w = FloatPoint3D(p) - transformOrigin; + + float d = layerNormal.dot(zAxis); + float n = -layerNormal.dot(w); + + // Check if layer is parallel to the z = 0 axis which will make it + // invisible and hence returning zero is fine. + if (!d) + return 0; + + // The intersection point would be given by: + // p + (n / d) * u but since we are only interested in the + // z coordinate and p's z coord is zero, all we need is the value of n/d. + return n / d; +} + +void CCLayerSorter::createGraphNodes(LayerList::iterator first, LayerList::iterator last) +{ +#if !defined( NDEBUG ) + LOG(CCLayerSorter, "Creating graph nodes:\n"); +#endif + float minZ = FLT_MAX; + float maxZ = -FLT_MAX; + for (LayerList::const_iterator it = first; it < last; it++) { + m_nodes.append(GraphNode(*it)); + GraphNode& node = m_nodes.at(m_nodes.size() - 1); + CCRenderSurface* renderSurface = node.layer->renderSurface(); + if (!node.layer->drawsContent() && !renderSurface) + continue; + +#if !defined( NDEBUG ) + LOG(CCLayerSorter, "Layer %d (%d x %d)\n", node.layer->id(), node.layer->bounds().width(), node.layer->bounds().height()); +#endif + + WebTransformationMatrix drawTransform; + float layerWidth, layerHeight; + if (renderSurface) { + drawTransform = renderSurface->drawTransform(); + layerWidth = renderSurface->contentRect().width(); + layerHeight = renderSurface->contentRect().height(); + } else { + drawTransform = node.layer->drawTransform(); + layerWidth = node.layer->contentBounds().width(); + layerHeight = node.layer->contentBounds().height(); + } + + node.shape = LayerShape(layerWidth, layerHeight, drawTransform); + + maxZ = max(maxZ, node.shape.transformOrigin.z()); + minZ = min(minZ, node.shape.transformOrigin.z()); + } + + m_zRange = fabsf(maxZ - minZ); +} + +void CCLayerSorter::createGraphEdges() +{ +#if !defined( NDEBUG ) + LOG(CCLayerSorter, "Edges:\n"); +#endif + // Fraction of the total zRange below which z differences + // are not considered reliable. + const float zThresholdFactor = 0.01f; + float zThreshold = m_zRange * zThresholdFactor; + + for (unsigned na = 0; na < m_nodes.size(); na++) { + GraphNode& nodeA = m_nodes[na]; + if (!nodeA.layer->drawsContent() && !nodeA.layer->renderSurface()) + continue; + for (unsigned nb = na + 1; nb < m_nodes.size(); nb++) { + GraphNode& nodeB = m_nodes[nb]; + if (!nodeB.layer->drawsContent() && !nodeB.layer->renderSurface()) + continue; + float weight = 0; + ABCompareResult overlapResult = checkOverlap(&nodeA.shape, &nodeB.shape, zThreshold, weight); + GraphNode* startNode = 0; + GraphNode* endNode = 0; + if (overlapResult == ABeforeB) { + startNode = &nodeA; + endNode = &nodeB; + } else if (overlapResult == BBeforeA) { + startNode = &nodeB; + endNode = &nodeA; + } + + if (startNode) { +#if !defined( NDEBUG ) + LOG(CCLayerSorter, "%d -> %d\n", startNode->layer->id(), endNode->layer->id()); +#endif + m_edges.append(GraphEdge(startNode, endNode, weight)); + } + } + } + + for (unsigned i = 0; i < m_edges.size(); i++) { + GraphEdge& edge = m_edges[i]; + m_activeEdges.add(&edge, &edge); + edge.from->outgoing.append(&edge); + edge.to->incoming.append(&edge); + edge.to->incomingEdgeWeight += edge.weight; + } +} + +// Finds and removes an edge from the list by doing a swap with the +// last element of the list. +void CCLayerSorter::removeEdgeFromList(GraphEdge* edge, Vector& list) +{ + size_t edgeIndex = list.find(edge); + ASSERT(edgeIndex != notFound); + if (list.size() == 1) { + ASSERT(!edgeIndex); + list.clear(); + return; + } + if (edgeIndex != list.size() - 1) + list[edgeIndex] = list[list.size() - 1]; + + list.removeLast(); +} + +// Sorts the given list of layers such that they can be painted in a back-to-front +// order. Sorting produces correct results for non-intersecting layers that don't have +// cyclical order dependencies. Cycles and intersections are broken (somewhat) aribtrarily. +// Sorting of layers is done via a topological sort of a directed graph whose nodes are +// the layers themselves. An edge from node A to node B signifies that layer A needs to +// be drawn before layer B. If A and B have no dependency between each other, then we +// preserve the ordering of those layers as they were in the original list. +// +// The draw order between two layers is determined by projecting the two triangles making +// up each layer quad to the Z = 0 plane, finding points of intersection between the triangles +// and backprojecting those points to the plane of the layer to determine the corresponding Z +// coordinate. The layer with the lower Z coordinate (farther from the eye) needs to be rendered +// first. +// +// If the layer projections don't intersect, then no edges (dependencies) are created +// between them in the graph. HOWEVER, in this case we still need to preserve the ordering +// of the original list of layers, since that list should already have proper z-index +// ordering of layers. +// +void CCLayerSorter::sort(LayerList::iterator first, LayerList::iterator last) +{ +#if !defined( NDEBUG ) + LOG(CCLayerSorter, "Sorting start ----\n"); +#endif + createGraphNodes(first, last); + + createGraphEdges(); + + Vector sortedList; + Deque noIncomingEdgeNodeList; + + // Find all the nodes that don't have incoming edges. + for (NodeList::iterator la = m_nodes.begin(); la < m_nodes.end(); la++) { + if (!la->incoming.size()) + noIncomingEdgeNodeList.append(la); + } + +#if !defined( NDEBUG ) + LOG(CCLayerSorter, "Sorted list: "); +#endif + while (m_activeEdges.size() || noIncomingEdgeNodeList.size()) { + while (noIncomingEdgeNodeList.size()) { + + // It is necessary to preserve the existing ordering of layers, when there are + // no explicit dependencies (because this existing ordering has correct + // z-index/layout ordering). To preserve this ordering, we process Nodes in + // the same order that they were added to the list. + GraphNode* fromNode = noIncomingEdgeNodeList.takeFirst(); + + // Add it to the final list. + sortedList.append(fromNode); + +#if !defined( NDEBUG ) + LOG(CCLayerSorter, "%d, ", fromNode->layer->id()); +#endif + + // Remove all its outgoing edges from the graph. + for (unsigned i = 0; i < fromNode->outgoing.size(); i++) { + GraphEdge* outgoingEdge = fromNode->outgoing[i]; + + m_activeEdges.remove(outgoingEdge); + removeEdgeFromList(outgoingEdge, outgoingEdge->to->incoming); + outgoingEdge->to->incomingEdgeWeight -= outgoingEdge->weight; + + if (!outgoingEdge->to->incoming.size()) + noIncomingEdgeNodeList.append(outgoingEdge->to); + } + fromNode->outgoing.clear(); + } + + if (!m_activeEdges.size()) + break; + + // If there are still active edges but the list of nodes without incoming edges + // is empty then we have run into a cycle. Break the cycle by finding the node + // with the smallest overall incoming edge weight and use it. This will favor + // nodes that have zero-weight incoming edges i.e. layers that are being + // occluded by a layer that intersects them. + float minIncomingEdgeWeight = FLT_MAX; + GraphNode* nextNode = 0; + for (unsigned i = 0; i < m_nodes.size(); i++) { + if (m_nodes[i].incoming.size() && m_nodes[i].incomingEdgeWeight < minIncomingEdgeWeight) { + minIncomingEdgeWeight = m_nodes[i].incomingEdgeWeight; + nextNode = &m_nodes[i]; + } + } + ASSERT(nextNode); + // Remove all its incoming edges. + for (unsigned e = 0; e < nextNode->incoming.size(); e++) { + GraphEdge* incomingEdge = nextNode->incoming[e]; + + m_activeEdges.remove(incomingEdge); + removeEdgeFromList(incomingEdge, incomingEdge->from->outgoing); + } + nextNode->incoming.clear(); + nextNode->incomingEdgeWeight = 0; + noIncomingEdgeNodeList.append(nextNode); +#if !defined( NDEBUG ) + LOG(CCLayerSorter, "Breaking cycle by cleaning up incoming edges from %d (weight = %f)\n", nextNode->layer->id(), minIncomingEdgeWeight); +#endif + } + + // Note: The original elements of the list are in no danger of having their ref count go to zero + // here as they are all nodes of the layer hierarchy and are kept alive by their parent nodes. + int count = 0; + for (LayerList::iterator it = first; it < last; it++) + *it = sortedList[count++]->layer; + +#if !defined( NDEBUG ) + LOG(CCLayerSorter, "Sorting end ----\n"); +#endif + + m_nodes.clear(); + m_edges.clear(); + m_activeEdges.clear(); +} + +} diff --git a/cc/layer_sorter.h b/cc/layer_sorter.h index 638cbb2..d4ca664 100644 --- a/cc/layer_sorter.h +++ b/cc/layer_sorter.h @@ -1,3 +1,92 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. +// Copyright 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CCLayerSorter_h +#define CCLayerSorter_h + +#include "base/basictypes.h" +#include "CCLayerImpl.h" +#include "FloatPoint3D.h" +#include "FloatQuad.h" +#include "FloatRect.h" +#include +#include +#include + +namespace WebKit { +class WebTransformationMatrix; +} + +namespace cc { + +class CCLayerSorter { +public: + CCLayerSorter(); + ~CCLayerSorter(); + + typedef std::vector LayerList; + + void sort(LayerList::iterator first, LayerList::iterator last); + + // Holds various useful properties derived from a layer's 3D outline. + struct LayerShape { + LayerShape(); + LayerShape(float width, float height, const WebKit::WebTransformationMatrix& drawTransform); + + float layerZFromProjectedPoint(const FloatPoint&) const; + + FloatPoint3D layerNormal; + FloatPoint3D transformOrigin; + FloatQuad projectedQuad; + FloatRect projectedBounds; + }; + + enum ABCompareResult { + ABeforeB, + BBeforeA, + None + }; + + static ABCompareResult checkOverlap(LayerShape*, LayerShape*, float zThreshold, float& weight); + +private: + struct GraphEdge; + + struct GraphNode { + explicit GraphNode(CCLayerImpl* cclayer); + ~GraphNode(); + + CCLayerImpl* layer; + LayerShape shape; + Vector incoming; + Vector outgoing; + float incomingEdgeWeight; + }; + + struct GraphEdge { + GraphEdge(GraphNode* fromNode, GraphNode* toNode, float weight) : from(fromNode), to(toNode), weight(weight) { }; + + GraphNode* from; + GraphNode* to; + float weight; + }; + + typedef Vector NodeList; + typedef Vector EdgeList; + NodeList m_nodes; + EdgeList m_edges; + float m_zRange; + + typedef HashMap EdgeMap; + EdgeMap m_activeEdges; + + void createGraphNodes(LayerList::iterator first, LayerList::iterator last); + void createGraphEdges(); + void removeEdgeFromList(GraphEdge*, Vector&); + + DISALLOW_COPY_AND_ASSIGN(CCLayerSorter); +}; + +} +#endif diff --git a/cc/layer_texture_sub_image.cc b/cc/layer_texture_sub_image.cc new file mode 100644 index 0000000..60f5311 --- /dev/null +++ b/cc/layer_texture_sub_image.cc @@ -0,0 +1,117 @@ +// Copyright 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#if USE(ACCELERATED_COMPOSITING) + +#include "LayerTextureSubImage.h" + +#include "CCRendererGL.h" // For the GLC() macro. +#include "GraphicsContext3D.h" +#include "Extensions3DChromium.h" +#include "TraceEvent.h" +#include + +using WebKit::WebGraphicsContext3D; + +namespace cc { + +LayerTextureSubImage::LayerTextureSubImage(bool useMapTexSubImage) + : m_useMapTexSubImage(useMapTexSubImage) + , m_subImageSize(0) +{ +} + +LayerTextureSubImage::~LayerTextureSubImage() +{ +} + +void LayerTextureSubImage::upload(const uint8_t* image, const IntRect& imageRect, + const IntRect& sourceRect, const IntSize& destOffset, + GC3Denum format, WebGraphicsContext3D* context) +{ + if (m_useMapTexSubImage) + uploadWithMapTexSubImage(image, imageRect, sourceRect, destOffset, format, context); + else + uploadWithTexSubImage(image, imageRect, sourceRect, destOffset, format, context); +} + +void LayerTextureSubImage::uploadWithTexSubImage(const uint8_t* image, const IntRect& imageRect, + const IntRect& sourceRect, const IntSize& destOffset, + GC3Denum format, WebGraphicsContext3D* context) +{ + TRACE_EVENT0("cc", "LayerTextureSubImage::uploadWithTexSubImage"); + + // Offset from image-rect to source-rect. + IntPoint offset(sourceRect.x() - imageRect.x(), sourceRect.y() - imageRect.y()); + + const uint8_t* pixelSource; + if (imageRect.width() == sourceRect.width() && !offset.x()) + pixelSource = &image[4 * offset.y() * imageRect.width()]; + else { + size_t neededSize = 4 * sourceRect.width() * sourceRect.height(); + if (m_subImageSize < neededSize) { + m_subImage = adoptArrayPtr(new uint8_t[neededSize]); + m_subImageSize = neededSize; + } + // Strides not equal, so do a row-by-row memcpy from the + // paint results into a temp buffer for uploading. + for (int row = 0; row < sourceRect.height(); ++row) + memcpy(&m_subImage[sourceRect.width() * 4 * row], + &image[4 * (offset.x() + (offset.y() + row) * imageRect.width())], + sourceRect.width() * 4); + + pixelSource = &m_subImage[0]; + } + + GLC(context, context->texSubImage2D(GraphicsContext3D::TEXTURE_2D, 0, destOffset.width(), destOffset.height(), sourceRect.width(), sourceRect.height(), format, GraphicsContext3D::UNSIGNED_BYTE, pixelSource)); +} + +void LayerTextureSubImage::uploadWithMapTexSubImage(const uint8_t* image, const IntRect& imageRect, + const IntRect& sourceRect, const IntSize& destOffset, + GC3Denum format, WebGraphicsContext3D* context) +{ + TRACE_EVENT0("cc", "LayerTextureSubImage::uploadWithMapTexSubImage"); + // Offset from image-rect to source-rect. + IntPoint offset(sourceRect.x() - imageRect.x(), sourceRect.y() - imageRect.y()); + + // Upload tile data via a mapped transfer buffer + uint8_t* pixelDest = static_cast(context->mapTexSubImage2DCHROMIUM(GraphicsContext3D::TEXTURE_2D, 0, destOffset.width(), destOffset.height(), sourceRect.width(), sourceRect.height(), format, GraphicsContext3D::UNSIGNED_BYTE, Extensions3DChromium::WRITE_ONLY)); + + if (!pixelDest) { + uploadWithTexSubImage(image, imageRect, sourceRect, destOffset, format, context); + return; + } + + unsigned int componentsPerPixel = 0; + switch (format) { + case GraphicsContext3D::RGBA: + case Extensions3D::BGRA_EXT: + componentsPerPixel = 4; + break; + case GraphicsContext3D::LUMINANCE: + componentsPerPixel = 1; + break; + default: + ASSERT_NOT_REACHED(); + } + unsigned int bytesPerComponent = 1; + + if (imageRect.width() == sourceRect.width() && !offset.x()) + memcpy(pixelDest, &image[offset.y() * imageRect.width() * componentsPerPixel * bytesPerComponent], imageRect.width() * sourceRect.height() * componentsPerPixel * bytesPerComponent); + else { + // Strides not equal, so do a row-by-row memcpy from the + // paint results into the pixelDest + for (int row = 0; row < sourceRect.height(); ++row) + memcpy(&pixelDest[sourceRect.width() * row * componentsPerPixel * bytesPerComponent], + &image[4 * (offset.x() + (offset.y() + row) * imageRect.width())], + sourceRect.width() * componentsPerPixel * bytesPerComponent); + } + GLC(context, context->unmapTexSubImage2DCHROMIUM(pixelDest)); +} + +} // namespace cc + +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/cc/layer_texture_sub_image.h b/cc/layer_texture_sub_image.h index 638cbb2..2c6cc14 100644 --- a/cc/layer_texture_sub_image.h +++ b/cc/layer_texture_sub_image.h @@ -1,3 +1,46 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. +// Copyright 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + + +#ifndef LayerTextureSubImage_h +#define LayerTextureSubImage_h + +#if USE(ACCELERATED_COMPOSITING) + +#include "GraphicsTypes3D.h" +#include "IntRect.h" +#include "IntSize.h" +#include + +namespace WebKit { +class WebGraphicsContext3D; +} + +namespace cc { + +class LayerTextureSubImage { +public: + explicit LayerTextureSubImage(bool useMapSubForUpload); + ~LayerTextureSubImage(); + + void upload(const uint8_t* image, const IntRect& imageRect, + const IntRect& sourceRect, const IntSize& destOffset, + GC3Denum format, WebKit::WebGraphicsContext3D*); + +private: + void uploadWithTexSubImage(const uint8_t* image, const IntRect& imageRect, + const IntRect& sourceRect, const IntSize& destOffset, + GC3Denum format, WebKit::WebGraphicsContext3D*); + void uploadWithMapTexSubImage(const uint8_t* image, const IntRect& imageRect, + const IntRect& sourceRect, const IntSize& destOffset, + GC3Denum format, WebKit::WebGraphicsContext3D*); + + bool m_useMapTexSubImage; + size_t m_subImageSize; + OwnArrayPtr m_subImage; +}; + +} // namespace cc +#endif // USE(ACCELERATED_COMPOSITING) +#endif // LayerTextureSubImage_h diff --git a/cc/layer_texture_updater.cc b/cc/layer_texture_updater.cc new file mode 100644 index 0000000..d4e708f --- /dev/null +++ b/cc/layer_texture_updater.cc @@ -0,0 +1,25 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#include "LayerTextureUpdater.h" + +namespace cc { + +LayerTextureUpdater::Texture::Texture(scoped_ptr texture) + : m_texture(texture.Pass()) +{ +} + +LayerTextureUpdater::Texture::~Texture() +{ +} + +bool LayerTextureUpdater::Texture::backingResourceWasEvicted() const +{ + return m_texture->backingResourceWasEvicted(); +} + +} diff --git a/cc/layer_texture_updater.h b/cc/layer_texture_updater.h index 638cbb2..89fc520 100644 --- a/cc/layer_texture_updater.h +++ b/cc/layer_texture_updater.h @@ -1,3 +1,69 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. +// Copyright 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + + +#ifndef LayerTextureUpdater_h +#define LayerTextureUpdater_h + +#if USE(ACCELERATED_COMPOSITING) + +#include "CCPrioritizedTexture.h" +#include "GraphicsTypes3D.h" +#include + +namespace cc { + +class IntRect; +class IntSize; +class TextureManager; +struct CCRenderingStats; + +class LayerTextureUpdater : public RefCounted { +public: + // Allows texture uploaders to store per-tile resources. + class Texture { + public: + virtual ~Texture(); + + CCPrioritizedTexture* texture() { return m_texture.get(); } + void swapTextureWith(scoped_ptr& texture) { m_texture.swap(texture); } + virtual void prepareRect(const IntRect& /* sourceRect */, CCRenderingStats&) { } + virtual void updateRect(CCResourceProvider*, const IntRect& sourceRect, const IntSize& destOffset) = 0; + virtual bool backingResourceWasEvicted() const; + protected: + explicit Texture(scoped_ptr texture); + + private: + scoped_ptr m_texture; + }; + + LayerTextureUpdater() + { + turnOffVerifier(); // In the component build we don't have WTF threading initialized in this DLL so the thread verifier explodes. + } + + virtual ~LayerTextureUpdater() { } + + enum SampledTexelFormat { + SampledTexelFormatRGBA, + SampledTexelFormatBGRA, + SampledTexelFormatInvalid, + }; + virtual PassOwnPtr createTexture(CCPrioritizedTextureManager*) = 0; + // Returns the format of the texel uploaded by this interface. + // This format should not be confused by texture internal format. + // This format specifies the component order in the sampled texel. + // If the format is TexelFormatBGRA, vec4.x is blue and vec4.z is red. + virtual SampledTexelFormat sampledTexelFormat(GC3Denum textureFormat) = 0; + // The |resultingOpaqueRect| gives back a region of the layer that was painted opaque. If the layer is marked opaque in the updater, + // then this region should be ignored in preference for the entire layer's area. + virtual void prepareToUpdate(const IntRect& contentRect, const IntSize& tileSize, float contentsWidthScale, float contentsHeightScale, IntRect& resultingOpaqueRect, CCRenderingStats&) { } + + // Set true by the layer when it is known that the entire output is going to be opaque. + virtual void setOpaque(bool) { } +}; + +} // namespace cc +#endif // USE(ACCELERATED_COMPOSITING) +#endif // LayerTextureUpdater_h diff --git a/cc/layer_tiling_data.cc b/cc/layer_tiling_data.cc new file mode 100644 index 0000000..12c7aef --- /dev/null +++ b/cc/layer_tiling_data.cc @@ -0,0 +1,158 @@ +// Copyright 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + +#include "config.h" + +#if USE(ACCELERATED_COMPOSITING) + +#include "CCLayerTilingData.h" + +using namespace std; + +namespace cc { + +PassOwnPtr CCLayerTilingData::create(const IntSize& tileSize, BorderTexelOption border) +{ + return adoptPtr(new CCLayerTilingData(tileSize, border)); +} + +CCLayerTilingData::CCLayerTilingData(const IntSize& tileSize, BorderTexelOption border) + : m_tilingData(tileSize, IntSize(), border == HasBorderTexels) +{ + setTileSize(tileSize); +} + +CCLayerTilingData::~CCLayerTilingData() +{ +} + +void CCLayerTilingData::setTileSize(const IntSize& size) +{ + if (tileSize() == size) + return; + + reset(); + + m_tilingData.setMaxTextureSize(size); +} + +IntSize CCLayerTilingData::tileSize() const +{ + return m_tilingData.maxTextureSize(); +} + +void CCLayerTilingData::setBorderTexelOption(BorderTexelOption borderTexelOption) +{ + bool borderTexels = borderTexelOption == HasBorderTexels; + if (hasBorderTexels() == borderTexels) + return; + + reset(); + m_tilingData.setHasBorderTexels(borderTexels); +} + +const CCLayerTilingData& CCLayerTilingData::operator=(const CCLayerTilingData& tiler) +{ + m_tilingData = tiler.m_tilingData; + + return *this; +} + +void CCLayerTilingData::addTile(PassOwnPtr tile, int i, int j) +{ + ASSERT(!tileAt(i, j)); + tile->moveTo(i, j); + m_tiles.add(make_pair(i, j), tile); +} + +PassOwnPtr CCLayerTilingData::takeTile(int i, int j) +{ + return m_tiles.take(make_pair(i, j)); +} + +CCLayerTilingData::Tile* CCLayerTilingData::tileAt(int i, int j) const +{ + return m_tiles.get(make_pair(i, j)); +} + +void CCLayerTilingData::reset() +{ + m_tiles.clear(); +} + +void CCLayerTilingData::contentRectToTileIndices(const IntRect& contentRect, int& left, int& top, int& right, int& bottom) const +{ + // An empty rect doesn't result in an empty set of tiles, so don't pass an empty rect. + // FIXME: Possibly we should fill a vector of tiles instead, + // since the normal use of this function is to enumerate some tiles. + ASSERT(!contentRect.isEmpty()); + + left = m_tilingData.tileXIndexFromSrcCoord(contentRect.x()); + top = m_tilingData.tileYIndexFromSrcCoord(contentRect.y()); + right = m_tilingData.tileXIndexFromSrcCoord(contentRect.maxX() - 1); + bottom = m_tilingData.tileYIndexFromSrcCoord(contentRect.maxY() - 1); +} + +IntRect CCLayerTilingData::tileRect(const Tile* tile) const +{ + IntRect tileRect = m_tilingData.tileBoundsWithBorder(tile->i(), tile->j()); + tileRect.setSize(tileSize()); + return tileRect; +} + +Region CCLayerTilingData::opaqueRegionInContentRect(const IntRect& contentRect) const +{ + if (contentRect.isEmpty()) + return Region(); + + Region opaqueRegion; + int left, top, right, bottom; + contentRectToTileIndices(contentRect, left, top, right, bottom); + for (int j = top; j <= bottom; ++j) { + for (int i = left; i <= right; ++i) { + Tile* tile = tileAt(i, j); + if (!tile) + continue; + + IntRect tileOpaqueRect = intersection(contentRect, tile->opaqueRect()); + opaqueRegion.unite(tileOpaqueRect); + } + } + return opaqueRegion; +} + +void CCLayerTilingData::setBounds(const IntSize& size) +{ + m_tilingData.setTotalSize(size); + if (size.isEmpty()) { + m_tiles.clear(); + return; + } + + // Any tiles completely outside our new bounds are invalid and should be dropped. + int left, top, right, bottom; + contentRectToTileIndices(IntRect(IntPoint(), size), left, top, right, bottom); + Vector invalidTileKeys; + for (TileMap::const_iterator it = m_tiles.begin(); it != m_tiles.end(); ++it) { +#if WTF_NEW_HASHMAP_ITERATORS_INTERFACE + if (it->key.first > right || it->key.second > bottom) + invalidTileKeys.append(it->key); +#else + if (it->first.first > right || it->first.second > bottom) + invalidTileKeys.append(it->first); +#endif + } + for (size_t i = 0; i < invalidTileKeys.size(); ++i) + m_tiles.remove(invalidTileKeys[i]); +} + +IntSize CCLayerTilingData::bounds() const +{ + return m_tilingData.totalSize(); +} + +} // namespace cc + +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/cc/layer_tiling_data.h b/cc/layer_tiling_data.h index 638cbb2..c73f057 100644 --- a/cc/layer_tiling_data.h +++ b/cc/layer_tiling_data.h @@ -1,3 +1,101 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. +// Copyright 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + + +#ifndef CCLayerTilingData_h +#define CCLayerTilingData_h + +#if USE(ACCELERATED_COMPOSITING) + +#include "base/basictypes.h" +#include "IntRect.h" +#include "Region.h" +#include "TilingData.h" +#include +#include +#include + +namespace cc { + +class CCLayerTilingData { +public: + enum BorderTexelOption { HasBorderTexels, NoBorderTexels }; + + ~CCLayerTilingData(); + + static PassOwnPtr create(const IntSize& tileSize, BorderTexelOption); + + bool hasEmptyBounds() const { return m_tilingData.hasEmptyBounds(); } + int numTilesX() const { return m_tilingData.numTilesX(); } + int numTilesY() const { return m_tilingData.numTilesY(); } + IntRect tileBounds(int i, int j) const { return m_tilingData.tileBounds(i, j); } + IntPoint textureOffset(int xIndex, int yIndex) const { return m_tilingData.textureOffset(xIndex, yIndex); } + + // Change the tile size. This may invalidate all the existing tiles. + void setTileSize(const IntSize&); + IntSize tileSize() const; + // Change the border texel setting. This may invalidate all existing tiles. + void setBorderTexelOption(BorderTexelOption); + bool hasBorderTexels() const { return m_tilingData.borderTexels(); } + + bool isEmpty() const { return hasEmptyBounds() || !tiles().size(); } + + const CCLayerTilingData& operator=(const CCLayerTilingData&); + + class Tile { + public: + Tile() : m_i(-1), m_j(-1) { } + virtual ~Tile() { } + + int i() const { return m_i; } + int j() const { return m_j; } + void moveTo(int i, int j) { m_i = i; m_j = j; } + + const IntRect& opaqueRect() const { return m_opaqueRect; } + void setOpaqueRect(const IntRect& opaqueRect) { m_opaqueRect = opaqueRect; } + private: + int m_i; + int m_j; + IntRect m_opaqueRect; + DISALLOW_COPY_AND_ASSIGN(Tile); + }; + // Default hash key traits for integers disallow 0 and -1 as a key, so + // use a custom hash trait which disallows -1 and -2 instead. + typedef std::pair TileMapKey; + struct TileMapKeyTraits : HashTraits { + static const bool emptyValueIsZero = false; + static const bool needsDestruction = false; + static TileMapKey emptyValue() { return std::make_pair(-1, -1); } + static void constructDeletedValue(TileMapKey& slot) { slot = std::make_pair(-2, -2); } + static bool isDeletedValue(TileMapKey value) { return value.first == -2 && value.second == -2; } + }; + typedef HashMap, DefaultHash::Hash, TileMapKeyTraits> TileMap; + + void addTile(PassOwnPtr, int, int); + PassOwnPtr takeTile(int, int); + Tile* tileAt(int, int) const; + const TileMap& tiles() const { return m_tiles; } + + void setBounds(const IntSize&); + IntSize bounds() const; + + void contentRectToTileIndices(const IntRect&, int &left, int &top, int &right, int &bottom) const; + IntRect tileRect(const Tile*) const; + + Region opaqueRegionInContentRect(const IntRect&) const; + + void reset(); + +protected: + CCLayerTilingData(const IntSize& tileSize, BorderTexelOption); + + TileMap m_tiles; + TilingData m_tilingData; +}; + +} + +#endif // USE(ACCELERATED_COMPOSITING) + +#endif diff --git a/cc/layer_tree_host.cc b/cc/layer_tree_host.cc new file mode 100644 index 0000000..d75a3d3 --- /dev/null +++ b/cc/layer_tree_host.cc @@ -0,0 +1,861 @@ +// Copyright 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#include "CCLayerTreeHost.h" + +#include "CCFontAtlas.h" +#include "CCGraphicsContext.h" +#include "CCHeadsUpDisplayLayerImpl.h" +#include "CCLayerAnimationController.h" +#include "CCLayerIterator.h" +#include "CCLayerTreeHostClient.h" +#include "CCLayerTreeHostCommon.h" +#include "CCLayerTreeHostImpl.h" +#include "CCOcclusionTracker.h" +#include "CCOverdrawMetrics.h" +#include "CCSettings.h" +#include "CCSingleThreadProxy.h" +#include "CCThreadProxy.h" +#include "HeadsUpDisplayLayerChromium.h" +#include "LayerChromium.h" +#include "Region.h" +#include "TraceEvent.h" +#include "TreeSynchronizer.h" + +using namespace std; +using WebKit::WebTransformationMatrix; + +namespace { +static int numLayerTreeInstances; +} + +namespace cc { + +bool CCLayerTreeHost::s_needsFilterContext = false; + +CCLayerTreeSettings::CCLayerTreeSettings() + : acceleratePainting(false) + , showFPSCounter(false) + , showPlatformLayerTree(false) + , showPaintRects(false) + , showPropertyChangedRects(false) + , showSurfaceDamageRects(false) + , showScreenSpaceRects(false) + , showReplicaScreenSpaceRects(false) + , showOccludingRects(false) + , renderVSyncEnabled(true) + , refreshRate(0) + , maxPartialTextureUpdates(std::numeric_limits::max()) + , defaultTileSize(IntSize(256, 256)) + , maxUntiledLayerSize(IntSize(512, 512)) + , minimumOcclusionTrackingSize(IntSize(160, 160)) +{ +} + +CCLayerTreeSettings::~CCLayerTreeSettings() +{ +} + +RendererCapabilities::RendererCapabilities() + : bestTextureFormat(0) + , contextHasCachedFrontBuffer(false) + , usingPartialSwap(false) + , usingAcceleratedPainting(false) + , usingSetVisibility(false) + , usingSwapCompleteCallback(false) + , usingGpuMemoryManager(false) + , usingDiscardFramebuffer(false) + , usingEglImage(false) + , maxTextureSize(0) +{ +} + +RendererCapabilities::~RendererCapabilities() +{ +} + +bool CCLayerTreeHost::anyLayerTreeHostInstanceExists() +{ + return numLayerTreeInstances > 0; +} + +scoped_ptr CCLayerTreeHost::create(CCLayerTreeHostClient* client, const CCLayerTreeSettings& settings) +{ + scoped_ptr layerTreeHost(new CCLayerTreeHost(client, settings)); + if (!layerTreeHost->initialize()) + return scoped_ptr(); + return layerTreeHost.Pass(); +} + +CCLayerTreeHost::CCLayerTreeHost(CCLayerTreeHostClient* client, const CCLayerTreeSettings& settings) + : m_animating(false) + , m_needsAnimateLayers(false) + , m_client(client) + , m_commitNumber(0) + , m_renderingStats() + , m_rendererInitialized(false) + , m_contextLost(false) + , m_numTimesRecreateShouldFail(0) + , m_numFailedRecreateAttempts(0) + , m_settings(settings) + , m_deviceScaleFactor(1) + , m_visible(true) + , m_pageScaleFactor(1) + , m_minPageScaleFactor(1) + , m_maxPageScaleFactor(1) + , m_triggerIdleUpdates(true) + , m_backgroundColor(SK_ColorWHITE) + , m_hasTransparentBackground(false) + , m_partialTextureUpdateRequests(0) +{ + ASSERT(CCProxy::isMainThread()); + numLayerTreeInstances++; +} + +bool CCLayerTreeHost::initialize() +{ + TRACE_EVENT0("cc", "CCLayerTreeHost::initialize"); + + if (CCProxy::hasImplThread()) + m_proxy = CCThreadProxy::create(this); + else + m_proxy = CCSingleThreadProxy::create(this); + m_proxy->start(); + + return m_proxy->initializeContext(); +} + +CCLayerTreeHost::~CCLayerTreeHost() +{ + if (m_rootLayer) + m_rootLayer->setLayerTreeHost(0); + ASSERT(CCProxy::isMainThread()); + TRACE_EVENT0("cc", "CCLayerTreeHost::~CCLayerTreeHost"); + ASSERT(m_proxy.get()); + m_proxy->stop(); + m_proxy.reset(); + numLayerTreeInstances--; + RateLimiterMap::iterator it = m_rateLimiters.begin(); + if (it != m_rateLimiters.end()) + it->second->stop(); +} + +void CCLayerTreeHost::setSurfaceReady() +{ + m_proxy->setSurfaceReady(); +} + +void CCLayerTreeHost::initializeRenderer() +{ + TRACE_EVENT0("cc", "CCLayerTreeHost::initializeRenderer"); + if (!m_proxy->initializeRenderer()) { + // Uh oh, better tell the client that we can't do anything with this context. + m_client->didRecreateOutputSurface(false); + return; + } + + // Update m_settings based on capabilities that we got back from the renderer. + m_settings.acceleratePainting = m_proxy->rendererCapabilities().usingAcceleratedPainting; + + // Update m_settings based on partial update capability. + m_settings.maxPartialTextureUpdates = min(m_settings.maxPartialTextureUpdates, m_proxy->maxPartialTextureUpdates()); + + m_contentsTextureManager = CCPrioritizedTextureManager::create(0, m_proxy->rendererCapabilities().maxTextureSize, CCRenderer::ContentPool); + m_surfaceMemoryPlaceholder = m_contentsTextureManager->createTexture(IntSize(), GraphicsContext3D::RGBA); + + m_rendererInitialized = true; + + m_settings.defaultTileSize = IntSize(min(m_settings.defaultTileSize.width(), m_proxy->rendererCapabilities().maxTextureSize), + min(m_settings.defaultTileSize.height(), m_proxy->rendererCapabilities().maxTextureSize)); + m_settings.maxUntiledLayerSize = IntSize(min(m_settings.maxUntiledLayerSize.width(), m_proxy->rendererCapabilities().maxTextureSize), + min(m_settings.maxUntiledLayerSize.height(), m_proxy->rendererCapabilities().maxTextureSize)); +} + +CCLayerTreeHost::RecreateResult CCLayerTreeHost::recreateContext() +{ + TRACE_EVENT0("cc", "CCLayerTreeHost::recreateContext"); + ASSERT(m_contextLost); + + bool recreated = false; + if (!m_numTimesRecreateShouldFail) + recreated = m_proxy->recreateContext(); + else + m_numTimesRecreateShouldFail--; + + if (recreated) { + m_client->didRecreateOutputSurface(true); + m_contextLost = false; + return RecreateSucceeded; + } + + // Tolerate a certain number of recreation failures to work around races + // in the context-lost machinery. + m_numFailedRecreateAttempts++; + if (m_numFailedRecreateAttempts < 5) { + // FIXME: The single thread does not self-schedule context + // recreation. So force another recreation attempt to happen by requesting + // another commit. + if (!CCProxy::hasImplThread()) + setNeedsCommit(); + return RecreateFailedButTryAgain; + } + + // We have tried too many times to recreate the context. Tell the host to fall + // back to software rendering. + m_client->didRecreateOutputSurface(false); + return RecreateFailedAndGaveUp; +} + +void CCLayerTreeHost::deleteContentsTexturesOnImplThread(CCResourceProvider* resourceProvider) +{ + ASSERT(CCProxy::isImplThread()); + if (m_rendererInitialized) + m_contentsTextureManager->clearAllMemory(resourceProvider); +} + +void CCLayerTreeHost::acquireLayerTextures() +{ + ASSERT(CCProxy::isMainThread()); + m_proxy->acquireLayerTextures(); +} + +void CCLayerTreeHost::updateAnimations(double monotonicFrameBeginTime) +{ + m_animating = true; + m_client->animate(monotonicFrameBeginTime); + animateLayers(monotonicFrameBeginTime); + m_animating = false; + + m_renderingStats.numAnimationFrames++; +} + +void CCLayerTreeHost::layout() +{ + m_client->layout(); +} + +void CCLayerTreeHost::beginCommitOnImplThread(CCLayerTreeHostImpl* hostImpl) +{ + ASSERT(CCProxy::isImplThread()); + TRACE_EVENT0("cc", "CCLayerTreeHost::commitTo"); + + m_contentsTextureManager->reduceMemory(hostImpl->resourceProvider()); +} + +// This function commits the CCLayerTreeHost to an impl tree. When modifying +// this function, keep in mind that the function *runs* on the impl thread! Any +// code that is logically a main thread operation, e.g. deletion of a LayerChromium, +// should be delayed until the CCLayerTreeHost::commitComplete, which will run +// after the commit, but on the main thread. +void CCLayerTreeHost::finishCommitOnImplThread(CCLayerTreeHostImpl* hostImpl) +{ + ASSERT(CCProxy::isImplThread()); + + hostImpl->setRootLayer(TreeSynchronizer::synchronizeTrees(rootLayer(), hostImpl->detachLayerTree(), hostImpl)); + + if (m_rootLayer && m_hudLayer) + hostImpl->setHudLayer(static_cast(CCLayerTreeHostCommon::findLayerInSubtree(hostImpl->rootLayer(), m_hudLayer->id()))); + else + hostImpl->setHudLayer(0); + + // We may have added an animation during the tree sync. This will cause both layer tree hosts + // to visit their controllers. + if (rootLayer() && m_needsAnimateLayers) + hostImpl->setNeedsAnimateLayers(); + + hostImpl->setSourceFrameNumber(commitNumber()); + hostImpl->setViewportSize(layoutViewportSize(), deviceViewportSize()); + hostImpl->setDeviceScaleFactor(deviceScaleFactor()); + hostImpl->setPageScaleFactorAndLimits(m_pageScaleFactor, m_minPageScaleFactor, m_maxPageScaleFactor); + hostImpl->setBackgroundColor(m_backgroundColor); + hostImpl->setHasTransparentBackground(m_hasTransparentBackground); + + m_commitNumber++; +} + +void CCLayerTreeHost::setFontAtlas(scoped_ptr fontAtlas) +{ + m_fontAtlas = fontAtlas.Pass(); + setNeedsCommit(); +} + +void CCLayerTreeHost::willCommit() +{ + m_client->willCommit(); + if (m_rootLayer && m_settings.showDebugInfo()) { + if (!m_hudLayer) + m_hudLayer = HeadsUpDisplayLayerChromium::create(); + + if (m_fontAtlas.get()) + m_hudLayer->setFontAtlas(m_fontAtlas.Pass()); + + if (!m_hudLayer->parent()) + m_rootLayer->addChild(m_hudLayer); + } +} + +void CCLayerTreeHost::commitComplete() +{ + m_deleteTextureAfterCommitList.clear(); + m_client->didCommit(); +} + +scoped_ptr CCLayerTreeHost::createContext() +{ + return m_client->createOutputSurface(); +} + +scoped_ptr CCLayerTreeHost::createInputHandler() +{ + return m_client->createInputHandler(); +} + +scoped_ptr CCLayerTreeHost::createLayerTreeHostImpl(CCLayerTreeHostImplClient* client) +{ + return CCLayerTreeHostImpl::create(m_settings, client); +} + +void CCLayerTreeHost::didLoseContext() +{ + TRACE_EVENT0("cc", "CCLayerTreeHost::didLoseContext"); + ASSERT(CCProxy::isMainThread()); + m_contextLost = true; + m_numFailedRecreateAttempts = 0; + setNeedsCommit(); +} + +bool CCLayerTreeHost::compositeAndReadback(void *pixels, const IntRect& rect) +{ + m_triggerIdleUpdates = false; + bool ret = m_proxy->compositeAndReadback(pixels, rect); + m_triggerIdleUpdates = true; + return ret; +} + +void CCLayerTreeHost::finishAllRendering() +{ + if (!m_rendererInitialized) + return; + m_proxy->finishAllRendering(); +} + +void CCLayerTreeHost::renderingStats(CCRenderingStats* stats) const +{ + *stats = m_renderingStats; + m_proxy->renderingStats(stats); +} + +const RendererCapabilities& CCLayerTreeHost::rendererCapabilities() const +{ + return m_proxy->rendererCapabilities(); +} + +void CCLayerTreeHost::setNeedsAnimate() +{ + ASSERT(CCProxy::hasImplThread()); + m_proxy->setNeedsAnimate(); +} + +void CCLayerTreeHost::setNeedsCommit() +{ + m_proxy->setNeedsCommit(); +} + +void CCLayerTreeHost::setNeedsRedraw() +{ + m_proxy->setNeedsRedraw(); + if (!CCThreadProxy::implThread()) + m_client->scheduleComposite(); +} + +bool CCLayerTreeHost::commitRequested() const +{ + return m_proxy->commitRequested(); +} + +void CCLayerTreeHost::setAnimationEvents(scoped_ptr events, double wallClockTime) +{ + ASSERT(CCThreadProxy::isMainThread()); + setAnimationEventsRecursive(*events.get(), m_rootLayer.get(), wallClockTime); +} + +void CCLayerTreeHost::didAddAnimation() +{ + m_needsAnimateLayers = true; + m_proxy->didAddAnimation(); +} + +void CCLayerTreeHost::setRootLayer(scoped_refptr rootLayer) +{ + if (m_rootLayer == rootLayer) + return; + + if (m_rootLayer) + m_rootLayer->setLayerTreeHost(0); + m_rootLayer = rootLayer; + if (m_rootLayer) + m_rootLayer->setLayerTreeHost(this); + + if (m_hudLayer) + m_hudLayer->removeFromParent(); + + setNeedsCommit(); +} + +void CCLayerTreeHost::setViewportSize(const IntSize& layoutViewportSize, const IntSize& deviceViewportSize) +{ + if (layoutViewportSize == m_layoutViewportSize && deviceViewportSize == m_deviceViewportSize) + return; + + m_layoutViewportSize = layoutViewportSize; + m_deviceViewportSize = deviceViewportSize; + + setNeedsCommit(); +} + +void CCLayerTreeHost::setPageScaleFactorAndLimits(float pageScaleFactor, float minPageScaleFactor, float maxPageScaleFactor) +{ + if (pageScaleFactor == m_pageScaleFactor && minPageScaleFactor == m_minPageScaleFactor && maxPageScaleFactor == m_maxPageScaleFactor) + return; + + m_pageScaleFactor = pageScaleFactor; + m_minPageScaleFactor = minPageScaleFactor; + m_maxPageScaleFactor = maxPageScaleFactor; + setNeedsCommit(); +} + +void CCLayerTreeHost::setVisible(bool visible) +{ + if (m_visible == visible) + return; + m_visible = visible; + m_proxy->setVisible(visible); +} + +void CCLayerTreeHost::reduceContentsTexturesMemoryOnImplThread(size_t limitBytes, CCResourceProvider* resourceProvider) +{ + ASSERT(CCProxy::isImplThread()); + ASSERT(m_contentsTextureManager.get()); + m_contentsTextureManager->reduceMemoryOnImplThread(limitBytes, resourceProvider); +} + +bool CCLayerTreeHost::evictedContentsTexturesBackingsExist() const +{ + ASSERT(CCProxy::isImplThread()); + ASSERT(m_contentsTextureManager.get()); + return m_contentsTextureManager->evictedBackingsExist(); +} + +void CCLayerTreeHost::getEvictedContentTexturesBackings(CCPrioritizedTextureManager::BackingVector& evictedBackings) +{ + ASSERT(CCProxy::isImplThread()); + evictedBackings.clear(); + if (m_rendererInitialized) + m_contentsTextureManager->getEvictedBackings(evictedBackings); +} + +void CCLayerTreeHost::unlinkEvictedContentTexturesBackings(const CCPrioritizedTextureManager::BackingVector& evictedBackings) +{ + ASSERT(CCProxy::isMainThread()); + ASSERT(m_contentsTextureManager.get()); + m_contentsTextureManager->unlinkEvictedBackings(evictedBackings); +} + +bool CCLayerTreeHost::deleteEvictedContentTexturesBackings() +{ + ASSERT(CCProxy::isImplThread() && CCProxy::isMainThreadBlocked()); + ASSERT(m_contentsTextureManager.get()); + return m_contentsTextureManager->deleteEvictedBackings(); +} + +void CCLayerTreeHost::startPageScaleAnimation(const IntSize& targetPosition, bool useAnchor, float scale, double durationSec) +{ + m_proxy->startPageScaleAnimation(targetPosition, useAnchor, scale, durationSec); +} + +void CCLayerTreeHost::loseContext(int numTimes) +{ + TRACE_EVENT1("cc", "CCLayerTreeHost::loseCompositorContext", "numTimes", numTimes); + m_numTimesRecreateShouldFail = numTimes - 1; + m_proxy->loseContext(); +} + +CCPrioritizedTextureManager* CCLayerTreeHost::contentsTextureManager() const +{ + return m_contentsTextureManager.get(); +} + +void CCLayerTreeHost::composite() +{ + ASSERT(!CCThreadProxy::implThread()); + static_cast(m_proxy.get())->compositeImmediately(); +} + +void CCLayerTreeHost::scheduleComposite() +{ + m_client->scheduleComposite(); +} + +bool CCLayerTreeHost::initializeRendererIfNeeded() +{ + if (!m_rendererInitialized) { + initializeRenderer(); + // If we couldn't initialize, then bail since we're returning to software mode. + if (!m_rendererInitialized) + return false; + } + if (m_contextLost) { + if (recreateContext() != RecreateSucceeded) + return false; + } + return true; +} + +void CCLayerTreeHost::updateLayers(CCTextureUpdateQueue& queue, size_t memoryAllocationLimitBytes) +{ + ASSERT(m_rendererInitialized); + ASSERT(memoryAllocationLimitBytes); + + if (!rootLayer()) + return; + + if (layoutViewportSize().isEmpty()) + return; + + m_contentsTextureManager->setMaxMemoryLimitBytes(memoryAllocationLimitBytes); + + updateLayers(rootLayer(), queue); +} + +static void setScale(LayerChromium* layer, float deviceScaleFactor, float pageScaleFactor) +{ + if (layer->boundsContainPageScale()) + layer->setContentsScale(deviceScaleFactor); + else + layer->setContentsScale(deviceScaleFactor * pageScaleFactor); +} + +static LayerChromium* findFirstScrollableLayer(LayerChromium* layer) +{ + if (!layer) + return 0; + + if (layer->scrollable()) + return layer; + + for (size_t i = 0; i < layer->children().size(); ++i) { + LayerChromium* found = findFirstScrollableLayer(layer->children()[i].get()); + if (found) + return found; + } + + return 0; +} + +static void updateLayerScale(LayerChromium* layer, float deviceScaleFactor, float pageScaleFactor) +{ + setScale(layer, deviceScaleFactor, pageScaleFactor); + + LayerChromium* maskLayer = layer->maskLayer(); + if (maskLayer) + setScale(maskLayer, deviceScaleFactor, pageScaleFactor); + + LayerChromium* replicaMaskLayer = layer->replicaLayer() ? layer->replicaLayer()->maskLayer() : 0; + if (replicaMaskLayer) + setScale(replicaMaskLayer, deviceScaleFactor, pageScaleFactor); + + const std::vector >& children = layer->children(); + for (unsigned int i = 0; i < children.size(); ++i) + updateLayerScale(children[i].get(), deviceScaleFactor, pageScaleFactor); +} + +void CCLayerTreeHost::updateLayers(LayerChromium* rootLayer, CCTextureUpdateQueue& queue) +{ + TRACE_EVENT0("cc", "CCLayerTreeHost::updateLayers"); + + updateLayerScale(rootLayer, m_deviceScaleFactor, m_pageScaleFactor); + + LayerList updateList; + + { + if (CCSettings::pageScalePinchZoomEnabled()) { + LayerChromium* rootScroll = findFirstScrollableLayer(rootLayer); + if (rootScroll) + rootScroll->setImplTransform(m_implTransform); + } + + TRACE_EVENT0("cc", "CCLayerTreeHost::updateLayers::calcDrawEtc"); + CCLayerTreeHostCommon::calculateDrawTransforms(rootLayer, deviceViewportSize(), m_deviceScaleFactor, rendererCapabilities().maxTextureSize, updateList); + } + + // Reset partial texture update requests. + m_partialTextureUpdateRequests = 0; + + bool needMoreUpdates = paintLayerContents(updateList, queue); + if (m_triggerIdleUpdates && needMoreUpdates) + setNeedsCommit(); + + for (size_t i = 0; i < updateList.size(); ++i) + updateList[i]->clearRenderSurface(); +} + +void CCLayerTreeHost::setPrioritiesForSurfaces(size_t surfaceMemoryBytes) +{ + // Surfaces have a place holder for their memory since they are managed + // independantly but should still be tracked and reduce other memory usage. + m_surfaceMemoryPlaceholder->setTextureManager(m_contentsTextureManager.get()); + m_surfaceMemoryPlaceholder->setRequestPriority(CCPriorityCalculator::renderSurfacePriority()); + m_surfaceMemoryPlaceholder->setToSelfManagedMemoryPlaceholder(surfaceMemoryBytes); +} + +void CCLayerTreeHost::setPrioritiesForLayers(const LayerList& updateList) +{ + // Use BackToFront since it's cheap and this isn't order-dependent. + typedef CCLayerIterator CCLayerIteratorType; + + CCPriorityCalculator calculator; + CCLayerIteratorType end = CCLayerIteratorType::end(&updateList); + for (CCLayerIteratorType it = CCLayerIteratorType::begin(&updateList); it != end; ++it) { + if (it.representsItself()) + it->setTexturePriorities(calculator); + else if (it.representsTargetRenderSurface()) { + if (it->maskLayer()) + it->maskLayer()->setTexturePriorities(calculator); + if (it->replicaLayer() && it->replicaLayer()->maskLayer()) + it->replicaLayer()->maskLayer()->setTexturePriorities(calculator); + } + } +} + +void CCLayerTreeHost::prioritizeTextures(const LayerList& renderSurfaceLayerList, CCOverdrawMetrics& metrics) +{ + m_contentsTextureManager->clearPriorities(); + + size_t memoryForRenderSurfacesMetric = calculateMemoryForRenderSurfaces(renderSurfaceLayerList); + + setPrioritiesForLayers(renderSurfaceLayerList); + setPrioritiesForSurfaces(memoryForRenderSurfacesMetric); + + metrics.didUseContentsTextureMemoryBytes(m_contentsTextureManager->memoryAboveCutoffBytes()); + metrics.didUseRenderSurfaceTextureMemoryBytes(memoryForRenderSurfacesMetric); + + m_contentsTextureManager->prioritizeTextures(); +} + +size_t CCLayerTreeHost::calculateMemoryForRenderSurfaces(const LayerList& updateList) +{ + size_t readbackBytes = 0; + size_t maxBackgroundTextureBytes = 0; + size_t contentsTextureBytes = 0; + + // Start iteration at 1 to skip the root surface as it does not have a texture cost. + for (size_t i = 1; i < updateList.size(); ++i) { + LayerChromium* renderSurfaceLayer = updateList[i].get(); + RenderSurfaceChromium* renderSurface = renderSurfaceLayer->renderSurface(); + + size_t bytes = CCTexture::memorySizeBytes(renderSurface->contentRect().size(), GraphicsContext3D::RGBA); + contentsTextureBytes += bytes; + + if (renderSurfaceLayer->backgroundFilters().isEmpty()) + continue; + + if (bytes > maxBackgroundTextureBytes) + maxBackgroundTextureBytes = bytes; + if (!readbackBytes) + readbackBytes = CCTexture::memorySizeBytes(m_deviceViewportSize, GraphicsContext3D::RGBA); + } + return readbackBytes + maxBackgroundTextureBytes + contentsTextureBytes; +} + +bool CCLayerTreeHost::paintMasksForRenderSurface(LayerChromium* renderSurfaceLayer, CCTextureUpdateQueue& queue) +{ + // Note: Masks and replicas only exist for layers that own render surfaces. If we reach this point + // in code, we already know that at least something will be drawn into this render surface, so the + // mask and replica should be painted. + + bool needMoreUpdates = false; + LayerChromium* maskLayer = renderSurfaceLayer->maskLayer(); + if (maskLayer) { + maskLayer->update(queue, 0, m_renderingStats); + needMoreUpdates |= maskLayer->needMoreUpdates(); + } + + LayerChromium* replicaMaskLayer = renderSurfaceLayer->replicaLayer() ? renderSurfaceLayer->replicaLayer()->maskLayer() : 0; + if (replicaMaskLayer) { + replicaMaskLayer->update(queue, 0, m_renderingStats); + needMoreUpdates |= replicaMaskLayer->needMoreUpdates(); + } + return needMoreUpdates; +} + +bool CCLayerTreeHost::paintLayerContents(const LayerList& renderSurfaceLayerList, CCTextureUpdateQueue& queue) +{ + // Use FrontToBack to allow for testing occlusion and performing culling during the tree walk. + typedef CCLayerIterator CCLayerIteratorType; + + bool needMoreUpdates = false; + bool recordMetricsForFrame = true; // FIXME: In the future, disable this when about:tracing is off. + CCOcclusionTracker occlusionTracker(m_rootLayer->renderSurface()->contentRect(), recordMetricsForFrame); + occlusionTracker.setMinimumTrackingSize(m_settings.minimumOcclusionTrackingSize); + + prioritizeTextures(renderSurfaceLayerList, occlusionTracker.overdrawMetrics()); + + CCLayerIteratorType end = CCLayerIteratorType::end(&renderSurfaceLayerList); + for (CCLayerIteratorType it = CCLayerIteratorType::begin(&renderSurfaceLayerList); it != end; ++it) { + occlusionTracker.enterLayer(it); + + if (it.representsTargetRenderSurface()) { + ASSERT(it->renderSurface()->drawOpacity() || it->renderSurface()->drawOpacityIsAnimating()); + needMoreUpdates |= paintMasksForRenderSurface(*it, queue); + } else if (it.representsItself()) { + ASSERT(!it->bounds().isEmpty()); + it->update(queue, &occlusionTracker, m_renderingStats); + needMoreUpdates |= it->needMoreUpdates(); + } + + occlusionTracker.leaveLayer(it); + } + + occlusionTracker.overdrawMetrics().recordMetrics(this); + + return needMoreUpdates; +} + +void CCLayerTreeHost::applyScrollAndScale(const CCScrollAndScaleSet& info) +{ + if (!m_rootLayer) + return; + + LayerChromium* rootScrollLayer = findFirstScrollableLayer(m_rootLayer.get()); + IntSize rootScrollDelta; + + for (size_t i = 0; i < info.scrolls.size(); ++i) { + LayerChromium* layer = CCLayerTreeHostCommon::findLayerInSubtree(m_rootLayer.get(), info.scrolls[i].layerId); + if (!layer) + continue; + if (layer == rootScrollLayer) + rootScrollDelta += info.scrolls[i].scrollDelta; + else + layer->setScrollPosition(layer->scrollPosition() + info.scrolls[i].scrollDelta); + } + if (!rootScrollDelta.isZero() || info.pageScaleDelta != 1) + m_client->applyScrollAndScale(rootScrollDelta, info.pageScaleDelta); +} + +void CCLayerTreeHost::setImplTransform(const WebKit::WebTransformationMatrix& transform) +{ + m_implTransform = transform; +} + +void CCLayerTreeHost::startRateLimiter(WebKit::WebGraphicsContext3D* context) +{ + if (m_animating) + return; + + ASSERT(context); + RateLimiterMap::iterator it = m_rateLimiters.find(context); + if (it != m_rateLimiters.end()) + it->second->start(); + else { + scoped_refptr rateLimiter = RateLimiter::create(context, this); + m_rateLimiters[context] = rateLimiter; + rateLimiter->start(); + } +} + +void CCLayerTreeHost::stopRateLimiter(WebKit::WebGraphicsContext3D* context) +{ + RateLimiterMap::iterator it = m_rateLimiters.find(context); + if (it != m_rateLimiters.end()) { + it->second->stop(); + m_rateLimiters.erase(it); + } +} + +void CCLayerTreeHost::rateLimit() +{ + // Force a no-op command on the compositor context, so that any ratelimiting commands will wait for the compositing + // context, and therefore for the SwapBuffers. + m_proxy->forceSerializeOnSwapBuffers(); +} + +bool CCLayerTreeHost::bufferedUpdates() +{ + return m_settings.maxPartialTextureUpdates != numeric_limits::max(); +} + +bool CCLayerTreeHost::requestPartialTextureUpdate() +{ + if (m_partialTextureUpdateRequests >= m_settings.maxPartialTextureUpdates) + return false; + + m_partialTextureUpdateRequests++; + return true; +} + +void CCLayerTreeHost::deleteTextureAfterCommit(scoped_ptr texture) +{ + m_deleteTextureAfterCommitList.append(texture.Pass()); +} + +void CCLayerTreeHost::setDeviceScaleFactor(float deviceScaleFactor) +{ + if (deviceScaleFactor == m_deviceScaleFactor) + return; + m_deviceScaleFactor = deviceScaleFactor; + + setNeedsCommit(); +} + +void CCLayerTreeHost::animateLayers(double monotonicTime) +{ + if (!CCSettings::acceleratedAnimationEnabled() || !m_needsAnimateLayers) + return; + + TRACE_EVENT0("cc", "CCLayerTreeHostImpl::animateLayers"); + m_needsAnimateLayers = animateLayersRecursive(m_rootLayer.get(), monotonicTime); +} + +bool CCLayerTreeHost::animateLayersRecursive(LayerChromium* current, double monotonicTime) +{ + if (!current) + return false; + + bool subtreeNeedsAnimateLayers = false; + CCLayerAnimationController* currentController = current->layerAnimationController(); + currentController->animate(monotonicTime, 0); + + // If the current controller still has an active animation, we must continue animating layers. + if (currentController->hasActiveAnimation()) + subtreeNeedsAnimateLayers = true; + + for (size_t i = 0; i < current->children().size(); ++i) { + if (animateLayersRecursive(current->children()[i].get(), monotonicTime)) + subtreeNeedsAnimateLayers = true; + } + + return subtreeNeedsAnimateLayers; +} + +void CCLayerTreeHost::setAnimationEventsRecursive(const CCAnimationEventsVector& events, LayerChromium* layer, double wallClockTime) +{ + if (!layer) + return; + + for (size_t eventIndex = 0; eventIndex < events.size(); ++eventIndex) { + if (layer->id() == events[eventIndex].layerId) { + if (events[eventIndex].type == CCAnimationEvent::Started) + layer->notifyAnimationStarted(events[eventIndex], wallClockTime); + else + layer->notifyAnimationFinished(wallClockTime); + } + } + + for (size_t childIndex = 0; childIndex < layer->children().size(); ++childIndex) + setAnimationEventsRecursive(events, layer->children()[childIndex].get(), wallClockTime); +} + +} // namespace cc diff --git a/cc/layer_tree_host.h b/cc/layer_tree_host.h index 638cbb2..277b1f0 100644 --- a/cc/layer_tree_host.h +++ b/cc/layer_tree_host.h @@ -1,3 +1,297 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. +// Copyright 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CCLayerTreeHost_h +#define CCLayerTreeHost_h + +#include "base/basictypes.h" +#include "base/hash_tables.h" +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" +#include "CCAnimationEvents.h" +#include "CCGraphicsContext.h" +#include "CCLayerTreeHostClient.h" +#include "CCLayerTreeHostCommon.h" +#include "CCOcclusionTracker.h" +#include "CCPrioritizedTextureManager.h" +#include "CCProxy.h" +#include "CCRenderingStats.h" +#include "IntRect.h" +#include "RateLimiter.h" +#include "scoped_ptr_vector.h" +#include "SkColor.h" +#include + +#if defined(COMPILER_GCC) +namespace BASE_HASH_NAMESPACE { +template<> +struct hash { + size_t operator()(WebKit::WebGraphicsContext3D* ptr) const { + return hash()(reinterpret_cast(ptr)); + } +}; +} // namespace BASE_HASH_NAMESPACE +#endif // COMPILER + +namespace cc { + +class CCFontAtlas; +class CCLayerChromium; +class CCLayerTreeHostImpl; +class CCLayerTreeHostImplClient; +class CCPrioritizedTextureManager; +class CCTextureUpdateQueue; +class HeadsUpDisplayLayerChromium; +class Region; +struct CCScrollAndScaleSet; + +struct CCLayerTreeSettings { + CCLayerTreeSettings(); + ~CCLayerTreeSettings(); + + bool acceleratePainting; + bool showFPSCounter; + bool showPlatformLayerTree; + bool showPaintRects; + bool showPropertyChangedRects; + bool showSurfaceDamageRects; + bool showScreenSpaceRects; + bool showReplicaScreenSpaceRects; + bool showOccludingRects; + bool renderVSyncEnabled; + double refreshRate; + size_t maxPartialTextureUpdates; + IntSize defaultTileSize; + IntSize maxUntiledLayerSize; + IntSize minimumOcclusionTrackingSize; + + bool showDebugInfo() const { return showPlatformLayerTree || showFPSCounter || showDebugRects(); } + bool showDebugRects() const { return showPaintRects || showPropertyChangedRects || showSurfaceDamageRects || showScreenSpaceRects || showReplicaScreenSpaceRects || showOccludingRects; } +}; + +// Provides information on an Impl's rendering capabilities back to the CCLayerTreeHost +struct RendererCapabilities { + RendererCapabilities(); + ~RendererCapabilities(); + + GC3Denum bestTextureFormat; + bool contextHasCachedFrontBuffer; + bool usingPartialSwap; + bool usingAcceleratedPainting; + bool usingSetVisibility; + bool usingSwapCompleteCallback; + bool usingGpuMemoryManager; + bool usingDiscardFramebuffer; + bool usingEglImage; + int maxTextureSize; +}; + +class CCLayerTreeHost : public RateLimiterClient { +public: + static scoped_ptr create(CCLayerTreeHostClient*, const CCLayerTreeSettings&); + virtual ~CCLayerTreeHost(); + + void setSurfaceReady(); + + // Returns true if any CCLayerTreeHost is alive. + static bool anyLayerTreeHostInstanceExists(); + + static bool needsFilterContext() { return s_needsFilterContext; } + static void setNeedsFilterContext(bool needsFilterContext) { s_needsFilterContext = needsFilterContext; } + bool needsSharedContext() const { return needsFilterContext() || settings().acceleratePainting; } + + // CCLayerTreeHost interface to CCProxy. + void willBeginFrame() { m_client->willBeginFrame(); } + void didBeginFrame() { m_client->didBeginFrame(); } + void updateAnimations(double monotonicFrameBeginTime); + void layout(); + void beginCommitOnImplThread(CCLayerTreeHostImpl*); + void finishCommitOnImplThread(CCLayerTreeHostImpl*); + void willCommit(); + void commitComplete(); + scoped_ptr createContext(); + scoped_ptr createInputHandler(); + virtual scoped_ptr createLayerTreeHostImpl(CCLayerTreeHostImplClient*); + void didLoseContext(); + enum RecreateResult { + RecreateSucceeded, + RecreateFailedButTryAgain, + RecreateFailedAndGaveUp, + }; + RecreateResult recreateContext(); + void didCommitAndDrawFrame() { m_client->didCommitAndDrawFrame(); } + void didCompleteSwapBuffers() { m_client->didCompleteSwapBuffers(); } + void deleteContentsTexturesOnImplThread(CCResourceProvider*); + virtual void acquireLayerTextures(); + // Returns false if we should abort this frame due to initialization failure. + bool initializeRendererIfNeeded(); + void updateLayers(CCTextureUpdateQueue&, size_t contentsMemoryLimitBytes); + + CCLayerTreeHostClient* client() { return m_client; } + + // Only used when compositing on the main thread. + void composite(); + void scheduleComposite(); + + // Composites and attempts to read back the result into the provided + // buffer. If it wasn't possible, e.g. due to context lost, will return + // false. + bool compositeAndReadback(void *pixels, const IntRect&); + + void finishAllRendering(); + + int commitNumber() const { return m_commitNumber; } + + void renderingStats(CCRenderingStats*) const; + + const RendererCapabilities& rendererCapabilities() const; + + // Test only hook + void loseContext(int numTimes); + + void setNeedsAnimate(); + // virtual for testing + virtual void setNeedsCommit(); + void setNeedsRedraw(); + bool commitRequested() const; + + void setAnimationEvents(scoped_ptr, double wallClockTime); + virtual void didAddAnimation(); + + LayerChromium* rootLayer() { return m_rootLayer.get(); } + const LayerChromium* rootLayer() const { return m_rootLayer.get(); } + void setRootLayer(scoped_refptr); + + const CCLayerTreeSettings& settings() const { return m_settings; } + + void setViewportSize(const IntSize& layoutViewportSize, const IntSize& deviceViewportSize); + + const IntSize& layoutViewportSize() const { return m_layoutViewportSize; } + const IntSize& deviceViewportSize() const { return m_deviceViewportSize; } + + void setPageScaleFactorAndLimits(float pageScaleFactor, float minPageScaleFactor, float maxPageScaleFactor); + + void setBackgroundColor(SkColor color) { m_backgroundColor = color; } + + void setHasTransparentBackground(bool transparent) { m_hasTransparentBackground = transparent; } + + CCPrioritizedTextureManager* contentsTextureManager() const; + + // Delete contents textures' backing resources until they use only bytesLimit bytes. This may + // be called on the impl thread while the main thread is running. + void reduceContentsTexturesMemoryOnImplThread(size_t bytesLimit, CCResourceProvider*); + // Returns true if there any evicted backing textures that have not been deleted. + bool evictedContentsTexturesBackingsExist() const; + // Retrieve the list of all contents textures' backings that have been evicted, to pass to the + // main thread to unlink them from their owning textures. + void getEvictedContentTexturesBackings(CCPrioritizedTextureManager::BackingVector&); + // Unlink the list of contents textures' backings from their owning textures on the main thread + // before updating layers. + void unlinkEvictedContentTexturesBackings(const CCPrioritizedTextureManager::BackingVector&); + // Deletes all evicted backings, unlinking them from their owning textures if needed. + // Returns true if this function had to unlink any backings from their owning texture when + // destroying them. If this was the case, the impl layer tree may contain invalid resources. + bool deleteEvictedContentTexturesBackings(); + + bool visible() const { return m_visible; } + void setVisible(bool); + + void startPageScaleAnimation(const IntSize& targetPosition, bool useAnchor, float scale, double durationSec); + + void applyScrollAndScale(const CCScrollAndScaleSet&); + void setImplTransform(const WebKit::WebTransformationMatrix&); + + void startRateLimiter(WebKit::WebGraphicsContext3D*); + void stopRateLimiter(WebKit::WebGraphicsContext3D*); + + // RateLimitClient implementation + virtual void rateLimit() OVERRIDE; + + bool bufferedUpdates(); + bool requestPartialTextureUpdate(); + void deleteTextureAfterCommit(scoped_ptr); + + void setDeviceScaleFactor(float); + float deviceScaleFactor() const { return m_deviceScaleFactor; } + + void setFontAtlas(scoped_ptr); + + HeadsUpDisplayLayerChromium* hudLayer() const { return m_hudLayer.get(); } + +protected: + CCLayerTreeHost(CCLayerTreeHostClient*, const CCLayerTreeSettings&); + bool initialize(); + +private: + typedef std::vector > LayerList; + + void initializeRenderer(); + + void update(LayerChromium*, CCTextureUpdateQueue&, const CCOcclusionTracker*); + bool paintLayerContents(const LayerList&, CCTextureUpdateQueue&); + bool paintMasksForRenderSurface(LayerChromium*, CCTextureUpdateQueue&); + + void updateLayers(LayerChromium*, CCTextureUpdateQueue&); + + void prioritizeTextures(const LayerList&, CCOverdrawMetrics&); + void setPrioritiesForSurfaces(size_t surfaceMemoryBytes); + void setPrioritiesForLayers(const LayerList&); + size_t calculateMemoryForRenderSurfaces(const LayerList& updateList); + + void animateLayers(double monotonicTime); + bool animateLayersRecursive(LayerChromium* current, double monotonicTime); + void setAnimationEventsRecursive(const CCAnimationEventsVector&, LayerChromium*, double wallClockTime); + + bool m_animating; + bool m_needsAnimateLayers; + + CCLayerTreeHostClient* m_client; + + int m_commitNumber; + CCRenderingStats m_renderingStats; + + scoped_ptr m_proxy; + bool m_rendererInitialized; + bool m_contextLost; + int m_numTimesRecreateShouldFail; + int m_numFailedRecreateAttempts; + + scoped_refptr m_rootLayer; + scoped_refptr m_hudLayer; + scoped_ptr m_fontAtlas; + + scoped_ptr m_contentsTextureManager; + scoped_ptr m_surfaceMemoryPlaceholder; + + CCLayerTreeSettings m_settings; + + IntSize m_layoutViewportSize; + IntSize m_deviceViewportSize; + float m_deviceScaleFactor; + + bool m_visible; + + typedef base::hash_map > RateLimiterMap; + RateLimiterMap m_rateLimiters; + + float m_pageScaleFactor; + float m_minPageScaleFactor, m_maxPageScaleFactor; + WebKit::WebTransformationMatrix m_implTransform; + bool m_triggerIdleUpdates; + + SkColor m_backgroundColor; + bool m_hasTransparentBackground; + + typedef ScopedPtrVector TextureList; + TextureList m_deleteTextureAfterCommitList; + size_t m_partialTextureUpdateRequests; + + static bool s_needsFilterContext; + + DISALLOW_COPY_AND_ASSIGN(CCLayerTreeHost); +}; + +} // namespace cc + +#endif diff --git a/cc/layer_tree_host_client.h b/cc/layer_tree_host_client.h index 638cbb2..1c88a75 100644 --- a/cc/layer_tree_host_client.h +++ b/cc/layer_tree_host_client.h @@ -1,3 +1,43 @@ // Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CCLayerTreeHostClient_h +#define CCLayerTreeHostClient_h + +#include "base/memory/scoped_ptr.h" + +namespace WebKit { +class WebCompositorOutputSurface; +} + +namespace cc { +class CCInputHandler; +class IntSize; + +class CCLayerTreeHostClient { +public: + virtual void willBeginFrame() = 0; + // Marks finishing compositing-related tasks on the main thread. In threaded mode, this corresponds to didCommit(). + virtual void didBeginFrame() = 0; + virtual void animate(double frameBeginTime) = 0; + virtual void layout() = 0; + virtual void applyScrollAndScale(const IntSize& scrollDelta, float pageScale) = 0; + virtual scoped_ptr createOutputSurface() = 0; + virtual void didRecreateOutputSurface(bool success) = 0; + virtual scoped_ptr createInputHandler() = 0; + virtual void willCommit() = 0; + virtual void didCommit() = 0; + virtual void didCommitAndDrawFrame() = 0; + virtual void didCompleteSwapBuffers() = 0; + + // Used only in the single-threaded path. + virtual void scheduleComposite() = 0; + +protected: + virtual ~CCLayerTreeHostClient() { } +}; + +} + +#endif // CCLayerTreeHostClient_h diff --git a/cc/layer_tree_host_common.cc b/cc/layer_tree_host_common.cc new file mode 100644 index 0000000..24274a6f --- /dev/null +++ b/cc/layer_tree_host_common.cc @@ -0,0 +1,865 @@ +// Copyright 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + +#include "config.h" + +#include "CCLayerTreeHostCommon.h" + +#include "CCLayerImpl.h" +#include "CCLayerIterator.h" +#include "CCLayerSorter.h" +#include "CCMathUtil.h" +#include "CCRenderSurface.h" +#include "FloatQuad.h" +#include "IntRect.h" +#include "LayerChromium.h" +#include "RenderSurfaceChromium.h" +#include + +using WebKit::WebTransformationMatrix; + +namespace cc { + +CCScrollAndScaleSet::CCScrollAndScaleSet() +{ +} + +CCScrollAndScaleSet::~CCScrollAndScaleSet() +{ +} + +IntRect CCLayerTreeHostCommon::calculateVisibleRect(const IntRect& targetSurfaceRect, const IntRect& layerBoundRect, const WebTransformationMatrix& transform) +{ + // Is this layer fully contained within the target surface? + IntRect layerInSurfaceSpace = CCMathUtil::mapClippedRect(transform, layerBoundRect); + if (targetSurfaceRect.contains(layerInSurfaceSpace)) + return layerBoundRect; + + // If the layer doesn't fill up the entire surface, then find the part of + // the surface rect where the layer could be visible. This avoids trying to + // project surface rect points that are behind the projection point. + IntRect minimalSurfaceRect = targetSurfaceRect; + minimalSurfaceRect.intersect(layerInSurfaceSpace); + + // Project the corners of the target surface rect into the layer space. + // This bounding rectangle may be larger than it needs to be (being + // axis-aligned), but is a reasonable filter on the space to consider. + // Non-invertible transforms will create an empty rect here. + const WebTransformationMatrix surfaceToLayer = transform.inverse(); + IntRect layerRect = enclosingIntRect(CCMathUtil::projectClippedRect(surfaceToLayer, FloatRect(minimalSurfaceRect))); + layerRect.intersect(layerBoundRect); + return layerRect; +} + +template +static inline bool layerIsInExisting3DRenderingContext(LayerType* layer) +{ + // According to current W3C spec on CSS transforms, a layer is part of an established + // 3d rendering context if its parent has transform-style of preserves-3d. + return layer->parent() && layer->parent()->preserves3D(); +} + +template +static bool layerIsRootOfNewRenderingContext(LayerType* layer) +{ + // According to current W3C spec on CSS transforms (Section 6.1), a layer is the + // beginning of 3d rendering context if its parent does not have transform-style: + // preserve-3d, but this layer itself does. + if (layer->parent()) + return !layer->parent()->preserves3D() && layer->preserves3D(); + + return layer->preserves3D(); +} + +template +static bool isLayerBackFaceVisible(LayerType* layer) +{ + // The current W3C spec on CSS transforms says that backface visibility should be + // determined differently depending on whether the layer is in a "3d rendering + // context" or not. For Chromium code, we can determine whether we are in a 3d + // rendering context by checking if the parent preserves 3d. + + if (layerIsInExisting3DRenderingContext(layer)) + return layer->drawTransform().isBackFaceVisible(); + + // In this case, either the layer establishes a new 3d rendering context, or is not in + // a 3d rendering context at all. + return layer->transform().isBackFaceVisible(); +} + +template +static bool isSurfaceBackFaceVisible(LayerType* layer, const WebTransformationMatrix& drawTransform) +{ + if (layerIsInExisting3DRenderingContext(layer)) + return drawTransform.isBackFaceVisible(); + + if (layerIsRootOfNewRenderingContext(layer)) + return layer->transform().isBackFaceVisible(); + + // If the renderSurface is not part of a new or existing rendering context, then the + // layers that contribute to this surface will decide back-face visibility for themselves. + return false; +} + +template +static inline bool layerClipsSubtree(LayerType* layer) +{ + return layer->masksToBounds() || layer->maskLayer(); +} + +template +static IntRect calculateVisibleContentRect(LayerType* layer) +{ + ASSERT(layer->renderTarget()); + + // Nothing is visible if the layer bounds are empty. + if (!layer->drawsContent() || layer->contentBounds().isEmpty() || layer->drawableContentRect().isEmpty()) + return IntRect(); + + IntRect targetSurfaceClipRect; + + // First, compute visible bounds in target surface space. + if (layer->renderTarget()->renderSurface()->clipRect().isEmpty()) + targetSurfaceClipRect = layer->drawableContentRect(); + else { + // In this case the target surface does clip layers that contribute to it. So, we + // have convert the current surface's clipRect from its ancestor surface space to + // the current surface space. + targetSurfaceClipRect = enclosingIntRect(CCMathUtil::projectClippedRect(layer->renderTarget()->renderSurface()->drawTransform().inverse(), layer->renderTarget()->renderSurface()->clipRect())); + targetSurfaceClipRect.intersect(layer->drawableContentRect()); + } + + if (targetSurfaceClipRect.isEmpty()) + return IntRect(); + + return CCLayerTreeHostCommon::calculateVisibleRect(targetSurfaceClipRect, IntRect(IntPoint(), layer->contentBounds()), layer->drawTransform()); +} + +static bool isScaleOrTranslation(const WebTransformationMatrix& m) +{ + return !m.m12() && !m.m13() && !m.m14() + && !m.m21() && !m.m23() && !m.m24() + && !m.m31() && !m.m32() && !m.m43() + && m.m44(); +} + +static inline bool transformToParentIsKnown(CCLayerImpl*) +{ + return true; +} + +static inline bool transformToParentIsKnown(LayerChromium* layer) +{ + return !layer->transformIsAnimating(); +} + +static inline bool transformToScreenIsKnown(CCLayerImpl*) +{ + return true; +} + +static inline bool transformToScreenIsKnown(LayerChromium* layer) +{ + return !layer->screenSpaceTransformIsAnimating(); +} + +template +static bool layerShouldBeSkipped(LayerType* layer) +{ + // Layers can be skipped if any of these conditions are met. + // - does not draw content. + // - is transparent + // - has empty bounds + // - the layer is not double-sided, but its back face is visible. + // + // Some additional conditions need to be computed at a later point after the recursion is finished. + // - the intersection of render surface content and layer clipRect is empty + // - the visibleContentRect is empty + // + // Note, if the layer should not have been drawn due to being fully transparent, + // we would have skipped the entire subtree and never made it into this function, + // so it is safe to omit this check here. + + if (!layer->drawsContent() || layer->bounds().isEmpty()) + return true; + + LayerType* backfaceTestLayer = layer; + if (layer->useParentBackfaceVisibility()) { + ASSERT(layer->parent()); + ASSERT(!layer->parent()->useParentBackfaceVisibility()); + backfaceTestLayer = layer->parent(); + } + + // The layer should not be drawn if (1) it is not double-sided and (2) the back of the layer is known to be facing the screen. + if (!backfaceTestLayer->doubleSided() && transformToScreenIsKnown(backfaceTestLayer) && isLayerBackFaceVisible(backfaceTestLayer)) + return true; + + return false; +} + +static inline bool subtreeShouldBeSkipped(CCLayerImpl* layer) +{ + // The opacity of a layer always applies to its children (either implicitly + // via a render surface or explicitly if the parent preserves 3D), so the + // entire subtree can be skipped if this layer is fully transparent. + return !layer->opacity(); +} + +static inline bool subtreeShouldBeSkipped(LayerChromium* layer) +{ + // If the opacity is being animated then the opacity on the main thread is unreliable + // (since the impl thread may be using a different opacity), so it should not be trusted. + // In particular, it should not cause the subtree to be skipped. + return !layer->opacity() && !layer->opacityIsAnimating(); +} + +template +static bool subtreeShouldRenderToSeparateSurface(LayerType* layer, bool axisAlignedWithRespectToParent) +{ + // The root layer has a special render surface that is set up externally, so + // it shouldn't be treated as a surface in this code. + if (!layer->parent()) + return false; + + // Cache this value, because otherwise it walks the entire subtree several times. + bool descendantDrawsContent = layer->descendantDrawsContent(); + + // + // A layer and its descendants should render onto a new RenderSurface if any of these rules hold: + // + + // If we force it. + if (layer->forceRenderSurface()) + return true; + + // If the layer uses a mask. + if (layer->maskLayer()) + return true; + + // If the layer has a reflection. + if (layer->replicaLayer()) + return true; + + // If the layer uses a CSS filter. + if (!layer->filters().isEmpty() || !layer->backgroundFilters().isEmpty()) + return true; + + // If the layer flattens its subtree (i.e. the layer doesn't preserve-3d), but it is + // treated as a 3D object by its parent (i.e. parent does preserve-3d). + if (layerIsInExisting3DRenderingContext(layer) && !layer->preserves3D() && descendantDrawsContent) + return true; + + // If the layer clips its descendants but it is not axis-aligned with respect to its parent. + if (layerClipsSubtree(layer) && !axisAlignedWithRespectToParent && descendantDrawsContent) + return true; + + // If the layer has opacity != 1 and does not have a preserves-3d transform style. + if (layer->opacity() != 1 && !layer->preserves3D() && descendantDrawsContent) + return true; + + return false; +} + +WebTransformationMatrix computeScrollCompensationForThisLayer(CCLayerImpl* scrollingLayer, const WebTransformationMatrix& parentMatrix) +{ + // For every layer that has non-zero scrollDelta, we have to compute a transform that can undo the + // scrollDelta translation. In particular, we want this matrix to premultiply a fixed-position layer's + // parentMatrix, so we design this transform in three steps as follows. The steps described here apply + // from right-to-left, so Step 1 would be the right-most matrix: + // + // Step 1. transform from target surface space to the exact space where scrollDelta is actually applied. + // -- this is inverse of the matrix in step 3 + // Step 2. undo the scrollDelta + // -- this is just a translation by scrollDelta. + // Step 3. transform back to target surface space. + // -- this transform is the "partialLayerOriginTransform" = (parentMatrix * scale(layer->pageScaleDelta())); + // + // These steps create a matrix that both start and end in targetSurfaceSpace. So this matrix can + // pre-multiply any fixed-position layer's drawTransform to undo the scrollDeltas -- as long as + // that fixed position layer is fixed onto the same renderTarget as this scrollingLayer. + // + + WebTransformationMatrix partialLayerOriginTransform = parentMatrix; + partialLayerOriginTransform.multiply(scrollingLayer->implTransform()); + + WebTransformationMatrix scrollCompensationForThisLayer = partialLayerOriginTransform; // Step 3 + scrollCompensationForThisLayer.translate(scrollingLayer->scrollDelta().width(), scrollingLayer->scrollDelta().height()); // Step 2 + scrollCompensationForThisLayer.multiply(partialLayerOriginTransform.inverse()); // Step 1 + return scrollCompensationForThisLayer; +} + +WebTransformationMatrix computeScrollCompensationMatrixForChildren(LayerChromium* currentLayer, const WebTransformationMatrix& currentParentMatrix, const WebTransformationMatrix& currentScrollCompensation) +{ + // The main thread (i.e. LayerChromium) does not need to worry about scroll compensation. + // So we can just return an identity matrix here. + return WebTransformationMatrix(); +} + +WebTransformationMatrix computeScrollCompensationMatrixForChildren(CCLayerImpl* layer, const WebTransformationMatrix& parentMatrix, const WebTransformationMatrix& currentScrollCompensationMatrix) +{ + // "Total scroll compensation" is the transform needed to cancel out all scrollDelta translations that + // occurred since the nearest container layer, even if there are renderSurfaces in-between. + // + // There are some edge cases to be aware of, that are not explicit in the code: + // - A layer that is both a fixed-position and container should not be its own container, instead, that means + // it is fixed to an ancestor, and is a container for any fixed-position descendants. + // - A layer that is a fixed-position container and has a renderSurface should behave the same as a container + // without a renderSurface, the renderSurface is irrelevant in that case. + // - A layer that does not have an explicit container is simply fixed to the viewport + // (i.e. the root renderSurface, and it would still compensate for root layer's scrollDelta). + // - If the fixed-position layer has its own renderSurface, then the renderSurface is + // the one who gets fixed. + // + // This function needs to be called AFTER layers create their own renderSurfaces. + // + + // Avoid the overheads (including stack allocation and matrix initialization/copy) if we know that the scroll compensation doesn't need to be reset or adjusted. + if (!layer->isContainerForFixedPositionLayers() && layer->scrollDelta().isZero() && !layer->renderSurface()) + return currentScrollCompensationMatrix; + + // Start as identity matrix. + WebTransformationMatrix nextScrollCompensationMatrix; + + // If this layer is not a container, then it inherits the existing scroll compensations. + if (!layer->isContainerForFixedPositionLayers()) + nextScrollCompensationMatrix = currentScrollCompensationMatrix; + + // If the current layer has a non-zero scrollDelta, then we should compute its local scrollCompensation + // and accumulate it to the nextScrollCompensationMatrix. + if (!layer->scrollDelta().isZero()) { + WebTransformationMatrix scrollCompensationForThisLayer = computeScrollCompensationForThisLayer(layer, parentMatrix); + nextScrollCompensationMatrix.multiply(scrollCompensationForThisLayer); + } + + // If the layer created its own renderSurface, we have to adjust nextScrollCompensationMatrix. + // The adjustment allows us to continue using the scrollCompensation on the next surface. + // Step 1 (right-most in the math): transform from the new surface to the original ancestor surface + // Step 2: apply the scroll compensation + // Step 3: transform back to the new surface. + if (layer->renderSurface() && !nextScrollCompensationMatrix.isIdentity()) + nextScrollCompensationMatrix = layer->renderSurface()->drawTransform().inverse() * nextScrollCompensationMatrix * layer->renderSurface()->drawTransform(); + + return nextScrollCompensationMatrix; +} + +// Should be called just before the recursive calculateDrawTransformsInternal(). +template +void setupRootLayerAndSurfaceForRecursion(LayerType* rootLayer, LayerList& renderSurfaceLayerList, const IntSize& deviceViewportSize) +{ + if (!rootLayer->renderSurface()) + rootLayer->createRenderSurface(); + + rootLayer->renderSurface()->setContentRect(IntRect(IntPoint::zero(), deviceViewportSize)); + rootLayer->renderSurface()->clearLayerLists(); + + ASSERT(renderSurfaceLayerList.empty()); + renderSurfaceLayerList.push_back(rootLayer); +} + +// Recursively walks the layer tree starting at the given node and computes all the +// necessary transformations, clipRects, render surfaces, etc. +template +static void calculateDrawTransformsInternal(LayerType* layer, LayerType* rootLayer, const WebTransformationMatrix& parentMatrix, + const WebTransformationMatrix& fullHierarchyMatrix, const WebTransformationMatrix& currentScrollCompensationMatrix, + const IntRect& clipRectFromAncestor, bool ancestorClipsSubtree, + RenderSurfaceType* nearestAncestorThatMovesPixels, LayerList& renderSurfaceLayerList, LayerList& layerList, + LayerSorter* layerSorter, int maxTextureSize, float deviceScaleFactor, IntRect& drawableContentRectOfSubtree) +{ + // This function computes the new matrix transformations recursively for this + // layer and all its descendants. It also computes the appropriate render surfaces. + // Some important points to remember: + // + // 0. Here, transforms are notated in Matrix x Vector order, and in words we describe what + // the transform does from left to right. + // + // 1. In our terminology, the "layer origin" refers to the top-left corner of a layer, and the + // positive Y-axis points downwards. This interpretation is valid because the orthographic + // projection applied at draw time flips the Y axis appropriately. + // + // 2. The anchor point, when given as a FloatPoint object, is specified in "unit layer space", + // where the bounds of the layer map to [0, 1]. However, as a WebTransformationMatrix object, + // the transform to the anchor point is specified in "layer space", where the bounds + // of the layer map to [bounds.width(), bounds.height()]. + // + // 3. Definition of various transforms used: + // M[parent] is the parent matrix, with respect to the nearest render surface, passed down recursively. + // M[root] is the full hierarchy, with respect to the root, passed down recursively. + // Tr[origin] is the translation matrix from the parent's origin to this layer's origin. + // Tr[origin2anchor] is the translation from the layer's origin to its anchor point + // Tr[origin2center] is the translation from the layer's origin to its center + // M[layer] is the layer's matrix (applied at the anchor point) + // M[sublayer] is the layer's sublayer transform (applied at the layer's center) + // S[layer2content] is the ratio of a layer's contentBounds() to its bounds(). + // + // Some composite transforms can help in understanding the sequence of transforms: + // compositeLayerTransform = Tr[origin2anchor] * M[layer] * Tr[origin2anchor].inverse() + // compositeSublayerTransform = Tr[origin2center] * M[sublayer] * Tr[origin2center].inverse() + // + // In words, the layer transform is applied about the anchor point, and the sublayer transform is + // applied about the center of the layer. + // + // 4. When a layer (or render surface) is drawn, it is drawn into a "target render surface". Therefore the draw + // transform does not necessarily transform from screen space to local layer space. Instead, the draw transform + // is the transform between the "target render surface space" and local layer space. Note that render surfaces, + // except for the root, also draw themselves into a different target render surface, and so their draw + // transform and origin transforms are also described with respect to the target. + // + // Using these definitions, then: + // + // The draw transform for the layer is: + // M[draw] = M[parent] * Tr[origin] * compositeLayerTransform * S[layer2content] + // = M[parent] * Tr[layer->position() + anchor] * M[layer] * Tr[anchor2origin] * S[layer2content] + // + // Interpreting the math left-to-right, this transforms from the layer's render surface to the origin of the layer in content space. + // + // The screen space transform is: + // M[screenspace] = M[root] * Tr[origin] * compositeLayerTransform * S[layer2content] + // = M[root] * Tr[layer->position() + anchor] * M[layer] * Tr[anchor2origin] * S[layer2content] + // + // Interpreting the math left-to-right, this transforms from the root render surface's content space to the local layer's origin in layer space. + // + // The transform hierarchy that is passed on to children (i.e. the child's parentMatrix) is: + // M[parent]_for_child = M[parent] * Tr[origin] * compositeLayerTransform * compositeSublayerTransform + // = M[parent] * Tr[layer->position() + anchor] * M[layer] * Tr[anchor2origin] * compositeSublayerTransform + // + // and a similar matrix for the full hierarchy with respect to the root. + // + // Finally, note that the final matrix used by the shader for the layer is P * M[draw] * S . This final product + // is computed in drawTexturedQuad(), where: + // P is the projection matrix + // S is the scale adjustment (to scale up a canonical quad to the layer's size) + // + // When a render surface has a replica layer, that layer's transform is used to draw a second copy of the surface. + // Transforms named here are relative to the surface, unless they specify they are relative to the replica layer. + // + // We will denote a scale by device scale S[deviceScale] + // + // The render surface draw transform to its target surface origin is: + // M[surfaceDraw] = M[owningLayer->Draw] + // + // The render surface origin transform to its the root (screen space) origin is: + // M[surface2root] = M[owningLayer->screenspace] * S[deviceScale].inverse() + // + // The replica draw transform to its target surface origin is: + // M[replicaDraw] = S[deviceScale] * M[surfaceDraw] * Tr[replica->position() + replica->anchor()] * Tr[replica] * Tr[origin2anchor].inverse() * S[contentsScale].inverse() + // + // The replica draw transform to the root (screen space) origin is: + // M[replica2root] = M[surface2root] * Tr[replica->position()] * Tr[replica] * Tr[origin2anchor].inverse() + // + + // If we early-exit anywhere in this function, the drawableContentRect of this subtree should be considered empty. + drawableContentRectOfSubtree = IntRect(); + + if (subtreeShouldBeSkipped(layer)) + return; + + IntRect clipRectForSubtree; + bool subtreeShouldBeClipped = false; + + float drawOpacity = layer->opacity(); + bool drawOpacityIsAnimating = layer->opacityIsAnimating(); + if (layer->parent() && layer->parent()->preserves3D()) { + drawOpacity *= layer->parent()->drawOpacity(); + drawOpacityIsAnimating |= layer->parent()->drawOpacityIsAnimating(); + } + + IntSize bounds = layer->bounds(); + FloatPoint anchorPoint = layer->anchorPoint(); + FloatPoint position = layer->position() - layer->scrollDelta(); + + WebTransformationMatrix layerLocalTransform; + // LT = M[impl transformation] + layerLocalTransform.multiply(layer->implTransform()); + // LT = M[impl transformation] * Tr[origin] * Tr[origin2anchor] + layerLocalTransform.translate3d(position.x() + anchorPoint.x() * bounds.width(), position.y() + anchorPoint.y() * bounds.height(), layer->anchorPointZ()); + // LT = M[impl transformation] * Tr[origin] * Tr[origin2anchor] * M[layer] + layerLocalTransform.multiply(layer->transform()); + // LT = S[impl transformation] * Tr[origin] * Tr[origin2anchor] * M[layer] * Tr[anchor2origin] + layerLocalTransform.translate3d(-anchorPoint.x() * bounds.width(), -anchorPoint.y() * bounds.height(), -layer->anchorPointZ()); + + WebTransformationMatrix combinedTransform = parentMatrix; + combinedTransform.multiply(layerLocalTransform); + + if (layer->fixedToContainerLayer()) { + // Special case: this layer is a composited fixed-position layer; we need to + // explicitly compensate for all ancestors' nonzero scrollDeltas to keep this layer + // fixed correctly. + combinedTransform = currentScrollCompensationMatrix * combinedTransform; + } + + // The drawTransform that gets computed below is effectively the layer's drawTransform, unless + // the layer itself creates a renderSurface. In that case, the renderSurface re-parents the transforms. + WebTransformationMatrix drawTransform = combinedTransform; + if (!layer->contentBounds().isEmpty() && !layer->bounds().isEmpty()) { + // M[draw] = M[parent] * LT * S[layer2content] + drawTransform.scaleNonUniform(layer->bounds().width() / static_cast(layer->contentBounds().width()), + layer->bounds().height() / static_cast(layer->contentBounds().height())); + } + + // layerScreenSpaceTransform represents the transform between root layer's "screen space" and local content space. + WebTransformationMatrix layerScreenSpaceTransform = fullHierarchyMatrix; + if (!layer->preserves3D()) + CCMathUtil::flattenTransformTo2d(layerScreenSpaceTransform); + layerScreenSpaceTransform.multiply(drawTransform); + layer->setScreenSpaceTransform(layerScreenSpaceTransform); + + bool animatingTransformToTarget = layer->transformIsAnimating(); + bool animatingTransformToScreen = animatingTransformToTarget; + if (layer->parent()) { + animatingTransformToTarget |= layer->parent()->drawTransformIsAnimating(); + animatingTransformToScreen |= layer->parent()->screenSpaceTransformIsAnimating(); + } + + FloatRect contentRect(FloatPoint(), layer->contentBounds()); + + // fullHierarchyMatrix is the matrix that transforms objects between screen space (except projection matrix) and the most recent RenderSurface's space. + // nextHierarchyMatrix will only change if this layer uses a new RenderSurface, otherwise remains the same. + WebTransformationMatrix nextHierarchyMatrix = fullHierarchyMatrix; + WebTransformationMatrix sublayerMatrix; + + if (subtreeShouldRenderToSeparateSurface(layer, isScaleOrTranslation(combinedTransform))) { + // Check back-face visibility before continuing with this surface and its subtree + if (!layer->doubleSided() && transformToParentIsKnown(layer) && isSurfaceBackFaceVisible(layer, combinedTransform)) + return; + + if (!layer->renderSurface()) + layer->createRenderSurface(); + + RenderSurfaceType* renderSurface = layer->renderSurface(); + renderSurface->clearLayerLists(); + + // The origin of the new surface is the upper left corner of the layer. + renderSurface->setDrawTransform(drawTransform); + WebTransformationMatrix layerDrawTransform; + layerDrawTransform.scale(deviceScaleFactor); + if (!layer->contentBounds().isEmpty() && !layer->bounds().isEmpty()) { + layerDrawTransform.scaleNonUniform(layer->bounds().width() / static_cast(layer->contentBounds().width()), + layer->bounds().height() / static_cast(layer->contentBounds().height())); + } + layer->setDrawTransform(layerDrawTransform); + + // The sublayer matrix transforms centered layer rects into target + // surface content space. + sublayerMatrix.makeIdentity(); + sublayerMatrix.scale(deviceScaleFactor); + + // The opacity value is moved from the layer to its surface, so that the entire subtree properly inherits opacity. + renderSurface->setDrawOpacity(drawOpacity); + renderSurface->setDrawOpacityIsAnimating(drawOpacityIsAnimating); + layer->setDrawOpacity(1); + layer->setDrawOpacityIsAnimating(false); + + renderSurface->setTargetSurfaceTransformsAreAnimating(animatingTransformToTarget); + renderSurface->setScreenSpaceTransformsAreAnimating(animatingTransformToScreen); + animatingTransformToTarget = false; + layer->setDrawTransformIsAnimating(animatingTransformToTarget); + layer->setScreenSpaceTransformIsAnimating(animatingTransformToScreen); + + // Update the aggregate hierarchy matrix to include the transform of the + // newly created RenderSurface. + nextHierarchyMatrix.multiply(renderSurface->drawTransform()); + + // The new renderSurface here will correctly clip the entire subtree. So, we do + // not need to continue propagating the clipping state further down the tree. This + // way, we can avoid transforming clipRects from ancestor target surface space to + // current target surface space that could cause more w < 0 headaches. + subtreeShouldBeClipped = false; + + if (layer->maskLayer()) { + layer->maskLayer()->setRenderTarget(layer); + layer->maskLayer()->setVisibleContentRect(IntRect(IntPoint(), layer->contentBounds())); + } + + if (layer->replicaLayer() && layer->replicaLayer()->maskLayer()) { + layer->replicaLayer()->maskLayer()->setRenderTarget(layer); + layer->replicaLayer()->maskLayer()->setVisibleContentRect(IntRect(IntPoint(), layer->contentBounds())); + } + + if (layer->filters().hasFilterThatMovesPixels()) + nearestAncestorThatMovesPixels = renderSurface; + + // The render surface clipRect is expressed in the space where this surface draws, i.e. the same space as clipRectFromAncestor. + if (ancestorClipsSubtree) + renderSurface->setClipRect(clipRectFromAncestor); + else + renderSurface->setClipRect(IntRect()); + + renderSurface->setNearestAncestorThatMovesPixels(nearestAncestorThatMovesPixels); + + renderSurfaceLayerList.push_back(layer); + } else { + layer->setDrawTransform(drawTransform); + layer->setDrawTransformIsAnimating(animatingTransformToTarget); + layer->setScreenSpaceTransformIsAnimating(animatingTransformToScreen); + sublayerMatrix = combinedTransform; + + layer->setDrawOpacity(drawOpacity); + layer->setDrawOpacityIsAnimating(drawOpacityIsAnimating); + + if (layer != rootLayer) { + ASSERT(layer->parent()); + layer->clearRenderSurface(); + + // Layers without renderSurfaces directly inherit the ancestor's clip status. + subtreeShouldBeClipped = ancestorClipsSubtree; + if (ancestorClipsSubtree) + clipRectForSubtree = clipRectFromAncestor; + + // Layers that are not their own renderTarget will render into the target of their nearest ancestor. + layer->setRenderTarget(layer->parent()->renderTarget()); + } else { + // FIXME: This root layer special case code should eventually go away. https://bugs.webkit.org/show_bug.cgi?id=92290 + ASSERT(!layer->parent()); + ASSERT(layer->renderSurface()); + ASSERT(ancestorClipsSubtree); + layer->renderSurface()->setClipRect(clipRectFromAncestor); + subtreeShouldBeClipped = false; + } + } + + IntRect rectInTargetSpace = enclosingIntRect(CCMathUtil::mapClippedRect(layer->drawTransform(), contentRect)); + + if (layerClipsSubtree(layer)) { + subtreeShouldBeClipped = true; + if (ancestorClipsSubtree && !layer->renderSurface()) { + clipRectForSubtree = clipRectFromAncestor; + clipRectForSubtree.intersect(rectInTargetSpace); + } else + clipRectForSubtree = rectInTargetSpace; + } + + // Flatten to 2D if the layer doesn't preserve 3D. + if (!layer->preserves3D()) + CCMathUtil::flattenTransformTo2d(sublayerMatrix); + + // Apply the sublayer transform at the center of the layer. + sublayerMatrix.translate(0.5 * bounds.width(), 0.5 * bounds.height()); + sublayerMatrix.multiply(layer->sublayerTransform()); + sublayerMatrix.translate(-0.5 * bounds.width(), -0.5 * bounds.height()); + + LayerList& descendants = (layer->renderSurface() ? layer->renderSurface()->layerList() : layerList); + + // Any layers that are appended after this point are in the layer's subtree and should be included in the sorting process. + unsigned sortingStartIndex = descendants.size(); + + if (!layerShouldBeSkipped(layer)) + descendants.push_back(layer); + + WebTransformationMatrix nextScrollCompensationMatrix = computeScrollCompensationMatrixForChildren(layer, parentMatrix, currentScrollCompensationMatrix);; + + IntRect accumulatedDrawableContentRectOfChildren; + for (size_t i = 0; i < layer->children().size(); ++i) { + LayerType* child = CCLayerTreeHostCommon::getChildAsRawPtr(layer->children(), i); + IntRect drawableContentRectOfChildSubtree; + calculateDrawTransformsInternal(child, rootLayer, sublayerMatrix, nextHierarchyMatrix, nextScrollCompensationMatrix, + clipRectForSubtree, subtreeShouldBeClipped, nearestAncestorThatMovesPixels, + renderSurfaceLayerList, descendants, layerSorter, maxTextureSize, deviceScaleFactor, drawableContentRectOfChildSubtree); + if (!drawableContentRectOfChildSubtree.isEmpty()) { + accumulatedDrawableContentRectOfChildren.unite(drawableContentRectOfChildSubtree); + if (child->renderSurface()) + descendants.push_back(child); + } + } + + // Compute the total drawableContentRect for this subtree (the rect is in targetSurface space) + IntRect localDrawableContentRectOfSubtree = accumulatedDrawableContentRectOfChildren; + if (layer->drawsContent()) + localDrawableContentRectOfSubtree.unite(rectInTargetSpace); + if (subtreeShouldBeClipped) + localDrawableContentRectOfSubtree.intersect(clipRectForSubtree); + + // Compute the layer's drawable content rect (the rect is in targetSurface space) + IntRect drawableContentRectOfLayer = rectInTargetSpace; + if (subtreeShouldBeClipped) + drawableContentRectOfLayer.intersect(clipRectForSubtree); + layer->setDrawableContentRect(drawableContentRectOfLayer); + + // Compute the layer's visible content rect (the rect is in content space) + IntRect visibleContentRectOfLayer = calculateVisibleContentRect(layer); + layer->setVisibleContentRect(visibleContentRectOfLayer); + + // Compute the remaining properties for the render surface, if the layer has one. + if (layer->renderSurface() && layer != rootLayer) { + RenderSurfaceType* renderSurface = layer->renderSurface(); + IntRect clippedContentRect = localDrawableContentRectOfSubtree; + + // Don't clip if the layer is reflected as the reflection shouldn't be + // clipped. If the layer is animating, then the surface's transform to + // its target is not known on the main thread, and we should not use it + // to clip. + if (!layer->replicaLayer() && transformToParentIsKnown(layer)) { + // Note, it is correct to use ancestorClipsSubtree here, because we are looking at this layer's renderSurface, not the layer itself. + if (ancestorClipsSubtree && !clippedContentRect.isEmpty()) { + IntRect surfaceClipRect = CCLayerTreeHostCommon::calculateVisibleRect(renderSurface->clipRect(), clippedContentRect, renderSurface->drawTransform()); + clippedContentRect.intersect(surfaceClipRect); + } + } + + // The RenderSurface backing texture cannot exceed the maximum supported + // texture size. + clippedContentRect.setWidth(std::min(clippedContentRect.width(), maxTextureSize)); + clippedContentRect.setHeight(std::min(clippedContentRect.height(), maxTextureSize)); + + if (clippedContentRect.isEmpty()) + renderSurface->clearLayerLists(); + + renderSurface->setContentRect(clippedContentRect); + renderSurface->setScreenSpaceTransform(layer->screenSpaceTransform()); + + if (layer->replicaLayer()) { + WebTransformationMatrix surfaceOriginToReplicaOriginTransform; + surfaceOriginToReplicaOriginTransform.scale(deviceScaleFactor); + surfaceOriginToReplicaOriginTransform.translate(layer->replicaLayer()->position().x() + layer->replicaLayer()->anchorPoint().x() * bounds.width(), + layer->replicaLayer()->position().y() + layer->replicaLayer()->anchorPoint().y() * bounds.height()); + surfaceOriginToReplicaOriginTransform.multiply(layer->replicaLayer()->transform()); + surfaceOriginToReplicaOriginTransform.translate(-layer->replicaLayer()->anchorPoint().x() * bounds.width(), -layer->replicaLayer()->anchorPoint().y() * bounds.height()); + surfaceOriginToReplicaOriginTransform.scale(1 / deviceScaleFactor); + + // Compute the replica's "originTransform" that maps from the replica's origin space to the target surface origin space. + WebTransformationMatrix replicaOriginTransform = layer->renderSurface()->drawTransform() * surfaceOriginToReplicaOriginTransform; + renderSurface->setReplicaDrawTransform(replicaOriginTransform); + + // Compute the replica's "screenSpaceTransform" that maps from the replica's origin space to the screen's origin space. + WebTransformationMatrix replicaScreenSpaceTransform = layer->renderSurface()->screenSpaceTransform() * surfaceOriginToReplicaOriginTransform; + renderSurface->setReplicaScreenSpaceTransform(replicaScreenSpaceTransform); + } + + // If a render surface has no layer list, then it and none of its children needed to get drawn. + if (!layer->renderSurface()->layerList().size()) { + // FIXME: Originally we asserted that this layer was already at the end of the + // list, and only needed to remove that layer. For now, we remove the + // entire subtree of surfaces to fix a crash bug. The root cause is + // https://bugs.webkit.org/show_bug.cgi?id=74147 and we should be able + // to put the original assert after fixing that. + while (renderSurfaceLayerList.back() != layer) { + renderSurfaceLayerList.back()->clearRenderSurface(); + renderSurfaceLayerList.pop_back(); + } + ASSERT(renderSurfaceLayerList.back() == layer); + renderSurfaceLayerList.pop_back(); + layer->clearRenderSurface(); + return; + } + } + + // If neither this layer nor any of its children were added, early out. + if (sortingStartIndex == descendants.size()) + return; + + // If preserves-3d then sort all the descendants in 3D so that they can be + // drawn from back to front. If the preserves-3d property is also set on the parent then + // skip the sorting as the parent will sort all the descendants anyway. + if (descendants.size() && layer->preserves3D() && (!layer->parent() || !layer->parent()->preserves3D())) + sortLayers(descendants.begin() + sortingStartIndex, descendants.end(), layerSorter); + + if (layer->renderSurface()) + drawableContentRectOfSubtree = enclosingIntRect(layer->renderSurface()->drawableContentRect()); + else + drawableContentRectOfSubtree = localDrawableContentRectOfSubtree; + + if (layer->hasContributingDelegatedRenderPasses()) + layer->renderTarget()->renderSurface()->addContributingDelegatedRenderPassLayer(layer); +} + +void CCLayerTreeHostCommon::calculateDrawTransforms(LayerChromium* rootLayer, const IntSize& deviceViewportSize, float deviceScaleFactor, int maxTextureSize, std::vector >& renderSurfaceLayerList) +{ + IntRect totalDrawableContentRect; + WebTransformationMatrix identityMatrix; + WebTransformationMatrix deviceScaleTransform; + deviceScaleTransform.scale(deviceScaleFactor); + + setupRootLayerAndSurfaceForRecursion > >(rootLayer, renderSurfaceLayerList, deviceViewportSize); + + cc::calculateDrawTransformsInternal >, RenderSurfaceChromium, void>(rootLayer, rootLayer, deviceScaleTransform, identityMatrix, identityMatrix, + rootLayer->renderSurface()->contentRect(), true, 0, renderSurfaceLayerList, + rootLayer->renderSurface()->layerList(), 0, maxTextureSize, deviceScaleFactor, totalDrawableContentRect); +} + +void CCLayerTreeHostCommon::calculateDrawTransforms(CCLayerImpl* rootLayer, const IntSize& deviceViewportSize, float deviceScaleFactor, CCLayerSorter* layerSorter, int maxTextureSize, std::vector& renderSurfaceLayerList) +{ + IntRect totalDrawableContentRect; + WebTransformationMatrix identityMatrix; + WebTransformationMatrix deviceScaleTransform; + deviceScaleTransform.scale(deviceScaleFactor); + + setupRootLayerAndSurfaceForRecursion >(rootLayer, renderSurfaceLayerList, deviceViewportSize); + + cc::calculateDrawTransformsInternal, CCRenderSurface, CCLayerSorter>(rootLayer, rootLayer, deviceScaleTransform, identityMatrix, identityMatrix, + rootLayer->renderSurface()->contentRect(), true, 0, renderSurfaceLayerList, + rootLayer->renderSurface()->layerList(), layerSorter, maxTextureSize, deviceScaleFactor, totalDrawableContentRect); +} + +static bool pointHitsRect(const IntPoint& viewportPoint, const WebTransformationMatrix& localSpaceToScreenSpaceTransform, FloatRect localSpaceRect) +{ + // If the transform is not invertible, then assume that this point doesn't hit this rect. + if (!localSpaceToScreenSpaceTransform.isInvertible()) + return false; + + // Transform the hit test point from screen space to the local space of the given rect. + bool clipped = false; + FloatPoint hitTestPointInLocalSpace = CCMathUtil::projectPoint(localSpaceToScreenSpaceTransform.inverse(), FloatPoint(viewportPoint), clipped); + + // If projectPoint could not project to a valid value, then we assume that this point doesn't hit this rect. + if (clipped) + return false; + + return localSpaceRect.contains(hitTestPointInLocalSpace); +} + +static bool pointIsClippedBySurfaceOrClipRect(const IntPoint& viewportPoint, CCLayerImpl* layer) +{ + CCLayerImpl* currentLayer = layer; + + // Walk up the layer tree and hit-test any renderSurfaces and any layer clipRects that are active. + while (currentLayer) { + if (currentLayer->renderSurface() && !pointHitsRect(viewportPoint, currentLayer->renderSurface()->screenSpaceTransform(), currentLayer->renderSurface()->contentRect())) + return true; + + // Note that drawableContentRects are actually in targetSurface space, so the transform we + // have to provide is the target surface's screenSpaceTransform. + CCLayerImpl* renderTarget = currentLayer->renderTarget(); + if (layerClipsSubtree(currentLayer) && !pointHitsRect(viewportPoint, renderTarget->renderSurface()->screenSpaceTransform(), currentLayer->drawableContentRect())) + return true; + + currentLayer = currentLayer->parent(); + } + + // If we have finished walking all ancestors without having already exited, then the point is not clipped by any ancestors. + return false; +} + +CCLayerImpl* CCLayerTreeHostCommon::findLayerThatIsHitByPoint(const IntPoint& viewportPoint, std::vector& renderSurfaceLayerList) +{ + CCLayerImpl* foundLayer = 0; + + typedef CCLayerIterator, CCRenderSurface, CCLayerIteratorActions::FrontToBack> CCLayerIteratorType; + CCLayerIteratorType end = CCLayerIteratorType::end(&renderSurfaceLayerList); + + for (CCLayerIteratorType it = CCLayerIteratorType::begin(&renderSurfaceLayerList); it != end; ++it) { + // We don't want to consider renderSurfaces for hit testing. + if (!it.representsItself()) + continue; + + CCLayerImpl* currentLayer = (*it); + + FloatRect contentRect(FloatPoint::zero(), currentLayer->contentBounds()); + if (!pointHitsRect(viewportPoint, currentLayer->screenSpaceTransform(), contentRect)) + continue; + + // At this point, we think the point does hit the layer, but we need to walk up + // the parents to ensure that the layer was not clipped in such a way that the + // hit point actually should not hit the layer. + if (pointIsClippedBySurfaceOrClipRect(viewportPoint, currentLayer)) + continue; + + foundLayer = currentLayer; + break; + } + + // This can potentially return 0, which means the viewportPoint did not successfully hit test any layers, not even the root layer. + return foundLayer; +} + +} // namespace cc diff --git a/cc/layer_tree_host_common.h b/cc/layer_tree_host_common.h index 638cbb2..01dc41e 100644 --- a/cc/layer_tree_host_common.h +++ b/cc/layer_tree_host_common.h @@ -1,3 +1,96 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. +// Copyright 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CCLayerTreeHostCommon_h +#define CCLayerTreeHostCommon_h + +#include "base/memory/ref_counted.h" +#include "cc/scoped_ptr_vector.h" +#include "IntRect.h" +#include "IntSize.h" +#include +#include + +namespace cc { + +class CCLayerImpl; +class CCLayerSorter; +class LayerChromium; + +class CCLayerTreeHostCommon { +public: + static IntRect calculateVisibleRect(const IntRect& targetSurfaceRect, const IntRect& layerBoundRect, const WebKit::WebTransformationMatrix&); + + static void calculateDrawTransforms(LayerChromium* rootLayer, const IntSize& deviceViewportSize, float deviceScaleFactor, int maxTextureSize, std::vector >& renderSurfaceLayerList); + static void calculateDrawTransforms(CCLayerImpl* rootLayer, const IntSize& deviceViewportSize, float deviceScaleFactor, CCLayerSorter*, int maxTextureSize, std::vector& renderSurfaceLayerList); + + // Performs hit testing for a given renderSurfaceLayerList. + static CCLayerImpl* findLayerThatIsHitByPoint(const IntPoint& viewportPoint, std::vector& renderSurfaceLayerList); + + template static bool renderSurfaceContributesToTarget(LayerType*, int targetSurfaceLayerID); + + // Returns a layer with the given id if one exists in the subtree starting + // from the given root layer (including mask and replica layers). + template static LayerType* findLayerInSubtree(LayerType* rootLayer, int layerId); + + static LayerChromium* getChildAsRawPtr(const std::vector >& children, size_t index) + { + return children[index].get(); + } + + static CCLayerImpl* getChildAsRawPtr(const ScopedPtrVector& children, size_t index) + { + return children[index]; + } + + struct ScrollUpdateInfo { + int layerId; + IntSize scrollDelta; + }; +}; + +struct CCScrollAndScaleSet { + CCScrollAndScaleSet(); + ~CCScrollAndScaleSet(); + + Vector scrolls; + float pageScaleDelta; +}; + +template +bool CCLayerTreeHostCommon::renderSurfaceContributesToTarget(LayerType* layer, int targetSurfaceLayerID) +{ + // A layer will either contribute its own content, or its render surface's content, to + // the target surface. The layer contributes its surface's content when both the + // following are true: + // (1) The layer actually has a renderSurface, and + // (2) The layer's renderSurface is not the same as the targetSurface. + // + // Otherwise, the layer just contributes itself to the target surface. + + return layer->renderSurface() && layer->id() != targetSurfaceLayerID; +} + +template +LayerType* CCLayerTreeHostCommon::findLayerInSubtree(LayerType* rootLayer, int layerId) +{ + if (rootLayer->id() == layerId) + return rootLayer; + + if (rootLayer->maskLayer() && rootLayer->maskLayer()->id() == layerId) + return rootLayer->maskLayer(); + + if (rootLayer->replicaLayer() && rootLayer->replicaLayer()->id() == layerId) + return rootLayer->replicaLayer(); + + for (size_t i = 0; i < rootLayer->children().size(); ++i) { + if (LayerType* found = findLayerInSubtree(getChildAsRawPtr(rootLayer->children(), i), layerId)) + return found; + } + return 0; +} + +} // namespace cc + +#endif diff --git a/cc/layer_tree_host_impl.cc b/cc/layer_tree_host_impl.cc new file mode 100644 index 0000000..bc50697 --- /dev/null +++ b/cc/layer_tree_host_impl.cc @@ -0,0 +1,1462 @@ +// Copyright 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#include "CCLayerTreeHostImpl.h" + +#include "base/basictypes.h" +#include "CCAppendQuadsData.h" +#include "CCDamageTracker.h" +#include "CCDebugRectHistory.h" +#include "CCDelayBasedTimeSource.h" +#include "CCFontAtlas.h" +#include "CCFrameRateCounter.h" +#include "CCHeadsUpDisplayLayerImpl.h" +#include "CCLayerIterator.h" +#include "CCLayerTreeHost.h" +#include "CCLayerTreeHostCommon.h" +#include "CCMathUtil.h" +#include "CCOverdrawMetrics.h" +#include "CCPageScaleAnimation.h" +#include "CCPrioritizedTextureManager.h" +#include "CCRenderPassDrawQuad.h" +#include "CCRendererGL.h" +#include "CCRendererSoftware.h" +#include "CCRenderingStats.h" +#include "CCScrollbarAnimationController.h" +#include "CCScrollbarLayerImpl.h" +#include "CCSettings.h" +#include "CCSingleThreadProxy.h" +#include "TextureUploader.h" +#include "TraceEvent.h" +#include +#include + +using WebKit::WebTransformationMatrix; + +namespace { + +void didVisibilityChange(cc::CCLayerTreeHostImpl* id, bool visible) +{ + if (visible) { + TRACE_EVENT_ASYNC_BEGIN1("webkit", "CCLayerTreeHostImpl::setVisible", id, "CCLayerTreeHostImpl", id); + return; + } + + TRACE_EVENT_ASYNC_END0("webkit", "CCLayerTreeHostImpl::setVisible", id); +} + +} // namespace + +namespace cc { + +CCPinchZoomViewport::CCPinchZoomViewport() + : m_pageScaleFactor(1) + , m_pageScaleDelta(1) + , m_sentPageScaleDelta(1) + , m_minPageScaleFactor(0) + , m_maxPageScaleFactor(0) +{ +} + +float CCPinchZoomViewport::totalPageScaleFactor() const +{ + return m_pageScaleFactor * m_pageScaleDelta; +} + +void CCPinchZoomViewport::setPageScaleDelta(float delta) +{ + // Clamp to the current min/max limits. + float totalPageScaleFactor = m_pageScaleFactor * delta; + if (m_minPageScaleFactor && totalPageScaleFactor < m_minPageScaleFactor) + delta = m_minPageScaleFactor / m_pageScaleFactor; + else if (m_maxPageScaleFactor && totalPageScaleFactor > m_maxPageScaleFactor) + delta = m_maxPageScaleFactor / m_pageScaleFactor; + + if (delta == m_pageScaleDelta) + return; + + m_pageScaleDelta = delta; +} + +bool CCPinchZoomViewport::setPageScaleFactorAndLimits(float pageScaleFactor, float minPageScaleFactor, float maxPageScaleFactor) +{ + ASSERT(pageScaleFactor); + + if (m_sentPageScaleDelta == 1 && pageScaleFactor == m_pageScaleFactor && minPageScaleFactor == m_minPageScaleFactor && maxPageScaleFactor == m_maxPageScaleFactor) + return false; + + m_minPageScaleFactor = minPageScaleFactor; + m_maxPageScaleFactor = maxPageScaleFactor; + + m_pageScaleFactor = pageScaleFactor; + return true; +} + +FloatRect CCPinchZoomViewport::bounds() const +{ + FloatSize scaledViewportSize = m_layoutViewportSize; + scaledViewportSize.scale(1 / totalPageScaleFactor()); + + FloatRect bounds(FloatPoint(0, 0), scaledViewportSize); + bounds.setLocation(m_pinchViewportScrollDelta); + + return bounds; +} + +FloatSize CCPinchZoomViewport::applyScroll(FloatSize& delta) +{ + FloatSize overflow; + FloatRect pinchedBounds = bounds(); + + pinchedBounds.move(delta); + if (pinchedBounds.x() < 0) { + overflow.setWidth(pinchedBounds.x()); + pinchedBounds.setX(0); + } + + if (pinchedBounds.y() < 0) { + overflow.setHeight(pinchedBounds.y()); + pinchedBounds.setY(0); + } + + if (pinchedBounds.maxX() > m_layoutViewportSize.width()) { + overflow.setWidth( + pinchedBounds.maxX() - m_layoutViewportSize.width()); + pinchedBounds.move( + m_layoutViewportSize.width() - pinchedBounds.maxX(), 0); + } + + if (pinchedBounds.maxY() > m_layoutViewportSize.height()) { + overflow.setHeight( + pinchedBounds.maxY() - m_layoutViewportSize.height()); + pinchedBounds.move( + 0, m_layoutViewportSize.height() - pinchedBounds.maxY()); + } + m_pinchViewportScrollDelta = pinchedBounds.location(); + + return overflow; +} + +WebTransformationMatrix CCPinchZoomViewport::implTransform() const +{ + WebTransformationMatrix transform; + transform.scale(m_pageScaleDelta); + + // If the pinch state is applied in the impl, then push it to the + // impl transform, otherwise the scale is handled by WebCore. + if (CCSettings::pageScalePinchZoomEnabled()) { + transform.scale(m_pageScaleFactor); + transform.translate(-m_pinchViewportScrollDelta.x(), + -m_pinchViewportScrollDelta.y()); + } + + return transform; +} + +class CCLayerTreeHostImplTimeSourceAdapter : public CCTimeSourceClient { +public: + static PassOwnPtr create(CCLayerTreeHostImpl* layerTreeHostImpl, PassRefPtr timeSource) + { + return adoptPtr(new CCLayerTreeHostImplTimeSourceAdapter(layerTreeHostImpl, timeSource)); + } + virtual ~CCLayerTreeHostImplTimeSourceAdapter() + { + m_timeSource->setClient(0); + m_timeSource->setActive(false); + } + + virtual void onTimerTick() OVERRIDE + { + // FIXME: We require that animate be called on the impl thread. This + // avoids asserts in single threaded mode. Ideally background ticking + // would be handled by the proxy/scheduler and this could be removed. + DebugScopedSetImplThread impl; + + m_layerTreeHostImpl->animate(monotonicallyIncreasingTime(), currentTime()); + } + + void setActive(bool active) + { + if (active != m_timeSource->active()) + m_timeSource->setActive(active); + } + +private: + CCLayerTreeHostImplTimeSourceAdapter(CCLayerTreeHostImpl* layerTreeHostImpl, PassRefPtr timeSource) + : m_layerTreeHostImpl(layerTreeHostImpl) + , m_timeSource(timeSource) + { + m_timeSource->setClient(this); + } + + CCLayerTreeHostImpl* m_layerTreeHostImpl; + RefPtr m_timeSource; + + DISALLOW_COPY_AND_ASSIGN(CCLayerTreeHostImplTimeSourceAdapter); +}; + +CCLayerTreeHostImpl::FrameData::FrameData() +{ +} + +CCLayerTreeHostImpl::FrameData::~FrameData() +{ +} + +scoped_ptr CCLayerTreeHostImpl::create(const CCLayerTreeSettings& settings, CCLayerTreeHostImplClient* client) +{ + return make_scoped_ptr(new CCLayerTreeHostImpl(settings, client)); +} + +CCLayerTreeHostImpl::CCLayerTreeHostImpl(const CCLayerTreeSettings& settings, CCLayerTreeHostImplClient* client) + : m_client(client) + , m_sourceFrameNumber(-1) + , m_rootScrollLayerImpl(0) + , m_currentlyScrollingLayerImpl(0) + , m_hudLayerImpl(0) + , m_scrollingLayerIdFromPreviousTree(-1) + , m_scrollDeltaIsInScreenSpace(false) + , m_settings(settings) + , m_deviceScaleFactor(1) + , m_visible(true) + , m_contentsTexturesPurged(false) + , m_memoryAllocationLimitBytes(CCPrioritizedTextureManager::defaultMemoryAllocationLimit()) + , m_backgroundColor(0) + , m_hasTransparentBackground(false) + , m_needsAnimateLayers(false) + , m_pinchGestureActive(false) + , m_fpsCounter(CCFrameRateCounter::create()) + , m_debugRectHistory(CCDebugRectHistory::create()) + , m_numImplThreadScrolls(0) + , m_numMainThreadScrolls(0) +{ + ASSERT(CCProxy::isImplThread()); + didVisibilityChange(this, m_visible); +} + +CCLayerTreeHostImpl::~CCLayerTreeHostImpl() +{ + ASSERT(CCProxy::isImplThread()); + TRACE_EVENT0("cc", "CCLayerTreeHostImpl::~CCLayerTreeHostImpl()"); + + if (m_rootLayerImpl) + clearRenderSurfaces(); +} + +void CCLayerTreeHostImpl::beginCommit() +{ +} + +void CCLayerTreeHostImpl::commitComplete() +{ + TRACE_EVENT0("cc", "CCLayerTreeHostImpl::commitComplete"); + // Recompute max scroll position; must be after layer content bounds are + // updated. + updateMaxScrollPosition(); +} + +bool CCLayerTreeHostImpl::canDraw() +{ + // Note: If you are changing this function or any other function that might + // affect the result of canDraw, make sure to call m_client->onCanDrawStateChanged + // in the proper places and update the notifyIfCanDrawChanged test. + + if (!m_rootLayerImpl) { + TRACE_EVENT_INSTANT0("cc", "CCLayerTreeHostImpl::canDraw no root layer"); + return false; + } + if (deviceViewportSize().isEmpty()) { + TRACE_EVENT_INSTANT0("cc", "CCLayerTreeHostImpl::canDraw empty viewport"); + return false; + } + if (!m_renderer) { + TRACE_EVENT_INSTANT0("cc", "CCLayerTreeHostImpl::canDraw no renderer"); + return false; + } + if (m_contentsTexturesPurged) { + TRACE_EVENT_INSTANT0("cc", "CCLayerTreeHostImpl::canDraw contents textures purged"); + return false; + } + return true; +} + +CCGraphicsContext* CCLayerTreeHostImpl::context() const +{ + return m_context.get(); +} + +void CCLayerTreeHostImpl::animate(double monotonicTime, double wallClockTime) +{ + animatePageScale(monotonicTime); + animateLayers(monotonicTime, wallClockTime); + animateScrollbars(monotonicTime); +} + +void CCLayerTreeHostImpl::startPageScaleAnimation(const IntSize& targetPosition, bool anchorPoint, float pageScale, double startTime, double duration) +{ + if (!m_rootScrollLayerImpl) + return; + + IntSize scrollTotal = flooredIntSize(m_rootScrollLayerImpl->scrollPosition() + m_rootScrollLayerImpl->scrollDelta()); + scrollTotal.scale(m_pinchZoomViewport.pageScaleDelta()); + float scaleTotal = m_pinchZoomViewport.totalPageScaleFactor(); + IntSize scaledContentSize = contentSize(); + scaledContentSize.scale(m_pinchZoomViewport.pageScaleDelta()); + + m_pageScaleAnimation = CCPageScaleAnimation::create(scrollTotal, scaleTotal, m_deviceViewportSize, scaledContentSize, startTime); + + if (anchorPoint) { + IntSize windowAnchor(targetPosition); + windowAnchor.scale(scaleTotal / pageScale); + windowAnchor -= scrollTotal; + m_pageScaleAnimation->zoomWithAnchor(windowAnchor, pageScale, duration); + } else + m_pageScaleAnimation->zoomTo(targetPosition, pageScale, duration); + + m_client->setNeedsRedrawOnImplThread(); + m_client->setNeedsCommitOnImplThread(); +} + +void CCLayerTreeHostImpl::scheduleAnimation() +{ + m_client->setNeedsRedrawOnImplThread(); +} + +void CCLayerTreeHostImpl::trackDamageForAllSurfaces(CCLayerImpl* rootDrawLayer, const CCLayerList& renderSurfaceLayerList) +{ + // For now, we use damage tracking to compute a global scissor. To do this, we must + // compute all damage tracking before drawing anything, so that we know the root + // damage rect. The root damage rect is then used to scissor each surface. + + for (int surfaceIndex = renderSurfaceLayerList.size() - 1; surfaceIndex >= 0 ; --surfaceIndex) { + CCLayerImpl* renderSurfaceLayer = renderSurfaceLayerList[surfaceIndex]; + CCRenderSurface* renderSurface = renderSurfaceLayer->renderSurface(); + ASSERT(renderSurface); + renderSurface->damageTracker()->updateDamageTrackingState(renderSurface->layerList(), renderSurfaceLayer->id(), renderSurface->surfacePropertyChangedOnlyFromDescendant(), renderSurface->contentRect(), renderSurfaceLayer->maskLayer(), renderSurfaceLayer->filters()); + } +} + +void CCLayerTreeHostImpl::updateRootScrollLayerImplTransform() +{ + if (m_rootScrollLayerImpl) { + m_rootScrollLayerImpl->setImplTransform(implTransform()); + } +} + +void CCLayerTreeHostImpl::calculateRenderSurfaceLayerList(CCLayerList& renderSurfaceLayerList) +{ + ASSERT(renderSurfaceLayerList.empty()); + ASSERT(m_rootLayerImpl); + ASSERT(m_renderer); // For maxTextureSize. + + { + updateRootScrollLayerImplTransform(); + + TRACE_EVENT0("cc", "CCLayerTreeHostImpl::calcDrawEtc"); + CCLayerTreeHostCommon::calculateDrawTransforms(m_rootLayerImpl.get(), deviceViewportSize(), m_deviceScaleFactor, &m_layerSorter, rendererCapabilities().maxTextureSize, renderSurfaceLayerList); + + trackDamageForAllSurfaces(m_rootLayerImpl.get(), renderSurfaceLayerList); + } +} + +void CCLayerTreeHostImpl::FrameData::appendRenderPass(scoped_ptr renderPass) +{ + CCRenderPass* pass = renderPass.get(); + renderPasses.push_back(pass); + renderPassesById.set(pass->id(), renderPass.Pass()); +} + +bool CCLayerTreeHostImpl::calculateRenderPasses(FrameData& frame) +{ + ASSERT(frame.renderPasses.empty()); + + calculateRenderSurfaceLayerList(*frame.renderSurfaceLayerList); + + TRACE_EVENT1("cc", "CCLayerTreeHostImpl::calculateRenderPasses", "renderSurfaceLayerList.size()", static_cast(frame.renderSurfaceLayerList->size())); + + // Create the render passes in dependency order. + for (int surfaceIndex = frame.renderSurfaceLayerList->size() - 1; surfaceIndex >= 0 ; --surfaceIndex) { + CCLayerImpl* renderSurfaceLayer = (*frame.renderSurfaceLayerList)[surfaceIndex]; + renderSurfaceLayer->renderSurface()->appendRenderPasses(frame); + } + + bool recordMetricsForFrame = true; // FIXME: In the future, disable this when about:tracing is off. + CCOcclusionTrackerImpl occlusionTracker(m_rootLayerImpl->renderSurface()->contentRect(), recordMetricsForFrame); + occlusionTracker.setMinimumTrackingSize(m_settings.minimumOcclusionTrackingSize); + + if (settings().showOccludingRects) + occlusionTracker.setOccludingScreenSpaceRectsContainer(&frame.occludingScreenSpaceRects); + + // Add quads to the Render passes in FrontToBack order to allow for testing occlusion and performing culling during the tree walk. + typedef CCLayerIterator, CCRenderSurface, CCLayerIteratorActions::FrontToBack> CCLayerIteratorType; + + // Typically when we are missing a texture and use a checkerboard quad, we still draw the frame. However when the layer being + // checkerboarded is moving due to an impl-animation, we drop the frame to avoid flashing due to the texture suddenly appearing + // in the future. + bool drawFrame = true; + + CCLayerIteratorType end = CCLayerIteratorType::end(frame.renderSurfaceLayerList); + for (CCLayerIteratorType it = CCLayerIteratorType::begin(frame.renderSurfaceLayerList); it != end; ++it) { + CCRenderPass::Id targetRenderPassId = it.targetRenderSurfaceLayer()->renderSurface()->renderPassId(); + CCRenderPass* targetRenderPass = frame.renderPassesById.get(targetRenderPassId); + + occlusionTracker.enterLayer(it); + + CCAppendQuadsData appendQuadsData(targetRenderPass->id()); + + if (it.representsContributingRenderSurface()) { + CCRenderPass::Id contributingRenderPassId = it->renderSurface()->renderPassId(); + CCRenderPass* contributingRenderPass = frame.renderPassesById.get(contributingRenderPassId); + targetRenderPass->appendQuadsForRenderSurfaceLayer(*it, contributingRenderPass, &occlusionTracker, appendQuadsData); + } else if (it.representsItself() && !it->visibleContentRect().isEmpty()) { + bool hasOcclusionFromOutsideTargetSurface; + if (occlusionTracker.occluded(*it, it->visibleContentRect(), &hasOcclusionFromOutsideTargetSurface)) + appendQuadsData.hadOcclusionFromOutsideTargetSurface |= hasOcclusionFromOutsideTargetSurface; + else { + it->willDraw(m_resourceProvider.get()); + frame.willDrawLayers.push_back(*it); + + if (it->hasContributingDelegatedRenderPasses()) { + CCRenderPass::Id contributingRenderPassId = it->firstContributingRenderPassId(); + while (frame.renderPassesById.contains(contributingRenderPassId)) { + CCRenderPass* renderPass = frame.renderPassesById.get(contributingRenderPassId); + + CCAppendQuadsData appendQuadsData(renderPass->id()); + renderPass->appendQuadsForLayer(*it, &occlusionTracker, appendQuadsData); + + contributingRenderPassId = it->nextContributingRenderPassId(contributingRenderPassId); + } + } + + targetRenderPass->appendQuadsForLayer(*it, &occlusionTracker, appendQuadsData); + } + } + + if (appendQuadsData.hadOcclusionFromOutsideTargetSurface) + targetRenderPass->setHasOcclusionFromOutsideTargetSurface(true); + + if (appendQuadsData.hadMissingTiles) { + bool layerHasAnimatingTransform = it->screenSpaceTransformIsAnimating() || it->drawTransformIsAnimating(); + if (layerHasAnimatingTransform || CCSettings::jankInsteadOfCheckerboard()) + drawFrame = false; + } + + occlusionTracker.leaveLayer(it); + } + +#if !ASSERT_DISABLED + for (size_t i = 0; i < frame.renderPasses.size(); ++i) { + for (size_t j = 0; j < frame.renderPasses[i]->quadList().size(); ++j) + ASSERT(frame.renderPasses[i]->quadList()[j]->sharedQuadStateId() >= 0); + ASSERT(frame.renderPassesById.contains(frame.renderPasses[i]->id())); + } +#endif + + if (!m_hasTransparentBackground) { + frame.renderPasses.back()->setHasTransparentBackground(false); + frame.renderPasses.back()->appendQuadsToFillScreen(m_rootLayerImpl.get(), m_backgroundColor, occlusionTracker); + } + + if (drawFrame) + occlusionTracker.overdrawMetrics().recordMetrics(this); + + removeRenderPasses(CullRenderPassesWithNoQuads(), frame); + m_renderer->decideRenderPassAllocationsForFrame(frame.renderPasses); + removeRenderPasses(CullRenderPassesWithCachedTextures(*m_renderer), frame); + + return drawFrame; +} + +void CCLayerTreeHostImpl::animateLayersRecursive(CCLayerImpl* current, double monotonicTime, double wallClockTime, CCAnimationEventsVector* events, bool& didAnimate, bool& needsAnimateLayers) +{ + bool subtreeNeedsAnimateLayers = false; + + CCLayerAnimationController* currentController = current->layerAnimationController(); + + bool hadActiveAnimation = currentController->hasActiveAnimation(); + currentController->animate(monotonicTime, events); + bool startedAnimation = events->size() > 0; + + // We animated if we either ticked a running animation, or started a new animation. + if (hadActiveAnimation || startedAnimation) + didAnimate = true; + + // If the current controller still has an active animation, we must continue animating layers. + if (currentController->hasActiveAnimation()) + subtreeNeedsAnimateLayers = true; + + for (size_t i = 0; i < current->children().size(); ++i) { + bool childNeedsAnimateLayers = false; + animateLayersRecursive(current->children()[i], monotonicTime, wallClockTime, events, didAnimate, childNeedsAnimateLayers); + if (childNeedsAnimateLayers) + subtreeNeedsAnimateLayers = true; + } + + needsAnimateLayers = subtreeNeedsAnimateLayers; +} + +void CCLayerTreeHostImpl::setBackgroundTickingEnabled(bool enabled) +{ + // Lazily create the timeSource adapter so that we can vary the interval for testing. + if (!m_timeSourceClientAdapter) + m_timeSourceClientAdapter = CCLayerTreeHostImplTimeSourceAdapter::create(this, CCDelayBasedTimeSource::create(lowFrequencyAnimationInterval(), CCProxy::currentThread())); + + m_timeSourceClientAdapter->setActive(enabled); +} + +IntSize CCLayerTreeHostImpl::contentSize() const +{ + // TODO(aelias): Hardcoding the first child here is weird. Think of + // a cleaner way to get the contentBounds on the Impl side. + if (!m_rootScrollLayerImpl || m_rootScrollLayerImpl->children().isEmpty()) + return IntSize(); + return m_rootScrollLayerImpl->children()[0]->contentBounds(); +} + +static inline CCRenderPass* findRenderPassById(CCRenderPass::Id renderPassId, const CCLayerTreeHostImpl::FrameData& frame) +{ + CCRenderPassIdHashMap::const_iterator it = frame.renderPassesById.find(renderPassId); + ASSERT(it != frame.renderPassesById.end()); + return it->second; +} + +static void removeRenderPassesRecursive(CCRenderPass::Id removeRenderPassId, CCLayerTreeHostImpl::FrameData& frame) +{ + CCRenderPass* removeRenderPass = findRenderPassById(removeRenderPassId, frame); + CCRenderPassList& renderPasses = frame.renderPasses; + CCRenderPassList::iterator toRemove = std::find(renderPasses.begin(), renderPasses.end(), removeRenderPass); + + // The pass was already removed by another quad - probably the original, and we are the replica. + if (toRemove == renderPasses.end()) + return; + + const CCRenderPass* removedPass = *toRemove; + frame.renderPasses.erase(toRemove); + + // Now follow up for all RenderPass quads and remove their RenderPasses recursively. + const CCQuadList& quadList = removedPass->quadList(); + CCQuadList::constBackToFrontIterator quadListIterator = quadList.backToFrontBegin(); + for (; quadListIterator != quadList.backToFrontEnd(); ++quadListIterator) { + CCDrawQuad* currentQuad = (*quadListIterator); + if (currentQuad->material() != CCDrawQuad::RenderPass) + continue; + + CCRenderPass::Id nextRemoveRenderPassId = CCRenderPassDrawQuad::materialCast(currentQuad)->renderPassId(); + removeRenderPassesRecursive(nextRemoveRenderPassId, frame); + } +} + +bool CCLayerTreeHostImpl::CullRenderPassesWithCachedTextures::shouldRemoveRenderPass(const CCRenderPassDrawQuad& quad, const FrameData&) const +{ + return quad.contentsChangedSinceLastFrame().isEmpty() && m_renderer.haveCachedResourcesForRenderPassId(quad.renderPassId()); +} + +bool CCLayerTreeHostImpl::CullRenderPassesWithNoQuads::shouldRemoveRenderPass(const CCRenderPassDrawQuad& quad, const FrameData& frame) const +{ + const CCRenderPass* renderPass = findRenderPassById(quad.renderPassId(), frame); + const CCRenderPassList& renderPasses = frame.renderPasses; + CCRenderPassList::const_iterator foundPass = std::find(renderPasses.begin(), renderPasses.end(), renderPass); + + bool renderPassAlreadyRemoved = foundPass == renderPasses.end(); + if (renderPassAlreadyRemoved) + return false; + + // If any quad or RenderPass draws into this RenderPass, then keep it. + const CCQuadList& quadList = (*foundPass)->quadList(); + for (CCQuadList::constBackToFrontIterator quadListIterator = quadList.backToFrontBegin(); quadListIterator != quadList.backToFrontEnd(); ++quadListIterator) { + CCDrawQuad* currentQuad = *quadListIterator; + + if (currentQuad->material() != CCDrawQuad::RenderPass) + return false; + + const CCRenderPass* contributingPass = findRenderPassById(CCRenderPassDrawQuad::materialCast(currentQuad)->renderPassId(), frame); + CCRenderPassList::const_iterator foundContributingPass = std::find(renderPasses.begin(), renderPasses.end(), contributingPass); + if (foundContributingPass != renderPasses.end()) + return false; + } + return true; +} + +// Defined for linking tests. +template void CCLayerTreeHostImpl::removeRenderPasses(CullRenderPassesWithCachedTextures, FrameData&); +template void CCLayerTreeHostImpl::removeRenderPasses(CullRenderPassesWithNoQuads, FrameData&); + +// static +template +void CCLayerTreeHostImpl::removeRenderPasses(RenderPassCuller culler, FrameData& frame) +{ + for (size_t it = culler.renderPassListBegin(frame.renderPasses); it != culler.renderPassListEnd(frame.renderPasses); it = culler.renderPassListNext(it)) { + const CCRenderPass* currentPass = frame.renderPasses[it]; + const CCQuadList& quadList = currentPass->quadList(); + CCQuadList::constBackToFrontIterator quadListIterator = quadList.backToFrontBegin(); + + for (; quadListIterator != quadList.backToFrontEnd(); ++quadListIterator) { + CCDrawQuad* currentQuad = *quadListIterator; + + if (currentQuad->material() != CCDrawQuad::RenderPass) + continue; + + CCRenderPassDrawQuad* renderPassQuad = static_cast(currentQuad); + if (!culler.shouldRemoveRenderPass(*renderPassQuad, frame)) + continue; + + // We are changing the vector in the middle of iteration. Because we + // delete render passes that draw into the current pass, we are + // guaranteed that any data from the iterator to the end will not + // change. So, capture the iterator position from the end of the + // list, and restore it after the change. + int positionFromEnd = frame.renderPasses.size() - it; + removeRenderPassesRecursive(renderPassQuad->renderPassId(), frame); + it = frame.renderPasses.size() - positionFromEnd; + ASSERT(it >= 0); + } + } +} + +bool CCLayerTreeHostImpl::prepareToDraw(FrameData& frame) +{ + TRACE_EVENT0("cc", "CCLayerTreeHostImpl::prepareToDraw"); + ASSERT(canDraw()); + + frame.renderSurfaceLayerList = &m_renderSurfaceLayerList; + frame.renderPasses.clear(); + frame.renderPassesById.clear(); + frame.renderSurfaceLayerList->clear(); + frame.willDrawLayers.clear(); + + if (!calculateRenderPasses(frame)) + return false; + + // If we return true, then we expect drawLayers() to be called before this function is called again. + return true; +} + +void CCLayerTreeHostImpl::releaseContentsTextures() +{ + if (m_contentsTexturesPurged) + return; + m_client->releaseContentsTexturesOnImplThread(); + setContentsTexturesPurged(); + m_client->setNeedsCommitOnImplThread(); + m_client->onCanDrawStateChanged(canDraw()); +} + +void CCLayerTreeHostImpl::setMemoryAllocationLimitBytes(size_t bytes) +{ + if (m_memoryAllocationLimitBytes == bytes) + return; + m_memoryAllocationLimitBytes = bytes; + + ASSERT(bytes); + m_client->setNeedsCommitOnImplThread(); +} + +void CCLayerTreeHostImpl::onVSyncParametersChanged(double monotonicTimebase, double intervalInSeconds) +{ + m_client->onVSyncParametersChanged(monotonicTimebase, intervalInSeconds); +} + +void CCLayerTreeHostImpl::drawLayers(const FrameData& frame) +{ + TRACE_EVENT0("cc", "CCLayerTreeHostImpl::drawLayers"); + ASSERT(canDraw()); + ASSERT(!frame.renderPasses.empty()); + + // FIXME: use the frame begin time from the overall compositor scheduler. + // This value is currently inaccessible because it is up in Chromium's + // RenderWidget. + m_fpsCounter->markBeginningOfFrame(currentTime()); + + if (m_settings.showDebugRects()) + m_debugRectHistory->saveDebugRectsForCurrentFrame(m_rootLayerImpl.get(), *frame.renderSurfaceLayerList, frame.occludingScreenSpaceRects, settings()); + + // Because the contents of the HUD depend on everything else in the frame, the contents + // of its texture are updated as the last thing before the frame is drawn. + if (m_hudLayerImpl) + m_hudLayerImpl->updateHudTexture(m_resourceProvider.get()); + + m_renderer->drawFrame(frame.renderPasses, frame.renderPassesById); + + // Once a RenderPass has been drawn, its damage should be cleared in + // case the RenderPass will be reused next frame. + for (unsigned int i = 0; i < frame.renderPasses.size(); i++) + frame.renderPasses[i]->setDamageRect(FloatRect()); + + // The next frame should start by assuming nothing has changed, and changes are noted as they occur. + for (unsigned int i = 0; i < frame.renderSurfaceLayerList->size(); i++) + (*frame.renderSurfaceLayerList)[i]->renderSurface()->damageTracker()->didDrawDamagedArea(); + m_rootLayerImpl->resetAllChangeTrackingForSubtree(); +} + +void CCLayerTreeHostImpl::didDrawAllLayers(const FrameData& frame) +{ + for (size_t i = 0; i < frame.willDrawLayers.size(); ++i) + frame.willDrawLayers[i]->didDraw(m_resourceProvider.get()); + + // Once all layers have been drawn, pending texture uploads should no + // longer block future uploads. + m_resourceProvider->textureUploader()->markPendingUploadsAsNonBlocking(); +} + +void CCLayerTreeHostImpl::finishAllRendering() +{ + if (m_renderer) + m_renderer->finish(); +} + +bool CCLayerTreeHostImpl::isContextLost() +{ + return m_renderer && m_renderer->isContextLost(); +} + +const RendererCapabilities& CCLayerTreeHostImpl::rendererCapabilities() const +{ + return m_renderer->capabilities(); +} + +bool CCLayerTreeHostImpl::swapBuffers() +{ + ASSERT(m_renderer); + + m_fpsCounter->markEndOfFrame(); + return m_renderer->swapBuffers(); +} + +const IntSize& CCLayerTreeHostImpl::deviceViewportSize() const +{ + return m_deviceViewportSize; +} + +const CCLayerTreeSettings& CCLayerTreeHostImpl::settings() const +{ + return m_settings; +} + +void CCLayerTreeHostImpl::didLoseContext() +{ + m_client->didLoseContextOnImplThread(); +} + +void CCLayerTreeHostImpl::onSwapBuffersComplete() +{ + m_client->onSwapBuffersCompleteOnImplThread(); +} + +void CCLayerTreeHostImpl::readback(void* pixels, const IntRect& rect) +{ + ASSERT(m_renderer); + m_renderer->getFramebufferPixels(pixels, rect); +} + +static CCLayerImpl* findRootScrollLayer(CCLayerImpl* layer) +{ + if (!layer) + return 0; + + if (layer->scrollable()) + return layer; + + for (size_t i = 0; i < layer->children().size(); ++i) { + CCLayerImpl* found = findRootScrollLayer(layer->children()[i]); + if (found) + return found; + } + + return 0; +} + +// Content layers can be either directly scrollable or contained in an outer +// scrolling layer which applies the scroll transform. Given a content layer, +// this function returns the associated scroll layer if any. +static CCLayerImpl* findScrollLayerForContentLayer(CCLayerImpl* layerImpl) +{ + if (!layerImpl) + return 0; + + if (layerImpl->scrollable()) + return layerImpl; + + if (layerImpl->drawsContent() && layerImpl->parent() && layerImpl->parent()->scrollable()) + return layerImpl->parent(); + + return 0; +} + +void CCLayerTreeHostImpl::setRootLayer(scoped_ptr layer) +{ + m_rootLayerImpl = layer.Pass(); + m_rootScrollLayerImpl = findRootScrollLayer(m_rootLayerImpl.get()); + m_currentlyScrollingLayerImpl = 0; + + if (m_rootLayerImpl && m_scrollingLayerIdFromPreviousTree != -1) + m_currentlyScrollingLayerImpl = CCLayerTreeHostCommon::findLayerInSubtree(m_rootLayerImpl.get(), m_scrollingLayerIdFromPreviousTree); + + m_scrollingLayerIdFromPreviousTree = -1; + + m_client->onCanDrawStateChanged(canDraw()); +} + +scoped_ptr CCLayerTreeHostImpl::detachLayerTree() +{ + // Clear all data structures that have direct references to the layer tree. + m_scrollingLayerIdFromPreviousTree = m_currentlyScrollingLayerImpl ? m_currentlyScrollingLayerImpl->id() : -1; + m_currentlyScrollingLayerImpl = 0; + m_renderSurfaceLayerList.clear(); + + return m_rootLayerImpl.Pass(); +} + +void CCLayerTreeHostImpl::setVisible(bool visible) +{ + ASSERT(CCProxy::isImplThread()); + + if (m_visible == visible) + return; + m_visible = visible; + didVisibilityChange(this, m_visible); + + if (!m_renderer) + return; + + m_renderer->setVisible(visible); + + setBackgroundTickingEnabled(!m_visible && m_needsAnimateLayers); +} + +bool CCLayerTreeHostImpl::initializeRenderer(scoped_ptr context) +{ + // Since we will create a new resource provider, we cannot continue to use + // the old resources (i.e. renderSurfaces and texture IDs). Clear them + // before we destroy the old resource provider. + if (m_rootLayerImpl) { + clearRenderSurfaces(); + sendDidLoseContextRecursive(m_rootLayerImpl.get()); + } + // Note: order is important here. + m_renderer.clear(); + m_resourceProvider.clear(); + m_context.reset(); + + if (!context->bindToClient(this)) + return false; + + OwnPtr resourceProvider = CCResourceProvider::create(context.get()); + if (!resourceProvider) + return false; + + if (context->context3D()) + m_renderer = CCRendererGL::create(this, resourceProvider.get()); + else if (context->softwareDevice()) + m_renderer = CCRendererSoftware::create(this, resourceProvider.get(), context->softwareDevice()); + if (!m_renderer) + return false; + + m_resourceProvider = resourceProvider.release(); + m_context = context.Pass(); + + if (!m_visible) + m_renderer->setVisible(m_visible); + + m_client->onCanDrawStateChanged(canDraw()); + + return true; +} + +void CCLayerTreeHostImpl::setContentsTexturesPurged() +{ + m_contentsTexturesPurged = true; + m_client->onCanDrawStateChanged(canDraw()); +} + +void CCLayerTreeHostImpl::resetContentsTexturesPurged() +{ + m_contentsTexturesPurged = false; + m_client->onCanDrawStateChanged(canDraw()); +} + +void CCLayerTreeHostImpl::setViewportSize(const IntSize& layoutViewportSize, const IntSize& deviceViewportSize) +{ + if (layoutViewportSize == m_layoutViewportSize && deviceViewportSize == m_deviceViewportSize) + return; + + m_layoutViewportSize = layoutViewportSize; + m_deviceViewportSize = deviceViewportSize; + + m_pinchZoomViewport.setLayoutViewportSize(FloatSize(layoutViewportSize)); + + updateMaxScrollPosition(); + + if (m_renderer) + m_renderer->viewportChanged(); + + m_client->onCanDrawStateChanged(canDraw()); +} + +static void adjustScrollsForPageScaleChange(CCLayerImpl* layerImpl, float pageScaleChange) +{ + if (!layerImpl) + return; + + if (layerImpl->scrollable()) { + // We need to convert impl-side scroll deltas to pageScale space. + FloatSize scrollDelta = layerImpl->scrollDelta(); + scrollDelta.scale(pageScaleChange); + layerImpl->setScrollDelta(scrollDelta); + } + + for (size_t i = 0; i < layerImpl->children().size(); ++i) + adjustScrollsForPageScaleChange(layerImpl->children()[i], pageScaleChange); +} + +void CCLayerTreeHostImpl::setDeviceScaleFactor(float deviceScaleFactor) +{ + if (deviceScaleFactor == m_deviceScaleFactor) + return; + m_deviceScaleFactor = deviceScaleFactor; + + updateMaxScrollPosition(); +} + +float CCLayerTreeHostImpl::pageScaleFactor() const +{ + return m_pinchZoomViewport.pageScaleFactor(); +} + +void CCLayerTreeHostImpl::setPageScaleFactorAndLimits(float pageScaleFactor, float minPageScaleFactor, float maxPageScaleFactor) +{ + if (!pageScaleFactor) + return; + + float pageScaleChange = pageScaleFactor / m_pinchZoomViewport.pageScaleFactor(); + m_pinchZoomViewport.setPageScaleFactorAndLimits(pageScaleFactor, minPageScaleFactor, maxPageScaleFactor); + + if (!CCSettings::pageScalePinchZoomEnabled()) { + if (pageScaleChange != 1) + adjustScrollsForPageScaleChange(m_rootScrollLayerImpl, pageScaleChange); + } + + // Clamp delta to limits and refresh display matrix. + setPageScaleDelta(m_pinchZoomViewport.pageScaleDelta() / m_pinchZoomViewport.sentPageScaleDelta()); + m_pinchZoomViewport.setSentPageScaleDelta(1); +} + +void CCLayerTreeHostImpl::setPageScaleDelta(float delta) +{ + m_pinchZoomViewport.setPageScaleDelta(delta); + + updateMaxScrollPosition(); +} + +void CCLayerTreeHostImpl::updateMaxScrollPosition() +{ + if (!m_rootScrollLayerImpl || !m_rootScrollLayerImpl->children().size()) + return; + + FloatSize viewBounds = m_deviceViewportSize; + if (CCLayerImpl* clipLayer = m_rootScrollLayerImpl->parent()) { + // Compensate for non-overlay scrollbars. + if (clipLayer->masksToBounds()) { + viewBounds = clipLayer->bounds(); + viewBounds.scale(m_deviceScaleFactor); + } + } + + IntSize contentBounds = contentSize(); + if (CCSettings::pageScalePinchZoomEnabled()) { + // Pinch with pageScale scrolls entirely in layout space. contentSize + // returns the bounds including the page scale factor, so calculate the + // pre page-scale layout size here. + float pageScaleFactor = m_pinchZoomViewport.pageScaleFactor(); + contentBounds.setWidth(contentBounds.width() / pageScaleFactor); + contentBounds.setHeight(contentBounds.height() / pageScaleFactor); + } else { + viewBounds.scale(1 / m_pinchZoomViewport.pageScaleDelta()); + } + + IntSize maxScroll = contentBounds - expandedIntSize(viewBounds); + maxScroll.scale(1 / m_deviceScaleFactor); + + // The viewport may be larger than the contents in some cases, such as + // having a vertical scrollbar but no horizontal overflow. + maxScroll.clampNegativeToZero(); + + m_rootScrollLayerImpl->setMaxScrollPosition(maxScroll); +} + +void CCLayerTreeHostImpl::setNeedsRedraw() +{ + m_client->setNeedsRedrawOnImplThread(); +} + +bool CCLayerTreeHostImpl::ensureRenderSurfaceLayerList() +{ + if (!m_rootLayerImpl) + return false; + if (!m_renderer) + return false; + + // We need both a non-empty render surface layer list and a root render + // surface to be able to iterate over the visible layers. + if (m_renderSurfaceLayerList.size() && m_rootLayerImpl->renderSurface()) + return true; + + // If we are called after setRootLayer() but before prepareToDraw(), we need + // to recalculate the visible layers. This prevents being unable to scroll + // during part of a commit. + m_renderSurfaceLayerList.clear(); + calculateRenderSurfaceLayerList(m_renderSurfaceLayerList); + + return m_renderSurfaceLayerList.size(); +} + +CCInputHandlerClient::ScrollStatus CCLayerTreeHostImpl::scrollBegin(const IntPoint& viewportPoint, CCInputHandlerClient::ScrollInputType type) +{ + TRACE_EVENT0("cc", "CCLayerTreeHostImpl::scrollBegin"); + + ASSERT(!m_currentlyScrollingLayerImpl); + clearCurrentlyScrollingLayer(); + + if (!ensureRenderSurfaceLayerList()) + return ScrollIgnored; + + IntPoint deviceViewportPoint = viewportPoint; + deviceViewportPoint.scale(m_deviceScaleFactor, m_deviceScaleFactor); + + // First find out which layer was hit from the saved list of visible layers + // in the most recent frame. + CCLayerImpl* layerImpl = CCLayerTreeHostCommon::findLayerThatIsHitByPoint(viewportPoint, m_renderSurfaceLayerList); + + // Walk up the hierarchy and look for a scrollable layer. + CCLayerImpl* potentiallyScrollingLayerImpl = 0; + for (; layerImpl; layerImpl = layerImpl->parent()) { + // The content layer can also block attempts to scroll outside the main thread. + if (layerImpl->tryScroll(deviceViewportPoint, type) == ScrollOnMainThread) { + m_numMainThreadScrolls++; + return ScrollOnMainThread; + } + + CCLayerImpl* scrollLayerImpl = findScrollLayerForContentLayer(layerImpl); + if (!scrollLayerImpl) + continue; + + ScrollStatus status = scrollLayerImpl->tryScroll(viewportPoint, type); + + // If any layer wants to divert the scroll event to the main thread, abort. + if (status == ScrollOnMainThread) { + m_numMainThreadScrolls++; + return ScrollOnMainThread; + } + + if (status == ScrollStarted && !potentiallyScrollingLayerImpl) + potentiallyScrollingLayerImpl = scrollLayerImpl; + } + + if (potentiallyScrollingLayerImpl) { + m_currentlyScrollingLayerImpl = potentiallyScrollingLayerImpl; + // Gesture events need to be transformed from screen coordinates to local layer coordinates + // so that the scrolling contents exactly follow the user's finger. In contrast, wheel + // events are already in local layer coordinates so we can just apply them directly. + m_scrollDeltaIsInScreenSpace = (type == Gesture); + m_numImplThreadScrolls++; + return ScrollStarted; + } + return ScrollIgnored; +} + +static FloatSize scrollLayerWithScreenSpaceDelta(CCPinchZoomViewport* viewport, CCLayerImpl& layerImpl, const FloatPoint& screenSpacePoint, const FloatSize& screenSpaceDelta) +{ + // Layers with non-invertible screen space transforms should not have passed the scroll hit + // test in the first place. + ASSERT(layerImpl.screenSpaceTransform().isInvertible()); + WebTransformationMatrix inverseScreenSpaceTransform = layerImpl.screenSpaceTransform().inverse(); + + // First project the scroll start and end points to local layer space to find the scroll delta + // in layer coordinates. + bool startClipped, endClipped; + FloatPoint screenSpaceEndPoint = screenSpacePoint + screenSpaceDelta; + FloatPoint localStartPoint = CCMathUtil::projectPoint(inverseScreenSpaceTransform, screenSpacePoint, startClipped); + FloatPoint localEndPoint = CCMathUtil::projectPoint(inverseScreenSpaceTransform, screenSpaceEndPoint, endClipped); + + // In general scroll point coordinates should not get clipped. + ASSERT(!startClipped); + ASSERT(!endClipped); + if (startClipped || endClipped) + return FloatSize(); + + // Apply the scroll delta. + FloatSize previousDelta(layerImpl.scrollDelta()); + FloatSize unscrolled = layerImpl.scrollBy(localEndPoint - localStartPoint); + + if (viewport) + viewport->applyScroll(unscrolled); + + // Calculate the applied scroll delta in screen space coordinates. + FloatPoint actualLocalEndPoint = localStartPoint + layerImpl.scrollDelta() - previousDelta; + FloatPoint actualScreenSpaceEndPoint = CCMathUtil::mapPoint(layerImpl.screenSpaceTransform(), actualLocalEndPoint, endClipped); + ASSERT(!endClipped); + if (endClipped) + return FloatSize(); + return actualScreenSpaceEndPoint - screenSpacePoint; +} + +static FloatSize scrollLayerWithLocalDelta(CCLayerImpl& layerImpl, const FloatSize& localDelta) +{ + FloatSize previousDelta(layerImpl.scrollDelta()); + layerImpl.scrollBy(localDelta); + return layerImpl.scrollDelta() - previousDelta; +} + +void CCLayerTreeHostImpl::scrollBy(const IntPoint& viewportPoint, const IntSize& scrollDelta) +{ + TRACE_EVENT0("cc", "CCLayerTreeHostImpl::scrollBy"); + if (!m_currentlyScrollingLayerImpl) + return; + + FloatSize pendingDelta(scrollDelta); + + pendingDelta.scale(m_deviceScaleFactor); + + for (CCLayerImpl* layerImpl = m_currentlyScrollingLayerImpl; layerImpl; layerImpl = layerImpl->parent()) { + if (!layerImpl->scrollable()) + continue; + + CCPinchZoomViewport* viewport = layerImpl == m_rootScrollLayerImpl ? &m_pinchZoomViewport : 0; + FloatSize appliedDelta; + if (m_scrollDeltaIsInScreenSpace) + appliedDelta = scrollLayerWithScreenSpaceDelta(viewport, *layerImpl, viewportPoint, pendingDelta); + else + appliedDelta = scrollLayerWithLocalDelta(*layerImpl, pendingDelta); + + // If the layer wasn't able to move, try the next one in the hierarchy. + float moveThresholdSquared = 0.1f * 0.1f; + if (appliedDelta.diagonalLengthSquared() < moveThresholdSquared) + continue; + + // If the applied delta is within 45 degrees of the input delta, bail out to make it easier + // to scroll just one layer in one direction without affecting any of its parents. + float angleThreshold = 45; + if (CCMathUtil::smallestAngleBetweenVectors(appliedDelta, pendingDelta) < angleThreshold) { + pendingDelta = FloatSize(); + break; + } + + // Allow further movement only on an axis perpendicular to the direction in which the layer + // moved. + FloatSize perpendicularAxis(-appliedDelta.height(), appliedDelta.width()); + pendingDelta = CCMathUtil::projectVector(pendingDelta, perpendicularAxis); + + if (flooredIntSize(pendingDelta).isZero()) + break; + } + + if (!scrollDelta.isZero() && flooredIntSize(pendingDelta).isEmpty()) { + m_client->setNeedsCommitOnImplThread(); + m_client->setNeedsRedrawOnImplThread(); + } +} + +void CCLayerTreeHostImpl::clearCurrentlyScrollingLayer() +{ + m_currentlyScrollingLayerImpl = 0; + m_scrollingLayerIdFromPreviousTree = -1; +} + +void CCLayerTreeHostImpl::scrollEnd() +{ + clearCurrentlyScrollingLayer(); +} + +void CCLayerTreeHostImpl::pinchGestureBegin() +{ + m_pinchGestureActive = true; + m_previousPinchAnchor = IntPoint(); + + if (m_rootScrollLayerImpl && m_rootScrollLayerImpl->scrollbarAnimationController()) + m_rootScrollLayerImpl->scrollbarAnimationController()->didPinchGestureBegin(); +} + +void CCLayerTreeHostImpl::pinchGestureUpdate(float magnifyDelta, + const IntPoint& anchor) +{ + TRACE_EVENT0("cc", "CCLayerTreeHostImpl::pinchGestureUpdate"); + + if (!m_rootScrollLayerImpl) + return; + + if (m_previousPinchAnchor == IntPoint::zero()) + m_previousPinchAnchor = anchor; + + // Keep the center-of-pinch anchor specified by (x, y) in a stable + // position over the course of the magnify. + float pageScaleDelta = m_pinchZoomViewport.pageScaleDelta(); + FloatPoint previousScaleAnchor(m_previousPinchAnchor.x() / pageScaleDelta, + m_previousPinchAnchor.y() / pageScaleDelta); + setPageScaleDelta(pageScaleDelta * magnifyDelta); + pageScaleDelta = m_pinchZoomViewport.pageScaleDelta(); + FloatPoint newScaleAnchor(anchor.x() / pageScaleDelta, anchor.y() / pageScaleDelta); + FloatSize move = previousScaleAnchor - newScaleAnchor; + + m_previousPinchAnchor = anchor; + + if (CCSettings::pageScalePinchZoomEnabled()) { + // Compute the application of the delta with respect to the current page zoom of the page. + move.scale(1 / (m_pinchZoomViewport.pageScaleFactor() * m_deviceScaleFactor)); + } + + FloatSize scrollOverflow = CCSettings::pageScalePinchZoomEnabled() ? m_pinchZoomViewport.applyScroll(move) : move; + m_rootScrollLayerImpl->scrollBy(roundedIntSize(scrollOverflow)); + + if (m_rootScrollLayerImpl->scrollbarAnimationController()) + m_rootScrollLayerImpl->scrollbarAnimationController()->didPinchGestureUpdate(); + + m_client->setNeedsCommitOnImplThread(); + m_client->setNeedsRedrawOnImplThread(); +} + +void CCLayerTreeHostImpl::pinchGestureEnd() +{ + m_pinchGestureActive = false; + + if (m_rootScrollLayerImpl && m_rootScrollLayerImpl->scrollbarAnimationController()) + m_rootScrollLayerImpl->scrollbarAnimationController()->didPinchGestureEnd(); + + m_client->setNeedsCommitOnImplThread(); +} + +void CCLayerTreeHostImpl::computeDoubleTapZoomDeltas(CCScrollAndScaleSet* scrollInfo) +{ + float pageScale = m_pageScaleAnimation->finalPageScale(); + IntSize scrollOffset = m_pageScaleAnimation->finalScrollOffset(); + scrollOffset.scale(m_pinchZoomViewport.pageScaleFactor() / pageScale); + makeScrollAndScaleSet(scrollInfo, scrollOffset, pageScale); +} + +void CCLayerTreeHostImpl::computePinchZoomDeltas(CCScrollAndScaleSet* scrollInfo) +{ + if (!m_rootScrollLayerImpl) + return; + + // Only send fake scroll/zoom deltas if we're pinch zooming out by a + // significant amount. This also ensures only one fake delta set will be + // sent. + const float pinchZoomOutSensitivity = 0.95f; + if (m_pinchZoomViewport.pageScaleDelta() > pinchZoomOutSensitivity) + return; + + // Compute where the scroll offset/page scale would be if fully pinch-zoomed + // out from the anchor point. + IntSize scrollBegin = flooredIntSize(m_rootScrollLayerImpl->scrollPosition() + m_rootScrollLayerImpl->scrollDelta()); + scrollBegin.scale(m_pinchZoomViewport.pageScaleDelta()); + float scaleBegin = m_pinchZoomViewport.totalPageScaleFactor(); + float pageScaleDeltaToSend = m_pinchZoomViewport.minPageScaleFactor() / m_pinchZoomViewport.pageScaleFactor(); + FloatSize scaledContentsSize = contentSize(); + scaledContentsSize.scale(pageScaleDeltaToSend); + + FloatSize anchor = toSize(m_previousPinchAnchor); + FloatSize scrollEnd = scrollBegin + anchor; + scrollEnd.scale(m_pinchZoomViewport.minPageScaleFactor() / scaleBegin); + scrollEnd -= anchor; + scrollEnd = scrollEnd.shrunkTo(roundedIntSize(scaledContentsSize - m_deviceViewportSize)).expandedTo(FloatSize(0, 0)); + scrollEnd.scale(1 / pageScaleDeltaToSend); + scrollEnd.scale(m_deviceScaleFactor); + + makeScrollAndScaleSet(scrollInfo, roundedIntSize(scrollEnd), m_pinchZoomViewport.minPageScaleFactor()); +} + +void CCLayerTreeHostImpl::makeScrollAndScaleSet(CCScrollAndScaleSet* scrollInfo, const IntSize& scrollOffset, float pageScale) +{ + if (!m_rootScrollLayerImpl) + return; + + CCLayerTreeHostCommon::ScrollUpdateInfo scroll; + scroll.layerId = m_rootScrollLayerImpl->id(); + scroll.scrollDelta = scrollOffset - toSize(m_rootScrollLayerImpl->scrollPosition()); + scrollInfo->scrolls.append(scroll); + m_rootScrollLayerImpl->setSentScrollDelta(scroll.scrollDelta); + scrollInfo->pageScaleDelta = pageScale / m_pinchZoomViewport.pageScaleFactor(); + m_pinchZoomViewport.setSentPageScaleDelta(scrollInfo->pageScaleDelta); +} + +static void collectScrollDeltas(CCScrollAndScaleSet* scrollInfo, CCLayerImpl* layerImpl) +{ + if (!layerImpl) + return; + + if (!layerImpl->scrollDelta().isZero()) { + IntSize scrollDelta = flooredIntSize(layerImpl->scrollDelta()); + CCLayerTreeHostCommon::ScrollUpdateInfo scroll; + scroll.layerId = layerImpl->id(); + scroll.scrollDelta = scrollDelta; + scrollInfo->scrolls.append(scroll); + layerImpl->setSentScrollDelta(scrollDelta); + } + + for (size_t i = 0; i < layerImpl->children().size(); ++i) + collectScrollDeltas(scrollInfo, layerImpl->children()[i]); +} + +scoped_ptr CCLayerTreeHostImpl::processScrollDeltas() +{ + scoped_ptr scrollInfo(new CCScrollAndScaleSet()); + + if (m_pinchGestureActive || m_pageScaleAnimation) { + scrollInfo->pageScaleDelta = 1; + m_pinchZoomViewport.setSentPageScaleDelta(1); + // FIXME(aelias): Make these painting optimizations compatible with + // compositor-side scaling. + if (!CCSettings::pageScalePinchZoomEnabled()) { + if (m_pinchGestureActive) + computePinchZoomDeltas(scrollInfo.get()); + else if (m_pageScaleAnimation.get()) + computeDoubleTapZoomDeltas(scrollInfo.get()); + } + return scrollInfo.Pass(); + } + + collectScrollDeltas(scrollInfo.get(), m_rootLayerImpl.get()); + scrollInfo->pageScaleDelta = m_pinchZoomViewport.pageScaleDelta(); + m_pinchZoomViewport.setSentPageScaleDelta(scrollInfo->pageScaleDelta); + + return scrollInfo.Pass(); +} + +WebTransformationMatrix CCLayerTreeHostImpl::implTransform() const +{ + return m_pinchZoomViewport.implTransform(); +} + +void CCLayerTreeHostImpl::setFullRootLayerDamage() +{ + if (m_rootLayerImpl) { + CCRenderSurface* renderSurface = m_rootLayerImpl->renderSurface(); + if (renderSurface) + renderSurface->damageTracker()->forceFullDamageNextUpdate(); + } +} + +void CCLayerTreeHostImpl::animatePageScale(double monotonicTime) +{ + if (!m_pageScaleAnimation || !m_rootScrollLayerImpl) + return; + + IntSize scrollTotal = flooredIntSize(m_rootScrollLayerImpl->scrollPosition() + m_rootScrollLayerImpl->scrollDelta()); + + setPageScaleDelta(m_pageScaleAnimation->pageScaleAtTime(monotonicTime) / m_pinchZoomViewport.pageScaleFactor()); + IntSize nextScroll = m_pageScaleAnimation->scrollOffsetAtTime(monotonicTime); + nextScroll.scale(1 / m_pinchZoomViewport.pageScaleDelta()); + m_rootScrollLayerImpl->scrollBy(nextScroll - scrollTotal); + m_client->setNeedsRedrawOnImplThread(); + + if (m_pageScaleAnimation->isAnimationCompleteAtTime(monotonicTime)) { + m_pageScaleAnimation.clear(); + m_client->setNeedsCommitOnImplThread(); + } +} + +void CCLayerTreeHostImpl::animateLayers(double monotonicTime, double wallClockTime) +{ + if (!CCSettings::acceleratedAnimationEnabled() || !m_needsAnimateLayers || !m_rootLayerImpl) + return; + + TRACE_EVENT0("cc", "CCLayerTreeHostImpl::animateLayers"); + + scoped_ptr events(make_scoped_ptr(new CCAnimationEventsVector)); + + bool didAnimate = false; + animateLayersRecursive(m_rootLayerImpl.get(), monotonicTime, wallClockTime, events.get(), didAnimate, m_needsAnimateLayers); + + if (!events->empty()) + m_client->postAnimationEventsToMainThreadOnImplThread(events.Pass(), wallClockTime); + + if (didAnimate) + m_client->setNeedsRedrawOnImplThread(); + + setBackgroundTickingEnabled(!m_visible && m_needsAnimateLayers); +} + +base::TimeDelta CCLayerTreeHostImpl::lowFrequencyAnimationInterval() const +{ + return base::TimeDelta::FromSeconds(1); +} + +void CCLayerTreeHostImpl::sendDidLoseContextRecursive(CCLayerImpl* current) +{ + ASSERT(current); + current->didLoseContext(); + if (current->maskLayer()) + sendDidLoseContextRecursive(current->maskLayer()); + if (current->replicaLayer()) + sendDidLoseContextRecursive(current->replicaLayer()); + for (size_t i = 0; i < current->children().size(); ++i) + sendDidLoseContextRecursive(current->children()[i]); +} + +static void clearRenderSurfacesOnCCLayerImplRecursive(CCLayerImpl* current) +{ + ASSERT(current); + for (size_t i = 0; i < current->children().size(); ++i) + clearRenderSurfacesOnCCLayerImplRecursive(current->children()[i]); + current->clearRenderSurface(); +} + +void CCLayerTreeHostImpl::clearRenderSurfaces() +{ + clearRenderSurfacesOnCCLayerImplRecursive(m_rootLayerImpl.get()); + m_renderSurfaceLayerList.clear(); +} + +std::string CCLayerTreeHostImpl::layerTreeAsText() const +{ + std::string str; + if (m_rootLayerImpl) { + str = m_rootLayerImpl->layerTreeAsText(); + str += "RenderSurfaces:\n"; + dumpRenderSurfaces(&str, 1, m_rootLayerImpl.get()); + } + return str; +} + +void CCLayerTreeHostImpl::dumpRenderSurfaces(std::string* str, int indent, const CCLayerImpl* layer) const +{ + if (layer->renderSurface()) + layer->renderSurface()->dumpSurface(str, indent); + + for (size_t i = 0; i < layer->children().size(); ++i) + dumpRenderSurfaces(str, indent, layer->children()[i]); +} + +int CCLayerTreeHostImpl::sourceAnimationFrameNumber() const +{ + return fpsCounter()->currentFrameNumber(); +} + +void CCLayerTreeHostImpl::renderingStats(CCRenderingStats* stats) const +{ + stats->numFramesSentToScreen = fpsCounter()->currentFrameNumber(); + stats->droppedFrameCount = fpsCounter()->droppedFrameCount(); + stats->numImplThreadScrolls = m_numImplThreadScrolls; + stats->numMainThreadScrolls = m_numMainThreadScrolls; +} + +void CCLayerTreeHostImpl::animateScrollbars(double monotonicTime) +{ + animateScrollbarsRecursive(m_rootLayerImpl.get(), monotonicTime); +} + +void CCLayerTreeHostImpl::animateScrollbarsRecursive(CCLayerImpl* layer, double monotonicTime) +{ + if (!layer) + return; + + CCScrollbarAnimationController* scrollbarController = layer->scrollbarAnimationController(); + if (scrollbarController && scrollbarController->animate(monotonicTime)) + m_client->setNeedsRedrawOnImplThread(); + + for (size_t i = 0; i < layer->children().size(); ++i) + animateScrollbarsRecursive(layer->children()[i], monotonicTime); +} + +} // namespace cc diff --git a/cc/layer_tree_host_impl.h b/cc/layer_tree_host_impl.h index 638cbb2..297f619 100644 --- a/cc/layer_tree_host_impl.h +++ b/cc/layer_tree_host_impl.h @@ -1,3 +1,356 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. +// Copyright 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CCLayerTreeHostImpl_h +#define CCLayerTreeHostImpl_h + +#include "base/basictypes.h" +#include "base/time.h" +#include "CCAnimationEvents.h" +#include "CCInputHandler.h" +#include "CCLayerSorter.h" +#include "CCRenderPass.h" +#include "CCRenderPassSink.h" +#include "CCRenderer.h" +#include "SkColor.h" +#include +#include +#include + +namespace cc { + +class CCCompletionEvent; +class CCDebugRectHistory; +class CCFrameRateCounter; +class CCHeadsUpDisplayLayerImpl; +class CCLayerImpl; +class CCLayerTreeHostImplTimeSourceAdapter; +class CCPageScaleAnimation; +class CCRenderPassDrawQuad; +class CCResourceProvider; +struct RendererCapabilities; +struct CCRenderingStats; + +// CCLayerTreeHost->CCProxy callback interface. +class CCLayerTreeHostImplClient { +public: + virtual void didLoseContextOnImplThread() = 0; + virtual void onSwapBuffersCompleteOnImplThread() = 0; + virtual void onVSyncParametersChanged(double monotonicTimebase, double intervalInSeconds) = 0; + virtual void onCanDrawStateChanged(bool canDraw) = 0; + virtual void setNeedsRedrawOnImplThread() = 0; + virtual void setNeedsCommitOnImplThread() = 0; + virtual void postAnimationEventsToMainThreadOnImplThread(scoped_ptr, double wallClockTime) = 0; + virtual void releaseContentsTexturesOnImplThread() = 0; +}; + +// CCPinchZoomViewport models the bounds and offset of the viewport that is used during a pinch-zoom operation. +// It tracks the layout-space dimensions of the viewport before any applied scale, and then tracks the layout-space +// coordinates of the viewport respecting the pinch settings. +class CCPinchZoomViewport { +public: + CCPinchZoomViewport(); + + float totalPageScaleFactor() const; + + void setPageScaleFactor(float factor) { m_pageScaleFactor = factor; } + float pageScaleFactor() const { return m_pageScaleFactor; } + + void setPageScaleDelta(float delta); + float pageScaleDelta() const { return m_pageScaleDelta; } + + float minPageScaleFactor() const { return m_minPageScaleFactor; } + float maxPageScaleFactor() const { return m_maxPageScaleFactor; } + + void setSentPageScaleDelta(float delta) { m_sentPageScaleDelta = delta; } + float sentPageScaleDelta() const { return m_sentPageScaleDelta; } + + // Returns true if the passed parameters were different from those previously + // cached. + bool setPageScaleFactorAndLimits(float pageScaleFactor, + float minPageScaleFactor, + float maxPageScaleFactor); + + // Returns the bounds and offset of the scaled and translated viewport to use for pinch-zoom. + FloatRect bounds() const; + const FloatPoint& scrollDelta() const { return m_pinchViewportScrollDelta; } + + void setLayoutViewportSize(const FloatSize& size) { m_layoutViewportSize = size; } + + // Apply the scroll offset in layout space to the offset of the pinch-zoom viewport. The viewport cannot be + // scrolled outside of the layout viewport bounds. Returns the component of the scroll that is un-applied due to + // this constraint. + FloatSize applyScroll(FloatSize&); + + WebKit::WebTransformationMatrix implTransform() const; + +private: + float m_pageScaleFactor; + float m_pageScaleDelta; + float m_sentPageScaleDelta; + float m_maxPageScaleFactor; + float m_minPageScaleFactor; + + FloatPoint m_pinchViewportScrollDelta; + FloatSize m_layoutViewportSize; +}; + +// CCLayerTreeHostImpl owns the CCLayerImpl tree as well as associated rendering state +class CCLayerTreeHostImpl : public CCInputHandlerClient, + public CCRendererClient, + public WebKit::WebCompositorOutputSurfaceClient { + typedef std::vector CCLayerList; + +public: + static scoped_ptr create(const CCLayerTreeSettings&, CCLayerTreeHostImplClient*); + virtual ~CCLayerTreeHostImpl(); + + // CCInputHandlerClient implementation + virtual CCInputHandlerClient::ScrollStatus scrollBegin(const IntPoint&, CCInputHandlerClient::ScrollInputType) OVERRIDE; + virtual void scrollBy(const IntPoint&, const IntSize&) OVERRIDE; + virtual void scrollEnd() OVERRIDE; + virtual void pinchGestureBegin() OVERRIDE; + virtual void pinchGestureUpdate(float, const IntPoint&) OVERRIDE; + virtual void pinchGestureEnd() OVERRIDE; + virtual void startPageScaleAnimation(const IntSize& targetPosition, bool anchorPoint, float pageScale, double startTime, double duration) OVERRIDE; + virtual void scheduleAnimation() OVERRIDE; + + struct FrameData : public CCRenderPassSink { + FrameData(); + ~FrameData(); + + Vector occludingScreenSpaceRects; + CCRenderPassList renderPasses; + CCRenderPassIdHashMap renderPassesById; + CCLayerList* renderSurfaceLayerList; + CCLayerList willDrawLayers; + + // CCRenderPassSink implementation. + virtual void appendRenderPass(scoped_ptr) OVERRIDE; + }; + + // Virtual for testing. + virtual void beginCommit(); + virtual void commitComplete(); + virtual void animate(double monotonicTime, double wallClockTime); + + // Returns false if problems occured preparing the frame, and we should try + // to avoid displaying the frame. If prepareToDraw is called, + // didDrawAllLayers must also be called, regardless of whether drawLayers is + // called between the two. + virtual bool prepareToDraw(FrameData&); + virtual void drawLayers(const FrameData&); + // Must be called if and only if prepareToDraw was called. + void didDrawAllLayers(const FrameData&); + + // CCRendererClient implementation + virtual const IntSize& deviceViewportSize() const OVERRIDE; + virtual const CCLayerTreeSettings& settings() const OVERRIDE; + virtual void didLoseContext() OVERRIDE; + virtual void onSwapBuffersComplete() OVERRIDE; + virtual void setFullRootLayerDamage() OVERRIDE; + virtual void releaseContentsTextures() OVERRIDE; + virtual void setMemoryAllocationLimitBytes(size_t) OVERRIDE; + + // WebCompositorOutputSurfaceClient implementation. + virtual void onVSyncParametersChanged(double monotonicTimebase, double intervalInSeconds) OVERRIDE; + + // Implementation + bool canDraw(); + CCGraphicsContext* context() const; + + std::string layerTreeAsText() const; + + void finishAllRendering(); + int sourceAnimationFrameNumber() const; + + bool initializeRenderer(scoped_ptr); + bool isContextLost(); + CCRenderer* renderer() { return m_renderer.get(); } + const RendererCapabilities& rendererCapabilities() const; + + bool swapBuffers(); + + void readback(void* pixels, const IntRect&); + + void setRootLayer(scoped_ptr); + CCLayerImpl* rootLayer() { return m_rootLayerImpl.get(); } + + void setHudLayer(CCHeadsUpDisplayLayerImpl* layerImpl) { m_hudLayerImpl = layerImpl; } + CCHeadsUpDisplayLayerImpl* hudLayer() { return m_hudLayerImpl; } + + // Release ownership of the current layer tree and replace it with an empty + // tree. Returns the root layer of the detached tree. + scoped_ptr detachLayerTree(); + + CCLayerImpl* rootScrollLayer() const { return m_rootScrollLayerImpl; } + + bool visible() const { return m_visible; } + void setVisible(bool); + + int sourceFrameNumber() const { return m_sourceFrameNumber; } + void setSourceFrameNumber(int frameNumber) { m_sourceFrameNumber = frameNumber; } + + bool contentsTexturesPurged() const { return m_contentsTexturesPurged; } + void setContentsTexturesPurged(); + void resetContentsTexturesPurged(); + size_t memoryAllocationLimitBytes() const { return m_memoryAllocationLimitBytes; } + + void setViewportSize(const IntSize& layoutViewportSize, const IntSize& deviceViewportSize); + const IntSize& layoutViewportSize() const { return m_layoutViewportSize; } + + float deviceScaleFactor() const { return m_deviceScaleFactor; } + void setDeviceScaleFactor(float); + + float pageScaleFactor() const; + void setPageScaleFactorAndLimits(float pageScaleFactor, float minPageScaleFactor, float maxPageScaleFactor); + + scoped_ptr processScrollDeltas(); + WebKit::WebTransformationMatrix implTransform() const; + + void startPageScaleAnimation(const IntSize& tragetPosition, bool useAnchor, float scale, double durationSec); + + SkColor backgroundColor() const { return m_backgroundColor; } + void setBackgroundColor(SkColor color) { m_backgroundColor = color; } + + bool hasTransparentBackground() const { return m_hasTransparentBackground; } + void setHasTransparentBackground(bool transparent) { m_hasTransparentBackground = transparent; } + + bool needsAnimateLayers() const { return m_needsAnimateLayers; } + void setNeedsAnimateLayers() { m_needsAnimateLayers = true; } + + void setNeedsRedraw(); + + void renderingStats(CCRenderingStats*) const; + + void updateRootScrollLayerImplTransform(); + + CCFrameRateCounter* fpsCounter() const { return m_fpsCounter.get(); } + CCDebugRectHistory* debugRectHistory() const { return m_debugRectHistory.get(); } + CCResourceProvider* resourceProvider() const { return m_resourceProvider.get(); } + + class CullRenderPassesWithCachedTextures { + public: + bool shouldRemoveRenderPass(const CCRenderPassDrawQuad&, const FrameData&) const; + + // Iterates from the root first, in order to remove the surfaces closest + // to the root with cached textures, and all surfaces that draw into + // them. + size_t renderPassListBegin(const CCRenderPassList& list) const { return list.size() - 1; } + size_t renderPassListEnd(const CCRenderPassList&) const { return 0 - 1; } + size_t renderPassListNext(size_t it) const { return it - 1; } + + CullRenderPassesWithCachedTextures(CCRenderer& renderer) : m_renderer(renderer) { } + private: + CCRenderer& m_renderer; + }; + + class CullRenderPassesWithNoQuads { + public: + bool shouldRemoveRenderPass(const CCRenderPassDrawQuad&, const FrameData&) const; + + // Iterates in draw order, so that when a surface is removed, and its + // target becomes empty, then its target can be removed also. + size_t renderPassListBegin(const CCRenderPassList&) const { return 0; } + size_t renderPassListEnd(const CCRenderPassList& list) const { return list.size(); } + size_t renderPassListNext(size_t it) const { return it + 1; } + }; + + template + static void removeRenderPasses(RenderPassCuller, FrameData&); + +protected: + CCLayerTreeHostImpl(const CCLayerTreeSettings&, CCLayerTreeHostImplClient*); + + void animatePageScale(double monotonicTime); + void animateScrollbars(double monotonicTime); + + // Exposed for testing. + void calculateRenderSurfaceLayerList(CCLayerList&); + + // Virtual for testing. + virtual void animateLayers(double monotonicTime, double wallClockTime); + + // Virtual for testing. + virtual base::TimeDelta lowFrequencyAnimationInterval() const; + + CCLayerTreeHostImplClient* m_client; + int m_sourceFrameNumber; + +private: + void computeDoubleTapZoomDeltas(CCScrollAndScaleSet* scrollInfo); + void computePinchZoomDeltas(CCScrollAndScaleSet* scrollInfo); + void makeScrollAndScaleSet(CCScrollAndScaleSet* scrollInfo, const IntSize& scrollOffset, float pageScale); + + void setPageScaleDelta(float); + void updateMaxScrollPosition(); + void trackDamageForAllSurfaces(CCLayerImpl* rootDrawLayer, const CCLayerList& renderSurfaceLayerList); + + // Returns false if the frame should not be displayed. This function should + // only be called from prepareToDraw, as didDrawAllLayers must be called + // if this helper function is called. + bool calculateRenderPasses(FrameData&); + void animateLayersRecursive(CCLayerImpl*, double monotonicTime, double wallClockTime, CCAnimationEventsVector*, bool& didAnimate, bool& needsAnimateLayers); + void setBackgroundTickingEnabled(bool); + IntSize contentSize() const; + + void sendDidLoseContextRecursive(CCLayerImpl*); + void clearRenderSurfaces(); + bool ensureRenderSurfaceLayerList(); + void clearCurrentlyScrollingLayer(); + + void animateScrollbarsRecursive(CCLayerImpl*, double monotonicTime); + + void dumpRenderSurfaces(std::string*, int indent, const CCLayerImpl*) const; + + scoped_ptr m_context; + OwnPtr m_resourceProvider; + OwnPtr m_renderer; + scoped_ptr m_rootLayerImpl; + CCLayerImpl* m_rootScrollLayerImpl; + CCLayerImpl* m_currentlyScrollingLayerImpl; + CCHeadsUpDisplayLayerImpl* m_hudLayerImpl; + int m_scrollingLayerIdFromPreviousTree; + bool m_scrollDeltaIsInScreenSpace; + CCLayerTreeSettings m_settings; + IntSize m_layoutViewportSize; + IntSize m_deviceViewportSize; + float m_deviceScaleFactor; + bool m_visible; + bool m_contentsTexturesPurged; + size_t m_memoryAllocationLimitBytes; + + SkColor m_backgroundColor; + bool m_hasTransparentBackground; + + // If this is true, it is necessary to traverse the layer tree ticking the animators. + bool m_needsAnimateLayers; + bool m_pinchGestureActive; + IntPoint m_previousPinchAnchor; + + OwnPtr m_pageScaleAnimation; + + // This is used for ticking animations slowly when hidden. + OwnPtr m_timeSourceClientAdapter; + + CCLayerSorter m_layerSorter; + + // List of visible layers for the most recently prepared frame. Used for + // rendering and input event hit testing. + CCLayerList m_renderSurfaceLayerList; + + CCPinchZoomViewport m_pinchZoomViewport; + + OwnPtr m_fpsCounter; + OwnPtr m_debugRectHistory; + + size_t m_numImplThreadScrolls; + size_t m_numMainThreadScrolls; + + DISALLOW_COPY_AND_ASSIGN(CCLayerTreeHostImpl); +}; + +}; + +#endif diff --git a/cc/math_util.cc b/cc/math_util.cc new file mode 100644 index 0000000..d90eb09 --- /dev/null +++ b/cc/math_util.cc @@ -0,0 +1,379 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#include "CCMathUtil.h" + +#include "FloatPoint.h" +#include "FloatQuad.h" +#include "IntRect.h" +#include + +using WebKit::WebTransformationMatrix; + +namespace cc { + +static HomogeneousCoordinate projectHomogeneousPoint(const WebTransformationMatrix& transform, const FloatPoint& p) +{ + // In this case, the layer we are trying to project onto is perpendicular to ray + // (point p and z-axis direction) that we are trying to project. This happens when the + // layer is rotated so that it is infinitesimally thin, or when it is co-planar with + // the camera origin -- i.e. when the layer is invisible anyway. + if (!transform.m33()) + return HomogeneousCoordinate(0, 0, 0, 1); + + double x = p.x(); + double y = p.y(); + double z = -(transform.m13() * x + transform.m23() * y + transform.m43()) / transform.m33(); + // implicit definition of w = 1; + + double outX = x * transform.m11() + y * transform.m21() + z * transform.m31() + transform.m41(); + double outY = x * transform.m12() + y * transform.m22() + z * transform.m32() + transform.m42(); + double outZ = x * transform.m13() + y * transform.m23() + z * transform.m33() + transform.m43(); + double outW = x * transform.m14() + y * transform.m24() + z * transform.m34() + transform.m44(); + + return HomogeneousCoordinate(outX, outY, outZ, outW); +} + +static HomogeneousCoordinate mapHomogeneousPoint(const WebTransformationMatrix& transform, const FloatPoint3D& p) +{ + double x = p.x(); + double y = p.y(); + double z = p.z(); + // implicit definition of w = 1; + + double outX = x * transform.m11() + y * transform.m21() + z * transform.m31() + transform.m41(); + double outY = x * transform.m12() + y * transform.m22() + z * transform.m32() + transform.m42(); + double outZ = x * transform.m13() + y * transform.m23() + z * transform.m33() + transform.m43(); + double outW = x * transform.m14() + y * transform.m24() + z * transform.m34() + transform.m44(); + + return HomogeneousCoordinate(outX, outY, outZ, outW); +} + +static HomogeneousCoordinate computeClippedPointForEdge(const HomogeneousCoordinate& h1, const HomogeneousCoordinate& h2) +{ + // Points h1 and h2 form a line in 4d, and any point on that line can be represented + // as an interpolation between h1 and h2: + // p = (1-t) h1 + (t) h2 + // + // We want to compute point p such that p.w == epsilon, where epsilon is a small + // non-zero number. (but the smaller the number is, the higher the risk of overflow) + // To do this, we solve for t in the following equation: + // p.w = epsilon = (1-t) * h1.w + (t) * h2.w + // + // Once paramter t is known, the rest of p can be computed via p = (1-t) h1 + (t) h2. + + // Technically this is a special case of the following assertion, but its a good idea to keep it an explicit sanity check here. + ASSERT(h2.w != h1.w); + // Exactly one of h1 or h2 (but not both) must be on the negative side of the w plane when this is called. + ASSERT(h1.shouldBeClipped() ^ h2.shouldBeClipped()); + + double w = 0.00001; // or any positive non-zero small epsilon + + double t = (w - h1.w) / (h2.w - h1.w); + + double x = (1-t) * h1.x + t * h2.x; + double y = (1-t) * h1.y + t * h2.y; + double z = (1-t) * h1.z + t * h2.z; + + return HomogeneousCoordinate(x, y, z, w); +} + +static inline void expandBoundsToIncludePoint(float& xmin, float& xmax, float& ymin, float& ymax, const FloatPoint& p) +{ + xmin = std::min(p.x(), xmin); + xmax = std::max(p.x(), xmax); + ymin = std::min(p.y(), ymin); + ymax = std::max(p.y(), ymax); +} + +static inline void addVertexToClippedQuad(const FloatPoint& newVertex, FloatPoint clippedQuad[8], int& numVerticesInClippedQuad) +{ + clippedQuad[numVerticesInClippedQuad] = newVertex; + numVerticesInClippedQuad++; +} + +IntRect CCMathUtil::mapClippedRect(const WebTransformationMatrix& transform, const IntRect& srcRect) +{ + return enclosingIntRect(mapClippedRect(transform, FloatRect(srcRect))); +} + +FloatRect CCMathUtil::mapClippedRect(const WebTransformationMatrix& transform, const FloatRect& srcRect) +{ + if (transform.isIdentityOrTranslation()) { + FloatRect mappedRect(srcRect); + mappedRect.move(static_cast(transform.m41()), static_cast(transform.m42())); + return mappedRect; + } + + // Apply the transform, but retain the result in homogeneous coordinates. + FloatQuad q = FloatQuad(FloatRect(srcRect)); + HomogeneousCoordinate h1 = mapHomogeneousPoint(transform, q.p1()); + HomogeneousCoordinate h2 = mapHomogeneousPoint(transform, q.p2()); + HomogeneousCoordinate h3 = mapHomogeneousPoint(transform, q.p3()); + HomogeneousCoordinate h4 = mapHomogeneousPoint(transform, q.p4()); + + return computeEnclosingClippedRect(h1, h2, h3, h4); +} + +FloatRect CCMathUtil::projectClippedRect(const WebTransformationMatrix& transform, const FloatRect& srcRect) +{ + // Perform the projection, but retain the result in homogeneous coordinates. + FloatQuad q = FloatQuad(FloatRect(srcRect)); + HomogeneousCoordinate h1 = projectHomogeneousPoint(transform, q.p1()); + HomogeneousCoordinate h2 = projectHomogeneousPoint(transform, q.p2()); + HomogeneousCoordinate h3 = projectHomogeneousPoint(transform, q.p3()); + HomogeneousCoordinate h4 = projectHomogeneousPoint(transform, q.p4()); + + return computeEnclosingClippedRect(h1, h2, h3, h4); +} + +void CCMathUtil::mapClippedQuad(const WebTransformationMatrix& transform, const FloatQuad& srcQuad, FloatPoint clippedQuad[8], int& numVerticesInClippedQuad) +{ + HomogeneousCoordinate h1 = mapHomogeneousPoint(transform, srcQuad.p1()); + HomogeneousCoordinate h2 = mapHomogeneousPoint(transform, srcQuad.p2()); + HomogeneousCoordinate h3 = mapHomogeneousPoint(transform, srcQuad.p3()); + HomogeneousCoordinate h4 = mapHomogeneousPoint(transform, srcQuad.p4()); + + // The order of adding the vertices to the array is chosen so that clockwise / counter-clockwise orientation is retained. + + numVerticesInClippedQuad = 0; + + if (!h1.shouldBeClipped()) + addVertexToClippedQuad(h1.cartesianPoint2d(), clippedQuad, numVerticesInClippedQuad); + + if (h1.shouldBeClipped() ^ h2.shouldBeClipped()) + addVertexToClippedQuad(computeClippedPointForEdge(h1, h2).cartesianPoint2d(), clippedQuad, numVerticesInClippedQuad); + + if (!h2.shouldBeClipped()) + addVertexToClippedQuad(h2.cartesianPoint2d(), clippedQuad, numVerticesInClippedQuad); + + if (h2.shouldBeClipped() ^ h3.shouldBeClipped()) + addVertexToClippedQuad(computeClippedPointForEdge(h2, h3).cartesianPoint2d(), clippedQuad, numVerticesInClippedQuad); + + if (!h3.shouldBeClipped()) + addVertexToClippedQuad(h3.cartesianPoint2d(), clippedQuad, numVerticesInClippedQuad); + + if (h3.shouldBeClipped() ^ h4.shouldBeClipped()) + addVertexToClippedQuad(computeClippedPointForEdge(h3, h4).cartesianPoint2d(), clippedQuad, numVerticesInClippedQuad); + + if (!h4.shouldBeClipped()) + addVertexToClippedQuad(h4.cartesianPoint2d(), clippedQuad, numVerticesInClippedQuad); + + if (h4.shouldBeClipped() ^ h1.shouldBeClipped()) + addVertexToClippedQuad(computeClippedPointForEdge(h4, h1).cartesianPoint2d(), clippedQuad, numVerticesInClippedQuad); + + ASSERT(numVerticesInClippedQuad <= 8); +} + +FloatRect CCMathUtil::computeEnclosingRectOfVertices(FloatPoint vertices[], int numVertices) +{ + if (numVertices < 2) + return FloatRect(); + + float xmin = std::numeric_limits::max(); + float xmax = -std::numeric_limits::max(); + float ymin = std::numeric_limits::max(); + float ymax = -std::numeric_limits::max(); + + for (int i = 0; i < numVertices; ++i) + expandBoundsToIncludePoint(xmin, xmax, ymin, ymax, vertices[i]); + + return FloatRect(FloatPoint(xmin, ymin), FloatSize(xmax - xmin, ymax - ymin)); +} + +FloatRect CCMathUtil::computeEnclosingClippedRect(const HomogeneousCoordinate& h1, const HomogeneousCoordinate& h2, const HomogeneousCoordinate& h3, const HomogeneousCoordinate& h4) +{ + // This function performs clipping as necessary and computes the enclosing 2d + // FloatRect of the vertices. Doing these two steps simultaneously allows us to avoid + // the overhead of storing an unknown number of clipped vertices. + + // If no vertices on the quad are clipped, then we can simply return the enclosing rect directly. + bool somethingClipped = h1.shouldBeClipped() || h2.shouldBeClipped() || h3.shouldBeClipped() || h4.shouldBeClipped(); + if (!somethingClipped) { + FloatQuad mappedQuad = FloatQuad(h1.cartesianPoint2d(), h2.cartesianPoint2d(), h3.cartesianPoint2d(), h4.cartesianPoint2d()); + return mappedQuad.boundingBox(); + } + + bool everythingClipped = h1.shouldBeClipped() && h2.shouldBeClipped() && h3.shouldBeClipped() && h4.shouldBeClipped(); + if (everythingClipped) + return FloatRect(); + + + float xmin = std::numeric_limits::max(); + float xmax = -std::numeric_limits::max(); + float ymin = std::numeric_limits::max(); + float ymax = -std::numeric_limits::max(); + + if (!h1.shouldBeClipped()) + expandBoundsToIncludePoint(xmin, xmax, ymin, ymax, h1.cartesianPoint2d()); + + if (h1.shouldBeClipped() ^ h2.shouldBeClipped()) + expandBoundsToIncludePoint(xmin, xmax, ymin, ymax, computeClippedPointForEdge(h1, h2).cartesianPoint2d()); + + if (!h2.shouldBeClipped()) + expandBoundsToIncludePoint(xmin, xmax, ymin, ymax, h2.cartesianPoint2d()); + + if (h2.shouldBeClipped() ^ h3.shouldBeClipped()) + expandBoundsToIncludePoint(xmin, xmax, ymin, ymax, computeClippedPointForEdge(h2, h3).cartesianPoint2d()); + + if (!h3.shouldBeClipped()) + expandBoundsToIncludePoint(xmin, xmax, ymin, ymax, h3.cartesianPoint2d()); + + if (h3.shouldBeClipped() ^ h4.shouldBeClipped()) + expandBoundsToIncludePoint(xmin, xmax, ymin, ymax, computeClippedPointForEdge(h3, h4).cartesianPoint2d()); + + if (!h4.shouldBeClipped()) + expandBoundsToIncludePoint(xmin, xmax, ymin, ymax, h4.cartesianPoint2d()); + + if (h4.shouldBeClipped() ^ h1.shouldBeClipped()) + expandBoundsToIncludePoint(xmin, xmax, ymin, ymax, computeClippedPointForEdge(h4, h1).cartesianPoint2d()); + + return FloatRect(FloatPoint(xmin, ymin), FloatSize(xmax - xmin, ymax - ymin)); +} + +FloatQuad CCMathUtil::mapQuad(const WebTransformationMatrix& transform, const FloatQuad& q, bool& clipped) +{ + if (transform.isIdentityOrTranslation()) { + FloatQuad mappedQuad(q); + mappedQuad.move(static_cast(transform.m41()), static_cast(transform.m42())); + clipped = false; + return mappedQuad; + } + + HomogeneousCoordinate h1 = mapHomogeneousPoint(transform, q.p1()); + HomogeneousCoordinate h2 = mapHomogeneousPoint(transform, q.p2()); + HomogeneousCoordinate h3 = mapHomogeneousPoint(transform, q.p3()); + HomogeneousCoordinate h4 = mapHomogeneousPoint(transform, q.p4()); + + clipped = h1.shouldBeClipped() || h2.shouldBeClipped() || h3.shouldBeClipped() || h4.shouldBeClipped(); + + // Result will be invalid if clipped == true. But, compute it anyway just in case, to emulate existing behavior. + return FloatQuad(h1.cartesianPoint2d(), h2.cartesianPoint2d(), h3.cartesianPoint2d(), h4.cartesianPoint2d()); +} + +FloatPoint CCMathUtil::mapPoint(const WebTransformationMatrix& transform, const FloatPoint& p, bool& clipped) +{ + HomogeneousCoordinate h = mapHomogeneousPoint(transform, p); + + if (h.w > 0) { + clipped = false; + return h.cartesianPoint2d(); + } + + // The cartesian coordinates will be invalid after dividing by w. + clipped = true; + + // Avoid dividing by w if w == 0. + if (!h.w) + return FloatPoint(); + + // This return value will be invalid because clipped == true, but (1) users of this + // code should be ignoring the return value when clipped == true anyway, and (2) this + // behavior is more consistent with existing behavior of WebKit transforms if the user + // really does not ignore the return value. + return h.cartesianPoint2d(); +} + +FloatPoint3D CCMathUtil::mapPoint(const WebTransformationMatrix& transform, const FloatPoint3D& p, bool& clipped) +{ + HomogeneousCoordinate h = mapHomogeneousPoint(transform, p); + + if (h.w > 0) { + clipped = false; + return h.cartesianPoint3d(); + } + + // The cartesian coordinates will be invalid after dividing by w. + clipped = true; + + // Avoid dividing by w if w == 0. + if (!h.w) + return FloatPoint3D(); + + // This return value will be invalid because clipped == true, but (1) users of this + // code should be ignoring the return value when clipped == true anyway, and (2) this + // behavior is more consistent with existing behavior of WebKit transforms if the user + // really does not ignore the return value. + return h.cartesianPoint3d(); +} + +FloatQuad CCMathUtil::projectQuad(const WebTransformationMatrix& transform, const FloatQuad& q, bool& clipped) +{ + FloatQuad projectedQuad; + bool clippedPoint; + projectedQuad.setP1(projectPoint(transform, q.p1(), clippedPoint)); + clipped = clippedPoint; + projectedQuad.setP2(projectPoint(transform, q.p2(), clippedPoint)); + clipped |= clippedPoint; + projectedQuad.setP3(projectPoint(transform, q.p3(), clippedPoint)); + clipped |= clippedPoint; + projectedQuad.setP4(projectPoint(transform, q.p4(), clippedPoint)); + clipped |= clippedPoint; + + return projectedQuad; +} + +FloatPoint CCMathUtil::projectPoint(const WebTransformationMatrix& transform, const FloatPoint& p, bool& clipped) +{ + HomogeneousCoordinate h = projectHomogeneousPoint(transform, p); + + if (h.w > 0) { + // The cartesian coordinates will be valid in this case. + clipped = false; + return h.cartesianPoint2d(); + } + + // The cartesian coordinates will be invalid after dividing by w. + clipped = true; + + // Avoid dividing by w if w == 0. + if (!h.w) + return FloatPoint(); + + // This return value will be invalid because clipped == true, but (1) users of this + // code should be ignoring the return value when clipped == true anyway, and (2) this + // behavior is more consistent with existing behavior of WebKit transforms if the user + // really does not ignore the return value. + return h.cartesianPoint2d(); +} + +void CCMathUtil::flattenTransformTo2d(WebTransformationMatrix& transform) +{ + // Set both the 3rd row and 3rd column to (0, 0, 1, 0). + // + // One useful interpretation of doing this operation: + // - For x and y values, the new transform behaves effectively like an orthographic + // projection was added to the matrix sequence. + // - For z values, the new transform overrides any effect that the transform had on + // z, and instead it preserves the z value for any points that are transformed. + // - Because of linearity of transforms, this flattened transform also preserves the + // effect that any subsequent (post-multiplied) transforms would have on z values. + // + transform.setM13(0); + transform.setM23(0); + transform.setM31(0); + transform.setM32(0); + transform.setM33(1); + transform.setM34(0); + transform.setM43(0); +} + +float CCMathUtil::smallestAngleBetweenVectors(const FloatSize& v1, const FloatSize& v2) +{ + float dotProduct = (v1.width() * v2.width() + v1.height() * v2.height()) / (v1.diagonalLength() * v2.diagonalLength()); + // Clamp to compensate for rounding errors. + dotProduct = std::max(-1.f, std::min(1.f, dotProduct)); + return rad2deg(acosf(dotProduct)); +} + +FloatSize CCMathUtil::projectVector(const FloatSize& source, const FloatSize& destination) +{ + float sourceDotDestination = source.width() * destination.width() + source.height() * destination.height(); + float projectedLength = sourceDotDestination / destination.diagonalLengthSquared(); + return FloatSize(projectedLength * destination.width(), projectedLength * destination.height()); +} + +} // namespace cc diff --git a/cc/math_util.h b/cc/math_util.h index 638cbb2..ed3848e 100644 --- a/cc/math_util.h +++ b/cc/math_util.h @@ -1,3 +1,107 @@ // Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CCMathUtil_h +#define CCMathUtil_h + +#include "FloatPoint.h" +#include "FloatPoint3D.h" + +namespace WebKit { +class WebTransformationMatrix; +} + +namespace cc { + +class IntRect; +class FloatRect; +class FloatQuad; + +struct HomogeneousCoordinate { + HomogeneousCoordinate(double newX, double newY, double newZ, double newW) + : x(newX) + , y(newY) + , z(newZ) + , w(newW) + { + } + + bool shouldBeClipped() const + { + return w <= 0; + } + + FloatPoint cartesianPoint2d() const + { + if (w == 1) + return FloatPoint(x, y); + + // For now, because this code is used privately only by CCMathUtil, it should never be called when w == 0, and we do not yet need to handle that case. + ASSERT(w); + double invW = 1.0 / w; + return FloatPoint(x * invW, y * invW); + } + + FloatPoint3D cartesianPoint3d() const + { + if (w == 1) + return FloatPoint3D(x, y, z); + + // For now, because this code is used privately only by CCMathUtil, it should never be called when w == 0, and we do not yet need to handle that case. + ASSERT(w); + double invW = 1.0 / w; + return FloatPoint3D(x * invW, y * invW, z * invW); + } + + double x; + double y; + double z; + double w; +}; + +class CCMathUtil { +public: + + // Background: WebTransformationMatrix code in WebCore does not do the right thing in + // mapRect / mapQuad / projectQuad when there is a perspective projection that causes + // one of the transformed vertices to go to w < 0. In those cases, it is necessary to + // perform clipping in homogeneous coordinates, after applying the transform, before + // dividing-by-w to convert to cartesian coordinates. + // + // These functions return the axis-aligned rect that encloses the correctly clipped, + // transformed polygon. + static IntRect mapClippedRect(const WebKit::WebTransformationMatrix&, const IntRect&); + static FloatRect mapClippedRect(const WebKit::WebTransformationMatrix&, const FloatRect&); + static FloatRect projectClippedRect(const WebKit::WebTransformationMatrix&, const FloatRect&); + + // Returns an array of vertices that represent the clipped polygon. After returning, indexes from + // 0 to numVerticesInClippedQuad are valid in the clippedQuad array. Note that + // numVerticesInClippedQuad may be zero, which means the entire quad was clipped, and + // none of the vertices in the array are valid. + static void mapClippedQuad(const WebKit::WebTransformationMatrix&, const FloatQuad& srcQuad, FloatPoint clippedQuad[8], int& numVerticesInClippedQuad); + + static FloatRect computeEnclosingRectOfVertices(FloatPoint vertices[], int numVertices); + static FloatRect computeEnclosingClippedRect(const HomogeneousCoordinate& h1, const HomogeneousCoordinate& h2, const HomogeneousCoordinate& h3, const HomogeneousCoordinate& h4); + + // NOTE: These functions do not do correct clipping against w = 0 plane, but they + // correctly detect the clipped condition via the boolean clipped. + static FloatQuad mapQuad(const WebKit::WebTransformationMatrix&, const FloatQuad&, bool& clipped); + static FloatPoint mapPoint(const WebKit::WebTransformationMatrix&, const FloatPoint&, bool& clipped); + static FloatPoint3D mapPoint(const WebKit::WebTransformationMatrix&, const FloatPoint3D&, bool& clipped); + static FloatQuad projectQuad(const WebKit::WebTransformationMatrix&, const FloatQuad&, bool& clipped); + static FloatPoint projectPoint(const WebKit::WebTransformationMatrix&, const FloatPoint&, bool& clipped); + + static void flattenTransformTo2d(WebKit::WebTransformationMatrix&); + + // Returns the smallest angle between the given two vectors in degrees. Neither vector is + // assumed to be normalized. + static float smallestAngleBetweenVectors(const FloatSize&, const FloatSize&); + + // Projects the |source| vector onto |destination|. Neither vector is assumed to be normalized. + static FloatSize projectVector(const FloatSize& source, const FloatSize& destination); +}; + +} // namespace cc + +#endif // #define CCMathUtil_h diff --git a/cc/occlusion_tracker.cc b/cc/occlusion_tracker.cc new file mode 100644 index 0000000..bedb80c --- /dev/null +++ b/cc/occlusion_tracker.cc @@ -0,0 +1,482 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#if USE(ACCELERATED_COMPOSITING) + +#include "CCOcclusionTracker.h" + +#include "CCLayerImpl.h" +#include "CCMathUtil.h" +#include "CCOverdrawMetrics.h" +#include "LayerChromium.h" +#include + +using namespace std; +using WebKit::WebTransformationMatrix; + +namespace cc { + +template +CCOcclusionTrackerBase::CCOcclusionTrackerBase(IntRect rootTargetRect, bool recordMetricsForFrame) + : m_rootTargetRect(rootTargetRect) + , m_overdrawMetrics(CCOverdrawMetrics::create(recordMetricsForFrame)) + , m_occludingScreenSpaceRects(0) +{ +} + +template +void CCOcclusionTrackerBase::enterLayer(const CCLayerIteratorPosition& layerIterator) +{ + LayerType* renderTarget = layerIterator.targetRenderSurfaceLayer; + + if (layerIterator.representsItself) + enterRenderTarget(renderTarget); + else if (layerIterator.representsTargetRenderSurface) + finishedRenderTarget(renderTarget); +} + +template +void CCOcclusionTrackerBase::leaveLayer(const CCLayerIteratorPosition& layerIterator) +{ + LayerType* renderTarget = layerIterator.targetRenderSurfaceLayer; + + if (layerIterator.representsItself) + markOccludedBehindLayer(layerIterator.currentLayer); + else if (layerIterator.representsContributingRenderSurface) + leaveToRenderTarget(renderTarget); +} + +template +void CCOcclusionTrackerBase::enterRenderTarget(const LayerType* newTarget) +{ + if (!m_stack.isEmpty() && m_stack.last().target == newTarget) + return; + + const LayerType* oldTarget = m_stack.isEmpty() ? 0 : m_stack.last().target; + const RenderSurfaceType* oldAncestorThatMovesPixels = !oldTarget ? 0 : oldTarget->renderSurface()->nearestAncestorThatMovesPixels(); + const RenderSurfaceType* newAncestorThatMovesPixels = newTarget->renderSurface()->nearestAncestorThatMovesPixels(); + + m_stack.append(StackObject(newTarget)); + + // We copy the screen occlusion into the new RenderSurface subtree, but we never copy in the + // target occlusion, since we are looking at a new RenderSurface target. + + // If we are entering a subtree that is going to move pixels around, then the occlusion we've computed + // so far won't apply to the pixels we're drawing here in the same way. We discard the occlusion thus + // far to be safe, and ensure we don't cull any pixels that are moved such that they become visible. + bool enteringSubtreeThatMovesPixels = newAncestorThatMovesPixels && newAncestorThatMovesPixels != oldAncestorThatMovesPixels; + + bool copyScreenOcclusionForward = m_stack.size() > 1 && !enteringSubtreeThatMovesPixels; + if (copyScreenOcclusionForward) { + int lastIndex = m_stack.size() - 1; + m_stack[lastIndex].occlusionInScreen = m_stack[lastIndex - 1].occlusionInScreen; + } +} + +static inline bool layerOpacityKnown(const LayerChromium* layer) { return !layer->drawOpacityIsAnimating(); } +static inline bool layerOpacityKnown(const CCLayerImpl*) { return true; } +static inline bool layerTransformsToTargetKnown(const LayerChromium* layer) { return !layer->drawTransformIsAnimating(); } +static inline bool layerTransformsToTargetKnown(const CCLayerImpl*) { return true; } +static inline bool layerTransformsToScreenKnown(const LayerChromium* layer) { return !layer->screenSpaceTransformIsAnimating(); } +static inline bool layerTransformsToScreenKnown(const CCLayerImpl*) { return true; } + +static inline bool surfaceOpacityKnown(const RenderSurfaceChromium* surface) { return !surface->drawOpacityIsAnimating(); } +static inline bool surfaceOpacityKnown(const CCRenderSurface*) { return true; } +static inline bool surfaceTransformsToTargetKnown(const RenderSurfaceChromium* surface) { return !surface->targetSurfaceTransformsAreAnimating(); } +static inline bool surfaceTransformsToTargetKnown(const CCRenderSurface*) { return true; } +static inline bool surfaceTransformsToScreenKnown(const RenderSurfaceChromium* surface) { return !surface->screenSpaceTransformsAreAnimating(); } +static inline bool surfaceTransformsToScreenKnown(const CCRenderSurface*) { return true; } + +static inline bool layerIsInUnsorted3dRenderingContext(const LayerChromium* layer) { return layer->parent() && layer->parent()->preserves3D(); } +static inline bool layerIsInUnsorted3dRenderingContext(const CCLayerImpl*) { return false; } + +template +void CCOcclusionTrackerBase::finishedRenderTarget(const LayerType* finishedTarget) +{ + // Make sure we know about the target surface. + enterRenderTarget(finishedTarget); + + RenderSurfaceType* surface = finishedTarget->renderSurface(); + + // If the occlusion within the surface can not be applied to things outside of the surface's subtree, then clear the occlusion here so it won't be used. + if (finishedTarget->maskLayer() || !surfaceOpacityKnown(surface) || surface->drawOpacity() < 1 || finishedTarget->filters().hasFilterThatAffectsOpacity()) { + m_stack.last().occlusionInScreen = Region(); + m_stack.last().occlusionInTarget = Region(); + } else { + if (!surfaceTransformsToTargetKnown(surface)) + m_stack.last().occlusionInTarget = Region(); + if (!surfaceTransformsToScreenKnown(surface)) + m_stack.last().occlusionInScreen = Region(); + } +} + +template +static inline Region transformSurfaceOpaqueRegion(const RenderSurfaceType* surface, const Region& region, const WebTransformationMatrix& transform) +{ + // Verify that rects within the |surface| will remain rects in its target surface after applying |transform|. If this is true, then + // apply |transform| to each rect within |region| in order to transform the entire Region. + + bool clipped; + FloatQuad transformedBoundsQuad = CCMathUtil::mapQuad(transform, FloatQuad(region.bounds()), clipped); + // FIXME: Find a rect interior to each transformed quad. + if (clipped || !transformedBoundsQuad.isRectilinear()) + return Region(); + + Region transformedRegion; + + Vector rects = region.rects(); + for (size_t i = 0; i < rects.size(); ++i) { + // We've already checked for clipping in the mapQuad call above, these calls should not clip anything further. + IntRect transformedRect = enclosedIntRect(CCMathUtil::mapClippedRect(transform, FloatRect(rects[i]))); + if (!surface->clipRect().isEmpty()) + transformedRect.intersect(surface->clipRect()); + transformedRegion.unite(transformedRect); + } + return transformedRegion; +} + +static inline void reduceOcclusion(const IntRect& affectedArea, const IntRect& expandedPixel, Region& occlusion) +{ + if (affectedArea.isEmpty()) + return; + + Region affectedOcclusion = intersect(occlusion, affectedArea); + Vector affectedOcclusionRects = affectedOcclusion.rects(); + + occlusion.subtract(affectedArea); + for (size_t j = 0; j < affectedOcclusionRects.size(); ++j) { + WebCore::IntRect& occlusionRect = affectedOcclusionRects[j]; + + // Shrink the rect by expanding the non-opaque pixels outside the rect. + + // The expandedPixel is the IntRect for a single pixel after being + // expanded by filters on the layer. The original pixel would be + // IntRect(0, 0, 1, 1), and the expanded pixel is the rect, relative + // to this original rect, that the original pixel can influence after + // being filtered. + // To convert the expandedPixel IntRect back to filter outsets: + // x = -leftOutset + // width = leftOutset + rightOutset + // maxX = x + width = -leftOutset + leftOutset + rightOutset = rightOutset + + // The leftOutset of the filters moves pixels on the right side of + // the occlusionRect into it, shrinking its right edge. + int shrinkLeft = occlusionRect.x() == affectedArea.x() ? 0 : expandedPixel.maxX(); + int shrinkTop = occlusionRect.y() == affectedArea.y() ? 0 : expandedPixel.maxY(); + int shrinkRight = occlusionRect.maxX() == affectedArea.maxX() ? 0 : -expandedPixel.x(); + int shrinkBottom = occlusionRect.maxY() == affectedArea.maxY() ? 0 : -expandedPixel.y(); + + occlusionRect.move(shrinkLeft, shrinkTop); + occlusionRect.contract(shrinkLeft + shrinkRight, shrinkTop + shrinkBottom); + + occlusion.unite(occlusionRect); + } +} + +template +static void reduceOcclusionBelowSurface(LayerType* contributingLayer, const IntRect& surfaceRect, const WebTransformationMatrix& surfaceTransform, LayerType* renderTarget, Region& occlusionInTarget, Region& occlusionInScreen) +{ + if (surfaceRect.isEmpty()) + return; + + IntRect boundsInTarget = enclosingIntRect(CCMathUtil::mapClippedRect(surfaceTransform, FloatRect(surfaceRect))); + if (!contributingLayer->renderSurface()->clipRect().isEmpty()) + boundsInTarget.intersect(contributingLayer->renderSurface()->clipRect()); + + int outsetTop, outsetRight, outsetBottom, outsetLeft; + contributingLayer->backgroundFilters().getOutsets(outsetTop, outsetRight, outsetBottom, outsetLeft); + + // The filter can move pixels from outside of the clip, so allow affectedArea to expand outside the clip. + boundsInTarget.move(-outsetLeft, -outsetTop); + boundsInTarget.expand(outsetLeft + outsetRight, outsetTop + outsetBottom); + + IntRect boundsInScreen = enclosingIntRect(CCMathUtil::mapClippedRect(renderTarget->renderSurface()->screenSpaceTransform(), FloatRect(boundsInTarget))); + + IntRect filterOutsetsInTarget(-outsetLeft, -outsetTop, outsetLeft + outsetRight, outsetTop + outsetBottom); + IntRect filterOutsetsInScreen = enclosingIntRect(CCMathUtil::mapClippedRect(renderTarget->renderSurface()->screenSpaceTransform(), FloatRect(filterOutsetsInTarget))); + + reduceOcclusion(boundsInTarget, filterOutsetsInTarget, occlusionInTarget); + reduceOcclusion(boundsInScreen, filterOutsetsInScreen, occlusionInScreen); +} + +template +void CCOcclusionTrackerBase::leaveToRenderTarget(const LayerType* newTarget) +{ + int lastIndex = m_stack.size() - 1; + bool surfaceWillBeAtTopAfterPop = m_stack.size() > 1 && m_stack[lastIndex - 1].target == newTarget; + + // We merge the screen occlusion from the current RenderSurface subtree out to its parent target RenderSurface. + // The target occlusion can be merged out as well but needs to be transformed to the new target. + + const LayerType* oldTarget = m_stack[lastIndex].target; + const RenderSurfaceType* oldSurface = oldTarget->renderSurface(); + Region oldTargetOcclusionInNewTarget = transformSurfaceOpaqueRegion(oldSurface, m_stack[lastIndex].occlusionInTarget, oldSurface->drawTransform()); + if (oldTarget->hasReplica() && !oldTarget->replicaHasMask()) + oldTargetOcclusionInNewTarget.unite(transformSurfaceOpaqueRegion(oldSurface, m_stack[lastIndex].occlusionInTarget, oldSurface->replicaDrawTransform())); + + IntRect unoccludedSurfaceRect; + IntRect unoccludedReplicaRect; + if (oldTarget->backgroundFilters().hasFilterThatMovesPixels()) { + unoccludedSurfaceRect = unoccludedContributingSurfaceContentRect(oldTarget, false, oldSurface->contentRect()); + if (oldTarget->hasReplica()) + unoccludedReplicaRect = unoccludedContributingSurfaceContentRect(oldTarget, true, oldSurface->contentRect()); + } + + if (surfaceWillBeAtTopAfterPop) { + // Merge the top of the stack down. + m_stack[lastIndex - 1].occlusionInScreen.unite(m_stack[lastIndex].occlusionInScreen); + m_stack[lastIndex - 1].occlusionInTarget.unite(oldTargetOcclusionInNewTarget); + m_stack.removeLast(); + } else { + // Replace the top of the stack with the new pushed surface. Copy the occluded screen region to the top. + m_stack.last().target = newTarget; + m_stack.last().occlusionInTarget = oldTargetOcclusionInNewTarget; + } + + if (oldTarget->backgroundFilters().hasFilterThatMovesPixels()) { + reduceOcclusionBelowSurface(oldTarget, unoccludedSurfaceRect, oldSurface->drawTransform(), newTarget, m_stack.last().occlusionInTarget, m_stack.last().occlusionInScreen); + if (oldTarget->hasReplica()) + reduceOcclusionBelowSurface(oldTarget, unoccludedReplicaRect, oldSurface->replicaDrawTransform(), newTarget, m_stack.last().occlusionInTarget, m_stack.last().occlusionInScreen); + } +} + +// FIXME: Remove usePaintTracking when paint tracking is on for paint culling. +template +static inline void addOcclusionBehindLayer(Region& region, const LayerType* layer, const WebTransformationMatrix& transform, const Region& opaqueContents, const IntRect& clipRectInTarget, const IntSize& minimumTrackingSize, Vector* occludingScreenSpaceRects) +{ + ASSERT(layer->visibleContentRect().contains(opaqueContents.bounds())); + + bool clipped; + FloatQuad visibleTransformedQuad = CCMathUtil::mapQuad(transform, FloatQuad(layer->visibleContentRect()), clipped); + // FIXME: Find a rect interior to each transformed quad. + if (clipped || !visibleTransformedQuad.isRectilinear()) + return; + + Vector contentRects = opaqueContents.rects(); + for (size_t i = 0; i < contentRects.size(); ++i) { + // We've already checked for clipping in the mapQuad call above, these calls should not clip anything further. + IntRect transformedRect = enclosedIntRect(CCMathUtil::mapClippedRect(transform, FloatRect(contentRects[i]))); + transformedRect.intersect(clipRectInTarget); + if (transformedRect.width() >= minimumTrackingSize.width() || transformedRect.height() >= minimumTrackingSize.height()) { + if (occludingScreenSpaceRects) + occludingScreenSpaceRects->append(transformedRect); + region.unite(transformedRect); + } + } +} + +template +void CCOcclusionTrackerBase::markOccludedBehindLayer(const LayerType* layer) +{ + ASSERT(!m_stack.isEmpty()); + ASSERT(layer->renderTarget() == m_stack.last().target); + if (m_stack.isEmpty()) + return; + + if (!layerOpacityKnown(layer) || layer->drawOpacity() < 1) + return; + + if (layerIsInUnsorted3dRenderingContext(layer)) + return; + + Region opaqueContents = layer->visibleContentOpaqueRegion(); + if (opaqueContents.isEmpty()) + return; + + IntRect clipRectInTarget = layerClipRectInTarget(layer); + if (layerTransformsToTargetKnown(layer)) + addOcclusionBehindLayer(m_stack.last().occlusionInTarget, layer, layer->drawTransform(), opaqueContents, clipRectInTarget, m_minimumTrackingSize, 0); + + // We must clip the occlusion within the layer's clipRectInTarget within screen space as well. If the clip rect can't be moved to screen space and + // remain rectilinear, then we don't add any occlusion in screen space. + + if (layerTransformsToScreenKnown(layer)) { + WebTransformationMatrix targetToScreenTransform = m_stack.last().target->renderSurface()->screenSpaceTransform(); + bool clipped; + FloatQuad clipQuadInScreen = CCMathUtil::mapQuad(targetToScreenTransform, FloatQuad(FloatRect(clipRectInTarget)), clipped); + // FIXME: Find a rect interior to the transformed clip quad. + if (clipped || !clipQuadInScreen.isRectilinear()) + return; + IntRect clipRectInScreen = intersection(m_rootTargetRect, enclosedIntRect(clipQuadInScreen.boundingBox())); + addOcclusionBehindLayer(m_stack.last().occlusionInScreen, layer, layer->screenSpaceTransform(), opaqueContents, clipRectInScreen, m_minimumTrackingSize, m_occludingScreenSpaceRects); + } +} + +static inline bool testContentRectOccluded(const IntRect& contentRect, const WebTransformationMatrix& contentSpaceTransform, const IntRect& clipRectInTarget, const Region& occlusion) +{ + FloatRect transformedRect = CCMathUtil::mapClippedRect(contentSpaceTransform, FloatRect(contentRect)); + // Take the enclosingIntRect, as we want to include partial pixels in the test. + IntRect targetRect = intersection(enclosingIntRect(transformedRect), clipRectInTarget); + return targetRect.isEmpty() || occlusion.contains(targetRect); +} + +template +bool CCOcclusionTrackerBase::occluded(const LayerType* layer, const IntRect& contentRect, bool* hasOcclusionFromOutsideTargetSurface) const +{ + if (hasOcclusionFromOutsideTargetSurface) + *hasOcclusionFromOutsideTargetSurface = false; + + ASSERT(!m_stack.isEmpty()); + if (m_stack.isEmpty()) + return false; + if (contentRect.isEmpty()) + return true; + + ASSERT(layer->renderTarget() == m_stack.last().target); + + if (layerTransformsToTargetKnown(layer) && testContentRectOccluded(contentRect, layer->drawTransform(), layerClipRectInTarget(layer), m_stack.last().occlusionInTarget)) + return true; + + if (layerTransformsToScreenKnown(layer) && testContentRectOccluded(contentRect, layer->screenSpaceTransform(), m_rootTargetRect, m_stack.last().occlusionInScreen)) { + if (hasOcclusionFromOutsideTargetSurface) + *hasOcclusionFromOutsideTargetSurface = true; + return true; + } + + return false; +} + +// Determines what portion of rect, if any, is unoccluded (not occluded by region). If +// the resulting unoccluded region is not rectangular, we return a rect containing it. +static inline IntRect rectSubtractRegion(const IntRect& rect, const Region& region) +{ + Region rectRegion(rect); + rectRegion.subtract(region); + return rectRegion.bounds(); +} + +static inline IntRect computeUnoccludedContentRect(const IntRect& contentRect, const WebTransformationMatrix& contentSpaceTransform, const IntRect& clipRectInTarget, const Region& occlusion) +{ + if (!contentSpaceTransform.isInvertible()) + return contentRect; + + // Take the enclosingIntRect at each step, as we want to contain any unoccluded partial pixels in the resulting IntRect. + FloatRect transformedRect = CCMathUtil::mapClippedRect(contentSpaceTransform, FloatRect(contentRect)); + IntRect shrunkRect = rectSubtractRegion(intersection(enclosingIntRect(transformedRect), clipRectInTarget), occlusion); + IntRect unoccludedRect = enclosingIntRect(CCMathUtil::projectClippedRect(contentSpaceTransform.inverse(), FloatRect(shrunkRect))); + // The rect back in content space is a bounding box and may extend outside of the original contentRect, so clamp it to the contentRectBounds. + return intersection(unoccludedRect, contentRect); +} + +template +IntRect CCOcclusionTrackerBase::unoccludedContentRect(const LayerType* layer, const IntRect& contentRect, bool* hasOcclusionFromOutsideTargetSurface) const +{ + ASSERT(!m_stack.isEmpty()); + if (m_stack.isEmpty()) + return contentRect; + if (contentRect.isEmpty()) + return contentRect; + + ASSERT(layer->renderTarget() == m_stack.last().target); + + // We want to return a rect that contains all the visible parts of |contentRect| in both screen space and in the target surface. + // So we find the visible parts of |contentRect| in each space, and take the intersection. + + IntRect unoccludedInScreen = contentRect; + if (layerTransformsToScreenKnown(layer)) + unoccludedInScreen = computeUnoccludedContentRect(contentRect, layer->screenSpaceTransform(), m_rootTargetRect, m_stack.last().occlusionInScreen); + + IntRect unoccludedInTarget = contentRect; + if (layerTransformsToTargetKnown(layer)) + unoccludedInTarget = computeUnoccludedContentRect(contentRect, layer->drawTransform(), layerClipRectInTarget(layer), m_stack.last().occlusionInTarget); + + if (hasOcclusionFromOutsideTargetSurface) + *hasOcclusionFromOutsideTargetSurface = (intersection(unoccludedInScreen, unoccludedInTarget) != unoccludedInTarget); + + return intersection(unoccludedInScreen, unoccludedInTarget); +} + +template +IntRect CCOcclusionTrackerBase::unoccludedContributingSurfaceContentRect(const LayerType* layer, bool forReplica, const IntRect& contentRect, bool* hasOcclusionFromOutsideTargetSurface) const +{ + ASSERT(!m_stack.isEmpty()); + // The layer is a contributing renderTarget so it should have a surface. + ASSERT(layer->renderSurface()); + // The layer is a contributing renderTarget so its target should be itself. + ASSERT(layer->renderTarget() == layer); + // The layer should not be the root, else what is is contributing to? + ASSERT(layer->parent()); + // This should be called while the layer is still considered the current target in the occlusion tracker. + ASSERT(layer == m_stack.last().target); + + if (contentRect.isEmpty()) + return contentRect; + + RenderSurfaceType* surface = layer->renderSurface(); + + IntRect surfaceClipRect = surface->clipRect(); + if (surfaceClipRect.isEmpty()) { + LayerType* contributingSurfaceRenderTarget = layer->parent()->renderTarget(); + surfaceClipRect = intersection(contributingSurfaceRenderTarget->renderSurface()->contentRect(), enclosingIntRect(surface->drawableContentRect())); + } + + // A contributing surface doesn't get occluded by things inside its own surface, so only things outside the surface can occlude it. That occlusion is + // found just below the top of the stack (if it exists). + bool hasOcclusion = m_stack.size() > 1; + + const WebTransformationMatrix& transformToScreen = forReplica ? surface->replicaScreenSpaceTransform() : surface->screenSpaceTransform(); + const WebTransformationMatrix& transformToTarget = forReplica ? surface->replicaDrawTransform() : surface->drawTransform(); + + IntRect unoccludedInScreen = contentRect; + if (surfaceTransformsToScreenKnown(surface)) { + if (hasOcclusion) { + const StackObject& secondLast = m_stack[m_stack.size() - 2]; + unoccludedInScreen = computeUnoccludedContentRect(contentRect, transformToScreen, m_rootTargetRect, secondLast.occlusionInScreen); + } else + unoccludedInScreen = computeUnoccludedContentRect(contentRect, transformToScreen, m_rootTargetRect, Region()); + } + + IntRect unoccludedInTarget = contentRect; + if (surfaceTransformsToTargetKnown(surface)) { + if (hasOcclusion) { + const StackObject& secondLast = m_stack[m_stack.size() - 2]; + unoccludedInTarget = computeUnoccludedContentRect(contentRect, transformToTarget, surfaceClipRect, secondLast.occlusionInTarget); + } else + unoccludedInTarget = computeUnoccludedContentRect(contentRect, transformToTarget, surfaceClipRect, Region()); + } + + if (hasOcclusionFromOutsideTargetSurface) + *hasOcclusionFromOutsideTargetSurface = (intersection(unoccludedInScreen, unoccludedInTarget) != unoccludedInTarget); + + return intersection(unoccludedInScreen, unoccludedInTarget); +} + +template +IntRect CCOcclusionTrackerBase::layerClipRectInTarget(const LayerType* layer) const +{ + // FIXME: we could remove this helper function, but unit tests currently override this + // function, and they need to be verified/adjusted before this can be removed. + return layer->drawableContentRect(); +} + +// Declare the possible functions here for the linker. +template CCOcclusionTrackerBase::CCOcclusionTrackerBase(IntRect rootTargetRect, bool recordMetricsForFrame); +template void CCOcclusionTrackerBase::enterLayer(const CCLayerIteratorPosition&); +template void CCOcclusionTrackerBase::leaveLayer(const CCLayerIteratorPosition&); +template void CCOcclusionTrackerBase::enterRenderTarget(const LayerChromium* newTarget); +template void CCOcclusionTrackerBase::finishedRenderTarget(const LayerChromium* finishedTarget); +template void CCOcclusionTrackerBase::leaveToRenderTarget(const LayerChromium* newTarget); +template void CCOcclusionTrackerBase::markOccludedBehindLayer(const LayerChromium*); +template bool CCOcclusionTrackerBase::occluded(const LayerChromium*, const IntRect& contentRect, bool* hasOcclusionFromOutsideTargetSurface) const; +template IntRect CCOcclusionTrackerBase::unoccludedContentRect(const LayerChromium*, const IntRect& contentRect, bool* hasOcclusionFromOutsideTargetSurface) const; +template IntRect CCOcclusionTrackerBase::unoccludedContributingSurfaceContentRect(const LayerChromium*, bool forReplica, const IntRect& contentRect, bool* hasOcclusionFromOutsideTargetSurface) const; +template IntRect CCOcclusionTrackerBase::layerClipRectInTarget(const LayerChromium*) const; + +template CCOcclusionTrackerBase::CCOcclusionTrackerBase(IntRect rootTargetRect, bool recordMetricsForFrame); +template void CCOcclusionTrackerBase::enterLayer(const CCLayerIteratorPosition&); +template void CCOcclusionTrackerBase::leaveLayer(const CCLayerIteratorPosition&); +template void CCOcclusionTrackerBase::enterRenderTarget(const CCLayerImpl* newTarget); +template void CCOcclusionTrackerBase::finishedRenderTarget(const CCLayerImpl* finishedTarget); +template void CCOcclusionTrackerBase::leaveToRenderTarget(const CCLayerImpl* newTarget); +template void CCOcclusionTrackerBase::markOccludedBehindLayer(const CCLayerImpl*); +template bool CCOcclusionTrackerBase::occluded(const CCLayerImpl*, const IntRect& contentRect, bool* hasOcclusionFromOutsideTargetSurface) const; +template IntRect CCOcclusionTrackerBase::unoccludedContentRect(const CCLayerImpl*, const IntRect& contentRect, bool* hasOcclusionFromOutsideTargetSurface) const; +template IntRect CCOcclusionTrackerBase::unoccludedContributingSurfaceContentRect(const CCLayerImpl*, bool forReplica, const IntRect& contentRect, bool* hasOcclusionFromOutsideTargetSurface) const; +template IntRect CCOcclusionTrackerBase::layerClipRectInTarget(const CCLayerImpl*) const; + + +} // namespace cc +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/cc/occlusion_tracker.h b/cc/occlusion_tracker.h index 638cbb2..c2526cd 100644 --- a/cc/occlusion_tracker.h +++ b/cc/occlusion_tracker.h @@ -1,3 +1,105 @@ // Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CCOcclusionTracker_h +#define CCOcclusionTracker_h + +#include "base/basictypes.h" +#include "CCLayerIterator.h" +#include "FloatQuad.h" +#include "Region.h" + +namespace cc { +class CCOverdrawMetrics; +class CCLayerImpl; +class CCRenderSurface; +class LayerChromium; +class RenderSurfaceChromium; + +// This class is used to track occlusion of layers while traversing them in a front-to-back order. As each layer is visited, one of the +// methods in this class is called to notify it about the current target surface. +// Then, occlusion in the content space of the current layer may be queried, via methods such as occluded() and unoccludedContentRect(). +// If the current layer owns a RenderSurface, then occlusion on that RenderSurface may also be queried via surfaceOccluded() and surfaceUnoccludedContentRect(). +// Finally, once finished with the layer, occlusion behind the layer should be marked by calling markOccludedBehindLayer(). +template +class CCOcclusionTrackerBase { +public: + CCOcclusionTrackerBase(IntRect rootTargetRect, bool recordMetricsForFrame); + + // Called at the beginning of each step in the CCLayerIterator's front-to-back traversal. + void enterLayer(const CCLayerIteratorPosition&); + // Called at the end of each step in the CCLayerIterator's front-to-back traversal. + void leaveLayer(const CCLayerIteratorPosition&); + + // Returns true if the given rect in content space for the layer is fully occluded in either screen space or the layer's target surface. + bool occluded(const LayerType*, const IntRect& contentRect, bool* hasOcclusionFromOutsideTargetSurface = 0) const; + // Gives an unoccluded sub-rect of |contentRect| in the content space of the layer. Used when considering occlusion for a layer that paints/draws something. + IntRect unoccludedContentRect(const LayerType*, const IntRect& contentRect, bool* hasOcclusionFromOutsideTargetSurface = 0) const; + + // Gives an unoccluded sub-rect of |contentRect| in the content space of the renderTarget owned by the layer. + // Used when considering occlusion for a contributing surface that is rendering into another target. + IntRect unoccludedContributingSurfaceContentRect(const LayerType*, bool forReplica, const IntRect& contentRect, bool* hasOcclusionFromOutsideTargetSurface = 0) const; + + // Report operations for recording overdraw metrics. + CCOverdrawMetrics& overdrawMetrics() const { return *m_overdrawMetrics.get(); } + + // Gives the region of the screen that is not occluded by something opaque. + Region computeVisibleRegionInScreen() const { return subtract(Region(m_rootTargetRect), m_stack.last().occlusionInScreen); } + + void setMinimumTrackingSize(const IntSize& size) { m_minimumTrackingSize = size; } + + // The following is used for visualization purposes. + void setOccludingScreenSpaceRectsContainer(Vector* rects) { m_occludingScreenSpaceRects = rects; } + +protected: + struct StackObject { + StackObject() : target(0) { } + StackObject(const LayerType* target) : target(target) { } + const LayerType* target; + Region occlusionInScreen; + Region occlusionInTarget; + }; + + // The stack holds occluded regions for subtrees in the RenderSurface-Layer tree, so that when we leave a subtree we may + // apply a mask to it, but not to the parts outside the subtree. + // - The first time we see a new subtree under a target, we add that target to the top of the stack. This can happen as a layer representing itself, or as a target surface. + // - When we visit a target surface, we apply its mask to its subtree, which is at the top of the stack. + // - When we visit a layer representing itself, we add its occlusion to the current subtree, which is at the top of the stack. + // - When we visit a layer representing a contributing surface, the current target will never be the top of the stack since we just came from the contributing surface. + // We merge the occlusion at the top of the stack with the new current subtree. This new target is pushed onto the stack if not already there. + Vector m_stack; + + // Allow tests to override this. + virtual IntRect layerClipRectInTarget(const LayerType*) const; + +private: + // Called when visiting a layer representing itself. If the target was not already current, then this indicates we have entered a new surface subtree. + void enterRenderTarget(const LayerType* newTarget); + + // Called when visiting a layer representing a target surface. This indicates we have visited all the layers within the surface, and we may + // perform any surface-wide operations. + void finishedRenderTarget(const LayerType* finishedTarget); + + // Called when visiting a layer representing a contributing surface. This indicates that we are leaving our current surface, and + // entering the new one. We then perform any operations required for merging results from the child subtree into its parent. + void leaveToRenderTarget(const LayerType* newTarget); + + // Add the layer's occlusion to the tracked state. + void markOccludedBehindLayer(const LayerType*); + + IntRect m_rootTargetRect; + OwnPtr m_overdrawMetrics; + IntSize m_minimumTrackingSize; + + // This is used for visualizing the occlusion tracking process. + Vector* m_occludingScreenSpaceRects; + + DISALLOW_COPY_AND_ASSIGN(CCOcclusionTrackerBase); +}; + +typedef CCOcclusionTrackerBase CCOcclusionTracker; +typedef CCOcclusionTrackerBase CCOcclusionTrackerImpl; + +} +#endif // CCOcclusionTracker_h diff --git a/cc/overdraw_metrics.cc b/cc/overdraw_metrics.cc new file mode 100644 index 0000000..4eba7d3 --- /dev/null +++ b/cc/overdraw_metrics.cc @@ -0,0 +1,190 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#if USE(ACCELERATED_COMPOSITING) + +#include "CCOverdrawMetrics.h" + +#include "CCLayerTreeHost.h" +#include "CCLayerTreeHostImpl.h" +#include "CCMathUtil.h" +#include "FloatQuad.h" +#include "IntRect.h" +#include "TraceEvent.h" +#include +#include + +using WebKit::WebTransformationMatrix; + +namespace cc { + +CCOverdrawMetrics::CCOverdrawMetrics(bool recordMetricsForFrame) + : m_recordMetricsForFrame(recordMetricsForFrame) + , m_pixelsPainted(0) + , m_pixelsUploadedOpaque(0) + , m_pixelsUploadedTranslucent(0) + , m_tilesCulledForUpload(0) + , m_contentsTextureUseBytes(0) + , m_renderSurfaceTextureUseBytes(0) + , m_pixelsDrawnOpaque(0) + , m_pixelsDrawnTranslucent(0) + , m_pixelsCulledForDrawing(0) +{ +} + +static inline float wedgeProduct(const FloatPoint& p1, const FloatPoint& p2) +{ + return p1.x() * p2.y() - p1.y() * p2.x(); +} + +// Calculates area of an arbitrary convex polygon with up to 8 points. +static inline float polygonArea(const FloatPoint points[8], int numPoints) +{ + if (numPoints < 3) + return 0; + + float area = 0; + for (int i = 0; i < numPoints; ++i) + area += wedgeProduct(points[i], points[(i+1)%numPoints]); + return fabs(0.5f * area); +} + +// Takes a given quad, maps it by the given transformation, and gives the area of the resulting polygon. +static inline float areaOfMappedQuad(const WebTransformationMatrix& transform, const FloatQuad& quad) +{ + FloatPoint clippedQuad[8]; + int numVerticesInClippedQuad = 0; + CCMathUtil::mapClippedQuad(transform, quad, clippedQuad, numVerticesInClippedQuad); + return polygonArea(clippedQuad, numVerticesInClippedQuad); +} + +void CCOverdrawMetrics::didPaint(const IntRect& paintedRect) +{ + if (!m_recordMetricsForFrame) + return; + + m_pixelsPainted += static_cast(paintedRect.width()) * paintedRect.height(); +} + +void CCOverdrawMetrics::didCullTileForUpload() +{ + if (m_recordMetricsForFrame) + ++m_tilesCulledForUpload; +} + +void CCOverdrawMetrics::didUpload(const WebTransformationMatrix& transformToTarget, const IntRect& uploadRect, const IntRect& opaqueRect) +{ + if (!m_recordMetricsForFrame) + return; + + float uploadArea = areaOfMappedQuad(transformToTarget, FloatQuad(uploadRect)); + float uploadOpaqueArea = areaOfMappedQuad(transformToTarget, FloatQuad(intersection(opaqueRect, uploadRect))); + + m_pixelsUploadedOpaque += uploadOpaqueArea; + m_pixelsUploadedTranslucent += uploadArea - uploadOpaqueArea; +} + +void CCOverdrawMetrics::didUseContentsTextureMemoryBytes(size_t contentsTextureUseBytes) +{ + if (!m_recordMetricsForFrame) + return; + + m_contentsTextureUseBytes += contentsTextureUseBytes; +} + +void CCOverdrawMetrics::didUseRenderSurfaceTextureMemoryBytes(size_t renderSurfaceUseBytes) +{ + if (!m_recordMetricsForFrame) + return; + + m_renderSurfaceTextureUseBytes += renderSurfaceUseBytes; +} + +void CCOverdrawMetrics::didCullForDrawing(const WebTransformationMatrix& transformToTarget, const IntRect& beforeCullRect, const IntRect& afterCullRect) +{ + if (!m_recordMetricsForFrame) + return; + + float beforeCullArea = areaOfMappedQuad(transformToTarget, FloatQuad(beforeCullRect)); + float afterCullArea = areaOfMappedQuad(transformToTarget, FloatQuad(afterCullRect)); + + m_pixelsCulledForDrawing += beforeCullArea - afterCullArea; +} + +void CCOverdrawMetrics::didDraw(const WebTransformationMatrix& transformToTarget, const IntRect& afterCullRect, const IntRect& opaqueRect) +{ + if (!m_recordMetricsForFrame) + return; + + float afterCullArea = areaOfMappedQuad(transformToTarget, FloatQuad(afterCullRect)); + float afterCullOpaqueArea = areaOfMappedQuad(transformToTarget, FloatQuad(intersection(opaqueRect, afterCullRect))); + + m_pixelsDrawnOpaque += afterCullOpaqueArea; + m_pixelsDrawnTranslucent += afterCullArea - afterCullOpaqueArea; +} + +void CCOverdrawMetrics::recordMetrics(const CCLayerTreeHost* layerTreeHost) const +{ + if (m_recordMetricsForFrame) + recordMetricsInternal(UpdateAndCommit, layerTreeHost); +} + +void CCOverdrawMetrics::recordMetrics(const CCLayerTreeHostImpl* layerTreeHost) const +{ + if (m_recordMetricsForFrame) + recordMetricsInternal(DrawingToScreen, layerTreeHost); +} + +template +void CCOverdrawMetrics::recordMetricsInternal(MetricsType metricsType, const LayerTreeHostType* layerTreeHost) const +{ + // This gives approximately 10x the percentage of pixels to fill the viewport once. + float normalization = 1000.f / (layerTreeHost->deviceViewportSize().width() * layerTreeHost->deviceViewportSize().height()); + // This gives approximately 100x the percentage of tiles to fill the viewport once, if all tiles were 256x256. + float tileNormalization = 10000.f / (layerTreeHost->deviceViewportSize().width() / 256.f * layerTreeHost->deviceViewportSize().height() / 256.f); + // This gives approximately 10x the percentage of bytes to fill the viewport once, assuming 4 bytes per pixel. + float byteNormalization = normalization / 4; + + switch (metricsType) { + case DrawingToScreen: + WebKit::Platform::current()->histogramCustomCounts("Renderer4.pixelCountOpaque_Draw", static_cast(normalization * m_pixelsDrawnOpaque), 100, 1000000, 50); + WebKit::Platform::current()->histogramCustomCounts("Renderer4.pixelCountTranslucent_Draw", static_cast(normalization * m_pixelsDrawnTranslucent), 100, 1000000, 50); + WebKit::Platform::current()->histogramCustomCounts("Renderer4.pixelCountCulled_Draw", static_cast(normalization * m_pixelsCulledForDrawing), 100, 1000000, 50); + + { + TRACE_COUNTER_ID1("cc", "DrawPixelsCulled", layerTreeHost, m_pixelsCulledForDrawing); + TRACE_EVENT2("cc", "CCOverdrawMetrics", "PixelsDrawnOpaque", m_pixelsDrawnOpaque, "PixelsDrawnTranslucent", m_pixelsDrawnTranslucent); + } + break; + case UpdateAndCommit: + WebKit::Platform::current()->histogramCustomCounts("Renderer4.pixelCountPainted", static_cast(normalization * m_pixelsPainted), 100, 1000000, 50); + WebKit::Platform::current()->histogramCustomCounts("Renderer4.pixelCountOpaque_Upload", static_cast(normalization * m_pixelsUploadedOpaque), 100, 1000000, 50); + WebKit::Platform::current()->histogramCustomCounts("Renderer4.pixelCountTranslucent_Upload", static_cast(normalization * m_pixelsUploadedTranslucent), 100, 1000000, 50); + WebKit::Platform::current()->histogramCustomCounts("Renderer4.tileCountCulled_Upload", static_cast(tileNormalization * m_tilesCulledForUpload), 100, 10000000, 50); + WebKit::Platform::current()->histogramCustomCounts("Renderer4.renderSurfaceTextureBytes_ViewportScaled", static_cast(byteNormalization * m_renderSurfaceTextureUseBytes), 10, 1000000, 50); + WebKit::Platform::current()->histogramCustomCounts("Renderer4.renderSurfaceTextureBytes_Unscaled", static_cast(m_renderSurfaceTextureUseBytes / 1000), 1000, 100000000, 50); + WebKit::Platform::current()->histogramCustomCounts("Renderer4.contentsTextureBytes_ViewportScaled", static_cast(byteNormalization * m_contentsTextureUseBytes), 10, 1000000, 50); + WebKit::Platform::current()->histogramCustomCounts("Renderer4.contentsTextureBytes_Unscaled", static_cast(m_contentsTextureUseBytes / 1000), 1000, 100000000, 50); + + { + TRACE_COUNTER_ID1("cc", "UploadTilesCulled", layerTreeHost, m_tilesCulledForUpload); + TRACE_EVENT2("cc", "CCOverdrawMetrics", "PixelsUploadedOpaque", m_pixelsUploadedOpaque, "PixelsUploadedTranslucent", m_pixelsUploadedTranslucent); + } + { + // This must be in a different scope than the TRACE_EVENT2 above. + TRACE_EVENT1("cc", "CCOverdrawPaintMetrics", "PixelsPainted", m_pixelsPainted); + } + { + // This must be in a different scope than the TRACE_EVENTs above. + TRACE_EVENT2("cc", "CCOverdrawPaintMetrics", "ContentsTextureBytes", m_contentsTextureUseBytes, "RenderSurfaceTextureBytes", m_renderSurfaceTextureUseBytes); + } + break; + } +} + +} // namespace cc + +#endif diff --git a/cc/overdraw_metrics.h b/cc/overdraw_metrics.h index 638cbb2..b907a64 100644 --- a/cc/overdraw_metrics.h +++ b/cc/overdraw_metrics.h @@ -1,3 +1,97 @@ // Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CCOverdrawMetrics_h +#define CCOverdrawMetrics_h + +#include + +namespace WebKit { +class WebTransformationMatrix; +} + +namespace cc { +class IntRect; +class CCLayerTreeHost; +class CCLayerTreeHostImpl; + +// FIXME: compute overdraw metrics only occasionally, not every frame. +class CCOverdrawMetrics { +public: + static PassOwnPtr create(bool recordMetricsForFrame) { return adoptPtr(new CCOverdrawMetrics(recordMetricsForFrame)); } + + // These methods are used for saving metrics during update/commit. + + // Record pixels painted by WebKit into the texture updater, but does not mean the pixels were rasterized in main memory. + void didPaint(const IntRect& paintedRect); + // Records that an invalid tile was culled and did not need to be painted/uploaded, and did not contribute to other tiles needing to be painted. + void didCullTileForUpload(); + // Records pixels that were uploaded to texture memory. + void didUpload(const WebKit::WebTransformationMatrix& transformToTarget, const IntRect& uploadRect, const IntRect& opaqueRect); + // Record contents texture(s) behind present using the given number of bytes. + void didUseContentsTextureMemoryBytes(size_t contentsTextureUseBytes); + // Record RenderSurface texture(s) being present using the given number of bytes. + void didUseRenderSurfaceTextureMemoryBytes(size_t renderSurfaceUseBytes); + + // These methods are used for saving metrics during draw. + + // Record pixels that were not drawn to screen. + void didCullForDrawing(const WebKit::WebTransformationMatrix& transformToTarget, const IntRect& beforeCullRect, const IntRect& afterCullRect); + // Record pixels that were drawn to screen. + void didDraw(const WebKit::WebTransformationMatrix& transformToTarget, const IntRect& afterCullRect, const IntRect& opaqueRect); + + void recordMetrics(const CCLayerTreeHost*) const; + void recordMetrics(const CCLayerTreeHostImpl*) const; + + // Accessors for tests. + float pixelsDrawnOpaque() const { return m_pixelsDrawnOpaque; } + float pixelsDrawnTranslucent() const { return m_pixelsDrawnTranslucent; } + float pixelsCulledForDrawing() const { return m_pixelsCulledForDrawing; } + float pixelsPainted() const { return m_pixelsPainted; } + float pixelsUploadedOpaque() const { return m_pixelsUploadedOpaque; } + float pixelsUploadedTranslucent() const { return m_pixelsUploadedTranslucent; } + int tilesCulledForUpload() const { return m_tilesCulledForUpload; } + +private: + enum MetricsType { + UpdateAndCommit, + DrawingToScreen + }; + + explicit CCOverdrawMetrics(bool recordMetricsForFrame); + + template + void recordMetricsInternal(MetricsType, const LayerTreeHostType*) const; + + // When false this class is a giant no-op. + bool m_recordMetricsForFrame; + + // These values are used for saving metrics during update/commit. + + // Count of pixels that were painted due to invalidation. + float m_pixelsPainted; + // Count of pixels uploaded to textures and known to be opaque. + float m_pixelsUploadedOpaque; + // Count of pixels uploaded to textures and not known to be opaque. + float m_pixelsUploadedTranslucent; + // Count of tiles that were invalidated but not uploaded. + int m_tilesCulledForUpload; + // Count the number of bytes in contents textures. + unsigned long long m_contentsTextureUseBytes; + // Count the number of bytes in RenderSurface textures. + unsigned long long m_renderSurfaceTextureUseBytes; + + // These values are used for saving metrics during draw. + + // Count of pixels that are opaque (and thus occlude). Ideally this is no more than wiewport width x height. + float m_pixelsDrawnOpaque; + // Count of pixels that are possibly translucent, and cannot occlude. + float m_pixelsDrawnTranslucent; + // Count of pixels not drawn as they are occluded by somthing opaque. + float m_pixelsCulledForDrawing; +}; + +} // namespace cc + +#endif diff --git a/cc/page_scale_animation.cc b/cc/page_scale_animation.cc new file mode 100644 index 0000000..12dda09 --- /dev/null +++ b/cc/page_scale_animation.cc @@ -0,0 +1,159 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#include "CCPageScaleAnimation.h" + +#include "FloatRect.h" +#include "FloatSize.h" + +#include + +namespace cc { + +PassOwnPtr CCPageScaleAnimation::create(const IntSize& scrollStart, float pageScaleStart, const IntSize& windowSize, const IntSize& contentSize, double startTime) +{ + return adoptPtr(new CCPageScaleAnimation(scrollStart, pageScaleStart, windowSize, contentSize, startTime)); +} + + +CCPageScaleAnimation::CCPageScaleAnimation(const IntSize& scrollStart, float pageScaleStart, const IntSize& windowSize, const IntSize& contentSize, double startTime) + : m_scrollStart(scrollStart) + , m_pageScaleStart(pageScaleStart) + , m_windowSize(windowSize) + , m_contentSize(contentSize) + , m_anchorMode(false) + , m_scrollEnd(scrollStart) + , m_pageScaleEnd(pageScaleStart) + , m_startTime(startTime) + , m_duration(0) +{ +} + +void CCPageScaleAnimation::zoomTo(const IntSize& finalScroll, float finalPageScale, double duration) +{ + if (m_pageScaleStart != finalPageScale) { + // For uniform-looking zooming, infer the anchor (point that remains in + // place throughout the zoom) from the start and end rects. + FloatRect startRect(IntPoint(m_scrollStart), m_windowSize); + FloatRect endRect(IntPoint(finalScroll), m_windowSize); + endRect.scale(m_pageScaleStart / finalPageScale); + + // The anchor is the point which is at the same ratio of the sides of + // both startRect and endRect. For example, a zoom-in double-tap to a + // perfectly centered rect will have anchor ratios (0.5, 0.5), while one + // to a rect touching the bottom-right of the screen will have anchor + // ratios (1.0, 1.0). In other words, it obeys the equations: + // anchorX = start_width * ratioX + start_x + // anchorX = end_width * ratioX + end_x + // anchorY = start_height * ratioY + start_y + // anchorY = end_height * ratioY + end_y + // where both anchor{x,y} and ratio{x,y} begin as unknowns. Solving + // for the ratios, we get the following formulas: + float ratioX = (startRect.x() - endRect.x()) / (endRect.width() - startRect.width()); + float ratioY = (startRect.y() - endRect.y()) / (endRect.height() - startRect.height()); + + IntSize anchor(m_windowSize.width() * ratioX, m_windowSize.height() * ratioY); + zoomWithAnchor(anchor, finalPageScale, duration); + } else { + // If this is a pure translation, then there exists no anchor. Linearly + // interpolate the scroll offset instead. + m_scrollEnd = finalScroll; + m_pageScaleEnd = finalPageScale; + m_duration = duration; + m_anchorMode = false; + } +} + +void CCPageScaleAnimation::zoomWithAnchor(const IntSize& anchor, float finalPageScale, double duration) +{ + m_scrollEnd = m_scrollStart + anchor; + m_scrollEnd.scale(finalPageScale / m_pageScaleStart); + m_scrollEnd -= anchor; + + m_scrollEnd.clampNegativeToZero(); + FloatSize scaledContentSize(m_contentSize); + scaledContentSize.scale(finalPageScale / m_pageScaleStart); + IntSize maxScrollPosition = roundedIntSize(scaledContentSize - m_windowSize); + m_scrollEnd = m_scrollEnd.shrunkTo(maxScrollPosition); + + m_anchor = anchor; + m_pageScaleEnd = finalPageScale; + m_duration = duration; + m_anchorMode = true; +} + +IntSize CCPageScaleAnimation::scrollOffsetAtTime(double time) const +{ + return scrollOffsetAtRatio(progressRatioForTime(time)); +} + +float CCPageScaleAnimation::pageScaleAtTime(double time) const +{ + return pageScaleAtRatio(progressRatioForTime(time)); +} + +bool CCPageScaleAnimation::isAnimationCompleteAtTime(double time) const +{ + return time >= endTime(); +} + +float CCPageScaleAnimation::progressRatioForTime(double time) const +{ + if (isAnimationCompleteAtTime(time)) + return 1; + + return (time - m_startTime) / m_duration; +} + +IntSize CCPageScaleAnimation::scrollOffsetAtRatio(float ratio) const +{ + if (ratio <= 0) + return m_scrollStart; + if (ratio >= 1) + return m_scrollEnd; + + float currentPageScale = pageScaleAtRatio(ratio); + IntSize currentScrollOffset; + if (m_anchorMode) { + // Keep the anchor stable on the screen at the current scale. + IntSize documentAnchor = m_scrollStart + m_anchor; + documentAnchor.scale(currentPageScale / m_pageScaleStart); + currentScrollOffset = documentAnchor - m_anchor; + } else { + // First move both scroll offsets to the current coordinate space. + FloatSize scaledStartScroll(m_scrollStart); + scaledStartScroll.scale(currentPageScale / m_pageScaleStart); + FloatSize scaledEndScroll(m_scrollEnd); + scaledEndScroll.scale(currentPageScale / m_pageScaleEnd); + + // Linearly interpolate between them. + FloatSize delta = scaledEndScroll - scaledStartScroll; + delta.scale(ratio); + currentScrollOffset = roundedIntSize(scaledStartScroll + delta); + } + + return currentScrollOffset; +} + +float CCPageScaleAnimation::pageScaleAtRatio(float ratio) const +{ + if (ratio <= 0) + return m_pageScaleStart; + if (ratio >= 1) + return m_pageScaleEnd; + + // Linearly interpolate the magnitude in log scale. + // Log scale is needed to maintain the appearance of uniform zoom. For + // example, if we zoom from 0.5 to 4.0 in 3 seconds, then we should + // be zooming by 2x every second. + float diff = m_pageScaleEnd / m_pageScaleStart; + float logDiff = log(diff); + logDiff *= ratio; + diff = exp(logDiff); + return m_pageScaleStart * diff; +} + +} // namespace cc diff --git a/cc/page_scale_animation.h b/cc/page_scale_animation.h index 638cbb2..f597026 100644 --- a/cc/page_scale_animation.h +++ b/cc/page_scale_animation.h @@ -1,3 +1,74 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. +// Copyright 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CCPageScaleAnimation_h +#define CCPageScaleAnimation_h + +#include "IntSize.h" +#include + +namespace cc { + +// A small helper class that does the math for zoom animations, primarily for +// double-tap zoom. Initialize it with starting and ending scroll/page scale +// positions and an animation length time, then call ...AtTime() at every frame +// to obtain the current interpolated position. +class CCPageScaleAnimation { +public: + // Construct with the starting page scale and scroll offset (which is in + // pageScaleStart space). The window size is the user-viewable area + // in pixels. + static PassOwnPtr create(const IntSize& scrollStart, float pageScaleStart, const IntSize& windowSize, const IntSize& contentSize, double startTime); + + // The following methods initialize the animation. Call one of them + // immediately after construction to set the final scroll and page scale. + + // Zoom while explicitly specifying the top-left scroll position. The + // scroll offset is in finalPageScale coordinates. + void zoomTo(const IntSize& finalScroll, float finalPageScale, double duration); + + // Zoom based on a specified onscreen anchor, which will remain at the same + // position on the screen throughout the animation. The anchor is in local + // space relative to scrollStart. + void zoomWithAnchor(const IntSize& anchor, float finalPageScale, double duration); + + // Call these functions while the animation is in progress to output the + // current state. + IntSize scrollOffsetAtTime(double time) const; + float pageScaleAtTime(double time) const; + bool isAnimationCompleteAtTime(double time) const; + + // The following methods return state which is invariant throughout the + // course of the animation. + double startTime() const { return m_startTime; } + double duration() const { return m_duration; } + double endTime() const { return m_startTime + m_duration; } + const IntSize& finalScrollOffset() const { return m_scrollEnd; } + float finalPageScale() const { return m_pageScaleEnd; } + +protected: + CCPageScaleAnimation(const IntSize& scrollStart, float pageScaleStart, const IntSize& windowSize, const IntSize& contentSize, double startTime); + +private: + float progressRatioForTime(double time) const; + IntSize scrollOffsetAtRatio(float ratio) const; + float pageScaleAtRatio(float ratio) const; + + IntSize m_scrollStart; + float m_pageScaleStart; + IntSize m_windowSize; + IntSize m_contentSize; + + bool m_anchorMode; + IntSize m_anchor; + IntSize m_scrollEnd; + float m_pageScaleEnd; + + double m_startTime; + double m_duration; +}; + +} // namespace cc + +#endif diff --git a/cc/platform_color.h b/cc/platform_color.h index 638cbb2..61ffd31 100644 --- a/cc/platform_color.h +++ b/cc/platform_color.h @@ -1,3 +1,58 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. +// Copyright 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef PlatformColor_h +#define PlatformColor_h + +#include "Extensions3D.h" +#include "GraphicsContext3D.h" +#include "SkTypes.h" +#include + +namespace cc { + +class PlatformColor { +public: + static GraphicsContext3D::SourceDataFormat format() + { + return SK_B32_SHIFT ? GraphicsContext3D::SourceFormatRGBA8 : GraphicsContext3D::SourceFormatBGRA8; + } + + // Returns the most efficient texture format for this platform. + static GC3Denum bestTextureFormat(WebKit::WebGraphicsContext3D* context, bool supportsBGRA8888) + { + GC3Denum textureFormat = GraphicsContext3D::RGBA; + switch (format()) { + case GraphicsContext3D::SourceFormatRGBA8: + break; + case GraphicsContext3D::SourceFormatBGRA8: + if (supportsBGRA8888) + textureFormat = Extensions3D::BGRA_EXT; + break; + default: + ASSERT_NOT_REACHED(); + break; + } + return textureFormat; + } + + // Return true if the given texture format has the same component order + // as the color on this platform. + static bool sameComponentOrder(GC3Denum textureFormat) + { + switch (format()) { + case GraphicsContext3D::SourceFormatRGBA8: + return textureFormat == GraphicsContext3D::RGBA; + case GraphicsContext3D::SourceFormatBGRA8: + return textureFormat == Extensions3D::BGRA_EXT; + default: + ASSERT_NOT_REACHED(); + return false; + } + } +}; + +} // namespace cc + +#endif diff --git a/cc/prioritized_texture.cc b/cc/prioritized_texture.cc new file mode 100644 index 0000000..2940e92 --- /dev/null +++ b/cc/prioritized_texture.cc @@ -0,0 +1,180 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#include "CCPrioritizedTexture.h" + +#include "CCPrioritizedTextureManager.h" +#include "CCPriorityCalculator.h" +#include "CCProxy.h" +#include + +using namespace std; + +namespace cc { + +CCPrioritizedTexture::CCPrioritizedTexture(CCPrioritizedTextureManager* manager, IntSize size, GC3Denum format) + : m_size(size) + , m_format(format) + , m_bytes(0) + , m_priority(CCPriorityCalculator::lowestPriority()) + , m_isAbovePriorityCutoff(false) + , m_isSelfManaged(false) + , m_backing(0) + , m_manager(0) +{ + // m_manager is set in registerTexture() so validity can be checked. + ASSERT(format || size.isEmpty()); + if (format) + m_bytes = CCTexture::memorySizeBytes(size, format); + if (manager) + manager->registerTexture(this); +} + +CCPrioritizedTexture::~CCPrioritizedTexture() +{ + if (m_manager) + m_manager->unregisterTexture(this); +} + +void CCPrioritizedTexture::setTextureManager(CCPrioritizedTextureManager* manager) +{ + if (m_manager == manager) + return; + if (m_manager) + m_manager->unregisterTexture(this); + if (manager) + manager->registerTexture(this); +} + +void CCPrioritizedTexture::setDimensions(IntSize size, GC3Denum format) +{ + if (m_format != format || m_size != size) { + m_isAbovePriorityCutoff = false; + m_format = format; + m_size = size; + m_bytes = CCTexture::memorySizeBytes(size, format); + ASSERT(m_manager || !m_backing); + if (m_manager) + m_manager->returnBackingTexture(this); + } +} + +bool CCPrioritizedTexture::requestLate() +{ + if (!m_manager) + return false; + return m_manager->requestLate(this); +} + +bool CCPrioritizedTexture::backingResourceWasEvicted() const +{ + return m_backing ? m_backing->resourceHasBeenDeleted() : false; +} + +void CCPrioritizedTexture::acquireBackingTexture(CCResourceProvider* resourceProvider) +{ + ASSERT(m_isAbovePriorityCutoff); + if (m_isAbovePriorityCutoff) + m_manager->acquireBackingTextureIfNeeded(this, resourceProvider); +} + +CCResourceProvider::ResourceId CCPrioritizedTexture::resourceId() const +{ + if (m_backing) + return m_backing->id(); + return 0; +} + +void CCPrioritizedTexture::upload(CCResourceProvider* resourceProvider, + const uint8_t* image, const IntRect& imageRect, + const IntRect& sourceRect, const IntSize& destOffset) +{ + ASSERT(m_isAbovePriorityCutoff); + if (m_isAbovePriorityCutoff) + acquireBackingTexture(resourceProvider); + ASSERT(m_backing); + resourceProvider->upload(resourceId(), image, imageRect, sourceRect, destOffset); +} + +void CCPrioritizedTexture::link(Backing* backing) +{ + ASSERT(backing); + ASSERT(!backing->m_owner); + ASSERT(!m_backing); + + m_backing = backing; + m_backing->m_owner = this; +} + +void CCPrioritizedTexture::unlink() +{ + ASSERT(m_backing); + ASSERT(m_backing->m_owner == this); + + m_backing->m_owner = 0; + m_backing = 0; +} + +void CCPrioritizedTexture::setToSelfManagedMemoryPlaceholder(size_t bytes) +{ + setDimensions(IntSize(), GraphicsContext3D::RGBA); + setIsSelfManaged(true); + m_bytes = bytes; +} + +CCPrioritizedTexture::Backing::Backing(unsigned id, CCResourceProvider* resourceProvider, IntSize size, GC3Denum format) + : CCTexture(id, size, format) + , m_owner(0) + , m_priorityAtLastPriorityUpdate(CCPriorityCalculator::lowestPriority()) + , m_ownerExistedAtLastPriorityUpdate(false) + , m_wasAbovePriorityCutoffAtLastPriorityUpdate(false) + , m_resourceHasBeenDeleted(false) +#ifndef NDEBUG + , m_resourceProvider(resourceProvider) +#endif +{ +} + +CCPrioritizedTexture::Backing::~Backing() +{ + ASSERT(!m_owner); + ASSERT(m_resourceHasBeenDeleted); +} + +void CCPrioritizedTexture::Backing::deleteResource(CCResourceProvider* resourceProvider) +{ + ASSERT(CCProxy::isImplThread()); + ASSERT(!m_resourceHasBeenDeleted); +#ifndef NDEBUG + ASSERT(resourceProvider == m_resourceProvider); +#endif + + resourceProvider->deleteResource(id()); + setId(0); + m_resourceHasBeenDeleted = true; +} + +bool CCPrioritizedTexture::Backing::resourceHasBeenDeleted() const +{ + ASSERT(CCProxy::isImplThread()); + return m_resourceHasBeenDeleted; +} + +void CCPrioritizedTexture::Backing::updatePriority() +{ + ASSERT(CCProxy::isImplThread() && CCProxy::isMainThreadBlocked()); + if (m_owner) { + m_ownerExistedAtLastPriorityUpdate = true; + m_priorityAtLastPriorityUpdate = m_owner->requestPriority(); + m_wasAbovePriorityCutoffAtLastPriorityUpdate = m_owner->isAbovePriorityCutoff(); + } else { + m_ownerExistedAtLastPriorityUpdate = false; + m_priorityAtLastPriorityUpdate = CCPriorityCalculator::lowestPriority(); + m_wasAbovePriorityCutoffAtLastPriorityUpdate = false; + } +} + +} // namespace cc diff --git a/cc/prioritized_texture.h b/cc/prioritized_texture.h index 638cbb2..3196867 100644 --- a/cc/prioritized_texture.h +++ b/cc/prioritized_texture.h @@ -1,3 +1,142 @@ // Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CCPrioritizedTexture_h +#define CCPrioritizedTexture_h + +#include "base/basictypes.h" +#include "base/memory/scoped_ptr.h" +#include "CCPriorityCalculator.h" +#include "CCResourceProvider.h" +#include "CCTexture.h" +#include "GraphicsContext3D.h" +#include "IntRect.h" +#include "IntSize.h" + +namespace cc { + +class CCPrioritizedTextureManager; + +class CCPrioritizedTexture { +public: + static scoped_ptr create(CCPrioritizedTextureManager* manager, IntSize size, GC3Denum format) + { + return make_scoped_ptr(new CCPrioritizedTexture(manager, size, format)); + } + static scoped_ptr create(CCPrioritizedTextureManager* manager) + { + return make_scoped_ptr(new CCPrioritizedTexture(manager, IntSize(), 0)); + } + ~CCPrioritizedTexture(); + + // Texture properties. Changing these causes the backing texture to be lost. + // Setting these to the same value is a no-op. + void setTextureManager(CCPrioritizedTextureManager*); + CCPrioritizedTextureManager* textureManager() { return m_manager; } + void setDimensions(IntSize, GC3Denum format); + GC3Denum format() const { return m_format; } + IntSize size() const { return m_size; } + size_t bytes() const { return m_bytes; } + + // Set priority for the requested texture. + void setRequestPriority(int priority) { m_priority = priority; } + int requestPriority() const { return m_priority; } + + // After CCPrioritizedTexture::prioritizeTextures() is called, this returns + // if the the request succeeded and this texture can be acquired for use. + bool canAcquireBackingTexture() const { return m_isAbovePriorityCutoff; } + + // This returns whether we still have a backing texture. This can continue + // to be true even after canAcquireBackingTexture() becomes false. In this + // case the texture can be used but shouldn't be updated since it will get + // taken away "soon". + bool haveBackingTexture() const { return !!backing(); } + + bool backingResourceWasEvicted() const; + + // If canAcquireBackingTexture() is true acquireBackingTexture() will acquire + // a backing texture for use. Call this whenever the texture is actually needed. + void acquireBackingTexture(CCResourceProvider*); + + // FIXME: Request late is really a hack for when we are totally out of memory + // (all textures are visible) but we can still squeeze into the limit + // by not painting occluded textures. In this case the manager + // refuses all visible textures and requestLate() will enable + // canAcquireBackingTexture() on a call-order basis. We might want to + // just remove this in the future (carefully) and just make sure we don't + // regress OOMs situations. + bool requestLate(); + + // Uploads pixels into the backing resource. This functions will aquire the backing if needed. + void upload(CCResourceProvider*, const uint8_t* image, const IntRect& imageRect, const IntRect& sourceRect, const IntSize& destOffset); + + CCResourceProvider::ResourceId resourceId() const; + + // Self-managed textures are accounted for when prioritizing other textures, + // but they are not allocated/recycled/deleted, so this needs to be done + // externally. canAcquireBackingTexture() indicates if the texture would have + // been allowed given its priority. + void setIsSelfManaged(bool isSelfManaged) { m_isSelfManaged = isSelfManaged; } + bool isSelfManaged() { return m_isSelfManaged; } + void setToSelfManagedMemoryPlaceholder(size_t bytes); + +private: + friend class CCPrioritizedTextureManager; + friend class CCPrioritizedTextureTest; + + class Backing : public CCTexture { + public: + Backing(unsigned id, CCResourceProvider*, IntSize, GC3Denum format); + ~Backing(); + void updatePriority(); + + CCPrioritizedTexture* owner() { return m_owner; } + bool hadOwnerAtLastPriorityUpdate() const { return m_ownerExistedAtLastPriorityUpdate; } + int requestPriorityAtLastPriorityUpdate() const { return m_priorityAtLastPriorityUpdate; } + bool wasAbovePriorityCutoffAtLastPriorityUpdate() const { return m_wasAbovePriorityCutoffAtLastPriorityUpdate; } + + void deleteResource(CCResourceProvider*); + bool resourceHasBeenDeleted() const; + + private: + friend class CCPrioritizedTexture; + CCPrioritizedTexture* m_owner; + int m_priorityAtLastPriorityUpdate; + bool m_ownerExistedAtLastPriorityUpdate; + bool m_wasAbovePriorityCutoffAtLastPriorityUpdate; + bool m_resourceHasBeenDeleted; +#ifndef NDEBUG + CCResourceProvider* m_resourceProvider; +#endif + + DISALLOW_COPY_AND_ASSIGN(Backing); + }; + + CCPrioritizedTexture(CCPrioritizedTextureManager*, IntSize, GC3Denum format); + + bool isAbovePriorityCutoff() { return m_isAbovePriorityCutoff; } + void setAbovePriorityCutoff(bool isAbovePriorityCutoff) { m_isAbovePriorityCutoff = isAbovePriorityCutoff; } + void setManagerInternal(CCPrioritizedTextureManager* manager) { m_manager = manager; } + + Backing* backing() const { return m_backing; } + void link(Backing*); + void unlink(); + + IntSize m_size; + GC3Denum m_format; + size_t m_bytes; + + int m_priority; + bool m_isAbovePriorityCutoff; + bool m_isSelfManaged; + + Backing* m_backing; + CCPrioritizedTextureManager* m_manager; + + DISALLOW_COPY_AND_ASSIGN(CCPrioritizedTexture); +}; + +} // namespace cc + +#endif diff --git a/cc/prioritized_texture_manager.cc b/cc/prioritized_texture_manager.cc new file mode 100644 index 0000000..a609548 --- /dev/null +++ b/cc/prioritized_texture_manager.cc @@ -0,0 +1,410 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#include "CCPrioritizedTextureManager.h" + +#include "base/stl_util.h" +#include "CCPrioritizedTexture.h" +#include "CCPriorityCalculator.h" +#include "CCProxy.h" +#include "TraceEvent.h" +#include + +using namespace std; + +namespace cc { + +CCPrioritizedTextureManager::CCPrioritizedTextureManager(size_t maxMemoryLimitBytes, int, int pool) + : m_maxMemoryLimitBytes(maxMemoryLimitBytes) + , m_memoryUseBytes(0) + , m_memoryAboveCutoffBytes(0) + , m_memoryAvailableBytes(0) + , m_pool(pool) + , m_needsUpdateBackingsPrioritites(false) +{ +} + +CCPrioritizedTextureManager::~CCPrioritizedTextureManager() +{ + while (m_textures.size() > 0) + unregisterTexture(*m_textures.begin()); + + deleteEvictedBackings(); + + // Each remaining backing is a leaked opengl texture. There should be none. + ASSERT(m_backings.isEmpty()); +} + +void CCPrioritizedTextureManager::prioritizeTextures() +{ + TRACE_EVENT0("cc", "CCPrioritizedTextureManager::prioritizeTextures"); + ASSERT(CCProxy::isMainThread()); + + // Sorting textures in this function could be replaced by a slightly + // modified O(n) quick-select to partition textures rather than + // sort them (if performance of the sort becomes an issue). + + TextureVector& sortedTextures = m_tempTextureVector; + sortedTextures.clear(); + + // Copy all textures into a vector and sort them. + for (TextureSet::iterator it = m_textures.begin(); it != m_textures.end(); ++it) + sortedTextures.append(*it); + std::sort(sortedTextures.begin(), sortedTextures.end(), compareTextures); + + m_memoryAvailableBytes = m_maxMemoryLimitBytes; + m_priorityCutoff = CCPriorityCalculator::lowestPriority(); + size_t memoryBytes = 0; + for (TextureVector::iterator it = sortedTextures.begin(); it != sortedTextures.end(); ++it) { + if ((*it)->requestPriority() == CCPriorityCalculator::lowestPriority()) + break; + + if ((*it)->isSelfManaged()) { + // Account for self-managed memory immediately by reducing the memory + // available (since it never gets acquired). + size_t newMemoryBytes = memoryBytes + (*it)->bytes(); + if (newMemoryBytes > m_memoryAvailableBytes) { + m_priorityCutoff = (*it)->requestPriority(); + m_memoryAvailableBytes = memoryBytes; + break; + } + m_memoryAvailableBytes -= (*it)->bytes(); + } else { + size_t newMemoryBytes = memoryBytes + (*it)->bytes(); + if (newMemoryBytes > m_memoryAvailableBytes) { + m_priorityCutoff = (*it)->requestPriority(); + break; + } + memoryBytes = newMemoryBytes; + } + } + + // Only allow textures if they are higher than the cutoff. All textures + // of the same priority are accepted or rejected together, rather than + // being partially allowed randomly. + m_memoryAboveCutoffBytes = 0; + for (TextureVector::iterator it = sortedTextures.begin(); it != sortedTextures.end(); ++it) { + bool isAbovePriorityCutoff = CCPriorityCalculator::priorityIsHigher((*it)->requestPriority(), m_priorityCutoff); + (*it)->setAbovePriorityCutoff(isAbovePriorityCutoff); + if (isAbovePriorityCutoff && !(*it)->isSelfManaged()) + m_memoryAboveCutoffBytes += (*it)->bytes(); + } + sortedTextures.clear(); + + m_needsUpdateBackingsPrioritites = true; + + ASSERT(m_memoryAboveCutoffBytes <= m_memoryAvailableBytes); + ASSERT(memoryAboveCutoffBytes() <= maxMemoryLimitBytes()); +} + +void CCPrioritizedTextureManager::updateBackingsPriorities() +{ + TRACE_EVENT0("cc", "CCPrioritizedTextureManager::updateBackingsPriorities"); + ASSERT(CCProxy::isImplThread() && CCProxy::isMainThreadBlocked()); + + if (!m_needsUpdateBackingsPrioritites) + return; + +#if !ASSERT_DISABLED + assertInvariants(); +#endif + + // Update backings' priorities and put backings in eviction/recycling order. + BackingVector& sortedBackings = m_tempBackingVector; + sortedBackings.clear(); + for (BackingSet::iterator it = m_backings.begin(); it != m_backings.end(); ++it) { + (*it)->updatePriority(); + sortedBackings.append(*it); + } + std::sort(sortedBackings.begin(), sortedBackings.end(), compareBackings); + + for (BackingVector::iterator it = sortedBackings.begin(); it != sortedBackings.end(); ++it) { + m_backings.remove(*it); + m_backings.add(*it); + } + sortedBackings.clear(); + m_needsUpdateBackingsPrioritites = false; + +#if !ASSERT_DISABLED + assertInvariants(); +#endif +} + +void CCPrioritizedTextureManager::clearPriorities() +{ + ASSERT(CCProxy::isMainThread()); + for (TextureSet::iterator it = m_textures.begin(); it != m_textures.end(); ++it) { + // FIXME: We should remove this and just set all priorities to + // CCPriorityCalculator::lowestPriority() once we have priorities + // for all textures (we can't currently calculate distances for + // off-screen textures). + (*it)->setRequestPriority(CCPriorityCalculator::lingeringPriority((*it)->requestPriority())); + } +} + +bool CCPrioritizedTextureManager::requestLate(CCPrioritizedTexture* texture) +{ + ASSERT(CCProxy::isMainThread()); + + // This is already above cutoff, so don't double count it's memory below. + if (texture->isAbovePriorityCutoff()) + return true; + + if (CCPriorityCalculator::priorityIsLower(texture->requestPriority(), m_priorityCutoff)) + return false; + + size_t newMemoryBytes = m_memoryAboveCutoffBytes + texture->bytes(); + if (newMemoryBytes > m_memoryAvailableBytes) + return false; + + m_memoryAboveCutoffBytes = newMemoryBytes; + texture->setAbovePriorityCutoff(true); + m_needsUpdateBackingsPrioritites = true; + return true; +} + +void CCPrioritizedTextureManager::acquireBackingTextureIfNeeded(CCPrioritizedTexture* texture, CCResourceProvider* resourceProvider) +{ + ASSERT(CCProxy::isImplThread() && CCProxy::isMainThreadBlocked()); + ASSERT(!texture->isSelfManaged()); + ASSERT(texture->isAbovePriorityCutoff()); + if (texture->backing() || !texture->isAbovePriorityCutoff()) + return; + + // Make sure that the backings list is up to date and sorted before traversing it. + updateBackingsPriorities(); + + // Find a backing below, by either recycling or allocating. + CCPrioritizedTexture::Backing* backing = 0; + + // First try to recycle + for (BackingSet::iterator it = m_backings.begin(); it != m_backings.end(); ++it) { + if ((*it)->hadOwnerAtLastPriorityUpdate() && (*it)->wasAbovePriorityCutoffAtLastPriorityUpdate()) + break; + if ((*it)->size() == texture->size() && (*it)->format() == texture->format()) { + backing = (*it); + break; + } + } + + // Otherwise reduce memory and just allocate a new backing texures. + if (!backing) { + evictBackingsToReduceMemory(m_memoryAvailableBytes - texture->bytes(), RespectManagerPriorityCutoff, resourceProvider); + backing = createBacking(texture->size(), texture->format(), resourceProvider); + } + + // Move the used backing texture to the end of the eviction list. + if (backing->owner()) + backing->owner()->unlink(); + texture->link(backing); + m_backings.remove(backing); + m_backings.add(backing); + + // Update the backing's priority from its new owner. + backing->updatePriority(); +} + +void CCPrioritizedTextureManager::evictBackingsToReduceMemory(size_t limitBytes, EvictionPriorityPolicy evictionPolicy, CCResourceProvider* resourceProvider) +{ + ASSERT(CCProxy::isImplThread()); + if (memoryUseBytes() <= limitBytes) + return; + + // Destroy backings until we are below the limit, + // or until all backings remaining are above the cutoff. + while (memoryUseBytes() > limitBytes && m_backings.size() > 0) { + CCPrioritizedTexture::Backing* backing = *m_backings.begin(); + if (evictionPolicy == RespectManagerPriorityCutoff) + if (backing->hadOwnerAtLastPriorityUpdate() && backing->wasAbovePriorityCutoffAtLastPriorityUpdate()) + break; + evictBackingResource(backing, resourceProvider); + } +} + +void CCPrioritizedTextureManager::reduceMemory(CCResourceProvider* resourceProvider) +{ + ASSERT(CCProxy::isImplThread() && CCProxy::isMainThreadBlocked()); + + // Make sure that the backings list is up to date and sorted before traversing it. + updateBackingsPriorities(); + + evictBackingsToReduceMemory(m_memoryAvailableBytes, RespectManagerPriorityCutoff, resourceProvider); + ASSERT(memoryUseBytes() <= maxMemoryLimitBytes()); + + // We currently collect backings from deleted textures for later recycling. + // However, if we do that forever we will always use the max limit even if + // we really need very little memory. This should probably be solved by reducing the + // limit externally, but until then this just does some "clean up" of unused + // backing textures (any more than 10%). + size_t wastedMemory = 0; + for (BackingSet::iterator it = m_backings.begin(); it != m_backings.end(); ++it) { + if ((*it)->owner()) + break; + wastedMemory += (*it)->bytes(); + } + size_t tenPercentOfMemory = m_memoryAvailableBytes / 10; + if (wastedMemory > tenPercentOfMemory) + evictBackingsToReduceMemory(memoryUseBytes() - (wastedMemory - tenPercentOfMemory), RespectManagerPriorityCutoff, resourceProvider); + + deleteEvictedBackings(); +} + +void CCPrioritizedTextureManager::clearAllMemory(CCResourceProvider* resourceProvider) +{ + ASSERT(CCProxy::isImplThread() && CCProxy::isMainThreadBlocked()); + ASSERT(resourceProvider); + evictBackingsToReduceMemory(0, DoNotRespectManagerPriorityCutoff, resourceProvider); + deleteEvictedBackings(); +} + +void CCPrioritizedTextureManager::reduceMemoryOnImplThread(size_t limitBytes, CCResourceProvider* resourceProvider) +{ + ASSERT(CCProxy::isImplThread()); + ASSERT(resourceProvider); + evictBackingsToReduceMemory(limitBytes, DoNotRespectManagerPriorityCutoff, resourceProvider); +} + +void CCPrioritizedTextureManager::getEvictedBackings(BackingVector& evictedBackings) +{ + ASSERT(CCProxy::isImplThread()); + evictedBackings.clear(); + evictedBackings.append(m_evictedBackings); +} + +void CCPrioritizedTextureManager::unlinkEvictedBackings(const BackingVector& evictedBackings) +{ + ASSERT(CCProxy::isMainThread()); + for (BackingVector::const_iterator it = evictedBackings.begin(); it != evictedBackings.end(); ++it) { + CCPrioritizedTexture::Backing* backing = (*it); + if (backing->owner()) + backing->owner()->unlink(); + } +} + +bool CCPrioritizedTextureManager::deleteEvictedBackings() +{ + ASSERT(CCProxy::isMainThread() || (CCProxy::isImplThread() && CCProxy::isMainThreadBlocked())); + bool linkedEvictedBackingsExisted = false; + for (BackingVector::const_iterator it = m_evictedBackings.begin(); it != m_evictedBackings.end(); ++it) { + CCPrioritizedTexture::Backing* backing = (*it); + if (backing->owner()) { + linkedEvictedBackingsExisted = true; + backing->owner()->unlink(); + } + delete backing; + } + m_evictedBackings.clear(); + return linkedEvictedBackingsExisted; +} + +void CCPrioritizedTextureManager::registerTexture(CCPrioritizedTexture* texture) +{ + ASSERT(CCProxy::isMainThread()); + ASSERT(texture); + ASSERT(!texture->textureManager()); + ASSERT(!texture->backing()); + ASSERT(!ContainsKey(m_textures, texture)); + + texture->setManagerInternal(this); + m_textures.insert(texture); + +} + +void CCPrioritizedTextureManager::unregisterTexture(CCPrioritizedTexture* texture) +{ + ASSERT(CCProxy::isMainThread() || (CCProxy::isImplThread() && CCProxy::isMainThreadBlocked())); + ASSERT(texture); + ASSERT(ContainsKey(m_textures, texture)); + + returnBackingTexture(texture); + texture->setManagerInternal(0); + m_textures.erase(texture); + texture->setAbovePriorityCutoff(false); +} + +void CCPrioritizedTextureManager::returnBackingTexture(CCPrioritizedTexture* texture) +{ + ASSERT(CCProxy::isMainThread() || (CCProxy::isImplThread() && CCProxy::isMainThreadBlocked())); + if (texture->backing()) { + texture->unlink(); + m_needsUpdateBackingsPrioritites = true; + } +} + +CCPrioritizedTexture::Backing* CCPrioritizedTextureManager::createBacking(IntSize size, GC3Denum format, CCResourceProvider* resourceProvider) +{ + ASSERT(CCProxy::isImplThread() && CCProxy::isMainThreadBlocked()); + ASSERT(resourceProvider); + CCResourceProvider::ResourceId resourceId = resourceProvider->createResource(m_pool, size, format, CCResourceProvider::TextureUsageAny); + CCPrioritizedTexture::Backing* backing = new CCPrioritizedTexture::Backing(resourceId, resourceProvider, size, format); + m_memoryUseBytes += backing->bytes(); + // Put backing texture at the front for eviction, since it isn't in use yet. + m_backings.insertBefore(m_backings.begin(), backing); + return backing; +} + +void CCPrioritizedTextureManager::evictBackingResource(CCPrioritizedTexture::Backing* backing, CCResourceProvider* resourceProvider) +{ + ASSERT(CCProxy::isImplThread()); + ASSERT(backing); + ASSERT(resourceProvider); + ASSERT(m_backings.find(backing) != m_backings.end()); + + // Note that we create a backing and its resource at the same time, but we + // delete the backing structure and its resource in two steps. This is because + // we can delete the resource while the main thread is running, but we cannot + // unlink backings while the main thread is running. + backing->deleteResource(resourceProvider); + m_memoryUseBytes -= backing->bytes(); + m_backings.remove(backing); + m_evictedBackings.append(backing); +} + +#if !ASSERT_DISABLED +void CCPrioritizedTextureManager::assertInvariants() +{ + ASSERT(CCProxy::isImplThread() && CCProxy::isMainThreadBlocked()); + + // If we hit any of these asserts, there is a bug in this class. To see + // where the bug is, call this function at the beginning and end of + // every public function. + + // Backings/textures must be doubly-linked and only to other backings/textures in this manager. + for (BackingSet::iterator it = m_backings.begin(); it != m_backings.end(); ++it) { + if ((*it)->owner()) { + ASSERT(ContainsKey(m_textures, (*it)->owner())); + ASSERT((*it)->owner()->backing() == (*it)); + } + } + for (TextureSet::iterator it = m_textures.begin(); it != m_textures.end(); ++it) { + if ((*it)->backing()) { + ASSERT(m_backings.find((*it)->backing()) != m_backings.end()); + ASSERT((*it)->backing()->owner() == (*it)); + } + } + + // At all times, backings that can be evicted must always come before + // backings that can't be evicted in the backing texture list (otherwise + // reduceMemory will not find all textures available for eviction/recycling). + bool reachedOwned = false; + bool reachedAboveCutoff = false; + for (BackingSet::iterator it = m_backings.begin(); it != m_backings.end(); ++it) { + if ((*it)->hadOwnerAtLastPriorityUpdate()) + reachedOwned = true; + if ((*it)->wasAbovePriorityCutoffAtLastPriorityUpdate()) + reachedAboveCutoff = true; + if (reachedOwned) + ASSERT((*it)->hadOwnerAtLastPriorityUpdate()); + if (reachedAboveCutoff) { + ASSERT((*it)->hadOwnerAtLastPriorityUpdate() && (*it)->wasAbovePriorityCutoffAtLastPriorityUpdate()); + ASSERT(reachedOwned); + } + } +} +#endif + + +} // namespace cc diff --git a/cc/prioritized_texture_manager.h b/cc/prioritized_texture_manager.h index 638cbb2..1b3b1ed 100644 --- a/cc/prioritized_texture_manager.h +++ b/cc/prioritized_texture_manager.h @@ -1,3 +1,159 @@ // Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CCPrioritizedTextureManager_h +#define CCPrioritizedTextureManager_h + +#include "base/basictypes.h" +#include "base/hash_tables.h" +#include "base/memory/scoped_ptr.h" +#include "CCPrioritizedTexture.h" +#include "CCPriorityCalculator.h" +#include "CCTexture.h" +#include "GraphicsContext3D.h" +#include "IntRect.h" +#include "IntSize.h" +#include +#include + +#if defined(COMPILER_GCC) +namespace BASE_HASH_NAMESPACE { +template<> +struct hash { + size_t operator()(cc::CCPrioritizedTexture* ptr) const { + return hash()(reinterpret_cast(ptr)); + } +}; +} // namespace BASE_HASH_NAMESPACE +#endif // COMPILER + +namespace cc { + +class CCPriorityCalculator; + +class CCPrioritizedTextureManager { +public: + static scoped_ptr create(size_t maxMemoryLimitBytes, int maxTextureSize, int pool) + { + return make_scoped_ptr(new CCPrioritizedTextureManager(maxMemoryLimitBytes, maxTextureSize, pool)); + } + scoped_ptr createTexture(IntSize size, GC3Denum format) + { + return make_scoped_ptr(new CCPrioritizedTexture(this, size, format)); + } + ~CCPrioritizedTextureManager(); + + typedef Vector BackingVector; + + // FIXME (http://crbug.com/137094): This 64MB default is a straggler from the + // old texture manager and is just to give us a default memory allocation before + // we get a callback from the GPU memory manager. We should probaby either: + // - wait for the callback before rendering anything instead + // - push this into the GPU memory manager somehow. + static size_t defaultMemoryAllocationLimit() { return 64 * 1024 * 1024; } + + // memoryUseBytes() describes the number of bytes used by existing allocated textures. + // memoryAboveCutoffBytes() describes the number of bytes that would be used if all + // textures that are above the cutoff were allocated. + // memoryUseBytes() <= memoryAboveCutoffBytes() should always be true. + size_t memoryUseBytes() const { return m_memoryUseBytes; } + size_t memoryAboveCutoffBytes() const { return m_memoryAboveCutoffBytes; } + size_t memoryForSelfManagedTextures() const { return m_maxMemoryLimitBytes - m_memoryAvailableBytes; } + + void setMaxMemoryLimitBytes(size_t bytes) { m_maxMemoryLimitBytes = bytes; } + size_t maxMemoryLimitBytes() const { return m_maxMemoryLimitBytes; } + + void prioritizeTextures(); + void clearPriorities(); + + void reduceMemoryOnImplThread(size_t limitBytes, CCResourceProvider*); + bool evictedBackingsExist() const { return !m_evictedBackings.isEmpty(); } + void getEvictedBackings(BackingVector& evictedBackings); + void unlinkEvictedBackings(const BackingVector& evictedBackings); + // Deletes all evicted backings, unlinking them from their owning textures if needed. + // Returns true if this function unlinked any backings from their owning texture while + // destroying them. + bool deleteEvictedBackings(); + + bool requestLate(CCPrioritizedTexture*); + + void reduceMemory(CCResourceProvider*); + void clearAllMemory(CCResourceProvider*); + + void acquireBackingTextureIfNeeded(CCPrioritizedTexture*, CCResourceProvider*); + + void registerTexture(CCPrioritizedTexture*); + void unregisterTexture(CCPrioritizedTexture*); + void returnBackingTexture(CCPrioritizedTexture*); + +private: + friend class CCPrioritizedTextureTest; + + enum EvictionPriorityPolicy { + RespectManagerPriorityCutoff, + DoNotRespectManagerPriorityCutoff, + }; + + // Compare textures. Highest priority first. + static inline bool compareTextures(CCPrioritizedTexture* a, CCPrioritizedTexture* b) + { + if (a->requestPriority() == b->requestPriority()) + return a < b; + return CCPriorityCalculator::priorityIsHigher(a->requestPriority(), b->requestPriority()); + } + // Compare backings. Lowest priority first. + static inline bool compareBackings(CCPrioritizedTexture::Backing* a, CCPrioritizedTexture::Backing* b) + { + int priorityA = a->requestPriorityAtLastPriorityUpdate(); + int priorityB = b->requestPriorityAtLastPriorityUpdate(); + if (priorityA != priorityB) + return CCPriorityCalculator::priorityIsLower(priorityA, priorityB); + bool aboveCutoffA = a->wasAbovePriorityCutoffAtLastPriorityUpdate(); + bool aboveCutoffB = b->wasAbovePriorityCutoffAtLastPriorityUpdate(); + if (!aboveCutoffA && aboveCutoffB) + return true; + if (aboveCutoffA && !aboveCutoffB) + return false; + return a < b; + } + + CCPrioritizedTextureManager(size_t maxMemoryLimitBytes, int maxTextureSize, int pool); + + void updateBackingsPriorities(); + void evictBackingsToReduceMemory(size_t limitBytes, EvictionPriorityPolicy, CCResourceProvider*); + CCPrioritizedTexture::Backing* createBacking(IntSize, GC3Denum format, CCResourceProvider*); + void evictBackingResource(CCPrioritizedTexture::Backing*, CCResourceProvider*); + +#if !ASSERT_DISABLED + void assertInvariants(); +#endif + + size_t m_maxMemoryLimitBytes; + unsigned m_priorityCutoff; + size_t m_memoryUseBytes; + size_t m_memoryAboveCutoffBytes; + size_t m_memoryAvailableBytes; + int m_pool; + + typedef base::hash_set TextureSet; + typedef ListHashSet BackingSet; + typedef Vector TextureVector; + + TextureSet m_textures; + BackingSet m_backings; + BackingVector m_evictedBackings; + + TextureVector m_tempTextureVector; + BackingVector m_tempBackingVector; + + // Set by the main thread when it adjust priorities in such a way that + // the m_backings array's view of priorities is now out of date. + bool m_needsUpdateBackingsPrioritites; + + DISALLOW_COPY_AND_ASSIGN(CCPrioritizedTextureManager); +}; + +} // namespace cc + +#endif diff --git a/cc/priority_calculator.cc b/cc/priority_calculator.cc new file mode 100644 index 0000000..055520c --- /dev/null +++ b/cc/priority_calculator.cc @@ -0,0 +1,84 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#include "CCPriorityCalculator.h" + +using namespace std; + +namespace cc { + +static const int uiDrawsToRootSurfacePriority = -1; +static const int visibleDrawsToRootSurfacePriority = 0; +static const int renderSurfacesPriority = 1; +static const int uiDoesNotDrawToRootSurfacePriority = 2; +static const int visibleDoesNotDrawToRootSurfacePriority = 3; + +// The lower digits are how far from being visible the texture is, +// in pixels. +static const int notVisibleBasePriority = 1000000; +static const int notVisibleLimitPriority = 1900000; + +// Small animated layers are treated as though they are 512 pixels +// from being visible. +static const int smallAnimatedLayerPriority = notVisibleBasePriority + 512; + +static const int lingeringBasePriority = 2000000; +static const int lingeringLimitPriority = 2900000; + +// static +int CCPriorityCalculator::uiPriority(bool drawsToRootSurface) +{ + return drawsToRootSurface ? uiDrawsToRootSurfacePriority : uiDoesNotDrawToRootSurfacePriority; +} + +// static +int CCPriorityCalculator::visiblePriority(bool drawsToRootSurface) +{ + return drawsToRootSurface ? visibleDrawsToRootSurfacePriority : visibleDoesNotDrawToRootSurfacePriority; +} + +// static +int CCPriorityCalculator::renderSurfacePriority() +{ + return renderSurfacesPriority; +} + +// static +int CCPriorityCalculator::lingeringPriority(int previousPriority) +{ + // FIXME: We should remove this once we have priorities for all + // textures (we can't currently calculate distances for + // off-screen textures). + return min(lingeringLimitPriority, + max(lingeringBasePriority, previousPriority + 1)); +} + +namespace { +int manhattanDistance(const IntRect& a, const IntRect& b) +{ + IntRect c = unionRect(a, b); + int x = max(0, c.width() - a.width() - b.width() + 1); + int y = max(0, c.height() - a.height() - b.height() + 1); + return (x + y); +} +} + +// static +int CCPriorityCalculator::priorityFromDistance(const IntRect& visibleRect, const IntRect& textureRect, bool drawsToRootSurface) +{ + int distance = manhattanDistance(visibleRect, textureRect); + if (!distance) + return visiblePriority(drawsToRootSurface); + return min(notVisibleLimitPriority, notVisibleBasePriority + distance); +} + +// static +int CCPriorityCalculator::smallAnimatedLayerMinPriority() +{ + return smallAnimatedLayerPriority; +} + +} // cc diff --git a/cc/priority_calculator.h b/cc/priority_calculator.h index 638cbb2..45f2e64 100644 --- a/cc/priority_calculator.h +++ b/cc/priority_calculator.h @@ -1,3 +1,32 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. +// Copyright 2010 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CCPriorityCalculator_h +#define CCPriorityCalculator_h + +#include "GraphicsContext3D.h" +#include "IntRect.h" +#include "IntSize.h" + +namespace cc { + +class CCPriorityCalculator { +public: + static int uiPriority(bool drawsToRootSurface); + static int visiblePriority(bool drawsToRootSurface); + static int renderSurfacePriority(); + static int lingeringPriority(int previousPriority); + static int priorityFromDistance(const IntRect& visibleRect, const IntRect& textureRect, bool drawsToRootSurface); + static int smallAnimatedLayerMinPriority(); + + static inline int highestPriority() { return std::numeric_limits::min(); } + static inline int lowestPriority() { return std::numeric_limits::max(); } + static inline bool priorityIsLower(int a, int b) { return a > b; } + static inline bool priorityIsHigher(int a, int b) { return a < b; } + static inline bool maxPriority(int a, int b) { return priorityIsHigher(a, b) ? a : b; } +}; + +} + +#endif diff --git a/cc/program_binding.cc b/cc/program_binding.cc new file mode 100644 index 0000000..27d5226 --- /dev/null +++ b/cc/program_binding.cc @@ -0,0 +1,147 @@ +// Copyright 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#if USE(ACCELERATED_COMPOSITING) + +#include "ProgramBinding.h" + +#include "CCRendererGL.h" // For the GLC() macro. +#include "GeometryBinding.h" +#include "GraphicsContext3D.h" +#include "TraceEvent.h" +#include + +using WebKit::WebGraphicsContext3D; + +namespace cc { + +ProgramBindingBase::ProgramBindingBase() + : m_program(0) + , m_vertexShaderId(0) + , m_fragmentShaderId(0) + , m_initialized(false) +{ +} + +ProgramBindingBase::~ProgramBindingBase() +{ + // If you hit these asserts, you initialized but forgot to call cleanup(). + ASSERT(!m_program); + ASSERT(!m_vertexShaderId); + ASSERT(!m_fragmentShaderId); + ASSERT(!m_initialized); +} + +static bool contextLost(WebGraphicsContext3D* context) +{ + return (context->getGraphicsResetStatusARB() != GraphicsContext3D::NO_ERROR); +} + + +void ProgramBindingBase::init(WebGraphicsContext3D* context, const std::string& vertexShader, const std::string& fragmentShader) +{ + TRACE_EVENT0("cc", "ProgramBindingBase::init"); + m_vertexShaderId = loadShader(context, GraphicsContext3D::VERTEX_SHADER, vertexShader); + if (!m_vertexShaderId) { + if (!contextLost(context)) + LOG_ERROR("Failed to create vertex shader"); + return; + } + + m_fragmentShaderId = loadShader(context, GraphicsContext3D::FRAGMENT_SHADER, fragmentShader); + if (!m_fragmentShaderId) { + GLC(context, context->deleteShader(m_vertexShaderId)); + m_vertexShaderId = 0; + if (!contextLost(context)) + LOG_ERROR("Failed to create fragment shader"); + return; + } + + m_program = createShaderProgram(context, m_vertexShaderId, m_fragmentShaderId); + ASSERT(m_program || contextLost(context)); +} + +void ProgramBindingBase::link(WebGraphicsContext3D* context) +{ + GLC(context, context->linkProgram(m_program)); + cleanupShaders(context); +#ifndef NDEBUG + int linked = 0; + GLC(context, context->getProgramiv(m_program, GraphicsContext3D::LINK_STATUS, &linked)); + if (!linked) { + if (!contextLost(context)) + LOG_ERROR("Failed to link shader program"); + GLC(context, context->deleteProgram(m_program)); + return; + } +#endif +} + +void ProgramBindingBase::cleanup(WebGraphicsContext3D* context) +{ + m_initialized = false; + if (!m_program) + return; + + ASSERT(context); + GLC(context, context->deleteProgram(m_program)); + m_program = 0; + + cleanupShaders(context); +} + +unsigned ProgramBindingBase::loadShader(WebGraphicsContext3D* context, unsigned type, const std::string& shaderSource) +{ + unsigned shader = context->createShader(type); + if (!shader) + return 0; + GLC(context, context->shaderSource(shader, shaderSource.data())); + GLC(context, context->compileShader(shader)); +#ifndef NDEBUG + int compiled = 0; + GLC(context, context->getShaderiv(shader, GraphicsContext3D::COMPILE_STATUS, &compiled)); + if (!compiled) { + GLC(context, context->deleteShader(shader)); + return 0; + } +#endif + return shader; +} + +unsigned ProgramBindingBase::createShaderProgram(WebGraphicsContext3D* context, unsigned vertexShader, unsigned fragmentShader) +{ + unsigned programObject = context->createProgram(); + if (!programObject) { + if (!contextLost(context)) + LOG_ERROR("Failed to create shader program"); + return 0; + } + + GLC(context, context->attachShader(programObject, vertexShader)); + GLC(context, context->attachShader(programObject, fragmentShader)); + + // Bind the common attrib locations. + GLC(context, context->bindAttribLocation(programObject, GeometryBinding::positionAttribLocation(), "a_position")); + GLC(context, context->bindAttribLocation(programObject, GeometryBinding::texCoordAttribLocation(), "a_texCoord")); + + return programObject; +} + +void ProgramBindingBase::cleanupShaders(WebGraphicsContext3D* context) +{ + if (m_vertexShaderId) { + GLC(context, context->deleteShader(m_vertexShaderId)); + m_vertexShaderId = 0; + } + if (m_fragmentShaderId) { + GLC(context, context->deleteShader(m_fragmentShaderId)); + m_fragmentShaderId = 0; + } +} + +} // namespace cc + +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/cc/program_binding.h b/cc/program_binding.h index 638cbb2..9f0d067 100644 --- a/cc/program_binding.h +++ b/cc/program_binding.h @@ -1,3 +1,84 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. +// Copyright 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef ProgramBinding_h +#define ProgramBinding_h + +#if USE(ACCELERATED_COMPOSITING) + +#include + +namespace WebKit { +class WebGraphicsContext3D; +} + +namespace cc { + +class ProgramBindingBase { +public: + ProgramBindingBase(); + ~ProgramBindingBase(); + + void init(WebKit::WebGraphicsContext3D*, const std::string& vertexShader, const std::string& fragmentShader); + void link(WebKit::WebGraphicsContext3D*); + void cleanup(WebKit::WebGraphicsContext3D*); + + unsigned program() const { ASSERT(m_initialized); return m_program; } + bool initialized() const { return m_initialized; } + +protected: + + unsigned loadShader(WebKit::WebGraphicsContext3D*, unsigned type, const std::string& shaderSource); + unsigned createShaderProgram(WebKit::WebGraphicsContext3D*, unsigned vertexShader, unsigned fragmentShader); + void cleanupShaders(WebKit::WebGraphicsContext3D*); + + unsigned m_program; + unsigned m_vertexShaderId; + unsigned m_fragmentShaderId; + bool m_initialized; +}; + +template +class ProgramBinding : public ProgramBindingBase { +public: + explicit ProgramBinding(WebKit::WebGraphicsContext3D* context) + { + ProgramBindingBase::init(context, m_vertexShader.getShaderString(), m_fragmentShader.getShaderString()); + } + + void initialize(WebKit::WebGraphicsContext3D* context, bool usingBindUniform) + { + ASSERT(context); + ASSERT(m_program); + ASSERT(!m_initialized); + + // Need to bind uniforms before linking + if (!usingBindUniform) + link(context); + + int baseUniformIndex = 0; + m_vertexShader.init(context, m_program, usingBindUniform, &baseUniformIndex); + m_fragmentShader.init(context, m_program, usingBindUniform, &baseUniformIndex); + + // Link after binding uniforms + if (usingBindUniform) + link(context); + + m_initialized = true; + } + + const VertexShader& vertexShader() const { return m_vertexShader; } + const FragmentShader& fragmentShader() const { return m_fragmentShader; } + +private: + + VertexShader m_vertexShader; + FragmentShader m_fragmentShader; +}; + +} // namespace cc + +#endif // USE(ACCELERATED_COMPOSITING) + +#endif diff --git a/cc/proxy.cc b/cc/proxy.cc new file mode 100644 index 0000000..bc5ae69 --- /dev/null +++ b/cc/proxy.cc @@ -0,0 +1,105 @@ +// Copyright 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#include "CCProxy.h" + +#include "CCThreadTask.h" + +using namespace WTF; + +namespace cc { + +namespace { +#ifndef NDEBUG +bool implThreadIsOverridden = false; +bool s_isMainThreadBlocked = false; +base::PlatformThreadId threadIDOverridenToBeImplThread; +#endif +CCThread* s_mainThread = 0; +CCThread* s_implThread = 0; +} + +void CCProxy::setMainThread(CCThread* thread) +{ + s_mainThread = thread; +} + +CCThread* CCProxy::mainThread() +{ + return s_mainThread; +} + +bool CCProxy::hasImplThread() +{ + return s_implThread; +} + +void CCProxy::setImplThread(CCThread* thread) +{ + s_implThread = thread; +} + +CCThread* CCProxy::implThread() +{ + return s_implThread; +} + +CCThread* CCProxy::currentThread() +{ + base::PlatformThreadId currentThreadIdentifier = base::PlatformThread::CurrentId(); + if (s_mainThread && s_mainThread->threadID() == currentThreadIdentifier) + return s_mainThread; + if (s_implThread && s_implThread->threadID() == currentThreadIdentifier) + return s_implThread; + return 0; +} + +#ifndef NDEBUG +bool CCProxy::isMainThread() +{ + ASSERT(s_mainThread); + if (implThreadIsOverridden && base::PlatformThread::CurrentId() == threadIDOverridenToBeImplThread) + return false; + return base::PlatformThread::CurrentId() == s_mainThread->threadID(); +} + +bool CCProxy::isImplThread() +{ + base::PlatformThreadId implThreadID = s_implThread ? s_implThread->threadID() : 0; + if (implThreadIsOverridden && base::PlatformThread::CurrentId() == threadIDOverridenToBeImplThread) + return true; + return base::PlatformThread::CurrentId() == implThreadID; +} + +void CCProxy::setCurrentThreadIsImplThread(bool isImplThread) +{ + implThreadIsOverridden = isImplThread; + if (isImplThread) + threadIDOverridenToBeImplThread = base::PlatformThread::CurrentId(); +} + +bool CCProxy::isMainThreadBlocked() +{ + return s_isMainThreadBlocked; +} + +void CCProxy::setMainThreadBlocked(bool isMainThreadBlocked) +{ + s_isMainThreadBlocked = isMainThreadBlocked; +} +#endif + +CCProxy::CCProxy() +{ + ASSERT(isMainThread()); +} + +CCProxy::~CCProxy() +{ + ASSERT(isMainThread()); +} + +} diff --git a/cc/proxy.h b/cc/proxy.h index 638cbb2..30a62cc 100644 --- a/cc/proxy.h +++ b/cc/proxy.h @@ -1,3 +1,129 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. +// Copyright 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CCProxy_h +#define CCProxy_h + +#include "base/basictypes.h" +#include +#include +#include + +namespace cc { + +class CCThread; +class IntRect; +class IntSize; +struct CCRenderingStats; +struct RendererCapabilities; + +// Abstract class responsible for proxying commands from the main-thread side of +// the compositor over to the compositor implementation. +class CCProxy { +public: + static void setMainThread(CCThread*); + static CCThread* mainThread(); + + static bool hasImplThread(); + static void setImplThread(CCThread*); + static CCThread* implThread(); + + // Returns 0 if the current thread is neither the main thread nor the impl thread. + static CCThread* currentThread(); + + virtual ~CCProxy(); + + virtual bool compositeAndReadback(void *pixels, const IntRect&) = 0; + + virtual void startPageScaleAnimation(const IntSize& targetPosition, bool useAnchor, float scale, double durationSec) = 0; + + virtual void finishAllRendering() = 0; + + virtual bool isStarted() const = 0; + + // Attempts to initialize a context to use for rendering. Returns false if the context could not be created. + // The context will not be used and no frames may be produced until initializeRenderer() is called. + virtual bool initializeContext() = 0; + + // Indicates that the compositing surface associated with our context is ready to use. + virtual void setSurfaceReady() = 0; + + virtual void setVisible(bool) = 0; + + // Attempts to initialize the layer renderer. Returns false if the context isn't usable for compositing. + virtual bool initializeRenderer() = 0; + + // Attempts to recreate the context and layer renderer after a context lost. Returns false if the renderer couldn't be + // reinitialized. + virtual bool recreateContext() = 0; + + virtual void renderingStats(CCRenderingStats*) = 0; + + virtual const RendererCapabilities& rendererCapabilities() const = 0; + + virtual void setNeedsAnimate() = 0; + virtual void setNeedsCommit() = 0; + virtual void setNeedsRedraw() = 0; + + virtual void didAddAnimation() = 0; + + virtual bool commitRequested() const = 0; + + virtual void start() = 0; // Must be called before using the proxy. + virtual void stop() = 0; // Must be called before deleting the proxy. + + // Forces 3D commands on all contexts to wait for all previous SwapBuffers to finish before executing in the GPU + // process. + virtual void forceSerializeOnSwapBuffers() = 0; + + // Maximum number of sub-region texture updates supported for each commit. + virtual size_t maxPartialTextureUpdates() const = 0; + + virtual void acquireLayerTextures() = 0; + + // Debug hooks +#ifndef NDEBUG + static bool isMainThread(); + static bool isImplThread(); + static bool isMainThreadBlocked(); + static void setMainThreadBlocked(bool); +#endif + + // Testing hooks + virtual void loseContext() = 0; + +#ifndef NDEBUG + static void setCurrentThreadIsImplThread(bool); +#endif + +protected: + CCProxy(); + friend class DebugScopedSetImplThread; + friend class DebugScopedSetMainThreadBlocked; + +private: + DISALLOW_COPY_AND_ASSIGN(CCProxy); +}; + +class DebugScopedSetMainThreadBlocked { +public: + DebugScopedSetMainThreadBlocked() + { +#if !ASSERT_DISABLED + ASSERT(!CCProxy::isMainThreadBlocked()); + CCProxy::setMainThreadBlocked(true); +#endif + } + ~DebugScopedSetMainThreadBlocked() + { +#if !ASSERT_DISABLED + ASSERT(CCProxy::isMainThreadBlocked()); + CCProxy::setMainThreadBlocked(false); +#endif + } +}; + +} + +#endif diff --git a/cc/quad_culler.cc b/cc/quad_culler.cc new file mode 100644 index 0000000..8955a98 --- /dev/null +++ b/cc/quad_culler.cc @@ -0,0 +1,94 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#if USE(ACCELERATED_COMPOSITING) + +#include "CCQuadCuller.h" + +#include "CCAppendQuadsData.h" +#include "CCDebugBorderDrawQuad.h" +#include "CCLayerImpl.h" +#include "CCOcclusionTracker.h" +#include "CCOverdrawMetrics.h" +#include "CCRenderPass.h" +#include "Region.h" +#include "SkColor.h" +#include + +using namespace std; + +namespace cc { + +static const int debugTileBorderWidth = 1; +static const int debugTileBorderAlpha = 120; +static const int debugTileBorderColorRed = 160; +static const int debugTileBorderColorGreen = 100; +static const int debugTileBorderColorBlue = 0; + +CCQuadCuller::CCQuadCuller(CCQuadList& quadList, CCSharedQuadStateList& sharedQuadStateList, CCLayerImpl* layer, const CCOcclusionTrackerImpl* occlusionTracker, bool showCullingWithDebugBorderQuads, bool forSurface) + : m_quadList(quadList) + , m_sharedQuadStateList(sharedQuadStateList) + , m_currentSharedQuadState(0) + , m_layer(layer) + , m_occlusionTracker(occlusionTracker) + , m_showCullingWithDebugBorderQuads(showCullingWithDebugBorderQuads) + , m_forSurface(forSurface) +{ +} + +CCSharedQuadState* CCQuadCuller::useSharedQuadState(scoped_ptr sharedQuadState) +{ + sharedQuadState->id = m_sharedQuadStateList.size(); + + // FIXME: If all quads are culled for the sharedQuadState, we can drop it from the list. + m_currentSharedQuadState = sharedQuadState.get(); + m_sharedQuadStateList.append(sharedQuadState.Pass()); + return m_currentSharedQuadState; +} + +static inline bool appendQuadInternal(scoped_ptr drawQuad, const IntRect& culledRect, CCQuadList& quadList, const CCOcclusionTrackerImpl& occlusionTracker, bool createDebugBorderQuads) +{ + bool keepQuad = !culledRect.isEmpty(); + if (keepQuad) + drawQuad->setQuadVisibleRect(culledRect); + + occlusionTracker.overdrawMetrics().didCullForDrawing(drawQuad->quadTransform(), drawQuad->quadRect(), culledRect); + occlusionTracker.overdrawMetrics().didDraw(drawQuad->quadTransform(), culledRect, drawQuad->opaqueRect()); + + if (keepQuad) { + if (createDebugBorderQuads && !drawQuad->isDebugQuad() && drawQuad->quadVisibleRect() != drawQuad->quadRect()) { + SkColor borderColor = SkColorSetARGB(debugTileBorderAlpha, debugTileBorderColorRed, debugTileBorderColorGreen, debugTileBorderColorBlue); + quadList.append(CCDebugBorderDrawQuad::create(drawQuad->sharedQuadState(), drawQuad->quadVisibleRect(), borderColor, debugTileBorderWidth).PassAs()); + } + + // Pass the quad after we're done using it. + quadList.append(drawQuad.Pass()); + } + return keepQuad; +} + +bool CCQuadCuller::append(scoped_ptr drawQuad, CCAppendQuadsData& appendQuadsData) +{ + ASSERT(drawQuad->sharedQuadState() == m_currentSharedQuadState); + ASSERT(drawQuad->sharedQuadStateId() == m_currentSharedQuadState->id); + ASSERT(!m_sharedQuadStateList.isEmpty()); + ASSERT(m_sharedQuadStateList.last() == m_currentSharedQuadState); + + IntRect culledRect; + bool hasOcclusionFromOutsideTargetSurface; + + if (m_forSurface) + culledRect = m_occlusionTracker->unoccludedContributingSurfaceContentRect(m_layer, false, drawQuad->quadRect(), &hasOcclusionFromOutsideTargetSurface); + else + culledRect = m_occlusionTracker->unoccludedContentRect(m_layer, drawQuad->quadRect(), &hasOcclusionFromOutsideTargetSurface); + + appendQuadsData.hadOcclusionFromOutsideTargetSurface |= hasOcclusionFromOutsideTargetSurface; + + return appendQuadInternal(drawQuad.Pass(), culledRect, m_quadList, *m_occlusionTracker, m_showCullingWithDebugBorderQuads); +} + +} // namespace cc +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/cc/quad_culler.h b/cc/quad_culler.h index 638cbb2..b3927cc 100644 --- a/cc/quad_culler.h +++ b/cc/quad_culler.h @@ -1,3 +1,37 @@ // Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CCQuadCuller_h +#define CCQuadCuller_h + +#include "CCQuadSink.h" +#include "CCRenderPass.h" + +namespace cc { +class CCLayerImpl; +class CCRenderSurface; +template +class CCOcclusionTrackerBase; + +class CCQuadCuller : public CCQuadSink { +public: + CCQuadCuller(CCQuadList&, CCSharedQuadStateList&, CCLayerImpl*, const CCOcclusionTrackerBase*, bool showCullingWithDebugBorderQuads, bool forSurface); + virtual ~CCQuadCuller() { } + + // CCQuadSink implementation. + virtual CCSharedQuadState* useSharedQuadState(scoped_ptr) OVERRIDE; + virtual bool append(scoped_ptr, CCAppendQuadsData&) OVERRIDE; + +private: + CCQuadList& m_quadList; + CCSharedQuadStateList& m_sharedQuadStateList; + CCSharedQuadState* m_currentSharedQuadState; + CCLayerImpl* m_layer; + const CCOcclusionTrackerBase* m_occlusionTracker; + bool m_showCullingWithDebugBorderQuads; + bool m_forSurface; +}; + +} +#endif // CCQuadCuller_h diff --git a/cc/quad_sink.h b/cc/quad_sink.h index 638cbb2..06d31b0 100644 --- a/cc/quad_sink.h +++ b/cc/quad_sink.h @@ -1,3 +1,30 @@ // Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CCQuadSink_h +#define CCQuadSink_h + +#include "base/memory/scoped_ptr.h" + +namespace cc { + +class CCDrawQuad; + +struct CCAppendQuadsData; +struct CCSharedQuadState; + +class CCQuadSink { +public: + virtual ~CCQuadSink() { } + + // Call this to add a SharedQuadState before appending quads that refer to it. Returns a pointer + // to the given SharedQuadState for convenience, that can be set on the quads to append. + virtual CCSharedQuadState* useSharedQuadState(scoped_ptr) = 0; + + // Returns true if the quad is added to the list, and false if the quad is entirely culled. + virtual bool append(scoped_ptr passDrawQuad, CCAppendQuadsData&) = 0; +}; + +} +#endif // CCQuadCuller_h diff --git a/cc/rate_limiter.cc b/cc/rate_limiter.cc new file mode 100644 index 0000000..a521525 --- /dev/null +++ b/cc/rate_limiter.cc @@ -0,0 +1,87 @@ +// Copyright 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#if USE(ACCELERATED_COMPOSITING) +#include "RateLimiter.h" + +#include "CCProxy.h" +#include "CCThread.h" +#include "TraceEvent.h" +#include +#include + +namespace cc { + +class RateLimiter::Task : public CCThread::Task { +public: + static PassOwnPtr create(RateLimiter* rateLimiter) + { + return adoptPtr(new Task(rateLimiter)); + } + virtual ~Task() { } + +private: + explicit Task(RateLimiter* rateLimiter) + : CCThread::Task(this) + , m_rateLimiter(rateLimiter) + { + } + + virtual void performTask() OVERRIDE + { + m_rateLimiter->rateLimitContext(); + } + + scoped_refptr m_rateLimiter; +}; + +scoped_refptr RateLimiter::create(WebKit::WebGraphicsContext3D* context, RateLimiterClient *client) +{ + return make_scoped_refptr(new RateLimiter(context, client)); +} + +RateLimiter::RateLimiter(WebKit::WebGraphicsContext3D* context, RateLimiterClient *client) + : m_context(context) + , m_active(false) + , m_client(client) +{ + ASSERT(context); +} + +RateLimiter::~RateLimiter() +{ +} + +void RateLimiter::start() +{ + if (m_active) + return; + + TRACE_EVENT0("cc", "RateLimiter::start"); + m_active = true; + CCProxy::mainThread()->postTask(RateLimiter::Task::create(this)); +} + +void RateLimiter::stop() +{ + TRACE_EVENT0("cc", "RateLimiter::stop"); + m_client = 0; +} + +void RateLimiter::rateLimitContext() +{ + if (!m_client) + return; + + TRACE_EVENT0("cc", "RateLimiter::rateLimitContext"); + + m_active = false; + m_client->rateLimit(); + m_context->rateLimitOffscreenContextCHROMIUM(); +} + +} +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/cc/rate_limiter.h b/cc/rate_limiter.h index 638cbb2..7b48d74 100644 --- a/cc/rate_limiter.h +++ b/cc/rate_limiter.h @@ -1,3 +1,53 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. +// Copyright 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef RateLimiter_h +#define RateLimiter_h + +#if USE(ACCELERATED_COMPOSITING) + +#include "base/memory/ref_counted.h" + +namespace WebKit { +class WebGraphicsContext3D; +} + +namespace cc { + +class RateLimiterClient { +public: + virtual void rateLimit() = 0; +}; + +// A RateLimiter can be used to make sure that a single context does not dominate all execution time. +// To use, construct a RateLimiter class around the context and call start() whenever calls are made on the +// context outside of normal flow control. RateLimiter will block if the context is too far ahead of the +// compositor. +class RateLimiter : public base::RefCounted { +public: + static scoped_refptr create(WebKit::WebGraphicsContext3D*, RateLimiterClient*); + + void start(); + + // Context and client will not be accessed after stop(). + void stop(); + +private: + RateLimiter(WebKit::WebGraphicsContext3D*, RateLimiterClient*); + ~RateLimiter(); + friend class base::RefCounted; + + class Task; + friend class Task; + void rateLimitContext(); + + WebKit::WebGraphicsContext3D* m_context; + bool m_active; + RateLimiterClient *m_client; +}; + +} +#endif // USE(ACCELERATED_COMPOSITING) + +#endif diff --git a/cc/render_pass.cc b/cc/render_pass.cc new file mode 100644 index 0000000..513bd8b --- /dev/null +++ b/cc/render_pass.cc @@ -0,0 +1,106 @@ +// Copyright 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#include "CCRenderPass.h" + +#include "CCLayerImpl.h" +#include "CCMathUtil.h" +#include "CCOcclusionTracker.h" +#include "CCQuadCuller.h" +#include "CCSharedQuadState.h" +#include "CCSolidColorDrawQuad.h" + +using WebKit::WebTransformationMatrix; + +namespace cc { + +scoped_ptr CCRenderPass::create(Id id, IntRect outputRect, const WebKit::WebTransformationMatrix& transformToRootTarget) +{ + return make_scoped_ptr(new CCRenderPass(id, outputRect, transformToRootTarget)); +} + +CCRenderPass::CCRenderPass(Id id, IntRect outputRect, const WebKit::WebTransformationMatrix& transformToRootTarget) + : m_id(id) + , m_transformToRootTarget(transformToRootTarget) + , m_outputRect(outputRect) + , m_hasTransparentBackground(true) + , m_hasOcclusionFromOutsideTargetSurface(false) +{ + ASSERT(id.layerId > 0); + ASSERT(id.index >= 0); +} + +CCRenderPass::~CCRenderPass() +{ +} + +scoped_ptr CCRenderPass::copy(Id newId) const +{ + ASSERT(newId != m_id); + + scoped_ptr copyPass(create(newId, m_outputRect, m_transformToRootTarget)); + copyPass->setDamageRect(m_damageRect); + copyPass->setHasTransparentBackground(m_hasTransparentBackground); + copyPass->setHasOcclusionFromOutsideTargetSurface(m_hasOcclusionFromOutsideTargetSurface); + copyPass->setFilters(m_filters); + copyPass->setBackgroundFilters(m_backgroundFilters); + return copyPass.Pass(); +} + +void CCRenderPass::appendQuadsForLayer(CCLayerImpl* layer, CCOcclusionTrackerImpl* occlusionTracker, CCAppendQuadsData& appendQuadsData) +{ + const bool forSurface = false; + CCQuadCuller quadCuller(m_quadList, m_sharedQuadStateList, layer, occlusionTracker, layer->hasDebugBorders(), forSurface); + + layer->appendQuads(quadCuller, appendQuadsData); +} + +void CCRenderPass::appendQuadsForRenderSurfaceLayer(CCLayerImpl* layer, const CCRenderPass* contributingRenderPass, CCOcclusionTrackerImpl* occlusionTracker, CCAppendQuadsData& appendQuadsData) +{ + const bool forSurface = true; + CCQuadCuller quadCuller(m_quadList, m_sharedQuadStateList, layer, occlusionTracker, layer->hasDebugBorders(), forSurface); + + bool isReplica = false; + layer->renderSurface()->appendQuads(quadCuller, appendQuadsData, isReplica, contributingRenderPass->id()); + + // Add replica after the surface so that it appears below the surface. + if (layer->hasReplica()) { + isReplica = true; + layer->renderSurface()->appendQuads(quadCuller, appendQuadsData, isReplica, contributingRenderPass->id()); + } +} + +void CCRenderPass::appendQuadsToFillScreen(CCLayerImpl* rootLayer, SkColor screenBackgroundColor, const CCOcclusionTrackerImpl& occlusionTracker) +{ + if (!rootLayer || !screenBackgroundColor) + return; + + Region fillRegion = occlusionTracker.computeVisibleRegionInScreen(); + if (fillRegion.isEmpty()) + return; + + bool forSurface = false; + CCQuadCuller quadCuller(m_quadList, m_sharedQuadStateList, rootLayer, &occlusionTracker, rootLayer->hasDebugBorders(), forSurface); + + // Manually create the quad state for the gutter quads, as the root layer + // doesn't have any bounds and so can't generate this itself. + // FIXME: Make the gutter quads generated by the solid color layer (make it smarter about generating quads to fill unoccluded areas). + IntRect rootTargetRect = rootLayer->renderSurface()->contentRect(); + float opacity = 1; + bool opaque = true; + CCSharedQuadState* sharedQuadState = quadCuller.useSharedQuadState(CCSharedQuadState::create(rootLayer->drawTransform(), rootTargetRect, rootTargetRect, opacity, opaque)); + ASSERT(rootLayer->screenSpaceTransform().isInvertible()); + WebTransformationMatrix transformToLayerSpace = rootLayer->screenSpaceTransform().inverse(); + Vector fillRects = fillRegion.rects(); + for (size_t i = 0; i < fillRects.size(); ++i) { + // The root layer transform is composed of translations and scales only, no perspective, so mapping is sufficient. + IntRect layerRect = CCMathUtil::mapClippedRect(transformToLayerSpace, cc::IntRect(fillRects[i])); + // Skip the quad culler and just append the quads directly to avoid occlusion checks. + m_quadList.append(CCSolidColorDrawQuad::create(sharedQuadState, layerRect, screenBackgroundColor).PassAs()); + } +} + +} // namespace cc diff --git a/cc/render_pass.h b/cc/render_pass.h index 638cbb2..cdfa958 100644 --- a/cc/render_pass.h +++ b/cc/render_pass.h @@ -1,3 +1,140 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. +// Copyright 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CCRenderPass_h +#define CCRenderPass_h + +#include "base/basictypes.h" +#include "cc/hash_pair.h" +#include "cc/scoped_ptr_hash_map.h" +#include "cc/scoped_ptr_vector.h" +#include "CCDrawQuad.h" +#include "CCSharedQuadState.h" +#include "FloatRect.h" +#include "SkColor.h" +#include +#include +#include + +namespace cc { + +class CCLayerImpl; +template +class CCOcclusionTrackerBase; +class CCRenderSurface; + +struct CCAppendQuadsData; + +typedef CCOcclusionTrackerBase CCOcclusionTrackerImpl; + +// A list of CCDrawQuad objects, sorted internally in front-to-back order. +class CCQuadList : public ScopedPtrVector { +public: + typedef reverse_iterator backToFrontIterator; + typedef const_reverse_iterator constBackToFrontIterator; + + inline backToFrontIterator backToFrontBegin() { return rbegin(); } + inline backToFrontIterator backToFrontEnd() { return rend(); } + inline constBackToFrontIterator backToFrontBegin() const { return rbegin(); } + inline constBackToFrontIterator backToFrontEnd() const { return rend(); } +}; + +typedef ScopedPtrVector CCSharedQuadStateList; + +class CCRenderPass { +public: + ~CCRenderPass(); + + struct Id { + int layerId; + int index; + + Id(int layerId, int index) + : layerId(layerId) + , index(index) + { + } + + bool operator==(const Id& other) const { return layerId == other.layerId && index == other.index; } + bool operator!=(const Id& other) const { return !(*this == other); } + bool operator<(const Id& other) const { return layerId < other.layerId || (layerId == other.layerId && index < other.index); } + }; + + static scoped_ptr create(Id, IntRect outputRect, const WebKit::WebTransformationMatrix& transformToRootTarget); + + // A shallow copy of the render pass, which does not include its quads. + scoped_ptr copy(Id newId) const; + + void appendQuadsForLayer(CCLayerImpl*, CCOcclusionTrackerImpl*, CCAppendQuadsData&); + void appendQuadsForRenderSurfaceLayer(CCLayerImpl*, const CCRenderPass* contributingRenderPass, CCOcclusionTrackerImpl*, CCAppendQuadsData&); + void appendQuadsToFillScreen(CCLayerImpl* rootLayer, SkColor screenBackgroundColor, const CCOcclusionTrackerImpl&); + + const CCQuadList& quadList() const { return m_quadList; } + + Id id() const { return m_id; } + + // FIXME: Modify this transform when merging the RenderPass into a parent compositor. + // Transforms from quad's original content space to the root target's content space. + const WebKit::WebTransformationMatrix& transformToRootTarget() const { return m_transformToRootTarget; } + + // This denotes the bounds in physical pixels of the output generated by this RenderPass. + const IntRect& outputRect() const { return m_outputRect; } + + FloatRect damageRect() const { return m_damageRect; } + void setDamageRect(FloatRect rect) { m_damageRect = rect; } + + const WebKit::WebFilterOperations& filters() const { return m_filters; } + void setFilters(const WebKit::WebFilterOperations& filters) { m_filters = filters; } + + const WebKit::WebFilterOperations& backgroundFilters() const { return m_backgroundFilters; } + void setBackgroundFilters(const WebKit::WebFilterOperations& filters) { m_backgroundFilters = filters; } + + bool hasTransparentBackground() const { return m_hasTransparentBackground; } + void setHasTransparentBackground(bool transparent) { m_hasTransparentBackground = transparent; } + + bool hasOcclusionFromOutsideTargetSurface() const { return m_hasOcclusionFromOutsideTargetSurface; } + void setHasOcclusionFromOutsideTargetSurface(bool hasOcclusionFromOutsideTargetSurface) { m_hasOcclusionFromOutsideTargetSurface = hasOcclusionFromOutsideTargetSurface; } +protected: + CCRenderPass(Id, IntRect outputRect, const WebKit::WebTransformationMatrix& transformToRootTarget); + + Id m_id; + CCQuadList m_quadList; + CCSharedQuadStateList m_sharedQuadStateList; + WebKit::WebTransformationMatrix m_transformToRootTarget; + IntRect m_outputRect; + FloatRect m_damageRect; + bool m_hasTransparentBackground; + bool m_hasOcclusionFromOutsideTargetSurface; + WebKit::WebFilterOperations m_filters; + WebKit::WebFilterOperations m_backgroundFilters; + + DISALLOW_COPY_AND_ASSIGN(CCRenderPass); +}; + +} // namespace cc + +namespace BASE_HASH_NAMESPACE { +#if defined(COMPILER_MSVC) +template<> +inline size_t hash_value(const cc::CCRenderPass::Id& key) { + return hash_value >(std::pair(key.layerId, key.index)); +} +#elif defined(COMPILER_GCC) +template<> +struct hash { + size_t operator()(cc::CCRenderPass::Id key) const { + return hash >()(std::pair(key.layerId, key.index)); + } +}; +#else +#error define a hash function for your compiler +#endif // COMPILER +} + +namespace cc { +typedef std::vector CCRenderPassList; +typedef ScopedPtrHashMap CCRenderPassIdHashMap; +} // namespace cc + +#endif diff --git a/cc/render_pass_draw_quad.cc b/cc/render_pass_draw_quad.cc new file mode 100644 index 0000000..9e385c6 --- /dev/null +++ b/cc/render_pass_draw_quad.cc @@ -0,0 +1,50 @@ +// Copyright 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#include "CCRenderPassDrawQuad.h" + +namespace cc { + +scoped_ptr CCRenderPassDrawQuad::create(const CCSharedQuadState* sharedQuadState, const IntRect& quadRect, CCRenderPass::Id renderPassId, bool isReplica, const CCResourceProvider::ResourceId maskResourceId, const IntRect& contentsChangedSinceLastFrame, float maskTexCoordScaleX, float maskTexCoordScaleY, float maskTexCoordOffsetX, float maskTexCoordOffsetY) +{ + return make_scoped_ptr(new CCRenderPassDrawQuad(sharedQuadState, quadRect, renderPassId, isReplica, maskResourceId, contentsChangedSinceLastFrame, maskTexCoordScaleX, maskTexCoordScaleY, maskTexCoordOffsetX, maskTexCoordOffsetY)); +} + +CCRenderPassDrawQuad::CCRenderPassDrawQuad(const CCSharedQuadState* sharedQuadState, const IntRect& quadRect, CCRenderPass::Id renderPassId, bool isReplica, CCResourceProvider::ResourceId maskResourceId, const IntRect& contentsChangedSinceLastFrame, float maskTexCoordScaleX, float maskTexCoordScaleY, float maskTexCoordOffsetX, float maskTexCoordOffsetY) + : CCDrawQuad(sharedQuadState, CCDrawQuad::RenderPass, quadRect) + , m_renderPassId(renderPassId) + , m_isReplica(isReplica) + , m_maskResourceId(maskResourceId) + , m_contentsChangedSinceLastFrame(contentsChangedSinceLastFrame) + , m_maskTexCoordScaleX(maskTexCoordScaleX) + , m_maskTexCoordScaleY(maskTexCoordScaleY) + , m_maskTexCoordOffsetX(maskTexCoordOffsetX) + , m_maskTexCoordOffsetY(maskTexCoordOffsetY) +{ + ASSERT(m_renderPassId.layerId > 0); + ASSERT(m_renderPassId.index >= 0); +} + +const CCRenderPassDrawQuad* CCRenderPassDrawQuad::materialCast(const CCDrawQuad* quad) +{ + ASSERT(quad->material() == CCDrawQuad::RenderPass); + return static_cast(quad); +} + +scoped_ptr CCRenderPassDrawQuad::copy(const CCSharedQuadState* copiedSharedQuadState, CCRenderPass::Id copiedRenderPassId) const +{ + unsigned bytes = size(); + ASSERT(bytes); + + scoped_ptr copyQuad(reinterpret_cast(new char[bytes])); + memcpy(copyQuad.get(), this, bytes); + copyQuad->setSharedQuadState(copiedSharedQuadState); + copyQuad->m_renderPassId = copiedRenderPassId; + + return copyQuad.Pass(); +} + +} // namespace cc diff --git a/cc/render_pass_draw_quad.h b/cc/render_pass_draw_quad.h index 638cbb2..99222d9 100644 --- a/cc/render_pass_draw_quad.h +++ b/cc/render_pass_draw_quad.h @@ -1,3 +1,51 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. +// Copyright 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CCRenderPassDrawQuad_h +#define CCRenderPassDrawQuad_h + +#include "base/basictypes.h" +#include "base/memory/scoped_ptr.h" +#include "CCDrawQuad.h" +#include "CCRenderPass.h" +#include "CCResourceProvider.h" +#include "IntRect.h" + +namespace cc { + +class CCRenderPassDrawQuad : public CCDrawQuad { +public: + static scoped_ptr create(const CCSharedQuadState*, const IntRect&, CCRenderPass::Id renderPassId, bool isReplica, CCResourceProvider::ResourceId maskResourceId, const IntRect& contentsChangedSinceLastFrame, float maskTexCoordScaleX, float maskTexCoordScaleY, float maskTexCoordOffsetX, float maskTexCoordOffsetY); + + CCRenderPass::Id renderPassId() const { return m_renderPassId; } + bool isReplica() const { return m_isReplica; } + CCResourceProvider::ResourceId maskResourceId() const { return m_maskResourceId; } + const IntRect& contentsChangedSinceLastFrame() const { return m_contentsChangedSinceLastFrame; } + + static const CCRenderPassDrawQuad* materialCast(const CCDrawQuad*); + float maskTexCoordScaleX() const { return m_maskTexCoordScaleX; } + float maskTexCoordScaleY() const { return m_maskTexCoordScaleY; } + float maskTexCoordOffsetX() const { return m_maskTexCoordOffsetX; } + float maskTexCoordOffsetY() const { return m_maskTexCoordOffsetY; } + + scoped_ptr copy(const CCSharedQuadState* copiedSharedQuadState, CCRenderPass::Id copiedRenderPassId) const; + +private: + CCRenderPassDrawQuad(const CCSharedQuadState*, const IntRect&, CCRenderPass::Id renderPassId, bool isReplica, CCResourceProvider::ResourceId maskResourceId, const IntRect& contentsChangedSinceLastFrame, float maskTexCoordScaleX, float maskTexCoordScaleY, float maskTexCoordOffsetX, float maskTexCoordOffsetY); + + CCRenderPass::Id m_renderPassId; + bool m_isReplica; + CCResourceProvider::ResourceId m_maskResourceId; + IntRect m_contentsChangedSinceLastFrame; + float m_maskTexCoordScaleX; + float m_maskTexCoordScaleY; + float m_maskTexCoordOffsetX; + float m_maskTexCoordOffsetY; + + DISALLOW_COPY_AND_ASSIGN(CCRenderPassDrawQuad); +}; + +} + +#endif diff --git a/cc/render_pass_sink.h b/cc/render_pass_sink.h index 638cbb2..f3bac1d 100644 --- a/cc/render_pass_sink.h +++ b/cc/render_pass_sink.h @@ -1,3 +1,20 @@ // Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CCRenderPassSink_h +#define CCRenderPassSink_h + +#include "base/memory/scoped_ptr.h" + +namespace cc { + +class CCRenderPass; + +class CCRenderPassSink { +public: + virtual void appendRenderPass(scoped_ptr) = 0; +}; + +} +#endif // CCRenderPassSink_h diff --git a/cc/render_surface.cc b/cc/render_surface.cc new file mode 100644 index 0000000..320a3d8 --- /dev/null +++ b/cc/render_surface.cc @@ -0,0 +1,42 @@ +// Copyright 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#if USE(ACCELERATED_COMPOSITING) + +#include "RenderSurfaceChromium.h" + +#include "CCMathUtil.h" +#include "LayerChromium.h" +#include + +using WebKit::WebTransformationMatrix; + +namespace cc { + +RenderSurfaceChromium::RenderSurfaceChromium(LayerChromium* owningLayer) + : m_owningLayer(owningLayer) + , m_drawOpacity(1) + , m_drawOpacityIsAnimating(false) + , m_targetSurfaceTransformsAreAnimating(false) + , m_screenSpaceTransformsAreAnimating(false) + , m_nearestAncestorThatMovesPixels(0) +{ +} + +RenderSurfaceChromium::~RenderSurfaceChromium() +{ +} + +FloatRect RenderSurfaceChromium::drawableContentRect() const +{ + FloatRect drawableContentRect = CCMathUtil::mapClippedRect(m_drawTransform, m_contentRect); + if (m_owningLayer->hasReplica()) + drawableContentRect.unite(CCMathUtil::mapClippedRect(m_replicaDrawTransform, m_contentRect)); + return drawableContentRect; +} + +} +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/cc/render_surface.h b/cc/render_surface.h index 638cbb2..67ed626 100644 --- a/cc/render_surface.h +++ b/cc/render_surface.h @@ -1,3 +1,107 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. +// Copyright 2010 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + + +#ifndef RenderSurfaceChromium_h +#define RenderSurfaceChromium_h + +#if USE(ACCELERATED_COMPOSITING) + +#include "base/basictypes.h" +#include "base/memory/ref_counted.h" +#include "FloatRect.h" +#include "IntRect.h" +#include +#include + +namespace cc { + +class LayerChromium; + +class RenderSurfaceChromium { +public: + explicit RenderSurfaceChromium(LayerChromium*); + ~RenderSurfaceChromium(); + + // Returns the rect that encloses the RenderSurface including any reflection. + FloatRect drawableContentRect() const; + + const IntRect& contentRect() const { return m_contentRect; } + void setContentRect(const IntRect& contentRect) { m_contentRect = contentRect; } + + float drawOpacity() const { return m_drawOpacity; } + void setDrawOpacity(float drawOpacity) { m_drawOpacity = drawOpacity; } + + bool drawOpacityIsAnimating() const { return m_drawOpacityIsAnimating; } + void setDrawOpacityIsAnimating(bool drawOpacityIsAnimating) { m_drawOpacityIsAnimating = drawOpacityIsAnimating; } + + // This goes from content space with the origin in the center of the rect being transformed to the target space with the origin in the top left of the + // rect being transformed. Position the rect so that the origin is in the center of it before applying this transform. + const WebKit::WebTransformationMatrix& drawTransform() const { return m_drawTransform; } + void setDrawTransform(const WebKit::WebTransformationMatrix& drawTransform) { m_drawTransform = drawTransform; } + + const WebKit::WebTransformationMatrix& screenSpaceTransform() const { return m_screenSpaceTransform; } + void setScreenSpaceTransform(const WebKit::WebTransformationMatrix& screenSpaceTransform) { m_screenSpaceTransform = screenSpaceTransform; } + + const WebKit::WebTransformationMatrix& replicaDrawTransform() const { return m_replicaDrawTransform; } + void setReplicaDrawTransform(const WebKit::WebTransformationMatrix& replicaDrawTransform) { m_replicaDrawTransform = replicaDrawTransform; } + + const WebKit::WebTransformationMatrix& replicaScreenSpaceTransform() const { return m_replicaScreenSpaceTransform; } + void setReplicaScreenSpaceTransform(const WebKit::WebTransformationMatrix& replicaScreenSpaceTransform) { m_replicaScreenSpaceTransform = replicaScreenSpaceTransform; } + + bool targetSurfaceTransformsAreAnimating() const { return m_targetSurfaceTransformsAreAnimating; } + void setTargetSurfaceTransformsAreAnimating(bool animating) { m_targetSurfaceTransformsAreAnimating = animating; } + bool screenSpaceTransformsAreAnimating() const { return m_screenSpaceTransformsAreAnimating; } + void setScreenSpaceTransformsAreAnimating(bool animating) { m_screenSpaceTransformsAreAnimating = animating; } + + const IntRect& clipRect() const { return m_clipRect; } + void setClipRect(const IntRect& clipRect) { m_clipRect = clipRect; } + + typedef std::vector > LayerList; + LayerList& layerList() { return m_layerList; } + // A no-op since DelegatedRendererLayers on the main thread don't have any + // RenderPasses so they can't contribute to a surface. + void addContributingDelegatedRenderPassLayer(LayerChromium*) { } + void clearLayerLists() { m_layerList.clear(); } + + void setNearestAncestorThatMovesPixels(RenderSurfaceChromium* surface) { m_nearestAncestorThatMovesPixels = surface; } + const RenderSurfaceChromium* nearestAncestorThatMovesPixels() const { return m_nearestAncestorThatMovesPixels; } + +private: + friend struct CCLayerIteratorActions; + + LayerChromium* m_owningLayer; + + // Uses this surface's space. + IntRect m_contentRect; + + float m_drawOpacity; + bool m_drawOpacityIsAnimating; + WebKit::WebTransformationMatrix m_drawTransform; + WebKit::WebTransformationMatrix m_screenSpaceTransform; + WebKit::WebTransformationMatrix m_replicaDrawTransform; + WebKit::WebTransformationMatrix m_replicaScreenSpaceTransform; + bool m_targetSurfaceTransformsAreAnimating; + bool m_screenSpaceTransformsAreAnimating; + + // Uses the space of the surface's target surface. + IntRect m_clipRect; + + LayerList m_layerList; + + // The nearest ancestor target surface that will contain the contents of this surface, and that is going + // to move pixels within the surface (such as with a blur). This can point to itself. + RenderSurfaceChromium* m_nearestAncestorThatMovesPixels; + + // For CCLayerIteratorActions + int m_targetRenderSurfaceLayerIndexHistory; + int m_currentLayerIndexHistory; + + DISALLOW_COPY_AND_ASSIGN(RenderSurfaceChromium); +}; + +} +#endif // USE(ACCELERATED_COMPOSITING) + +#endif diff --git a/cc/render_surface_filters.cc b/cc/render_surface_filters.cc new file mode 100644 index 0000000..40344c6 --- /dev/null +++ b/cc/render_surface_filters.cc @@ -0,0 +1,446 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#if USE(ACCELERATED_COMPOSITING) + +#include "CCRenderSurfaceFilters.h" + +#include "FloatSize.h" +#include "SkBlurImageFilter.h" +#include "SkCanvas.h" +#include "SkColorMatrixFilter.h" +#include "SkGpuDevice.h" +#include "SkGrPixelRef.h" +#include "SkMagnifierImageFilter.h" +#include +#include +#include +#include + +using namespace cc; + +namespace { + +void getBrightnessMatrix(float amount, SkScalar matrix[20]) +{ + memset(matrix, 0, 20 * sizeof(SkScalar)); + // Old implementation, a la the draft spec, a straight-up scale, + // representing + // (See http://dvcs.w3.org/hg/FXTF/raw-file/tip/filters/index.html#brightnessEquivalent) + // matrix[0] = matrix[6] = matrix[12] = amount; + // matrix[18] = 1; + // New implementation, a translation in color space, representing + // + // (See https://www.w3.org/Bugs/Public/show_bug.cgi?id=15647) + matrix[0] = matrix[6] = matrix[12] = matrix[18] = 1; + matrix[4] = matrix[9] = matrix[14] = amount * 255; +} + +void getContrastMatrix(float amount, SkScalar matrix[20]) +{ + memset(matrix, 0, 20 * sizeof(SkScalar)); + matrix[0] = matrix[6] = matrix[12] = amount; + matrix[4] = matrix[9] = matrix[14] = (-0.5f * amount + 0.5f) * 255; + matrix[18] = 1; +} + +void getSaturateMatrix(float amount, SkScalar matrix[20]) +{ + // Note, these values are computed to ensure matrixNeedsClamping is false + // for amount in [0..1] + matrix[0] = 0.213f + 0.787f * amount; + matrix[1] = 0.715f - 0.715f * amount; + matrix[2] = 1.f - (matrix[0] + matrix[1]); + matrix[3] = matrix[4] = 0; + matrix[5] = 0.213f - 0.213f * amount; + matrix[6] = 0.715f + 0.285f * amount; + matrix[7] = 1.f - (matrix[5] + matrix[6]); + matrix[8] = matrix[9] = 0; + matrix[10] = 0.213f - 0.213f * amount; + matrix[11] = 0.715f - 0.715f * amount; + matrix[12] = 1.f - (matrix[10] + matrix[11]); + matrix[13] = matrix[14] = 0; + matrix[15] = matrix[16] = matrix[17] = matrix[19] = 0; + matrix[18] = 1; +} + +void getHueRotateMatrix(float hue, SkScalar matrix[20]) +{ + float cosHue = cosf(hue * piFloat / 180); + float sinHue = sinf(hue * piFloat / 180); + matrix[0] = 0.213f + cosHue * 0.787f - sinHue * 0.213f; + matrix[1] = 0.715f - cosHue * 0.715f - sinHue * 0.715f; + matrix[2] = 0.072f - cosHue * 0.072f + sinHue * 0.928f; + matrix[3] = matrix[4] = 0; + matrix[5] = 0.213f - cosHue * 0.213f + sinHue * 0.143f; + matrix[6] = 0.715f + cosHue * 0.285f + sinHue * 0.140f; + matrix[7] = 0.072f - cosHue * 0.072f - sinHue * 0.283f; + matrix[8] = matrix[9] = 0; + matrix[10] = 0.213f - cosHue * 0.213f - sinHue * 0.787f; + matrix[11] = 0.715f - cosHue * 0.715f + sinHue * 0.715f; + matrix[12] = 0.072f + cosHue * 0.928f + sinHue * 0.072f; + matrix[13] = matrix[14] = 0; + matrix[15] = matrix[16] = matrix[17] = 0; + matrix[18] = 1; + matrix[19] = 0; +} + +void getInvertMatrix(float amount, SkScalar matrix[20]) +{ + memset(matrix, 0, 20 * sizeof(SkScalar)); + matrix[0] = matrix[6] = matrix[12] = 1 - 2 * amount; + matrix[4] = matrix[9] = matrix[14] = amount * 255; + matrix[18] = 1; +} + +void getOpacityMatrix(float amount, SkScalar matrix[20]) +{ + memset(matrix, 0, 20 * sizeof(SkScalar)); + matrix[0] = matrix[6] = matrix[12] = 1; + matrix[18] = amount; +} + +void getGrayscaleMatrix(float amount, SkScalar matrix[20]) +{ + // Note, these values are computed to ensure matrixNeedsClamping is false + // for amount in [0..1] + matrix[0] = 0.2126f + 0.7874f * amount; + matrix[1] = 0.7152f - 0.7152f * amount; + matrix[2] = 1.f - (matrix[0] + matrix[1]); + matrix[3] = matrix[4] = 0; + + matrix[5] = 0.2126f - 0.2126f * amount; + matrix[6] = 0.7152f + 0.2848f * amount; + matrix[7] = 1.f - (matrix[5] + matrix[6]); + matrix[8] = matrix[9] = 0; + + matrix[10] = 0.2126f - 0.2126f * amount; + matrix[11] = 0.7152f - 0.7152f * amount; + matrix[12] = 1.f - (matrix[10] + matrix[11]); + matrix[13] = matrix[14] = 0; + + matrix[15] = matrix[16] = matrix[17] = matrix[19] = 0; + matrix[18] = 1; +} + +void getSepiaMatrix(float amount, SkScalar matrix[20]) +{ + matrix[0] = 0.393f + 0.607f * amount; + matrix[1] = 0.769f - 0.769f * amount; + matrix[2] = 0.189f - 0.189f * amount; + matrix[3] = matrix[4] = 0; + + matrix[5] = 0.349f - 0.349f * amount; + matrix[6] = 0.686f + 0.314f * amount; + matrix[7] = 0.168f - 0.168f * amount; + matrix[8] = matrix[9] = 0; + + matrix[10] = 0.272f - 0.272f * amount; + matrix[11] = 0.534f - 0.534f * amount; + matrix[12] = 0.131f + 0.869f * amount; + matrix[13] = matrix[14] = 0; + + matrix[15] = matrix[16] = matrix[17] = matrix[19] = 0; + matrix[18] = 1; +} + +// The 5x4 matrix is really a "compressed" version of a 5x5 matrix that'd have +// (0 0 0 0 1) as a last row, and that would be applied to a 5-vector extended +// from the 4-vector color with a 1. +void multColorMatrix(SkScalar a[20], SkScalar b[20], SkScalar out[20]) +{ + for (int j = 0; j < 4; ++j) { + for (int i = 0; i < 5; ++i) { + out[i+j*5] = i == 4 ? a[4+j*5] : 0; + for (int k = 0; k < 4; ++k) + out[i+j*5] += a[k+j*5] * b[i+k*5]; + } + } +} + +// To detect if we need to apply clamping after applying a matrix, we check if +// any output component might go outside of [0, 255] for any combination of +// input components in [0..255]. +// Each output component is an affine transformation of the input component, so +// the minimum and maximum values are for any combination of minimum or maximum +// values of input components (i.e. 0 or 255). +// E.g. if R' = x*R + y*G + z*B + w*A + t +// Then the maximum value will be for R=255 if x>0 or R=0 if x<0, and the +// minimum value will be for R=0 if x>0 or R=255 if x<0. +// Same goes for all components. +bool componentNeedsClamping(SkScalar row[5]) +{ + SkScalar maxValue = row[4] / 255; + SkScalar minValue = row[4] / 255; + for (int i = 0; i < 4; ++i) { + if (row[i] > 0) + maxValue += row[i]; + else + minValue += row[i]; + } + return (maxValue > 1) || (minValue < 0); +} + +bool matrixNeedsClamping(SkScalar matrix[20]) +{ + return componentNeedsClamping(matrix) + || componentNeedsClamping(matrix+5) + || componentNeedsClamping(matrix+10) + || componentNeedsClamping(matrix+15); +} + +bool getColorMatrix(const WebKit::WebFilterOperation& op, SkScalar matrix[20]) +{ + switch (op.type()) { + case WebKit::WebFilterOperation::FilterTypeBrightness: { + getBrightnessMatrix(op.amount(), matrix); + return true; + } + case WebKit::WebFilterOperation::FilterTypeContrast: { + getContrastMatrix(op.amount(), matrix); + return true; + } + case WebKit::WebFilterOperation::FilterTypeGrayscale: { + getGrayscaleMatrix(1 - op.amount(), matrix); + return true; + } + case WebKit::WebFilterOperation::FilterTypeSepia: { + getSepiaMatrix(1 - op.amount(), matrix); + return true; + } + case WebKit::WebFilterOperation::FilterTypeSaturate: { + getSaturateMatrix(op.amount(), matrix); + return true; + } + case WebKit::WebFilterOperation::FilterTypeHueRotate: { + getHueRotateMatrix(op.amount(), matrix); + return true; + } + case WebKit::WebFilterOperation::FilterTypeInvert: { + getInvertMatrix(op.amount(), matrix); + return true; + } + case WebKit::WebFilterOperation::FilterTypeOpacity: { + getOpacityMatrix(op.amount(), matrix); + return true; + } + case WebKit::WebFilterOperation::FilterTypeColorMatrix: { + memcpy(matrix, op.matrix(), sizeof(SkScalar[20])); + return true; + } + default: + return false; + } +} + +class FilterBufferState { +public: + FilterBufferState(GrContext* grContext, const FloatSize& size, unsigned textureId) + : m_grContext(grContext) + , m_currentTexture(0) + { + // Wrap the source texture in a Ganesh platform texture. + GrPlatformTextureDesc platformTextureDescription; + platformTextureDescription.fWidth = size.width(); + platformTextureDescription.fHeight = size.height(); + platformTextureDescription.fConfig = kSkia8888_GrPixelConfig; + platformTextureDescription.fTextureHandle = textureId; + SkAutoTUnref texture(grContext->createPlatformTexture(platformTextureDescription)); + // Place the platform texture inside an SkBitmap. + m_source.setConfig(SkBitmap::kARGB_8888_Config, size.width(), size.height()); + m_source.setPixelRef(new SkGrPixelRef(texture.get()))->unref(); + } + + ~FilterBufferState() { } + + bool init(int filterCount) + { + int scratchCount = std::min(2, filterCount); + GrTextureDesc desc; + desc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit; + desc.fSampleCnt = 0; + desc.fWidth = m_source.width(); + desc.fHeight = m_source.height(); + desc.fConfig = kSkia8888_GrPixelConfig; + for (int i = 0; i < scratchCount; ++i) { + GrAutoScratchTexture scratchTexture(m_grContext, desc, GrContext::kExact_ScratchTexMatch); + m_scratchTextures[i].reset(scratchTexture.detach()); + if (!m_scratchTextures[i].get()) + return false; + } + return true; + } + + SkCanvas* canvas() + { + if (!m_canvas.get()) + createCanvas(); + return m_canvas.get(); + } + + const SkBitmap& source() { return m_source; } + + void swap() + { + m_canvas->flush(); + m_canvas.reset(0); + m_device.reset(0); + + m_source.setPixelRef(new SkGrPixelRef(m_scratchTextures[m_currentTexture].get()))->unref(); + m_currentTexture = 1 - m_currentTexture; + } + +private: + void createCanvas() + { + ASSERT(m_scratchTextures[m_currentTexture].get()); + m_device.reset(new SkGpuDevice(m_grContext, m_scratchTextures[m_currentTexture].get())); + m_canvas.reset(new SkCanvas(m_device.get())); + m_canvas->clear(0x0); + } + + GrContext* m_grContext; + SkBitmap m_source; + SkAutoTUnref m_scratchTextures[2]; + int m_currentTexture; + SkAutoTUnref m_device; + SkAutoTUnref m_canvas; +}; + +} + +namespace cc { + +WebKit::WebFilterOperations CCRenderSurfaceFilters::optimize(const WebKit::WebFilterOperations& filters) +{ + WebKit::WebFilterOperations newList; + + SkScalar accumulatedColorMatrix[20]; + bool haveAccumulatedColorMatrix = false; + for (unsigned i = 0; i < filters.size(); ++i) { + const WebKit::WebFilterOperation& op = filters.at(i); + + // If the filter is a color matrix, we may be able to combine it with + // following filter(s) that also are color matrices. + SkScalar matrix[20]; + if (getColorMatrix(op, matrix)) { + if (haveAccumulatedColorMatrix) { + SkScalar newMatrix[20]; + multColorMatrix(matrix, accumulatedColorMatrix, newMatrix); + memcpy(accumulatedColorMatrix, newMatrix, sizeof(accumulatedColorMatrix)); + } else { + memcpy(accumulatedColorMatrix, matrix, sizeof(accumulatedColorMatrix)); + haveAccumulatedColorMatrix = true; + } + + // We can only combine matrices if clamping of color components + // would have no effect. + if (!matrixNeedsClamping(accumulatedColorMatrix)) + continue; + } + + if (haveAccumulatedColorMatrix) + newList.append(WebKit::WebFilterOperation::createColorMatrixFilter(accumulatedColorMatrix)); + haveAccumulatedColorMatrix = false; + + switch (op.type()) { + case WebKit::WebFilterOperation::FilterTypeBlur: + case WebKit::WebFilterOperation::FilterTypeDropShadow: + case WebKit::WebFilterOperation::FilterTypeZoom: + newList.append(op); + break; + case WebKit::WebFilterOperation::FilterTypeBrightness: + case WebKit::WebFilterOperation::FilterTypeContrast: + case WebKit::WebFilterOperation::FilterTypeGrayscale: + case WebKit::WebFilterOperation::FilterTypeSepia: + case WebKit::WebFilterOperation::FilterTypeSaturate: + case WebKit::WebFilterOperation::FilterTypeHueRotate: + case WebKit::WebFilterOperation::FilterTypeInvert: + case WebKit::WebFilterOperation::FilterTypeOpacity: + case WebKit::WebFilterOperation::FilterTypeColorMatrix: + break; + } + } + if (haveAccumulatedColorMatrix) + newList.append(WebKit::WebFilterOperation::createColorMatrixFilter(accumulatedColorMatrix)); + return newList; +} + +SkBitmap CCRenderSurfaceFilters::apply(const WebKit::WebFilterOperations& filters, unsigned textureId, const FloatSize& size, WebKit::WebGraphicsContext3D* context3D, GrContext* grContext) +{ + if (!context3D || !grContext) + return SkBitmap(); + + WebKit::WebFilterOperations optimizedFilters = optimize(filters); + FilterBufferState state(grContext, size, textureId); + if (!state.init(optimizedFilters.size())) + return SkBitmap(); + + for (unsigned i = 0; i < optimizedFilters.size(); ++i) { + const WebKit::WebFilterOperation& op = optimizedFilters.at(i); + SkCanvas* canvas = state.canvas(); + switch (op.type()) { + case WebKit::WebFilterOperation::FilterTypeColorMatrix: { + SkPaint paint; + paint.setColorFilter(new SkColorMatrixFilter(op.matrix()))->unref(); + canvas->drawBitmap(state.source(), 0, 0, &paint); + break; + } + case WebKit::WebFilterOperation::FilterTypeBlur: { + float stdDeviation = op.amount(); + SkAutoTUnref filter(new SkBlurImageFilter(stdDeviation, stdDeviation)); + SkPaint paint; + paint.setImageFilter(filter.get()); + canvas->drawSprite(state.source(), 0, 0, &paint); + break; + } + case WebKit::WebFilterOperation::FilterTypeDropShadow: { + SkAutoTUnref blurFilter(new SkBlurImageFilter(op.amount(), op.amount())); + SkAutoTUnref colorFilter(SkColorFilter::CreateModeFilter(op.dropShadowColor(), SkXfermode::kSrcIn_Mode)); + SkPaint paint; + paint.setImageFilter(blurFilter.get()); + paint.setColorFilter(colorFilter.get()); + paint.setXfermodeMode(SkXfermode::kSrcOver_Mode); + canvas->saveLayer(0, &paint); + canvas->drawBitmap(state.source(), op.dropShadowOffset().x, -op.dropShadowOffset().y); + canvas->restore(); + canvas->drawBitmap(state.source(), 0, 0); + break; + } + case WebKit::WebFilterOperation::FilterTypeZoom: { + SkPaint paint; + SkAutoTUnref zoomFilter( + new SkMagnifierImageFilter( + SkRect::MakeXYWH(op.zoomRect().x, + op.zoomRect().y, + op.zoomRect().width, + op.zoomRect().height), + op.amount())); + paint.setImageFilter(zoomFilter.get()); + canvas->saveLayer(0, &paint); + canvas->drawBitmap(state.source(), 0, 0); + canvas->restore(); + break; + } + case WebKit::WebFilterOperation::FilterTypeBrightness: + case WebKit::WebFilterOperation::FilterTypeContrast: + case WebKit::WebFilterOperation::FilterTypeGrayscale: + case WebKit::WebFilterOperation::FilterTypeSepia: + case WebKit::WebFilterOperation::FilterTypeSaturate: + case WebKit::WebFilterOperation::FilterTypeHueRotate: + case WebKit::WebFilterOperation::FilterTypeInvert: + case WebKit::WebFilterOperation::FilterTypeOpacity: + ASSERT_NOT_REACHED(); + break; + } + state.swap(); + } + context3D->flush(); + return state.source(); +} + +} +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/cc/render_surface_filters.h b/cc/render_surface_filters.h index 638cbb2..cd199b5 100644 --- a/cc/render_surface_filters.h +++ b/cc/render_surface_filters.h @@ -1,3 +1,34 @@ // Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + + +#ifndef CCRenderSurfaceFilters_h +#define CCRenderSurfaceFilters_h + +#if USE(ACCELERATED_COMPOSITING) + +class GrContext; +class SkBitmap; + +namespace WebKit { +class WebFilterOperations; +class WebGraphicsContext3D; +} + +namespace cc { +class FloatSize; + +class CCRenderSurfaceFilters { +public: + static SkBitmap apply(const WebKit::WebFilterOperations& filters, unsigned textureId, const FloatSize&, WebKit::WebGraphicsContext3D*, GrContext*); + static WebKit::WebFilterOperations optimize(const WebKit::WebFilterOperations& filters); + +private: + CCRenderSurfaceFilters(); +}; + +} +#endif // USE(ACCELERATED_COMPOSITING) + +#endif diff --git a/cc/render_surface_impl.cc b/cc/render_surface_impl.cc new file mode 100644 index 0000000..f10c83b --- /dev/null +++ b/cc/render_surface_impl.cc @@ -0,0 +1,253 @@ +// Copyright 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#if USE(ACCELERATED_COMPOSITING) + +#include "CCRenderSurface.h" + +#include "base/stringprintf.h" +#include "CCDamageTracker.h" +#include "CCDebugBorderDrawQuad.h" +#include "CCDelegatedRendererLayerImpl.h" +#include "CCLayerImpl.h" +#include "CCMathUtil.h" +#include "CCQuadSink.h" +#include "CCRenderPass.h" +#include "CCRenderPassDrawQuad.h" +#include "CCRenderPassSink.h" +#include "CCSharedQuadState.h" +#include + +using WebKit::WebTransformationMatrix; + +namespace cc { + +static const int debugSurfaceBorderWidth = 2; +static const int debugSurfaceBorderAlpha = 100; +static const int debugSurfaceBorderColorRed = 0; +static const int debugSurfaceBorderColorGreen = 0; +static const int debugSurfaceBorderColorBlue = 255; +static const int debugReplicaBorderColorRed = 160; +static const int debugReplicaBorderColorGreen = 0; +static const int debugReplicaBorderColorBlue = 255; + +CCRenderSurface::CCRenderSurface(CCLayerImpl* owningLayer) + : m_owningLayer(owningLayer) + , m_surfacePropertyChanged(false) + , m_drawOpacity(1) + , m_drawOpacityIsAnimating(false) + , m_targetSurfaceTransformsAreAnimating(false) + , m_screenSpaceTransformsAreAnimating(false) + , m_nearestAncestorThatMovesPixels(0) + , m_targetRenderSurfaceLayerIndexHistory(0) + , m_currentLayerIndexHistory(0) +{ + m_damageTracker = CCDamageTracker::create(); +} + +CCRenderSurface::~CCRenderSurface() +{ +} + +FloatRect CCRenderSurface::drawableContentRect() const +{ + FloatRect drawableContentRect = CCMathUtil::mapClippedRect(m_drawTransform, m_contentRect); + if (m_owningLayer->hasReplica()) + drawableContentRect.unite(CCMathUtil::mapClippedRect(m_replicaDrawTransform, m_contentRect)); + + return drawableContentRect; +} + +std::string CCRenderSurface::name() const +{ + return base::StringPrintf("RenderSurface(id=%i,owner=%s)", m_owningLayer->id(), m_owningLayer->debugName().data()); +} + +static std::string indentString(int indent) +{ + std::string str; + for (int i = 0; i != indent; ++i) + str.append(" "); + return str; +} + +void CCRenderSurface::dumpSurface(std::string* str, int indent) const +{ + std::string indentStr = indentString(indent); + str->append(indentStr); + base::StringAppendF(str, "%s\n", name().data()); + + indentStr.append(" "); + str->append(indentStr); + base::StringAppendF(str, "contentRect: (%d, %d, %d, %d)\n", m_contentRect.x(), m_contentRect.y(), m_contentRect.width(), m_contentRect.height()); + + str->append(indentStr); + base::StringAppendF(str, "drawTransform: %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f\n", + m_drawTransform.m11(), m_drawTransform.m12(), m_drawTransform.m13(), m_drawTransform.m14(), + m_drawTransform.m21(), m_drawTransform.m22(), m_drawTransform.m23(), m_drawTransform.m24(), + m_drawTransform.m31(), m_drawTransform.m32(), m_drawTransform.m33(), m_drawTransform.m34(), + m_drawTransform.m41(), m_drawTransform.m42(), m_drawTransform.m43(), m_drawTransform.m44()); + + str->append(indentStr); + base::StringAppendF(str, "damageRect is pos(%f, %f), size(%f, %f)\n", + m_damageTracker->currentDamageRect().x(), m_damageTracker->currentDamageRect().y(), + m_damageTracker->currentDamageRect().width(), m_damageTracker->currentDamageRect().height()); +} + +int CCRenderSurface::owningLayerId() const +{ + return m_owningLayer ? m_owningLayer->id() : 0; +} + + +void CCRenderSurface::setClipRect(const IntRect& clipRect) +{ + if (m_clipRect == clipRect) + return; + + m_surfacePropertyChanged = true; + m_clipRect = clipRect; +} + +bool CCRenderSurface::contentsChanged() const +{ + return !m_damageTracker->currentDamageRect().isEmpty(); +} + +void CCRenderSurface::setContentRect(const IntRect& contentRect) +{ + if (m_contentRect == contentRect) + return; + + m_surfacePropertyChanged = true; + m_contentRect = contentRect; +} + +bool CCRenderSurface::surfacePropertyChanged() const +{ + // Surface property changes are tracked as follows: + // + // - m_surfacePropertyChanged is flagged when the clipRect or contentRect change. As + // of now, these are the only two properties that can be affected by descendant layers. + // + // - all other property changes come from the owning layer (or some ancestor layer + // that propagates its change to the owning layer). + // + ASSERT(m_owningLayer); + return m_surfacePropertyChanged || m_owningLayer->layerPropertyChanged(); +} + +bool CCRenderSurface::surfacePropertyChangedOnlyFromDescendant() const +{ + return m_surfacePropertyChanged && !m_owningLayer->layerPropertyChanged(); +} + +void CCRenderSurface::addContributingDelegatedRenderPassLayer(CCLayerImpl* layer) +{ + ASSERT(std::find(m_layerList.begin(), m_layerList.end(), layer) != m_layerList.end()); + CCDelegatedRendererLayerImpl* delegatedRendererLayer = static_cast(layer); + m_contributingDelegatedRenderPassLayerList.push_back(delegatedRendererLayer); +} + +void CCRenderSurface::clearLayerLists() +{ + m_layerList.clear(); + m_contributingDelegatedRenderPassLayerList.clear(); +} + +static inline IntRect computeClippedRectInTarget(const CCLayerImpl* owningLayer) +{ + ASSERT(owningLayer->parent()); + + const CCLayerImpl* renderTarget = owningLayer->parent()->renderTarget(); + const CCRenderSurface* self = owningLayer->renderSurface(); + + IntRect clippedRectInTarget = self->clipRect(); + if (owningLayer->backgroundFilters().hasFilterThatMovesPixels()) { + // If the layer has background filters that move pixels, we cannot scissor as tightly. + // FIXME: this should be able to be a tighter scissor, perhaps expanded by the filter outsets? + clippedRectInTarget = renderTarget->renderSurface()->contentRect(); + } else if (clippedRectInTarget.isEmpty()) { + // For surfaces, empty clipRect means that the surface does not clip anything. + clippedRectInTarget = enclosingIntRect(intersection(renderTarget->renderSurface()->contentRect(), self->drawableContentRect())); + } else + clippedRectInTarget.intersect(enclosingIntRect(self->drawableContentRect())); + return clippedRectInTarget; +} + +CCRenderPass::Id CCRenderSurface::renderPassId() +{ + int layerId = m_owningLayer->id(); + int subId = 0; + ASSERT(layerId > 0); + return CCRenderPass::Id(layerId, subId); +} + +void CCRenderSurface::appendRenderPasses(CCRenderPassSink& passSink) +{ + for (size_t i = 0; i < m_contributingDelegatedRenderPassLayerList.size(); ++i) + m_contributingDelegatedRenderPassLayerList[i]->appendContributingRenderPasses(passSink); + + scoped_ptr pass = CCRenderPass::create(renderPassId(), m_contentRect, m_screenSpaceTransform); + pass->setDamageRect(m_damageTracker->currentDamageRect()); + pass->setFilters(m_owningLayer->filters()); + pass->setBackgroundFilters(m_owningLayer->backgroundFilters()); + passSink.appendRenderPass(pass.Pass()); +} + +void CCRenderSurface::appendQuads(CCQuadSink& quadSink, CCAppendQuadsData& appendQuadsData, bool forReplica, CCRenderPass::Id renderPassId) +{ + ASSERT(!forReplica || m_owningLayer->hasReplica()); + + IntRect clippedRectInTarget = computeClippedRectInTarget(m_owningLayer); + bool isOpaque = false; + const WebTransformationMatrix& drawTransform = forReplica ? m_replicaDrawTransform : m_drawTransform; + CCSharedQuadState* sharedQuadState = quadSink.useSharedQuadState(CCSharedQuadState::create(drawTransform, m_contentRect, clippedRectInTarget, m_drawOpacity, isOpaque).Pass()); + + if (m_owningLayer->hasDebugBorders()) { + int red = forReplica ? debugReplicaBorderColorRed : debugSurfaceBorderColorRed; + int green = forReplica ? debugReplicaBorderColorGreen : debugSurfaceBorderColorGreen; + int blue = forReplica ? debugReplicaBorderColorBlue : debugSurfaceBorderColorBlue; + SkColor color = SkColorSetARGB(debugSurfaceBorderAlpha, red, green, blue); + quadSink.append(CCDebugBorderDrawQuad::create(sharedQuadState, contentRect(), color, debugSurfaceBorderWidth).PassAs(), appendQuadsData); + } + + // FIXME: By using the same RenderSurface for both the content and its reflection, + // it's currently not possible to apply a separate mask to the reflection layer + // or correctly handle opacity in reflections (opacity must be applied after drawing + // both the layer and its reflection). The solution is to introduce yet another RenderSurface + // to draw the layer and its reflection in. For now we only apply a separate reflection + // mask if the contents don't have a mask of their own. + CCLayerImpl* maskLayer = m_owningLayer->maskLayer(); + if (maskLayer && (!maskLayer->drawsContent() || maskLayer->bounds().isEmpty())) + maskLayer = 0; + + if (!maskLayer && forReplica) { + maskLayer = m_owningLayer->replicaLayer()->maskLayer(); + if (maskLayer && (!maskLayer->drawsContent() || maskLayer->bounds().isEmpty())) + maskLayer = 0; + } + + float maskTexCoordScaleX = 1; + float maskTexCoordScaleY = 1; + float maskTexCoordOffsetX = 1; + float maskTexCoordOffsetY = 1; + if (maskLayer) { + maskTexCoordScaleX = static_cast(contentRect().width()) / maskLayer->contentBounds().width(); + maskTexCoordScaleY = static_cast(contentRect().height()) / maskLayer->contentBounds().height(); + maskTexCoordOffsetX = static_cast(contentRect().x()) / contentRect().width() * maskTexCoordScaleX; + maskTexCoordOffsetY = static_cast(contentRect().y()) / contentRect().height() * maskTexCoordScaleY; + } + + CCResourceProvider::ResourceId maskResourceId = maskLayer ? maskLayer->contentsResourceId() : 0; + IntRect contentsChangedSinceLastFrame = contentsChanged() ? m_contentRect : IntRect(); + + quadSink.append(CCRenderPassDrawQuad::create(sharedQuadState, contentRect(), renderPassId, forReplica, maskResourceId, contentsChangedSinceLastFrame, + maskTexCoordScaleX, maskTexCoordScaleY, maskTexCoordOffsetX, maskTexCoordOffsetY).PassAs(), appendQuadsData); +} + +} +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/cc/render_surface_impl.h b/cc/render_surface_impl.h index 638cbb2..afdf062 100644 --- a/cc/render_surface_impl.h +++ b/cc/render_surface_impl.h @@ -1,3 +1,132 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. +// Copyright 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CCRenderSurface_h +#define CCRenderSurface_h + +#if USE(ACCELERATED_COMPOSITING) + +#include "base/basictypes.h" +#include "base/memory/scoped_ptr.h" +#include "CCRenderPass.h" +#include "CCSharedQuadState.h" +#include "FloatRect.h" +#include "IntRect.h" +#include + +namespace cc { + +class CCDamageTracker; +class CCDelegatedRendererLayerImpl; +class CCQuadSink; +class CCRenderPassSink; +class CCLayerImpl; + +struct CCAppendQuadsData; + +class CCRenderSurface { +public: + explicit CCRenderSurface(CCLayerImpl*); + virtual ~CCRenderSurface(); + + std::string name() const; + void dumpSurface(std::string*, int indent) const; + + FloatPoint contentRectCenter() const { return FloatRect(m_contentRect).center(); } + + // Returns the rect that encloses the RenderSurface including any reflection. + FloatRect drawableContentRect() const; + + float drawOpacity() const { return m_drawOpacity; } + void setDrawOpacity(float opacity) { m_drawOpacity = opacity; } + + void setNearestAncestorThatMovesPixels(CCRenderSurface* surface) { m_nearestAncestorThatMovesPixels = surface; } + const CCRenderSurface* nearestAncestorThatMovesPixels() const { return m_nearestAncestorThatMovesPixels; } + + bool drawOpacityIsAnimating() const { return m_drawOpacityIsAnimating; } + void setDrawOpacityIsAnimating(bool drawOpacityIsAnimating) { m_drawOpacityIsAnimating = drawOpacityIsAnimating; } + + void setDrawTransform(const WebKit::WebTransformationMatrix& drawTransform) { m_drawTransform = drawTransform; } + const WebKit::WebTransformationMatrix& drawTransform() const { return m_drawTransform; } + + void setScreenSpaceTransform(const WebKit::WebTransformationMatrix& screenSpaceTransform) { m_screenSpaceTransform = screenSpaceTransform; } + const WebKit::WebTransformationMatrix& screenSpaceTransform() const { return m_screenSpaceTransform; } + + void setReplicaDrawTransform(const WebKit::WebTransformationMatrix& replicaDrawTransform) { m_replicaDrawTransform = replicaDrawTransform; } + const WebKit::WebTransformationMatrix& replicaDrawTransform() const { return m_replicaDrawTransform; } + + void setReplicaScreenSpaceTransform(const WebKit::WebTransformationMatrix& replicaScreenSpaceTransform) { m_replicaScreenSpaceTransform = replicaScreenSpaceTransform; } + const WebKit::WebTransformationMatrix& replicaScreenSpaceTransform() const { return m_replicaScreenSpaceTransform; } + + bool targetSurfaceTransformsAreAnimating() const { return m_targetSurfaceTransformsAreAnimating; } + void setTargetSurfaceTransformsAreAnimating(bool animating) { m_targetSurfaceTransformsAreAnimating = animating; } + bool screenSpaceTransformsAreAnimating() const { return m_screenSpaceTransformsAreAnimating; } + void setScreenSpaceTransformsAreAnimating(bool animating) { m_screenSpaceTransformsAreAnimating = animating; } + + void setClipRect(const IntRect&); + const IntRect& clipRect() const { return m_clipRect; } + + bool contentsChanged() const; + + void setContentRect(const IntRect&); + const IntRect& contentRect() const { return m_contentRect; } + + std::vector& layerList() { return m_layerList; } + void addContributingDelegatedRenderPassLayer(CCLayerImpl*); + void clearLayerLists(); + + int owningLayerId() const; + + void resetPropertyChangedFlag() { m_surfacePropertyChanged = false; } + bool surfacePropertyChanged() const; + bool surfacePropertyChangedOnlyFromDescendant() const; + + CCDamageTracker* damageTracker() const { return m_damageTracker.get(); } + + CCRenderPass::Id renderPassId(); + + void appendRenderPasses(CCRenderPassSink&); + void appendQuads(CCQuadSink&, CCAppendQuadsData&, bool forReplica, CCRenderPass::Id renderPassId); + +private: + CCLayerImpl* m_owningLayer; + + // Uses this surface's space. + IntRect m_contentRect; + bool m_surfacePropertyChanged; + + float m_drawOpacity; + bool m_drawOpacityIsAnimating; + WebKit::WebTransformationMatrix m_drawTransform; + WebKit::WebTransformationMatrix m_screenSpaceTransform; + WebKit::WebTransformationMatrix m_replicaDrawTransform; + WebKit::WebTransformationMatrix m_replicaScreenSpaceTransform; + bool m_targetSurfaceTransformsAreAnimating; + bool m_screenSpaceTransformsAreAnimating; + + // Uses the space of the surface's target surface. + IntRect m_clipRect; + + std::vector m_layerList; + std::vector m_contributingDelegatedRenderPassLayerList; + + // The nearest ancestor target surface that will contain the contents of this surface, and that is going + // to move pixels within the surface (such as with a blur). This can point to itself. + CCRenderSurface* m_nearestAncestorThatMovesPixels; + + scoped_ptr m_damageTracker; + + // For CCLayerIteratorActions + int m_targetRenderSurfaceLayerIndexHistory; + int m_currentLayerIndexHistory; + + friend struct CCLayerIteratorActions; + + DISALLOW_COPY_AND_ASSIGN(CCRenderSurface); +}; + +} +#endif // USE(ACCELERATED_COMPOSITING) + +#endif diff --git a/cc/renderer.cc b/cc/renderer.cc new file mode 100644 index 0000000..69c04df --- /dev/null +++ b/cc/renderer.cc @@ -0,0 +1,21 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#include "CCRenderer.h" + +namespace cc { + +bool CCRenderer::haveCachedResourcesForRenderPassId(CCRenderPass::Id) const +{ + return false; +} + +bool CCRenderer::isContextLost() +{ + return false; +} + +} diff --git a/cc/renderer.h b/cc/renderer.h index 638cbb2..740ba0b 100644 --- a/cc/renderer.h +++ b/cc/renderer.h @@ -1,3 +1,84 @@ // Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CCRenderer_h +#define CCRenderer_h + +#include "base/basictypes.h" +#include "CCLayerTreeHost.h" +#include "CCRenderPass.h" +#include "FloatQuad.h" +#include "IntRect.h" +#include + +namespace cc { + +class CCScopedTexture; + +class CCRendererClient { +public: + virtual const IntSize& deviceViewportSize() const = 0; + virtual const CCLayerTreeSettings& settings() const = 0; + virtual void didLoseContext() = 0; + virtual void onSwapBuffersComplete() = 0; + virtual void releaseContentsTextures() = 0; + virtual void setFullRootLayerDamage() = 0; + virtual void setMemoryAllocationLimitBytes(size_t) = 0; +protected: + virtual ~CCRendererClient() { } +}; + +class CCRenderer { +public: + // This enum defines the various resource pools for the CCResourceProvider + // where textures get allocated. + enum ResourcePool { + ImplPool = 1, // This pool is for textures that get allocated on the impl thread (e.g. RenderSurfaces). + ContentPool // This pool is for textures that get allocated on the main thread (e.g. tiles). + }; + + virtual ~CCRenderer() { } + + virtual const RendererCapabilities& capabilities() const = 0; + + const CCLayerTreeSettings& settings() const { return m_client->settings(); } + + const IntSize& viewportSize() { return m_client->deviceViewportSize(); } + int viewportWidth() { return viewportSize().width(); } + int viewportHeight() { return viewportSize().height(); } + + virtual void viewportChanged() { } + + virtual void decideRenderPassAllocationsForFrame(const CCRenderPassList&) { } + virtual bool haveCachedResourcesForRenderPassId(CCRenderPass::Id) const; + + virtual void drawFrame(const CCRenderPassList&, const CCRenderPassIdHashMap&) = 0; + + // waits for rendering to finish + virtual void finish() = 0; + + virtual void doNoOp() { } + // puts backbuffer onscreen + virtual bool swapBuffers() = 0; + + virtual void getFramebufferPixels(void *pixels, const IntRect&) = 0; + + virtual bool isContextLost(); + + virtual void setVisible(bool) = 0; + +protected: + explicit CCRenderer(CCRendererClient* client) + : m_client(client) + { + } + + CCRendererClient* m_client; + + DISALLOW_COPY_AND_ASSIGN(CCRenderer); +}; + +} + +#endif // CCRenderer_h diff --git a/cc/rendering_stats.h b/cc/rendering_stats.h index 638cbb2..fb178a8 100644 --- a/cc/rendering_stats.h +++ b/cc/rendering_stats.h @@ -1,3 +1,38 @@ // Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CCRenderingStats_h +#define CCRenderingStats_h + +namespace cc { + +struct CCRenderingStats { + // FIXME: Rename these to animationFrameCount and screenFrameCount, crbug.com/138641. + int numAnimationFrames; + int numFramesSentToScreen; + int droppedFrameCount; + double totalPaintTimeInSeconds; + double totalRasterizeTimeInSeconds; + double totalCommitTimeInSeconds; + size_t totalCommitCount; + size_t numImplThreadScrolls; + size_t numMainThreadScrolls; + + CCRenderingStats() + : numAnimationFrames(0) + , numFramesSentToScreen(0) + , droppedFrameCount(0) + , totalPaintTimeInSeconds(0) + , totalRasterizeTimeInSeconds(0) + , totalCommitTimeInSeconds(0) + , totalCommitCount(0) + , numImplThreadScrolls(0) + , numMainThreadScrolls(0) + { + } +}; + +} + +#endif diff --git a/cc/resource_provider.cc b/cc/resource_provider.cc new file mode 100644 index 0000000..29ca7d4 --- /dev/null +++ b/cc/resource_provider.cc @@ -0,0 +1,708 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#include "CCResourceProvider.h" +#ifdef LOG +#undef LOG +#endif + +#include + +#include "base/debug/alias.h" +#include "base/hash_tables.h" +#include "base/stl_util.h" +#include "base/string_split.h" +#include "base/string_util.h" +#include "CCProxy.h" +#include "CCRendererGL.h" // For the GLC() macro. +#include "Extensions3DChromium.h" +#include "IntRect.h" +#include "LayerTextureSubImage.h" +#include "ThrottledTextureUploader.h" +#include "UnthrottledTextureUploader.h" +#include + +using WebKit::WebGraphicsContext3D; + +namespace cc { + +static GC3Denum textureToStorageFormat(GC3Denum textureFormat) +{ + GC3Denum storageFormat = Extensions3D::RGBA8_OES; + switch (textureFormat) { + case GraphicsContext3D::RGBA: + break; + case Extensions3D::BGRA_EXT: + storageFormat = Extensions3DChromium::BGRA8_EXT; + break; + default: + ASSERT_NOT_REACHED(); + break; + } + + return storageFormat; +} + +static bool isTextureFormatSupportedForStorage(GC3Denum format) +{ + return (format == GraphicsContext3D::RGBA || format == Extensions3D::BGRA_EXT); +} + +CCResourceProvider::TransferableResourceList::TransferableResourceList() +{ +} + +CCResourceProvider::TransferableResourceList::~TransferableResourceList() +{ +} + +CCResourceProvider::Resource::Resource() + : glId(0) + , pixels(0) + , pool(0) + , lockForReadCount(0) + , lockedForWrite(false) + , external(false) + , exported(false) + , size() + , format(0) + , type(static_cast(0)) +{ +} + +CCResourceProvider::Resource::Resource(unsigned textureId, int pool, const IntSize& size, GC3Denum format) + : glId(textureId) + , pixels(0) + , pool(pool) + , lockForReadCount(0) + , lockedForWrite(false) + , external(false) + , exported(false) + , size(size) + , format(format) + , type(GLTexture) +{ +} + +CCResourceProvider::Resource::Resource(uint8_t* pixels, int pool, const IntSize& size, GC3Denum format) + : glId(0) + , pixels(pixels) + , pool(pool) + , lockForReadCount(0) + , lockedForWrite(false) + , external(false) + , exported(false) + , size(size) + , format(format) + , type(Bitmap) +{ +} + +CCResourceProvider::Child::Child() +{ +} + +CCResourceProvider::Child::~Child() +{ +} + +PassOwnPtr CCResourceProvider::create(CCGraphicsContext* context) +{ + OwnPtr resourceProvider(adoptPtr(new CCResourceProvider(context))); + if (!resourceProvider->initialize()) + return nullptr; + return resourceProvider.release(); +} + +CCResourceProvider::~CCResourceProvider() +{ + WebGraphicsContext3D* context3d = m_context->context3D(); + if (!context3d || !context3d->makeContextCurrent()) + return; + m_textureUploader.clear(); + m_textureCopier.clear(); +} + +WebGraphicsContext3D* CCResourceProvider::graphicsContext3D() +{ + ASSERT(CCProxy::isImplThread()); + return m_context->context3D(); +} + +bool CCResourceProvider::inUseByConsumer(ResourceId id) +{ + ASSERT(CCProxy::isImplThread()); + ResourceMap::iterator it = m_resources.find(id); + CHECK(it != m_resources.end()); +#if WTF_NEW_HASHMAP_ITERATORS_INTERFACE + Resource* resource = &it->value; +#else + Resource* resource = &it->second; +#endif + return !!resource->lockForReadCount || resource->exported; +} + +CCResourceProvider::ResourceId CCResourceProvider::createResource(int pool, const IntSize& size, GC3Denum format, TextureUsageHint hint) +{ + switch (m_defaultResourceType) { + case GLTexture: + return createGLTexture(pool, size, format, hint); + case Bitmap: + ASSERT(format == GraphicsContext3D::RGBA); + return createBitmap(pool, size); + } + + CRASH(); + return 0; +} + +CCResourceProvider::ResourceId CCResourceProvider::createGLTexture(int pool, const IntSize& size, GC3Denum format, TextureUsageHint hint) +{ + ASSERT(CCProxy::isImplThread()); + unsigned textureId = 0; + WebGraphicsContext3D* context3d = m_context->context3D(); + ASSERT(context3d); + GLC(context3d, textureId = context3d->createTexture()); + GLC(context3d, context3d->bindTexture(GraphicsContext3D::TEXTURE_2D, textureId)); + GLC(context3d, context3d->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR)); + GLC(context3d, context3d->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR)); + GLC(context3d, context3d->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE)); + GLC(context3d, context3d->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE)); + + if (m_useTextureUsageHint && hint == TextureUsageFramebuffer) + GLC(context3d, context3d->texParameteri(GraphicsContext3D::TEXTURE_2D, Extensions3DChromium::GL_TEXTURE_USAGE_ANGLE, Extensions3DChromium::GL_FRAMEBUFFER_ATTACHMENT_ANGLE)); + if (m_useTextureStorageExt && isTextureFormatSupportedForStorage(format)) { + GC3Denum storageFormat = textureToStorageFormat(format); + GLC(context3d, context3d->texStorage2DEXT(GraphicsContext3D::TEXTURE_2D, 1, storageFormat, size.width(), size.height())); + } else + GLC(context3d, context3d->texImage2D(GraphicsContext3D::TEXTURE_2D, 0, format, size.width(), size.height(), 0, format, GraphicsContext3D::UNSIGNED_BYTE, 0)); + ResourceId id = m_nextId++; + Resource resource(textureId, pool, size, format); + m_resources.add(id, resource); + return id; +} + +CCResourceProvider::ResourceId CCResourceProvider::createBitmap(int pool, const IntSize& size) +{ + ASSERT(CCProxy::isImplThread()); + + uint8_t* pixels = new uint8_t[size.width() * size.height() * 4]; + + ResourceId id = m_nextId++; + Resource resource(pixels, pool, size, GraphicsContext3D::RGBA); + m_resources.add(id, resource); + return id; +} + +CCResourceProvider::ResourceId CCResourceProvider::createResourceFromExternalTexture(unsigned textureId) +{ + ASSERT(CCProxy::isImplThread()); + ASSERT(m_context->context3D()); + ResourceId id = m_nextId++; + Resource resource(textureId, 0, IntSize(), 0); + resource.external = true; + m_resources.add(id, resource); + return id; +} + +void CCResourceProvider::deleteResource(ResourceId id) +{ + ASSERT(CCProxy::isImplThread()); + ResourceMap::iterator it = m_resources.find(id); + CHECK(it != m_resources.end()); +#if WTF_NEW_HASHMAP_ITERATORS_INTERFACE + Resource* resource = &it->value; +#else + Resource* resource = &it->second; +#endif + ASSERT(!resource->lockedForWrite); + ASSERT(!resource->lockForReadCount); + + if (resource->glId && !resource->external) { + WebGraphicsContext3D* context3d = m_context->context3D(); + ASSERT(context3d); + GLC(context3d, context3d->deleteTexture(resource->glId)); + } + if (resource->pixels) + delete resource->pixels; + + m_resources.remove(it); +} + +void CCResourceProvider::deleteOwnedResources(int pool) +{ + ASSERT(CCProxy::isImplThread()); + ResourceIdArray toDelete; + for (ResourceMap::iterator it = m_resources.begin(); it != m_resources.end(); ++it) { +#if WTF_NEW_HASHMAP_ITERATORS_INTERFACE + if (it->value.pool == pool && !it->value.external) + toDelete.append(it->key); +#else + if (it->second.pool == pool && !it->second.external) + toDelete.append(it->first); +#endif + } + for (ResourceIdArray::iterator it = toDelete.begin(); it != toDelete.end(); ++it) + deleteResource(*it); +} + +CCResourceProvider::ResourceType CCResourceProvider::resourceType(ResourceId id) +{ + ResourceMap::iterator it = m_resources.find(id); + CHECK(it != m_resources.end()); +#if WTF_NEW_HASHMAP_ITERATORS_INTERFACE + Resource* resource = &it->value; +#else + Resource* resource = &it->second; +#endif + return resource->type; +} + +void CCResourceProvider::upload(ResourceId id, const uint8_t* image, const IntRect& imageRect, const IntRect& sourceRect, const IntSize& destOffset) +{ + ASSERT(CCProxy::isImplThread()); + ResourceMap::iterator it = m_resources.find(id); + CHECK(it != m_resources.end()); +#if WTF_NEW_HASHMAP_ITERATORS_INTERFACE + Resource* resource = &it->value; +#else + Resource* resource = &it->second; +#endif + ASSERT(!resource->lockedForWrite); + ASSERT(!resource->lockForReadCount); + ASSERT(!resource->external); + + if (resource->glId) { + WebGraphicsContext3D* context3d = m_context->context3D(); + ASSERT(context3d); + ASSERT(m_texSubImage.get()); + context3d->bindTexture(GraphicsContext3D::TEXTURE_2D, resource->glId); + m_texSubImage->upload(image, imageRect, sourceRect, destOffset, resource->format, context3d); + } + + if (resource->pixels) { + SkBitmap srcFull; + srcFull.setConfig(SkBitmap::kARGB_8888_Config, imageRect.width(), imageRect.height()); + srcFull.setPixels(const_cast(image)); + SkBitmap srcSubset; + SkIRect skSourceRect = SkIRect::MakeXYWH(sourceRect.x(), sourceRect.y(), sourceRect.width(), sourceRect.height()); + skSourceRect.offset(-imageRect.x(), -imageRect.y()); + srcFull.extractSubset(&srcSubset, skSourceRect); + + ScopedWriteLockSoftware lock(this, id); + SkCanvas* dest = lock.skCanvas(); + dest->writePixels(srcSubset, destOffset.width(), destOffset.height()); + } +} + +void CCResourceProvider::flush() +{ + ASSERT(CCProxy::isImplThread()); + WebGraphicsContext3D* context3d = m_context->context3D(); + if (context3d) + context3d->flush(); +} + +bool CCResourceProvider::shallowFlushIfSupported() +{ + ASSERT(CCProxy::isImplThread()); + WebGraphicsContext3D* context3d = m_context->context3D(); + if (!context3d || !m_useShallowFlush) + return false; + + context3d->shallowFlushCHROMIUM(); + return true; +} + +const CCResourceProvider::Resource* CCResourceProvider::lockForRead(ResourceId id) +{ + ASSERT(CCProxy::isImplThread()); + ResourceMap::iterator it = m_resources.find(id); + CHECK(it != m_resources.end()); + +#if WTF_NEW_HASHMAP_ITERATORS_INTERFACE + Resource* resource = &it->value; +#else + Resource* resource = &it->second; +#endif + ASSERT(!resource->lockedForWrite); + resource->lockForReadCount++; + return resource; +} + +void CCResourceProvider::unlockForRead(ResourceId id) +{ + ASSERT(CCProxy::isImplThread()); + ResourceMap::iterator it = m_resources.find(id); + CHECK(it != m_resources.end()); +#if WTF_NEW_HASHMAP_ITERATORS_INTERFACE + Resource* resource = &it->value; +#else + Resource* resource = &it->second; +#endif + ASSERT(resource->lockForReadCount > 0); + resource->lockForReadCount--; +} + +const CCResourceProvider::Resource* CCResourceProvider::lockForWrite(ResourceId id) +{ + ASSERT(CCProxy::isImplThread()); + ResourceMap::iterator it = m_resources.find(id); + CHECK(it != m_resources.end()); +#if WTF_NEW_HASHMAP_ITERATORS_INTERFACE + Resource* resource = &it->value; +#else + Resource* resource = &it->second; +#endif + ASSERT(!resource->lockedForWrite); + ASSERT(!resource->lockForReadCount); + ASSERT(!resource->external); + resource->lockedForWrite = true; + return resource; +} + +void CCResourceProvider::unlockForWrite(ResourceId id) +{ + ASSERT(CCProxy::isImplThread()); + ResourceMap::iterator it = m_resources.find(id); + CHECK(it != m_resources.end()); +#if WTF_NEW_HASHMAP_ITERATORS_INTERFACE + Resource* resource = &it->value; +#else + Resource* resource = &it->second; +#endif + ASSERT(resource->lockedForWrite); + ASSERT(!resource->external); + resource->lockedForWrite = false; +} + +CCResourceProvider::ScopedReadLockGL::ScopedReadLockGL(CCResourceProvider* resourceProvider, CCResourceProvider::ResourceId resourceId) + : m_resourceProvider(resourceProvider) + , m_resourceId(resourceId) + , m_textureId(resourceProvider->lockForRead(resourceId)->glId) +{ + ASSERT(m_textureId); +} + +CCResourceProvider::ScopedReadLockGL::~ScopedReadLockGL() +{ + m_resourceProvider->unlockForRead(m_resourceId); +} + +CCResourceProvider::ScopedWriteLockGL::ScopedWriteLockGL(CCResourceProvider* resourceProvider, CCResourceProvider::ResourceId resourceId) + : m_resourceProvider(resourceProvider) + , m_resourceId(resourceId) + , m_textureId(resourceProvider->lockForWrite(resourceId)->glId) +{ + ASSERT(m_textureId); +} + +CCResourceProvider::ScopedWriteLockGL::~ScopedWriteLockGL() +{ + m_resourceProvider->unlockForWrite(m_resourceId); +} + +void CCResourceProvider::populateSkBitmapWithResource(SkBitmap* skBitmap, const Resource* resource) +{ + ASSERT(resource->pixels); + ASSERT(resource->format == GraphicsContext3D::RGBA); + skBitmap->setConfig(SkBitmap::kARGB_8888_Config, resource->size.width(), resource->size.height()); + skBitmap->setPixels(resource->pixels); +} + +CCResourceProvider::ScopedReadLockSoftware::ScopedReadLockSoftware(CCResourceProvider* resourceProvider, CCResourceProvider::ResourceId resourceId) + : m_resourceProvider(resourceProvider) + , m_resourceId(resourceId) +{ + CCResourceProvider::populateSkBitmapWithResource(&m_skBitmap, resourceProvider->lockForRead(resourceId)); +} + +CCResourceProvider::ScopedReadLockSoftware::~ScopedReadLockSoftware() +{ + m_resourceProvider->unlockForRead(m_resourceId); +} + +CCResourceProvider::ScopedWriteLockSoftware::ScopedWriteLockSoftware(CCResourceProvider* resourceProvider, CCResourceProvider::ResourceId resourceId) + : m_resourceProvider(resourceProvider) + , m_resourceId(resourceId) +{ + CCResourceProvider::populateSkBitmapWithResource(&m_skBitmap, resourceProvider->lockForWrite(resourceId)); + m_skCanvas = adoptPtr(new SkCanvas(m_skBitmap)); +} + +CCResourceProvider::ScopedWriteLockSoftware::~ScopedWriteLockSoftware() +{ + m_resourceProvider->unlockForWrite(m_resourceId); +} + +CCResourceProvider::CCResourceProvider(CCGraphicsContext* context) + : m_context(context) + , m_nextId(1) + , m_nextChild(1) + , m_defaultResourceType(GLTexture) + , m_useTextureStorageExt(false) + , m_useTextureUsageHint(false) + , m_useShallowFlush(false) + , m_maxTextureSize(0) +{ +} + +bool CCResourceProvider::initialize() +{ + ASSERT(CCProxy::isImplThread()); + WebGraphicsContext3D* context3d = m_context->context3D(); + if (!context3d) { + m_maxTextureSize = INT_MAX / 2; + m_textureUploader = UnthrottledTextureUploader::create(); + return true; + } + if (!context3d->makeContextCurrent()) + return false; + + std::string extensionsString = UTF16ToASCII(context3d->getString(GraphicsContext3D::EXTENSIONS)); + std::vector extensions; + base::SplitString(extensionsString, ' ', &extensions); + bool useMapSub = false; + bool useBindUniform = false; + for (size_t i = 0; i < extensions.size(); ++i) { + if (extensions[i] == "GL_EXT_texture_storage") + m_useTextureStorageExt = true; + else if (extensions[i] == "GL_ANGLE_texture_usage") + m_useTextureUsageHint = true; + else if (extensions[i] == "GL_CHROMIUM_map_sub") + useMapSub = true; + else if (extensions[i] == "GL_CHROMIUM_shallow_flush") + m_useShallowFlush = true; + else if (extensions[i] == "GL_CHROMIUM_bind_uniform_location") + useBindUniform = true; + } + + m_texSubImage = adoptPtr(new LayerTextureSubImage(useMapSub)); + m_textureCopier = AcceleratedTextureCopier::create(context3d, useBindUniform); + + m_textureUploader = ThrottledTextureUploader::create(context3d); + GLC(context3d, context3d->getIntegerv(GraphicsContext3D::MAX_TEXTURE_SIZE, &m_maxTextureSize)); + return true; +} + +int CCResourceProvider::createChild(int pool) +{ + ASSERT(CCProxy::isImplThread()); + Child childInfo; + childInfo.pool = pool; + int child = m_nextChild++; + m_children.add(child, childInfo); + return child; +} + +void CCResourceProvider::destroyChild(int child) +{ + ASSERT(CCProxy::isImplThread()); + ChildMap::iterator it = m_children.find(child); + ASSERT(it != m_children.end()); +#if WTF_NEW_HASHMAP_ITERATORS_INTERFACE + deleteOwnedResources(it->value.pool); +#else + deleteOwnedResources(it->second.pool); +#endif + m_children.remove(it); + trimMailboxDeque(); +} + +const CCResourceProvider::ResourceIdMap& CCResourceProvider::getChildToParentMap(int child) const +{ + ASSERT(CCProxy::isImplThread()); + ChildMap::const_iterator it = m_children.find(child); + ASSERT(it != m_children.end()); +#if WTF_NEW_HASHMAP_ITERATORS_INTERFACE + return it->value.childToParentMap; +#else + return it->second.childToParentMap; +#endif +} + +CCResourceProvider::TransferableResourceList CCResourceProvider::prepareSendToParent(const ResourceIdArray& resources) +{ + ASSERT(CCProxy::isImplThread()); + TransferableResourceList list; + list.syncPoint = 0; + WebGraphicsContext3D* context3d = m_context->context3D(); + if (!context3d || !context3d->makeContextCurrent()) { + // FIXME: Implement this path for software compositing. + return list; + } + for (ResourceIdArray::const_iterator it = resources.begin(); it != resources.end(); ++it) { + TransferableResource resource; + if (transferResource(context3d, *it, &resource)) { +#if WTF_NEW_HASHMAP_ITERATORS_INTERFACE + m_resources.find(*it)->value.exported = true; +#else + m_resources.find(*it)->second.exported = true; +#endif + list.resources.append(resource); + } + } + if (list.resources.size()) + list.syncPoint = context3d->insertSyncPoint(); + return list; +} + +CCResourceProvider::TransferableResourceList CCResourceProvider::prepareSendToChild(int child, const ResourceIdArray& resources) +{ + ASSERT(CCProxy::isImplThread()); + TransferableResourceList list; + list.syncPoint = 0; + WebGraphicsContext3D* context3d = m_context->context3D(); + if (!context3d || !context3d->makeContextCurrent()) { + // FIXME: Implement this path for software compositing. + return list; + } +#if WTF_NEW_HASHMAP_ITERATORS_INTERFACE + Child& childInfo = m_children.find(child)->value; +#else + Child& childInfo = m_children.find(child)->second; +#endif + for (ResourceIdArray::const_iterator it = resources.begin(); it != resources.end(); ++it) { + TransferableResource resource; + if (!transferResource(context3d, *it, &resource)) + ASSERT_NOT_REACHED(); + resource.id = childInfo.parentToChildMap.get(*it); + childInfo.parentToChildMap.remove(*it); + childInfo.childToParentMap.remove(resource.id); + list.resources.append(resource); + deleteResource(*it); + } + if (list.resources.size()) + list.syncPoint = context3d->insertSyncPoint(); + return list; +} + +void CCResourceProvider::receiveFromChild(int child, const TransferableResourceList& resources) +{ + ASSERT(CCProxy::isImplThread()); + WebGraphicsContext3D* context3d = m_context->context3D(); + if (!context3d || !context3d->makeContextCurrent()) { + // FIXME: Implement this path for software compositing. + return; + } + if (resources.syncPoint) { + // NOTE: If the parent is a browser and the child a renderer, the parent + // is not supposed to have its context wait, because that could induce + // deadlocks and/or security issues. The caller is responsible for + // waiting asynchronously, and resetting syncPoint before calling this. + // However if the parent is a renderer (e.g. browser tag), it may be ok + // (and is simpler) to wait. + GLC(context3d, context3d->waitSyncPoint(resources.syncPoint)); + } +#if WTF_NEW_HASHMAP_ITERATORS_INTERFACE + Child& childInfo = m_children.find(child)->value; +#else + Child& childInfo = m_children.find(child)->second; +#endif + for (Vector::const_iterator it = resources.resources.begin(); it != resources.resources.end(); ++it) { + unsigned textureId; + GLC(context3d, textureId = context3d->createTexture()); + GLC(context3d, context3d->bindTexture(GraphicsContext3D::TEXTURE_2D, textureId)); + GLC(context3d, context3d->consumeTextureCHROMIUM(GraphicsContext3D::TEXTURE_2D, it->mailbox.name)); + ResourceId id = m_nextId++; + Resource resource(textureId, childInfo.pool, it->size, it->format); + m_resources.add(id, resource); + m_mailboxes.append(it->mailbox); + childInfo.parentToChildMap.add(id, it->id); + childInfo.childToParentMap.add(it->id, id); + } +} + +void CCResourceProvider::receiveFromParent(const TransferableResourceList& resources) +{ + ASSERT(CCProxy::isImplThread()); + WebGraphicsContext3D* context3d = m_context->context3D(); + if (!context3d || !context3d->makeContextCurrent()) { + // FIXME: Implement this path for software compositing. + return; + } + if (resources.syncPoint) + GLC(context3d, context3d->waitSyncPoint(resources.syncPoint)); + for (Vector::const_iterator it = resources.resources.begin(); it != resources.resources.end(); ++it) { +#if WTF_NEW_HASHMAP_ITERATORS_INTERFACE + Resource* resource = &m_resources.find(it->id)->value; +#else + Resource* resource = &m_resources.find(it->id)->second; +#endif + ASSERT(resource->exported); + resource->exported = false; + GLC(context3d, context3d->bindTexture(GraphicsContext3D::TEXTURE_2D, resource->glId)); + GLC(context3d, context3d->consumeTextureCHROMIUM(GraphicsContext3D::TEXTURE_2D, it->mailbox.name)); + m_mailboxes.append(it->mailbox); + } +} + +bool CCResourceProvider::transferResource(WebGraphicsContext3D* context, ResourceId id, TransferableResource* resource) +{ + ASSERT(CCProxy::isImplThread()); + ResourceMap::const_iterator it = m_resources.find(id); + CHECK(it != m_resources.end()); +#if WTF_NEW_HASHMAP_ITERATORS_INTERFACE + const Resource* source = &it->value; +#else + const Resource* source = &it->second; +#endif + ASSERT(!source->lockedForWrite); + ASSERT(!source->lockForReadCount); + ASSERT(!source->external); + if (source->exported) + return false; + resource->id = id; + resource->format = source->format; + resource->size = source->size; + if (!m_mailboxes.isEmpty()) + resource->mailbox = m_mailboxes.takeFirst(); + else + GLC(context, context->genMailboxCHROMIUM(resource->mailbox.name)); + GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, source->glId)); + GLC(context, context->produceTextureCHROMIUM(GraphicsContext3D::TEXTURE_2D, resource->mailbox.name)); + return true; +} + +void CCResourceProvider::trimMailboxDeque() +{ + // Trim the mailbox deque to the maximum number of resources we may need to + // send. + // If we have a parent, any non-external resource not already transfered is + // eligible to be sent to the parent. Otherwise, all resources belonging to + // a child might need to be sent back to the child. + size_t maxMailboxCount = 0; + if (m_context->capabilities().hasParentCompositor) { + for (ResourceMap::iterator it = m_resources.begin(); it != m_resources.end(); ++it) { +#if WTF_NEW_HASHMAP_ITERATORS_INTERFACE + if (!it->value.exported && !it->value.external) +#else + if (!it->second.exported && !it->second.external) +#endif + ++maxMailboxCount; + } + } else { + base::hash_set childPoolSet; + for (ChildMap::iterator it = m_children.begin(); it != m_children.end(); ++it) +#if WTF_NEW_HASHMAP_ITERATORS_INTERFACE + childPoolSet.insert(it->value.pool); +#else + childPoolSet.insert(it->second.pool); +#endif + for (ResourceMap::iterator it = m_resources.begin(); it != m_resources.end(); ++it) { +#if WTF_NEW_HASHMAP_ITERATORS_INTERFACE + if (ContainsKey(childPoolSet, it->value.pool)) +#else + if (ContainsKey(childPoolSet, it->second.pool)) +#endif + ++maxMailboxCount; + } + } + while (m_mailboxes.size() > maxMailboxCount) + m_mailboxes.removeFirst(); +} + +} diff --git a/cc/resource_provider.h b/cc/resource_provider.h index 638cbb2..f515c11 100644 --- a/cc/resource_provider.h +++ b/cc/resource_provider.h @@ -1,3 +1,275 @@ // Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CCResourceProvider_h +#define CCResourceProvider_h + +#include "base/basictypes.h" +#include "CCGraphicsContext.h" +#include "GraphicsContext3D.h" +#include "IntSize.h" +#include "SkBitmap.h" +#include "SkCanvas.h" +#include "TextureCopier.h" +#include +#include +#include +#include +#include +#include +#include + +namespace WebKit { +class WebGraphicsContext3D; +} + +namespace cc { + +class IntRect; +class LayerTextureSubImage; +class TextureCopier; +class TextureUploader; + +// Thread-safety notes: this class is not thread-safe and can only be called +// from the thread it was created on (in practice, the compositor thread). +class CCResourceProvider { +public: + typedef unsigned ResourceId; + typedef Vector ResourceIdArray; + typedef HashMap ResourceIdMap; + enum TextureUsageHint { TextureUsageAny, TextureUsageFramebuffer }; + enum ResourceType { + GLTexture = 1, + Bitmap, + }; + struct Mailbox { + GC3Dbyte name[64]; + }; + struct TransferableResource { + unsigned id; + GC3Denum format; + IntSize size; + Mailbox mailbox; + }; + typedef Vector TransferableResourceArray; + struct TransferableResourceList { + TransferableResourceList(); + ~TransferableResourceList(); + + TransferableResourceArray resources; + unsigned syncPoint; + }; + + static PassOwnPtr create(CCGraphicsContext*); + + virtual ~CCResourceProvider(); + + WebKit::WebGraphicsContext3D* graphicsContext3D(); + TextureUploader* textureUploader() const { return m_textureUploader.get(); } + TextureCopier* textureCopier() const { return m_textureCopier.get(); } + int maxTextureSize() const { return m_maxTextureSize; } + unsigned numResources() const { return m_resources.size(); } + + // Checks whether a resource is in use by a consumer. + bool inUseByConsumer(ResourceId); + + + // Producer interface. + + void setDefaultResourceType(ResourceType type) { m_defaultResourceType = type; } + ResourceType defaultResourceType() const { return m_defaultResourceType; } + ResourceType resourceType(ResourceId); + + // Creates a resource of the default resource type. + ResourceId createResource(int pool, const IntSize&, GC3Denum format, TextureUsageHint); + + // You can also explicitly create a specific resource type. + ResourceId createGLTexture(int pool, const IntSize&, GC3Denum format, TextureUsageHint); + ResourceId createBitmap(int pool, const IntSize&); + // Wraps an external texture into a GL resource. + ResourceId createResourceFromExternalTexture(unsigned textureId); + + void deleteResource(ResourceId); + + // Deletes all resources owned by a given pool. + void deleteOwnedResources(int pool); + + // Upload data from image, copying sourceRect (in image) into destRect (in the resource). + void upload(ResourceId, const uint8_t* image, const IntRect& imageRect, const IntRect& sourceRect, const IntSize& destOffset); + + // Flush all context operations, kicking uploads and ensuring ordering with + // respect to other contexts. + void flush(); + + // Only flush the command buffer if supported. + // Returns true if the shallow flush occurred, false otherwise. + bool shallowFlushIfSupported(); + + // Creates accounting for a child, and associate it with a pool. Resources + // transfered from that child will go to that pool. Returns a child ID. + int createChild(int pool); + + // Destroys accounting for the child, deleting all resources from that pool. + void destroyChild(int child); + + // Gets the child->parent resource ID map. + const ResourceIdMap& getChildToParentMap(int child) const; + + // Prepares resources to be transfered to the parent, moving them to + // mailboxes and serializing meta-data into TransferableResources. + // Resources are not removed from the CCResourceProvider, but are markes as + // "in use". + TransferableResourceList prepareSendToParent(const ResourceIdArray&); + + // Prepares resources to be transfered back to the child, moving them to + // mailboxes and serializing meta-data into TransferableResources. + // Resources are removed from the CCResourceProvider. Note: the resource IDs + // passed are in the parent namespace and will be translated to the child + // namespace when returned. + TransferableResourceList prepareSendToChild(int child, const ResourceIdArray&); + + // Receives resources from a child, moving them from mailboxes. Resource IDs + // passed are in the child namespace, and will be translated to the parent + // namespace, added to the child->parent map. + // NOTE: if the syncPoint filed in TransferableResourceList is set, this + // will wait on it. + void receiveFromChild(int child, const TransferableResourceList&); + + // Receives resources from the parent, moving them from mailboxes. Resource IDs + // passed are in the child namespace. + // NOTE: if the syncPoint filed in TransferableResourceList is set, this + // will wait on it. + void receiveFromParent(const TransferableResourceList&); + + // Only for testing + size_t mailboxCount() const { return m_mailboxes.size(); } + + // The following lock classes are part of the CCResourceProvider API and are + // needed to read and write the resource contents. The user must ensure + // that they only use GL locks on GL resources, etc, and this is enforced + // by assertions. + class ScopedReadLockGL { + public: + ScopedReadLockGL(CCResourceProvider*, CCResourceProvider::ResourceId); + ~ScopedReadLockGL(); + + unsigned textureId() const { return m_textureId; } + + private: + CCResourceProvider* m_resourceProvider; + CCResourceProvider::ResourceId m_resourceId; + unsigned m_textureId; + + DISALLOW_COPY_AND_ASSIGN(ScopedReadLockGL); + }; + + class ScopedWriteLockGL { + public: + ScopedWriteLockGL(CCResourceProvider*, CCResourceProvider::ResourceId); + ~ScopedWriteLockGL(); + + unsigned textureId() const { return m_textureId; } + + private: + CCResourceProvider* m_resourceProvider; + CCResourceProvider::ResourceId m_resourceId; + unsigned m_textureId; + + DISALLOW_COPY_AND_ASSIGN(ScopedWriteLockGL); + }; + + class ScopedReadLockSoftware { + public: + ScopedReadLockSoftware(CCResourceProvider*, CCResourceProvider::ResourceId); + ~ScopedReadLockSoftware(); + + const SkBitmap* skBitmap() const { return &m_skBitmap; } + + private: + CCResourceProvider* m_resourceProvider; + CCResourceProvider::ResourceId m_resourceId; + SkBitmap m_skBitmap; + + DISALLOW_COPY_AND_ASSIGN(ScopedReadLockSoftware); + }; + + class ScopedWriteLockSoftware { + public: + ScopedWriteLockSoftware(CCResourceProvider*, CCResourceProvider::ResourceId); + ~ScopedWriteLockSoftware(); + + SkCanvas* skCanvas() { return m_skCanvas.get(); } + + private: + CCResourceProvider* m_resourceProvider; + CCResourceProvider::ResourceId m_resourceId; + SkBitmap m_skBitmap; + OwnPtr m_skCanvas; + + DISALLOW_COPY_AND_ASSIGN(ScopedWriteLockSoftware); + }; + +private: + struct Resource { + Resource(); + Resource(unsigned textureId, int pool, const IntSize& size, GC3Denum format); + Resource(uint8_t* pixels, int pool, const IntSize& size, GC3Denum format); + + unsigned glId; + uint8_t* pixels; + int pool; + int lockForReadCount; + bool lockedForWrite; + bool external; + bool exported; + IntSize size; + GC3Denum format; + ResourceType type; + }; + typedef HashMap ResourceMap; + struct Child { + Child(); + ~Child(); + + int pool; + ResourceIdMap childToParentMap; + ResourceIdMap parentToChildMap; + }; + typedef HashMap ChildMap; + + explicit CCResourceProvider(CCGraphicsContext*); + bool initialize(); + + const Resource* lockForRead(ResourceId); + void unlockForRead(ResourceId); + const Resource* lockForWrite(ResourceId); + void unlockForWrite(ResourceId); + static void populateSkBitmapWithResource(SkBitmap*, const Resource*); + + bool transferResource(WebKit::WebGraphicsContext3D*, ResourceId, TransferableResource*); + void trimMailboxDeque(); + + CCGraphicsContext* m_context; + ResourceId m_nextId; + ResourceMap m_resources; + int m_nextChild; + ChildMap m_children; + + Deque m_mailboxes; + + ResourceType m_defaultResourceType; + bool m_useTextureStorageExt; + bool m_useTextureUsageHint; + bool m_useShallowFlush; + OwnPtr m_texSubImage; + OwnPtr m_textureUploader; + OwnPtr m_textureCopier; + int m_maxTextureSize; + + DISALLOW_COPY_AND_ASSIGN(CCResourceProvider); +}; + +} + +#endif diff --git a/cc/scheduler.cc b/cc/scheduler.cc new file mode 100644 index 0000000..869cd19 --- /dev/null +++ b/cc/scheduler.cc @@ -0,0 +1,192 @@ +// Copyright 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#include "CCScheduler.h" + +#include "TraceEvent.h" +#include + +namespace cc { + +CCScheduler::CCScheduler(CCSchedulerClient* client, scoped_ptr frameRateController) + : m_client(client) + , m_frameRateController(frameRateController.Pass()) + , m_insideProcessScheduledActions(false) +{ + ASSERT(m_client); + m_frameRateController->setClient(this); + ASSERT(!m_stateMachine.vsyncCallbackNeeded()); +} + +CCScheduler::~CCScheduler() +{ + m_frameRateController->setActive(false); +} + +void CCScheduler::setCanBeginFrame(bool can) +{ + m_stateMachine.setCanBeginFrame(can); + processScheduledActions(); +} + +void CCScheduler::setVisible(bool visible) +{ + m_stateMachine.setVisible(visible); + processScheduledActions(); +} + +void CCScheduler::setCanDraw(bool canDraw) +{ + m_stateMachine.setCanDraw(canDraw); + processScheduledActions(); +} + +void CCScheduler::setNeedsCommit() +{ + m_stateMachine.setNeedsCommit(); + processScheduledActions(); +} + +void CCScheduler::setNeedsForcedCommit() +{ + m_stateMachine.setNeedsForcedCommit(); + processScheduledActions(); +} + +void CCScheduler::setNeedsRedraw() +{ + m_stateMachine.setNeedsRedraw(); + processScheduledActions(); +} + +void CCScheduler::setNeedsForcedRedraw() +{ + m_stateMachine.setNeedsForcedRedraw(); + processScheduledActions(); +} + +void CCScheduler::setMainThreadNeedsLayerTextures() +{ + m_stateMachine.setMainThreadNeedsLayerTextures(); + processScheduledActions(); +} + +void CCScheduler::beginFrameComplete() +{ + TRACE_EVENT0("cc", "CCScheduler::beginFrameComplete"); + m_stateMachine.beginFrameComplete(); + processScheduledActions(); +} + +void CCScheduler::beginFrameAborted() +{ + TRACE_EVENT0("cc", "CCScheduler::beginFrameAborted"); + m_stateMachine.beginFrameAborted(); + processScheduledActions(); +} + +void CCScheduler::setMaxFramesPending(int maxFramesPending) +{ + m_frameRateController->setMaxFramesPending(maxFramesPending); +} + +void CCScheduler::setSwapBuffersCompleteSupported(bool supported) +{ + m_frameRateController->setSwapBuffersCompleteSupported(supported); +} + +void CCScheduler::didSwapBuffersComplete() +{ + TRACE_EVENT0("cc", "CCScheduler::didSwapBuffersComplete"); + m_frameRateController->didFinishFrame(); +} + +void CCScheduler::didLoseContext() +{ + TRACE_EVENT0("cc", "CCScheduler::didLoseContext"); + m_frameRateController->didAbortAllPendingFrames(); + m_stateMachine.didLoseContext(); + processScheduledActions(); +} + +void CCScheduler::didRecreateContext() +{ + TRACE_EVENT0("cc", "CCScheduler::didRecreateContext"); + m_stateMachine.didRecreateContext(); + processScheduledActions(); +} + +void CCScheduler::setTimebaseAndInterval(base::TimeTicks timebase, base::TimeDelta interval) +{ + m_frameRateController->setTimebaseAndInterval(timebase, interval); +} + +base::TimeTicks CCScheduler::anticipatedDrawTime() +{ + return m_frameRateController->nextTickTime(); +} + +void CCScheduler::vsyncTick(bool throttled) +{ + TRACE_EVENT1("cc", "CCScheduler::vsyncTick", "throttled", throttled); + if (!throttled) + m_stateMachine.didEnterVSync(); + processScheduledActions(); + if (!throttled) + m_stateMachine.didLeaveVSync(); +} + +void CCScheduler::processScheduledActions() +{ + // We do not allow processScheduledActions to be recursive. + // The top-level call will iteratively execute the next action for us anyway. + if (m_insideProcessScheduledActions) + return; + + AutoReset markInside(&m_insideProcessScheduledActions, true); + + CCSchedulerStateMachine::Action action = m_stateMachine.nextAction(); + while (action != CCSchedulerStateMachine::ACTION_NONE) { + m_stateMachine.updateState(action); + TRACE_EVENT1("cc", "CCScheduler::processScheduledActions()", "action", action); + + switch (action) { + case CCSchedulerStateMachine::ACTION_NONE: + break; + case CCSchedulerStateMachine::ACTION_BEGIN_FRAME: + m_client->scheduledActionBeginFrame(); + break; + case CCSchedulerStateMachine::ACTION_COMMIT: + m_client->scheduledActionCommit(); + break; + case CCSchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE: { + CCScheduledActionDrawAndSwapResult result = m_client->scheduledActionDrawAndSwapIfPossible(); + m_stateMachine.didDrawIfPossibleCompleted(result.didDraw); + if (result.didSwap) + m_frameRateController->didBeginFrame(); + break; + } + case CCSchedulerStateMachine::ACTION_DRAW_FORCED: { + CCScheduledActionDrawAndSwapResult result = m_client->scheduledActionDrawAndSwapForced(); + if (result.didSwap) + m_frameRateController->didBeginFrame(); + break; + } case CCSchedulerStateMachine::ACTION_BEGIN_CONTEXT_RECREATION: + m_client->scheduledActionBeginContextRecreation(); + break; + case CCSchedulerStateMachine::ACTION_ACQUIRE_LAYER_TEXTURES_FOR_MAIN_THREAD: + m_client->scheduledActionAcquireLayerTexturesForMainThread(); + break; + } + action = m_stateMachine.nextAction(); + } + + // Activate or deactivate the frame rate controller. + m_frameRateController->setActive(m_stateMachine.vsyncCallbackNeeded()); + m_client->didAnticipatedDrawTimeChange(m_frameRateController->nextTickTime()); +} + +} // namespace cc diff --git a/cc/scheduler.h b/cc/scheduler.h index 638cbb2..1b48307 100644 --- a/cc/scheduler.h +++ b/cc/scheduler.h @@ -1,3 +1,109 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. +// Copyright 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CCScheduler_h +#define CCScheduler_h + +#include "base/basictypes.h" +#include "base/memory/scoped_ptr.h" +#include "base/time.h" +#include "CCFrameRateController.h" +#include "CCSchedulerStateMachine.h" +#include + +namespace cc { + +class CCThread; + +struct CCScheduledActionDrawAndSwapResult { + CCScheduledActionDrawAndSwapResult() + : didDraw(false) + , didSwap(false) + { + } + CCScheduledActionDrawAndSwapResult(bool didDraw, bool didSwap) + : didDraw(didDraw) + , didSwap(didSwap) + { + } + bool didDraw; + bool didSwap; +}; + +class CCSchedulerClient { +public: + virtual void scheduledActionBeginFrame() = 0; + virtual CCScheduledActionDrawAndSwapResult scheduledActionDrawAndSwapIfPossible() = 0; + virtual CCScheduledActionDrawAndSwapResult scheduledActionDrawAndSwapForced() = 0; + virtual void scheduledActionCommit() = 0; + virtual void scheduledActionBeginContextRecreation() = 0; + virtual void scheduledActionAcquireLayerTexturesForMainThread() = 0; + virtual void didAnticipatedDrawTimeChange(base::TimeTicks) = 0; + +protected: + virtual ~CCSchedulerClient() { } +}; + +class CCScheduler : CCFrameRateControllerClient { +public: + static PassOwnPtr create(CCSchedulerClient* client, scoped_ptr frameRateController) + { + return adoptPtr(new CCScheduler(client, frameRateController.Pass())); + } + + virtual ~CCScheduler(); + + void setCanBeginFrame(bool); + + void setVisible(bool); + void setCanDraw(bool); + + void setNeedsCommit(); + + // Like setNeedsCommit(), but ensures a commit will definitely happen even if we are not visible. + void setNeedsForcedCommit(); + + void setNeedsRedraw(); + + void setMainThreadNeedsLayerTextures(); + + // Like setNeedsRedraw(), but ensures the draw will definitely happen even if we are not visible. + void setNeedsForcedRedraw(); + + void beginFrameComplete(); + void beginFrameAborted(); + + void setMaxFramesPending(int); + void setSwapBuffersCompleteSupported(bool); + void didSwapBuffersComplete(); + + void didLoseContext(); + void didRecreateContext(); + + bool commitPending() const { return m_stateMachine.commitPending(); } + bool redrawPending() const { return m_stateMachine.redrawPending(); } + + void setTimebaseAndInterval(base::TimeTicks timebase, base::TimeDelta interval); + + base::TimeTicks anticipatedDrawTime(); + + // CCFrameRateControllerClient implementation + virtual void vsyncTick(bool throttled) OVERRIDE; + +private: + CCScheduler(CCSchedulerClient*, scoped_ptr); + + void processScheduledActions(); + + CCSchedulerClient* m_client; + scoped_ptr m_frameRateController; + CCSchedulerStateMachine m_stateMachine; + bool m_insideProcessScheduledActions; + + DISALLOW_COPY_AND_ASSIGN(CCScheduler); +}; + +} // namespace cc + +#endif // CCScheduler_h diff --git a/cc/scheduler_state_machine.cc b/cc/scheduler_state_machine.cc new file mode 100644 index 0000000..3eaf5cd --- /dev/null +++ b/cc/scheduler_state_machine.cc @@ -0,0 +1,317 @@ +// Copyright 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#include "CCSchedulerStateMachine.h" +#include "base/stringprintf.h" + + +namespace cc { + +CCSchedulerStateMachine::CCSchedulerStateMachine() + : m_commitState(COMMIT_STATE_IDLE) + , m_currentFrameNumber(0) + , m_lastFrameNumberWhereDrawWasCalled(-1) + , m_consecutiveFailedDraws(0) + , m_maximumNumberOfFailedDrawsBeforeDrawIsForced(3) + , m_needsRedraw(false) + , m_needsForcedRedraw(false) + , m_needsForcedRedrawAfterNextCommit(false) + , m_needsCommit(false) + , m_needsForcedCommit(false) + , m_mainThreadNeedsLayerTextures(false) + , m_insideVSync(false) + , m_visible(false) + , m_canBeginFrame(false) + , m_canDraw(false) + , m_drawIfPossibleFailed(false) + , m_textureState(LAYER_TEXTURE_STATE_UNLOCKED) + , m_contextState(CONTEXT_ACTIVE) +{ +} + +std::string CCSchedulerStateMachine::toString() +{ + std::string str; + base::StringAppendF(&str, "m_commitState = %d; ", m_commitState); + base::StringAppendF(&str, "m_currentFrameNumber = %d; ", m_currentFrameNumber); + base::StringAppendF(&str, "m_lastFrameNumberWhereDrawWasCalled = %d; ", m_lastFrameNumberWhereDrawWasCalled); + base::StringAppendF(&str, "m_consecutiveFailedDraws = %d; ", m_consecutiveFailedDraws); + base::StringAppendF(&str, "m_maximumNumberOfFailedDrawsBeforeDrawIsForced = %d; ", m_maximumNumberOfFailedDrawsBeforeDrawIsForced); + base::StringAppendF(&str, "m_needsRedraw = %d; ", m_needsRedraw); + base::StringAppendF(&str, "m_needsForcedRedraw = %d; ", m_needsForcedRedraw); + base::StringAppendF(&str, "m_needsForcedRedrawAfterNextCommit = %d; ", m_needsForcedRedrawAfterNextCommit); + base::StringAppendF(&str, "m_needsCommit = %d; ", m_needsCommit); + base::StringAppendF(&str, "m_needsForcedCommit = %d; ", m_needsForcedCommit); + base::StringAppendF(&str, "m_mainThreadNeedsLayerTextures = %d; ", m_mainThreadNeedsLayerTextures); + base::StringAppendF(&str, "m_insideVSync = %d; ", m_insideVSync); + base::StringAppendF(&str, "m_visible = %d; ", m_visible); + base::StringAppendF(&str, "m_canBeginFrame = %d; ", m_canBeginFrame); + base::StringAppendF(&str, "m_canDraw = %d; ", m_canDraw); + base::StringAppendF(&str, "m_drawIfPossibleFailed = %d; ", m_drawIfPossibleFailed); + base::StringAppendF(&str, "m_textureState = %d; ", m_textureState); + base::StringAppendF(&str, "m_contextState = %d; ", m_contextState); + return str; +} + +bool CCSchedulerStateMachine::hasDrawnThisFrame() const +{ + return m_currentFrameNumber == m_lastFrameNumberWhereDrawWasCalled; +} + +bool CCSchedulerStateMachine::drawSuspendedUntilCommit() const +{ + if (!m_canDraw) + return true; + if (!m_visible) + return true; + if (m_textureState == LAYER_TEXTURE_STATE_ACQUIRED_BY_MAIN_THREAD) + return true; + return false; +} + +bool CCSchedulerStateMachine::scheduledToDraw() const +{ + if (!m_needsRedraw) + return false; + if (drawSuspendedUntilCommit()) + return false; + return true; +} + +bool CCSchedulerStateMachine::shouldDraw() const +{ + if (m_needsForcedRedraw) + return true; + + if (!scheduledToDraw()) + return false; + if (!m_insideVSync) + return false; + if (hasDrawnThisFrame()) + return false; + if (m_contextState != CONTEXT_ACTIVE) + return false; + return true; +} + +bool CCSchedulerStateMachine::shouldAcquireLayerTexturesForMainThread() const +{ + if (!m_mainThreadNeedsLayerTextures) + return false; + if (m_textureState == LAYER_TEXTURE_STATE_UNLOCKED) + return true; + ASSERT(m_textureState == LAYER_TEXTURE_STATE_ACQUIRED_BY_IMPL_THREAD); + // Transfer the lock from impl thread to main thread immediately if the + // impl thread is not even scheduled to draw. Guards against deadlocking. + if (!scheduledToDraw()) + return true; + if (!vsyncCallbackNeeded()) + return true; + return false; +} + +CCSchedulerStateMachine::Action CCSchedulerStateMachine::nextAction() const +{ + if (shouldAcquireLayerTexturesForMainThread()) + return ACTION_ACQUIRE_LAYER_TEXTURES_FOR_MAIN_THREAD; + switch (m_commitState) { + case COMMIT_STATE_IDLE: + if (m_contextState != CONTEXT_ACTIVE && m_needsForcedRedraw) + return ACTION_DRAW_FORCED; + if (m_contextState != CONTEXT_ACTIVE && m_needsForcedCommit) + return ACTION_BEGIN_FRAME; + if (m_contextState == CONTEXT_LOST) + return ACTION_BEGIN_CONTEXT_RECREATION; + if (m_contextState == CONTEXT_RECREATING) + return ACTION_NONE; + if (shouldDraw()) + return m_needsForcedRedraw ? ACTION_DRAW_FORCED : ACTION_DRAW_IF_POSSIBLE; + if (m_needsCommit && ((m_visible && m_canBeginFrame) || m_needsForcedCommit)) + return ACTION_BEGIN_FRAME; + return ACTION_NONE; + + case COMMIT_STATE_FRAME_IN_PROGRESS: + if (shouldDraw()) + return m_needsForcedRedraw ? ACTION_DRAW_FORCED : ACTION_DRAW_IF_POSSIBLE; + return ACTION_NONE; + + case COMMIT_STATE_READY_TO_COMMIT: + return ACTION_COMMIT; + + case COMMIT_STATE_WAITING_FOR_FIRST_DRAW: + if (shouldDraw() || m_contextState == CONTEXT_LOST) + return m_needsForcedRedraw ? ACTION_DRAW_FORCED : ACTION_DRAW_IF_POSSIBLE; + // COMMIT_STATE_WAITING_FOR_FIRST_DRAW wants to enforce a draw. If m_canDraw is false + // or textures are not available, proceed to the next step (similar as in COMMIT_STATE_IDLE). + bool canCommit = m_visible || m_needsForcedCommit; + if (m_needsCommit && canCommit && drawSuspendedUntilCommit()) + return ACTION_BEGIN_FRAME; + return ACTION_NONE; + } + ASSERT_NOT_REACHED(); + return ACTION_NONE; +} + +void CCSchedulerStateMachine::updateState(Action action) +{ + switch (action) { + case ACTION_NONE: + return; + + case ACTION_BEGIN_FRAME: + ASSERT(m_visible || m_needsForcedCommit); + m_commitState = COMMIT_STATE_FRAME_IN_PROGRESS; + m_needsCommit = false; + m_needsForcedCommit = false; + return; + + case ACTION_COMMIT: + m_commitState = COMMIT_STATE_WAITING_FOR_FIRST_DRAW; + m_needsRedraw = true; + if (m_drawIfPossibleFailed) + m_lastFrameNumberWhereDrawWasCalled = -1; + + if (m_needsForcedRedrawAfterNextCommit) { + m_needsForcedRedrawAfterNextCommit = false; + m_needsForcedRedraw = true; + } + + m_textureState = LAYER_TEXTURE_STATE_ACQUIRED_BY_IMPL_THREAD; + return; + + case ACTION_DRAW_FORCED: + case ACTION_DRAW_IF_POSSIBLE: + m_needsRedraw = false; + m_needsForcedRedraw = false; + m_drawIfPossibleFailed = false; + if (m_insideVSync) + m_lastFrameNumberWhereDrawWasCalled = m_currentFrameNumber; + if (m_commitState == COMMIT_STATE_WAITING_FOR_FIRST_DRAW) + m_commitState = COMMIT_STATE_IDLE; + if (m_textureState == LAYER_TEXTURE_STATE_ACQUIRED_BY_IMPL_THREAD) + m_textureState = LAYER_TEXTURE_STATE_UNLOCKED; + return; + + case ACTION_BEGIN_CONTEXT_RECREATION: + ASSERT(m_commitState == COMMIT_STATE_IDLE); + ASSERT(m_contextState == CONTEXT_LOST); + m_contextState = CONTEXT_RECREATING; + return; + + case ACTION_ACQUIRE_LAYER_TEXTURES_FOR_MAIN_THREAD: + m_textureState = LAYER_TEXTURE_STATE_ACQUIRED_BY_MAIN_THREAD; + m_mainThreadNeedsLayerTextures = false; + if (m_commitState != COMMIT_STATE_FRAME_IN_PROGRESS) + m_needsCommit = true; + return; + } +} + +void CCSchedulerStateMachine::setMainThreadNeedsLayerTextures() +{ + ASSERT(!m_mainThreadNeedsLayerTextures); + ASSERT(m_textureState != LAYER_TEXTURE_STATE_ACQUIRED_BY_MAIN_THREAD); + m_mainThreadNeedsLayerTextures = true; +} + +bool CCSchedulerStateMachine::vsyncCallbackNeeded() const +{ + // If we can't draw, don't tick until we are notified that we can draw again. + if (!m_canDraw) + return false; + + if (m_needsForcedRedraw) + return true; + + return m_needsRedraw && m_visible && m_contextState == CONTEXT_ACTIVE; +} + +void CCSchedulerStateMachine::didEnterVSync() +{ + m_insideVSync = true; +} + +void CCSchedulerStateMachine::didLeaveVSync() +{ + m_currentFrameNumber++; + m_insideVSync = false; +} + +void CCSchedulerStateMachine::setVisible(bool visible) +{ + m_visible = visible; +} + +void CCSchedulerStateMachine::setNeedsRedraw() +{ + m_needsRedraw = true; +} + +void CCSchedulerStateMachine::setNeedsForcedRedraw() +{ + m_needsForcedRedraw = true; +} + +void CCSchedulerStateMachine::didDrawIfPossibleCompleted(bool success) +{ + m_drawIfPossibleFailed = !success; + if (m_drawIfPossibleFailed) { + m_needsRedraw = true; + m_needsCommit = true; + m_consecutiveFailedDraws++; + if (m_consecutiveFailedDraws >= m_maximumNumberOfFailedDrawsBeforeDrawIsForced) { + m_consecutiveFailedDraws = 0; + // We need to force a draw, but it doesn't make sense to do this until + // we've committed and have new textures. + m_needsForcedRedrawAfterNextCommit = true; + } + } else + m_consecutiveFailedDraws = 0; +} + +void CCSchedulerStateMachine::setNeedsCommit() +{ + m_needsCommit = true; +} + +void CCSchedulerStateMachine::setNeedsForcedCommit() +{ + m_needsForcedCommit = true; +} + +void CCSchedulerStateMachine::beginFrameComplete() +{ + ASSERT(m_commitState == COMMIT_STATE_FRAME_IN_PROGRESS); + m_commitState = COMMIT_STATE_READY_TO_COMMIT; +} + +void CCSchedulerStateMachine::beginFrameAborted() +{ + ASSERT(m_commitState == COMMIT_STATE_FRAME_IN_PROGRESS); + m_commitState = COMMIT_STATE_IDLE; + setNeedsCommit(); +} + +void CCSchedulerStateMachine::didLoseContext() +{ + if (m_contextState == CONTEXT_LOST || m_contextState == CONTEXT_RECREATING) + return; + m_contextState = CONTEXT_LOST; +} + +void CCSchedulerStateMachine::didRecreateContext() +{ + ASSERT(m_contextState == CONTEXT_RECREATING); + m_contextState = CONTEXT_ACTIVE; + setNeedsCommit(); +} + +void CCSchedulerStateMachine::setMaximumNumberOfFailedDrawsBeforeDrawIsForced(int numDraws) +{ + m_maximumNumberOfFailedDrawsBeforeDrawIsForced = numDraws; +} + +} diff --git a/cc/scheduler_state_machine.h b/cc/scheduler_state_machine.h index 638cbb2..092231f 100644 --- a/cc/scheduler_state_machine.h +++ b/cc/scheduler_state_machine.h @@ -1,3 +1,161 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. +// Copyright 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CCSchedulerStateMachine_h +#define CCSchedulerStateMachine_h + +#include + +#include "base/basictypes.h" + +namespace cc { + +// The CCSchedulerStateMachine decides how to coordinate main thread activites +// like painting/running javascript with rendering and input activities on the +// impl thread. +// +// The state machine tracks internal state but is also influenced by external state. +// Internal state includes things like whether a frame has been requested, while +// external state includes things like the current time being near to the vblank time. +// +// The scheduler seperates "what to do next" from the updating of its internal state to +// make testing cleaner. +class CCSchedulerStateMachine { +public: + CCSchedulerStateMachine(); + + enum CommitState { + COMMIT_STATE_IDLE, + COMMIT_STATE_FRAME_IN_PROGRESS, + COMMIT_STATE_READY_TO_COMMIT, + COMMIT_STATE_WAITING_FOR_FIRST_DRAW, + }; + + enum TextureState { + LAYER_TEXTURE_STATE_UNLOCKED, + LAYER_TEXTURE_STATE_ACQUIRED_BY_MAIN_THREAD, + LAYER_TEXTURE_STATE_ACQUIRED_BY_IMPL_THREAD, + }; + + enum ContextState { + CONTEXT_ACTIVE, + CONTEXT_LOST, + CONTEXT_RECREATING, + }; + + bool commitPending() const + { + return m_commitState != COMMIT_STATE_IDLE; + } + + bool redrawPending() const { return m_needsRedraw; } + + enum Action { + ACTION_NONE, + ACTION_BEGIN_FRAME, + ACTION_COMMIT, + ACTION_DRAW_IF_POSSIBLE, + ACTION_DRAW_FORCED, + ACTION_BEGIN_CONTEXT_RECREATION, + ACTION_ACQUIRE_LAYER_TEXTURES_FOR_MAIN_THREAD, + }; + Action nextAction() const; + void updateState(Action); + + // Indicates whether the scheduler needs a vsync callback in order to make + // progress. + bool vsyncCallbackNeeded() const; + + // Indicates that the system has entered and left a vsync callback. + // The scheduler will not draw more than once in a given vsync callback. + void didEnterVSync(); + void didLeaveVSync(); + + // Indicates whether the LayerTreeHostImpl is visible. + void setVisible(bool); + + // Indicates that a redraw is required, either due to the impl tree changing + // or the screen being damaged and simply needing redisplay. + void setNeedsRedraw(); + + // As setNeedsRedraw(), but ensures the draw will definitely happen even if + // we are not visible. + void setNeedsForcedRedraw(); + + // Indicates whether ACTION_DRAW_IF_POSSIBLE drew to the screen or not. + void didDrawIfPossibleCompleted(bool success); + + // Indicates that a new commit flow needs to be performed, either to pull + // updates from the main thread to the impl, or to push deltas from the impl + // thread to main. + void setNeedsCommit(); + + // As setNeedsCommit(), but ensures the beginFrame will definitely happen even if + // we are not visible. + void setNeedsForcedCommit(); + + // Call this only in response to receiving an ACTION_BEGIN_FRAME + // from nextState. Indicates that all painting is complete. + void beginFrameComplete(); + + // Call this only in response to receiving an ACTION_BEGIN_FRAME + // from nextState if the client rejects the beginFrame message. + void beginFrameAborted(); + + // Request exclusive access to the textures that back single buffered + // layers on behalf of the main thread. Upon acqusition, + // ACTION_DRAW_IF_POSSIBLE will not draw until the main thread releases the + // textures to the impl thread by committing the layers. + void setMainThreadNeedsLayerTextures(); + + // Indicates whether we can successfully begin a frame at this time. + void setCanBeginFrame(bool can) { m_canBeginFrame = can; } + + // Indicates whether drawing would, at this time, make sense. + // canDraw can be used to supress flashes or checkerboarding + // when such behavior would be undesirable. + void setCanDraw(bool can) { m_canDraw = can; } + + void didLoseContext(); + void didRecreateContext(); + + // Exposed for testing purposes. + void setMaximumNumberOfFailedDrawsBeforeDrawIsForced(int); + + std::string toString(); + +protected: + bool shouldDrawForced() const; + bool drawSuspendedUntilCommit() const; + bool scheduledToDraw() const; + bool shouldDraw() const; + bool shouldAcquireLayerTexturesForMainThread() const; + bool hasDrawnThisFrame() const; + + CommitState m_commitState; + + int m_currentFrameNumber; + int m_lastFrameNumberWhereDrawWasCalled; + int m_consecutiveFailedDraws; + int m_maximumNumberOfFailedDrawsBeforeDrawIsForced; + bool m_needsRedraw; + bool m_needsForcedRedraw; + bool m_needsForcedRedrawAfterNextCommit; + bool m_needsCommit; + bool m_needsForcedCommit; + bool m_mainThreadNeedsLayerTextures; + bool m_insideVSync; + bool m_visible; + bool m_canBeginFrame; + bool m_canDraw; + bool m_drawIfPossibleFailed; + TextureState m_textureState; + ContextState m_contextState; + + DISALLOW_COPY_AND_ASSIGN(CCSchedulerStateMachine); +}; + +} + +#endif // CCSchedulerStateMachine_h diff --git a/cc/scoped_texture.cc b/cc/scoped_texture.cc new file mode 100644 index 0000000..d43ebe3 --- /dev/null +++ b/cc/scoped_texture.cc @@ -0,0 +1,51 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#include "CCScopedTexture.h" + +namespace cc { + +CCScopedTexture::CCScopedTexture(CCResourceProvider* resourceProvider) + : m_resourceProvider(resourceProvider) +{ + ASSERT(m_resourceProvider); +} + +CCScopedTexture::~CCScopedTexture() +{ + free(); +} + +bool CCScopedTexture::allocate(int pool, const IntSize& size, GC3Denum format, CCResourceProvider::TextureUsageHint hint) +{ + ASSERT(!id()); + ASSERT(!size.isEmpty()); + + setDimensions(size, format); + setId(m_resourceProvider->createResource(pool, size, format, hint)); + +#if !ASSERT_DISABLED + m_allocateThreadIdentifier = base::PlatformThread::CurrentId(); +#endif + + return id(); +} + +void CCScopedTexture::free() +{ + if (id()) { + ASSERT(m_allocateThreadIdentifier == base::PlatformThread::CurrentId()); + m_resourceProvider->deleteResource(id()); + } + setId(0); +} + +void CCScopedTexture::leak() +{ + setId(0); +} + +} diff --git a/cc/scoped_texture.h b/cc/scoped_texture.h index 638cbb2..a5b615c 100644 --- a/cc/scoped_texture.h +++ b/cc/scoped_texture.h @@ -1,3 +1,46 @@ // Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CCScopedTexture_h +#define CCScopedTexture_h + +#include "base/basictypes.h" +#include "CCTexture.h" + +#if !ASSERT_DISABLED +#include "base/threading/platform_thread.h" +#endif + +namespace cc { + +class CCScopedTexture : protected CCTexture { +public: + static PassOwnPtr create(CCResourceProvider* resourceProvider) { return adoptPtr(new CCScopedTexture(resourceProvider)); } + virtual ~CCScopedTexture(); + + using CCTexture::id; + using CCTexture::size; + using CCTexture::format; + using CCTexture::bytes; + + bool allocate(int pool, const IntSize&, GC3Denum format, CCResourceProvider::TextureUsageHint); + void free(); + void leak(); + +protected: + explicit CCScopedTexture(CCResourceProvider*); + +private: + CCResourceProvider* m_resourceProvider; + +#if !ASSERT_DISABLED + base::PlatformThreadId m_allocateThreadIdentifier; +#endif + + DISALLOW_COPY_AND_ASSIGN(CCScopedTexture); +}; + +} + +#endif diff --git a/cc/scoped_thread_proxy.cc b/cc/scoped_thread_proxy.cc new file mode 100644 index 0000000..c2f1b13 --- /dev/null +++ b/cc/scoped_thread_proxy.cc @@ -0,0 +1,21 @@ +// Copyright 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#include "CCScopedThreadProxy.h" + +namespace cc { + +CCScopedThreadProxy::CCScopedThreadProxy(CCThread* targetThread) + : m_targetThread(targetThread) + , m_shutdown(false) +{ +} + +CCScopedThreadProxy::~CCScopedThreadProxy() +{ +} + +} diff --git a/cc/scoped_thread_proxy.h b/cc/scoped_thread_proxy.h index 638cbb2..802046d 100644 --- a/cc/scoped_thread_proxy.h +++ b/cc/scoped_thread_proxy.h @@ -1,3 +1,74 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. +// Copyright 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CCScopedThreadProxy_h +#define CCScopedThreadProxy_h + +#include "CCThreadTask.h" +#include "base/threading/platform_thread.h" +#include +#include +#include + +namespace cc { + +// This class is a proxy used to post tasks to an target thread from any other thread. The proxy may be shut down at +// any point from the target thread after which no more tasks posted to the proxy will run. In other words, all +// tasks posted via a proxy are scoped to the lifecycle of the proxy. Use this when posting tasks to an object that +// might die with tasks in flight. +// +// The proxy must be created and shut down from the target thread, tasks may be posted from any thread. +// +// Implementation note: Unlike ScopedRunnableMethodFactory in Chromium, pending tasks are not cancelled by actually +// destroying the proxy. Instead each pending task holds a reference to the proxy to avoid maintaining an explicit +// list of outstanding tasks. +class CCScopedThreadProxy : public ThreadSafeRefCounted { +public: + static PassRefPtr create(CCThread* targetThread) + { + ASSERT(base::PlatformThread::CurrentId() == targetThread->threadID()); + return adoptRef(new CCScopedThreadProxy(targetThread)); + } + + ~CCScopedThreadProxy(); + + // Can be called from any thread. Posts a task to the target thread that runs unless + // shutdown() is called before it runs. + void postTask(PassOwnPtr task) + { + ref(); + m_targetThread->postTask(createCCThreadTask(this, &CCScopedThreadProxy::runTaskIfNotShutdown, task)); + } + + void shutdown() + { + ASSERT(base::PlatformThread::CurrentId() == m_targetThread->threadID()); + ASSERT(!m_shutdown); + m_shutdown = true; + } + +private: + explicit CCScopedThreadProxy(CCThread* targetThread); + + void runTaskIfNotShutdown(PassOwnPtr popTask) + { + OwnPtr task = popTask; + // If our shutdown flag is set, it's possible that m_targetThread has already been destroyed so don't + // touch it. + if (m_shutdown) { + deref(); + return; + } + ASSERT(base::PlatformThread::CurrentId() == m_targetThread->threadID()); + task->performTask(); + deref(); + } + + CCThread* m_targetThread; + bool m_shutdown; // Only accessed on the target thread +}; + +} + +#endif diff --git a/cc/scrollbar_animation_controller.cc b/cc/scrollbar_animation_controller.cc new file mode 100644 index 0000000..89f74cb --- /dev/null +++ b/cc/scrollbar_animation_controller.cc @@ -0,0 +1,97 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#include "CCScrollbarAnimationController.h" + +#include "CCScrollbarLayerImpl.h" +#include + +#if OS(ANDROID) +#include "CCScrollbarAnimationControllerLinearFade.h" +#endif + +namespace cc { + +#if OS(ANDROID) +PassOwnPtr CCScrollbarAnimationController::create(CCLayerImpl* scrollLayer) +{ + static const double fadeoutDelay = 0.3; + static const double fadeoutLength = 0.3; + return CCScrollbarAnimationControllerLinearFade::create(scrollLayer, fadeoutDelay, fadeoutLength); +} +#else +PassOwnPtr CCScrollbarAnimationController::create(CCLayerImpl* scrollLayer) +{ + return adoptPtr(new CCScrollbarAnimationController(scrollLayer)); +} +#endif + +CCScrollbarAnimationController::CCScrollbarAnimationController(CCLayerImpl* scrollLayer) + : m_horizontalScrollbarLayer(0) + , m_verticalScrollbarLayer(0) +{ + CCScrollbarAnimationController::updateScrollOffsetAtTime(scrollLayer, 0); +} + +CCScrollbarAnimationController::~CCScrollbarAnimationController() +{ +} + +bool CCScrollbarAnimationController::animate(double) +{ + return false; +} + +void CCScrollbarAnimationController::didPinchGestureBegin() +{ + didPinchGestureBeginAtTime(monotonicallyIncreasingTime()); +} + +void CCScrollbarAnimationController::didPinchGestureUpdate() +{ + didPinchGestureUpdateAtTime(monotonicallyIncreasingTime()); +} + +void CCScrollbarAnimationController::didPinchGestureEnd() +{ + didPinchGestureEndAtTime(monotonicallyIncreasingTime()); +} + +void CCScrollbarAnimationController::updateScrollOffset(CCLayerImpl* scrollLayer) +{ + updateScrollOffsetAtTime(scrollLayer, monotonicallyIncreasingTime()); +} + +IntSize CCScrollbarAnimationController::getScrollLayerBounds(const CCLayerImpl* scrollLayer) +{ + if (!scrollLayer->children().size()) + return IntSize(); + // Copy & paste from CCLayerTreeHostImpl... + // FIXME: Hardcoding the first child here is weird. Think of + // a cleaner way to get the contentBounds on the Impl side. + return scrollLayer->children()[0]->bounds(); +} + +void CCScrollbarAnimationController::updateScrollOffsetAtTime(CCLayerImpl* scrollLayer, double) +{ + m_currentPos = scrollLayer->scrollPosition() + scrollLayer->scrollDelta(); + m_totalSize = getScrollLayerBounds(scrollLayer); + m_maximum = scrollLayer->maxScrollPosition(); + + if (m_horizontalScrollbarLayer) { + m_horizontalScrollbarLayer->setCurrentPos(m_currentPos.x()); + m_horizontalScrollbarLayer->setTotalSize(m_totalSize.width()); + m_horizontalScrollbarLayer->setMaximum(m_maximum.width()); + } + + if (m_verticalScrollbarLayer) { + m_verticalScrollbarLayer->setCurrentPos(m_currentPos.y()); + m_verticalScrollbarLayer->setTotalSize(m_totalSize.height()); + m_verticalScrollbarLayer->setMaximum(m_maximum.height()); + } +} + +} // namespace cc diff --git a/cc/scrollbar_animation_controller.h b/cc/scrollbar_animation_controller.h index 638cbb2..bb387d7 100644 --- a/cc/scrollbar_animation_controller.h +++ b/cc/scrollbar_animation_controller.h @@ -1,3 +1,64 @@ // Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CCScrollbarAnimationController_h +#define CCScrollbarAnimationController_h + +#include "FloatPoint.h" +#include "IntSize.h" +#include + +namespace cc { + +class CCLayerImpl; +class CCScrollbarLayerImpl; + +// This abstract class represents the compositor-side analogy of ScrollbarAnimator. +// Individual platforms should subclass it to provide specialized implementation. +class CCScrollbarAnimationController { +public: + // Implemented by subclass. + static PassOwnPtr create(CCLayerImpl* scrollLayer); + + virtual ~CCScrollbarAnimationController(); + + virtual bool animate(double monotonicTime); + void didPinchGestureBegin(); + void didPinchGestureUpdate(); + void didPinchGestureEnd(); + void updateScrollOffset(CCLayerImpl* scrollLayer); + + void setHorizontalScrollbarLayer(CCScrollbarLayerImpl* layer) { m_horizontalScrollbarLayer = layer; } + CCScrollbarLayerImpl* horizontalScrollbarLayer() const { return m_horizontalScrollbarLayer; } + + void setVerticalScrollbarLayer(CCScrollbarLayerImpl* layer) { m_verticalScrollbarLayer = layer; } + CCScrollbarLayerImpl* verticalScrollbarLayer() const { return m_verticalScrollbarLayer; } + + FloatPoint currentPos() const { return m_currentPos; } + IntSize totalSize() const { return m_totalSize; } + IntSize maximum() const { return m_maximum; } + + virtual void didPinchGestureBeginAtTime(double monotonicTime) { } + virtual void didPinchGestureUpdateAtTime(double monotonicTime) { } + virtual void didPinchGestureEndAtTime(double monotonicTime) { } + virtual void updateScrollOffsetAtTime(CCLayerImpl* scrollLayer, double monotonicTime); + +protected: + explicit CCScrollbarAnimationController(CCLayerImpl* scrollLayer); + +private: + static IntSize getScrollLayerBounds(const CCLayerImpl*); + + // Beware of dangling pointer. Always update these during tree synchronization. + CCScrollbarLayerImpl* m_horizontalScrollbarLayer; + CCScrollbarLayerImpl* m_verticalScrollbarLayer; + + FloatPoint m_currentPos; + IntSize m_totalSize; + IntSize m_maximum; +}; + +} // namespace cc + +#endif // CCScrollbarAnimationController_h diff --git a/cc/scrollbar_animation_controller_linear_fade.cc b/cc/scrollbar_animation_controller_linear_fade.cc new file mode 100644 index 0000000..95ad198 --- /dev/null +++ b/cc/scrollbar_animation_controller_linear_fade.cc @@ -0,0 +1,77 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#include "CCScrollbarAnimationControllerLinearFade.h" + +#include "CCScrollbarLayerImpl.h" + +namespace cc { + +PassOwnPtr CCScrollbarAnimationControllerLinearFade::create(CCLayerImpl* scrollLayer, double fadeoutDelay, double fadeoutLength) +{ + return adoptPtr(new CCScrollbarAnimationControllerLinearFade(scrollLayer, fadeoutDelay, fadeoutLength)); +} + +CCScrollbarAnimationControllerLinearFade::CCScrollbarAnimationControllerLinearFade(CCLayerImpl* scrollLayer, double fadeoutDelay, double fadeoutLength) + : CCScrollbarAnimationController(scrollLayer) + , m_lastAwakenTime(-100000000) // arbitrary invalid timestamp + , m_pinchGestureInEffect(false) + , m_fadeoutDelay(fadeoutDelay) + , m_fadeoutLength(fadeoutLength) +{ +} + +CCScrollbarAnimationControllerLinearFade::~CCScrollbarAnimationControllerLinearFade() +{ +} + +bool CCScrollbarAnimationControllerLinearFade::animate(double monotonicTime) +{ + float opacity = opacityAtTime(monotonicTime); + if (horizontalScrollbarLayer()) + horizontalScrollbarLayer()->setOpacity(opacity); + if (verticalScrollbarLayer()) + verticalScrollbarLayer()->setOpacity(opacity); + return opacity; +} + +void CCScrollbarAnimationControllerLinearFade::didPinchGestureUpdateAtTime(double) +{ + m_pinchGestureInEffect = true; +} + +void CCScrollbarAnimationControllerLinearFade::didPinchGestureEndAtTime(double monotonicTime) +{ + m_pinchGestureInEffect = false; + m_lastAwakenTime = monotonicTime; +} + +void CCScrollbarAnimationControllerLinearFade::updateScrollOffsetAtTime(CCLayerImpl* scrollLayer, double monotonicTime) +{ + FloatPoint previousPos = currentPos(); + CCScrollbarAnimationController::updateScrollOffsetAtTime(scrollLayer, monotonicTime); + + if (previousPos == currentPos()) + return; + + m_lastAwakenTime = monotonicTime; +} + +float CCScrollbarAnimationControllerLinearFade::opacityAtTime(double monotonicTime) +{ + if (m_pinchGestureInEffect) + return 1; + + double delta = monotonicTime - m_lastAwakenTime; + + if (delta <= m_fadeoutDelay) + return 1; + if (delta < m_fadeoutDelay + m_fadeoutLength) + return (m_fadeoutDelay + m_fadeoutLength - delta) / m_fadeoutLength; + return 0; +} + +} // namespace cc diff --git a/cc/scrollbar_animation_controller_linear_fade.h b/cc/scrollbar_animation_controller_linear_fade.h index 638cbb2..749dca5 100644 --- a/cc/scrollbar_animation_controller_linear_fade.h +++ b/cc/scrollbar_animation_controller_linear_fade.h @@ -1,3 +1,39 @@ // Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CCScrollbarAnimationControllerLinearFade_h +#define CCScrollbarAnimationControllerLinearFade_h + +#include "CCScrollbarAnimationController.h" + +namespace cc { + +class CCScrollbarAnimationControllerLinearFade : public CCScrollbarAnimationController { +public: + static PassOwnPtr create(CCLayerImpl* scrollLayer, double fadeoutDelay, double fadeoutLength); + + virtual ~CCScrollbarAnimationControllerLinearFade(); + + virtual bool animate(double monotonicTime) OVERRIDE; + + virtual void didPinchGestureUpdateAtTime(double monotonicTime) OVERRIDE; + virtual void didPinchGestureEndAtTime(double monotonicTime) OVERRIDE; + virtual void updateScrollOffsetAtTime(CCLayerImpl* scrollLayer, double monotonicTime) OVERRIDE; + +protected: + CCScrollbarAnimationControllerLinearFade(CCLayerImpl* scrollLayer, double fadeoutDelay, double fadeoutLength); + +private: + float opacityAtTime(double monotonicTime); + + double m_lastAwakenTime; + bool m_pinchGestureInEffect; + + double m_fadeoutDelay; + double m_fadeoutLength; +}; + +} // namespace cc + +#endif // CCScrollbarAnimationControllerLinearFade_h diff --git a/cc/scrollbar_geometry_fixed_thumb.cc b/cc/scrollbar_geometry_fixed_thumb.cc new file mode 100644 index 0000000..dc55829 --- /dev/null +++ b/cc/scrollbar_geometry_fixed_thumb.cc @@ -0,0 +1,94 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#include "CCScrollbarGeometryFixedThumb.h" + +#include +#include +#include + +using WebKit::WebRect; +using WebKit::WebScrollbar; +using WebKit::WebScrollbarThemeGeometry; + +namespace cc { + +PassOwnPtr CCScrollbarGeometryFixedThumb::create(PassOwnPtr geometry) +{ + return adoptPtr(new CCScrollbarGeometryFixedThumb(geometry)); +} + +CCScrollbarGeometryFixedThumb::~CCScrollbarGeometryFixedThumb() +{ +} + +void CCScrollbarGeometryFixedThumb::update(WebScrollbar* scrollbar) +{ + int length = CCScrollbarGeometryStub::thumbLength(scrollbar); + + if (scrollbar->orientation() == WebScrollbar::Horizontal) + m_thumbSize = IntSize(length, scrollbar->size().height); + else + m_thumbSize = IntSize(scrollbar->size().width, length); +} + +WebScrollbarThemeGeometry* CCScrollbarGeometryFixedThumb::clone() const +{ + CCScrollbarGeometryFixedThumb* geometry = new CCScrollbarGeometryFixedThumb(adoptPtr(CCScrollbarGeometryStub::clone())); + geometry->m_thumbSize = m_thumbSize; + return geometry; +} + +int CCScrollbarGeometryFixedThumb::thumbLength(WebScrollbar* scrollbar) +{ + if (scrollbar->orientation() == WebScrollbar::Horizontal) + return m_thumbSize.width(); + return m_thumbSize.height(); +} + +int CCScrollbarGeometryFixedThumb::thumbPosition(WebScrollbar* scrollbar) +{ + if (scrollbar->enabled()) { + float size = scrollbar->maximum(); + if (!size) + return 1; + int value = std::min(std::max(0, scrollbar->value()), scrollbar->maximum()); + float pos = (trackLength(scrollbar) - thumbLength(scrollbar)) * value / size; + return static_cast(floorf((pos < 1 && pos > 0) ? 1 : pos)); + } + return 0; +} +void CCScrollbarGeometryFixedThumb::splitTrack(WebScrollbar* scrollbar, const WebRect& unconstrainedTrackRect, WebRect& beforeThumbRect, WebRect& thumbRect, WebRect& afterThumbRect) +{ + // This is a reimplementation of ScrollbarThemeComposite::splitTrack. + // Because the WebScrollbarThemeGeometry functions call down to native + // ScrollbarThemeComposite code which uses ScrollbarThemeComposite virtual + // helpers, there's no way to override a helper like thumbLength from + // the WebScrollbarThemeGeometry level. So, these three functions + // (splitTrack, thumbPosition, thumbLength) are copied here so that the + // WebScrollbarThemeGeometry helper functions are used instead and + // a fixed size thumbLength can be used. + + WebRect trackRect = constrainTrackRectToTrackPieces(scrollbar, unconstrainedTrackRect); + int thickness = scrollbar->orientation() == WebScrollbar::Horizontal ? scrollbar->size().height : scrollbar->size().width; + int thumbPos = thumbPosition(scrollbar); + if (scrollbar->orientation() == WebScrollbar::Horizontal) { + thumbRect = WebRect(trackRect.x + thumbPos, trackRect.y + (trackRect.height - thickness) / 2, thumbLength(scrollbar), thickness); + beforeThumbRect = WebRect(trackRect.x, trackRect.y, thumbPos + thumbRect.width / 2, trackRect.height); + afterThumbRect = WebRect(trackRect.x + beforeThumbRect.width, trackRect.y, trackRect.x + trackRect.width - beforeThumbRect.x - beforeThumbRect.width, trackRect.height); + } else { + thumbRect = WebRect(trackRect.x + (trackRect.width - thickness) / 2, trackRect.y + thumbPos, thickness, thumbLength(scrollbar)); + beforeThumbRect = WebRect(trackRect.x, trackRect.y, trackRect.width, thumbPos + thumbRect.height / 2); + afterThumbRect = WebRect(trackRect.x, trackRect.y + beforeThumbRect.height, trackRect.width, trackRect.y + trackRect.height - beforeThumbRect.y - beforeThumbRect.height); + } +} + +CCScrollbarGeometryFixedThumb::CCScrollbarGeometryFixedThumb(PassOwnPtr geometry) + : CCScrollbarGeometryStub(geometry) +{ +} + +} diff --git a/cc/scrollbar_geometry_fixed_thumb.h b/cc/scrollbar_geometry_fixed_thumb.h index 638cbb2..fe0db12 100644 --- a/cc/scrollbar_geometry_fixed_thumb.h +++ b/cc/scrollbar_geometry_fixed_thumb.h @@ -1,3 +1,39 @@ // Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CCScrollbarGeometryFixedThumb_h +#define CCScrollbarGeometryFixedThumb_h + +#include "CCScrollbarGeometryStub.h" +#include "IntSize.h" + +namespace cc { + +// This scrollbar geometry class behaves exactly like a normal geometry except +// it always returns a fixed thumb length. This allows a page to zoom (changing +// the total size of the scrollable area, changing the thumb length) while not +// requiring the thumb resource to be repainted. +class CCScrollbarGeometryFixedThumb : public CCScrollbarGeometryStub { +public: + static PassOwnPtr create(PassOwnPtr); + virtual ~CCScrollbarGeometryFixedThumb(); + + // Update thumb length from scrollbar + void update(WebKit::WebScrollbar*); + + // WebScrollbarThemeGeometry interface + virtual WebKit::WebScrollbarThemeGeometry* clone() const OVERRIDE; + virtual int thumbLength(WebKit::WebScrollbar*) OVERRIDE; + virtual int thumbPosition(WebKit::WebScrollbar*) OVERRIDE; + virtual void splitTrack(WebKit::WebScrollbar*, const WebKit::WebRect& track, WebKit::WebRect& startTrack, WebKit::WebRect& thumb, WebKit::WebRect& endTrack) OVERRIDE; + +private: + explicit CCScrollbarGeometryFixedThumb(PassOwnPtr); + + IntSize m_thumbSize; +}; + +} + +#endif diff --git a/cc/scrollbar_geometry_stub.cc b/cc/scrollbar_geometry_stub.cc new file mode 100644 index 0000000..7be7b15 --- /dev/null +++ b/cc/scrollbar_geometry_stub.cc @@ -0,0 +1,109 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#include "CCScrollbarGeometryStub.h" + +using WebKit::WebRect; +using WebKit::WebScrollbar; +using WebKit::WebScrollbarThemeGeometry; + +namespace cc { + +CCScrollbarGeometryStub::CCScrollbarGeometryStub(PassOwnPtr geometry) + : m_geometry(geometry) +{ +} + +CCScrollbarGeometryStub::~CCScrollbarGeometryStub() +{ +} + +WebScrollbarThemeGeometry* CCScrollbarGeometryStub::clone() const +{ + return m_geometry->clone(); +} + +int CCScrollbarGeometryStub::thumbPosition(WebScrollbar* scrollbar) +{ + return m_geometry->thumbPosition(scrollbar); +} + +int CCScrollbarGeometryStub::thumbLength(WebScrollbar* scrollbar) +{ + return m_geometry->thumbLength(scrollbar); +} + +int CCScrollbarGeometryStub::trackPosition(WebScrollbar* scrollbar) +{ + return m_geometry->trackPosition(scrollbar); +} + +int CCScrollbarGeometryStub::trackLength(WebScrollbar* scrollbar) +{ + return m_geometry->trackLength(scrollbar); +} + +bool CCScrollbarGeometryStub::hasButtons(WebScrollbar* scrollbar) +{ + return m_geometry->hasButtons(scrollbar); +} + +bool CCScrollbarGeometryStub::hasThumb(WebScrollbar* scrollbar) +{ + return m_geometry->hasThumb(scrollbar); +} + +WebRect CCScrollbarGeometryStub::trackRect(WebScrollbar* scrollbar) +{ + return m_geometry->trackRect(scrollbar); +} + +WebRect CCScrollbarGeometryStub::thumbRect(WebScrollbar* scrollbar) +{ + return m_geometry->thumbRect(scrollbar); +} + +int CCScrollbarGeometryStub::minimumThumbLength(WebScrollbar* scrollbar) +{ + return m_geometry->minimumThumbLength(scrollbar); +} + +int CCScrollbarGeometryStub::scrollbarThickness(WebScrollbar* scrollbar) +{ + return m_geometry->scrollbarThickness(scrollbar); +} + +WebRect CCScrollbarGeometryStub::backButtonStartRect(WebScrollbar* scrollbar) +{ + return m_geometry->backButtonStartRect(scrollbar); +} + +WebRect CCScrollbarGeometryStub::backButtonEndRect(WebScrollbar* scrollbar) +{ + return m_geometry->backButtonEndRect(scrollbar); +} + +WebRect CCScrollbarGeometryStub::forwardButtonStartRect(WebScrollbar* scrollbar) +{ + return m_geometry->forwardButtonStartRect(scrollbar); +} + +WebRect CCScrollbarGeometryStub::forwardButtonEndRect(WebScrollbar* scrollbar) +{ + return m_geometry->forwardButtonEndRect(scrollbar); +} + +WebRect CCScrollbarGeometryStub::constrainTrackRectToTrackPieces(WebScrollbar* scrollbar, const WebRect& rect) +{ + return m_geometry->constrainTrackRectToTrackPieces(scrollbar, rect); +} + +void CCScrollbarGeometryStub::splitTrack(WebScrollbar* scrollbar, const WebRect& unconstrainedTrackRect, WebRect& beforeThumbRect, WebRect& thumbRect, WebRect& afterThumbRect) +{ + m_geometry->splitTrack(scrollbar, unconstrainedTrackRect, beforeThumbRect, thumbRect, afterThumbRect); +} + +} diff --git a/cc/scrollbar_geometry_stub.h b/cc/scrollbar_geometry_stub.h index 638cbb2..0d23a4e 100644 --- a/cc/scrollbar_geometry_stub.h +++ b/cc/scrollbar_geometry_stub.h @@ -1,3 +1,52 @@ // Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CCScrollbarGeometryStub_h +#define CCScrollbarGeometryStub_h + +#include +#include +#include + +namespace cc { + +// This subclass wraps an existing scrollbar geometry class so that +// another class can derive from it and override specific functions, while +// passing through the remaining ones. +class CCScrollbarGeometryStub : public WebKit::WebScrollbarThemeGeometry { +public: + virtual ~CCScrollbarGeometryStub(); + + // Allow derived classes to update themselves from a scrollbar. + void update(WebKit::WebScrollbar*) { } + + // WebScrollbarThemeGeometry interface + virtual WebKit::WebScrollbarThemeGeometry* clone() const OVERRIDE; + virtual int thumbPosition(WebKit::WebScrollbar*) OVERRIDE; + virtual int thumbLength(WebKit::WebScrollbar*) OVERRIDE; + virtual int trackPosition(WebKit::WebScrollbar*) OVERRIDE; + virtual int trackLength(WebKit::WebScrollbar*) OVERRIDE; + virtual bool hasButtons(WebKit::WebScrollbar*) OVERRIDE; + virtual bool hasThumb(WebKit::WebScrollbar*) OVERRIDE; + virtual WebKit::WebRect trackRect(WebKit::WebScrollbar*) OVERRIDE; + virtual WebKit::WebRect thumbRect(WebKit::WebScrollbar*) OVERRIDE; + virtual int minimumThumbLength(WebKit::WebScrollbar*) OVERRIDE; + virtual int scrollbarThickness(WebKit::WebScrollbar*) OVERRIDE; + virtual WebKit::WebRect backButtonStartRect(WebKit::WebScrollbar*) OVERRIDE; + virtual WebKit::WebRect backButtonEndRect(WebKit::WebScrollbar*) OVERRIDE; + virtual WebKit::WebRect forwardButtonStartRect(WebKit::WebScrollbar*) OVERRIDE; + virtual WebKit::WebRect forwardButtonEndRect(WebKit::WebScrollbar*) OVERRIDE; + virtual WebKit::WebRect constrainTrackRectToTrackPieces(WebKit::WebScrollbar*, const WebKit::WebRect&) OVERRIDE; + virtual void splitTrack(WebKit::WebScrollbar*, const WebKit::WebRect& track, WebKit::WebRect& startTrack, WebKit::WebRect& thumb, WebKit::WebRect& endTrack) OVERRIDE; + +protected: + explicit CCScrollbarGeometryStub(PassOwnPtr); + +private: + OwnPtr m_geometry; +}; + +} + +#endif diff --git a/cc/scrollbar_layer.cc b/cc/scrollbar_layer.cc new file mode 100644 index 0000000..4259b7b --- /dev/null +++ b/cc/scrollbar_layer.cc @@ -0,0 +1,290 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#if USE(ACCELERATED_COMPOSITING) + +#include "ScrollbarLayerChromium.h" + +#include "base/basictypes.h" +#include "CCLayerTreeHost.h" +#include "CCScrollbarLayerImpl.h" +#include "CCTextureUpdateQueue.h" +#include "LayerPainterChromium.h" +#include "TraceEvent.h" +#include + +using WebKit::WebRect; + +namespace cc { + +scoped_ptr ScrollbarLayerChromium::createCCLayerImpl() +{ + return CCScrollbarLayerImpl::create(id()).PassAs(); +} + +scoped_refptr ScrollbarLayerChromium::create(PassOwnPtr scrollbar, WebKit::WebScrollbarThemePainter painter, PassOwnPtr geometry, int scrollLayerId) +{ + return make_scoped_refptr(new ScrollbarLayerChromium(scrollbar, painter, geometry, scrollLayerId)); +} + +ScrollbarLayerChromium::ScrollbarLayerChromium(PassOwnPtr scrollbar, WebKit::WebScrollbarThemePainter painter, PassOwnPtr geometry, int scrollLayerId) + : m_scrollbar(scrollbar) + , m_painter(painter) + , m_geometry(geometry) + , m_scrollLayerId(scrollLayerId) + , m_textureFormat(GraphicsContext3D::INVALID_ENUM) +{ +} + +ScrollbarLayerChromium::~ScrollbarLayerChromium() +{ +} + +void ScrollbarLayerChromium::pushPropertiesTo(CCLayerImpl* layer) +{ + LayerChromium::pushPropertiesTo(layer); + + CCScrollbarLayerImpl* scrollbarLayer = static_cast(layer); + + if (!scrollbarLayer->scrollbarGeometry()) + scrollbarLayer->setScrollbarGeometry(CCScrollbarGeometryFixedThumb::create(adoptPtr(m_geometry->clone()))); + + scrollbarLayer->setScrollbarData(m_scrollbar.get()); + + if (m_backTrack && m_backTrack->texture()->haveBackingTexture()) + scrollbarLayer->setBackTrackResourceId(m_backTrack->texture()->resourceId()); + else + scrollbarLayer->setBackTrackResourceId(0); + + if (m_foreTrack && m_foreTrack->texture()->haveBackingTexture()) + scrollbarLayer->setForeTrackResourceId(m_foreTrack->texture()->resourceId()); + else + scrollbarLayer->setForeTrackResourceId(0); + + if (m_thumb && m_thumb->texture()->haveBackingTexture()) + scrollbarLayer->setThumbResourceId(m_thumb->texture()->resourceId()); + else + scrollbarLayer->setThumbResourceId(0); +} + +ScrollbarLayerChromium* ScrollbarLayerChromium::toScrollbarLayerChromium() +{ + return this; +} + +class ScrollbarBackgroundPainter : public LayerPainterChromium { +public: + static PassOwnPtr create(WebKit::WebScrollbar* scrollbar, WebKit::WebScrollbarThemePainter painter, WebKit::WebScrollbarThemeGeometry* geometry, WebKit::WebScrollbar::ScrollbarPart trackPart) + { + return adoptPtr(new ScrollbarBackgroundPainter(scrollbar, painter, geometry, trackPart)); + } + + virtual void paint(SkCanvas* skCanvas, const IntRect& contentRect, FloatRect&) OVERRIDE + { + WebKit::WebCanvas* canvas = skCanvas; + // The following is a simplification of ScrollbarThemeComposite::paint. + WebKit::WebRect contentWebRect(contentRect.x(), contentRect.y(), contentRect.width(), contentRect.height()); + m_painter.paintScrollbarBackground(canvas, contentWebRect); + + if (m_geometry->hasButtons(m_scrollbar)) { + WebRect backButtonStartPaintRect = m_geometry->backButtonStartRect(m_scrollbar); + m_painter.paintBackButtonStart(canvas, backButtonStartPaintRect); + + WebRect backButtonEndPaintRect = m_geometry->backButtonEndRect(m_scrollbar); + m_painter.paintBackButtonEnd(canvas, backButtonEndPaintRect); + + WebRect forwardButtonStartPaintRect = m_geometry->forwardButtonStartRect(m_scrollbar); + m_painter.paintForwardButtonStart(canvas, forwardButtonStartPaintRect); + + WebRect forwardButtonEndPaintRect = m_geometry->forwardButtonEndRect(m_scrollbar); + m_painter.paintForwardButtonEnd(canvas, forwardButtonEndPaintRect); + } + + WebRect trackPaintRect = m_geometry->trackRect(m_scrollbar); + m_painter.paintTrackBackground(canvas, trackPaintRect); + + bool thumbPresent = m_geometry->hasThumb(m_scrollbar); + if (thumbPresent) { + if (m_trackPart == WebKit::WebScrollbar::ForwardTrackPart) + m_painter.paintForwardTrackPart(canvas, trackPaintRect); + else + m_painter.paintBackTrackPart(canvas, trackPaintRect); + } + + m_painter.paintTickmarks(canvas, trackPaintRect); + } +private: + ScrollbarBackgroundPainter(WebKit::WebScrollbar* scrollbar, WebKit::WebScrollbarThemePainter painter, WebKit::WebScrollbarThemeGeometry* geometry, WebKit::WebScrollbar::ScrollbarPart trackPart) + : m_scrollbar(scrollbar) + , m_painter(painter) + , m_geometry(geometry) + , m_trackPart(trackPart) + { + } + + WebKit::WebScrollbar* m_scrollbar; + WebKit::WebScrollbarThemePainter m_painter; + WebKit::WebScrollbarThemeGeometry* m_geometry; + WebKit::WebScrollbar::ScrollbarPart m_trackPart; + + DISALLOW_COPY_AND_ASSIGN(ScrollbarBackgroundPainter); +}; + +bool ScrollbarLayerChromium::needsContentsScale() const +{ + return true; +} + +IntSize ScrollbarLayerChromium::contentBounds() const +{ + return IntSize(lroundf(bounds().width() * contentsScale()), lroundf(bounds().height() * contentsScale())); +} + +class ScrollbarThumbPainter : public LayerPainterChromium { +public: + static PassOwnPtr create(WebKit::WebScrollbar* scrollbar, WebKit::WebScrollbarThemePainter painter, WebKit::WebScrollbarThemeGeometry* geometry) + { + return adoptPtr(new ScrollbarThumbPainter(scrollbar, painter, geometry)); + } + + virtual void paint(SkCanvas* skCanvas, const IntRect& contentRect, FloatRect& opaque) OVERRIDE + { + WebKit::WebCanvas* canvas = skCanvas; + + // Consider the thumb to be at the origin when painting. + WebRect thumbRect = m_geometry->thumbRect(m_scrollbar); + thumbRect.x = 0; + thumbRect.y = 0; + m_painter.paintThumb(canvas, thumbRect); + } + +private: + ScrollbarThumbPainter(WebKit::WebScrollbar* scrollbar, WebKit::WebScrollbarThemePainter painter, WebKit::WebScrollbarThemeGeometry* geometry) + : m_scrollbar(scrollbar) + , m_painter(painter) + , m_geometry(geometry) + { + } + + WebKit::WebScrollbar* m_scrollbar; + WebKit::WebScrollbarThemePainter m_painter; + WebKit::WebScrollbarThemeGeometry* m_geometry; + + DISALLOW_COPY_AND_ASSIGN(ScrollbarThumbPainter); +}; + +void ScrollbarLayerChromium::setLayerTreeHost(CCLayerTreeHost* host) +{ + if (!host || host != layerTreeHost()) { + m_backTrackUpdater.clear(); + m_backTrack.clear(); + m_thumbUpdater.clear(); + m_thumb.clear(); + } + + LayerChromium::setLayerTreeHost(host); +} + +void ScrollbarLayerChromium::createTextureUpdaterIfNeeded() +{ + m_textureFormat = layerTreeHost()->rendererCapabilities().bestTextureFormat; + + if (!m_backTrackUpdater) + m_backTrackUpdater = CachingBitmapCanvasLayerTextureUpdater::Create(ScrollbarBackgroundPainter::create(m_scrollbar.get(), m_painter, m_geometry.get(), WebKit::WebScrollbar::BackTrackPart)); + if (!m_backTrack) + m_backTrack = m_backTrackUpdater->createTexture(layerTreeHost()->contentsTextureManager()); + + // Only create two-part track if we think the two parts could be different in appearance. + if (m_scrollbar->isCustomScrollbar()) { + if (!m_foreTrackUpdater) + m_foreTrackUpdater = CachingBitmapCanvasLayerTextureUpdater::Create(ScrollbarBackgroundPainter::create(m_scrollbar.get(), m_painter, m_geometry.get(), WebKit::WebScrollbar::ForwardTrackPart)); + if (!m_foreTrack) + m_foreTrack = m_foreTrackUpdater->createTexture(layerTreeHost()->contentsTextureManager()); + } + + if (!m_thumbUpdater) + m_thumbUpdater = CachingBitmapCanvasLayerTextureUpdater::Create(ScrollbarThumbPainter::create(m_scrollbar.get(), m_painter, m_geometry.get())); + if (!m_thumb) + m_thumb = m_thumbUpdater->createTexture(layerTreeHost()->contentsTextureManager()); +} + +void ScrollbarLayerChromium::updatePart(CachingBitmapCanvasLayerTextureUpdater* painter, LayerTextureUpdater::Texture* texture, const IntRect& rect, CCTextureUpdateQueue& queue, CCRenderingStats& stats) +{ + // Skip painting and uploading if there are no invalidations and + // we already have valid texture data. + if (texture->texture()->haveBackingTexture() + && texture->texture()->size() == rect.size() + && m_updateRect.isEmpty()) + return; + + // We should always have enough memory for UI. + ASSERT(texture->texture()->canAcquireBackingTexture()); + if (!texture->texture()->canAcquireBackingTexture()) + return; + + // Paint and upload the entire part. + float widthScale = static_cast(contentBounds().width()) / bounds().width(); + float heightScale = static_cast(contentBounds().height()) / bounds().height(); + IntRect paintedOpaqueRect; + painter->prepareToUpdate(rect, rect.size(), widthScale, heightScale, paintedOpaqueRect, stats); + if (!painter->pixelsDidChange() && texture->texture()->haveBackingTexture()) { + TRACE_EVENT_INSTANT0("cc","ScrollbarLayerChromium::updatePart no texture upload needed"); + return; + } + + texture->prepareRect(rect, stats); + + IntSize destOffset(0, 0); + TextureUploader::Parameters upload = { texture, rect, destOffset }; + queue.appendFullUpload(upload); +} + + +void ScrollbarLayerChromium::setTexturePriorities(const CCPriorityCalculator&) +{ + if (contentBounds().isEmpty()) + return; + + createTextureUpdaterIfNeeded(); + + bool drawsToRoot = !renderTarget()->parent(); + if (m_backTrack) { + m_backTrack->texture()->setDimensions(contentBounds(), m_textureFormat); + m_backTrack->texture()->setRequestPriority(CCPriorityCalculator::uiPriority(drawsToRoot)); + } + if (m_foreTrack) { + m_foreTrack->texture()->setDimensions(contentBounds(), m_textureFormat); + m_foreTrack->texture()->setRequestPriority(CCPriorityCalculator::uiPriority(drawsToRoot)); + } + if (m_thumb) { + IntSize thumbSize = layerRectToContentRect(m_geometry->thumbRect(m_scrollbar.get())).size(); + m_thumb->texture()->setDimensions(thumbSize, m_textureFormat); + m_thumb->texture()->setRequestPriority(CCPriorityCalculator::uiPriority(drawsToRoot)); + } +} + +void ScrollbarLayerChromium::update(CCTextureUpdateQueue& queue, const CCOcclusionTracker*, CCRenderingStats& stats) +{ + if (contentBounds().isEmpty()) + return; + + createTextureUpdaterIfNeeded(); + + IntPoint scrollbarOrigin(m_scrollbar->location().x, m_scrollbar->location().y); + IntRect contentRect = layerRectToContentRect(WebKit::WebRect(scrollbarOrigin.x(), scrollbarOrigin.y(), bounds().width(), bounds().height())); + updatePart(m_backTrackUpdater.get(), m_backTrack.get(), contentRect, queue, stats); + if (m_foreTrack && m_foreTrackUpdater) + updatePart(m_foreTrackUpdater.get(), m_foreTrack.get(), contentRect, queue, stats); + + // Consider the thumb to be at the origin when painting. + WebKit::WebRect thumbRect = m_geometry->thumbRect(m_scrollbar.get()); + IntRect originThumbRect = layerRectToContentRect(WebKit::WebRect(0, 0, thumbRect.width, thumbRect.height)); + if (!originThumbRect.isEmpty()) + updatePart(m_thumbUpdater.get(), m_thumb.get(), originThumbRect, queue, stats); +} + +} +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/cc/scrollbar_layer.h b/cc/scrollbar_layer.h index 638cbb2..5c7cc5c 100644 --- a/cc/scrollbar_layer.h +++ b/cc/scrollbar_layer.h @@ -1,3 +1,70 @@ // Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + + +#ifndef ScrollbarLayerChromium_h +#define ScrollbarLayerChromium_h + +#if USE(ACCELERATED_COMPOSITING) + +#include "LayerChromium.h" +#include "caching_bitmap_canvas_layer_texture_updater.h" +#include +#include +#include + +namespace cc { + +class Scrollbar; +class ScrollbarThemeComposite; +class CCTextureUpdateQueue; + +class ScrollbarLayerChromium : public LayerChromium { +public: + virtual scoped_ptr createCCLayerImpl() OVERRIDE; + + static scoped_refptr create(PassOwnPtr, WebKit::WebScrollbarThemePainter, PassOwnPtr, int scrollLayerId); + + // LayerChromium interface + virtual bool needsContentsScale() const OVERRIDE; + virtual IntSize contentBounds() const OVERRIDE; + virtual void setTexturePriorities(const CCPriorityCalculator&) OVERRIDE; + virtual void update(CCTextureUpdateQueue&, const CCOcclusionTracker*, CCRenderingStats&) OVERRIDE; + virtual void setLayerTreeHost(CCLayerTreeHost*) OVERRIDE; + virtual void pushPropertiesTo(CCLayerImpl*) OVERRIDE; + + int scrollLayerId() const { return m_scrollLayerId; } + void setScrollLayerId(int id) { m_scrollLayerId = id; } + + virtual ScrollbarLayerChromium* toScrollbarLayerChromium() OVERRIDE; + +protected: + ScrollbarLayerChromium(PassOwnPtr, WebKit::WebScrollbarThemePainter, PassOwnPtr, int scrollLayerId); + virtual ~ScrollbarLayerChromium(); + +private: + void updatePart(CachingBitmapCanvasLayerTextureUpdater*, LayerTextureUpdater::Texture*, const IntRect&, CCTextureUpdateQueue&, CCRenderingStats&); + void createTextureUpdaterIfNeeded(); + + OwnPtr m_scrollbar; + WebKit::WebScrollbarThemePainter m_painter; + OwnPtr m_geometry; + int m_scrollLayerId; + + GC3Denum m_textureFormat; + + RefPtr m_backTrackUpdater; + RefPtr m_foreTrackUpdater; + RefPtr m_thumbUpdater; + + // All the parts of the scrollbar except the thumb + OwnPtr m_backTrack; + OwnPtr m_foreTrack; + OwnPtr m_thumb; +}; + +} +#endif // USE(ACCELERATED_COMPOSITING) + +#endif diff --git a/cc/scrollbar_layer_impl.cc b/cc/scrollbar_layer_impl.cc new file mode 100644 index 0000000..8a832e7 --- /dev/null +++ b/cc/scrollbar_layer_impl.cc @@ -0,0 +1,206 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#if USE(ACCELERATED_COMPOSITING) + +#include "CCScrollbarLayerImpl.h" + +#include "CCQuadSink.h" +#include "CCScrollbarAnimationController.h" +#include "CCTextureDrawQuad.h" + +using WebKit::WebRect; +using WebKit::WebScrollbar; + +namespace cc { + +scoped_ptr CCScrollbarLayerImpl::create(int id) +{ + return make_scoped_ptr(new CCScrollbarLayerImpl(id)); +} + +CCScrollbarLayerImpl::CCScrollbarLayerImpl(int id) + : CCLayerImpl(id) + , m_scrollbar(this) + , m_backTrackResourceId(0) + , m_foreTrackResourceId(0) + , m_thumbResourceId(0) + , m_scrollbarOverlayStyle(WebScrollbar::ScrollbarOverlayStyleDefault) + , m_orientation(WebScrollbar::Horizontal) + , m_controlSize(WebScrollbar::RegularScrollbar) + , m_pressedPart(WebScrollbar::NoPart) + , m_hoveredPart(WebScrollbar::NoPart) + , m_isScrollableAreaActive(false) + , m_isScrollViewScrollbar(false) + , m_enabled(false) + , m_isCustomScrollbar(false) + , m_isOverlayScrollbar(false) +{ +} + +CCScrollbarLayerImpl::~CCScrollbarLayerImpl() +{ +} + +void CCScrollbarLayerImpl::setScrollbarGeometry(PassOwnPtr geometry) +{ + m_geometry = geometry; +} + +void CCScrollbarLayerImpl::setScrollbarData(WebScrollbar* scrollbar) +{ + m_scrollbarOverlayStyle = scrollbar->scrollbarOverlayStyle(); + m_orientation = scrollbar->orientation(); + m_controlSize = scrollbar->controlSize(); + m_pressedPart = scrollbar->pressedPart(); + m_hoveredPart = scrollbar->hoveredPart(); + m_isScrollableAreaActive = scrollbar->isScrollableAreaActive(); + m_isScrollViewScrollbar = scrollbar->isScrollViewScrollbar(); + m_enabled = scrollbar->enabled(); + m_isCustomScrollbar = scrollbar->isCustomScrollbar(); + m_isOverlayScrollbar = scrollbar->isOverlay(); + + scrollbar->getTickmarks(m_tickmarks); + + m_geometry->update(scrollbar); +} + +static FloatRect toUVRect(const WebRect& r, const IntRect& bounds) +{ + return FloatRect(static_cast(r.x) / bounds.width(), static_cast(r.y) / bounds.height(), + static_cast(r.width) / bounds.width(), static_cast(r.height) / bounds.height()); +} + +void CCScrollbarLayerImpl::appendQuads(CCQuadSink& quadSink, CCAppendQuadsData& appendQuadsData) +{ + bool premultipledAlpha = false; + bool flipped = false; + FloatRect uvRect(0, 0, 1, 1); + IntRect boundsRect(IntPoint(), bounds()); + IntRect contentBoundsRect(IntPoint(), contentBounds()); + + CCSharedQuadState* sharedQuadState = quadSink.useSharedQuadState(createSharedQuadState()); + appendDebugBorderQuad(quadSink, sharedQuadState, appendQuadsData); + + WebRect thumbRect, backTrackRect, foreTrackRect; + m_geometry->splitTrack(&m_scrollbar, m_geometry->trackRect(&m_scrollbar), backTrackRect, thumbRect, foreTrackRect); + if (!m_geometry->hasThumb(&m_scrollbar)) + thumbRect = WebRect(); + + if (m_thumbResourceId && !thumbRect.isEmpty()) { + scoped_ptr quad = CCTextureDrawQuad::create(sharedQuadState, layerRectToContentRect(thumbRect), m_thumbResourceId, premultipledAlpha, uvRect, flipped); + quad->setNeedsBlending(); + quadSink.append(quad.PassAs(), appendQuadsData); + } + + if (!m_backTrackResourceId) + return; + + // We only paint the track in two parts if we were given a texture for the forward track part. + if (m_foreTrackResourceId && !foreTrackRect.isEmpty()) + quadSink.append(CCTextureDrawQuad::create(sharedQuadState, layerRectToContentRect(foreTrackRect), m_foreTrackResourceId, premultipledAlpha, toUVRect(foreTrackRect, boundsRect), flipped).PassAs(), appendQuadsData); + + // Order matters here: since the back track texture is being drawn to the entire contents rect, we must append it after the thumb and + // fore track quads. The back track texture contains (and displays) the buttons. + if (!contentBoundsRect.isEmpty()) + quadSink.append(CCTextureDrawQuad::create(sharedQuadState, IntRect(contentBoundsRect), m_backTrackResourceId, premultipledAlpha, uvRect, flipped).PassAs(), appendQuadsData); +} + +void CCScrollbarLayerImpl::didLoseContext() +{ + m_backTrackResourceId = 0; + m_foreTrackResourceId = 0; + m_thumbResourceId = 0; +} + +bool CCScrollbarLayerImpl::CCScrollbar::isOverlay() const +{ + return m_owner->m_isOverlayScrollbar; +} + +int CCScrollbarLayerImpl::CCScrollbar::value() const +{ + return m_owner->m_currentPos; +} + +WebKit::WebPoint CCScrollbarLayerImpl::CCScrollbar::location() const +{ + return WebKit::WebPoint(); +} + +WebKit::WebSize CCScrollbarLayerImpl::CCScrollbar::size() const +{ + return WebKit::WebSize(m_owner->bounds().width(), m_owner->bounds().height()); +} + +bool CCScrollbarLayerImpl::CCScrollbar::enabled() const +{ + return m_owner->m_enabled; +} + +int CCScrollbarLayerImpl::CCScrollbar::maximum() const +{ + return m_owner->m_maximum; +} + +int CCScrollbarLayerImpl::CCScrollbar::totalSize() const +{ + return m_owner->m_totalSize; +} + +bool CCScrollbarLayerImpl::CCScrollbar::isScrollViewScrollbar() const +{ + return m_owner->m_isScrollViewScrollbar; +} + +bool CCScrollbarLayerImpl::CCScrollbar::isScrollableAreaActive() const +{ + return m_owner->m_isScrollableAreaActive; +} + +void CCScrollbarLayerImpl::CCScrollbar::getTickmarks(WebKit::WebVector& tickmarks) const +{ + tickmarks = m_owner->m_tickmarks; +} + +WebScrollbar::ScrollbarControlSize CCScrollbarLayerImpl::CCScrollbar::controlSize() const +{ + return m_owner->m_controlSize; +} + +WebScrollbar::ScrollbarPart CCScrollbarLayerImpl::CCScrollbar::pressedPart() const +{ + return m_owner->m_pressedPart; +} + +WebScrollbar::ScrollbarPart CCScrollbarLayerImpl::CCScrollbar::hoveredPart() const +{ + return m_owner->m_hoveredPart; +} + +WebScrollbar::ScrollbarOverlayStyle CCScrollbarLayerImpl::CCScrollbar::scrollbarOverlayStyle() const +{ + return m_owner->m_scrollbarOverlayStyle; +} + +WebScrollbar::Orientation CCScrollbarLayerImpl::CCScrollbar::orientation() const +{ + return m_owner->m_orientation; +} + +bool CCScrollbarLayerImpl::CCScrollbar::isCustomScrollbar() const +{ + return m_owner->m_isCustomScrollbar; +} + +const char* CCScrollbarLayerImpl::layerTypeAsString() const +{ + return "ScrollbarLayer"; +} + +} + +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/cc/scrollbar_layer_impl.h b/cc/scrollbar_layer_impl.h index 638cbb2..e7cf584 100644 --- a/cc/scrollbar_layer_impl.h +++ b/cc/scrollbar_layer_impl.h @@ -1,3 +1,112 @@ // Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CCScrollbarLayerImpl_h +#define CCScrollbarLayerImpl_h + +#if USE(ACCELERATED_COMPOSITING) + +#include "CCLayerImpl.h" +#include "CCScrollbarGeometryFixedThumb.h" +#include +#include +#include + +namespace cc { + +class ScrollView; + +class CCScrollbarLayerImpl : public CCLayerImpl { +public: + static scoped_ptr create(int id); + virtual ~CCScrollbarLayerImpl(); + + CCScrollbarGeometryFixedThumb* scrollbarGeometry() const { return m_geometry.get(); } + void setScrollbarGeometry(PassOwnPtr); + void setScrollbarData(WebKit::WebScrollbar*); + + void setBackTrackResourceId(CCResourceProvider::ResourceId id) { m_backTrackResourceId = id; } + void setForeTrackResourceId(CCResourceProvider::ResourceId id) { m_foreTrackResourceId = id; } + void setThumbResourceId(CCResourceProvider::ResourceId id) { m_thumbResourceId = id; } + + float currentPos() const { return m_currentPos; } + void setCurrentPos(float currentPos) { m_currentPos = currentPos; } + + int totalSize() const { return m_totalSize; } + void setTotalSize(int totalSize) { m_totalSize = totalSize; } + + int maximum() const { return m_maximum; } + void setMaximum(int maximum) { m_maximum = maximum; } + + WebKit::WebScrollbar::Orientation orientation() const { return m_orientation; } + + virtual void appendQuads(CCQuadSink&, CCAppendQuadsData&) OVERRIDE; + + virtual void didLoseContext() OVERRIDE; + +protected: + explicit CCScrollbarLayerImpl(int id); + +private: + // nested class only to avoid namespace problem + class CCScrollbar : public WebKit::WebScrollbar { + public: + explicit CCScrollbar(CCScrollbarLayerImpl* owner) : m_owner(owner) { } + + // WebScrollbar implementation + virtual bool isOverlay() const; + virtual int value() const; + virtual WebKit::WebPoint location() const; + virtual WebKit::WebSize size() const; + virtual bool enabled() const; + virtual int maximum() const; + virtual int totalSize() const; + virtual bool isScrollViewScrollbar() const; + virtual bool isScrollableAreaActive() const; + virtual void getTickmarks(WebKit::WebVector& tickmarks) const; + virtual WebScrollbar::ScrollbarControlSize controlSize() const; + virtual WebScrollbar::ScrollbarPart pressedPart() const; + virtual WebScrollbar::ScrollbarPart hoveredPart() const; + virtual WebScrollbar::ScrollbarOverlayStyle scrollbarOverlayStyle() const; + virtual WebScrollbar::Orientation orientation() const; + virtual bool isCustomScrollbar() const; + + private: + CCScrollbarLayerImpl* m_owner; + + }; + + virtual const char* layerTypeAsString() const OVERRIDE; + + CCScrollbar m_scrollbar; + + CCResourceProvider::ResourceId m_backTrackResourceId; + CCResourceProvider::ResourceId m_foreTrackResourceId; + CCResourceProvider::ResourceId m_thumbResourceId; + + OwnPtr m_geometry; + + // Data to implement CCScrollbar + WebKit::WebScrollbar::ScrollbarOverlayStyle m_scrollbarOverlayStyle; + WebKit::WebVector m_tickmarks; + WebKit::WebScrollbar::Orientation m_orientation; + WebKit::WebScrollbar::ScrollbarControlSize m_controlSize; + WebKit::WebScrollbar::ScrollbarPart m_pressedPart; + WebKit::WebScrollbar::ScrollbarPart m_hoveredPart; + + float m_currentPos; + int m_totalSize; + int m_maximum; + + bool m_isScrollableAreaActive; + bool m_isScrollViewScrollbar; + bool m_enabled; + bool m_isCustomScrollbar; + bool m_isOverlayScrollbar; +}; + +} +#endif // USE(ACCELERATED_COMPOSITING) + +#endif diff --git a/cc/settings.cc b/cc/settings.cc new file mode 100644 index 0000000..cfdc258 --- /dev/null +++ b/cc/settings.cc @@ -0,0 +1,50 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#include "base/command_line.h" +#include "CCSettings.h" +#include "cc/switches.h" + +namespace { +static bool s_perTilePaintingEnabled = false; +static bool s_partialSwapEnabled = false; +static bool s_acceleratedAnimationEnabled = false; +static bool s_pageScalePinchZoomEnabled = false; +} // namespace + +namespace cc { + +bool CCSettings::perTilePaintingEnabled() { return s_perTilePaintingEnabled; } +void CCSettings::setPerTilePaintingEnabled(bool enabled) { s_perTilePaintingEnabled = enabled; } + +bool CCSettings::partialSwapEnabled() { return s_partialSwapEnabled; } +void CCSettings::setPartialSwapEnabled(bool enabled) { s_partialSwapEnabled = enabled; } + +bool CCSettings::acceleratedAnimationEnabled() { return s_acceleratedAnimationEnabled; } +void CCSettings::setAcceleratedAnimationEnabled(bool enabled) { s_acceleratedAnimationEnabled = enabled; } + +bool CCSettings::pageScalePinchZoomEnabled() { return s_pageScalePinchZoomEnabled; } +void CCSettings::setPageScalePinchZoomEnabled(bool enabled) { s_pageScalePinchZoomEnabled = enabled; } + +bool CCSettings::jankInsteadOfCheckerboard() +{ + return CommandLine::ForCurrentProcess()->HasSwitch(switches::kJankInsteadOfCheckerboard); +} + +bool CCSettings::backgroundColorInsteadOfCheckerboard() +{ + return CommandLine::ForCurrentProcess()->HasSwitch(switches::kBackgroundColorInsteadOfCheckerboard); +} + +void CCSettings::reset() +{ + s_perTilePaintingEnabled = false; + s_partialSwapEnabled = false; + s_acceleratedAnimationEnabled = false; + s_pageScalePinchZoomEnabled = false; +} + +} // namespace cc diff --git a/cc/settings.h b/cc/settings.h index 638cbb2..cde48ca 100644 --- a/cc/settings.h +++ b/cc/settings.h @@ -1,3 +1,40 @@ // Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CCSettings_h +#define CCSettings_h + +#include "IntSize.h" + +namespace cc { + +// This file is for settings that apply to all compositors. Add settings to +// CCLayerTreeSettings if a ui and renderer compositor might not want the same +// setting. + +class CCSettings { +public: + static bool perTilePaintingEnabled(); + static bool partialSwapEnabled(); + static bool acceleratedAnimationEnabled(); + static bool pageScalePinchZoomEnabled(); + + static bool jankInsteadOfCheckerboard(); + static bool backgroundColorInsteadOfCheckerboard(); + + // These setters should only be used on the main thread before the layer + // renderer is initialized. + static void setPerTilePaintingEnabled(bool); + static void setPartialSwapEnabled(bool); + static void setAcceleratedAnimationEnabled(bool); + static void setPageScalePinchZoomEnabled(bool); + + // These settings are meant to be set only once, and only read thereafter. + // This function is only for resetting settings in tests. + static void reset(); +}; + +} // namespace cc + +#endif // CCSettings_h diff --git a/cc/shader.cc b/cc/shader.cc new file mode 100644 index 0000000..cf485c1 --- /dev/null +++ b/cc/shader.cc @@ -0,0 +1,888 @@ +// Copyright 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#if USE(ACCELERATED_COMPOSITING) + +#include "ShaderChromium.h" + +#include +#include + +#define SHADER0(Src) #Src +#define SHADER(Src) SHADER0(Src) + +using WebKit::WebGraphicsContext3D; + +namespace cc { + +namespace { + +static void getProgramUniformLocations(WebGraphicsContext3D* context, unsigned program, const char** shaderUniforms, size_t count, size_t maxLocations, int* locations, bool usingBindUniform, int* baseUniformIndex) +{ + for (size_t uniformIndex = 0; uniformIndex < count; uniformIndex ++) { + ASSERT(uniformIndex < maxLocations); + + if (usingBindUniform) { + locations[uniformIndex] = (*baseUniformIndex)++; + context->bindUniformLocationCHROMIUM(program, locations[uniformIndex], shaderUniforms[uniformIndex]); + } else + locations[uniformIndex] = context->getUniformLocation(program, shaderUniforms[uniformIndex]); + } +} + +} + +VertexShaderPosTex::VertexShaderPosTex() + : m_matrixLocation(-1) +{ +} + +void VertexShaderPosTex::init(WebGraphicsContext3D* context, unsigned program, bool usingBindUniform, int* baseUniformIndex) +{ + static const char* shaderUniforms[] = { + "matrix", + }; + int locations[1]; + + getProgramUniformLocations(context, program, shaderUniforms, WTF_ARRAY_LENGTH(shaderUniforms), WTF_ARRAY_LENGTH(locations), locations, usingBindUniform, baseUniformIndex); + + m_matrixLocation = locations[0]; + ASSERT(m_matrixLocation != -1); +} + +std::string VertexShaderPosTex::getShaderString() const +{ + return SHADER( + attribute vec4 a_position; + attribute vec2 a_texCoord; + uniform mat4 matrix; + varying vec2 v_texCoord; + void main() + { + gl_Position = matrix * a_position; + v_texCoord = a_texCoord; + } + ); +} + +VertexShaderPosTexYUVStretch::VertexShaderPosTexYUVStretch() + : m_matrixLocation(-1) + , m_yWidthScaleFactorLocation(-1) + , m_uvWidthScaleFactorLocation(-1) +{ +} + +void VertexShaderPosTexYUVStretch::init(WebGraphicsContext3D* context, unsigned program, bool usingBindUniform, int* baseUniformIndex) +{ + static const char* shaderUniforms[] = { + "matrix", + "y_widthScaleFactor", + "uv_widthScaleFactor", + }; + int locations[3]; + + getProgramUniformLocations(context, program, shaderUniforms, WTF_ARRAY_LENGTH(shaderUniforms), WTF_ARRAY_LENGTH(locations), locations, usingBindUniform, baseUniformIndex); + + m_matrixLocation = locations[0]; + m_yWidthScaleFactorLocation = locations[1]; + m_uvWidthScaleFactorLocation = locations[2]; + ASSERT(m_matrixLocation != -1 && m_yWidthScaleFactorLocation != -1 && m_uvWidthScaleFactorLocation != -1); +} + +std::string VertexShaderPosTexYUVStretch::getShaderString() const +{ + return SHADER( + precision mediump float; + attribute vec4 a_position; + attribute vec2 a_texCoord; + uniform mat4 matrix; + varying vec2 y_texCoord; + varying vec2 uv_texCoord; + uniform float y_widthScaleFactor; + uniform float uv_widthScaleFactor; + void main() + { + gl_Position = matrix * a_position; + y_texCoord = vec2(y_widthScaleFactor * a_texCoord.x, a_texCoord.y); + uv_texCoord = vec2(uv_widthScaleFactor * a_texCoord.x, a_texCoord.y); + } + ); +} + +VertexShaderPos::VertexShaderPos() + : m_matrixLocation(-1) +{ +} + +void VertexShaderPos::init(WebGraphicsContext3D* context, unsigned program, bool usingBindUniform, int* baseUniformIndex) +{ + static const char* shaderUniforms[] = { + "matrix", + }; + int locations[1]; + + getProgramUniformLocations(context, program, shaderUniforms, WTF_ARRAY_LENGTH(shaderUniforms), WTF_ARRAY_LENGTH(locations), locations, usingBindUniform, baseUniformIndex); + + m_matrixLocation = locations[0]; + ASSERT(m_matrixLocation != -1); +} + +std::string VertexShaderPos::getShaderString() const +{ + return SHADER( + attribute vec4 a_position; + uniform mat4 matrix; + void main() + { + gl_Position = matrix * a_position; + } + ); +} + +VertexShaderPosTexTransform::VertexShaderPosTexTransform() + : m_matrixLocation(-1) + , m_texTransformLocation(-1) +{ +} + +void VertexShaderPosTexTransform::init(WebGraphicsContext3D* context, unsigned program, bool usingBindUniform, int* baseUniformIndex) +{ + static const char* shaderUniforms[] = { + "matrix", + "texTransform", + }; + int locations[2]; + + getProgramUniformLocations(context, program, shaderUniforms, WTF_ARRAY_LENGTH(shaderUniforms), WTF_ARRAY_LENGTH(locations), locations, usingBindUniform, baseUniformIndex); + + m_matrixLocation = locations[0]; + m_texTransformLocation = locations[1]; + ASSERT(m_matrixLocation != -1 && m_texTransformLocation != -1); +} + +std::string VertexShaderPosTexTransform::getShaderString() const +{ + return SHADER( + attribute vec4 a_position; + attribute vec2 a_texCoord; + uniform mat4 matrix; + uniform vec4 texTransform; + varying vec2 v_texCoord; + void main() + { + gl_Position = matrix * a_position; + v_texCoord = a_texCoord * texTransform.zw + texTransform.xy; + } + ); +} + +VertexShaderQuad::VertexShaderQuad() + : m_matrixLocation(-1) + , m_pointLocation(-1) +{ +} + +std::string VertexShaderPosTexIdentity::getShaderString() const +{ + return SHADER( + attribute vec4 a_position; + varying vec2 v_texCoord; + void main() + { + gl_Position = a_position; + v_texCoord = (a_position.xy + vec2(1.0)) * 0.5; + } + ); +} + +void VertexShaderQuad::init(WebGraphicsContext3D* context, unsigned program, bool usingBindUniform, int* baseUniformIndex) +{ + static const char* shaderUniforms[] = { + "matrix", + "point", + }; + int locations[2]; + + getProgramUniformLocations(context, program, shaderUniforms, WTF_ARRAY_LENGTH(shaderUniforms), WTF_ARRAY_LENGTH(locations), locations, usingBindUniform, baseUniformIndex); + + m_matrixLocation = locations[0]; + m_pointLocation = locations[1]; + ASSERT(m_matrixLocation != -1 && m_pointLocation != -1); +} + +std::string VertexShaderQuad::getShaderString() const +{ + return SHADER( + attribute vec4 a_position; + attribute vec2 a_texCoord; + uniform mat4 matrix; + uniform vec2 point[4]; + varying vec2 v_texCoord; + void main() + { + vec2 complement = abs(a_texCoord - 1.0); + vec4 pos = vec4(0.0, 0.0, a_position.z, a_position.w); + pos.xy += (complement.x * complement.y) * point[0]; + pos.xy += (a_texCoord.x * complement.y) * point[1]; + pos.xy += (a_texCoord.x * a_texCoord.y) * point[2]; + pos.xy += (complement.x * a_texCoord.y) * point[3]; + gl_Position = matrix * pos; + v_texCoord = pos.xy + vec2(0.5); + } + ); +} + +VertexShaderTile::VertexShaderTile() + : m_matrixLocation(-1) + , m_pointLocation(-1) + , m_vertexTexTransformLocation(-1) +{ +} + +void VertexShaderTile::init(WebGraphicsContext3D* context, unsigned program, bool usingBindUniform, int* baseUniformIndex) +{ + static const char* shaderUniforms[] = { + "matrix", + "point", + "vertexTexTransform", + }; + int locations[3]; + + getProgramUniformLocations(context, program, shaderUniforms, WTF_ARRAY_LENGTH(shaderUniforms), WTF_ARRAY_LENGTH(locations), locations, usingBindUniform, baseUniformIndex); + + m_matrixLocation = locations[0]; + m_pointLocation = locations[1]; + m_vertexTexTransformLocation = locations[2]; + ASSERT(m_matrixLocation != -1 && m_pointLocation != -1 && m_vertexTexTransformLocation != -1); +} + +std::string VertexShaderTile::getShaderString() const +{ + return SHADER( + attribute vec4 a_position; + attribute vec2 a_texCoord; + uniform mat4 matrix; + uniform vec2 point[4]; + uniform vec4 vertexTexTransform; + varying vec2 v_texCoord; + void main() + { + vec2 complement = abs(a_texCoord - 1.0); + vec4 pos = vec4(0.0, 0.0, a_position.z, a_position.w); + pos.xy += (complement.x * complement.y) * point[0]; + pos.xy += (a_texCoord.x * complement.y) * point[1]; + pos.xy += (a_texCoord.x * a_texCoord.y) * point[2]; + pos.xy += (complement.x * a_texCoord.y) * point[3]; + gl_Position = matrix * pos; + v_texCoord = pos.xy * vertexTexTransform.zw + vertexTexTransform.xy; + } + ); +} + +VertexShaderVideoTransform::VertexShaderVideoTransform() + : m_matrixLocation(-1) + , m_texMatrixLocation(-1) +{ +} + +bool VertexShaderVideoTransform::init(WebGraphicsContext3D* context, unsigned program, bool usingBindUniform, int* baseUniformIndex) +{ + static const char* shaderUniforms[] = { + "matrix", + "texMatrix", + }; + int locations[2]; + + getProgramUniformLocations(context, program, shaderUniforms, WTF_ARRAY_LENGTH(shaderUniforms), WTF_ARRAY_LENGTH(locations), locations, usingBindUniform, baseUniformIndex); + + m_matrixLocation = locations[0]; + m_texMatrixLocation = locations[1]; + return m_matrixLocation != -1 && m_texMatrixLocation != -1; +} + +std::string VertexShaderVideoTransform::getShaderString() const +{ + return SHADER( + attribute vec4 a_position; + attribute vec2 a_texCoord; + uniform mat4 matrix; + uniform mat4 texMatrix; + varying vec2 v_texCoord; + void main() + { + gl_Position = matrix * a_position; + v_texCoord = vec2(texMatrix * vec4(a_texCoord.x, 1.0 - a_texCoord.y, 0.0, 1.0)); + } + ); +} + +FragmentTexAlphaBinding::FragmentTexAlphaBinding() + : m_samplerLocation(-1) + , m_alphaLocation(-1) +{ +} + +void FragmentTexAlphaBinding::init(WebGraphicsContext3D* context, unsigned program, bool usingBindUniform, int* baseUniformIndex) +{ + static const char* shaderUniforms[] = { + "s_texture", + "alpha", + }; + int locations[2]; + + getProgramUniformLocations(context, program, shaderUniforms, WTF_ARRAY_LENGTH(shaderUniforms), WTF_ARRAY_LENGTH(locations), locations, usingBindUniform, baseUniformIndex); + + m_samplerLocation = locations[0]; + m_alphaLocation = locations[1]; + ASSERT(m_samplerLocation != -1 && m_alphaLocation != -1); +} + +FragmentTexOpaqueBinding::FragmentTexOpaqueBinding() + : m_samplerLocation(-1) +{ +} + +void FragmentTexOpaqueBinding::init(WebGraphicsContext3D* context, unsigned program, bool usingBindUniform, int* baseUniformIndex) +{ + static const char* shaderUniforms[] = { + "s_texture", + }; + int locations[1]; + + getProgramUniformLocations(context, program, shaderUniforms, WTF_ARRAY_LENGTH(shaderUniforms), WTF_ARRAY_LENGTH(locations), locations, usingBindUniform, baseUniformIndex); + + m_samplerLocation = locations[0]; + ASSERT(m_samplerLocation != -1); +} + +std::string FragmentShaderRGBATexFlipAlpha::getShaderString() const +{ + return SHADER( + precision mediump float; + varying vec2 v_texCoord; + uniform sampler2D s_texture; + uniform float alpha; + void main() + { + vec4 texColor = texture2D(s_texture, vec2(v_texCoord.x, 1.0 - v_texCoord.y)); + gl_FragColor = vec4(texColor.x, texColor.y, texColor.z, texColor.w) * alpha; + } + ); +} + +bool FragmentShaderOESImageExternal::init(WebGraphicsContext3D* context, unsigned program, bool usingBindUniform, int* baseUniformIndex) +{ + static const char* shaderUniforms[] = { + "s_texture", + }; + int locations[1]; + + getProgramUniformLocations(context, program, shaderUniforms, WTF_ARRAY_LENGTH(shaderUniforms), WTF_ARRAY_LENGTH(locations), locations, usingBindUniform, baseUniformIndex); + + m_samplerLocation = locations[0]; + return m_samplerLocation != -1; +} + +std::string FragmentShaderOESImageExternal::getShaderString() const +{ + // Cannot use the SHADER() macro because of the '#' char + return "#extension GL_OES_EGL_image_external : require \n" + "precision mediump float;\n" + "varying vec2 v_texCoord;\n" + "uniform samplerExternalOES s_texture;\n" + "void main()\n" + "{\n" + " vec4 texColor = texture2D(s_texture, v_texCoord);\n" + " gl_FragColor = vec4(texColor.x, texColor.y, texColor.z, texColor.w);\n" + "}\n"; +} + +std::string FragmentShaderRGBATexAlpha::getShaderString() const +{ + return SHADER( + precision mediump float; + varying vec2 v_texCoord; + uniform sampler2D s_texture; + uniform float alpha; + void main() + { + vec4 texColor = texture2D(s_texture, v_texCoord); + gl_FragColor = texColor * alpha; + } + ); +} + +std::string FragmentShaderRGBATexRectFlipAlpha::getShaderString() const +{ + // This must be paired with VertexShaderPosTexTransform to pick up the texTransform uniform. + // The necessary #extension preprocessing directive breaks the SHADER and SHADER0 macros. + return "#extension GL_ARB_texture_rectangle : require\n" + "precision mediump float;\n" + "varying vec2 v_texCoord;\n" + "uniform vec4 texTransform;\n" + "uniform sampler2DRect s_texture;\n" + "uniform float alpha;\n" + "void main()\n" + "{\n" + " vec4 texColor = texture2DRect(s_texture, vec2(v_texCoord.x, texTransform.w - v_texCoord.y));\n" + " gl_FragColor = vec4(texColor.x, texColor.y, texColor.z, texColor.w) * alpha;\n" + "}\n"; +} + +std::string FragmentShaderRGBATexRectAlpha::getShaderString() const +{ + return "#extension GL_ARB_texture_rectangle : require\n" + "precision mediump float;\n" + "varying vec2 v_texCoord;\n" + "uniform sampler2DRect s_texture;\n" + "uniform float alpha;\n" + "void main()\n" + "{\n" + " vec4 texColor = texture2DRect(s_texture, v_texCoord);\n" + " gl_FragColor = texColor * alpha;\n" + "}\n"; +} + +std::string FragmentShaderRGBATexOpaque::getShaderString() const +{ + return SHADER( + precision mediump float; + varying vec2 v_texCoord; + uniform sampler2D s_texture; + void main() + { + vec4 texColor = texture2D(s_texture, v_texCoord); + gl_FragColor = vec4(texColor.rgb, 1.0); + } + ); +} + +std::string FragmentShaderRGBATex::getShaderString() const +{ + return SHADER( + precision mediump float; + varying vec2 v_texCoord; + uniform sampler2D s_texture; + void main() + { + gl_FragColor = texture2D(s_texture, v_texCoord); + } + ); +} + +std::string FragmentShaderRGBATexSwizzleAlpha::getShaderString() const +{ + return SHADER( + precision mediump float; + varying vec2 v_texCoord; + uniform sampler2D s_texture; + uniform float alpha; + void main() + { + vec4 texColor = texture2D(s_texture, v_texCoord); + gl_FragColor = vec4(texColor.z, texColor.y, texColor.x, texColor.w) * alpha; + } + ); +} + +std::string FragmentShaderRGBATexSwizzleOpaque::getShaderString() const +{ + return SHADER( + precision mediump float; + varying vec2 v_texCoord; + uniform sampler2D s_texture; + void main() + { + vec4 texColor = texture2D(s_texture, v_texCoord); + gl_FragColor = vec4(texColor.z, texColor.y, texColor.x, 1.0); + } + ); +} + +FragmentShaderRGBATexAlphaAA::FragmentShaderRGBATexAlphaAA() + : m_samplerLocation(-1) + , m_alphaLocation(-1) + , m_edgeLocation(-1) +{ +} + +void FragmentShaderRGBATexAlphaAA::init(WebGraphicsContext3D* context, unsigned program, bool usingBindUniform, int* baseUniformIndex) +{ + static const char* shaderUniforms[] = { + "s_texture", + "alpha", + "edge", + }; + int locations[3]; + + getProgramUniformLocations(context, program, shaderUniforms, WTF_ARRAY_LENGTH(shaderUniforms), WTF_ARRAY_LENGTH(locations), locations, usingBindUniform, baseUniformIndex); + + m_samplerLocation = locations[0]; + m_alphaLocation = locations[1]; + m_edgeLocation = locations[2]; + ASSERT(m_samplerLocation != -1 && m_alphaLocation != -1 && m_edgeLocation != -1); +} + +std::string FragmentShaderRGBATexAlphaAA::getShaderString() const +{ + return SHADER( + precision mediump float; + varying vec2 v_texCoord; + uniform sampler2D s_texture; + uniform float alpha; + uniform vec3 edge[8]; + void main() + { + vec4 texColor = texture2D(s_texture, v_texCoord); + vec3 pos = vec3(gl_FragCoord.xy, 1); + float a0 = clamp(dot(edge[0], pos), 0.0, 1.0); + float a1 = clamp(dot(edge[1], pos), 0.0, 1.0); + float a2 = clamp(dot(edge[2], pos), 0.0, 1.0); + float a3 = clamp(dot(edge[3], pos), 0.0, 1.0); + float a4 = clamp(dot(edge[4], pos), 0.0, 1.0); + float a5 = clamp(dot(edge[5], pos), 0.0, 1.0); + float a6 = clamp(dot(edge[6], pos), 0.0, 1.0); + float a7 = clamp(dot(edge[7], pos), 0.0, 1.0); + gl_FragColor = texColor * alpha * min(min(a0, a2) * min(a1, a3), min(a4, a6) * min(a5, a7)); + } + ); +} + +FragmentTexClampAlphaAABinding::FragmentTexClampAlphaAABinding() + : m_samplerLocation(-1) + , m_alphaLocation(-1) + , m_fragmentTexTransformLocation(-1) + , m_edgeLocation(-1) +{ +} + +void FragmentTexClampAlphaAABinding::init(WebGraphicsContext3D* context, unsigned program, bool usingBindUniform, int* baseUniformIndex) +{ + static const char* shaderUniforms[] = { + "s_texture", + "alpha", + "fragmentTexTransform", + "edge", + }; + int locations[4]; + + getProgramUniformLocations(context, program, shaderUniforms, WTF_ARRAY_LENGTH(shaderUniforms), WTF_ARRAY_LENGTH(locations), locations, usingBindUniform, baseUniformIndex); + + m_samplerLocation = locations[0]; + m_alphaLocation = locations[1]; + m_fragmentTexTransformLocation = locations[2]; + m_edgeLocation = locations[3]; + ASSERT(m_samplerLocation != -1 && m_alphaLocation != -1 && m_fragmentTexTransformLocation != -1 && m_edgeLocation != -1); +} + +std::string FragmentShaderRGBATexClampAlphaAA::getShaderString() const +{ + return SHADER( + precision mediump float; + varying vec2 v_texCoord; + uniform sampler2D s_texture; + uniform float alpha; + uniform vec4 fragmentTexTransform; + uniform vec3 edge[8]; + void main() + { + vec2 texCoord = clamp(v_texCoord, 0.0, 1.0) * fragmentTexTransform.zw + fragmentTexTransform.xy; + vec4 texColor = texture2D(s_texture, texCoord); + vec3 pos = vec3(gl_FragCoord.xy, 1); + float a0 = clamp(dot(edge[0], pos), 0.0, 1.0); + float a1 = clamp(dot(edge[1], pos), 0.0, 1.0); + float a2 = clamp(dot(edge[2], pos), 0.0, 1.0); + float a3 = clamp(dot(edge[3], pos), 0.0, 1.0); + float a4 = clamp(dot(edge[4], pos), 0.0, 1.0); + float a5 = clamp(dot(edge[5], pos), 0.0, 1.0); + float a6 = clamp(dot(edge[6], pos), 0.0, 1.0); + float a7 = clamp(dot(edge[7], pos), 0.0, 1.0); + gl_FragColor = texColor * alpha * min(min(a0, a2) * min(a1, a3), min(a4, a6) * min(a5, a7)); + } + ); +} + +std::string FragmentShaderRGBATexClampSwizzleAlphaAA::getShaderString() const +{ + return SHADER( + precision mediump float; + varying vec2 v_texCoord; + uniform sampler2D s_texture; + uniform float alpha; + uniform vec4 fragmentTexTransform; + uniform vec3 edge[8]; + void main() + { + vec2 texCoord = clamp(v_texCoord, 0.0, 1.0) * fragmentTexTransform.zw + fragmentTexTransform.xy; + vec4 texColor = texture2D(s_texture, texCoord); + vec3 pos = vec3(gl_FragCoord.xy, 1); + float a0 = clamp(dot(edge[0], pos), 0.0, 1.0); + float a1 = clamp(dot(edge[1], pos), 0.0, 1.0); + float a2 = clamp(dot(edge[2], pos), 0.0, 1.0); + float a3 = clamp(dot(edge[3], pos), 0.0, 1.0); + float a4 = clamp(dot(edge[4], pos), 0.0, 1.0); + float a5 = clamp(dot(edge[5], pos), 0.0, 1.0); + float a6 = clamp(dot(edge[6], pos), 0.0, 1.0); + float a7 = clamp(dot(edge[7], pos), 0.0, 1.0); + gl_FragColor = vec4(texColor.z, texColor.y, texColor.x, texColor.w) * alpha * min(min(a0, a2) * min(a1, a3), min(a4, a6) * min(a5, a7)); + } + ); +} + +FragmentShaderRGBATexAlphaMask::FragmentShaderRGBATexAlphaMask() + : m_samplerLocation(-1) + , m_maskSamplerLocation(-1) + , m_alphaLocation(-1) + , m_maskTexCoordScaleLocation(-1) +{ +} + +void FragmentShaderRGBATexAlphaMask::init(WebGraphicsContext3D* context, unsigned program, bool usingBindUniform, int* baseUniformIndex) +{ + static const char* shaderUniforms[] = { + "s_texture", + "s_mask", + "alpha", + "maskTexCoordScale", + "maskTexCoordOffset", + }; + int locations[5]; + + getProgramUniformLocations(context, program, shaderUniforms, WTF_ARRAY_LENGTH(shaderUniforms), WTF_ARRAY_LENGTH(locations), locations, usingBindUniform, baseUniformIndex); + + m_samplerLocation = locations[0]; + m_maskSamplerLocation = locations[1]; + m_alphaLocation = locations[2]; + m_maskTexCoordScaleLocation = locations[3]; + m_maskTexCoordOffsetLocation = locations[4]; + ASSERT(m_samplerLocation != -1 && m_maskSamplerLocation != -1 && m_alphaLocation != -1); +} + +std::string FragmentShaderRGBATexAlphaMask::getShaderString() const +{ + return SHADER( + precision mediump float; + varying vec2 v_texCoord; + uniform sampler2D s_texture; + uniform sampler2D s_mask; + uniform vec2 maskTexCoordScale; + uniform vec2 maskTexCoordOffset; + uniform float alpha; + void main() + { + vec4 texColor = texture2D(s_texture, v_texCoord); + vec2 maskTexCoord = vec2(maskTexCoordOffset.x + v_texCoord.x * maskTexCoordScale.x, maskTexCoordOffset.y + v_texCoord.y * maskTexCoordScale.y); + vec4 maskColor = texture2D(s_mask, maskTexCoord); + gl_FragColor = vec4(texColor.x, texColor.y, texColor.z, texColor.w) * alpha * maskColor.w; + } + ); +} + +FragmentShaderRGBATexAlphaMaskAA::FragmentShaderRGBATexAlphaMaskAA() + : m_samplerLocation(-1) + , m_maskSamplerLocation(-1) + , m_alphaLocation(-1) + , m_edgeLocation(-1) + , m_maskTexCoordScaleLocation(-1) +{ +} + +void FragmentShaderRGBATexAlphaMaskAA::init(WebGraphicsContext3D* context, unsigned program, bool usingBindUniform, int* baseUniformIndex) +{ + static const char* shaderUniforms[] = { + "s_texture", + "s_mask", + "alpha", + "edge", + "maskTexCoordScale", + "maskTexCoordOffset", + }; + int locations[6]; + + getProgramUniformLocations(context, program, shaderUniforms, WTF_ARRAY_LENGTH(shaderUniforms), WTF_ARRAY_LENGTH(locations), locations, usingBindUniform, baseUniformIndex); + + m_samplerLocation = locations[0]; + m_maskSamplerLocation = locations[1]; + m_alphaLocation = locations[2]; + m_edgeLocation = locations[3]; + m_maskTexCoordScaleLocation = locations[4]; + m_maskTexCoordOffsetLocation = locations[5]; + ASSERT(m_samplerLocation != -1 && m_maskSamplerLocation != -1 && m_alphaLocation != -1 && m_edgeLocation != -1); +} + +std::string FragmentShaderRGBATexAlphaMaskAA::getShaderString() const +{ + return SHADER( + precision mediump float; + varying vec2 v_texCoord; + uniform sampler2D s_texture; + uniform sampler2D s_mask; + uniform vec2 maskTexCoordScale; + uniform vec2 maskTexCoordOffset; + uniform float alpha; + uniform vec3 edge[8]; + void main() + { + vec4 texColor = texture2D(s_texture, v_texCoord); + vec2 maskTexCoord = vec2(maskTexCoordOffset.x + v_texCoord.x * maskTexCoordScale.x, maskTexCoordOffset.y + v_texCoord.y * maskTexCoordScale.y); + vec4 maskColor = texture2D(s_mask, maskTexCoord); + vec3 pos = vec3(gl_FragCoord.xy, 1); + float a0 = clamp(dot(edge[0], pos), 0.0, 1.0); + float a1 = clamp(dot(edge[1], pos), 0.0, 1.0); + float a2 = clamp(dot(edge[2], pos), 0.0, 1.0); + float a3 = clamp(dot(edge[3], pos), 0.0, 1.0); + float a4 = clamp(dot(edge[4], pos), 0.0, 1.0); + float a5 = clamp(dot(edge[5], pos), 0.0, 1.0); + float a6 = clamp(dot(edge[6], pos), 0.0, 1.0); + float a7 = clamp(dot(edge[7], pos), 0.0, 1.0); + gl_FragColor = vec4(texColor.x, texColor.y, texColor.z, texColor.w) * alpha * maskColor.w * min(min(a0, a2) * min(a1, a3), min(a4, a6) * min(a5, a7)); + } + ); +} + +FragmentShaderYUVVideo::FragmentShaderYUVVideo() + : m_yTextureLocation(-1) + , m_uTextureLocation(-1) + , m_vTextureLocation(-1) + , m_alphaLocation(-1) + , m_ccMatrixLocation(-1) + , m_yuvAdjLocation(-1) +{ +} + +void FragmentShaderYUVVideo::init(WebGraphicsContext3D* context, unsigned program, bool usingBindUniform, int* baseUniformIndex) +{ + static const char* shaderUniforms[] = { + "y_texture", + "u_texture", + "v_texture", + "alpha", + "cc_matrix", + "yuv_adj", + }; + int locations[6]; + + getProgramUniformLocations(context, program, shaderUniforms, WTF_ARRAY_LENGTH(shaderUniforms), WTF_ARRAY_LENGTH(locations), locations, usingBindUniform, baseUniformIndex); + + m_yTextureLocation = locations[0]; + m_uTextureLocation = locations[1]; + m_vTextureLocation = locations[2]; + m_alphaLocation = locations[3]; + m_ccMatrixLocation = locations[4]; + m_yuvAdjLocation = locations[5]; + + ASSERT(m_yTextureLocation != -1 && m_uTextureLocation != -1 && m_vTextureLocation != -1 + && m_alphaLocation != -1 && m_ccMatrixLocation != -1 && m_yuvAdjLocation != -1); +} + +std::string FragmentShaderYUVVideo::getShaderString() const +{ + return SHADER( + precision mediump float; + precision mediump int; + varying vec2 y_texCoord; + varying vec2 uv_texCoord; + uniform sampler2D y_texture; + uniform sampler2D u_texture; + uniform sampler2D v_texture; + uniform float alpha; + uniform vec3 yuv_adj; + uniform mat3 cc_matrix; + void main() + { + float y_raw = texture2D(y_texture, y_texCoord).x; + float u_unsigned = texture2D(u_texture, uv_texCoord).x; + float v_unsigned = texture2D(v_texture, uv_texCoord).x; + vec3 yuv = vec3(y_raw, u_unsigned, v_unsigned) + yuv_adj; + vec3 rgb = cc_matrix * yuv; + gl_FragColor = vec4(rgb, float(1)) * alpha; + } + ); +} + +FragmentShaderColor::FragmentShaderColor() + : m_colorLocation(-1) +{ +} + +void FragmentShaderColor::init(WebGraphicsContext3D* context, unsigned program, bool usingBindUniform, int* baseUniformIndex) +{ + static const char* shaderUniforms[] = { + "color", + }; + int locations[1]; + + getProgramUniformLocations(context, program, shaderUniforms, WTF_ARRAY_LENGTH(shaderUniforms), WTF_ARRAY_LENGTH(locations), locations, usingBindUniform, baseUniformIndex); + + m_colorLocation = locations[0]; + ASSERT(m_colorLocation != -1); +} + +std::string FragmentShaderColor::getShaderString() const +{ + return SHADER( + precision mediump float; + uniform vec4 color; + void main() + { + gl_FragColor = color; + } + ); +} + +FragmentShaderCheckerboard::FragmentShaderCheckerboard() + : m_alphaLocation(-1) + , m_texTransformLocation(-1) + , m_frequencyLocation(-1) +{ +} + +void FragmentShaderCheckerboard::init(WebGraphicsContext3D* context, unsigned program, bool usingBindUniform, int* baseUniformIndex) +{ + static const char* shaderUniforms[] = { + "alpha", + "texTransform", + "frequency", + "color", + }; + int locations[4]; + + getProgramUniformLocations(context, program, shaderUniforms, WTF_ARRAY_LENGTH(shaderUniforms), WTF_ARRAY_LENGTH(locations), locations, usingBindUniform, baseUniformIndex); + + m_alphaLocation = locations[0]; + m_texTransformLocation = locations[1]; + m_frequencyLocation = locations[2]; + m_colorLocation = locations[3]; + ASSERT(m_alphaLocation != -1 && m_texTransformLocation != -1 && m_frequencyLocation != -1 && m_colorLocation != -1); +} + +std::string FragmentShaderCheckerboard::getShaderString() const +{ + // Shader based on Example 13-17 of "OpenGL ES 2.0 Programming Guide" + // by Munshi, Ginsburg, Shreiner. + return SHADER( + precision mediump float; + precision mediump int; + varying vec2 v_texCoord; + uniform float alpha; + uniform float frequency; + uniform vec4 texTransform; + uniform vec4 color; + void main() + { + vec4 color1 = vec4(1.0, 1.0, 1.0, 1.0); + vec4 color2 = color; + vec2 texCoord = clamp(v_texCoord, 0.0, 1.0) * texTransform.zw + texTransform.xy; + vec2 coord = mod(floor(texCoord * frequency * 2.0), 2.0); + float picker = abs(coord.x - coord.y); + gl_FragColor = mix(color1, color2, picker) * alpha; + } + ); +} + +} // namespace cc + +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/cc/shader.h b/cc/shader.h index 638cbb2..2518382 100644 --- a/cc/shader.h +++ b/cc/shader.h @@ -1,3 +1,353 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. +// Copyright 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef ShaderChromium_h +#define ShaderChromium_h + +#if USE(ACCELERATED_COMPOSITING) + +#include "SkColorPriv.h" +#include + +namespace WebKit { +class WebGraphicsContext3D; +} + +namespace cc { + +class VertexShaderPosTex { +public: + VertexShaderPosTex(); + + void init(WebKit::WebGraphicsContext3D*, unsigned program, bool usingBindUniform, int* baseUniformIndex); + std::string getShaderString() const; + + int matrixLocation() const { return m_matrixLocation; } + +private: + int m_matrixLocation; +}; + +class VertexShaderPosTexYUVStretch { +public: + VertexShaderPosTexYUVStretch(); + + void init(WebKit::WebGraphicsContext3D*, unsigned program, bool usingBindUniform, int* baseUniformIndex); + std::string getShaderString() const; + + int matrixLocation() const { return m_matrixLocation; } + int yWidthScaleFactorLocation() const { return m_yWidthScaleFactorLocation; } + int uvWidthScaleFactorLocation() const { return m_uvWidthScaleFactorLocation; } + +private: + int m_matrixLocation; + int m_yWidthScaleFactorLocation; + int m_uvWidthScaleFactorLocation; +}; + +class VertexShaderPos { +public: + VertexShaderPos(); + + void init(WebKit::WebGraphicsContext3D*, unsigned program, bool usingBindUniform, int* baseUniformIndex); + std::string getShaderString() const; + + int matrixLocation() const { return m_matrixLocation; } + +private: + int m_matrixLocation; +}; + +class VertexShaderPosTexIdentity { +public: + void init(WebKit::WebGraphicsContext3D*, unsigned program, bool usingBindUniform, int* baseUniformIndex) { } + std::string getShaderString() const; +}; + +class VertexShaderPosTexTransform { +public: + VertexShaderPosTexTransform(); + + void init(WebKit::WebGraphicsContext3D*, unsigned program, bool usingBindUniform, int* baseUniformIndex); + std::string getShaderString() const; + + int matrixLocation() const { return m_matrixLocation; } + int texTransformLocation() const { return m_texTransformLocation; } + +private: + int m_matrixLocation; + int m_texTransformLocation; +}; + +class VertexShaderQuad { +public: + VertexShaderQuad(); + + void init(WebKit::WebGraphicsContext3D*, unsigned program, bool usingBindUniform, int* baseUniformIndex); + std::string getShaderString() const; + + int matrixLocation() const { return m_matrixLocation; } + int pointLocation() const { return m_pointLocation; } + +private: + int m_matrixLocation; + int m_pointLocation; +}; + +class VertexShaderTile { +public: + VertexShaderTile(); + + void init(WebKit::WebGraphicsContext3D*, unsigned program, bool usingBindUniform, int* baseUniformIndex); + std::string getShaderString() const; + + int matrixLocation() const { return m_matrixLocation; } + int pointLocation() const { return m_pointLocation; } + int vertexTexTransformLocation() const { return m_vertexTexTransformLocation; } + +private: + int m_matrixLocation; + int m_pointLocation; + int m_vertexTexTransformLocation; +}; + +class VertexShaderVideoTransform { +public: + VertexShaderVideoTransform(); + + bool init(WebKit::WebGraphicsContext3D*, unsigned program, bool usingBindUniform, int* baseUniformIndex); + std::string getShaderString() const; + + int matrixLocation() const { return m_matrixLocation; } + int texMatrixLocation() const { return m_texMatrixLocation; } + +private: + int m_matrixLocation; + int m_texMatrixLocation; +}; + +class FragmentTexAlphaBinding { +public: + FragmentTexAlphaBinding(); + + void init(WebKit::WebGraphicsContext3D*, unsigned program, bool usingBindUniform, int* baseUniformIndex); + int alphaLocation() const { return m_alphaLocation; } + int edgeLocation() const { return -1; } + int fragmentTexTransformLocation() const { return -1; } + int samplerLocation() const { return m_samplerLocation; } + +private: + int m_samplerLocation; + int m_alphaLocation; +}; + +class FragmentTexOpaqueBinding { +public: + FragmentTexOpaqueBinding(); + + void init(WebKit::WebGraphicsContext3D*, unsigned program, bool usingBindUniform, int* baseUniformIndex); + int alphaLocation() const { return -1; } + int edgeLocation() const { return -1; } + int fragmentTexTransformLocation() const { return -1; } + int samplerLocation() const { return m_samplerLocation; } + +private: + int m_samplerLocation; +}; + +class FragmentShaderRGBATexFlipAlpha : public FragmentTexAlphaBinding { +public: + std::string getShaderString() const; +}; + +class FragmentShaderRGBATexAlpha : public FragmentTexAlphaBinding { +public: + std::string getShaderString() const; +}; + +class FragmentShaderRGBATexRectFlipAlpha : public FragmentTexAlphaBinding { +public: + std::string getShaderString() const; +}; + +class FragmentShaderRGBATexRectAlpha : public FragmentTexAlphaBinding { +public: + std::string getShaderString() const; +}; + +class FragmentShaderRGBATexOpaque : public FragmentTexOpaqueBinding { +public: + std::string getShaderString() const; +}; + +class FragmentShaderRGBATex : public FragmentTexOpaqueBinding { +public: + std::string getShaderString() const; +}; + +// Swizzles the red and blue component of sampled texel with alpha. +class FragmentShaderRGBATexSwizzleAlpha : public FragmentTexAlphaBinding { +public: + std::string getShaderString() const; +}; + +// Swizzles the red and blue component of sampled texel without alpha. +class FragmentShaderRGBATexSwizzleOpaque : public FragmentTexOpaqueBinding { +public: + std::string getShaderString() const; +}; + +// Fragment shader for external textures. +class FragmentShaderOESImageExternal : public FragmentTexAlphaBinding { +public: + std::string getShaderString() const; + bool init(WebKit::WebGraphicsContext3D*, unsigned program, bool usingBindUniform, int* baseUniformIndex); +private: + int m_samplerLocation; +}; + +class FragmentShaderRGBATexAlphaAA { +public: + FragmentShaderRGBATexAlphaAA(); + + void init(WebKit::WebGraphicsContext3D*, unsigned program, bool usingBindUniform, int* baseUniformIndex); + std::string getShaderString() const; + + int alphaLocation() const { return m_alphaLocation; } + int samplerLocation() const { return m_samplerLocation; } + int edgeLocation() const { return m_edgeLocation; } + +private: + int m_samplerLocation; + int m_alphaLocation; + int m_edgeLocation; +}; + +class FragmentTexClampAlphaAABinding { +public: + FragmentTexClampAlphaAABinding(); + + void init(WebKit::WebGraphicsContext3D*, unsigned program, bool usingBindUniform, int* baseUniformIndex); + int alphaLocation() const { return m_alphaLocation; } + int samplerLocation() const { return m_samplerLocation; } + int fragmentTexTransformLocation() const { return m_fragmentTexTransformLocation; } + int edgeLocation() const { return m_edgeLocation; } + +private: + int m_samplerLocation; + int m_alphaLocation; + int m_fragmentTexTransformLocation; + int m_edgeLocation; +}; + +class FragmentShaderRGBATexClampAlphaAA : public FragmentTexClampAlphaAABinding { +public: + std::string getShaderString() const; +}; + +// Swizzles the red and blue component of sampled texel. +class FragmentShaderRGBATexClampSwizzleAlphaAA : public FragmentTexClampAlphaAABinding { +public: + std::string getShaderString() const; +}; + +class FragmentShaderRGBATexAlphaMask { +public: + FragmentShaderRGBATexAlphaMask(); + std::string getShaderString() const; + + void init(WebKit::WebGraphicsContext3D*, unsigned program, bool usingBindUniform, int* baseUniformIndex); + int alphaLocation() const { return m_alphaLocation; } + int samplerLocation() const { return m_samplerLocation; } + int maskSamplerLocation() const { return m_maskSamplerLocation; } + int maskTexCoordScaleLocation() const { return m_maskTexCoordScaleLocation; } + int maskTexCoordOffsetLocation() const { return m_maskTexCoordOffsetLocation; } + +private: + int m_samplerLocation; + int m_maskSamplerLocation; + int m_alphaLocation; + int m_maskTexCoordScaleLocation; + int m_maskTexCoordOffsetLocation; +}; + +class FragmentShaderRGBATexAlphaMaskAA { +public: + FragmentShaderRGBATexAlphaMaskAA(); + std::string getShaderString() const; + + void init(WebKit::WebGraphicsContext3D*, unsigned program, bool usingBindUniform, int* baseUniformIndex); + int alphaLocation() const { return m_alphaLocation; } + int samplerLocation() const { return m_samplerLocation; } + int maskSamplerLocation() const { return m_maskSamplerLocation; } + int edgeLocation() const { return m_edgeLocation; } + int maskTexCoordScaleLocation() const { return m_maskTexCoordScaleLocation; } + int maskTexCoordOffsetLocation() const { return m_maskTexCoordOffsetLocation; } + +private: + int m_samplerLocation; + int m_maskSamplerLocation; + int m_alphaLocation; + int m_edgeLocation; + int m_maskTexCoordScaleLocation; + int m_maskTexCoordOffsetLocation; +}; + +class FragmentShaderYUVVideo { +public: + FragmentShaderYUVVideo(); + std::string getShaderString() const; + + void init(WebKit::WebGraphicsContext3D*, unsigned program, bool usingBindUniform, int* baseUniformIndex); + + int yTextureLocation() const { return m_yTextureLocation; } + int uTextureLocation() const { return m_uTextureLocation; } + int vTextureLocation() const { return m_vTextureLocation; } + int alphaLocation() const { return m_alphaLocation; } + int ccMatrixLocation() const { return m_ccMatrixLocation; } + int yuvAdjLocation() const { return m_yuvAdjLocation; } + +private: + int m_yTextureLocation; + int m_uTextureLocation; + int m_vTextureLocation; + int m_alphaLocation; + int m_ccMatrixLocation; + int m_yuvAdjLocation; +}; + +class FragmentShaderColor { +public: + FragmentShaderColor(); + std::string getShaderString() const; + + void init(WebKit::WebGraphicsContext3D*, unsigned program, bool usingBindUniform, int* baseUniformIndex); + int colorLocation() const { return m_colorLocation; } + +private: + int m_colorLocation; +}; + +class FragmentShaderCheckerboard { +public: + FragmentShaderCheckerboard(); + std::string getShaderString() const; + + void init(WebKit::WebGraphicsContext3D*, unsigned program, bool usingBindUniform, int* baseUniformIndex); + int alphaLocation() const { return m_alphaLocation; } + int texTransformLocation() const { return m_texTransformLocation; } + int frequencyLocation() const { return m_frequencyLocation; } + int colorLocation() const { return m_colorLocation; } +private: + int m_alphaLocation; + int m_texTransformLocation; + int m_frequencyLocation; + int m_colorLocation; +}; + +} // namespace cc + +#endif // USE(ACCELERATED_COMPOSITING) + +#endif diff --git a/cc/shared_quad_state.cc b/cc/shared_quad_state.cc new file mode 100644 index 0000000..ede07a5 --- /dev/null +++ b/cc/shared_quad_state.cc @@ -0,0 +1,35 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#include "CCSharedQuadState.h" + +#include "FloatQuad.h" + +namespace cc { + +scoped_ptr CCSharedQuadState::create(const WebKit::WebTransformationMatrix& quadTransform, const IntRect& visibleContentRect, const IntRect& clippedRectInTarget, float opacity, bool opaque) +{ + return make_scoped_ptr(new CCSharedQuadState(quadTransform, visibleContentRect, clippedRectInTarget, opacity, opaque)); +} + +CCSharedQuadState::CCSharedQuadState(const WebKit::WebTransformationMatrix& quadTransform, const IntRect& visibleContentRect, const IntRect& clippedRectInTarget, float opacity, bool opaque) + : id(-1) + , quadTransform(quadTransform) + , visibleContentRect(visibleContentRect) + , clippedRectInTarget(clippedRectInTarget) + , opacity(opacity) + , opaque(opaque) +{ +} + +scoped_ptr CCSharedQuadState::copy() const +{ + scoped_ptr copiedState(create(quadTransform, visibleContentRect, clippedRectInTarget, opacity, opaque)); + copiedState->id = id; + return copiedState.Pass(); +} + +} // namespace cc diff --git a/cc/shared_quad_state.h b/cc/shared_quad_state.h index 638cbb2..0f5e386 100644 --- a/cc/shared_quad_state.h +++ b/cc/shared_quad_state.h @@ -1,3 +1,33 @@ // Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CCSharedQuadState_h +#define CCSharedQuadState_h + +#include "IntRect.h" +#include "base/memory/scoped_ptr.h" +#include + +namespace cc { + +struct CCSharedQuadState { + int id; + + // Transforms from quad's original content space to its target content space. + WebKit::WebTransformationMatrix quadTransform; + // This rect lives in the content space for the quad's originating layer. + IntRect visibleContentRect; + IntRect clippedRectInTarget; + float opacity; + bool opaque; + + static scoped_ptr create(const WebKit::WebTransformationMatrix& quadTransform, const IntRect& visibleContentRect, const IntRect& clippedRectInTarget, float opacity, bool opaque); + CCSharedQuadState(const WebKit::WebTransformationMatrix& quadTransform, const IntRect& visibleContentRect, const IntRect& clippedRectInTarget, float opacity, bool opaque); + + scoped_ptr copy() const; +}; + +} + +#endif diff --git a/cc/single_thread_proxy.cc b/cc/single_thread_proxy.cc new file mode 100644 index 0000000..7f89cf5 --- /dev/null +++ b/cc/single_thread_proxy.cc @@ -0,0 +1,385 @@ +// Copyright 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#include "CCSingleThreadProxy.h" + +#include "CCDrawQuad.h" +#include "CCGraphicsContext.h" +#include "CCLayerTreeHost.h" +#include "CCTextureUpdateController.h" +#include "CCTimer.h" +#include "TraceEvent.h" +#include + +using namespace WTF; + +namespace cc { + +scoped_ptr CCSingleThreadProxy::create(CCLayerTreeHost* layerTreeHost) +{ + return make_scoped_ptr(new CCSingleThreadProxy(layerTreeHost)).PassAs(); +} + +CCSingleThreadProxy::CCSingleThreadProxy(CCLayerTreeHost* layerTreeHost) + : m_layerTreeHost(layerTreeHost) + , m_contextLost(false) + , m_rendererInitialized(false) + , m_nextFrameIsNewlyCommittedFrame(false) + , m_totalCommitCount(0) +{ + TRACE_EVENT0("cc", "CCSingleThreadProxy::CCSingleThreadProxy"); + ASSERT(CCProxy::isMainThread()); +} + +void CCSingleThreadProxy::start() +{ + DebugScopedSetImplThread impl; + m_layerTreeHostImpl = m_layerTreeHost->createLayerTreeHostImpl(this); +} + +CCSingleThreadProxy::~CCSingleThreadProxy() +{ + TRACE_EVENT0("cc", "CCSingleThreadProxy::~CCSingleThreadProxy"); + ASSERT(CCProxy::isMainThread()); + ASSERT(!m_layerTreeHostImpl.get() && !m_layerTreeHost); // make sure stop() got called. +} + +bool CCSingleThreadProxy::compositeAndReadback(void *pixels, const IntRect& rect) +{ + TRACE_EVENT0("cc", "CCSingleThreadProxy::compositeAndReadback"); + ASSERT(CCProxy::isMainThread()); + + if (!commitAndComposite()) + return false; + + m_layerTreeHostImpl->readback(pixels, rect); + + if (m_layerTreeHostImpl->isContextLost()) + return false; + + m_layerTreeHostImpl->swapBuffers(); + didSwapFrame(); + + return true; +} + +void CCSingleThreadProxy::startPageScaleAnimation(const IntSize& targetPosition, bool useAnchor, float scale, double duration) +{ + m_layerTreeHostImpl->startPageScaleAnimation(targetPosition, useAnchor, scale, monotonicallyIncreasingTime(), duration); +} + +void CCSingleThreadProxy::finishAllRendering() +{ + ASSERT(CCProxy::isMainThread()); + { + DebugScopedSetImplThread impl; + m_layerTreeHostImpl->finishAllRendering(); + } +} + +bool CCSingleThreadProxy::isStarted() const +{ + ASSERT(CCProxy::isMainThread()); + return m_layerTreeHostImpl.get(); +} + +bool CCSingleThreadProxy::initializeContext() +{ + ASSERT(CCProxy::isMainThread()); + scoped_ptr context = m_layerTreeHost->createContext(); + if (!context.get()) + return false; + m_contextBeforeInitialization = context.Pass(); + return true; +} + +void CCSingleThreadProxy::setSurfaceReady() +{ + // Scheduling is controlled by the embedder in the single thread case, so nothing to do. +} + +void CCSingleThreadProxy::setVisible(bool visible) +{ + DebugScopedSetImplThread impl; + m_layerTreeHostImpl->setVisible(visible); +} + +bool CCSingleThreadProxy::initializeRenderer() +{ + ASSERT(CCProxy::isMainThread()); + ASSERT(m_contextBeforeInitialization.get()); + { + DebugScopedSetImplThread impl; + bool ok = m_layerTreeHostImpl->initializeRenderer(m_contextBeforeInitialization.Pass()); + if (ok) { + m_rendererInitialized = true; + m_RendererCapabilitiesForMainThread = m_layerTreeHostImpl->rendererCapabilities(); + } + + return ok; + } +} + +bool CCSingleThreadProxy::recreateContext() +{ + TRACE_EVENT0("cc", "CCSingleThreadProxy::recreateContext"); + ASSERT(CCProxy::isMainThread()); + ASSERT(m_contextLost); + + scoped_ptr context = m_layerTreeHost->createContext(); + if (!context.get()) + return false; + + bool initialized; + { + DebugScopedSetMainThreadBlocked mainThreadBlocked; + DebugScopedSetImplThread impl; + if (!m_layerTreeHostImpl->contentsTexturesPurged()) + m_layerTreeHost->deleteContentsTexturesOnImplThread(m_layerTreeHostImpl->resourceProvider()); + initialized = m_layerTreeHostImpl->initializeRenderer(context.Pass()); + if (initialized) { + m_RendererCapabilitiesForMainThread = m_layerTreeHostImpl->rendererCapabilities(); + } + } + + if (initialized) + m_contextLost = false; + + return initialized; +} + +void CCSingleThreadProxy::renderingStats(CCRenderingStats* stats) +{ + stats->totalCommitTimeInSeconds = m_totalCommitTime.InSecondsF(); + stats->totalCommitCount = m_totalCommitCount; + m_layerTreeHostImpl->renderingStats(stats); +} + +const RendererCapabilities& CCSingleThreadProxy::rendererCapabilities() const +{ + ASSERT(m_rendererInitialized); + // Note: this gets called during the commit by the "impl" thread + return m_RendererCapabilitiesForMainThread; +} + +void CCSingleThreadProxy::loseContext() +{ + ASSERT(CCProxy::isMainThread()); + m_layerTreeHost->didLoseContext(); + m_contextLost = true; +} + +void CCSingleThreadProxy::setNeedsAnimate() +{ + // CCThread-only feature + ASSERT_NOT_REACHED(); +} + +void CCSingleThreadProxy::doCommit(PassOwnPtr queue) +{ + ASSERT(CCProxy::isMainThread()); + // Commit immediately + { + DebugScopedSetMainThreadBlocked mainThreadBlocked; + DebugScopedSetImplThread impl; + + base::TimeTicks startTime = base::TimeTicks::HighResNow(); + m_layerTreeHostImpl->beginCommit(); + + m_layerTreeHost->beginCommitOnImplThread(m_layerTreeHostImpl.get()); + + OwnPtr updateController = + CCTextureUpdateController::create( + NULL, + CCProxy::mainThread(), + queue, + m_layerTreeHostImpl->resourceProvider(), + m_layerTreeHostImpl->resourceProvider()->textureUploader()); + updateController->finalize(); + + m_layerTreeHost->finishCommitOnImplThread(m_layerTreeHostImpl.get()); + + m_layerTreeHostImpl->commitComplete(); + +#if !ASSERT_DISABLED + // In the single-threaded case, the scroll deltas should never be + // touched on the impl layer tree. + scoped_ptr scrollInfo = m_layerTreeHostImpl->processScrollDeltas(); + ASSERT(!scrollInfo->scrolls.size()); +#endif + + base::TimeTicks endTime = base::TimeTicks::HighResNow(); + m_totalCommitTime += endTime - startTime; + m_totalCommitCount++; + } + m_layerTreeHost->commitComplete(); + m_nextFrameIsNewlyCommittedFrame = true; +} + +void CCSingleThreadProxy::setNeedsCommit() +{ + ASSERT(CCProxy::isMainThread()); + m_layerTreeHost->scheduleComposite(); +} + +void CCSingleThreadProxy::setNeedsRedraw() +{ + // FIXME: Once we move render_widget scheduling into this class, we can + // treat redraw requests more efficiently than commitAndRedraw requests. + m_layerTreeHostImpl->setFullRootLayerDamage(); + setNeedsCommit(); +} + +bool CCSingleThreadProxy::commitRequested() const +{ + return false; +} + +void CCSingleThreadProxy::didAddAnimation() +{ +} + +size_t CCSingleThreadProxy::maxPartialTextureUpdates() const +{ + return std::numeric_limits::max(); +} + +void CCSingleThreadProxy::stop() +{ + TRACE_EVENT0("cc", "CCSingleThreadProxy::stop"); + ASSERT(CCProxy::isMainThread()); + { + DebugScopedSetMainThreadBlocked mainThreadBlocked; + DebugScopedSetImplThread impl; + + if (!m_layerTreeHostImpl->contentsTexturesPurged()) + m_layerTreeHost->deleteContentsTexturesOnImplThread(m_layerTreeHostImpl->resourceProvider()); + m_layerTreeHostImpl.reset(); + } + m_layerTreeHost = 0; +} + +void CCSingleThreadProxy::setNeedsRedrawOnImplThread() +{ + m_layerTreeHost->scheduleComposite(); +} + +void CCSingleThreadProxy::setNeedsCommitOnImplThread() +{ + m_layerTreeHost->scheduleComposite(); +} + +void CCSingleThreadProxy::postAnimationEventsToMainThreadOnImplThread(scoped_ptr events, double wallClockTime) +{ + ASSERT(CCProxy::isImplThread()); + DebugScopedSetMainThread main; + m_layerTreeHost->setAnimationEvents(events.Pass(), wallClockTime); +} + +void CCSingleThreadProxy::releaseContentsTexturesOnImplThread() +{ + ASSERT(isImplThread()); + m_layerTreeHost->reduceContentsTexturesMemoryOnImplThread(0, m_layerTreeHostImpl->resourceProvider()); +} + +// Called by the legacy scheduling path (e.g. where render_widget does the scheduling) +void CCSingleThreadProxy::compositeImmediately() +{ + if (commitAndComposite()) { + m_layerTreeHostImpl->swapBuffers(); + didSwapFrame(); + } +} + +void CCSingleThreadProxy::forceSerializeOnSwapBuffers() +{ + { + DebugScopedSetImplThread impl; + if (m_rendererInitialized) + m_layerTreeHostImpl->renderer()->doNoOp(); + } +} + +void CCSingleThreadProxy::onSwapBuffersCompleteOnImplThread() +{ + ASSERT_NOT_REACHED(); +} + +bool CCSingleThreadProxy::commitAndComposite() +{ + ASSERT(CCProxy::isMainThread()); + + if (!m_layerTreeHost->initializeRendererIfNeeded()) + return false; + + // Unlink any texture backings that were deleted + CCPrioritizedTextureManager::BackingVector evictedContentsTexturesBackings; + { + DebugScopedSetImplThread implThread; + m_layerTreeHost->getEvictedContentTexturesBackings(evictedContentsTexturesBackings); + } + m_layerTreeHost->unlinkEvictedContentTexturesBackings(evictedContentsTexturesBackings); + { + DebugScopedSetImplThreadAndMainThreadBlocked implAndMainBlocked; + m_layerTreeHost->deleteEvictedContentTexturesBackings(); + } + + OwnPtr queue = adoptPtr(new CCTextureUpdateQueue); + m_layerTreeHost->updateLayers(*(queue.get()), m_layerTreeHostImpl->memoryAllocationLimitBytes()); + + if (m_layerTreeHostImpl->contentsTexturesPurged()) + m_layerTreeHostImpl->resetContentsTexturesPurged(); + + m_layerTreeHost->willCommit(); + doCommit(queue.release()); + bool result = doComposite(); + m_layerTreeHost->didBeginFrame(); + return result; +} + +bool CCSingleThreadProxy::doComposite() +{ + ASSERT(!m_contextLost); + { + DebugScopedSetImplThread impl; + + if (!m_layerTreeHostImpl->visible()) + return false; + + double monotonicTime = monotonicallyIncreasingTime(); + double wallClockTime = currentTime(); + m_layerTreeHostImpl->animate(monotonicTime, wallClockTime); + + // We guard prepareToDraw() with canDraw() because it always returns a valid frame, so can only + // be used when such a frame is possible. Since drawLayers() depends on the result of + // prepareToDraw(), it is guarded on canDraw() as well. + if (!m_layerTreeHostImpl->canDraw()) + return false; + + CCLayerTreeHostImpl::FrameData frame; + m_layerTreeHostImpl->prepareToDraw(frame); + m_layerTreeHostImpl->drawLayers(frame); + m_layerTreeHostImpl->didDrawAllLayers(frame); + } + + if (m_layerTreeHostImpl->isContextLost()) { + m_contextLost = true; + m_layerTreeHost->didLoseContext(); + return false; + } + + return true; +} + +void CCSingleThreadProxy::didSwapFrame() +{ + if (m_nextFrameIsNewlyCommittedFrame) { + m_nextFrameIsNewlyCommittedFrame = false; + m_layerTreeHost->didCommitAndDrawFrame(); + } +} + +} diff --git a/cc/single_thread_proxy.h b/cc/single_thread_proxy.h index 638cbb2..979dbb3 100644 --- a/cc/single_thread_proxy.h +++ b/cc/single_thread_proxy.h @@ -1,3 +1,134 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. +// Copyright 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CCSingleThreadProxy_h +#define CCSingleThreadProxy_h + +#include "CCAnimationEvents.h" +#include "CCLayerTreeHostImpl.h" +#include "CCProxy.h" +#include +#include + +namespace cc { + +class CCLayerTreeHost; + +class CCSingleThreadProxy : public CCProxy, CCLayerTreeHostImplClient { +public: + static scoped_ptr create(CCLayerTreeHost*); + virtual ~CCSingleThreadProxy(); + + // CCProxy implementation + virtual bool compositeAndReadback(void *pixels, const IntRect&) OVERRIDE; + virtual void startPageScaleAnimation(const IntSize& targetPosition, bool useAnchor, float scale, double duration) OVERRIDE; + virtual void finishAllRendering() OVERRIDE; + virtual bool isStarted() const OVERRIDE; + virtual bool initializeContext() OVERRIDE; + virtual void setSurfaceReady() OVERRIDE; + virtual void setVisible(bool) OVERRIDE; + virtual bool initializeRenderer() OVERRIDE; + virtual bool recreateContext() OVERRIDE; + virtual void renderingStats(CCRenderingStats*) OVERRIDE; + virtual const RendererCapabilities& rendererCapabilities() const OVERRIDE; + virtual void loseContext() OVERRIDE; + virtual void setNeedsAnimate() OVERRIDE; + virtual void setNeedsCommit() OVERRIDE; + virtual void setNeedsRedraw() OVERRIDE; + virtual bool commitRequested() const OVERRIDE; + virtual void didAddAnimation() OVERRIDE; + virtual void start() OVERRIDE; + virtual void stop() OVERRIDE; + virtual size_t maxPartialTextureUpdates() const OVERRIDE; + virtual void acquireLayerTextures() OVERRIDE { } + virtual void forceSerializeOnSwapBuffers() OVERRIDE; + + // CCLayerTreeHostImplClient implementation + virtual void didLoseContextOnImplThread() OVERRIDE { } + virtual void onSwapBuffersCompleteOnImplThread() OVERRIDE; + virtual void onVSyncParametersChanged(double monotonicTimebase, double intervalInSeconds) OVERRIDE { } + virtual void onCanDrawStateChanged(bool canDraw) OVERRIDE { } + virtual void setNeedsRedrawOnImplThread() OVERRIDE; + virtual void setNeedsCommitOnImplThread() OVERRIDE; + virtual void postAnimationEventsToMainThreadOnImplThread(scoped_ptr, double wallClockTime) OVERRIDE; + virtual void releaseContentsTexturesOnImplThread() OVERRIDE; + + // Called by the legacy path where RenderWidget does the scheduling. + void compositeImmediately(); + +private: + explicit CCSingleThreadProxy(CCLayerTreeHost*); + + bool commitAndComposite(); + void doCommit(PassOwnPtr); + bool doComposite(); + void didSwapFrame(); + + // Accessed on main thread only. + CCLayerTreeHost* m_layerTreeHost; + bool m_contextLost; + + // Holds on to the context between initializeContext() and initializeRenderer() calls. Shouldn't + // be used for anything else. + scoped_ptr m_contextBeforeInitialization; + + // Used on the CCThread, but checked on main thread during initialization/shutdown. + scoped_ptr m_layerTreeHostImpl; + bool m_rendererInitialized; + RendererCapabilities m_RendererCapabilitiesForMainThread; + + bool m_nextFrameIsNewlyCommittedFrame; + + base::TimeDelta m_totalCommitTime; + size_t m_totalCommitCount; +}; + +// For use in the single-threaded case. In debug builds, it pretends that the +// code is running on the impl thread to satisfy assertion checks. +class DebugScopedSetImplThread { +public: + DebugScopedSetImplThread() + { +#if !ASSERT_DISABLED + CCProxy::setCurrentThreadIsImplThread(true); +#endif + } + ~DebugScopedSetImplThread() + { +#if !ASSERT_DISABLED + CCProxy::setCurrentThreadIsImplThread(false); +#endif + } +}; + +// For use in the single-threaded case. In debug builds, it pretends that the +// code is running on the main thread to satisfy assertion checks. +class DebugScopedSetMainThread { +public: + DebugScopedSetMainThread() + { +#if !ASSERT_DISABLED + CCProxy::setCurrentThreadIsImplThread(false); +#endif + } + ~DebugScopedSetMainThread() + { +#if !ASSERT_DISABLED + CCProxy::setCurrentThreadIsImplThread(true); +#endif + } +}; + +// For use in the single-threaded case. In debug builds, it pretends that the +// code is running on the impl thread and that the main thread is blocked to +// satisfy assertion checks +class DebugScopedSetImplThreadAndMainThreadBlocked { +private: + DebugScopedSetImplThread m_implThread; + DebugScopedSetMainThreadBlocked m_mainThreadBlocked; +}; + +} // namespace cc + +#endif diff --git a/cc/skpicture_canvas_layer_texture_updater.cc b/cc/skpicture_canvas_layer_texture_updater.cc new file mode 100644 index 0000000..62026d7 --- /dev/null +++ b/cc/skpicture_canvas_layer_texture_updater.cc @@ -0,0 +1,47 @@ +// Copyright 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + +#include "config.h" + +#if USE(ACCELERATED_COMPOSITING) + +#include "SkPictureCanvasLayerTextureUpdater.h" + +#include "LayerPainterChromium.h" +#include "SkCanvas.h" +#include "TraceEvent.h" + +namespace cc { + +SkPictureCanvasLayerTextureUpdater::SkPictureCanvasLayerTextureUpdater(PassOwnPtr painter) + : CanvasLayerTextureUpdater(painter) + , m_layerIsOpaque(false) +{ +} + +SkPictureCanvasLayerTextureUpdater::~SkPictureCanvasLayerTextureUpdater() +{ +} + +void SkPictureCanvasLayerTextureUpdater::prepareToUpdate(const IntRect& contentRect, const IntSize&, float contentsWidthScale, float contentsHeightScale, IntRect& resultingOpaqueRect, CCRenderingStats& stats) +{ + SkCanvas* canvas = m_picture.beginRecording(contentRect.width(), contentRect.height()); + paintContents(canvas, contentRect, contentsWidthScale, contentsHeightScale, resultingOpaqueRect, stats); + m_picture.endRecording(); +} + +void SkPictureCanvasLayerTextureUpdater::drawPicture(SkCanvas* canvas) +{ + TRACE_EVENT0("cc", "SkPictureCanvasLayerTextureUpdater::drawPicture"); + canvas->drawPicture(m_picture); +} + +void SkPictureCanvasLayerTextureUpdater::setOpaque(bool opaque) +{ + m_layerIsOpaque = opaque; +} + +} // namespace cc +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/cc/skpicture_canvas_layer_texture_updater.h b/cc/skpicture_canvas_layer_texture_updater.h index 638cbb2..fd9bb5f 100644 --- a/cc/skpicture_canvas_layer_texture_updater.h +++ b/cc/skpicture_canvas_layer_texture_updater.h @@ -1,3 +1,48 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. +// Copyright 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + + +#ifndef SkPictureCanvasLayerTextureUpdater_h +#define SkPictureCanvasLayerTextureUpdater_h + +#if USE(ACCELERATED_COMPOSITING) + +#include "CanvasLayerTextureUpdater.h" +#include "SkPicture.h" + +class SkCanvas; + +namespace cc { + +class LayerPainterChromium; + +// This class records the contentRect into an SkPicture. Subclasses, provide +// different implementations of tile updating based on this recorded picture. +// The BitmapSkPictureCanvasLayerTextureUpdater and +// FrameBufferSkPictureCanvasLayerTextureUpdater are two examples of such +// implementations. +class SkPictureCanvasLayerTextureUpdater : public CanvasLayerTextureUpdater { +public: + virtual ~SkPictureCanvasLayerTextureUpdater(); + + virtual void setOpaque(bool) OVERRIDE; + +protected: + explicit SkPictureCanvasLayerTextureUpdater(PassOwnPtr); + + virtual void prepareToUpdate(const IntRect& contentRect, const IntSize& tileSize, float contentsWidthScale, float contentsHeightScale, IntRect& resultingOpaqueRect, CCRenderingStats&) OVERRIDE; + void drawPicture(SkCanvas*); + + bool layerIsOpaque() const { return m_layerIsOpaque; } + +private: + // Recording canvas. + SkPicture m_picture; + // True when it is known that all output pixels will be opaque. + bool m_layerIsOpaque; +}; + +} // namespace cc +#endif // USE(ACCELERATED_COMPOSITING) +#endif // SkPictureCanvasLayerTextureUpdater_h diff --git a/cc/software_renderer.cc b/cc/software_renderer.cc new file mode 100644 index 0000000..e833780 --- /dev/null +++ b/cc/software_renderer.cc @@ -0,0 +1,279 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#include "CCRendererSoftware.h" + +#include "CCDebugBorderDrawQuad.h" +#include "CCSolidColorDrawQuad.h" +#include "CCTextureDrawQuad.h" +#include "CCTileDrawQuad.h" +#include "SkCanvas.h" +#include "SkColor.h" +#include "SkMatrix.h" +#include "SkPixelRef.h" +#include +#include +#include +#include + +using WebKit::WebCompositorSoftwareOutputDevice; +using WebKit::WebImage; +using WebKit::WebSize; +using WebKit::WebTransformationMatrix; + +namespace cc { + +namespace { + +SkRect toSkRect(const FloatRect& rect) +{ + return SkRect::MakeXYWH(rect.x(), rect.y(), rect.width(), rect.height()); +} + +SkIRect toSkIRect(const IntRect& rect) +{ + return SkIRect::MakeXYWH(rect.x(), rect.y(), rect.width(), rect.height()); +} + +void toSkMatrix(SkMatrix* flattened, const WebTransformationMatrix& m) +{ + // Convert from 4x4 to 3x3 by dropping the third row and column. + flattened->set(0, m.m11()); + flattened->set(1, m.m21()); + flattened->set(2, m.m41()); + flattened->set(3, m.m12()); + flattened->set(4, m.m22()); + flattened->set(5, m.m42()); + flattened->set(6, m.m14()); + flattened->set(7, m.m24()); + flattened->set(8, m.m44()); +} + +} // anonymous namespace + +PassOwnPtr CCRendererSoftware::create(CCRendererClient* client, CCResourceProvider* resourceProvider, WebCompositorSoftwareOutputDevice* outputDevice) +{ + return adoptPtr(new CCRendererSoftware(client, resourceProvider, outputDevice)); +} + +CCRendererSoftware::CCRendererSoftware(CCRendererClient* client, CCResourceProvider* resourceProvider, WebCompositorSoftwareOutputDevice* outputDevice) + : CCDirectRenderer(client, resourceProvider) + , m_visible(true) + , m_outputDevice(outputDevice) + , m_skCurrentCanvas(0) +{ + m_resourceProvider->setDefaultResourceType(CCResourceProvider::Bitmap); + + m_capabilities.maxTextureSize = INT_MAX; + m_capabilities.bestTextureFormat = GraphicsContext3D::RGBA; + m_capabilities.contextHasCachedFrontBuffer = true; + m_capabilities.usingSetVisibility = true; + + viewportChanged(); +} + +CCRendererSoftware::~CCRendererSoftware() +{ +} + +const RendererCapabilities& CCRendererSoftware::capabilities() const +{ + return m_capabilities; +} + +void CCRendererSoftware::viewportChanged() +{ + m_outputDevice->didChangeViewportSize(WebSize(viewportSize().width(), viewportSize().height())); +} + +void CCRendererSoftware::beginDrawingFrame(DrawingFrame& frame) +{ + m_skRootCanvas = adoptPtr(new SkCanvas(m_outputDevice->lock(true)->getSkBitmap())); +} + +void CCRendererSoftware::finishDrawingFrame(DrawingFrame& frame) +{ + m_currentFramebufferLock.clear(); + m_skCurrentCanvas = 0; + m_skRootCanvas.clear(); + m_outputDevice->unlock(); +} + +bool CCRendererSoftware::flippedFramebuffer() const +{ + return false; +} + +void CCRendererSoftware::finish() +{ +} + +void CCRendererSoftware::bindFramebufferToOutputSurface(DrawingFrame& frame) +{ + m_currentFramebufferLock.clear(); + m_skCurrentCanvas = m_skRootCanvas.get(); +} + +bool CCRendererSoftware::bindFramebufferToTexture(DrawingFrame& frame, const CCScopedTexture* texture, const IntRect& framebufferRect) +{ + m_currentFramebufferLock = adoptPtr(new CCResourceProvider::ScopedWriteLockSoftware(m_resourceProvider, texture->id())); + m_skCurrentCanvas = m_currentFramebufferLock->skCanvas(); + initializeMatrices(frame, framebufferRect, false); + setDrawViewportSize(framebufferRect.size()); + + return true; +} + +void CCRendererSoftware::enableScissorTestRect(const IntRect& scissorRect) +{ + m_skCurrentCanvas->clipRect(toSkRect(scissorRect), SkRegion::kReplace_Op); +} + +void CCRendererSoftware::disableScissorTest() +{ + IntRect canvasRect(IntPoint(), viewportSize()); + m_skCurrentCanvas->clipRect(toSkRect(canvasRect), SkRegion::kReplace_Op); +} + +void CCRendererSoftware::clearFramebuffer(DrawingFrame& frame) +{ + m_skCurrentCanvas->clear(SK_ColorGREEN); +} + +void CCRendererSoftware::setDrawViewportSize(const IntSize& viewportSize) +{ +} + +bool CCRendererSoftware::isSoftwareResource(CCResourceProvider::ResourceId id) const +{ + switch (m_resourceProvider->resourceType(id)) { + case CCResourceProvider::GLTexture: + return false; + case CCResourceProvider::Bitmap: + return true; + } + + CRASH(); + return false; +} + +void CCRendererSoftware::drawQuad(DrawingFrame& frame, const CCDrawQuad* quad) +{ + WebTransformationMatrix quadRectMatrix; + quadRectTransform(&quadRectMatrix, quad->quadTransform(), quad->quadRect()); + WebTransformationMatrix windowMatrix = frame.windowMatrix * frame.projectionMatrix * quadRectMatrix; + SkMatrix skWindowMatrix; + toSkMatrix(&skWindowMatrix, windowMatrix); + m_skCurrentCanvas->setMatrix(skWindowMatrix); + + m_skCurrentPaint.reset(); + if (quad->needsBlending()) + m_skCurrentPaint.setAlpha(quad->opacity() * 255); + else + m_skCurrentPaint.setXfermodeMode(SkXfermode::kSrc_Mode); + + switch (quad->material()) { + case CCDrawQuad::DebugBorder: + drawDebugBorderQuad(frame, CCDebugBorderDrawQuad::materialCast(quad)); + break; + case CCDrawQuad::SolidColor: + drawSolidColorQuad(frame, CCSolidColorDrawQuad::materialCast(quad)); + break; + case CCDrawQuad::TextureContent: + drawTextureQuad(frame, CCTextureDrawQuad::materialCast(quad)); + break; + case CCDrawQuad::TiledContent: + drawTileQuad(frame, CCTileDrawQuad::materialCast(quad)); + break; + default: + drawUnsupportedQuad(frame, quad); + break; + } + + m_skCurrentCanvas->resetMatrix(); +} + +void CCRendererSoftware::drawDebugBorderQuad(const DrawingFrame& frame, const CCDebugBorderDrawQuad* quad) +{ + // We need to apply the matrix manually to have pixel-sized stroke width. + SkPoint vertices[4]; + toSkRect(quadVertexRect()).toQuad(vertices); + SkPoint transformedVertices[4]; + m_skCurrentCanvas->getTotalMatrix().mapPoints(transformedVertices, vertices, 4); + m_skCurrentCanvas->resetMatrix(); + + m_skCurrentPaint.setColor(quad->color()); + m_skCurrentPaint.setAlpha(quad->opacity() * SkColorGetA(quad->color())); + m_skCurrentPaint.setStyle(SkPaint::kStroke_Style); + m_skCurrentPaint.setStrokeWidth(quad->width()); + m_skCurrentCanvas->drawPoints(SkCanvas::kPolygon_PointMode, 4, transformedVertices, m_skCurrentPaint); +} + +void CCRendererSoftware::drawSolidColorQuad(const DrawingFrame& frame, const CCSolidColorDrawQuad* quad) +{ + m_skCurrentPaint.setColor(quad->color()); + m_skCurrentPaint.setAlpha(quad->opacity() * SkColorGetA(quad->color())); + m_skCurrentCanvas->drawRect(toSkRect(quadVertexRect()), m_skCurrentPaint); +} + +void CCRendererSoftware::drawTextureQuad(const DrawingFrame& frame, const CCTextureDrawQuad* quad) +{ + if (!isSoftwareResource(quad->resourceId())) { + drawUnsupportedQuad(frame, quad); + return; + } + + // FIXME: Add support for non-premultiplied alpha. + CCResourceProvider::ScopedReadLockSoftware quadResourceLock(m_resourceProvider, quad->resourceId()); + FloatRect uvRect = quad->uvRect(); + uvRect.scale(quad->quadRect().width(), quad->quadRect().height()); + SkIRect skUvRect = toSkIRect(enclosingIntRect(uvRect)); + if (quad->flipped()) + m_skCurrentCanvas->scale(1, -1); + m_skCurrentCanvas->drawBitmapRect(*quadResourceLock.skBitmap(), &skUvRect, toSkRect(quadVertexRect()), &m_skCurrentPaint); +} + +void CCRendererSoftware::drawTileQuad(const DrawingFrame& frame, const CCTileDrawQuad* quad) +{ + ASSERT(isSoftwareResource(quad->resourceId())); + CCResourceProvider::ScopedReadLockSoftware quadResourceLock(m_resourceProvider, quad->resourceId()); + + SkIRect uvRect = toSkIRect(IntRect(quad->textureOffset(), quad->quadRect().size())); + m_skCurrentCanvas->drawBitmapRect(*quadResourceLock.skBitmap(), &uvRect, toSkRect(quadVertexRect()), &m_skCurrentPaint); +} + +void CCRendererSoftware::drawUnsupportedQuad(const DrawingFrame& frame, const CCDrawQuad* quad) +{ + m_skCurrentPaint.setColor(SK_ColorMAGENTA); + m_skCurrentPaint.setAlpha(quad->opacity() * 255); + m_skCurrentCanvas->drawRect(toSkRect(quadVertexRect()), m_skCurrentPaint); +} + +bool CCRendererSoftware::swapBuffers() +{ + if (CCProxy::hasImplThread()) + m_client->onSwapBuffersComplete(); + return true; +} + +void CCRendererSoftware::getFramebufferPixels(void *pixels, const IntRect& rect) +{ + SkBitmap fullBitmap = m_outputDevice->lock(false)->getSkBitmap(); + SkBitmap subsetBitmap; + SkIRect invertRect = SkIRect::MakeXYWH(rect.x(), viewportSize().height() - rect.maxY(), rect.width(), rect.height()); + fullBitmap.extractSubset(&subsetBitmap, invertRect); + subsetBitmap.copyPixelsTo(pixels, rect.width() * rect.height() * 4, rect.width() * 4); + m_outputDevice->unlock(); +} + +void CCRendererSoftware::setVisible(bool visible) +{ + if (m_visible == visible) + return; + m_visible = visible; +} + +} diff --git a/cc/software_renderer.h b/cc/software_renderer.h index 638cbb2..2ad688f 100644 --- a/cc/software_renderer.h +++ b/cc/software_renderer.h @@ -1,3 +1,76 @@ // Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CCRendererSoftware_h +#define CCRendererSoftware_h + +#include "base/basictypes.h" +#include "CCDirectRenderer.h" +#include "CCLayerTreeHost.h" +#include + +namespace cc { + +class CCDebugBorderDrawQuad; +class CCRendererClient; +class CCResourceProvider; +class CCSolidColorDrawQuad; +class CCTextureDrawQuad; +class CCTileDrawQuad; + +class CCRendererSoftware : public CCDirectRenderer { +public: + static PassOwnPtr create(CCRendererClient*, CCResourceProvider*, WebKit::WebCompositorSoftwareOutputDevice*); + virtual ~CCRendererSoftware(); + + virtual const RendererCapabilities& capabilities() const OVERRIDE; + + virtual void viewportChanged() OVERRIDE; + + virtual void finish() OVERRIDE; + + virtual bool swapBuffers() OVERRIDE; + + virtual void getFramebufferPixels(void *pixels, const IntRect&) OVERRIDE; + + virtual void setVisible(bool) OVERRIDE; + +protected: + virtual void bindFramebufferToOutputSurface(DrawingFrame&) OVERRIDE; + virtual bool bindFramebufferToTexture(DrawingFrame&, const CCScopedTexture*, const IntRect& framebufferRect) OVERRIDE; + virtual void setDrawViewportSize(const IntSize&) OVERRIDE; + virtual void enableScissorTestRect(const IntRect& scissorRect) OVERRIDE; + virtual void disableScissorTest() OVERRIDE; + virtual void clearFramebuffer(DrawingFrame&) OVERRIDE; + virtual void drawQuad(DrawingFrame&, const CCDrawQuad*) OVERRIDE; + virtual void beginDrawingFrame(DrawingFrame&) OVERRIDE; + virtual void finishDrawingFrame(DrawingFrame&) OVERRIDE; + virtual bool flippedFramebuffer() const OVERRIDE; + +private: + CCRendererSoftware(CCRendererClient*, CCResourceProvider*, WebKit::WebCompositorSoftwareOutputDevice*); + + bool isSoftwareResource(CCResourceProvider::ResourceId) const; + + void drawDebugBorderQuad(const DrawingFrame&, const CCDebugBorderDrawQuad*); + void drawSolidColorQuad(const DrawingFrame&, const CCSolidColorDrawQuad*); + void drawTextureQuad(const DrawingFrame&, const CCTextureDrawQuad*); + void drawTileQuad(const DrawingFrame&, const CCTileDrawQuad*); + void drawUnsupportedQuad(const DrawingFrame&, const CCDrawQuad*); + + RendererCapabilities m_capabilities; + bool m_visible; + + WebKit::WebCompositorSoftwareOutputDevice* m_outputDevice; + OwnPtr m_skRootCanvas; + SkCanvas* m_skCurrentCanvas; + SkPaint m_skCurrentPaint; + OwnPtr m_currentFramebufferLock; + + DISALLOW_COPY_AND_ASSIGN(CCRendererSoftware); +}; + +} + +#endif diff --git a/cc/solid_color_draw_quad.cc b/cc/solid_color_draw_quad.cc new file mode 100644 index 0000000..157acd9 --- /dev/null +++ b/cc/solid_color_draw_quad.cc @@ -0,0 +1,32 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#include "CCSolidColorDrawQuad.h" + +namespace cc { + +scoped_ptr CCSolidColorDrawQuad::create(const CCSharedQuadState* sharedQuadState, const IntRect& quadRect, SkColor color) +{ + return make_scoped_ptr(new CCSolidColorDrawQuad(sharedQuadState, quadRect, color)); +} + +CCSolidColorDrawQuad::CCSolidColorDrawQuad(const CCSharedQuadState* sharedQuadState, const IntRect& quadRect, SkColor color) + : CCDrawQuad(sharedQuadState, CCDrawQuad::SolidColor, quadRect) + , m_color(color) +{ + if (SkColorGetA(m_color) < 255) + m_quadOpaque = false; + else + m_opaqueRect = quadRect; +} + +const CCSolidColorDrawQuad* CCSolidColorDrawQuad::materialCast(const CCDrawQuad* quad) +{ + ASSERT(quad->material() == CCDrawQuad::SolidColor); + return static_cast(quad); +} + +} // namespacec cc diff --git a/cc/solid_color_draw_quad.h b/cc/solid_color_draw_quad.h index 638cbb2..6825612 100644 --- a/cc/solid_color_draw_quad.h +++ b/cc/solid_color_draw_quad.h @@ -1,3 +1,33 @@ // Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CCSolidColorDrawQuad_h +#define CCSolidColorDrawQuad_h + +#include "CCDrawQuad.h" +#include "SkColor.h" +#include "base/memory/scoped_ptr.h" + +namespace cc { + +#pragma pack(push, 4) + +class CCSolidColorDrawQuad : public CCDrawQuad { +public: + static scoped_ptr create(const CCSharedQuadState*, const IntRect&, SkColor); + + SkColor color() const { return m_color; }; + + static const CCSolidColorDrawQuad* materialCast(const CCDrawQuad*); +private: + CCSolidColorDrawQuad(const CCSharedQuadState*, const IntRect&, SkColor); + + SkColor m_color; +}; + +#pragma pack(pop) + +} + +#endif diff --git a/cc/solid_color_layer.cc b/cc/solid_color_layer.cc new file mode 100644 index 0000000..d5c0b42 --- /dev/null +++ b/cc/solid_color_layer.cc @@ -0,0 +1,36 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#if USE(ACCELERATED_COMPOSITING) + +#include "SolidColorLayerChromium.h" + +#include "CCSolidColorLayerImpl.h" + +namespace cc { + +scoped_ptr SolidColorLayerChromium::createCCLayerImpl() +{ + return CCSolidColorLayerImpl::create(id()).PassAs(); +} + +scoped_refptr SolidColorLayerChromium::create() +{ + return make_scoped_refptr(new SolidColorLayerChromium()); +} + +SolidColorLayerChromium::SolidColorLayerChromium() + : LayerChromium() +{ +} + +SolidColorLayerChromium::~SolidColorLayerChromium() +{ +} + +} // namespace cc + +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/cc/solid_color_layer.h b/cc/solid_color_layer.h index 638cbb2..9123484 100644 --- a/cc/solid_color_layer.h +++ b/cc/solid_color_layer.h @@ -1,3 +1,33 @@ // Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + + +#ifndef SolidColorLayerChromium_h +#define SolidColorLayerChromium_h + +#if USE(ACCELERATED_COMPOSITING) + +#include "LayerChromium.h" + +namespace cc { + +// A Layer that renders a solid color. The color is specified by using +// setBackgroundColor() on the base class. +class SolidColorLayerChromium : public LayerChromium { +public: + static scoped_refptr create(); + + virtual scoped_ptr createCCLayerImpl() OVERRIDE; + +protected: + SolidColorLayerChromium(); + +private: + virtual ~SolidColorLayerChromium(); +}; + +} +#endif // USE(ACCELERATED_COMPOSITING) + +#endif diff --git a/cc/solid_color_layer_impl.cc b/cc/solid_color_layer_impl.cc new file mode 100644 index 0000000..abf8d48 --- /dev/null +++ b/cc/solid_color_layer_impl.cc @@ -0,0 +1,53 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#if USE(ACCELERATED_COMPOSITING) + +#include "CCSolidColorLayerImpl.h" + +#include "CCQuadSink.h" +#include "CCSolidColorDrawQuad.h" +#include + +using namespace std; +using WebKit::WebTransformationMatrix; + +namespace cc { + +CCSolidColorLayerImpl::CCSolidColorLayerImpl(int id) + : CCLayerImpl(id) + , m_tileSize(256) +{ +} + +CCSolidColorLayerImpl::~CCSolidColorLayerImpl() +{ +} + +void CCSolidColorLayerImpl::appendQuads(CCQuadSink& quadSink, CCAppendQuadsData& appendQuadsData) +{ + CCSharedQuadState* sharedQuadState = quadSink.useSharedQuadState(createSharedQuadState()); + appendDebugBorderQuad(quadSink, sharedQuadState, appendQuadsData); + + // We create a series of smaller quads instead of just one large one so that the + // culler can reduce the total pixels drawn. + int width = contentBounds().width(); + int height = contentBounds().height(); + for (int x = 0; x < width; x += m_tileSize) { + for (int y = 0; y < height; y += m_tileSize) { + IntRect solidTileRect(x, y, min(width - x, m_tileSize), min(height - y, m_tileSize)); + quadSink.append(CCSolidColorDrawQuad::create(sharedQuadState, solidTileRect, backgroundColor()).PassAs(), appendQuadsData); + } + } +} + +const char* CCSolidColorLayerImpl::layerTypeAsString() const +{ + return "SolidColorLayer"; +} + +} // namespace cc +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/cc/solid_color_layer_impl.h b/cc/solid_color_layer_impl.h index 638cbb2..72beb25 100644 --- a/cc/solid_color_layer_impl.h +++ b/cc/solid_color_layer_impl.h @@ -1,3 +1,34 @@ // Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CCSolidColorLayerImpl_h +#define CCSolidColorLayerImpl_h + +#include "CCLayerImpl.h" +#include + +namespace cc { + +class CCSolidColorLayerImpl : public CCLayerImpl { +public: + static scoped_ptr create(int id) + { + return make_scoped_ptr(new CCSolidColorLayerImpl(id)); + } + virtual ~CCSolidColorLayerImpl(); + + virtual void appendQuads(CCQuadSink&, CCAppendQuadsData&) OVERRIDE; + +protected: + explicit CCSolidColorLayerImpl(int id); + +private: + virtual const char* layerTypeAsString() const OVERRIDE; + + const int m_tileSize; +}; + +} + +#endif // CCSolidColorLayerImpl_h diff --git a/cc/stream_video_draw_quad.cc b/cc/stream_video_draw_quad.cc new file mode 100644 index 0000000..e92d98a --- /dev/null +++ b/cc/stream_video_draw_quad.cc @@ -0,0 +1,29 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#include "CCStreamVideoDrawQuad.h" + +namespace cc { + +scoped_ptr CCStreamVideoDrawQuad::create(const CCSharedQuadState* sharedQuadState, const IntRect& quadRect, unsigned textureId, const WebKit::WebTransformationMatrix& matrix) +{ + return make_scoped_ptr(new CCStreamVideoDrawQuad(sharedQuadState, quadRect, textureId, matrix)); +} + +CCStreamVideoDrawQuad::CCStreamVideoDrawQuad(const CCSharedQuadState* sharedQuadState, const IntRect& quadRect, unsigned textureId, const WebKit::WebTransformationMatrix& matrix) + : CCDrawQuad(sharedQuadState, CCDrawQuad::StreamVideoContent, quadRect) + , m_textureId(textureId) + , m_matrix(matrix) +{ +} + +const CCStreamVideoDrawQuad* CCStreamVideoDrawQuad::materialCast(const CCDrawQuad* quad) +{ + ASSERT(quad->material() == CCDrawQuad::StreamVideoContent); + return static_cast(quad); +} + +} // namespace cc diff --git a/cc/stream_video_draw_quad.h b/cc/stream_video_draw_quad.h index 638cbb2..6a1b6c4 100644 --- a/cc/stream_video_draw_quad.h +++ b/cc/stream_video_draw_quad.h @@ -1,3 +1,35 @@ // Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CCStreamVideoDrawQuad_h +#define CCStreamVideoDrawQuad_h + +#include "CCDrawQuad.h" +#include "base/memory/scoped_ptr.h" +#include + +namespace cc { + +#pragma pack(push, 4) + +class CCStreamVideoDrawQuad : public CCDrawQuad { +public: + static scoped_ptr create(const CCSharedQuadState*, const IntRect&, unsigned textureId, const WebKit::WebTransformationMatrix&); + + unsigned textureId() const { return m_textureId; } + const WebKit::WebTransformationMatrix& matrix() const { return m_matrix; } + + static const CCStreamVideoDrawQuad* materialCast(const CCDrawQuad*); +private: + CCStreamVideoDrawQuad(const CCSharedQuadState*, const IntRect&, unsigned textureId, const WebKit::WebTransformationMatrix&); + + unsigned m_textureId; + WebKit::WebTransformationMatrix m_matrix; +}; + +#pragma pack(pop) + +} + +#endif diff --git a/cc/stubs/Extensions3D.h b/cc/stubs/Extensions3D.h index bbeb9e6..77f010e 100644 --- a/cc/stubs/Extensions3D.h +++ b/cc/stubs/Extensions3D.h @@ -1,25 +1,6 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CC_STUBS_EXTENSIONS3D_H_ -#define CC_STUBS_EXTENSIONS3D_H_ - -#include "third_party/khronos/GLES2/gl2.h" -#include "third_party/khronos/GLES2/gl2ext.h" - -namespace cc { - -class Extensions3D { -public: - enum { - TEXTURE_RECTANGLE_ARB = GL_TEXTURE_RECTANGLE_ARB, - BGRA_EXT = GL_BGRA_EXT, - RGBA8_OES = GL_RGBA8_OES, - }; -}; - -} - - -#endif // CC_STUBS_EXTENSIONS3D_H_ +// Temporary forwarding header +#include "cc/stubs/extensions_3d.h" diff --git a/cc/stubs/Extensions3DChromium.h b/cc/stubs/Extensions3DChromium.h index f5d36d2..f3c6fa9 100644 --- a/cc/stubs/Extensions3DChromium.h +++ b/cc/stubs/Extensions3DChromium.h @@ -1,54 +1,6 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CC_STUBS_EXTENSIONS3DCHROMIUM_H_ -#define CC_STUBS_EXTENSIONS3DCHROMIUM_H_ - -#include "Extensions3D.h" - -// These enum names collides with gl2ext.h, so we just redefine them. -#ifdef GL_TEXTURE_EXTERNAL_OES -#undef GL_TEXTURE_EXTERNAL_OES -#endif -#ifdef GL_TEXTURE_USAGE_ANGLE -#undef GL_TEXTURE_USAGE_ANGLE -#endif -#ifdef GL_FRAMEBUFFER_ATTACHMENT_ANGLE -#undef GL_FRAMEBUFFER_ATTACHMENT_ANGLE -#endif - -namespace cc { - -class Extensions3DChromium { -public: - enum { - // GL_OES_EGL_image_external - GL_TEXTURE_EXTERNAL_OES = 0x8D65, - - // GL_CHROMIUM_map_sub (enums inherited from GL_ARB_vertex_buffer_object) - READ_ONLY = 0x88B8, - WRITE_ONLY = 0x88B9, - - // GL_ANGLE_texture_usage - GL_TEXTURE_USAGE_ANGLE = 0x93A2, - GL_FRAMEBUFFER_ATTACHMENT_ANGLE = 0x93A3, - - // GL_EXT_texture_storage - BGRA8_EXT = 0x93A1, - - // GL_EXT_occlusion_query_boolean - ANY_SAMPLES_PASSED_EXT = 0x8C2F, - ANY_SAMPLES_PASSED_CONSERVATIVE_EXT = 0x8D6A, - CURRENT_QUERY_EXT = 0x8865, - QUERY_RESULT_EXT = 0x8866, - QUERY_RESULT_AVAILABLE_EXT = 0x8867, - - // GL_CHROMIUM_command_buffer_query - COMMANDS_ISSUED_CHROMIUM = 0x84F2 - }; -}; - -} - -#endif // CC_STUBS_EXTENSIONS3DCHROMIUM_H_ +// Temporary forwarding header +#include "cc/stubs/extensions_3d_chromium.h" diff --git a/cc/stubs/FloatPoint.h b/cc/stubs/FloatPoint.h index 4ce2681..df1fe9f 100644 --- a/cc/stubs/FloatPoint.h +++ b/cc/stubs/FloatPoint.h @@ -1,51 +1,6 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CC_STUBS_FLOATPOINT_H_ -#define CC_STUBS_FLOATPOINT_H_ - -#include "FloatSize.h" -#include "IntPoint.h" -#if INSIDE_WEBKIT_BUILD -#include "Source/WebCore/platform/graphics/FloatPoint.h" -#else -#include "third_party/WebKit/Source/WebCore/platform/graphics/FloatPoint.h" -#endif - -namespace cc { - -class FloatPoint : public WebCore::FloatPoint { -public: - FloatPoint() { } - - FloatPoint(float width, float height) - : WebCore::FloatPoint(width, height) - { - } - - FloatPoint(FloatSize size) - : WebCore::FloatPoint(size) - { - } - - FloatPoint(IntPoint point) - : WebCore::FloatPoint(point) - { - } - - FloatPoint(WebCore::IntPoint point) - : WebCore::FloatPoint(point) - { - } - - FloatPoint(WebCore::FloatPoint point) - : WebCore::FloatPoint(point.x(), point.y()) - { - - } -}; - -} - -#endif +// Temporary forwarding header +#include "cc/stubs/float_point.h" diff --git a/cc/stubs/FloatPoint3D.h b/cc/stubs/FloatPoint3D.h index 02ff076..3d5f90c 100644 --- a/cc/stubs/FloatPoint3D.h +++ b/cc/stubs/FloatPoint3D.h @@ -1,50 +1,6 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CC_STUBS_FLOATPOINT3D_H_ -#define CC_STUBS_FLOATPOINT3D_H_ - -#include "FloatPoint.h" - -#if INSIDE_WEBKIT_BUILD -#include "Source/WebCore/platform/graphics/FloatPoint3D.h" -#else -#include "third_party/WebKit/Source/WebCore/platform/graphics/FloatPoint3D.h" -#endif - -namespace cc { - -class FloatPoint3D : public WebCore::FloatPoint3D { -public: - FloatPoint3D() { } - - FloatPoint3D(float x, float y, float z) - : WebCore::FloatPoint3D(x, y, z) - { - } - - FloatPoint3D(FloatPoint point) - : WebCore::FloatPoint3D(point.x(), point.y(), 0) - { - } - - FloatPoint3D(const FloatPoint3D& point) - : WebCore::FloatPoint3D(point) - { - } - - FloatPoint3D(WebCore::FloatPoint3D point) - : WebCore::FloatPoint3D(point) - { - } - - FloatPoint3D(WebCore::FloatPoint point) - : WebCore::FloatPoint3D(point) - { - } -}; - -} - -#endif +// Temporary forwarding header +#include "cc/stubs/float_point_3d.h" diff --git a/cc/stubs/FloatQuad.h b/cc/stubs/FloatQuad.h index f2f45ed..4495a84 100644 --- a/cc/stubs/FloatQuad.h +++ b/cc/stubs/FloatQuad.h @@ -1,56 +1,6 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CC_STUBS_FLOATQUAD_H_ -#define CC_STUBS_FLOATQUAD_H_ - -#include "FloatPoint.h" -#include "FloatRect.h" -#if INSIDE_WEBKIT_BUILD -#include "Source/WebCore/platform/graphics/FloatQuad.h" -#else -#include "third_party/WebKit/Source/WebCore/platform/graphics/FloatQuad.h" -#endif - -namespace cc { - -class FloatQuad : public WebCore::FloatQuad -{ -public: - FloatQuad() { } - - FloatQuad(const FloatPoint& p1, const FloatPoint& p2, const FloatPoint& p3, const FloatPoint& p4) - : WebCore::FloatQuad(p1, p2, p3, p4) - { - } - - FloatQuad(const FloatRect& rect) - : WebCore::FloatQuad(rect) - { - } - - FloatQuad(const IntRect& rect) - : WebCore::FloatQuad(rect) - { - } - - FloatQuad(const WebCore::FloatRect& rect) - : WebCore::FloatQuad(rect) - { - } - - FloatQuad(const WebCore::IntRect& rect) - : WebCore::FloatQuad(rect) - { - } - - FloatQuad(const WebCore::FloatQuad& quad) - : WebCore::FloatQuad(quad) - { - } -}; - -} - -#endif +// Temporary forwarding header +#include "cc/stubs/float_quad.h" diff --git a/cc/stubs/FloatRect.h b/cc/stubs/FloatRect.h index 2eb03e2..1957e86 100644 --- a/cc/stubs/FloatRect.h +++ b/cc/stubs/FloatRect.h @@ -1,56 +1,6 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CC_STUBS_FLOATRECT_H_ -#define CC_STUBS_FLOATRECT_H_ - -#include "FloatPoint.h" -#include "FloatSize.h" -#include "IntRect.h" -#if INSIDE_WEBKIT_BUILD -#include "Source/WebCore/platform/graphics/FloatRect.h" -#else -#include "third_party/WebKit/Source/WebCore/platform/graphics/FloatRect.h" -#endif - -namespace cc { - -class FloatRect : public WebCore::FloatRect { -public: - FloatRect() { } - - FloatRect(const FloatPoint& location, const FloatSize& size) - : WebCore::FloatRect(location, size) - { - } - - FloatRect(const IntPoint& location, const IntSize& size) - : WebCore::FloatRect(location, size) - { - } - - FloatRect(float x, float y, float width, float height) - : WebCore::FloatRect(x, y, width, height) - { - } - - FloatRect(const IntRect& rect) - : WebCore::FloatRect(rect) - { - } - - FloatRect(const WebCore::IntRect& rect) - : WebCore::FloatRect(rect) - { - } - - FloatRect(const WebCore::FloatRect& rect) - :WebCore::FloatRect(rect) - { - } -}; - -} - -#endif +// Temporary forwarding header +#include "cc/stubs/float_rect.h" diff --git a/cc/stubs/FloatSize.h b/cc/stubs/FloatSize.h index 9db5978..f5d5c4e 100644 --- a/cc/stubs/FloatSize.h +++ b/cc/stubs/FloatSize.h @@ -1,43 +1,6 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CC_STUBS_FLOATSIZE_H_ -#define CC_STUBS_FLOATSIZE_H_ - -#include "IntSize.h" -#if INSIDE_WEBKIT_BUILD -#include "Source/WebCore/platform/graphics/FloatSize.h" -#else -#include "third_party/WebKit/Source/WebCore/platform/graphics/FloatSize.h" -#endif - -namespace cc { -class FloatSize : public WebCore::FloatSize { -public: - FloatSize() { } - - FloatSize(float width, float height) - : WebCore::FloatSize(width, height) - { - } - - FloatSize(IntSize size) - : WebCore::FloatSize(size.width(), size.height()) - { - } - - FloatSize(WebCore::FloatSize size) - : WebCore::FloatSize(size.width(), size.height()) - { - } - - FloatSize(WebCore::IntSize size) - : WebCore::FloatSize(size.width(), size.height()) - { - } -}; - -} - -#endif +// Temporary forwarding header +#include "cc/stubs/float_size.h" diff --git a/cc/stubs/GraphicsContext3D.h b/cc/stubs/GraphicsContext3D.h index e7f7a60..3460a30 100644 --- a/cc/stubs/GraphicsContext3D.h +++ b/cc/stubs/GraphicsContext3D.h @@ -1,74 +1,6 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CC_STUBS_GRAPHICSCONTEXT3D_H_ -#define CC_STUBS_GRAPHICSCONTEXT3D_H_ - -#include "GraphicsTypes3D.h" -#include "IntSize.h" -#include "third_party/khronos/GLES2/gl2.h" - -#ifdef NO_ERROR -#undef NO_ERROR -#endif - -namespace cc { - -class GraphicsContext3D { -public: - enum SourceDataFormat { SourceFormatRGBA8, SourceFormatBGRA8 }; - static bool computeFormatAndTypeParameters(unsigned, unsigned, unsigned* componentsPerPixel, unsigned* bytesPerComponent); - - enum { - ARRAY_BUFFER = GL_ARRAY_BUFFER, - BLEND = GL_BLEND, - CLAMP_TO_EDGE = GL_CLAMP_TO_EDGE, - COLOR_ATTACHMENT0 = GL_COLOR_ATTACHMENT0, - COLOR_BUFFER_BIT = GL_COLOR_BUFFER_BIT, - COMPILE_STATUS = GL_COMPILE_STATUS, - CULL_FACE = GL_CULL_FACE, - DEPTH_TEST = GL_DEPTH_TEST, - ELEMENT_ARRAY_BUFFER = GL_ELEMENT_ARRAY_BUFFER, - EXTENSIONS = GL_EXTENSIONS, - FLOAT = GL_FLOAT, - FRAGMENT_SHADER = GL_FRAGMENT_SHADER, - FRAMEBUFFER_COMPLETE = GL_FRAMEBUFFER_COMPLETE, - FRAMEBUFFER = GL_FRAMEBUFFER, - INVALID_ENUM = GL_INVALID_ENUM, - INVALID_VALUE = GL_INVALID_VALUE, - LINEAR = GL_LINEAR, - LINE_LOOP = GL_LINE_LOOP , - LINK_STATUS = GL_LINK_STATUS, - LUMINANCE = GL_LUMINANCE, - MAX_TEXTURE_SIZE = GL_MAX_TEXTURE_SIZE, - NEAREST = GL_NEAREST, - NO_ERROR = GL_NO_ERROR, - ONE = GL_ONE, - ONE_MINUS_SRC_ALPHA = GL_ONE_MINUS_SRC_ALPHA, - RGBA = GL_RGBA, - RGB = GL_RGB, - SCISSOR_TEST = GL_SCISSOR_TEST, - SRC_ALPHA = GL_SRC_ALPHA, - STATIC_DRAW = GL_STATIC_DRAW, - TEXTURE0 = GL_TEXTURE0, - TEXTURE1 = GL_TEXTURE1, - TEXTURE_2D = GL_TEXTURE_2D, - TEXTURE2 = GL_TEXTURE2, - TEXTURE3 = GL_TEXTURE3, - TEXTURE_MAG_FILTER = GL_TEXTURE_MAG_FILTER, - TEXTURE_MIN_FILTER = GL_TEXTURE_MIN_FILTER, - TEXTURE_WRAP_S = GL_TEXTURE_WRAP_S, - TEXTURE_WRAP_T = GL_TEXTURE_WRAP_T, - TRIANGLES = GL_TRIANGLES, - TRIANGLE_FAN = GL_TRIANGLE_FAN, - UNSIGNED_BYTE = GL_UNSIGNED_BYTE, - UNSIGNED_SHORT = GL_UNSIGNED_SHORT, - VERTEX_SHADER = GL_VERTEX_SHADER, - ZERO = GL_ZERO, - }; -}; - -} - -#endif // CC_STUBS_GRAPHICSCONTEXT3D_H_ +// Temporary forwarding header +#include "cc/stubs/graphics_context_3d.h" diff --git a/cc/stubs/GraphicsTypes3D.h b/cc/stubs/GraphicsTypes3D.h index a01414e..8d08bb3 100644 --- a/cc/stubs/GraphicsTypes3D.h +++ b/cc/stubs/GraphicsTypes3D.h @@ -1,18 +1,6 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CC_STUBS_GRAPHICSTYPES3D_H_ -#define CC_STUBS_GRAPHICSTYPES3D_H_ - -#define NullPlatform3DObject 0 - -typedef unsigned char GC3Dboolean; -typedef unsigned GC3Denum; -typedef unsigned GC3Duint; -typedef unsigned Platform3DObject; -typedef int GC3Dint; -typedef signed char GC3Dbyte; - -#endif // CC_STUBS_GRAPHICSTYPES3D_H_ - +// Temporary forwarding header +#include "cc/stubs/graphics_types_3d.h" diff --git a/cc/stubs/IntPoint.h b/cc/stubs/IntPoint.h index fa12dea..d996ea8 100644 --- a/cc/stubs/IntPoint.h +++ b/cc/stubs/IntPoint.h @@ -1,40 +1,6 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CC_STUBS_INTPOINT_H_ -#define CC_STUBS_INTPOINT_H_ - -#include "IntSize.h" -#if INSIDE_WEBKIT_BUILD -#include "Source/WebCore/platform/graphics/IntPoint.h" -#else -#include "third_party/WebKit/Source/WebCore/platform/graphics/IntPoint.h" -#endif - -namespace cc { - -class IntPoint : public WebCore::IntPoint { -public: - IntPoint() { } - - IntPoint(int width, int height) - : WebCore::IntPoint(width, height) - { - } - - IntPoint(IntSize size) - : WebCore::IntPoint(size.width(), size.height()) - { - } - - IntPoint(WebCore::IntPoint point) - : WebCore::IntPoint(point.x(), point.y()) - { - - } -}; - -} - -#endif +// Temporary forwarding header +#include "cc/stubs/int_point.h" diff --git a/cc/stubs/IntRect.h b/cc/stubs/IntRect.h index 1599967..1d136ed 100644 --- a/cc/stubs/IntRect.h +++ b/cc/stubs/IntRect.h @@ -1,41 +1,6 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CC_STUBS_INTRECT_H_ -#define CC_STUBS_INTRECT_H_ - -#include "IntPoint.h" -#include "IntSize.h" -#if INSIDE_WEBKIT_BUILD -#include "Source/WebCore/platform/graphics/IntRect.h" -#else -#include "third_party/WebKit/Source/WebCore/platform/graphics/IntRect.h" -#endif - -namespace cc { - -class IntRect : public WebCore::IntRect { -public: - IntRect() { } - - IntRect(const IntPoint& location, const IntSize& size) - : WebCore::IntRect(location, size) - { - } - - IntRect(int x, int y, int width, int height) - : WebCore::IntRect(x, y, width, height) - { - } - - IntRect(WebCore::IntRect rect) - : WebCore::IntRect(rect.x(), rect.y(), rect.width(), rect.height()) - { - - } -}; - -} - -#endif +// Temporary forwarding header +#include "cc/stubs/int_rect.h" diff --git a/cc/stubs/IntSize.h b/cc/stubs/IntSize.h index c53f4f1..4508c69 100644 --- a/cc/stubs/IntSize.h +++ b/cc/stubs/IntSize.h @@ -1,34 +1,6 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CC_STUBS_INTSIZE_H_ -#define CC_STUBS_INTSIZE_H_ - -#if INSIDE_WEBKIT_BUILD -#include "Source/WebCore/platform/graphics/IntSize.h" -#else -#include "third_party/WebKit/Source/WebCore/platform/graphics/IntSize.h" -#endif - -namespace cc { - -class IntSize : public WebCore::IntSize { -public: - IntSize() { } - - IntSize(int width, int height) - : WebCore::IntSize(width, height) - { - } - - IntSize(WebCore::IntSize size) - : WebCore::IntSize(size.width(), size.height()) - { - - } -}; - -} - -#endif +// Temporary forwarding header +#include "cc/stubs/int_size.h" diff --git a/cc/stubs/NotImplemented.h b/cc/stubs/NotImplemented.h index 7c6bba5..4ac19a5 100644 --- a/cc/stubs/NotImplemented.h +++ b/cc/stubs/NotImplemented.h @@ -1,10 +1,6 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CC_STUBS_NOTIMPLEMENTED_H -#define CC_STUBS_NOTIMPLEMENTED_H - -#define notImplemented() do { } while(0) - -#endif // CC_STUBS_NOTIMPLEMENTED_H +// Temporary forwarding header +#include "cc/stubs/not_implemented.h" diff --git a/cc/stubs/SkiaUtils.h b/cc/stubs/SkiaUtils.h index fb81f3e..c3bbf89 100644 --- a/cc/stubs/SkiaUtils.h +++ b/cc/stubs/SkiaUtils.h @@ -1,17 +1,6 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CC_STUBS_SKIAUTILS_H_ -#define CC_STUBS_SKIAUTILS_H_ - -namespace cc { - -inline SkScalar CCFloatToSkScalar(float f) -{ - return SkFloatToScalar(isfinite(f) ? f : 0); -} - -} - -#endif // CC_STUBS_SKIAUTILS_H_ +// Temporary forwarding header +#include "cc/stubs/skia_utils.h" diff --git a/cc/stubs/TilingData.h b/cc/stubs/TilingData.h index 0221500..e6507e3 100644 --- a/cc/stubs/TilingData.h +++ b/cc/stubs/TilingData.h @@ -1,18 +1,6 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CC_STUBS_TILINGDATA_H_ -#define CC_STUBS_TILINGDATA_H_ - -#if INSIDE_WEBKIT_BUILD -#include "Source/WebCore/platform/graphics/gpu/TilingData.h" -#else -#include "third_party/WebKit/Source/WebCore/platform/graphics/gpu/TilingData.h" -#endif - -namespace cc { - typedef WebCore::TilingData TilingData; -} - -#endif // CC_STUBS_TILINGDATA_H_ +// Temporary forwarding header +#include "cc/stubs/tiling_data.h" diff --git a/cc/stubs/TraceEvent.h b/cc/stubs/TraceEvent.h index 75587a3..27e4089 100644 --- a/cc/stubs/TraceEvent.h +++ b/cc/stubs/TraceEvent.h @@ -1,10 +1,6 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Chromium's LOG() macro collides with one from WTF. -#ifdef LOG -#undef LOG -#endif - -#include "base/debug/trace_event.h" +// Temporary forwarding header +#include "cc/stubs/trace_event.h" diff --git a/cc/stubs/UnitBezier.h b/cc/stubs/UnitBezier.h index 1ff5da9..d6a792d 100644 --- a/cc/stubs/UnitBezier.h +++ b/cc/stubs/UnitBezier.h @@ -1,14 +1,6 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// TODO(jamesr): Remove or refactor this dependency. -#if INSIDE_WEBKIT_BUILD -#include "Source/WebCore/platform/graphics/UnitBezier.h" -#else -#include "third_party/WebKit/Source/WebCore/platform/graphics/UnitBezier.h" -#endif - -namespace cc { -typedef WebCore::UnitBezier UnitBezier; -} +// Temporary forwarding header +#include "cc/stubs/unit_bezier.h" diff --git a/cc/stubs/extensions_3d.h b/cc/stubs/extensions_3d.h index 638cbb2..bbeb9e6 100644 --- a/cc/stubs/extensions_3d.h +++ b/cc/stubs/extensions_3d.h @@ -1,3 +1,25 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CC_STUBS_EXTENSIONS3D_H_ +#define CC_STUBS_EXTENSIONS3D_H_ + +#include "third_party/khronos/GLES2/gl2.h" +#include "third_party/khronos/GLES2/gl2ext.h" + +namespace cc { + +class Extensions3D { +public: + enum { + TEXTURE_RECTANGLE_ARB = GL_TEXTURE_RECTANGLE_ARB, + BGRA_EXT = GL_BGRA_EXT, + RGBA8_OES = GL_RGBA8_OES, + }; +}; + +} + + +#endif // CC_STUBS_EXTENSIONS3D_H_ diff --git a/cc/stubs/extensions_3d_chromium.h b/cc/stubs/extensions_3d_chromium.h index 638cbb2..f5d36d2 100644 --- a/cc/stubs/extensions_3d_chromium.h +++ b/cc/stubs/extensions_3d_chromium.h @@ -1,3 +1,54 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CC_STUBS_EXTENSIONS3DCHROMIUM_H_ +#define CC_STUBS_EXTENSIONS3DCHROMIUM_H_ + +#include "Extensions3D.h" + +// These enum names collides with gl2ext.h, so we just redefine them. +#ifdef GL_TEXTURE_EXTERNAL_OES +#undef GL_TEXTURE_EXTERNAL_OES +#endif +#ifdef GL_TEXTURE_USAGE_ANGLE +#undef GL_TEXTURE_USAGE_ANGLE +#endif +#ifdef GL_FRAMEBUFFER_ATTACHMENT_ANGLE +#undef GL_FRAMEBUFFER_ATTACHMENT_ANGLE +#endif + +namespace cc { + +class Extensions3DChromium { +public: + enum { + // GL_OES_EGL_image_external + GL_TEXTURE_EXTERNAL_OES = 0x8D65, + + // GL_CHROMIUM_map_sub (enums inherited from GL_ARB_vertex_buffer_object) + READ_ONLY = 0x88B8, + WRITE_ONLY = 0x88B9, + + // GL_ANGLE_texture_usage + GL_TEXTURE_USAGE_ANGLE = 0x93A2, + GL_FRAMEBUFFER_ATTACHMENT_ANGLE = 0x93A3, + + // GL_EXT_texture_storage + BGRA8_EXT = 0x93A1, + + // GL_EXT_occlusion_query_boolean + ANY_SAMPLES_PASSED_EXT = 0x8C2F, + ANY_SAMPLES_PASSED_CONSERVATIVE_EXT = 0x8D6A, + CURRENT_QUERY_EXT = 0x8865, + QUERY_RESULT_EXT = 0x8866, + QUERY_RESULT_AVAILABLE_EXT = 0x8867, + + // GL_CHROMIUM_command_buffer_query + COMMANDS_ISSUED_CHROMIUM = 0x84F2 + }; +}; + +} + +#endif // CC_STUBS_EXTENSIONS3DCHROMIUM_H_ diff --git a/cc/stubs/float_point.h b/cc/stubs/float_point.h index 638cbb2..4ce2681 100644 --- a/cc/stubs/float_point.h +++ b/cc/stubs/float_point.h @@ -1,3 +1,51 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CC_STUBS_FLOATPOINT_H_ +#define CC_STUBS_FLOATPOINT_H_ + +#include "FloatSize.h" +#include "IntPoint.h" +#if INSIDE_WEBKIT_BUILD +#include "Source/WebCore/platform/graphics/FloatPoint.h" +#else +#include "third_party/WebKit/Source/WebCore/platform/graphics/FloatPoint.h" +#endif + +namespace cc { + +class FloatPoint : public WebCore::FloatPoint { +public: + FloatPoint() { } + + FloatPoint(float width, float height) + : WebCore::FloatPoint(width, height) + { + } + + FloatPoint(FloatSize size) + : WebCore::FloatPoint(size) + { + } + + FloatPoint(IntPoint point) + : WebCore::FloatPoint(point) + { + } + + FloatPoint(WebCore::IntPoint point) + : WebCore::FloatPoint(point) + { + } + + FloatPoint(WebCore::FloatPoint point) + : WebCore::FloatPoint(point.x(), point.y()) + { + + } +}; + +} + +#endif diff --git a/cc/stubs/float_point_3d.h b/cc/stubs/float_point_3d.h index 638cbb2..02ff076 100644 --- a/cc/stubs/float_point_3d.h +++ b/cc/stubs/float_point_3d.h @@ -1,3 +1,50 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CC_STUBS_FLOATPOINT3D_H_ +#define CC_STUBS_FLOATPOINT3D_H_ + +#include "FloatPoint.h" + +#if INSIDE_WEBKIT_BUILD +#include "Source/WebCore/platform/graphics/FloatPoint3D.h" +#else +#include "third_party/WebKit/Source/WebCore/platform/graphics/FloatPoint3D.h" +#endif + +namespace cc { + +class FloatPoint3D : public WebCore::FloatPoint3D { +public: + FloatPoint3D() { } + + FloatPoint3D(float x, float y, float z) + : WebCore::FloatPoint3D(x, y, z) + { + } + + FloatPoint3D(FloatPoint point) + : WebCore::FloatPoint3D(point.x(), point.y(), 0) + { + } + + FloatPoint3D(const FloatPoint3D& point) + : WebCore::FloatPoint3D(point) + { + } + + FloatPoint3D(WebCore::FloatPoint3D point) + : WebCore::FloatPoint3D(point) + { + } + + FloatPoint3D(WebCore::FloatPoint point) + : WebCore::FloatPoint3D(point) + { + } +}; + +} + +#endif diff --git a/cc/stubs/float_quad.h b/cc/stubs/float_quad.h index 638cbb2..f2f45ed 100644 --- a/cc/stubs/float_quad.h +++ b/cc/stubs/float_quad.h @@ -1,3 +1,56 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CC_STUBS_FLOATQUAD_H_ +#define CC_STUBS_FLOATQUAD_H_ + +#include "FloatPoint.h" +#include "FloatRect.h" +#if INSIDE_WEBKIT_BUILD +#include "Source/WebCore/platform/graphics/FloatQuad.h" +#else +#include "third_party/WebKit/Source/WebCore/platform/graphics/FloatQuad.h" +#endif + +namespace cc { + +class FloatQuad : public WebCore::FloatQuad +{ +public: + FloatQuad() { } + + FloatQuad(const FloatPoint& p1, const FloatPoint& p2, const FloatPoint& p3, const FloatPoint& p4) + : WebCore::FloatQuad(p1, p2, p3, p4) + { + } + + FloatQuad(const FloatRect& rect) + : WebCore::FloatQuad(rect) + { + } + + FloatQuad(const IntRect& rect) + : WebCore::FloatQuad(rect) + { + } + + FloatQuad(const WebCore::FloatRect& rect) + : WebCore::FloatQuad(rect) + { + } + + FloatQuad(const WebCore::IntRect& rect) + : WebCore::FloatQuad(rect) + { + } + + FloatQuad(const WebCore::FloatQuad& quad) + : WebCore::FloatQuad(quad) + { + } +}; + +} + +#endif diff --git a/cc/stubs/float_rect.h b/cc/stubs/float_rect.h index 638cbb2..2eb03e2 100644 --- a/cc/stubs/float_rect.h +++ b/cc/stubs/float_rect.h @@ -1,3 +1,56 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CC_STUBS_FLOATRECT_H_ +#define CC_STUBS_FLOATRECT_H_ + +#include "FloatPoint.h" +#include "FloatSize.h" +#include "IntRect.h" +#if INSIDE_WEBKIT_BUILD +#include "Source/WebCore/platform/graphics/FloatRect.h" +#else +#include "third_party/WebKit/Source/WebCore/platform/graphics/FloatRect.h" +#endif + +namespace cc { + +class FloatRect : public WebCore::FloatRect { +public: + FloatRect() { } + + FloatRect(const FloatPoint& location, const FloatSize& size) + : WebCore::FloatRect(location, size) + { + } + + FloatRect(const IntPoint& location, const IntSize& size) + : WebCore::FloatRect(location, size) + { + } + + FloatRect(float x, float y, float width, float height) + : WebCore::FloatRect(x, y, width, height) + { + } + + FloatRect(const IntRect& rect) + : WebCore::FloatRect(rect) + { + } + + FloatRect(const WebCore::IntRect& rect) + : WebCore::FloatRect(rect) + { + } + + FloatRect(const WebCore::FloatRect& rect) + :WebCore::FloatRect(rect) + { + } +}; + +} + +#endif diff --git a/cc/stubs/float_size.h b/cc/stubs/float_size.h index 638cbb2..9db5978 100644 --- a/cc/stubs/float_size.h +++ b/cc/stubs/float_size.h @@ -1,3 +1,43 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CC_STUBS_FLOATSIZE_H_ +#define CC_STUBS_FLOATSIZE_H_ + +#include "IntSize.h" +#if INSIDE_WEBKIT_BUILD +#include "Source/WebCore/platform/graphics/FloatSize.h" +#else +#include "third_party/WebKit/Source/WebCore/platform/graphics/FloatSize.h" +#endif + +namespace cc { +class FloatSize : public WebCore::FloatSize { +public: + FloatSize() { } + + FloatSize(float width, float height) + : WebCore::FloatSize(width, height) + { + } + + FloatSize(IntSize size) + : WebCore::FloatSize(size.width(), size.height()) + { + } + + FloatSize(WebCore::FloatSize size) + : WebCore::FloatSize(size.width(), size.height()) + { + } + + FloatSize(WebCore::IntSize size) + : WebCore::FloatSize(size.width(), size.height()) + { + } +}; + +} + +#endif diff --git a/cc/stubs/graphics_context_3d.h b/cc/stubs/graphics_context_3d.h index 638cbb2..e7f7a60 100644 --- a/cc/stubs/graphics_context_3d.h +++ b/cc/stubs/graphics_context_3d.h @@ -1,3 +1,74 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CC_STUBS_GRAPHICSCONTEXT3D_H_ +#define CC_STUBS_GRAPHICSCONTEXT3D_H_ + +#include "GraphicsTypes3D.h" +#include "IntSize.h" +#include "third_party/khronos/GLES2/gl2.h" + +#ifdef NO_ERROR +#undef NO_ERROR +#endif + +namespace cc { + +class GraphicsContext3D { +public: + enum SourceDataFormat { SourceFormatRGBA8, SourceFormatBGRA8 }; + static bool computeFormatAndTypeParameters(unsigned, unsigned, unsigned* componentsPerPixel, unsigned* bytesPerComponent); + + enum { + ARRAY_BUFFER = GL_ARRAY_BUFFER, + BLEND = GL_BLEND, + CLAMP_TO_EDGE = GL_CLAMP_TO_EDGE, + COLOR_ATTACHMENT0 = GL_COLOR_ATTACHMENT0, + COLOR_BUFFER_BIT = GL_COLOR_BUFFER_BIT, + COMPILE_STATUS = GL_COMPILE_STATUS, + CULL_FACE = GL_CULL_FACE, + DEPTH_TEST = GL_DEPTH_TEST, + ELEMENT_ARRAY_BUFFER = GL_ELEMENT_ARRAY_BUFFER, + EXTENSIONS = GL_EXTENSIONS, + FLOAT = GL_FLOAT, + FRAGMENT_SHADER = GL_FRAGMENT_SHADER, + FRAMEBUFFER_COMPLETE = GL_FRAMEBUFFER_COMPLETE, + FRAMEBUFFER = GL_FRAMEBUFFER, + INVALID_ENUM = GL_INVALID_ENUM, + INVALID_VALUE = GL_INVALID_VALUE, + LINEAR = GL_LINEAR, + LINE_LOOP = GL_LINE_LOOP , + LINK_STATUS = GL_LINK_STATUS, + LUMINANCE = GL_LUMINANCE, + MAX_TEXTURE_SIZE = GL_MAX_TEXTURE_SIZE, + NEAREST = GL_NEAREST, + NO_ERROR = GL_NO_ERROR, + ONE = GL_ONE, + ONE_MINUS_SRC_ALPHA = GL_ONE_MINUS_SRC_ALPHA, + RGBA = GL_RGBA, + RGB = GL_RGB, + SCISSOR_TEST = GL_SCISSOR_TEST, + SRC_ALPHA = GL_SRC_ALPHA, + STATIC_DRAW = GL_STATIC_DRAW, + TEXTURE0 = GL_TEXTURE0, + TEXTURE1 = GL_TEXTURE1, + TEXTURE_2D = GL_TEXTURE_2D, + TEXTURE2 = GL_TEXTURE2, + TEXTURE3 = GL_TEXTURE3, + TEXTURE_MAG_FILTER = GL_TEXTURE_MAG_FILTER, + TEXTURE_MIN_FILTER = GL_TEXTURE_MIN_FILTER, + TEXTURE_WRAP_S = GL_TEXTURE_WRAP_S, + TEXTURE_WRAP_T = GL_TEXTURE_WRAP_T, + TRIANGLES = GL_TRIANGLES, + TRIANGLE_FAN = GL_TRIANGLE_FAN, + UNSIGNED_BYTE = GL_UNSIGNED_BYTE, + UNSIGNED_SHORT = GL_UNSIGNED_SHORT, + VERTEX_SHADER = GL_VERTEX_SHADER, + ZERO = GL_ZERO, + }; +}; + +} + +#endif // CC_STUBS_GRAPHICSCONTEXT3D_H_ diff --git a/cc/stubs/graphics_types_3d.h b/cc/stubs/graphics_types_3d.h index 638cbb2..a01414e 100644 --- a/cc/stubs/graphics_types_3d.h +++ b/cc/stubs/graphics_types_3d.h @@ -1,3 +1,18 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CC_STUBS_GRAPHICSTYPES3D_H_ +#define CC_STUBS_GRAPHICSTYPES3D_H_ + +#define NullPlatform3DObject 0 + +typedef unsigned char GC3Dboolean; +typedef unsigned GC3Denum; +typedef unsigned GC3Duint; +typedef unsigned Platform3DObject; +typedef int GC3Dint; +typedef signed char GC3Dbyte; + +#endif // CC_STUBS_GRAPHICSTYPES3D_H_ + diff --git a/cc/stubs/int_point.h b/cc/stubs/int_point.h index 638cbb2..fa12dea 100644 --- a/cc/stubs/int_point.h +++ b/cc/stubs/int_point.h @@ -1,3 +1,40 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CC_STUBS_INTPOINT_H_ +#define CC_STUBS_INTPOINT_H_ + +#include "IntSize.h" +#if INSIDE_WEBKIT_BUILD +#include "Source/WebCore/platform/graphics/IntPoint.h" +#else +#include "third_party/WebKit/Source/WebCore/platform/graphics/IntPoint.h" +#endif + +namespace cc { + +class IntPoint : public WebCore::IntPoint { +public: + IntPoint() { } + + IntPoint(int width, int height) + : WebCore::IntPoint(width, height) + { + } + + IntPoint(IntSize size) + : WebCore::IntPoint(size.width(), size.height()) + { + } + + IntPoint(WebCore::IntPoint point) + : WebCore::IntPoint(point.x(), point.y()) + { + + } +}; + +} + +#endif diff --git a/cc/stubs/int_rect.h b/cc/stubs/int_rect.h index 638cbb2..1599967 100644 --- a/cc/stubs/int_rect.h +++ b/cc/stubs/int_rect.h @@ -1,3 +1,41 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CC_STUBS_INTRECT_H_ +#define CC_STUBS_INTRECT_H_ + +#include "IntPoint.h" +#include "IntSize.h" +#if INSIDE_WEBKIT_BUILD +#include "Source/WebCore/platform/graphics/IntRect.h" +#else +#include "third_party/WebKit/Source/WebCore/platform/graphics/IntRect.h" +#endif + +namespace cc { + +class IntRect : public WebCore::IntRect { +public: + IntRect() { } + + IntRect(const IntPoint& location, const IntSize& size) + : WebCore::IntRect(location, size) + { + } + + IntRect(int x, int y, int width, int height) + : WebCore::IntRect(x, y, width, height) + { + } + + IntRect(WebCore::IntRect rect) + : WebCore::IntRect(rect.x(), rect.y(), rect.width(), rect.height()) + { + + } +}; + +} + +#endif diff --git a/cc/stubs/int_size.h b/cc/stubs/int_size.h index 638cbb2..c53f4f1 100644 --- a/cc/stubs/int_size.h +++ b/cc/stubs/int_size.h @@ -1,3 +1,34 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CC_STUBS_INTSIZE_H_ +#define CC_STUBS_INTSIZE_H_ + +#if INSIDE_WEBKIT_BUILD +#include "Source/WebCore/platform/graphics/IntSize.h" +#else +#include "third_party/WebKit/Source/WebCore/platform/graphics/IntSize.h" +#endif + +namespace cc { + +class IntSize : public WebCore::IntSize { +public: + IntSize() { } + + IntSize(int width, int height) + : WebCore::IntSize(width, height) + { + } + + IntSize(WebCore::IntSize size) + : WebCore::IntSize(size.width(), size.height()) + { + + } +}; + +} + +#endif diff --git a/cc/stubs/not_implemented.h b/cc/stubs/not_implemented.h index 638cbb2..7c6bba5 100644 --- a/cc/stubs/not_implemented.h +++ b/cc/stubs/not_implemented.h @@ -1,3 +1,10 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CC_STUBS_NOTIMPLEMENTED_H +#define CC_STUBS_NOTIMPLEMENTED_H + +#define notImplemented() do { } while(0) + +#endif // CC_STUBS_NOTIMPLEMENTED_H diff --git a/cc/stubs/skia_utils.h b/cc/stubs/skia_utils.h index 638cbb2..fb81f3e 100644 --- a/cc/stubs/skia_utils.h +++ b/cc/stubs/skia_utils.h @@ -1,3 +1,17 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CC_STUBS_SKIAUTILS_H_ +#define CC_STUBS_SKIAUTILS_H_ + +namespace cc { + +inline SkScalar CCFloatToSkScalar(float f) +{ + return SkFloatToScalar(isfinite(f) ? f : 0); +} + +} + +#endif // CC_STUBS_SKIAUTILS_H_ diff --git a/cc/stubs/tiling_data.h b/cc/stubs/tiling_data.h index 638cbb2..0221500 100644 --- a/cc/stubs/tiling_data.h +++ b/cc/stubs/tiling_data.h @@ -1,3 +1,18 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CC_STUBS_TILINGDATA_H_ +#define CC_STUBS_TILINGDATA_H_ + +#if INSIDE_WEBKIT_BUILD +#include "Source/WebCore/platform/graphics/gpu/TilingData.h" +#else +#include "third_party/WebKit/Source/WebCore/platform/graphics/gpu/TilingData.h" +#endif + +namespace cc { + typedef WebCore::TilingData TilingData; +} + +#endif // CC_STUBS_TILINGDATA_H_ diff --git a/cc/stubs/trace_event.h b/cc/stubs/trace_event.h index 638cbb2..75587a3 100644 --- a/cc/stubs/trace_event.h +++ b/cc/stubs/trace_event.h @@ -1,3 +1,10 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +// Chromium's LOG() macro collides with one from WTF. +#ifdef LOG +#undef LOG +#endif + +#include "base/debug/trace_event.h" diff --git a/cc/stubs/unit_bezier.h b/cc/stubs/unit_bezier.h index 638cbb2..1ff5da9 100644 --- a/cc/stubs/unit_bezier.h +++ b/cc/stubs/unit_bezier.h @@ -1,3 +1,14 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +// TODO(jamesr): Remove or refactor this dependency. +#if INSIDE_WEBKIT_BUILD +#include "Source/WebCore/platform/graphics/UnitBezier.h" +#else +#include "third_party/WebKit/Source/WebCore/platform/graphics/UnitBezier.h" +#endif + +namespace cc { +typedef WebCore::UnitBezier UnitBezier; +} diff --git a/cc/texture.cc b/cc/texture.cc new file mode 100644 index 0000000..add8429 --- /dev/null +++ b/cc/texture.cc @@ -0,0 +1,32 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#include "CCTexture.h" + +namespace cc { + +void CCTexture::setDimensions(const IntSize& size, GC3Denum format) +{ + m_size = size; + m_format = format; +} + +size_t CCTexture::bytes() const +{ + if (m_size.isEmpty()) + return 0u; + + return memorySizeBytes(m_size, m_format); +} + +size_t CCTexture::memorySizeBytes(const IntSize& size, GC3Denum format) +{ + unsigned int componentsPerPixel = 4; + unsigned int bytesPerComponent = 1; + return componentsPerPixel * bytesPerComponent * size.width() * size.height(); +} + +} diff --git a/cc/texture.h b/cc/texture.h index 638cbb2..8d0def3 100644 --- a/cc/texture.h +++ b/cc/texture.h @@ -1,3 +1,42 @@ // Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CCTexture_h +#define CCTexture_h + +#include "CCResourceProvider.h" +#include "CCTexture.h" +#include "GraphicsContext3D.h" +#include "IntSize.h" + +namespace cc { + +class CCTexture { +public: + CCTexture() : m_id(0) { } + CCTexture(unsigned id, IntSize size, GC3Denum format) + : m_id(id) + , m_size(size) + , m_format(format) { } + + CCResourceProvider::ResourceId id() const { return m_id; } + const IntSize& size() const { return m_size; } + GC3Denum format() const { return m_format; } + + void setId(CCResourceProvider::ResourceId id) { m_id = id; } + void setDimensions(const IntSize&, GC3Denum format); + + size_t bytes() const; + + static size_t memorySizeBytes(const IntSize&, GC3Denum format); + +private: + CCResourceProvider::ResourceId m_id; + IntSize m_size; + GC3Denum m_format; +}; + +} + +#endif diff --git a/cc/texture_copier.cc b/cc/texture_copier.cc new file mode 100644 index 0000000..b0db144 --- /dev/null +++ b/cc/texture_copier.cc @@ -0,0 +1,101 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#include "TextureCopier.h" + +#include "CCRendererGL.h" // For the GLC() macro. +#include "GraphicsContext3D.h" +#include "TraceEvent.h" +#include + +namespace cc { + +#if USE(ACCELERATED_COMPOSITING) +AcceleratedTextureCopier::AcceleratedTextureCopier(WebKit::WebGraphicsContext3D* context, bool usingBindUniforms) + : m_context(context) + , m_usingBindUniforms(usingBindUniforms) +{ + ASSERT(m_context); + GLC(m_context, m_fbo = m_context->createFramebuffer()); + GLC(m_context, m_positionBuffer = m_context->createBuffer()); + + static const float kPositions[4][4] = { + {-1, -1, 0, 1}, + { 1, -1, 0, 1}, + { 1, 1, 0, 1}, + {-1, 1, 0, 1} + }; + + GLC(m_context, m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, m_positionBuffer)); + GLC(m_context, m_context->bufferData(GraphicsContext3D::ARRAY_BUFFER, sizeof(kPositions), kPositions, GraphicsContext3D::STATIC_DRAW)); + GLC(m_context, m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, 0)); + + m_blitProgram = adoptPtr(new BlitProgram(m_context)); +} + +AcceleratedTextureCopier::~AcceleratedTextureCopier() +{ + if (m_blitProgram) + m_blitProgram->cleanup(m_context); + if (m_positionBuffer) + GLC(m_context, m_context->deleteBuffer(m_positionBuffer)); + if (m_fbo) + GLC(m_context, m_context->deleteFramebuffer(m_fbo)); +} + +void AcceleratedTextureCopier::copyTexture(Parameters parameters) +{ + TRACE_EVENT0("cc", "TextureCopier::copyTexture"); + + // Note: this code does not restore the viewport, bound program, 2D texture, framebuffer, buffer or blend enable. + GLC(m_context, m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_fbo)); + GLC(m_context, m_context->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE_2D, parameters.destTexture, 0)); + +#if OS(ANDROID) + // Clear destination to improve performance on tiling GPUs. + // TODO: Use EXT_discard_framebuffer or skip clearing if it isn't available. + GLC(m_context, m_context->clear(GraphicsContext3D::COLOR_BUFFER_BIT)); +#endif + + GLC(m_context, m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, parameters.sourceTexture)); + GLC(m_context, m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::NEAREST)); + GLC(m_context, m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::NEAREST)); + + if (!m_blitProgram->initialized()) + m_blitProgram->initialize(m_context, m_usingBindUniforms); + + // TODO: Use EXT_framebuffer_blit if available. + GLC(m_context, m_context->useProgram(m_blitProgram->program())); + + const int kPositionAttribute = 0; + GLC(m_context, m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, m_positionBuffer)); + GLC(m_context, m_context->vertexAttribPointer(kPositionAttribute, 4, GraphicsContext3D::FLOAT, false, 0, 0)); + GLC(m_context, m_context->enableVertexAttribArray(kPositionAttribute)); + GLC(m_context, m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, 0)); + + GLC(m_context, m_context->viewport(0, 0, parameters.size.width(), parameters.size.height())); + GLC(m_context, m_context->disable(GraphicsContext3D::BLEND)); + GLC(m_context, m_context->drawArrays(GraphicsContext3D::TRIANGLE_FAN, 0, 4)); + + GLC(m_context, m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR)); + GLC(m_context, m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR)); + GLC(m_context, m_context->disableVertexAttribArray(kPositionAttribute)); + + GLC(m_context, m_context->useProgram(0)); + + GLC(m_context, m_context->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE_2D, 0, 0)); + GLC(m_context, m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, 0)); + GLC(m_context, m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, 0)); +} + +void AcceleratedTextureCopier::flush() +{ + GLC(m_context, m_context->flush()); +} + +} + +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/cc/texture_copier.h b/cc/texture_copier.h index 638cbb2..ba8d7bf 100644 --- a/cc/texture_copier.h +++ b/cc/texture_copier.h @@ -1,3 +1,70 @@ // Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef TextureCopier_h +#define TextureCopier_h + +#include "base/basictypes.h" +#include "GraphicsContext3D.h" +#include "ProgramBinding.h" +#include "ShaderChromium.h" +#include +#include + +namespace WebKit { +class WebGraphicsContext3D; +} + +namespace cc { +class IntSize; + +class TextureCopier { +public: + struct Parameters { + unsigned sourceTexture; + unsigned destTexture; + IntSize size; + }; + // Copy the base level contents of |sourceTexture| to |destTexture|. Both texture objects + // must be complete and have a base level of |size| dimensions. The color formats do not need + // to match, but |destTexture| must have a renderable format. + virtual void copyTexture(Parameters) = 0; + virtual void flush() = 0; + + virtual ~TextureCopier() { } +}; + +#if USE(ACCELERATED_COMPOSITING) + +class AcceleratedTextureCopier : public TextureCopier { +public: + static PassOwnPtr create(WebKit::WebGraphicsContext3D* context, bool usingBindUniforms) + { + return adoptPtr(new AcceleratedTextureCopier(context, usingBindUniforms)); + } + virtual ~AcceleratedTextureCopier(); + + virtual void copyTexture(Parameters) OVERRIDE; + virtual void flush() OVERRIDE; + +protected: + AcceleratedTextureCopier(WebKit::WebGraphicsContext3D*, bool usingBindUniforms); + +private: + typedef ProgramBinding BlitProgram; + + WebKit::WebGraphicsContext3D* m_context; + Platform3DObject m_fbo; + Platform3DObject m_positionBuffer; + OwnPtr m_blitProgram; + bool m_usingBindUniforms; + + DISALLOW_COPY_AND_ASSIGN(AcceleratedTextureCopier); +}; + +#endif // USE(ACCELERATED_COMPOSITING) + +} + +#endif diff --git a/cc/texture_draw_quad.cc b/cc/texture_draw_quad.cc new file mode 100644 index 0000000..db985ad --- /dev/null +++ b/cc/texture_draw_quad.cc @@ -0,0 +1,36 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#include "CCTextureDrawQuad.h" + +namespace cc { + +scoped_ptr CCTextureDrawQuad::create(const CCSharedQuadState* sharedQuadState, const IntRect& quadRect, unsigned resourceId, bool premultipliedAlpha, const FloatRect& uvRect, bool flipped) +{ + return make_scoped_ptr(new CCTextureDrawQuad(sharedQuadState, quadRect, resourceId, premultipliedAlpha, uvRect, flipped)); +} + +CCTextureDrawQuad::CCTextureDrawQuad(const CCSharedQuadState* sharedQuadState, const IntRect& quadRect, unsigned resourceId, bool premultipliedAlpha, const FloatRect& uvRect, bool flipped) + : CCDrawQuad(sharedQuadState, CCDrawQuad::TextureContent, quadRect) + , m_resourceId(resourceId) + , m_premultipliedAlpha(premultipliedAlpha) + , m_uvRect(uvRect) + , m_flipped(flipped) +{ +} + +void CCTextureDrawQuad::setNeedsBlending() +{ + m_needsBlending = true; +} + +const CCTextureDrawQuad* CCTextureDrawQuad::materialCast(const CCDrawQuad* quad) +{ + ASSERT(quad->material() == CCDrawQuad::TextureContent); + return static_cast(quad); +} + +} diff --git a/cc/texture_draw_quad.h b/cc/texture_draw_quad.h index 638cbb2..daa600f 100644 --- a/cc/texture_draw_quad.h +++ b/cc/texture_draw_quad.h @@ -1,3 +1,41 @@ // Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CCTextureDrawQuad_h +#define CCTextureDrawQuad_h + +#include "CCDrawQuad.h" +#include "FloatRect.h" +#include "base/memory/scoped_ptr.h" + +namespace cc { + +#pragma pack(push, 4) + +class CCTextureDrawQuad : public CCDrawQuad { +public: + static scoped_ptr create(const CCSharedQuadState*, const IntRect&, unsigned resourceId, bool premultipliedAlpha, const FloatRect& uvRect, bool flipped); + FloatRect uvRect() const { return m_uvRect; } + + unsigned resourceId() const { return m_resourceId; } + bool premultipliedAlpha() const { return m_premultipliedAlpha; } + bool flipped() const { return m_flipped; } + + void setNeedsBlending(); + + static const CCTextureDrawQuad* materialCast(const CCDrawQuad*); +private: + CCTextureDrawQuad(const CCSharedQuadState*, const IntRect&, unsigned resourceId, bool premultipliedAlpha, const FloatRect& uvRect, bool flipped); + + unsigned m_resourceId; + bool m_premultipliedAlpha; + FloatRect m_uvRect; + bool m_flipped; +}; + +#pragma pack(pop) + +} + +#endif diff --git a/cc/texture_layer.cc b/cc/texture_layer.cc new file mode 100644 index 0000000..e1b4851 --- /dev/null +++ b/cc/texture_layer.cc @@ -0,0 +1,135 @@ +// Copyright 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#if USE(ACCELERATED_COMPOSITING) + +#include "TextureLayerChromium.h" + +#include "CCLayerTreeHost.h" +#include "CCTextureLayerImpl.h" +#include "GraphicsContext3D.h" +#include "TextureLayerChromiumClient.h" +#include + +namespace cc { + +scoped_refptr TextureLayerChromium::create(TextureLayerChromiumClient* client) +{ + return scoped_refptr(new TextureLayerChromium(client)); +} + +TextureLayerChromium::TextureLayerChromium(TextureLayerChromiumClient* client) + : LayerChromium() + , m_client(client) + , m_flipped(true) + , m_uvRect(0, 0, 1, 1) + , m_premultipliedAlpha(true) + , m_rateLimitContext(false) + , m_contextLost(false) + , m_textureId(0) +{ +} + +TextureLayerChromium::~TextureLayerChromium() +{ + if (layerTreeHost()) { + if (m_textureId) + layerTreeHost()->acquireLayerTextures(); + if (m_rateLimitContext && m_client) + layerTreeHost()->stopRateLimiter(m_client->context()); + } +} + +scoped_ptr TextureLayerChromium::createCCLayerImpl() +{ + return CCTextureLayerImpl::create(m_layerId).PassAs(); +} + +void TextureLayerChromium::setFlipped(bool flipped) +{ + m_flipped = flipped; + setNeedsCommit(); +} + +void TextureLayerChromium::setUVRect(const FloatRect& rect) +{ + m_uvRect = rect; + setNeedsCommit(); +} + +void TextureLayerChromium::setPremultipliedAlpha(bool premultipliedAlpha) +{ + m_premultipliedAlpha = premultipliedAlpha; + setNeedsCommit(); +} + +void TextureLayerChromium::setRateLimitContext(bool rateLimit) +{ + if (!rateLimit && m_rateLimitContext && m_client && layerTreeHost()) + layerTreeHost()->stopRateLimiter(m_client->context()); + + m_rateLimitContext = rateLimit; +} + +void TextureLayerChromium::setTextureId(unsigned id) +{ + if (m_textureId == id) + return; + if (m_textureId && layerTreeHost()) + layerTreeHost()->acquireLayerTextures(); + m_textureId = id; + setNeedsCommit(); +} + +void TextureLayerChromium::willModifyTexture() +{ + if (layerTreeHost()) + layerTreeHost()->acquireLayerTextures(); +} + +void TextureLayerChromium::setNeedsDisplayRect(const FloatRect& dirtyRect) +{ + LayerChromium::setNeedsDisplayRect(dirtyRect); + + if (m_rateLimitContext && m_client && layerTreeHost()) + layerTreeHost()->startRateLimiter(m_client->context()); +} + +void TextureLayerChromium::setLayerTreeHost(CCLayerTreeHost* host) +{ + if (m_textureId && layerTreeHost() && host != layerTreeHost()) + layerTreeHost()->acquireLayerTextures(); + LayerChromium::setLayerTreeHost(host); +} + +bool TextureLayerChromium::drawsContent() const +{ + return (m_client || m_textureId) && !m_contextLost && LayerChromium::drawsContent(); +} + +void TextureLayerChromium::update(CCTextureUpdateQueue& queue, const CCOcclusionTracker*, CCRenderingStats&) +{ + if (m_client) { + m_textureId = m_client->prepareTexture(queue); + m_contextLost = m_client->context()->getGraphicsResetStatusARB() != GraphicsContext3D::NO_ERROR; + } + + m_needsDisplay = false; +} + +void TextureLayerChromium::pushPropertiesTo(CCLayerImpl* layer) +{ + LayerChromium::pushPropertiesTo(layer); + + CCTextureLayerImpl* textureLayer = static_cast(layer); + textureLayer->setFlipped(m_flipped); + textureLayer->setUVRect(m_uvRect); + textureLayer->setPremultipliedAlpha(m_premultipliedAlpha); + textureLayer->setTextureId(m_textureId); +} + +} +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/cc/texture_layer.h b/cc/texture_layer.h index 638cbb2..124f845 100644 --- a/cc/texture_layer.h +++ b/cc/texture_layer.h @@ -1,3 +1,77 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. +// Copyright 2010 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef TextureLayerChromium_h +#define TextureLayerChromium_h + +#if USE(ACCELERATED_COMPOSITING) + +#include "LayerChromium.h" + +namespace WebKit { +class WebGraphicsContext3D; +} + +namespace cc { + +class TextureLayerChromiumClient; + +// A Layer containing a the rendered output of a plugin instance. +class TextureLayerChromium : public LayerChromium { +public: + // If this texture layer requires special preparation logic for each frame driven by + // the compositor, pass in a non-nil client. Pass in a nil client pointer if texture updates + // are driven by an external process. + static scoped_refptr create(TextureLayerChromiumClient*); + + void clearClient() { m_client = 0; } + + virtual scoped_ptr createCCLayerImpl() OVERRIDE; + + // Sets whether this texture should be Y-flipped at draw time. Defaults to true. + void setFlipped(bool); + + // Sets a UV transform to be used at draw time. Defaults to (0, 0, 1, 1). + void setUVRect(const FloatRect&); + + // Sets whether the alpha channel is premultiplied or unpremultiplied. Defaults to true. + void setPremultipliedAlpha(bool); + + // Sets whether this context should rate limit on damage to prevent too many frames from + // being queued up before the compositor gets a chance to run. Requires a non-nil client. + // Defaults to false. + void setRateLimitContext(bool); + + // Code path for plugins which supply their own texture ID. + void setTextureId(unsigned); + + void willModifyTexture(); + + virtual void setNeedsDisplayRect(const FloatRect&) OVERRIDE; + + virtual void setLayerTreeHost(CCLayerTreeHost*) OVERRIDE; + virtual bool drawsContent() const OVERRIDE; + virtual void update(CCTextureUpdateQueue&, const CCOcclusionTracker*, CCRenderingStats&) OVERRIDE; + virtual void pushPropertiesTo(CCLayerImpl*) OVERRIDE; + +protected: + explicit TextureLayerChromium(TextureLayerChromiumClient*); + virtual ~TextureLayerChromium(); + +private: + TextureLayerChromiumClient* m_client; + + bool m_flipped; + FloatRect m_uvRect; + bool m_premultipliedAlpha; + bool m_rateLimitContext; + bool m_contextLost; + + unsigned m_textureId; +}; + +} +#endif // USE(ACCELERATED_COMPOSITING) + +#endif diff --git a/cc/texture_layer_client.h b/cc/texture_layer_client.h index 638cbb2..4edbe9f 100644 --- a/cc/texture_layer_client.h +++ b/cc/texture_layer_client.h @@ -1,3 +1,31 @@ // Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef TextureLayerChromiumClient_h +#define TextureLayerChromiumClient_h + +namespace WebKit { +class WebGraphicsContext3D; +} + +namespace cc { +class CCTextureUpdateQueue; + +class TextureLayerChromiumClient { +public: + // Called to prepare this layer's texture for compositing. The client may queue a texture + // upload or copy on the CCTextureUpdateQueue. + // Returns the texture ID to be used for compositing. + virtual unsigned prepareTexture(CCTextureUpdateQueue&) = 0; + + // Returns the context that is providing the texture. Used for rate limiting and detecting lost context. + virtual WebKit::WebGraphicsContext3D* context() = 0; + +protected: + virtual ~TextureLayerChromiumClient() { } +}; + +} + +#endif // TextureLayerChromiumClient_h diff --git a/cc/texture_layer_impl.cc b/cc/texture_layer_impl.cc new file mode 100644 index 0000000..441265f --- /dev/null +++ b/cc/texture_layer_impl.cc @@ -0,0 +1,84 @@ +// Copyright 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#if USE(ACCELERATED_COMPOSITING) + +#include "CCTextureLayerImpl.h" + +#include "base/stringprintf.h" +#include "CCQuadSink.h" +#include "CCRenderer.h" +#include "CCTextureDrawQuad.h" + +namespace cc { + +CCTextureLayerImpl::CCTextureLayerImpl(int id) + : CCLayerImpl(id) + , m_textureId(0) + , m_externalTextureResource(0) + , m_premultipliedAlpha(true) + , m_flipped(true) + , m_uvRect(0, 0, 1, 1) +{ +} + +CCTextureLayerImpl::~CCTextureLayerImpl() +{ +} + +void CCTextureLayerImpl::willDraw(CCResourceProvider* resourceProvider) +{ + if (!m_textureId) + return; + ASSERT(!m_externalTextureResource); + m_externalTextureResource = resourceProvider->createResourceFromExternalTexture(m_textureId); +} + +void CCTextureLayerImpl::appendQuads(CCQuadSink& quadSink, CCAppendQuadsData& appendQuadsData) +{ + if (!m_externalTextureResource) + return; + + CCSharedQuadState* sharedQuadState = quadSink.useSharedQuadState(createSharedQuadState()); + appendDebugBorderQuad(quadSink, sharedQuadState, appendQuadsData); + + IntRect quadRect(IntPoint(), contentBounds()); + quadSink.append(CCTextureDrawQuad::create(sharedQuadState, quadRect, m_externalTextureResource, m_premultipliedAlpha, m_uvRect, m_flipped).PassAs(), appendQuadsData); +} + +void CCTextureLayerImpl::didDraw(CCResourceProvider* resourceProvider) +{ + if (!m_externalTextureResource) + return; + // FIXME: the following assert will not be true when sending resources to a + // parent compositor. A synchronization scheme (double-buffering or + // pipelining of updates) for the client will need to exist to solve this. + ASSERT(!resourceProvider->inUseByConsumer(m_externalTextureResource)); + resourceProvider->deleteResource(m_externalTextureResource); + m_externalTextureResource = 0; +} + +void CCTextureLayerImpl::dumpLayerProperties(std::string* str, int indent) const +{ + str->append(indentString(indent)); + base::StringAppendF(str, "texture layer texture id: %u premultiplied: %d\n", m_textureId, m_premultipliedAlpha); + CCLayerImpl::dumpLayerProperties(str, indent); +} + +void CCTextureLayerImpl::didLoseContext() +{ + m_textureId = 0; + m_externalTextureResource = 0; +} + +const char* CCTextureLayerImpl::layerTypeAsString() const +{ + return "TextureLayer"; +} + +} + +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/cc/texture_layer_impl.h b/cc/texture_layer_impl.h index 638cbb2..ff88ff3 100644 --- a/cc/texture_layer_impl.h +++ b/cc/texture_layer_impl.h @@ -1,3 +1,48 @@ // Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CCTextureLayerImpl_h +#define CCTextureLayerImpl_h + +#include "CCLayerImpl.h" + +namespace cc { + +class CCTextureLayerImpl : public CCLayerImpl { +public: + static scoped_ptr create(int id) + { + return make_scoped_ptr(new CCTextureLayerImpl(id)); + } + virtual ~CCTextureLayerImpl(); + + virtual void willDraw(CCResourceProvider*) OVERRIDE; + virtual void appendQuads(CCQuadSink&, CCAppendQuadsData&) OVERRIDE; + virtual void didDraw(CCResourceProvider*) OVERRIDE; + + virtual void didLoseContext() OVERRIDE; + + virtual void dumpLayerProperties(std::string*, int indent) const OVERRIDE; + + unsigned textureId() const { return m_textureId; } + void setTextureId(unsigned id) { m_textureId = id; } + void setPremultipliedAlpha(bool premultipliedAlpha) { m_premultipliedAlpha = premultipliedAlpha; } + void setFlipped(bool flipped) { m_flipped = flipped; } + void setUVRect(const FloatRect& rect) { m_uvRect = rect; } + +private: + explicit CCTextureLayerImpl(int); + + virtual const char* layerTypeAsString() const OVERRIDE; + + unsigned m_textureId; + CCResourceProvider::ResourceId m_externalTextureResource; + bool m_premultipliedAlpha; + bool m_flipped; + FloatRect m_uvRect; +}; + +} + +#endif // CCTextureLayerImpl_h diff --git a/cc/texture_update_controller.cc b/cc/texture_update_controller.cc new file mode 100644 index 0000000..200948d --- /dev/null +++ b/cc/texture_update_controller.cc @@ -0,0 +1,197 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#include "CCTextureUpdateController.h" + +#include "GraphicsContext3D.h" +#include "TextureCopier.h" +#include "TextureUploader.h" +#include "TraceEvent.h" +#include +#include + +namespace { + +// Number of partial updates we allow. +static const size_t partialTextureUpdatesMax = 12; + +// Measured in seconds. +static const double textureUpdateTickRate = 0.004; + +// Measured in seconds. +static const double uploaderBusyTickRate = 0.001; + +// Flush interval when performing texture uploads. +static const int textureUploadFlushPeriod = 4; + +// Number of blocking update intervals to allow. +static const size_t maxBlockingUpdateIntervals = 4; + +} // anonymous namespace + +namespace cc { + +size_t CCTextureUpdateController::maxPartialTextureUpdates() +{ + return partialTextureUpdatesMax; +} + +size_t CCTextureUpdateController::maxFullUpdatesPerTick(TextureUploader* uploader) +{ + double texturesPerSecond = uploader->estimatedTexturesPerSecond(); + size_t texturesPerTick = floor(textureUpdateTickRate * texturesPerSecond); + return texturesPerTick ? texturesPerTick : 1; +} + +CCTextureUpdateController::CCTextureUpdateController(CCTextureUpdateControllerClient* client, CCThread* thread, PassOwnPtr queue, CCResourceProvider* resourceProvider, TextureUploader* uploader) + : m_client(client) + , m_timer(adoptPtr(new CCTimer(thread, this))) + , m_queue(queue) + , m_resourceProvider(resourceProvider) + , m_uploader(uploader) + , m_textureUpdatesPerTick(maxFullUpdatesPerTick(uploader)) + , m_firstUpdateAttempt(true) +{ +} + +CCTextureUpdateController::~CCTextureUpdateController() +{ +} + +void CCTextureUpdateController::performMoreUpdates( + base::TimeTicks timeLimit) +{ + m_timeLimit = timeLimit; + + // Update already in progress. + if (m_timer->isActive()) + return; + + // Call updateMoreTexturesNow() directly unless it's the first update + // attempt. This ensures that we empty the update queue in a finite + // amount of time. + if (m_firstUpdateAttempt) { + // Post a 0-delay task when no updates were left. When it runs, + // readyToFinalizeTextureUpdates() will be called. + if (!updateMoreTexturesIfEnoughTimeRemaining()) + m_timer->startOneShot(0); + + m_firstUpdateAttempt = false; + } else + updateMoreTexturesNow(); +} + +void CCTextureUpdateController::discardUploadsToEvictedResources() +{ + m_queue->clearUploadsToEvictedResources(); +} + +void CCTextureUpdateController::finalize() +{ + size_t uploadCount = 0; + while (m_queue->fullUploadSize()) { + if (!(uploadCount % textureUploadFlushPeriod) && uploadCount) + m_resourceProvider->shallowFlushIfSupported(); + + m_uploader->uploadTexture( + m_resourceProvider, m_queue->takeFirstFullUpload()); + uploadCount++; + } + + while (m_queue->partialUploadSize()) { + if (!(uploadCount % textureUploadFlushPeriod) && uploadCount) + m_resourceProvider->shallowFlushIfSupported(); + + m_uploader->uploadTexture( + m_resourceProvider, m_queue->takeFirstPartialUpload()); + uploadCount++; + } + + if (uploadCount) + m_resourceProvider->shallowFlushIfSupported(); + + if (m_queue->copySize()) { + TextureCopier* copier = m_resourceProvider->textureCopier(); + while (m_queue->copySize()) + copier->copyTexture(m_queue->takeFirstCopy()); + + // If we've performed any texture copies, we need to insert a flush + // here into the compositor context before letting the main thread + // proceed as it may make draw calls to the source texture of one of + // our copy operations. + copier->flush(); + } +} + +void CCTextureUpdateController::onTimerFired() +{ + if (!updateMoreTexturesIfEnoughTimeRemaining()) + m_client->readyToFinalizeTextureUpdates(); +} + +base::TimeTicks CCTextureUpdateController::now() const +{ + return base::TimeTicks::Now(); +} + +base::TimeDelta CCTextureUpdateController::updateMoreTexturesTime() const +{ + return base::TimeDelta::FromMilliseconds(textureUpdateTickRate * 1000); +} + +size_t CCTextureUpdateController::updateMoreTexturesSize() const +{ + return m_textureUpdatesPerTick; +} + +size_t CCTextureUpdateController::maxBlockingUpdates() const +{ + return updateMoreTexturesSize() * maxBlockingUpdateIntervals; +} + +bool CCTextureUpdateController::updateMoreTexturesIfEnoughTimeRemaining() +{ + // Blocking uploads will increase when we're too aggressive in our upload + // time estimate. We use a different timeout here to prevent unnecessary + // amounts of idle time when blocking uploads have reached the max. + if (m_uploader->numBlockingUploads() >= maxBlockingUpdates()) { + m_timer->startOneShot(uploaderBusyTickRate); + return true; + } + + if (!m_queue->fullUploadSize()) + return false; + + bool hasTimeRemaining = m_timeLimit.is_null() || + this->now() < m_timeLimit - updateMoreTexturesTime(); + if (hasTimeRemaining) + updateMoreTexturesNow(); + + return true; +} + +void CCTextureUpdateController::updateMoreTexturesNow() +{ + size_t uploads = std::min( + m_queue->fullUploadSize(), updateMoreTexturesSize()); + m_timer->startOneShot( + updateMoreTexturesTime().InSecondsF() / updateMoreTexturesSize() * + uploads); + + if (!uploads) + return; + + size_t uploadCount = 0; + while (m_queue->fullUploadSize() && uploadCount < uploads) { + if (!(uploadCount % textureUploadFlushPeriod) && uploadCount) + m_resourceProvider->shallowFlushIfSupported(); + m_uploader->uploadTexture(m_resourceProvider, m_queue->takeFirstFullUpload()); + uploadCount++; + } + m_resourceProvider->shallowFlushIfSupported(); +} + +} diff --git a/cc/texture_update_controller.h b/cc/texture_update_controller.h index 638cbb2..74bb8ca 100644 --- a/cc/texture_update_controller.h +++ b/cc/texture_update_controller.h @@ -1,3 +1,77 @@ // Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CCTextureUpdateController_h +#define CCTextureUpdateController_h + +#include "base/basictypes.h" +#include "base/time.h" +#include "CCTextureUpdateQueue.h" +#include "CCTimer.h" +#include + +namespace cc { + +class TextureUploader; + +class CCTextureUpdateControllerClient { +public: + virtual void readyToFinalizeTextureUpdates() = 0; + +protected: + virtual ~CCTextureUpdateControllerClient() { } +}; + +class CCTextureUpdateController : public CCTimerClient { +public: + static PassOwnPtr create(CCTextureUpdateControllerClient* client, CCThread* thread, PassOwnPtr queue, CCResourceProvider* resourceProvider, TextureUploader* uploader) + { + return adoptPtr(new CCTextureUpdateController(client, thread, queue, resourceProvider, uploader)); + } + static size_t maxPartialTextureUpdates(); + + virtual ~CCTextureUpdateController(); + + // Discard uploads to textures that were evicted on the impl thread. + void discardUploadsToEvictedResources(); + + void performMoreUpdates(base::TimeTicks timeLimit); + void finalize(); + + // CCTimerClient implementation. + virtual void onTimerFired() OVERRIDE; + + // Virtual for testing. + virtual base::TimeTicks now() const; + virtual base::TimeDelta updateMoreTexturesTime() const; + virtual size_t updateMoreTexturesSize() const; + +protected: + CCTextureUpdateController(CCTextureUpdateControllerClient*, CCThread*, PassOwnPtr, CCResourceProvider*, TextureUploader*); + + static size_t maxFullUpdatesPerTick(TextureUploader*); + + size_t maxBlockingUpdates() const; + + // This returns true when there were textures left to update. + bool updateMoreTexturesIfEnoughTimeRemaining(); + void updateMoreTexturesNow(); + + CCTextureUpdateControllerClient* m_client; + OwnPtr m_timer; + OwnPtr m_queue; + bool m_contentsTexturesPurged; + CCResourceProvider* m_resourceProvider; + TextureUploader* m_uploader; + base::TimeTicks m_timeLimit; + size_t m_textureUpdatesPerTick; + bool m_firstUpdateAttempt; + +private: + DISALLOW_COPY_AND_ASSIGN(CCTextureUpdateController); +}; + +} + +#endif // CCTextureUpdateController_h diff --git a/cc/texture_update_queue.cc b/cc/texture_update_queue.cc new file mode 100644 index 0000000..b5ebdf5 --- /dev/null +++ b/cc/texture_update_queue.cc @@ -0,0 +1,75 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#if USE(ACCELERATED_COMPOSITING) + +#include "CCTextureUpdateQueue.h" + +namespace cc { + +CCTextureUpdateQueue::CCTextureUpdateQueue() +{ +} + +CCTextureUpdateQueue::~CCTextureUpdateQueue() +{ +} + +void CCTextureUpdateQueue::appendFullUpload(TextureUploader::Parameters upload) +{ + m_fullEntries.append(upload); +} + +void CCTextureUpdateQueue::appendPartialUpload(TextureUploader::Parameters upload) +{ + m_partialEntries.append(upload); +} + +void CCTextureUpdateQueue::appendCopy(TextureCopier::Parameters copy) +{ + m_copyEntries.append(copy); +} + +void CCTextureUpdateQueue::clearUploadsToEvictedResources() +{ + clearUploadsToEvictedResources(m_fullEntries); + clearUploadsToEvictedResources(m_partialEntries); +} + +void CCTextureUpdateQueue::clearUploadsToEvictedResources(Deque& entryQueue) +{ + Deque temp; + entryQueue.swap(temp); + while (temp.size()) { + TextureUploader::Parameters upload = temp.takeFirst(); + if (!upload.texture->backingResourceWasEvicted()) + entryQueue.append(upload); + } +} + +TextureUploader::Parameters CCTextureUpdateQueue::takeFirstFullUpload() +{ + return m_fullEntries.takeFirst(); +} + +TextureUploader::Parameters CCTextureUpdateQueue::takeFirstPartialUpload() +{ + return m_partialEntries.takeFirst(); +} + +TextureCopier::Parameters CCTextureUpdateQueue::takeFirstCopy() +{ + return m_copyEntries.takeFirst(); +} + +bool CCTextureUpdateQueue::hasMoreUpdates() const +{ + return m_fullEntries.size() || m_partialEntries.size() || m_copyEntries.size(); +} + +} + +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/cc/texture_update_queue.h b/cc/texture_update_queue.h index 638cbb2..4cf29338 100644 --- a/cc/texture_update_queue.h +++ b/cc/texture_update_queue.h @@ -1,3 +1,47 @@ // Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CCTextureUpdateQueue_h +#define CCTextureUpdateQueue_h + +#include "base/basictypes.h" +#include "TextureCopier.h" +#include "TextureUploader.h" +#include + +namespace cc { + +class CCTextureUpdateQueue { +public: + CCTextureUpdateQueue(); + virtual ~CCTextureUpdateQueue(); + + void appendFullUpload(TextureUploader::Parameters); + void appendPartialUpload(TextureUploader::Parameters); + void appendCopy(TextureCopier::Parameters); + + void clearUploadsToEvictedResources(); + + TextureUploader::Parameters takeFirstFullUpload(); + TextureUploader::Parameters takeFirstPartialUpload(); + TextureCopier::Parameters takeFirstCopy(); + + size_t fullUploadSize() const { return m_fullEntries.size(); } + size_t partialUploadSize() const { return m_partialEntries.size(); } + size_t copySize() const { return m_copyEntries.size(); } + + bool hasMoreUpdates() const; + +private: + void clearUploadsToEvictedResources(Deque& entryQueue); + Deque m_fullEntries; + Deque m_partialEntries; + Deque m_copyEntries; + + DISALLOW_COPY_AND_ASSIGN(CCTextureUpdateQueue); +}; + +} + +#endif // CCTextureUpdateQueue_h diff --git a/cc/texture_uploader.h b/cc/texture_uploader.h index 638cbb2..5505204 100644 --- a/cc/texture_uploader.h +++ b/cc/texture_uploader.h @@ -1,3 +1,32 @@ // Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef TextureUploader_h +#define TextureUploader_h + +#include "LayerTextureUpdater.h" + +namespace cc { + +class TextureUploader { +public: + struct Parameters { + LayerTextureUpdater::Texture* texture; + IntRect sourceRect; + IntSize destOffset; + }; + + virtual ~TextureUploader() { } + + virtual size_t numBlockingUploads() = 0; + virtual void markPendingUploadsAsNonBlocking() = 0; + + // Returns our throughput on the GPU process + virtual double estimatedTexturesPerSecond() = 0; + virtual void uploadTexture(CCResourceProvider*, Parameters) = 0; +}; + +} + +#endif diff --git a/cc/thread.h b/cc/thread.h index 638cbb2..1ac4946 100644 --- a/cc/thread.h +++ b/cc/thread.h @@ -1,3 +1,43 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. +// Copyright 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CCThread_h +#define CCThread_h + +#include "base/basictypes.h" +#include "base/threading/platform_thread.h" +#include + +namespace cc { + +// CCThread provides basic infrastructure for messaging with the compositor in a +// platform-neutral way. +class CCThread { +public: + virtual ~CCThread() { } + + class Task { + public: + virtual ~Task() { } + virtual void performTask() = 0; + void* instance() const { return m_instance; } + protected: + Task(void* instance) : m_instance(instance) { } + void* m_instance; + private: + DISALLOW_COPY_AND_ASSIGN(Task); + }; + + // Executes the task on context's thread asynchronously. + virtual void postTask(PassOwnPtr) = 0; + + // Executes the task after the specified delay. + virtual void postDelayedTask(PassOwnPtr, long long delayMs) = 0; + + virtual base::PlatformThreadId threadID() const = 0; +}; + +} + +#endif diff --git a/cc/thread_proxy.cc b/cc/thread_proxy.cc new file mode 100644 index 0000000..1d3f2d3 --- /dev/null +++ b/cc/thread_proxy.cc @@ -0,0 +1,957 @@ +// Copyright 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#include "CCThreadProxy.h" + +#include "CCDelayBasedTimeSource.h" +#include "CCDrawQuad.h" +#include "CCFrameRateController.h" +#include "CCGraphicsContext.h" +#include "CCInputHandler.h" +#include "CCLayerTreeHost.h" +#include "CCScheduler.h" +#include "CCScopedThreadProxy.h" +#include "CCThreadTask.h" +#include "TraceEvent.h" +#include +#include + +using namespace WTF; +using WebKit::WebSharedGraphicsContext3D; + +namespace { + +// Measured in seconds. +const double contextRecreationTickRate = 0.03; + +} // namespace + +namespace cc { + +scoped_ptr CCThreadProxy::create(CCLayerTreeHost* layerTreeHost) +{ + return make_scoped_ptr(new CCThreadProxy(layerTreeHost)).PassAs(); +} + +CCThreadProxy::CCThreadProxy(CCLayerTreeHost* layerTreeHost) + : m_animateRequested(false) + , m_commitRequested(false) + , m_commitRequestSentToImplThread(false) + , m_forcedCommitRequested(false) + , m_layerTreeHost(layerTreeHost) + , m_rendererInitialized(false) + , m_started(false) + , m_texturesAcquired(true) + , m_inCompositeAndReadback(false) + , m_mainThreadProxy(CCScopedThreadProxy::create(CCProxy::mainThread())) + , m_beginFrameCompletionEventOnImplThread(0) + , m_readbackRequestOnImplThread(0) + , m_commitCompletionEventOnImplThread(0) + , m_textureAcquisitionCompletionEventOnImplThread(0) + , m_resetContentsTexturesPurgedAfterCommitOnImplThread(false) + , m_nextFrameIsNewlyCommittedFrameOnImplThread(false) + , m_renderVSyncEnabled(layerTreeHost->settings().renderVSyncEnabled) + , m_totalCommitCount(0) +{ + TRACE_EVENT0("cc", "CCThreadProxy::CCThreadProxy"); + ASSERT(isMainThread()); +} + +CCThreadProxy::~CCThreadProxy() +{ + TRACE_EVENT0("cc", "CCThreadProxy::~CCThreadProxy"); + ASSERT(isMainThread()); + ASSERT(!m_started); +} + +bool CCThreadProxy::compositeAndReadback(void *pixels, const IntRect& rect) +{ + TRACE_EVENT0("cc", "CCThreadPRoxy::compositeAndReadback"); + ASSERT(isMainThread()); + ASSERT(m_layerTreeHost); + + if (!m_layerTreeHost->initializeRendererIfNeeded()) { + TRACE_EVENT0("cc", "compositeAndReadback_EarlyOut_LR_Uninitialized"); + return false; + } + + + // Perform a synchronous commit. + { + DebugScopedSetMainThreadBlocked mainThreadBlocked; + CCCompletionEvent beginFrameCompletion; + CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::forceBeginFrameOnImplThread, &beginFrameCompletion)); + beginFrameCompletion.wait(); + } + m_inCompositeAndReadback = true; + beginFrame(); + m_inCompositeAndReadback = false; + + // Perform a synchronous readback. + ReadbackRequest request; + request.rect = rect; + request.pixels = pixels; + { + DebugScopedSetMainThreadBlocked mainThreadBlocked; + CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::requestReadbackOnImplThread, &request)); + request.completion.wait(); + } + return request.success; +} + +void CCThreadProxy::requestReadbackOnImplThread(ReadbackRequest* request) +{ + ASSERT(CCProxy::isImplThread()); + ASSERT(!m_readbackRequestOnImplThread); + if (!m_layerTreeHostImpl.get()) { + request->success = false; + request->completion.signal(); + return; + } + + m_readbackRequestOnImplThread = request; + m_schedulerOnImplThread->setNeedsRedraw(); + m_schedulerOnImplThread->setNeedsForcedRedraw(); +} + +void CCThreadProxy::startPageScaleAnimation(const IntSize& targetPosition, bool useAnchor, float scale, double duration) +{ + ASSERT(CCProxy::isMainThread()); + CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::requestStartPageScaleAnimationOnImplThread, targetPosition, useAnchor, scale, duration)); +} + +void CCThreadProxy::requestStartPageScaleAnimationOnImplThread(IntSize targetPosition, bool useAnchor, float scale, double duration) +{ + ASSERT(CCProxy::isImplThread()); + if (m_layerTreeHostImpl.get()) + m_layerTreeHostImpl->startPageScaleAnimation(targetPosition, useAnchor, scale, monotonicallyIncreasingTime(), duration); +} + +void CCThreadProxy::finishAllRendering() +{ + ASSERT(CCProxy::isMainThread()); + + // Make sure all GL drawing is finished on the impl thread. + DebugScopedSetMainThreadBlocked mainThreadBlocked; + CCCompletionEvent completion; + CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::finishAllRenderingOnImplThread, &completion)); + completion.wait(); +} + +bool CCThreadProxy::isStarted() const +{ + ASSERT(CCProxy::isMainThread()); + return m_started; +} + +bool CCThreadProxy::initializeContext() +{ + TRACE_EVENT0("cc", "CCThreadProxy::initializeContext"); + scoped_ptr context = m_layerTreeHost->createContext(); + if (!context.get()) + return false; + + CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::initializeContextOnImplThread, + context.release())); + return true; +} + +void CCThreadProxy::setSurfaceReady() +{ + TRACE_EVENT0("cc", "CCThreadProxy::setSurfaceReady"); + CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::setSurfaceReadyOnImplThread)); +} + +void CCThreadProxy::setSurfaceReadyOnImplThread() +{ + TRACE_EVENT0("cc", "CCThreadProxy::setSurfaceReadyOnImplThread"); + m_schedulerOnImplThread->setCanBeginFrame(true); +} + +void CCThreadProxy::setVisible(bool visible) +{ + TRACE_EVENT0("cc", "CCThreadProxy::setVisible"); + DebugScopedSetMainThreadBlocked mainThreadBlocked; + CCCompletionEvent completion; + CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::setVisibleOnImplThread, &completion, visible)); + completion.wait(); +} + +void CCThreadProxy::setVisibleOnImplThread(CCCompletionEvent* completion, bool visible) +{ + TRACE_EVENT0("cc", "CCThreadProxy::setVisibleOnImplThread"); + m_layerTreeHostImpl->setVisible(visible); + m_schedulerOnImplThread->setVisible(visible); + completion->signal(); +} + +bool CCThreadProxy::initializeRenderer() +{ + TRACE_EVENT0("cc", "CCThreadProxy::initializeRenderer"); + // Make a blocking call to initializeRendererOnImplThread. The results of that call + // are pushed into the initializeSucceeded and capabilities local variables. + CCCompletionEvent completion; + bool initializeSucceeded = false; + RendererCapabilities capabilities; + DebugScopedSetMainThreadBlocked mainThreadBlocked; + CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::initializeRendererOnImplThread, + &completion, + &initializeSucceeded, + &capabilities)); + completion.wait(); + + if (initializeSucceeded) { + m_rendererInitialized = true; + m_RendererCapabilitiesMainThreadCopy = capabilities; + } + return initializeSucceeded; +} + +bool CCThreadProxy::recreateContext() +{ + TRACE_EVENT0("cc", "CCThreadProxy::recreateContext"); + ASSERT(isMainThread()); + + // Try to create the context. + scoped_ptr context = m_layerTreeHost->createContext(); + if (!context.get()) + return false; + if (m_layerTreeHost->needsSharedContext()) + if (!WebSharedGraphicsContext3D::createCompositorThreadContext()) + return false; + + // Make a blocking call to recreateContextOnImplThread. The results of that + // call are pushed into the recreateSucceeded and capabilities local + // variables. + CCCompletionEvent completion; + bool recreateSucceeded = false; + RendererCapabilities capabilities; + DebugScopedSetMainThreadBlocked mainThreadBlocked; + CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::recreateContextOnImplThread, + &completion, + context.release(), + &recreateSucceeded, + &capabilities)); + completion.wait(); + + if (recreateSucceeded) + m_RendererCapabilitiesMainThreadCopy = capabilities; + return recreateSucceeded; +} + +void CCThreadProxy::renderingStats(CCRenderingStats* stats) +{ + ASSERT(isMainThread()); + + DebugScopedSetMainThreadBlocked mainThreadBlocked; + CCCompletionEvent completion; + CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::renderingStatsOnImplThread, + &completion, + stats)); + stats->totalCommitTimeInSeconds = m_totalCommitTime.InSecondsF(); + stats->totalCommitCount = m_totalCommitCount; + + completion.wait(); +} + +const RendererCapabilities& CCThreadProxy::rendererCapabilities() const +{ + ASSERT(m_rendererInitialized); + return m_RendererCapabilitiesMainThreadCopy; +} + +void CCThreadProxy::loseContext() +{ + CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::didLoseContextOnImplThread)); +} + +void CCThreadProxy::setNeedsAnimate() +{ + ASSERT(isMainThread()); + if (m_animateRequested) + return; + + TRACE_EVENT0("cc", "CCThreadProxy::setNeedsAnimate"); + m_animateRequested = true; + + if (m_commitRequestSentToImplThread) + return; + m_commitRequestSentToImplThread = true; + CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::setNeedsCommitOnImplThread)); +} + +void CCThreadProxy::setNeedsCommit() +{ + ASSERT(isMainThread()); + if (m_commitRequested) + return; + TRACE_EVENT0("cc", "CCThreadProxy::setNeedsCommit"); + m_commitRequested = true; + + if (m_commitRequestSentToImplThread) + return; + m_commitRequestSentToImplThread = true; + CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::setNeedsCommitOnImplThread)); +} + +void CCThreadProxy::didLoseContextOnImplThread() +{ + ASSERT(isImplThread()); + TRACE_EVENT0("cc", "CCThreadProxy::didLoseContextOnImplThread"); + m_schedulerOnImplThread->didLoseContext(); +} + +void CCThreadProxy::onSwapBuffersCompleteOnImplThread() +{ + ASSERT(isImplThread()); + TRACE_EVENT0("cc", "CCThreadProxy::onSwapBuffersCompleteOnImplThread"); + m_schedulerOnImplThread->didSwapBuffersComplete(); + m_mainThreadProxy->postTask(createCCThreadTask(this, &CCThreadProxy::didCompleteSwapBuffers)); +} + +void CCThreadProxy::onVSyncParametersChanged(double monotonicTimebase, double intervalInSeconds) +{ + ASSERT(isImplThread()); + TRACE_EVENT2("cc", "CCThreadProxy::onVSyncParametersChanged", "monotonicTimebase", monotonicTimebase, "intervalInSeconds", intervalInSeconds); + base::TimeTicks timebase = base::TimeTicks::FromInternalValue(monotonicTimebase * base::Time::kMicrosecondsPerSecond); + base::TimeDelta interval = base::TimeDelta::FromMicroseconds(intervalInSeconds * base::Time::kMicrosecondsPerSecond); + m_schedulerOnImplThread->setTimebaseAndInterval(timebase, interval); +} + +void CCThreadProxy::onCanDrawStateChanged(bool canDraw) +{ + ASSERT(isImplThread()); + TRACE_EVENT1("cc", "CCThreadProxy::onCanDrawStateChanged", "canDraw", canDraw); + m_schedulerOnImplThread->setCanDraw(canDraw); +} + +void CCThreadProxy::setNeedsCommitOnImplThread() +{ + ASSERT(isImplThread()); + TRACE_EVENT0("cc", "CCThreadProxy::setNeedsCommitOnImplThread"); + m_schedulerOnImplThread->setNeedsCommit(); +} + +void CCThreadProxy::setNeedsForcedCommitOnImplThread() +{ + ASSERT(isImplThread()); + TRACE_EVENT0("cc", "CCThreadProxy::setNeedsForcedCommitOnImplThread"); + m_schedulerOnImplThread->setNeedsCommit(); + m_schedulerOnImplThread->setNeedsForcedCommit(); +} + +void CCThreadProxy::postAnimationEventsToMainThreadOnImplThread(scoped_ptr events, double wallClockTime) +{ + ASSERT(isImplThread()); + TRACE_EVENT0("cc", "CCThreadProxy::postAnimationEventsToMainThreadOnImplThread"); + m_mainThreadProxy->postTask(createCCThreadTask(this, &CCThreadProxy::setAnimationEvents, events.release(), wallClockTime)); +} + +void CCThreadProxy::releaseContentsTexturesOnImplThread() +{ + ASSERT(isImplThread()); + + m_layerTreeHost->reduceContentsTexturesMemoryOnImplThread(0, m_layerTreeHostImpl->resourceProvider()); + + // Make sure that we get a new commit before drawing again. + m_resetContentsTexturesPurgedAfterCommitOnImplThread = false; + // The texture upload queue may reference textures that were just purged, clear + // them from the queue. + if (m_currentTextureUpdateControllerOnImplThread.get() && m_layerTreeHost->evictedContentsTexturesBackingsExist()) + m_currentTextureUpdateControllerOnImplThread->discardUploadsToEvictedResources(); +} + +void CCThreadProxy::setNeedsRedraw() +{ + ASSERT(isMainThread()); + TRACE_EVENT0("cc", "CCThreadProxy::setNeedsRedraw"); + CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::setFullRootLayerDamageOnImplThread)); + CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::setNeedsRedrawOnImplThread)); +} + +bool CCThreadProxy::commitRequested() const +{ + ASSERT(isMainThread()); + return m_commitRequested; +} + +void CCThreadProxy::setNeedsRedrawOnImplThread() +{ + ASSERT(isImplThread()); + TRACE_EVENT0("cc", "CCThreadProxy::setNeedsRedrawOnImplThread"); + m_schedulerOnImplThread->setNeedsRedraw(); +} + +void CCThreadProxy::start() +{ + ASSERT(isMainThread()); + ASSERT(CCProxy::implThread()); + // Create LayerTreeHostImpl. + DebugScopedSetMainThreadBlocked mainThreadBlocked; + CCCompletionEvent completion; + scoped_ptr handler = m_layerTreeHost->createInputHandler(); + CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::initializeImplOnImplThread, &completion, handler.release())); + completion.wait(); + + m_started = true; +} + +void CCThreadProxy::stop() +{ + TRACE_EVENT0("cc", "CCThreadProxy::stop"); + ASSERT(isMainThread()); + ASSERT(m_started); + + // Synchronously deletes the impl. + { + DebugScopedSetMainThreadBlocked mainThreadBlocked; + + CCCompletionEvent completion; + CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::layerTreeHostClosedOnImplThread, &completion)); + completion.wait(); + } + + m_mainThreadProxy->shutdown(); // Stop running tasks posted to us. + + ASSERT(!m_layerTreeHostImpl.get()); // verify that the impl deleted. + m_layerTreeHost = 0; + m_started = false; +} + +void CCThreadProxy::forceSerializeOnSwapBuffers() +{ + DebugScopedSetMainThreadBlocked mainThreadBlocked; + CCCompletionEvent completion; + CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::forceSerializeOnSwapBuffersOnImplThread, &completion)); + completion.wait(); +} + +void CCThreadProxy::forceSerializeOnSwapBuffersOnImplThread(CCCompletionEvent* completion) +{ + if (m_rendererInitialized) + m_layerTreeHostImpl->renderer()->doNoOp(); + completion->signal(); +} + + +void CCThreadProxy::finishAllRenderingOnImplThread(CCCompletionEvent* completion) +{ + TRACE_EVENT0("cc", "CCThreadProxy::finishAllRenderingOnImplThread"); + ASSERT(isImplThread()); + m_layerTreeHostImpl->finishAllRendering(); + completion->signal(); +} + +void CCThreadProxy::forceBeginFrameOnImplThread(CCCompletionEvent* completion) +{ + TRACE_EVENT0("cc", "CCThreadProxy::forceBeginFrameOnImplThread"); + ASSERT(!m_beginFrameCompletionEventOnImplThread); + + if (m_schedulerOnImplThread->commitPending()) { + completion->signal(); + return; + } + + m_beginFrameCompletionEventOnImplThread = completion; + setNeedsForcedCommitOnImplThread(); +} + +void CCThreadProxy::scheduledActionBeginFrame() +{ + TRACE_EVENT0("cc", "CCThreadProxy::scheduledActionBeginFrame"); + ASSERT(!m_pendingBeginFrameRequest); + m_pendingBeginFrameRequest = adoptPtr(new BeginFrameAndCommitState()); + m_pendingBeginFrameRequest->monotonicFrameBeginTime = monotonicallyIncreasingTime(); + m_pendingBeginFrameRequest->scrollInfo = m_layerTreeHostImpl->processScrollDeltas(); + m_pendingBeginFrameRequest->implTransform = m_layerTreeHostImpl->implTransform(); + m_pendingBeginFrameRequest->memoryAllocationLimitBytes = m_layerTreeHostImpl->memoryAllocationLimitBytes(); + m_layerTreeHost->getEvictedContentTexturesBackings(m_pendingBeginFrameRequest->evictedContentsTexturesBackings); + + m_mainThreadProxy->postTask(createCCThreadTask(this, &CCThreadProxy::beginFrame)); + + if (m_beginFrameCompletionEventOnImplThread) { + m_beginFrameCompletionEventOnImplThread->signal(); + m_beginFrameCompletionEventOnImplThread = 0; + } +} + +void CCThreadProxy::beginFrame() +{ + TRACE_EVENT0("cc", "CCThreadProxy::beginFrame"); + ASSERT(isMainThread()); + if (!m_layerTreeHost) + return; + + if (!m_pendingBeginFrameRequest) { + TRACE_EVENT0("cc", "EarlyOut_StaleBeginFrameMessage"); + return; + } + + if (m_layerTreeHost->needsSharedContext() && !WebSharedGraphicsContext3D::haveCompositorThreadContext()) + WebSharedGraphicsContext3D::createCompositorThreadContext(); + + OwnPtr request(m_pendingBeginFrameRequest.release()); + + // Do not notify the impl thread of commit requests that occur during + // the apply/animate/layout part of the beginFrameAndCommit process since + // those commit requests will get painted immediately. Once we have done + // the paint, m_commitRequested will be set to false to allow new commit + // requests to be scheduled. + m_commitRequested = true; + m_commitRequestSentToImplThread = true; + + // On the other hand, the animationRequested flag needs to be cleared + // here so that any animation requests generated by the apply or animate + // callbacks will trigger another frame. + m_animateRequested = false; + + // FIXME: technically, scroll deltas need to be applied for dropped commits as well. + // Re-do the commit flow so that we don't send the scrollInfo on the BFAC message. + m_layerTreeHost->applyScrollAndScale(*request->scrollInfo); + m_layerTreeHost->setImplTransform(request->implTransform); + + if (!m_inCompositeAndReadback && !m_layerTreeHost->visible()) { + m_commitRequested = false; + m_commitRequestSentToImplThread = false; + m_forcedCommitRequested = false; + + TRACE_EVENT0("cc", "EarlyOut_NotVisible"); + CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::beginFrameAbortedOnImplThread)); + return; + } + + m_layerTreeHost->willBeginFrame(); + + m_layerTreeHost->updateAnimations(request->monotonicFrameBeginTime); + m_layerTreeHost->layout(); + + // Clear the commit flag after updating animations and layout here --- objects that only + // layout when painted will trigger another setNeedsCommit inside + // updateLayers. + m_commitRequested = false; + m_commitRequestSentToImplThread = false; + m_forcedCommitRequested = false; + + if (!m_layerTreeHost->initializeRendererIfNeeded()) { + TRACE_EVENT0("cc", "EarlyOut_InitializeFailed"); + return; + } + + m_layerTreeHost->unlinkEvictedContentTexturesBackings(request->evictedContentsTexturesBackings); + + OwnPtr queue = adoptPtr(new CCTextureUpdateQueue); + m_layerTreeHost->updateLayers(*(queue.get()), request->memoryAllocationLimitBytes); + + // Once single buffered layers are committed, they cannot be modified until + // they are drawn by the impl thread. + m_texturesAcquired = false; + + m_layerTreeHost->willCommit(); + // Before applying scrolls and calling animate, we set m_animateRequested to + // false. If it is true now, it means setNeedAnimate was called again, but + // during a state when m_commitRequestSentToImplThread = true. We need to + // force that call to happen again now so that the commit request is sent to + // the impl thread. + if (m_animateRequested) { + // Forces setNeedsAnimate to consider posting a commit task. + m_animateRequested = false; + setNeedsAnimate(); + } + + // Notify the impl thread that the beginFrame has completed. This will + // begin the commit process, which is blocking from the main thread's + // point of view, but asynchronously performed on the impl thread, + // coordinated by the CCScheduler. + { + TRACE_EVENT0("cc", "commit"); + + DebugScopedSetMainThreadBlocked mainThreadBlocked; + + base::TimeTicks startTime = base::TimeTicks::HighResNow(); + CCCompletionEvent completion; + CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::beginFrameCompleteOnImplThread, &completion, queue.release())); + completion.wait(); + base::TimeTicks endTime = base::TimeTicks::HighResNow(); + + m_totalCommitTime += endTime - startTime; + m_totalCommitCount++; + } + + m_layerTreeHost->commitComplete(); + m_layerTreeHost->didBeginFrame(); +} + +void CCThreadProxy::beginFrameCompleteOnImplThread(CCCompletionEvent* completion, PassOwnPtr queue) +{ + TRACE_EVENT0("cc", "CCThreadProxy::beginFrameCompleteOnImplThread"); + ASSERT(!m_commitCompletionEventOnImplThread); + ASSERT(isImplThread() && isMainThreadBlocked()); + ASSERT(m_schedulerOnImplThread); + ASSERT(m_schedulerOnImplThread->commitPending()); + + if (!m_layerTreeHostImpl.get()) { + TRACE_EVENT0("cc", "EarlyOut_NoLayerTree"); + completion->signal(); + return; + } + + // Clear any uploads we were making to textures linked to evicted + // resources + if (m_layerTreeHost->evictedContentsTexturesBackingsExist()) + queue->clearUploadsToEvictedResources(); + + // If we unlinked evicted textures on the main thread, delete them now. + if (m_layerTreeHost->deleteEvictedContentTexturesBackings()) { + // Deleting the evicted textures' backings resulted in some textures in the + // layer tree being invalidated (unliked from their backings). Kick off + // another commit to fill them again. + setNeedsCommitOnImplThread(); + } else { + // The layer tree does not reference evicted textures, so mark that we + // can draw this tree once this commit is complete. + if (m_layerTreeHostImpl->contentsTexturesPurged()) + m_resetContentsTexturesPurgedAfterCommitOnImplThread = true; + } + + m_currentTextureUpdateControllerOnImplThread = CCTextureUpdateController::create(this, CCProxy::implThread(), queue, m_layerTreeHostImpl->resourceProvider(), m_layerTreeHostImpl->resourceProvider()->textureUploader()); + m_currentTextureUpdateControllerOnImplThread->performMoreUpdates( + m_schedulerOnImplThread->anticipatedDrawTime()); + + m_commitCompletionEventOnImplThread = completion; +} + +void CCThreadProxy::beginFrameAbortedOnImplThread() +{ + TRACE_EVENT0("cc", "CCThreadProxy::beginFrameAbortedOnImplThread"); + ASSERT(isImplThread()); + ASSERT(m_schedulerOnImplThread); + ASSERT(m_schedulerOnImplThread->commitPending()); + + m_schedulerOnImplThread->beginFrameAborted(); +} + +void CCThreadProxy::scheduledActionCommit() +{ + TRACE_EVENT0("cc", "CCThreadProxy::scheduledActionCommit"); + ASSERT(isImplThread()); + ASSERT(m_commitCompletionEventOnImplThread); + ASSERT(m_currentTextureUpdateControllerOnImplThread); + + // Complete all remaining texture updates. + m_currentTextureUpdateControllerOnImplThread->finalize(); + m_currentTextureUpdateControllerOnImplThread.clear(); + + m_layerTreeHostImpl->beginCommit(); + + m_layerTreeHost->beginCommitOnImplThread(m_layerTreeHostImpl.get()); + m_layerTreeHost->finishCommitOnImplThread(m_layerTreeHostImpl.get()); + + if (m_resetContentsTexturesPurgedAfterCommitOnImplThread) { + m_resetContentsTexturesPurgedAfterCommitOnImplThread = false; + m_layerTreeHostImpl->resetContentsTexturesPurged(); + } + + m_layerTreeHostImpl->commitComplete(); + + m_nextFrameIsNewlyCommittedFrameOnImplThread = true; + + m_commitCompletionEventOnImplThread->signal(); + m_commitCompletionEventOnImplThread = 0; + + // SetVisible kicks off the next scheduler action, so this must be last. + m_schedulerOnImplThread->setVisible(m_layerTreeHostImpl->visible()); +} + +void CCThreadProxy::scheduledActionBeginContextRecreation() +{ + ASSERT(isImplThread()); + m_mainThreadProxy->postTask(createCCThreadTask(this, &CCThreadProxy::beginContextRecreation)); +} + +CCScheduledActionDrawAndSwapResult CCThreadProxy::scheduledActionDrawAndSwapInternal(bool forcedDraw) +{ + TRACE_EVENT0("cc", "CCThreadProxy::scheduledActionDrawAndSwap"); + CCScheduledActionDrawAndSwapResult result; + result.didDraw = false; + result.didSwap = false; + ASSERT(isImplThread()); + ASSERT(m_layerTreeHostImpl.get()); + if (!m_layerTreeHostImpl.get()) + return result; + + ASSERT(m_layerTreeHostImpl->renderer()); + if (!m_layerTreeHostImpl->renderer()) + return result; + + // FIXME: compute the frame display time more intelligently + double monotonicTime = monotonicallyIncreasingTime(); + double wallClockTime = currentTime(); + + if (m_inputHandlerOnImplThread.get()) + m_inputHandlerOnImplThread->animate(monotonicTime); + m_layerTreeHostImpl->animate(monotonicTime, wallClockTime); + + // This method is called on a forced draw, regardless of whether we are able to produce a frame, + // as the calling site on main thread is blocked until its request completes, and we signal + // completion here. If canDraw() is false, we will indicate success=false to the caller, but we + // must still signal completion to avoid deadlock. + + // We guard prepareToDraw() with canDraw() because it always returns a valid frame, so can only + // be used when such a frame is possible. Since drawLayers() depends on the result of + // prepareToDraw(), it is guarded on canDraw() as well. + + CCLayerTreeHostImpl::FrameData frame; + bool drawFrame = m_layerTreeHostImpl->canDraw() && (m_layerTreeHostImpl->prepareToDraw(frame) || forcedDraw); + if (drawFrame) { + m_layerTreeHostImpl->drawLayers(frame); + result.didDraw = true; + } + m_layerTreeHostImpl->didDrawAllLayers(frame); + + // Check for a pending compositeAndReadback. + if (m_readbackRequestOnImplThread) { + m_readbackRequestOnImplThread->success = false; + if (drawFrame) { + m_layerTreeHostImpl->readback(m_readbackRequestOnImplThread->pixels, m_readbackRequestOnImplThread->rect); + m_readbackRequestOnImplThread->success = !m_layerTreeHostImpl->isContextLost(); + } + m_readbackRequestOnImplThread->completion.signal(); + m_readbackRequestOnImplThread = 0; + } else if (drawFrame) + result.didSwap = m_layerTreeHostImpl->swapBuffers(); + + // Tell the main thread that the the newly-commited frame was drawn. + if (m_nextFrameIsNewlyCommittedFrameOnImplThread) { + m_nextFrameIsNewlyCommittedFrameOnImplThread = false; + m_mainThreadProxy->postTask(createCCThreadTask(this, &CCThreadProxy::didCommitAndDrawFrame)); + } + + return result; +} + +void CCThreadProxy::acquireLayerTextures() +{ + // Called when the main thread needs to modify a layer texture that is used + // directly by the compositor. + // This method will block until the next compositor draw if there is a + // previously committed frame that is still undrawn. This is necessary to + // ensure that the main thread does not monopolize access to the textures. + ASSERT(isMainThread()); + + if (m_texturesAcquired) + return; + + TRACE_EVENT0("cc", "CCThreadProxy::acquireLayerTextures"); + DebugScopedSetMainThreadBlocked mainThreadBlocked; + CCCompletionEvent completion; + CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::acquireLayerTexturesForMainThreadOnImplThread, &completion)); + completion.wait(); // Block until it is safe to write to layer textures from the main thread. + + m_texturesAcquired = true; +} + +void CCThreadProxy::acquireLayerTexturesForMainThreadOnImplThread(CCCompletionEvent* completion) +{ + ASSERT(isImplThread()); + ASSERT(!m_textureAcquisitionCompletionEventOnImplThread); + + m_textureAcquisitionCompletionEventOnImplThread = completion; + m_schedulerOnImplThread->setMainThreadNeedsLayerTextures(); +} + +void CCThreadProxy::scheduledActionAcquireLayerTexturesForMainThread() +{ + ASSERT(m_textureAcquisitionCompletionEventOnImplThread); + m_textureAcquisitionCompletionEventOnImplThread->signal(); + m_textureAcquisitionCompletionEventOnImplThread = 0; +} + +CCScheduledActionDrawAndSwapResult CCThreadProxy::scheduledActionDrawAndSwapIfPossible() +{ + return scheduledActionDrawAndSwapInternal(false); +} + +CCScheduledActionDrawAndSwapResult CCThreadProxy::scheduledActionDrawAndSwapForced() +{ + return scheduledActionDrawAndSwapInternal(true); +} + +void CCThreadProxy::didAnticipatedDrawTimeChange(base::TimeTicks time) +{ + if (!m_currentTextureUpdateControllerOnImplThread) + return; + + m_currentTextureUpdateControllerOnImplThread->performMoreUpdates(time); +} + +void CCThreadProxy::readyToFinalizeTextureUpdates() +{ + ASSERT(isImplThread()); + m_schedulerOnImplThread->beginFrameComplete(); +} + +void CCThreadProxy::didCommitAndDrawFrame() +{ + ASSERT(isMainThread()); + if (!m_layerTreeHost) + return; + m_layerTreeHost->didCommitAndDrawFrame(); +} + +void CCThreadProxy::didCompleteSwapBuffers() +{ + ASSERT(isMainThread()); + if (!m_layerTreeHost) + return; + m_layerTreeHost->didCompleteSwapBuffers(); +} + +void CCThreadProxy::setAnimationEvents(CCAnimationEventsVector* passed_events, double wallClockTime) +{ + scoped_ptr events(make_scoped_ptr(passed_events)); + + TRACE_EVENT0("cc", "CCThreadProxy::setAnimationEvents"); + ASSERT(isMainThread()); + if (!m_layerTreeHost) + return; + m_layerTreeHost->setAnimationEvents(events.Pass(), wallClockTime); +} + +class CCThreadProxyContextRecreationTimer : public CCTimer, CCTimerClient { +public: + static PassOwnPtr create(CCThreadProxy* proxy) { return adoptPtr(new CCThreadProxyContextRecreationTimer(proxy)); } + + virtual void onTimerFired() OVERRIDE + { + m_proxy->tryToRecreateContext(); + } + +private: + explicit CCThreadProxyContextRecreationTimer(CCThreadProxy* proxy) + : CCTimer(CCProxy::mainThread(), this) + , m_proxy(proxy) + { + } + + CCThreadProxy* m_proxy; +}; + +void CCThreadProxy::beginContextRecreation() +{ + TRACE_EVENT0("cc", "CCThreadProxy::beginContextRecreation"); + ASSERT(isMainThread()); + ASSERT(!m_contextRecreationTimer); + m_contextRecreationTimer = CCThreadProxyContextRecreationTimer::create(this); + m_layerTreeHost->didLoseContext(); + m_contextRecreationTimer->startOneShot(contextRecreationTickRate); +} + +void CCThreadProxy::tryToRecreateContext() +{ + ASSERT(isMainThread()); + ASSERT(m_layerTreeHost); + CCLayerTreeHost::RecreateResult result = m_layerTreeHost->recreateContext(); + if (result == CCLayerTreeHost::RecreateFailedButTryAgain) + m_contextRecreationTimer->startOneShot(contextRecreationTickRate); + else if (result == CCLayerTreeHost::RecreateSucceeded) + m_contextRecreationTimer.clear(); +} + +void CCThreadProxy::initializeImplOnImplThread(CCCompletionEvent* completion, CCInputHandler* handler) +{ + TRACE_EVENT0("cc", "CCThreadProxy::initializeImplOnImplThread"); + ASSERT(isImplThread()); + m_layerTreeHostImpl = m_layerTreeHost->createLayerTreeHostImpl(this); + const base::TimeDelta displayRefreshInterval = base::TimeDelta::FromMicroseconds(base::Time::kMicrosecondsPerSecond / 60); + scoped_ptr frameRateController; + if (m_renderVSyncEnabled) + frameRateController.reset(new CCFrameRateController(CCDelayBasedTimeSource::create(displayRefreshInterval, CCProxy::implThread()))); + else + frameRateController.reset(new CCFrameRateController(CCProxy::implThread())); + m_schedulerOnImplThread = CCScheduler::create(this, frameRateController.Pass()); + m_schedulerOnImplThread->setVisible(m_layerTreeHostImpl->visible()); + + m_inputHandlerOnImplThread = scoped_ptr(handler); + if (m_inputHandlerOnImplThread.get()) + m_inputHandlerOnImplThread->bindToClient(m_layerTreeHostImpl.get()); + + completion->signal(); +} + +void CCThreadProxy::initializeContextOnImplThread(CCGraphicsContext* context) +{ + TRACE_EVENT0("cc", "CCThreadProxy::initializeContextOnImplThread"); + ASSERT(isImplThread()); + m_contextBeforeInitializationOnImplThread = scoped_ptr(context).Pass(); +} + +void CCThreadProxy::initializeRendererOnImplThread(CCCompletionEvent* completion, bool* initializeSucceeded, RendererCapabilities* capabilities) +{ + TRACE_EVENT0("cc", "CCThreadProxy::initializeRendererOnImplThread"); + ASSERT(isImplThread()); + ASSERT(m_contextBeforeInitializationOnImplThread.get()); + *initializeSucceeded = m_layerTreeHostImpl->initializeRenderer(m_contextBeforeInitializationOnImplThread.Pass()); + if (*initializeSucceeded) { + *capabilities = m_layerTreeHostImpl->rendererCapabilities(); + m_schedulerOnImplThread->setSwapBuffersCompleteSupported( + capabilities->usingSwapCompleteCallback); + } + + completion->signal(); +} + +void CCThreadProxy::layerTreeHostClosedOnImplThread(CCCompletionEvent* completion) +{ + TRACE_EVENT0("cc", "CCThreadProxy::layerTreeHostClosedOnImplThread"); + ASSERT(isImplThread()); + m_layerTreeHost->deleteContentsTexturesOnImplThread(m_layerTreeHostImpl->resourceProvider()); + m_inputHandlerOnImplThread.reset(); + m_layerTreeHostImpl.reset(); + m_schedulerOnImplThread.clear(); + completion->signal(); +} + +void CCThreadProxy::setFullRootLayerDamageOnImplThread() +{ + ASSERT(isImplThread()); + m_layerTreeHostImpl->setFullRootLayerDamage(); +} + +size_t CCThreadProxy::maxPartialTextureUpdates() const +{ + return CCTextureUpdateController::maxPartialTextureUpdates(); +} + +void CCThreadProxy::recreateContextOnImplThread(CCCompletionEvent* completion, CCGraphicsContext* contextPtr, bool* recreateSucceeded, RendererCapabilities* capabilities) +{ + TRACE_EVENT0("cc", "CCThreadProxy::recreateContextOnImplThread"); + ASSERT(isImplThread()); + m_layerTreeHost->deleteContentsTexturesOnImplThread(m_layerTreeHostImpl->resourceProvider()); + *recreateSucceeded = m_layerTreeHostImpl->initializeRenderer(scoped_ptr(contextPtr).Pass()); + if (*recreateSucceeded) { + *capabilities = m_layerTreeHostImpl->rendererCapabilities(); + m_schedulerOnImplThread->didRecreateContext(); + } + completion->signal(); +} + +void CCThreadProxy::renderingStatsOnImplThread(CCCompletionEvent* completion, CCRenderingStats* stats) +{ + ASSERT(isImplThread()); + m_layerTreeHostImpl->renderingStats(stats); + completion->signal(); +} + +CCThreadProxy::BeginFrameAndCommitState::BeginFrameAndCommitState() + : monotonicFrameBeginTime(0) +{ +} + +CCThreadProxy::BeginFrameAndCommitState::~BeginFrameAndCommitState() +{ +} + +} // namespace cc diff --git a/cc/thread_proxy.h b/cc/thread_proxy.h index 638cbb2..a6ea6ac 100644 --- a/cc/thread_proxy.h +++ b/cc/thread_proxy.h @@ -1,3 +1,185 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. +// Copyright 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CCThreadProxy_h +#define CCThreadProxy_h + +#include "CCAnimationEvents.h" +#include "CCCompletionEvent.h" +#include "CCLayerTreeHostImpl.h" +#include "CCProxy.h" +#include "CCScheduler.h" +#include "CCTextureUpdateController.h" +#include +#include + +namespace cc { + +class CCInputHandler; +class CCLayerTreeHost; +class CCScheduler; +class CCScopedThreadProxy; +class CCTextureUpdateQueue; +class CCThread; +class CCThreadProxyContextRecreationTimer; + +class CCThreadProxy : public CCProxy, CCLayerTreeHostImplClient, CCSchedulerClient, CCTextureUpdateControllerClient { +public: + static scoped_ptr create(CCLayerTreeHost*); + + virtual ~CCThreadProxy(); + + // CCProxy implementation + virtual bool compositeAndReadback(void *pixels, const IntRect&) OVERRIDE; + virtual void startPageScaleAnimation(const IntSize& targetPosition, bool useAnchor, float scale, double duration) OVERRIDE; + virtual void finishAllRendering() OVERRIDE; + virtual bool isStarted() const OVERRIDE; + virtual bool initializeContext() OVERRIDE; + virtual void setSurfaceReady() OVERRIDE; + virtual void setVisible(bool) OVERRIDE; + virtual bool initializeRenderer() OVERRIDE; + virtual bool recreateContext() OVERRIDE; + virtual void renderingStats(CCRenderingStats*) OVERRIDE; + virtual const RendererCapabilities& rendererCapabilities() const OVERRIDE; + virtual void loseContext() OVERRIDE; + virtual void setNeedsAnimate() OVERRIDE; + virtual void setNeedsCommit() OVERRIDE; + virtual void setNeedsRedraw() OVERRIDE; + virtual bool commitRequested() const OVERRIDE; + virtual void didAddAnimation() OVERRIDE { } + virtual void start() OVERRIDE; + virtual void stop() OVERRIDE; + virtual size_t maxPartialTextureUpdates() const OVERRIDE; + virtual void acquireLayerTextures() OVERRIDE; + virtual void forceSerializeOnSwapBuffers() OVERRIDE; + + // CCLayerTreeHostImplClient implementation + virtual void didLoseContextOnImplThread() OVERRIDE; + virtual void onSwapBuffersCompleteOnImplThread() OVERRIDE; + virtual void onVSyncParametersChanged(double monotonicTimebase, double intervalInSeconds) OVERRIDE; + virtual void onCanDrawStateChanged(bool canDraw) OVERRIDE; + virtual void setNeedsRedrawOnImplThread() OVERRIDE; + virtual void setNeedsCommitOnImplThread() OVERRIDE; + virtual void postAnimationEventsToMainThreadOnImplThread(scoped_ptr, double wallClockTime) OVERRIDE; + virtual void releaseContentsTexturesOnImplThread() OVERRIDE; + + // CCSchedulerClient implementation + virtual void scheduledActionBeginFrame() OVERRIDE; + virtual CCScheduledActionDrawAndSwapResult scheduledActionDrawAndSwapIfPossible() OVERRIDE; + virtual CCScheduledActionDrawAndSwapResult scheduledActionDrawAndSwapForced() OVERRIDE; + virtual void scheduledActionCommit() OVERRIDE; + virtual void scheduledActionBeginContextRecreation() OVERRIDE; + virtual void scheduledActionAcquireLayerTexturesForMainThread() OVERRIDE; + virtual void didAnticipatedDrawTimeChange(base::TimeTicks) OVERRIDE; + + // CCTextureUpdateControllerClient implementation + virtual void readyToFinalizeTextureUpdates() OVERRIDE; + +private: + explicit CCThreadProxy(CCLayerTreeHost*); + friend class CCThreadProxyContextRecreationTimer; + + // Set on impl thread, read on main thread. + struct BeginFrameAndCommitState { + BeginFrameAndCommitState(); + ~BeginFrameAndCommitState(); + + double monotonicFrameBeginTime; + scoped_ptr scrollInfo; + WebKit::WebTransformationMatrix implTransform; + CCPrioritizedTextureManager::BackingVector evictedContentsTexturesBackings; + size_t memoryAllocationLimitBytes; + }; + OwnPtr m_pendingBeginFrameRequest; + + // Called on main thread + void beginFrame(); + void didCommitAndDrawFrame(); + void didCompleteSwapBuffers(); + void setAnimationEvents(CCAnimationEventsVector*, double wallClockTime); + void beginContextRecreation(); + void tryToRecreateContext(); + + // Called on impl thread + struct ReadbackRequest { + CCCompletionEvent completion; + bool success; + void* pixels; + IntRect rect; + }; + void forceBeginFrameOnImplThread(CCCompletionEvent*); + void beginFrameCompleteOnImplThread(CCCompletionEvent*, PassOwnPtr); + void beginFrameAbortedOnImplThread(); + void requestReadbackOnImplThread(ReadbackRequest*); + void requestStartPageScaleAnimationOnImplThread(IntSize targetPosition, bool useAnchor, float scale, double durationSec); + void finishAllRenderingOnImplThread(CCCompletionEvent*); + void initializeImplOnImplThread(CCCompletionEvent*, CCInputHandler*); + void setSurfaceReadyOnImplThread(); + void setVisibleOnImplThread(CCCompletionEvent*, bool); + void initializeContextOnImplThread(CCGraphicsContext*); + void initializeRendererOnImplThread(CCCompletionEvent*, bool* initializeSucceeded, RendererCapabilities*); + void layerTreeHostClosedOnImplThread(CCCompletionEvent*); + void setFullRootLayerDamageOnImplThread(); + void acquireLayerTexturesForMainThreadOnImplThread(CCCompletionEvent*); + void recreateContextOnImplThread(CCCompletionEvent*, CCGraphicsContext*, bool* recreateSucceeded, RendererCapabilities*); + void renderingStatsOnImplThread(CCCompletionEvent*, CCRenderingStats*); + CCScheduledActionDrawAndSwapResult scheduledActionDrawAndSwapInternal(bool forcedDraw); + void forceSerializeOnSwapBuffersOnImplThread(CCCompletionEvent*); + void setNeedsForcedCommitOnImplThread(); + + // Accessed on main thread only. + bool m_animateRequested; // Set only when setNeedsAnimate is called. + bool m_commitRequested; // Set only when setNeedsCommit is called. + bool m_commitRequestSentToImplThread; // Set by setNeedsCommit and setNeedsAnimate. + bool m_forcedCommitRequested; + OwnPtr m_contextRecreationTimer; + CCLayerTreeHost* m_layerTreeHost; + bool m_rendererInitialized; + RendererCapabilities m_RendererCapabilitiesMainThreadCopy; + bool m_started; + bool m_texturesAcquired; + bool m_inCompositeAndReadback; + + scoped_ptr m_layerTreeHostImpl; + + scoped_ptr m_inputHandlerOnImplThread; + + OwnPtr m_schedulerOnImplThread; + + RefPtr m_mainThreadProxy; + + // Holds on to the context we might use for compositing in between initializeContext() + // and initializeRenderer() calls. + scoped_ptr m_contextBeforeInitializationOnImplThread; + + // Set when the main thread is waiting on a scheduledActionBeginFrame to be issued. + CCCompletionEvent* m_beginFrameCompletionEventOnImplThread; + + // Set when the main thread is waiting on a readback. + ReadbackRequest* m_readbackRequestOnImplThread; + + // Set when the main thread is waiting on a commit to complete. + CCCompletionEvent* m_commitCompletionEventOnImplThread; + + // Set when the main thread is waiting on layers to be drawn. + CCCompletionEvent* m_textureAcquisitionCompletionEventOnImplThread; + + OwnPtr m_currentTextureUpdateControllerOnImplThread; + + // Set when we need to reset the contentsTexturesPurged flag after the + // commit. + bool m_resetContentsTexturesPurgedAfterCommitOnImplThread; + + // Set when the next draw should post didCommitAndDrawFrame to the main thread. + bool m_nextFrameIsNewlyCommittedFrameOnImplThread; + + bool m_renderVSyncEnabled; + + base::TimeDelta m_totalCommitTime; + size_t m_totalCommitCount; +}; + +} + +#endif diff --git a/cc/thread_task.h b/cc/thread_task.h index 638cbb2..25c5509 100644 --- a/cc/thread_task.h +++ b/cc/thread_task.h @@ -1,3 +1,305 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. +// Copyright 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#ifndef CCThreadTask_h +#define CCThreadTask_h + +#include "CCThread.h" +#include +#include + +namespace cc { + +template +class CCThreadTask0 : public CCThread::Task { +public: + typedef void (T::*Method)(); + typedef CCThreadTask0 CCThreadTaskImpl; + + static PassOwnPtr create(T* instance, Method method) + { + return adoptPtr(new CCThreadTaskImpl(instance, method)); + } + +private: + CCThreadTask0(T* instance, Method method) + : CCThread::Task(instance) + , m_method(method) + { + } + + virtual void performTask() OVERRIDE + { + (*static_cast(instance()).*m_method)(); + } + +private: + Method m_method; +}; + +template +class CCThreadTask1 : public CCThread::Task { +public: + typedef void (T::*Method)(MP1); + typedef CCThreadTask1 CCThreadTaskImpl; + + static PassOwnPtr create(T* instance, Method method, P1 parameter1) + { + return adoptPtr(new CCThreadTaskImpl(instance, method, parameter1)); + } + +private: + CCThreadTask1(T* instance, Method method, P1 parameter1) + : CCThread::Task(instance) + , m_method(method) + , m_parameter1(parameter1) + { + } + + virtual void performTask() OVERRIDE + { + (*static_cast(instance()).*m_method)(m_parameter1); + } + +private: + Method m_method; + P1 m_parameter1; +}; + +template +class CCThreadTask2 : public CCThread::Task { +public: + typedef void (T::*Method)(MP1, MP2); + typedef CCThreadTask2 CCThreadTaskImpl; + + static PassOwnPtr create(T* instance, Method method, P1 parameter1, P2 parameter2) + { + return adoptPtr(new CCThreadTaskImpl(instance, method, parameter1, parameter2)); + } + +private: + CCThreadTask2(T* instance, Method method, P1 parameter1, P2 parameter2) + : CCThread::Task(instance) + , m_method(method) + , m_parameter1(parameter1) + , m_parameter2(parameter2) + { + } + + virtual void performTask() OVERRIDE + { + (*static_cast(instance()).*m_method)(m_parameter1, m_parameter2); + } + +private: + Method m_method; + P1 m_parameter1; + P2 m_parameter2; +}; + +template +class CCThreadTask3 : public CCThread::Task { +public: + typedef void (T::*Method)(MP1, MP2, MP3); + typedef CCThreadTask3 CCThreadTaskImpl; + + static PassOwnPtr create(T* instance, Method method, P1 parameter1, P2 parameter2, P3 parameter3) + { + return adoptPtr(new CCThreadTaskImpl(instance, method, parameter1, parameter2, parameter3)); + } + +private: + CCThreadTask3(T* instance, Method method, P1 parameter1, P2 parameter2, P3 parameter3) + : CCThread::Task(instance) + , m_method(method) + , m_parameter1(parameter1) + , m_parameter2(parameter2) + , m_parameter3(parameter3) + { + } + + virtual void performTask() OVERRIDE + { + (*static_cast(instance()).*m_method)(m_parameter1, m_parameter2, m_parameter3); + } + +private: + Method m_method; + P1 m_parameter1; + P2 m_parameter2; + P3 m_parameter3; +}; + + +template +class CCThreadTask4 : public CCThread::Task { +public: + typedef void (T::*Method)(MP1, MP2, MP3, MP4); + typedef CCThreadTask4 CCThreadTaskImpl; + + static PassOwnPtr create(T* instance, Method method, P1 parameter1, P2 parameter2, P3 parameter3, P4 parameter4) + { + return adoptPtr(new CCThreadTaskImpl(instance, method, parameter1, parameter2, parameter3, parameter4)); + } + +private: + CCThreadTask4(T* instance, Method method, P1 parameter1, P2 parameter2, P3 parameter3, P4 parameter4) + : CCThread::Task(instance) + , m_method(method) + , m_parameter1(parameter1) + , m_parameter2(parameter2) + , m_parameter3(parameter3) + , m_parameter4(parameter4) + { + } + + virtual void performTask() OVERRIDE + { + (*static_cast(instance()).*m_method)(m_parameter1, m_parameter2, m_parameter3, m_parameter4); + } + +private: + Method m_method; + P1 m_parameter1; + P2 m_parameter2; + P3 m_parameter3; + P4 m_parameter4; +}; + +template +class CCThreadTask5 : public CCThread::Task { +public: + typedef void (T::*Method)(MP1, MP2, MP3, MP4, MP5); + typedef CCThreadTask5 CCThreadTaskImpl; + + static PassOwnPtr create(T* instance, Method method, P1 parameter1, P2 parameter2, P3 parameter3, P4 parameter4, P5 parameter5) + { + return adoptPtr(new CCThreadTaskImpl(instance, method, parameter1, parameter2, parameter3, parameter4, parameter5)); + } + +private: + CCThreadTask5(T* instance, Method method, P1 parameter1, P2 parameter2, P3 parameter3, P4 parameter4, P5 parameter5) + : CCThread::Task(instance) + , m_method(method) + , m_parameter1(parameter1) + , m_parameter2(parameter2) + , m_parameter3(parameter3) + , m_parameter4(parameter4) + , m_parameter5(parameter5) + { + } + + virtual void performTask() OVERRIDE + { + (*static_cast(instance()).*m_method)(m_parameter1, m_parameter2, m_parameter3, m_parameter4, m_parameter5); + } + +private: + Method m_method; + P1 m_parameter1; + P2 m_parameter2; + P3 m_parameter3; + P4 m_parameter4; + P5 m_parameter5; +}; + +template +PassOwnPtr createCCThreadTask( + T* const callee, + void (T::*method)()); + +template +PassOwnPtr createCCThreadTask( + T* const callee, + void (T::*method)()) +{ + return CCThreadTask0::create( + callee, + method); +} + +template +PassOwnPtr createCCThreadTask( + T* const callee, + void (T::*method)(MP1), + const P1& parameter1) +{ + return CCThreadTask1::create( + callee, + method, + parameter1); +} + +template +PassOwnPtr createCCThreadTask( + T* const callee, + void (T::*method)(MP1, MP2), + const P1& parameter1, + const P2& parameter2) +{ + return CCThreadTask2::create( + callee, + method, + parameter1, + parameter2); +} + +template +PassOwnPtr createCCThreadTask( + T* const callee, + void (T::*method)(MP1, MP2, MP3), + const P1& parameter1, + const P2& parameter2, + const P3& parameter3) +{ + return CCThreadTask3::create( + callee, + method, + parameter1, + parameter2, + parameter3); +} + +template +PassOwnPtr createCCThreadTask( + T* const callee, + void (T::*method)(MP1, MP2, MP3, MP4), + const P1& parameter1, + const P2& parameter2, + const P3& parameter3, + const P4& parameter4) +{ + return CCThreadTask4::create( + callee, + method, + parameter1, + parameter2, + parameter3, + parameter4); + +} + +template +PassOwnPtr createCCThreadTask( + T* const callee, + void (T::*method)(MP1, MP2, MP3, MP4, MP5), + const P1& parameter1, + const P2& parameter2, + const P3& parameter3, + const P4& parameter4, + const P5& parameter5) +{ + return CCThreadTask5::create( + callee, + method, + parameter1, + parameter2, + parameter3, + parameter4, + parameter5); + +} + +} // namespace cc + +#endif // CCThreadTask_h diff --git a/cc/throttled_texture_uploader.cc b/cc/throttled_texture_uploader.cc new file mode 100644 index 0000000..179f2b6 --- /dev/null +++ b/cc/throttled_texture_uploader.cc @@ -0,0 +1,186 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "ThrottledTextureUploader.h" + +#include "Extensions3DChromium.h" +#include "TraceEvent.h" +#include +#include +#include +#include + +namespace { + +// How many previous uploads to use when predicting future throughput. +static const size_t uploadHistorySize = 100; + +// Global estimated number of textures per second to maintain estimates across +// subsequent instances of ThrottledTextureUploader. +// More than one thread will not access this variable, so we do not need to synchronize access. +static double estimatedTexturesPerSecondGlobal = 48.0 * 60.0; + +} // anonymous namespace + +namespace cc { + +ThrottledTextureUploader::Query::Query(WebKit::WebGraphicsContext3D* context) + : m_context(context) + , m_queryId(0) + , m_value(0) + , m_hasValue(false) + , m_isNonBlocking(false) +{ + m_queryId = m_context->createQueryEXT(); +} + +ThrottledTextureUploader::Query::~Query() +{ + m_context->deleteQueryEXT(m_queryId); +} + +void ThrottledTextureUploader::Query::begin() +{ + m_hasValue = false; + m_isNonBlocking = false; + m_context->beginQueryEXT(Extensions3DChromium::COMMANDS_ISSUED_CHROMIUM, m_queryId); +} + +void ThrottledTextureUploader::Query::end() +{ + m_context->endQueryEXT(Extensions3DChromium::COMMANDS_ISSUED_CHROMIUM); +} + +bool ThrottledTextureUploader::Query::isPending() +{ + unsigned available = 1; + m_context->getQueryObjectuivEXT(m_queryId, Extensions3DChromium::QUERY_RESULT_AVAILABLE_EXT, &available); + return !available; +} + +void ThrottledTextureUploader::Query::wait() +{ + value(); + return; +} + +unsigned ThrottledTextureUploader::Query::value() +{ + if (!m_hasValue) { + m_context->getQueryObjectuivEXT(m_queryId, Extensions3DChromium::QUERY_RESULT_EXT, &m_value); + m_hasValue = true; + } + return m_value; +} + +void ThrottledTextureUploader::Query::markAsNonBlocking() +{ + m_isNonBlocking = true; +} + +bool ThrottledTextureUploader::Query::isNonBlocking() +{ + return m_isNonBlocking; +} + +ThrottledTextureUploader::ThrottledTextureUploader(WebKit::WebGraphicsContext3D* context) + : m_context(context) + , m_texturesPerSecondHistory(uploadHistorySize, estimatedTexturesPerSecondGlobal) + , m_numBlockingTextureUploads(0) +{ +} + +ThrottledTextureUploader::~ThrottledTextureUploader() +{ +} + +size_t ThrottledTextureUploader::numBlockingUploads() +{ + processQueries(); + return m_numBlockingTextureUploads; +} + +void ThrottledTextureUploader::markPendingUploadsAsNonBlocking() +{ + for (Deque >::iterator it = m_pendingQueries.begin(); + it != m_pendingQueries.end(); ++it) { + if (it->get()->isNonBlocking()) + continue; + + m_numBlockingTextureUploads--; + it->get()->markAsNonBlocking(); + } + + ASSERT(!m_numBlockingTextureUploads); +} + +double ThrottledTextureUploader::estimatedTexturesPerSecond() +{ + processQueries(); + + // The history should never be empty because we initialize all elements with an estimate. + ASSERT(m_texturesPerSecondHistory.size() == uploadHistorySize); + + // Sort the history and use the median as our estimate. + std::vector sortedHistory(m_texturesPerSecondHistory.begin(), + m_texturesPerSecondHistory.end()); + std::sort(sortedHistory.begin(), sortedHistory.end()); + + estimatedTexturesPerSecondGlobal = sortedHistory[sortedHistory.size() * 2 / 3]; + TRACE_COUNTER1("cc", "estimatedTexturesPerSecond", estimatedTexturesPerSecondGlobal); + return estimatedTexturesPerSecondGlobal; +} + +void ThrottledTextureUploader::beginQuery() +{ + if (m_availableQueries.isEmpty()) + m_availableQueries.append(Query::create(m_context)); + + m_availableQueries.first()->begin(); +} + +void ThrottledTextureUploader::endQuery() +{ + m_availableQueries.first()->end(); + m_pendingQueries.append(m_availableQueries.takeFirst()); + m_numBlockingTextureUploads++; +} + +void ThrottledTextureUploader::uploadTexture(CCResourceProvider* resourceProvider, Parameters upload) +{ + bool isFullUpload = upload.destOffset.isZero() && + upload.sourceRect.size() == upload.texture->texture()->size(); + + if (isFullUpload) + beginQuery(); + + upload.texture->updateRect(resourceProvider, upload.sourceRect, upload.destOffset); + + if (isFullUpload) + endQuery(); +} + +void ThrottledTextureUploader::processQueries() +{ + while (!m_pendingQueries.isEmpty()) { + if (m_pendingQueries.first()->isPending()) + break; + + unsigned usElapsed = m_pendingQueries.first()->value(); + WebKit::Platform::current()->histogramCustomCounts("Renderer4.TextureGpuUploadTimeUS", usElapsed, 0, 100000, 50); + + if (!m_pendingQueries.first()->isNonBlocking()) + m_numBlockingTextureUploads--; + + // Remove the oldest values from our history and insert the new one + double texturesPerSecond = 1.0 / (usElapsed * 1e-6); + m_texturesPerSecondHistory.pop_back(); + m_texturesPerSecondHistory.push_front(texturesPerSecond); + + m_availableQueries.append(m_pendingQueries.takeFirst()); + } +} + +} diff --git a/cc/throttled_texture_uploader.h b/cc/throttled_texture_uploader.h index 638cbb2..f517401 100644 --- a/cc/throttled_texture_uploader.h +++ b/cc/throttled_texture_uploader.h @@ -1,3 +1,76 @@ // Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef ThrottledTextureUploader_h +#define ThrottledTextureUploader_h + +#include "TextureUploader.h" + +#include "base/basictypes.h" +#include +#include + +namespace WebKit { +class WebGraphicsContext3D; +} + +namespace cc { + +class ThrottledTextureUploader : public TextureUploader { +public: + static PassOwnPtr create(WebKit::WebGraphicsContext3D* context) + { + return adoptPtr(new ThrottledTextureUploader(context)); + } + virtual ~ThrottledTextureUploader(); + + virtual size_t numBlockingUploads() OVERRIDE; + virtual void markPendingUploadsAsNonBlocking() OVERRIDE; + virtual double estimatedTexturesPerSecond() OVERRIDE; + virtual void uploadTexture(CCResourceProvider*, Parameters) OVERRIDE; + +private: + class Query { + public: + static PassOwnPtr create(WebKit::WebGraphicsContext3D* context) { return adoptPtr(new Query(context)); } + + virtual ~Query(); + + void begin(); + void end(); + bool isPending(); + void wait(); + unsigned value(); + size_t texturesUploaded(); + void markAsNonBlocking(); + bool isNonBlocking(); + + private: + explicit Query(WebKit::WebGraphicsContext3D*); + + WebKit::WebGraphicsContext3D* m_context; + unsigned m_queryId; + unsigned m_value; + bool m_hasValue; + bool m_isNonBlocking; + }; + + ThrottledTextureUploader(WebKit::WebGraphicsContext3D*); + + void beginQuery(); + void endQuery(); + void processQueries(); + + WebKit::WebGraphicsContext3D* m_context; + Deque > m_pendingQueries; + Deque > m_availableQueries; + std::deque m_texturesPerSecondHistory; + size_t m_numBlockingTextureUploads; + + DISALLOW_COPY_AND_ASSIGN(ThrottledTextureUploader); +}; + +} + +#endif diff --git a/cc/tile_draw_quad.cc b/cc/tile_draw_quad.cc new file mode 100644 index 0000000..a5ac33d --- /dev/null +++ b/cc/tile_draw_quad.cc @@ -0,0 +1,39 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#include "CCTileDrawQuad.h" + +namespace cc { + +scoped_ptr CCTileDrawQuad::create(const CCSharedQuadState* sharedQuadState, const IntRect& quadRect, const IntRect& opaqueRect, unsigned resourceId, const IntPoint& textureOffset, const IntSize& textureSize, GC3Dint textureFilter, bool swizzleContents, bool leftEdgeAA, bool topEdgeAA, bool rightEdgeAA, bool bottomEdgeAA) +{ + return make_scoped_ptr(new CCTileDrawQuad(sharedQuadState, quadRect, opaqueRect, resourceId, textureOffset, textureSize, textureFilter, swizzleContents, leftEdgeAA, topEdgeAA, rightEdgeAA, bottomEdgeAA)); +} + +CCTileDrawQuad::CCTileDrawQuad(const CCSharedQuadState* sharedQuadState, const IntRect& quadRect, const IntRect& opaqueRect, unsigned resourceId, const IntPoint& textureOffset, const IntSize& textureSize, GC3Dint textureFilter, bool swizzleContents, bool leftEdgeAA, bool topEdgeAA, bool rightEdgeAA, bool bottomEdgeAA) + : CCDrawQuad(sharedQuadState, CCDrawQuad::TiledContent, quadRect) + , m_resourceId(resourceId) + , m_textureOffset(textureOffset) + , m_textureSize(textureSize) + , m_textureFilter(textureFilter) + , m_swizzleContents(swizzleContents) + , m_leftEdgeAA(leftEdgeAA) + , m_topEdgeAA(topEdgeAA) + , m_rightEdgeAA(rightEdgeAA) + , m_bottomEdgeAA(bottomEdgeAA) +{ + if (isAntialiased()) + m_needsBlending = true; + m_opaqueRect = opaqueRect; +} + +const CCTileDrawQuad* CCTileDrawQuad::materialCast(const CCDrawQuad* quad) +{ + ASSERT(quad->material() == CCDrawQuad::TiledContent); + return static_cast(quad); +} + +} diff --git a/cc/tile_draw_quad.h b/cc/tile_draw_quad.h index 638cbb2..21a98cf 100644 --- a/cc/tile_draw_quad.h +++ b/cc/tile_draw_quad.h @@ -1,3 +1,54 @@ // Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CCTileDrawQuad_h +#define CCTileDrawQuad_h + +#include "CCDrawQuad.h" +#include "GraphicsTypes3D.h" +#include "IntPoint.h" +#include "IntSize.h" +#include "base/memory/scoped_ptr.h" + +namespace cc { + +#pragma pack(push, 4) + +class CCTileDrawQuad : public CCDrawQuad { +public: + static scoped_ptr create(const CCSharedQuadState*, const IntRect& quadRect, const IntRect& opaqueRect, unsigned resourceId, const IntPoint& textureOffset, const IntSize& textureSize, GC3Dint textureFilter, bool swizzleContents, bool leftEdgeAA, bool topEdgeAA, bool rightEdgeAA, bool bottomEdgeAA); + + unsigned resourceId() const { return m_resourceId; } + IntPoint textureOffset() const { return m_textureOffset; } + IntSize textureSize() const { return m_textureSize; } + GC3Dint textureFilter() const { return m_textureFilter; } + bool swizzleContents() const { return m_swizzleContents; } + + bool leftEdgeAA() const { return m_leftEdgeAA; } + bool topEdgeAA() const { return m_topEdgeAA; } + bool rightEdgeAA() const { return m_rightEdgeAA; } + bool bottomEdgeAA() const { return m_bottomEdgeAA; } + + bool isAntialiased() const { return leftEdgeAA() || topEdgeAA() || rightEdgeAA() || bottomEdgeAA(); } + + static const CCTileDrawQuad* materialCast(const CCDrawQuad*); +private: + CCTileDrawQuad(const CCSharedQuadState*, const IntRect& quadRect, const IntRect& opaqueRect, unsigned resourceId, const IntPoint& textureOffset, const IntSize& textureSize, GC3Dint textureFilter, bool swizzleContents, bool leftEdgeAA, bool topEdgeAA, bool rightEdgeAA, bool bottomEdgeAA); + + unsigned m_resourceId; + IntPoint m_textureOffset; + IntSize m_textureSize; + GC3Dint m_textureFilter; + bool m_swizzleContents; + bool m_leftEdgeAA; + bool m_topEdgeAA; + bool m_rightEdgeAA; + bool m_bottomEdgeAA; +}; + +#pragma pack(pop) + +} + +#endif diff --git a/cc/tiled_layer.cc b/cc/tiled_layer.cc new file mode 100644 index 0000000..f2219e6 --- /dev/null +++ b/cc/tiled_layer.cc @@ -0,0 +1,820 @@ +// Copyright 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#if USE(ACCELERATED_COMPOSITING) + +#include "base/basictypes.h" +#include "TiledLayerChromium.h" + +#include "CCLayerImpl.h" +#include "CCLayerTreeHost.h" +#include "CCOverdrawMetrics.h" +#include "CCTextureUpdateQueue.h" +#include "CCTiledLayerImpl.h" +#include "GraphicsContext3D.h" +#include "Region.h" +#include +#include + +using namespace std; +using WebKit::WebTransformationMatrix; + +namespace cc { + +class UpdatableTile : public CCLayerTilingData::Tile { +public: + static PassOwnPtr create(PassOwnPtr texture) + { + return adoptPtr(new UpdatableTile(texture)); + } + + LayerTextureUpdater::Texture* texture() { return m_texture.get(); } + CCPrioritizedTexture* managedTexture() { return m_texture->texture(); } + + bool isDirty() const { return !dirtyRect.isEmpty(); } + + // Reset update state for the current frame. This should occur before painting + // for all layers. Since painting one layer can invalidate another layer + // after it has already painted, mark all non-dirty tiles as valid before painting + // such that invalidations during painting won't prevent them from being pushed. + void resetUpdateState() + { + updateRect = IntRect(); + occluded = false; + partialUpdate = false; + validForFrame = !isDirty(); + } + + // This promises to update the tile and therefore also guarantees the tile + // will be valid for this frame. dirtyRect is copied into updateRect so + // we can continue to track re-entrant invalidations that occur during painting. + void markForUpdate() + { + validForFrame = true; + updateRect = dirtyRect; + dirtyRect = IntRect(); + } + + IntRect dirtyRect; + IntRect updateRect; + bool partialUpdate; + bool validForFrame; + bool occluded; + bool isInUseOnImpl; +private: + explicit UpdatableTile(PassOwnPtr texture) + : partialUpdate(false) + , validForFrame(false) + , occluded(false) + , isInUseOnImpl(false) + , m_texture(texture) + { + } + + OwnPtr m_texture; + + DISALLOW_COPY_AND_ASSIGN(UpdatableTile); +}; + +TiledLayerChromium::TiledLayerChromium() + : LayerChromium() + , m_textureFormat(GraphicsContext3D::INVALID_ENUM) + , m_skipsDraw(false) + , m_failedUpdate(false) + , m_sampledTexelFormat(LayerTextureUpdater::SampledTexelFormatInvalid) + , m_tilingOption(AutoTile) +{ + m_tiler = CCLayerTilingData::create(IntSize(), CCLayerTilingData::HasBorderTexels); +} + +TiledLayerChromium::~TiledLayerChromium() +{ +} + +scoped_ptr TiledLayerChromium::createCCLayerImpl() +{ + return CCTiledLayerImpl::create(id()).PassAs(); +} + +void TiledLayerChromium::updateTileSizeAndTilingOption() +{ + ASSERT(layerTreeHost()); + + const IntSize& defaultTileSize = layerTreeHost()->settings().defaultTileSize; + const IntSize& maxUntiledLayerSize = layerTreeHost()->settings().maxUntiledLayerSize; + int layerWidth = contentBounds().width(); + int layerHeight = contentBounds().height(); + + const IntSize tileSize(min(defaultTileSize.width(), layerWidth), min(defaultTileSize.height(), layerHeight)); + + // Tile if both dimensions large, or any one dimension large and the other + // extends into a second tile but the total layer area isn't larger than that + // of the largest possible untiled layer. This heuristic allows for long skinny layers + // (e.g. scrollbars) that are Nx1 tiles to minimize wasted texture space but still avoids + // creating very large tiles. + const bool anyDimensionLarge = layerWidth > maxUntiledLayerSize.width() || layerHeight > maxUntiledLayerSize.height(); + const bool anyDimensionOneTile = (layerWidth <= defaultTileSize.width() || layerHeight <= defaultTileSize.height()) + && (layerWidth * layerHeight) <= (maxUntiledLayerSize.width() * maxUntiledLayerSize.height()); + const bool autoTiled = anyDimensionLarge && !anyDimensionOneTile; + + bool isTiled; + if (m_tilingOption == AlwaysTile) + isTiled = true; + else if (m_tilingOption == NeverTile) + isTiled = false; + else + isTiled = autoTiled; + + IntSize requestedSize = isTiled ? tileSize : contentBounds(); + const int maxSize = layerTreeHost()->rendererCapabilities().maxTextureSize; + IntSize clampedSize = requestedSize.shrunkTo(IntSize(maxSize, maxSize)); + setTileSize(clampedSize); +} + +void TiledLayerChromium::updateBounds() +{ + IntSize oldBounds = m_tiler->bounds(); + IntSize newBounds = contentBounds(); + if (oldBounds == newBounds) + return; + m_tiler->setBounds(newBounds); + + // Invalidate any areas that the new bounds exposes. + Region oldRegion(IntRect(IntPoint(), oldBounds)); + Region newRegion(IntRect(IntPoint(), newBounds)); + newRegion.subtract(oldRegion); + Vector rects = newRegion.rects(); + for (size_t i = 0; i < rects.size(); ++i) + invalidateContentRect(rects[i]); +} + +void TiledLayerChromium::setTileSize(const IntSize& size) +{ + m_tiler->setTileSize(size); +} + +void TiledLayerChromium::setBorderTexelOption(CCLayerTilingData::BorderTexelOption borderTexelOption) +{ + m_tiler->setBorderTexelOption(borderTexelOption); +} + +bool TiledLayerChromium::drawsContent() const +{ + if (!LayerChromium::drawsContent()) + return false; + + bool hasMoreThanOneTile = m_tiler->numTilesX() > 1 || m_tiler->numTilesY() > 1; + if (m_tilingOption == NeverTile && hasMoreThanOneTile) + return false; + + return true; +} + +bool TiledLayerChromium::needsContentsScale() const +{ + return true; +} + +IntSize TiledLayerChromium::contentBounds() const +{ + return IntSize(lroundf(bounds().width() * contentsScale()), lroundf(bounds().height() * contentsScale())); +} + +void TiledLayerChromium::setTilingOption(TilingOption tilingOption) +{ + m_tilingOption = tilingOption; +} + +void TiledLayerChromium::setIsMask(bool isMask) +{ + setTilingOption(isMask ? NeverTile : AutoTile); +} + +void TiledLayerChromium::pushPropertiesTo(CCLayerImpl* layer) +{ + LayerChromium::pushPropertiesTo(layer); + + CCTiledLayerImpl* tiledLayer = static_cast(layer); + + tiledLayer->setSkipsDraw(m_skipsDraw); + tiledLayer->setContentsSwizzled(m_sampledTexelFormat != LayerTextureUpdater::SampledTexelFormatRGBA); + tiledLayer->setTilingData(*m_tiler); + Vector invalidTiles; + + for (CCLayerTilingData::TileMap::const_iterator iter = m_tiler->tiles().begin(); iter != m_tiler->tiles().end(); ++iter) { +#if WTF_NEW_HASHMAP_ITERATORS_INTERFACE + int i = iter->key.first; + int j = iter->key.second; + UpdatableTile* tile = static_cast(iter->value.get()); +#else + int i = iter->first.first; + int j = iter->first.second; + UpdatableTile* tile = static_cast(iter->second.get()); +#endif + // FIXME: This should not ever be null. + if (!tile) + continue; + + tile->isInUseOnImpl = false; + + if (!tile->managedTexture()->haveBackingTexture()) { + // Evicted tiles get deleted from both layers + invalidTiles.append(tile); + continue; + } + + if (!tile->validForFrame) { + // Invalidated tiles are set so they can get different debug colors. + tiledLayer->pushInvalidTile(i, j); + continue; + } + + tiledLayer->pushTileProperties(i, j, tile->managedTexture()->resourceId(), tile->opaqueRect()); + tile->isInUseOnImpl = true; + } + for (Vector::const_iterator iter = invalidTiles.begin(); iter != invalidTiles.end(); ++iter) + m_tiler->takeTile((*iter)->i(), (*iter)->j()); +} + +CCPrioritizedTextureManager* TiledLayerChromium::textureManager() const +{ + if (!layerTreeHost()) + return 0; + return layerTreeHost()->contentsTextureManager(); +} + +void TiledLayerChromium::setLayerTreeHost(CCLayerTreeHost* host) +{ + if (host && host != layerTreeHost()) { + for (CCLayerTilingData::TileMap::const_iterator iter = m_tiler->tiles().begin(); iter != m_tiler->tiles().end(); ++iter) { +#if WTF_NEW_HASHMAP_ITERATORS_INTERFACE + UpdatableTile* tile = static_cast(iter->value.get()); +#else + UpdatableTile* tile = static_cast(iter->second.get()); +#endif + // FIXME: This should not ever be null. + if (!tile) + continue; + tile->managedTexture()->setTextureManager(host->contentsTextureManager()); + } + } + LayerChromium::setLayerTreeHost(host); +} + +UpdatableTile* TiledLayerChromium::tileAt(int i, int j) const +{ + return static_cast(m_tiler->tileAt(i, j)); +} + +UpdatableTile* TiledLayerChromium::createTile(int i, int j) +{ + createTextureUpdaterIfNeeded(); + + OwnPtr tile(UpdatableTile::create(textureUpdater()->createTexture(textureManager()))); + tile->managedTexture()->setDimensions(m_tiler->tileSize(), m_textureFormat); + + UpdatableTile* addedTile = tile.get(); + m_tiler->addTile(tile.release(), i, j); + + addedTile->dirtyRect = m_tiler->tileRect(addedTile); + + // Temporary diagnostic crash. + if (!addedTile) + CRASH(); + if (!tileAt(i, j)) + CRASH(); + + return addedTile; +} + +void TiledLayerChromium::setNeedsDisplayRect(const FloatRect& dirtyRect) +{ + float contentsWidthScale = static_cast(contentBounds().width()) / bounds().width(); + float contentsHeightScale = static_cast(contentBounds().height()) / bounds().height(); + FloatRect scaledDirtyRect(dirtyRect); + scaledDirtyRect.scale(contentsWidthScale, contentsHeightScale); + IntRect dirty = enclosingIntRect(scaledDirtyRect); + invalidateContentRect(dirty); + LayerChromium::setNeedsDisplayRect(dirtyRect); +} + +void TiledLayerChromium::setUseLCDText(bool useLCDText) +{ + LayerChromium::setUseLCDText(useLCDText); + + CCLayerTilingData::BorderTexelOption borderTexelOption; +#if OS(ANDROID) + // Always want border texels and GL_LINEAR due to pinch zoom. + borderTexelOption = CCLayerTilingData::HasBorderTexels; +#else + borderTexelOption = useLCDText ? CCLayerTilingData::NoBorderTexels : CCLayerTilingData::HasBorderTexels; +#endif + setBorderTexelOption(borderTexelOption); +} + +void TiledLayerChromium::invalidateContentRect(const IntRect& contentRect) +{ + updateBounds(); + if (m_tiler->isEmpty() || contentRect.isEmpty() || m_skipsDraw) + return; + + for (CCLayerTilingData::TileMap::const_iterator iter = m_tiler->tiles().begin(); iter != m_tiler->tiles().end(); ++iter) { +#if WTF_NEW_HASHMAP_ITERATORS_INTERFACE + UpdatableTile* tile = static_cast(iter->value.get()); +#else + UpdatableTile* tile = static_cast(iter->second.get()); +#endif + ASSERT(tile); + // FIXME: This should not ever be null. + if (!tile) + continue; + IntRect bound = m_tiler->tileRect(tile); + bound.intersect(contentRect); + tile->dirtyRect.unite(bound); + } +} + +// Returns true if tile is dirty and only part of it needs to be updated. +bool TiledLayerChromium::tileOnlyNeedsPartialUpdate(UpdatableTile* tile) +{ + return !tile->dirtyRect.contains(m_tiler->tileRect(tile)); +} + +// Dirty tiles with valid textures needs buffered update to guarantee that +// we don't modify textures currently used for drawing by the impl thread. +bool TiledLayerChromium::tileNeedsBufferedUpdate(UpdatableTile* tile) +{ + if (!tile->managedTexture()->haveBackingTexture()) + return false; + + if (!tile->isDirty()) + return false; + + if (!tile->isInUseOnImpl) + return false; + + return true; +} + + +bool TiledLayerChromium::updateTiles(int left, int top, int right, int bottom, CCTextureUpdateQueue& queue, const CCOcclusionTracker* occlusion, CCRenderingStats& stats, bool& didPaint) +{ + didPaint = false; + createTextureUpdaterIfNeeded(); + + bool ignoreOcclusions = !occlusion; + if (!haveTexturesForTiles(left, top, right, bottom, ignoreOcclusions)) { + m_failedUpdate = true; + return false; + } + + IntRect paintRect = markTilesForUpdate(left, top, right, bottom, ignoreOcclusions); + + if (occlusion) + occlusion->overdrawMetrics().didPaint(paintRect); + + if (paintRect.isEmpty()) + return true; + + didPaint = true; + updateTileTextures(paintRect, left, top, right, bottom, queue, occlusion, stats); + return true; +} + +void TiledLayerChromium::markOcclusionsAndRequestTextures(int left, int top, int right, int bottom, const CCOcclusionTracker* occlusion) +{ + // There is some difficult dependancies between occlusions, recording occlusion metrics + // and requesting memory so those are encapsulated in this function: + // - We only want to call requestLate on unoccluded textures (to preserve + // memory for other layers when near OOM). + // - We only want to record occlusion metrics if all memory requests succeed. + + int occludedTileCount = 0; + bool succeeded = true; + for (int j = top; j <= bottom; ++j) { + for (int i = left; i <= right; ++i) { + UpdatableTile* tile = tileAt(i, j); + ASSERT(tile); // Did setTexturePriorities get skipped? + // FIXME: This should not ever be null. + if (!tile) + continue; + ASSERT(!tile->occluded); // Did resetUpdateState get skipped? Are we doing more than one occlusion pass? + IntRect visibleTileRect = intersection(m_tiler->tileBounds(i, j), visibleContentRect()); + if (occlusion && occlusion->occluded(this, visibleTileRect)) { + tile->occluded = true; + occludedTileCount++; + } else { + succeeded &= tile->managedTexture()->requestLate(); + } + } + } + + if (!succeeded) + return; + + // FIXME: Remove the loop and just pass the count! + for (int i = 0; i < occludedTileCount; i++) + occlusion->overdrawMetrics().didCullTileForUpload(); +} + +bool TiledLayerChromium::haveTexturesForTiles(int left, int top, int right, int bottom, bool ignoreOcclusions) +{ + for (int j = top; j <= bottom; ++j) { + for (int i = left; i <= right; ++i) { + UpdatableTile* tile = tileAt(i, j); + ASSERT(tile); // Did setTexturePriorites get skipped? + // FIXME: This should not ever be null. + if (!tile) + continue; + + // Ensure the entire tile is dirty if we don't have the texture. + if (!tile->managedTexture()->haveBackingTexture()) + tile->dirtyRect = m_tiler->tileRect(tile); + + // If using occlusion and the visible region of the tile is occluded, + // don't reserve a texture or update the tile. + if (tile->occluded && !ignoreOcclusions) + continue; + + if (!tile->managedTexture()->canAcquireBackingTexture()) + return false; + } + } + return true; +} + +IntRect TiledLayerChromium::markTilesForUpdate(int left, int top, int right, int bottom, bool ignoreOcclusions) +{ + IntRect paintRect; + for (int j = top; j <= bottom; ++j) { + for (int i = left; i <= right; ++i) { + UpdatableTile* tile = tileAt(i, j); + ASSERT(tile); // Did setTexturePriorites get skipped? + // FIXME: This should not ever be null. + if (!tile) + continue; + if (tile->occluded && !ignoreOcclusions) + continue; + paintRect.unite(tile->dirtyRect); + tile->markForUpdate(); + } + } + return paintRect; +} + +void TiledLayerChromium::updateTileTextures(const IntRect& paintRect, int left, int top, int right, int bottom, CCTextureUpdateQueue& queue, const CCOcclusionTracker* occlusion, CCRenderingStats& stats) +{ + // The updateRect should be in layer space. So we have to convert the paintRect from content space to layer space. + m_updateRect = FloatRect(paintRect); + float widthScale = bounds().width() / static_cast(contentBounds().width()); + float heightScale = bounds().height() / static_cast(contentBounds().height()); + m_updateRect.scale(widthScale, heightScale); + + // Calling prepareToUpdate() calls into WebKit to paint, which may have the side + // effect of disabling compositing, which causes our reference to the texture updater to be deleted. + // However, we can't free the memory backing the SkCanvas until the paint finishes, + // so we grab a local reference here to hold the updater alive until the paint completes. + RefPtr protector(textureUpdater()); + IntRect paintedOpaqueRect; + textureUpdater()->prepareToUpdate(paintRect, m_tiler->tileSize(), 1 / widthScale, 1 / heightScale, paintedOpaqueRect, stats); + + for (int j = top; j <= bottom; ++j) { + for (int i = left; i <= right; ++i) { + UpdatableTile* tile = tileAt(i, j); + ASSERT(tile); // Did setTexturePriorites get skipped? + // FIXME: This should not ever be null. + if (!tile) + continue; + + IntRect tileRect = m_tiler->tileBounds(i, j); + + // Use updateRect as the above loop copied the dirty rect for this frame to updateRect. + const IntRect& dirtyRect = tile->updateRect; + if (dirtyRect.isEmpty()) + continue; + + // Save what was painted opaque in the tile. Keep the old area if the paint didn't touch it, and didn't paint some + // other part of the tile opaque. + IntRect tilePaintedRect = intersection(tileRect, paintRect); + IntRect tilePaintedOpaqueRect = intersection(tileRect, paintedOpaqueRect); + if (!tilePaintedRect.isEmpty()) { + IntRect paintInsideTileOpaqueRect = intersection(tile->opaqueRect(), tilePaintedRect); + bool paintInsideTileOpaqueRectIsNonOpaque = !tilePaintedOpaqueRect.contains(paintInsideTileOpaqueRect); + bool opaquePaintNotInsideTileOpaqueRect = !tilePaintedOpaqueRect.isEmpty() && !tile->opaqueRect().contains(tilePaintedOpaqueRect); + + if (paintInsideTileOpaqueRectIsNonOpaque || opaquePaintNotInsideTileOpaqueRect) + tile->setOpaqueRect(tilePaintedOpaqueRect); + } + + // sourceRect starts as a full-sized tile with border texels included. + IntRect sourceRect = m_tiler->tileRect(tile); + sourceRect.intersect(dirtyRect); + // Paint rect not guaranteed to line up on tile boundaries, so + // make sure that sourceRect doesn't extend outside of it. + sourceRect.intersect(paintRect); + + tile->updateRect = sourceRect; + + if (sourceRect.isEmpty()) + continue; + + tile->texture()->prepareRect(sourceRect, stats); + if (occlusion) + occlusion->overdrawMetrics().didUpload(WebTransformationMatrix(), sourceRect, tile->opaqueRect()); + + const IntPoint anchor = m_tiler->tileRect(tile).location(); + + // Calculate tile-space rectangle to upload into. + IntSize destOffset(sourceRect.x() - anchor.x(), sourceRect.y() - anchor.y()); + if (destOffset.width() < 0) + CRASH(); + if (destOffset.height() < 0) + CRASH(); + + // Offset from paint rectangle to this tile's dirty rectangle. + IntPoint paintOffset(sourceRect.x() - paintRect.x(), sourceRect.y() - paintRect.y()); + if (paintOffset.x() < 0) + CRASH(); + if (paintOffset.y() < 0) + CRASH(); + if (paintOffset.x() + sourceRect.width() > paintRect.width()) + CRASH(); + if (paintOffset.y() + sourceRect.height() > paintRect.height()) + CRASH(); + + TextureUploader::Parameters upload = { tile->texture(), sourceRect, destOffset }; + if (tile->partialUpdate) + queue.appendPartialUpload(upload); + else + queue.appendFullUpload(upload); + } + } +} + +namespace { +// This picks a small animated layer to be anything less than one viewport. This +// is specifically for page transitions which are viewport-sized layers. The extra +// 64 pixels is due to these layers being slightly larger than the viewport in some cases. +bool isSmallAnimatedLayer(TiledLayerChromium* layer) +{ + if (!layer->drawTransformIsAnimating() && !layer->screenSpaceTransformIsAnimating()) + return false; + IntSize viewportSize = layer->layerTreeHost() ? layer->layerTreeHost()->deviceViewportSize() : IntSize(); + IntRect contentRect(IntPoint::zero(), layer->contentBounds()); + return contentRect.width() <= viewportSize.width() + 64 + && contentRect.height() <= viewportSize.height() + 64; +} + +// FIXME: Remove this and make this based on distance once distance can be calculated +// for offscreen layers. For now, prioritize all small animated layers after 512 +// pixels of pre-painting. +void setPriorityForTexture(const IntRect& visibleRect, + const IntRect& tileRect, + bool drawsToRoot, + bool isSmallAnimatedLayer, + CCPrioritizedTexture* texture) +{ + int priority = CCPriorityCalculator::lowestPriority(); + if (!visibleRect.isEmpty()) + priority = CCPriorityCalculator::priorityFromDistance(visibleRect, tileRect, drawsToRoot); + if (isSmallAnimatedLayer) + priority = CCPriorityCalculator::maxPriority(priority, CCPriorityCalculator::smallAnimatedLayerMinPriority()); + if (priority != CCPriorityCalculator::lowestPriority()) + texture->setRequestPriority(priority); +} +} + +void TiledLayerChromium::setTexturePriorities(const CCPriorityCalculator& priorityCalc) +{ + updateBounds(); + resetUpdateState(); + + if (m_tiler->hasEmptyBounds()) + return; + + bool drawsToRoot = !renderTarget()->parent(); + bool smallAnimatedLayer = isSmallAnimatedLayer(this); + + // Minimally create the tiles in the desired pre-paint rect. + IntRect createTilesRect = idlePaintRect(); + if (!createTilesRect.isEmpty()) { + int left, top, right, bottom; + m_tiler->contentRectToTileIndices(createTilesRect, left, top, right, bottom); + for (int j = top; j <= bottom; ++j) { + for (int i = left; i <= right; ++i) { + if (!tileAt(i, j)) + createTile(i, j); + } + } + } + + // Also, minimally create all tiles for small animated layers and also + // double-buffer them since we have limited their size to be reasonable. + IntRect doubleBufferedRect = visibleContentRect(); + if (smallAnimatedLayer) + doubleBufferedRect = IntRect(IntPoint::zero(), contentBounds()); + + // Create additional textures for double-buffered updates when needed. + // These textures must stay alive while the updated textures are incrementally + // uploaded, swapped atomically via pushProperties, and finally deleted + // after the commit is complete, after which they can be recycled. + if (!doubleBufferedRect.isEmpty()) { + int left, top, right, bottom; + m_tiler->contentRectToTileIndices(doubleBufferedRect, left, top, right, bottom); + for (int j = top; j <= bottom; ++j) { + for (int i = left; i <= right; ++i) { + UpdatableTile* tile = tileAt(i, j); + if (!tile) + tile = createTile(i, j); + // We need an additional texture if the tile needs a buffered-update and it's not a partial update. + // FIXME: Decide if partial update should be allowed based on cost + // of update. https://bugs.webkit.org/show_bug.cgi?id=77376 + if (!layerTreeHost() || !layerTreeHost()->bufferedUpdates() || !tileNeedsBufferedUpdate(tile)) + continue; + if (tileOnlyNeedsPartialUpdate(tile) && layerTreeHost()->requestPartialTextureUpdate()) { + tile->partialUpdate = true; + continue; + } + + IntRect tileRect = m_tiler->tileRect(tile); + tile->dirtyRect = tileRect; + LayerTextureUpdater::Texture* backBuffer = tile->texture(); + setPriorityForTexture(visibleContentRect(), tile->dirtyRect, drawsToRoot, smallAnimatedLayer, backBuffer->texture()); + scoped_ptr frontBuffer = CCPrioritizedTexture::create(backBuffer->texture()->textureManager(), + backBuffer->texture()->size(), + backBuffer->texture()->format()); + // Swap backBuffer into frontBuffer and add it to delete after commit queue. + backBuffer->swapTextureWith(frontBuffer); + layerTreeHost()->deleteTextureAfterCommit(frontBuffer.Pass()); + } + } + } + + // Now update priorities on all tiles we have in the layer, no matter where they are. + for (CCLayerTilingData::TileMap::const_iterator iter = m_tiler->tiles().begin(); iter != m_tiler->tiles().end(); ++iter) { +#if WTF_NEW_HASHMAP_ITERATORS_INTERFACE + UpdatableTile* tile = static_cast(iter->value.get()); +#else + UpdatableTile* tile = static_cast(iter->second.get()); +#endif + // FIXME: This should not ever be null. + if (!tile) + continue; + IntRect tileRect = m_tiler->tileRect(tile); + setPriorityForTexture(visibleContentRect(), tileRect, drawsToRoot, smallAnimatedLayer, tile->managedTexture()); + } +} + +Region TiledLayerChromium::visibleContentOpaqueRegion() const +{ + if (m_skipsDraw) + return Region(); + if (contentsOpaque()) + return visibleContentRect(); + return m_tiler->opaqueRegionInContentRect(visibleContentRect()); +} + +void TiledLayerChromium::resetUpdateState() +{ + m_skipsDraw = false; + m_failedUpdate = false; + + CCLayerTilingData::TileMap::const_iterator end = m_tiler->tiles().end(); + for (CCLayerTilingData::TileMap::const_iterator iter = m_tiler->tiles().begin(); iter != end; ++iter) { +#if WTF_NEW_HASHMAP_ITERATORS_INTERFACE + UpdatableTile* tile = static_cast(iter->value.get()); +#else + UpdatableTile* tile = static_cast(iter->second.get()); +#endif + // FIXME: This should not ever be null. + if (!tile) + continue; + tile->resetUpdateState(); + } +} + +void TiledLayerChromium::update(CCTextureUpdateQueue& queue, const CCOcclusionTracker* occlusion, CCRenderingStats& stats) +{ + ASSERT(!m_skipsDraw && !m_failedUpdate); // Did resetUpdateState get skipped? + updateBounds(); + if (m_tiler->hasEmptyBounds() || !drawsContent()) + return; + + bool didPaint = false; + + // Animation pre-paint. If the layer is small, try to paint it all + // immediately whether or not it is occluded, to avoid paint/upload + // hiccups while it is animating. + if (isSmallAnimatedLayer(this)) { + int left, top, right, bottom; + m_tiler->contentRectToTileIndices(IntRect(IntPoint::zero(), contentBounds()), left, top, right, bottom); + updateTiles(left, top, right, bottom, queue, 0, stats, didPaint); + if (didPaint) + return; + // This was an attempt to paint the entire layer so if we fail it's okay, + // just fallback on painting visible etc. below. + m_failedUpdate = false; + } + + if (visibleContentRect().isEmpty()) + return; + + // Visible painting. First occlude visible tiles and paint the non-occluded tiles. + int left, top, right, bottom; + m_tiler->contentRectToTileIndices(visibleContentRect(), left, top, right, bottom); + markOcclusionsAndRequestTextures(left, top, right, bottom, occlusion); + m_skipsDraw = !updateTiles(left, top, right, bottom, queue, occlusion, stats, didPaint); + if (m_skipsDraw) + m_tiler->reset(); + if (m_skipsDraw || didPaint) + return; + + // If we have already painting everything visible. Do some pre-painting while idle. + IntRect idlePaintContentRect = idlePaintRect(); + if (idlePaintContentRect.isEmpty()) + return; + + // Prepaint anything that was occluded but inside the layer's visible region. + if (!updateTiles(left, top, right, bottom, queue, 0, stats, didPaint) || didPaint) + return; + + int prepaintLeft, prepaintTop, prepaintRight, prepaintBottom; + m_tiler->contentRectToTileIndices(idlePaintContentRect, prepaintLeft, prepaintTop, prepaintRight, prepaintBottom); + + // Then expand outwards from the visible area until we find a dirty row or column to update. + while (left > prepaintLeft || top > prepaintTop || right < prepaintRight || bottom < prepaintBottom) { + if (bottom < prepaintBottom) { + ++bottom; + if (!updateTiles(left, bottom, right, bottom, queue, 0, stats, didPaint) || didPaint) + return; + } + if (top > prepaintTop) { + --top; + if (!updateTiles(left, top, right, top, queue, 0, stats, didPaint) || didPaint) + return; + } + if (left > prepaintLeft) { + --left; + if (!updateTiles(left, top, left, bottom, queue, 0, stats, didPaint) || didPaint) + return; + } + if (right < prepaintRight) { + ++right; + if (!updateTiles(right, top, right, bottom, queue, 0, stats, didPaint) || didPaint) + return; + } + } +} + +bool TiledLayerChromium::needsIdlePaint() +{ + // Don't trigger more paints if we failed (as we'll just fail again). + if (m_failedUpdate || visibleContentRect().isEmpty() || m_tiler->hasEmptyBounds() || !drawsContent()) + return false; + + IntRect idlePaintContentRect = idlePaintRect(); + if (idlePaintContentRect.isEmpty()) + return false; + + int left, top, right, bottom; + m_tiler->contentRectToTileIndices(idlePaintContentRect, left, top, right, bottom); + + for (int j = top; j <= bottom; ++j) { + for (int i = left; i <= right; ++i) { + UpdatableTile* tile = tileAt(i, j); + ASSERT(tile); // Did setTexturePriorities get skipped? + if (!tile) + continue; + + bool updated = !tile->updateRect.isEmpty(); + bool canAcquire = tile->managedTexture()->canAcquireBackingTexture(); + bool dirty = tile->isDirty() || !tile->managedTexture()->haveBackingTexture(); + if (!updated && canAcquire && dirty) + return true; + } + } + return false; +} + +IntRect TiledLayerChromium::idlePaintRect() +{ + // Don't inflate an empty rect. + if (visibleContentRect().isEmpty()) + return IntRect(); + + // FIXME: This can be made a lot larger now! We should increase + // this slowly while insuring it doesn't cause any perf issues. + IntRect prepaintRect = visibleContentRect(); + prepaintRect.inflateX(m_tiler->tileSize().width()); + prepaintRect.inflateY(m_tiler->tileSize().height() * 2); + IntRect contentRect(IntPoint::zero(), contentBounds()); + prepaintRect.intersect(contentRect); + + return prepaintRect; +} + +} +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/cc/tiled_layer.h b/cc/tiled_layer.h index 638cbb2..3c27382 100644 --- a/cc/tiled_layer.h +++ b/cc/tiled_layer.h @@ -1,3 +1,105 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. +// Copyright 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef TiledLayerChromium_h +#define TiledLayerChromium_h + +#if USE(ACCELERATED_COMPOSITING) + +#include "CCLayerTilingData.h" +#include "LayerChromium.h" +#include "LayerTextureUpdater.h" + +namespace cc { +class UpdatableTile; + +class TiledLayerChromium : public LayerChromium { +public: + enum TilingOption { AlwaysTile, NeverTile, AutoTile }; + + virtual void setIsMask(bool) OVERRIDE; + + virtual void pushPropertiesTo(CCLayerImpl*) OVERRIDE; + + virtual bool drawsContent() const OVERRIDE; + virtual bool needsContentsScale() const OVERRIDE; + + virtual IntSize contentBounds() const OVERRIDE; + + virtual void setNeedsDisplayRect(const FloatRect&) OVERRIDE; + + virtual void setUseLCDText(bool) OVERRIDE; + + virtual void setLayerTreeHost(CCLayerTreeHost*) OVERRIDE; + + virtual void setTexturePriorities(const CCPriorityCalculator&) OVERRIDE; + + virtual Region visibleContentOpaqueRegion() const OVERRIDE; + + virtual void update(CCTextureUpdateQueue&, const CCOcclusionTracker*, CCRenderingStats&) OVERRIDE; + +protected: + TiledLayerChromium(); + virtual ~TiledLayerChromium(); + + void updateTileSizeAndTilingOption(); + void updateBounds(); + + // Exposed to subclasses for testing. + void setTileSize(const IntSize&); + void setTextureFormat(GC3Denum textureFormat) { m_textureFormat = textureFormat; } + void setBorderTexelOption(CCLayerTilingData::BorderTexelOption); + void setSampledTexelFormat(LayerTextureUpdater::SampledTexelFormat sampledTexelFormat) { m_sampledTexelFormat = sampledTexelFormat; } + size_t numPaintedTiles() { return m_tiler->tiles().size(); } + + virtual LayerTextureUpdater* textureUpdater() const = 0; + virtual void createTextureUpdaterIfNeeded() = 0; + + // Set invalidations to be potentially repainted during update(). + void invalidateContentRect(const IntRect& contentRect); + + // Reset state on tiles that will be used for updating the layer. + void resetUpdateState(); + + // After preparing an update, returns true if more painting is needed. + bool needsIdlePaint(); + IntRect idlePaintRect(); + + bool skipsDraw() const { return m_skipsDraw; } + + // Virtual for testing + virtual CCPrioritizedTextureManager* textureManager() const; + +private: + virtual scoped_ptr createCCLayerImpl() OVERRIDE; + + void createTilerIfNeeded(); + void setTilingOption(TilingOption); + + bool tileOnlyNeedsPartialUpdate(UpdatableTile*); + bool tileNeedsBufferedUpdate(UpdatableTile*); + + void markOcclusionsAndRequestTextures(int left, int top, int right, int bottom, const CCOcclusionTracker*); + + bool updateTiles(int left, int top, int right, int bottom, CCTextureUpdateQueue&, const CCOcclusionTracker*, CCRenderingStats&, bool& didPaint); + bool haveTexturesForTiles(int left, int top, int right, int bottom, bool ignoreOcclusions); + IntRect markTilesForUpdate(int left, int top, int right, int bottom, bool ignoreOcclusions); + void updateTileTextures(const IntRect& paintRect, int left, int top, int right, int bottom, CCTextureUpdateQueue&, const CCOcclusionTracker*, CCRenderingStats&); + + UpdatableTile* tileAt(int, int) const; + UpdatableTile* createTile(int, int); + + GC3Denum m_textureFormat; + bool m_skipsDraw; + bool m_failedUpdate; + LayerTextureUpdater::SampledTexelFormat m_sampledTexelFormat; + + TilingOption m_tilingOption; + OwnPtr m_tiler; +}; + +} +#endif // USE(ACCELERATED_COMPOSITING) + +#endif diff --git a/cc/tiled_layer_impl.cc b/cc/tiled_layer_impl.cc new file mode 100644 index 0000000..faa8ef8 --- /dev/null +++ b/cc/tiled_layer_impl.cc @@ -0,0 +1,253 @@ +// Copyright 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#if USE(ACCELERATED_COMPOSITING) + +#include "CCTiledLayerImpl.h" + +#include "base/basictypes.h" +#include "base/stringprintf.h" +#include "CCAppendQuadsData.h" +#include "CCCheckerboardDrawQuad.h" +#include "CCDebugBorderDrawQuad.h" +#include "CCLayerTilingData.h" +#include "CCMathUtil.h" +#include "CCQuadSink.h" +#include "CCSolidColorDrawQuad.h" +#include "CCTileDrawQuad.h" +#include "FloatQuad.h" +#include "GraphicsContext3D.h" +#include "SkColor.h" + +using namespace std; +using WebKit::WebTransformationMatrix; + +namespace cc { + +static const int debugTileBorderWidth = 1; +static const int debugTileBorderAlpha = 100; +static const int debugTileBorderColorRed = 80; +static const int debugTileBorderColorGreen = 200; +static const int debugTileBorderColorBlue = 200; +static const int debugTileBorderMissingTileColorRed = 255; +static const int debugTileBorderMissingTileColorGreen = 0; +static const int debugTileBorderMissingTileColorBlue = 0; + +static const int defaultCheckerboardColorRed = 241; +static const int defaultCheckerboardColorGreen = 241; +static const int defaultCheckerboardColorBlue = 241; +static const int debugTileEvictedCheckerboardColorRed = 255; +static const int debugTileEvictedCheckerboardColorGreen = 200; +static const int debugTileEvictedCheckerboardColorBlue = 200; +static const int debugTileInvalidatedCheckerboardColorRed = 128; +static const int debugTileInvalidatedCheckerboardColorGreen = 200; +static const int debugTileInvalidatedCheckerboardColorBlue = 245; + +class DrawableTile : public CCLayerTilingData::Tile { +public: + static PassOwnPtr create() { return adoptPtr(new DrawableTile()); } + + CCResourceProvider::ResourceId resourceId() const { return m_resourceId; } + void setResourceId(CCResourceProvider::ResourceId resourceId) { m_resourceId = resourceId; } + +private: + DrawableTile() : m_resourceId(0) { } + + CCResourceProvider::ResourceId m_resourceId; + + DISALLOW_COPY_AND_ASSIGN(DrawableTile); +}; + +CCTiledLayerImpl::CCTiledLayerImpl(int id) + : CCLayerImpl(id) + , m_skipsDraw(true) + , m_contentsSwizzled(false) +{ +} + +CCTiledLayerImpl::~CCTiledLayerImpl() +{ +} + +CCResourceProvider::ResourceId CCTiledLayerImpl::contentsResourceId() const +{ + // This function is only valid for single texture layers, e.g. masks. + ASSERT(m_tiler); + ASSERT(m_tiler->numTilesX() == 1); + ASSERT(m_tiler->numTilesY() == 1); + + DrawableTile* tile = tileAt(0, 0); + CCResourceProvider::ResourceId resourceId = tile ? tile->resourceId() : 0; + return resourceId; +} + +void CCTiledLayerImpl::dumpLayerProperties(std::string* str, int indent) const +{ + str->append(indentString(indent)); + base::StringAppendF(str, "skipsDraw: %d\n", (!m_tiler || m_skipsDraw)); + CCLayerImpl::dumpLayerProperties(str, indent); +} + +bool CCTiledLayerImpl::hasTileAt(int i, int j) const +{ + return m_tiler->tileAt(i, j); +} + +bool CCTiledLayerImpl::hasResourceIdForTileAt(int i, int j) const +{ + return hasTileAt(i, j) && tileAt(i, j)->resourceId(); +} + +DrawableTile* CCTiledLayerImpl::tileAt(int i, int j) const +{ + return static_cast(m_tiler->tileAt(i, j)); +} + +DrawableTile* CCTiledLayerImpl::createTile(int i, int j) +{ + OwnPtr tile(DrawableTile::create()); + DrawableTile* addedTile = tile.get(); + m_tiler->addTile(tile.release(), i, j); + return addedTile; +} + +void CCTiledLayerImpl::appendQuads(CCQuadSink& quadSink, CCAppendQuadsData& appendQuadsData) +{ + const IntRect& contentRect = visibleContentRect(); + + if (!m_tiler || m_tiler->hasEmptyBounds() || contentRect.isEmpty()) + return; + + CCSharedQuadState* sharedQuadState = quadSink.useSharedQuadState(createSharedQuadState()); + appendDebugBorderQuad(quadSink, sharedQuadState, appendQuadsData); + + int left, top, right, bottom; + m_tiler->contentRectToTileIndices(contentRect, left, top, right, bottom); + + if (hasDebugBorders()) { + for (int j = top; j <= bottom; ++j) { + for (int i = left; i <= right; ++i) { + DrawableTile* tile = tileAt(i, j); + IntRect tileRect = m_tiler->tileBounds(i, j); + SkColor borderColor; + + if (m_skipsDraw || !tile || !tile->resourceId()) + borderColor = SkColorSetARGB(debugTileBorderAlpha, debugTileBorderMissingTileColorRed, debugTileBorderMissingTileColorGreen, debugTileBorderMissingTileColorBlue); + else + borderColor = SkColorSetARGB(debugTileBorderAlpha, debugTileBorderColorRed, debugTileBorderColorGreen, debugTileBorderColorBlue); + quadSink.append(CCDebugBorderDrawQuad::create(sharedQuadState, tileRect, borderColor, debugTileBorderWidth).PassAs(), appendQuadsData); + } + } + } + + if (m_skipsDraw) + return; + + for (int j = top; j <= bottom; ++j) { + for (int i = left; i <= right; ++i) { + DrawableTile* tile = tileAt(i, j); + IntRect tileRect = m_tiler->tileBounds(i, j); + IntRect displayRect = tileRect; + tileRect.intersect(contentRect); + + // Skip empty tiles. + if (tileRect.isEmpty()) + continue; + + if (!tile || !tile->resourceId()) { + if (drawCheckerboardForMissingTiles()) { + SkColor defaultColor = SkColorSetRGB(defaultCheckerboardColorRed, defaultCheckerboardColorGreen, defaultCheckerboardColorBlue); + SkColor evictedColor = SkColorSetRGB(debugTileEvictedCheckerboardColorRed, debugTileEvictedCheckerboardColorGreen, debugTileEvictedCheckerboardColorBlue); + SkColor invalidatedColor = SkColorSetRGB(debugTileInvalidatedCheckerboardColorRed, debugTileEvictedCheckerboardColorGreen, debugTileEvictedCheckerboardColorBlue); + + SkColor checkerColor; + if (hasDebugBorders()) + checkerColor = tile ? invalidatedColor : evictedColor; + else + checkerColor = defaultColor; + + appendQuadsData.hadMissingTiles |= quadSink.append(CCCheckerboardDrawQuad::create(sharedQuadState, tileRect, checkerColor).PassAs(), appendQuadsData); + } else + appendQuadsData.hadMissingTiles |= quadSink.append(CCSolidColorDrawQuad::create(sharedQuadState, tileRect, backgroundColor()).PassAs(), appendQuadsData); + continue; + } + + IntRect tileOpaqueRect = tile->opaqueRect(); + tileOpaqueRect.intersect(contentRect); + + // Keep track of how the top left has moved, so the texture can be + // offset the same amount. + IntSize displayOffset = tileRect.minXMinYCorner() - displayRect.minXMinYCorner(); + IntPoint textureOffset = m_tiler->textureOffset(i, j) + displayOffset; + float tileWidth = static_cast(m_tiler->tileSize().width()); + float tileHeight = static_cast(m_tiler->tileSize().height()); + IntSize textureSize(tileWidth, tileHeight); + + bool clipped = false; + FloatQuad visibleContentInTargetQuad = CCMathUtil::mapQuad(drawTransform(), FloatQuad(visibleContentRect()), clipped); + bool isAxisAlignedInTarget = !clipped && visibleContentInTargetQuad.isRectilinear(); + bool useAA = m_tiler->hasBorderTexels() && !isAxisAlignedInTarget; + + bool leftEdgeAA = !i && useAA; + bool topEdgeAA = !j && useAA; + bool rightEdgeAA = i == m_tiler->numTilesX() - 1 && useAA; + bool bottomEdgeAA = j == m_tiler->numTilesY() - 1 && useAA; + + const GC3Dint textureFilter = m_tiler->hasBorderTexels() ? GraphicsContext3D::LINEAR : GraphicsContext3D::NEAREST; + quadSink.append(CCTileDrawQuad::create(sharedQuadState, tileRect, tileOpaqueRect, tile->resourceId(), textureOffset, textureSize, textureFilter, contentsSwizzled(), leftEdgeAA, topEdgeAA, rightEdgeAA, bottomEdgeAA).PassAs(), appendQuadsData); + } + } +} + +void CCTiledLayerImpl::setTilingData(const CCLayerTilingData& tiler) +{ + if (m_tiler) + m_tiler->reset(); + else + m_tiler = CCLayerTilingData::create(tiler.tileSize(), tiler.hasBorderTexels() ? CCLayerTilingData::HasBorderTexels : CCLayerTilingData::NoBorderTexels); + *m_tiler = tiler; +} + +void CCTiledLayerImpl::pushTileProperties(int i, int j, CCResourceProvider::ResourceId resourceId, const IntRect& opaqueRect) +{ + DrawableTile* tile = tileAt(i, j); + if (!tile) + tile = createTile(i, j); + tile->setResourceId(resourceId); + tile->setOpaqueRect(opaqueRect); +} + +void CCTiledLayerImpl::pushInvalidTile(int i, int j) +{ + DrawableTile* tile = tileAt(i, j); + if (!tile) + tile = createTile(i, j); + tile->setResourceId(0); + tile->setOpaqueRect(IntRect()); +} + +Region CCTiledLayerImpl::visibleContentOpaqueRegion() const +{ + if (m_skipsDraw) + return Region(); + if (contentsOpaque()) + return visibleContentRect(); + return m_tiler->opaqueRegionInContentRect(visibleContentRect()); +} + +void CCTiledLayerImpl::didLoseContext() +{ + m_tiler->reset(); +} + +const char* CCTiledLayerImpl::layerTypeAsString() const +{ + return "ContentLayer"; +} + +} // namespace cc + +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/cc/tiled_layer_impl.h b/cc/tiled_layer_impl.h index 638cbb2..2d6803d 100644 --- a/cc/tiled_layer_impl.h +++ b/cc/tiled_layer_impl.h @@ -1,3 +1,62 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. +// Copyright 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CCTiledLayerImpl_h +#define CCTiledLayerImpl_h + +#include "CCLayerImpl.h" +#include + +namespace cc { + +class CCLayerTilingData; +class DrawableTile; + +class CCTiledLayerImpl : public CCLayerImpl { +public: + static scoped_ptr create(int id) + { + return make_scoped_ptr(new CCTiledLayerImpl(id)); + } + virtual ~CCTiledLayerImpl(); + + virtual void appendQuads(CCQuadSink&, CCAppendQuadsData&) OVERRIDE; + + virtual CCResourceProvider::ResourceId contentsResourceId() const OVERRIDE; + + virtual void dumpLayerProperties(std::string*, int indent) const OVERRIDE; + + void setSkipsDraw(bool skipsDraw) { m_skipsDraw = skipsDraw; } + void setTilingData(const CCLayerTilingData& tiler); + void pushTileProperties(int, int, CCResourceProvider::ResourceId, const IntRect& opaqueRect); + void pushInvalidTile(int, int); + + void setContentsSwizzled(bool contentsSwizzled) { m_contentsSwizzled = contentsSwizzled; } + bool contentsSwizzled() const { return m_contentsSwizzled; } + + virtual Region visibleContentOpaqueRegion() const OVERRIDE; + virtual void didLoseContext() OVERRIDE; + +protected: + explicit CCTiledLayerImpl(int id); + // Exposed for testing. + bool hasTileAt(int, int) const; + bool hasResourceIdForTileAt(int, int) const; + +private: + + virtual const char* layerTypeAsString() const OVERRIDE; + + DrawableTile* tileAt(int, int) const; + DrawableTile* createTile(int, int); + + bool m_skipsDraw; + bool m_contentsSwizzled; + + OwnPtr m_tiler; +}; + +} + +#endif // CCTiledLayerImpl_h diff --git a/cc/time_source.h b/cc/time_source.h index 638cbb2..6f24d35 100644 --- a/cc/time_source.h +++ b/cc/time_source.h @@ -1,3 +1,40 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. +// Copyright 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CCTimeSource_h +#define CCTimeSource_h + +#include "base/time.h" +#include + +namespace cc { + +class CCThread; + +class CCTimeSourceClient { +public: + virtual void onTimerTick() = 0; + +protected: + virtual ~CCTimeSourceClient() { } +}; + +// An generic interface for getting a reliably-ticking timesource of +// a specified rate. +// +// Be sure to call setActive(false) before releasing your reference to the +// timer, or it will keep on ticking! +class CCTimeSource : public RefCounted { +public: + virtual ~CCTimeSource() { } + virtual void setClient(CCTimeSourceClient*) = 0; + virtual void setActive(bool) = 0; + virtual bool active() const = 0; + virtual void setTimebaseAndInterval(base::TimeTicks timebase, base::TimeDelta interval) = 0; + virtual base::TimeTicks lastTickTime() = 0; + virtual base::TimeTicks nextTickTime() = 0; +}; + +} +#endif // CCSmoothedTimer_h diff --git a/cc/timer.cc b/cc/timer.cc new file mode 100644 index 0000000..089c12b --- /dev/null +++ b/cc/timer.cc @@ -0,0 +1,80 @@ +// Copyright 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#include "CCTimer.h" + +#include "base/compiler_specific.h" +#include "CCThread.h" + +namespace cc { + +class CCTimerTask : public CCThread::Task { +public: + explicit CCTimerTask(CCTimer* timer) + : CCThread::Task(0) + , m_timer(timer) + { + } + + virtual ~CCTimerTask() + { + if (!m_timer) + return; + + ASSERT(m_timer->m_task == this); + m_timer->stop(); + } + + virtual void performTask() OVERRIDE + { + if (!m_timer) + return; + + CCTimerClient* client = m_timer->m_client; + + m_timer->stop(); + if (client) + client->onTimerFired(); + } + +private: + friend class CCTimer; + + CCTimer* m_timer; // null if cancelled +}; + +CCTimer::CCTimer(CCThread* thread, CCTimerClient* client) + : m_client(client) + , m_thread(thread) + , m_task(0) +{ +} + +CCTimer::~CCTimer() +{ + stop(); +} + +void CCTimer::startOneShot(double intervalSeconds) +{ + stop(); + + m_task = new CCTimerTask(this); + + // The thread expects delays in milliseconds. + m_thread->postDelayedTask(adoptPtr(m_task), intervalSeconds * 1000.0); +} + +void CCTimer::stop() +{ + if (!m_task) + return; + + m_task->m_timer = 0; + m_task = 0; +} + +} // namespace cc diff --git a/cc/timer.h b/cc/timer.h index 638cbb2..9424aef 100644 --- a/cc/timer.h +++ b/cc/timer.h @@ -1,3 +1,41 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. +// Copyright 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CCTimer_h +#define CCTimer_h + +namespace cc { + +class CCThread; +class CCTimerTask; + +class CCTimerClient { +public: + virtual ~CCTimerClient() { } + + virtual void onTimerFired() = 0; +}; + +class CCTimer { +public: + CCTimer(CCThread*, CCTimerClient*); + ~CCTimer(); + + // If a previous task is pending, it will be replaced with the new one. + void startOneShot(double intervalSeconds); + void stop(); + + bool isActive() const { return m_task; } + +private: + friend class CCTimerTask; + + CCTimerClient* m_client; + CCThread* m_thread; + CCTimerTask* m_task; // weak pointer +}; + +} // namespace cc + +#endif diff --git a/cc/timing_function.cc b/cc/timing_function.cc new file mode 100644 index 0000000..3a4ecd4 --- /dev/null +++ b/cc/timing_function.cc @@ -0,0 +1,74 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#include "CCTimingFunction.h" + +namespace { +const double epsilon = 1e-6; +} // namespace + +namespace cc { + +CCTimingFunction::CCTimingFunction() +{ +} + +CCTimingFunction::~CCTimingFunction() +{ +} + +double CCTimingFunction::duration() const +{ + return 1.0; +} + +scoped_ptr CCCubicBezierTimingFunction::create(double x1, double y1, double x2, double y2) +{ + return make_scoped_ptr(new CCCubicBezierTimingFunction(x1, y1, x2, y2)); +} + +CCCubicBezierTimingFunction::CCCubicBezierTimingFunction(double x1, double y1, double x2, double y2) + : m_curve(x1, y1, x2, y2) +{ +} + +CCCubicBezierTimingFunction::~CCCubicBezierTimingFunction() +{ +} + +float CCCubicBezierTimingFunction::getValue(double x) const +{ + UnitBezier temp(m_curve); + return static_cast(temp.solve(x, epsilon)); +} + +scoped_ptr CCCubicBezierTimingFunction::clone() const +{ + return make_scoped_ptr(new CCCubicBezierTimingFunction(*this)).PassAs(); +} + +// These numbers come from http://www.w3.org/TR/css3-transitions/#transition-timing-function_tag. +scoped_ptr CCEaseTimingFunction::create() +{ + return CCCubicBezierTimingFunction::create(0.25, 0.1, 0.25, 1).PassAs(); +} + +scoped_ptr CCEaseInTimingFunction::create() +{ + return CCCubicBezierTimingFunction::create(0.42, 0, 1.0, 1).PassAs(); +} + +scoped_ptr CCEaseOutTimingFunction::create() +{ + return CCCubicBezierTimingFunction::create(0, 0, 0.58, 1).PassAs(); +} + +scoped_ptr CCEaseInOutTimingFunction::create() +{ + return CCCubicBezierTimingFunction::create(0.42, 0, 0.58, 1).PassAs(); +} + +} // namespace cc diff --git a/cc/timing_function.h b/cc/timing_function.h index 638cbb2..993ab87 100644 --- a/cc/timing_function.h +++ b/cc/timing_function.h @@ -1,3 +1,62 @@ // Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CCTimingFunction_h +#define CCTimingFunction_h + +#include "CCAnimationCurve.h" +#include "UnitBezier.h" + +namespace cc { + +// See http://www.w3.org/TR/css3-transitions/. +class CCTimingFunction : public CCFloatAnimationCurve { +public: + virtual ~CCTimingFunction(); + + // Partial implementation of CCFloatAnimationCurve. + virtual double duration() const OVERRIDE; + +protected: + CCTimingFunction(); +}; + +class CCCubicBezierTimingFunction : public CCTimingFunction { +public: + static scoped_ptr create(double x1, double y1, double x2, double y2); + virtual ~CCCubicBezierTimingFunction(); + + // Partial implementation of CCFloatAnimationCurve. + virtual float getValue(double time) const OVERRIDE; + virtual scoped_ptr clone() const OVERRIDE; + +protected: + CCCubicBezierTimingFunction(double x1, double y1, double x2, double y2); + + UnitBezier m_curve; +}; + +class CCEaseTimingFunction { +public: + static scoped_ptr create(); +}; + +class CCEaseInTimingFunction { +public: + static scoped_ptr create(); +}; + +class CCEaseOutTimingFunction { +public: + static scoped_ptr create(); +}; + +class CCEaseInOutTimingFunction { +public: + static scoped_ptr create(); +}; + +} // namespace cc + +#endif // CCTimingFunction_h diff --git a/cc/tree_synchronizer.cc b/cc/tree_synchronizer.cc new file mode 100644 index 0000000..b7e76bb --- /dev/null +++ b/cc/tree_synchronizer.cc @@ -0,0 +1,112 @@ +// Copyright 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#include "TreeSynchronizer.h" + +#include "CCLayerImpl.h" +#include "CCScrollbarAnimationController.h" +#include "CCScrollbarLayerImpl.h" +#include "LayerChromium.h" +#include "ScrollbarLayerChromium.h" + +namespace cc { + +scoped_ptr TreeSynchronizer::synchronizeTrees(LayerChromium* layerChromiumRoot, scoped_ptr oldCCLayerImplRoot, CCLayerTreeHostImpl* hostImpl) +{ + ScopedPtrCCLayerImplMap oldLayers; + RawPtrCCLayerImplMap newLayers; + + collectExistingCCLayerImplRecursive(oldLayers, oldCCLayerImplRoot.Pass()); + + scoped_ptr newTree = synchronizeTreeRecursive(newLayers, oldLayers, layerChromiumRoot, hostImpl); + + updateScrollbarLayerPointersRecursive(newLayers, layerChromiumRoot); + + return newTree.Pass(); +} + +void TreeSynchronizer::collectExistingCCLayerImplRecursive(ScopedPtrCCLayerImplMap& oldLayers, scoped_ptr ccLayerImpl) +{ + if (!ccLayerImpl) + return; + + ScopedPtrVector& children = ccLayerImpl->m_children; + for (size_t i = 0; i < children.size(); ++i) + collectExistingCCLayerImplRecursive(oldLayers, children.take(i)); + + collectExistingCCLayerImplRecursive(oldLayers, ccLayerImpl->m_maskLayer.Pass()); + collectExistingCCLayerImplRecursive(oldLayers, ccLayerImpl->m_replicaLayer.Pass()); + + int id = ccLayerImpl->id(); + oldLayers.set(id, ccLayerImpl.Pass()); +} + +scoped_ptr TreeSynchronizer::reuseOrCreateCCLayerImpl(RawPtrCCLayerImplMap& newLayers, ScopedPtrCCLayerImplMap& oldLayers, LayerChromium* layer) +{ + scoped_ptr ccLayerImpl = oldLayers.take(layer->id()); + + if (!ccLayerImpl) + ccLayerImpl = layer->createCCLayerImpl(); + + newLayers[layer->id()] = ccLayerImpl.get(); + return ccLayerImpl.Pass(); +} + +scoped_ptr TreeSynchronizer::synchronizeTreeRecursive(RawPtrCCLayerImplMap& newLayers, ScopedPtrCCLayerImplMap& oldLayers, LayerChromium* layer, CCLayerTreeHostImpl* hostImpl) +{ + if (!layer) + return scoped_ptr(); + + scoped_ptr ccLayerImpl = reuseOrCreateCCLayerImpl(newLayers, oldLayers, layer); + + ccLayerImpl->clearChildList(); + const std::vector >& children = layer->children(); + for (size_t i = 0; i < children.size(); ++i) + ccLayerImpl->addChild(synchronizeTreeRecursive(newLayers, oldLayers, children[i].get(), hostImpl)); + + ccLayerImpl->setMaskLayer(synchronizeTreeRecursive(newLayers, oldLayers, layer->maskLayer(), hostImpl)); + ccLayerImpl->setReplicaLayer(synchronizeTreeRecursive(newLayers, oldLayers, layer->replicaLayer(), hostImpl)); + + layer->pushPropertiesTo(ccLayerImpl.get()); + ccLayerImpl->setLayerTreeHostImpl(hostImpl); + + // Remove all dangling pointers. The pointers will be setup later in updateScrollbarLayerPointersRecursive phase + if (CCScrollbarAnimationController* scrollbarController = ccLayerImpl->scrollbarAnimationController()) { + scrollbarController->setHorizontalScrollbarLayer(0); + scrollbarController->setVerticalScrollbarLayer(0); + } + + return ccLayerImpl.Pass(); +} + +void TreeSynchronizer::updateScrollbarLayerPointersRecursive(const RawPtrCCLayerImplMap& newLayers, LayerChromium* layer) +{ + if (!layer) + return; + + const std::vector >& children = layer->children(); + for (size_t i = 0; i < children.size(); ++i) + updateScrollbarLayerPointersRecursive(newLayers, children[i].get()); + + ScrollbarLayerChromium* scrollbarLayer = layer->toScrollbarLayerChromium(); + if (!scrollbarLayer) + return; + + RawPtrCCLayerImplMap::const_iterator iter = newLayers.find(scrollbarLayer->id()); + CCScrollbarLayerImpl* ccScrollbarLayerImpl = iter != newLayers.end() ? static_cast(iter->second) : NULL; + iter = newLayers.find(scrollbarLayer->scrollLayerId()); + CCLayerImpl* ccScrollLayerImpl = iter != newLayers.end() ? iter->second : NULL; + + ASSERT(ccScrollbarLayerImpl); + ASSERT(ccScrollLayerImpl); + + if (ccScrollbarLayerImpl->orientation() == WebKit::WebScrollbar::Horizontal) + ccScrollLayerImpl->setHorizontalScrollbarLayer(ccScrollbarLayerImpl); + else + ccScrollLayerImpl->setVerticalScrollbarLayer(ccScrollbarLayerImpl); +} + +} // namespace cc diff --git a/cc/tree_synchronizer.h b/cc/tree_synchronizer.h index 638cbb2..2609841 100644 --- a/cc/tree_synchronizer.h +++ b/cc/tree_synchronizer.h @@ -1,3 +1,41 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. +// Copyright 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef TreeSynchronizer_h +#define TreeSynchronizer_h + +#include "base/basictypes.h" +#include "base/memory/scoped_ptr.h" +#include "cc/scoped_ptr_hash_map.h" + +namespace cc { + +class CCLayerImpl; +class CCLayerTreeHostImpl; +class LayerChromium; + +class TreeSynchronizer { +public: + // Accepts a LayerChromium tree and returns a reference to a CCLayerImpl tree that duplicates the structure + // of the LayerChromium tree, reusing the CCLayerImpls in the tree provided by oldCCLayerImplRoot if possible. + static scoped_ptr synchronizeTrees(LayerChromium* layerRoot, scoped_ptr oldCCLayerImplRoot, CCLayerTreeHostImpl*); + +private: + TreeSynchronizer(); // Not instantiable. + + typedef ScopedPtrHashMap ScopedPtrCCLayerImplMap; + typedef base::hash_map RawPtrCCLayerImplMap; + + // Declared as static member functions so they can access functions on LayerChromium as a friend class. + static scoped_ptr reuseOrCreateCCLayerImpl(RawPtrCCLayerImplMap& newLayers, ScopedPtrCCLayerImplMap& oldLayers, LayerChromium*); + static void collectExistingCCLayerImplRecursive(ScopedPtrCCLayerImplMap& oldLayers, scoped_ptr); + static scoped_ptr synchronizeTreeRecursive(RawPtrCCLayerImplMap& newLayers, ScopedPtrCCLayerImplMap& oldLayers, LayerChromium*, CCLayerTreeHostImpl*); + static void updateScrollbarLayerPointersRecursive(const RawPtrCCLayerImplMap& newLayers, LayerChromium*); + + DISALLOW_COPY_AND_ASSIGN(TreeSynchronizer); +}; + +} // namespace cc + +#endif // TreeSynchronizer_h diff --git a/cc/unthrottled_texture_uploader.cc b/cc/unthrottled_texture_uploader.cc new file mode 100644 index 0000000..82b4337 --- /dev/null +++ b/cc/unthrottled_texture_uploader.cc @@ -0,0 +1,30 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#include "UnthrottledTextureUploader.h" + +namespace cc { + +size_t UnthrottledTextureUploader::numBlockingUploads() +{ + return 0; +} + +void UnthrottledTextureUploader::markPendingUploadsAsNonBlocking() +{ +} + +double UnthrottledTextureUploader::estimatedTexturesPerSecond() +{ + return std::numeric_limits::max(); +} + +void UnthrottledTextureUploader::uploadTexture(CCResourceProvider* resourceProvider, Parameters upload) +{ + upload.texture->updateRect(resourceProvider, upload.sourceRect, upload.destOffset); +} + +} diff --git a/cc/unthrottled_texture_uploader.h b/cc/unthrottled_texture_uploader.h index 638cbb2..bc0822a 100644 --- a/cc/unthrottled_texture_uploader.h +++ b/cc/unthrottled_texture_uploader.h @@ -1,3 +1,36 @@ // Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef UnthrottledTextureUploader_h +#define UnthrottledTextureUploader_h + +#include "base/basictypes.h" +#include "CCResourceProvider.h" +#include "TextureUploader.h" + +namespace cc { + +class UnthrottledTextureUploader : public TextureUploader { +public: + static PassOwnPtr create() + { + return adoptPtr(new UnthrottledTextureUploader()); + } + virtual ~UnthrottledTextureUploader() { } + + virtual size_t numBlockingUploads() OVERRIDE; + virtual void markPendingUploadsAsNonBlocking() OVERRIDE; + virtual double estimatedTexturesPerSecond() OVERRIDE; + virtual void uploadTexture(CCResourceProvider* resourceProvider, Parameters upload) OVERRIDE; + +protected: + UnthrottledTextureUploader() { } + +private: + DISALLOW_COPY_AND_ASSIGN(UnthrottledTextureUploader); +}; + +} + +#endif diff --git a/cc/video_layer.cc b/cc/video_layer.cc new file mode 100644 index 0000000..e210473 --- /dev/null +++ b/cc/video_layer.cc @@ -0,0 +1,37 @@ +// Copyright 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#if USE(ACCELERATED_COMPOSITING) +#include "VideoLayerChromium.h" + +#include "CCVideoLayerImpl.h" + +namespace cc { + +scoped_refptr VideoLayerChromium::create(WebKit::WebVideoFrameProvider* provider) +{ + return make_scoped_refptr(new VideoLayerChromium(provider)); +} + +VideoLayerChromium::VideoLayerChromium(WebKit::WebVideoFrameProvider* provider) + : LayerChromium() + , m_provider(provider) +{ + ASSERT(m_provider); +} + +VideoLayerChromium::~VideoLayerChromium() +{ +} + +scoped_ptr VideoLayerChromium::createCCLayerImpl() +{ + return CCVideoLayerImpl::create(m_layerId, m_provider).PassAs(); +} + +} // namespace cc + +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/cc/video_layer.h b/cc/video_layer.h index 638cbb2..92b5e13 100644 --- a/cc/video_layer.h +++ b/cc/video_layer.h @@ -1,3 +1,39 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. +// Copyright 2010 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + + +#ifndef VideoLayerChromium_h +#define VideoLayerChromium_h + +#if USE(ACCELERATED_COMPOSITING) + +#include "LayerChromium.h" + +namespace WebKit { +class WebVideoFrameProvider; +} + +namespace cc { + +class CCVideoLayerImpl; + +// A Layer that contains a Video element. +class VideoLayerChromium : public LayerChromium { +public: + static scoped_refptr create(WebKit::WebVideoFrameProvider*); + + virtual scoped_ptr createCCLayerImpl() OVERRIDE; + +private: + explicit VideoLayerChromium(WebKit::WebVideoFrameProvider*); + virtual ~VideoLayerChromium(); + + // This pointer is only for passing to CCVideoLayerImpl's constructor. It should never be dereferenced by this class. + WebKit::WebVideoFrameProvider* m_provider; +}; + +} +#endif // USE(ACCELERATED_COMPOSITING) + +#endif diff --git a/cc/video_layer_impl.cc b/cc/video_layer_impl.cc new file mode 100644 index 0000000..d1fb412 --- /dev/null +++ b/cc/video_layer_impl.cc @@ -0,0 +1,391 @@ +// Copyright 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#if USE(ACCELERATED_COMPOSITING) + +#include "CCVideoLayerImpl.h" + +#include "CCIOSurfaceDrawQuad.h" +#include "CCLayerTreeHostImpl.h" +#include "CCProxy.h" +#include "CCQuadSink.h" +#include "CCResourceProvider.h" +#include "CCStreamVideoDrawQuad.h" +#include "CCTextureDrawQuad.h" +#include "CCYUVVideoDrawQuad.h" +#include "Extensions3DChromium.h" +#include "GraphicsContext3D.h" +#include "NotImplemented.h" +#include + +namespace cc { + +CCVideoLayerImpl::CCVideoLayerImpl(int id, WebKit::WebVideoFrameProvider* provider) + : CCLayerImpl(id) + , m_provider(provider) + , m_frame(0) + , m_externalTextureResource(0) +{ + // This matrix is the default transformation for stream textures, and flips on the Y axis. + m_streamTextureMatrix = WebKit::WebTransformationMatrix( + 1, 0, 0, 0, + 0, -1, 0, 0, + 0, 0, 1, 0, + 0, 1, 0, 1); + + // This only happens during a commit on the compositor thread while the main + // thread is blocked. That makes this a thread-safe call to set the video + // frame provider client that does not require a lock. The same is true of + // the call in the destructor. + ASSERT(CCProxy::isMainThreadBlocked()); + m_provider->setVideoFrameProviderClient(this); +} + +CCVideoLayerImpl::~CCVideoLayerImpl() +{ + // See comment in constructor for why this doesn't need a lock. + ASSERT(CCProxy::isMainThreadBlocked()); + if (m_provider) { + m_provider->setVideoFrameProviderClient(0); + m_provider = 0; + } + freePlaneData(layerTreeHostImpl()->resourceProvider()); + +#if !ASSERT_DISABLED + for (unsigned i = 0; i < WebKit::WebVideoFrame::maxPlanes; ++i) + ASSERT(!m_framePlanes[i].resourceId); + ASSERT(!m_externalTextureResource); +#endif +} + +void CCVideoLayerImpl::stopUsingProvider() +{ + // Block the provider from shutting down until this client is done + // using the frame. + MutexLocker locker(m_providerMutex); + ASSERT(!m_frame); + m_provider = 0; +} + +// Convert WebKit::WebVideoFrame::Format to GraphicsContext3D's format enum values. +static GC3Denum convertVFCFormatToGC3DFormat(const WebKit::WebVideoFrame& frame) +{ + switch (frame.format()) { + case WebKit::WebVideoFrame::FormatYV12: + case WebKit::WebVideoFrame::FormatYV16: + return GraphicsContext3D::LUMINANCE; + case WebKit::WebVideoFrame::FormatNativeTexture: + return frame.textureTarget(); + case WebKit::WebVideoFrame::FormatInvalid: + case WebKit::WebVideoFrame::FormatRGB32: + case WebKit::WebVideoFrame::FormatEmpty: + case WebKit::WebVideoFrame::FormatI420: + notImplemented(); + } + return GraphicsContext3D::INVALID_VALUE; +} + +void CCVideoLayerImpl::willDraw(CCResourceProvider* resourceProvider) +{ + ASSERT(CCProxy::isImplThread()); + CCLayerImpl::willDraw(resourceProvider); + + // Explicitly lock and unlock the provider mutex so it can be held from + // willDraw to didDraw. Since the compositor thread is in the middle of + // drawing, the layer will not be destroyed before didDraw is called. + // Therefore, the only thing that will prevent this lock from being released + // is the GPU process locking it. As the GPU process can't cause the + // destruction of the provider (calling stopUsingProvider), holding this + // lock should not cause a deadlock. + m_providerMutex.lock(); + + willDrawInternal(resourceProvider); + freeUnusedPlaneData(resourceProvider); + + if (!m_frame) + m_providerMutex.unlock(); +} + +void CCVideoLayerImpl::willDrawInternal(CCResourceProvider* resourceProvider) +{ + ASSERT(CCProxy::isImplThread()); + ASSERT(!m_externalTextureResource); + + if (!m_provider) { + m_frame = 0; + return; + } + + m_frame = m_provider->getCurrentFrame(); + + if (!m_frame) + return; + + m_format = convertVFCFormatToGC3DFormat(*m_frame); + + if (m_format == GraphicsContext3D::INVALID_VALUE) { + m_provider->putCurrentFrame(m_frame); + m_frame = 0; + return; + } + + if (m_frame->planes() > WebKit::WebVideoFrame::maxPlanes) { + m_provider->putCurrentFrame(m_frame); + m_frame = 0; + return; + } + + if (!allocatePlaneData(resourceProvider)) { + m_provider->putCurrentFrame(m_frame); + m_frame = 0; + return; + } + + if (!copyPlaneData(resourceProvider)) { + m_provider->putCurrentFrame(m_frame); + m_frame = 0; + return; + } + + if (m_format == GraphicsContext3D::TEXTURE_2D) + m_externalTextureResource = resourceProvider->createResourceFromExternalTexture(m_frame->textureId()); +} + +void CCVideoLayerImpl::appendQuads(CCQuadSink& quadSink, CCAppendQuadsData& appendQuadsData) +{ + ASSERT(CCProxy::isImplThread()); + + if (!m_frame) + return; + + CCSharedQuadState* sharedQuadState = quadSink.useSharedQuadState(createSharedQuadState()); + appendDebugBorderQuad(quadSink, sharedQuadState, appendQuadsData); + + // FIXME: When we pass quads out of process, we need to double-buffer, or + // otherwise synchonize use of all textures in the quad. + + IntRect quadRect(IntPoint(), contentBounds()); + + switch (m_format) { + case GraphicsContext3D::LUMINANCE: { + // YUV software decoder. + const FramePlane& yPlane = m_framePlanes[WebKit::WebVideoFrame::yPlane]; + const FramePlane& uPlane = m_framePlanes[WebKit::WebVideoFrame::uPlane]; + const FramePlane& vPlane = m_framePlanes[WebKit::WebVideoFrame::vPlane]; + scoped_ptr yuvVideoQuad = CCYUVVideoDrawQuad::create(sharedQuadState, quadRect, yPlane, uPlane, vPlane); + quadSink.append(yuvVideoQuad.PassAs(), appendQuadsData); + break; + } + case GraphicsContext3D::RGBA: { + // RGBA software decoder. + const FramePlane& plane = m_framePlanes[WebKit::WebVideoFrame::rgbPlane]; + float widthScaleFactor = static_cast(plane.visibleSize.width()) / plane.size.width(); + + bool premultipliedAlpha = true; + FloatRect uvRect(0, 0, widthScaleFactor, 1); + bool flipped = false; + scoped_ptr textureQuad = CCTextureDrawQuad::create(sharedQuadState, quadRect, plane.resourceId, premultipliedAlpha, uvRect, flipped); + quadSink.append(textureQuad.PassAs(), appendQuadsData); + break; + } + case GraphicsContext3D::TEXTURE_2D: { + // NativeTexture hardware decoder. + bool premultipliedAlpha = true; + FloatRect uvRect(0, 0, 1, 1); + bool flipped = false; + scoped_ptr textureQuad = CCTextureDrawQuad::create(sharedQuadState, quadRect, m_externalTextureResource, premultipliedAlpha, uvRect, flipped); + quadSink.append(textureQuad.PassAs(), appendQuadsData); + break; + } + case Extensions3D::TEXTURE_RECTANGLE_ARB: { + IntSize textureSize(m_frame->width(), m_frame->height()); + scoped_ptr ioSurfaceQuad = CCIOSurfaceDrawQuad::create(sharedQuadState, quadRect, textureSize, m_frame->textureId(), CCIOSurfaceDrawQuad::Unflipped); + quadSink.append(ioSurfaceQuad.PassAs(), appendQuadsData); + break; + } + case Extensions3DChromium::GL_TEXTURE_EXTERNAL_OES: { + // StreamTexture hardware decoder. + scoped_ptr streamVideoQuad = CCStreamVideoDrawQuad::create(sharedQuadState, quadRect, m_frame->textureId(), m_streamTextureMatrix); + quadSink.append(streamVideoQuad.PassAs(), appendQuadsData); + break; + } + default: + CRASH(); // Someone updated convertVFCFormatToGC3DFormat above but update this! + } +} + +void CCVideoLayerImpl::didDraw(CCResourceProvider* resourceProvider) +{ + ASSERT(CCProxy::isImplThread()); + CCLayerImpl::didDraw(resourceProvider); + + if (!m_frame) + return; + + if (m_format == GraphicsContext3D::TEXTURE_2D) { + ASSERT(m_externalTextureResource); + // FIXME: the following assert will not be true when sending resources to a + // parent compositor. We will probably need to hold on to m_frame for + // longer, and have several "current frames" in the pipeline. + ASSERT(!resourceProvider->inUseByConsumer(m_externalTextureResource)); + resourceProvider->deleteResource(m_externalTextureResource); + m_externalTextureResource = 0; + } + + m_provider->putCurrentFrame(m_frame); + m_frame = 0; + + m_providerMutex.unlock(); +} + +static int videoFrameDimension(int originalDimension, unsigned plane, int format) +{ + if (format == WebKit::WebVideoFrame::FormatYV12 && plane != WebKit::WebVideoFrame::yPlane) + return originalDimension / 2; + return originalDimension; +} + +static bool hasPaddingBytes(const WebKit::WebVideoFrame& frame, unsigned plane) +{ + return frame.stride(plane) > videoFrameDimension(frame.width(), plane, frame.format()); +} + +IntSize CCVideoLayerImpl::computeVisibleSize(const WebKit::WebVideoFrame& frame, unsigned plane) +{ + int visibleWidth = videoFrameDimension(frame.width(), plane, frame.format()); + int originalWidth = visibleWidth; + int visibleHeight = videoFrameDimension(frame.height(), plane, frame.format()); + + // When there are dead pixels at the edge of the texture, decrease + // the frame width by 1 to prevent the rightmost pixels from + // interpolating with the dead pixels. + if (hasPaddingBytes(frame, plane)) + --visibleWidth; + + // In YV12, every 2x2 square of Y values corresponds to one U and + // one V value. If we decrease the width of the UV plane, we must decrease the + // width of the Y texture by 2 for proper alignment. This must happen + // always, even if Y's texture does not have padding bytes. + if (plane == WebKit::WebVideoFrame::yPlane && frame.format() == WebKit::WebVideoFrame::FormatYV12) { + if (hasPaddingBytes(frame, WebKit::WebVideoFrame::uPlane)) + visibleWidth = originalWidth - 2; + } + + return IntSize(visibleWidth, visibleHeight); +} + +bool CCVideoLayerImpl::FramePlane::allocateData(CCResourceProvider* resourceProvider) +{ + if (resourceId) + return true; + + resourceId = resourceProvider->createResource(CCRenderer::ImplPool, size, format, CCResourceProvider::TextureUsageAny); + return resourceId; +} + +void CCVideoLayerImpl::FramePlane::freeData(CCResourceProvider* resourceProvider) +{ + if (!resourceId) + return; + + resourceProvider->deleteResource(resourceId); + resourceId = 0; +} + +bool CCVideoLayerImpl::allocatePlaneData(CCResourceProvider* resourceProvider) +{ + int maxTextureSize = resourceProvider->maxTextureSize(); + for (unsigned planeIndex = 0; planeIndex < m_frame->planes(); ++planeIndex) { + CCVideoLayerImpl::FramePlane& plane = m_framePlanes[planeIndex]; + + IntSize requiredTextureSize(m_frame->stride(planeIndex), videoFrameDimension(m_frame->height(), planeIndex, m_frame->format())); + // FIXME: Remove the test against maxTextureSize when tiled layers are implemented. + if (requiredTextureSize.isZero() || requiredTextureSize.width() > maxTextureSize || requiredTextureSize.height() > maxTextureSize) + return false; + + if (plane.size != requiredTextureSize || plane.format != m_format) { + plane.freeData(resourceProvider); + plane.size = requiredTextureSize; + plane.format = m_format; + } + + if (!plane.resourceId) { + if (!plane.allocateData(resourceProvider)) + return false; + plane.visibleSize = computeVisibleSize(*m_frame, planeIndex); + } + } + return true; +} + +bool CCVideoLayerImpl::copyPlaneData(CCResourceProvider* resourceProvider) +{ + size_t softwarePlaneCount = m_frame->planes(); + if (!softwarePlaneCount) + return true; + + for (size_t softwarePlaneIndex = 0; softwarePlaneIndex < softwarePlaneCount; ++softwarePlaneIndex) { + CCVideoLayerImpl::FramePlane& plane = m_framePlanes[softwarePlaneIndex]; + const uint8_t* softwarePlanePixels = static_cast(m_frame->data(softwarePlaneIndex)); + IntRect planeRect(IntPoint(), plane.size); + resourceProvider->upload(plane.resourceId, softwarePlanePixels, planeRect, planeRect, IntSize()); + } + return true; +} + +void CCVideoLayerImpl::freePlaneData(CCResourceProvider* resourceProvider) +{ + for (unsigned i = 0; i < WebKit::WebVideoFrame::maxPlanes; ++i) + m_framePlanes[i].freeData(resourceProvider); +} + +void CCVideoLayerImpl::freeUnusedPlaneData(CCResourceProvider* resourceProvider) +{ + unsigned firstUnusedPlane = m_frame ? m_frame->planes() : 0; + for (unsigned i = firstUnusedPlane; i < WebKit::WebVideoFrame::maxPlanes; ++i) + m_framePlanes[i].freeData(resourceProvider); +} + +void CCVideoLayerImpl::didReceiveFrame() +{ + setNeedsRedraw(); +} + +void CCVideoLayerImpl::didUpdateMatrix(const float matrix[16]) +{ + m_streamTextureMatrix = WebKit::WebTransformationMatrix( + 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]); + setNeedsRedraw(); +} + +void CCVideoLayerImpl::didLoseContext() +{ + freePlaneData(layerTreeHostImpl()->resourceProvider()); +} + +void CCVideoLayerImpl::setNeedsRedraw() +{ + layerTreeHostImpl()->setNeedsRedraw(); +} + +void CCVideoLayerImpl::dumpLayerProperties(std::string* str, int indent) const +{ + str->append(indentString(indent)); + str->append("video layer\n"); + CCLayerImpl::dumpLayerProperties(str, indent); +} + +const char* CCVideoLayerImpl::layerTypeAsString() const +{ + return "VideoLayer"; +} + +} + +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/cc/video_layer_impl.h b/cc/video_layer_impl.h index 638cbb2..b254e8c 100644 --- a/cc/video_layer_impl.h +++ b/cc/video_layer_impl.h @@ -1,3 +1,89 @@ // Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CCVideoLayerImpl_h +#define CCVideoLayerImpl_h + +#include "CCLayerImpl.h" +#include "GraphicsContext3D.h" +#include "IntSize.h" +#include +#include + +namespace WebKit { +class WebVideoFrame; +} + +namespace cc { + +class CCLayerTreeHostImpl; +class CCVideoLayerImpl; + +class CCVideoLayerImpl : public CCLayerImpl + , public WebKit::WebVideoFrameProvider::Client { +public: + static scoped_ptr create(int id, WebKit::WebVideoFrameProvider* provider) + { + return make_scoped_ptr(new CCVideoLayerImpl(id, provider)); + } + virtual ~CCVideoLayerImpl(); + + virtual void willDraw(CCResourceProvider*) OVERRIDE; + virtual void appendQuads(CCQuadSink&, CCAppendQuadsData&) OVERRIDE; + virtual void didDraw(CCResourceProvider*) OVERRIDE; + + virtual void dumpLayerProperties(std::string*, int indent) const OVERRIDE; + + Mutex& providerMutex() { return m_providerMutex; } + + // WebKit::WebVideoFrameProvider::Client implementation. + virtual void stopUsingProvider(); // Callable on any thread. + virtual void didReceiveFrame(); // Callable on impl thread. + virtual void didUpdateMatrix(const float*); // Callable on impl thread. + + virtual void didLoseContext() OVERRIDE; + + void setNeedsRedraw(); + + struct FramePlane { + CCResourceProvider::ResourceId resourceId; + IntSize size; + GC3Denum format; + IntSize visibleSize; + + FramePlane() : resourceId(0) { } + + bool allocateData(CCResourceProvider*); + void freeData(CCResourceProvider*); + }; + +private: + CCVideoLayerImpl(int, WebKit::WebVideoFrameProvider*); + + static IntSize computeVisibleSize(const WebKit::WebVideoFrame&, unsigned plane); + virtual const char* layerTypeAsString() const OVERRIDE; + + void willDrawInternal(CCResourceProvider*); + bool allocatePlaneData(CCResourceProvider*); + bool copyPlaneData(CCResourceProvider*); + void freePlaneData(CCResourceProvider*); + void freeUnusedPlaneData(CCResourceProvider*); + + // Guards the destruction of m_provider and the frame that it provides + Mutex m_providerMutex; + WebKit::WebVideoFrameProvider* m_provider; + + WebKit::WebTransformationMatrix m_streamTextureMatrix; + + WebKit::WebVideoFrame* m_frame; + GC3Denum m_format; + CCResourceProvider::ResourceId m_externalTextureResource; + + // Each index in this array corresponds to a plane in WebKit::WebVideoFrame. + FramePlane m_framePlanes[WebKit::WebVideoFrame::maxPlanes]; +}; + +} + +#endif // CCVideoLayerImpl_h diff --git a/cc/yuv_video_draw_quad.cc b/cc/yuv_video_draw_quad.cc new file mode 100644 index 0000000..41d5490 --- /dev/null +++ b/cc/yuv_video_draw_quad.cc @@ -0,0 +1,30 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#include "CCYUVVideoDrawQuad.h" + +namespace cc { + +scoped_ptr CCYUVVideoDrawQuad::create(const CCSharedQuadState* sharedQuadState, const IntRect& quadRect, const CCVideoLayerImpl::FramePlane& yPlane, const CCVideoLayerImpl::FramePlane& uPlane, const CCVideoLayerImpl::FramePlane& vPlane) +{ + return make_scoped_ptr(new CCYUVVideoDrawQuad(sharedQuadState, quadRect, yPlane, uPlane, vPlane)); +} + +CCYUVVideoDrawQuad::CCYUVVideoDrawQuad(const CCSharedQuadState* sharedQuadState, const IntRect& quadRect, const CCVideoLayerImpl::FramePlane& yPlane, const CCVideoLayerImpl::FramePlane& uPlane, const CCVideoLayerImpl::FramePlane& vPlane) + : CCDrawQuad(sharedQuadState, CCDrawQuad::YUVVideoContent, quadRect) + , m_yPlane(yPlane) + , m_uPlane(uPlane) + , m_vPlane(vPlane) +{ +} + +const CCYUVVideoDrawQuad* CCYUVVideoDrawQuad::materialCast(const CCDrawQuad* quad) +{ + ASSERT(quad->material() == CCDrawQuad::YUVVideoContent); + return static_cast(quad); +} + +} // namespace cc diff --git a/cc/yuv_video_draw_quad.h b/cc/yuv_video_draw_quad.h index 638cbb2..5d574b7b 100644 --- a/cc/yuv_video_draw_quad.h +++ b/cc/yuv_video_draw_quad.h @@ -1,3 +1,36 @@ // Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +#ifndef CCYUVVideoDrawQuad_h +#define CCYUVVideoDrawQuad_h + +#include "base/basictypes.h" +#include "base/memory/scoped_ptr.h" +#include "CCDrawQuad.h" +#include "CCVideoLayerImpl.h" + +namespace cc { + +class CCYUVVideoDrawQuad : public CCDrawQuad { +public: + static scoped_ptr create(const CCSharedQuadState*, const IntRect&, const CCVideoLayerImpl::FramePlane& yPlane, const CCVideoLayerImpl::FramePlane& uPlane, const CCVideoLayerImpl::FramePlane& vPlane); + + const CCVideoLayerImpl::FramePlane& yPlane() const { return m_yPlane; } + const CCVideoLayerImpl::FramePlane& uPlane() const { return m_uPlane; } + const CCVideoLayerImpl::FramePlane& vPlane() const { return m_vPlane; } + + static const CCYUVVideoDrawQuad* materialCast(const CCDrawQuad*); +private: + CCYUVVideoDrawQuad(const CCSharedQuadState*, const IntRect&, const CCVideoLayerImpl::FramePlane& yPlane, const CCVideoLayerImpl::FramePlane& uPlane, const CCVideoLayerImpl::FramePlane& vPlane); + + CCVideoLayerImpl::FramePlane m_yPlane; + CCVideoLayerImpl::FramePlane m_uPlane; + CCVideoLayerImpl::FramePlane m_vPlane; + + DISALLOW_COPY_AND_ASSIGN(CCYUVVideoDrawQuad); +}; + +} + +#endif -- cgit v1.1