From 22bb2f5b68dc9e3c3608629629460513bf213938 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Wed, 25 Apr 2018 15:04:38 +0200 Subject: Add handling of device pixel ratio to animated sprites MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I472f61241d1875daf0de0a597bf27c019314f48f Task-number: QTBUG-50119 Reviewed-by: Mitch Curtis Reviewed-by: Morten Johan Sørvig --- src/particles/qquickimageparticle.cpp | 2 +- src/quick/items/qquickanimatedsprite.cpp | 4 +- src/quick/items/qquickimagebase_p.h | 2 +- src/quick/items/qquicksprite.cpp | 7 ++- src/quick/items/qquicksprite_p.h | 12 ++++++ src/quick/items/qquickspriteengine.cpp | 50 ++++++++++++++-------- src/quick/items/qquickspritesequence.cpp | 2 +- .../adaptations/software/qsgsoftwarespritenode.cpp | 2 +- 8 files changed, 56 insertions(+), 25 deletions(-) diff --git a/src/particles/qquickimageparticle.cpp b/src/particles/qquickimageparticle.cpp index d2fb78d72a..abd7793a74 100644 --- a/src/particles/qquickimageparticle.cpp +++ b/src/particles/qquickimageparticle.cpp @@ -1321,7 +1321,7 @@ void QQuickImageParticle::finishBuildParticleNodes(QSGNode** node) m_material = SpriteMaterial::createMaterial(); if (imageLoaded) getState(m_material)->texture = QSGPlainTexture::fromImage(image); - getState(m_material)->animSheetSize = QSizeF(image.size()); + getState(m_material)->animSheetSize = QSizeF(image.size() / image.devicePixelRatioF()); if (m_spriteEngine) m_spriteEngine->setCount(m_count); Q_FALLTHROUGH(); diff --git a/src/quick/items/qquickanimatedsprite.cpp b/src/quick/items/qquickanimatedsprite.cpp index 190c48ac88..887c30f999 100644 --- a/src/quick/items/qquickanimatedsprite.cpp +++ b/src/quick/items/qquickanimatedsprite.cpp @@ -527,6 +527,8 @@ void QQuickAnimatedSprite::setSource(QUrl arg) Q_D(QQuickAnimatedSprite); if (d->m_sprite->m_source != arg) { + const qreal targetDevicePixelRatio = (window() ? window()->effectiveDevicePixelRatio() : qApp->devicePixelRatio()); + d->m_sprite->setDevicePixelRatio(targetDevicePixelRatio); d->m_sprite->setSource(arg); Q_EMIT sourceChanged(arg); reloadImage(); @@ -713,7 +715,7 @@ QSGSpriteNode* QQuickAnimatedSprite::initNode() QSGSpriteNode *node = d->sceneGraphContext()->createSpriteNode(); - d->m_sheetSize = QSize(image.size()); + d->m_sheetSize = QSize(image.size() / image.devicePixelRatioF()); node->setTexture(window()->createTextureFromImage(image)); d->m_spriteEngine->start(0); node->setTime(0.0f); diff --git a/src/quick/items/qquickimagebase_p.h b/src/quick/items/qquickimagebase_p.h index eb04a1d162..d8d0be9b8c 100644 --- a/src/quick/items/qquickimagebase_p.h +++ b/src/quick/items/qquickimagebase_p.h @@ -98,7 +98,7 @@ public: virtual void setAutoTransform(bool transform); bool autoTransform() const; - void resolve2xLocalFile(const QUrl &url, qreal targetDevicePixelRatio, QUrl *sourceUrl, qreal *sourceDevicePixelRatio); + static void resolve2xLocalFile(const QUrl &url, qreal targetDevicePixelRatio, QUrl *sourceUrl, qreal *sourceDevicePixelRatio); // Use a virtual rather than a signal->signal to avoid the huge // connect/conneciton overhead for this rare case. diff --git a/src/quick/items/qquicksprite.cpp b/src/quick/items/qquicksprite.cpp index 6b8567439b..8c59a68982 100644 --- a/src/quick/items/qquicksprite.cpp +++ b/src/quick/items/qquicksprite.cpp @@ -38,6 +38,7 @@ ****************************************************************************/ #include "qquicksprite_p.h" +#include "qquickimagebase_p.h" #include #include #include @@ -222,6 +223,7 @@ QQuickSprite::QQuickSprite(QObject *parent) , m_frameDuration(unsetDuration) , m_frameDurationVariation(0) , m_frameSync(false) + , m_devicePixelRatio(1.0) { } @@ -265,7 +267,10 @@ void QQuickSprite::startImageLoading() if (!e) qWarning() << "QQuickSprite: Cannot find QQmlEngine - this class is only for use in QML and may not work"; } - m_pix.load(e, m_source); + QUrl loadUrl = m_source; + QQuickImageBase::resolve2xLocalFile(m_source, m_devicePixelRatio, &loadUrl, &m_devicePixelRatio); + + m_pix.load(e, loadUrl); } } diff --git a/src/quick/items/qquicksprite_p.h b/src/quick/items/qquicksprite_p.h index 8e119a80a9..fab9e75190 100644 --- a/src/quick/items/qquicksprite_p.h +++ b/src/quick/items/qquicksprite_p.h @@ -168,6 +168,16 @@ public: return m_frameSync; } + void setDevicePixelRatio(qreal dpr) + { + m_devicePixelRatio = dpr; + } + + qreal devicePixelRatio() const + { + return m_devicePixelRatio; + } + Q_SIGNALS: void sourceChanged(QUrl arg); @@ -308,6 +318,7 @@ private: friend class QQuickAnimatedSprite; friend class QQuickSpriteEngine; friend class QQuickStochasticEngine; + int m_generatedCount; int m_framesPerRow; int m_rowY; @@ -325,6 +336,7 @@ private: int m_frameDuration; int m_frameDurationVariation; bool m_frameSync; + qreal m_devicePixelRatio; QQuickPixmap m_pix; }; diff --git a/src/quick/items/qquickspriteengine.cpp b/src/quick/items/qquickspriteengine.cpp index 1fd15e61e3..03f0fa94a4 100644 --- a/src/quick/items/qquickspriteengine.cpp +++ b/src/quick/items/qquickspriteengine.cpp @@ -390,6 +390,7 @@ QImage QQuickSpriteEngine::assembledImage(int maxSize) int w = 0; m_maxFrames = 0; m_imageStateCount = 0; + qreal pixelRatio = 1.0; for (QQuickSprite* state : qAsConst(m_sprites)) { if (state->frames() > m_maxFrames) @@ -413,6 +414,8 @@ QImage QQuickSpriteEngine::assembledImage(int maxSize) if (!state->m_frameHeight) state->m_frameHeight = img.height(); + pixelRatio = qMax(pixelRatio, state->devicePixelRatio()); + if (state->frames() * state->frameWidth() > maxSize){ struct helper{ static int divRoundUp(int a, int b){return (a+b-1)/b;} @@ -437,43 +440,58 @@ QImage QQuickSpriteEngine::assembledImage(int maxSize) } } + if (h > maxSize){ + qWarning() << "SpriteEngine: Too many animations to fit in one texture..."; + qWarning() << "SpriteEngine: Your texture max size today is " << maxSize; + return QImage(); + } + //maxFrames is max number in a line of the texture - QImage image(w, h, QImage::Format_ARGB32_Premultiplied); + QImage image(w * pixelRatio, h * pixelRatio, QImage::Format_ARGB32_Premultiplied); + image.setDevicePixelRatio(pixelRatio); image.fill(0); QPainter p(&image); int y = 0; for (QQuickSprite* state : qAsConst(m_sprites)) { QImage img(state->m_pix.image()); - int frameWidth = state->m_frameWidth; - int frameHeight = state->m_frameHeight; - if (img.height() == frameHeight && img.width() < maxSize){//Simple case - p.drawImage(0,y,img.copy(state->m_frameX,0,state->m_frames * frameWidth, frameHeight)); + const int frameWidth = state->m_frameWidth; + const int frameHeight = state->m_frameHeight; + const int imgHeight = img.height() / state->devicePixelRatio(); + const int imgWidth = img.width() / state->devicePixelRatio(); + if (imgHeight == frameHeight && imgWidth < maxSize){ //Simple case + p.drawImage(QRect(0, y, state->m_frames * frameWidth, frameHeight), + img, + QRect(state->m_frameX * state->devicePixelRatio(), 0, state->m_frames * frameWidth * state->devicePixelRatio(), frameHeight * state->devicePixelRatio())); state->m_rowStartX = 0; state->m_rowY = y; y += frameHeight; - }else{//Chopping up image case - state->m_framesPerRow = image.width()/frameWidth; + } else { //Chopping up image case + state->m_framesPerRow = w/frameWidth; state->m_rowY = y; int x = 0; int curX = state->m_frameX; int curY = state->m_frameY; int framesLeft = state->frames(); while (framesLeft > 0){ - if (image.width() - x + curX <= img.width()){//finish a row in image (dest) - int copied = image.width() - x; + if (w - x + curX <= imgWidth){//finish a row in image (dest) + int copied = w - x; framesLeft -= copied/frameWidth; - p.drawImage(x,y,img.copy(curX,curY,copied,frameHeight)); + p.drawImage(QRect(x, y, copied, frameHeight), + img, + QRect(curX * state->devicePixelRatio(), curY * state->devicePixelRatio(), copied * state->devicePixelRatio(), frameHeight * state->devicePixelRatio())); y += frameHeight; curX += copied; x = 0; - if (curX == img.width()){ + if (curX == imgWidth){ curX = 0; curY += frameHeight; } }else{//finish a row in img (src) - int copied = img.width() - curX; + int copied = imgWidth - curX; framesLeft -= copied/frameWidth; - p.drawImage(x,y,img.copy(curX,curY,copied,frameHeight)); + p.drawImage(QRect(x, y, copied, frameHeight), + img, + QRect(curX * state->devicePixelRatio(), curY * state->devicePixelRatio(), copied * state->devicePixelRatio(), frameHeight * state->devicePixelRatio())); curY += frameHeight; x += copied; curX = 0; @@ -484,12 +502,6 @@ QImage QQuickSpriteEngine::assembledImage(int maxSize) } } - if (image.height() > maxSize){ - qWarning() << "SpriteEngine: Too many animations to fit in one texture..."; - qWarning() << "SpriteEngine: Your texture max size today is " << maxSize; - return QImage(); - } - #ifdef SPRITE_IMAGE_DEBUG QString fPath = QDir::tempPath() + "/SpriteImage.%1.png"; int acc = 0; diff --git a/src/quick/items/qquickspritesequence.cpp b/src/quick/items/qquickspritesequence.cpp index 72761ab82b..df6a6e336e 100644 --- a/src/quick/items/qquickspritesequence.cpp +++ b/src/quick/items/qquickspritesequence.cpp @@ -226,7 +226,7 @@ QSGSpriteNode *QQuickSpriteSequence::initNode() QSGSpriteNode *node = d->sceneGraphContext()->createSpriteNode(); - d->m_sheetSize = QSize(image.size()); + d->m_sheetSize = QSize(image.size() / image.devicePixelRatioF()); node->setTexture(window()->createTextureFromImage(image)); d->m_spriteEngine->start(0); node->setTime(0.0f); diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarespritenode.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwarespritenode.cpp index ba7bbc2d11..d4e5e98d68 100644 --- a/src/quick/scenegraph/adaptations/software/qsgsoftwarespritenode.cpp +++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarespritenode.cpp @@ -123,7 +123,7 @@ void QSGSoftwareSpriteNode::paint(QPainter *painter) // XXX try to do some kind of interpolation between sourceA and sourceB using time painter->drawPixmap(QRectF(0, 0, m_size.width(), m_size.height()), pixmap, - QRectF(m_sourceA, m_spriteSize)); + QRectF(m_sourceA * pixmap.devicePixelRatioF(), m_spriteSize * pixmap.devicePixelRatioF())); } bool QSGSoftwareSpriteNode::isOpaque() const -- cgit v1.2.3 From dd1b13a50b55652253cc04cc3fa52d2280f1da56 Mon Sep 17 00:00:00 2001 From: Kimmo Ollila Date: Wed, 25 Apr 2018 12:57:55 +0300 Subject: Enable JIT on INTEGRITY ARM64 This patch enables JIT on INTEGRITY s820Am and other ARM64 builds Change-Id: I2fa130f41a6c5bc6aa86bcfd5a01c2d431300561 Reviewed-by: Simon Hausmann Reviewed-by: Nikola Velinov --- src/3rdparty/masm/assembler/ARM64Assembler.h | 6 ++++++ src/3rdparty/masm/stubs/ExecutableAllocator.h | 8 ++++++++ src/3rdparty/masm/wtf/OSAllocator.h | 4 ++++ src/3rdparty/masm/wtf/OSAllocatorIntegrity.cpp | 12 ++++++++++++ src/3rdparty/masm/wtf/Platform.h | 5 +++++ src/qml/jsruntime/qv4global_p.h | 2 +- 6 files changed, 36 insertions(+), 1 deletion(-) diff --git a/src/3rdparty/masm/assembler/ARM64Assembler.h b/src/3rdparty/masm/assembler/ARM64Assembler.h index 008f03bccf..1787e921e8 100644 --- a/src/3rdparty/masm/assembler/ARM64Assembler.h +++ b/src/3rdparty/masm/assembler/ARM64Assembler.h @@ -39,6 +39,10 @@ #include #endif +#if OS(INTEGRITY) +#include +#endif + #define CHECK_DATASIZE_OF(datasize) ASSERT(datasize == 32 || datasize == 64) #define DATASIZE_OF(datasize) ((datasize == 64) ? Datasize_64 : Datasize_32) #define MEMOPSIZE_OF(datasize) ((datasize == 8 || datasize == 128) ? MemOpSize_8_or_128 : (datasize == 16) ? MemOpSize_16 : (datasize == 32) ? MemOpSize_32 : MemOpSize_64) @@ -3039,6 +3043,8 @@ public: UNUSED_PARAM(code); UNUSED_PARAM(size); #endif +#elif OS(INTEGRITY) + ManageCaches((Address)code, size, ACCESS_DST_COHERENT); #else #error "The cacheFlush support is missing on this platform." #endif diff --git a/src/3rdparty/masm/stubs/ExecutableAllocator.h b/src/3rdparty/masm/stubs/ExecutableAllocator.h index 3b84b5c986..1ab28588fb 100644 --- a/src/3rdparty/masm/stubs/ExecutableAllocator.h +++ b/src/3rdparty/masm/stubs/ExecutableAllocator.h @@ -45,6 +45,10 @@ #include +#if OS(INTEGRITY) +#include "OSAllocator.h" +#endif + #if OS(WINDOWS) #include #else @@ -118,6 +122,8 @@ struct ExecutableAllocator { Q_UNREACHABLE(); } # endif +# elif OS(INTEGRITY) + OSAllocator::setMemoryAttributes(addr, /*writable*/ true, /*executable*/ false); # else int mode = PROT_READ | PROT_WRITE; if (mprotect(addr, size, mode) != 0) { @@ -152,6 +158,8 @@ struct ExecutableAllocator { Q_UNREACHABLE(); } # endif +# elif OS(INTEGRITY) + OSAllocator::setMemoryAttributes(addr, /*writable*/ false, /*executable*/ true); # else int mode = PROT_READ | PROT_EXEC; if (mprotect(addr, size, mode) != 0) { diff --git a/src/3rdparty/masm/wtf/OSAllocator.h b/src/3rdparty/masm/wtf/OSAllocator.h index 933b3cda0a..366dd73993 100644 --- a/src/3rdparty/masm/wtf/OSAllocator.h +++ b/src/3rdparty/masm/wtf/OSAllocator.h @@ -73,6 +73,10 @@ public: static T* reallocateCommitted(T*, size_t oldSize, size_t newSize, Usage = UnknownUsage, bool writable = true, bool executable = false); static bool canAllocateExecutableMemory(); + +#if defined(Q_OS_INTEGRITY) + static void setMemoryAttributes(void* addr, bool writable, bool executable); +#endif }; inline void* OSAllocator::reserveAndCommit(size_t reserveSize, size_t commitSize, Usage usage, bool writable, bool executable) diff --git a/src/3rdparty/masm/wtf/OSAllocatorIntegrity.cpp b/src/3rdparty/masm/wtf/OSAllocatorIntegrity.cpp index 451ca147d1..7addf9e5c2 100644 --- a/src/3rdparty/masm/wtf/OSAllocatorIntegrity.cpp +++ b/src/3rdparty/masm/wtf/OSAllocatorIntegrity.cpp @@ -123,6 +123,12 @@ Error setAttributes(MemoryRegion mr, bool writable, bool executable) return SetMemoryRegionAttributes(mr, attributes); } +void OSAllocator::setMemoryAttributes(void* addr, bool writable, bool executable) +{ + const MRPair* pair = memoryRegionsContainer.getMRPair((Address)addr); + CheckSuccess(setAttributes(pair->vmr, writable, executable)); +} + void* OSAllocator::reserveUncommitted(size_t bytes, Usage usage, bool writable, bool executable) { MemoryRegion VMR; @@ -229,4 +235,10 @@ void OSAllocator::releaseDecommitted(void* address, size_t bytes) memoryRegionsContainer.deleteMRPair(pair); } } + +bool OSAllocator::canAllocateExecutableMemory() +{ + return true; +} + } // namespace WTF diff --git a/src/3rdparty/masm/wtf/Platform.h b/src/3rdparty/masm/wtf/Platform.h index 4f37245495..5905f42f45 100644 --- a/src/3rdparty/masm/wtf/Platform.h +++ b/src/3rdparty/masm/wtf/Platform.h @@ -171,6 +171,11 @@ #define WTF_CPU_ARM64 1 #endif +/* CPU(ARM64) - INTEGRITY */ +#if (defined(__ARM64__)) +#define WTF_CPU_ARM64 1 +#endif + /* CPU(ARM) - ARM, any version*/ #define WTF_ARM_ARCH_AT_LEAST(N) (CPU(ARM) && WTF_ARM_ARCH_VERSION >= N) diff --git a/src/qml/jsruntime/qv4global_p.h b/src/qml/jsruntime/qv4global_p.h index 9b13d4e341..1fa4bae049 100644 --- a/src/qml/jsruntime/qv4global_p.h +++ b/src/qml/jsruntime/qv4global_p.h @@ -101,7 +101,7 @@ inline double trunc(double d) { return d > 0 ? floor(d) : ceil(d); } # define V4_ENABLE_JIT # endif #elif defined(Q_PROCESSOR_ARM_64) && (QT_POINTER_SIZE == 8) -# if defined(Q_OS_LINUX) || defined(Q_OS_QNX) +# if defined(Q_OS_LINUX) || defined(Q_OS_QNX) || defined(Q_OS_INTEGRITY) # define V4_ENABLE_JIT # endif //#elif defined(Q_PROCESSOR_MIPS_32) && defined(Q_OS_LINUX) -- cgit v1.2.3 From 4b27062f5fae891850fd0f048f2a2421ca9b6c7c Mon Sep 17 00:00:00 2001 From: Kimmo Ollila Date: Wed, 25 Apr 2018 13:25:45 +0300 Subject: Fix JIT build on INTEGRITY ARM64 -typedef "Jump" may not be used in an elaborated type specifier -explicit specialization of function must precede its first use -"Value" is ambiguous Change-Id: Ic15c196f1b33211cd3f2f25a54ba478747336fe4 Reviewed-by: Simon Hausmann Reviewed-by: Janne Koskinen Reviewed-by: Nikola Velinov --- .../masm/assembler/AbstractMacroAssembler.h | 6 + src/3rdparty/masm/assembler/MacroAssemblerARM64.h | 203 ++++++++++++--------- src/qml/jsapi/qjsvalue.cpp | 8 +- src/qml/jsruntime/qv4qobjectwrapper.cpp | 10 +- src/qml/jsruntime/qv4stringobject.cpp | 4 +- src/qml/jsruntime/qv4vme_moth.cpp | 74 ++++---- 6 files changed, 173 insertions(+), 132 deletions(-) diff --git a/src/3rdparty/masm/assembler/AbstractMacroAssembler.h b/src/3rdparty/masm/assembler/AbstractMacroAssembler.h index 6fac27fdf1..1076384900 100644 --- a/src/3rdparty/masm/assembler/AbstractMacroAssembler.h +++ b/src/3rdparty/masm/assembler/AbstractMacroAssembler.h @@ -327,7 +327,13 @@ public: template friend class AbstractMacroAssembler; friend struct DFG::OSRExit; + +#if CPU(ARM_THUMB2) || CPU(ARM64) || defined(V4_BOOTSTRAP) + using Jump = typename AssemblerType::template Jump