1 /*
2 Software License :
3
4 Copyright (c) 2012, The Open Effects Association Ltd. All rights reserved.
5
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions are met:
8
9 * Redistributions of source code must retain the above copyright notice,
10 this list of conditions and the following disclaimer.
11 * Redistributions in binary form must reproduce the above copyright notice,
12 this list of conditions and the following disclaimer in the documentation
13 and/or other materials provided with the distribution.
14 * Neither the name The Open Effects Association Ltd, nor the names of its
15 contributors may be used to endorse or promote products derived from this
16 software without specific prior written permission.
17
18 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
22 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
25 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30
31 /*
32 Direct GPU processing using OpenGL
33 */
34 #include <stdio.h>
35 #include <string.h>
36 #include <stdarg.h>
37 #include <cuda.h>
38 #include <cuda_runtime_api.h>
39
40 #include "ofxImageEffect.h"
41 #include "ofxMemory.h"
42 #include "ofxMultiThread.h"
43
44 #include "ofxUtilities.H" // example support utils
45
46 // pointers64 to various bits of the host
47 OfxHost *gHost;
48 OfxImageEffectSuiteV1 *gEffectHost = 0;
49 OfxPropertySuiteV1 *gPropHost = 0;
50 OfxParameterSuiteV1 *gParamHost = 0;
51 OfxMemorySuiteV1 *gMemoryHost = 0;
52 OfxMultiThreadSuiteV1 *gThreadHost = 0;
53 OfxMessageSuiteV1 *gMessageSuite = 0;
54 OfxInteractSuiteV1 *gInteractHost = 0;
55
56 // some flags about the host's behaviour
57 int gHostSupportsMultipleBitDepths = false;
58 int gHostSupportsCuda = false;
59
60 #define CHECK_STATUS(args) check_status_fun args
61
62 static void
check_status_fun(int status,int expected,const char * name)63 check_status_fun(int status, int expected, const char *name)
64 {
65 if (status != expected) {
66 fprintf(stderr, "OFX error in %s: expected status %d, got %d\n",
67 name, expected, status);
68 }
69 }
70
71 #define DPRINT(args) print_dbg args
print_dbg(const char * fmt,...)72 void print_dbg(const char *fmt, ...)
73 {
74 char msg[1024];
75 va_list ap;
76
77 va_start(ap, fmt);
78 vsnprintf(msg, 1023, fmt, ap);
79 fwrite(msg, sizeof(char), strlen(msg), stderr);
80 fflush(stderr);
81 #ifdef _WIN32
82 OutputDebugString(msg);
83 #endif
84 va_end(ap);
85 }
86
87 // private instance data type
88 struct MyInstanceData {
89 bool isGeneralEffect;
90
91 // handles to the clips we deal with
92 OfxImageClipHandle sourceClip;
93 OfxImageClipHandle outputClip;
94
95 // handles to our parameters
96 OfxParamHandle rGainParam;
97 OfxParamHandle gGainParam;
98 OfxParamHandle bGainParam;
99 };
100
101 /* mandatory function to set up the host structures */
102
103
104 // Convinience wrapper to get private data
105 static MyInstanceData *
getMyInstanceData(OfxImageEffectHandle effect)106 getMyInstanceData( OfxImageEffectHandle effect)
107 {
108 // get the property handle for the plugin
109 OfxPropertySetHandle effectProps;
110 gEffectHost->getPropertySet(effect, &effectProps);
111
112 // get my data pointer out of that
113 MyInstanceData *myData = 0;
114 gPropHost->propGetPointer(effectProps, kOfxPropInstanceData, 0,
115 (void **) &myData);
116 return myData;
117 }
118
119 /** @brief Called at load */
120 static OfxStatus
onLoad(void)121 onLoad(void)
122 {
123 return kOfxStatOK;
124 }
125
126 /** @brief Called before unload */
127 static OfxStatus
onUnLoad(void)128 onUnLoad(void)
129 {
130 return kOfxStatOK;
131 }
132
133 // instance construction
134 static OfxStatus
createInstance(OfxImageEffectHandle effect)135 createInstance( OfxImageEffectHandle effect)
136 {
137 // get a pointer to the effect properties
138 OfxPropertySetHandle effectProps;
139 gEffectHost->getPropertySet(effect, &effectProps);
140
141 // get a pointer to the effect's parameter set
142 OfxParamSetHandle paramSet;
143 gEffectHost->getParamSet(effect, ¶mSet);
144
145 // make my private instance data
146 MyInstanceData *myData = new MyInstanceData;
147 const char *context = 0;
148
149 // is this instance a general effect ?
150 gPropHost->propGetString(effectProps, kOfxImageEffectPropContext, 0, &context);
151 myData->isGeneralEffect = context && (strcmp(context, kOfxImageEffectContextGeneral) == 0);
152
153 // cache away our param handles
154 gParamHost->paramGetHandle(paramSet, "R Gain", &myData->rGainParam, 0);
155 gParamHost->paramGetHandle(paramSet, "G Gain", &myData->gGainParam, 0);
156 gParamHost->paramGetHandle(paramSet, "B Gain", &myData->bGainParam, 0);
157
158 // cache away our clip handles
159 gEffectHost->clipGetHandle(effect, "Source", &myData->sourceClip, 0);
160 gEffectHost->clipGetHandle(effect, "Output", &myData->outputClip, 0);
161
162 // set my private instance data
163 gPropHost->propSetPointer(effectProps, kOfxPropInstanceData, 0, (void *) myData);
164
165 return kOfxStatOK;
166 }
167
168 // instance destruction
169 static OfxStatus
destroyInstance(OfxImageEffectHandle effect)170 destroyInstance( OfxImageEffectHandle effect)
171 {
172 // get my instance data
173 MyInstanceData *myData = getMyInstanceData(effect);
174
175 // and delete it
176 if(myData)
177 delete myData;
178 return kOfxStatOK;
179 }
180
181 // tells the host what region we are capable of filling
182 OfxStatus
getSpatialRoD(OfxImageEffectHandle effect,OfxPropertySetHandle inArgs,OfxPropertySetHandle outArgs)183 getSpatialRoD( OfxImageEffectHandle effect, OfxPropertySetHandle inArgs, OfxPropertySetHandle outArgs)
184 {
185 // retrieve any instance data associated with this effect
186 MyInstanceData *myData = getMyInstanceData(effect);
187
188 OfxTime time;
189 gPropHost->propGetDouble(inArgs, kOfxPropTime, 0, &time);
190
191 // my RoD is the same as my input's
192 OfxRectD rod;
193 gEffectHost->clipGetRegionOfDefinition(myData->sourceClip, time, &rod);
194
195 // set the rod in the out args
196 gPropHost->propSetDoubleN(outArgs, kOfxImageEffectPropRegionOfDefinition, 4, &rod.x1);
197
198 return kOfxStatOK;
199 }
200
201 // tells the host how much of the input we need to fill the given window
202 OfxStatus
getSpatialRoI(OfxImageEffectHandle effect,OfxPropertySetHandle inArgs,OfxPropertySetHandle outArgs)203 getSpatialRoI( OfxImageEffectHandle effect, OfxPropertySetHandle inArgs, OfxPropertySetHandle outArgs)
204 {
205 // get the RoI the effect is interested in from inArgs
206 OfxRectD roi;
207 gPropHost->propGetDoubleN(inArgs, kOfxImageEffectPropRegionOfInterest, 4, &roi.x1);
208
209 // the input needed is the same as the output, so set that on the source clip
210 gPropHost->propSetDoubleN(outArgs, "OfxImageClipPropRoI_Source", 4, &roi.x1);
211
212 // retrieve any instance data associated with this effect
213 MyInstanceData *myData = getMyInstanceData(effect);
214
215 return kOfxStatOK;
216 }
217
218 // Tells the host how many frames we can fill, only called in the general context.
219 // This is actually redundant as this is the default behaviour, but for illustrative
220 // purposes.
221 OfxStatus
getTemporalDomain(OfxImageEffectHandle effect,OfxPropertySetHandle inArgs,OfxPropertySetHandle outArgs)222 getTemporalDomain( OfxImageEffectHandle effect, OfxPropertySetHandle inArgs, OfxPropertySetHandle outArgs)
223 {
224 MyInstanceData *myData = getMyInstanceData(effect);
225
226 double sourceRange[2];
227
228 // get the frame range of the source clip
229 OfxPropertySetHandle props; gEffectHost->clipGetPropertySet(myData->sourceClip, &props);
230 gPropHost->propGetDoubleN(props, kOfxImageEffectPropFrameRange, 2, sourceRange);
231
232 // set it on the out args
233 gPropHost->propSetDoubleN(outArgs, kOfxImageEffectPropFrameRange, 2, sourceRange);
234
235 return kOfxStatOK;
236 }
237
238
239 // Set our clip preferences
240 static OfxStatus
getClipPreferences(OfxImageEffectHandle effect,OfxPropertySetHandle inArgs,OfxPropertySetHandle outArgs)241 getClipPreferences( OfxImageEffectHandle effect, OfxPropertySetHandle inArgs, OfxPropertySetHandle outArgs)
242 {
243 // retrieve any instance data associated with this effect
244 MyInstanceData *myData = getMyInstanceData(effect);
245
246 // get the component type and bit depth of our main input
247 int bitDepth;
248 bool isRGBA;
249 ofxuClipGetFormat(myData->sourceClip, bitDepth, isRGBA, true); // get the unmapped clip component
250
251 // get the strings used to label the various bit depths
252 const char *bitDepthStr = bitDepth == 8 ? kOfxBitDepthByte : (bitDepth == 16 ? kOfxBitDepthShort : kOfxBitDepthFloat);
253 const char *componentStr = isRGBA ? kOfxImageComponentRGBA : kOfxImageComponentAlpha;
254
255 // set out output to be the same same as the input, component and bitdepth
256 gPropHost->propSetString(outArgs, "OfxImageClipPropComponents_Output", 0, componentStr);
257 if(gHostSupportsMultipleBitDepths)
258 gPropHost->propSetString(outArgs, "OfxImageClipPropDepth_Output", 0, bitDepthStr);
259
260 return kOfxStatOK;
261 }
262
263 // are the settings of the effect performing an identity operation
264 static OfxStatus
isIdentity(OfxImageEffectHandle effect,OfxPropertySetHandle inArgs,OfxPropertySetHandle outArgs)265 isIdentity( OfxImageEffectHandle effect,
266 OfxPropertySetHandle inArgs,
267 OfxPropertySetHandle outArgs)
268 {
269 // In this case do the default, which in this case is to render
270 return kOfxStatReplyDefault;
271 }
272
273 ////////////////////////////////////////////////////////////////////////////////
274 // function called when the instance has been changed by anything
275 static OfxStatus
instanceChanged(OfxImageEffectHandle effect,OfxPropertySetHandle inArgs,OfxPropertySetHandle outArgs)276 instanceChanged( OfxImageEffectHandle effect,
277 OfxPropertySetHandle inArgs,
278 OfxPropertySetHandle outArgs)
279 {
280 // don't trap any others
281 return kOfxStatReplyDefault;
282 }
283
284 ////////////////////////////////////////////////////////////////////////////////
285 // rendering routines
286
287 extern void RunKernel(int p_Width, int p_Height, float p_RGain, float p_GGain, float p_BGain, float* p_Input, float* p_Output);
288
289 // the process code that the host sees
render(OfxImageEffectHandle instance,OfxPropertySetHandle inArgs,OfxPropertySetHandle outArgs)290 static OfxStatus render( OfxImageEffectHandle instance,
291 OfxPropertySetHandle inArgs,
292 OfxPropertySetHandle outArgs)
293 {
294 // get the render window and the time from the inArgs
295 OfxTime time;
296 OfxRectI renderWindow;
297 OfxStatus status = kOfxStatOK;
298
299 gPropHost->propGetDouble(inArgs, kOfxPropTime, 0, &time);
300 gPropHost->propGetIntN(inArgs, kOfxImageEffectPropRenderWindow, 4, &renderWindow.x1);
301
302 // Retrieve instance data associated with this effect
303 MyInstanceData *myData = getMyInstanceData(instance);
304
305 // property handles and members of each image
306 OfxPropertySetHandle sourceImg = NULL, outputImg = NULL;
307 int srcRowBytes, srcBitDepth, dstRowBytes, dstBitDepth;
308 bool srcIsAlpha, dstIsAlpha;
309 OfxRectI dstRect, srcRect;
310 void *src, *dst;
311
312 DPRINT(("Render: window = [%d, %d - %d, %d]\n",
313 renderWindow.x1, renderWindow.y1,
314 renderWindow.x2, renderWindow.y2));
315
316 int isCudaEnabled = 0;
317 if (gHostSupportsCuda)
318 {
319 gPropHost->propGetInt(inArgs, kOfxImageEffectPropCudaEnabled, 0, &isCudaEnabled);
320 DPRINT(("render: Cuda rendering %s\n", isCudaEnabled ? "enabled" : "DISABLED"));
321 }
322
323 cudaError_t cudaError;
324 int deviceCount;
325
326 cudaGetDeviceCount(&deviceCount);
327
328 cudaDeviceProp deviceProp;
329 for (int i = 0; i < deviceCount; ++i)
330 {
331 cudaGetDeviceProperties(&deviceProp, i);
332 DPRINT(("Device [%d/%d] %s (Unified addressing %d)\n", i, deviceCount, deviceProp.name, deviceProp.unifiedAddressing));
333 }
334
335 // Get the Cuda device that the host is running on
336 int hostDevice;
337 cudaGetDevice(&hostDevice);
338
339 // Use the first Cuda device
340 int pluginDevice = 0;
341 cudaError = cudaSetDevice(pluginDevice);
342 if (cudaError != cudaSuccess)
343 {
344 DPRINT(("cudaSetDevice: cudaError %d\n", cudaError));
345 }
346
347 cudaGetDeviceProperties(&deviceProp, pluginDevice);
348 DPRINT(("Using %s for plugin\n", deviceProp.name));
349
350 // get the source image
351 sourceImg = ofxuGetImage(myData->sourceClip, time, srcRowBytes, srcBitDepth, srcIsAlpha, srcRect, src);
352
353 // get the output image
354 outputImg = ofxuGetImage(myData->outputClip, time, dstRowBytes, dstBitDepth, dstIsAlpha, dstRect, dst);
355
356 // get the scale parameter
357 double rGain = 1, gGain = 1, bGain = 1;
358 gParamHost->paramGetValueAtTime(myData->rGainParam, time, &rGain);
359 gParamHost->paramGetValueAtTime(myData->gGainParam, time, &gGain);
360 gParamHost->paramGetValueAtTime(myData->bGainParam, time, &bGain);
361 DPRINT(("Gain(%f %f %f)\n", rGain, gGain, bGain));
362
363 float w = (renderWindow.x2 - renderWindow.x1);
364 float h = (renderWindow.y2 - renderWindow.y1);
365
366 // Allocate the temporary buffers on the plugin device
367 void* inBuffer;
368 cudaError = cudaMalloc(&inBuffer, sizeof(float) * w * h * 4);
369 if (cudaError != cudaSuccess)
370 {
371 DPRINT(("cudaMalloc: cudaError %d\n", cudaError));
372 }
373 void* outBuffer;
374 cudaError = cudaMalloc(&outBuffer, sizeof(float) * w * h * 4);
375 if (cudaError != cudaSuccess)
376 {
377 DPRINT(("cudaMalloc: cudaError %d\n", cudaError));
378 }
379
380 if (isCudaEnabled)
381 {
382 if (pluginDevice == hostDevice)
383 {
384 DPRINT(("Using Cuda transfers (same device)\n"));
385
386 RunKernel(w, h, rGain, gGain, bGain, static_cast<float*>(src), static_cast<float*>(dst));
387
388 if (cudaError != cudaSuccess)
389 {
390 DPRINT(("cudaMemcpy: cudaError %d\n", cudaError));
391 }
392 }
393 else
394 {
395 DPRINT(("Using Cuda transfers (different devices)\n"));
396
397 // Copy the buffer from the host device to the plugin device
398 cudaError = cudaMemcpyPeer(inBuffer, pluginDevice, src, hostDevice, sizeof(float) * w * h * 4);
399
400 if (cudaError != cudaSuccess)
401 {
402 DPRINT(("cudaMemcpyPeer: cudaError %d\n", cudaError));
403 }
404
405 RunKernel(w, h, rGain, gGain, bGain, static_cast<float*>(inBuffer), static_cast<float*>(outBuffer));
406
407 if (cudaError != cudaSuccess)
408 {
409 DPRINT(("cudaMemcpy: cudaError %d\n", cudaError));
410 }
411
412
413 // Copy the buffer from the plugin device to the host device
414 cudaError = cudaMemcpyPeer(dst, hostDevice, outBuffer, pluginDevice, sizeof(float) * w * h * 4);
415
416 if (cudaError != cudaSuccess)
417 {
418 DPRINT(("cudaMemcpyPeer: cudaError %d\n", cudaError));
419 }
420 }
421 }
422 else
423 {
424 DPRINT(("Using CPU transfers\n"));
425
426 // Copy the buffer from the CPU to the plugin device
427 cudaError = cudaMemcpy(inBuffer, src, sizeof(float) * w * h * 4, cudaMemcpyHostToDevice);
428
429 if (cudaError != cudaSuccess)
430 {
431 DPRINT(("cudaMemcpy: cudaError %d\n", cudaError));
432 }
433
434 RunKernel(w, h, rGain, gGain, bGain, static_cast<float*>(inBuffer), static_cast<float*>(outBuffer));
435
436 if (cudaError != cudaSuccess)
437 {
438 DPRINT(("cudaMemcpy: cudaError %d\n", cudaError));
439 }
440
441 // Copy the buffer from the plugin device to the CPU
442 cudaError = cudaMemcpy(dst, outBuffer, sizeof(float) * w * h * 4, cudaMemcpyDeviceToHost);
443
444 if (cudaError != cudaSuccess)
445 {
446 DPRINT(("cudaMemcpy: cudaError %d\n", cudaError));
447 }
448 }
449
450 // Free the temporary buffers on the plugin device
451 cudaFree(inBuffer);
452 cudaFree(outBuffer);
453
454 // Set back the Cuda device that the host is running on
455 cudaSetDevice(hostDevice);
456
457 if (sourceImg)
458 {
459 gEffectHost->clipReleaseImage(sourceImg);
460 }
461
462 if (outputImg)
463 {
464 gEffectHost->clipReleaseImage(outputImg);
465 }
466
467 return status;
468 }
469
470 // convience function to define parameters
471 static void
defineParam(OfxParamSetHandle effectParams,const char * name,const char * label,const char * scriptName,const char * hint,const char * parent)472 defineParam( OfxParamSetHandle effectParams,
473 const char *name,
474 const char *label,
475 const char *scriptName,
476 const char *hint,
477 const char *parent)
478 {
479 OfxParamHandle param;
480 OfxPropertySetHandle props;
481 gParamHost->paramDefine(effectParams, kOfxParamTypeDouble, name, &props);
482
483 // say we are a scaling parameter
484 gPropHost->propSetString(props, kOfxParamPropDoubleType, 0, kOfxParamDoubleTypeScale);
485 gPropHost->propSetDouble(props, kOfxParamPropDefault, 0, 1.0);
486 gPropHost->propSetDouble(props, kOfxParamPropMin, 0, 0.01);
487 gPropHost->propSetDouble(props, kOfxParamPropDisplayMin, 0, 0.01);
488 gPropHost->propSetDouble(props, kOfxParamPropDisplayMax, 0, 2.0);
489 gPropHost->propSetDouble(props, kOfxParamPropIncrement, 0, 0.01);
490 gPropHost->propSetString(props, kOfxParamPropHint, 0, hint);
491 gPropHost->propSetString(props, kOfxParamPropScriptName, 0, scriptName);
492 gPropHost->propSetString(props, kOfxPropLabel, 0, label);
493 if(parent)
494 gPropHost->propSetString(props, kOfxParamPropParent, 0, parent);
495 }
496
497 // describe the plugin in context
498 static OfxStatus
describeInContext(OfxImageEffectHandle effect,OfxPropertySetHandle inArgs)499 describeInContext( OfxImageEffectHandle effect, OfxPropertySetHandle inArgs)
500 {
501 // get the context from the inArgs handle
502 const char *context;
503 gPropHost->propGetString(inArgs, kOfxImageEffectPropContext, 0, &context);
504 bool isGeneralContext = strcmp(context, kOfxImageEffectContextGeneral) == 0;
505
506 OfxPropertySetHandle props;
507 // define the single output clip in both contexts
508 gEffectHost->clipDefine(effect, "Output", &props);
509
510 // set the component types we can handle on out output
511 gPropHost->propSetString(props, kOfxImageEffectPropSupportedComponents, 0, kOfxImageComponentRGBA);
512 gPropHost->propSetString(props, kOfxImageEffectPropSupportedComponents, 1, kOfxImageComponentAlpha);
513
514 // define the single source clip in both contexts
515 gEffectHost->clipDefine(effect, "Source", &props);
516
517 // set the component types we can handle on our main input
518 gPropHost->propSetString(props, kOfxImageEffectPropSupportedComponents, 0, kOfxImageComponentRGBA);
519 gPropHost->propSetString(props, kOfxImageEffectPropSupportedComponents, 1, kOfxImageComponentAlpha);
520
521 ////////////////////////////////////////////////////////////////////////////////
522 // define the parameters for this context
523 // fetch the parameter set from the effect
524 OfxParamSetHandle paramSet;
525 gEffectHost->getParamSet(effect, ¶mSet);
526
527 defineParam(paramSet, "R Gain", "R Gain", "R Gain",
528 "Red Gain", 0);
529 defineParam(paramSet, "G Gain", "G Gain", "G Gain",
530 "Green Gain", 0);
531 defineParam(paramSet, "B Gain", "B Gain", "B Gain",
532 "Blue Gain", 0);
533
534 // make a page of controls and add my parameters to it
535 OfxParamHandle page;
536 gParamHost->paramDefine(paramSet, kOfxParamTypePage, "Main", &props);
537 gPropHost->propSetString(props, kOfxParamPropPageChild, 0, "R Gain");
538 gPropHost->propSetString(props, kOfxParamPropPageChild, 1, "G Gain");
539 gPropHost->propSetString(props, kOfxParamPropPageChild, 2, "B Gain");
540 return kOfxStatOK;
541 }
542
543 ////////////////////////////////////////////////////////////////////////////////
544 // the plugin's description routine
545 static OfxStatus
describe(OfxImageEffectHandle effect)546 describe(OfxImageEffectHandle effect)
547 {
548 // first fetch the host APIs, this cannot be done before this call
549 OfxStatus stat;
550 if((stat = ofxuFetchHostSuites()) != kOfxStatOK)
551 return stat;
552
553 // record a few host features
554 gPropHost->propGetInt(gHost->host, kOfxImageEffectPropSupportsMultipleClipDepths, 0, &gHostSupportsMultipleBitDepths);
555
556 // get the property handle for the plugin
557 OfxPropertySetHandle effectProps;
558 gEffectHost->getPropertySet(effect, &effectProps);
559
560 // We can render both fields in a fielded images in one hit if there is no animation
561 // So set the flag that allows us to do this
562 gPropHost->propSetInt(effectProps, kOfxImageEffectPluginPropFieldRenderTwiceAlways, 0, 0);
563
564 // say we can support multiple pixel depths and let the clip preferences action deal with it all.
565 gPropHost->propSetInt(effectProps, kOfxImageEffectPropSupportsMultipleClipDepths, 0, 1);
566
567 // set the bit depths the plugin can handle
568 gPropHost->propSetString(effectProps, kOfxImageEffectPropSupportedPixelDepths, 0, kOfxBitDepthByte);
569 gPropHost->propSetString(effectProps, kOfxImageEffectPropSupportedPixelDepths, 1, kOfxBitDepthShort);
570 gPropHost->propSetString(effectProps, kOfxImageEffectPropSupportedPixelDepths, 2, kOfxBitDepthFloat);
571
572 // set some labels and the group it belongs to
573 gPropHost->propSetString(effectProps, kOfxPropLabel, 0, "Resolve Simple Gain (CUDA)");
574 gPropHost->propSetString(effectProps, kOfxImageEffectPluginPropGrouping, 0, "Resolve Simple Gain");
575
576 // define the contexts we can be used in
577 gPropHost->propSetString(effectProps, kOfxImageEffectPropSupportedContexts, 0, kOfxImageEffectContextFilter);
578 gPropHost->propSetString(effectProps, kOfxImageEffectPropSupportedContexts, 1, kOfxImageEffectContextGeneral);
579
580 // we support Cuda rendering
581 gPropHost->propSetString(effectProps, kOfxImageEffectPropCudaRenderSupported, 0, "true");
582
583 {
584 const char *s = "<undefined>";
585 stat = gPropHost->propGetString(gHost->host, kOfxImageEffectPropCudaRenderSupported, 0, &s);
586 DPRINT(("Host has Cuda render support: %s (stat=%d)\n", s, stat));
587 gHostSupportsCuda = stat == 0 && !strcmp(s, "true");
588 }
589
590 return kOfxStatOK;
591 }
592
593 ////////////////////////////////////////////////////////////////////////////////
594 // The main function
595 static OfxStatus
pluginMain(const char * action,const void * handle,OfxPropertySetHandle inArgs,OfxPropertySetHandle outArgs)596 pluginMain(const char *action, const void *handle, OfxPropertySetHandle inArgs, OfxPropertySetHandle outArgs)
597 {
598 // cast to appropriate type
599 OfxImageEffectHandle effect = (OfxImageEffectHandle) handle;
600
601 if(strcmp(action, kOfxActionDescribe) == 0) {
602 return describe(effect);
603 }
604 else if(strcmp(action, kOfxImageEffectActionDescribeInContext) == 0) {
605 return describeInContext(effect, inArgs);
606 }
607 else if(strcmp(action, kOfxActionLoad) == 0) {
608 return onLoad();
609 }
610 else if(strcmp(action, kOfxActionUnload) == 0) {
611 return onUnLoad();
612 }
613 else if(strcmp(action, kOfxActionCreateInstance) == 0) {
614 return createInstance(effect);
615 }
616 else if(strcmp(action, kOfxActionDestroyInstance) == 0) {
617 return destroyInstance(effect);
618 }
619 else if(strcmp(action, kOfxImageEffectActionIsIdentity) == 0) {
620 return isIdentity(effect, inArgs, outArgs);
621 }
622 else if(strcmp(action, kOfxImageEffectActionRender) == 0) {
623 return render(effect, inArgs, outArgs);
624 }
625 else if(strcmp(action, kOfxImageEffectActionGetRegionOfDefinition) == 0) {
626 return getSpatialRoD(effect, inArgs, outArgs);
627 }
628 else if(strcmp(action, kOfxImageEffectActionGetRegionsOfInterest) == 0) {
629 return getSpatialRoI(effect, inArgs, outArgs);
630 }
631 else if(strcmp(action, kOfxImageEffectActionGetClipPreferences) == 0) {
632 return getClipPreferences(effect, inArgs, outArgs);
633 }
634 else if(strcmp(action, kOfxActionInstanceChanged) == 0) {
635 return instanceChanged(effect, inArgs, outArgs);
636 }
637 else if(strcmp(action, kOfxImageEffectActionGetTimeDomain) == 0) {
638 return getTemporalDomain(effect, inArgs, outArgs);
639 }
640
641
642 // other actions to take the default value
643 return kOfxStatReplyDefault;
644 }
645
646 // function to set the host structure
647 static void
setHostFunc(OfxHost * hostStruct)648 setHostFunc(OfxHost *hostStruct)
649 {
650 gHost = hostStruct;
651 }
652
653 ////////////////////////////////////////////////////////////////////////////////
654 // the plugin struct
655 static OfxPlugin basicPlugin =
656 {
657 kOfxImageEffectPluginApi,
658 1,
659 "com.blackmagicdesign.ResolveSimpleGainCUDAPlugin",
660 1,
661 0,
662 setHostFunc,
663 pluginMain
664 };
665
666 // the two mandated functions
667 OfxPlugin *
OfxGetPlugin(int nth)668 OfxGetPlugin(int nth)
669 {
670 if(nth == 0)
671 return &basicPlugin;
672 return 0;
673 }
674
675 int
OfxGetNumberOfPlugins(void)676 OfxGetNumberOfPlugins(void)
677 {
678 return 1;
679 }
680