1 /*
2  * This file is part of openfx-arena <https://github.com/olear/openfx-arena>,
3  * Copyright (C) 2016 INRIA
4  *
5  * openfx-arena is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as published
7  * by the Free Software Foundation.
8  *
9  * openfx-arena is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with openfx-arena.  If not, see <http://www.gnu.org/licenses/gpl-2.0.html>
16 */
17 
18 #include "OCLPlugin.h"
19 
20 using namespace OFX;
21 OFXS_NAMESPACE_ANONYMOUS_ENTER
22 
23 #define kPluginName "CLFilter"
24 #define kPluginGrouping "Filter"
25 #define kPluginIdentifier "net.fxarena.opencl.CLFilter"
26 #define kPluginDescription "OpenCL filter meta node."
27 #define kPluginVersionMajor 1
28 #define kPluginVersionMinor 0
29 
30 #define kSupportsTiles 0
31 #define kSupportsMultiResolution 1
32 #define kSupportsRenderScale 1
33 #define kRenderThreadSafety eRenderFullySafe
34 #define kHostFrameThreading false
35 #define kHostMasking true
36 #define kHostMixing true
37 
38 #define kParamKernel "kernel"
39 #define kParamKernelLabel "Kernel"
40 #define kParamKernelHint "The kernel to build and use."
41 #define kParamKernelDefault \
42     "const sampler_t sampler = CLK_NORMALIZED_COORDS_FALSE | CLK_ADDRESS_CLAMP_TO_EDGE | CLK_FILTER_LINEAR;\n" \
43     "void kernel filter(__read_only image2d_t input, __write_only image2d_t output)\n" \
44     "{ /* basic image copy: */ \n"\
45         "int2 pos = {get_global_id(0), get_global_id(1)};\n" \
46         "float4 pixels = read_imagef(input, sampler, pos);\n" \
47         "write_imagef(output, pos, pixels);\n" \
48     "}\n"
49 
50 class CLFilterCLPlugin
51     : public OCLPluginHelper<kSupportsRenderScale>
52 {
53 public:
CLFilterCLPlugin(OfxImageEffectHandle handle)54     CLFilterCLPlugin(OfxImageEffectHandle handle)
55         : OCLPluginHelper<kSupportsRenderScale>(handle, "", "")
56         , _kSource(NULL)
57     {
58         _kSource = fetchStringParam(kParamKernel);
59         assert(_kSource);
60 
61         std::string source;
62         _kSource->getValue(source);
63         setupContext(false, source);
64     }
65 
render(const OFX::RenderArguments &,cl::Kernel)66     virtual void render(const OFX::RenderArguments &/*args*/, cl::Kernel /*kernel*/) OVERRIDE FINAL
67     {
68     }
69     virtual void changedParam(const OFX::InstanceChangedArgs &args, const std::string &paramName) OVERRIDE FINAL;
70 private:
71     OFX::StringParam *_kSource;
72 };
73 
changedParam(const OFX::InstanceChangedArgs & args,const std::string & paramName)74 void CLFilterCLPlugin::changedParam(const OFX::InstanceChangedArgs &args, const std::string &paramName)
75 {
76     if (!kSupportsRenderScale && (args.renderScale.x != 1. || args.renderScale.y != 1.)) {
77         OFX::throwSuiteStatusException(kOfxStatFailed);
78         return;
79     }
80 
81     std::string source;
82     _kSource->getValueAtTime(args.time, source);
83 
84     if (paramName == kParamOCLDevice) {
85         setupContext(true, source);
86     }
87     else if (paramName == kParamKernel) {
88         setupContext(false, source);
89     }
90 
91     clearPersistentMessage();
92 }
93 
94 mDeclarePluginFactory(CLFilterCLPluginFactory, {}, {});
95 
describe(ImageEffectDescriptor & desc)96 void CLFilterCLPluginFactory::describe(ImageEffectDescriptor &desc)
97 {
98     desc.setLabel(kPluginName);
99     desc.setPluginGrouping(kPluginGrouping);
100     desc.setPluginDescription(kPluginDescription);
101     desc.addSupportedContext(eContextGeneral);
102     desc.addSupportedContext(eContextFilter);
103     desc.addSupportedBitDepth(eBitDepthFloat);
104     desc.setSupportsTiles(kSupportsTiles);
105     desc.setSupportsMultiResolution(kSupportsMultiResolution);
106     desc.setRenderThreadSafety(kRenderThreadSafety);
107     desc.setHostFrameThreading(kHostFrameThreading);
108     desc.setHostMaskingEnabled(kHostMasking);
109     desc.setHostMixingEnabled(kHostMixing);
110 }
111 
describeInContext(ImageEffectDescriptor & desc,ContextEnum context)112 void CLFilterCLPluginFactory::describeInContext(ImageEffectDescriptor &desc, ContextEnum context)
113 {
114     OFX::PageParamDescriptor *page = CLFilterCLPlugin::describeInContextBegin(desc, context);
115     {
116         StringParamDescriptor* param = desc.defineStringParam(kParamKernel);
117         param->setLabel(kParamKernelLabel);
118         param->setHint(kParamKernelHint);
119         param->setStringType(eStringTypeMultiLine);
120         param->setAnimates(true);
121         param->setDefault(kParamKernelDefault);
122         page->addChild(*param);
123     }
124     CLFilterCLPlugin::describeInContextEnd(desc, context, page);
125 }
126 
127 OFX::ImageEffect*
createInstance(OfxImageEffectHandle handle,ContextEnum)128 CLFilterCLPluginFactory::createInstance(OfxImageEffectHandle handle, ContextEnum /*context*/)
129 {
130     return new CLFilterCLPlugin(handle);
131 }
132 
133 static CLFilterCLPluginFactory p(kPluginIdentifier, kPluginVersionMajor, kPluginVersionMinor);
134 mRegisterPluginFactoryInstance(p)
135 
136 OFXS_NAMESPACE_ANONYMOUS_EXIT
137