| /* |
| * 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_COMMON_SCRATCH_SURFACE_CACHE_H_ |
| #define COBALT_RENDERER_RASTERIZER_COMMON_SCRATCH_SURFACE_CACHE_H_ |
| |
| #include <vector> |
| |
| #include "base/callback.h" |
| #include "base/logging.h" |
| #include "cobalt/math/size.h" |
| |
| namespace cobalt { |
| namespace renderer { |
| namespace rasterizer { |
| namespace common { |
| |
| // The ScratchSurfaceCache manages a set of platform-specific surface objects |
| // that can be used for offscreen rendering (e.g. by a RenderTreeNodeVisitor). |
| // In order to acquire surfaces from ScratchSurfaceCache, one should construct |
| // a CachedScratchSurface object, from which they can get a pointer to the |
| // Surface object. |
| // It is unique because it caters to RenderTreeNodeVisitor's scratch |
| // surface allocation pattern. In particular, we don't mind handing out very |
| // large scratch surfaces when very small surfaces are requested, because |
| // typically only one surface is ever needed at a time. When multiple surfaces |
| // are necessary, the subsequent ones tend to be smaller than the previous |
| // (because rendering is now happening within the previous ones), and so handing |
| // out textures in large to small order makes sense. |
| class ScratchSurfaceCache { |
| public: |
| class Surface { |
| public: |
| virtual ~Surface() {} |
| virtual math::Size GetSize() const = 0; |
| }; |
| class Delegate { |
| public: |
| virtual Surface* CreateSurface(const math::Size& size) = 0; |
| virtual void DestroySurface(Surface* surface) = 0; |
| virtual void PrepareForUse(Surface* surface, const math::Size& area) = 0; |
| }; |
| |
| ScratchSurfaceCache(Delegate* delegate, int cache_capacity_in_bytes); |
| ~ScratchSurfaceCache(); |
| |
| private: |
| // Acquire (either via cache lookup or by creation if that fails) a scratch |
| // surface. |
| Surface* AcquireScratchSurface(const math::Size& size); |
| void ReleaseScratchSurface(Surface* surface); |
| |
| // Searches through |unused_surfaces_| for one the one that best matches the |
| // requested size, among all those cached surfaces that have at least the |
| // requested size. |
| Surface* FindBestCachedSurface(const math::Size& size); |
| |
| // Removes elements from the cache until we are below the cache limit. |
| void Purge(); |
| |
| // Allocate a new Surface and return it. |
| Surface* CreateScratchSurface(const math::Size& size); |
| |
| // Implementation-specific details about how to create/destroy surfaces. |
| Delegate* delegate_; |
| |
| // The maximum number of surface bytes that can be stored in the cache. |
| int cache_capacity_in_bytes_; |
| |
| // We keep track of all surfaces we've handed out using |surface_stack_|. |
| // This is mostly for debug checks to verify that surfaces returned to us |
| // actually did come from us, and that they are returned in the expected |
| // order. |
| std::vector<Surface*> surface_stack_; |
| |
| // |unused_surfaces_| is the heart of the cache, as it stores the surfaces |
| // that are unused but allocated and available to be handed out upon request. |
| // Most recently used surfaces are found at the end of this vector. |
| std::vector<Surface*> unused_surfaces_; |
| |
| // Tracks how much total memory we've allocated towards surfaces. |
| size_t surface_memory_; |
| |
| friend class CachedScratchSurface; |
| }; |
| |
| // The primary interface to ScratchSurfaceCache is through CachedScratchSurface |
| // objects. These effectively scope the acquisition of a cached surface, RAII |
| // style. |
| class CachedScratchSurface { |
| public: |
| CachedScratchSurface(ScratchSurfaceCache* cache, const math::Size& size) |
| : cache_(cache) { |
| surface_ = cache_->AcquireScratchSurface(size); |
| } |
| |
| ~CachedScratchSurface() { |
| if (surface_) { |
| cache_->ReleaseScratchSurface(surface_); |
| } |
| } |
| |
| // Returns a pointer to the platform-specific surface. The platform can then |
| // downcast to the expected surface type. |
| ScratchSurfaceCache::Surface* GetSurface() { return surface_; } |
| |
| private: |
| ScratchSurfaceCache* cache_; |
| ScratchSurfaceCache::Surface* surface_; |
| }; |
| |
| } // namespace common |
| } // namespace rasterizer |
| } // namespace renderer |
| } // namespace cobalt |
| |
| #endif // COBALT_RENDERER_RASTERIZER_COMMON_SCRATCH_SURFACE_CACHE_H_ |