int FrameViewRequest::markDependencyAsRendered(const TreeRenderExecutionDataPtr& request, const FrameViewRequestPtr& deps) { FrameViewRequestStatusEnum status = getStatus(); QMutexLocker k(&_imp->lock); PerLaunchRequestData& data = _imp->requestData[request]; // If this FrameViewRequest is pass-through, copy results from the pass-through dependency if (status == eFrameViewRequestStatusPassThrough) { assert(deps && data.dependencies.size() == 1 && *data.dependencies.begin() == deps); _imp->requestedScaleImage = deps->getRequestedScaleImagePlane(); _imp->fullScaleImage = _imp->requestedScaleImage; _imp->finalRoi = deps->getCurrentRoI(); } std::set<FrameViewRequestPtr>::iterator foundDep = data.dependencies.find(deps); if (foundDep != data.dependencies.end()) { // The dependency might not exist if we did not call addDependency. // This may happen if we were aborted data.dependencies.erase(foundDep); data.renderedDependencies.insert(deps); } return data.dependencies.size(); }
std::pair<ImagePtr, RectD> TrackMarker::getMarkerImage(TimeValue time, const RectD& roi) const { assert( !roi.isNull() ); NodePtr node = getModel()->getNode(); NodePtr input = node->getInput(0); if (!input) { return std::make_pair(ImagePtr(), roi); } TreeRender::CtorArgsPtr args(new TreeRender::CtorArgs); { args->treeRootEffect = input->getEffectInstance(); args->time = time; args->view = ViewIdx(0); // Render default plane args->plane = 0; args->mipMapLevel = 0; args->proxyScale = RenderScale(1.); args->canonicalRoI = &roi; args->draftMode = false; args->playback = false; args->byPassCache = false; } TreeRenderPtr render = TreeRender::create(args); FrameViewRequestPtr outputRequest; ActionRetCodeEnum stat = render->launchRender(&outputRequest); if (isFailureRetCode(stat)) { return std::make_pair(ImagePtr(), roi); } ImagePtr sourceImage = outputRequest->getRequestedScaleImagePlane(); // Make sure the Natron image rendered is RGBA full rect and on CPU, we don't support other formats if (sourceImage->getStorageMode() != eStorageModeRAM) { Image::InitStorageArgs initArgs; initArgs.bounds = sourceImage->getBounds(); initArgs.plane = sourceImage->getLayer(); initArgs.bufferFormat = eImageBufferLayoutRGBAPackedFullRect; initArgs.storage = eStorageModeRAM; initArgs.bitdepth = sourceImage->getBitDepth(); ImagePtr tmpImage = Image::create(initArgs); if (!tmpImage) { return std::make_pair(ImagePtr(), roi); } Image::CopyPixelsArgs cpyArgs; cpyArgs.roi = initArgs.bounds; tmpImage->copyPixels(*sourceImage, cpyArgs); sourceImage = tmpImage; } return std::make_pair(sourceImage, roi); } // TrackMarker::getMarkerImage
void ViewerRenderFrameSubResult::onTreeRenderFinished(int inputIndex) { PerViewerInputRenderData& inputData = perInputsData[inputIndex]; if (inputIndex == 1 && copyInputBFromA) { inputData = perInputsData[0]; return; } FrameViewRequestPtr outputRequest; if (inputData.render) { inputData.retCode = inputData.render->getStatus(); outputRequest = inputData.render->getOutputRequest(); } if (outputRequest) { inputData.viewerProcessImage = outputRequest->getRequestedScaleImagePlane(); } // There might be no output image if the RoI that was passed to render is outside of the RoD of the effect if (isFailureRetCode(inputData.retCode) || !inputData.viewerProcessImage) { inputData.viewerProcessImage.reset(); inputData.render.reset(); return; } // Find the key of the image and store it so that in the gui // we can later on re-use this key to check the cache for the timeline's cache line ImageCacheEntryPtr cacheEntry = inputData.viewerProcessImage->getCacheEntry(); if (cacheEntry) { inputData.viewerProcessImageKey = cacheEntry->getCacheKey(); } // Convert the image to a format that can be uploaded to a OpenGL texture RectI imageConvertRoI; RectD ctorCanonicalRoI = inputData.render->getCtorRoI(); if (inputData.render && !ctorCanonicalRoI.isNull()) { RenderScale scale = EffectInstance::getCombinedScale(inputData.viewerProcessImage->getMipMapLevel(), inputData.viewerProcessImage->getProxyScale()); double par = inputData.viewerProcessNode->getEffectInstance()->getAspectRatio(-1); ctorCanonicalRoI.toPixelEnclosing(scale, par, &imageConvertRoI); } else { imageConvertRoI = inputData.viewerProcessImage->getBounds(); } // If we are drawing with the RotoPaint node, only update the texture portion if (textureTransferType == OpenGLViewerI::TextureTransferArgs::eTextureTransferTypeModify) { RectI strokeArea; bool strokeAreaSet = inputData.render->getRotoPaintActiveStrokeUpdateArea(&strokeArea); if (strokeAreaSet) { imageConvertRoI = strokeArea; } } // The viewer-process node may not have rendered a 4 channel image, but this is required but the OpenGL viewer // which only draws RGBA images. // If we are in accumulation, force a copy of the image because another render thread might modify it in a future render whilst it may // still be read from the main-thread when updating the ViewerGL texture. // If texture transfer is eTextureTransferTypeOverlay, we want to upload the texture to exactly what was requested const bool forceOutputImageCopy = (inputData.viewerProcessImage == inputData.viewerProcessNode->getEffectInstance()->getAccumBuffer(inputData.viewerProcessImage->getLayer()) || (textureTransferType == OpenGLViewerI::TextureTransferArgs::eTextureTransferTypeOverlay && inputData.viewerProcessImage->getBounds() != imageConvertRoI)); inputData.viewerProcessImage = convertImageForViewerDisplay(imageConvertRoI, forceOutputImageCopy, true /*the texture must have 4 channels*/, inputData.viewerProcessImage); // Extra color-picker images as-well. if (inputData.colorPickerNode) { { FrameViewRequestPtr req = inputData.render->getExtraRequestedResultsForNode(inputData.colorPickerNode); if (req) { inputData.colorPickerImage = req->getRequestedScaleImagePlane(); if (inputData.colorPickerImage) { inputData.colorPickerImage = convertImageForViewerDisplay(inputData.colorPickerImage->getBounds(), false, false /*the picker can accept non 4-channel image*/, inputData.colorPickerImage); } } } if (inputData.colorPickerInputNode) { FrameViewRequestPtr req = inputData.render->getExtraRequestedResultsForNode(inputData.colorPickerInputNode); if (req) { inputData.colorPickerInputImage = req->getRequestedScaleImagePlane(); if (inputData.colorPickerInputImage) { inputData.colorPickerInputImage = convertImageForViewerDisplay(inputData.colorPickerInputImage->getBounds(), false, false /*the picker can accept non 4-channel image*/, inputData.colorPickerInputImage); } } } } inputData.render.reset(); } // onTreeRenderFinished