diff --git a/libs/ui/CMakeLists.txt b/libs/ui/CMakeLists.txt --- a/libs/ui/CMakeLists.txt +++ b/libs/ui/CMakeLists.txt @@ -14,6 +14,7 @@ if (APPLE) find_library(FOUNDATION_LIBRARY Foundation) find_library(APPKIT_LIBRARY AppKit) + find_library(OPENGL_LIBRARY OpenGL) endif () set(kritaui_LIB_SRCS @@ -538,6 +539,7 @@ if(APPLE) target_link_libraries(kritaui ${FOUNDATION_LIBRARY}) target_link_libraries(kritaui ${APPKIT_LIBRARY}) + target_link_libraries(kritaui ${OPENGL_LIBRARY}) endif () diff --git a/libs/ui/canvas/kis_canvas2.cpp b/libs/ui/canvas/kis_canvas2.cpp --- a/libs/ui/canvas/kis_canvas2.cpp +++ b/libs/ui/canvas/kis_canvas2.cpp @@ -102,6 +102,10 @@ , toolProxy(parent) , displayColorConverter(resourceManager, view) { +#ifdef Q_OS_OSX + retryUpdateProjection.setSingleShot(false); + retryUpdateProjection.setInterval(20); +#endif } KisCoordinatesConverter *coordinatesConverter; @@ -117,6 +121,9 @@ KisSignalCompressor updateSignalCompressor; QRect savedUpdateRect; +#ifdef Q_OS_OSX + QTimer retryUpdateProjection; +#endif QBitArray channelFlags; KisProofingConfigurationSP proofingConfig; @@ -675,6 +682,13 @@ void KisCanvas2::updateCanvasProjection() { +#ifdef Q_OS_OSX + if (m_d->canvasWidget->isBusy()) { + m_d->retryUpdateProjection.start(); + return; + } +#endif + while (KisUpdateInfoSP info = m_d->projectionUpdatesCompressor.takeUpdateInfo()) { QRect vRect = m_d->canvasWidget->updateCanvasProjection(info); if (!vRect.isEmpty()) { @@ -686,6 +700,10 @@ if (m_d->currentCanvasIsOpenGL) { updateCanvasWidgetImpl(); } + +#ifdef Q_OS_OSX + m_d->retryUpdateProjection.stop(); +#endif } void KisCanvas2::slotDoCanvasUpdate() diff --git a/libs/ui/opengl/kis_opengl_canvas2.cpp b/libs/ui/opengl/kis_opengl_canvas2.cpp --- a/libs/ui/opengl/kis_opengl_canvas2.cpp +++ b/libs/ui/opengl/kis_opengl_canvas2.cpp @@ -362,6 +362,12 @@ cfg.writeEntry("canvasState", "OPENGL_PAINT_STARTED"); } +#ifdef Q_OS_OSX + if (isBusy()) { + glFinish(); + } +#endif + KisOpenglCanvasDebugger::instance()->nofityPaintRequested(); renderCanvasGL(); @@ -467,9 +473,20 @@ bool KisOpenGLCanvas2::isBusy() const { - const bool isBusyStatus = Sync::syncStatus(d->glSyncObject) == Sync::Unsignaled; + bool isBusyStatus = Sync::syncStatus(d->glSyncObject) == Sync::Unsignaled; KisOpenglCanvasDebugger::instance()->nofitySyncStatus(isBusyStatus); +#ifdef Q_OS_OSX + /** + * There is a bug on OSX: if we issue frame redraw before the tiles finished + * uploading, the tiles will become corrupted. Depending on the GPU/driver + * version either the tile itself, or its mipmaps will become totally + * transparent. + */ + + isBusyStatus = isBusyStatus || !d->openGLImageTextures->isFinished(); +#endif + return isBusyStatus; } @@ -884,17 +901,6 @@ d->openGLImageTextures->recalculateCache(info); } -#ifdef Q_OS_OSX - /** - * There is a bug on OSX: if we issue frame redraw before the tiles finished - * uploading, the tiles will become corrupted. Depending on the GPU/driver - * version either the tile itself, or its mipmaps will become totally - * transparent. - */ - - glFinish(); -#endif - return QRect(); // FIXME: Implement dirty rect for OpenGL } diff --git a/libs/ui/opengl/kis_opengl_image_textures.h b/libs/ui/opengl/kis_opengl_image_textures.h --- a/libs/ui/opengl/kis_opengl_image_textures.h +++ b/libs/ui/opengl/kis_opengl_image_textures.h @@ -104,6 +104,10 @@ void updateConfig(bool useBuffer, int NumMipmapLevels); +#ifdef Q_OS_OSX + bool isFinished(); +#endif + public: inline QRect storedImageBounds() { return m_storedImageBounds; @@ -202,6 +206,10 @@ KisTextureTileInfoPoolSP m_infoChunksPool; +#ifdef Q_OS_OSX + QSet m_busy; +#endif + private: typedef QMap ImageTexturesMap; static ImageTexturesMap imageTexturesMap; diff --git a/libs/ui/opengl/kis_opengl_image_textures.cpp b/libs/ui/opengl/kis_opengl_image_textures.cpp --- a/libs/ui/opengl/kis_opengl_image_textures.cpp +++ b/libs/ui/opengl/kis_opengl_image_textures.cpp @@ -246,6 +246,10 @@ { if (m_textureTiles.isEmpty()) return; +#ifdef Q_OS_OSX + m_busy.clear(); +#endif + Q_FOREACH (KisTextureTile *tile, m_textureTiles) { delete tile; } @@ -386,6 +390,10 @@ KIS_ASSERT_RECOVER_RETURN(tile); tile->update(*tileInfo); + +#ifdef Q_OS_OSX + m_busy.insert(tile); +#endif } } @@ -451,6 +459,23 @@ } } +#ifdef Q_OS_OSX +bool KisOpenGLImageTextures::isFinished() +{ + QMutableSetIterator i(m_busy); + + while (i.hasNext()) { + KisTextureTile *tile = i.next(); + if (!tile->isFinished()) { + return false; + } + i.remove(); + } + + return true; +} +#endif + void KisOpenGLImageTextures::slotImageSizeChanged(qint32 /*w*/, qint32 /*h*/) { createImageTextureTiles(); diff --git a/libs/ui/opengl/kis_texture_tile.h b/libs/ui/opengl/kis_texture_tile.h --- a/libs/ui/opengl/kis_texture_tile.h +++ b/libs/ui/opengl/kis_texture_tile.h @@ -97,6 +97,13 @@ void bindToActiveTexture(); int currentLodPlane() const; +#ifdef Q_OS_OSX + bool isFinished() const { + // see https://www.khronos.org/registry/OpenGL/extensions/APPLE/APPLE_fence.txt + return glTestObjectAPPLE(GL_TEXTURE, m_textureId); + } +#endif + private: inline void setTextureParameters();