From 7717aa0e47cb2dafd1a4194b26fa53bee67948c5 Mon Sep 17 00:00:00 2001 From: falkTX Date: Wed, 27 Mar 2019 02:26:06 +0100 Subject: [PATCH] Fixes and caching for inline displays Signed-off-by: falkTX --- source/backend/plugin/CarlaPluginLV2.cpp | 4 -- source/frontend/carla_backend.py | 7 +-- source/frontend/carla_host.py | 23 ++++---- source/frontend/patchcanvas/canvasbox.py | 61 +++++++++++++++++----- source/frontend/patchcanvas/patchcanvas.py | 20 +++---- 5 files changed, 71 insertions(+), 44 deletions(-) diff --git a/source/backend/plugin/CarlaPluginLV2.cpp b/source/backend/plugin/CarlaPluginLV2.cpp index 9dfb614ae..9508aff32 100644 --- a/source/backend/plugin/CarlaPluginLV2.cpp +++ b/source/backend/plugin/CarlaPluginLV2.cpp @@ -4705,15 +4705,11 @@ public: fExt.worker = nullptr; fExt.inlineDisplay = nullptr; - carla_stdout("Plugin has %u extensions", fRdfDescriptor->ExtensionCount); - for (uint32_t i=0; i < fRdfDescriptor->ExtensionCount; ++i) { const char* const extension = fRdfDescriptor->Extensions[i]; CARLA_SAFE_ASSERT_CONTINUE(extension != nullptr); - carla_stdout("Extension %u/%u %s", i+1, fRdfDescriptor->ExtensionCount, extension); - /**/ if (std::strcmp(extension, LV2_OPTIONS__interface) == 0) pData->hints |= PLUGIN_HAS_EXTENSION_OPTIONS; else if (std::strcmp(extension, LV2_PROGRAMS__Interface) == 0) diff --git a/source/frontend/carla_backend.py b/source/frontend/carla_backend.py index 5be30a967..9d7f41a0a 100644 --- a/source/frontend/carla_backend.py +++ b/source/frontend/carla_backend.py @@ -22,8 +22,6 @@ from abc import ABCMeta, abstractmethod from ctypes import * from platform import architecture -from sip import voidptr -from struct import pack from sys import platform, maxsize # ------------------------------------------------------------------------------------------------------------ @@ -2847,10 +2845,9 @@ class CarlaHostDLL(CarlaHostMeta): return None contents = ptr.contents datalen = contents.height * contents.stride - unpacked = tuple(contents.data[i] for i in range(datalen)) - packed = pack("%iB" % datalen, *unpacked) + databuf = tuple(contents.data[i] for i in range(datalen)) data = { - 'data': voidptr(packed), + 'data': databuf, 'width': contents.width, 'height': contents.height, 'stride': contents.stride, diff --git a/source/frontend/carla_host.py b/source/frontend/carla_host.py index 55b5bdfd3..902b3c64b 100644 --- a/source/frontend/carla_host.py +++ b/source/frontend/carla_host.py @@ -401,19 +401,11 @@ class HostWindow(QMainWindow): if withCanvas: self.scene = patchcanvas.PatchScene(self, self.ui.graphicsView) self.ui.graphicsView.setScene(self.scene) - self.ui.graphicsView.setViewportUpdateMode(QGraphicsView.FullViewportUpdate) - - if self.fSavedSettings[CARLA_KEY_CANVAS_ANTIALIASING] != patchcanvas.ANTIALIASING_NONE: - self.ui.graphicsView.setRenderHint(QPainter.Antialiasing, True) - - if self.fSavedSettings[CARLA_KEY_CANVAS_ANTIALIASING] != patchcanvas.ANTIALIASING_FULL: - self.ui.graphicsView.setRenderHint(QPainter.SmoothPixmapTransform, True) - self.ui.graphicsView.setRenderHint(QPainter.TextAntialiasing, True) + #self.ui.graphicsView.setViewportUpdateMode(QGraphicsView.FullViewportUpdate) if self.fSavedSettings[CARLA_KEY_CANVAS_USE_OPENGL] and hasGL: self.ui.glView = QGLWidget(self) self.ui.graphicsView.setViewport(self.ui.glView) - self.ui.graphicsView.setRenderHint(QPainter.HighQualityAntialiasing, self.fSavedSettings[CARLA_KEY_CANVAS_HQ_ANTIALIASING]) self.setupCanvas() @@ -1373,6 +1365,19 @@ class HostWindow(QMainWindow): self.ui.miniCanvasPreview.setViewTheme(patchcanvas.canvas.theme.canvas_bg, patchcanvas.canvas.theme.rubberband_brush, patchcanvas.canvas.theme.rubberband_pen.color()) self.ui.miniCanvasPreview.init(self.scene, self.fCanvasWidth, self.fCanvasHeight, self.fSavedSettings[CARLA_KEY_CUSTOM_PAINTING]) + if self.fSavedSettings[CARLA_KEY_CANVAS_ANTIALIASING] != patchcanvas.ANTIALIASING_NONE: + self.ui.graphicsView.setRenderHint(QPainter.Antialiasing, True) + + fullAA = self.fSavedSettings[CARLA_KEY_CANVAS_ANTIALIASING] == patchcanvas.ANTIALIASING_FULL + self.ui.graphicsView.setRenderHint(QPainter.SmoothPixmapTransform, fullAA) + self.ui.graphicsView.setRenderHint(QPainter.TextAntialiasing, fullAA) + + if self.fSavedSettings[CARLA_KEY_CANVAS_USE_OPENGL] and hasGL: + self.ui.graphicsView.setRenderHint(QPainter.HighQualityAntialiasing, self.fSavedSettings[CARLA_KEY_CANVAS_HQ_ANTIALIASING]) + + else: + self.ui.graphicsView.setRenderHint(QPainter.Antialiasing, False) + def updateCanvasInitialPos(self): x = self.ui.graphicsView.horizontalScrollBar().value() + self.width()/4 y = self.ui.graphicsView.verticalScrollBar().value() + self.height()/4 diff --git a/source/frontend/patchcanvas/canvasbox.py b/source/frontend/patchcanvas/canvasbox.py index d8f7f2d70..677d8a191 100644 --- a/source/frontend/patchcanvas/canvasbox.py +++ b/source/frontend/patchcanvas/canvasbox.py @@ -19,6 +19,9 @@ # ------------------------------------------------------------------------------------------------------------ # Imports (Global) +from sip import voidptr +from struct import pack + from PyQt5.QtCore import qCritical, Qt, QPointF, QRectF, QTimer from PyQt5.QtGui import QCursor, QFont, QFontMetrics, QImage, QLinearGradient, QPainter, QPen from PyQt5.QtWidgets import QGraphicsItem, QMenu @@ -103,7 +106,9 @@ class CanvasBox(QGraphicsItem): self.m_cursor_moving = False self.m_forced_split = False self.m_mouse_down = False + self.m_inline_data = None self.m_inline_image = None + self.m_inline_scaling = 1.0 self.m_port_list_ids = [] self.m_connection_lines = [] @@ -171,11 +176,28 @@ class CanvasBox(QGraphicsItem): def redrawInlineDisplay(self): if self.m_plugin_inline == self.INLINE_DISPLAY_CACHED: self.m_plugin_inline = self.INLINE_DISPLAY_ENABLED + self.update() + + def removeAsPlugin(self): + #del self.m_inline_image + #self.m_inline_data = None + #self.m_inline_image = None + #self.m_inline_scaling = 1.0 + + self.m_plugin_id = -1 + self.m_plugin_ui = False + #self.m_plugin_inline = self.INLINE_DISPLAY_DISABLED def setAsPlugin(self, plugin_id, hasUI, hasInlineDisplay): if hasInlineDisplay and not options.inline_displays: hasInlineDisplay = False + if not hasInlineDisplay: + del self.m_inline_image + self.m_inline_data = None + self.m_inline_image = None + self.m_inline_scaling = 1.0 + self.m_plugin_id = plugin_id self.m_plugin_ui = hasUI self.m_plugin_inline = self.INLINE_DISPLAY_ENABLED if hasInlineDisplay else self.INLINE_DISPLAY_DISABLED @@ -672,26 +694,41 @@ class CanvasBox(QGraphicsItem): painter.restore() def paintInlineDisplay(self, painter): - if self.m_plugin_id < 0 or self.m_plugin_id > MAX_PLUGIN_ID_ALLOWED: - return if self.m_plugin_inline == self.INLINE_DISPLAY_DISABLED: return if not options.inline_displays: return - if self.m_plugin_inline == self.INLINE_DISPLAY_ENABLED: - inwidth = self.p_width - self.p_width_in - self.p_width_out - 16 - inheight = self.p_height - canvas.theme.box_header_height - scaling = canvas.scene.getScaleFactor() * canvas.scene.getDevicePixelRatioF() + inwidth = self.p_width - self.p_width_in - self.p_width_out - 16 + inheight = self.p_height - canvas.theme.box_header_height - canvas.theme.box_header_spacing - canvas.theme.port_spacing - 3 + scaling = canvas.scene.getScaleFactor() * canvas.scene.getDevicePixelRatioF() + + if self.m_plugin_id >= 0 and self.m_plugin_id <= MAX_PLUGIN_ID_ALLOWED and ( + self.m_plugin_inline == self.INLINE_DISPLAY_ENABLED or self.m_inline_scaling != scaling): size = "%i:%i" % (int(inwidth*scaling), int(inheight*scaling)) data = canvas.callback(ACTION_INLINE_DISPLAY, self.m_plugin_id, 0, size) - self.m_inline_image = QImage(data['data'], data['width'], data['height'], data['stride'], QImage.Format_ARGB32) - #self.m_plugin_inline = self.INLINE_DISPLAY_CACHED + if data is None: + return + + # invalidate old image first + del self.m_inline_image + + self.m_inline_data = pack("%iB" % (data['height'] * data['stride']), *data['data']) + self.m_inline_image = QImage(voidptr(self.m_inline_data), data['width'], data['height'], data['stride'], QImage.Format_ARGB32) + self.m_inline_scaling = scaling + self.m_plugin_inline = self.INLINE_DISPLAY_CACHED + + if self.m_inline_image is None: + print("ERROR: inline display image is None for", self.m_plugin_id, self.m_group_name) + return srcx = self.p_width_in + 7 - srcy = int(canvas.theme.box_header_height - + (self.p_height - canvas.theme.box_header_height) / 2 - - data['height'] / 2 / scaling - 1) - painter.drawImage(QRectF(srcx, srcy, inwidth, inheight), self.m_inline_image) + srcy = int(canvas.theme.box_header_height + canvas.theme.box_header_spacing + 1 + + (inheight - self.m_inline_image.height() / scaling) / 2) + # FIXME vertical center inline displays + #+ (inheight - self.m_inline_image.height() / scaling) / 2) + painter.drawImage(QRectF(srcx, srcy, + self.m_inline_image.width() / scaling, + self.m_inline_image.height() / scaling), self.m_inline_image) # ------------------------------------------------------------------------------------------------------------ diff --git a/source/frontend/patchcanvas/patchcanvas.py b/source/frontend/patchcanvas/patchcanvas.py index b8b7ec1f9..b3bfd946f 100644 --- a/source/frontend/patchcanvas/patchcanvas.py +++ b/source/frontend/patchcanvas/patchcanvas.py @@ -915,10 +915,10 @@ def redrawPluginGroup(plugin_id): #qCritical("PatchCanvas::redrawPluginGroup(%i) - unable to find group" % plugin_id) return - group.widgets[0].update() + group.widgets[0].redrawInlineDisplay() if group.split and group.widgets[1]: - group.widgets[1].update() + group.widgets[1].redrawInlineDisplay() def handlePluginRemoved(plugin_id): if canvas.debug: @@ -930,14 +930,10 @@ def handlePluginRemoved(plugin_id): group.plugin_id = -1 group.plugin_ui = False group.plugin_inline = False - group.widgets[0].m_plugin_id = -1 - group.widgets[0].m_plugin_ui = False - group.widgets[0].m_plugin_inline = CanvasBox.INLINE_DISPLAY_DISABLED + group.widgets[0].removeAsPlugin() if group.split and group.widgets[1]: - group.widgets[1].m_plugin_id = -1 - group.widgets[1].m_plugin_ui = False - group.widgets[1].m_plugin_inline = CanvasBox.INLINE_DISPLAY_DISABLED + group.widgets[1].removeAsPlugin() for group in canvas.group_list: if group.plugin_id < plugin_id or group.plugin_id > MAX_PLUGIN_ID_ALLOWED: @@ -966,13 +962,9 @@ def handleAllPluginsRemoved(): group.plugin_id = -1 group.plugin_ui = False group.plugin_inline = False - group.widgets[0].m_plugin_id = -1 - group.widgets[0].m_plugin_ui = False - group.widgets[0].m_plugin_inline = CanvasBox.INLINE_DISPLAY_DISABLED + group.widgets[0].removeAsPlugin() if group.split and group.widgets[1]: - group.widgets[1].m_plugin_id = -1 - group.widgets[1].m_plugin_ui = False - group.widgets[1].m_plugin_inline = CanvasBox.INLINE_DISPLAY_DISABLED + group.widgets[1].removeAsPlugin() # ------------------------------------------------------------------------------------------------------------