| // 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_BLITTER_CACHED_SOFTWARE_RASTERIZER_H_ |
| #define COBALT_RENDERER_RASTERIZER_BLITTER_CACHED_SOFTWARE_RASTERIZER_H_ |
| |
| #include "base/containers/linked_hash_map.h" |
| #include "base/hash_tables.h" |
| #include "base/memory/ref_counted.h" |
| #include "cobalt/base/c_val.h" |
| #include "cobalt/render_tree/node.h" |
| #include "cobalt/renderer/rasterizer/blitter/render_state.h" |
| #include "cobalt/renderer/rasterizer/common/offscreen_render_coordinate_mapping.h" |
| #include "cobalt/renderer/rasterizer/skia/software_rasterizer.h" |
| #include "starboard/blitter.h" |
| |
| #if SB_HAS(BLITTER) |
| |
| namespace cobalt { |
| namespace renderer { |
| namespace rasterizer { |
| namespace blitter { |
| |
| // This class is responsible for creating SbBlitterSurfaces and software |
| // rasterizing render tree nodes to them to be used by clients. The class |
| // manages a cache of software surfaces in order to avoid duplicate work. Its |
| // main public interface is for clients to construct |
| // CachedSoftwareRasterizer::SurfaceReference objects from which they can |
| // extract the software-rasterized surface. Internally, software rasterization |
| // is handled via a skia::SoftwareRasterizer object. |
| class CachedSoftwareRasterizer { |
| public: |
| struct Surface { |
| // The actual surface containing rendered data. |
| SbBlitterSurface surface; |
| |
| // True if this surface was referenced at least once since the last time |
| // OnStartNewFrame() was called. |
| bool referenced; |
| |
| #if defined(ENABLE_DEBUG_CONSOLE) |
| // True if OnStartNewFrame() has not been called since this surface was |
| // created. |
| bool created; |
| #endif // defined(ENABLE_DEBUG_CONSOLE) |
| |
| // Transform information detailing how the surface should be output to |
| // the display such that sub-pixel alignments are respected. |
| common::OffscreenRenderCoordinateMapping coord_mapping; |
| |
| // A duplicate of the key, though as a smart pointer, to keep a reference |
| // to the node alive. |
| scoped_refptr<render_tree::Node> node; |
| |
| // Is this surface cached or not. |
| bool cached; |
| |
| // The scale used for rasterization when the surface was cached. |
| math::Vector2dF scale; |
| |
| size_t GetEstimatedMemoryUsage() const; |
| }; |
| |
| CachedSoftwareRasterizer(SbBlitterDevice device, SbBlitterContext context, |
| int cache_capacity); |
| ~CachedSoftwareRasterizer(); |
| |
| // Should be called once per frame. This method will remove from the cache |
| // anything that hasn't been referenced in the last frame. |
| void OnStartNewFrame(); |
| |
| // A SurfaceReference is the mechanism through which clients can request |
| // renders from the CachedSoftwareRasterizer. The main reason that we don't |
| // make GetSurface() the direct public interface is so that we can decide |
| // to rasterize something without caching it, in which case it should be |
| // cleaned up when the reference to it expires. |
| class SurfaceReference { |
| public: |
| // The |transform| parameter should be the transform that the node will |
| // ultimately have applied to it, and is used for ensuring that the rendered |
| // result is sub-pixel aligned properly. |
| SurfaceReference(CachedSoftwareRasterizer* rasterizer, |
| render_tree::Node* node, const Transform& transform) |
| : surface_(rasterizer->GetSurface(node, transform)) {} |
| ~SurfaceReference() { |
| // If the surface returned to us was not actually cached, then destroy |
| // it here when the surface reference is destroyed. |
| if (!surface_.cached && SbBlitterIsSurfaceValid(surface_.surface)) { |
| SbBlitterDestroySurface(surface_.surface); |
| } |
| } |
| const Surface& surface() const { return surface_; } |
| |
| private: |
| Surface surface_; |
| |
| DISALLOW_COPY_AND_ASSIGN(SurfaceReference); |
| }; |
| |
| Surface GetSurface(render_tree::Node* node, const Transform& transform); |
| |
| render_tree::ResourceProvider* GetResourceProvider() { |
| return software_rasterizer_.GetResourceProvider(); |
| } |
| |
| private: |
| typedef base::linked_hash_map<render_tree::Node*, Surface> CacheMap; |
| |
| // Release surfaces until we have |space_needed| free bytes in the cache. |
| // This function will never release surfaces that were referenced this frame. |
| // It is an error to call this function if it is impossible to purge |
| // unreferenced surfaces until the desired amount of free space is available. |
| void PurgeUntilSpaceAvailable(int space_needed); |
| |
| // The cache, mapping input render_tree::Node references to cached surfaces. |
| CacheMap surface_map_; |
| |
| const int cache_capacity_; |
| |
| // The Blitter device/context that all image allocation/blitting operations |
| // will occur within. |
| SbBlitterDevice device_; |
| SbBlitterContext context_; |
| |
| // The internal rasterizer used to actually render nodes. |
| skia::SoftwareRasterizer software_rasterizer_; |
| |
| // The amount of memory currently consumed by the surfaces populating the |
| // cache. |
| base::CVal<base::cval::SizeInBytes> cache_memory_usage_; |
| |
| // Cache memory used this frame only. |
| base::CVal<base::cval::SizeInBytes> cache_frame_usage_; |
| }; |
| |
| } // namespace blitter |
| } // namespace rasterizer |
| } // namespace renderer |
| } // namespace cobalt |
| |
| #endif // #if SB_HAS(BLITTER) |
| |
| #endif // COBALT_RENDERER_RASTERIZER_BLITTER_CACHED_SOFTWARE_RASTERIZER_H_ |