| // Copyright 2016 Google Inc. All Rights Reserved. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| #ifndef COBALT_RENDERER_RASTERIZER_SKIA_SURFACE_CACHE_DELEGATE_H_ |
| #define COBALT_RENDERER_RASTERIZER_SKIA_SURFACE_CACHE_DELEGATE_H_ |
| |
| #include <string> |
| |
| #include "base/callback.h" |
| #include "base/optional.h" |
| #if defined(ENABLE_DEBUG_CONSOLE) |
| #include "cobalt/base/console_commands.h" |
| #endif |
| #include "cobalt/renderer/rasterizer/common/offscreen_render_coordinate_mapping.h" |
| #include "cobalt/renderer/rasterizer/common/surface_cache.h" |
| #include "cobalt/renderer/rasterizer/skia/render_tree_node_visitor_draw_state.h" |
| #include "third_party/skia/include/core/SkSurface.h" |
| |
| namespace cobalt { |
| namespace renderer { |
| namespace rasterizer { |
| namespace skia { |
| |
| // Implements skia-specific cache recording and playback surface management |
| // in order to provide skia-support for the render tree surface caching system. |
| class SurfaceCacheDelegate : public common::SurfaceCache::Delegate { |
| private: |
| class CachedSurface : public common::SurfaceCache::CachedSurface { |
| public: |
| CachedSurface(SkSurface* surface, const math::Vector2dF& output_post_scale, |
| const math::Vector2dF& output_pre_translate, |
| const math::Rect& output_bounds) |
| : surface_(surface), |
| image_(surface_ ? surface_->newImageSnapshot() : NULL), |
| output_post_scale_(output_post_scale), |
| output_pre_translate_(output_pre_translate), |
| output_bounds_(output_bounds) {} |
| ~CachedSurface() OVERRIDE {} |
| |
| SkImage* image() const { return image_.get(); } |
| const math::Vector2dF& output_post_scale() const { |
| return output_post_scale_; |
| } |
| const math::Vector2dF& output_pre_translate() const { |
| return output_pre_translate_; |
| } |
| const math::Rect& output_bounds() const { return output_bounds_; } |
| |
| private: |
| // The actual skia surface representing the cached render tree. |
| SkAutoTUnref<SkSurface> surface_; |
| // For convenience, we save the image snapshot associated with |surface_| |
| // above. |
| SkAutoTUnref<SkImage> image_; |
| // When applying |surface_| to another render target, the current |
| // transformation should be post-multiplied by |output_post_scale_|, and |
| // pre-multiplied by |output_pre_translate_|. |
| math::Vector2dF output_post_scale_; |
| math::Vector2dF output_pre_translate_; |
| // The rectangle coordinates into which |surface_| should be rendered. |
| math::Rect output_bounds_; |
| }; |
| |
| public: |
| typedef base::Callback<SkSurface*(const math::Size&)> CreateSkSurfaceFunction; |
| |
| // Creating a ScopedContext object declares a render tree visitor context, |
| // and so there should be one ScopedContext per render tree visitor. Since |
| // it is typical to recursively create sub render tree visitors, this class |
| // is designed to be instantiated multiple times on the same |
| // SurfaceCacheDelegate object. |
| class ScopedContext { |
| public: |
| ScopedContext(SurfaceCacheDelegate* delegate, |
| RenderTreeNodeVisitorDrawState* draw_state) |
| : delegate_(delegate), old_draw_state_(delegate_->draw_state_) { |
| // Setup our new draw state (including render target) to the provided one. |
| delegate_->draw_state_ = draw_state; |
| |
| // A new canvas may mean a new total matrix, so inform our delegate to |
| // refresh its scale. |
| delegate_->UpdateCanvasScale(); |
| } |
| ~ScopedContext() { |
| // Restore the draw state to the old setting. |
| delegate_->draw_state_ = old_draw_state_; |
| |
| if (delegate_->draw_state_) { |
| delegate_->UpdateCanvasScale(); |
| } |
| } |
| |
| private: |
| SurfaceCacheDelegate* delegate_; |
| RenderTreeNodeVisitorDrawState* old_draw_state_; |
| }; |
| |
| SurfaceCacheDelegate( |
| const CreateSkSurfaceFunction& create_sk_surface_function, |
| const math::Size& max_surface_size); |
| |
| // Must be called every time our client changes the current scale on us, e.g. |
| // when visiting a MatrixTransformNode. |
| void UpdateCanvasScale(); |
| |
| void ApplySurface(common::SurfaceCache::CachedSurface* surface) OVERRIDE; |
| void StartRecording(const math::RectF& local_bounds) OVERRIDE; |
| common::SurfaceCache::CachedSurface* EndRecording() OVERRIDE; |
| void ReleaseSurface(common::SurfaceCache::CachedSurface* surface) OVERRIDE; |
| math::Size GetRenderSize(const math::SizeF& local_size) OVERRIDE; |
| math::Size MaximumSurfaceSize() OVERRIDE; |
| |
| private: |
| // Defines a set of data that is relevant only while recording. |
| struct RecordingData { |
| RecordingData(const RenderTreeNodeVisitorDrawState& original_draw_state, |
| const common::OffscreenRenderCoordinateMapping& coord_mapping, |
| SkSurface* surface) |
| : original_draw_state(original_draw_state), |
| coord_mapping(coord_mapping), |
| surface(surface) {} |
| |
| // The original draw state (including render target/canvas) that the |
| // recorded draw calls would have otherwise targeted if we were not |
| // recording. |
| RenderTreeNodeVisitorDrawState original_draw_state; |
| |
| // Information about how to map the offscreen cached surface to the main |
| // render target. |
| common::OffscreenRenderCoordinateMapping coord_mapping; |
| |
| // The offscreen cached surface that we are recording to. |
| SkSurface* surface; |
| }; |
| |
| #if defined(ENABLE_DEBUG_CONSOLE) |
| void OnToggleCacheHighlights(const std::string& message); |
| #endif |
| |
| // A function that will return a fresh SkSurface object when we need to cache |
| // something new. |
| CreateSkSurfaceFunction create_sk_surface_function_; |
| |
| // The maximum size of an SkSurface. |
| math::Size max_surface_size_; |
| |
| // The current draw state (including the SkCanvas) that is being targeted, |
| // whether its the main onscreen surface or a cached surface. |
| RenderTreeNodeVisitorDrawState* draw_state_; |
| |
| // If we are currently recording, this will contain all of the data relevant |
| // to that recording. |
| base::optional<RecordingData> recording_data_; |
| |
| // The current scale of draw_state_->render_target->getTotalMatrix(). This |
| // lets us quickly check if the scale of a render node changes from the last |
| // time we observed it, which may happen if an animation is targeting a |
| // MatrixTransformNode render tree node. |
| math::Vector2dF scale_; |
| |
| #if defined(ENABLE_DEBUG_CONSOLE) |
| // Debug command to toggle cache highlights to help visualize which nodes |
| // are being cached. |
| bool toggle_cache_highlights_; |
| base::ConsoleCommandManager::CommandHandler |
| toggle_cache_highlights_command_handler_; |
| #endif |
| }; |
| |
| } // namespace skia |
| } // namespace rasterizer |
| } // namespace renderer |
| } // namespace cobalt |
| |
| #endif // COBALT_RENDERER_RASTERIZER_SKIA_SURFACE_CACHE_DELEGATE_H_ |