Beispiel #1
0
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();
}
Beispiel #2
0
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