1 
2 //
3 // This source file is part of appleseed.
4 // Visit https://appleseedhq.net/ for additional information and resources.
5 //
6 // This software is released under the MIT license.
7 //
8 // Copyright (c) 2012-2013 Esteban Tovagliari, Jupiter Jazz Limited
9 // Copyright (c) 2014-2018 Esteban Tovagliari, The appleseedhq Organization
10 //
11 // Permission is hereby granted, free of charge, to any person obtaining a copy
12 // of this software and associated documentation files (the "Software"), to deal
13 // in the Software without restriction, including without limitation the rights
14 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 // copies of the Software, and to permit persons to whom the Software is
16 // furnished to do so, subject to the following conditions:
17 //
18 // The above copyright notice and this permission notice shall be included in
19 // all copies or substantial portions of the Software.
20 //
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27 // THE SOFTWARE.
28 //
29 
30 // appleseed.python headers.
31 #include "gillocks.h"
32 
33 // appleseed.renderer headers.
34 #include "renderer/api/frame.h"
35 #include "renderer/kernel/rendering/itilecallback.h"
36 
37 // appleseed.foundation headers.
38 #include "foundation/platform/compiler.h"
39 #include "foundation/platform/python.h"
40 
41 namespace bpy = boost::python;
42 using namespace foundation;
43 using namespace renderer;
44 
45 namespace
46 {
47     class ITileCallbackWrapper
48       : public ITileCallback
49       , public bpy::wrapper<ITileCallback>
50     {
51       public:
release()52         void release() override
53         {
54             delete this;
55         }
56 
on_tiled_frame_begin(const Frame * frame)57         void on_tiled_frame_begin(const Frame* frame) override
58         {
59             // Lock Python's global interpreter lock (it was released in MasterRenderer.render).
60             ScopedGILLock lock;
61 
62             if (bpy::override f = this->get_override("on_tiled_frame_begin"))
63                 f(bpy::ptr(frame));
64         }
65 
default_on_tiled_frame_begin(const Frame * frame)66         void default_on_tiled_frame_begin(const Frame* frame)
67         {
68         }
69 
on_tiled_frame_end(const Frame * frame)70         void on_tiled_frame_end(const Frame* frame) override
71         {
72             // Lock Python's global interpreter lock (it was released in MasterRenderer.render).
73             ScopedGILLock lock;
74 
75             if (bpy::override f = this->get_override("on_tiled_frame_end"))
76                 f(bpy::ptr(frame));
77         }
78 
default_on_tiled_frame_end(const Frame * frame)79         void default_on_tiled_frame_end(const Frame* frame)
80         {
81         }
82 
on_tile_begin(const Frame * frame,const size_t tile_x,const size_t tile_y)83         void on_tile_begin(
84             const Frame*    frame,
85             const size_t    tile_x,
86             const size_t    tile_y) override
87         {
88             // Lock Python's global interpreter lock (it was released in MasterRenderer.render).
89             ScopedGILLock lock;
90 
91             if (bpy::override f = this->get_override("on_tile_begin"))
92                 f(bpy::ptr(frame), tile_x, tile_y);
93         }
94 
default_on_tile_begin(const Frame * frame,const size_t tile_x,const size_t tile_y)95         void default_on_tile_begin(
96             const Frame*    frame,
97             const size_t    tile_x,
98             const size_t    tile_y)
99         {
100         }
101 
on_tile_end(const Frame * frame,const size_t tile_x,const size_t tile_y)102         void on_tile_end(
103             const Frame*    frame,
104             const size_t    tile_x,
105             const size_t    tile_y) override
106         {
107             // Lock Python's global interpreter lock (it was released in MasterRenderer.render).
108             ScopedGILLock lock;
109 
110             if (bpy::override f = this->get_override("on_tile_end"))
111                 f(bpy::ptr(frame), tile_x, tile_y);
112         }
113 
default_on_tile_end(const Frame * frame,const size_t tile_x,const size_t tile_y)114         void default_on_tile_end(
115             const Frame*    frame,
116             const size_t    tile_x,
117             const size_t    tile_y)
118         {
119         }
120 
on_progressive_frame_update(const Frame * frame)121         void on_progressive_frame_update(const Frame* frame) override
122         {
123             // Lock Python's global interpreter lock (it was released in MasterRenderer.render).
124             ScopedGILLock lock;
125 
126             if (bpy::override f = this->get_override("on_progressive_frame_update"))
127                 f(bpy::ptr(frame));
128         }
129 
default_on_progressive_frame_update(const Frame * frame)130         void default_on_progressive_frame_update(const Frame* frame)
131         {
132         }
133     };
134 }
135 
bind_tile_callback()136 void bind_tile_callback()
137 {
138     bpy::class_<ITileCallbackWrapper, boost::noncopyable>("ITileCallback")
139         .def("on_tiled_frame_begin", &ITileCallback::on_tiled_frame_begin, &ITileCallbackWrapper::default_on_tiled_frame_begin)
140         .def("on_tiled_frame_end", &ITileCallback::on_tiled_frame_end, &ITileCallbackWrapper::default_on_tiled_frame_end)
141         .def("on_tile_begin", &ITileCallback::on_tile_begin, &ITileCallbackWrapper::default_on_tile_begin)
142         .def("on_tile_end", &ITileCallback::on_tile_end, &ITileCallbackWrapper::default_on_tile_end)
143         .def("on_progressive_frame_update", &ITileCallback::on_progressive_frame_update, &ITileCallbackWrapper::default_on_progressive_frame_update);
144 }
145