Changeset View
Changeset View
Standalone View
Standalone View
source/blender/draw/engines/image/image_buffer_cache.hh
- This file was copied to source/blender/draw/engines/image/image_buffer_cache.cc.
| /* SPDX-License-Identifier: GPL-2.0-or-later | /* SPDX-License-Identifier: GPL-2.0-or-later | ||||
| * Copyright 2022 Blender Foundation. */ | * Copyright 2022 Blender Foundation. */ | ||||
| /** \file | /** \file | ||||
| * \ingroup draw_engine | * \ingroup draw_engine | ||||
| */ | */ | ||||
| #pragma once | #pragma once | ||||
| #include "BLI_vector.hh" | |||||
| #include "IMB_imbuf.h" | #include "IMB_imbuf.h" | ||||
| #include "IMB_imbuf_types.h" | #include "IMB_imbuf_types.h" | ||||
| struct FloatImageBuffer { | /** | ||||
| ImBuf *source_buffer = nullptr; | * Returns a float buffer of the given image buffer. | ||||
| ImBuf *float_buffer = nullptr; | * This could be the given image buffer when it already has a float buffer. | ||||
| bool is_used = true; | * or a copy of the given image buffer where only the float buffer is available. | ||||
| */ | |||||
| FloatImageBuffer(ImBuf *source_buffer, ImBuf *float_buffer) | ImBuf *IMAGE_buffer_cache_float_ensure(ImBuf *image_buffer); | ||||
| : source_buffer(source_buffer), float_buffer(float_buffer) | |||||
| { | /** | ||||
| } | * Mark an image and its cached float buffer to be still in use. | ||||
| */ | |||||
| FloatImageBuffer(FloatImageBuffer &&other) noexcept | void IMAGE_buffer_cache_mark_used(ImBuf *image_buffer); | ||||
| { | |||||
| source_buffer = other.source_buffer; | /** | ||||
| float_buffer = other.float_buffer; | * Free cached float buffers that aren't used anymore. | ||||
| is_used = other.is_used; | */ | ||||
| other.source_buffer = nullptr; | void IMAGE_buffer_cache_free_unused(); | ||||
| other.float_buffer = nullptr; | |||||
| } | /** Free all buffers (when exiting blender). */ | ||||
| void IMAGE_buffer_cache_free(); | |||||
| virtual ~FloatImageBuffer() | |||||
| { | |||||
| IMB_freeImBuf(float_buffer); | |||||
| float_buffer = nullptr; | |||||
| source_buffer = nullptr; | |||||
| } | |||||
| FloatImageBuffer &operator=(FloatImageBuffer &&other) noexcept | |||||
| { | |||||
| this->source_buffer = other.source_buffer; | |||||
| this->float_buffer = other.float_buffer; | |||||
| is_used = other.is_used; | |||||
| other.source_buffer = nullptr; | |||||
| other.float_buffer = nullptr; | |||||
| return *this; | |||||
| } | |||||
| }; | |||||
| struct FloatBufferCache { | |||||
| private: | |||||
| blender::Vector<FloatImageBuffer> cache_; | |||||
| public: | |||||
| ImBuf *ensure_float_buffer(ImBuf *image_buffer) | |||||
| { | |||||
| /* Check if we can use the float buffer of the given image_buffer. */ | |||||
| if (image_buffer->rect_float != nullptr) { | |||||
| return image_buffer; | |||||
| } | |||||
| /* Do we have a cached float buffer. */ | |||||
| for (FloatImageBuffer &item : cache_) { | |||||
| if (item.source_buffer == image_buffer) { | |||||
| item.is_used = true; | |||||
| return item.float_buffer; | |||||
| } | |||||
| } | |||||
| /* Generate a new float buffer. */ | |||||
| IMB_float_from_rect(image_buffer); | |||||
| ImBuf *new_imbuf = IMB_allocImBuf(image_buffer->x, image_buffer->y, image_buffer->planes, 0); | |||||
| new_imbuf->rect_float = image_buffer->rect_float; | |||||
| new_imbuf->flags |= IB_rectfloat; | |||||
| new_imbuf->mall |= IB_rectfloat; | |||||
| image_buffer->rect_float = nullptr; | |||||
| image_buffer->flags &= ~IB_rectfloat; | |||||
| image_buffer->mall &= ~IB_rectfloat; | |||||
| cache_.append(FloatImageBuffer(image_buffer, new_imbuf)); | |||||
| return new_imbuf; | |||||
| } | |||||
| void reset_usage_flags() | |||||
| { | |||||
| for (FloatImageBuffer &buffer : cache_) { | |||||
| buffer.is_used = false; | |||||
| } | |||||
| } | |||||
| void mark_used(const ImBuf *image_buffer) | |||||
| { | |||||
| for (FloatImageBuffer &item : cache_) { | |||||
| if (item.source_buffer == image_buffer) { | |||||
| item.is_used = true; | |||||
| return; | |||||
| } | |||||
| } | |||||
| } | |||||
| void remove_unused_buffers() | |||||
| { | |||||
| for (int64_t i = cache_.size() - 1; i >= 0; i--) { | |||||
| if (!cache_[i].is_used) { | |||||
| cache_.remove_and_reorder(i); | |||||
| } | |||||
| } | |||||
| } | |||||
| void clear() | |||||
| { | |||||
| cache_.clear(); | |||||
| } | |||||
| }; | |||||