diff --git a/src/app/memorychecker.cpp b/src/app/memorychecker.cpp index 9b53042ac..24e7d2ecf 100644 --- a/src/app/memorychecker.cpp +++ b/src/app/memorychecker.cpp @@ -108,6 +108,17 @@ void MemoryChecker::sGetFreeKB(intKB& procFreeKB, (task_info_t)&vm_info, &vm_info_count) == KERN_SUCCESS) { bytes_in_use_by_app = vm_info.phys_footprint; + } else { + task_basic_info_data_t basic_info; + mach_msg_type_number_t basic_info_count = TASK_BASIC_INFO_COUNT; + if (task_info(mach_task_self(), + TASK_BASIC_INFO, + (task_info_t)&basic_info, + &basic_info_count) == KERN_SUCCESS) { + bytes_in_use_by_app = basic_info.resident_size; + } else { + RuntimeThrow("Could not retrieve process memory usage"); + } } #endif diff --git a/src/core/Boxes/boundingbox.cpp b/src/core/Boxes/boundingbox.cpp index 4da8ea0fd..fe65b6013 100644 --- a/src/core/Boxes/boundingbox.cpp +++ b/src/core/Boxes/boundingbox.cpp @@ -555,6 +555,9 @@ void BoundingBox::planUpdate(const UpdateReason reason) { if(reason == UpdateReason::userChange) { mStateId++; mRenderDataHandler.clear(); + if(const auto canvas = enve_cast(this)) { + canvas->invalidateSceneFramesCache(); + } } mDrawRenderContainer.setExpired(true); diff --git a/src/core/CacheHandlers/hddcachablecachehandler.h b/src/core/CacheHandlers/hddcachablecachehandler.h index 33f1ebae6..a4698f44b 100644 --- a/src/core/CacheHandlers/hddcachablecachehandler.h +++ b/src/core/CacheHandlers/hddcachablecachehandler.h @@ -99,7 +99,7 @@ class CORE_EXPORT HddCachableCacheHandler { } auto begin() const { return mConts.begin(); } - auto end() const { return mConts.begin(); } + auto end() const { return mConts.end(); } private: RangeMap> mConts; UsedRange mUsedRange; diff --git a/src/core/CacheHandlers/hddcachablecont.cpp b/src/core/CacheHandlers/hddcachablecont.cpp index 2b10587d3..c96fa90aa 100644 --- a/src/core/CacheHandlers/hddcachablecont.cpp +++ b/src/core/CacheHandlers/hddcachablecont.cpp @@ -49,6 +49,10 @@ eTask *HddCachableCont::scheduleDeleteTmpFile() { eTask *HddCachableCont::scheduleSaveToTmpFile() { if(mTmpSaveTask || mTmpFile) return nullptr; mTmpSaveTask = createTmpFileDataSaver(); + if(!mTmpSaveTask) { + tmpFileSaveFailed(); + return nullptr; + } mTmpSaveTask->queTask(); return mTmpSaveTask.get(); } @@ -59,6 +63,10 @@ eTask *HddCachableCont::scheduleLoadFromTmpFile() { if(!mTmpSaveTask && !mTmpFile) return nullptr; mTmpLoadTask = createTmpFileDataLoader(); + if(!mTmpLoadTask) { + tmpFileLoadFailed(); + return nullptr; + } if(mTmpSaveTask) mTmpSaveTask->addDependent(mTmpLoadTask.get()); mTmpLoadTask->queTask(); @@ -70,6 +78,16 @@ void HddCachableCont::setDataSavedToTmpFile(const qsptr &tmpFile mTmpFile = tmpFile; } +void HddCachableCont::tmpFileSaveFailed() { + mTmpSaveTask.reset(); + if(!mDataInMemory && !mTmpFile) noDataLeft_k(); +} + +void HddCachableCont::tmpFileLoadFailed() { + mTmpLoadTask.reset(); + if(!mDataInMemory && !mTmpFile && !mTmpSaveTask) noDataLeft_k(); +} + void HddCachableCont::afterDataLoadedFromTmpFile() { setDataInMemory(true); mTmpLoadTask.reset(); diff --git a/src/core/CacheHandlers/hddcachablecont.h b/src/core/CacheHandlers/hddcachablecont.h index bb3194589..5efb40857 100644 --- a/src/core/CacheHandlers/hddcachablecont.h +++ b/src/core/CacheHandlers/hddcachablecont.h @@ -45,6 +45,8 @@ class CORE_EXPORT HddCachableCont : public CacheContainer { eTask* scheduleLoadFromTmpFile(); void setDataSavedToTmpFile(const qsptr &tmpFile); + void tmpFileSaveFailed(); + void tmpFileLoadFailed(); bool storesDataInMemory() const { return mDataInMemory; } qsptr getTmpFile() const { return mTmpFile; } diff --git a/src/core/CacheHandlers/imagecachecontainer.cpp b/src/core/CacheHandlers/imagecachecontainer.cpp index e40491e30..545b44065 100644 --- a/src/core/CacheHandlers/imagecachecontainer.cpp +++ b/src/core/CacheHandlers/imagecachecontainer.cpp @@ -49,6 +49,10 @@ int ImageCacheContainer::getByteCount() { } void ImageCacheContainer::setDataLoadedFromTmpFile(const sk_sp &img) { + if(!img) { + tmpFileLoadFailed(); + return; + } replaceImage(img); afterDataLoadedFromTmpFile(); } @@ -58,6 +62,7 @@ int ImageCacheContainer::clearMemory() { } stdsptr ImageCacheContainer::createTmpFileDataSaver() { + if(!getImage()) return nullptr; return enve::make_shared(this, getImage()); } diff --git a/src/core/CacheHandlers/imagecachecontainer.h b/src/core/CacheHandlers/imagecachecontainer.h index c62aae1f7..d1a702913 100644 --- a/src/core/CacheHandlers/imagecachecontainer.h +++ b/src/core/CacheHandlers/imagecachecontainer.h @@ -64,6 +64,7 @@ class CORE_EXPORT ImgSaver : public TmpSaver { TmpSaver(target), mImage(image) {} void write(eWriteStream& dst) { + if(!mImage) return; SkiaHelpers::writeImg(mImage, dst); } private: diff --git a/src/core/CacheHandlers/soundcachecontainer.cpp b/src/core/CacheHandlers/soundcachecontainer.cpp index a2483a275..b186fbe15 100644 --- a/src/core/CacheHandlers/soundcachecontainer.cpp +++ b/src/core/CacheHandlers/soundcachecontainer.cpp @@ -38,6 +38,7 @@ SoundCacheContainer::SoundCacheContainer(const stdsptr& samples, } stdsptr SoundCacheContainer::createTmpFileDataSaver() { + if(!mSamples) return nullptr; return enve::make_shared(mSamples, this); } diff --git a/src/core/CacheHandlers/soundtmpfilehandlers.cpp b/src/core/CacheHandlers/soundtmpfilehandlers.cpp index b175c6bed..13d0908d3 100644 --- a/src/core/CacheHandlers/soundtmpfilehandlers.cpp +++ b/src/core/CacheHandlers/soundtmpfilehandlers.cpp @@ -36,6 +36,10 @@ void SoundContainerTmpFileDataLoader::read(eReadStream& src) { } void SoundContainerTmpFileDataLoader::afterProcessing() { + if(!mSamples) { + if(mTarget) mTarget->tmpFileLoadFailed(); + return; + } mTarget->setDataLoadedFromTmpFile(mSamples); } @@ -45,5 +49,6 @@ SoundContainerTmpFileDataSaver::SoundContainerTmpFileDataSaver( TmpSaver(target), mSamples(samples) {} void SoundContainerTmpFileDataSaver::write(eWriteStream& dst) { + if(!mSamples) return; mSamples->write(dst); } diff --git a/src/core/CacheHandlers/tmploader.cpp b/src/core/CacheHandlers/tmploader.cpp index 77c42c8a0..ab63ae43a 100644 --- a/src/core/CacheHandlers/tmploader.cpp +++ b/src/core/CacheHandlers/tmploader.cpp @@ -30,7 +30,7 @@ TmpLoader::TmpLoader(const qsptr &file, mTmpFile(file), mTarget(target) {} void TmpLoader::process() { - if(!mTmpFile) return; + if(!mTmpFile) RuntimeThrow("Temporary cache file is missing."); if(mTmpFile->open()) { eReadStream src(mTmpFile.get()); read(src); diff --git a/src/core/CacheHandlers/tmpsaver.cpp b/src/core/CacheHandlers/tmpsaver.cpp index 9799b876d..c4eb1ef8a 100644 --- a/src/core/CacheHandlers/tmpsaver.cpp +++ b/src/core/CacheHandlers/tmpsaver.cpp @@ -24,12 +24,18 @@ // Fork of enve - Copyright (C) 2016-2020 Maurycy Liebner #include "tmpsaver.h" +#include "appsupport.h" + +#include TmpSaver::TmpSaver(HddCachableCont* const target) : mTarget(target) {} void TmpSaver::process() { - mTmpFile = qsptr(new QTemporaryFile()); + QDir().mkpath(AppSupport::getAppTempPath()); + const QString templ = AppSupport::getAppTempPath() + + "/friction-cache-XXXXXX.tmp"; + mTmpFile = qsptr(new QTemporaryFile(templ)); if(mTmpFile->open()) { eWriteStream dst(mTmpFile.get()); write(dst); @@ -42,6 +48,13 @@ void TmpSaver::process() { void TmpSaver::afterProcessing() { if(!mTarget) return; - if(!mSavingSuccessful) return; + if(!mSavingSuccessful) { + mTarget->tmpFileSaveFailed(); + return; + } mTarget->setDataSavedToTmpFile(mTmpFile); } + +void TmpSaver::afterCanceled() { + if(mTarget) mTarget->tmpFileSaveFailed(); +} diff --git a/src/core/CacheHandlers/tmpsaver.h b/src/core/CacheHandlers/tmpsaver.h index acebce5a5..480619b18 100644 --- a/src/core/CacheHandlers/tmpsaver.h +++ b/src/core/CacheHandlers/tmpsaver.h @@ -41,6 +41,7 @@ class CORE_EXPORT TmpSaver : public eHddTask { void process(); void afterProcessing(); + void afterCanceled(); private: const stdptr mTarget; bool mSavingSuccessful = false; diff --git a/src/core/canvas.cpp b/src/core/canvas.cpp index f6e587c51..197bfa9c3 100644 --- a/src/core/canvas.cpp +++ b/src/core/canvas.cpp @@ -125,11 +125,21 @@ qreal Canvas::getResolution() const void Canvas::setResolution(const qreal percent) { + if(isZero6Dec(mResolution - percent)) return; mResolution = percent; + invalidateSceneFramesCache(); prp_afterWholeInfluenceRangeChanged(); updateAllBoxes(UpdateReason::userChange); } +void Canvas::invalidateSceneFramesCache() +{ + mSceneFrame.reset(); + mLoadingSceneFrame.reset(); + mSceneFrameOutdated = true; + mSceneFramesHandler.clear(); +} + void Canvas::setCurrentGroupParentAsCurrentGroup() { setCurrentBoxesGroup(mCurrentContainer->getParentGroup()); diff --git a/src/core/canvas.h b/src/core/canvas.h index 6bdeb5c6c..490818883 100644 --- a/src/core/canvas.h +++ b/src/core/canvas.h @@ -192,6 +192,7 @@ class CORE_EXPORT Canvas : public CanvasBase void setWorldToScreen(const QTransform& transform, qreal devicePixelRatio); void setResolution(const qreal percent); + void invalidateSceneFramesCache(); void applyCurrentTransformToSelected(); QPointF getSelectedPointsAbsPivotPos(); diff --git a/src/core/videoencoder.cpp b/src/core/videoencoder.cpp index e65177f6c..c2b52f5a4 100644 --- a/src/core/videoencoder.cpp +++ b/src/core/videoencoder.cpp @@ -276,16 +276,14 @@ static void addVideoStream(OutputStream * const ost, static AVFrame *getVideoFrame(OutputStream * const ost, const sk_sp &image) { - AVCodecContext *c = ost->fCodec; + if(!image) RuntimeThrow("Missing image for video frame"); - if (c->width != image->width() || c->height != image->height()) { - RuntimeThrow("Image size don't match codec size"); - } + AVCodecContext *c = ost->fCodec; /* rely on cache manager to produce fSwsCtx if it hasn't already * been produced. */ ost->fSwsCtx = sws_getCachedContext(ost->fSwsCtx, - c->width, c->height, + image->width(), image->height(), AV_PIX_FMT_RGBA, c->width, c->height, c->pix_fmt, SWS_BICUBIC, @@ -297,7 +295,13 @@ static AVFrame *getVideoFrame(OutputStream * const ost, SkPixmap pixmap; SkBitmap unpremulBitmap; - image->peekPixels(&pixmap); + sk_sp rasterImage; + if(!image->peekPixels(&pixmap)) { + rasterImage = image->makeRasterImage(); + if(!rasterImage || !rasterImage->peekPixels(&pixmap)) { + RuntimeThrow("Could not peek image pixels"); + } + } // check if we need to convert to "unpremultiplied" const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->pix_fmt); @@ -323,12 +327,13 @@ static AVFrame *getVideoFrame(OutputStream * const ost, const uint8_t * const dstSk[] = {static_cast(pixmap.writable_addr())}; int linesizesSk[4]; - av_image_fill_linesizes(linesizesSk, AV_PIX_FMT_RGBA, image->width()); + av_image_fill_linesizes(linesizesSk, AV_PIX_FMT_RGBA, pixmap.width()); + linesizesSk[0] = static_cast(pixmap.rowBytes()); const int ret = av_frame_make_writable(ost->fDstFrame) ; if (ret < 0) { AV_RuntimeThrow(ret, "Could not make AVFrame writable") } sws_scale(ost->fSwsCtx, dstSk, - linesizesSk, 0, c->height, + linesizesSk, 0, pixmap.height(), ost->fDstFrame->data, ost->fDstFrame->linesize);