New ImageResourceDisplay implementation that should decrease RAM usage
This commit is contained in:
parent
a69d9e3c6c
commit
fec602e46a
11 changed files with 246 additions and 98 deletions
|
|
@ -17,7 +17,7 @@ bool FileResourceDisplay::update_draw() const {
|
|||
void FileResourceDisplay::update(World& w) {
|
||||
}
|
||||
|
||||
bool FileResourceDisplay::load(ResourceManager& rMan, const std::string& fileName, const std::string& fileData) {
|
||||
bool FileResourceDisplay::load(ResourceManager& rMan, const std::string& fileName, const std::shared_ptr<std::string>& fileData) {
|
||||
this->fileName = fileName;
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
class FileResourceDisplay : public ResourceDisplay {
|
||||
public:
|
||||
virtual void update(World& w) override;
|
||||
virtual bool load(ResourceManager& rMan, const std::string& fileName, const std::string& fileData) override;
|
||||
virtual bool load(ResourceManager& rMan, const std::string& fileName, const std::shared_ptr<std::string>& fileData) override;
|
||||
virtual bool update_draw() const override;
|
||||
virtual void draw(SkCanvas* canvas, const DrawData& drawData, const SkRect& imRect) override;
|
||||
virtual Vector2f get_dimensions() const override;
|
||||
|
|
|
|||
|
|
@ -11,6 +11,8 @@
|
|||
#include <include/core/SkCanvas.h>
|
||||
#include "../MainProgram.hpp"
|
||||
#include <Helpers/Logger.hpp>
|
||||
#include <include/core/SkImageInfo.h>
|
||||
#include <include/core/SkSamplingOptions.h>
|
||||
|
||||
#ifdef USE_SKIA_BACKEND_GRAPHITE
|
||||
#include <include/gpu/graphite/Surface.h>
|
||||
|
|
@ -19,7 +21,7 @@
|
|||
#include <include/gpu/ganesh/SkSurfaceGanesh.h>
|
||||
#endif
|
||||
|
||||
std::array<const SkCodecs::Decoder, 7> decoders = {
|
||||
std::array<const SkCodecs::Decoder, 7> decoders2 = {
|
||||
SkBmpDecoder::Decoder(),
|
||||
SkGifDecoder::Decoder(),
|
||||
SkIcoDecoder::Decoder(),
|
||||
|
|
@ -30,60 +32,50 @@ std::array<const SkCodecs::Decoder, 7> decoders = {
|
|||
SkWebpDecoder::Decoder()
|
||||
};
|
||||
|
||||
void ImageResourceDisplay::load_thread() {
|
||||
for(int i = 0; i < totalFramesToLoad; i++) {
|
||||
if(shutdownLoadThread)
|
||||
break;
|
||||
SkCodec::Options imageOptions;
|
||||
imageOptions.fFrameIndex = i;
|
||||
SkCodec::FrameInfo frameInfo;
|
||||
float frameTime = -1.0f;
|
||||
if(codec->getFrameInfo(i, &frameInfo))
|
||||
frameTime = frameInfo.fDuration;
|
||||
auto decodeResult = codec->getImage(imageInfo, &imageOptions);
|
||||
if(std::get<1>(decodeResult) == SkCodec::Result::kSuccess)
|
||||
frames[i] = {std::get<0>(decodeResult), frameTime};
|
||||
else {
|
||||
Logger::get().log("WORLDFATAL", "Could not decode image, got error code " + std::to_string(std::get<1>(decodeResult)) + ". Image has dimensions " + std::to_string(imageInfo.width()) + " " + std::to_string(imageInfo.height()));
|
||||
break;
|
||||
}
|
||||
loadedFrames++;
|
||||
}
|
||||
imageRawData = nullptr;
|
||||
codec = nullptr;
|
||||
}
|
||||
std::unordered_map<std::shared_ptr<std::string>, sk_sp<SkImage>> ImageResourceDisplay::screenshotCache;
|
||||
std::atomic<int> ImageResourceDisplay::imageLoadThreadCount = 0;
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
int ImageResourceDisplay::IMAGE_LOAD_THREAD_COUNT_MAX = 1;
|
||||
#else
|
||||
int ImageResourceDisplay::IMAGE_LOAD_THREAD_COUNT_MAX = 4;
|
||||
#endif
|
||||
|
||||
bool ImageResourceDisplay::update_draw() const {
|
||||
return mustUpdateDraw;
|
||||
}
|
||||
|
||||
void ImageResourceDisplay::update(World& w) {
|
||||
for(auto& frame : frames) {
|
||||
std::erase_if(frame.mipmapLevels, [](const auto& mipmapPair) {
|
||||
static constexpr std::chrono::duration TIME_TO_REMOVE_MIPMAP_CACHE = std::chrono::seconds(40);
|
||||
return std::chrono::steady_clock::now() - mipmapPair.second.timeLastUsed > TIME_TO_REMOVE_MIPMAP_CACHE;
|
||||
});
|
||||
screenshotCache.clear();
|
||||
|
||||
for(size_t mipmapLevel = 0; mipmapLevel < mipmapLevelsStatus.size(); mipmapLevel++) {
|
||||
if(mipmapLevelsStatus[mipmapLevel] == MipmapLevelStatus::ALLOCATED_JUST_SET)
|
||||
mipmapLevelsStatus[mipmapLevel] = MipmapLevelStatus::ALLOCATED_WILL_REMOVE;
|
||||
else if(mipmapLevelsStatus[mipmapLevel] == MipmapLevelStatus::ALLOCATED_WILL_REMOVE) {
|
||||
mipmapLevelsStatus[mipmapLevel] = MipmapLevelStatus::UNALLOCATED;
|
||||
for(auto& frame : frames)
|
||||
frame.mipmapLevels[mipmapLevel] = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
mustUpdateDraw = false;
|
||||
if(!loadedFirstFrame && loadedFrames >= 1) {
|
||||
if(mustUpdateDrawLoadThread) {
|
||||
mustUpdateDraw = true;
|
||||
loadedFirstFrame = true;
|
||||
mustUpdateDrawLoadThread = false;
|
||||
}
|
||||
if(loadedFrames <= 1)
|
||||
else
|
||||
mustUpdateDraw = false;
|
||||
|
||||
if(frames.size() == 1)
|
||||
return;
|
||||
currentTime += w.main.deltaTime * 1000.0;
|
||||
|
||||
currentTime += w.main.deltaTime;
|
||||
for(;;) {
|
||||
if(currentTime >= frames[frameIndex].duration) {
|
||||
currentTime -= frames[frameIndex].duration;
|
||||
frameIndex++;
|
||||
if(frameIndex >= loadedFrames) {
|
||||
if(loadedFrames != totalFramesToLoad) // Dont loop the GIF if it's not completely loaded yet
|
||||
frameIndex--;
|
||||
else
|
||||
frameIndex = 0;
|
||||
}
|
||||
mustUpdateDraw = true;
|
||||
if(frameIndex >= static_cast<int>(frames.size()))
|
||||
frameIndex = 0;
|
||||
}
|
||||
else
|
||||
return;
|
||||
|
|
@ -92,64 +84,185 @@ void ImageResourceDisplay::update(World& w) {
|
|||
}
|
||||
}
|
||||
|
||||
bool ImageResourceDisplay::load(ResourceManager& rMan, const std::string& fileName, const std::string& fileData) {
|
||||
imageRawData = SkData::MakeWithoutCopy(fileData.c_str(), fileData.size());
|
||||
codec = SkCodec::MakeFromData(imageRawData, decoders);
|
||||
sk_sp<SkImage> ImageResourceDisplay::load_frame_with_codec(const std::unique_ptr<SkCodec>& codec, unsigned width, unsigned height, unsigned frameIndexToLoad) {
|
||||
SkCodec::Options imageOptions;
|
||||
imageOptions.fFrameIndex = frameIndexToLoad;
|
||||
auto decodeResult = codec->getImage(imageInfo, &imageOptions);
|
||||
if(std::get<1>(decodeResult) != SkCodec::Result::kSuccess)
|
||||
throw std::runtime_error("Could not decode image, got error code " + std::to_string(std::get<1>(decodeResult)) + ". Image decoded with dimensions " + std::to_string(imageInfo.width()) + " " + std::to_string(imageInfo.height()));
|
||||
sk_sp<SkImage> ogImage = std::get<0>(decodeResult);
|
||||
SkImageInfo scaledImageInfo = imageInfo.makeDimensions(SkISize(width, height));
|
||||
auto scaledImage = ogImage->makeScaled(scaledImageInfo, {SkFilterMode::kLinear, SkMipmapMode::kNone});
|
||||
if(!scaledImage)
|
||||
throw std::runtime_error("Could not scale image.");
|
||||
return scaledImage;
|
||||
}
|
||||
|
||||
void ImageResourceDisplay::camera_view_update(const CoordSpaceHelper& compCoords, const SCollision::AABB<WorldScalar>& compAABB, const DrawData& drawData, const SkRect& imRect) {
|
||||
if(!smallestMipmapLevelLoaded)
|
||||
attempt_load_mipmap_in_separate_thread(get_smallest_mipmap_level());
|
||||
else {
|
||||
if(SCollision::collide(compAABB, drawData.cam.viewingAreaGenerousCollider)) {
|
||||
Vector2f transformedImRectDimensions;
|
||||
transformedImRectDimensions.x() = drawData.cam.c.scalar_to_space(compCoords.scalar_from_space(imRect.width()));
|
||||
transformedImRectDimensions.y() = drawData.cam.c.scalar_to_space(compCoords.scalar_from_space(imRect.height()));
|
||||
int mipmapLevel = get_exact_mipmap_level_for_dimensions(transformedImRectDimensions.cast<int>());
|
||||
if(mipmapLevel != get_smallest_mipmap_level()) {
|
||||
if(mipmapLevelsStatus[mipmapLevel] == MipmapLevelStatus::UNALLOCATED) {
|
||||
attempt_load_mipmap_in_separate_thread(mipmapLevel);
|
||||
int nextBestMipmapLevel = get_best_allocated_mipmap_level(mipmapLevel);
|
||||
if(nextBestMipmapLevel != get_smallest_mipmap_level())
|
||||
mipmapLevelsStatus[nextBestMipmapLevel] = MipmapLevelStatus::ALLOCATED_JUST_SET;
|
||||
}
|
||||
else
|
||||
mipmapLevelsStatus[mipmapLevel] = MipmapLevelStatus::ALLOCATED_JUST_SET;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ImageResourceDisplay::load(ResourceManager& rMan, const std::string& fileName, const std::shared_ptr<std::string>& fileData) {
|
||||
this->fileData = fileData;
|
||||
auto codec = SkCodec::MakeFromData(SkData::MakeWithoutCopy(this->fileData->c_str(), this->fileData->size()), decoders2);
|
||||
mustUpdateDraw = true;
|
||||
mustUpdateDrawLoadThread = true;
|
||||
if(codec) {
|
||||
auto origin = codec->getOrigin();
|
||||
bool rotate = (origin == kLeftTop_SkEncodedOrigin || origin == kRightTop_SkEncodedOrigin || origin == kRightBottom_SkEncodedOrigin || origin == kLeftBottom_SkEncodedOrigin);
|
||||
totalFramesToLoad = codec->getFrameCount();
|
||||
imageInfo = codec->getInfo();
|
||||
frames.resize(totalFramesToLoad);
|
||||
loadedFrames = 0;
|
||||
|
||||
mipmapLevelsStatus = std::vector<std::atomic<MipmapLevelStatus>>(calculate_smallest_mipmap_level());
|
||||
for(auto& mipmapLevelStatus : mipmapLevelsStatus)
|
||||
mipmapLevelStatus = MipmapLevelStatus::UNALLOCATED;
|
||||
|
||||
frames.resize(codec->getFrameCount());
|
||||
for(size_t i = 0; i < frames.size(); i++) {
|
||||
auto& frame = frames[i];
|
||||
frame.mipmapLevels.resize(get_smallest_mipmap_level());
|
||||
SkCodec::FrameInfo frameInfo;
|
||||
if(codec->getFrameInfo(i, &frameInfo))
|
||||
frame.duration = static_cast<float>(frameInfo.fDuration) / 1000.0f; // get frametime in seconds
|
||||
else
|
||||
frame.duration = -1.0f;
|
||||
}
|
||||
|
||||
if(rotate) {
|
||||
Logger::get().log("INFO", "Image loaded is rotated, so must rotate dimensions");
|
||||
imageInfo = imageInfo.makeDimensions(SkISize(imageInfo.height(), imageInfo.width()));
|
||||
}
|
||||
try{
|
||||
loadThread = std::make_unique<std::thread>(&ImageResourceDisplay::load_thread, this);
|
||||
}
|
||||
catch(...) {
|
||||
Logger::get().log("INFO", "[ImageResourceDisplay::load] Failed to create load thread, loading on main thread");
|
||||
load_thread();
|
||||
}
|
||||
codec = nullptr;
|
||||
attempt_load_mipmap_in_separate_thread(get_smallest_mipmap_level());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ImageResourceDisplay::attempt_load_mipmap_in_separate_thread(int mipmapLevel) {
|
||||
if(imageLoadThreadCount >= IMAGE_LOAD_THREAD_COUNT_MAX)
|
||||
return;
|
||||
if(!loadThread) {
|
||||
shutdownLoadThread = false;
|
||||
imageLoadThreadCount++;
|
||||
loadThread = std::make_unique<std::thread>(&ImageResourceDisplay::load_thread_func, this, mipmapLevel);
|
||||
}
|
||||
else if(shutdownLoadThread) {
|
||||
loadThread->join();
|
||||
shutdownLoadThread = false;
|
||||
imageLoadThreadCount++;
|
||||
loadThread = std::make_unique<std::thread>(&ImageResourceDisplay::load_thread_func, this, mipmapLevel);
|
||||
}
|
||||
}
|
||||
|
||||
void ImageResourceDisplay::load_thread_func(int mipmapLevel) {
|
||||
auto codec = SkCodec::MakeFromData(SkData::MakeWithoutCopy(this->fileData->c_str(), this->fileData->size()), decoders2);
|
||||
Vector2i imDim = get_mipmap_level_image_dimensions(mipmapLevel);
|
||||
for(size_t i = 0; i < frames.size(); i++) {
|
||||
if(shutdownLoadThread)
|
||||
return;
|
||||
auto& frame = frames[i];
|
||||
auto& mipmapImage = (mipmapLevel == get_smallest_mipmap_level()) ? frame.smallestMipmapLevel : frame.mipmapLevels[mipmapLevel];
|
||||
mipmapImage = load_frame_with_codec(codec, imDim.x(), imDim.y(), i);
|
||||
}
|
||||
if(mipmapLevel == get_smallest_mipmap_level())
|
||||
smallestMipmapLevelLoaded = true;
|
||||
else
|
||||
mipmapLevelsStatus[mipmapLevel] = MipmapLevelStatus::ALLOCATED_JUST_SET;
|
||||
mustUpdateDrawLoadThread = true;
|
||||
imageLoadThreadCount--;
|
||||
shutdownLoadThread = true;
|
||||
}
|
||||
|
||||
void ImageResourceDisplay::draw(SkCanvas* canvas, const DrawData& drawData, const SkRect& imRect) {
|
||||
if(loadedFrames == 0)
|
||||
if(!smallestMipmapLevelLoaded)
|
||||
canvas->drawRect(imRect, SkPaint({0.5f, 0.5f, 0.5f, 0.5f}));
|
||||
else {
|
||||
SkRect imRectPixelSize = canvas->getLocalToDeviceAs3x3().mapRect(imRect);
|
||||
float imWidth = std::max(imRectPixelSize.width(), 32.0f);
|
||||
unsigned divisionLevel = imageInfo.width() / imWidth;
|
||||
int mipmapLevel = get_exact_mipmap_level_for_dimensions({imRectPixelSize.width(), imRectPixelSize.height()});
|
||||
auto& frame = frames[frameIndex];
|
||||
if(divisionLevel <= 1)
|
||||
canvas->drawImageRect(frame.data, imRect, {SkFilterMode::kLinear, SkMipmapMode::kNone});
|
||||
else {
|
||||
unsigned mipmapLevel = std::log2(divisionLevel);
|
||||
auto mipmapIt = frame.mipmapLevels.find(mipmapLevel);
|
||||
|
||||
if(mipmapIt == frame.mipmapLevels.end()) {
|
||||
unsigned divideResolutionBy = std::exp2(mipmapLevel);
|
||||
SkISize mipmapResolution(imageInfo.width() / divideResolutionBy, imageInfo.height() / divideResolutionBy);
|
||||
|
||||
SkImageInfo mipmapImgInfo = imageInfo.makeDimensions(mipmapResolution);
|
||||
sk_sp<SkImage> mipmapImage = frame.data->makeScaled(mipmapImgInfo, SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kNone));
|
||||
frame.mipmapLevels.emplace(mipmapLevel, MipmapLevelData{mipmapImage, std::chrono::steady_clock::now()});
|
||||
canvas->drawImageRect(mipmapImage, imRect, {SkFilterMode::kLinear, SkMipmapMode::kNone});
|
||||
int closestMipmapLevel = get_best_allocated_mipmap_level(mipmapLevel);
|
||||
if(drawData.main->takingScreenshot) {
|
||||
if(closestMipmapLevel == mipmapLevel) {
|
||||
if(closestMipmapLevel == get_smallest_mipmap_level())
|
||||
canvas->drawImageRect(frame.smallestMipmapLevel, imRect, {SkFilterMode::kLinear, SkMipmapMode::kNone});
|
||||
else
|
||||
canvas->drawImageRect(frame.mipmapLevels[closestMipmapLevel], imRect, {SkFilterMode::kLinear, SkMipmapMode::kNone});
|
||||
}
|
||||
else {
|
||||
mipmapIt->second.timeLastUsed = std::chrono::steady_clock::now();
|
||||
canvas->drawImageRect(mipmapIt->second.imageData, imRect, {SkFilterMode::kLinear, SkMipmapMode::kNone});
|
||||
if(screenshotCache.contains(fileData))
|
||||
canvas->drawImageRect(screenshotCache[fileData], imRect, {SkFilterMode::kLinear, SkMipmapMode::kNone});
|
||||
else {
|
||||
auto codec = SkCodec::MakeFromData(SkData::MakeWithoutCopy(this->fileData->c_str(), this->fileData->size()), decoders2);
|
||||
screenshotCache[fileData] = load_frame_with_codec(codec, imageInfo.width(), imageInfo.height(), frameIndex);
|
||||
canvas->drawImageRect(screenshotCache[fileData], imRect, {SkFilterMode::kLinear, SkMipmapMode::kNone});
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(closestMipmapLevel == get_smallest_mipmap_level())
|
||||
canvas->drawImageRect(frame.smallestMipmapLevel, imRect, {SkFilterMode::kLinear, SkMipmapMode::kNone});
|
||||
else
|
||||
canvas->drawImageRect(frame.mipmapLevels[closestMipmapLevel], imRect, {SkFilterMode::kLinear, SkMipmapMode::kNone});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int ImageResourceDisplay::get_exact_mipmap_level_for_dimensions(const Vector2i& dim) {
|
||||
int minimumImageDim = std::min(imageInfo.width(), imageInfo.height());
|
||||
int minimumRectDim = std::min(dim.x(), dim.y());
|
||||
int imDim = std::max<int>(minimumRectDim, SMALLEST_MIPMAP_RESOLUTION);
|
||||
int divisionLevel = minimumImageDim / imDim;
|
||||
return (divisionLevel <= 1) ? 0 : std::log2(divisionLevel);
|
||||
}
|
||||
|
||||
int ImageResourceDisplay::get_best_allocated_mipmap_level(int mipmapLevel) {
|
||||
if(mipmapLevel == get_smallest_mipmap_level())
|
||||
return mipmapLevel;
|
||||
for(int i = mipmapLevel; i >= 0; i--) {
|
||||
if(mipmapLevelsStatus[i] != MipmapLevelStatus::UNALLOCATED)
|
||||
return i;
|
||||
}
|
||||
for(int i = mipmapLevel; i < get_smallest_mipmap_level(); i++) {
|
||||
if(mipmapLevelsStatus[i] != MipmapLevelStatus::UNALLOCATED)
|
||||
return i;
|
||||
}
|
||||
return get_smallest_mipmap_level();
|
||||
}
|
||||
|
||||
int ImageResourceDisplay::calculate_smallest_mipmap_level() {
|
||||
int minimumImageDim = std::min(imageInfo.width(), imageInfo.height());
|
||||
int divisionLevel = minimumImageDim / SMALLEST_MIPMAP_RESOLUTION;
|
||||
return (divisionLevel <= 1) ? 0 : std::log2(divisionLevel);
|
||||
}
|
||||
|
||||
int ImageResourceDisplay::get_smallest_mipmap_level() const {
|
||||
return mipmapLevelsStatus.size();
|
||||
}
|
||||
|
||||
Vector2i ImageResourceDisplay::get_mipmap_level_image_dimensions(int mipmapLevel) const {
|
||||
unsigned divideResolutionBy = std::exp2(mipmapLevel);
|
||||
return {imageInfo.width() / divideResolutionBy, imageInfo.height() / divideResolutionBy};
|
||||
}
|
||||
|
||||
Vector2f ImageResourceDisplay::get_dimensions() const {
|
||||
return {imageInfo.width(), imageInfo.height()};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,42 +4,65 @@
|
|||
#include <vector>
|
||||
#include <thread>
|
||||
#include <include/codec/SkCodec.h>
|
||||
#include <queue>
|
||||
|
||||
class ImageResourceDisplay : public ResourceDisplay {
|
||||
public:
|
||||
virtual void update(World& w) override;
|
||||
virtual bool load(ResourceManager& rMan, const std::string& fileName, const std::string& fileData) override;
|
||||
virtual bool load(ResourceManager& rMan, const std::string& fileName, const std::shared_ptr<std::string>& fileData) override;
|
||||
virtual bool update_draw() const override;
|
||||
virtual void draw(SkCanvas* canvas, const DrawData& drawData, const SkRect& imRect) override;
|
||||
virtual Vector2f get_dimensions() const override;
|
||||
virtual float get_dimension_scale() const override;
|
||||
virtual Type get_type() const override;
|
||||
virtual void camera_view_update(const CoordSpaceHelper& compCoords, const SCollision::AABB<WorldScalar>& compAABB, const DrawData& drawData, const SkRect& imRect) override;
|
||||
virtual ~ImageResourceDisplay() override;
|
||||
|
||||
static int IMAGE_LOAD_THREAD_COUNT_MAX;
|
||||
|
||||
private:
|
||||
struct MipmapLevelData {
|
||||
sk_sp<SkImage> imageData;
|
||||
std::chrono::steady_clock::time_point timeLastUsed;
|
||||
};
|
||||
static constexpr int SMALLEST_MIPMAP_RESOLUTION = 128;
|
||||
|
||||
struct FrameData {
|
||||
sk_sp<SkImage> data;
|
||||
float duration;
|
||||
std::unordered_map<unsigned, MipmapLevelData> mipmapLevels;
|
||||
// Mipmap level calculation is done using the smaller dimension, not the bigger one, to ensure that the dimensions are never invalid
|
||||
std::vector<sk_sp<SkImage>> mipmapLevels;
|
||||
sk_sp<SkImage> smallestMipmapLevel; // Smaller dimension of this should be around SMALLEST_MIPMAP_RESOLUTION pixels. Is always allocated and used when cachedMipmapLevel is unavailable or when the image is viewed from far away
|
||||
float duration = -1.0f;
|
||||
};
|
||||
|
||||
static std::unordered_map<std::shared_ptr<std::string>, sk_sp<SkImage>> screenshotCache;
|
||||
|
||||
static std::atomic<int> imageLoadThreadCount;
|
||||
|
||||
std::vector<FrameData> frames;
|
||||
|
||||
enum class MipmapLevelStatus {
|
||||
UNALLOCATED,
|
||||
ALLOCATED_JUST_SET,
|
||||
ALLOCATED_WILL_REMOVE
|
||||
};
|
||||
|
||||
std::vector<std::atomic<MipmapLevelStatus>> mipmapLevelsStatus;
|
||||
std::atomic<bool> smallestMipmapLevelLoaded = false;
|
||||
|
||||
std::shared_ptr<std::string> fileData;
|
||||
SkImageInfo imageInfo;
|
||||
|
||||
void load_thread();
|
||||
|
||||
int totalFramesToLoad;
|
||||
std::atomic<int> loadedFrames = 0;
|
||||
sk_sp<SkData> imageRawData;
|
||||
std::unique_ptr<SkCodec> codec;
|
||||
std::atomic<bool> shutdownLoadThread = false;
|
||||
std::unique_ptr<std::thread> loadThread;
|
||||
|
||||
float currentTime = 0.0f;
|
||||
int frameIndex = 0;
|
||||
bool mustUpdateDraw = false;
|
||||
bool loadedFirstFrame = false;
|
||||
bool mustUpdateDraw = false;
|
||||
|
||||
std::unique_ptr<std::thread> loadThread;
|
||||
std::atomic<bool> shutdownLoadThread = false;
|
||||
std::atomic<bool> mustUpdateDrawLoadThread = false;
|
||||
|
||||
int get_exact_mipmap_level_for_dimensions(const Vector2i& dim);
|
||||
int get_best_allocated_mipmap_level(int mipmapLevel);
|
||||
int get_smallest_mipmap_level() const;
|
||||
Vector2i get_mipmap_level_image_dimensions(int mipmapLevel) const;
|
||||
int calculate_smallest_mipmap_level();
|
||||
void load_thread_func(int mipmapLevel);
|
||||
void attempt_load_mipmap_in_separate_thread(int mipmapLevel);
|
||||
sk_sp<SkImage> load_frame_with_codec(const std::unique_ptr<SkCodec>& codec, unsigned width, unsigned height, unsigned frameIndexToLoad);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,3 +1,6 @@
|
|||
#include "ResourceDisplay.hpp"
|
||||
|
||||
void ResourceDisplay::camera_view_update(const CoordSpaceHelper& compCoords, const SCollision::AABB<WorldScalar>& compAABB, const DrawData& drawData, const SkRect& imRect) {
|
||||
}
|
||||
|
||||
ResourceDisplay::~ResourceDisplay() {}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,9 @@
|
|||
#include <include/core/SkCanvas.h>
|
||||
#include <include/core/SkRect.h>
|
||||
#include <Eigen/Dense>
|
||||
#include "../SharedTypes.hpp"
|
||||
#include <Helpers/SCollision.hpp>
|
||||
#include "../CoordSpaceHelper.hpp"
|
||||
|
||||
using namespace Eigen;
|
||||
|
||||
|
|
@ -17,11 +20,12 @@ class ResourceDisplay {
|
|||
SVG
|
||||
};
|
||||
virtual void update(World& w) = 0;
|
||||
virtual bool load(ResourceManager& rMan, const std::string& fileName, const std::string& fileData) = 0;
|
||||
virtual bool load(ResourceManager& rMan, const std::string& fileName, const std::shared_ptr<std::string>& fileData) = 0;
|
||||
virtual bool update_draw() const = 0;
|
||||
virtual void draw(SkCanvas* canvas, const DrawData& drawData, const SkRect& imRect) = 0;
|
||||
virtual Vector2f get_dimensions() const = 0;
|
||||
virtual float get_dimension_scale() const = 0;
|
||||
virtual Type get_type() const = 0;
|
||||
virtual void camera_view_update(const CoordSpaceHelper& compCoords, const SCollision::AABB<WorldScalar>& compAABB, const DrawData& drawData, const SkRect& imRect);
|
||||
virtual ~ResourceDisplay();
|
||||
};
|
||||
|
|
|
|||
|
|
@ -12,8 +12,8 @@ void SvgResourceDisplay::update(World& w) {
|
|||
mustUpdateDraw = false;
|
||||
}
|
||||
|
||||
bool SvgResourceDisplay::load(ResourceManager& rMan, const std::string& fileName, const std::string& fileData) {
|
||||
SkMemoryStream strm(fileData.c_str(), fileData.size());
|
||||
bool SvgResourceDisplay::load(ResourceManager& rMan, const std::string& fileName, const std::shared_ptr<std::string>& fileData) {
|
||||
SkMemoryStream strm(fileData->c_str(), fileData->size());
|
||||
svgDom = SkSVGDOM::Builder().make(strm);
|
||||
|
||||
mustUpdateDraw = true;
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
class SvgResourceDisplay : public ResourceDisplay {
|
||||
public:
|
||||
virtual void update(World& w) override;
|
||||
virtual bool load(ResourceManager& rMan, const std::string& fileName, const std::string& fileData) override;
|
||||
virtual bool load(ResourceManager& rMan, const std::string& fileName, const std::shared_ptr<std::string>& fileData) override;
|
||||
virtual bool update_draw() const override;
|
||||
virtual void draw(SkCanvas* canvas, const DrawData& drawData, const SkRect& imRect) override;
|
||||
virtual Vector2f get_dimensions() const override;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue