Replace scene pointer with scene name to prevent possible misusages
[blender.git] / source / blender / compositor / operations / COM_CompositorOperation.cpp
1 /*
2  * Copyright 2011, Blender Foundation.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program 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 this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * Contributor:
19  *              Jeroen Bakker
20  *              Monique Dewanchand
21  */
22
23 #include "COM_CompositorOperation.h"
24 #include "COM_SocketConnection.h"
25 #include "BLI_listbase.h"
26 #include "DNA_scene_types.h"
27 #include "BKE_image.h"
28
29 extern "C" {
30         #include "BLI_threads.h"
31         #include "RE_pipeline.h"
32         #include "RE_shader_ext.h"
33         #include "RE_render_ext.h"
34         #include "MEM_guardedalloc.h"
35         #include "render_types.h"
36 }
37 #include "PIL_time.h"
38
39
40 CompositorOperation::CompositorOperation() : NodeOperation()
41 {
42         this->addInputSocket(COM_DT_COLOR);
43         this->addInputSocket(COM_DT_VALUE);
44         this->addInputSocket(COM_DT_VALUE);
45
46         this->setRenderData(NULL);
47         this->m_outputBuffer = NULL;
48         this->m_depthBuffer = NULL;
49         this->m_imageInput = NULL;
50         this->m_alphaInput = NULL;
51         this->m_depthInput = NULL;
52
53         this->m_sceneName[0] = '\0';
54 }
55
56 void CompositorOperation::initExecution()
57 {
58         // When initializing the tree during initial load the width and height can be zero.
59         this->m_imageInput = getInputSocketReader(0);
60         this->m_alphaInput = getInputSocketReader(1);
61         this->m_depthInput = getInputSocketReader(2);
62         if (this->getWidth() * this->getHeight() != 0) {
63                 this->m_outputBuffer = (float *) MEM_callocN(this->getWidth() * this->getHeight() * 4 * sizeof(float), "CompositorOperation");
64         }
65         if (this->m_depthInput != NULL) {
66                 this->m_depthBuffer = (float *) MEM_callocN(this->getWidth() * this->getHeight() * sizeof(float), "CompositorOperation");
67         }
68 }
69
70 void CompositorOperation::deinitExecution()
71 {
72         if (!isBreaked()) {
73                 Render *re = RE_GetRender(this->m_sceneName);
74                 RenderResult *rr = RE_AcquireResultWrite(re);
75
76                 if (rr) {
77                         if (rr->rectf != NULL) {
78                                 MEM_freeN(rr->rectf);
79                         }
80                         rr->rectf = this->m_outputBuffer;
81                         if (rr->rectz != NULL) {
82                                 MEM_freeN(rr->rectz);
83                         }
84                         rr->rectz = this->m_depthBuffer;
85                 }
86                 else {
87                         if (this->m_outputBuffer) {
88                                 MEM_freeN(this->m_outputBuffer);
89                         }
90                         if (this->m_depthBuffer) {
91                                 MEM_freeN(this->m_depthBuffer);
92                         }
93                 }
94
95                 BLI_lock_thread(LOCK_DRAW_IMAGE);
96                 BKE_image_signal(BKE_image_verify_viewer(IMA_TYPE_R_RESULT, "Render Result"), NULL, IMA_SIGNAL_FREE);
97                 BLI_unlock_thread(LOCK_DRAW_IMAGE);
98
99                 if (re) {
100                         RE_ReleaseResult(re);
101                         re = NULL;
102                 }
103         }
104         else {
105                 if (this->m_outputBuffer) {
106                         MEM_freeN(this->m_outputBuffer);
107                 }
108                 if (this->m_depthBuffer) {
109                         MEM_freeN(this->m_depthBuffer);
110                 }
111         }
112
113         this->m_outputBuffer = NULL;
114         this->m_depthBuffer = NULL;
115         this->m_imageInput = NULL;
116         this->m_alphaInput = NULL;
117         this->m_depthInput = NULL;
118 }
119
120
121 void CompositorOperation::executeRegion(rcti *rect, unsigned int tileNumber)
122 {
123         float color[8]; // 7 is enough
124         float *buffer = this->m_outputBuffer;
125         float *zbuffer = this->m_depthBuffer;
126
127         if (!buffer) return;
128         int x1 = rect->xmin;
129         int y1 = rect->ymin;
130         int x2 = rect->xmax;
131         int y2 = rect->ymax;
132         int offset = (y1 * this->getWidth() + x1);
133         int add = (this->getWidth() - (x2 - x1));
134         int offset4 = offset * COM_NUMBER_OF_CHANNELS;
135         int x;
136         int y;
137         bool breaked = false;
138
139         for (y = y1; y < y2 && (!breaked); y++) {
140                 for (x = x1; x < x2 && (!breaked); x++) {
141                         this->m_imageInput->read(color, x, y, COM_PS_NEAREST);
142                         if (this->m_alphaInput != NULL) {
143                                 this->m_alphaInput->read(&(color[3]), x, y, COM_PS_NEAREST);
144                         }
145                         copy_v4_v4(buffer + offset4, color);
146
147                         if (this->m_depthInput != NULL) {
148                                 this->m_depthInput->read(color, x, y, COM_PS_NEAREST);
149                                 zbuffer[offset] = color[0];
150                         }
151                         offset4 += COM_NUMBER_OF_CHANNELS;
152                         offset++;
153                         if (isBreaked()) {
154                                 breaked = true;
155                         }
156                 }
157                 offset += add;
158                 offset4 += add * COM_NUMBER_OF_CHANNELS;
159         }
160 }
161
162 void CompositorOperation::determineResolution(unsigned int resolution[], unsigned int preferredResolution[])
163 {
164         int width = this->m_rd->xsch * this->m_rd->size / 100;
165         int height = this->m_rd->ysch * this->m_rd->size / 100;
166
167         // check actual render resolution with cropping it may differ with cropped border.rendering
168         // FIX for: [31777] Border Crop gives black (easy)
169         Render *re = RE_GetRender(this->m_sceneName);
170         if (re) {
171                 RenderResult *rr = RE_AcquireResultRead(re);
172                 if (rr) {
173                         width = rr->rectx;
174                         height = rr->recty;
175                 }
176                 RE_ReleaseResult(re);
177         }
178
179         preferredResolution[0] = width;
180         preferredResolution[1] = height;
181
182         NodeOperation::determineResolution(resolution, preferredResolution);
183
184         resolution[0] = width;
185         resolution[1] = height;
186 }