// the process code that the host sees static OfxStatus render( OfxImageEffectHandle instance, OfxPropertySetHandle inArgs, OfxPropertySetHandle outArgs) { // get the render window and the time from the inArgs OfxTime time; OfxRectI renderWindow; OfxStatus status = kOfxStatOK; gPropHost->propGetDouble(inArgs, kOfxPropTime, 0, &time); gPropHost->propGetIntN(inArgs, kOfxImageEffectPropRenderWindow, 4, &renderWindow.x1); // retrieve any instance data associated with this effect MyInstanceData *myData = getMyInstanceData(instance); // property handles and members of each image // in reality, we would put this in a struct as the C++ support layer does OfxPropertySetHandle sourceImg = NULL, outputImg = NULL, maskImg = NULL; int srcRowBytes, srcBitDepth, dstRowBytes, dstBitDepth, maskRowBytes, maskBitDepth; bool srcIsAlpha, dstIsAlpha, maskIsAlpha; OfxRectI dstRect, srcRect, maskRect; void *src, *dst, *mask = NULL; try { // get the source image sourceImg = ofxuGetImage(myData->sourceClip, time, srcRowBytes, srcBitDepth, srcIsAlpha, srcRect, src); if(sourceImg == NULL) throw OfxuNoImageException(); // get the output image outputImg = ofxuGetImage(myData->outputClip, time, dstRowBytes, dstBitDepth, dstIsAlpha, dstRect, dst); if(outputImg == NULL) throw OfxuNoImageException(); if(myData->isGeneralEffect) { // is the mask connected? if(ofxuIsClipConnected(instance, "Mask")) { maskImg = ofxuGetImage(myData->maskClip, time, maskRowBytes, maskBitDepth, maskIsAlpha, maskRect, mask); if(maskImg != NULL) { // and see that it is a single component if(!maskIsAlpha || maskBitDepth != srcBitDepth) { throw OfxuStatusException(kOfxStatErrImageFormat); } } } } // see if they have the same depths and bytes and all if(srcBitDepth != dstBitDepth || srcIsAlpha != dstIsAlpha) { throw OfxuStatusException(kOfxStatErrImageFormat); } // are we compenent scaling bool scaleComponents; gParamHost->paramGetValueAtTime(myData->perComponentScaleParam, time, &scaleComponents); // get the scale parameters double scale, rScale = 1, gScale = 1, bScale = 1, aScale = 1; gParamHost->paramGetValueAtTime(myData->scaleParam, time, &scale); if(scaleComponents) { gParamHost->paramGetValueAtTime(myData->scaleRParam, time, &rScale); gParamHost->paramGetValueAtTime(myData->scaleGParam, time, &gScale); gParamHost->paramGetValueAtTime(myData->scaleBParam, time, &bScale); gParamHost->paramGetValueAtTime(myData->scaleAParam, time, &aScale); } rScale *= scale; gScale *= scale; bScale *= scale; aScale *= scale; // do the rendering if(!dstIsAlpha) { switch(dstBitDepth) { case 8 : { ProcessRGBA<OfxRGBAColourB, unsigned char, 255, 0> fred(instance, rScale, gScale, bScale, aScale, src, srcRect, srcRowBytes, dst, dstRect, dstRowBytes, mask, maskRect, maskRowBytes, renderWindow); fred.process(); } break; case 16 : { ProcessRGBA<OfxRGBAColourS, unsigned short, 65535, 0> fred(instance, rScale, gScale, bScale, aScale, src, srcRect, srcRowBytes, dst, dstRect, dstRowBytes, mask, maskRect, maskRowBytes, renderWindow); fred.process(); } break; case 32 : { ProcessRGBA<OfxRGBAColourF, float, 1, 1> fred(instance, rScale, gScale, bScale, aScale, src, srcRect, srcRowBytes, dst, dstRect, dstRowBytes, mask, maskRect, maskRowBytes, renderWindow); fred.process(); break; } } } else { switch(dstBitDepth) { case 8 : { ProcessAlpha<unsigned char, unsigned char, 255, 0> fred(instance, scale, src, srcRect, srcRowBytes, dst, dstRect, dstRowBytes, mask, maskRect, maskRowBytes, renderWindow); fred.process(); } break; case 16 : { ProcessAlpha<unsigned short, unsigned short, 65535, 0> fred(instance, scale, src, srcRect, srcRowBytes, dst, dstRect, dstRowBytes, mask, maskRect, maskRowBytes, renderWindow); fred.process(); } break; case 32 : { ProcessAlpha<float, float, 1, 1> fred(instance, scale, src, srcRect, srcRowBytes, dst, dstRect, dstRowBytes, mask, maskRect, maskRowBytes, renderWindow); fred.process(); } break; } } } catch(OfxuNoImageException &ex) { // if we were interrupted, the failed fetch is fine, just return kOfxStatOK // otherwise, something wierd happened if(!gEffectHost->abort(instance)) { status = kOfxStatFailed; } } catch(OfxuStatusException &ex) { status = ex.status(); } // release the data pointers if(maskImg) gEffectHost->clipReleaseImage(maskImg); if(sourceImg) gEffectHost->clipReleaseImage(sourceImg); if(outputImg) gEffectHost->clipReleaseImage(outputImg); return status; }
// the process code that the host sees static OfxStatus render(OfxImageEffectHandle effect, OfxPropertySetHandle inArgs, OfxPropertySetHandle outArgs) { // get the render window and the time from the inArgs OfxTime time; OfxRectI renderWindow; OfxStatus status = kOfxStatOK; gPropHost->propGetDouble(inArgs, kOfxPropTime, 0, &time); gPropHost->propGetIntN(inArgs, kOfxImageEffectPropRenderWindow, 4, &renderWindow.x1); // retrieve any instance data associated with this effect MyInstanceData *myData = getMyInstanceData(effect); // property handles and members of each image // in reality, we would put this in a struct as the C++ support layer does OfxPropertySetHandle sourceImg = NULL, outputImg = NULL; int srcRowBytes, srcBitDepth, dstRowBytes, dstBitDepth; bool srcIsAlpha, dstIsAlpha; OfxRectI dstRect, srcRect; void *src, *dst; try { outputImg = ofxuGetImage(myData->outputClip, time, dstRowBytes, dstBitDepth, dstIsAlpha, dstRect, dst); if(outputImg == NULL) throw OfxuNoImageException(); sourceImg = ofxuGetImage(myData->sourceClip, time, srcRowBytes, srcBitDepth, srcIsAlpha, srcRect, src); if(sourceImg == NULL) throw OfxuNoImageException(); int nComponents = dstIsAlpha ? 1 : 4; // set up the processor that we pass to the individual constructors Processor proc(effect, nComponents, src, srcRect, srcRowBytes, dst, dstRect, dstRowBytes, renderWindow); // now instantiate the templated processor depending on src and dest pixel types, 9 cases in all switch(dstBitDepth) { case 8 : { switch(srcBitDepth) { case 8 : {ProcessPix<unsigned char, 255, 0, unsigned char, 255, 0> pixProc(proc); break;} case 16 : {ProcessPix<unsigned short, 65535, 0, unsigned char, 255, 0> pixProc(proc); break;} case 32 : {ProcessPix<float, 1, 1, unsigned char, 255, 0> pixProc(proc); break;} } } break; case 16 : { switch(srcBitDepth) { case 8 : {ProcessPix<unsigned char, 255, 0, unsigned short, 65535, 0> pixProc(proc); break;} case 16 : {ProcessPix<unsigned short, 65535, 0, unsigned short, 65535, 0> pixProc(proc); break;} case 32 : {ProcessPix<float, 1, 1, unsigned short, 65535, 0> pixProc(proc); break;} } } break; case 32 : { switch(srcBitDepth) { case 8 : {ProcessPix<unsigned char, 255, 0, float, 1, 1> pixProc(proc); break;} case 16 : {ProcessPix<unsigned short, 65535, 0, float, 1, 1> pixProc(proc); break;} case 32 : {ProcessPix<float, 1, 1, float, 1, 1> pixProc(proc); break;} } } break; } } catch(OfxuNoImageException &ex) { // if we were interrupted, the failed fetch is fine, just return kOfxStatOK // otherwise, something wierd happened if(!gEffectHost->abort(effect)) { status = kOfxStatFailed; } } // release the data pointers; if(sourceImg) gEffectHost->clipReleaseImage(sourceImg); if(outputImg) gEffectHost->clipReleaseImage(outputImg); return status; }
// the process code that the host sees static OfxStatus render( OfxImageEffectHandle instance, OfxPropertySetHandle inArgs, OfxPropertySetHandle outArgs) { // get the render window and the time from the inArgs OfxTime time; OfxRectI renderWindow; OfxStatus status = kOfxStatOK; gPropHost->propGetDouble(inArgs, kOfxPropTime, 0, &time); gPropHost->propGetIntN(inArgs, kOfxImageEffectPropRenderWindow, 4, &renderWindow.x1); // Retrieve instance data associated with this effect MyInstanceData *myData = getMyInstanceData(instance); // property handles and members of each image OfxPropertySetHandle sourceImg = NULL, outputImg = NULL; int srcRowBytes, srcBitDepth, dstRowBytes, dstBitDepth; bool srcIsAlpha, dstIsAlpha; OfxRectI dstRect, srcRect; void *src, *dst; DPRINT(("Render: window = [%d, %d - %d, %d]\n", renderWindow.x1, renderWindow.y1, renderWindow.x2, renderWindow.y2)); int isOpenCLEnabled = 0; if (gHostSupportsOpenCL) { gPropHost->propGetInt(inArgs, kOfxImageEffectPropOpenCLEnabled, 0, &isOpenCLEnabled); DPRINT(("render: OpenCL rendering %s\n", isOpenCLEnabled ? "enabled" : "DISABLED")); } cl_context clContext = NULL; cl_command_queue cmdQ = NULL; cl_device_id deviceId = NULL; if (isOpenCLEnabled) { void* voidPtrCmdQ; gPropHost->propGetPointer(inArgs, kOfxImageEffectPropOpenCLCommandQueue, 0, &voidPtrCmdQ); cmdQ = reinterpret_cast<cl_command_queue>(voidPtrCmdQ); clGetCommandQueueInfo(cmdQ, CL_QUEUE_CONTEXT, sizeof(cl_context), &clContext, NULL); clGetCommandQueueInfo(cmdQ, CL_QUEUE_DEVICE, sizeof(cl_device_id), &deviceId, NULL); } else { clContext = GetContext(deviceId); cmdQ = clCreateCommandQueue(clContext, deviceId, 0, NULL); } char deviceName[128]; clGetDeviceInfo(deviceId, CL_DEVICE_NAME, 128, deviceName, NULL); DPRINT(("Using %s for plugin\n", deviceName)); cl_kernel kernel = GetKernel(clContext); // get the source image sourceImg = ofxuGetImage(myData->sourceClip, time, srcRowBytes, srcBitDepth, srcIsAlpha, srcRect, src); // get the output image outputImg = ofxuGetImage(myData->outputClip, time, dstRowBytes, dstBitDepth, dstIsAlpha, dstRect, dst); // get the scale parameter double rGain = 1, gGain = 1, bGain = 1; gParamHost->paramGetValueAtTime(myData->rGainParam, time, &rGain); gParamHost->paramGetValueAtTime(myData->gGainParam, time, &gGain); gParamHost->paramGetValueAtTime(myData->bGainParam, time, &bGain); DPRINT(("Gain(%f %f %f)\n", rGain, gGain, bGain)); float w = (renderWindow.x2 - renderWindow.x1); float h = (renderWindow.y2 - renderWindow.y1); const size_t rowSize = w * 4 * sizeof(float); if (isOpenCLEnabled) { DPRINT(("Using OpenCL transfers (same device)\n")); RunKernel(cmdQ, deviceId, kernel, w, h, rGain, gGain, bGain, (cl_mem)src, (cl_mem)dst); } else { DPRINT(("Using CPU transfers\n")); const size_t bufferSize = w * h * 4 * sizeof(float); // Allocate the temporary buffers on the plugin device cl_mem inBuffer = clCreateBuffer(clContext, CL_MEM_READ_ONLY, bufferSize, NULL, NULL); cl_mem outBuffer = clCreateBuffer(clContext, CL_MEM_WRITE_ONLY, bufferSize, NULL, NULL); // Copy the buffer from the CPU to the plugin device clEnqueueWriteBuffer(cmdQ, inBuffer, CL_TRUE, 0, bufferSize, src, 0, NULL, NULL); RunKernel(cmdQ, deviceId, kernel, w, h, rGain, gGain, bGain, inBuffer, outBuffer); // Copy the buffer from the plugin device to the CPU clEnqueueReadBuffer(cmdQ, outBuffer, CL_TRUE, 0, bufferSize, dst, 0, NULL, NULL); clFinish(cmdQ); // Free the temporary buffers on the plugin device clReleaseMemObject(inBuffer); clReleaseMemObject(outBuffer); } if (sourceImg) { gEffectHost->clipReleaseImage(sourceImg); } if (outputImg) { gEffectHost->clipReleaseImage(outputImg); } return status; }