ActionRetCodeEnum ViewerDisplayScheduler::createFrameRenderResultsGeneric(const ViewerNodePtr& viewer, const TreeRenderQueueProviderPtr& provider, TimeValue time, bool isPlayback, const RotoStrokeItemPtr& activeDrawingStroke, const std::vector<ViewIdx>& viewsToRender, bool enableRenderStats, RenderFrameResultsContainerPtr* future) { // A global statistics object for this frame render if requested RenderStatsPtr stats; if (enableRenderStats) { stats.reset( new RenderStats(enableRenderStats) ); } // Get parameters from the viewport bool fullFrameProcessing = viewer->isFullFrameProcessingEnabled(); bool draftModeEnabled = viewer->getApp()->isDraftRenderEnabled(); unsigned int mipMapLevel = getViewerMipMapLevel(viewer, draftModeEnabled, fullFrameProcessing); bool byPassCache = viewer->isRenderWithoutCacheEnabledAndTurnOff(); ViewerCompositingOperatorEnum viewerBlend = viewer->getCurrentOperator(); bool viewerBEqualsViewerA = viewer->getCurrentAInput() == viewer->getCurrentBInput(); // Create the global results object ViewerRenderFrameResultsContainerPtr results(new ViewerRenderFrameResultsContainer(provider)); *future = results; results->time = time; results->recenterViewer = viewer->getViewerCenterPoint(&results->viewerCenter); std::list<RectD> rois; if (!viewer->isDoingPartialUpdates()) { rois.push_back(RectD()); } else { // If the viewer is doing partial updates (i.e: during tracking we only update the markers areas) // Then we launch multiple renders over the partial areas std::list<RectD> partialUpdates = viewer->getPartialUpdateRects(); for (std::list<RectD>::const_iterator it = partialUpdates.begin(); it != partialUpdates.end(); ++it) { if (!it->isNull()) { rois.push_back(*it); } } } for (std::list<RectD>::const_iterator it = rois.begin(); it != rois.end(); ++it) { // Render all requested views for (std::size_t view_i = 0; view_i < viewsToRender.size(); ++view_i) { ActionRetCodeEnum stat = createFrameRenderResultsForView(viewer, provider, results, viewsToRender[view_i], stats, isPlayback, it->isNull() ? 0 : &(*it), mipMapLevel, viewerBlend, byPassCache, draftModeEnabled, fullFrameProcessing, viewerBEqualsViewerA, activeDrawingStroke); if (isFailureRetCode(stat)) { return stat; } } // for each view } return eActionStatusOK; } // createFrameRenderResultsGeneric
static ActionRetCodeEnum createFrameRenderResultsForView(const ViewerNodePtr& viewer, const TreeRenderQueueProviderPtr& provider, const ViewerRenderFrameResultsContainerPtr& results, ViewIdx view, const RenderStatsPtr& stats, bool isPlayback, const RectD* partialUpdateRoIParam, unsigned int mipMapLevel, ViewerCompositingOperatorEnum viewerBlend, bool byPassCache, bool draftModeEnabled, bool fullFrameProcessing, bool viewerBEqualsViewerA, const RotoStrokeItemPtr& activeDrawingStroke) { // Initialize for each view a sub-result. // Each view has 2 renders: the A and B viewerprocess ViewerRenderFrameSubResultPtr subResult(new ViewerRenderFrameSubResult); results->frames.push_back(subResult); subResult->view = view; subResult->stats = stats; if (partialUpdateRoIParam) { subResult->textureTransferType = OpenGLViewerI::TextureTransferArgs::eTextureTransferTypeOverlay; } else if (activeDrawingStroke && activeDrawingStroke->getRenderCloneCurrentStrokeStartPointIndex() > 0) { // Upon painting ticks, we just have to update the viewer for the area that was painted subResult->textureTransferType = OpenGLViewerI::TextureTransferArgs::eTextureTransferTypeModify; } else { subResult->textureTransferType = OpenGLViewerI::TextureTransferArgs::eTextureTransferTypeReplace; } for (int viewerInputIndex = 0; viewerInputIndex < 2; ++viewerInputIndex) { subResult->perInputsData[viewerInputIndex].retCode = eActionStatusFailed; if (viewerInputIndex == 1 && (viewerBEqualsViewerA || viewerBlend == eViewerCompositingOperatorNone)) { if (viewerBEqualsViewerA && viewerBlend != eViewerCompositingOperatorNone) { subResult->copyInputBFromA = true; } continue; } if (viewer->isViewerPaused(viewerInputIndex)) { subResult->perInputsData[viewerInputIndex].retCode = eActionStatusAborted; continue; } ViewerInstancePtr viewerProcess = viewer->getViewerProcessNode(viewerInputIndex); subResult->perInputsData[viewerInputIndex].viewerProcessNode = viewerProcess->getNode(); TreeRender::CtorArgsPtr initArgs(new TreeRender::CtorArgs); initArgs->treeRootEffect = viewerProcess; initArgs->provider = provider; initArgs->time = results->time; initArgs->view = subResult->view; // Render by default on disk is always using a mipmap level of 0 but using the proxy scale of the project initArgs->mipMapLevel = mipMapLevel; #pragma message WARN("Todo: set proxy scale here") initArgs->proxyScale = RenderScale(1.); // Render the RoD if fullframe processing if (partialUpdateRoIParam) { initArgs->canonicalRoI = *partialUpdateRoIParam; } else { RectD roi; if (!fullFrameProcessing) { roi = viewerProcess->getViewerRoI(); } initArgs->canonicalRoI = roi; } initArgs->stats = stats; initArgs->activeRotoDrawableItem = activeDrawingStroke; initArgs->draftMode = draftModeEnabled; initArgs->playback = isPlayback; initArgs->byPassCache = byPassCache; initArgs->preventConcurrentTreeRenders = (activeDrawingStroke || partialUpdateRoIParam); if (!isPlayback && subResult->textureTransferType == OpenGLViewerI::TextureTransferArgs::eTextureTransferTypeReplace && !activeDrawingStroke) { subResult->perInputsData[viewerInputIndex].colorPickerNode = viewerInputIndex == 0 ? viewer->getCurrentAInput() : viewer->getCurrentBInput(); if (subResult->perInputsData[viewerInputIndex].colorPickerNode) { // Also sample the "main" input of the color picker node, this is useful for keyers. int mainInput = subResult->perInputsData[viewerInputIndex].colorPickerNode->getPreferredInput(); subResult->perInputsData[viewerInputIndex].colorPickerInputNode = subResult->perInputsData[viewerInputIndex].colorPickerNode->getInput(mainInput); } } if (subResult->perInputsData[viewerInputIndex].colorPickerNode) { initArgs->extraNodesToSample.push_back(subResult->perInputsData[viewerInputIndex].colorPickerNode); } if (subResult->perInputsData[viewerInputIndex].colorPickerInputImage) { initArgs->extraNodesToSample.push_back(subResult->perInputsData[viewerInputIndex].colorPickerInputNode); } subResult->perInputsData[viewerInputIndex].render = TreeRender::create(initArgs); if (!subResult->perInputsData[viewerInputIndex].render) { return eActionStatusFailed; } } // for each viewer input return eActionStatusOK; } // createFrameRenderResultsForView