| // Copyright 2017 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_EGL_OFFSCREEN_TARGET_MANAGER_H_ |
| #define COBALT_RENDERER_RASTERIZER_EGL_OFFSCREEN_TARGET_MANAGER_H_ |
| |
| #include "base/callback.h" |
| #include "base/memory/scoped_ptr.h" |
| #include "base/memory/scoped_vector.h" |
| #include "cobalt/math/rect_f.h" |
| #include "cobalt/math/size.h" |
| #include "cobalt/render_tree/node.h" |
| #include "cobalt/renderer/backend/egl/framebuffer_render_target.h" |
| #include "cobalt/renderer/backend/egl/graphics_context.h" |
| #include "third_party/skia/include/core/SkCanvas.h" |
| #include "third_party/skia/include/core/SkSurface.h" |
| |
| namespace cobalt { |
| namespace renderer { |
| namespace rasterizer { |
| namespace egl { |
| |
| // Manage allocating and caching offscreen render targets for render_tree::Node |
| // rendering. This uses atlases instead of individual render targets to |
| // minimize the cost of switching render targets. |
| class OffscreenTargetManager { |
| public: |
| typedef base::Callback<sk_sp<SkSurface>(const backend::RenderTarget*)> |
| CreateFallbackSurfaceFunction; |
| |
| struct TargetInfo { |
| TargetInfo() |
| : framebuffer(NULL), |
| skia_canvas(NULL) {} |
| backend::FramebufferRenderTargetEGL* framebuffer; |
| SkCanvas* skia_canvas; |
| math::RectF region; |
| }; |
| |
| // Offscreen targets are cached with additional ErrorData. When searching for |
| // a match, the caller specifies an error function which is used to verify |
| // that a particular cache entry is suitable for use. A cache entry is |
| // suitable if CacheErrorFunction(ErrorData) < |cache_error_threshold_|. If |
| // multiple entries meet this criteria, then the entry with the lowest error |
| // is chosen. |
| typedef math::RectF ErrorData; |
| typedef base::Callback<float(const ErrorData&)> CacheErrorFunction; |
| typedef float ErrorData1D; |
| typedef base::Callback<float(const ErrorData1D&)> CacheErrorFunction1D; |
| |
| OffscreenTargetManager(backend::GraphicsContextEGL* graphics_context, |
| const CreateFallbackSurfaceFunction& create_fallback_surface, |
| size_t memory_limit); |
| ~OffscreenTargetManager(); |
| |
| // Update must be called once per frame, before any allocation requests are |
| // made for that frame. |
| void Update(const math::Size& frame_size); |
| |
| // Flush all render targets that have been used thus far. |
| void Flush(); |
| |
| // Specify the acceptable limit for the return value of the cache error |
| // function. A cached target can be a match only if the error value is less |
| // than the specified threshold. The default threshold is 1. |
| void SetCacheErrorThreshold(float threshold); |
| |
| // Return whether a cached version of the requested render target is |
| // available. If a cache does exist, then the output parameters are set, |
| // otherwise, they are untouched. |
| // The returned values are only valid until the next call to Update(). |
| bool GetCachedTarget(const render_tree::Node* node, |
| const CacheErrorFunction& error_function, TargetInfo* out_target_info); |
| bool GetCachedTarget(const render_tree::Node* node, |
| const CacheErrorFunction1D& error_function, TargetInfo* out_target_info); |
| |
| // Allocate a cached offscreen target of the specified size. |
| // The returned values are only valid until the next call to Update(). |
| void AllocateCachedTarget(const render_tree::Node* node, |
| const math::SizeF& size, const ErrorData& error_data, |
| TargetInfo* out_target_info); |
| void AllocateCachedTarget(const render_tree::Node* node, |
| float size, const ErrorData1D& error_data, TargetInfo* out_target_info); |
| |
| // Allocate an uncached render target. The contents of the target cannot be |
| // reused in subsequent frames. If there was an error allocating the |
| // render target, out_target_info->framebuffer will be set to nullptr. |
| void AllocateUncachedTarget(const math::SizeF& size, |
| TargetInfo* out_target_info); |
| |
| private: |
| // Use an atlas for offscreen targets. |
| struct OffscreenAtlas; |
| |
| void InitializeTargets(const math::Size& frame_size); |
| scoped_ptr<OffscreenAtlas> CreateOffscreenAtlas(const math::Size& size, |
| bool create_canvas); |
| void SelectAtlasCache(ScopedVector<OffscreenAtlas>* atlases, |
| scoped_ptr<OffscreenAtlas>* cache); |
| |
| backend::GraphicsContextEGL* graphics_context_; |
| CreateFallbackSurfaceFunction create_fallback_surface_; |
| |
| ScopedVector<OffscreenAtlas> offscreen_atlases_; |
| scoped_ptr<OffscreenAtlas> offscreen_cache_; |
| |
| ScopedVector<OffscreenAtlas> offscreen_atlases_1d_; |
| scoped_ptr<OffscreenAtlas> offscreen_cache_1d_; |
| |
| ScopedVector<OffscreenAtlas> uncached_targets_; |
| |
| // Align offscreen targets to a particular size to more efficiently use the |
| // offscreen target atlas. Use a power of 2 for the alignment so that a bit |
| // mask can be used for the alignment calculation. |
| math::Size offscreen_target_size_mask_; |
| |
| // Maximum number of bytes that can be used for offscreen atlases. |
| size_t memory_limit_; |
| |
| // A cached target can be a match only if the cache error function returns |
| // a value less than the cache error threshold. |
| float cache_error_threshold_; |
| }; |
| |
| } // namespace egl |
| } // namespace rasterizer |
| } // namespace renderer |
| } // namespace cobalt |
| |
| #endif // COBALT_RENDERER_RASTERIZER_EGL_OFFSCREEN_TARGET_MANAGER_H_ |