comparison view/View.cpp @ 1490:c83504eb2649

Attempt a mechanism for the View to time-align a layer on display using an aligning version of the ViewProxy
author Chris Cannam
date Fri, 02 Aug 2019 16:44:32 +0100
parents c3cc36c014b8
children a2fbcfeb2572
comparison
equal deleted inserted replaced
1489:b402121d8f5f 1490:c83504eb2649
69 m_cacheCentreFrame(0), 69 m_cacheCentreFrame(0),
70 m_cacheZoomLevel(ZoomLevel::FramesPerPixel, 1024), 70 m_cacheZoomLevel(ZoomLevel::FramesPerPixel, 1024),
71 m_selectionCached(false), 71 m_selectionCached(false),
72 m_deleting(false), 72 m_deleting(false),
73 m_haveSelectedLayer(false), 73 m_haveSelectedLayer(false),
74 m_useAligningProxy(false),
74 m_manager(nullptr), 75 m_manager(nullptr),
75 m_propertyContainer(new ViewPropertyContainer(this)) 76 m_propertyContainer(new ViewPropertyContainer(this))
76 { 77 {
77 // cerr << "View::View(" << this << ")" << endl; 78 // cerr << "View::View(" << this << ")" << endl;
78 } 79 }
1347 } 1348 }
1348 1349
1349 ModelId 1350 ModelId
1350 View::getAligningModel() const 1351 View::getAligningModel() const
1351 { 1352 {
1353 ModelId aligning, reference;
1354 getAligningAndReferenceModels(aligning, reference);
1355 return aligning;
1356 }
1357
1358 void
1359 View::getAligningAndReferenceModels(ModelId &aligning,
1360 ModelId &reference) const
1361 {
1352 if (!m_manager || 1362 if (!m_manager ||
1353 !m_manager->getAlignMode() || 1363 !m_manager->getAlignMode() ||
1354 m_manager->getPlaybackModel().isNone()) { 1364 m_manager->getPlaybackModel().isNone()) {
1355 return {}; 1365 return;
1356 } 1366 }
1357 1367
1358 ModelId anyModel; 1368 ModelId anyModel;
1359 ModelId alignedModel;
1360 ModelId goodModel;
1361 1369
1362 for (auto layer: m_layerStack) { 1370 for (auto layer: m_layerStack) {
1363 1371
1364 if (!layer) continue; 1372 if (!layer) continue;
1365 if (dynamic_cast<TimeRulerLayer *>(layer)) continue; 1373 if (dynamic_cast<TimeRulerLayer *>(layer)) continue;
1369 if (!model) continue; 1377 if (!model) continue;
1370 1378
1371 anyModel = thisId; 1379 anyModel = thisId;
1372 1380
1373 if (!model->getAlignmentReference().isNone()) { 1381 if (!model->getAlignmentReference().isNone()) {
1374 alignedModel = thisId; 1382
1375 if (layer->isLayerOpaque() || 1383 if (layer->isLayerOpaque() ||
1376 std::dynamic_pointer_cast 1384 std::dynamic_pointer_cast
1377 <RangeSummarisableTimeValueModel>(model)) { 1385 <RangeSummarisableTimeValueModel>(model)) {
1378 goodModel = thisId; 1386
1379 } 1387 aligning = thisId;
1380 } 1388 reference = model->getAlignmentReference();
1381 } 1389 return;
1382 1390
1383 if (!goodModel.isNone()) return goodModel; 1391 } else if (aligning.isNone()) {
1384 else if (!alignedModel.isNone()) return alignedModel; 1392
1385 else return anyModel; 1393 aligning = thisId;
1394 reference = model->getAlignmentReference();
1395 }
1396 }
1397 }
1398
1399 if (aligning.isNone()) {
1400 aligning = anyModel;
1401 reference = {};
1402 }
1386 } 1403 }
1387 1404
1388 sv_frame_t 1405 sv_frame_t
1389 View::alignFromReference(sv_frame_t f) const 1406 View::alignFromReference(sv_frame_t f) const
1390 { 1407 {
2130 // shouldUseCache is also false, then the scrollables can't 2147 // shouldUseCache is also false, then the scrollables can't
2131 // appear because they will only be on the cache 2148 // appear because they will only be on the cache
2132 throw std::logic_error("ERROR: shouldRepaintCache is true, but shouldUseCache is false: this can't lead to the correct result"); 2149 throw std::logic_error("ERROR: shouldRepaintCache is true, but shouldUseCache is false: this can't lead to the correct result");
2133 } 2150 }
2134 2151
2152 // Create the ViewProxy for geometry provision, using the
2153 // device-pixel ratio for pixel-doubled hi-dpi rendering as
2154 // appropriate.
2155
2156 ViewProxy proxy(this, dpratio);
2157
2158 // Some layers may need an aligning proxy. If a layer's model has
2159 // a source model that is the reference model for the aligning
2160 // model, and the layer is tagged as to be aligned, then we use an
2161 // aligning proxy.
2162
2163 ModelId alignmentModelId;
2164 ModelId alignmentReferenceId;
2165 auto aligningModel = ModelById::get(getAligningModel());
2166 if (aligningModel) {
2167 alignmentModelId = aligningModel->getAlignment();
2168 alignmentReferenceId = aligningModel->getAlignmentReference();
2169 SVCERR << "alignmentModelId = " << alignmentModelId << " (reference = " << alignmentReferenceId << ")" << endl;
2170 } else {
2171 SVCERR << "no aligningModel" << endl;
2172 }
2173 ViewProxy aligningProxy(this, dpratio, alignmentModelId);
2174
2135 // Scrollable (cacheable) items first. If we are repainting the 2175 // Scrollable (cacheable) items first. If we are repainting the
2136 // cache, then we paint these to the cache; otherwise straight to 2176 // cache, then we paint these to the cache; otherwise straight to
2137 // the buffer. 2177 // the buffer.
2138
2139 ViewProxy proxy(this, dpratio);
2140 QRect areaToPaint; 2178 QRect areaToPaint;
2141 QPainter paint; 2179 QPainter paint;
2142 2180
2143 if (shouldRepaintCache) { 2181 if (shouldRepaintCache) {
2144 paint.begin(m_cache); 2182 paint.begin(m_cache);
2162 i != scrollables.end(); ++i) { 2200 i != scrollables.end(); ++i) {
2163 2201
2164 paint.setRenderHint(QPainter::Antialiasing, false); 2202 paint.setRenderHint(QPainter::Antialiasing, false);
2165 paint.save(); 2203 paint.save();
2166 2204
2205 Layer *layer = *i;
2206
2207 bool useAligningProxy = false;
2208 if (m_useAligningProxy) {
2209 if (layer->getModel() == alignmentReferenceId ||
2210 layer->getSourceModel() == alignmentReferenceId) {
2211 useAligningProxy = true;
2212 }
2213 }
2214
2167 #ifdef DEBUG_VIEW_WIDGET_PAINT 2215 #ifdef DEBUG_VIEW_WIDGET_PAINT
2168 cerr << "Painting scrollable layer " << *i << " using proxy with shouldRepaintCache = " << shouldRepaintCache << ", dpratio = " << dpratio << ", areaToPaint = " << areaToPaint.x() << "," << areaToPaint.y() << " " << areaToPaint.width() << "x" << areaToPaint.height() << endl; 2216 cerr << "Painting scrollable layer " << layer << " (model " << layer->getModel() << ", source model " << layer->getSourceModel() << ") with shouldRepaintCache = " << shouldRepaintCache << ", useAligningProxy = " << useAligningProxy << ", dpratio = " << dpratio << ", areaToPaint = " << areaToPaint.x() << "," << areaToPaint.y() << " " << areaToPaint.width() << "x" << areaToPaint.height() << endl;
2169 #endif 2217 #endif
2170 2218
2171 (*i)->paint(&proxy, paint, areaToPaint); 2219 layer->paint(useAligningProxy ? &aligningProxy : &proxy,
2220 paint, areaToPaint);
2172 2221
2173 paint.restore(); 2222 paint.restore();
2174 } 2223 }
2175 2224
2176 paint.end(); 2225 paint.end();
2202 paint.setPen(getForeground()); 2251 paint.setPen(getForeground());
2203 paint.setBrush(Qt::NoBrush); 2252 paint.setBrush(Qt::NoBrush);
2204 2253
2205 for (LayerList::iterator i = nonScrollables.begin(); 2254 for (LayerList::iterator i = nonScrollables.begin();
2206 i != nonScrollables.end(); ++i) { 2255 i != nonScrollables.end(); ++i) {
2207 2256
2208 // Profiler profiler2("View::paintEvent non-cacheable"); 2257 Layer *layer = *i;
2258
2259 bool useAligningProxy = false;
2260 if (m_useAligningProxy) {
2261 if (layer->getModel() == alignmentReferenceId ||
2262 layer->getSourceModel() == alignmentReferenceId) {
2263 useAligningProxy = true;
2264 }
2265 }
2266
2209 #ifdef DEBUG_VIEW_WIDGET_PAINT 2267 #ifdef DEBUG_VIEW_WIDGET_PAINT
2210 cerr << "Painting non-scrollable layer " << *i << " without proxy with shouldRepaintCache = " << shouldRepaintCache << ", dpratio = " << dpratio << ", requestedPaintArea = " << requestedPaintArea.x() << "," << requestedPaintArea.y() << " " << requestedPaintArea.width() << "x" << requestedPaintArea.height() << endl; 2268 cerr << "Painting non-scrollable layer " << layer << " (model " << layer->getModel() << ", source model " << layer->getSourceModel() << ") with shouldRepaintCache = " << shouldRepaintCache << ", useAligningProxy = " << useAligningProxy << ", dpratio = " << dpratio << ", requestedPaintArea = " << requestedPaintArea.x() << "," << requestedPaintArea.y() << " " << requestedPaintArea.width() << "x" << requestedPaintArea.height() << endl;
2211 #endif 2269 #endif
2212 (*i)->paint(&proxy, paint, requestedPaintArea); 2270
2271 layer->paint(useAligningProxy ? &aligningProxy : &proxy,
2272 paint, requestedPaintArea);
2213 } 2273 }
2214 2274
2215 paint.end(); 2275 paint.end();
2216 2276
2217 // Now paint to widget from buffer: target rects from here on, 2277 // Now paint to widget from buffer: target rects from here on,