Mercurial > hg > svgui
comparison layer/SpectrogramLayer.cpp @ 331:d2d2521a6c7e
* Some fixes to cache repainting strategy -- should make things a little
quicker, but some glitches remain
author | Chris Cannam |
---|---|
date | Mon, 19 Nov 2007 15:50:14 +0000 |
parents | 29fcf125f98b |
children | 0a74248af622 |
comparison
equal
deleted
inserted
replaced
328:b6df8b44b98d | 331:d2d2521a6c7e |
---|---|
899 void | 899 void |
900 SpectrogramLayer::setLayerDormant(const View *v, bool dormant) | 900 SpectrogramLayer::setLayerDormant(const View *v, bool dormant) |
901 { | 901 { |
902 if (dormant) { | 902 if (dormant) { |
903 | 903 |
904 #ifdef DEBUG_SPECTROGRAM_REPAINT | |
905 std::cerr << "SpectrogramLayer::setLayerDormant(" << dormant << ")" | |
906 << std::endl; | |
907 #endif | |
908 | |
904 if (isLayerDormant(v)) { | 909 if (isLayerDormant(v)) { |
905 return; | 910 return; |
906 } | 911 } |
907 | 912 |
908 Layer::setLayerDormant(v, true); | 913 Layer::setLayerDormant(v, true); |
1752 | 1757 |
1753 if (dx != 0 && | 1758 if (dx != 0 && |
1754 dx > -cache.pixmap.width() && | 1759 dx > -cache.pixmap.width() && |
1755 dx < cache.pixmap.width()) { | 1760 dx < cache.pixmap.width()) { |
1756 | 1761 |
1757 #if defined(Q_WS_WIN32) || defined(Q_WS_MAC) | 1762 QPixmap tmp = cache.pixmap; |
1758 // Copying a pixmap to itself doesn't work | 1763 QPainter cachePainter(&cache.pixmap); |
1759 // properly on Windows or Mac (it only works when | 1764 if (dx < 0) { |
1760 // moving in one direction). | 1765 cachePainter.drawPixmap |
1761 | 1766 (QRect(0, 0, |
1762 //!!! Need a utility function for this | 1767 cache.pixmap.width() + dx, |
1763 | 1768 cache.pixmap.height()), |
1764 static QPixmap *tmpPixmap = 0; | 1769 tmp, |
1765 if (!tmpPixmap || | 1770 QRect(-dx, 0, |
1766 tmpPixmap->width() != cache.pixmap.width() || | 1771 cache.pixmap.width() + dx, |
1767 tmpPixmap->height() != cache.pixmap.height()) { | 1772 cache.pixmap.height())); |
1768 delete tmpPixmap; | 1773 } else { |
1769 tmpPixmap = new QPixmap(cache.pixmap.width(), | 1774 cachePainter.drawPixmap |
1770 cache.pixmap.height()); | 1775 (QRect(dx, 0, |
1771 } | 1776 cache.pixmap.width() - dx, |
1772 QPainter cachePainter; | 1777 cache.pixmap.height()), |
1773 cachePainter.begin(tmpPixmap); | 1778 tmp, |
1774 cachePainter.drawPixmap(0, 0, cache.pixmap); | 1779 QRect(0, 0, |
1775 cachePainter.end(); | 1780 cache.pixmap.width() - dx, |
1776 cachePainter.begin(&cache.pixmap); | 1781 cache.pixmap.height())); |
1777 cachePainter.drawPixmap(dx, 0, *tmpPixmap); | 1782 } |
1778 cachePainter.end(); | |
1779 #else | |
1780 QPainter cachePainter(&cache.pixmap); | |
1781 cachePainter.drawPixmap(dx, 0, cache.pixmap); | |
1782 cachePainter.end(); | |
1783 #endif | |
1784 | 1783 |
1785 int px = cache.validArea.x(); | 1784 int px = cache.validArea.x(); |
1786 int pw = cache.validArea.width(); | 1785 int pw = cache.validArea.width(); |
1787 | 1786 |
1788 if (dx < 0) { | 1787 if (dx < 0) { |
1806 | 1805 |
1807 cache.validArea = | 1806 cache.validArea = |
1808 QRect(px, cache.validArea.y(), | 1807 QRect(px, cache.validArea.y(), |
1809 pw, cache.validArea.height()); | 1808 pw, cache.validArea.height()); |
1810 | 1809 |
1810 #ifdef DEBUG_SPECTROGRAM_REPAINT | |
1811 std::cerr << "valid area now " | |
1812 << px << "," << cache.validArea.y() | |
1813 << " " << pw << "x" << cache.validArea.height() | |
1814 << std::endl; | |
1815 #endif | |
1816 | |
1811 paint.drawPixmap(rect & cache.validArea, | 1817 paint.drawPixmap(rect & cache.validArea, |
1812 cache.pixmap, | 1818 cache.pixmap, |
1813 rect & cache.validArea); | 1819 rect & cache.validArea); |
1814 } | 1820 |
1821 } else if (dx != 0) { | |
1822 | |
1823 // we scrolled too far to be of use | |
1824 | |
1825 cache.validArea = QRect(); | |
1826 recreateWholePixmapCache = true; | |
1827 } | |
1815 } | 1828 } |
1816 } else { | 1829 } else { |
1817 #ifdef DEBUG_SPECTROGRAM_REPAINT | 1830 #ifdef DEBUG_SPECTROGRAM_REPAINT |
1818 std::cerr << "SpectrogramLayer: pixmap cache useless" << std::endl; | 1831 std::cerr << "SpectrogramLayer: pixmap cache useless" << std::endl; |
1819 if (int(cache.zoomLevel) != zoomLevel) { | 1832 if (int(cache.zoomLevel) != zoomLevel) { |
1835 | 1848 |
1836 if (updateViewMagnitudes(v)) { | 1849 if (updateViewMagnitudes(v)) { |
1837 #ifdef DEBUG_SPECTROGRAM_REPAINT | 1850 #ifdef DEBUG_SPECTROGRAM_REPAINT |
1838 std::cerr << "SpectrogramLayer: magnitude range changed to [" << m_viewMags[v].getMin() << "->" << m_viewMags[v].getMax() << "]" << std::endl; | 1851 std::cerr << "SpectrogramLayer: magnitude range changed to [" << m_viewMags[v].getMin() << "->" << m_viewMags[v].getMax() << "]" << std::endl; |
1839 #endif | 1852 #endif |
1840 recreateWholePixmapCache = true; | 1853 if (m_normalizeVisibleArea) { |
1854 cache.validArea = QRect(); | |
1855 recreateWholePixmapCache = true; | |
1856 } | |
1841 } else { | 1857 } else { |
1842 #ifdef DEBUG_SPECTROGRAM_REPAINT | 1858 #ifdef DEBUG_SPECTROGRAM_REPAINT |
1843 std::cerr << "No change in magnitude range [" << m_viewMags[v].getMin() << "->" << m_viewMags[v].getMax() << "]" << std::endl; | 1859 std::cerr << "No change in magnitude range [" << m_viewMags[v].getMin() << "->" << m_viewMags[v].getMax() << "]" << std::endl; |
1844 #endif | 1860 #endif |
1845 } | 1861 } |
1885 | 1901 |
1886 int h = v->height(); | 1902 int h = v->height(); |
1887 | 1903 |
1888 if (cache.validArea.width() > 0) { | 1904 if (cache.validArea.width() > 0) { |
1889 | 1905 |
1906 // If part of the cache is known to be valid, select a strip | |
1907 // immediately to left or right of the valid part | |
1908 | |
1890 int vx0 = 0, vx1 = 0; | 1909 int vx0 = 0, vx1 = 0; |
1891 vx0 = cache.validArea.x(); | 1910 vx0 = cache.validArea.x(); |
1892 vx1 = cache.validArea.x() + cache.validArea.width(); | 1911 vx1 = cache.validArea.x() + cache.validArea.width(); |
1893 | 1912 |
1894 #ifdef DEBUG_SPECTROGRAM_REPAINT | 1913 #ifdef DEBUG_SPECTROGRAM_REPAINT |
1895 std::cerr << "x0 " << x0 << ", x1 " << x1 << ", vx0 " << vx0 << ", vx1 " << vx1 << ", paintBlockWidth " << paintBlockWidth << std::endl; | 1914 std::cerr << "x0 " << x0 << ", x1 " << x1 << ", vx0 " << vx0 << ", vx1 " << vx1 << ", paintBlockWidth " << paintBlockWidth << std::endl; |
1896 #endif | 1915 #endif |
1897 if (x0 < vx0) { | 1916 if (x0 < vx0) { |
1898 if (x0 + paintBlockWidth < vx0) { | 1917 if (x0 + paintBlockWidth < vx0) { |
1899 x0 = vx0 - paintBlockWidth; | 1918 x0 = vx0 - paintBlockWidth; |
1919 } | |
1920 x1 = vx0; | |
1921 } else if (x0 >= vx1) { | |
1922 x0 = vx1; | |
1923 if (x1 > x0 + paintBlockWidth) { | |
1924 x1 = x0 + paintBlockWidth; | |
1925 } | |
1926 } else { | |
1927 // x0 is within the valid area | |
1928 if (x1 > vx1) { | |
1929 x0 = vx1; | |
1930 if (x0 + paintBlockWidth < x1) { | |
1931 x1 = x0 + paintBlockWidth; | |
1932 } | |
1900 } else { | 1933 } else { |
1901 x0 = 0; | 1934 x1 = x0; // it's all valid, paint nothing |
1902 } | |
1903 } else if (x0 > vx1) { | |
1904 x0 = vx1; | |
1905 } | |
1906 | |
1907 if (x1 < vx0) { | |
1908 x1 = vx0; | |
1909 } else if (x1 > vx1) { | |
1910 if (vx1 + paintBlockWidth < x1) { | |
1911 x1 = vx1 + paintBlockWidth; | |
1912 } else { | |
1913 x1 = v->width(); | |
1914 } | 1935 } |
1915 } | 1936 } |
1916 | 1937 |
1917 cache.validArea = QRect | 1938 cache.validArea = QRect |
1918 (std::min(vx0, x0), cache.validArea.y(), | 1939 (std::min(vx0, x0), cache.validArea.y(), |
1919 std::max(vx1 - std::min(vx0, x0), | 1940 std::max(vx1 - std::min(vx0, x0), |
1920 x1 - std::min(vx0, x0)), | 1941 x1 - std::min(vx0, x0)), |
1921 cache.validArea.height()); | 1942 cache.validArea.height()); |
2027 std::cerr << ((float(v->getFrameForX(1) - v->getFrameForX(0))) / increment) << " bin(s) per pixel" << std::endl; | 2048 std::cerr << ((float(v->getFrameForX(1) - v->getFrameForX(0))) / increment) << " bin(s) per pixel" << std::endl; |
2028 #endif | 2049 #endif |
2029 | 2050 |
2030 bool runOutOfData = false; | 2051 bool runOutOfData = false; |
2031 | 2052 |
2053 if (w == 0) { | |
2054 std::cerr << "*** NOTE: w == 0" << std::endl; | |
2055 } | |
2056 | |
2057 #ifdef DEBUG_SPECTROGRAM_REPAINT | |
2058 size_t pixels = 0; | |
2059 #endif | |
2060 | |
2032 for (int x = 0; x < w; ++x) { | 2061 for (int x = 0; x < w; ++x) { |
2033 | 2062 |
2034 if (runOutOfData) break; | 2063 if (runOutOfData) { |
2064 #ifdef DEBUG_SPECTROGRAM_REPAINT | |
2065 std::cerr << "Run out of data -- dropping out of loop" << std::endl; | |
2066 #endif | |
2067 break; | |
2068 } | |
2035 | 2069 |
2036 for (int y = 0; y < h; ++y) { | 2070 for (int y = 0; y < h; ++y) { |
2037 ymag[y] = 0.f; | 2071 ymag[y] = 0.f; |
2038 ydiv[y] = 0.f; | 2072 ydiv[y] = 0.f; |
2039 } | 2073 } |
2048 int s0i = int(s0 + 0.001); | 2082 int s0i = int(s0 + 0.001); |
2049 int s1i = int(s1); | 2083 int s1i = int(s1); |
2050 | 2084 |
2051 if (s1i >= int(fft->getWidth())) { | 2085 if (s1i >= int(fft->getWidth())) { |
2052 if (s0i >= int(fft->getWidth())) { | 2086 if (s0i >= int(fft->getWidth())) { |
2087 #ifdef DEBUG_SPECTROGRAM_REPAINT | |
2088 std::cerr << "Column " << s0i << " out of range" << std::endl; | |
2089 #endif | |
2053 continue; | 2090 continue; |
2054 } else { | 2091 } else { |
2055 s1i = s0i; | 2092 s1i = s0i; |
2056 } | 2093 } |
2057 } | 2094 } |
2216 | 2253 |
2217 assert(x <= m_drawBuffer.width()); | 2254 assert(x <= m_drawBuffer.width()); |
2218 QColor c = m_palette.getColour(pixel); | 2255 QColor c = m_palette.getColour(pixel); |
2219 m_drawBuffer.setPixel(x, y, | 2256 m_drawBuffer.setPixel(x, y, |
2220 qRgb(c.red(), c.green(), c.blue())); | 2257 qRgb(c.red(), c.green(), c.blue())); |
2258 #ifdef DEBUG_SPECTROGRAM_REPAINT | |
2259 ++pixels; | |
2260 #endif | |
2221 } | 2261 } |
2222 } | 2262 } |
2223 } | 2263 } |
2224 | 2264 |
2265 #ifdef DEBUG_SPECTROGRAM_REPAINT | |
2266 std::cerr << pixels << " pixels drawn" << std::endl; | |
2267 #endif | |
2268 | |
2225 if (overallMagChanged) { | 2269 if (overallMagChanged) { |
2226 m_viewMags[v] = overallMag; | 2270 m_viewMags[v] = overallMag; |
2227 #ifdef DEBUG_SPECTROGRAM_REPAINT | 2271 #ifdef DEBUG_SPECTROGRAM_REPAINT |
2228 std::cerr << "Overall mag is now [" << m_viewMags[v].getMin() << "->" << m_viewMags[v].getMax() << "] - will be updating" << std::endl; | 2272 std::cerr << "Overall mag is now [" << m_viewMags[v].getMin() << "->" << m_viewMags[v].getMax() << "] - will be updating" << std::endl; |
2229 #endif | 2273 #endif |
2233 #endif | 2277 #endif |
2234 } | 2278 } |
2235 | 2279 |
2236 Profiler profiler2("SpectrogramLayer::paint: draw image", true); | 2280 Profiler profiler2("SpectrogramLayer::paint: draw image", true); |
2237 | 2281 |
2238 #ifdef DEBUG_SPECTROGRAM_REPAINT | 2282 if (w > 0) { |
2239 std::cerr << "Painting " << w << "x" << rect.height() | 2283 #ifdef DEBUG_SPECTROGRAM_REPAINT |
2240 << " from draw buffer at " << 0 << "," << rect.y() | 2284 std::cerr << "Painting " << w << "x" << rect.height() |
2241 << " to window at " << x0 << "," << rect.y() << std::endl; | 2285 << " from draw buffer at " << 0 << "," << rect.y() |
2242 #endif | 2286 << " to window at " << x0 << "," << rect.y() << std::endl; |
2243 | 2287 #endif |
2244 paint.drawImage(x0, rect.y(), m_drawBuffer, 0, rect.y(), w, rect.height()); | 2288 |
2289 paint.drawImage(x0, rect.y(), m_drawBuffer, | |
2290 0, rect.y(), w, rect.height()); | |
2291 } | |
2245 | 2292 |
2246 if (recreateWholePixmapCache) { | 2293 if (recreateWholePixmapCache) { |
2294 std::cerr << "Recreating pixmap cache: width = " << v->width() | |
2295 << ", height = " << h << std::endl; | |
2247 cache.pixmap = QPixmap(v->width(), h); | 2296 cache.pixmap = QPixmap(v->width(), h); |
2248 } | 2297 } |
2249 | 2298 |
2250 #ifdef DEBUG_SPECTROGRAM_REPAINT | 2299 if (w > 0) { |
2251 std::cerr << "Painting " << w << "x" << h | 2300 #ifdef DEBUG_SPECTROGRAM_REPAINT |
2252 << " from draw buffer at " << 0 << "," << 0 | 2301 std::cerr << "Painting " << w << "x" << h |
2253 << " to cache at " << x0 << "," << 0 << std::endl; | 2302 << " from draw buffer at " << 0 << "," << 0 |
2254 #endif | 2303 << " to cache at " << x0 << "," << 0 << std::endl; |
2255 | 2304 #endif |
2256 QPainter cachePainter(&cache.pixmap); | 2305 |
2257 cachePainter.drawImage(x0, 0, m_drawBuffer, 0, 0, w, h); | 2306 QPainter cachePainter(&cache.pixmap); |
2258 cachePainter.end(); | 2307 cachePainter.drawImage(x0, 0, m_drawBuffer, 0, 0, w, h); |
2308 cachePainter.end(); | |
2309 } | |
2310 | |
2311 cache.startFrame = startFrame; | |
2312 cache.zoomLevel = zoomLevel; | |
2259 | 2313 |
2260 if (!m_normalizeVisibleArea || !overallMagChanged) { | 2314 if (!m_normalizeVisibleArea || !overallMagChanged) { |
2261 | 2315 |
2262 cache.startFrame = startFrame; | |
2263 cache.zoomLevel = zoomLevel; | |
2264 | |
2265 if (cache.validArea.x() > 0) { | 2316 if (cache.validArea.x() > 0) { |
2266 #ifdef DEBUG_SPECTROGRAM_REPAINT | 2317 #ifdef DEBUG_SPECTROGRAM_REPAINT |
2267 std::cerr << "SpectrogramLayer::paint() updating left (0, " | 2318 std::cerr << "SpectrogramLayer::paint() updating left (0, " |
2268 << cache.validArea.x() << ")" << std::endl; | 2319 << cache.validArea.x() << ")" << std::endl; |
2269 #endif | 2320 #endif |
2286 cache.validArea.width()), | 2337 cache.validArea.width()), |
2287 h); | 2338 h); |
2288 } | 2339 } |
2289 } else { | 2340 } else { |
2290 // overallMagChanged | 2341 // overallMagChanged |
2342 std::cerr << "\noverallMagChanged - updating all\n" << std::endl; | |
2291 cache.validArea = QRect(); | 2343 cache.validArea = QRect(); |
2292 v->update(); | 2344 v->update(); |
2293 } | 2345 } |
2294 | 2346 |
2295 illuminateLocalFeatures(v, paint); | 2347 illuminateLocalFeatures(v, paint); |