Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2019-04-17 07:17:24 +0300
committerCampbell Barton <ideasman42@gmail.com>2019-04-17 07:21:24 +0300
commite12c08e8d170b7ca40f204a5b0423c23a9fbc2c1 (patch)
tree8cf3453d12edb177a218ef8009357518ec6cab6a /source/blender/compositor/intern
parentb3dabc200a4b0399ec6b81f2ff2730d07b44fcaa (diff)
ClangFormat: apply to source, most of intern
Apply clang format as proposed in T53211. For details on usage and instructions for migrating branches without conflicts, see: https://wiki.blender.org/wiki/Tools/ClangFormat
Diffstat (limited to 'source/blender/compositor/intern')
-rw-r--r--source/blender/compositor/intern/COM_CPUDevice.cpp16
-rw-r--r--source/blender/compositor/intern/COM_CPUDevice.h23
-rw-r--r--source/blender/compositor/intern/COM_ChunkOrder.cpp30
-rw-r--r--source/blender/compositor/intern/COM_ChunkOrder.h44
-rw-r--r--source/blender/compositor/intern/COM_ChunkOrderHotspot.cpp16
-rw-r--r--source/blender/compositor/intern/COM_ChunkOrderHotspot.h19
-rw-r--r--source/blender/compositor/intern/COM_CompositorContext.cpp26
-rw-r--r--source/blender/compositor/intern/COM_CompositorContext.h403
-rw-r--r--source/blender/compositor/intern/COM_Converter.cpp811
-rw-r--r--source/blender/compositor/intern/COM_Converter.h80
-rw-r--r--source/blender/compositor/intern/COM_Debug.cpp733
-rw-r--r--source/blender/compositor/intern/COM_Debug.h70
-rw-r--r--source/blender/compositor/intern/COM_Device.h53
-rw-r--r--source/blender/compositor/intern/COM_ExecutionGroup.cpp964
-rw-r--r--source/blender/compositor/intern/COM_ExecutionGroup.h750
-rw-r--r--source/blender/compositor/intern/COM_ExecutionSystem.cpp333
-rw-r--r--source/blender/compositor/intern/COM_ExecutionSystem.h147
-rw-r--r--source/blender/compositor/intern/COM_MemoryBuffer.cpp268
-rw-r--r--source/blender/compositor/intern/COM_MemoryBuffer.h563
-rw-r--r--source/blender/compositor/intern/COM_MemoryProxy.cpp27
-rw-r--r--source/blender/compositor/intern/COM_MemoryProxy.h167
-rw-r--r--source/blender/compositor/intern/COM_Node.cpp186
-rw-r--r--source/blender/compositor/intern/COM_Node.h487
-rw-r--r--source/blender/compositor/intern/COM_NodeConverter.cpp97
-rw-r--r--source/blender/compositor/intern/COM_NodeConverter.h154
-rw-r--r--source/blender/compositor/intern/COM_NodeGraph.cpp394
-rw-r--r--source/blender/compositor/intern/COM_NodeGraph.h157
-rw-r--r--source/blender/compositor/intern/COM_NodeOperation.cpp258
-rw-r--r--source/blender/compositor/intern/COM_NodeOperation.h760
-rw-r--r--source/blender/compositor/intern/COM_NodeOperationBuilder.cpp953
-rw-r--r--source/blender/compositor/intern/COM_NodeOperationBuilder.h237
-rw-r--r--source/blender/compositor/intern/COM_OpenCLDevice.cpp334
-rw-r--r--source/blender/compositor/intern/COM_OpenCLDevice.h174
-rw-r--r--source/blender/compositor/intern/COM_SingleThreadedOperation.cpp35
-rw-r--r--source/blender/compositor/intern/COM_SingleThreadedOperation.h50
-rw-r--r--source/blender/compositor/intern/COM_SocketReader.h178
-rw-r--r--source/blender/compositor/intern/COM_WorkPackage.cpp4
-rw-r--r--source/blender/compositor/intern/COM_WorkPackage.h57
-rw-r--r--source/blender/compositor/intern/COM_WorkScheduler.cpp460
-rw-r--r--source/blender/compositor/intern/COM_WorkScheduler.h138
-rw-r--r--source/blender/compositor/intern/COM_compositor.cpp151
41 files changed, 5756 insertions, 5051 deletions
diff --git a/source/blender/compositor/intern/COM_CPUDevice.cpp b/source/blender/compositor/intern/COM_CPUDevice.cpp
index 102a882876b..bcb14e4dbb2 100644
--- a/source/blender/compositor/intern/COM_CPUDevice.cpp
+++ b/source/blender/compositor/intern/COM_CPUDevice.cpp
@@ -18,21 +18,19 @@
#include "COM_CPUDevice.h"
-CPUDevice::CPUDevice(int thread_id)
- : Device(),
- m_thread_id(thread_id)
+CPUDevice::CPUDevice(int thread_id) : Device(), m_thread_id(thread_id)
{
}
void CPUDevice::execute(WorkPackage *work)
{
- const unsigned int chunkNumber = work->getChunkNumber();
- ExecutionGroup *executionGroup = work->getExecutionGroup();
- rcti rect;
+ const unsigned int chunkNumber = work->getChunkNumber();
+ ExecutionGroup *executionGroup = work->getExecutionGroup();
+ rcti rect;
- executionGroup->determineChunkRect(&rect, chunkNumber);
+ executionGroup->determineChunkRect(&rect, chunkNumber);
- executionGroup->getOutputOperation()->executeRegion(&rect, chunkNumber);
+ executionGroup->getOutputOperation()->executeRegion(&rect, chunkNumber);
- executionGroup->finalizeChunkExecution(chunkNumber, NULL);
+ executionGroup->finalizeChunkExecution(chunkNumber, NULL);
}
diff --git a/source/blender/compositor/intern/COM_CPUDevice.h b/source/blender/compositor/intern/COM_CPUDevice.h
index 36016a44252..d82046a729f 100644
--- a/source/blender/compositor/intern/COM_CPUDevice.h
+++ b/source/blender/compositor/intern/COM_CPUDevice.h
@@ -26,19 +26,22 @@
* \note for every hardware thread in the system a CPUDevice instance will exist in the workscheduler
*/
class CPUDevice : public Device {
-public:
- CPUDevice(int thread_id);
+ public:
+ CPUDevice(int thread_id);
- /**
- * \brief execute a WorkPackage
- * \param work: the WorkPackage to execute
- */
- void execute(WorkPackage *work);
+ /**
+ * \brief execute a WorkPackage
+ * \param work: the WorkPackage to execute
+ */
+ void execute(WorkPackage *work);
- int thread_id() { return m_thread_id; }
+ int thread_id()
+ {
+ return m_thread_id;
+ }
-protected:
- int m_thread_id;
+ protected:
+ int m_thread_id;
};
#endif
diff --git a/source/blender/compositor/intern/COM_ChunkOrder.cpp b/source/blender/compositor/intern/COM_ChunkOrder.cpp
index f26a8af1f5c..7c9e5013c5d 100644
--- a/source/blender/compositor/intern/COM_ChunkOrder.cpp
+++ b/source/blender/compositor/intern/COM_ChunkOrder.cpp
@@ -21,27 +21,27 @@
ChunkOrder::ChunkOrder()
{
- this->m_distance = 0.0;
- this->m_number = 0;
- this->m_x = 0;
- this->m_y = 0;
+ this->m_distance = 0.0;
+ this->m_number = 0;
+ this->m_x = 0;
+ this->m_y = 0;
}
void ChunkOrder::determineDistance(ChunkOrderHotspot **hotspots, unsigned int numberOfHotspots)
{
- unsigned int index;
- double distance = FLT_MAX;
- for (index = 0; index < numberOfHotspots; index++) {
- ChunkOrderHotspot *hotspot = hotspots[index];
- double ndistance = hotspot->determineDistance(this->m_x, this->m_y);
- if (ndistance < distance) {
- distance = ndistance;
- }
- }
- this->m_distance = distance;
+ unsigned int index;
+ double distance = FLT_MAX;
+ for (index = 0; index < numberOfHotspots; index++) {
+ ChunkOrderHotspot *hotspot = hotspots[index];
+ double ndistance = hotspot->determineDistance(this->m_x, this->m_y);
+ if (ndistance < distance) {
+ distance = ndistance;
+ }
+ }
+ this->m_distance = distance;
}
bool operator<(const ChunkOrder &a, const ChunkOrder &b)
{
- return a.m_distance < b.m_distance;
+ return a.m_distance < b.m_distance;
}
diff --git a/source/blender/compositor/intern/COM_ChunkOrder.h b/source/blender/compositor/intern/COM_ChunkOrder.h
index 52c0e0a800a..e75c07136b4 100644
--- a/source/blender/compositor/intern/COM_ChunkOrder.h
+++ b/source/blender/compositor/intern/COM_ChunkOrder.h
@@ -21,21 +21,37 @@
#include "COM_ChunkOrderHotspot.h"
class ChunkOrder {
-private:
- unsigned int m_number;
- int m_x;
- int m_y;
- double m_distance;
-public:
- ChunkOrder();
- void determineDistance(ChunkOrderHotspot **hotspots, unsigned int numberOfHotspots);
- friend bool operator<(const ChunkOrder &a, const ChunkOrder &b);
+ private:
+ unsigned int m_number;
+ int m_x;
+ int m_y;
+ double m_distance;
- void setChunkNumber(unsigned int chunknumber) { this->m_number = chunknumber; }
- void setX(int x) { this->m_x = x; }
- void setY(int y) { this->m_y = y; }
- unsigned int getChunkNumber() { return this->m_number; }
- double getDistance() { return this->m_distance; }
+ public:
+ ChunkOrder();
+ void determineDistance(ChunkOrderHotspot **hotspots, unsigned int numberOfHotspots);
+ friend bool operator<(const ChunkOrder &a, const ChunkOrder &b);
+
+ void setChunkNumber(unsigned int chunknumber)
+ {
+ this->m_number = chunknumber;
+ }
+ void setX(int x)
+ {
+ this->m_x = x;
+ }
+ void setY(int y)
+ {
+ this->m_y = y;
+ }
+ unsigned int getChunkNumber()
+ {
+ return this->m_number;
+ }
+ double getDistance()
+ {
+ return this->m_distance;
+ }
};
#endif
diff --git a/source/blender/compositor/intern/COM_ChunkOrderHotspot.cpp b/source/blender/compositor/intern/COM_ChunkOrderHotspot.cpp
index cf299e8370b..e95dd4233c4 100644
--- a/source/blender/compositor/intern/COM_ChunkOrderHotspot.cpp
+++ b/source/blender/compositor/intern/COM_ChunkOrderHotspot.cpp
@@ -21,16 +21,16 @@
ChunkOrderHotspot::ChunkOrderHotspot(int x, int y, float addition)
{
- this->m_x = x;
- this->m_y = y;
- this->m_addition = addition;
+ this->m_x = x;
+ this->m_y = y;
+ this->m_addition = addition;
}
double ChunkOrderHotspot::determineDistance(int x, int y)
{
- int dx = x - this->m_x;
- int dy = y - this->m_y;
- double result = sqrt((double)(dx * dx + dy * dy));
- result += (double)this->m_addition;
- return result;
+ int dx = x - this->m_x;
+ int dy = y - this->m_y;
+ double result = sqrt((double)(dx * dx + dy * dy));
+ result += (double)this->m_addition;
+ return result;
}
diff --git a/source/blender/compositor/intern/COM_ChunkOrderHotspot.h b/source/blender/compositor/intern/COM_ChunkOrderHotspot.h
index 2b6b646310b..f0bc92ad6d6 100644
--- a/source/blender/compositor/intern/COM_ChunkOrderHotspot.h
+++ b/source/blender/compositor/intern/COM_ChunkOrderHotspot.h
@@ -20,22 +20,21 @@
#define __COM_CHUNKORDERHOTSPOT_H__
#ifdef WITH_CXX_GUARDEDALLOC
-#include "MEM_guardedalloc.h"
+# include "MEM_guardedalloc.h"
#endif
class ChunkOrderHotspot {
-private:
- int m_x;
- int m_y;
- float m_addition;
-
-public:
- ChunkOrderHotspot(int x, int y, float addition);
- double determineDistance(int x, int y);
+ private:
+ int m_x;
+ int m_y;
+ float m_addition;
+ public:
+ ChunkOrderHotspot(int x, int y, float addition);
+ double determineDistance(int x, int y);
#ifdef WITH_CXX_GUARDEDALLOC
- MEM_CXX_CLASS_ALLOC_FUNCS("COM:ChunkOrderHotspot")
+ MEM_CXX_CLASS_ALLOC_FUNCS("COM:ChunkOrderHotspot")
#endif
};
diff --git a/source/blender/compositor/intern/COM_CompositorContext.cpp b/source/blender/compositor/intern/COM_CompositorContext.cpp
index 0715436bf51..e572fe7c99e 100644
--- a/source/blender/compositor/intern/COM_CompositorContext.cpp
+++ b/source/blender/compositor/intern/COM_CompositorContext.cpp
@@ -22,21 +22,21 @@
CompositorContext::CompositorContext()
{
- this->m_scene = NULL;
- this->m_rd = NULL;
- this->m_quality = COM_QUALITY_HIGH;
- this->m_hasActiveOpenCLDevices = false;
- this->m_fastCalculation = false;
- this->m_viewSettings = NULL;
- this->m_displaySettings = NULL;
+ this->m_scene = NULL;
+ this->m_rd = NULL;
+ this->m_quality = COM_QUALITY_HIGH;
+ this->m_hasActiveOpenCLDevices = false;
+ this->m_fastCalculation = false;
+ this->m_viewSettings = NULL;
+ this->m_displaySettings = NULL;
}
int CompositorContext::getFramenumber() const
{
- if (this->m_rd) {
- return this->m_rd->cfra;
- }
- else {
- return -1; /* this should never happen */
- }
+ if (this->m_rd) {
+ return this->m_rd->cfra;
+ }
+ else {
+ return -1; /* this should never happen */
+ }
}
diff --git a/source/blender/compositor/intern/COM_CompositorContext.h b/source/blender/compositor/intern/COM_CompositorContext.h
index e36dd5ac2aa..466779ec9bd 100644
--- a/source/blender/compositor/intern/COM_CompositorContext.h
+++ b/source/blender/compositor/intern/COM_CompositorContext.h
@@ -31,172 +31,243 @@
* \brief Overall context of the compositor
*/
class CompositorContext {
-private:
- /**
- * \brief The rendering field describes if we are rendering (F12) or if we are editing (Node editor)
- * This field is initialized in ExecutionSystem and must only be read from that point on.
- * \see ExecutionSystem
- */
- bool m_rendering;
-
- /**
- * \brief The quality of the composite.
- * This field is initialized in ExecutionSystem and must only be read from that point on.
- * \see ExecutionSystem
- */
- CompositorQuality m_quality;
-
- Scene *m_scene;
-
- /**
- * \brief Reference to the render data that is being composited.
- * This field is initialized in ExecutionSystem and must only be read from that point on.
- * \see ExecutionSystem
- */
- RenderData *m_rd;
-
- /**
- * \brief reference to the bNodeTree
- * This field is initialized in ExecutionSystem and must only be read from that point on.
- * \see ExecutionSystem
- */
- bNodeTree *m_bnodetree;
-
- /**
- * \brief Preview image hash table
- * This field is initialized in ExecutionSystem and must only be read from that point on.
- */
- bNodeInstanceHash *m_previews;
-
- /**
- * \brief does this system have active opencl devices?
- */
- bool m_hasActiveOpenCLDevices;
-
- /**
- * \brief Skip slow nodes
- */
- bool m_fastCalculation;
-
- /* \brief color management settings */
- const ColorManagedViewSettings *m_viewSettings;
- const ColorManagedDisplaySettings *m_displaySettings;
-
- /**
- * \brief active rendering view name
- */
- const char *m_viewName;
-
-public:
- /**
- * \brief constructor initializes the context with default values.
- */
- CompositorContext();
-
- /**
- * \brief set the rendering field of the context
- */
- void setRendering(bool rendering) { this->m_rendering = rendering; }
-
- /**
- * \brief get the rendering field of the context
- */
- bool isRendering() const { return this->m_rendering; }
-
- /**
- * \brief set the scene of the context
- */
- void setRenderData(RenderData *rd) { this->m_rd = rd; }
-
- /**
- * \brief set the bnodetree of the context
- */
- void setbNodeTree(bNodeTree *bnodetree) { this->m_bnodetree = bnodetree; }
-
- /**
- * \brief get the bnodetree of the context
- */
- const bNodeTree *getbNodeTree() const { return this->m_bnodetree; }
-
- /**
- * \brief get the scene of the context
- */
- const RenderData *getRenderData() const { return this->m_rd; }
-
- void setScene(Scene *scene) { m_scene = scene; }
- Scene *getScene() const { return m_scene; }
-
- /**
- * \brief set the preview image hash table
- */
- void setPreviewHash(bNodeInstanceHash *previews) { this->m_previews = previews; }
-
- /**
- * \brief get the preview image hash table
- */
- bNodeInstanceHash *getPreviewHash() const { return this->m_previews; }
-
- /**
- * \brief set view settings of color color management
- */
- void setViewSettings(const ColorManagedViewSettings *viewSettings) { this->m_viewSettings = viewSettings; }
-
- /**
- * \brief get view settings of color color management
- */
- const ColorManagedViewSettings *getViewSettings() const { return this->m_viewSettings; }
-
- /**
- * \brief set display settings of color color management
- */
- void setDisplaySettings(const ColorManagedDisplaySettings *displaySettings) { this->m_displaySettings = displaySettings; }
-
- /**
- * \brief get display settings of color color management
- */
- const ColorManagedDisplaySettings *getDisplaySettings() const { return this->m_displaySettings; }
-
- /**
- * \brief set the quality
- */
- void setQuality(CompositorQuality quality) { this->m_quality = quality; }
-
- /**
- * \brief get the quality
- */
- CompositorQuality getQuality() const { return this->m_quality; }
-
- /**
- * \brief get the current framenumber of the scene in this context
- */
- int getFramenumber() const;
-
- /**
- * \brief has this system active openclDevices?
- */
- bool getHasActiveOpenCLDevices() const { return this->m_hasActiveOpenCLDevices; }
-
- /**
- * \brief set has this system active openclDevices?
- */
- void setHasActiveOpenCLDevices(bool hasAvtiveOpenCLDevices) { this->m_hasActiveOpenCLDevices = hasAvtiveOpenCLDevices; }
-
- /**
- * \brief get the active rendering view
- */
- const char *getViewName() const { return this->m_viewName; }
-
- /**
- * \brief set the active rendering view
- */
- void setViewName(const char *viewName) { this->m_viewName = viewName; }
-
- int getChunksize() const { return this->getbNodeTree()->chunksize; }
-
- void setFastCalculation(bool fastCalculation) {this->m_fastCalculation = fastCalculation;}
- bool isFastCalculation() const { return this->m_fastCalculation; }
- bool isGroupnodeBufferEnabled() const { return (this->getbNodeTree()->flag & NTREE_COM_GROUPNODE_BUFFER) != 0; }
+ private:
+ /**
+ * \brief The rendering field describes if we are rendering (F12) or if we are editing (Node editor)
+ * This field is initialized in ExecutionSystem and must only be read from that point on.
+ * \see ExecutionSystem
+ */
+ bool m_rendering;
+
+ /**
+ * \brief The quality of the composite.
+ * This field is initialized in ExecutionSystem and must only be read from that point on.
+ * \see ExecutionSystem
+ */
+ CompositorQuality m_quality;
+
+ Scene *m_scene;
+
+ /**
+ * \brief Reference to the render data that is being composited.
+ * This field is initialized in ExecutionSystem and must only be read from that point on.
+ * \see ExecutionSystem
+ */
+ RenderData *m_rd;
+
+ /**
+ * \brief reference to the bNodeTree
+ * This field is initialized in ExecutionSystem and must only be read from that point on.
+ * \see ExecutionSystem
+ */
+ bNodeTree *m_bnodetree;
+
+ /**
+ * \brief Preview image hash table
+ * This field is initialized in ExecutionSystem and must only be read from that point on.
+ */
+ bNodeInstanceHash *m_previews;
+
+ /**
+ * \brief does this system have active opencl devices?
+ */
+ bool m_hasActiveOpenCLDevices;
+
+ /**
+ * \brief Skip slow nodes
+ */
+ bool m_fastCalculation;
+
+ /* \brief color management settings */
+ const ColorManagedViewSettings *m_viewSettings;
+ const ColorManagedDisplaySettings *m_displaySettings;
+
+ /**
+ * \brief active rendering view name
+ */
+ const char *m_viewName;
+
+ public:
+ /**
+ * \brief constructor initializes the context with default values.
+ */
+ CompositorContext();
+
+ /**
+ * \brief set the rendering field of the context
+ */
+ void setRendering(bool rendering)
+ {
+ this->m_rendering = rendering;
+ }
+
+ /**
+ * \brief get the rendering field of the context
+ */
+ bool isRendering() const
+ {
+ return this->m_rendering;
+ }
+
+ /**
+ * \brief set the scene of the context
+ */
+ void setRenderData(RenderData *rd)
+ {
+ this->m_rd = rd;
+ }
+
+ /**
+ * \brief set the bnodetree of the context
+ */
+ void setbNodeTree(bNodeTree *bnodetree)
+ {
+ this->m_bnodetree = bnodetree;
+ }
+
+ /**
+ * \brief get the bnodetree of the context
+ */
+ const bNodeTree *getbNodeTree() const
+ {
+ return this->m_bnodetree;
+ }
+
+ /**
+ * \brief get the scene of the context
+ */
+ const RenderData *getRenderData() const
+ {
+ return this->m_rd;
+ }
+
+ void setScene(Scene *scene)
+ {
+ m_scene = scene;
+ }
+ Scene *getScene() const
+ {
+ return m_scene;
+ }
+
+ /**
+ * \brief set the preview image hash table
+ */
+ void setPreviewHash(bNodeInstanceHash *previews)
+ {
+ this->m_previews = previews;
+ }
+
+ /**
+ * \brief get the preview image hash table
+ */
+ bNodeInstanceHash *getPreviewHash() const
+ {
+ return this->m_previews;
+ }
+
+ /**
+ * \brief set view settings of color color management
+ */
+ void setViewSettings(const ColorManagedViewSettings *viewSettings)
+ {
+ this->m_viewSettings = viewSettings;
+ }
+
+ /**
+ * \brief get view settings of color color management
+ */
+ const ColorManagedViewSettings *getViewSettings() const
+ {
+ return this->m_viewSettings;
+ }
+
+ /**
+ * \brief set display settings of color color management
+ */
+ void setDisplaySettings(const ColorManagedDisplaySettings *displaySettings)
+ {
+ this->m_displaySettings = displaySettings;
+ }
+
+ /**
+ * \brief get display settings of color color management
+ */
+ const ColorManagedDisplaySettings *getDisplaySettings() const
+ {
+ return this->m_displaySettings;
+ }
+
+ /**
+ * \brief set the quality
+ */
+ void setQuality(CompositorQuality quality)
+ {
+ this->m_quality = quality;
+ }
+
+ /**
+ * \brief get the quality
+ */
+ CompositorQuality getQuality() const
+ {
+ return this->m_quality;
+ }
+
+ /**
+ * \brief get the current framenumber of the scene in this context
+ */
+ int getFramenumber() const;
+
+ /**
+ * \brief has this system active openclDevices?
+ */
+ bool getHasActiveOpenCLDevices() const
+ {
+ return this->m_hasActiveOpenCLDevices;
+ }
+
+ /**
+ * \brief set has this system active openclDevices?
+ */
+ void setHasActiveOpenCLDevices(bool hasAvtiveOpenCLDevices)
+ {
+ this->m_hasActiveOpenCLDevices = hasAvtiveOpenCLDevices;
+ }
+
+ /**
+ * \brief get the active rendering view
+ */
+ const char *getViewName() const
+ {
+ return this->m_viewName;
+ }
+
+ /**
+ * \brief set the active rendering view
+ */
+ void setViewName(const char *viewName)
+ {
+ this->m_viewName = viewName;
+ }
+
+ int getChunksize() const
+ {
+ return this->getbNodeTree()->chunksize;
+ }
+
+ void setFastCalculation(bool fastCalculation)
+ {
+ this->m_fastCalculation = fastCalculation;
+ }
+ bool isFastCalculation() const
+ {
+ return this->m_fastCalculation;
+ }
+ bool isGroupnodeBufferEnabled() const
+ {
+ return (this->getbNodeTree()->flag & NTREE_COM_GROUPNODE_BUFFER) != 0;
+ }
};
-
#endif
diff --git a/source/blender/compositor/intern/COM_Converter.cpp b/source/blender/compositor/intern/COM_Converter.cpp
index c97105da385..d7fac8bb5b4 100644
--- a/source/blender/compositor/intern/COM_Converter.cpp
+++ b/source/blender/compositor/intern/COM_Converter.cpp
@@ -117,435 +117,430 @@ extern "C" {
bool Converter::is_fast_node(bNode *b_node)
{
- return !(b_node->type == CMP_NODE_BLUR ||
- b_node->type == CMP_NODE_VECBLUR ||
- b_node->type == CMP_NODE_BILATERALBLUR ||
- b_node->type == CMP_NODE_DEFOCUS ||
- b_node->type == CMP_NODE_BOKEHBLUR ||
- b_node->type == CMP_NODE_GLARE ||
- b_node->type == CMP_NODE_DBLUR ||
- b_node->type == CMP_NODE_MOVIEDISTORTION ||
- b_node->type == CMP_NODE_LENSDIST ||
- b_node->type == CMP_NODE_DOUBLEEDGEMASK ||
- b_node->type == CMP_NODE_DILATEERODE);
+ return !(b_node->type == CMP_NODE_BLUR || b_node->type == CMP_NODE_VECBLUR ||
+ b_node->type == CMP_NODE_BILATERALBLUR || b_node->type == CMP_NODE_DEFOCUS ||
+ b_node->type == CMP_NODE_BOKEHBLUR || b_node->type == CMP_NODE_GLARE ||
+ b_node->type == CMP_NODE_DBLUR || b_node->type == CMP_NODE_MOVIEDISTORTION ||
+ b_node->type == CMP_NODE_LENSDIST || b_node->type == CMP_NODE_DOUBLEEDGEMASK ||
+ b_node->type == CMP_NODE_DILATEERODE);
}
Node *Converter::convert(bNode *b_node)
{
- Node *node = NULL;
+ Node *node = NULL;
- /* ignore undefined nodes with missing or invalid node data */
- if (!nodeIsRegistered(b_node))
- return NULL;
+ /* ignore undefined nodes with missing or invalid node data */
+ if (!nodeIsRegistered(b_node))
+ return NULL;
- switch (b_node->type) {
- case CMP_NODE_COMPOSITE:
- node = new CompositorNode(b_node);
- break;
- case CMP_NODE_R_LAYERS:
- node = new RenderLayersNode(b_node);
- break;
- case CMP_NODE_TEXTURE:
- node = new TextureNode(b_node);
- break;
- case CMP_NODE_RGBTOBW:
- node = new ColorToBWNode(b_node);
- break;
- case CMP_NODE_MIX_RGB:
- node = new MixNode(b_node);
- break;
- case CMP_NODE_TRANSLATE:
- node = new TranslateNode(b_node);
- break;
- case CMP_NODE_SCALE:
- node = new ScaleNode(b_node);
- break;
- case CMP_NODE_ROTATE:
- node = new RotateNode(b_node);
- break;
- case CMP_NODE_FLIP:
- node = new FlipNode(b_node);
- break;
- case CMP_NODE_FILTER:
- node = new FilterNode(b_node);
- break;
- case CMP_NODE_ID_MASK:
- node = new IDMaskNode(b_node);
- break;
- case CMP_NODE_BRIGHTCONTRAST:
- node = new BrightnessNode(b_node);
- break;
- case CMP_NODE_SEPRGBA:
- node = new SeparateRGBANode(b_node);
- break;
- case CMP_NODE_COMBRGBA:
- node = new CombineRGBANode(b_node);
- break;
- case CMP_NODE_SEPHSVA:
- node = new SeparateHSVANode(b_node);
- break;
- case CMP_NODE_COMBHSVA:
- node = new CombineHSVANode(b_node);
- break;
- case CMP_NODE_SEPYUVA:
- node = new SeparateYUVANode(b_node);
- break;
- case CMP_NODE_COMBYUVA:
- node = new CombineYUVANode(b_node);
- break;
- case CMP_NODE_SEPYCCA:
- node = new SeparateYCCANode(b_node);
- break;
- case CMP_NODE_COMBYCCA:
- node = new CombineYCCANode(b_node);
- break;
- case CMP_NODE_ALPHAOVER:
- node = new AlphaOverNode(b_node);
- break;
- case CMP_NODE_COLORBALANCE:
- node = new ColorBalanceNode(b_node);
- break;
- case CMP_NODE_VIEWER:
- node = new ViewerNode(b_node);
- break;
- case CMP_NODE_SPLITVIEWER:
- node = new SplitViewerNode(b_node);
- break;
- case CMP_NODE_INVERT:
- node = new InvertNode(b_node);
- break;
- case NODE_GROUP:
- case NODE_GROUP_INPUT:
- case NODE_GROUP_OUTPUT:
- /* handled in NodeCompiler */
- break;
- case CMP_NODE_NORMAL:
- node = new NormalNode(b_node);
- break;
- case CMP_NODE_NORMALIZE:
- node = new NormalizeNode(b_node);
- break;
- case CMP_NODE_IMAGE:
- node = new ImageNode(b_node);
- break;
- case CMP_NODE_SETALPHA:
- node = new SetAlphaNode(b_node);
- break;
- case CMP_NODE_PREMULKEY:
- node = new ConvertAlphaNode(b_node);
- break;
- case CMP_NODE_MATH:
- node = new MathNode(b_node);
- break;
- case CMP_NODE_HUE_SAT:
- node = new HueSaturationValueNode(b_node);
- break;
- case CMP_NODE_COLORCORRECTION:
- node = new ColorCorrectionNode(b_node);
- break;
- case CMP_NODE_MASK_BOX:
- node = new BoxMaskNode(b_node);
- break;
- case CMP_NODE_MASK_ELLIPSE:
- node = new EllipseMaskNode(b_node);
- break;
- case CMP_NODE_GAMMA:
- node = new GammaNode(b_node);
- break;
- case CMP_NODE_CURVE_RGB:
- node = new ColorCurveNode(b_node);
- break;
- case CMP_NODE_CURVE_VEC:
- node = new VectorCurveNode(b_node);
- break;
- case CMP_NODE_HUECORRECT:
- node = new HueSaturationValueCorrectNode(b_node);
- break;
- case CMP_NODE_MAP_UV:
- node = new MapUVNode(b_node);
- break;
- case CMP_NODE_DISPLACE:
- node = new DisplaceNode(b_node);
- break;
- case CMP_NODE_VALTORGB:
- node = new ColorRampNode(b_node);
- break;
- case CMP_NODE_DIFF_MATTE:
- node = new DifferenceMatteNode(b_node);
- break;
- case CMP_NODE_LUMA_MATTE:
- node = new LuminanceMatteNode(b_node);
- break;
- case CMP_NODE_DIST_MATTE:
- node = new DistanceMatteNode(b_node);
- break;
- case CMP_NODE_CHROMA_MATTE:
- node = new ChromaMatteNode(b_node);
- break;
- case CMP_NODE_COLOR_MATTE:
- node = new ColorMatteNode(b_node);
- break;
- case CMP_NODE_CHANNEL_MATTE:
- node = new ChannelMatteNode(b_node);
- break;
- case CMP_NODE_BLUR:
- node = new BlurNode(b_node);
- break;
- case CMP_NODE_BOKEHIMAGE:
- node = new BokehImageNode(b_node);
- break;
- case CMP_NODE_BOKEHBLUR:
- node = new BokehBlurNode(b_node);
- break;
- case CMP_NODE_DILATEERODE:
- node = new DilateErodeNode(b_node);
- break;
- case CMP_NODE_INPAINT:
- node = new InpaintNode(b_node);
- break;
- case CMP_NODE_DESPECKLE:
- node = new DespeckleNode(b_node);
- break;
- case CMP_NODE_LENSDIST:
- node = new LensDistortionNode(b_node);
- break;
- case CMP_NODE_RGB:
- node = new ColorNode(b_node);
- break;
- case CMP_NODE_VALUE:
- node = new ValueNode(b_node);
- break;
- case CMP_NODE_TIME:
- node = new TimeNode(b_node);
- break;
- case CMP_NODE_DBLUR:
- node = new DirectionalBlurNode(b_node);
- break;
- case CMP_NODE_ZCOMBINE:
- node = new ZCombineNode(b_node);
- break;
- case CMP_NODE_TONEMAP:
- node = new TonemapNode(b_node);
- break;
- case CMP_NODE_SWITCH:
- node = new SwitchNode(b_node);
- break;
- case CMP_NODE_SWITCH_VIEW:
- node = new SwitchViewNode(b_node);
- break;
- case CMP_NODE_GLARE:
- node = new GlareNode(b_node);
- break;
- case CMP_NODE_MOVIECLIP:
- node = new MovieClipNode(b_node);
- break;
- case CMP_NODE_COLOR_SPILL:
- node = new ColorSpillNode(b_node);
- break;
- case CMP_NODE_OUTPUT_FILE:
- node = new OutputFileNode(b_node);
- break;
- case CMP_NODE_MAP_VALUE:
- node = new MapValueNode(b_node);
- break;
- case CMP_NODE_MAP_RANGE:
- node = new MapRangeNode(b_node);
- break;
- case CMP_NODE_TRANSFORM:
- node = new TransformNode(b_node);
- break;
- case CMP_NODE_STABILIZE2D:
- node = new Stabilize2dNode(b_node);
- break;
- case CMP_NODE_BILATERALBLUR:
- node = new BilateralBlurNode(b_node);
- break;
- case CMP_NODE_VECBLUR:
- node = new VectorBlurNode(b_node);
- break;
- case CMP_NODE_MOVIEDISTORTION:
- node = new MovieDistortionNode(b_node);
- break;
- case CMP_NODE_VIEW_LEVELS:
- node = new ViewLevelsNode(b_node);
- break;
- case CMP_NODE_DEFOCUS:
- node = new DefocusNode(b_node);
- break;
- case CMP_NODE_DOUBLEEDGEMASK:
- node = new DoubleEdgeMaskNode(b_node);
- break;
- case CMP_NODE_CROP:
- node = new CropNode(b_node);
- break;
- case CMP_NODE_MASK:
- node = new MaskNode(b_node);
- break;
- case CMP_NODE_KEYINGSCREEN:
- node = new KeyingScreenNode(b_node);
- break;
- case CMP_NODE_KEYING:
- node = new KeyingNode(b_node);
- break;
- case CMP_NODE_TRACKPOS:
- node = new TrackPositionNode(b_node);
- break;
- /* not implemented yet */
- case CMP_NODE_PIXELATE:
- node = new PixelateNode(b_node);
- break;
- case CMP_NODE_PLANETRACKDEFORM:
- node = new PlaneTrackDeformNode(b_node);
- break;
- case CMP_NODE_CORNERPIN:
- node = new CornerPinNode(b_node);
- break;
- case CMP_NODE_SUNBEAMS:
- node = new SunBeamsNode(b_node);
- break;
- case CMP_NODE_CRYPTOMATTE:
- node = new CryptomatteNode(b_node);
- break;
- }
- return node;
+ switch (b_node->type) {
+ case CMP_NODE_COMPOSITE:
+ node = new CompositorNode(b_node);
+ break;
+ case CMP_NODE_R_LAYERS:
+ node = new RenderLayersNode(b_node);
+ break;
+ case CMP_NODE_TEXTURE:
+ node = new TextureNode(b_node);
+ break;
+ case CMP_NODE_RGBTOBW:
+ node = new ColorToBWNode(b_node);
+ break;
+ case CMP_NODE_MIX_RGB:
+ node = new MixNode(b_node);
+ break;
+ case CMP_NODE_TRANSLATE:
+ node = new TranslateNode(b_node);
+ break;
+ case CMP_NODE_SCALE:
+ node = new ScaleNode(b_node);
+ break;
+ case CMP_NODE_ROTATE:
+ node = new RotateNode(b_node);
+ break;
+ case CMP_NODE_FLIP:
+ node = new FlipNode(b_node);
+ break;
+ case CMP_NODE_FILTER:
+ node = new FilterNode(b_node);
+ break;
+ case CMP_NODE_ID_MASK:
+ node = new IDMaskNode(b_node);
+ break;
+ case CMP_NODE_BRIGHTCONTRAST:
+ node = new BrightnessNode(b_node);
+ break;
+ case CMP_NODE_SEPRGBA:
+ node = new SeparateRGBANode(b_node);
+ break;
+ case CMP_NODE_COMBRGBA:
+ node = new CombineRGBANode(b_node);
+ break;
+ case CMP_NODE_SEPHSVA:
+ node = new SeparateHSVANode(b_node);
+ break;
+ case CMP_NODE_COMBHSVA:
+ node = new CombineHSVANode(b_node);
+ break;
+ case CMP_NODE_SEPYUVA:
+ node = new SeparateYUVANode(b_node);
+ break;
+ case CMP_NODE_COMBYUVA:
+ node = new CombineYUVANode(b_node);
+ break;
+ case CMP_NODE_SEPYCCA:
+ node = new SeparateYCCANode(b_node);
+ break;
+ case CMP_NODE_COMBYCCA:
+ node = new CombineYCCANode(b_node);
+ break;
+ case CMP_NODE_ALPHAOVER:
+ node = new AlphaOverNode(b_node);
+ break;
+ case CMP_NODE_COLORBALANCE:
+ node = new ColorBalanceNode(b_node);
+ break;
+ case CMP_NODE_VIEWER:
+ node = new ViewerNode(b_node);
+ break;
+ case CMP_NODE_SPLITVIEWER:
+ node = new SplitViewerNode(b_node);
+ break;
+ case CMP_NODE_INVERT:
+ node = new InvertNode(b_node);
+ break;
+ case NODE_GROUP:
+ case NODE_GROUP_INPUT:
+ case NODE_GROUP_OUTPUT:
+ /* handled in NodeCompiler */
+ break;
+ case CMP_NODE_NORMAL:
+ node = new NormalNode(b_node);
+ break;
+ case CMP_NODE_NORMALIZE:
+ node = new NormalizeNode(b_node);
+ break;
+ case CMP_NODE_IMAGE:
+ node = new ImageNode(b_node);
+ break;
+ case CMP_NODE_SETALPHA:
+ node = new SetAlphaNode(b_node);
+ break;
+ case CMP_NODE_PREMULKEY:
+ node = new ConvertAlphaNode(b_node);
+ break;
+ case CMP_NODE_MATH:
+ node = new MathNode(b_node);
+ break;
+ case CMP_NODE_HUE_SAT:
+ node = new HueSaturationValueNode(b_node);
+ break;
+ case CMP_NODE_COLORCORRECTION:
+ node = new ColorCorrectionNode(b_node);
+ break;
+ case CMP_NODE_MASK_BOX:
+ node = new BoxMaskNode(b_node);
+ break;
+ case CMP_NODE_MASK_ELLIPSE:
+ node = new EllipseMaskNode(b_node);
+ break;
+ case CMP_NODE_GAMMA:
+ node = new GammaNode(b_node);
+ break;
+ case CMP_NODE_CURVE_RGB:
+ node = new ColorCurveNode(b_node);
+ break;
+ case CMP_NODE_CURVE_VEC:
+ node = new VectorCurveNode(b_node);
+ break;
+ case CMP_NODE_HUECORRECT:
+ node = new HueSaturationValueCorrectNode(b_node);
+ break;
+ case CMP_NODE_MAP_UV:
+ node = new MapUVNode(b_node);
+ break;
+ case CMP_NODE_DISPLACE:
+ node = new DisplaceNode(b_node);
+ break;
+ case CMP_NODE_VALTORGB:
+ node = new ColorRampNode(b_node);
+ break;
+ case CMP_NODE_DIFF_MATTE:
+ node = new DifferenceMatteNode(b_node);
+ break;
+ case CMP_NODE_LUMA_MATTE:
+ node = new LuminanceMatteNode(b_node);
+ break;
+ case CMP_NODE_DIST_MATTE:
+ node = new DistanceMatteNode(b_node);
+ break;
+ case CMP_NODE_CHROMA_MATTE:
+ node = new ChromaMatteNode(b_node);
+ break;
+ case CMP_NODE_COLOR_MATTE:
+ node = new ColorMatteNode(b_node);
+ break;
+ case CMP_NODE_CHANNEL_MATTE:
+ node = new ChannelMatteNode(b_node);
+ break;
+ case CMP_NODE_BLUR:
+ node = new BlurNode(b_node);
+ break;
+ case CMP_NODE_BOKEHIMAGE:
+ node = new BokehImageNode(b_node);
+ break;
+ case CMP_NODE_BOKEHBLUR:
+ node = new BokehBlurNode(b_node);
+ break;
+ case CMP_NODE_DILATEERODE:
+ node = new DilateErodeNode(b_node);
+ break;
+ case CMP_NODE_INPAINT:
+ node = new InpaintNode(b_node);
+ break;
+ case CMP_NODE_DESPECKLE:
+ node = new DespeckleNode(b_node);
+ break;
+ case CMP_NODE_LENSDIST:
+ node = new LensDistortionNode(b_node);
+ break;
+ case CMP_NODE_RGB:
+ node = new ColorNode(b_node);
+ break;
+ case CMP_NODE_VALUE:
+ node = new ValueNode(b_node);
+ break;
+ case CMP_NODE_TIME:
+ node = new TimeNode(b_node);
+ break;
+ case CMP_NODE_DBLUR:
+ node = new DirectionalBlurNode(b_node);
+ break;
+ case CMP_NODE_ZCOMBINE:
+ node = new ZCombineNode(b_node);
+ break;
+ case CMP_NODE_TONEMAP:
+ node = new TonemapNode(b_node);
+ break;
+ case CMP_NODE_SWITCH:
+ node = new SwitchNode(b_node);
+ break;
+ case CMP_NODE_SWITCH_VIEW:
+ node = new SwitchViewNode(b_node);
+ break;
+ case CMP_NODE_GLARE:
+ node = new GlareNode(b_node);
+ break;
+ case CMP_NODE_MOVIECLIP:
+ node = new MovieClipNode(b_node);
+ break;
+ case CMP_NODE_COLOR_SPILL:
+ node = new ColorSpillNode(b_node);
+ break;
+ case CMP_NODE_OUTPUT_FILE:
+ node = new OutputFileNode(b_node);
+ break;
+ case CMP_NODE_MAP_VALUE:
+ node = new MapValueNode(b_node);
+ break;
+ case CMP_NODE_MAP_RANGE:
+ node = new MapRangeNode(b_node);
+ break;
+ case CMP_NODE_TRANSFORM:
+ node = new TransformNode(b_node);
+ break;
+ case CMP_NODE_STABILIZE2D:
+ node = new Stabilize2dNode(b_node);
+ break;
+ case CMP_NODE_BILATERALBLUR:
+ node = new BilateralBlurNode(b_node);
+ break;
+ case CMP_NODE_VECBLUR:
+ node = new VectorBlurNode(b_node);
+ break;
+ case CMP_NODE_MOVIEDISTORTION:
+ node = new MovieDistortionNode(b_node);
+ break;
+ case CMP_NODE_VIEW_LEVELS:
+ node = new ViewLevelsNode(b_node);
+ break;
+ case CMP_NODE_DEFOCUS:
+ node = new DefocusNode(b_node);
+ break;
+ case CMP_NODE_DOUBLEEDGEMASK:
+ node = new DoubleEdgeMaskNode(b_node);
+ break;
+ case CMP_NODE_CROP:
+ node = new CropNode(b_node);
+ break;
+ case CMP_NODE_MASK:
+ node = new MaskNode(b_node);
+ break;
+ case CMP_NODE_KEYINGSCREEN:
+ node = new KeyingScreenNode(b_node);
+ break;
+ case CMP_NODE_KEYING:
+ node = new KeyingNode(b_node);
+ break;
+ case CMP_NODE_TRACKPOS:
+ node = new TrackPositionNode(b_node);
+ break;
+ /* not implemented yet */
+ case CMP_NODE_PIXELATE:
+ node = new PixelateNode(b_node);
+ break;
+ case CMP_NODE_PLANETRACKDEFORM:
+ node = new PlaneTrackDeformNode(b_node);
+ break;
+ case CMP_NODE_CORNERPIN:
+ node = new CornerPinNode(b_node);
+ break;
+ case CMP_NODE_SUNBEAMS:
+ node = new SunBeamsNode(b_node);
+ break;
+ case CMP_NODE_CRYPTOMATTE:
+ node = new CryptomatteNode(b_node);
+ break;
+ }
+ return node;
}
NodeOperation *Converter::convertDataType(NodeOperationOutput *from, NodeOperationInput *to)
{
- DataType fromDatatype = from->getDataType();
- DataType toDatatype = to->getDataType();
+ DataType fromDatatype = from->getDataType();
+ DataType toDatatype = to->getDataType();
- if (fromDatatype == COM_DT_VALUE && toDatatype == COM_DT_COLOR) {
- return new ConvertValueToColorOperation();
- }
- else if (fromDatatype == COM_DT_VALUE && toDatatype == COM_DT_VECTOR) {
- return new ConvertValueToVectorOperation();
- }
- else if (fromDatatype == COM_DT_COLOR && toDatatype == COM_DT_VALUE) {
- return new ConvertColorToValueOperation();
- }
- else if (fromDatatype == COM_DT_COLOR && toDatatype == COM_DT_VECTOR) {
- return new ConvertColorToVectorOperation();
- }
- else if (fromDatatype == COM_DT_VECTOR && toDatatype == COM_DT_VALUE) {
- return new ConvertVectorToValueOperation();
- }
- else if (fromDatatype == COM_DT_VECTOR && toDatatype == COM_DT_COLOR) {
- return new ConvertVectorToColorOperation();
- }
+ if (fromDatatype == COM_DT_VALUE && toDatatype == COM_DT_COLOR) {
+ return new ConvertValueToColorOperation();
+ }
+ else if (fromDatatype == COM_DT_VALUE && toDatatype == COM_DT_VECTOR) {
+ return new ConvertValueToVectorOperation();
+ }
+ else if (fromDatatype == COM_DT_COLOR && toDatatype == COM_DT_VALUE) {
+ return new ConvertColorToValueOperation();
+ }
+ else if (fromDatatype == COM_DT_COLOR && toDatatype == COM_DT_VECTOR) {
+ return new ConvertColorToVectorOperation();
+ }
+ else if (fromDatatype == COM_DT_VECTOR && toDatatype == COM_DT_VALUE) {
+ return new ConvertVectorToValueOperation();
+ }
+ else if (fromDatatype == COM_DT_VECTOR && toDatatype == COM_DT_COLOR) {
+ return new ConvertVectorToColorOperation();
+ }
- return NULL;
+ return NULL;
}
-void Converter::convertResolution(NodeOperationBuilder &builder, NodeOperationOutput *fromSocket, NodeOperationInput *toSocket)
+void Converter::convertResolution(NodeOperationBuilder &builder,
+ NodeOperationOutput *fromSocket,
+ NodeOperationInput *toSocket)
{
- InputResizeMode mode = toSocket->getResizeMode();
+ InputResizeMode mode = toSocket->getResizeMode();
- NodeOperation *toOperation = &toSocket->getOperation();
- const float toWidth = toOperation->getWidth();
- const float toHeight = toOperation->getHeight();
- NodeOperation *fromOperation = &fromSocket->getOperation();
- const float fromWidth = fromOperation->getWidth();
- const float fromHeight = fromOperation->getHeight();
- bool doCenter = false;
- bool doScale = false;
- float addX = (toWidth - fromWidth) / 2.0f;
- float addY = (toHeight - fromHeight) / 2.0f;
- float scaleX = 0;
- float scaleY = 0;
+ NodeOperation *toOperation = &toSocket->getOperation();
+ const float toWidth = toOperation->getWidth();
+ const float toHeight = toOperation->getHeight();
+ NodeOperation *fromOperation = &fromSocket->getOperation();
+ const float fromWidth = fromOperation->getWidth();
+ const float fromHeight = fromOperation->getHeight();
+ bool doCenter = false;
+ bool doScale = false;
+ float addX = (toWidth - fromWidth) / 2.0f;
+ float addY = (toHeight - fromHeight) / 2.0f;
+ float scaleX = 0;
+ float scaleY = 0;
- switch (mode) {
- case COM_SC_NO_RESIZE:
- break;
- case COM_SC_CENTER:
- doCenter = true;
- break;
- case COM_SC_FIT_WIDTH:
- doCenter = true;
- doScale = true;
- scaleX = scaleY = toWidth / fromWidth;
- break;
- case COM_SC_FIT_HEIGHT:
- doCenter = true;
- doScale = true;
- scaleX = scaleY = toHeight / fromHeight;
- break;
- case COM_SC_FIT:
- doCenter = true;
- doScale = true;
- scaleX = toWidth / fromWidth;
- scaleY = toHeight / fromHeight;
- if (scaleX < scaleY) {
- scaleX = scaleY;
- }
- else {
- scaleY = scaleX;
- }
- break;
- case COM_SC_STRETCH:
- doCenter = true;
- doScale = true;
- scaleX = toWidth / fromWidth;
- scaleY = toHeight / fromHeight;
- break;
+ switch (mode) {
+ case COM_SC_NO_RESIZE:
+ break;
+ case COM_SC_CENTER:
+ doCenter = true;
+ break;
+ case COM_SC_FIT_WIDTH:
+ doCenter = true;
+ doScale = true;
+ scaleX = scaleY = toWidth / fromWidth;
+ break;
+ case COM_SC_FIT_HEIGHT:
+ doCenter = true;
+ doScale = true;
+ scaleX = scaleY = toHeight / fromHeight;
+ break;
+ case COM_SC_FIT:
+ doCenter = true;
+ doScale = true;
+ scaleX = toWidth / fromWidth;
+ scaleY = toHeight / fromHeight;
+ if (scaleX < scaleY) {
+ scaleX = scaleY;
+ }
+ else {
+ scaleY = scaleX;
+ }
+ break;
+ case COM_SC_STRETCH:
+ doCenter = true;
+ doScale = true;
+ scaleX = toWidth / fromWidth;
+ scaleY = toHeight / fromHeight;
+ break;
+ }
- }
+ if (doCenter) {
+ NodeOperation *first = NULL;
+ ScaleOperation *scaleOperation = NULL;
+ if (doScale) {
+ scaleOperation = new ScaleOperation();
+ scaleOperation->getInputSocket(1)->setResizeMode(COM_SC_NO_RESIZE);
+ scaleOperation->getInputSocket(2)->setResizeMode(COM_SC_NO_RESIZE);
+ first = scaleOperation;
+ SetValueOperation *sxop = new SetValueOperation();
+ sxop->setValue(scaleX);
+ builder.addLink(sxop->getOutputSocket(), scaleOperation->getInputSocket(1));
+ SetValueOperation *syop = new SetValueOperation();
+ syop->setValue(scaleY);
+ builder.addLink(syop->getOutputSocket(), scaleOperation->getInputSocket(2));
+ builder.addOperation(sxop);
+ builder.addOperation(syop);
- if (doCenter) {
- NodeOperation *first = NULL;
- ScaleOperation *scaleOperation = NULL;
- if (doScale) {
- scaleOperation = new ScaleOperation();
- scaleOperation->getInputSocket(1)->setResizeMode(COM_SC_NO_RESIZE);
- scaleOperation->getInputSocket(2)->setResizeMode(COM_SC_NO_RESIZE);
- first = scaleOperation;
- SetValueOperation *sxop = new SetValueOperation();
- sxop->setValue(scaleX);
- builder.addLink(sxop->getOutputSocket(), scaleOperation->getInputSocket(1));
- SetValueOperation *syop = new SetValueOperation();
- syop->setValue(scaleY);
- builder.addLink(syop->getOutputSocket(), scaleOperation->getInputSocket(2));
- builder.addOperation(sxop);
- builder.addOperation(syop);
+ unsigned int resolution[2] = {fromOperation->getWidth(), fromOperation->getHeight()};
+ scaleOperation->setResolution(resolution);
+ sxop->setResolution(resolution);
+ syop->setResolution(resolution);
+ builder.addOperation(scaleOperation);
+ }
- unsigned int resolution[2] = {fromOperation->getWidth(),
- fromOperation->getHeight()};
- scaleOperation->setResolution(resolution);
- sxop->setResolution(resolution);
- syop->setResolution(resolution);
- builder.addOperation(scaleOperation);
- }
+ TranslateOperation *translateOperation = new TranslateOperation();
+ translateOperation->getInputSocket(1)->setResizeMode(COM_SC_NO_RESIZE);
+ translateOperation->getInputSocket(2)->setResizeMode(COM_SC_NO_RESIZE);
+ if (!first)
+ first = translateOperation;
+ SetValueOperation *xop = new SetValueOperation();
+ xop->setValue(addX);
+ builder.addLink(xop->getOutputSocket(), translateOperation->getInputSocket(1));
+ SetValueOperation *yop = new SetValueOperation();
+ yop->setValue(addY);
+ builder.addLink(yop->getOutputSocket(), translateOperation->getInputSocket(2));
+ builder.addOperation(xop);
+ builder.addOperation(yop);
- TranslateOperation *translateOperation = new TranslateOperation();
- translateOperation->getInputSocket(1)->setResizeMode(COM_SC_NO_RESIZE);
- translateOperation->getInputSocket(2)->setResizeMode(COM_SC_NO_RESIZE);
- if (!first) first = translateOperation;
- SetValueOperation *xop = new SetValueOperation();
- xop->setValue(addX);
- builder.addLink(xop->getOutputSocket(), translateOperation->getInputSocket(1));
- SetValueOperation *yop = new SetValueOperation();
- yop->setValue(addY);
- builder.addLink(yop->getOutputSocket(), translateOperation->getInputSocket(2));
- builder.addOperation(xop);
- builder.addOperation(yop);
+ unsigned int resolution[2] = {toOperation->getWidth(), toOperation->getHeight()};
+ translateOperation->setResolution(resolution);
+ xop->setResolution(resolution);
+ yop->setResolution(resolution);
+ builder.addOperation(translateOperation);
- unsigned int resolution[2] = {toOperation->getWidth(),
- toOperation->getHeight()};
- translateOperation->setResolution(resolution);
- xop->setResolution(resolution);
- yop->setResolution(resolution);
- builder.addOperation(translateOperation);
+ if (doScale) {
+ translateOperation->getInputSocket(0)->setResizeMode(COM_SC_NO_RESIZE);
+ builder.addLink(scaleOperation->getOutputSocket(), translateOperation->getInputSocket(0));
+ }
- if (doScale) {
- translateOperation->getInputSocket(0)->setResizeMode(COM_SC_NO_RESIZE);
- builder.addLink(scaleOperation->getOutputSocket(), translateOperation->getInputSocket(0));
- }
-
- /* remove previous link and replace */
- builder.removeInputLink(toSocket);
- first->getInputSocket(0)->setResizeMode(COM_SC_NO_RESIZE);
- toSocket->setResizeMode(COM_SC_NO_RESIZE);
- builder.addLink(fromSocket, first->getInputSocket(0));
- builder.addLink(translateOperation->getOutputSocket(), toSocket);
- }
+ /* remove previous link and replace */
+ builder.removeInputLink(toSocket);
+ first->getInputSocket(0)->setResizeMode(COM_SC_NO_RESIZE);
+ toSocket->setResizeMode(COM_SC_NO_RESIZE);
+ builder.addLink(fromSocket, first->getInputSocket(0));
+ builder.addLink(translateOperation->getOutputSocket(), toSocket);
+ }
}
diff --git a/source/blender/compositor/intern/COM_Converter.h b/source/blender/compositor/intern/COM_Converter.h
index 512bd10f29f..0d7fc40de17 100644
--- a/source/blender/compositor/intern/COM_Converter.h
+++ b/source/blender/compositor/intern/COM_Converter.h
@@ -35,50 +35,52 @@ class NodeOperationBuilder;
* \brief Conversion methods for the compositor
*/
class Converter {
-public:
- /**
- * \brief Convert/wraps a bNode in its Node instance.
- *
- * For all nodetypes a wrapper class is created.
- *
- * \note When adding a new node to blender, this method needs to be changed to return the correct Node instance.
- *
- * \see Node
- */
- static Node *convert(bNode *b_node);
+ public:
+ /**
+ * \brief Convert/wraps a bNode in its Node instance.
+ *
+ * For all nodetypes a wrapper class is created.
+ *
+ * \note When adding a new node to blender, this method needs to be changed to return the correct Node instance.
+ *
+ * \see Node
+ */
+ static Node *convert(bNode *b_node);
- /**
- * \brief True if the node is considered 'fast'.
- *
- * Slow nodes will be skipped if fast execution is required.
- */
- static bool is_fast_node(bNode *b_node);
+ /**
+ * \brief True if the node is considered 'fast'.
+ *
+ * Slow nodes will be skipped if fast execution is required.
+ */
+ static bool is_fast_node(bNode *b_node);
- /**
- * \brief This method will add a datetype conversion rule when the to-socket does not support the from-socket actual data type.
- *
- * \note this method is called when conversion is needed.
- *
- * \param link: the NodeLink what needs conversion
- * \param system: the ExecutionSystem to add the conversion to.
- * \see NodeLink - a link between two sockets
- */
- static NodeOperation *convertDataType(NodeOperationOutput *from, NodeOperationInput *to);
+ /**
+ * \brief This method will add a datetype conversion rule when the to-socket does not support the from-socket actual data type.
+ *
+ * \note this method is called when conversion is needed.
+ *
+ * \param link: the NodeLink what needs conversion
+ * \param system: the ExecutionSystem to add the conversion to.
+ * \see NodeLink - a link between two sockets
+ */
+ static NodeOperation *convertDataType(NodeOperationOutput *from, NodeOperationInput *to);
- /**
- * \brief This method will add a resolution rule based on the settings of the NodeInput.
- *
- * \note Conversion logic is implemented in this method
- * \see InputSocketResizeMode for the possible conversions.
- *
- * \param link: the NodeLink what needs conversion
- * \param system: the ExecutionSystem to add the conversion to.
- * \see NodeLink - a link between two sockets
- */
- static void convertResolution(NodeOperationBuilder &builder, NodeOperationOutput *fromSocket, NodeOperationInput *toSocket);
+ /**
+ * \brief This method will add a resolution rule based on the settings of the NodeInput.
+ *
+ * \note Conversion logic is implemented in this method
+ * \see InputSocketResizeMode for the possible conversions.
+ *
+ * \param link: the NodeLink what needs conversion
+ * \param system: the ExecutionSystem to add the conversion to.
+ * \see NodeLink - a link between two sockets
+ */
+ static void convertResolution(NodeOperationBuilder &builder,
+ NodeOperationOutput *fromSocket,
+ NodeOperationInput *toSocket);
#ifdef WITH_CXX_GUARDEDALLOC
- MEM_CXX_CLASS_ALLOC_FUNCS("COM:Converter")
+ MEM_CXX_CLASS_ALLOC_FUNCS("COM:Converter")
#endif
};
#endif
diff --git a/source/blender/compositor/intern/COM_Debug.cpp b/source/blender/compositor/intern/COM_Debug.cpp
index 59acdad000c..67ac350de83 100644
--- a/source/blender/compositor/intern/COM_Debug.cpp
+++ b/source/blender/compositor/intern/COM_Debug.cpp
@@ -20,29 +20,28 @@
#ifdef COM_DEBUG
-#include <typeinfo>
-#include <map>
-#include <vector>
+# include <typeinfo>
+# include <map>
+# include <vector>
extern "C" {
-#include "BLI_sys_types.h"
-#include "BLI_fileops.h"
-#include "BLI_path_util.h"
-#include "BLI_string.h"
-
-#include "DNA_node_types.h"
-#include "BKE_appdir.h"
-#include "BKE_node.h"
+# include "BLI_sys_types.h"
+# include "BLI_fileops.h"
+# include "BLI_path_util.h"
+# include "BLI_string.h"
+
+# include "DNA_node_types.h"
+# include "BKE_appdir.h"
+# include "BKE_node.h"
}
-#include "COM_Node.h"
-#include "COM_ExecutionSystem.h"
-#include "COM_ExecutionGroup.h"
-
-#include "COM_ReadBufferOperation.h"
-#include "COM_ViewerOperation.h"
-#include "COM_WriteBufferOperation.h"
+# include "COM_Node.h"
+# include "COM_ExecutionSystem.h"
+# include "COM_ExecutionGroup.h"
+# include "COM_ReadBufferOperation.h"
+# include "COM_ViewerOperation.h"
+# include "COM_WriteBufferOperation.h"
int DebugInfo::m_file_index = 0;
DebugInfo::NodeNameMap DebugInfo::m_node_names;
@@ -53,373 +52,465 @@ DebugInfo::GroupStateMap DebugInfo::m_group_states;
std::string DebugInfo::node_name(const Node *node)
{
- NodeNameMap::const_iterator it = m_node_names.find(node);
- if (it != m_node_names.end())
- return it->second;
- else
- return "";
+ NodeNameMap::const_iterator it = m_node_names.find(node);
+ if (it != m_node_names.end())
+ return it->second;
+ else
+ return "";
}
std::string DebugInfo::operation_name(const NodeOperation *op)
{
- OpNameMap::const_iterator it = m_op_names.find(op);
- if (it != m_op_names.end())
- return it->second;
- else
- return "";
+ OpNameMap::const_iterator it = m_op_names.find(op);
+ if (it != m_op_names.end())
+ return it->second;
+ else
+ return "";
}
void DebugInfo::convert_started()
{
- m_op_names.clear();
+ m_op_names.clear();
}
void DebugInfo::execute_started(const ExecutionSystem *system)
{
- m_file_index = 1;
- m_group_states.clear();
- for (ExecutionSystem::Groups::const_iterator it = system->m_groups.begin(); it != system->m_groups.end(); ++it)
- m_group_states[*it] = EG_WAIT;
+ m_file_index = 1;
+ m_group_states.clear();
+ for (ExecutionSystem::Groups::const_iterator it = system->m_groups.begin();
+ it != system->m_groups.end();
+ ++it)
+ m_group_states[*it] = EG_WAIT;
}
void DebugInfo::node_added(const Node *node)
{
- m_node_names[node] = std::string(node->getbNode() ? node->getbNode()->name : "");
+ m_node_names[node] = std::string(node->getbNode() ? node->getbNode()->name : "");
}
void DebugInfo::node_to_operations(const Node *node)
{
- m_current_node_name = m_node_names[node];
+ m_current_node_name = m_node_names[node];
}
void DebugInfo::operation_added(const NodeOperation *operation)
{
- m_op_names[operation] = m_current_node_name;
+ m_op_names[operation] = m_current_node_name;
}
void DebugInfo::operation_read_write_buffer(const NodeOperation *operation)
{
- m_current_op_name = m_op_names[operation];
+ m_current_op_name = m_op_names[operation];
}
void DebugInfo::execution_group_started(const ExecutionGroup *group)
{
- m_group_states[group] = EG_RUNNING;
+ m_group_states[group] = EG_RUNNING;
}
void DebugInfo::execution_group_finished(const ExecutionGroup *group)
{
- m_group_states[group] = EG_FINISHED;
+ m_group_states[group] = EG_FINISHED;
}
-int DebugInfo::graphviz_operation(const ExecutionSystem *system, const NodeOperation *operation, const ExecutionGroup *group, char *str, int maxlen)
+int DebugInfo::graphviz_operation(const ExecutionSystem *system,
+ const NodeOperation *operation,
+ const ExecutionGroup *group,
+ char *str,
+ int maxlen)
{
- int len = 0;
-
- std::string fillcolor = "gainsboro";
- if (operation->isViewerOperation()) {
- const ViewerOperation *viewer = (const ViewerOperation *)operation;
- if (viewer->isActiveViewerOutput()) {
- fillcolor = "lightskyblue1";
- }
- else {
- fillcolor = "lightskyblue3";
- }
- }
- else if (operation->isOutputOperation(system->getContext().isRendering())) {
- fillcolor = "dodgerblue1";
- }
- else if (operation->isSetOperation()) {
- fillcolor = "khaki1";
- }
- else if (operation->isReadBufferOperation()) {
- fillcolor = "darkolivegreen3";
- }
- else if (operation->isWriteBufferOperation()) {
- fillcolor = "darkorange";
- }
-
- len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "// OPERATION: %p\r\n", operation);
- if (group)
- len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "\"O_%p_%p\"", operation, group);
- else
- len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "\"O_%p\"", operation);
- len += snprintf(str + len, maxlen > len ? maxlen - len : 0, " [fillcolor=%s,style=filled,shape=record,label=\"{", fillcolor.c_str());
-
- int totinputs = operation->getNumberOfInputSockets();
- if (totinputs != 0) {
- len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "{");
- for (int k = 0; k < totinputs; k++) {
- NodeOperationInput *socket = operation->getInputSocket(k);
- if (k != 0) {
- len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "|");
- }
- len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "<IN_%p>", socket);
- switch (socket->getDataType()) {
- case COM_DT_VALUE:
- len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "Value");
- break;
- case COM_DT_VECTOR:
- len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "Vector");
- break;
- case COM_DT_COLOR:
- len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "Color");
- break;
- }
- }
- len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "}");
- len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "|");
- }
-
- len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "%s\\n(%s)", m_op_names[operation].c_str(), typeid(*operation).name());
-
- len += snprintf(str + len, maxlen > len ? maxlen - len : 0, " (%u,%u)", operation->getWidth(), operation->getHeight());
-
- int totoutputs = operation->getNumberOfOutputSockets();
- if (totoutputs != 0) {
- len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "|");
- len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "{");
- for (int k = 0; k < totoutputs; k++) {
- NodeOperationOutput *socket = operation->getOutputSocket(k);
- if (k != 0) {
- len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "|");
- }
- len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "<OUT_%p>", socket);
- switch (socket->getDataType()) {
- case COM_DT_VALUE:
- len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "Value");
- break;
- case COM_DT_VECTOR:
- len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "Vector");
- break;
- case COM_DT_COLOR:
- len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "Color");
- break;
- }
- }
- len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "}");
- }
- len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "}\"]");
- len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "\r\n");
-
- return len;
+ int len = 0;
+
+ std::string fillcolor = "gainsboro";
+ if (operation->isViewerOperation()) {
+ const ViewerOperation *viewer = (const ViewerOperation *)operation;
+ if (viewer->isActiveViewerOutput()) {
+ fillcolor = "lightskyblue1";
+ }
+ else {
+ fillcolor = "lightskyblue3";
+ }
+ }
+ else if (operation->isOutputOperation(system->getContext().isRendering())) {
+ fillcolor = "dodgerblue1";
+ }
+ else if (operation->isSetOperation()) {
+ fillcolor = "khaki1";
+ }
+ else if (operation->isReadBufferOperation()) {
+ fillcolor = "darkolivegreen3";
+ }
+ else if (operation->isWriteBufferOperation()) {
+ fillcolor = "darkorange";
+ }
+
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "// OPERATION: %p\r\n", operation);
+ if (group)
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "\"O_%p_%p\"", operation, group);
+ else
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "\"O_%p\"", operation);
+ len += snprintf(str + len,
+ maxlen > len ? maxlen - len : 0,
+ " [fillcolor=%s,style=filled,shape=record,label=\"{",
+ fillcolor.c_str());
+
+ int totinputs = operation->getNumberOfInputSockets();
+ if (totinputs != 0) {
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "{");
+ for (int k = 0; k < totinputs; k++) {
+ NodeOperationInput *socket = operation->getInputSocket(k);
+ if (k != 0) {
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "|");
+ }
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "<IN_%p>", socket);
+ switch (socket->getDataType()) {
+ case COM_DT_VALUE:
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "Value");
+ break;
+ case COM_DT_VECTOR:
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "Vector");
+ break;
+ case COM_DT_COLOR:
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "Color");
+ break;
+ }
+ }
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "}");
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "|");
+ }
+
+ len += snprintf(str + len,
+ maxlen > len ? maxlen - len : 0,
+ "%s\\n(%s)",
+ m_op_names[operation].c_str(),
+ typeid(*operation).name());
+
+ len += snprintf(str + len,
+ maxlen > len ? maxlen - len : 0,
+ " (%u,%u)",
+ operation->getWidth(),
+ operation->getHeight());
+
+ int totoutputs = operation->getNumberOfOutputSockets();
+ if (totoutputs != 0) {
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "|");
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "{");
+ for (int k = 0; k < totoutputs; k++) {
+ NodeOperationOutput *socket = operation->getOutputSocket(k);
+ if (k != 0) {
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "|");
+ }
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "<OUT_%p>", socket);
+ switch (socket->getDataType()) {
+ case COM_DT_VALUE:
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "Value");
+ break;
+ case COM_DT_VECTOR:
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "Vector");
+ break;
+ case COM_DT_COLOR:
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "Color");
+ break;
+ }
+ }
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "}");
+ }
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "}\"]");
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "\r\n");
+
+ return len;
}
int DebugInfo::graphviz_legend_color(const char *name, const char *color, char *str, int maxlen)
{
- int len = 0;
- len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "<TR><TD>%s</TD><TD BGCOLOR=\"%s\"></TD></TR>\r\n", name, color);
- return len;
+ int len = 0;
+ len += snprintf(str + len,
+ maxlen > len ? maxlen - len : 0,
+ "<TR><TD>%s</TD><TD BGCOLOR=\"%s\"></TD></TR>\r\n",
+ name,
+ color);
+ return len;
}
-int DebugInfo::graphviz_legend_line(const char * /*name*/, const char * /*color*/, const char * /*style*/, char *str, int maxlen)
+int DebugInfo::graphviz_legend_line(
+ const char * /*name*/, const char * /*color*/, const char * /*style*/, char *str, int maxlen)
{
- /* XXX TODO */
- int len = 0;
- len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "\r\n");
- return len;
+ /* XXX TODO */
+ int len = 0;
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "\r\n");
+ return len;
}
-int DebugInfo::graphviz_legend_group(const char *name, const char *color, const char * /*style*/, char *str, int maxlen)
+int DebugInfo::graphviz_legend_group(
+ const char *name, const char *color, const char * /*style*/, char *str, int maxlen)
{
- int len = 0;
- len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "<TR><TD>%s</TD><TD CELLPADDING=\"4\"><TABLE BORDER=\"1\" CELLBORDER=\"0\" CELLSPACING=\"0\" CELLPADDING=\"0\"><TR><TD BGCOLOR=\"%s\"></TD></TR></TABLE></TD></TR>\r\n", name, color);
- return len;
+ int len = 0;
+ len += snprintf(str + len,
+ maxlen > len ? maxlen - len : 0,
+ "<TR><TD>%s</TD><TD CELLPADDING=\"4\"><TABLE BORDER=\"1\" CELLBORDER=\"0\" "
+ "CELLSPACING=\"0\" CELLPADDING=\"0\"><TR><TD "
+ "BGCOLOR=\"%s\"></TD></TR></TABLE></TD></TR>\r\n",
+ name,
+ color);
+ return len;
}
int DebugInfo::graphviz_legend(char *str, int maxlen)
{
- int len = 0;
-
- len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "{\r\n");
- len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "rank = sink;\r\n");
- len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "Legend [shape=none, margin=0, label=<\r\n");
-
- len += snprintf(str + len, maxlen > len ? maxlen - len : 0, " <TABLE BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\" CELLPADDING=\"4\">\r\n");
- len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "<TR><TD COLSPAN=\"2\"><B>Legend</B></TD></TR>\r\n");
-
- len += graphviz_legend_color("NodeOperation", "gainsboro", str + len, maxlen > len ? maxlen - len : 0);
- len += graphviz_legend_color("Output", "dodgerblue1", str + len, maxlen > len ? maxlen - len : 0);
- len += graphviz_legend_color("Viewer", "lightskyblue3", str + len, maxlen > len ? maxlen - len : 0);
- len += graphviz_legend_color("Active Viewer", "lightskyblue1", str + len, maxlen > len ? maxlen - len : 0);
- len += graphviz_legend_color("Write Buffer", "darkorange", str + len, maxlen > len ? maxlen - len : 0);
- len += graphviz_legend_color("Read Buffer", "darkolivegreen3", str + len, maxlen > len ? maxlen - len : 0);
- len += graphviz_legend_color("Input Value", "khaki1", str + len, maxlen > len ? maxlen - len : 0);
-
- len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "<TR><TD></TD></TR>\r\n");
-
- len += graphviz_legend_group("Group Waiting", "white", "dashed", str + len, maxlen > len ? maxlen - len : 0);
- len += graphviz_legend_group("Group Running", "firebrick1", "solid", str + len, maxlen > len ? maxlen - len : 0);
- len += graphviz_legend_group("Group Finished", "chartreuse4", "solid", str + len, maxlen > len ? maxlen - len : 0);
-
- len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "</TABLE>\r\n");
- len += snprintf(str + len, maxlen > len ? maxlen - len : 0, ">];\r\n");
- len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "}\r\n");
-
- return len;
+ int len = 0;
+
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "{\r\n");
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "rank = sink;\r\n");
+ len += snprintf(
+ str + len, maxlen > len ? maxlen - len : 0, "Legend [shape=none, margin=0, label=<\r\n");
+
+ len += snprintf(
+ str + len,
+ maxlen > len ? maxlen - len : 0,
+ " <TABLE BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\" CELLPADDING=\"4\">\r\n");
+ len += snprintf(str + len,
+ maxlen > len ? maxlen - len : 0,
+ "<TR><TD COLSPAN=\"2\"><B>Legend</B></TD></TR>\r\n");
+
+ len += graphviz_legend_color(
+ "NodeOperation", "gainsboro", str + len, maxlen > len ? maxlen - len : 0);
+ len += graphviz_legend_color(
+ "Output", "dodgerblue1", str + len, maxlen > len ? maxlen - len : 0);
+ len += graphviz_legend_color(
+ "Viewer", "lightskyblue3", str + len, maxlen > len ? maxlen - len : 0);
+ len += graphviz_legend_color(
+ "Active Viewer", "lightskyblue1", str + len, maxlen > len ? maxlen - len : 0);
+ len += graphviz_legend_color(
+ "Write Buffer", "darkorange", str + len, maxlen > len ? maxlen - len : 0);
+ len += graphviz_legend_color(
+ "Read Buffer", "darkolivegreen3", str + len, maxlen > len ? maxlen - len : 0);
+ len += graphviz_legend_color(
+ "Input Value", "khaki1", str + len, maxlen > len ? maxlen - len : 0);
+
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "<TR><TD></TD></TR>\r\n");
+
+ len += graphviz_legend_group(
+ "Group Waiting", "white", "dashed", str + len, maxlen > len ? maxlen - len : 0);
+ len += graphviz_legend_group(
+ "Group Running", "firebrick1", "solid", str + len, maxlen > len ? maxlen - len : 0);
+ len += graphviz_legend_group(
+ "Group Finished", "chartreuse4", "solid", str + len, maxlen > len ? maxlen - len : 0);
+
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "</TABLE>\r\n");
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, ">];\r\n");
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "}\r\n");
+
+ return len;
}
bool DebugInfo::graphviz_system(const ExecutionSystem *system, char *str, int maxlen)
{
- char strbuf[64];
- int len = 0;
-
- len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "digraph compositorexecution {\r\n");
- len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "ranksep=1.5\r\n");
- len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "rankdir=LR\r\n");
- len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "splines=false\r\n");
-
-#if 0
- for (ExecutionSystem::Operations::const_iterator it = system->m_operations.begin();
- it != system->m_operations.end(); ++it)
- {
- NodeOperation *op = *it;
- len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "// OPERATION: %s\r\n", node->getbNode()->typeinfo->ui_name);
- }
-#endif
-
- int totops = system->m_operations.size();
- int totgroups = system->m_groups.size();
- std::map<NodeOperation *, std::vector<std::string> > op_groups;
- for (int i = 0; i < totgroups; ++i) {
- const ExecutionGroup *group = system->m_groups[i];
-
- len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "// GROUP: %d\r\n", i);
- len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "subgraph cluster_%d{\r\n", i);
- /* used as a check for executing group */
- if (m_group_states[group] == EG_WAIT) {
- len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "style=dashed\r\n");
- }
- else if (m_group_states[group] == EG_RUNNING) {
- len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "style=filled\r\n");
- len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "color=black\r\n");
- len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "fillcolor=firebrick1\r\n");
- }
- else if (m_group_states[group] == EG_FINISHED) {
- len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "style=filled\r\n");
- len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "color=black\r\n");
- len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "fillcolor=chartreuse4\r\n");
- }
-
- for (ExecutionGroup::Operations::const_iterator it = group->m_operations.begin(); it != group->m_operations.end(); ++it) {
- NodeOperation *operation = *it;
-
- sprintf(strbuf, "_%p", group);
- op_groups[operation].push_back(std::string(strbuf));
-
- len += graphviz_operation(system, operation, group, str + len, maxlen > len ? maxlen - len : 0);
- }
-
-// len += snprintf(str+len, maxlen>len ? maxlen-len : 0, "// OUTPUTOPERATION: %p\r\n", group->getOutputOperation());
-// len += snprintf(str+len, maxlen>len ? maxlen-len : 0, " O_%p\r\n", group->getOutputOperation());
- len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "}\r\n");
- }
-
- /* operations not included in any group */
- for (int j = 0; j < totops; ++j) {
- NodeOperation *operation = system->m_operations[j];
- if (op_groups.find(operation) != op_groups.end())
- continue;
-
- op_groups[operation].push_back(std::string(""));
-
- len += graphviz_operation(system, operation, 0, str + len, maxlen > len ? maxlen - len : 0);
- }
-
- for (int i = 0; i < totops; i++) {
- NodeOperation *operation = system->m_operations[i];
-
- if (operation->isReadBufferOperation()) {
- ReadBufferOperation *read = (ReadBufferOperation *)operation;
- WriteBufferOperation *write = read->getMemoryProxy()->getWriteBufferOperation();
- std::vector<std::string> &read_groups = op_groups[read];
- std::vector<std::string> &write_groups = op_groups[write];
-
- for (int k = 0; k < write_groups.size(); ++k) {
- for (int l = 0; l < read_groups.size(); ++l) {
- len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "\"O_%p%s\" -> \"O_%p%s\" [style=dotted]\r\n", write, write_groups[k].c_str(), read, read_groups[l].c_str());
- }
- }
- }
- }
-
- for (int i = 0; i < totops; i++) {
- NodeOperation *op = system->m_operations[i];
-
- for (NodeOperation::Inputs::const_iterator it = op->m_inputs.begin(); it != op->m_inputs.end(); ++it) {
- NodeOperationInput *to = *it;
- NodeOperationOutput *from = to->getLink();
-
- if (!from)
- continue;
-
- std::string color;
- switch (from->getDataType()) {
- case COM_DT_VALUE:
- color = "gray";
- break;
- case COM_DT_VECTOR:
- color = "blue";
- break;
- case COM_DT_COLOR:
- color = "orange";
- break;
- }
-
- NodeOperation *to_op = &to->getOperation();
- NodeOperation *from_op = &from->getOperation();
- std::vector<std::string> &from_groups = op_groups[from_op];
- std::vector<std::string> &to_groups = op_groups[to_op];
-
- len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "// CONNECTION: %p.%p -> %p.%p\r\n",
- from_op, from, to_op, to);
- for (int k = 0; k < from_groups.size(); ++k) {
- for (int l = 0; l < to_groups.size(); ++l) {
- len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "\"O_%p%s\":\"OUT_%p\":e -> \"O_%p%s\":\"IN_%p\":w",
- from_op, from_groups[k].c_str(), from, to_op, to_groups[l].c_str(), to);
- len += snprintf(str + len, maxlen > len ? maxlen - len : 0, " [color=%s]", color.c_str());
- len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "\r\n");
- }
- }
- }
- }
-
- len += graphviz_legend(str + len, maxlen > len ? maxlen - len : 0);
-
- len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "}\r\n");
-
- return (len < maxlen);
+ char strbuf[64];
+ int len = 0;
+
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "digraph compositorexecution {\r\n");
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "ranksep=1.5\r\n");
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "rankdir=LR\r\n");
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "splines=false\r\n");
+
+# if 0
+ for (ExecutionSystem::Operations::const_iterator it = system->m_operations.begin();
+ it != system->m_operations.end(); ++it)
+ {
+ NodeOperation *op = *it;
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "// OPERATION: %s\r\n", node->getbNode()->typeinfo->ui_name);
+ }
+# endif
+
+ int totops = system->m_operations.size();
+ int totgroups = system->m_groups.size();
+ std::map<NodeOperation *, std::vector<std::string>> op_groups;
+ for (int i = 0; i < totgroups; ++i) {
+ const ExecutionGroup *group = system->m_groups[i];
+
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "// GROUP: %d\r\n", i);
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "subgraph cluster_%d{\r\n", i);
+ /* used as a check for executing group */
+ if (m_group_states[group] == EG_WAIT) {
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "style=dashed\r\n");
+ }
+ else if (m_group_states[group] == EG_RUNNING) {
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "style=filled\r\n");
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "color=black\r\n");
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "fillcolor=firebrick1\r\n");
+ }
+ else if (m_group_states[group] == EG_FINISHED) {
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "style=filled\r\n");
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "color=black\r\n");
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "fillcolor=chartreuse4\r\n");
+ }
+
+ for (ExecutionGroup::Operations::const_iterator it = group->m_operations.begin();
+ it != group->m_operations.end();
+ ++it) {
+ NodeOperation *operation = *it;
+
+ sprintf(strbuf, "_%p", group);
+ op_groups[operation].push_back(std::string(strbuf));
+
+ len += graphviz_operation(
+ system, operation, group, str + len, maxlen > len ? maxlen - len : 0);
+ }
+
+ // len += snprintf(str+len, maxlen>len ? maxlen-len : 0, "// OUTPUTOPERATION: %p\r\n", group->getOutputOperation());
+ // len += snprintf(str+len, maxlen>len ? maxlen-len : 0, " O_%p\r\n", group->getOutputOperation());
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "}\r\n");
+ }
+
+ /* operations not included in any group */
+ for (int j = 0; j < totops; ++j) {
+ NodeOperation *operation = system->m_operations[j];
+ if (op_groups.find(operation) != op_groups.end())
+ continue;
+
+ op_groups[operation].push_back(std::string(""));
+
+ len += graphviz_operation(system, operation, 0, str + len, maxlen > len ? maxlen - len : 0);
+ }
+
+ for (int i = 0; i < totops; i++) {
+ NodeOperation *operation = system->m_operations[i];
+
+ if (operation->isReadBufferOperation()) {
+ ReadBufferOperation *read = (ReadBufferOperation *)operation;
+ WriteBufferOperation *write = read->getMemoryProxy()->getWriteBufferOperation();
+ std::vector<std::string> &read_groups = op_groups[read];
+ std::vector<std::string> &write_groups = op_groups[write];
+
+ for (int k = 0; k < write_groups.size(); ++k) {
+ for (int l = 0; l < read_groups.size(); ++l) {
+ len += snprintf(str + len,
+ maxlen > len ? maxlen - len : 0,
+ "\"O_%p%s\" -> \"O_%p%s\" [style=dotted]\r\n",
+ write,
+ write_groups[k].c_str(),
+ read,
+ read_groups[l].c_str());
+ }
+ }
+ }
+ }
+
+ for (int i = 0; i < totops; i++) {
+ NodeOperation *op = system->m_operations[i];
+
+ for (NodeOperation::Inputs::const_iterator it = op->m_inputs.begin(); it != op->m_inputs.end();
+ ++it) {
+ NodeOperationInput *to = *it;
+ NodeOperationOutput *from = to->getLink();
+
+ if (!from)
+ continue;
+
+ std::string color;
+ switch (from->getDataType()) {
+ case COM_DT_VALUE:
+ color = "gray";
+ break;
+ case COM_DT_VECTOR:
+ color = "blue";
+ break;
+ case COM_DT_COLOR:
+ color = "orange";
+ break;
+ }
+
+ NodeOperation *to_op = &to->getOperation();
+ NodeOperation *from_op = &from->getOperation();
+ std::vector<std::string> &from_groups = op_groups[from_op];
+ std::vector<std::string> &to_groups = op_groups[to_op];
+
+ len += snprintf(str + len,
+ maxlen > len ? maxlen - len : 0,
+ "// CONNECTION: %p.%p -> %p.%p\r\n",
+ from_op,
+ from,
+ to_op,
+ to);
+ for (int k = 0; k < from_groups.size(); ++k) {
+ for (int l = 0; l < to_groups.size(); ++l) {
+ len += snprintf(str + len,
+ maxlen > len ? maxlen - len : 0,
+ "\"O_%p%s\":\"OUT_%p\":e -> \"O_%p%s\":\"IN_%p\":w",
+ from_op,
+ from_groups[k].c_str(),
+ from,
+ to_op,
+ to_groups[l].c_str(),
+ to);
+ len += snprintf(
+ str + len, maxlen > len ? maxlen - len : 0, " [color=%s]", color.c_str());
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "\r\n");
+ }
+ }
+ }
+ }
+
+ len += graphviz_legend(str + len, maxlen > len ? maxlen - len : 0);
+
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "}\r\n");
+
+ return (len < maxlen);
}
void DebugInfo::graphviz(const ExecutionSystem *system)
{
- char str[1000000];
- if (graphviz_system(system, str, sizeof(str) - 1)) {
- char basename[FILE_MAX];
- char filename[FILE_MAX];
-
- BLI_snprintf(basename, sizeof(basename), "compositor_%d.dot", m_file_index);
- BLI_join_dirfile(filename, sizeof(filename), BKE_tempdir_session(), basename);
- ++m_file_index;
-
- FILE *fp = BLI_fopen(filename, "wb");
- fputs(str, fp);
- fclose(fp);
- }
+ char str[1000000];
+ if (graphviz_system(system, str, sizeof(str) - 1)) {
+ char basename[FILE_MAX];
+ char filename[FILE_MAX];
+
+ BLI_snprintf(basename, sizeof(basename), "compositor_%d.dot", m_file_index);
+ BLI_join_dirfile(filename, sizeof(filename), BKE_tempdir_session(), basename);
+ ++m_file_index;
+
+ FILE *fp = BLI_fopen(filename, "wb");
+ fputs(str, fp);
+ fclose(fp);
+ }
}
#else
-std::string DebugInfo::node_name(const Node * /*node*/) { return ""; }
-std::string DebugInfo::operation_name(const NodeOperation * /*op*/) { return ""; }
-void DebugInfo::convert_started() {}
-void DebugInfo::execute_started(const ExecutionSystem * /*system*/) {}
-void DebugInfo::node_added(const Node * /*node*/) {}
-void DebugInfo::node_to_operations(const Node * /*node*/) {}
-void DebugInfo::operation_added(const NodeOperation * /*operation*/) {}
-void DebugInfo::operation_read_write_buffer(const NodeOperation * /*operation*/) {}
-void DebugInfo::execution_group_started(const ExecutionGroup * /*group*/) {}
-void DebugInfo::execution_group_finished(const ExecutionGroup * /*group*/) {}
-void DebugInfo::graphviz(const ExecutionSystem * /*system*/) {}
+std::string DebugInfo::node_name(const Node * /*node*/)
+{
+ return "";
+}
+std::string DebugInfo::operation_name(const NodeOperation * /*op*/)
+{
+ return "";
+}
+void DebugInfo::convert_started()
+{
+}
+void DebugInfo::execute_started(const ExecutionSystem * /*system*/)
+{
+}
+void DebugInfo::node_added(const Node * /*node*/)
+{
+}
+void DebugInfo::node_to_operations(const Node * /*node*/)
+{
+}
+void DebugInfo::operation_added(const NodeOperation * /*operation*/)
+{
+}
+void DebugInfo::operation_read_write_buffer(const NodeOperation * /*operation*/)
+{
+}
+void DebugInfo::execution_group_started(const ExecutionGroup * /*group*/)
+{
+}
+void DebugInfo::execution_group_finished(const ExecutionGroup * /*group*/)
+{
+}
+void DebugInfo::graphviz(const ExecutionSystem * /*system*/)
+{
+}
#endif
diff --git a/source/blender/compositor/intern/COM_Debug.h b/source/blender/compositor/intern/COM_Debug.h
index 955bcf120cc..250f360fa35 100644
--- a/source/blender/compositor/intern/COM_Debug.h
+++ b/source/blender/compositor/intern/COM_Debug.h
@@ -30,49 +30,51 @@ class ExecutionSystem;
class ExecutionGroup;
class DebugInfo {
-public:
- typedef enum {
- EG_WAIT,
- EG_RUNNING,
- EG_FINISHED
- } GroupState;
+ public:
+ typedef enum { EG_WAIT, EG_RUNNING, EG_FINISHED } GroupState;
- typedef std::map<const Node *, std::string> NodeNameMap;
- typedef std::map<const NodeOperation *, std::string> OpNameMap;
- typedef std::map<const ExecutionGroup *, GroupState> GroupStateMap;
+ typedef std::map<const Node *, std::string> NodeNameMap;
+ typedef std::map<const NodeOperation *, std::string> OpNameMap;
+ typedef std::map<const ExecutionGroup *, GroupState> GroupStateMap;
- static std::string node_name(const Node *node);
- static std::string operation_name(const NodeOperation *op);
+ static std::string node_name(const Node *node);
+ static std::string operation_name(const NodeOperation *op);
- static void convert_started();
- static void execute_started(const ExecutionSystem *system);
+ static void convert_started();
+ static void execute_started(const ExecutionSystem *system);
- static void node_added(const Node *node);
- static void node_to_operations(const Node *node);
- static void operation_added(const NodeOperation *operation);
- static void operation_read_write_buffer(const NodeOperation *operation);
+ static void node_added(const Node *node);
+ static void node_to_operations(const Node *node);
+ static void operation_added(const NodeOperation *operation);
+ static void operation_read_write_buffer(const NodeOperation *operation);
- static void execution_group_started(const ExecutionGroup *group);
- static void execution_group_finished(const ExecutionGroup *group);
+ static void execution_group_started(const ExecutionGroup *group);
+ static void execution_group_finished(const ExecutionGroup *group);
- static void graphviz(const ExecutionSystem *system);
+ static void graphviz(const ExecutionSystem *system);
#ifdef COM_DEBUG
-protected:
- static int graphviz_operation(const ExecutionSystem *system, const NodeOperation *operation, const ExecutionGroup *group, char *str, int maxlen);
- static int graphviz_legend_color(const char *name, const char *color, char *str, int maxlen);
- static int graphviz_legend_line(const char *name, const char *color, const char *style, char *str, int maxlen);
- static int graphviz_legend_group(const char *name, const char *color, const char *style, char *str, int maxlen);
- static int graphviz_legend(char *str, int maxlen);
- static bool graphviz_system(const ExecutionSystem *system, char *str, int maxlen);
+ protected:
+ static int graphviz_operation(const ExecutionSystem *system,
+ const NodeOperation *operation,
+ const ExecutionGroup *group,
+ char *str,
+ int maxlen);
+ static int graphviz_legend_color(const char *name, const char *color, char *str, int maxlen);
+ static int graphviz_legend_line(
+ const char *name, const char *color, const char *style, char *str, int maxlen);
+ static int graphviz_legend_group(
+ const char *name, const char *color, const char *style, char *str, int maxlen);
+ static int graphviz_legend(char *str, int maxlen);
+ static bool graphviz_system(const ExecutionSystem *system, char *str, int maxlen);
-private:
- static int m_file_index;
- static NodeNameMap m_node_names; /**< map nodes to usable names for debug output */
- static OpNameMap m_op_names; /**< map operations to usable names for debug output */
- static std::string m_current_node_name; /**< base name for all operations added by a node */
- static std::string m_current_op_name; /**< base name for automatic sub-operations */
- static GroupStateMap m_group_states; /**< for visualizing group states */
+ private:
+ static int m_file_index;
+ static NodeNameMap m_node_names; /**< map nodes to usable names for debug output */
+ static OpNameMap m_op_names; /**< map operations to usable names for debug output */
+ static std::string m_current_node_name; /**< base name for all operations added by a node */
+ static std::string m_current_op_name; /**< base name for automatic sub-operations */
+ static GroupStateMap m_group_states; /**< for visualizing group states */
#endif
};
diff --git a/source/blender/compositor/intern/COM_Device.h b/source/blender/compositor/intern/COM_Device.h
index 6767a475c82..8573f69658e 100644
--- a/source/blender/compositor/intern/COM_Device.h
+++ b/source/blender/compositor/intern/COM_Device.h
@@ -28,31 +28,38 @@
*/
class Device {
-public:
- /**
- * \brief Declaration of the virtual destructor
- * \note resolve warning gcc 4.7
- */
- virtual ~Device() {}
-
- /**
- * \brief initialize the device
- */
- virtual bool initialize() { return true; }
-
- /**
- * \brief deinitialize the device
- */
- virtual void deinitialize() {}
-
- /**
- * \brief execute a WorkPackage
- * \param work: the WorkPackage to execute
- */
- virtual void execute(WorkPackage *work) = 0;
+ public:
+ /**
+ * \brief Declaration of the virtual destructor
+ * \note resolve warning gcc 4.7
+ */
+ virtual ~Device()
+ {
+ }
+
+ /**
+ * \brief initialize the device
+ */
+ virtual bool initialize()
+ {
+ return true;
+ }
+
+ /**
+ * \brief deinitialize the device
+ */
+ virtual void deinitialize()
+ {
+ }
+
+ /**
+ * \brief execute a WorkPackage
+ * \param work: the WorkPackage to execute
+ */
+ virtual void execute(WorkPackage *work) = 0;
#ifdef WITH_CXX_GUARDEDALLOC
- MEM_CXX_CLASS_ALLOC_FUNCS("COM:Device")
+ MEM_CXX_CLASS_ALLOC_FUNCS("COM:Device")
#endif
};
diff --git a/source/blender/compositor/intern/COM_ExecutionGroup.cpp b/source/blender/compositor/intern/COM_ExecutionGroup.cpp
index f636a211ff6..50caf51cf48 100644
--- a/source/blender/compositor/intern/COM_ExecutionGroup.cpp
+++ b/source/blender/compositor/intern/COM_ExecutionGroup.cpp
@@ -43,135 +43,147 @@
ExecutionGroup::ExecutionGroup()
{
- this->m_isOutput = false;
- this->m_complex = false;
- this->m_chunkExecutionStates = NULL;
- this->m_bTree = NULL;
- this->m_height = 0;
- this->m_width = 0;
- this->m_cachedMaxReadBufferOffset = 0;
- this->m_numberOfXChunks = 0;
- this->m_numberOfYChunks = 0;
- this->m_numberOfChunks = 0;
- this->m_initialized = false;
- this->m_openCL = false;
- this->m_singleThreaded = false;
- this->m_chunksFinished = 0;
- BLI_rcti_init(&this->m_viewerBorder, 0, 0, 0, 0);
- this->m_executionStartTime = 0;
+ this->m_isOutput = false;
+ this->m_complex = false;
+ this->m_chunkExecutionStates = NULL;
+ this->m_bTree = NULL;
+ this->m_height = 0;
+ this->m_width = 0;
+ this->m_cachedMaxReadBufferOffset = 0;
+ this->m_numberOfXChunks = 0;
+ this->m_numberOfYChunks = 0;
+ this->m_numberOfChunks = 0;
+ this->m_initialized = false;
+ this->m_openCL = false;
+ this->m_singleThreaded = false;
+ this->m_chunksFinished = 0;
+ BLI_rcti_init(&this->m_viewerBorder, 0, 0, 0, 0);
+ this->m_executionStartTime = 0;
}
CompositorPriority ExecutionGroup::getRenderPriotrity()
{
- return this->getOutputOperation()->getRenderPriority();
+ return this->getOutputOperation()->getRenderPriority();
}
bool ExecutionGroup::canContainOperation(NodeOperation *operation)
{
- if (!this->m_initialized) { return true; }
-
- if (operation->isReadBufferOperation()) { return true; }
- if (operation->isWriteBufferOperation()) { return false; }
- if (operation->isSetOperation()) { return true; }
-
- /* complex groups don't allow further ops (except read buffer and values, see above) */
- if (m_complex) { return false; }
- /* complex ops can't be added to other groups (except their own, which they initialize, see above) */
- if (operation->isComplex()) { return false; }
-
- return true;
+ if (!this->m_initialized) {
+ return true;
+ }
+
+ if (operation->isReadBufferOperation()) {
+ return true;
+ }
+ if (operation->isWriteBufferOperation()) {
+ return false;
+ }
+ if (operation->isSetOperation()) {
+ return true;
+ }
+
+ /* complex groups don't allow further ops (except read buffer and values, see above) */
+ if (m_complex) {
+ return false;
+ }
+ /* complex ops can't be added to other groups (except their own, which they initialize, see above) */
+ if (operation->isComplex()) {
+ return false;
+ }
+
+ return true;
}
bool ExecutionGroup::addOperation(NodeOperation *operation)
{
- if (!canContainOperation(operation))
- return false;
+ if (!canContainOperation(operation))
+ return false;
- if (!operation->isReadBufferOperation() && !operation->isWriteBufferOperation()) {
- m_complex = operation->isComplex();
- m_openCL = operation->isOpenCL();
- m_singleThreaded = operation->isSingleThreaded();
- m_initialized = true;
- }
+ if (!operation->isReadBufferOperation() && !operation->isWriteBufferOperation()) {
+ m_complex = operation->isComplex();
+ m_openCL = operation->isOpenCL();
+ m_singleThreaded = operation->isSingleThreaded();
+ m_initialized = true;
+ }
- m_operations.push_back(operation);
+ m_operations.push_back(operation);
- return true;
+ return true;
}
NodeOperation *ExecutionGroup::getOutputOperation() const
{
- return this->m_operations[0]; // the first operation of the group is always the output operation.
+ return this
+ ->m_operations[0]; // the first operation of the group is always the output operation.
}
void ExecutionGroup::initExecution()
{
- if (this->m_chunkExecutionStates != NULL) {
- MEM_freeN(this->m_chunkExecutionStates);
- }
- unsigned int index;
- determineNumberOfChunks();
-
- this->m_chunkExecutionStates = NULL;
- if (this->m_numberOfChunks != 0) {
- this->m_chunkExecutionStates = (ChunkExecutionState *)MEM_mallocN(sizeof(ChunkExecutionState) * this->m_numberOfChunks, __func__);
- for (index = 0; index < this->m_numberOfChunks; index++) {
- this->m_chunkExecutionStates[index] = COM_ES_NOT_SCHEDULED;
- }
- }
-
-
- unsigned int maxNumber = 0;
-
- for (index = 0; index < this->m_operations.size(); index++) {
- NodeOperation *operation = this->m_operations[index];
- if (operation->isReadBufferOperation()) {
- ReadBufferOperation *readOperation = (ReadBufferOperation *)operation;
- this->m_cachedReadOperations.push_back(readOperation);
- maxNumber = max(maxNumber, readOperation->getOffset());
- }
- }
- maxNumber++;
- this->m_cachedMaxReadBufferOffset = maxNumber;
-
+ if (this->m_chunkExecutionStates != NULL) {
+ MEM_freeN(this->m_chunkExecutionStates);
+ }
+ unsigned int index;
+ determineNumberOfChunks();
+
+ this->m_chunkExecutionStates = NULL;
+ if (this->m_numberOfChunks != 0) {
+ this->m_chunkExecutionStates = (ChunkExecutionState *)MEM_mallocN(
+ sizeof(ChunkExecutionState) * this->m_numberOfChunks, __func__);
+ for (index = 0; index < this->m_numberOfChunks; index++) {
+ this->m_chunkExecutionStates[index] = COM_ES_NOT_SCHEDULED;
+ }
+ }
+
+ unsigned int maxNumber = 0;
+
+ for (index = 0; index < this->m_operations.size(); index++) {
+ NodeOperation *operation = this->m_operations[index];
+ if (operation->isReadBufferOperation()) {
+ ReadBufferOperation *readOperation = (ReadBufferOperation *)operation;
+ this->m_cachedReadOperations.push_back(readOperation);
+ maxNumber = max(maxNumber, readOperation->getOffset());
+ }
+ }
+ maxNumber++;
+ this->m_cachedMaxReadBufferOffset = maxNumber;
}
void ExecutionGroup::deinitExecution()
{
- if (this->m_chunkExecutionStates != NULL) {
- MEM_freeN(this->m_chunkExecutionStates);
- this->m_chunkExecutionStates = NULL;
- }
- this->m_numberOfChunks = 0;
- this->m_numberOfXChunks = 0;
- this->m_numberOfYChunks = 0;
- this->m_cachedReadOperations.clear();
- this->m_bTree = NULL;
+ if (this->m_chunkExecutionStates != NULL) {
+ MEM_freeN(this->m_chunkExecutionStates);
+ this->m_chunkExecutionStates = NULL;
+ }
+ this->m_numberOfChunks = 0;
+ this->m_numberOfXChunks = 0;
+ this->m_numberOfYChunks = 0;
+ this->m_cachedReadOperations.clear();
+ this->m_bTree = NULL;
}
void ExecutionGroup::determineResolution(unsigned int resolution[2])
{
- NodeOperation *operation = this->getOutputOperation();
- resolution[0] = operation->getWidth();
- resolution[1] = operation->getHeight();
- this->setResolution(resolution);
- BLI_rcti_init(&this->m_viewerBorder, 0, this->m_width, 0, this->m_height);
+ NodeOperation *operation = this->getOutputOperation();
+ resolution[0] = operation->getWidth();
+ resolution[1] = operation->getHeight();
+ this->setResolution(resolution);
+ BLI_rcti_init(&this->m_viewerBorder, 0, this->m_width, 0, this->m_height);
}
void ExecutionGroup::determineNumberOfChunks()
{
- if (this->m_singleThreaded) {
- this->m_numberOfXChunks = 1;
- this->m_numberOfYChunks = 1;
- this->m_numberOfChunks = 1;
- }
- else {
- const float chunkSizef = this->m_chunkSize;
- const int border_width = BLI_rcti_size_x(&this->m_viewerBorder);
- const int border_height = BLI_rcti_size_y(&this->m_viewerBorder);
- this->m_numberOfXChunks = ceil(border_width / chunkSizef);
- this->m_numberOfYChunks = ceil(border_height / chunkSizef);
- this->m_numberOfChunks = this->m_numberOfXChunks * this->m_numberOfYChunks;
- }
+ if (this->m_singleThreaded) {
+ this->m_numberOfXChunks = 1;
+ this->m_numberOfYChunks = 1;
+ this->m_numberOfChunks = 1;
+ }
+ else {
+ const float chunkSizef = this->m_chunkSize;
+ const int border_width = BLI_rcti_size_x(&this->m_viewerBorder);
+ const int border_height = BLI_rcti_size_y(&this->m_viewerBorder);
+ this->m_numberOfXChunks = ceil(border_width / chunkSizef);
+ this->m_numberOfYChunks = ceil(border_height / chunkSizef);
+ this->m_numberOfChunks = this->m_numberOfXChunks * this->m_numberOfYChunks;
+ }
}
/**
@@ -179,422 +191,452 @@ void ExecutionGroup::determineNumberOfChunks()
*/
void ExecutionGroup::execute(ExecutionSystem *graph)
{
- const CompositorContext &context = graph->getContext();
- const bNodeTree *bTree = context.getbNodeTree();
- if (this->m_width == 0 || this->m_height == 0) {return; } /// \note: break out... no pixels to calculate.
- if (bTree->test_break && bTree->test_break(bTree->tbh)) {return; } /// \note: early break out for blur and preview nodes
- if (this->m_numberOfChunks == 0) {return; } /// \note: early break out
- unsigned int chunkNumber;
-
- this->m_executionStartTime = PIL_check_seconds_timer();
-
- this->m_chunksFinished = 0;
- this->m_bTree = bTree;
- unsigned int index;
- unsigned int *chunkOrder = (unsigned int *)MEM_mallocN(sizeof(unsigned int) * this->m_numberOfChunks, __func__);
-
- for (chunkNumber = 0; chunkNumber < this->m_numberOfChunks; chunkNumber++) {
- chunkOrder[chunkNumber] = chunkNumber;
- }
- NodeOperation *operation = this->getOutputOperation();
- float centerX = 0.5;
- float centerY = 0.5;
- OrderOfChunks chunkorder = COM_ORDER_OF_CHUNKS_DEFAULT;
-
- if (operation->isViewerOperation()) {
- ViewerOperation *viewer = (ViewerOperation *)operation;
- centerX = viewer->getCenterX();
- centerY = viewer->getCenterY();
- chunkorder = viewer->getChunkOrder();
- }
-
- const int border_width = BLI_rcti_size_x(&this->m_viewerBorder);
- const int border_height = BLI_rcti_size_y(&this->m_viewerBorder);
-
- switch (chunkorder) {
- case COM_TO_RANDOM:
- for (index = 0; index < 2 * this->m_numberOfChunks; index++) {
- int index1 = rand() % this->m_numberOfChunks;
- int index2 = rand() % this->m_numberOfChunks;
- int s = chunkOrder[index1];
- chunkOrder[index1] = chunkOrder[index2];
- chunkOrder[index2] = s;
- }
- break;
- case COM_TO_CENTER_OUT:
- {
- ChunkOrderHotspot *hotspots[1];
- hotspots[0] = new ChunkOrderHotspot(border_width * centerX, border_height * centerY, 0.0f);
- rcti rect;
- ChunkOrder *chunkOrders = (ChunkOrder *)MEM_mallocN(sizeof(ChunkOrder) * this->m_numberOfChunks, __func__);
- for (index = 0; index < this->m_numberOfChunks; index++) {
- determineChunkRect(&rect, index);
- chunkOrders[index].setChunkNumber(index);
- chunkOrders[index].setX(rect.xmin - this->m_viewerBorder.xmin);
- chunkOrders[index].setY(rect.ymin - this->m_viewerBorder.ymin);
- chunkOrders[index].determineDistance(hotspots, 1);
- }
-
- std::sort(&chunkOrders[0], &chunkOrders[this->m_numberOfChunks - 1]);
- for (index = 0; index < this->m_numberOfChunks; index++) {
- chunkOrder[index] = chunkOrders[index].getChunkNumber();
- }
-
- delete hotspots[0];
- MEM_freeN(chunkOrders);
- break;
- }
- case COM_TO_RULE_OF_THIRDS:
- {
- ChunkOrderHotspot *hotspots[9];
- unsigned int tx = border_width / 6;
- unsigned int ty = border_height / 6;
- unsigned int mx = border_width / 2;
- unsigned int my = border_height / 2;
- unsigned int bx = mx + 2 * tx;
- unsigned int by = my + 2 * ty;
-
- float addition = this->m_numberOfChunks / COM_RULE_OF_THIRDS_DIVIDER;
- hotspots[0] = new ChunkOrderHotspot(mx, my, addition * 0);
- hotspots[1] = new ChunkOrderHotspot(tx, my, addition * 1);
- hotspots[2] = new ChunkOrderHotspot(bx, my, addition * 2);
- hotspots[3] = new ChunkOrderHotspot(bx, by, addition * 3);
- hotspots[4] = new ChunkOrderHotspot(tx, ty, addition * 4);
- hotspots[5] = new ChunkOrderHotspot(bx, ty, addition * 5);
- hotspots[6] = new ChunkOrderHotspot(tx, by, addition * 6);
- hotspots[7] = new ChunkOrderHotspot(mx, ty, addition * 7);
- hotspots[8] = new ChunkOrderHotspot(mx, by, addition * 8);
- rcti rect;
- ChunkOrder *chunkOrders = (ChunkOrder *)MEM_mallocN(sizeof(ChunkOrder) * this->m_numberOfChunks, __func__);
- for (index = 0; index < this->m_numberOfChunks; index++) {
- determineChunkRect(&rect, index);
- chunkOrders[index].setChunkNumber(index);
- chunkOrders[index].setX(rect.xmin - this->m_viewerBorder.xmin);
- chunkOrders[index].setY(rect.ymin - this->m_viewerBorder.ymin);
- chunkOrders[index].determineDistance(hotspots, 9);
- }
-
- std::sort(&chunkOrders[0], &chunkOrders[this->m_numberOfChunks]);
-
- for (index = 0; index < this->m_numberOfChunks; index++) {
- chunkOrder[index] = chunkOrders[index].getChunkNumber();
- }
-
- delete hotspots[0];
- delete hotspots[1];
- delete hotspots[2];
- delete hotspots[3];
- delete hotspots[4];
- delete hotspots[5];
- delete hotspots[6];
- delete hotspots[7];
- delete hotspots[8];
- MEM_freeN(chunkOrders);
- break;
- }
- case COM_TO_TOP_DOWN:
- default:
- break;
- }
-
- DebugInfo::execution_group_started(this);
- DebugInfo::graphviz(graph);
-
- bool breaked = false;
- bool finished = false;
- unsigned int startIndex = 0;
- const int maxNumberEvaluated = BLI_system_thread_count() * 2;
-
- while (!finished && !breaked) {
- bool startEvaluated = false;
- finished = true;
- int numberEvaluated = 0;
-
- for (index = startIndex; index < this->m_numberOfChunks && numberEvaluated < maxNumberEvaluated; index++) {
- chunkNumber = chunkOrder[index];
- int yChunk = chunkNumber / this->m_numberOfXChunks;
- int xChunk = chunkNumber - (yChunk * this->m_numberOfXChunks);
- const ChunkExecutionState state = this->m_chunkExecutionStates[chunkNumber];
- if (state == COM_ES_NOT_SCHEDULED) {
- scheduleChunkWhenPossible(graph, xChunk, yChunk);
- finished = false;
- startEvaluated = true;
- numberEvaluated++;
-
- if (bTree->update_draw)
- bTree->update_draw(bTree->udh);
- }
- else if (state == COM_ES_SCHEDULED) {
- finished = false;
- startEvaluated = true;
- numberEvaluated++;
- }
- else if (state == COM_ES_EXECUTED && !startEvaluated) {
- startIndex = index + 1;
- }
- }
-
- WorkScheduler::finish();
-
- if (bTree->test_break && bTree->test_break(bTree->tbh)) {
- breaked = true;
- }
- }
- DebugInfo::execution_group_finished(this);
- DebugInfo::graphviz(graph);
-
- MEM_freeN(chunkOrder);
+ const CompositorContext &context = graph->getContext();
+ const bNodeTree *bTree = context.getbNodeTree();
+ if (this->m_width == 0 || this->m_height == 0) {
+ return;
+ } /// \note: break out... no pixels to calculate.
+ if (bTree->test_break && bTree->test_break(bTree->tbh)) {
+ return;
+ } /// \note: early break out for blur and preview nodes
+ if (this->m_numberOfChunks == 0) {
+ return;
+ } /// \note: early break out
+ unsigned int chunkNumber;
+
+ this->m_executionStartTime = PIL_check_seconds_timer();
+
+ this->m_chunksFinished = 0;
+ this->m_bTree = bTree;
+ unsigned int index;
+ unsigned int *chunkOrder = (unsigned int *)MEM_mallocN(
+ sizeof(unsigned int) * this->m_numberOfChunks, __func__);
+
+ for (chunkNumber = 0; chunkNumber < this->m_numberOfChunks; chunkNumber++) {
+ chunkOrder[chunkNumber] = chunkNumber;
+ }
+ NodeOperation *operation = this->getOutputOperation();
+ float centerX = 0.5;
+ float centerY = 0.5;
+ OrderOfChunks chunkorder = COM_ORDER_OF_CHUNKS_DEFAULT;
+
+ if (operation->isViewerOperation()) {
+ ViewerOperation *viewer = (ViewerOperation *)operation;
+ centerX = viewer->getCenterX();
+ centerY = viewer->getCenterY();
+ chunkorder = viewer->getChunkOrder();
+ }
+
+ const int border_width = BLI_rcti_size_x(&this->m_viewerBorder);
+ const int border_height = BLI_rcti_size_y(&this->m_viewerBorder);
+
+ switch (chunkorder) {
+ case COM_TO_RANDOM:
+ for (index = 0; index < 2 * this->m_numberOfChunks; index++) {
+ int index1 = rand() % this->m_numberOfChunks;
+ int index2 = rand() % this->m_numberOfChunks;
+ int s = chunkOrder[index1];
+ chunkOrder[index1] = chunkOrder[index2];
+ chunkOrder[index2] = s;
+ }
+ break;
+ case COM_TO_CENTER_OUT: {
+ ChunkOrderHotspot *hotspots[1];
+ hotspots[0] = new ChunkOrderHotspot(border_width * centerX, border_height * centerY, 0.0f);
+ rcti rect;
+ ChunkOrder *chunkOrders = (ChunkOrder *)MEM_mallocN(
+ sizeof(ChunkOrder) * this->m_numberOfChunks, __func__);
+ for (index = 0; index < this->m_numberOfChunks; index++) {
+ determineChunkRect(&rect, index);
+ chunkOrders[index].setChunkNumber(index);
+ chunkOrders[index].setX(rect.xmin - this->m_viewerBorder.xmin);
+ chunkOrders[index].setY(rect.ymin - this->m_viewerBorder.ymin);
+ chunkOrders[index].determineDistance(hotspots, 1);
+ }
+
+ std::sort(&chunkOrders[0], &chunkOrders[this->m_numberOfChunks - 1]);
+ for (index = 0; index < this->m_numberOfChunks; index++) {
+ chunkOrder[index] = chunkOrders[index].getChunkNumber();
+ }
+
+ delete hotspots[0];
+ MEM_freeN(chunkOrders);
+ break;
+ }
+ case COM_TO_RULE_OF_THIRDS: {
+ ChunkOrderHotspot *hotspots[9];
+ unsigned int tx = border_width / 6;
+ unsigned int ty = border_height / 6;
+ unsigned int mx = border_width / 2;
+ unsigned int my = border_height / 2;
+ unsigned int bx = mx + 2 * tx;
+ unsigned int by = my + 2 * ty;
+
+ float addition = this->m_numberOfChunks / COM_RULE_OF_THIRDS_DIVIDER;
+ hotspots[0] = new ChunkOrderHotspot(mx, my, addition * 0);
+ hotspots[1] = new ChunkOrderHotspot(tx, my, addition * 1);
+ hotspots[2] = new ChunkOrderHotspot(bx, my, addition * 2);
+ hotspots[3] = new ChunkOrderHotspot(bx, by, addition * 3);
+ hotspots[4] = new ChunkOrderHotspot(tx, ty, addition * 4);
+ hotspots[5] = new ChunkOrderHotspot(bx, ty, addition * 5);
+ hotspots[6] = new ChunkOrderHotspot(tx, by, addition * 6);
+ hotspots[7] = new ChunkOrderHotspot(mx, ty, addition * 7);
+ hotspots[8] = new ChunkOrderHotspot(mx, by, addition * 8);
+ rcti rect;
+ ChunkOrder *chunkOrders = (ChunkOrder *)MEM_mallocN(
+ sizeof(ChunkOrder) * this->m_numberOfChunks, __func__);
+ for (index = 0; index < this->m_numberOfChunks; index++) {
+ determineChunkRect(&rect, index);
+ chunkOrders[index].setChunkNumber(index);
+ chunkOrders[index].setX(rect.xmin - this->m_viewerBorder.xmin);
+ chunkOrders[index].setY(rect.ymin - this->m_viewerBorder.ymin);
+ chunkOrders[index].determineDistance(hotspots, 9);
+ }
+
+ std::sort(&chunkOrders[0], &chunkOrders[this->m_numberOfChunks]);
+
+ for (index = 0; index < this->m_numberOfChunks; index++) {
+ chunkOrder[index] = chunkOrders[index].getChunkNumber();
+ }
+
+ delete hotspots[0];
+ delete hotspots[1];
+ delete hotspots[2];
+ delete hotspots[3];
+ delete hotspots[4];
+ delete hotspots[5];
+ delete hotspots[6];
+ delete hotspots[7];
+ delete hotspots[8];
+ MEM_freeN(chunkOrders);
+ break;
+ }
+ case COM_TO_TOP_DOWN:
+ default:
+ break;
+ }
+
+ DebugInfo::execution_group_started(this);
+ DebugInfo::graphviz(graph);
+
+ bool breaked = false;
+ bool finished = false;
+ unsigned int startIndex = 0;
+ const int maxNumberEvaluated = BLI_system_thread_count() * 2;
+
+ while (!finished && !breaked) {
+ bool startEvaluated = false;
+ finished = true;
+ int numberEvaluated = 0;
+
+ for (index = startIndex;
+ index < this->m_numberOfChunks && numberEvaluated < maxNumberEvaluated;
+ index++) {
+ chunkNumber = chunkOrder[index];
+ int yChunk = chunkNumber / this->m_numberOfXChunks;
+ int xChunk = chunkNumber - (yChunk * this->m_numberOfXChunks);
+ const ChunkExecutionState state = this->m_chunkExecutionStates[chunkNumber];
+ if (state == COM_ES_NOT_SCHEDULED) {
+ scheduleChunkWhenPossible(graph, xChunk, yChunk);
+ finished = false;
+ startEvaluated = true;
+ numberEvaluated++;
+
+ if (bTree->update_draw)
+ bTree->update_draw(bTree->udh);
+ }
+ else if (state == COM_ES_SCHEDULED) {
+ finished = false;
+ startEvaluated = true;
+ numberEvaluated++;
+ }
+ else if (state == COM_ES_EXECUTED && !startEvaluated) {
+ startIndex = index + 1;
+ }
+ }
+
+ WorkScheduler::finish();
+
+ if (bTree->test_break && bTree->test_break(bTree->tbh)) {
+ breaked = true;
+ }
+ }
+ DebugInfo::execution_group_finished(this);
+ DebugInfo::graphviz(graph);
+
+ MEM_freeN(chunkOrder);
}
MemoryBuffer **ExecutionGroup::getInputBuffersOpenCL(int chunkNumber)
{
- rcti rect;
- vector<MemoryProxy *> memoryproxies;
- unsigned int index;
- determineChunkRect(&rect, chunkNumber);
-
- this->determineDependingMemoryProxies(&memoryproxies);
- MemoryBuffer **memoryBuffers = (MemoryBuffer **)MEM_callocN(sizeof(MemoryBuffer *) * this->m_cachedMaxReadBufferOffset, __func__);
- rcti output;
- for (index = 0; index < this->m_cachedReadOperations.size(); index++) {
- ReadBufferOperation *readOperation = (ReadBufferOperation *)this->m_cachedReadOperations[index];
- MemoryProxy *memoryProxy = readOperation->getMemoryProxy();
- this->determineDependingAreaOfInterest(&rect, readOperation, &output);
- MemoryBuffer *memoryBuffer = memoryProxy->getExecutor()->constructConsolidatedMemoryBuffer(memoryProxy, &output);
- memoryBuffers[readOperation->getOffset()] = memoryBuffer;
- }
- return memoryBuffers;
+ rcti rect;
+ vector<MemoryProxy *> memoryproxies;
+ unsigned int index;
+ determineChunkRect(&rect, chunkNumber);
+
+ this->determineDependingMemoryProxies(&memoryproxies);
+ MemoryBuffer **memoryBuffers = (MemoryBuffer **)MEM_callocN(
+ sizeof(MemoryBuffer *) * this->m_cachedMaxReadBufferOffset, __func__);
+ rcti output;
+ for (index = 0; index < this->m_cachedReadOperations.size(); index++) {
+ ReadBufferOperation *readOperation =
+ (ReadBufferOperation *)this->m_cachedReadOperations[index];
+ MemoryProxy *memoryProxy = readOperation->getMemoryProxy();
+ this->determineDependingAreaOfInterest(&rect, readOperation, &output);
+ MemoryBuffer *memoryBuffer = memoryProxy->getExecutor()->constructConsolidatedMemoryBuffer(
+ memoryProxy, &output);
+ memoryBuffers[readOperation->getOffset()] = memoryBuffer;
+ }
+ return memoryBuffers;
}
-MemoryBuffer *ExecutionGroup::constructConsolidatedMemoryBuffer(MemoryProxy *memoryProxy, rcti *rect)
+MemoryBuffer *ExecutionGroup::constructConsolidatedMemoryBuffer(MemoryProxy *memoryProxy,
+ rcti *rect)
{
- MemoryBuffer *imageBuffer = memoryProxy->getBuffer();
- MemoryBuffer *result = new MemoryBuffer(memoryProxy, rect);
- result->copyContentFrom(imageBuffer);
- return result;
+ MemoryBuffer *imageBuffer = memoryProxy->getBuffer();
+ MemoryBuffer *result = new MemoryBuffer(memoryProxy, rect);
+ result->copyContentFrom(imageBuffer);
+ return result;
}
void ExecutionGroup::finalizeChunkExecution(int chunkNumber, MemoryBuffer **memoryBuffers)
{
- if (this->m_chunkExecutionStates[chunkNumber] == COM_ES_SCHEDULED)
- this->m_chunkExecutionStates[chunkNumber] = COM_ES_EXECUTED;
-
- atomic_add_and_fetch_u(&this->m_chunksFinished, 1);
- if (memoryBuffers) {
- for (unsigned int index = 0; index < this->m_cachedMaxReadBufferOffset; index++) {
- MemoryBuffer *buffer = memoryBuffers[index];
- if (buffer) {
- if (buffer->isTemporarily()) {
- memoryBuffers[index] = NULL;
- delete buffer;
- }
- }
- }
- MEM_freeN(memoryBuffers);
- }
- if (this->m_bTree) {
- // status report is only performed for top level Execution Groups.
- float progress = this->m_chunksFinished;
- progress /= this->m_numberOfChunks;
- this->m_bTree->progress(this->m_bTree->prh, progress);
-
- char buf[128];
- BLI_snprintf(buf, sizeof(buf), IFACE_("Compositing | Tile %u-%u"),
- this->m_chunksFinished,
- this->m_numberOfChunks);
- this->m_bTree->stats_draw(this->m_bTree->sdh, buf);
- }
+ if (this->m_chunkExecutionStates[chunkNumber] == COM_ES_SCHEDULED)
+ this->m_chunkExecutionStates[chunkNumber] = COM_ES_EXECUTED;
+
+ atomic_add_and_fetch_u(&this->m_chunksFinished, 1);
+ if (memoryBuffers) {
+ for (unsigned int index = 0; index < this->m_cachedMaxReadBufferOffset; index++) {
+ MemoryBuffer *buffer = memoryBuffers[index];
+ if (buffer) {
+ if (buffer->isTemporarily()) {
+ memoryBuffers[index] = NULL;
+ delete buffer;
+ }
+ }
+ }
+ MEM_freeN(memoryBuffers);
+ }
+ if (this->m_bTree) {
+ // status report is only performed for top level Execution Groups.
+ float progress = this->m_chunksFinished;
+ progress /= this->m_numberOfChunks;
+ this->m_bTree->progress(this->m_bTree->prh, progress);
+
+ char buf[128];
+ BLI_snprintf(buf,
+ sizeof(buf),
+ IFACE_("Compositing | Tile %u-%u"),
+ this->m_chunksFinished,
+ this->m_numberOfChunks);
+ this->m_bTree->stats_draw(this->m_bTree->sdh, buf);
+ }
}
-inline void ExecutionGroup::determineChunkRect(rcti *rect, const unsigned int xChunk, const unsigned int yChunk) const
+inline void ExecutionGroup::determineChunkRect(rcti *rect,
+ const unsigned int xChunk,
+ const unsigned int yChunk) const
{
- const int border_width = BLI_rcti_size_x(&this->m_viewerBorder);
- const int border_height = BLI_rcti_size_y(&this->m_viewerBorder);
-
- if (this->m_singleThreaded) {
- BLI_rcti_init(rect, this->m_viewerBorder.xmin, border_width, this->m_viewerBorder.ymin, border_height);
- }
- else {
- const unsigned int minx = xChunk * this->m_chunkSize + this->m_viewerBorder.xmin;
- const unsigned int miny = yChunk * this->m_chunkSize + this->m_viewerBorder.ymin;
- const unsigned int width = min((unsigned int) this->m_viewerBorder.xmax, this->m_width);
- const unsigned int height = min((unsigned int) this->m_viewerBorder.ymax, this->m_height);
- BLI_rcti_init(rect, min(minx, this->m_width), min(minx + this->m_chunkSize, width), min(miny, this->m_height), min(miny + this->m_chunkSize, height));
- }
+ const int border_width = BLI_rcti_size_x(&this->m_viewerBorder);
+ const int border_height = BLI_rcti_size_y(&this->m_viewerBorder);
+
+ if (this->m_singleThreaded) {
+ BLI_rcti_init(
+ rect, this->m_viewerBorder.xmin, border_width, this->m_viewerBorder.ymin, border_height);
+ }
+ else {
+ const unsigned int minx = xChunk * this->m_chunkSize + this->m_viewerBorder.xmin;
+ const unsigned int miny = yChunk * this->m_chunkSize + this->m_viewerBorder.ymin;
+ const unsigned int width = min((unsigned int)this->m_viewerBorder.xmax, this->m_width);
+ const unsigned int height = min((unsigned int)this->m_viewerBorder.ymax, this->m_height);
+ BLI_rcti_init(rect,
+ min(minx, this->m_width),
+ min(minx + this->m_chunkSize, width),
+ min(miny, this->m_height),
+ min(miny + this->m_chunkSize, height));
+ }
}
void ExecutionGroup::determineChunkRect(rcti *rect, const unsigned int chunkNumber) const
{
- const unsigned int yChunk = chunkNumber / this->m_numberOfXChunks;
- const unsigned int xChunk = chunkNumber - (yChunk * this->m_numberOfXChunks);
- determineChunkRect(rect, xChunk, yChunk);
+ const unsigned int yChunk = chunkNumber / this->m_numberOfXChunks;
+ const unsigned int xChunk = chunkNumber - (yChunk * this->m_numberOfXChunks);
+ determineChunkRect(rect, xChunk, yChunk);
}
-MemoryBuffer *ExecutionGroup::allocateOutputBuffer(int /*chunkNumber*/,
- rcti *rect)
+MemoryBuffer *ExecutionGroup::allocateOutputBuffer(int /*chunkNumber*/, rcti *rect)
{
- // we assume that this method is only called from complex execution groups.
- NodeOperation *operation = this->getOutputOperation();
- if (operation->isWriteBufferOperation()) {
- WriteBufferOperation *writeOperation = (WriteBufferOperation *)operation;
- MemoryBuffer *buffer = new MemoryBuffer(writeOperation->getMemoryProxy(), rect);
- return buffer;
- }
- return NULL;
+ // we assume that this method is only called from complex execution groups.
+ NodeOperation *operation = this->getOutputOperation();
+ if (operation->isWriteBufferOperation()) {
+ WriteBufferOperation *writeOperation = (WriteBufferOperation *)operation;
+ MemoryBuffer *buffer = new MemoryBuffer(writeOperation->getMemoryProxy(), rect);
+ return buffer;
+ }
+ return NULL;
}
-
bool ExecutionGroup::scheduleAreaWhenPossible(ExecutionSystem *graph, rcti *area)
{
- if (this->m_singleThreaded) {
- return scheduleChunkWhenPossible(graph, 0, 0);
- }
- // find all chunks inside the rect
- // determine minxchunk, minychunk, maxxchunk, maxychunk where x and y are chunknumbers
-
- int indexx, indexy;
- int minx = max_ii(area->xmin - m_viewerBorder.xmin, 0);
- int maxx = min_ii(area->xmax - m_viewerBorder.xmin, m_viewerBorder.xmax - m_viewerBorder.xmin);
- int miny = max_ii(area->ymin - m_viewerBorder.ymin, 0);
- int maxy = min_ii(area->ymax - m_viewerBorder.ymin, m_viewerBorder.ymax - m_viewerBorder.ymin);
- int minxchunk = minx / (int)m_chunkSize;
- int maxxchunk = (maxx + (int)m_chunkSize - 1) / (int)m_chunkSize;
- int minychunk = miny / (int)m_chunkSize;
- int maxychunk = (maxy + (int)m_chunkSize - 1) / (int)m_chunkSize;
- minxchunk = max_ii(minxchunk, 0);
- minychunk = max_ii(minychunk, 0);
- maxxchunk = min_ii(maxxchunk, (int)m_numberOfXChunks);
- maxychunk = min_ii(maxychunk, (int)m_numberOfYChunks);
-
- bool result = true;
- for (indexx = minxchunk; indexx < maxxchunk; indexx++) {
- for (indexy = minychunk; indexy < maxychunk; indexy++) {
- if (!scheduleChunkWhenPossible(graph, indexx, indexy)) {
- result = false;
- }
- }
- }
-
- return result;
+ if (this->m_singleThreaded) {
+ return scheduleChunkWhenPossible(graph, 0, 0);
+ }
+ // find all chunks inside the rect
+ // determine minxchunk, minychunk, maxxchunk, maxychunk where x and y are chunknumbers
+
+ int indexx, indexy;
+ int minx = max_ii(area->xmin - m_viewerBorder.xmin, 0);
+ int maxx = min_ii(area->xmax - m_viewerBorder.xmin, m_viewerBorder.xmax - m_viewerBorder.xmin);
+ int miny = max_ii(area->ymin - m_viewerBorder.ymin, 0);
+ int maxy = min_ii(area->ymax - m_viewerBorder.ymin, m_viewerBorder.ymax - m_viewerBorder.ymin);
+ int minxchunk = minx / (int)m_chunkSize;
+ int maxxchunk = (maxx + (int)m_chunkSize - 1) / (int)m_chunkSize;
+ int minychunk = miny / (int)m_chunkSize;
+ int maxychunk = (maxy + (int)m_chunkSize - 1) / (int)m_chunkSize;
+ minxchunk = max_ii(minxchunk, 0);
+ minychunk = max_ii(minychunk, 0);
+ maxxchunk = min_ii(maxxchunk, (int)m_numberOfXChunks);
+ maxychunk = min_ii(maxychunk, (int)m_numberOfYChunks);
+
+ bool result = true;
+ for (indexx = minxchunk; indexx < maxxchunk; indexx++) {
+ for (indexy = minychunk; indexy < maxychunk; indexy++) {
+ if (!scheduleChunkWhenPossible(graph, indexx, indexy)) {
+ result = false;
+ }
+ }
+ }
+
+ return result;
}
bool ExecutionGroup::scheduleChunk(unsigned int chunkNumber)
{
- if (this->m_chunkExecutionStates[chunkNumber] == COM_ES_NOT_SCHEDULED) {
- this->m_chunkExecutionStates[chunkNumber] = COM_ES_SCHEDULED;
- WorkScheduler::schedule(this, chunkNumber);
- return true;
- }
- return false;
+ if (this->m_chunkExecutionStates[chunkNumber] == COM_ES_NOT_SCHEDULED) {
+ this->m_chunkExecutionStates[chunkNumber] = COM_ES_SCHEDULED;
+ WorkScheduler::schedule(this, chunkNumber);
+ return true;
+ }
+ return false;
}
bool ExecutionGroup::scheduleChunkWhenPossible(ExecutionSystem *graph, int xChunk, int yChunk)
{
- if (xChunk < 0 || xChunk >= (int)this->m_numberOfXChunks) {
- return true;
- }
- if (yChunk < 0 || yChunk >= (int)this->m_numberOfYChunks) {
- return true;
- }
- int chunkNumber = yChunk * this->m_numberOfXChunks + xChunk;
- // chunk is already executed
- if (this->m_chunkExecutionStates[chunkNumber] == COM_ES_EXECUTED) {
- return true;
- }
-
- // chunk is scheduled, but not executed
- if (this->m_chunkExecutionStates[chunkNumber] == COM_ES_SCHEDULED) {
- return false;
- }
-
- // chunk is nor executed nor scheduled.
- vector<MemoryProxy *> memoryProxies;
- this->determineDependingMemoryProxies(&memoryProxies);
-
- rcti rect;
- determineChunkRect(&rect, xChunk, yChunk);
- unsigned int index;
- bool canBeExecuted = true;
- rcti area;
-
- for (index = 0; index < this->m_cachedReadOperations.size(); index++) {
- ReadBufferOperation *readOperation = (ReadBufferOperation *)this->m_cachedReadOperations[index];
- BLI_rcti_init(&area, 0, 0, 0, 0);
- MemoryProxy *memoryProxy = memoryProxies[index];
- determineDependingAreaOfInterest(&rect, readOperation, &area);
- ExecutionGroup *group = memoryProxy->getExecutor();
-
- if (group != NULL) {
- if (!group->scheduleAreaWhenPossible(graph, &area)) {
- canBeExecuted = false;
- }
- }
- else {
- throw "ERROR";
- }
- }
-
- if (canBeExecuted) {
- scheduleChunk(chunkNumber);
- }
-
- return false;
+ if (xChunk < 0 || xChunk >= (int)this->m_numberOfXChunks) {
+ return true;
+ }
+ if (yChunk < 0 || yChunk >= (int)this->m_numberOfYChunks) {
+ return true;
+ }
+ int chunkNumber = yChunk * this->m_numberOfXChunks + xChunk;
+ // chunk is already executed
+ if (this->m_chunkExecutionStates[chunkNumber] == COM_ES_EXECUTED) {
+ return true;
+ }
+
+ // chunk is scheduled, but not executed
+ if (this->m_chunkExecutionStates[chunkNumber] == COM_ES_SCHEDULED) {
+ return false;
+ }
+
+ // chunk is nor executed nor scheduled.
+ vector<MemoryProxy *> memoryProxies;
+ this->determineDependingMemoryProxies(&memoryProxies);
+
+ rcti rect;
+ determineChunkRect(&rect, xChunk, yChunk);
+ unsigned int index;
+ bool canBeExecuted = true;
+ rcti area;
+
+ for (index = 0; index < this->m_cachedReadOperations.size(); index++) {
+ ReadBufferOperation *readOperation =
+ (ReadBufferOperation *)this->m_cachedReadOperations[index];
+ BLI_rcti_init(&area, 0, 0, 0, 0);
+ MemoryProxy *memoryProxy = memoryProxies[index];
+ determineDependingAreaOfInterest(&rect, readOperation, &area);
+ ExecutionGroup *group = memoryProxy->getExecutor();
+
+ if (group != NULL) {
+ if (!group->scheduleAreaWhenPossible(graph, &area)) {
+ canBeExecuted = false;
+ }
+ }
+ else {
+ throw "ERROR";
+ }
+ }
+
+ if (canBeExecuted) {
+ scheduleChunk(chunkNumber);
+ }
+
+ return false;
}
-void ExecutionGroup::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output)
+void ExecutionGroup::determineDependingAreaOfInterest(rcti *input,
+ ReadBufferOperation *readOperation,
+ rcti *output)
{
- this->getOutputOperation()->determineDependingAreaOfInterest(input, readOperation, output);
+ this->getOutputOperation()->determineDependingAreaOfInterest(input, readOperation, output);
}
void ExecutionGroup::determineDependingMemoryProxies(vector<MemoryProxy *> *memoryProxies)
{
- unsigned int index;
- for (index = 0; index < this->m_cachedReadOperations.size(); index++) {
- ReadBufferOperation *readOperation = (ReadBufferOperation *) this->m_cachedReadOperations[index];
- memoryProxies->push_back(readOperation->getMemoryProxy());
- }
+ unsigned int index;
+ for (index = 0; index < this->m_cachedReadOperations.size(); index++) {
+ ReadBufferOperation *readOperation =
+ (ReadBufferOperation *)this->m_cachedReadOperations[index];
+ memoryProxies->push_back(readOperation->getMemoryProxy());
+ }
}
bool ExecutionGroup::isOpenCL()
{
- return this->m_openCL;
+ return this->m_openCL;
}
void ExecutionGroup::setViewerBorder(float xmin, float xmax, float ymin, float ymax)
{
- NodeOperation *operation = this->getOutputOperation();
-
- if (operation->isViewerOperation() || operation->isPreviewOperation()) {
- BLI_rcti_init(&this->m_viewerBorder, xmin * this->m_width, xmax * this->m_width,
- ymin * this->m_height, ymax * this->m_height);
- }
+ NodeOperation *operation = this->getOutputOperation();
+
+ if (operation->isViewerOperation() || operation->isPreviewOperation()) {
+ BLI_rcti_init(&this->m_viewerBorder,
+ xmin * this->m_width,
+ xmax * this->m_width,
+ ymin * this->m_height,
+ ymax * this->m_height);
+ }
}
void ExecutionGroup::setRenderBorder(float xmin, float xmax, float ymin, float ymax)
{
- NodeOperation *operation = this->getOutputOperation();
-
- if (operation->isOutputOperation(true)) {
- /* Basically, setting border need to happen for only operations
- * which operates in render resolution buffers (like compositor
- * output nodes).
- *
- * In this cases adding border will lead to mapping coordinates
- * from output buffer space to input buffer spaces when executing
- * operation.
- *
- * But nodes like viewer and file output just shall display or
- * safe the same exact buffer which goes to their input, no need
- * in any kind of coordinates mapping.
- */
-
- bool operationNeedsBorder = !(operation->isViewerOperation() ||
- operation->isPreviewOperation() ||
- operation->isFileOutputOperation());
-
- if (operationNeedsBorder) {
- BLI_rcti_init(&this->m_viewerBorder, xmin * this->m_width, xmax * this->m_width,
- ymin * this->m_height, ymax * this->m_height);
- }
- }
+ NodeOperation *operation = this->getOutputOperation();
+
+ if (operation->isOutputOperation(true)) {
+ /* Basically, setting border need to happen for only operations
+ * which operates in render resolution buffers (like compositor
+ * output nodes).
+ *
+ * In this cases adding border will lead to mapping coordinates
+ * from output buffer space to input buffer spaces when executing
+ * operation.
+ *
+ * But nodes like viewer and file output just shall display or
+ * safe the same exact buffer which goes to their input, no need
+ * in any kind of coordinates mapping.
+ */
+
+ bool operationNeedsBorder = !(operation->isViewerOperation() ||
+ operation->isPreviewOperation() ||
+ operation->isFileOutputOperation());
+
+ if (operationNeedsBorder) {
+ BLI_rcti_init(&this->m_viewerBorder,
+ xmin * this->m_width,
+ xmax * this->m_width,
+ ymin * this->m_height,
+ ymax * this->m_height);
+ }
+ }
}
diff --git a/source/blender/compositor/intern/COM_ExecutionGroup.h b/source/blender/compositor/intern/COM_ExecutionGroup.h
index c7a371b226a..ff9ac5d0582 100644
--- a/source/blender/compositor/intern/COM_ExecutionGroup.h
+++ b/source/blender/compositor/intern/COM_ExecutionGroup.h
@@ -39,18 +39,18 @@ class Device;
* \ingroup Execution
*/
typedef enum ChunkExecutionState {
- /**
- * \brief chunk is not yet scheduled
- */
- COM_ES_NOT_SCHEDULED = 0,
- /**
- * \brief chunk is scheduled, but not yet executed
- */
- COM_ES_SCHEDULED = 1,
- /**
- * \brief chunk is executed.
- */
- COM_ES_EXECUTED = 2,
+ /**
+ * \brief chunk is not yet scheduled
+ */
+ COM_ES_NOT_SCHEDULED = 0,
+ /**
+ * \brief chunk is scheduled, but not yet executed
+ */
+ COM_ES_SCHEDULED = 1,
+ /**
+ * \brief chunk is executed.
+ */
+ COM_ES_EXECUTED = 2,
} ChunkExecutionState;
/**
@@ -59,361 +59,381 @@ typedef enum ChunkExecutionState {
* \ingroup Execution
*/
class ExecutionGroup {
-public:
- typedef std::vector<NodeOperation*> Operations;
-
-private:
- // fields
-
- /**
- * \brief list of operations in this ExecutionGroup
- */
- Operations m_operations;
-
- /**
- * \brief is this ExecutionGroup an input ExecutionGroup
- * an input execution group is a group that is at the end of the calculation (the output is important for the user)
- */
- int m_isOutput;
-
- /**
- * \brief Width of the output
- */
- unsigned int m_width;
-
- /**
- * \brief Height of the output
- */
- unsigned int m_height;
-
- /**
- * \brief size of a single chunk, being Width or of height
- * a chunk is always a square, except at the edges of the MemoryBuffer
- */
- unsigned int m_chunkSize;
-
- /**
- * \brief number of chunks in the x-axis
- */
- unsigned int m_numberOfXChunks;
-
- /**
- * \brief number of chunks in the y-axis
- */
- unsigned int m_numberOfYChunks;
-
- /**
- * \brief total number of chunks
- */
- unsigned int m_numberOfChunks;
-
- /**
- * \brief contains this ExecutionGroup a complex NodeOperation.
- */
- bool m_complex;
-
- /**
- * \brief can this ExecutionGroup be scheduled on an OpenCLDevice
- */
- bool m_openCL;
-
- /**
- * \brief Is this Execution group SingleThreaded
- */
- bool m_singleThreaded;
-
- /**
- * \brief what is the maximum number field of all ReadBufferOperation in this ExecutionGroup.
- * \note this is used to construct the MemoryBuffers that will be passed during execution.
- */
- unsigned int m_cachedMaxReadBufferOffset;
-
- /**
- * \brief a cached vector of all read operations in the execution group.
- */
- Operations m_cachedReadOperations;
-
- /**
- * \brief reference to the original bNodeTree, this field is only set for the 'top' execution group.
- * \note can only be used to call the callbacks for progress, status and break
- */
- const bNodeTree *m_bTree;
-
- /**
- * \brief total number of chunks that have been calculated for this ExecutionGroup
- */
- unsigned int m_chunksFinished;
-
- /**
- * \brief the chunkExecutionStates holds per chunk the execution state. this state can be
- * - COM_ES_NOT_SCHEDULED: not scheduled
- * - COM_ES_SCHEDULED: scheduled
- * - COM_ES_EXECUTED: executed
- */
- ChunkExecutionState *m_chunkExecutionStates;
-
- /**
- * \brief indicator when this ExecutionGroup has valid Operations in its vector for Execution
- * \note When building the ExecutionGroup Operations are added via recursion. First a WriteBufferOperations is added, then the
- * \note Operation containing the settings that is important for the ExecutiongGroup is added,
- * \note When this occurs, these settings are copied over from the node to the ExecutionGroup
- * \note and the Initialized flag is set to true.
- * \see complex
- * \see openCL
- */
- bool m_initialized;
-
- /**
- * \brief denotes boundary for border compositing
- * \note measured in pixel space
- */
- rcti m_viewerBorder;
-
- /**
- * \brief start time of execution
- */
- double m_executionStartTime;
-
- // methods
- /**
- * \brief check whether parameter operation can be added to the execution group
- * \param operation: the operation to be added
- */
- bool canContainOperation(NodeOperation *operation);
-
- /**
- * \brief calculate the actual chunk size of this execution group.
- * \note A chunk size is an unsigned int that is both the height and width of a chunk.
- * \note The chunk size will not be stored in the chunkSize field. This needs to be done
- * \note by the calling method.
- */
- unsigned int determineChunkSize();
-
-
- /**
- * \brief Determine the rect (minx, maxx, miny, maxy) of a chunk at a position.
- * \note Only gives useful results ater the determination of the chunksize
- * \see determineChunkSize()
- */
- void determineChunkRect(rcti *rect, const unsigned int xChunk, const unsigned int yChunk) const;
-
- /**
- * \brief determine the number of chunks, based on the chunkSize, width and height.
- * \note The result are stored in the fields numberOfChunks, numberOfXChunks, numberOfYChunks
- */
- void determineNumberOfChunks();
-
- /**
- * \brief try to schedule a specific chunk.
- * \note scheduling succeeds when all input requirements are met and the chunks hasn't been scheduled yet.
- * \param graph:
- * \param xChunk:
- * \param yChunk:
- * \return [true:false]
- * true: package(s) are scheduled
- * false: scheduling is deferred (depending workpackages are scheduled)
- */
- bool scheduleChunkWhenPossible(ExecutionSystem *graph, int xChunk, int yChunk);
-
- /**
- * \brief try to schedule a specific area.
- * \note Check if a certain area is available, when not available this are will be checked.
- * \note This method is called from other ExecutionGroup's.
- * \param graph:
- * \param rect:
- * \return [true:false]
- * true: package(s) are scheduled
- * false: scheduling is deferred (depending workpackages are scheduled)
- */
- bool scheduleAreaWhenPossible(ExecutionSystem *graph, rcti *rect);
-
- /**
- * \brief add a chunk to the WorkScheduler.
- * \param chunknumber:
- */
- bool scheduleChunk(unsigned int chunkNumber);
-
- /**
- * \brief determine the area of interest of a certain input area
- * \note This method only evaluates a single ReadBufferOperation
- * \param input: the input area
- * \param readOperation: The ReadBufferOperation where the area needs to be evaluated
- * \param output: the area needed of the ReadBufferOperation. Result
- */
- void determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output);
-
-
-public:
- // constructors
- ExecutionGroup();
-
- // methods
- /**
- * \brief add an operation to this ExecutionGroup
- * \note this method will add input of the operations recursively
- * \note this method can create multiple ExecutionGroup's
- * \param system:
- * \param operation:
- * \return True if the operation was successfully added
- */
- bool addOperation(NodeOperation *operation);
-
- /**
- * \brief is this ExecutionGroup an output ExecutionGroup
- * \note An OutputExecution group are groups containing a
- * \note ViewerOperation, CompositeOperation, PreviewOperation.
- * \see NodeOperation.isOutputOperation
- */
- int isOutputExecutionGroup() const { return this->m_isOutput; }
-
- /**
- * \brief set whether this ExecutionGroup is an output
- * \param isOutput:
- */
- void setOutputExecutionGroup(int isOutput) { this->m_isOutput = isOutput; }
-
- /**
- * \brief determine the resolution of this ExecutionGroup
- * \param resolution:
- */
- void determineResolution(unsigned int resolution[2]);
-
- /**
- * \brief set the resolution of this executiongroup
- * \param resolution:
- */
- void setResolution(unsigned int resolution[2]) { this->m_width = resolution[0]; this->m_height = resolution[1]; }
-
- /**
- * \brief get the width of this execution group
- */
- unsigned int getWidth() const { return m_width; }
-
- /**
- * \brief get the height of this execution group
- */
- unsigned int getHeight() const { return m_height; }
-
- /**
- * \brief does this ExecutionGroup contains a complex NodeOperation
- */
- bool isComplex() const { return m_complex; }
-
-
- /**
- * \brief get the output operation of this ExecutionGroup
- * \return NodeOperation *output operation
- */
- NodeOperation *getOutputOperation() const;
-
- /**
- * \brief compose multiple chunks into a single chunk
- * \return Memorybuffer *consolidated chunk
- */
- MemoryBuffer *constructConsolidatedMemoryBuffer(MemoryProxy *memoryProxy, rcti *output);
-
- /**
- * \brief initExecution is called just before the execution of the whole graph will be done.
- * \note The implementation will calculate the chunkSize of this execution group.
- */
- void initExecution();
-
- /**
- * \brief get all inputbuffers needed to calculate an chunk
- * \note all inputbuffers must be executed
- * \param chunkNumber: the chunk to be calculated
- * \return (MemoryBuffer **) the inputbuffers
- */
- MemoryBuffer **getInputBuffersCPU();
-
- /**
- * \brief get all inputbuffers needed to calculate an chunk
- * \note all inputbuffers must be executed
- * \param chunkNumber: the chunk to be calculated
- * \return (MemoryBuffer **) the inputbuffers
- */
- MemoryBuffer **getInputBuffersOpenCL(int chunkNumber);
-
- /**
- * \brief allocate the outputbuffer of a chunk
- * \param chunkNumber: the number of the chunk in the ExecutionGroup
- * \param rect: the rect of that chunk
- * \see determineChunkRect
- */
- MemoryBuffer *allocateOutputBuffer(int chunkNumber, rcti *rect);
-
- /**
- * \brief after a chunk is executed the needed resources can be freed or unlocked.
- * \param chunknumber:
- * \param memorybuffers:
- */
- void finalizeChunkExecution(int chunkNumber, MemoryBuffer **memoryBuffers);
-
- /**
- * \brief deinitExecution is called just after execution the whole graph.
- * \note It will release all needed resources
- */
- void deinitExecution();
-
-
- /**
- * \brief schedule an ExecutionGroup
- * \note this method will return when all chunks have been calculated, or the execution has breaked (by user)
- *
- * first the order of the chunks will be determined. This is determined by finding the ViewerOperation and get the relevant information from it.
- * - ChunkOrdering
- * - CenterX
- * - CenterY
- *
- * After determining the order of the chunks the chunks will be scheduled
- *
- * \see ViewerOperation
- * \param system:
- */
- void execute(ExecutionSystem *system);
-
- /**
- * \brief this method determines the MemoryProxy's where this execution group depends on.
- * \note After this method determineDependingAreaOfInterest can be called to determine
- * \note the area of the MemoryProxy.creator that has to be executed.
- * \param memoryProxies: result
- */
- void determineDependingMemoryProxies(vector<MemoryProxy *> *memoryProxies);
-
- /**
- * \brief Determine the rect (minx, maxx, miny, maxy) of a chunk.
- * \note Only gives useful results ater the determination of the chunksize
- * \see determineChunkSize()
- */
- void determineChunkRect(rcti *rect, const unsigned int chunkNumber) const;
-
- /**
- * \brief can this ExecutionGroup be scheduled on an OpenCLDevice
- * \see WorkScheduler.schedule
- */
- bool isOpenCL();
-
- void setChunksize(int chunksize) { this->m_chunkSize = chunksize; }
-
- /**
- * \brief get the Render priority of this ExecutionGroup
- * \see ExecutionSystem.execute
- */
- CompositorPriority getRenderPriotrity();
-
- /**
- * \brief set border for viewer operation
- * \note all the coordinates are assumed to be in normalized space
- */
- void setViewerBorder(float xmin, float xmax, float ymin, float ymax);
-
- void setRenderBorder(float xmin, float xmax, float ymin, float ymax);
-
- /* allow the DebugInfo class to look at internals */
- friend class DebugInfo;
+ public:
+ typedef std::vector<NodeOperation *> Operations;
+
+ private:
+ // fields
+
+ /**
+ * \brief list of operations in this ExecutionGroup
+ */
+ Operations m_operations;
+
+ /**
+ * \brief is this ExecutionGroup an input ExecutionGroup
+ * an input execution group is a group that is at the end of the calculation (the output is important for the user)
+ */
+ int m_isOutput;
+
+ /**
+ * \brief Width of the output
+ */
+ unsigned int m_width;
+
+ /**
+ * \brief Height of the output
+ */
+ unsigned int m_height;
+
+ /**
+ * \brief size of a single chunk, being Width or of height
+ * a chunk is always a square, except at the edges of the MemoryBuffer
+ */
+ unsigned int m_chunkSize;
+
+ /**
+ * \brief number of chunks in the x-axis
+ */
+ unsigned int m_numberOfXChunks;
+
+ /**
+ * \brief number of chunks in the y-axis
+ */
+ unsigned int m_numberOfYChunks;
+
+ /**
+ * \brief total number of chunks
+ */
+ unsigned int m_numberOfChunks;
+
+ /**
+ * \brief contains this ExecutionGroup a complex NodeOperation.
+ */
+ bool m_complex;
+
+ /**
+ * \brief can this ExecutionGroup be scheduled on an OpenCLDevice
+ */
+ bool m_openCL;
+
+ /**
+ * \brief Is this Execution group SingleThreaded
+ */
+ bool m_singleThreaded;
+
+ /**
+ * \brief what is the maximum number field of all ReadBufferOperation in this ExecutionGroup.
+ * \note this is used to construct the MemoryBuffers that will be passed during execution.
+ */
+ unsigned int m_cachedMaxReadBufferOffset;
+
+ /**
+ * \brief a cached vector of all read operations in the execution group.
+ */
+ Operations m_cachedReadOperations;
+
+ /**
+ * \brief reference to the original bNodeTree, this field is only set for the 'top' execution group.
+ * \note can only be used to call the callbacks for progress, status and break
+ */
+ const bNodeTree *m_bTree;
+
+ /**
+ * \brief total number of chunks that have been calculated for this ExecutionGroup
+ */
+ unsigned int m_chunksFinished;
+
+ /**
+ * \brief the chunkExecutionStates holds per chunk the execution state. this state can be
+ * - COM_ES_NOT_SCHEDULED: not scheduled
+ * - COM_ES_SCHEDULED: scheduled
+ * - COM_ES_EXECUTED: executed
+ */
+ ChunkExecutionState *m_chunkExecutionStates;
+
+ /**
+ * \brief indicator when this ExecutionGroup has valid Operations in its vector for Execution
+ * \note When building the ExecutionGroup Operations are added via recursion. First a WriteBufferOperations is added, then the
+ * \note Operation containing the settings that is important for the ExecutiongGroup is added,
+ * \note When this occurs, these settings are copied over from the node to the ExecutionGroup
+ * \note and the Initialized flag is set to true.
+ * \see complex
+ * \see openCL
+ */
+ bool m_initialized;
+
+ /**
+ * \brief denotes boundary for border compositing
+ * \note measured in pixel space
+ */
+ rcti m_viewerBorder;
+
+ /**
+ * \brief start time of execution
+ */
+ double m_executionStartTime;
+
+ // methods
+ /**
+ * \brief check whether parameter operation can be added to the execution group
+ * \param operation: the operation to be added
+ */
+ bool canContainOperation(NodeOperation *operation);
+
+ /**
+ * \brief calculate the actual chunk size of this execution group.
+ * \note A chunk size is an unsigned int that is both the height and width of a chunk.
+ * \note The chunk size will not be stored in the chunkSize field. This needs to be done
+ * \note by the calling method.
+ */
+ unsigned int determineChunkSize();
+
+ /**
+ * \brief Determine the rect (minx, maxx, miny, maxy) of a chunk at a position.
+ * \note Only gives useful results ater the determination of the chunksize
+ * \see determineChunkSize()
+ */
+ void determineChunkRect(rcti *rect, const unsigned int xChunk, const unsigned int yChunk) const;
+
+ /**
+ * \brief determine the number of chunks, based on the chunkSize, width and height.
+ * \note The result are stored in the fields numberOfChunks, numberOfXChunks, numberOfYChunks
+ */
+ void determineNumberOfChunks();
+
+ /**
+ * \brief try to schedule a specific chunk.
+ * \note scheduling succeeds when all input requirements are met and the chunks hasn't been scheduled yet.
+ * \param graph:
+ * \param xChunk:
+ * \param yChunk:
+ * \return [true:false]
+ * true: package(s) are scheduled
+ * false: scheduling is deferred (depending workpackages are scheduled)
+ */
+ bool scheduleChunkWhenPossible(ExecutionSystem *graph, int xChunk, int yChunk);
+
+ /**
+ * \brief try to schedule a specific area.
+ * \note Check if a certain area is available, when not available this are will be checked.
+ * \note This method is called from other ExecutionGroup's.
+ * \param graph:
+ * \param rect:
+ * \return [true:false]
+ * true: package(s) are scheduled
+ * false: scheduling is deferred (depending workpackages are scheduled)
+ */
+ bool scheduleAreaWhenPossible(ExecutionSystem *graph, rcti *rect);
+
+ /**
+ * \brief add a chunk to the WorkScheduler.
+ * \param chunknumber:
+ */
+ bool scheduleChunk(unsigned int chunkNumber);
+
+ /**
+ * \brief determine the area of interest of a certain input area
+ * \note This method only evaluates a single ReadBufferOperation
+ * \param input: the input area
+ * \param readOperation: The ReadBufferOperation where the area needs to be evaluated
+ * \param output: the area needed of the ReadBufferOperation. Result
+ */
+ void determineDependingAreaOfInterest(rcti *input,
+ ReadBufferOperation *readOperation,
+ rcti *output);
+
+ public:
+ // constructors
+ ExecutionGroup();
+
+ // methods
+ /**
+ * \brief add an operation to this ExecutionGroup
+ * \note this method will add input of the operations recursively
+ * \note this method can create multiple ExecutionGroup's
+ * \param system:
+ * \param operation:
+ * \return True if the operation was successfully added
+ */
+ bool addOperation(NodeOperation *operation);
+
+ /**
+ * \brief is this ExecutionGroup an output ExecutionGroup
+ * \note An OutputExecution group are groups containing a
+ * \note ViewerOperation, CompositeOperation, PreviewOperation.
+ * \see NodeOperation.isOutputOperation
+ */
+ int isOutputExecutionGroup() const
+ {
+ return this->m_isOutput;
+ }
+
+ /**
+ * \brief set whether this ExecutionGroup is an output
+ * \param isOutput:
+ */
+ void setOutputExecutionGroup(int isOutput)
+ {
+ this->m_isOutput = isOutput;
+ }
+
+ /**
+ * \brief determine the resolution of this ExecutionGroup
+ * \param resolution:
+ */
+ void determineResolution(unsigned int resolution[2]);
+
+ /**
+ * \brief set the resolution of this executiongroup
+ * \param resolution:
+ */
+ void setResolution(unsigned int resolution[2])
+ {
+ this->m_width = resolution[0];
+ this->m_height = resolution[1];
+ }
+
+ /**
+ * \brief get the width of this execution group
+ */
+ unsigned int getWidth() const
+ {
+ return m_width;
+ }
+
+ /**
+ * \brief get the height of this execution group
+ */
+ unsigned int getHeight() const
+ {
+ return m_height;
+ }
+
+ /**
+ * \brief does this ExecutionGroup contains a complex NodeOperation
+ */
+ bool isComplex() const
+ {
+ return m_complex;
+ }
+
+ /**
+ * \brief get the output operation of this ExecutionGroup
+ * \return NodeOperation *output operation
+ */
+ NodeOperation *getOutputOperation() const;
+
+ /**
+ * \brief compose multiple chunks into a single chunk
+ * \return Memorybuffer *consolidated chunk
+ */
+ MemoryBuffer *constructConsolidatedMemoryBuffer(MemoryProxy *memoryProxy, rcti *output);
+
+ /**
+ * \brief initExecution is called just before the execution of the whole graph will be done.
+ * \note The implementation will calculate the chunkSize of this execution group.
+ */
+ void initExecution();
+
+ /**
+ * \brief get all inputbuffers needed to calculate an chunk
+ * \note all inputbuffers must be executed
+ * \param chunkNumber: the chunk to be calculated
+ * \return (MemoryBuffer **) the inputbuffers
+ */
+ MemoryBuffer **getInputBuffersCPU();
+
+ /**
+ * \brief get all inputbuffers needed to calculate an chunk
+ * \note all inputbuffers must be executed
+ * \param chunkNumber: the chunk to be calculated
+ * \return (MemoryBuffer **) the inputbuffers
+ */
+ MemoryBuffer **getInputBuffersOpenCL(int chunkNumber);
+
+ /**
+ * \brief allocate the outputbuffer of a chunk
+ * \param chunkNumber: the number of the chunk in the ExecutionGroup
+ * \param rect: the rect of that chunk
+ * \see determineChunkRect
+ */
+ MemoryBuffer *allocateOutputBuffer(int chunkNumber, rcti *rect);
+
+ /**
+ * \brief after a chunk is executed the needed resources can be freed or unlocked.
+ * \param chunknumber:
+ * \param memorybuffers:
+ */
+ void finalizeChunkExecution(int chunkNumber, MemoryBuffer **memoryBuffers);
+
+ /**
+ * \brief deinitExecution is called just after execution the whole graph.
+ * \note It will release all needed resources
+ */
+ void deinitExecution();
+
+ /**
+ * \brief schedule an ExecutionGroup
+ * \note this method will return when all chunks have been calculated, or the execution has breaked (by user)
+ *
+ * first the order of the chunks will be determined. This is determined by finding the ViewerOperation and get the relevant information from it.
+ * - ChunkOrdering
+ * - CenterX
+ * - CenterY
+ *
+ * After determining the order of the chunks the chunks will be scheduled
+ *
+ * \see ViewerOperation
+ * \param system:
+ */
+ void execute(ExecutionSystem *system);
+
+ /**
+ * \brief this method determines the MemoryProxy's where this execution group depends on.
+ * \note After this method determineDependingAreaOfInterest can be called to determine
+ * \note the area of the MemoryProxy.creator that has to be executed.
+ * \param memoryProxies: result
+ */
+ void determineDependingMemoryProxies(vector<MemoryProxy *> *memoryProxies);
+
+ /**
+ * \brief Determine the rect (minx, maxx, miny, maxy) of a chunk.
+ * \note Only gives useful results ater the determination of the chunksize
+ * \see determineChunkSize()
+ */
+ void determineChunkRect(rcti *rect, const unsigned int chunkNumber) const;
+
+ /**
+ * \brief can this ExecutionGroup be scheduled on an OpenCLDevice
+ * \see WorkScheduler.schedule
+ */
+ bool isOpenCL();
+
+ void setChunksize(int chunksize)
+ {
+ this->m_chunkSize = chunksize;
+ }
+
+ /**
+ * \brief get the Render priority of this ExecutionGroup
+ * \see ExecutionSystem.execute
+ */
+ CompositorPriority getRenderPriotrity();
+
+ /**
+ * \brief set border for viewer operation
+ * \note all the coordinates are assumed to be in normalized space
+ */
+ void setViewerBorder(float xmin, float xmax, float ymin, float ymax);
+
+ void setRenderBorder(float xmin, float xmax, float ymin, float ymax);
+
+ /* allow the DebugInfo class to look at internals */
+ friend class DebugInfo;
#ifdef WITH_CXX_GUARDEDALLOC
- MEM_CXX_CLASS_ALLOC_FUNCS("COM:ExecutionGroup")
+ MEM_CXX_CLASS_ALLOC_FUNCS("COM:ExecutionGroup")
#endif
};
diff --git a/source/blender/compositor/intern/COM_ExecutionSystem.cpp b/source/blender/compositor/intern/COM_ExecutionSystem.cpp
index 67e69129246..0d1fefc857d 100644
--- a/source/blender/compositor/intern/COM_ExecutionSystem.cpp
+++ b/source/blender/compositor/intern/COM_ExecutionSystem.cpp
@@ -35,193 +35,202 @@ extern "C" {
#include "COM_Debug.h"
#ifdef WITH_CXX_GUARDEDALLOC
-#include "MEM_guardedalloc.h"
+# include "MEM_guardedalloc.h"
#endif
-ExecutionSystem::ExecutionSystem(RenderData *rd, Scene *scene, bNodeTree *editingtree, bool rendering, bool fastcalculation,
- const ColorManagedViewSettings *viewSettings, const ColorManagedDisplaySettings *displaySettings,
+ExecutionSystem::ExecutionSystem(RenderData *rd,
+ Scene *scene,
+ bNodeTree *editingtree,
+ bool rendering,
+ bool fastcalculation,
+ const ColorManagedViewSettings *viewSettings,
+ const ColorManagedDisplaySettings *displaySettings,
const char *viewName)
{
- this->m_context.setViewName(viewName);
- this->m_context.setScene(scene);
- this->m_context.setbNodeTree(editingtree);
- this->m_context.setPreviewHash(editingtree->previews);
- this->m_context.setFastCalculation(fastcalculation);
- /* initialize the CompositorContext */
- if (rendering) {
- this->m_context.setQuality((CompositorQuality)editingtree->render_quality);
- }
- else {
- this->m_context.setQuality((CompositorQuality)editingtree->edit_quality);
- }
- this->m_context.setRendering(rendering);
- this->m_context.setHasActiveOpenCLDevices(WorkScheduler::hasGPUDevices() && (editingtree->flag & NTREE_COM_OPENCL));
-
- this->m_context.setRenderData(rd);
- this->m_context.setViewSettings(viewSettings);
- this->m_context.setDisplaySettings(displaySettings);
-
- {
- NodeOperationBuilder builder(&m_context, editingtree);
- builder.convertToOperations(this);
- }
-
- unsigned int index;
- unsigned int resolution[2];
-
- rctf *viewer_border = &editingtree->viewer_border;
- bool use_viewer_border = (editingtree->flag & NTREE_VIEWER_BORDER) &&
- viewer_border->xmin < viewer_border->xmax &&
- viewer_border->ymin < viewer_border->ymax;
-
- editingtree->stats_draw(editingtree->sdh, IFACE_("Compositing | Determining resolution"));
-
- for (index = 0; index < this->m_groups.size(); index++) {
- resolution[0] = 0;
- resolution[1] = 0;
- ExecutionGroup *executionGroup = this->m_groups[index];
- executionGroup->determineResolution(resolution);
-
- if (rendering) {
- /* case when cropping to render border happens is handled in
- * compositor output and render layer nodes
- */
- if ((rd->mode & R_BORDER) && !(rd->mode & R_CROP)) {
- executionGroup->setRenderBorder(rd->border.xmin, rd->border.xmax,
- rd->border.ymin, rd->border.ymax);
- }
- }
-
- if (use_viewer_border) {
- executionGroup->setViewerBorder(viewer_border->xmin, viewer_border->xmax,
- viewer_border->ymin, viewer_border->ymax);
- }
- }
-
-// DebugInfo::graphviz(this);
+ this->m_context.setViewName(viewName);
+ this->m_context.setScene(scene);
+ this->m_context.setbNodeTree(editingtree);
+ this->m_context.setPreviewHash(editingtree->previews);
+ this->m_context.setFastCalculation(fastcalculation);
+ /* initialize the CompositorContext */
+ if (rendering) {
+ this->m_context.setQuality((CompositorQuality)editingtree->render_quality);
+ }
+ else {
+ this->m_context.setQuality((CompositorQuality)editingtree->edit_quality);
+ }
+ this->m_context.setRendering(rendering);
+ this->m_context.setHasActiveOpenCLDevices(WorkScheduler::hasGPUDevices() &&
+ (editingtree->flag & NTREE_COM_OPENCL));
+
+ this->m_context.setRenderData(rd);
+ this->m_context.setViewSettings(viewSettings);
+ this->m_context.setDisplaySettings(displaySettings);
+
+ {
+ NodeOperationBuilder builder(&m_context, editingtree);
+ builder.convertToOperations(this);
+ }
+
+ unsigned int index;
+ unsigned int resolution[2];
+
+ rctf *viewer_border = &editingtree->viewer_border;
+ bool use_viewer_border = (editingtree->flag & NTREE_VIEWER_BORDER) &&
+ viewer_border->xmin < viewer_border->xmax &&
+ viewer_border->ymin < viewer_border->ymax;
+
+ editingtree->stats_draw(editingtree->sdh, IFACE_("Compositing | Determining resolution"));
+
+ for (index = 0; index < this->m_groups.size(); index++) {
+ resolution[0] = 0;
+ resolution[1] = 0;
+ ExecutionGroup *executionGroup = this->m_groups[index];
+ executionGroup->determineResolution(resolution);
+
+ if (rendering) {
+ /* case when cropping to render border happens is handled in
+ * compositor output and render layer nodes
+ */
+ if ((rd->mode & R_BORDER) && !(rd->mode & R_CROP)) {
+ executionGroup->setRenderBorder(
+ rd->border.xmin, rd->border.xmax, rd->border.ymin, rd->border.ymax);
+ }
+ }
+
+ if (use_viewer_border) {
+ executionGroup->setViewerBorder(
+ viewer_border->xmin, viewer_border->xmax, viewer_border->ymin, viewer_border->ymax);
+ }
+ }
+
+ // DebugInfo::graphviz(this);
}
ExecutionSystem::~ExecutionSystem()
{
- unsigned int index;
- for (index = 0; index < this->m_operations.size(); index++) {
- NodeOperation *operation = this->m_operations[index];
- delete operation;
- }
- this->m_operations.clear();
- for (index = 0; index < this->m_groups.size(); index++) {
- ExecutionGroup *group = this->m_groups[index];
- delete group;
- }
- this->m_groups.clear();
+ unsigned int index;
+ for (index = 0; index < this->m_operations.size(); index++) {
+ NodeOperation *operation = this->m_operations[index];
+ delete operation;
+ }
+ this->m_operations.clear();
+ for (index = 0; index < this->m_groups.size(); index++) {
+ ExecutionGroup *group = this->m_groups[index];
+ delete group;
+ }
+ this->m_groups.clear();
}
void ExecutionSystem::set_operations(const Operations &operations, const Groups &groups)
{
- m_operations = operations;
- m_groups = groups;
+ m_operations = operations;
+ m_groups = groups;
}
void ExecutionSystem::execute()
{
- const bNodeTree *editingtree = this->m_context.getbNodeTree();
- editingtree->stats_draw(editingtree->sdh, IFACE_("Compositing | Initializing execution"));
-
- DebugInfo::execute_started(this);
-
- unsigned int order = 0;
- for (vector<NodeOperation *>::iterator iter = this->m_operations.begin(); iter != this->m_operations.end(); ++iter) {
- NodeOperation *operation = *iter;
- if (operation->isReadBufferOperation()) {
- ReadBufferOperation *readOperation = (ReadBufferOperation *)operation;
- readOperation->setOffset(order);
- order++;
- }
- }
- unsigned int index;
-
- // First allocale all write buffer
- for (index = 0; index < this->m_operations.size(); index++) {
- NodeOperation *operation = this->m_operations[index];
- if (operation->isWriteBufferOperation()) {
- operation->setbNodeTree(this->m_context.getbNodeTree());
- operation->initExecution();
- }
- }
- // Connect read buffers to their write buffers
- for (index = 0; index < this->m_operations.size(); index++) {
- NodeOperation *operation = this->m_operations[index];
- if (operation->isReadBufferOperation()) {
- ReadBufferOperation *readOperation = (ReadBufferOperation *)operation;
- readOperation->updateMemoryBuffer();
- }
- }
- // initialize other operations
- for (index = 0; index < this->m_operations.size(); index++) {
- NodeOperation *operation = this->m_operations[index];
- if (!operation->isWriteBufferOperation()) {
- operation->setbNodeTree(this->m_context.getbNodeTree());
- operation->initExecution();
- }
- }
- for (index = 0; index < this->m_groups.size(); index++) {
- ExecutionGroup *executionGroup = this->m_groups[index];
- executionGroup->setChunksize(this->m_context.getChunksize());
- executionGroup->initExecution();
- }
-
- WorkScheduler::start(this->m_context);
-
- executeGroups(COM_PRIORITY_HIGH);
- if (!this->getContext().isFastCalculation()) {
- executeGroups(COM_PRIORITY_MEDIUM);
- executeGroups(COM_PRIORITY_LOW);
- }
-
- WorkScheduler::finish();
- WorkScheduler::stop();
-
- editingtree->stats_draw(editingtree->sdh, IFACE_("Compositing | De-initializing execution"));
- for (index = 0; index < this->m_operations.size(); index++) {
- NodeOperation *operation = this->m_operations[index];
- operation->deinitExecution();
- }
- for (index = 0; index < this->m_groups.size(); index++) {
- ExecutionGroup *executionGroup = this->m_groups[index];
- executionGroup->deinitExecution();
- }
+ const bNodeTree *editingtree = this->m_context.getbNodeTree();
+ editingtree->stats_draw(editingtree->sdh, IFACE_("Compositing | Initializing execution"));
+
+ DebugInfo::execute_started(this);
+
+ unsigned int order = 0;
+ for (vector<NodeOperation *>::iterator iter = this->m_operations.begin();
+ iter != this->m_operations.end();
+ ++iter) {
+ NodeOperation *operation = *iter;
+ if (operation->isReadBufferOperation()) {
+ ReadBufferOperation *readOperation = (ReadBufferOperation *)operation;
+ readOperation->setOffset(order);
+ order++;
+ }
+ }
+ unsigned int index;
+
+ // First allocale all write buffer
+ for (index = 0; index < this->m_operations.size(); index++) {
+ NodeOperation *operation = this->m_operations[index];
+ if (operation->isWriteBufferOperation()) {
+ operation->setbNodeTree(this->m_context.getbNodeTree());
+ operation->initExecution();
+ }
+ }
+ // Connect read buffers to their write buffers
+ for (index = 0; index < this->m_operations.size(); index++) {
+ NodeOperation *operation = this->m_operations[index];
+ if (operation->isReadBufferOperation()) {
+ ReadBufferOperation *readOperation = (ReadBufferOperation *)operation;
+ readOperation->updateMemoryBuffer();
+ }
+ }
+ // initialize other operations
+ for (index = 0; index < this->m_operations.size(); index++) {
+ NodeOperation *operation = this->m_operations[index];
+ if (!operation->isWriteBufferOperation()) {
+ operation->setbNodeTree(this->m_context.getbNodeTree());
+ operation->initExecution();
+ }
+ }
+ for (index = 0; index < this->m_groups.size(); index++) {
+ ExecutionGroup *executionGroup = this->m_groups[index];
+ executionGroup->setChunksize(this->m_context.getChunksize());
+ executionGroup->initExecution();
+ }
+
+ WorkScheduler::start(this->m_context);
+
+ executeGroups(COM_PRIORITY_HIGH);
+ if (!this->getContext().isFastCalculation()) {
+ executeGroups(COM_PRIORITY_MEDIUM);
+ executeGroups(COM_PRIORITY_LOW);
+ }
+
+ WorkScheduler::finish();
+ WorkScheduler::stop();
+
+ editingtree->stats_draw(editingtree->sdh, IFACE_("Compositing | De-initializing execution"));
+ for (index = 0; index < this->m_operations.size(); index++) {
+ NodeOperation *operation = this->m_operations[index];
+ operation->deinitExecution();
+ }
+ for (index = 0; index < this->m_groups.size(); index++) {
+ ExecutionGroup *executionGroup = this->m_groups[index];
+ executionGroup->deinitExecution();
+ }
}
void ExecutionSystem::executeGroups(CompositorPriority priority)
{
- unsigned int index;
- vector<ExecutionGroup *> executionGroups;
- this->findOutputExecutionGroup(&executionGroups, priority);
-
- for (index = 0; index < executionGroups.size(); index++) {
- ExecutionGroup *group = executionGroups[index];
- group->execute(this);
- }
+ unsigned int index;
+ vector<ExecutionGroup *> executionGroups;
+ this->findOutputExecutionGroup(&executionGroups, priority);
+
+ for (index = 0; index < executionGroups.size(); index++) {
+ ExecutionGroup *group = executionGroups[index];
+ group->execute(this);
+ }
}
-void ExecutionSystem::findOutputExecutionGroup(vector<ExecutionGroup *> *result, CompositorPriority priority) const
+void ExecutionSystem::findOutputExecutionGroup(vector<ExecutionGroup *> *result,
+ CompositorPriority priority) const
{
- unsigned int index;
- for (index = 0; index < this->m_groups.size(); index++) {
- ExecutionGroup *group = this->m_groups[index];
- if (group->isOutputExecutionGroup() && group->getRenderPriotrity() == priority) {
- result->push_back(group);
- }
- }
+ unsigned int index;
+ for (index = 0; index < this->m_groups.size(); index++) {
+ ExecutionGroup *group = this->m_groups[index];
+ if (group->isOutputExecutionGroup() && group->getRenderPriotrity() == priority) {
+ result->push_back(group);
+ }
+ }
}
void ExecutionSystem::findOutputExecutionGroup(vector<ExecutionGroup *> *result) const
{
- unsigned int index;
- for (index = 0; index < this->m_groups.size(); index++) {
- ExecutionGroup *group = this->m_groups[index];
- if (group->isOutputExecutionGroup()) {
- result->push_back(group);
- }
- }
+ unsigned int index;
+ for (index = 0; index < this->m_groups.size(); index++) {
+ ExecutionGroup *group = this->m_groups[index];
+ if (group->isOutputExecutionGroup()) {
+ result->push_back(group);
+ }
+ }
}
diff --git a/source/blender/compositor/intern/COM_ExecutionSystem.h b/source/blender/compositor/intern/COM_ExecutionSystem.h
index 476dd3ccc06..55c2ed6c22b 100644
--- a/source/blender/compositor/intern/COM_ExecutionSystem.h
+++ b/source/blender/compositor/intern/COM_ExecutionSystem.h
@@ -107,77 +107,86 @@ class ExecutionGroup;
* \brief the ExecutionSystem contains the whole compositor tree.
*/
class ExecutionSystem {
-public:
- typedef std::vector<NodeOperation*> Operations;
- typedef std::vector<ExecutionGroup*> Groups;
-
-private:
- /**
- * \brief the context used during execution
- */
- CompositorContext m_context;
-
- /**
- * \brief vector of operations
- */
- Operations m_operations;
-
- /**
- * \brief vector of groups
- */
- Groups m_groups;
-
-private: //methods
- /**
- * find all execution group with output nodes
- */
- void findOutputExecutionGroup(vector<ExecutionGroup *> *result, CompositorPriority priority) const;
-
- /**
- * find all execution group with output nodes
- */
- void findOutputExecutionGroup(vector<ExecutionGroup *> *result) const;
-
-public:
- /**
- * \brief Create a new ExecutionSystem and initialize it with the
- * editingtree.
- *
- * \param editingtree: [bNodeTree *]
- * \param rendering: [true false]
- */
- ExecutionSystem(RenderData *rd, Scene *scene, bNodeTree *editingtree, bool rendering, bool fastcalculation,
- const ColorManagedViewSettings *viewSettings, const ColorManagedDisplaySettings *displaySettings,
- const char *viewName);
-
- /**
- * Destructor
- */
- ~ExecutionSystem();
-
- void set_operations(const Operations &operations, const Groups &groups);
-
- /**
- * \brief execute this system
- * - initialize the NodeOperation's and ExecutionGroup's
- * - schedule the output ExecutionGroup's based on their priority
- * - deinitialize the ExecutionGroup's and NodeOperation's
- */
- void execute();
-
- /**
- * \brief get the reference to the compositor context
- */
- const CompositorContext &getContext() const { return this->m_context; }
-
-private:
- void executeGroups(CompositorPriority priority);
-
- /* allow the DebugInfo class to look at internals */
- friend class DebugInfo;
+ public:
+ typedef std::vector<NodeOperation *> Operations;
+ typedef std::vector<ExecutionGroup *> Groups;
+
+ private:
+ /**
+ * \brief the context used during execution
+ */
+ CompositorContext m_context;
+
+ /**
+ * \brief vector of operations
+ */
+ Operations m_operations;
+
+ /**
+ * \brief vector of groups
+ */
+ Groups m_groups;
+
+ private: //methods
+ /**
+ * find all execution group with output nodes
+ */
+ void findOutputExecutionGroup(vector<ExecutionGroup *> *result,
+ CompositorPriority priority) const;
+
+ /**
+ * find all execution group with output nodes
+ */
+ void findOutputExecutionGroup(vector<ExecutionGroup *> *result) const;
+
+ public:
+ /**
+ * \brief Create a new ExecutionSystem and initialize it with the
+ * editingtree.
+ *
+ * \param editingtree: [bNodeTree *]
+ * \param rendering: [true false]
+ */
+ ExecutionSystem(RenderData *rd,
+ Scene *scene,
+ bNodeTree *editingtree,
+ bool rendering,
+ bool fastcalculation,
+ const ColorManagedViewSettings *viewSettings,
+ const ColorManagedDisplaySettings *displaySettings,
+ const char *viewName);
+
+ /**
+ * Destructor
+ */
+ ~ExecutionSystem();
+
+ void set_operations(const Operations &operations, const Groups &groups);
+
+ /**
+ * \brief execute this system
+ * - initialize the NodeOperation's and ExecutionGroup's
+ * - schedule the output ExecutionGroup's based on their priority
+ * - deinitialize the ExecutionGroup's and NodeOperation's
+ */
+ void execute();
+
+ /**
+ * \brief get the reference to the compositor context
+ */
+ const CompositorContext &getContext() const
+ {
+ return this->m_context;
+ }
+
+ private:
+ void executeGroups(CompositorPriority priority);
+
+ /* allow the DebugInfo class to look at internals */
+ friend class DebugInfo;
#ifdef WITH_CXX_GUARDEDALLOC
- MEM_CXX_CLASS_ALLOC_FUNCS("COM:ExecutionSystem")
+ MEM_CXX_CLASS_ALLOC_FUNCS("COM:ExecutionSystem")
#endif
};
diff --git a/source/blender/compositor/intern/COM_MemoryBuffer.cpp b/source/blender/compositor/intern/COM_MemoryBuffer.cpp
index 5f3cf83d4b2..b958314d1b4 100644
--- a/source/blender/compositor/intern/COM_MemoryBuffer.cpp
+++ b/source/blender/compositor/intern/COM_MemoryBuffer.cpp
@@ -20,202 +20,212 @@
#include "MEM_guardedalloc.h"
-using std::min;
using std::max;
+using std::min;
static unsigned int determine_num_channels(DataType datatype)
{
- switch (datatype) {
- case COM_DT_VALUE:
- return COM_NUM_CHANNELS_VALUE;
- case COM_DT_VECTOR:
- return COM_NUM_CHANNELS_VECTOR;
- case COM_DT_COLOR:
- default:
- return COM_NUM_CHANNELS_COLOR;
- }
+ switch (datatype) {
+ case COM_DT_VALUE:
+ return COM_NUM_CHANNELS_VALUE;
+ case COM_DT_VECTOR:
+ return COM_NUM_CHANNELS_VECTOR;
+ case COM_DT_COLOR:
+ default:
+ return COM_NUM_CHANNELS_COLOR;
+ }
}
unsigned int MemoryBuffer::determineBufferSize()
{
- return getWidth() * getHeight();
+ return getWidth() * getHeight();
}
int MemoryBuffer::getWidth() const
{
- return this->m_width;
+ return this->m_width;
}
int MemoryBuffer::getHeight() const
{
- return this->m_height;
+ return this->m_height;
}
MemoryBuffer::MemoryBuffer(MemoryProxy *memoryProxy, unsigned int chunkNumber, rcti *rect)
{
- BLI_rcti_init(&this->m_rect, rect->xmin, rect->xmax, rect->ymin, rect->ymax);
- this->m_width = BLI_rcti_size_x(&this->m_rect);
- this->m_height = BLI_rcti_size_y(&this->m_rect);
- this->m_memoryProxy = memoryProxy;
- this->m_chunkNumber = chunkNumber;
- this->m_num_channels = determine_num_channels(memoryProxy->getDataType());
- this->m_buffer = (float *)MEM_mallocN_aligned(sizeof(float) * determineBufferSize() * this->m_num_channels, 16, "COM_MemoryBuffer");
- this->m_state = COM_MB_ALLOCATED;
- this->m_datatype = memoryProxy->getDataType();
+ BLI_rcti_init(&this->m_rect, rect->xmin, rect->xmax, rect->ymin, rect->ymax);
+ this->m_width = BLI_rcti_size_x(&this->m_rect);
+ this->m_height = BLI_rcti_size_y(&this->m_rect);
+ this->m_memoryProxy = memoryProxy;
+ this->m_chunkNumber = chunkNumber;
+ this->m_num_channels = determine_num_channels(memoryProxy->getDataType());
+ this->m_buffer = (float *)MEM_mallocN_aligned(
+ sizeof(float) * determineBufferSize() * this->m_num_channels, 16, "COM_MemoryBuffer");
+ this->m_state = COM_MB_ALLOCATED;
+ this->m_datatype = memoryProxy->getDataType();
}
MemoryBuffer::MemoryBuffer(MemoryProxy *memoryProxy, rcti *rect)
{
- BLI_rcti_init(&this->m_rect, rect->xmin, rect->xmax, rect->ymin, rect->ymax);
- this->m_width = BLI_rcti_size_x(&this->m_rect);
- this->m_height = BLI_rcti_size_y(&this->m_rect);
- this->m_memoryProxy = memoryProxy;
- this->m_chunkNumber = -1;
- this->m_num_channels = determine_num_channels(memoryProxy->getDataType());
- this->m_buffer = (float *)MEM_mallocN_aligned(sizeof(float) * determineBufferSize() * this->m_num_channels, 16, "COM_MemoryBuffer");
- this->m_state = COM_MB_TEMPORARILY;
- this->m_datatype = memoryProxy->getDataType();
+ BLI_rcti_init(&this->m_rect, rect->xmin, rect->xmax, rect->ymin, rect->ymax);
+ this->m_width = BLI_rcti_size_x(&this->m_rect);
+ this->m_height = BLI_rcti_size_y(&this->m_rect);
+ this->m_memoryProxy = memoryProxy;
+ this->m_chunkNumber = -1;
+ this->m_num_channels = determine_num_channels(memoryProxy->getDataType());
+ this->m_buffer = (float *)MEM_mallocN_aligned(
+ sizeof(float) * determineBufferSize() * this->m_num_channels, 16, "COM_MemoryBuffer");
+ this->m_state = COM_MB_TEMPORARILY;
+ this->m_datatype = memoryProxy->getDataType();
}
MemoryBuffer::MemoryBuffer(DataType dataType, rcti *rect)
{
- BLI_rcti_init(&this->m_rect, rect->xmin, rect->xmax, rect->ymin, rect->ymax);
- this->m_width = BLI_rcti_size_x(&this->m_rect);
- this->m_height = BLI_rcti_size_y(&this->m_rect);
- this->m_height = this->m_rect.ymax - this->m_rect.ymin;
- this->m_memoryProxy = NULL;
- this->m_chunkNumber = -1;
- this->m_num_channels = determine_num_channels(dataType);
- this->m_buffer = (float *)MEM_mallocN_aligned(sizeof(float) * determineBufferSize() * this->m_num_channels, 16, "COM_MemoryBuffer");
- this->m_state = COM_MB_TEMPORARILY;
- this->m_datatype = dataType;
+ BLI_rcti_init(&this->m_rect, rect->xmin, rect->xmax, rect->ymin, rect->ymax);
+ this->m_width = BLI_rcti_size_x(&this->m_rect);
+ this->m_height = BLI_rcti_size_y(&this->m_rect);
+ this->m_height = this->m_rect.ymax - this->m_rect.ymin;
+ this->m_memoryProxy = NULL;
+ this->m_chunkNumber = -1;
+ this->m_num_channels = determine_num_channels(dataType);
+ this->m_buffer = (float *)MEM_mallocN_aligned(
+ sizeof(float) * determineBufferSize() * this->m_num_channels, 16, "COM_MemoryBuffer");
+ this->m_state = COM_MB_TEMPORARILY;
+ this->m_datatype = dataType;
}
MemoryBuffer *MemoryBuffer::duplicate()
{
- MemoryBuffer *result = new MemoryBuffer(this->m_memoryProxy, &this->m_rect);
- memcpy(result->m_buffer, this->m_buffer, this->determineBufferSize() * this->m_num_channels * sizeof(float));
- return result;
+ MemoryBuffer *result = new MemoryBuffer(this->m_memoryProxy, &this->m_rect);
+ memcpy(result->m_buffer,
+ this->m_buffer,
+ this->determineBufferSize() * this->m_num_channels * sizeof(float));
+ return result;
}
void MemoryBuffer::clear()
{
- memset(this->m_buffer, 0, this->determineBufferSize() * this->m_num_channels * sizeof(float));
+ memset(this->m_buffer, 0, this->determineBufferSize() * this->m_num_channels * sizeof(float));
}
-
float MemoryBuffer::getMaximumValue()
{
- float result = this->m_buffer[0];
- const unsigned int size = this->determineBufferSize();
- unsigned int i;
+ float result = this->m_buffer[0];
+ const unsigned int size = this->determineBufferSize();
+ unsigned int i;
- const float *fp_src = this->m_buffer;
+ const float *fp_src = this->m_buffer;
- for (i = 0; i < size; i++, fp_src += this->m_num_channels) {
- float value = *fp_src;
- if (value > result) {
- result = value;
- }
- }
+ for (i = 0; i < size; i++, fp_src += this->m_num_channels) {
+ float value = *fp_src;
+ if (value > result) {
+ result = value;
+ }
+ }
- return result;
+ return result;
}
float MemoryBuffer::getMaximumValue(rcti *rect)
{
- rcti rect_clamp;
+ rcti rect_clamp;
- /* first clamp the rect by the bounds or we get un-initialized values */
- BLI_rcti_isect(rect, &this->m_rect, &rect_clamp);
+ /* first clamp the rect by the bounds or we get un-initialized values */
+ BLI_rcti_isect(rect, &this->m_rect, &rect_clamp);
- if (!BLI_rcti_is_empty(&rect_clamp)) {
- MemoryBuffer *temp = new MemoryBuffer(this->m_datatype, &rect_clamp);
- temp->copyContentFrom(this);
- float result = temp->getMaximumValue();
- delete temp;
- return result;
- }
- else {
- BLI_assert(0);
- return 0.0f;
- }
+ if (!BLI_rcti_is_empty(&rect_clamp)) {
+ MemoryBuffer *temp = new MemoryBuffer(this->m_datatype, &rect_clamp);
+ temp->copyContentFrom(this);
+ float result = temp->getMaximumValue();
+ delete temp;
+ return result;
+ }
+ else {
+ BLI_assert(0);
+ return 0.0f;
+ }
}
MemoryBuffer::~MemoryBuffer()
{
- if (this->m_buffer) {
- MEM_freeN(this->m_buffer);
- this->m_buffer = NULL;
- }
+ if (this->m_buffer) {
+ MEM_freeN(this->m_buffer);
+ this->m_buffer = NULL;
+ }
}
void MemoryBuffer::copyContentFrom(MemoryBuffer *otherBuffer)
{
- if (!otherBuffer) {
- BLI_assert(0);
- return;
- }
- unsigned int otherY;
- unsigned int minX = max(this->m_rect.xmin, otherBuffer->m_rect.xmin);
- unsigned int maxX = min(this->m_rect.xmax, otherBuffer->m_rect.xmax);
- unsigned int minY = max(this->m_rect.ymin, otherBuffer->m_rect.ymin);
- unsigned int maxY = min(this->m_rect.ymax, otherBuffer->m_rect.ymax);
- int offset;
- int otherOffset;
-
-
- for (otherY = minY; otherY < maxY; otherY++) {
- otherOffset = ((otherY - otherBuffer->m_rect.ymin) * otherBuffer->m_width + minX - otherBuffer->m_rect.xmin) * this->m_num_channels;
- offset = ((otherY - this->m_rect.ymin) * this->m_width + minX - this->m_rect.xmin) * this->m_num_channels;
- memcpy(&this->m_buffer[offset], &otherBuffer->m_buffer[otherOffset], (maxX - minX) * this->m_num_channels * sizeof(float));
- }
+ if (!otherBuffer) {
+ BLI_assert(0);
+ return;
+ }
+ unsigned int otherY;
+ unsigned int minX = max(this->m_rect.xmin, otherBuffer->m_rect.xmin);
+ unsigned int maxX = min(this->m_rect.xmax, otherBuffer->m_rect.xmax);
+ unsigned int minY = max(this->m_rect.ymin, otherBuffer->m_rect.ymin);
+ unsigned int maxY = min(this->m_rect.ymax, otherBuffer->m_rect.ymax);
+ int offset;
+ int otherOffset;
+
+ for (otherY = minY; otherY < maxY; otherY++) {
+ otherOffset = ((otherY - otherBuffer->m_rect.ymin) * otherBuffer->m_width + minX -
+ otherBuffer->m_rect.xmin) *
+ this->m_num_channels;
+ offset = ((otherY - this->m_rect.ymin) * this->m_width + minX - this->m_rect.xmin) *
+ this->m_num_channels;
+ memcpy(&this->m_buffer[offset],
+ &otherBuffer->m_buffer[otherOffset],
+ (maxX - minX) * this->m_num_channels * sizeof(float));
+ }
}
void MemoryBuffer::writePixel(int x, int y, const float color[4])
{
- if (x >= this->m_rect.xmin && x < this->m_rect.xmax &&
- y >= this->m_rect.ymin && y < this->m_rect.ymax)
- {
- const int offset = (this->m_width * (y - this->m_rect.ymin) + x - this->m_rect.xmin) * this->m_num_channels;
- memcpy(&this->m_buffer[offset], color, sizeof(float) * this->m_num_channels);
- }
+ if (x >= this->m_rect.xmin && x < this->m_rect.xmax && y >= this->m_rect.ymin &&
+ y < this->m_rect.ymax) {
+ const int offset = (this->m_width * (y - this->m_rect.ymin) + x - this->m_rect.xmin) *
+ this->m_num_channels;
+ memcpy(&this->m_buffer[offset], color, sizeof(float) * this->m_num_channels);
+ }
}
void MemoryBuffer::addPixel(int x, int y, const float color[4])
{
- if (x >= this->m_rect.xmin && x < this->m_rect.xmax &&
- y >= this->m_rect.ymin && y < this->m_rect.ymax)
- {
- const int offset = (this->m_width * (y - this->m_rect.ymin) + x - this->m_rect.xmin) * this->m_num_channels;
- float *dst = &this->m_buffer[offset];
- const float *src = color;
- for (int i = 0; i < this->m_num_channels ; i++, dst++, src++) {
- *dst += *src;
- }
- }
+ if (x >= this->m_rect.xmin && x < this->m_rect.xmax && y >= this->m_rect.ymin &&
+ y < this->m_rect.ymax) {
+ const int offset = (this->m_width * (y - this->m_rect.ymin) + x - this->m_rect.xmin) *
+ this->m_num_channels;
+ float *dst = &this->m_buffer[offset];
+ const float *src = color;
+ for (int i = 0; i < this->m_num_channels; i++, dst++, src++) {
+ *dst += *src;
+ }
+ }
}
static void read_ewa_pixel_sampled(void *userdata, int x, int y, float result[4])
{
- MemoryBuffer *buffer = (MemoryBuffer *) userdata;
- buffer->read(result, x, y);
+ MemoryBuffer *buffer = (MemoryBuffer *)userdata;
+ buffer->read(result, x, y);
}
void MemoryBuffer::readEWA(float *result, const float uv[2], const float derivatives[2][2])
{
- BLI_assert(this->m_datatype == COM_DT_COLOR);
- float inv_width = 1.0f / (float)this->getWidth(),
- inv_height = 1.0f / (float)this->getHeight();
- /* TODO(sergey): Render pipeline uses normalized coordinates and derivatives,
- * but compositor uses pixel space. For now let's just divide the values and
- * switch compositor to normalized space for EWA later.
- */
- float uv_normal[2] = {uv[0] * inv_width, uv[1] * inv_height};
- float du_normal[2] = {derivatives[0][0] * inv_width, derivatives[0][1] * inv_height};
- float dv_normal[2] = {derivatives[1][0] * inv_width, derivatives[1][1] * inv_height};
-
- BLI_ewa_filter(this->getWidth(), this->getHeight(),
- false,
- true,
- uv_normal, du_normal, dv_normal,
- read_ewa_pixel_sampled,
- this,
- result);
+ BLI_assert(this->m_datatype == COM_DT_COLOR);
+ float inv_width = 1.0f / (float)this->getWidth(), inv_height = 1.0f / (float)this->getHeight();
+ /* TODO(sergey): Render pipeline uses normalized coordinates and derivatives,
+ * but compositor uses pixel space. For now let's just divide the values and
+ * switch compositor to normalized space for EWA later.
+ */
+ float uv_normal[2] = {uv[0] * inv_width, uv[1] * inv_height};
+ float du_normal[2] = {derivatives[0][0] * inv_width, derivatives[0][1] * inv_height};
+ float dv_normal[2] = {derivatives[1][0] * inv_width, derivatives[1][1] * inv_height};
+
+ BLI_ewa_filter(this->getWidth(),
+ this->getHeight(),
+ false,
+ true,
+ uv_normal,
+ du_normal,
+ dv_normal,
+ read_ewa_pixel_sampled,
+ this,
+ result);
}
diff --git a/source/blender/compositor/intern/COM_MemoryBuffer.h b/source/blender/compositor/intern/COM_MemoryBuffer.h
index 63897da0b8a..12cd55c95a3 100644
--- a/source/blender/compositor/intern/COM_MemoryBuffer.h
+++ b/source/blender/compositor/intern/COM_MemoryBuffer.h
@@ -26,8 +26,8 @@ class MemoryBuffer;
#include "COM_SocketReader.h"
extern "C" {
-# include "BLI_math.h"
-# include "BLI_rect.h"
+#include "BLI_math.h"
+#include "BLI_rect.h"
}
/**
@@ -35,18 +35,18 @@ extern "C" {
* \ingroup Memory
*/
typedef enum MemoryBufferState {
- /** \brief memory has been allocated on creator device and CPU machine, but kernel has not been executed */
- COM_MB_ALLOCATED = 1,
- /** \brief memory is available for use, content has been created */
- COM_MB_AVAILABLE = 2,
- /** \brief chunk is consolidated from other chunks. special state.*/
- COM_MB_TEMPORARILY = 6,
+ /** \brief memory has been allocated on creator device and CPU machine, but kernel has not been executed */
+ COM_MB_ALLOCATED = 1,
+ /** \brief memory is available for use, content has been created */
+ COM_MB_AVAILABLE = 2,
+ /** \brief chunk is consolidated from other chunks. special state.*/
+ COM_MB_TEMPORARILY = 6,
} MemoryBufferState;
typedef enum MemoryBufferExtend {
- COM_MB_CLIP,
- COM_MB_EXTEND,
- COM_MB_REPEAT,
+ COM_MB_CLIP,
+ COM_MB_EXTEND,
+ COM_MB_REPEAT,
} MemoryBufferExtend;
class MemoryProxy;
@@ -55,262 +55,299 @@ class MemoryProxy;
* \brief a MemoryBuffer contains access to the data of a chunk
*/
class MemoryBuffer {
-private:
- /**
- * \brief proxy of the memory (same for all chunks in the same buffer)
- */
- MemoryProxy *m_memoryProxy;
-
- /**
- * \brief the type of buffer COM_DT_VALUE, COM_DT_VECTOR, COM_DT_COLOR
- */
- DataType m_datatype;
-
-
- /**
- * \brief region of this buffer inside relative to the MemoryProxy
- */
- rcti m_rect;
-
- /**
- * brief refers to the chunknumber within the executiongroup where related to the MemoryProxy
- * \see memoryProxy
- */
- unsigned int m_chunkNumber;
-
- /**
- * \brief state of the buffer
- */
- MemoryBufferState m_state;
-
- /**
- * \brief the actual float buffer/data
- */
- float *m_buffer;
-
- /**
- * \brief the number of channels of a single value in the buffer.
- * For value buffers this is 1, vector 3 and color 4
- */
- unsigned int m_num_channels;
-
- int m_width;
- int m_height;
-
-public:
- /**
- * \brief construct new MemoryBuffer for a chunk
- */
- MemoryBuffer(MemoryProxy *memoryProxy, unsigned int chunkNumber, rcti *rect);
-
- /**
- * \brief construct new temporarily MemoryBuffer for an area
- */
- MemoryBuffer(MemoryProxy *memoryProxy, rcti *rect);
-
- /**
- * \brief construct new temporarily MemoryBuffer for an area
- */
- MemoryBuffer(DataType datatype, rcti *rect);
-
- /**
- * \brief destructor
- */
- ~MemoryBuffer();
-
- /**
- * \brief read the ChunkNumber of this MemoryBuffer
- */
- unsigned int getChunkNumber() { return this->m_chunkNumber; }
-
- unsigned int get_num_channels() { return this->m_num_channels; }
-
- /**
- * \brief get the data of this MemoryBuffer
- * \note buffer should already be available in memory
- */
- float *getBuffer() { return this->m_buffer; }
-
- /**
- * \brief after execution the state will be set to available by calling this method
- */
- void setCreatedState()
- {
- this->m_state = COM_MB_AVAILABLE;
- }
-
- inline void wrap_pixel(int &x, int &y, MemoryBufferExtend extend_x, MemoryBufferExtend extend_y)
- {
- int w = this->m_width;
- int h = this->m_height;
- x = x - m_rect.xmin;
- y = y - m_rect.ymin;
-
- switch (extend_x) {
- case COM_MB_CLIP:
- break;
- case COM_MB_EXTEND:
- if (x < 0) x = 0;
- if (x >= w) x = w;
- break;
- case COM_MB_REPEAT:
- x = (x >= 0.0f ? (x % w) : (x % w) + w);
- break;
- }
-
- switch (extend_y) {
- case COM_MB_CLIP:
- break;
- case COM_MB_EXTEND:
- if (y < 0) y = 0;
- if (y >= h) y = h;
- break;
- case COM_MB_REPEAT:
- y = (y >= 0.0f ? (y % h) : (y % h) + h);
- break;
- }
- }
-
- inline void wrap_pixel(float &x, float &y, MemoryBufferExtend extend_x, MemoryBufferExtend extend_y)
- {
- float w = (float)this->m_width;
- float h = (float)this->m_height;
- x = x - m_rect.xmin;
- y = y - m_rect.ymin;
-
- switch (extend_x) {
- case COM_MB_CLIP:
- break;
- case COM_MB_EXTEND:
- if (x < 0) x = 0.0f;
- if (x >= w) x = w;
- break;
- case COM_MB_REPEAT:
- x = fmodf(x, w);
- break;
- }
-
- switch (extend_y) {
- case COM_MB_CLIP:
- break;
- case COM_MB_EXTEND:
- if (y < 0) y = 0.0f;
- if (y >= h) y = h;
- break;
- case COM_MB_REPEAT:
- y = fmodf(y, h);
- break;
- }
- }
-
- inline void read(float *result, int x, int y,
- MemoryBufferExtend extend_x = COM_MB_CLIP,
- MemoryBufferExtend extend_y = COM_MB_CLIP)
- {
- bool clip_x = (extend_x == COM_MB_CLIP && (x < m_rect.xmin || x >= m_rect.xmax));
- bool clip_y = (extend_y == COM_MB_CLIP && (y < m_rect.ymin || y >= m_rect.ymax));
- if (clip_x || clip_y) {
- /* clip result outside rect is zero */
- memset(result, 0, this->m_num_channels * sizeof(float));
- }
- else {
- int u = x;
- int v = y;
- this->wrap_pixel(u, v, extend_x, extend_y);
- const int offset = (this->m_width * y + x) * this->m_num_channels;
- float *buffer = &this->m_buffer[offset];
- memcpy(result, buffer, sizeof(float) * this->m_num_channels);
- }
- }
-
- inline void readNoCheck(float *result, int x, int y,
- MemoryBufferExtend extend_x = COM_MB_CLIP,
- MemoryBufferExtend extend_y = COM_MB_CLIP)
- {
- int u = x;
- int v = y;
-
- this->wrap_pixel(u, v, extend_x, extend_y);
- const int offset = (this->m_width * v + u) * this->m_num_channels;
-
- BLI_assert(offset >= 0);
- BLI_assert(offset < this->determineBufferSize() * this->m_num_channels);
- BLI_assert(!(extend_x == COM_MB_CLIP && (u < m_rect.xmin || u >= m_rect.xmax)) &&
- !(extend_y == COM_MB_CLIP && (v < m_rect.ymin || v >= m_rect.ymax)));
+ private:
+ /**
+ * \brief proxy of the memory (same for all chunks in the same buffer)
+ */
+ MemoryProxy *m_memoryProxy;
+
+ /**
+ * \brief the type of buffer COM_DT_VALUE, COM_DT_VECTOR, COM_DT_COLOR
+ */
+ DataType m_datatype;
+
+ /**
+ * \brief region of this buffer inside relative to the MemoryProxy
+ */
+ rcti m_rect;
+
+ /**
+ * brief refers to the chunknumber within the executiongroup where related to the MemoryProxy
+ * \see memoryProxy
+ */
+ unsigned int m_chunkNumber;
+
+ /**
+ * \brief state of the buffer
+ */
+ MemoryBufferState m_state;
+
+ /**
+ * \brief the actual float buffer/data
+ */
+ float *m_buffer;
+
+ /**
+ * \brief the number of channels of a single value in the buffer.
+ * For value buffers this is 1, vector 3 and color 4
+ */
+ unsigned int m_num_channels;
+
+ int m_width;
+ int m_height;
+
+ public:
+ /**
+ * \brief construct new MemoryBuffer for a chunk
+ */
+ MemoryBuffer(MemoryProxy *memoryProxy, unsigned int chunkNumber, rcti *rect);
+
+ /**
+ * \brief construct new temporarily MemoryBuffer for an area
+ */
+ MemoryBuffer(MemoryProxy *memoryProxy, rcti *rect);
+
+ /**
+ * \brief construct new temporarily MemoryBuffer for an area
+ */
+ MemoryBuffer(DataType datatype, rcti *rect);
+
+ /**
+ * \brief destructor
+ */
+ ~MemoryBuffer();
+
+ /**
+ * \brief read the ChunkNumber of this MemoryBuffer
+ */
+ unsigned int getChunkNumber()
+ {
+ return this->m_chunkNumber;
+ }
+
+ unsigned int get_num_channels()
+ {
+ return this->m_num_channels;
+ }
+
+ /**
+ * \brief get the data of this MemoryBuffer
+ * \note buffer should already be available in memory
+ */
+ float *getBuffer()
+ {
+ return this->m_buffer;
+ }
+
+ /**
+ * \brief after execution the state will be set to available by calling this method
+ */
+ void setCreatedState()
+ {
+ this->m_state = COM_MB_AVAILABLE;
+ }
+
+ inline void wrap_pixel(int &x, int &y, MemoryBufferExtend extend_x, MemoryBufferExtend extend_y)
+ {
+ int w = this->m_width;
+ int h = this->m_height;
+ x = x - m_rect.xmin;
+ y = y - m_rect.ymin;
+
+ switch (extend_x) {
+ case COM_MB_CLIP:
+ break;
+ case COM_MB_EXTEND:
+ if (x < 0)
+ x = 0;
+ if (x >= w)
+ x = w;
+ break;
+ case COM_MB_REPEAT:
+ x = (x >= 0.0f ? (x % w) : (x % w) + w);
+ break;
+ }
+
+ switch (extend_y) {
+ case COM_MB_CLIP:
+ break;
+ case COM_MB_EXTEND:
+ if (y < 0)
+ y = 0;
+ if (y >= h)
+ y = h;
+ break;
+ case COM_MB_REPEAT:
+ y = (y >= 0.0f ? (y % h) : (y % h) + h);
+ break;
+ }
+ }
+
+ inline void wrap_pixel(float &x,
+ float &y,
+ MemoryBufferExtend extend_x,
+ MemoryBufferExtend extend_y)
+ {
+ float w = (float)this->m_width;
+ float h = (float)this->m_height;
+ x = x - m_rect.xmin;
+ y = y - m_rect.ymin;
+
+ switch (extend_x) {
+ case COM_MB_CLIP:
+ break;
+ case COM_MB_EXTEND:
+ if (x < 0)
+ x = 0.0f;
+ if (x >= w)
+ x = w;
+ break;
+ case COM_MB_REPEAT:
+ x = fmodf(x, w);
+ break;
+ }
+
+ switch (extend_y) {
+ case COM_MB_CLIP:
+ break;
+ case COM_MB_EXTEND:
+ if (y < 0)
+ y = 0.0f;
+ if (y >= h)
+ y = h;
+ break;
+ case COM_MB_REPEAT:
+ y = fmodf(y, h);
+ break;
+ }
+ }
+
+ inline void read(float *result,
+ int x,
+ int y,
+ MemoryBufferExtend extend_x = COM_MB_CLIP,
+ MemoryBufferExtend extend_y = COM_MB_CLIP)
+ {
+ bool clip_x = (extend_x == COM_MB_CLIP && (x < m_rect.xmin || x >= m_rect.xmax));
+ bool clip_y = (extend_y == COM_MB_CLIP && (y < m_rect.ymin || y >= m_rect.ymax));
+ if (clip_x || clip_y) {
+ /* clip result outside rect is zero */
+ memset(result, 0, this->m_num_channels * sizeof(float));
+ }
+ else {
+ int u = x;
+ int v = y;
+ this->wrap_pixel(u, v, extend_x, extend_y);
+ const int offset = (this->m_width * y + x) * this->m_num_channels;
+ float *buffer = &this->m_buffer[offset];
+ memcpy(result, buffer, sizeof(float) * this->m_num_channels);
+ }
+ }
+
+ inline void readNoCheck(float *result,
+ int x,
+ int y,
+ MemoryBufferExtend extend_x = COM_MB_CLIP,
+ MemoryBufferExtend extend_y = COM_MB_CLIP)
+ {
+ int u = x;
+ int v = y;
+
+ this->wrap_pixel(u, v, extend_x, extend_y);
+ const int offset = (this->m_width * v + u) * this->m_num_channels;
+
+ BLI_assert(offset >= 0);
+ BLI_assert(offset < this->determineBufferSize() * this->m_num_channels);
+ BLI_assert(!(extend_x == COM_MB_CLIP && (u < m_rect.xmin || u >= m_rect.xmax)) &&
+ !(extend_y == COM_MB_CLIP && (v < m_rect.ymin || v >= m_rect.ymax)));
#if 0
- /* always true */
- BLI_assert((int)(MEM_allocN_len(this->m_buffer) / sizeof(*this->m_buffer)) ==
- (int)(this->determineBufferSize() * COM_NUMBER_OF_CHANNELS));
+ /* always true */
+ BLI_assert((int)(MEM_allocN_len(this->m_buffer) / sizeof(*this->m_buffer)) ==
+ (int)(this->determineBufferSize() * COM_NUMBER_OF_CHANNELS));
#endif
- float *buffer = &this->m_buffer[offset];
- memcpy(result, buffer, sizeof(float) * this->m_num_channels);
- }
-
- void writePixel(int x, int y, const float color[4]);
- void addPixel(int x, int y, const float color[4]);
- inline void readBilinear(float *result, float x, float y,
- MemoryBufferExtend extend_x = COM_MB_CLIP,
- MemoryBufferExtend extend_y = COM_MB_CLIP)
- {
- float u = x;
- float v = y;
- this->wrap_pixel(u, v, extend_x, extend_y);
- if ((extend_x != COM_MB_REPEAT && (u < 0.0f || u >= this->m_width)) ||
- (extend_y != COM_MB_REPEAT && (v < 0.0f || v >= this->m_height)))
- {
- copy_vn_fl(result, this->m_num_channels, 0.0f);
- return;
- }
- BLI_bilinear_interpolation_wrap_fl(
- this->m_buffer, result, this->m_width, this->m_height, this->m_num_channels, u, v,
- extend_x == COM_MB_REPEAT, extend_y == COM_MB_REPEAT);
- }
-
- void readEWA(float *result, const float uv[2], const float derivatives[2][2]);
-
- /**
- * \brief is this MemoryBuffer a temporarily buffer (based on an area, not on a chunk)
- */
- inline bool isTemporarily() const { return this->m_state == COM_MB_TEMPORARILY; }
-
- /**
- * \brief add the content from otherBuffer to this MemoryBuffer
- * \param otherBuffer: source buffer
- *
- * \note take care when running this on a new buffer since it wont fill in
- * uninitialized values in areas where the buffers don't overlap.
- */
- void copyContentFrom(MemoryBuffer *otherBuffer);
-
- /**
- * \brief get the rect of this MemoryBuffer
- */
- rcti *getRect() { return &this->m_rect; }
-
- /**
- * \brief get the width of this MemoryBuffer
- */
- int getWidth() const;
-
- /**
- * \brief get the height of this MemoryBuffer
- */
- int getHeight() const;
-
- /**
- * \brief clear the buffer. Make all pixels black transparent.
- */
- void clear();
-
- MemoryBuffer *duplicate();
-
- float getMaximumValue();
- float getMaximumValue(rcti *rect);
-private:
- unsigned int determineBufferSize();
+ float *buffer = &this->m_buffer[offset];
+ memcpy(result, buffer, sizeof(float) * this->m_num_channels);
+ }
+
+ void writePixel(int x, int y, const float color[4]);
+ void addPixel(int x, int y, const float color[4]);
+ inline void readBilinear(float *result,
+ float x,
+ float y,
+ MemoryBufferExtend extend_x = COM_MB_CLIP,
+ MemoryBufferExtend extend_y = COM_MB_CLIP)
+ {
+ float u = x;
+ float v = y;
+ this->wrap_pixel(u, v, extend_x, extend_y);
+ if ((extend_x != COM_MB_REPEAT && (u < 0.0f || u >= this->m_width)) ||
+ (extend_y != COM_MB_REPEAT && (v < 0.0f || v >= this->m_height))) {
+ copy_vn_fl(result, this->m_num_channels, 0.0f);
+ return;
+ }
+ BLI_bilinear_interpolation_wrap_fl(this->m_buffer,
+ result,
+ this->m_width,
+ this->m_height,
+ this->m_num_channels,
+ u,
+ v,
+ extend_x == COM_MB_REPEAT,
+ extend_y == COM_MB_REPEAT);
+ }
+
+ void readEWA(float *result, const float uv[2], const float derivatives[2][2]);
+
+ /**
+ * \brief is this MemoryBuffer a temporarily buffer (based on an area, not on a chunk)
+ */
+ inline bool isTemporarily() const
+ {
+ return this->m_state == COM_MB_TEMPORARILY;
+ }
+
+ /**
+ * \brief add the content from otherBuffer to this MemoryBuffer
+ * \param otherBuffer: source buffer
+ *
+ * \note take care when running this on a new buffer since it wont fill in
+ * uninitialized values in areas where the buffers don't overlap.
+ */
+ void copyContentFrom(MemoryBuffer *otherBuffer);
+
+ /**
+ * \brief get the rect of this MemoryBuffer
+ */
+ rcti *getRect()
+ {
+ return &this->m_rect;
+ }
+
+ /**
+ * \brief get the width of this MemoryBuffer
+ */
+ int getWidth() const;
+
+ /**
+ * \brief get the height of this MemoryBuffer
+ */
+ int getHeight() const;
+
+ /**
+ * \brief clear the buffer. Make all pixels black transparent.
+ */
+ void clear();
+
+ MemoryBuffer *duplicate();
+
+ float getMaximumValue();
+ float getMaximumValue(rcti *rect);
+
+ private:
+ unsigned int determineBufferSize();
#ifdef WITH_CXX_GUARDEDALLOC
- MEM_CXX_CLASS_ALLOC_FUNCS("COM:MemoryBuffer")
+ MEM_CXX_CLASS_ALLOC_FUNCS("COM:MemoryBuffer")
#endif
};
diff --git a/source/blender/compositor/intern/COM_MemoryProxy.cpp b/source/blender/compositor/intern/COM_MemoryProxy.cpp
index ab8df14de56..b73bac469d0 100644
--- a/source/blender/compositor/intern/COM_MemoryProxy.cpp
+++ b/source/blender/compositor/intern/COM_MemoryProxy.cpp
@@ -18,29 +18,28 @@
#include "COM_MemoryProxy.h"
-
MemoryProxy::MemoryProxy(DataType datatype)
{
- this->m_writeBufferOperation = NULL;
- this->m_executor = NULL;
- this->m_datatype = datatype;
+ this->m_writeBufferOperation = NULL;
+ this->m_executor = NULL;
+ this->m_datatype = datatype;
}
void MemoryProxy::allocate(unsigned int width, unsigned int height)
{
- rcti result;
- result.xmin = 0;
- result.xmax = width;
- result.ymin = 0;
- result.ymax = height;
+ rcti result;
+ result.xmin = 0;
+ result.xmax = width;
+ result.ymin = 0;
+ result.ymax = height;
- this->m_buffer = new MemoryBuffer(this, 1, &result);
+ this->m_buffer = new MemoryBuffer(this, 1, &result);
}
void MemoryProxy::free()
{
- if (this->m_buffer) {
- delete this->m_buffer;
- this->m_buffer = NULL;
- }
+ if (this->m_buffer) {
+ delete this->m_buffer;
+ this->m_buffer = NULL;
+ }
}
diff --git a/source/blender/compositor/intern/COM_MemoryProxy.h b/source/blender/compositor/intern/COM_MemoryProxy.h
index 6f911a92f42..c363bf610cc 100644
--- a/source/blender/compositor/intern/COM_MemoryProxy.h
+++ b/source/blender/compositor/intern/COM_MemoryProxy.h
@@ -18,7 +18,6 @@
class MemoryProxy;
-
#ifndef __COM_MEMORYPROXY_H__
#define __COM_MEMORYPROXY_H__
#include "COM_ExecutionGroup.h"
@@ -33,82 +32,100 @@ class WriteBufferOperation;
* \ingroup Memory
*/
class MemoryProxy {
-private:
- /**
- * \brief reference to the output operation of the executiongroup
- */
- WriteBufferOperation *m_writeBufferOperation;
-
- /**
- * \brief reference to the executor. the Execution group that can fill a chunk
- */
- ExecutionGroup *m_executor;
-
- /**
- * \brief datatype of this MemoryProxy
- */
- /* DataType m_datatype; */ /* UNUSED */
-
- /**
- * \brief channel information of this buffer
- */
- /* ChannelInfo m_channelInfo[COM_NUMBER_OF_CHANNELS]; */ /* UNUSED */
-
- /**
- * \brief the allocated memory
- */
- MemoryBuffer *m_buffer;
-
- /**
- * \brief datatype of this MemoryProxy
- */
- DataType m_datatype;
-
-public:
- MemoryProxy(DataType type);
-
- /**
- * \brief set the ExecutionGroup that can be scheduled to calculate a certain chunk.
- * \param group: the ExecutionGroup to set
- */
- void setExecutor(ExecutionGroup *executor) { this->m_executor = executor; }
-
- /**
- * \brief get the ExecutionGroup that can be scheduled to calculate a certain chunk.
- */
- ExecutionGroup *getExecutor() { return this->m_executor; }
-
- /**
- * \brief set the WriteBufferOperation that is responsible for writing to this MemoryProxy
- * \param operation:
- */
- void setWriteBufferOperation(WriteBufferOperation *operation) { this->m_writeBufferOperation = operation; }
-
- /**
- * \brief get the WriteBufferOperation that is responsible for writing to this MemoryProxy
- * \return WriteBufferOperation
- */
- WriteBufferOperation *getWriteBufferOperation() { return this->m_writeBufferOperation; }
-
- /**
- * \brief allocate memory of size width x height
- */
- void allocate(unsigned int width, unsigned int height);
-
- /**
- * \brief free the allocated memory
- */
- void free();
-
- /**
- * \brief get the allocated memory
- */
- inline MemoryBuffer *getBuffer() { return this->m_buffer; }
-
- inline DataType getDataType() { return this->m_datatype; }
+ private:
+ /**
+ * \brief reference to the output operation of the executiongroup
+ */
+ WriteBufferOperation *m_writeBufferOperation;
+
+ /**
+ * \brief reference to the executor. the Execution group that can fill a chunk
+ */
+ ExecutionGroup *m_executor;
+
+ /**
+ * \brief datatype of this MemoryProxy
+ */
+ /* DataType m_datatype; */ /* UNUSED */
+
+ /**
+ * \brief channel information of this buffer
+ */
+ /* ChannelInfo m_channelInfo[COM_NUMBER_OF_CHANNELS]; */ /* UNUSED */
+
+ /**
+ * \brief the allocated memory
+ */
+ MemoryBuffer *m_buffer;
+
+ /**
+ * \brief datatype of this MemoryProxy
+ */
+ DataType m_datatype;
+
+ public:
+ MemoryProxy(DataType type);
+
+ /**
+ * \brief set the ExecutionGroup that can be scheduled to calculate a certain chunk.
+ * \param group: the ExecutionGroup to set
+ */
+ void setExecutor(ExecutionGroup *executor)
+ {
+ this->m_executor = executor;
+ }
+
+ /**
+ * \brief get the ExecutionGroup that can be scheduled to calculate a certain chunk.
+ */
+ ExecutionGroup *getExecutor()
+ {
+ return this->m_executor;
+ }
+
+ /**
+ * \brief set the WriteBufferOperation that is responsible for writing to this MemoryProxy
+ * \param operation:
+ */
+ void setWriteBufferOperation(WriteBufferOperation *operation)
+ {
+ this->m_writeBufferOperation = operation;
+ }
+
+ /**
+ * \brief get the WriteBufferOperation that is responsible for writing to this MemoryProxy
+ * \return WriteBufferOperation
+ */
+ WriteBufferOperation *getWriteBufferOperation()
+ {
+ return this->m_writeBufferOperation;
+ }
+
+ /**
+ * \brief allocate memory of size width x height
+ */
+ void allocate(unsigned int width, unsigned int height);
+
+ /**
+ * \brief free the allocated memory
+ */
+ void free();
+
+ /**
+ * \brief get the allocated memory
+ */
+ inline MemoryBuffer *getBuffer()
+ {
+ return this->m_buffer;
+ }
+
+ inline DataType getDataType()
+ {
+ return this->m_datatype;
+ }
#ifdef WITH_CXX_GUARDEDALLOC
- MEM_CXX_CLASS_ALLOC_FUNCS("COM:MemoryProxy")
+ MEM_CXX_CLASS_ALLOC_FUNCS("COM:MemoryProxy")
#endif
};
diff --git a/source/blender/compositor/intern/COM_Node.cpp b/source/blender/compositor/intern/COM_Node.cpp
index 5435c0475c8..b38493e19f2 100644
--- a/source/blender/compositor/intern/COM_Node.cpp
+++ b/source/blender/compositor/intern/COM_Node.cpp
@@ -38,175 +38,171 @@ extern "C" {
**** Node ****
**************/
-Node::Node(bNode *editorNode, bool create_sockets) :
- m_editorNodeTree(NULL),
- m_editorNode(editorNode),
- m_inActiveGroup(false),
- m_instanceKey(NODE_INSTANCE_KEY_NONE)
-{
- if (create_sockets) {
- bNodeSocket *input = (bNodeSocket *)editorNode->inputs.first;
- while (input != NULL) {
- DataType dt = COM_DT_VALUE;
- if (input->type == SOCK_RGBA) dt = COM_DT_COLOR;
- if (input->type == SOCK_VECTOR) dt = COM_DT_VECTOR;
-
- this->addInputSocket(dt, input);
- input = input->next;
- }
- bNodeSocket *output = (bNodeSocket *)editorNode->outputs.first;
- while (output != NULL) {
- DataType dt = COM_DT_VALUE;
- if (output->type == SOCK_RGBA) dt = COM_DT_COLOR;
- if (output->type == SOCK_VECTOR) dt = COM_DT_VECTOR;
-
- this->addOutputSocket(dt, output);
- output = output->next;
- }
- }
+Node::Node(bNode *editorNode, bool create_sockets)
+ : m_editorNodeTree(NULL),
+ m_editorNode(editorNode),
+ m_inActiveGroup(false),
+ m_instanceKey(NODE_INSTANCE_KEY_NONE)
+{
+ if (create_sockets) {
+ bNodeSocket *input = (bNodeSocket *)editorNode->inputs.first;
+ while (input != NULL) {
+ DataType dt = COM_DT_VALUE;
+ if (input->type == SOCK_RGBA)
+ dt = COM_DT_COLOR;
+ if (input->type == SOCK_VECTOR)
+ dt = COM_DT_VECTOR;
+
+ this->addInputSocket(dt, input);
+ input = input->next;
+ }
+ bNodeSocket *output = (bNodeSocket *)editorNode->outputs.first;
+ while (output != NULL) {
+ DataType dt = COM_DT_VALUE;
+ if (output->type == SOCK_RGBA)
+ dt = COM_DT_COLOR;
+ if (output->type == SOCK_VECTOR)
+ dt = COM_DT_VECTOR;
+
+ this->addOutputSocket(dt, output);
+ output = output->next;
+ }
+ }
}
Node::~Node()
{
- while (!this->m_outputsockets.empty()) {
- delete (this->m_outputsockets.back());
- this->m_outputsockets.pop_back();
- }
- while (!this->m_inputsockets.empty()) {
- delete (this->m_inputsockets.back());
- this->m_inputsockets.pop_back();
- }
+ while (!this->m_outputsockets.empty()) {
+ delete (this->m_outputsockets.back());
+ this->m_outputsockets.pop_back();
+ }
+ while (!this->m_inputsockets.empty()) {
+ delete (this->m_inputsockets.back());
+ this->m_inputsockets.pop_back();
+ }
}
void Node::addInputSocket(DataType datatype)
{
- this->addInputSocket(datatype, NULL);
+ this->addInputSocket(datatype, NULL);
}
void Node::addInputSocket(DataType datatype, bNodeSocket *bSocket)
{
- NodeInput *socket = new NodeInput(this, bSocket, datatype);
- this->m_inputsockets.push_back(socket);
+ NodeInput *socket = new NodeInput(this, bSocket, datatype);
+ this->m_inputsockets.push_back(socket);
}
void Node::addOutputSocket(DataType datatype)
{
- this->addOutputSocket(datatype, NULL);
-
+ this->addOutputSocket(datatype, NULL);
}
void Node::addOutputSocket(DataType datatype, bNodeSocket *bSocket)
{
- NodeOutput *socket = new NodeOutput(this, bSocket, datatype);
- this->m_outputsockets.push_back(socket);
+ NodeOutput *socket = new NodeOutput(this, bSocket, datatype);
+ this->m_outputsockets.push_back(socket);
}
NodeOutput *Node::getOutputSocket(unsigned int index) const
{
- BLI_assert(index < this->m_outputsockets.size());
- return this->m_outputsockets[index];
+ BLI_assert(index < this->m_outputsockets.size());
+ return this->m_outputsockets[index];
}
NodeInput *Node::getInputSocket(unsigned int index) const
{
- BLI_assert(index < this->m_inputsockets.size());
- return this->m_inputsockets[index];
+ BLI_assert(index < this->m_inputsockets.size());
+ return this->m_inputsockets[index];
}
bNodeSocket *Node::getEditorInputSocket(int editorNodeInputSocketIndex)
{
- bNodeSocket *bSock = (bNodeSocket *)this->getbNode()->inputs.first;
- int index = 0;
- while (bSock != NULL) {
- if (index == editorNodeInputSocketIndex) {
- return bSock;
- }
- index++;
- bSock = bSock->next;
- }
- return NULL;
+ bNodeSocket *bSock = (bNodeSocket *)this->getbNode()->inputs.first;
+ int index = 0;
+ while (bSock != NULL) {
+ if (index == editorNodeInputSocketIndex) {
+ return bSock;
+ }
+ index++;
+ bSock = bSock->next;
+ }
+ return NULL;
}
bNodeSocket *Node::getEditorOutputSocket(int editorNodeInputSocketIndex)
{
- bNodeSocket *bSock = (bNodeSocket *)this->getbNode()->outputs.first;
- int index = 0;
- while (bSock != NULL) {
- if (index == editorNodeInputSocketIndex) {
- return bSock;
- }
- index++;
- bSock = bSock->next;
- }
- return NULL;
+ bNodeSocket *bSock = (bNodeSocket *)this->getbNode()->outputs.first;
+ int index = 0;
+ while (bSock != NULL) {
+ if (index == editorNodeInputSocketIndex) {
+ return bSock;
+ }
+ index++;
+ bSock = bSock->next;
+ }
+ return NULL;
}
-
/*******************
**** NodeInput ****
*******************/
-NodeInput::NodeInput(Node *node, bNodeSocket *b_socket, DataType datatype) :
- m_node(node),
- m_editorSocket(b_socket),
- m_datatype(datatype),
- m_link(NULL)
+NodeInput::NodeInput(Node *node, bNodeSocket *b_socket, DataType datatype)
+ : m_node(node), m_editorSocket(b_socket), m_datatype(datatype), m_link(NULL)
{
}
void NodeInput::setLink(NodeOutput *link)
{
- m_link = link;
+ m_link = link;
}
float NodeInput::getEditorValueFloat()
{
- PointerRNA ptr;
- RNA_pointer_create((ID *)getNode()->getbNodeTree(), &RNA_NodeSocket, getbNodeSocket(), &ptr);
- return RNA_float_get(&ptr, "default_value");
+ PointerRNA ptr;
+ RNA_pointer_create((ID *)getNode()->getbNodeTree(), &RNA_NodeSocket, getbNodeSocket(), &ptr);
+ return RNA_float_get(&ptr, "default_value");
}
void NodeInput::getEditorValueColor(float *value)
{
- PointerRNA ptr;
- RNA_pointer_create((ID *)getNode()->getbNodeTree(), &RNA_NodeSocket, getbNodeSocket(), &ptr);
- return RNA_float_get_array(&ptr, "default_value", value);
+ PointerRNA ptr;
+ RNA_pointer_create((ID *)getNode()->getbNodeTree(), &RNA_NodeSocket, getbNodeSocket(), &ptr);
+ return RNA_float_get_array(&ptr, "default_value", value);
}
void NodeInput::getEditorValueVector(float *value)
{
- PointerRNA ptr;
- RNA_pointer_create((ID *)getNode()->getbNodeTree(), &RNA_NodeSocket, getbNodeSocket(), &ptr);
- return RNA_float_get_array(&ptr, "default_value", value);
+ PointerRNA ptr;
+ RNA_pointer_create((ID *)getNode()->getbNodeTree(), &RNA_NodeSocket, getbNodeSocket(), &ptr);
+ return RNA_float_get_array(&ptr, "default_value", value);
}
-
/********************
**** NodeOutput ****
********************/
-NodeOutput::NodeOutput(Node *node, bNodeSocket *b_socket, DataType datatype) :
- m_node(node),
- m_editorSocket(b_socket),
- m_datatype(datatype)
+NodeOutput::NodeOutput(Node *node, bNodeSocket *b_socket, DataType datatype)
+ : m_node(node), m_editorSocket(b_socket), m_datatype(datatype)
{
}
float NodeOutput::getEditorValueFloat()
{
- PointerRNA ptr;
- RNA_pointer_create((ID *)getNode()->getbNodeTree(), &RNA_NodeSocket, getbNodeSocket(), &ptr);
- return RNA_float_get(&ptr, "default_value");
+ PointerRNA ptr;
+ RNA_pointer_create((ID *)getNode()->getbNodeTree(), &RNA_NodeSocket, getbNodeSocket(), &ptr);
+ return RNA_float_get(&ptr, "default_value");
}
void NodeOutput::getEditorValueColor(float *value)
{
- PointerRNA ptr;
- RNA_pointer_create((ID *)getNode()->getbNodeTree(), &RNA_NodeSocket, getbNodeSocket(), &ptr);
- return RNA_float_get_array(&ptr, "default_value", value);
+ PointerRNA ptr;
+ RNA_pointer_create((ID *)getNode()->getbNodeTree(), &RNA_NodeSocket, getbNodeSocket(), &ptr);
+ return RNA_float_get_array(&ptr, "default_value", value);
}
void NodeOutput::getEditorValueVector(float *value)
{
- PointerRNA ptr;
- RNA_pointer_create((ID *)getNode()->getbNodeTree(), &RNA_NodeSocket, getbNodeSocket(), &ptr);
- return RNA_float_get_array(&ptr, "default_value", value);
+ PointerRNA ptr;
+ RNA_pointer_create((ID *)getNode()->getbNodeTree(), &RNA_NodeSocket, getbNodeSocket(), &ptr);
+ return RNA_float_get_array(&ptr, "default_value", value);
}
diff --git a/source/blender/compositor/intern/COM_Node.h b/source/blender/compositor/intern/COM_Node.h
index 33c86bd2cc1..9bacf271283 100644
--- a/source/blender/compositor/intern/COM_Node.h
+++ b/source/blender/compositor/intern/COM_Node.h
@@ -38,230 +38,295 @@ class NodeConverter;
* My node documentation.
*/
class Node {
-public:
- typedef std::vector<NodeInput *> Inputs;
- typedef std::vector<NodeOutput *> Outputs;
-
-private:
- /**
- * \brief stores the reference to the SDNA bNode struct
- */
- bNodeTree *m_editorNodeTree;
-
- /**
- * \brief stores the reference to the SDNA bNode struct
- */
- bNode *m_editorNode;
-
- /**
- * \brief the list of actual inputsockets \see NodeInput
- */
- Inputs m_inputsockets;
-
- /**
- * \brief the list of actual outputsockets \see NodeOutput
- */
- Outputs m_outputsockets;
-
- /**
- * \brief Is this node part of the active group
- */
- bool m_inActiveGroup;
-
- /**
- * \brief Instance key to identify the node in an instance hash table
- */
- bNodeInstanceKey m_instanceKey;
-
-protected:
- /**
- * \brief get access to the vector of input sockets
- */
- const Inputs &getInputSockets() const { return this->m_inputsockets; }
-
- /**
- * \brief get access to the vector of input sockets
- */
- const Outputs &getOutputSockets() const { return this->m_outputsockets; }
-
-public:
- Node(bNode *editorNode, bool create_sockets = true);
- virtual ~Node();
-
- /**
- * \brief get the reference to the SDNA bNode struct
- */
- bNode *getbNode() const {return m_editorNode;}
-
- /**
- * \brief get the reference to the SDNA bNodeTree struct
- */
- bNodeTree *getbNodeTree() const {return m_editorNodeTree;}
-
- /**
- * \brief set the reference to the bNode
- * \note used in Node instances to receive the storage/settings and complex node for highlight during execution
- * \param bNode:
- */
- void setbNode(bNode *node) {this->m_editorNode = node;}
-
- /**
- * \brief set the reference to the bNodeTree
- * \param bNodeTree:
- */
- void setbNodeTree(bNodeTree *nodetree) {this->m_editorNodeTree = nodetree;}
-
- /**
- * \brief Return the number of input sockets of this node.
- */
- unsigned int getNumberOfInputSockets() const { return this->m_inputsockets.size(); }
-
- /**
- * \brief Return the number of output sockets of this node.
- */
- unsigned int getNumberOfOutputSockets() const { return this->m_outputsockets.size(); }
-
- /**
- * get the reference to a certain outputsocket
- * \param index:
- * the index of the needed outputsocket
- */
- NodeOutput *getOutputSocket(const unsigned int index) const;
-
- /**
- * get the reference to the first outputsocket
- * \param index:
- * the index of the needed outputsocket
- */
- inline NodeOutput *getOutputSocket() const { return getOutputSocket(0); }
-
- /**
- * get the reference to a certain inputsocket
- * \param index:
- * the index of the needed inputsocket
- */
- NodeInput *getInputSocket(const unsigned int index) const;
-
- /** Check if this is an input node
- * An input node is a node that only has output sockets and no input sockets
- */
- bool isInputNode() const { return m_inputsockets.empty(); }
-
- /**
- * \brief Is this node in the active group (the group that is being edited)
- * \param isInActiveGroup:
- */
- void setIsInActiveGroup(bool value) { this->m_inActiveGroup = value; }
-
- /**
- * \brief Is this node part of the active group
- * the active group is the group that is currently being edited. When no group is edited,
- * the active group will be the main tree (all nodes that are not part of a group will be active)
- * \return bool [false:true]
- */
- inline bool isInActiveGroup() const { return this->m_inActiveGroup; }
-
- /**
- * \brief convert node to operation
- *
- * \todo this must be described further
- *
- * \param system: the ExecutionSystem where the operations need to be added
- * \param context: reference to the CompositorContext
- */
- virtual void convertToOperations(NodeConverter &converter, const CompositorContext &context) const = 0;
-
- /**
- * Create dummy warning operation, use when we can't get the source data.
- */
- NodeOperation *convertToOperations_invalid_index(NodeConverter *compiler, int index) const;
- /**
- * when a node has no valid data (missing image or a group nodes ID pointer is NULL)
- * call this function from #convertToOperations, this way the node sockets are converted
- * into valid outputs, without this the compositor system gets confused and crashes, see [#32490]
- */
- void convertToOperations_invalid(NodeConverter *compiler) const;
-
- void setInstanceKey(bNodeInstanceKey instance_key) { m_instanceKey = instance_key; }
- bNodeInstanceKey getInstanceKey() const { return m_instanceKey; }
-
-protected:
- /**
- * \brief add an NodeInput to the collection of inputsockets
- * \note may only be called in an constructor
- * \param socket: the NodeInput to add
- */
- void addInputSocket(DataType datatype);
- void addInputSocket(DataType datatype, bNodeSocket *socket);
-
- /**
- * \brief add an NodeOutput to the collection of outputsockets
- * \note may only be called in an constructor
- * \param socket: the NodeOutput to add
- */
- void addOutputSocket(DataType datatype);
- void addOutputSocket(DataType datatype, bNodeSocket *socket);
-
- bNodeSocket *getEditorInputSocket(int editorNodeInputSocketIndex);
- bNodeSocket *getEditorOutputSocket(int editorNodeOutputSocketIndex);
+ public:
+ typedef std::vector<NodeInput *> Inputs;
+ typedef std::vector<NodeOutput *> Outputs;
+
+ private:
+ /**
+ * \brief stores the reference to the SDNA bNode struct
+ */
+ bNodeTree *m_editorNodeTree;
+
+ /**
+ * \brief stores the reference to the SDNA bNode struct
+ */
+ bNode *m_editorNode;
+
+ /**
+ * \brief the list of actual inputsockets \see NodeInput
+ */
+ Inputs m_inputsockets;
+
+ /**
+ * \brief the list of actual outputsockets \see NodeOutput
+ */
+ Outputs m_outputsockets;
+
+ /**
+ * \brief Is this node part of the active group
+ */
+ bool m_inActiveGroup;
+
+ /**
+ * \brief Instance key to identify the node in an instance hash table
+ */
+ bNodeInstanceKey m_instanceKey;
+
+ protected:
+ /**
+ * \brief get access to the vector of input sockets
+ */
+ const Inputs &getInputSockets() const
+ {
+ return this->m_inputsockets;
+ }
+
+ /**
+ * \brief get access to the vector of input sockets
+ */
+ const Outputs &getOutputSockets() const
+ {
+ return this->m_outputsockets;
+ }
+
+ public:
+ Node(bNode *editorNode, bool create_sockets = true);
+ virtual ~Node();
+
+ /**
+ * \brief get the reference to the SDNA bNode struct
+ */
+ bNode *getbNode() const
+ {
+ return m_editorNode;
+ }
+
+ /**
+ * \brief get the reference to the SDNA bNodeTree struct
+ */
+ bNodeTree *getbNodeTree() const
+ {
+ return m_editorNodeTree;
+ }
+
+ /**
+ * \brief set the reference to the bNode
+ * \note used in Node instances to receive the storage/settings and complex node for highlight during execution
+ * \param bNode:
+ */
+ void setbNode(bNode *node)
+ {
+ this->m_editorNode = node;
+ }
+
+ /**
+ * \brief set the reference to the bNodeTree
+ * \param bNodeTree:
+ */
+ void setbNodeTree(bNodeTree *nodetree)
+ {
+ this->m_editorNodeTree = nodetree;
+ }
+
+ /**
+ * \brief Return the number of input sockets of this node.
+ */
+ unsigned int getNumberOfInputSockets() const
+ {
+ return this->m_inputsockets.size();
+ }
+
+ /**
+ * \brief Return the number of output sockets of this node.
+ */
+ unsigned int getNumberOfOutputSockets() const
+ {
+ return this->m_outputsockets.size();
+ }
+
+ /**
+ * get the reference to a certain outputsocket
+ * \param index:
+ * the index of the needed outputsocket
+ */
+ NodeOutput *getOutputSocket(const unsigned int index) const;
+
+ /**
+ * get the reference to the first outputsocket
+ * \param index:
+ * the index of the needed outputsocket
+ */
+ inline NodeOutput *getOutputSocket() const
+ {
+ return getOutputSocket(0);
+ }
+
+ /**
+ * get the reference to a certain inputsocket
+ * \param index:
+ * the index of the needed inputsocket
+ */
+ NodeInput *getInputSocket(const unsigned int index) const;
+
+ /** Check if this is an input node
+ * An input node is a node that only has output sockets and no input sockets
+ */
+ bool isInputNode() const
+ {
+ return m_inputsockets.empty();
+ }
+
+ /**
+ * \brief Is this node in the active group (the group that is being edited)
+ * \param isInActiveGroup:
+ */
+ void setIsInActiveGroup(bool value)
+ {
+ this->m_inActiveGroup = value;
+ }
+
+ /**
+ * \brief Is this node part of the active group
+ * the active group is the group that is currently being edited. When no group is edited,
+ * the active group will be the main tree (all nodes that are not part of a group will be active)
+ * \return bool [false:true]
+ */
+ inline bool isInActiveGroup() const
+ {
+ return this->m_inActiveGroup;
+ }
+
+ /**
+ * \brief convert node to operation
+ *
+ * \todo this must be described further
+ *
+ * \param system: the ExecutionSystem where the operations need to be added
+ * \param context: reference to the CompositorContext
+ */
+ virtual void convertToOperations(NodeConverter &converter,
+ const CompositorContext &context) const = 0;
+
+ /**
+ * Create dummy warning operation, use when we can't get the source data.
+ */
+ NodeOperation *convertToOperations_invalid_index(NodeConverter *compiler, int index) const;
+ /**
+ * when a node has no valid data (missing image or a group nodes ID pointer is NULL)
+ * call this function from #convertToOperations, this way the node sockets are converted
+ * into valid outputs, without this the compositor system gets confused and crashes, see [#32490]
+ */
+ void convertToOperations_invalid(NodeConverter *compiler) const;
+
+ void setInstanceKey(bNodeInstanceKey instance_key)
+ {
+ m_instanceKey = instance_key;
+ }
+ bNodeInstanceKey getInstanceKey() const
+ {
+ return m_instanceKey;
+ }
+
+ protected:
+ /**
+ * \brief add an NodeInput to the collection of inputsockets
+ * \note may only be called in an constructor
+ * \param socket: the NodeInput to add
+ */
+ void addInputSocket(DataType datatype);
+ void addInputSocket(DataType datatype, bNodeSocket *socket);
+
+ /**
+ * \brief add an NodeOutput to the collection of outputsockets
+ * \note may only be called in an constructor
+ * \param socket: the NodeOutput to add
+ */
+ void addOutputSocket(DataType datatype);
+ void addOutputSocket(DataType datatype, bNodeSocket *socket);
+
+ bNodeSocket *getEditorInputSocket(int editorNodeInputSocketIndex);
+ bNodeSocket *getEditorOutputSocket(int editorNodeOutputSocketIndex);
};
-
/**
* \brief NodeInput are sockets that can receive data/input
* \ingroup Model
*/
class NodeInput {
-private:
- Node *m_node;
- bNodeSocket *m_editorSocket;
-
- DataType m_datatype;
-
- /**
- * \brief link connected to this NodeInput.
- * An input socket can only have a single link
- */
- NodeOutput *m_link;
-
-public:
- NodeInput(Node *node, bNodeSocket *b_socket, DataType datatype);
-
- Node *getNode() const { return this->m_node; }
- DataType getDataType() const { return m_datatype; }
- bNodeSocket *getbNodeSocket() const { return this->m_editorSocket; }
-
- void setLink(NodeOutput *link);
- bool isLinked() const { return m_link; }
- NodeOutput *getLink() { return m_link; }
-
- float getEditorValueFloat();
- void getEditorValueColor(float *value);
- void getEditorValueVector(float *value);
+ private:
+ Node *m_node;
+ bNodeSocket *m_editorSocket;
+
+ DataType m_datatype;
+
+ /**
+ * \brief link connected to this NodeInput.
+ * An input socket can only have a single link
+ */
+ NodeOutput *m_link;
+
+ public:
+ NodeInput(Node *node, bNodeSocket *b_socket, DataType datatype);
+
+ Node *getNode() const
+ {
+ return this->m_node;
+ }
+ DataType getDataType() const
+ {
+ return m_datatype;
+ }
+ bNodeSocket *getbNodeSocket() const
+ {
+ return this->m_editorSocket;
+ }
+
+ void setLink(NodeOutput *link);
+ bool isLinked() const
+ {
+ return m_link;
+ }
+ NodeOutput *getLink()
+ {
+ return m_link;
+ }
+
+ float getEditorValueFloat();
+ void getEditorValueColor(float *value);
+ void getEditorValueVector(float *value);
};
-
/**
* \brief NodeOutput are sockets that can send data/input
* \ingroup Model
*/
class NodeOutput {
-private:
- Node *m_node;
- bNodeSocket *m_editorSocket;
-
- DataType m_datatype;
-
-public:
- NodeOutput(Node *node, bNodeSocket *b_socket, DataType datatype);
-
- Node *getNode() const { return this->m_node; }
- DataType getDataType() const { return m_datatype; }
- bNodeSocket *getbNodeSocket() const { return this->m_editorSocket; }
-
- float getEditorValueFloat();
- void getEditorValueColor(float *value);
- void getEditorValueVector(float *value);
+ private:
+ Node *m_node;
+ bNodeSocket *m_editorSocket;
+
+ DataType m_datatype;
+
+ public:
+ NodeOutput(Node *node, bNodeSocket *b_socket, DataType datatype);
+
+ Node *getNode() const
+ {
+ return this->m_node;
+ }
+ DataType getDataType() const
+ {
+ return m_datatype;
+ }
+ bNodeSocket *getbNodeSocket() const
+ {
+ return this->m_editorSocket;
+ }
+
+ float getEditorValueFloat();
+ void getEditorValueColor(float *value);
+ void getEditorValueVector(float *value);
};
-#endif /* __COM_NODE_H__ */
+#endif /* __COM_NODE_H__ */
diff --git a/source/blender/compositor/intern/COM_NodeConverter.cpp b/source/blender/compositor/intern/COM_NodeConverter.cpp
index c775a9ed49f..c44721e3939 100644
--- a/source/blender/compositor/intern/COM_NodeConverter.cpp
+++ b/source/blender/compositor/intern/COM_NodeConverter.cpp
@@ -31,135 +31,134 @@ extern "C" {
#include "COM_NodeConverter.h" /* own include */
-NodeConverter::NodeConverter(NodeOperationBuilder *builder) :
- m_builder(builder)
+NodeConverter::NodeConverter(NodeOperationBuilder *builder) : m_builder(builder)
{
}
void NodeConverter::addOperation(NodeOperation *operation)
{
- m_builder->addOperation(operation);
+ m_builder->addOperation(operation);
}
void NodeConverter::mapInputSocket(NodeInput *node_socket, NodeOperationInput *operation_socket)
{
- m_builder->mapInputSocket(node_socket, operation_socket);
+ m_builder->mapInputSocket(node_socket, operation_socket);
}
void NodeConverter::mapOutputSocket(NodeOutput *node_socket, NodeOperationOutput *operation_socket)
{
- m_builder->mapOutputSocket(node_socket, operation_socket);
+ m_builder->mapOutputSocket(node_socket, operation_socket);
}
void NodeConverter::addLink(NodeOperationOutput *from, NodeOperationInput *to)
{
- m_builder->addLink(from, to);
+ m_builder->addLink(from, to);
}
void NodeConverter::addPreview(NodeOperationOutput *output)
{
- m_builder->addPreview(output);
+ m_builder->addPreview(output);
}
void NodeConverter::addNodeInputPreview(NodeInput *input)
{
- m_builder->addNodeInputPreview(input);
+ m_builder->addNodeInputPreview(input);
}
NodeOperation *NodeConverter::setInvalidOutput(NodeOutput *output)
{
- /* this is a really bad situation - bring on the pink! - so artists know this is bad */
- const float warning_color[4] = {1.0f, 0.0f, 1.0f, 1.0f};
+ /* this is a really bad situation - bring on the pink! - so artists know this is bad */
+ const float warning_color[4] = {1.0f, 0.0f, 1.0f, 1.0f};
- SetColorOperation *operation = new SetColorOperation();
- operation->setChannels(warning_color);
+ SetColorOperation *operation = new SetColorOperation();
+ operation->setChannels(warning_color);
- m_builder->addOperation(operation);
- m_builder->mapOutputSocket(output, operation->getOutputSocket());
+ m_builder->addOperation(operation);
+ m_builder->mapOutputSocket(output, operation->getOutputSocket());
- return operation;
+ return operation;
}
NodeOperationOutput *NodeConverter::addInputProxy(NodeInput *input, bool use_conversion)
{
- SocketProxyOperation *proxy = new SocketProxyOperation(input->getDataType(), use_conversion);
- m_builder->addOperation(proxy);
+ SocketProxyOperation *proxy = new SocketProxyOperation(input->getDataType(), use_conversion);
+ m_builder->addOperation(proxy);
- m_builder->mapInputSocket(input, proxy->getInputSocket(0));
+ m_builder->mapInputSocket(input, proxy->getInputSocket(0));
- return proxy->getOutputSocket();
+ return proxy->getOutputSocket();
}
NodeOperationInput *NodeConverter::addOutputProxy(NodeOutput *output, bool use_conversion)
{
- SocketProxyOperation *proxy = new SocketProxyOperation(output->getDataType(), use_conversion);
- m_builder->addOperation(proxy);
+ SocketProxyOperation *proxy = new SocketProxyOperation(output->getDataType(), use_conversion);
+ m_builder->addOperation(proxy);
- m_builder->mapOutputSocket(output, proxy->getOutputSocket());
+ m_builder->mapOutputSocket(output, proxy->getOutputSocket());
- return proxy->getInputSocket(0);
+ return proxy->getInputSocket(0);
}
void NodeConverter::addInputValue(NodeOperationInput *input, float value)
{
- SetValueOperation *operation = new SetValueOperation();
- operation->setValue(value);
+ SetValueOperation *operation = new SetValueOperation();
+ operation->setValue(value);
- m_builder->addOperation(operation);
- m_builder->addLink(operation->getOutputSocket(), input);
+ m_builder->addOperation(operation);
+ m_builder->addLink(operation->getOutputSocket(), input);
}
void NodeConverter::addInputColor(NodeOperationInput *input, const float value[4])
{
- SetColorOperation *operation = new SetColorOperation();
- operation->setChannels(value);
+ SetColorOperation *operation = new SetColorOperation();
+ operation->setChannels(value);
- m_builder->addOperation(operation);
- m_builder->addLink(operation->getOutputSocket(), input);
+ m_builder->addOperation(operation);
+ m_builder->addLink(operation->getOutputSocket(), input);
}
void NodeConverter::addInputVector(NodeOperationInput *input, const float value[3])
{
- SetVectorOperation *operation = new SetVectorOperation();
- operation->setVector(value);
+ SetVectorOperation *operation = new SetVectorOperation();
+ operation->setVector(value);
- m_builder->addOperation(operation);
- m_builder->addLink(operation->getOutputSocket(), input);
+ m_builder->addOperation(operation);
+ m_builder->addLink(operation->getOutputSocket(), input);
}
void NodeConverter::addOutputValue(NodeOutput *output, float value)
{
- SetValueOperation *operation = new SetValueOperation();
- operation->setValue(value);
+ SetValueOperation *operation = new SetValueOperation();
+ operation->setValue(value);
- m_builder->addOperation(operation);
- m_builder->mapOutputSocket(output, operation->getOutputSocket());
+ m_builder->addOperation(operation);
+ m_builder->mapOutputSocket(output, operation->getOutputSocket());
}
void NodeConverter::addOutputColor(NodeOutput *output, const float value[4])
{
- SetColorOperation *operation = new SetColorOperation();
- operation->setChannels(value);
+ SetColorOperation *operation = new SetColorOperation();
+ operation->setChannels(value);
- m_builder->addOperation(operation);
- m_builder->mapOutputSocket(output, operation->getOutputSocket());
+ m_builder->addOperation(operation);
+ m_builder->mapOutputSocket(output, operation->getOutputSocket());
}
void NodeConverter::addOutputVector(NodeOutput *output, const float value[3])
{
- SetVectorOperation *operation = new SetVectorOperation();
- operation->setVector(value);
+ SetVectorOperation *operation = new SetVectorOperation();
+ operation->setVector(value);
- m_builder->addOperation(operation);
- m_builder->mapOutputSocket(output, operation->getOutputSocket());
+ m_builder->addOperation(operation);
+ m_builder->mapOutputSocket(output, operation->getOutputSocket());
}
void NodeConverter::registerViewer(ViewerOperation *viewer)
{
- m_builder->registerViewer(viewer);
+ m_builder->registerViewer(viewer);
}
ViewerOperation *NodeConverter::active_viewer() const
{
- return m_builder->active_viewer();
+ return m_builder->active_viewer();
}
diff --git a/source/blender/compositor/intern/COM_NodeConverter.h b/source/blender/compositor/intern/COM_NodeConverter.h
index c3d9a115435..56e9aa85010 100644
--- a/source/blender/compositor/intern/COM_NodeConverter.h
+++ b/source/blender/compositor/intern/COM_NodeConverter.h
@@ -40,85 +40,85 @@ class ViewerOperation;
* and map original node sockets to their inputs or outputs.
*/
class NodeConverter {
-public:
- NodeConverter(NodeOperationBuilder *builder);
-
- /**
- * Insert a new operation into the operations graph.
- * The operation must be created by the node.
- */
- void addOperation(NodeOperation *operation);
-
- /**
- * Map input socket of the node to an operation socket.
- * Links between nodes will then generate equivalent links between
- * the mapped operation sockets.
- *
- * \note A \a Node input can be mapped to multiple \a NodeOperation inputs.
- */
- void mapInputSocket(NodeInput *node_socket, NodeOperationInput *operation_socket);
- /**
- * Map output socket of the node to an operation socket.
- * Links between nodes will then generate equivalent links between
- * the mapped operation sockets.
- *
- * \note A \a Node output can only be mapped to one \a NodeOperation output.
- * Any existing operation output mapping will be replaced.
- */
- void mapOutputSocket(NodeOutput *node_socket, NodeOperationOutput *operation_socket);
-
- /**
- * Create a proxy operation for a node input.
- * This operation will be removed later and replaced
- * by direct links between the connected operations.
- */
- NodeOperationOutput *addInputProxy(NodeInput *input, bool use_conversion);
- /**
- * Create a proxy operation for a node output.
- * This operation will be removed later and replaced
- * by direct links between the connected operations.
- */
- NodeOperationInput *addOutputProxy(NodeOutput *output, bool use_conversion);
-
- /** Define a constant input value. */
- void addInputValue(NodeOperationInput *input, float value);
- /** Define a constant input color. */
- void addInputColor(NodeOperationInput *input, const float value[4]);
- /** Define a constant input vector. */
- void addInputVector(NodeOperationInput *input, const float value[3]);
-
- /** Define a constant output value. */
- void addOutputValue(NodeOutput *output, float value);
- /** Define a constant output color. */
- void addOutputColor(NodeOutput *output, const float value[4]);
- /** Define a constant output vector. */
- void addOutputVector(NodeOutput *output, const float value[3]);
-
- /** Add an explicit link between two operations. */
- void addLink(NodeOperationOutput *from, NodeOperationInput *to);
-
- /** Add a preview operation for a operation output. */
- void addPreview(NodeOperationOutput *output);
- /** Add a preview operation for a node input. */
- void addNodeInputPreview(NodeInput *input);
-
- /**
- * When a node has no valid data
- * \note missing image / group pointer, or missing renderlayer from EXR
- */
- NodeOperation *setInvalidOutput(NodeOutput *output);
-
- /** Define a viewer operation as the active output, if possible */
- void registerViewer(ViewerOperation *viewer);
- /** The currently active viewer output operation */
- ViewerOperation *active_viewer() const;
-
-private:
- /** The internal builder for storing the results of the graph construction. */
- NodeOperationBuilder *m_builder;
+ public:
+ NodeConverter(NodeOperationBuilder *builder);
+
+ /**
+ * Insert a new operation into the operations graph.
+ * The operation must be created by the node.
+ */
+ void addOperation(NodeOperation *operation);
+
+ /**
+ * Map input socket of the node to an operation socket.
+ * Links between nodes will then generate equivalent links between
+ * the mapped operation sockets.
+ *
+ * \note A \a Node input can be mapped to multiple \a NodeOperation inputs.
+ */
+ void mapInputSocket(NodeInput *node_socket, NodeOperationInput *operation_socket);
+ /**
+ * Map output socket of the node to an operation socket.
+ * Links between nodes will then generate equivalent links between
+ * the mapped operation sockets.
+ *
+ * \note A \a Node output can only be mapped to one \a NodeOperation output.
+ * Any existing operation output mapping will be replaced.
+ */
+ void mapOutputSocket(NodeOutput *node_socket, NodeOperationOutput *operation_socket);
+
+ /**
+ * Create a proxy operation for a node input.
+ * This operation will be removed later and replaced
+ * by direct links between the connected operations.
+ */
+ NodeOperationOutput *addInputProxy(NodeInput *input, bool use_conversion);
+ /**
+ * Create a proxy operation for a node output.
+ * This operation will be removed later and replaced
+ * by direct links between the connected operations.
+ */
+ NodeOperationInput *addOutputProxy(NodeOutput *output, bool use_conversion);
+
+ /** Define a constant input value. */
+ void addInputValue(NodeOperationInput *input, float value);
+ /** Define a constant input color. */
+ void addInputColor(NodeOperationInput *input, const float value[4]);
+ /** Define a constant input vector. */
+ void addInputVector(NodeOperationInput *input, const float value[3]);
+
+ /** Define a constant output value. */
+ void addOutputValue(NodeOutput *output, float value);
+ /** Define a constant output color. */
+ void addOutputColor(NodeOutput *output, const float value[4]);
+ /** Define a constant output vector. */
+ void addOutputVector(NodeOutput *output, const float value[3]);
+
+ /** Add an explicit link between two operations. */
+ void addLink(NodeOperationOutput *from, NodeOperationInput *to);
+
+ /** Add a preview operation for a operation output. */
+ void addPreview(NodeOperationOutput *output);
+ /** Add a preview operation for a node input. */
+ void addNodeInputPreview(NodeInput *input);
+
+ /**
+ * When a node has no valid data
+ * \note missing image / group pointer, or missing renderlayer from EXR
+ */
+ NodeOperation *setInvalidOutput(NodeOutput *output);
+
+ /** Define a viewer operation as the active output, if possible */
+ void registerViewer(ViewerOperation *viewer);
+ /** The currently active viewer output operation */
+ ViewerOperation *active_viewer() const;
+
+ private:
+ /** The internal builder for storing the results of the graph construction. */
+ NodeOperationBuilder *m_builder;
#ifdef WITH_CXX_GUARDEDALLOC
- MEM_CXX_CLASS_ALLOC_FUNCS("COM:NodeCompiler")
+ MEM_CXX_CLASS_ALLOC_FUNCS("COM:NodeCompiler")
#endif
};
diff --git a/source/blender/compositor/intern/COM_NodeGraph.cpp b/source/blender/compositor/intern/COM_NodeGraph.cpp
index f23b186416d..89f4542d42f 100644
--- a/source/blender/compositor/intern/COM_NodeGraph.cpp
+++ b/source/blender/compositor/intern/COM_NodeGraph.cpp
@@ -45,254 +45,282 @@ NodeGraph::NodeGraph()
NodeGraph::~NodeGraph()
{
- for (int index = 0; index < this->m_nodes.size(); index++) {
- Node *node = this->m_nodes[index];
- delete node;
- }
+ for (int index = 0; index < this->m_nodes.size(); index++) {
+ Node *node = this->m_nodes[index];
+ delete node;
+ }
}
void NodeGraph::from_bNodeTree(const CompositorContext &context, bNodeTree *tree)
{
- add_bNodeTree(context, 0, tree, NODE_INSTANCE_KEY_BASE);
+ add_bNodeTree(context, 0, tree, NODE_INSTANCE_KEY_BASE);
}
bNodeSocket *NodeGraph::find_b_node_input(bNode *b_group_node, const char *identifier)
{
- for (bNodeSocket *b_sock = (bNodeSocket *)b_group_node->inputs.first; b_sock; b_sock = b_sock->next) {
- if (STREQ(b_sock->identifier, identifier))
- return b_sock;
- }
- return NULL;
+ for (bNodeSocket *b_sock = (bNodeSocket *)b_group_node->inputs.first; b_sock;
+ b_sock = b_sock->next) {
+ if (STREQ(b_sock->identifier, identifier))
+ return b_sock;
+ }
+ return NULL;
}
bNodeSocket *NodeGraph::find_b_node_output(bNode *b_group_node, const char *identifier)
{
- for (bNodeSocket *b_sock = (bNodeSocket *)b_group_node->outputs.first; b_sock; b_sock = b_sock->next) {
- if (STREQ(b_sock->identifier, identifier))
- return b_sock;
- }
- return NULL;
+ for (bNodeSocket *b_sock = (bNodeSocket *)b_group_node->outputs.first; b_sock;
+ b_sock = b_sock->next) {
+ if (STREQ(b_sock->identifier, identifier))
+ return b_sock;
+ }
+ return NULL;
}
-void NodeGraph::add_node(Node *node, bNodeTree *b_ntree, bNodeInstanceKey key, bool is_active_group)
+void NodeGraph::add_node(Node *node,
+ bNodeTree *b_ntree,
+ bNodeInstanceKey key,
+ bool is_active_group)
{
- node->setbNodeTree(b_ntree);
- node->setInstanceKey(key);
- node->setIsInActiveGroup(is_active_group);
+ node->setbNodeTree(b_ntree);
+ node->setInstanceKey(key);
+ node->setIsInActiveGroup(is_active_group);
- m_nodes.push_back(node);
+ m_nodes.push_back(node);
- DebugInfo::node_added(node);
+ DebugInfo::node_added(node);
}
void NodeGraph::add_link(NodeOutput *fromSocket, NodeInput *toSocket)
{
- m_links.push_back(Link(fromSocket, toSocket));
+ m_links.push_back(Link(fromSocket, toSocket));
- /* register with the input */
- toSocket->setLink(fromSocket);
+ /* register with the input */
+ toSocket->setLink(fromSocket);
}
-void NodeGraph::add_bNodeTree(const CompositorContext &context, int nodes_start, bNodeTree *tree, bNodeInstanceKey parent_key)
+void NodeGraph::add_bNodeTree(const CompositorContext &context,
+ int nodes_start,
+ bNodeTree *tree,
+ bNodeInstanceKey parent_key)
{
- const bNodeTree *basetree = context.getbNodeTree();
-
- /* update viewers in the active edittree as well the base tree (for backdrop) */
- bool is_active_group = (parent_key.value == basetree->active_viewer_key.value);
-
- /* add all nodes of the tree to the node list */
- for (bNode *node = (bNode *)tree->nodes.first; node; node = node->next) {
- bNodeInstanceKey key = BKE_node_instance_key(parent_key, tree, node);
- add_bNode(context, tree, node, key, is_active_group);
- }
-
- NodeRange node_range(m_nodes.begin() + nodes_start, m_nodes.end());
- /* add all nodelinks of the tree to the link list */
- for (bNodeLink *nodelink = (bNodeLink *)tree->links.first; nodelink; nodelink = nodelink->next) {
- add_bNodeLink(node_range, nodelink);
- }
+ const bNodeTree *basetree = context.getbNodeTree();
+
+ /* update viewers in the active edittree as well the base tree (for backdrop) */
+ bool is_active_group = (parent_key.value == basetree->active_viewer_key.value);
+
+ /* add all nodes of the tree to the node list */
+ for (bNode *node = (bNode *)tree->nodes.first; node; node = node->next) {
+ bNodeInstanceKey key = BKE_node_instance_key(parent_key, tree, node);
+ add_bNode(context, tree, node, key, is_active_group);
+ }
+
+ NodeRange node_range(m_nodes.begin() + nodes_start, m_nodes.end());
+ /* add all nodelinks of the tree to the link list */
+ for (bNodeLink *nodelink = (bNodeLink *)tree->links.first; nodelink; nodelink = nodelink->next) {
+ add_bNodeLink(node_range, nodelink);
+ }
}
-void NodeGraph::add_bNode(const CompositorContext &context, bNodeTree *b_ntree, bNode *b_node, bNodeInstanceKey key, bool is_active_group)
+void NodeGraph::add_bNode(const CompositorContext &context,
+ bNodeTree *b_ntree,
+ bNode *b_node,
+ bNodeInstanceKey key,
+ bool is_active_group)
{
- /* replace muted nodes by proxies for internal links */
- if (b_node->flag & NODE_MUTED) {
- add_proxies_mute(b_ntree, b_node, key, is_active_group);
- return;
- }
-
- /* replace slow nodes with proxies for fast execution */
- if (context.isFastCalculation() && !Converter::is_fast_node(b_node)) {
- add_proxies_skip(b_ntree, b_node, key, is_active_group);
- return;
- }
-
- /* special node types */
- if (ELEM(b_node->type, NODE_GROUP, NODE_CUSTOM_GROUP)) {
- add_proxies_group(context, b_node, key);
- }
- else if (b_node->type == NODE_REROUTE) {
- add_proxies_reroute(b_ntree, b_node, key, is_active_group);
- }
- else {
- /* regular nodes, handled in Converter */
- Node *node = Converter::convert(b_node);
- if (node)
- add_node(node, b_ntree, key, is_active_group);
- }
+ /* replace muted nodes by proxies for internal links */
+ if (b_node->flag & NODE_MUTED) {
+ add_proxies_mute(b_ntree, b_node, key, is_active_group);
+ return;
+ }
+
+ /* replace slow nodes with proxies for fast execution */
+ if (context.isFastCalculation() && !Converter::is_fast_node(b_node)) {
+ add_proxies_skip(b_ntree, b_node, key, is_active_group);
+ return;
+ }
+
+ /* special node types */
+ if (ELEM(b_node->type, NODE_GROUP, NODE_CUSTOM_GROUP)) {
+ add_proxies_group(context, b_node, key);
+ }
+ else if (b_node->type == NODE_REROUTE) {
+ add_proxies_reroute(b_ntree, b_node, key, is_active_group);
+ }
+ else {
+ /* regular nodes, handled in Converter */
+ Node *node = Converter::convert(b_node);
+ if (node)
+ add_node(node, b_ntree, key, is_active_group);
+ }
}
NodeGraph::NodeInputs NodeGraph::find_inputs(const NodeRange &node_range, bNodeSocket *b_socket)
{
- NodeInputs result;
- for (NodeGraph::NodeIterator it = node_range.first; it != node_range.second; ++it) {
- Node *node = *it;
- for (int index = 0; index < node->getNumberOfInputSockets(); index++) {
- NodeInput *input = node->getInputSocket(index);
- if (input->getbNodeSocket() == b_socket) {
- result.push_back(input);
- }
- }
- }
- return result;
+ NodeInputs result;
+ for (NodeGraph::NodeIterator it = node_range.first; it != node_range.second; ++it) {
+ Node *node = *it;
+ for (int index = 0; index < node->getNumberOfInputSockets(); index++) {
+ NodeInput *input = node->getInputSocket(index);
+ if (input->getbNodeSocket() == b_socket) {
+ result.push_back(input);
+ }
+ }
+ }
+ return result;
}
NodeOutput *NodeGraph::find_output(const NodeRange &node_range, bNodeSocket *b_socket)
{
- for (NodeGraph::NodeIterator it = node_range.first; it != node_range.second; ++it) {
- Node *node = *it;
- for (int index = 0; index < node->getNumberOfOutputSockets(); index++) {
- NodeOutput *output = node->getOutputSocket(index);
- if (output->getbNodeSocket() == b_socket) {
- return output;
- }
- }
- }
- return NULL;
+ for (NodeGraph::NodeIterator it = node_range.first; it != node_range.second; ++it) {
+ Node *node = *it;
+ for (int index = 0; index < node->getNumberOfOutputSockets(); index++) {
+ NodeOutput *output = node->getOutputSocket(index);
+ if (output->getbNodeSocket() == b_socket) {
+ return output;
+ }
+ }
+ }
+ return NULL;
}
void NodeGraph::add_bNodeLink(const NodeRange &node_range, bNodeLink *b_nodelink)
{
- /// \note: ignore invalid links
- if (!(b_nodelink->flag & NODE_LINK_VALID))
- return;
- if ((b_nodelink->fromsock->flag & SOCK_UNAVAIL) || (b_nodelink->tosock->flag & SOCK_UNAVAIL))
- return;
-
- /* Note: a DNA input socket can have multiple NodeInput in the compositor tree! (proxies)
- * The output then gets linked to each one of them.
- */
-
- NodeOutput *output = find_output(node_range, b_nodelink->fromsock);
- if (!output)
- return;
-
- NodeInputs inputs = find_inputs(node_range, b_nodelink->tosock);
- for (NodeInputs::const_iterator it = inputs.begin(); it != inputs.end(); ++it) {
- NodeInput *input = *it;
- if (input->isLinked())
- continue;
- add_link(output, input);
- }
+ /// \note: ignore invalid links
+ if (!(b_nodelink->flag & NODE_LINK_VALID))
+ return;
+ if ((b_nodelink->fromsock->flag & SOCK_UNAVAIL) || (b_nodelink->tosock->flag & SOCK_UNAVAIL))
+ return;
+
+ /* Note: a DNA input socket can have multiple NodeInput in the compositor tree! (proxies)
+ * The output then gets linked to each one of them.
+ */
+
+ NodeOutput *output = find_output(node_range, b_nodelink->fromsock);
+ if (!output)
+ return;
+
+ NodeInputs inputs = find_inputs(node_range, b_nodelink->tosock);
+ for (NodeInputs::const_iterator it = inputs.begin(); it != inputs.end(); ++it) {
+ NodeInput *input = *it;
+ if (input->isLinked())
+ continue;
+ add_link(output, input);
+ }
}
/* **** Special proxy node type conversions **** */
-void NodeGraph::add_proxies_mute(bNodeTree *b_ntree, bNode *b_node, bNodeInstanceKey key, bool is_active_group)
+void NodeGraph::add_proxies_mute(bNodeTree *b_ntree,
+ bNode *b_node,
+ bNodeInstanceKey key,
+ bool is_active_group)
{
- for (bNodeLink *b_link = (bNodeLink *)b_node->internal_links.first; b_link; b_link = b_link->next) {
- SocketProxyNode *proxy = new SocketProxyNode(b_node, b_link->fromsock, b_link->tosock, false);
- add_node(proxy, b_ntree, key, is_active_group);
- }
+ for (bNodeLink *b_link = (bNodeLink *)b_node->internal_links.first; b_link;
+ b_link = b_link->next) {
+ SocketProxyNode *proxy = new SocketProxyNode(b_node, b_link->fromsock, b_link->tosock, false);
+ add_node(proxy, b_ntree, key, is_active_group);
+ }
}
-void NodeGraph::add_proxies_skip(bNodeTree *b_ntree, bNode *b_node, bNodeInstanceKey key, bool is_active_group)
+void NodeGraph::add_proxies_skip(bNodeTree *b_ntree,
+ bNode *b_node,
+ bNodeInstanceKey key,
+ bool is_active_group)
{
- for (bNodeSocket *output = (bNodeSocket *)b_node->outputs.first; output; output = output->next) {
- bNodeSocket *input;
-
- /* look for first input with matching datatype for each output */
- for (input = (bNodeSocket *)b_node->inputs.first; input; input = input->next) {
- if (input->type == output->type)
- break;
- }
-
- if (input) {
- SocketProxyNode *proxy = new SocketProxyNode(b_node, input, output, true);
- add_node(proxy, b_ntree, key, is_active_group);
- }
- }
+ for (bNodeSocket *output = (bNodeSocket *)b_node->outputs.first; output; output = output->next) {
+ bNodeSocket *input;
+
+ /* look for first input with matching datatype for each output */
+ for (input = (bNodeSocket *)b_node->inputs.first; input; input = input->next) {
+ if (input->type == output->type)
+ break;
+ }
+
+ if (input) {
+ SocketProxyNode *proxy = new SocketProxyNode(b_node, input, output, true);
+ add_node(proxy, b_ntree, key, is_active_group);
+ }
+ }
}
void NodeGraph::add_proxies_group_inputs(bNode *b_node, bNode *b_node_io)
{
- bNodeTree *b_group_tree = (bNodeTree *)b_node->id;
- BLI_assert(b_group_tree); /* should have been checked in advance */
-
- /* not important for proxies */
- bNodeInstanceKey key = NODE_INSTANCE_KEY_BASE;
- bool is_active_group = false;
-
- for (bNodeSocket *b_sock_io = (bNodeSocket *)b_node_io->outputs.first; b_sock_io; b_sock_io = b_sock_io->next) {
- bNodeSocket *b_sock_group = find_b_node_input(b_node, b_sock_io->identifier);
- if (b_sock_group) {
- SocketProxyNode *proxy = new SocketProxyNode(b_node_io, b_sock_group, b_sock_io, true);
- add_node(proxy, b_group_tree, key, is_active_group);
- }
- }
+ bNodeTree *b_group_tree = (bNodeTree *)b_node->id;
+ BLI_assert(b_group_tree); /* should have been checked in advance */
+
+ /* not important for proxies */
+ bNodeInstanceKey key = NODE_INSTANCE_KEY_BASE;
+ bool is_active_group = false;
+
+ for (bNodeSocket *b_sock_io = (bNodeSocket *)b_node_io->outputs.first; b_sock_io;
+ b_sock_io = b_sock_io->next) {
+ bNodeSocket *b_sock_group = find_b_node_input(b_node, b_sock_io->identifier);
+ if (b_sock_group) {
+ SocketProxyNode *proxy = new SocketProxyNode(b_node_io, b_sock_group, b_sock_io, true);
+ add_node(proxy, b_group_tree, key, is_active_group);
+ }
+ }
}
void NodeGraph::add_proxies_group_outputs(bNode *b_node, bNode *b_node_io, bool use_buffer)
{
- bNodeTree *b_group_tree = (bNodeTree *)b_node->id;
- BLI_assert(b_group_tree); /* should have been checked in advance */
-
- /* not important for proxies */
- bNodeInstanceKey key = NODE_INSTANCE_KEY_BASE;
- bool is_active_group = false;
-
- for (bNodeSocket *b_sock_io = (bNodeSocket *)b_node_io->inputs.first; b_sock_io; b_sock_io = b_sock_io->next) {
- bNodeSocket *b_sock_group = find_b_node_output(b_node, b_sock_io->identifier);
- if (b_sock_group) {
- if (use_buffer) {
- SocketBufferNode *buffer = new SocketBufferNode(b_node_io, b_sock_io, b_sock_group);
- add_node(buffer, b_group_tree, key, is_active_group);
- }
- else {
- SocketProxyNode *proxy = new SocketProxyNode(b_node_io, b_sock_io, b_sock_group, true);
- add_node(proxy, b_group_tree, key, is_active_group);
- }
- }
- }
+ bNodeTree *b_group_tree = (bNodeTree *)b_node->id;
+ BLI_assert(b_group_tree); /* should have been checked in advance */
+
+ /* not important for proxies */
+ bNodeInstanceKey key = NODE_INSTANCE_KEY_BASE;
+ bool is_active_group = false;
+
+ for (bNodeSocket *b_sock_io = (bNodeSocket *)b_node_io->inputs.first; b_sock_io;
+ b_sock_io = b_sock_io->next) {
+ bNodeSocket *b_sock_group = find_b_node_output(b_node, b_sock_io->identifier);
+ if (b_sock_group) {
+ if (use_buffer) {
+ SocketBufferNode *buffer = new SocketBufferNode(b_node_io, b_sock_io, b_sock_group);
+ add_node(buffer, b_group_tree, key, is_active_group);
+ }
+ else {
+ SocketProxyNode *proxy = new SocketProxyNode(b_node_io, b_sock_io, b_sock_group, true);
+ add_node(proxy, b_group_tree, key, is_active_group);
+ }
+ }
+ }
}
-void NodeGraph::add_proxies_group(const CompositorContext &context, bNode *b_node, bNodeInstanceKey key)
+void NodeGraph::add_proxies_group(const CompositorContext &context,
+ bNode *b_node,
+ bNodeInstanceKey key)
{
- bNodeTree *b_group_tree = (bNodeTree *)b_node->id;
+ bNodeTree *b_group_tree = (bNodeTree *)b_node->id;
- /* missing node group datablock can happen with library linking */
- if (!b_group_tree) {
- /* this error case its handled in convertToOperations() so we don't get un-convertred sockets */
- return;
- }
+ /* missing node group datablock can happen with library linking */
+ if (!b_group_tree) {
+ /* this error case its handled in convertToOperations() so we don't get un-convertred sockets */
+ return;
+ }
- /* use node list size before adding proxies, so they can be connected in add_bNodeTree */
- int nodes_start = m_nodes.size();
+ /* use node list size before adding proxies, so they can be connected in add_bNodeTree */
+ int nodes_start = m_nodes.size();
- /* create proxy nodes for group input/output nodes */
- for (bNode *b_node_io = (bNode *)b_group_tree->nodes.first; b_node_io; b_node_io = b_node_io->next) {
- if (b_node_io->type == NODE_GROUP_INPUT)
- add_proxies_group_inputs(b_node, b_node_io);
+ /* create proxy nodes for group input/output nodes */
+ for (bNode *b_node_io = (bNode *)b_group_tree->nodes.first; b_node_io;
+ b_node_io = b_node_io->next) {
+ if (b_node_io->type == NODE_GROUP_INPUT)
+ add_proxies_group_inputs(b_node, b_node_io);
- if (b_node_io->type == NODE_GROUP_OUTPUT && (b_node_io->flag & NODE_DO_OUTPUT))
- add_proxies_group_outputs(b_node, b_node_io, context.isGroupnodeBufferEnabled());
- }
+ if (b_node_io->type == NODE_GROUP_OUTPUT && (b_node_io->flag & NODE_DO_OUTPUT))
+ add_proxies_group_outputs(b_node, b_node_io, context.isGroupnodeBufferEnabled());
+ }
- add_bNodeTree(context, nodes_start, b_group_tree, key);
+ add_bNodeTree(context, nodes_start, b_group_tree, key);
}
-void NodeGraph::add_proxies_reroute(bNodeTree *b_ntree, bNode *b_node, bNodeInstanceKey key, bool is_active_group)
+void NodeGraph::add_proxies_reroute(bNodeTree *b_ntree,
+ bNode *b_node,
+ bNodeInstanceKey key,
+ bool is_active_group)
{
- SocketProxyNode *proxy = new SocketProxyNode(b_node, (bNodeSocket *)b_node->inputs.first, (bNodeSocket *)b_node->outputs.first, false);
- add_node(proxy, b_ntree, key, is_active_group);
+ SocketProxyNode *proxy = new SocketProxyNode(
+ b_node, (bNodeSocket *)b_node->inputs.first, (bNodeSocket *)b_node->outputs.first, false);
+ add_node(proxy, b_ntree, key, is_active_group);
}
diff --git a/source/blender/compositor/intern/COM_NodeGraph.h b/source/blender/compositor/intern/COM_NodeGraph.h
index a2da8fec911..087b3dda48d 100644
--- a/source/blender/compositor/intern/COM_NodeGraph.h
+++ b/source/blender/compositor/intern/COM_NodeGraph.h
@@ -40,73 +40,100 @@ class NodeOutput;
* This structure is converted into operations by \a NodeCompiler.
*/
class NodeGraph {
-public:
- class Link {
- private:
- NodeOutput *m_from;
- NodeInput *m_to;
-
- public:
- Link(NodeOutput *from, NodeInput *to) :
- m_from(from),
- m_to(to)
- {}
-
- NodeOutput *getFromSocket() const { return m_from; }
- NodeInput *getToSocket() const { return m_to; }
- };
-
- typedef std::vector<Node *> Nodes;
- typedef Nodes::iterator NodeIterator;
- typedef std::vector<Link> Links;
-
-private:
- Nodes m_nodes;
- Links m_links;
-
-public:
- NodeGraph();
- ~NodeGraph();
-
- const Nodes &nodes() const { return m_nodes; }
- const Links &links() const { return m_links; }
-
- void from_bNodeTree(const CompositorContext &context, bNodeTree *tree);
-
-protected:
- typedef std::pair<NodeIterator, NodeIterator> NodeRange;
- typedef std::vector<NodeInput *> NodeInputs;
-
- static bNodeSocket *find_b_node_input(bNode *b_node, const char *identifier);
- static bNodeSocket *find_b_node_output(bNode *b_node, const char *identifier);
-
- void add_node(Node *node, bNodeTree *b_ntree, bNodeInstanceKey key, bool is_active_group);
- void add_link(NodeOutput *fromSocket, NodeInput *toSocket);
-
- void add_bNodeTree(const CompositorContext &context, int nodes_start, bNodeTree *tree, bNodeInstanceKey parent_key);
-
- void add_bNode(const CompositorContext &context, bNodeTree *b_ntree, bNode *b_node, bNodeInstanceKey key, bool is_active_group);
-
- NodeInputs find_inputs(const NodeRange &node_range, bNodeSocket *b_socket);
- NodeOutput *find_output(const NodeRange &node_range, bNodeSocket *b_socket);
- void add_bNodeLink(const NodeRange &node_range, bNodeLink *bNodeLink);
-
- /* **** Special proxy node type conversions **** */
- /* These nodes are not represented in the node graph themselves,
- * but converted into a number of proxy links
- */
-
- void add_proxies_mute(bNodeTree *b_ntree, bNode *b_node, bNodeInstanceKey key, bool is_active_group);
- void add_proxies_skip(bNodeTree *b_ntree, bNode *b_node, bNodeInstanceKey key, bool is_active_group);
-
- void add_proxies_group_inputs(bNode *b_node, bNode *b_node_io);
- void add_proxies_group_outputs(bNode *b_node, bNode *b_node_io, bool use_buffer);
- void add_proxies_group(const CompositorContext &context, bNode *b_node, bNodeInstanceKey key);
-
- void add_proxies_reroute(bNodeTree *b_ntree, bNode *b_node, bNodeInstanceKey key, bool is_active_group);
+ public:
+ class Link {
+ private:
+ NodeOutput *m_from;
+ NodeInput *m_to;
+
+ public:
+ Link(NodeOutput *from, NodeInput *to) : m_from(from), m_to(to)
+ {
+ }
+
+ NodeOutput *getFromSocket() const
+ {
+ return m_from;
+ }
+ NodeInput *getToSocket() const
+ {
+ return m_to;
+ }
+ };
+
+ typedef std::vector<Node *> Nodes;
+ typedef Nodes::iterator NodeIterator;
+ typedef std::vector<Link> Links;
+
+ private:
+ Nodes m_nodes;
+ Links m_links;
+
+ public:
+ NodeGraph();
+ ~NodeGraph();
+
+ const Nodes &nodes() const
+ {
+ return m_nodes;
+ }
+ const Links &links() const
+ {
+ return m_links;
+ }
+
+ void from_bNodeTree(const CompositorContext &context, bNodeTree *tree);
+
+ protected:
+ typedef std::pair<NodeIterator, NodeIterator> NodeRange;
+ typedef std::vector<NodeInput *> NodeInputs;
+
+ static bNodeSocket *find_b_node_input(bNode *b_node, const char *identifier);
+ static bNodeSocket *find_b_node_output(bNode *b_node, const char *identifier);
+
+ void add_node(Node *node, bNodeTree *b_ntree, bNodeInstanceKey key, bool is_active_group);
+ void add_link(NodeOutput *fromSocket, NodeInput *toSocket);
+
+ void add_bNodeTree(const CompositorContext &context,
+ int nodes_start,
+ bNodeTree *tree,
+ bNodeInstanceKey parent_key);
+
+ void add_bNode(const CompositorContext &context,
+ bNodeTree *b_ntree,
+ bNode *b_node,
+ bNodeInstanceKey key,
+ bool is_active_group);
+
+ NodeInputs find_inputs(const NodeRange &node_range, bNodeSocket *b_socket);
+ NodeOutput *find_output(const NodeRange &node_range, bNodeSocket *b_socket);
+ void add_bNodeLink(const NodeRange &node_range, bNodeLink *bNodeLink);
+
+ /* **** Special proxy node type conversions **** */
+ /* These nodes are not represented in the node graph themselves,
+ * but converted into a number of proxy links
+ */
+
+ void add_proxies_mute(bNodeTree *b_ntree,
+ bNode *b_node,
+ bNodeInstanceKey key,
+ bool is_active_group);
+ void add_proxies_skip(bNodeTree *b_ntree,
+ bNode *b_node,
+ bNodeInstanceKey key,
+ bool is_active_group);
+
+ void add_proxies_group_inputs(bNode *b_node, bNode *b_node_io);
+ void add_proxies_group_outputs(bNode *b_node, bNode *b_node_io, bool use_buffer);
+ void add_proxies_group(const CompositorContext &context, bNode *b_node, bNodeInstanceKey key);
+
+ void add_proxies_reroute(bNodeTree *b_ntree,
+ bNode *b_node,
+ bNodeInstanceKey key,
+ bool is_active_group);
#ifdef WITH_CXX_GUARDEDALLOC
- MEM_CXX_CLASS_ALLOC_FUNCS("COM:NodeGraph")
+ MEM_CXX_CLASS_ALLOC_FUNCS("COM:NodeGraph")
#endif
};
diff --git a/source/blender/compositor/intern/COM_NodeOperation.cpp b/source/blender/compositor/intern/COM_NodeOperation.cpp
index 9f569307581..b0f7bf746fa 100644
--- a/source/blender/compositor/intern/COM_NodeOperation.cpp
+++ b/source/blender/compositor/intern/COM_NodeOperation.cpp
@@ -30,213 +30,215 @@
NodeOperation::NodeOperation()
{
- this->m_resolutionInputSocketIndex = 0;
- this->m_complex = false;
- this->m_width = 0;
- this->m_height = 0;
- this->m_isResolutionSet = false;
- this->m_openCL = false;
- this->m_btree = NULL;
+ this->m_resolutionInputSocketIndex = 0;
+ this->m_complex = false;
+ this->m_width = 0;
+ this->m_height = 0;
+ this->m_isResolutionSet = false;
+ this->m_openCL = false;
+ this->m_btree = NULL;
}
NodeOperation::~NodeOperation()
{
- while (!this->m_outputs.empty()) {
- delete (this->m_outputs.back());
- this->m_outputs.pop_back();
- }
- while (!this->m_inputs.empty()) {
- delete (this->m_inputs.back());
- this->m_inputs.pop_back();
- }
+ while (!this->m_outputs.empty()) {
+ delete (this->m_outputs.back());
+ this->m_outputs.pop_back();
+ }
+ while (!this->m_inputs.empty()) {
+ delete (this->m_inputs.back());
+ this->m_inputs.pop_back();
+ }
}
NodeOperationOutput *NodeOperation::getOutputSocket(unsigned int index) const
{
- BLI_assert(index < m_outputs.size());
- return m_outputs[index];
+ BLI_assert(index < m_outputs.size());
+ return m_outputs[index];
}
NodeOperationInput *NodeOperation::getInputSocket(unsigned int index) const
{
- BLI_assert(index < m_inputs.size());
- return m_inputs[index];
+ BLI_assert(index < m_inputs.size());
+ return m_inputs[index];
}
void NodeOperation::addInputSocket(DataType datatype, InputResizeMode resize_mode)
{
- NodeOperationInput *socket = new NodeOperationInput(this, datatype, resize_mode);
- m_inputs.push_back(socket);
+ NodeOperationInput *socket = new NodeOperationInput(this, datatype, resize_mode);
+ m_inputs.push_back(socket);
}
void NodeOperation::addOutputSocket(DataType datatype)
{
- NodeOperationOutput *socket = new NodeOperationOutput(this, datatype);
- m_outputs.push_back(socket);
-}
-
-void NodeOperation::determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2])
-{
- unsigned int temp[2];
- unsigned int temp2[2];
-
- for (unsigned int index = 0; index < m_inputs.size(); index++) {
- NodeOperationInput *input = m_inputs[index];
- if (input->isConnected()) {
- if (index == this->m_resolutionInputSocketIndex) {
- input->determineResolution(resolution, preferredResolution);
- temp2[0] = resolution[0];
- temp2[1] = resolution[1];
- break;
- }
- }
- }
- for (unsigned int index = 0; index < m_inputs.size(); index++) {
- NodeOperationInput *input = m_inputs[index];
- if (input->isConnected()) {
- if (index != this->m_resolutionInputSocketIndex) {
- input->determineResolution(temp, temp2);
- }
- }
- }
+ NodeOperationOutput *socket = new NodeOperationOutput(this, datatype);
+ m_outputs.push_back(socket);
+}
+
+void NodeOperation::determineResolution(unsigned int resolution[2],
+ unsigned int preferredResolution[2])
+{
+ unsigned int temp[2];
+ unsigned int temp2[2];
+
+ for (unsigned int index = 0; index < m_inputs.size(); index++) {
+ NodeOperationInput *input = m_inputs[index];
+ if (input->isConnected()) {
+ if (index == this->m_resolutionInputSocketIndex) {
+ input->determineResolution(resolution, preferredResolution);
+ temp2[0] = resolution[0];
+ temp2[1] = resolution[1];
+ break;
+ }
+ }
+ }
+ for (unsigned int index = 0; index < m_inputs.size(); index++) {
+ NodeOperationInput *input = m_inputs[index];
+ if (input->isConnected()) {
+ if (index != this->m_resolutionInputSocketIndex) {
+ input->determineResolution(temp, temp2);
+ }
+ }
+ }
}
void NodeOperation::setResolutionInputSocketIndex(unsigned int index)
{
- this->m_resolutionInputSocketIndex = index;
+ this->m_resolutionInputSocketIndex = index;
}
void NodeOperation::initExecution()
{
- /* pass */
+ /* pass */
}
void NodeOperation::initMutex()
{
- BLI_mutex_init(&this->m_mutex);
+ BLI_mutex_init(&this->m_mutex);
}
void NodeOperation::lockMutex()
{
- BLI_mutex_lock(&this->m_mutex);
+ BLI_mutex_lock(&this->m_mutex);
}
void NodeOperation::unlockMutex()
{
- BLI_mutex_unlock(&this->m_mutex);
+ BLI_mutex_unlock(&this->m_mutex);
}
void NodeOperation::deinitMutex()
{
- BLI_mutex_end(&this->m_mutex);
+ BLI_mutex_end(&this->m_mutex);
}
void NodeOperation::deinitExecution()
{
- /* pass */
+ /* pass */
}
SocketReader *NodeOperation::getInputSocketReader(unsigned int inputSocketIndex)
{
- return this->getInputSocket(inputSocketIndex)->getReader();
+ return this->getInputSocket(inputSocketIndex)->getReader();
}
NodeOperation *NodeOperation::getInputOperation(unsigned int inputSocketIndex)
{
- NodeOperationInput *input = getInputSocket(inputSocketIndex);
- if (input && input->isConnected())
- return &input->getLink()->getOperation();
- else
- return NULL;
+ NodeOperationInput *input = getInputSocket(inputSocketIndex);
+ if (input && input->isConnected())
+ return &input->getLink()->getOperation();
+ else
+ return NULL;
}
void NodeOperation::getConnectedInputSockets(Inputs *sockets)
{
- for (Inputs::const_iterator it = m_inputs.begin(); it != m_inputs.end(); ++it) {
- NodeOperationInput *input = *it;
- if (input->isConnected()) {
- sockets->push_back(input);
- }
- }
-}
-
-bool NodeOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output)
-{
- if (isInputOperation()) {
- BLI_rcti_init(output, input->xmin, input->xmax, input->ymin, input->ymax);
- return false;
- }
- else {
- rcti tempOutput;
- bool first = true;
- for (int i = 0; i < getNumberOfInputSockets(); i ++) {
- NodeOperation *inputOperation = this->getInputOperation(i);
- if (inputOperation && inputOperation->determineDependingAreaOfInterest(input, readOperation, &tempOutput)) {
- if (first) {
- output->xmin = tempOutput.xmin;
- output->ymin = tempOutput.ymin;
- output->xmax = tempOutput.xmax;
- output->ymax = tempOutput.ymax;
- first = false;
- }
- else {
- output->xmin = min(output->xmin, tempOutput.xmin);
- output->ymin = min(output->ymin, tempOutput.ymin);
- output->xmax = max(output->xmax, tempOutput.xmax);
- output->ymax = max(output->ymax, tempOutput.ymax);
- }
- }
- }
- return !first;
- }
+ for (Inputs::const_iterator it = m_inputs.begin(); it != m_inputs.end(); ++it) {
+ NodeOperationInput *input = *it;
+ if (input->isConnected()) {
+ sockets->push_back(input);
+ }
+ }
+}
+
+bool NodeOperation::determineDependingAreaOfInterest(rcti *input,
+ ReadBufferOperation *readOperation,
+ rcti *output)
+{
+ if (isInputOperation()) {
+ BLI_rcti_init(output, input->xmin, input->xmax, input->ymin, input->ymax);
+ return false;
+ }
+ else {
+ rcti tempOutput;
+ bool first = true;
+ for (int i = 0; i < getNumberOfInputSockets(); i++) {
+ NodeOperation *inputOperation = this->getInputOperation(i);
+ if (inputOperation &&
+ inputOperation->determineDependingAreaOfInterest(input, readOperation, &tempOutput)) {
+ if (first) {
+ output->xmin = tempOutput.xmin;
+ output->ymin = tempOutput.ymin;
+ output->xmax = tempOutput.xmax;
+ output->ymax = tempOutput.ymax;
+ first = false;
+ }
+ else {
+ output->xmin = min(output->xmin, tempOutput.xmin);
+ output->ymin = min(output->ymin, tempOutput.ymin);
+ output->xmax = max(output->xmax, tempOutput.xmax);
+ output->ymax = max(output->ymax, tempOutput.ymax);
+ }
+ }
+ }
+ return !first;
+ }
}
-
/*****************
**** OpInput ****
*****************/
-NodeOperationInput::NodeOperationInput(NodeOperation *op, DataType datatype, InputResizeMode resizeMode) :
- m_operation(op),
- m_datatype(datatype),
- m_resizeMode(resizeMode),
- m_link(NULL)
+NodeOperationInput::NodeOperationInput(NodeOperation *op,
+ DataType datatype,
+ InputResizeMode resizeMode)
+ : m_operation(op), m_datatype(datatype), m_resizeMode(resizeMode), m_link(NULL)
{
}
SocketReader *NodeOperationInput::getReader()
{
- if (isConnected()) {
- return &m_link->getOperation();
- }
- else {
- return NULL;
- }
+ if (isConnected()) {
+ return &m_link->getOperation();
+ }
+ else {
+ return NULL;
+ }
}
-void NodeOperationInput::determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2])
+void NodeOperationInput::determineResolution(unsigned int resolution[2],
+ unsigned int preferredResolution[2])
{
- if (m_link)
- m_link->determineResolution(resolution, preferredResolution);
+ if (m_link)
+ m_link->determineResolution(resolution, preferredResolution);
}
-
/******************
**** OpOutput ****
******************/
-NodeOperationOutput::NodeOperationOutput(NodeOperation *op, DataType datatype) :
- m_operation(op),
- m_datatype(datatype)
+NodeOperationOutput::NodeOperationOutput(NodeOperation *op, DataType datatype)
+ : m_operation(op), m_datatype(datatype)
{
}
-void NodeOperationOutput::determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2])
+void NodeOperationOutput::determineResolution(unsigned int resolution[2],
+ unsigned int preferredResolution[2])
{
- NodeOperation &operation = getOperation();
- if (operation.isResolutionSet()) {
- resolution[0] = operation.getWidth();
- resolution[1] = operation.getHeight();
- }
- else {
- operation.determineResolution(resolution, preferredResolution);
- operation.setResolution(resolution);
- }
+ NodeOperation &operation = getOperation();
+ if (operation.isResolutionSet()) {
+ resolution[0] = operation.getWidth();
+ resolution[1] = operation.getHeight();
+ }
+ else {
+ operation.determineResolution(resolution, preferredResolution);
+ operation.setResolution(resolution);
+ }
}
diff --git a/source/blender/compositor/intern/COM_NodeOperation.h b/source/blender/compositor/intern/COM_NodeOperation.h
index 9296b1bfd22..939d3e1f8a7 100644
--- a/source/blender/compositor/intern/COM_NodeOperation.h
+++ b/source/blender/compositor/intern/COM_NodeOperation.h
@@ -37,8 +37,8 @@ extern "C" {
#include "clew.h"
using std::list;
-using std::min;
using std::max;
+using std::min;
class OpenCLDevice;
class ReadBufferOperation;
@@ -53,18 +53,18 @@ class NodeOperationOutput;
* \ingroup Model
*/
typedef enum InputResizeMode {
- /** \brief Center the input image to the center of the working area of the node, no resizing occurs */
- COM_SC_CENTER = NS_CR_CENTER,
- /** \brief The bottom left of the input image is the bottom left of the working area of the node, no resizing occurs */
- COM_SC_NO_RESIZE = NS_CR_NONE,
- /** \brief Fit the width of the input image to the width of the working area of the node */
- COM_SC_FIT_WIDTH = NS_CR_FIT_WIDTH,
- /** \brief Fit the height of the input image to the height of the working area of the node */
- COM_SC_FIT_HEIGHT = NS_CR_FIT_HEIGHT,
- /** \brief Fit the width or the height of the input image to the width or height of the working area of the node, image will be larger than the working area */
- COM_SC_FIT = NS_CR_FIT,
- /** \brief Fit the width and the height of the input image to the width and height of the working area of the node, image will be equally larger than the working area */
- COM_SC_STRETCH = NS_CR_STRETCH,
+ /** \brief Center the input image to the center of the working area of the node, no resizing occurs */
+ COM_SC_CENTER = NS_CR_CENTER,
+ /** \brief The bottom left of the input image is the bottom left of the working area of the node, no resizing occurs */
+ COM_SC_NO_RESIZE = NS_CR_NONE,
+ /** \brief Fit the width of the input image to the width of the working area of the node */
+ COM_SC_FIT_WIDTH = NS_CR_FIT_WIDTH,
+ /** \brief Fit the height of the input image to the height of the working area of the node */
+ COM_SC_FIT_HEIGHT = NS_CR_FIT_HEIGHT,
+ /** \brief Fit the width or the height of the input image to the width or height of the working area of the node, image will be larger than the working area */
+ COM_SC_FIT = NS_CR_FIT,
+ /** \brief Fit the width and the height of the input image to the width and height of the working area of the node, image will be equally larger than the working area */
+ COM_SC_STRETCH = NS_CR_STRETCH,
} InputResizeMode;
/**
@@ -74,332 +74,442 @@ typedef enum InputResizeMode {
* \ingroup Model
*/
class NodeOperation : public SocketReader {
-public:
- typedef std::vector<NodeOperationInput*> Inputs;
- typedef std::vector<NodeOperationOutput*> Outputs;
-
-private:
- Inputs m_inputs;
- Outputs m_outputs;
-
- /**
- * \brief the index of the input socket that will be used to determine the resolution
- */
- unsigned int m_resolutionInputSocketIndex;
-
- /**
- * \brief is this operation a complex one.
- *
- * Complex operations are typically doing many reads to calculate the output of a single pixel.
- * Mostly Filter types (Blurs, Convolution, Defocus etc) need this to be set to true.
- */
- bool m_complex;
-
- /**
- * \brief can this operation be scheduled on an OpenCL device.
- * \note Only applicable if complex is True
- */
- bool m_openCL;
-
- /**
- * \brief mutex reference for very special node initializations
- * \note only use when you really know what you are doing.
- * this mutex is used to share data among chunks in the same operation
- * \see TonemapOperation for an example of usage
- * \see NodeOperation.initMutex initializes this mutex
- * \see NodeOperation.deinitMutex deinitializes this mutex
- * \see NodeOperation.getMutex retrieve a pointer to this mutex.
- */
- ThreadMutex m_mutex;
-
- /**
- * \brief reference to the editing bNodeTree, used for break and update callback
- */
- const bNodeTree *m_btree;
-
- /**
- * \brief set to truth when resolution for this operation is set
- */
- bool m_isResolutionSet;
-
-public:
- virtual ~NodeOperation();
-
- unsigned int getNumberOfInputSockets() const { return m_inputs.size(); }
- unsigned int getNumberOfOutputSockets() const { return m_outputs.size(); }
- NodeOperationOutput *getOutputSocket(unsigned int index) const;
- NodeOperationOutput *getOutputSocket() const { return getOutputSocket(0); }
- NodeOperationInput *getInputSocket(unsigned int index) const;
-
- /** Check if this is an input operation
- * An input operation is an operation that only has output sockets and no input sockets
- */
- bool isInputOperation() const { return m_inputs.empty(); }
-
- /**
- * \brief determine the resolution of this node
- * \note this method will not set the resolution, this is the responsibility of the caller
- * \param resolution: the result of this operation
- * \param preferredResolution: the preferable resolution as no resolution could be determined
- */
- virtual void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]);
-
- /**
- * \brief isOutputOperation determines whether this operation is an output of the ExecutionSystem during rendering or editing.
- *
- * Default behavior if not overridden, this operation will not be evaluated as being an output of the ExecutionSystem.
- *
- * \see ExecutionSystem
- * \group check
- * \param rendering: [true false]
- * true: rendering
- * false: editing
- *
- * \return bool the result of this method
- */
- virtual bool isOutputOperation(bool /*rendering*/) const { return false; }
-
- virtual int isSingleThreaded() { return false; }
-
- void setbNodeTree(const bNodeTree *tree) { this->m_btree = tree; }
- virtual void initExecution();
-
- /**
- * \brief when a chunk is executed by a CPUDevice, this method is called
- * \ingroup execution
- * \param rect: the rectangle of the chunk (location and size)
- * \param chunkNumber: the chunkNumber to be calculated
- * \param memoryBuffers: all input MemoryBuffer's needed
- */
- virtual void executeRegion(rcti * /*rect*/,
- unsigned int /*chunkNumber*/) {}
-
- /**
- * \brief when a chunk is executed by an OpenCLDevice, this method is called
- * \ingroup execution
- * \note this method is only implemented in WriteBufferOperation
- * \param context: the OpenCL context
- * \param program: the OpenCL program containing all compositor kernels
- * \param queue: the OpenCL command queue of the device the chunk is executed on
- * \param rect: the rectangle of the chunk (location and size)
- * \param chunkNumber: the chunkNumber to be calculated
- * \param memoryBuffers: all input MemoryBuffer's needed
- * \param outputBuffer: the outputbuffer to write to
- */
- virtual void executeOpenCLRegion(OpenCLDevice * /*device*/,
- rcti * /*rect*/,
- unsigned int /*chunkNumber*/,
- MemoryBuffer ** /*memoryBuffers*/,
- MemoryBuffer * /*outputBuffer*/) {}
-
- /**
- * \brief custom handle to add new tasks to the OpenCL command queue in order to execute a chunk on an GPUDevice
- * \ingroup execution
- * \param context: the OpenCL context
- * \param program: the OpenCL program containing all compositor kernels
- * \param queue: the OpenCL command queue of the device the chunk is executed on
- * \param outputMemoryBuffer: the allocated memory buffer in main CPU memory
- * \param clOutputBuffer: the allocated memory buffer in OpenCLDevice memory
- * \param inputMemoryBuffers: all input MemoryBuffer's needed
- * \param clMemToCleanUp: all created cl_mem references must be added to this list. Framework will clean this after execution
- * \param clKernelsToCleanUp: all created cl_kernel references must be added to this list. Framework will clean this after execution
- */
- virtual void executeOpenCL(OpenCLDevice * /*device*/,
- MemoryBuffer * /*outputMemoryBuffer*/,
- cl_mem /*clOutputBuffer*/,
- MemoryBuffer ** /*inputMemoryBuffers*/,
- list<cl_mem> * /*clMemToCleanUp*/,
- list<cl_kernel> * /*clKernelsToCleanUp*/) {}
- virtual void deinitExecution();
-
- bool isResolutionSet() {
- return this->m_isResolutionSet;
- }
-
- /**
- * \brief set the resolution
- * \param resolution: the resolution to set
- */
- void setResolution(unsigned int resolution[2]) {
- if (!isResolutionSet()) {
- this->m_width = resolution[0];
- this->m_height = resolution[1];
- this->m_isResolutionSet = true;
- }
- }
-
-
- void getConnectedInputSockets(Inputs *sockets);
-
- /**
- * \brief is this operation complex
- *
- * Complex operations are typically doing many reads to calculate the output of a single pixel.
- * Mostly Filter types (Blurs, Convolution, Defocus etc) need this to be set to true.
- */
- bool isComplex() const { return this->m_complex; }
-
- virtual bool isSetOperation() const { return false; }
-
- /**
- * \brief is this operation of type ReadBufferOperation
- * \return [true:false]
- * \see ReadBufferOperation
- */
- virtual bool isReadBufferOperation() const { return false; }
-
- /**
- * \brief is this operation of type WriteBufferOperation
- * \return [true:false]
- * \see WriteBufferOperation
- */
- virtual bool isWriteBufferOperation() const { return false; }
-
- /**
- * \brief is this operation the active viewer output
- * user can select an ViewerNode to be active (the result of this node will be drawn on the backdrop)
- * \return [true:false]
- * \see BaseViewerOperation
- */
- virtual bool isActiveViewerOutput() const { return false; }
-
- virtual bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output);
-
- /**
- * \brief set the index of the input socket that will determine the resolution of this operation
- * \param index: the index to set
- */
- void setResolutionInputSocketIndex(unsigned int index);
-
- /**
- * \brief get the render priority of this node.
- * \note only applicable for output operations like ViewerOperation
- * \return CompositorPriority
- */
- virtual CompositorPriority getRenderPriority() const { return COM_PRIORITY_LOW; }
-
- /**
- * \brief can this NodeOperation be scheduled on an OpenCLDevice
- * \see WorkScheduler.schedule
- * \see ExecutionGroup.addOperation
- */
- bool isOpenCL() const { return this->m_openCL; }
-
- virtual bool isViewerOperation() const { return false; }
- virtual bool isPreviewOperation() const { return false; }
- virtual bool isFileOutputOperation() const { return false; }
- virtual bool isProxyOperation() const { return false; }
-
- virtual bool useDatatypeConversion() const { return true; }
-
- inline bool isBreaked() const {
- return this->m_btree->test_break(this->m_btree->tbh);
- }
-
- inline void updateDraw() {
- if (this->m_btree->update_draw)
- this->m_btree->update_draw(this->m_btree->udh);
- }
-protected:
- NodeOperation();
-
- void addInputSocket(DataType datatype, InputResizeMode resize_mode = COM_SC_CENTER);
- void addOutputSocket(DataType datatype);
-
- void setWidth(unsigned int width) { this->m_width = width; this->m_isResolutionSet = true; }
- void setHeight(unsigned int height) { this->m_height = height; this->m_isResolutionSet = true; }
- SocketReader *getInputSocketReader(unsigned int inputSocketindex);
- NodeOperation *getInputOperation(unsigned int inputSocketindex);
-
- void deinitMutex();
- void initMutex();
- void lockMutex();
- void unlockMutex();
-
- /**
- * \brief set whether this operation is complex
- *
- * Complex operations are typically doing many reads to calculate the output of a single pixel.
- * Mostly Filter types (Blurs, Convolution, Defocus etc) need this to be set to true.
- */
- void setComplex(bool complex) { this->m_complex = complex; }
-
- /**
- * \brief set if this NodeOperation can be scheduled on a OpenCLDevice
- */
- void setOpenCL(bool openCL) { this->m_openCL = openCL; }
-
- /* allow the DebugInfo class to look at internals */
- friend class DebugInfo;
+ public:
+ typedef std::vector<NodeOperationInput *> Inputs;
+ typedef std::vector<NodeOperationOutput *> Outputs;
+
+ private:
+ Inputs m_inputs;
+ Outputs m_outputs;
+
+ /**
+ * \brief the index of the input socket that will be used to determine the resolution
+ */
+ unsigned int m_resolutionInputSocketIndex;
+
+ /**
+ * \brief is this operation a complex one.
+ *
+ * Complex operations are typically doing many reads to calculate the output of a single pixel.
+ * Mostly Filter types (Blurs, Convolution, Defocus etc) need this to be set to true.
+ */
+ bool m_complex;
+
+ /**
+ * \brief can this operation be scheduled on an OpenCL device.
+ * \note Only applicable if complex is True
+ */
+ bool m_openCL;
+
+ /**
+ * \brief mutex reference for very special node initializations
+ * \note only use when you really know what you are doing.
+ * this mutex is used to share data among chunks in the same operation
+ * \see TonemapOperation for an example of usage
+ * \see NodeOperation.initMutex initializes this mutex
+ * \see NodeOperation.deinitMutex deinitializes this mutex
+ * \see NodeOperation.getMutex retrieve a pointer to this mutex.
+ */
+ ThreadMutex m_mutex;
+
+ /**
+ * \brief reference to the editing bNodeTree, used for break and update callback
+ */
+ const bNodeTree *m_btree;
+
+ /**
+ * \brief set to truth when resolution for this operation is set
+ */
+ bool m_isResolutionSet;
+
+ public:
+ virtual ~NodeOperation();
+
+ unsigned int getNumberOfInputSockets() const
+ {
+ return m_inputs.size();
+ }
+ unsigned int getNumberOfOutputSockets() const
+ {
+ return m_outputs.size();
+ }
+ NodeOperationOutput *getOutputSocket(unsigned int index) const;
+ NodeOperationOutput *getOutputSocket() const
+ {
+ return getOutputSocket(0);
+ }
+ NodeOperationInput *getInputSocket(unsigned int index) const;
+
+ /** Check if this is an input operation
+ * An input operation is an operation that only has output sockets and no input sockets
+ */
+ bool isInputOperation() const
+ {
+ return m_inputs.empty();
+ }
+
+ /**
+ * \brief determine the resolution of this node
+ * \note this method will not set the resolution, this is the responsibility of the caller
+ * \param resolution: the result of this operation
+ * \param preferredResolution: the preferable resolution as no resolution could be determined
+ */
+ virtual void determineResolution(unsigned int resolution[2],
+ unsigned int preferredResolution[2]);
+
+ /**
+ * \brief isOutputOperation determines whether this operation is an output of the ExecutionSystem during rendering or editing.
+ *
+ * Default behavior if not overridden, this operation will not be evaluated as being an output of the ExecutionSystem.
+ *
+ * \see ExecutionSystem
+ * \group check
+ * \param rendering: [true false]
+ * true: rendering
+ * false: editing
+ *
+ * \return bool the result of this method
+ */
+ virtual bool isOutputOperation(bool /*rendering*/) const
+ {
+ return false;
+ }
+
+ virtual int isSingleThreaded()
+ {
+ return false;
+ }
+
+ void setbNodeTree(const bNodeTree *tree)
+ {
+ this->m_btree = tree;
+ }
+ virtual void initExecution();
+
+ /**
+ * \brief when a chunk is executed by a CPUDevice, this method is called
+ * \ingroup execution
+ * \param rect: the rectangle of the chunk (location and size)
+ * \param chunkNumber: the chunkNumber to be calculated
+ * \param memoryBuffers: all input MemoryBuffer's needed
+ */
+ virtual void executeRegion(rcti * /*rect*/, unsigned int /*chunkNumber*/)
+ {
+ }
+
+ /**
+ * \brief when a chunk is executed by an OpenCLDevice, this method is called
+ * \ingroup execution
+ * \note this method is only implemented in WriteBufferOperation
+ * \param context: the OpenCL context
+ * \param program: the OpenCL program containing all compositor kernels
+ * \param queue: the OpenCL command queue of the device the chunk is executed on
+ * \param rect: the rectangle of the chunk (location and size)
+ * \param chunkNumber: the chunkNumber to be calculated
+ * \param memoryBuffers: all input MemoryBuffer's needed
+ * \param outputBuffer: the outputbuffer to write to
+ */
+ virtual void executeOpenCLRegion(OpenCLDevice * /*device*/,
+ rcti * /*rect*/,
+ unsigned int /*chunkNumber*/,
+ MemoryBuffer ** /*memoryBuffers*/,
+ MemoryBuffer * /*outputBuffer*/)
+ {
+ }
+
+ /**
+ * \brief custom handle to add new tasks to the OpenCL command queue in order to execute a chunk on an GPUDevice
+ * \ingroup execution
+ * \param context: the OpenCL context
+ * \param program: the OpenCL program containing all compositor kernels
+ * \param queue: the OpenCL command queue of the device the chunk is executed on
+ * \param outputMemoryBuffer: the allocated memory buffer in main CPU memory
+ * \param clOutputBuffer: the allocated memory buffer in OpenCLDevice memory
+ * \param inputMemoryBuffers: all input MemoryBuffer's needed
+ * \param clMemToCleanUp: all created cl_mem references must be added to this list. Framework will clean this after execution
+ * \param clKernelsToCleanUp: all created cl_kernel references must be added to this list. Framework will clean this after execution
+ */
+ virtual void executeOpenCL(OpenCLDevice * /*device*/,
+ MemoryBuffer * /*outputMemoryBuffer*/,
+ cl_mem /*clOutputBuffer*/,
+ MemoryBuffer ** /*inputMemoryBuffers*/,
+ list<cl_mem> * /*clMemToCleanUp*/,
+ list<cl_kernel> * /*clKernelsToCleanUp*/)
+ {
+ }
+ virtual void deinitExecution();
+
+ bool isResolutionSet()
+ {
+ return this->m_isResolutionSet;
+ }
+
+ /**
+ * \brief set the resolution
+ * \param resolution: the resolution to set
+ */
+ void setResolution(unsigned int resolution[2])
+ {
+ if (!isResolutionSet()) {
+ this->m_width = resolution[0];
+ this->m_height = resolution[1];
+ this->m_isResolutionSet = true;
+ }
+ }
+
+ void getConnectedInputSockets(Inputs *sockets);
+
+ /**
+ * \brief is this operation complex
+ *
+ * Complex operations are typically doing many reads to calculate the output of a single pixel.
+ * Mostly Filter types (Blurs, Convolution, Defocus etc) need this to be set to true.
+ */
+ bool isComplex() const
+ {
+ return this->m_complex;
+ }
+
+ virtual bool isSetOperation() const
+ {
+ return false;
+ }
+
+ /**
+ * \brief is this operation of type ReadBufferOperation
+ * \return [true:false]
+ * \see ReadBufferOperation
+ */
+ virtual bool isReadBufferOperation() const
+ {
+ return false;
+ }
+
+ /**
+ * \brief is this operation of type WriteBufferOperation
+ * \return [true:false]
+ * \see WriteBufferOperation
+ */
+ virtual bool isWriteBufferOperation() const
+ {
+ return false;
+ }
+
+ /**
+ * \brief is this operation the active viewer output
+ * user can select an ViewerNode to be active (the result of this node will be drawn on the backdrop)
+ * \return [true:false]
+ * \see BaseViewerOperation
+ */
+ virtual bool isActiveViewerOutput() const
+ {
+ return false;
+ }
+
+ virtual bool determineDependingAreaOfInterest(rcti *input,
+ ReadBufferOperation *readOperation,
+ rcti *output);
+
+ /**
+ * \brief set the index of the input socket that will determine the resolution of this operation
+ * \param index: the index to set
+ */
+ void setResolutionInputSocketIndex(unsigned int index);
+
+ /**
+ * \brief get the render priority of this node.
+ * \note only applicable for output operations like ViewerOperation
+ * \return CompositorPriority
+ */
+ virtual CompositorPriority getRenderPriority() const
+ {
+ return COM_PRIORITY_LOW;
+ }
+
+ /**
+ * \brief can this NodeOperation be scheduled on an OpenCLDevice
+ * \see WorkScheduler.schedule
+ * \see ExecutionGroup.addOperation
+ */
+ bool isOpenCL() const
+ {
+ return this->m_openCL;
+ }
+
+ virtual bool isViewerOperation() const
+ {
+ return false;
+ }
+ virtual bool isPreviewOperation() const
+ {
+ return false;
+ }
+ virtual bool isFileOutputOperation() const
+ {
+ return false;
+ }
+ virtual bool isProxyOperation() const
+ {
+ return false;
+ }
+
+ virtual bool useDatatypeConversion() const
+ {
+ return true;
+ }
+
+ inline bool isBreaked() const
+ {
+ return this->m_btree->test_break(this->m_btree->tbh);
+ }
+
+ inline void updateDraw()
+ {
+ if (this->m_btree->update_draw)
+ this->m_btree->update_draw(this->m_btree->udh);
+ }
+
+ protected:
+ NodeOperation();
+
+ void addInputSocket(DataType datatype, InputResizeMode resize_mode = COM_SC_CENTER);
+ void addOutputSocket(DataType datatype);
+
+ void setWidth(unsigned int width)
+ {
+ this->m_width = width;
+ this->m_isResolutionSet = true;
+ }
+ void setHeight(unsigned int height)
+ {
+ this->m_height = height;
+ this->m_isResolutionSet = true;
+ }
+ SocketReader *getInputSocketReader(unsigned int inputSocketindex);
+ NodeOperation *getInputOperation(unsigned int inputSocketindex);
+
+ void deinitMutex();
+ void initMutex();
+ void lockMutex();
+ void unlockMutex();
+
+ /**
+ * \brief set whether this operation is complex
+ *
+ * Complex operations are typically doing many reads to calculate the output of a single pixel.
+ * Mostly Filter types (Blurs, Convolution, Defocus etc) need this to be set to true.
+ */
+ void setComplex(bool complex)
+ {
+ this->m_complex = complex;
+ }
+
+ /**
+ * \brief set if this NodeOperation can be scheduled on a OpenCLDevice
+ */
+ void setOpenCL(bool openCL)
+ {
+ this->m_openCL = openCL;
+ }
+
+ /* allow the DebugInfo class to look at internals */
+ friend class DebugInfo;
#ifdef WITH_CXX_GUARDEDALLOC
- MEM_CXX_CLASS_ALLOC_FUNCS("COM:NodeOperation")
+ MEM_CXX_CLASS_ALLOC_FUNCS("COM:NodeOperation")
#endif
};
-
class NodeOperationInput {
-private:
- NodeOperation *m_operation;
-
- /** Datatype of this socket. Is used for automatically data transformation.
- * \section data-conversion
- */
- DataType m_datatype;
-
- /** Resize mode of this socket */
- InputResizeMode m_resizeMode;
-
- /** Connected output */
- NodeOperationOutput *m_link;
-
-public:
- NodeOperationInput(NodeOperation *op, DataType datatype, InputResizeMode resizeMode = COM_SC_CENTER);
-
- NodeOperation &getOperation() const { return *m_operation; }
- DataType getDataType() const { return m_datatype; }
-
- void setLink(NodeOperationOutput *link) { m_link = link; }
- NodeOperationOutput *getLink() const { return m_link; }
- bool isConnected() const { return m_link; }
-
- void setResizeMode(InputResizeMode resizeMode) { this->m_resizeMode = resizeMode; }
- InputResizeMode getResizeMode() const { return this->m_resizeMode; }
-
- SocketReader *getReader();
-
- void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]);
+ private:
+ NodeOperation *m_operation;
+
+ /** Datatype of this socket. Is used for automatically data transformation.
+ * \section data-conversion
+ */
+ DataType m_datatype;
+
+ /** Resize mode of this socket */
+ InputResizeMode m_resizeMode;
+
+ /** Connected output */
+ NodeOperationOutput *m_link;
+
+ public:
+ NodeOperationInput(NodeOperation *op,
+ DataType datatype,
+ InputResizeMode resizeMode = COM_SC_CENTER);
+
+ NodeOperation &getOperation() const
+ {
+ return *m_operation;
+ }
+ DataType getDataType() const
+ {
+ return m_datatype;
+ }
+
+ void setLink(NodeOperationOutput *link)
+ {
+ m_link = link;
+ }
+ NodeOperationOutput *getLink() const
+ {
+ return m_link;
+ }
+ bool isConnected() const
+ {
+ return m_link;
+ }
+
+ void setResizeMode(InputResizeMode resizeMode)
+ {
+ this->m_resizeMode = resizeMode;
+ }
+ InputResizeMode getResizeMode() const
+ {
+ return this->m_resizeMode;
+ }
+
+ SocketReader *getReader();
+
+ void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]);
#ifdef WITH_CXX_GUARDEDALLOC
- MEM_CXX_CLASS_ALLOC_FUNCS("COM:NodeOperation")
+ MEM_CXX_CLASS_ALLOC_FUNCS("COM:NodeOperation")
#endif
};
-
class NodeOperationOutput {
-private:
- NodeOperation *m_operation;
-
- /** Datatype of this socket. Is used for automatically data transformation.
- * \section data-conversion
- */
- DataType m_datatype;
-
-public:
- NodeOperationOutput(NodeOperation *op, DataType datatype);
-
- NodeOperation &getOperation() const { return *m_operation; }
- DataType getDataType() const { return m_datatype; }
-
- /**
- * \brief determine the resolution of this data going through this socket
- * \param resolution: the result of this operation
- * \param preferredResolution: the preferable resolution as no resolution could be determined
- */
- void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]);
+ private:
+ NodeOperation *m_operation;
+
+ /** Datatype of this socket. Is used for automatically data transformation.
+ * \section data-conversion
+ */
+ DataType m_datatype;
+
+ public:
+ NodeOperationOutput(NodeOperation *op, DataType datatype);
+
+ NodeOperation &getOperation() const
+ {
+ return *m_operation;
+ }
+ DataType getDataType() const
+ {
+ return m_datatype;
+ }
+
+ /**
+ * \brief determine the resolution of this data going through this socket
+ * \param resolution: the result of this operation
+ * \param preferredResolution: the preferable resolution as no resolution could be determined
+ */
+ void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]);
#ifdef WITH_CXX_GUARDEDALLOC
- MEM_CXX_CLASS_ALLOC_FUNCS("COM:NodeOperation")
+ MEM_CXX_CLASS_ALLOC_FUNCS("COM:NodeOperation")
#endif
};
diff --git a/source/blender/compositor/intern/COM_NodeOperationBuilder.cpp b/source/blender/compositor/intern/COM_NodeOperationBuilder.cpp
index 37a1d7c005f..0f331a25ed9 100644
--- a/source/blender/compositor/intern/COM_NodeOperationBuilder.cpp
+++ b/source/blender/compositor/intern/COM_NodeOperationBuilder.cpp
@@ -39,12 +39,10 @@ extern "C" {
#include "COM_NodeOperationBuilder.h" /* own include */
-NodeOperationBuilder::NodeOperationBuilder(const CompositorContext *context, bNodeTree *b_nodetree) :
- m_context(context),
- m_current_node(NULL),
- m_active_viewer(NULL)
+NodeOperationBuilder::NodeOperationBuilder(const CompositorContext *context, bNodeTree *b_nodetree)
+ : m_context(context), m_current_node(NULL), m_active_viewer(NULL)
{
- m_graph.from_bNodeTree(*context, b_nodetree);
+ m_graph.from_bNodeTree(*context, b_nodetree);
}
NodeOperationBuilder::~NodeOperationBuilder()
@@ -53,208 +51,215 @@ NodeOperationBuilder::~NodeOperationBuilder()
void NodeOperationBuilder::convertToOperations(ExecutionSystem *system)
{
- /* interface handle for nodes */
- NodeConverter converter(this);
+ /* interface handle for nodes */
+ NodeConverter converter(this);
- for (int index = 0; index < m_graph.nodes().size(); index++) {
- Node *node = (Node *)m_graph.nodes()[index];
+ for (int index = 0; index < m_graph.nodes().size(); index++) {
+ Node *node = (Node *)m_graph.nodes()[index];
- m_current_node = node;
+ m_current_node = node;
- DebugInfo::node_to_operations(node);
- node->convertToOperations(converter, *m_context);
- }
+ DebugInfo::node_to_operations(node);
+ node->convertToOperations(converter, *m_context);
+ }
- m_current_node = NULL;
+ m_current_node = NULL;
- /* The input map constructed by nodes maps operation inputs to node inputs.
- * Inverting yields a map of node inputs to all connected operation inputs,
- * so multiple operations can use the same node input.
- */
- OpInputInverseMap inverse_input_map;
- for (InputSocketMap::const_iterator it = m_input_map.begin(); it != m_input_map.end(); ++it)
- inverse_input_map[it->second].push_back(it->first);
+ /* The input map constructed by nodes maps operation inputs to node inputs.
+ * Inverting yields a map of node inputs to all connected operation inputs,
+ * so multiple operations can use the same node input.
+ */
+ OpInputInverseMap inverse_input_map;
+ for (InputSocketMap::const_iterator it = m_input_map.begin(); it != m_input_map.end(); ++it)
+ inverse_input_map[it->second].push_back(it->first);
- for (NodeGraph::Links::const_iterator it = m_graph.links().begin(); it != m_graph.links().end(); ++it) {
- const NodeGraph::Link &link = *it;
- NodeOutput *from = link.getFromSocket();
- NodeInput *to = link.getToSocket();
+ for (NodeGraph::Links::const_iterator it = m_graph.links().begin(); it != m_graph.links().end();
+ ++it) {
+ const NodeGraph::Link &link = *it;
+ NodeOutput *from = link.getFromSocket();
+ NodeInput *to = link.getToSocket();
- NodeOperationOutput *op_from = find_operation_output(m_output_map, from);
- const OpInputs &op_to_list = find_operation_inputs(inverse_input_map, to);
- if (!op_from || op_to_list.empty()) {
- /* XXX allow this? error/debug message? */
- //BLI_assert(false);
- /* XXX note: this can happen with certain nodes (e.g. OutputFile)
- * which only generate operations in certain circumstances (rendering)
- * just let this pass silently for now ...
- */
- continue;
- }
+ NodeOperationOutput *op_from = find_operation_output(m_output_map, from);
+ const OpInputs &op_to_list = find_operation_inputs(inverse_input_map, to);
+ if (!op_from || op_to_list.empty()) {
+ /* XXX allow this? error/debug message? */
+ //BLI_assert(false);
+ /* XXX note: this can happen with certain nodes (e.g. OutputFile)
+ * which only generate operations in certain circumstances (rendering)
+ * just let this pass silently for now ...
+ */
+ continue;
+ }
- for (OpInputs::const_iterator it = op_to_list.begin(); it != op_to_list.end(); ++it) {
- NodeOperationInput *op_to = *it;
- addLink(op_from, op_to);
- }
- }
+ for (OpInputs::const_iterator it = op_to_list.begin(); it != op_to_list.end(); ++it) {
+ NodeOperationInput *op_to = *it;
+ addLink(op_from, op_to);
+ }
+ }
- add_operation_input_constants();
+ add_operation_input_constants();
- resolve_proxies();
+ resolve_proxies();
- add_datatype_conversions();
+ add_datatype_conversions();
- determineResolutions();
+ determineResolutions();
- /* surround complex ops with read/write buffer */
- add_complex_operation_buffers();
+ /* surround complex ops with read/write buffer */
+ add_complex_operation_buffers();
- /* links not available from here on */
- /* XXX make m_links a local variable to avoid confusion! */
- m_links.clear();
+ /* links not available from here on */
+ /* XXX make m_links a local variable to avoid confusion! */
+ m_links.clear();
- prune_operations();
+ prune_operations();
- /* ensure topological (link-based) order of nodes */
- /*sort_operations();*/ /* not needed yet */
+ /* ensure topological (link-based) order of nodes */
+ /*sort_operations();*/ /* not needed yet */
- /* create execution groups */
- group_operations();
+ /* create execution groups */
+ group_operations();
- /* transfer resulting operations to the system */
- system->set_operations(m_operations, m_groups);
+ /* transfer resulting operations to the system */
+ system->set_operations(m_operations, m_groups);
}
void NodeOperationBuilder::addOperation(NodeOperation *operation)
{
- m_operations.push_back(operation);
+ m_operations.push_back(operation);
}
-void NodeOperationBuilder::mapInputSocket(NodeInput *node_socket, NodeOperationInput *operation_socket)
+void NodeOperationBuilder::mapInputSocket(NodeInput *node_socket,
+ NodeOperationInput *operation_socket)
{
- BLI_assert(m_current_node);
- BLI_assert(node_socket->getNode() == m_current_node);
+ BLI_assert(m_current_node);
+ BLI_assert(node_socket->getNode() == m_current_node);
- /* note: this maps operation sockets to node sockets.
- * for resolving links the map will be inverted first in convertToOperations,
- * to get a list of links for each node input socket.
- */
- m_input_map[operation_socket] = node_socket;
+ /* note: this maps operation sockets to node sockets.
+ * for resolving links the map will be inverted first in convertToOperations,
+ * to get a list of links for each node input socket.
+ */
+ m_input_map[operation_socket] = node_socket;
}
-void NodeOperationBuilder::mapOutputSocket(NodeOutput *node_socket, NodeOperationOutput *operation_socket)
+void NodeOperationBuilder::mapOutputSocket(NodeOutput *node_socket,
+ NodeOperationOutput *operation_socket)
{
- BLI_assert(m_current_node);
- BLI_assert(node_socket->getNode() == m_current_node);
+ BLI_assert(m_current_node);
+ BLI_assert(node_socket->getNode() == m_current_node);
- m_output_map[node_socket] = operation_socket;
+ m_output_map[node_socket] = operation_socket;
}
void NodeOperationBuilder::addLink(NodeOperationOutput *from, NodeOperationInput *to)
{
- if (to->isConnected())
- return;
+ if (to->isConnected())
+ return;
- m_links.push_back(Link(from, to));
+ m_links.push_back(Link(from, to));
- /* register with the input */
- to->setLink(from);
+ /* register with the input */
+ to->setLink(from);
}
void NodeOperationBuilder::removeInputLink(NodeOperationInput *to)
{
- for (Links::iterator it = m_links.begin(); it != m_links.end(); ++it) {
- Link &link = *it;
- if (link.to() == to) {
- /* unregister with the input */
- to->setLink(NULL);
+ for (Links::iterator it = m_links.begin(); it != m_links.end(); ++it) {
+ Link &link = *it;
+ if (link.to() == to) {
+ /* unregister with the input */
+ to->setLink(NULL);
- m_links.erase(it);
- return;
- }
- }
+ m_links.erase(it);
+ return;
+ }
+ }
}
-NodeInput *NodeOperationBuilder::find_node_input(const InputSocketMap &map, NodeOperationInput *op_input)
+NodeInput *NodeOperationBuilder::find_node_input(const InputSocketMap &map,
+ NodeOperationInput *op_input)
{
- InputSocketMap::const_iterator it = map.find(op_input);
- return (it != map.end() ? it->second : NULL);
+ InputSocketMap::const_iterator it = map.find(op_input);
+ return (it != map.end() ? it->second : NULL);
}
-const NodeOperationBuilder::OpInputs &NodeOperationBuilder::find_operation_inputs(const OpInputInverseMap &map, NodeInput *node_input)
+const NodeOperationBuilder::OpInputs &NodeOperationBuilder::find_operation_inputs(
+ const OpInputInverseMap &map, NodeInput *node_input)
{
- static const OpInputs empty_list;
- OpInputInverseMap::const_iterator it = map.find(node_input);
- return (it != map.end() ? it->second : empty_list);
+ static const OpInputs empty_list;
+ OpInputInverseMap::const_iterator it = map.find(node_input);
+ return (it != map.end() ? it->second : empty_list);
}
-NodeOperationOutput *NodeOperationBuilder::find_operation_output(const OutputSocketMap &map, NodeOutput *node_output)
+NodeOperationOutput *NodeOperationBuilder::find_operation_output(const OutputSocketMap &map,
+ NodeOutput *node_output)
{
- OutputSocketMap::const_iterator it = map.find(node_output);
- return (it != map.end() ? it->second : NULL);
+ OutputSocketMap::const_iterator it = map.find(node_output);
+ return (it != map.end() ? it->second : NULL);
}
PreviewOperation *NodeOperationBuilder::make_preview_operation() const
{
- BLI_assert(m_current_node);
+ BLI_assert(m_current_node);
- if (!(m_current_node->getbNode()->flag & NODE_PREVIEW))
- return NULL;
- /* previews only in the active group */
- if (!m_current_node->isInActiveGroup())
- return NULL;
- /* do not calculate previews of hidden nodes */
- if (m_current_node->getbNode()->flag & NODE_HIDDEN)
- return NULL;
+ if (!(m_current_node->getbNode()->flag & NODE_PREVIEW))
+ return NULL;
+ /* previews only in the active group */
+ if (!m_current_node->isInActiveGroup())
+ return NULL;
+ /* do not calculate previews of hidden nodes */
+ if (m_current_node->getbNode()->flag & NODE_HIDDEN)
+ return NULL;
- bNodeInstanceHash *previews = m_context->getPreviewHash();
- if (previews) {
- PreviewOperation *operation = new PreviewOperation(m_context->getViewSettings(), m_context->getDisplaySettings());
- operation->setbNodeTree(m_context->getbNodeTree());
- operation->verifyPreview(previews, m_current_node->getInstanceKey());
- return operation;
- }
+ bNodeInstanceHash *previews = m_context->getPreviewHash();
+ if (previews) {
+ PreviewOperation *operation = new PreviewOperation(m_context->getViewSettings(),
+ m_context->getDisplaySettings());
+ operation->setbNodeTree(m_context->getbNodeTree());
+ operation->verifyPreview(previews, m_current_node->getInstanceKey());
+ return operation;
+ }
- return NULL;
+ return NULL;
}
void NodeOperationBuilder::addPreview(NodeOperationOutput *output)
{
- PreviewOperation *operation = make_preview_operation();
- if (operation) {
- addOperation(operation);
+ PreviewOperation *operation = make_preview_operation();
+ if (operation) {
+ addOperation(operation);
- addLink(output, operation->getInputSocket(0));
- }
+ addLink(output, operation->getInputSocket(0));
+ }
}
void NodeOperationBuilder::addNodeInputPreview(NodeInput *input)
{
- PreviewOperation *operation = make_preview_operation();
- if (operation) {
- addOperation(operation);
+ PreviewOperation *operation = make_preview_operation();
+ if (operation) {
+ addOperation(operation);
- mapInputSocket(input, operation->getInputSocket(0));
- }
+ mapInputSocket(input, operation->getInputSocket(0));
+ }
}
void NodeOperationBuilder::registerViewer(ViewerOperation *viewer)
{
- if (m_active_viewer) {
- if (m_current_node->isInActiveGroup()) {
- /* deactivate previous viewer */
- m_active_viewer->setActive(false);
+ if (m_active_viewer) {
+ if (m_current_node->isInActiveGroup()) {
+ /* deactivate previous viewer */
+ m_active_viewer->setActive(false);
- m_active_viewer = viewer;
- viewer->setActive(true);
- }
- }
- else {
- if (m_current_node->getbNodeTree() == m_context->getbNodeTree()) {
- m_active_viewer = viewer;
- viewer->setActive(true);
- }
- }
+ m_active_viewer = viewer;
+ viewer->setActive(true);
+ }
+ }
+ else {
+ if (m_current_node->getbNodeTree() == m_context->getbNodeTree()) {
+ m_active_viewer = viewer;
+ viewer->setActive(true);
+ }
+ }
}
/****************************
@@ -263,430 +268,436 @@ void NodeOperationBuilder::registerViewer(ViewerOperation *viewer)
void NodeOperationBuilder::add_datatype_conversions()
{
- Links convert_links;
- for (Links::const_iterator it = m_links.begin(); it != m_links.end(); ++it) {
- const Link &link = *it;
+ Links convert_links;
+ for (Links::const_iterator it = m_links.begin(); it != m_links.end(); ++it) {
+ const Link &link = *it;
- /* proxy operations can skip data type conversion */
- NodeOperation *from_op = &link.from()->getOperation();
- NodeOperation *to_op = &link.to()->getOperation();
- if (!(from_op->useDatatypeConversion() || to_op->useDatatypeConversion()))
- continue;
+ /* proxy operations can skip data type conversion */
+ NodeOperation *from_op = &link.from()->getOperation();
+ NodeOperation *to_op = &link.to()->getOperation();
+ if (!(from_op->useDatatypeConversion() || to_op->useDatatypeConversion()))
+ continue;
- if (link.from()->getDataType() != link.to()->getDataType())
- convert_links.push_back(link);
- }
- for (Links::const_iterator it = convert_links.begin(); it != convert_links.end(); ++it) {
- const Link &link = *it;
- NodeOperation *converter = Converter::convertDataType(link.from(), link.to());
- if (converter) {
- addOperation(converter);
+ if (link.from()->getDataType() != link.to()->getDataType())
+ convert_links.push_back(link);
+ }
+ for (Links::const_iterator it = convert_links.begin(); it != convert_links.end(); ++it) {
+ const Link &link = *it;
+ NodeOperation *converter = Converter::convertDataType(link.from(), link.to());
+ if (converter) {
+ addOperation(converter);
- removeInputLink(link.to());
- addLink(link.from(), converter->getInputSocket(0));
- addLink(converter->getOutputSocket(0), link.to());
- }
- }
+ removeInputLink(link.to());
+ addLink(link.from(), converter->getInputSocket(0));
+ addLink(converter->getOutputSocket(0), link.to());
+ }
+ }
}
void NodeOperationBuilder::add_operation_input_constants()
{
- /* Note: unconnected inputs cached first to avoid modifying
- * m_operations while iterating over it
- */
- typedef std::vector<NodeOperationInput*> Inputs;
- Inputs pending_inputs;
- for (Operations::const_iterator it = m_operations.begin(); it != m_operations.end(); ++it) {
- NodeOperation *op = *it;
- for (int k = 0; k < op->getNumberOfInputSockets(); ++k) {
- NodeOperationInput *input = op->getInputSocket(k);
- if (!input->isConnected())
- pending_inputs.push_back(input);
- }
- }
- for (Inputs::const_iterator it = pending_inputs.begin(); it != pending_inputs.end(); ++it) {
- NodeOperationInput *input = *it;
- add_input_constant_value(input, find_node_input(m_input_map, input));
- }
-}
-
-void NodeOperationBuilder::add_input_constant_value(NodeOperationInput *input, NodeInput *node_input)
-{
- switch (input->getDataType()) {
- case COM_DT_VALUE: {
- float value;
- if (node_input && node_input->getbNodeSocket())
- value = node_input->getEditorValueFloat();
- else
- value = 0.0f;
-
- SetValueOperation *op = new SetValueOperation();
- op->setValue(value);
- addOperation(op);
- addLink(op->getOutputSocket(), input);
- break;
- }
- case COM_DT_COLOR: {
- float value[4];
- if (node_input && node_input->getbNodeSocket())
- node_input->getEditorValueColor(value);
- else
- zero_v4(value);
-
- SetColorOperation *op = new SetColorOperation();
- op->setChannels(value);
- addOperation(op);
- addLink(op->getOutputSocket(), input);
- break;
- }
- case COM_DT_VECTOR: {
- float value[3];
- if (node_input && node_input->getbNodeSocket())
- node_input->getEditorValueVector(value);
- else
- zero_v3(value);
-
- SetVectorOperation *op = new SetVectorOperation();
- op->setVector(value);
- addOperation(op);
- addLink(op->getOutputSocket(), input);
- break;
- }
- }
+ /* Note: unconnected inputs cached first to avoid modifying
+ * m_operations while iterating over it
+ */
+ typedef std::vector<NodeOperationInput *> Inputs;
+ Inputs pending_inputs;
+ for (Operations::const_iterator it = m_operations.begin(); it != m_operations.end(); ++it) {
+ NodeOperation *op = *it;
+ for (int k = 0; k < op->getNumberOfInputSockets(); ++k) {
+ NodeOperationInput *input = op->getInputSocket(k);
+ if (!input->isConnected())
+ pending_inputs.push_back(input);
+ }
+ }
+ for (Inputs::const_iterator it = pending_inputs.begin(); it != pending_inputs.end(); ++it) {
+ NodeOperationInput *input = *it;
+ add_input_constant_value(input, find_node_input(m_input_map, input));
+ }
+}
+
+void NodeOperationBuilder::add_input_constant_value(NodeOperationInput *input,
+ NodeInput *node_input)
+{
+ switch (input->getDataType()) {
+ case COM_DT_VALUE: {
+ float value;
+ if (node_input && node_input->getbNodeSocket())
+ value = node_input->getEditorValueFloat();
+ else
+ value = 0.0f;
+
+ SetValueOperation *op = new SetValueOperation();
+ op->setValue(value);
+ addOperation(op);
+ addLink(op->getOutputSocket(), input);
+ break;
+ }
+ case COM_DT_COLOR: {
+ float value[4];
+ if (node_input && node_input->getbNodeSocket())
+ node_input->getEditorValueColor(value);
+ else
+ zero_v4(value);
+
+ SetColorOperation *op = new SetColorOperation();
+ op->setChannels(value);
+ addOperation(op);
+ addLink(op->getOutputSocket(), input);
+ break;
+ }
+ case COM_DT_VECTOR: {
+ float value[3];
+ if (node_input && node_input->getbNodeSocket())
+ node_input->getEditorValueVector(value);
+ else
+ zero_v3(value);
+
+ SetVectorOperation *op = new SetVectorOperation();
+ op->setVector(value);
+ addOperation(op);
+ addLink(op->getOutputSocket(), input);
+ break;
+ }
+ }
}
void NodeOperationBuilder::resolve_proxies()
{
- Links proxy_links;
- for (Links::const_iterator it = m_links.begin(); it != m_links.end(); ++it) {
- const Link &link = *it;
- /* don't replace links from proxy to proxy, since we may need them for replacing others! */
- if (link.from()->getOperation().isProxyOperation() &&
- !link.to()->getOperation().isProxyOperation())
- {
- proxy_links.push_back(link);
- }
- }
-
- for (Links::const_iterator it = proxy_links.begin(); it != proxy_links.end(); ++it) {
- const Link &link = *it;
-
- NodeOperationInput *to = link.to();
- NodeOperationOutput *from = link.from();
- do {
- /* walk upstream bypassing the proxy operation */
- from = from->getOperation().getInputSocket(0)->getLink();
- } while (from && from->getOperation().isProxyOperation());
-
- removeInputLink(to);
- /* we may not have a final proxy input link,
- * in that case it just gets dropped
- */
- if (from)
- addLink(from, to);
- }
+ Links proxy_links;
+ for (Links::const_iterator it = m_links.begin(); it != m_links.end(); ++it) {
+ const Link &link = *it;
+ /* don't replace links from proxy to proxy, since we may need them for replacing others! */
+ if (link.from()->getOperation().isProxyOperation() &&
+ !link.to()->getOperation().isProxyOperation()) {
+ proxy_links.push_back(link);
+ }
+ }
+
+ for (Links::const_iterator it = proxy_links.begin(); it != proxy_links.end(); ++it) {
+ const Link &link = *it;
+
+ NodeOperationInput *to = link.to();
+ NodeOperationOutput *from = link.from();
+ do {
+ /* walk upstream bypassing the proxy operation */
+ from = from->getOperation().getInputSocket(0)->getLink();
+ } while (from && from->getOperation().isProxyOperation());
+
+ removeInputLink(to);
+ /* we may not have a final proxy input link,
+ * in that case it just gets dropped
+ */
+ if (from)
+ addLink(from, to);
+ }
}
void NodeOperationBuilder::determineResolutions()
{
- /* determine all resolutions of the operations (Width/Height) */
- for (Operations::const_iterator it = m_operations.begin(); it != m_operations.end(); ++it) {
- NodeOperation *op = *it;
-
- if (op->isOutputOperation(m_context->isRendering()) && !op->isPreviewOperation()) {
- unsigned int resolution[2] = {0, 0};
- unsigned int preferredResolution[2] = {0, 0};
- op->determineResolution(resolution, preferredResolution);
- op->setResolution(resolution);
- }
- }
-
- for (Operations::const_iterator it = m_operations.begin(); it != m_operations.end(); ++it) {
- NodeOperation *op = *it;
-
- if (op->isOutputOperation(m_context->isRendering()) && op->isPreviewOperation()) {
- unsigned int resolution[2] = {0, 0};
- unsigned int preferredResolution[2] = {0, 0};
- op->determineResolution(resolution, preferredResolution);
- op->setResolution(resolution);
- }
- }
-
- /* add convert resolution operations when needed */
- {
- Links convert_links;
- for (Links::const_iterator it = m_links.begin(); it != m_links.end(); ++it) {
- const Link &link = *it;
-
- if (link.to()->getResizeMode() != COM_SC_NO_RESIZE) {
- NodeOperation &from_op = link.from()->getOperation();
- NodeOperation &to_op = link.to()->getOperation();
- if (from_op.getWidth() != to_op.getWidth() || from_op.getHeight() != to_op.getHeight())
- convert_links.push_back(link);
- }
- }
- for (Links::const_iterator it = convert_links.begin(); it != convert_links.end(); ++it) {
- const Link &link = *it;
- Converter::convertResolution(*this, link.from(), link.to());
- }
- }
-}
-
-NodeOperationBuilder::OpInputs NodeOperationBuilder::cache_output_links(NodeOperationOutput *output) const
-{
- OpInputs inputs;
- for (Links::const_iterator it = m_links.begin(); it != m_links.end(); ++it) {
- const Link &link = *it;
- if (link.from() == output)
- inputs.push_back(link.to());
- }
- return inputs;
-}
-
-WriteBufferOperation *NodeOperationBuilder::find_attached_write_buffer_operation(NodeOperationOutput *output) const
-{
- for (Links::const_iterator it = m_links.begin(); it != m_links.end(); ++it) {
- const Link &link = *it;
- if (link.from() == output) {
- NodeOperation &op = link.to()->getOperation();
- if (op.isWriteBufferOperation())
- return (WriteBufferOperation *)(&op);
- }
- }
- return NULL;
+ /* determine all resolutions of the operations (Width/Height) */
+ for (Operations::const_iterator it = m_operations.begin(); it != m_operations.end(); ++it) {
+ NodeOperation *op = *it;
+
+ if (op->isOutputOperation(m_context->isRendering()) && !op->isPreviewOperation()) {
+ unsigned int resolution[2] = {0, 0};
+ unsigned int preferredResolution[2] = {0, 0};
+ op->determineResolution(resolution, preferredResolution);
+ op->setResolution(resolution);
+ }
+ }
+
+ for (Operations::const_iterator it = m_operations.begin(); it != m_operations.end(); ++it) {
+ NodeOperation *op = *it;
+
+ if (op->isOutputOperation(m_context->isRendering()) && op->isPreviewOperation()) {
+ unsigned int resolution[2] = {0, 0};
+ unsigned int preferredResolution[2] = {0, 0};
+ op->determineResolution(resolution, preferredResolution);
+ op->setResolution(resolution);
+ }
+ }
+
+ /* add convert resolution operations when needed */
+ {
+ Links convert_links;
+ for (Links::const_iterator it = m_links.begin(); it != m_links.end(); ++it) {
+ const Link &link = *it;
+
+ if (link.to()->getResizeMode() != COM_SC_NO_RESIZE) {
+ NodeOperation &from_op = link.from()->getOperation();
+ NodeOperation &to_op = link.to()->getOperation();
+ if (from_op.getWidth() != to_op.getWidth() || from_op.getHeight() != to_op.getHeight())
+ convert_links.push_back(link);
+ }
+ }
+ for (Links::const_iterator it = convert_links.begin(); it != convert_links.end(); ++it) {
+ const Link &link = *it;
+ Converter::convertResolution(*this, link.from(), link.to());
+ }
+ }
+}
+
+NodeOperationBuilder::OpInputs NodeOperationBuilder::cache_output_links(
+ NodeOperationOutput *output) const
+{
+ OpInputs inputs;
+ for (Links::const_iterator it = m_links.begin(); it != m_links.end(); ++it) {
+ const Link &link = *it;
+ if (link.from() == output)
+ inputs.push_back(link.to());
+ }
+ return inputs;
+}
+
+WriteBufferOperation *NodeOperationBuilder::find_attached_write_buffer_operation(
+ NodeOperationOutput *output) const
+{
+ for (Links::const_iterator it = m_links.begin(); it != m_links.end(); ++it) {
+ const Link &link = *it;
+ if (link.from() == output) {
+ NodeOperation &op = link.to()->getOperation();
+ if (op.isWriteBufferOperation())
+ return (WriteBufferOperation *)(&op);
+ }
+ }
+ return NULL;
}
void NodeOperationBuilder::add_input_buffers(NodeOperation * /*operation*/,
NodeOperationInput *input)
{
- if (!input->isConnected())
- return;
+ if (!input->isConnected())
+ return;
- NodeOperationOutput *output = input->getLink();
- if (output->getOperation().isReadBufferOperation()) {
- /* input is already buffered, no need to add another */
- return;
- }
+ NodeOperationOutput *output = input->getLink();
+ if (output->getOperation().isReadBufferOperation()) {
+ /* input is already buffered, no need to add another */
+ return;
+ }
- /* this link will be replaced below */
- removeInputLink(input);
+ /* this link will be replaced below */
+ removeInputLink(input);
- /* check of other end already has write operation, otherwise add a new one */
- WriteBufferOperation *writeoperation = find_attached_write_buffer_operation(output);
- if (!writeoperation) {
- writeoperation = new WriteBufferOperation(output->getDataType());
- writeoperation->setbNodeTree(m_context->getbNodeTree());
- addOperation(writeoperation);
+ /* check of other end already has write operation, otherwise add a new one */
+ WriteBufferOperation *writeoperation = find_attached_write_buffer_operation(output);
+ if (!writeoperation) {
+ writeoperation = new WriteBufferOperation(output->getDataType());
+ writeoperation->setbNodeTree(m_context->getbNodeTree());
+ addOperation(writeoperation);
- addLink(output, writeoperation->getInputSocket(0));
+ addLink(output, writeoperation->getInputSocket(0));
- writeoperation->readResolutionFromInputSocket();
- }
+ writeoperation->readResolutionFromInputSocket();
+ }
- /* add readbuffer op for the input */
- ReadBufferOperation *readoperation = new ReadBufferOperation(output->getDataType());
- readoperation->setMemoryProxy(writeoperation->getMemoryProxy());
- this->addOperation(readoperation);
+ /* add readbuffer op for the input */
+ ReadBufferOperation *readoperation = new ReadBufferOperation(output->getDataType());
+ readoperation->setMemoryProxy(writeoperation->getMemoryProxy());
+ this->addOperation(readoperation);
- addLink(readoperation->getOutputSocket(), input);
+ addLink(readoperation->getOutputSocket(), input);
- readoperation->readResolutionFromWriteBuffer();
+ readoperation->readResolutionFromWriteBuffer();
}
-void NodeOperationBuilder::add_output_buffers(NodeOperation *operation, NodeOperationOutput *output)
+void NodeOperationBuilder::add_output_buffers(NodeOperation *operation,
+ NodeOperationOutput *output)
{
- /* cache connected sockets, so we can safely remove links first before replacing them */
- OpInputs targets = cache_output_links(output);
- if (targets.empty())
- return;
+ /* cache connected sockets, so we can safely remove links first before replacing them */
+ OpInputs targets = cache_output_links(output);
+ if (targets.empty())
+ return;
- WriteBufferOperation *writeOperation = NULL;
- for (OpInputs::const_iterator it = targets.begin(); it != targets.end(); ++it) {
- NodeOperationInput *target = *it;
+ WriteBufferOperation *writeOperation = NULL;
+ for (OpInputs::const_iterator it = targets.begin(); it != targets.end(); ++it) {
+ NodeOperationInput *target = *it;
- /* try to find existing write buffer operation */
- if (target->getOperation().isWriteBufferOperation()) {
- BLI_assert(writeOperation == NULL); /* there should only be one write op connected */
- writeOperation = (WriteBufferOperation *)(&target->getOperation());
- }
- else {
- /* remove all links to other nodes */
- removeInputLink(target);
- }
- }
+ /* try to find existing write buffer operation */
+ if (target->getOperation().isWriteBufferOperation()) {
+ BLI_assert(writeOperation == NULL); /* there should only be one write op connected */
+ writeOperation = (WriteBufferOperation *)(&target->getOperation());
+ }
+ else {
+ /* remove all links to other nodes */
+ removeInputLink(target);
+ }
+ }
- /* if no write buffer operation exists yet, create a new one */
- if (!writeOperation) {
- writeOperation = new WriteBufferOperation(operation->getOutputSocket()->getDataType());
- writeOperation->setbNodeTree(m_context->getbNodeTree());
- addOperation(writeOperation);
+ /* if no write buffer operation exists yet, create a new one */
+ if (!writeOperation) {
+ writeOperation = new WriteBufferOperation(operation->getOutputSocket()->getDataType());
+ writeOperation->setbNodeTree(m_context->getbNodeTree());
+ addOperation(writeOperation);
- addLink(output, writeOperation->getInputSocket(0));
- }
+ addLink(output, writeOperation->getInputSocket(0));
+ }
- writeOperation->readResolutionFromInputSocket();
+ writeOperation->readResolutionFromInputSocket();
- /* add readbuffer op for every former connected input */
- for (OpInputs::const_iterator it = targets.begin(); it != targets.end(); ++it) {
- NodeOperationInput *target = *it;
- if (&target->getOperation() == writeOperation)
- continue; /* skip existing write op links */
+ /* add readbuffer op for every former connected input */
+ for (OpInputs::const_iterator it = targets.begin(); it != targets.end(); ++it) {
+ NodeOperationInput *target = *it;
+ if (&target->getOperation() == writeOperation)
+ continue; /* skip existing write op links */
- ReadBufferOperation *readoperation = new ReadBufferOperation(operation->getOutputSocket()->getDataType());
- readoperation->setMemoryProxy(writeOperation->getMemoryProxy());
- addOperation(readoperation);
+ ReadBufferOperation *readoperation = new ReadBufferOperation(
+ operation->getOutputSocket()->getDataType());
+ readoperation->setMemoryProxy(writeOperation->getMemoryProxy());
+ addOperation(readoperation);
- addLink(readoperation->getOutputSocket(), target);
+ addLink(readoperation->getOutputSocket(), target);
- readoperation->readResolutionFromWriteBuffer();
- }
+ readoperation->readResolutionFromWriteBuffer();
+ }
}
void NodeOperationBuilder::add_complex_operation_buffers()
{
- /* note: complex ops and get cached here first, since adding operations
- * will invalidate iterators over the main m_operations
- */
- Operations complex_ops;
- for (Operations::const_iterator it = m_operations.begin(); it != m_operations.end(); ++it)
- if ((*it)->isComplex())
- complex_ops.push_back(*it);
+ /* note: complex ops and get cached here first, since adding operations
+ * will invalidate iterators over the main m_operations
+ */
+ Operations complex_ops;
+ for (Operations::const_iterator it = m_operations.begin(); it != m_operations.end(); ++it)
+ if ((*it)->isComplex())
+ complex_ops.push_back(*it);
- for (Operations::const_iterator it = complex_ops.begin(); it != complex_ops.end(); ++it) {
- NodeOperation *op = *it;
+ for (Operations::const_iterator it = complex_ops.begin(); it != complex_ops.end(); ++it) {
+ NodeOperation *op = *it;
- DebugInfo::operation_read_write_buffer(op);
+ DebugInfo::operation_read_write_buffer(op);
- for (int index = 0; index < op->getNumberOfInputSockets(); index++)
- add_input_buffers(op, op->getInputSocket(index));
+ for (int index = 0; index < op->getNumberOfInputSockets(); index++)
+ add_input_buffers(op, op->getInputSocket(index));
- for (int index = 0; index < op->getNumberOfOutputSockets(); index++)
- add_output_buffers(op, op->getOutputSocket(index));
- }
+ for (int index = 0; index < op->getNumberOfOutputSockets(); index++)
+ add_output_buffers(op, op->getOutputSocket(index));
+ }
}
-typedef std::set<NodeOperation*> Tags;
+typedef std::set<NodeOperation *> Tags;
static void find_reachable_operations_recursive(Tags &reachable, NodeOperation *op)
{
- if (reachable.find(op) != reachable.end())
- return;
- reachable.insert(op);
+ if (reachable.find(op) != reachable.end())
+ return;
+ reachable.insert(op);
- for (int i = 0; i < op->getNumberOfInputSockets(); ++i) {
- NodeOperationInput *input = op->getInputSocket(i);
- if (input->isConnected())
- find_reachable_operations_recursive(reachable, &input->getLink()->getOperation());
- }
+ for (int i = 0; i < op->getNumberOfInputSockets(); ++i) {
+ NodeOperationInput *input = op->getInputSocket(i);
+ if (input->isConnected())
+ find_reachable_operations_recursive(reachable, &input->getLink()->getOperation());
+ }
- /* associated write-buffer operations are executed as well */
- if (op->isReadBufferOperation()) {
- ReadBufferOperation *read_op = (ReadBufferOperation *)op;
- MemoryProxy *memproxy = read_op->getMemoryProxy();
- find_reachable_operations_recursive(reachable, memproxy->getWriteBufferOperation());
- }
+ /* associated write-buffer operations are executed as well */
+ if (op->isReadBufferOperation()) {
+ ReadBufferOperation *read_op = (ReadBufferOperation *)op;
+ MemoryProxy *memproxy = read_op->getMemoryProxy();
+ find_reachable_operations_recursive(reachable, memproxy->getWriteBufferOperation());
+ }
}
void NodeOperationBuilder::prune_operations()
{
- Tags reachable;
- for (Operations::const_iterator it = m_operations.begin(); it != m_operations.end(); ++it) {
- NodeOperation *op = *it;
+ Tags reachable;
+ for (Operations::const_iterator it = m_operations.begin(); it != m_operations.end(); ++it) {
+ NodeOperation *op = *it;
- /* output operations are primary executed operations */
- if (op->isOutputOperation(m_context->isRendering()))
- find_reachable_operations_recursive(reachable, op);
- }
+ /* output operations are primary executed operations */
+ if (op->isOutputOperation(m_context->isRendering()))
+ find_reachable_operations_recursive(reachable, op);
+ }
- /* delete unreachable operations */
- Operations reachable_ops;
- for (Operations::const_iterator it = m_operations.begin(); it != m_operations.end(); ++it) {
- NodeOperation *op = *it;
+ /* delete unreachable operations */
+ Operations reachable_ops;
+ for (Operations::const_iterator it = m_operations.begin(); it != m_operations.end(); ++it) {
+ NodeOperation *op = *it;
- if (reachable.find(op) != reachable.end())
- reachable_ops.push_back(op);
- else
- delete op;
- }
- /* finally replace the operations list with the pruned list */
- m_operations = reachable_ops;
+ if (reachable.find(op) != reachable.end())
+ reachable_ops.push_back(op);
+ else
+ delete op;
+ }
+ /* finally replace the operations list with the pruned list */
+ m_operations = reachable_ops;
}
/* topological (depth-first) sorting of operations */
-static void sort_operations_recursive(NodeOperationBuilder::Operations &sorted, Tags &visited, NodeOperation *op)
+static void sort_operations_recursive(NodeOperationBuilder::Operations &sorted,
+ Tags &visited,
+ NodeOperation *op)
{
- if (visited.find(op) != visited.end())
- return;
- visited.insert(op);
+ if (visited.find(op) != visited.end())
+ return;
+ visited.insert(op);
- for (int i = 0; i < op->getNumberOfInputSockets(); ++i) {
- NodeOperationInput *input = op->getInputSocket(i);
- if (input->isConnected())
- sort_operations_recursive(sorted, visited, &input->getLink()->getOperation());
- }
+ for (int i = 0; i < op->getNumberOfInputSockets(); ++i) {
+ NodeOperationInput *input = op->getInputSocket(i);
+ if (input->isConnected())
+ sort_operations_recursive(sorted, visited, &input->getLink()->getOperation());
+ }
- sorted.push_back(op);
+ sorted.push_back(op);
}
void NodeOperationBuilder::sort_operations()
{
- Operations sorted;
- sorted.reserve(m_operations.size());
- Tags visited;
+ Operations sorted;
+ sorted.reserve(m_operations.size());
+ Tags visited;
- for (Operations::const_iterator it = m_operations.begin(); it != m_operations.end(); ++it)
- sort_operations_recursive(sorted, visited, *it);
+ for (Operations::const_iterator it = m_operations.begin(); it != m_operations.end(); ++it)
+ sort_operations_recursive(sorted, visited, *it);
- m_operations = sorted;
+ m_operations = sorted;
}
static void add_group_operations_recursive(Tags &visited, NodeOperation *op, ExecutionGroup *group)
{
- if (visited.find(op) != visited.end())
- return;
- visited.insert(op);
+ if (visited.find(op) != visited.end())
+ return;
+ visited.insert(op);
- if (!group->addOperation(op))
- return;
+ if (!group->addOperation(op))
+ return;
- /* add all eligible input ops to the group */
- for (int i = 0; i < op->getNumberOfInputSockets(); ++i) {
- NodeOperationInput *input = op->getInputSocket(i);
- if (input->isConnected())
- add_group_operations_recursive(visited, &input->getLink()->getOperation(), group);
- }
+ /* add all eligible input ops to the group */
+ for (int i = 0; i < op->getNumberOfInputSockets(); ++i) {
+ NodeOperationInput *input = op->getInputSocket(i);
+ if (input->isConnected())
+ add_group_operations_recursive(visited, &input->getLink()->getOperation(), group);
+ }
}
ExecutionGroup *NodeOperationBuilder::make_group(NodeOperation *op)
{
- ExecutionGroup *group = new ExecutionGroup();
- m_groups.push_back(group);
+ ExecutionGroup *group = new ExecutionGroup();
+ m_groups.push_back(group);
- Tags visited;
- add_group_operations_recursive(visited, op, group);
+ Tags visited;
+ add_group_operations_recursive(visited, op, group);
- return group;
+ return group;
}
void NodeOperationBuilder::group_operations()
{
- for (Operations::const_iterator it = m_operations.begin(); it != m_operations.end(); ++it) {
- NodeOperation *op = *it;
-
- if (op->isOutputOperation(m_context->isRendering())) {
- ExecutionGroup *group = make_group(op);
- group->setOutputExecutionGroup(true);
- }
-
- /* add new groups for associated memory proxies where needed */
- if (op->isReadBufferOperation()) {
- ReadBufferOperation *read_op = (ReadBufferOperation *)op;
- MemoryProxy *memproxy = read_op->getMemoryProxy();
-
- if (memproxy->getExecutor() == NULL) {
- ExecutionGroup *group = make_group(memproxy->getWriteBufferOperation());
- memproxy->setExecutor(group);
- }
- }
- }
+ for (Operations::const_iterator it = m_operations.begin(); it != m_operations.end(); ++it) {
+ NodeOperation *op = *it;
+
+ if (op->isOutputOperation(m_context->isRendering())) {
+ ExecutionGroup *group = make_group(op);
+ group->setOutputExecutionGroup(true);
+ }
+
+ /* add new groups for associated memory proxies where needed */
+ if (op->isReadBufferOperation()) {
+ ReadBufferOperation *read_op = (ReadBufferOperation *)op;
+ MemoryProxy *memproxy = read_op->getMemoryProxy();
+
+ if (memproxy->getExecutor() == NULL) {
+ ExecutionGroup *group = make_group(memproxy->getWriteBufferOperation());
+ memproxy->setExecutor(group);
+ }
+ }
+ }
}
diff --git a/source/blender/compositor/intern/COM_NodeOperationBuilder.h b/source/blender/compositor/intern/COM_NodeOperationBuilder.h
index f4ab18b4f31..917fa2888fd 100644
--- a/source/blender/compositor/intern/COM_NodeOperationBuilder.h
+++ b/source/blender/compositor/intern/COM_NodeOperationBuilder.h
@@ -44,123 +44,136 @@ class WriteBufferOperation;
class ViewerOperation;
class NodeOperationBuilder {
-public:
- class Link {
- private:
- NodeOperationOutput *m_from;
- NodeOperationInput *m_to;
+ public:
+ class Link {
+ private:
+ NodeOperationOutput *m_from;
+ NodeOperationInput *m_to;
+
+ public:
+ Link(NodeOperationOutput *from, NodeOperationInput *to) : m_from(from), m_to(to)
+ {
+ }
+
+ NodeOperationOutput *from() const
+ {
+ return m_from;
+ }
+ NodeOperationInput *to() const
+ {
+ return m_to;
+ }
+ };
+
+ typedef std::vector<NodeOperation *> Operations;
+ typedef std::vector<Link> Links;
+ typedef std::vector<ExecutionGroup *> Groups;
+
+ typedef std::map<NodeOperationInput *, NodeInput *> InputSocketMap;
+ typedef std::map<NodeOutput *, NodeOperationOutput *> OutputSocketMap;
+
+ typedef std::vector<NodeOperationInput *> OpInputs;
+ typedef std::map<NodeInput *, OpInputs> OpInputInverseMap;
+
+ private:
+ const CompositorContext *m_context;
+ NodeGraph m_graph;
+
+ Operations m_operations;
+ Links m_links;
+ Groups m_groups;
+
+ /** Maps operation inputs to node inputs */
+ InputSocketMap m_input_map;
+ /** Maps node outputs to operation outputs */
+ OutputSocketMap m_output_map;
+
+ Node *m_current_node;
+
+ /** Operation that will be writing to the viewer image
+ * Only one operation can occupy this place at a time,
+ * to avoid race conditions
+ */
+ ViewerOperation *m_active_viewer;
+
+ public:
+ NodeOperationBuilder(const CompositorContext *context, bNodeTree *b_nodetree);
+ ~NodeOperationBuilder();
+
+ const CompositorContext &context() const
+ {
+ return *m_context;
+ }
+
+ void convertToOperations(ExecutionSystem *system);
+
+ void addOperation(NodeOperation *operation);
+
+ /** Map input socket of the current node to an operation socket */
+ void mapInputSocket(NodeInput *node_socket, NodeOperationInput *operation_socket);
+ /** Map output socket of the current node to an operation socket */
+ void mapOutputSocket(NodeOutput *node_socket, NodeOperationOutput *operation_socket);
+
+ void addLink(NodeOperationOutput *from, NodeOperationInput *to);
+ void removeInputLink(NodeOperationInput *to);
+
+ /** Add a preview operation for a operation output */
+ void addPreview(NodeOperationOutput *output);
+ /** Add a preview operation for a node input */
+ void addNodeInputPreview(NodeInput *input);
+
+ /** Define a viewer operation as the active output, if possible */
+ void registerViewer(ViewerOperation *viewer);
+ /** The currently active viewer output operation */
+ ViewerOperation *active_viewer() const
+ {
+ return m_active_viewer;
+ }
+
+ protected:
+ static NodeInput *find_node_input(const InputSocketMap &map, NodeOperationInput *op_input);
+ static const OpInputs &find_operation_inputs(const OpInputInverseMap &map,
+ NodeInput *node_input);
+ static NodeOperationOutput *find_operation_output(const OutputSocketMap &map,
+ NodeOutput *node_output);
+
+ /** Add datatype conversion where needed */
+ void add_datatype_conversions();
+
+ /** Construct a constant value operation for every unconnected input */
+ void add_operation_input_constants();
+ void add_input_constant_value(NodeOperationInput *input, NodeInput *node_input);
+
+ /** Replace proxy operations with direct links */
+ void resolve_proxies();
+
+ /** Calculate resolution for each operation */
+ void determineResolutions();
+
+ /** Helper function to store connected inputs for replacement */
+ OpInputs cache_output_links(NodeOperationOutput *output) const;
+ /** Find a connected write buffer operation to an OpOutput */
+ WriteBufferOperation *find_attached_write_buffer_operation(NodeOperationOutput *output) const;
+ /** Add read/write buffer operations around complex operations */
+ void add_complex_operation_buffers();
+ void add_input_buffers(NodeOperation *operation, NodeOperationInput *input);
+ void add_output_buffers(NodeOperation *operation, NodeOperationOutput *output);
+
+ /** Remove unreachable operations */
+ void prune_operations();
- public:
- Link(NodeOperationOutput *from, NodeOperationInput *to) :
- m_from(from),
- m_to(to)
- {}
+ /** Sort operations by link dependencies */
+ void sort_operations();
- NodeOperationOutput *from() const { return m_from; }
- NodeOperationInput *to() const { return m_to; }
- };
+ /** Create execution groups */
+ void group_operations();
+ ExecutionGroup *make_group(NodeOperation *op);
- typedef std::vector<NodeOperation *> Operations;
- typedef std::vector<Link> Links;
- typedef std::vector<ExecutionGroup *> Groups;
-
- typedef std::map<NodeOperationInput *, NodeInput *> InputSocketMap;
- typedef std::map<NodeOutput *, NodeOperationOutput *> OutputSocketMap;
-
- typedef std::vector<NodeOperationInput *> OpInputs;
- typedef std::map<NodeInput *, OpInputs> OpInputInverseMap;
-
-private:
- const CompositorContext *m_context;
- NodeGraph m_graph;
-
- Operations m_operations;
- Links m_links;
- Groups m_groups;
-
- /** Maps operation inputs to node inputs */
- InputSocketMap m_input_map;
- /** Maps node outputs to operation outputs */
- OutputSocketMap m_output_map;
-
- Node *m_current_node;
-
- /** Operation that will be writing to the viewer image
- * Only one operation can occupy this place at a time,
- * to avoid race conditions
- */
- ViewerOperation *m_active_viewer;
-
-public:
- NodeOperationBuilder(const CompositorContext *context, bNodeTree *b_nodetree);
- ~NodeOperationBuilder();
-
- const CompositorContext &context() const { return *m_context; }
-
- void convertToOperations(ExecutionSystem *system);
-
- void addOperation(NodeOperation *operation);
-
- /** Map input socket of the current node to an operation socket */
- void mapInputSocket(NodeInput *node_socket, NodeOperationInput *operation_socket);
- /** Map output socket of the current node to an operation socket */
- void mapOutputSocket(NodeOutput *node_socket, NodeOperationOutput *operation_socket);
-
- void addLink(NodeOperationOutput *from, NodeOperationInput *to);
- void removeInputLink(NodeOperationInput *to);
-
- /** Add a preview operation for a operation output */
- void addPreview(NodeOperationOutput *output);
- /** Add a preview operation for a node input */
- void addNodeInputPreview(NodeInput *input);
-
- /** Define a viewer operation as the active output, if possible */
- void registerViewer(ViewerOperation *viewer);
- /** The currently active viewer output operation */
- ViewerOperation *active_viewer() const { return m_active_viewer; }
-
-protected:
- static NodeInput *find_node_input(const InputSocketMap &map, NodeOperationInput *op_input);
- static const OpInputs &find_operation_inputs(const OpInputInverseMap &map, NodeInput *node_input);
- static NodeOperationOutput *find_operation_output(const OutputSocketMap &map, NodeOutput *node_output);
-
- /** Add datatype conversion where needed */
- void add_datatype_conversions();
-
- /** Construct a constant value operation for every unconnected input */
- void add_operation_input_constants();
- void add_input_constant_value(NodeOperationInput *input, NodeInput *node_input);
-
- /** Replace proxy operations with direct links */
- void resolve_proxies();
-
- /** Calculate resolution for each operation */
- void determineResolutions();
-
- /** Helper function to store connected inputs for replacement */
- OpInputs cache_output_links(NodeOperationOutput *output) const;
- /** Find a connected write buffer operation to an OpOutput */
- WriteBufferOperation *find_attached_write_buffer_operation(NodeOperationOutput *output) const;
- /** Add read/write buffer operations around complex operations */
- void add_complex_operation_buffers();
- void add_input_buffers(NodeOperation *operation, NodeOperationInput *input);
- void add_output_buffers(NodeOperation *operation, NodeOperationOutput *output);
-
- /** Remove unreachable operations */
- void prune_operations();
-
- /** Sort operations by link dependencies */
- void sort_operations();
-
- /** Create execution groups */
- void group_operations();
- ExecutionGroup *make_group(NodeOperation *op);
-
-private:
- PreviewOperation *make_preview_operation() const;
+ private:
+ PreviewOperation *make_preview_operation() const;
#ifdef WITH_CXX_GUARDEDALLOC
- MEM_CXX_CLASS_ALLOC_FUNCS("COM:NodeCompilerImpl")
+ MEM_CXX_CLASS_ALLOC_FUNCS("COM:NodeCompilerImpl")
#endif
};
diff --git a/source/blender/compositor/intern/COM_OpenCLDevice.cpp b/source/blender/compositor/intern/COM_OpenCLDevice.cpp
index fd74c7ebfa4..12e072b9b12 100644
--- a/source/blender/compositor/intern/COM_OpenCLDevice.cpp
+++ b/source/blender/compositor/intern/COM_OpenCLDevice.cpp
@@ -19,200 +19,250 @@
#include "COM_OpenCLDevice.h"
#include "COM_WorkScheduler.h"
-typedef enum COM_VendorID {NVIDIA = 0x10DE, AMD = 0x1002} COM_VendorID;
+typedef enum COM_VendorID { NVIDIA = 0x10DE, AMD = 0x1002 } COM_VendorID;
const cl_image_format IMAGE_FORMAT_COLOR = {
- CL_RGBA,
- CL_FLOAT,
+ CL_RGBA,
+ CL_FLOAT,
};
const cl_image_format IMAGE_FORMAT_VECTOR = {
- CL_RGB,
- CL_FLOAT,
+ CL_RGB,
+ CL_FLOAT,
};
const cl_image_format IMAGE_FORMAT_VALUE = {
- CL_R,
- CL_FLOAT,
+ CL_R,
+ CL_FLOAT,
};
-OpenCLDevice::OpenCLDevice(cl_context context, cl_device_id device, cl_program program, cl_int vendorId)
+OpenCLDevice::OpenCLDevice(cl_context context,
+ cl_device_id device,
+ cl_program program,
+ cl_int vendorId)
{
- this->m_device = device;
- this->m_context = context;
- this->m_program = program;
- this->m_queue = NULL;
- this->m_vendorID = vendorId;
+ this->m_device = device;
+ this->m_context = context;
+ this->m_program = program;
+ this->m_queue = NULL;
+ this->m_vendorID = vendorId;
}
bool OpenCLDevice::initialize()
{
- cl_int error;
- this->m_queue = clCreateCommandQueue(this->m_context, this->m_device, 0, &error);
- return false;
+ cl_int error;
+ this->m_queue = clCreateCommandQueue(this->m_context, this->m_device, 0, &error);
+ return false;
}
void OpenCLDevice::deinitialize()
{
- if (this->m_queue) {
- clReleaseCommandQueue(this->m_queue);
- }
+ if (this->m_queue) {
+ clReleaseCommandQueue(this->m_queue);
+ }
}
void OpenCLDevice::execute(WorkPackage *work)
{
- const unsigned int chunkNumber = work->getChunkNumber();
- ExecutionGroup *executionGroup = work->getExecutionGroup();
- rcti rect;
+ const unsigned int chunkNumber = work->getChunkNumber();
+ ExecutionGroup *executionGroup = work->getExecutionGroup();
+ rcti rect;
- executionGroup->determineChunkRect(&rect, chunkNumber);
- MemoryBuffer **inputBuffers = executionGroup->getInputBuffersOpenCL(chunkNumber);
- MemoryBuffer *outputBuffer = executionGroup->allocateOutputBuffer(chunkNumber, &rect);
+ executionGroup->determineChunkRect(&rect, chunkNumber);
+ MemoryBuffer **inputBuffers = executionGroup->getInputBuffersOpenCL(chunkNumber);
+ MemoryBuffer *outputBuffer = executionGroup->allocateOutputBuffer(chunkNumber, &rect);
- executionGroup->getOutputOperation()->executeOpenCLRegion(this, &rect,
- chunkNumber, inputBuffers, outputBuffer);
+ executionGroup->getOutputOperation()->executeOpenCLRegion(
+ this, &rect, chunkNumber, inputBuffers, outputBuffer);
- delete outputBuffer;
+ delete outputBuffer;
- executionGroup->finalizeChunkExecution(chunkNumber, inputBuffers);
+ executionGroup->finalizeChunkExecution(chunkNumber, inputBuffers);
}
-cl_mem OpenCLDevice::COM_clAttachMemoryBufferToKernelParameter(cl_kernel kernel, int parameterIndex, int offsetIndex,
- list<cl_mem> *cleanup, MemoryBuffer **inputMemoryBuffers,
+cl_mem OpenCLDevice::COM_clAttachMemoryBufferToKernelParameter(cl_kernel kernel,
+ int parameterIndex,
+ int offsetIndex,
+ list<cl_mem> *cleanup,
+ MemoryBuffer **inputMemoryBuffers,
SocketReader *reader)
{
- return COM_clAttachMemoryBufferToKernelParameter(kernel, parameterIndex, offsetIndex, cleanup, inputMemoryBuffers, (ReadBufferOperation *)reader);
+ return COM_clAttachMemoryBufferToKernelParameter(kernel,
+ parameterIndex,
+ offsetIndex,
+ cleanup,
+ inputMemoryBuffers,
+ (ReadBufferOperation *)reader);
}
const cl_image_format *OpenCLDevice::determineImageFormat(MemoryBuffer *memoryBuffer)
{
- const cl_image_format *imageFormat;
- int num_channels = memoryBuffer->get_num_channels();
- if (num_channels == 1) {
- imageFormat = &IMAGE_FORMAT_VALUE;
- }
- else if (num_channels == 3) {
- imageFormat = &IMAGE_FORMAT_VECTOR;
- }
- else {
- imageFormat = &IMAGE_FORMAT_COLOR;
- }
-
- return imageFormat;
+ const cl_image_format *imageFormat;
+ int num_channels = memoryBuffer->get_num_channels();
+ if (num_channels == 1) {
+ imageFormat = &IMAGE_FORMAT_VALUE;
+ }
+ else if (num_channels == 3) {
+ imageFormat = &IMAGE_FORMAT_VECTOR;
+ }
+ else {
+ imageFormat = &IMAGE_FORMAT_COLOR;
+ }
+
+ return imageFormat;
}
-cl_mem OpenCLDevice::COM_clAttachMemoryBufferToKernelParameter(cl_kernel kernel, int parameterIndex, int offsetIndex,
- list<cl_mem> *cleanup, MemoryBuffer **inputMemoryBuffers,
+cl_mem OpenCLDevice::COM_clAttachMemoryBufferToKernelParameter(cl_kernel kernel,
+ int parameterIndex,
+ int offsetIndex,
+ list<cl_mem> *cleanup,
+ MemoryBuffer **inputMemoryBuffers,
ReadBufferOperation *reader)
{
- cl_int error;
-
- MemoryBuffer *result = reader->getInputMemoryBuffer(inputMemoryBuffers);
-
- const cl_image_format *imageFormat = determineImageFormat(result);
-
- cl_mem clBuffer = clCreateImage2D(this->m_context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, imageFormat, result->getWidth(),
- result->getHeight(), 0, result->getBuffer(), &error);
-
- if (error != CL_SUCCESS) { printf("CLERROR[%d]: %s\n", error, clewErrorString(error)); }
- if (error == CL_SUCCESS) cleanup->push_back(clBuffer);
-
- error = clSetKernelArg(kernel, parameterIndex, sizeof(cl_mem), &clBuffer);
- if (error != CL_SUCCESS) { printf("CLERROR[%d]: %s\n", error, clewErrorString(error)); }
-
- COM_clAttachMemoryBufferOffsetToKernelParameter(kernel, offsetIndex, result);
- return clBuffer;
+ cl_int error;
+
+ MemoryBuffer *result = reader->getInputMemoryBuffer(inputMemoryBuffers);
+
+ const cl_image_format *imageFormat = determineImageFormat(result);
+
+ cl_mem clBuffer = clCreateImage2D(this->m_context,
+ CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,
+ imageFormat,
+ result->getWidth(),
+ result->getHeight(),
+ 0,
+ result->getBuffer(),
+ &error);
+
+ if (error != CL_SUCCESS) {
+ printf("CLERROR[%d]: %s\n", error, clewErrorString(error));
+ }
+ if (error == CL_SUCCESS)
+ cleanup->push_back(clBuffer);
+
+ error = clSetKernelArg(kernel, parameterIndex, sizeof(cl_mem), &clBuffer);
+ if (error != CL_SUCCESS) {
+ printf("CLERROR[%d]: %s\n", error, clewErrorString(error));
+ }
+
+ COM_clAttachMemoryBufferOffsetToKernelParameter(kernel, offsetIndex, result);
+ return clBuffer;
}
-void OpenCLDevice::COM_clAttachMemoryBufferOffsetToKernelParameter(cl_kernel kernel, int offsetIndex, MemoryBuffer *memoryBuffer)
+void OpenCLDevice::COM_clAttachMemoryBufferOffsetToKernelParameter(cl_kernel kernel,
+ int offsetIndex,
+ MemoryBuffer *memoryBuffer)
{
- if (offsetIndex != -1) {
- cl_int error;
- rcti *rect = memoryBuffer->getRect();
- cl_int2 offset = {{rect->xmin, rect->ymin}};
-
- error = clSetKernelArg(kernel, offsetIndex, sizeof(cl_int2), &offset);
- if (error != CL_SUCCESS) { printf("CLERROR[%d]: %s\n", error, clewErrorString(error)); }
- }
+ if (offsetIndex != -1) {
+ cl_int error;
+ rcti *rect = memoryBuffer->getRect();
+ cl_int2 offset = {{rect->xmin, rect->ymin}};
+
+ error = clSetKernelArg(kernel, offsetIndex, sizeof(cl_int2), &offset);
+ if (error != CL_SUCCESS) {
+ printf("CLERROR[%d]: %s\n", error, clewErrorString(error));
+ }
+ }
}
-void OpenCLDevice::COM_clAttachSizeToKernelParameter(cl_kernel kernel, int offsetIndex, NodeOperation *operation)
+void OpenCLDevice::COM_clAttachSizeToKernelParameter(cl_kernel kernel,
+ int offsetIndex,
+ NodeOperation *operation)
{
- if (offsetIndex != -1) {
- cl_int error;
- cl_int2 offset = {{(cl_int)operation->getWidth(), (cl_int)operation->getHeight()}};
-
- error = clSetKernelArg(kernel, offsetIndex, sizeof(cl_int2), &offset);
- if (error != CL_SUCCESS) { printf("CLERROR[%d]: %s\n", error, clewErrorString(error)); }
- }
+ if (offsetIndex != -1) {
+ cl_int error;
+ cl_int2 offset = {{(cl_int)operation->getWidth(), (cl_int)operation->getHeight()}};
+
+ error = clSetKernelArg(kernel, offsetIndex, sizeof(cl_int2), &offset);
+ if (error != CL_SUCCESS) {
+ printf("CLERROR[%d]: %s\n", error, clewErrorString(error));
+ }
+ }
}
-void OpenCLDevice::COM_clAttachOutputMemoryBufferToKernelParameter(cl_kernel kernel, int parameterIndex, cl_mem clOutputMemoryBuffer)
+void OpenCLDevice::COM_clAttachOutputMemoryBufferToKernelParameter(cl_kernel kernel,
+ int parameterIndex,
+ cl_mem clOutputMemoryBuffer)
{
- cl_int error;
- error = clSetKernelArg(kernel, parameterIndex, sizeof(cl_mem), &clOutputMemoryBuffer);
- if (error != CL_SUCCESS) { printf("CLERROR[%d]: %s\n", error, clewErrorString(error)); }
+ cl_int error;
+ error = clSetKernelArg(kernel, parameterIndex, sizeof(cl_mem), &clOutputMemoryBuffer);
+ if (error != CL_SUCCESS) {
+ printf("CLERROR[%d]: %s\n", error, clewErrorString(error));
+ }
}
void OpenCLDevice::COM_clEnqueueRange(cl_kernel kernel, MemoryBuffer *outputMemoryBuffer)
{
- cl_int error;
- const size_t size[] = {(size_t)outputMemoryBuffer->getWidth(), (size_t)outputMemoryBuffer->getHeight()};
-
- error = clEnqueueNDRangeKernel(this->m_queue, kernel, 2, NULL, size, 0, 0, 0, NULL);
- if (error != CL_SUCCESS) { printf("CLERROR[%d]: %s\n", error, clewErrorString(error)); }
+ cl_int error;
+ const size_t size[] = {(size_t)outputMemoryBuffer->getWidth(),
+ (size_t)outputMemoryBuffer->getHeight()};
+
+ error = clEnqueueNDRangeKernel(this->m_queue, kernel, 2, NULL, size, 0, 0, 0, NULL);
+ if (error != CL_SUCCESS) {
+ printf("CLERROR[%d]: %s\n", error, clewErrorString(error));
+ }
}
-void OpenCLDevice::COM_clEnqueueRange(cl_kernel kernel, MemoryBuffer *outputMemoryBuffer, int offsetIndex, NodeOperation *operation)
+void OpenCLDevice::COM_clEnqueueRange(cl_kernel kernel,
+ MemoryBuffer *outputMemoryBuffer,
+ int offsetIndex,
+ NodeOperation *operation)
{
- cl_int error;
- const int width = outputMemoryBuffer->getWidth();
- const int height = outputMemoryBuffer->getHeight();
- int offsetx;
- int offsety;
- int localSize = 1024;
- size_t size[2];
- cl_int2 offset;
-
- if (this->m_vendorID == NVIDIA) {
- localSize = 32;
- }
-
- bool breaked = false;
- for (offsety = 0; offsety < height && (!breaked); offsety += localSize) {
- offset.s[1] = offsety;
- if (offsety + localSize < height) {
- size[1] = localSize;
- }
- else {
- size[1] = height - offsety;
- }
-
- for (offsetx = 0; offsetx < width && (!breaked); offsetx += localSize) {
- if (offsetx + localSize < width) {
- size[0] = localSize;
- }
- else {
- size[0] = width - offsetx;
- }
- offset.s[0] = offsetx;
-
- error = clSetKernelArg(kernel, offsetIndex, sizeof(cl_int2), &offset);
- if (error != CL_SUCCESS) { printf("CLERROR[%d]: %s\n", error, clewErrorString(error)); }
- error = clEnqueueNDRangeKernel(this->m_queue, kernel, 2, NULL, size, 0, 0, 0, NULL);
- if (error != CL_SUCCESS) { printf("CLERROR[%d]: %s\n", error, clewErrorString(error)); }
- clFlush(this->m_queue);
- if (operation->isBreaked()) {
- breaked = false;
- }
- }
- }
+ cl_int error;
+ const int width = outputMemoryBuffer->getWidth();
+ const int height = outputMemoryBuffer->getHeight();
+ int offsetx;
+ int offsety;
+ int localSize = 1024;
+ size_t size[2];
+ cl_int2 offset;
+
+ if (this->m_vendorID == NVIDIA) {
+ localSize = 32;
+ }
+
+ bool breaked = false;
+ for (offsety = 0; offsety < height && (!breaked); offsety += localSize) {
+ offset.s[1] = offsety;
+ if (offsety + localSize < height) {
+ size[1] = localSize;
+ }
+ else {
+ size[1] = height - offsety;
+ }
+
+ for (offsetx = 0; offsetx < width && (!breaked); offsetx += localSize) {
+ if (offsetx + localSize < width) {
+ size[0] = localSize;
+ }
+ else {
+ size[0] = width - offsetx;
+ }
+ offset.s[0] = offsetx;
+
+ error = clSetKernelArg(kernel, offsetIndex, sizeof(cl_int2), &offset);
+ if (error != CL_SUCCESS) {
+ printf("CLERROR[%d]: %s\n", error, clewErrorString(error));
+ }
+ error = clEnqueueNDRangeKernel(this->m_queue, kernel, 2, NULL, size, 0, 0, 0, NULL);
+ if (error != CL_SUCCESS) {
+ printf("CLERROR[%d]: %s\n", error, clewErrorString(error));
+ }
+ clFlush(this->m_queue);
+ if (operation->isBreaked()) {
+ breaked = false;
+ }
+ }
+ }
}
-cl_kernel OpenCLDevice::COM_clCreateKernel(const char *kernelname, list<cl_kernel> *clKernelsToCleanUp)
+cl_kernel OpenCLDevice::COM_clCreateKernel(const char *kernelname,
+ list<cl_kernel> *clKernelsToCleanUp)
{
- cl_int error;
- cl_kernel kernel = clCreateKernel(this->m_program, kernelname, &error);
- if (error != CL_SUCCESS) { printf("CLERROR[%d]: %s\n", error, clewErrorString(error)); }
- else {
- if (clKernelsToCleanUp) clKernelsToCleanUp->push_back(kernel);
- }
- return kernel;
-
+ cl_int error;
+ cl_kernel kernel = clCreateKernel(this->m_program, kernelname, &error);
+ if (error != CL_SUCCESS) {
+ printf("CLERROR[%d]: %s\n", error, clewErrorString(error));
+ }
+ else {
+ if (clKernelsToCleanUp)
+ clKernelsToCleanUp->push_back(kernel);
+ }
+ return kernel;
}
diff --git a/source/blender/compositor/intern/COM_OpenCLDevice.h b/source/blender/compositor/intern/COM_OpenCLDevice.h
index 8cd0c31e658..7a83bda162c 100644
--- a/source/blender/compositor/intern/COM_OpenCLDevice.h
+++ b/source/blender/compositor/intern/COM_OpenCLDevice.h
@@ -33,81 +33,105 @@ using std::list;
* an instance of this class represents a single cl_device
*/
class OpenCLDevice : public Device {
-private:
- /**
- * \brief opencl context
- */
- cl_context m_context;
-
- /**
- * \brief opencl device
- */
- cl_device_id m_device;
-
- /**
- * \brief opencl program
- */
- cl_program m_program;
-
- /**
- * \brief opencl command queue
- */
- cl_command_queue m_queue;
-
- /**
- * \brief opencl vendor ID
- */
- cl_int m_vendorID;
-
-public:
- /**
- * \brief constructor with opencl device
- * \param context:
- * \param device:
- * \param program:
- * \param vendorID:
- */
- OpenCLDevice(cl_context context, cl_device_id device, cl_program program, cl_int vendorId);
-
-
- /**
- * \brief initialize the device
- * During initialization the OpenCL cl_command_queue is created
- * the command queue is stored in the field queue.
- * \see queue
- */
- bool initialize();
-
- /**
- * \brief deinitialize the device
- * During deintiialization the command queue is cleared
- */
- void deinitialize();
-
- /**
- * \brief execute a WorkPackage
- * \param work: the WorkPackage to execute
- */
- void execute(WorkPackage *work);
-
- /**
- * \brief determine an image format
- * \param memorybuffer:
- */
- static const cl_image_format *determineImageFormat(MemoryBuffer *memoryBuffer);
-
- cl_context getContext() { return this->m_context; }
-
- cl_command_queue getQueue() { return this->m_queue; }
-
- cl_mem COM_clAttachMemoryBufferToKernelParameter(cl_kernel kernel, int parameterIndex, int offsetIndex, list<cl_mem> *cleanup, MemoryBuffer **inputMemoryBuffers, SocketReader *reader);
- cl_mem COM_clAttachMemoryBufferToKernelParameter(cl_kernel kernel, int parameterIndex, int offsetIndex, list<cl_mem> *cleanup, MemoryBuffer **inputMemoryBuffers, ReadBufferOperation *reader);
- void COM_clAttachMemoryBufferOffsetToKernelParameter(cl_kernel kernel, int offsetIndex, MemoryBuffer *memoryBuffers);
- void COM_clAttachOutputMemoryBufferToKernelParameter(cl_kernel kernel, int parameterIndex, cl_mem clOutputMemoryBuffer);
- void COM_clAttachSizeToKernelParameter(cl_kernel kernel, int offsetIndex, NodeOperation *operation);
- void COM_clEnqueueRange(cl_kernel kernel, MemoryBuffer *outputMemoryBuffer);
- void COM_clEnqueueRange(cl_kernel kernel, MemoryBuffer *outputMemoryBuffer, int offsetIndex, NodeOperation *operation);
- cl_kernel COM_clCreateKernel(const char *kernelname, list<cl_kernel> *clKernelsToCleanUp);
+ private:
+ /**
+ * \brief opencl context
+ */
+ cl_context m_context;
+
+ /**
+ * \brief opencl device
+ */
+ cl_device_id m_device;
+
+ /**
+ * \brief opencl program
+ */
+ cl_program m_program;
+
+ /**
+ * \brief opencl command queue
+ */
+ cl_command_queue m_queue;
+
+ /**
+ * \brief opencl vendor ID
+ */
+ cl_int m_vendorID;
+
+ public:
+ /**
+ * \brief constructor with opencl device
+ * \param context:
+ * \param device:
+ * \param program:
+ * \param vendorID:
+ */
+ OpenCLDevice(cl_context context, cl_device_id device, cl_program program, cl_int vendorId);
+
+ /**
+ * \brief initialize the device
+ * During initialization the OpenCL cl_command_queue is created
+ * the command queue is stored in the field queue.
+ * \see queue
+ */
+ bool initialize();
+
+ /**
+ * \brief deinitialize the device
+ * During deintiialization the command queue is cleared
+ */
+ void deinitialize();
+
+ /**
+ * \brief execute a WorkPackage
+ * \param work: the WorkPackage to execute
+ */
+ void execute(WorkPackage *work);
+
+ /**
+ * \brief determine an image format
+ * \param memorybuffer:
+ */
+ static const cl_image_format *determineImageFormat(MemoryBuffer *memoryBuffer);
+
+ cl_context getContext()
+ {
+ return this->m_context;
+ }
+
+ cl_command_queue getQueue()
+ {
+ return this->m_queue;
+ }
+
+ cl_mem COM_clAttachMemoryBufferToKernelParameter(cl_kernel kernel,
+ int parameterIndex,
+ int offsetIndex,
+ list<cl_mem> *cleanup,
+ MemoryBuffer **inputMemoryBuffers,
+ SocketReader *reader);
+ cl_mem COM_clAttachMemoryBufferToKernelParameter(cl_kernel kernel,
+ int parameterIndex,
+ int offsetIndex,
+ list<cl_mem> *cleanup,
+ MemoryBuffer **inputMemoryBuffers,
+ ReadBufferOperation *reader);
+ void COM_clAttachMemoryBufferOffsetToKernelParameter(cl_kernel kernel,
+ int offsetIndex,
+ MemoryBuffer *memoryBuffers);
+ void COM_clAttachOutputMemoryBufferToKernelParameter(cl_kernel kernel,
+ int parameterIndex,
+ cl_mem clOutputMemoryBuffer);
+ void COM_clAttachSizeToKernelParameter(cl_kernel kernel,
+ int offsetIndex,
+ NodeOperation *operation);
+ void COM_clEnqueueRange(cl_kernel kernel, MemoryBuffer *outputMemoryBuffer);
+ void COM_clEnqueueRange(cl_kernel kernel,
+ MemoryBuffer *outputMemoryBuffer,
+ int offsetIndex,
+ NodeOperation *operation);
+ cl_kernel COM_clCreateKernel(const char *kernelname, list<cl_kernel> *clKernelsToCleanUp);
};
#endif
diff --git a/source/blender/compositor/intern/COM_SingleThreadedOperation.cpp b/source/blender/compositor/intern/COM_SingleThreadedOperation.cpp
index 10d9929d2cc..e6b018eeb94 100644
--- a/source/blender/compositor/intern/COM_SingleThreadedOperation.cpp
+++ b/source/blender/compositor/intern/COM_SingleThreadedOperation.cpp
@@ -20,37 +20,38 @@
SingleThreadedOperation::SingleThreadedOperation() : NodeOperation()
{
- this->m_cachedInstance = NULL;
- setComplex(true);
+ this->m_cachedInstance = NULL;
+ setComplex(true);
}
void SingleThreadedOperation::initExecution()
{
- initMutex();
+ initMutex();
}
void SingleThreadedOperation::executePixel(float output[4], int x, int y, void * /*data*/)
{
- this->m_cachedInstance->readNoCheck(output, x, y);
+ this->m_cachedInstance->readNoCheck(output, x, y);
}
void SingleThreadedOperation::deinitExecution()
{
- deinitMutex();
- if (this->m_cachedInstance) {
- delete this->m_cachedInstance;
- this->m_cachedInstance = NULL;
- }
+ deinitMutex();
+ if (this->m_cachedInstance) {
+ delete this->m_cachedInstance;
+ this->m_cachedInstance = NULL;
+ }
}
void *SingleThreadedOperation::initializeTileData(rcti *rect)
{
- if (this->m_cachedInstance) return this->m_cachedInstance;
+ if (this->m_cachedInstance)
+ return this->m_cachedInstance;
- lockMutex();
- if (this->m_cachedInstance == NULL) {
- //
- this->m_cachedInstance = createMemoryBuffer(rect);
- }
- unlockMutex();
- return this->m_cachedInstance;
+ lockMutex();
+ if (this->m_cachedInstance == NULL) {
+ //
+ this->m_cachedInstance = createMemoryBuffer(rect);
+ }
+ unlockMutex();
+ return this->m_cachedInstance;
}
diff --git a/source/blender/compositor/intern/COM_SingleThreadedOperation.h b/source/blender/compositor/intern/COM_SingleThreadedOperation.h
index bafd092a5b1..68c7f05a6c2 100644
--- a/source/blender/compositor/intern/COM_SingleThreadedOperation.h
+++ b/source/blender/compositor/intern/COM_SingleThreadedOperation.h
@@ -21,36 +21,40 @@
#include "COM_NodeOperation.h"
class SingleThreadedOperation : public NodeOperation {
-private:
- MemoryBuffer *m_cachedInstance;
+ private:
+ MemoryBuffer *m_cachedInstance;
-protected:
- inline bool isCached() {
- return this->m_cachedInstance != NULL;
- }
+ protected:
+ inline bool isCached()
+ {
+ return this->m_cachedInstance != NULL;
+ }
-public:
- SingleThreadedOperation();
+ public:
+ SingleThreadedOperation();
- /**
- * the inner loop of this program
- */
- void executePixel(float output[4], int x, int y, void *data);
+ /**
+ * the inner loop of this program
+ */
+ void executePixel(float output[4], int x, int y, void *data);
- /**
- * Initialize the execution
- */
- void initExecution();
+ /**
+ * Initialize the execution
+ */
+ void initExecution();
- /**
- * Deinitialize the execution
- */
- void deinitExecution();
+ /**
+ * Deinitialize the execution
+ */
+ void deinitExecution();
- void *initializeTileData(rcti *rect);
+ void *initializeTileData(rcti *rect);
- virtual MemoryBuffer *createMemoryBuffer(rcti *rect) = 0;
+ virtual MemoryBuffer *createMemoryBuffer(rcti *rect) = 0;
- int isSingleThreaded() { return true; }
+ int isSingleThreaded()
+ {
+ return true;
+ }
};
#endif
diff --git a/source/blender/compositor/intern/COM_SocketReader.h b/source/blender/compositor/intern/COM_SocketReader.h
index dfab1084dae..82bebd5e7b9 100644
--- a/source/blender/compositor/intern/COM_SocketReader.h
+++ b/source/blender/compositor/intern/COM_SocketReader.h
@@ -22,13 +22,13 @@
#include "COM_defines.h"
#ifdef WITH_CXX_GUARDEDALLOC
-#include "MEM_guardedalloc.h"
+# include "MEM_guardedalloc.h"
#endif
typedef enum PixelSampler {
- COM_PS_NEAREST = 0,
- COM_PS_BILINEAR = 1,
- COM_PS_BICUBIC = 2,
+ COM_PS_NEAREST = 0,
+ COM_PS_BILINEAR = 1,
+ COM_PS_BICUBIC = 2,
} PixelSampler;
class MemoryBuffer;
@@ -38,82 +38,104 @@ class MemoryBuffer;
* \ingroup Execution
*/
class SocketReader {
-private:
-protected:
- /**
- * \brief Holds the width of the output of this operation.
- */
- unsigned int m_width;
-
- /**
- * \brief Holds the height of the output of this operation.
- */
- unsigned int m_height;
-
-
- /**
- * \brief calculate a single pixel
- * \note this method is called for non-complex
- * \param result: is a float[4] array to store the result
- * \param x: the x-coordinate of the pixel to calculate in image space
- * \param y: the y-coordinate of the pixel to calculate in image space
- * \param inputBuffers: chunks that can be read by their ReadBufferOperation.
- */
- virtual void executePixelSampled(float /*output*/[4],
- float /*x*/,
- float /*y*/,
- PixelSampler /*sampler*/) { }
-
- /**
- * \brief calculate a single pixel
- * \note this method is called for complex
- * \param result: is a float[4] array to store the result
- * \param x: the x-coordinate of the pixel to calculate in image space
- * \param y: the y-coordinate of the pixel to calculate in image space
- * \param inputBuffers: chunks that can be read by their ReadBufferOperation.
- * \param chunkData: chunk specific data a during execution time.
- */
- virtual void executePixel(float output[4], int x, int y, void * /*chunkData*/) {
- executePixelSampled(output, x, y, COM_PS_NEAREST);
- }
-
- /**
- * \brief calculate a single pixel using an EWA filter
- * \note this method is called for complex
- * \param result: is a float[4] array to store the result
- * \param x: the x-coordinate of the pixel to calculate in image space
- * \param y: the y-coordinate of the pixel to calculate in image space
- * \param dx:
- * \param dy:
- * \param inputBuffers: chunks that can be read by their ReadBufferOperation.
- */
- virtual void executePixelFiltered(float /*output*/[4],
- float /*x*/, float /*y*/,
- float /*dx*/[2], float /*dy*/[2]) {}
-
-public:
- inline void readSampled(float result[4], float x, float y, PixelSampler sampler) {
- executePixelSampled(result, x, y, sampler);
- }
- inline void read(float result[4], int x, int y, void *chunkData) {
- executePixel(result, x, y, chunkData);
- }
- inline void readFiltered(float result[4], float x, float y, float dx[2], float dy[2]) {
- executePixelFiltered(result, x, y, dx, dy);
- }
-
- virtual void *initializeTileData(rcti * /*rect*/) { return 0; }
- virtual void deinitializeTileData(rcti * /*rect*/, void * /*data*/) {}
-
- virtual ~SocketReader() {}
-
- virtual MemoryBuffer *getInputMemoryBuffer(MemoryBuffer ** /*memoryBuffers*/) { return 0; }
-
- inline unsigned int getWidth() const { return this->m_width; }
- inline unsigned int getHeight() const { return this->m_height; }
+ private:
+ protected:
+ /**
+ * \brief Holds the width of the output of this operation.
+ */
+ unsigned int m_width;
+
+ /**
+ * \brief Holds the height of the output of this operation.
+ */
+ unsigned int m_height;
+
+ /**
+ * \brief calculate a single pixel
+ * \note this method is called for non-complex
+ * \param result: is a float[4] array to store the result
+ * \param x: the x-coordinate of the pixel to calculate in image space
+ * \param y: the y-coordinate of the pixel to calculate in image space
+ * \param inputBuffers: chunks that can be read by their ReadBufferOperation.
+ */
+ virtual void executePixelSampled(float /*output*/[4],
+ float /*x*/,
+ float /*y*/,
+ PixelSampler /*sampler*/)
+ {
+ }
+
+ /**
+ * \brief calculate a single pixel
+ * \note this method is called for complex
+ * \param result: is a float[4] array to store the result
+ * \param x: the x-coordinate of the pixel to calculate in image space
+ * \param y: the y-coordinate of the pixel to calculate in image space
+ * \param inputBuffers: chunks that can be read by their ReadBufferOperation.
+ * \param chunkData: chunk specific data a during execution time.
+ */
+ virtual void executePixel(float output[4], int x, int y, void * /*chunkData*/)
+ {
+ executePixelSampled(output, x, y, COM_PS_NEAREST);
+ }
+
+ /**
+ * \brief calculate a single pixel using an EWA filter
+ * \note this method is called for complex
+ * \param result: is a float[4] array to store the result
+ * \param x: the x-coordinate of the pixel to calculate in image space
+ * \param y: the y-coordinate of the pixel to calculate in image space
+ * \param dx:
+ * \param dy:
+ * \param inputBuffers: chunks that can be read by their ReadBufferOperation.
+ */
+ virtual void executePixelFiltered(
+ float /*output*/[4], float /*x*/, float /*y*/, float /*dx*/[2], float /*dy*/[2])
+ {
+ }
+
+ public:
+ inline void readSampled(float result[4], float x, float y, PixelSampler sampler)
+ {
+ executePixelSampled(result, x, y, sampler);
+ }
+ inline void read(float result[4], int x, int y, void *chunkData)
+ {
+ executePixel(result, x, y, chunkData);
+ }
+ inline void readFiltered(float result[4], float x, float y, float dx[2], float dy[2])
+ {
+ executePixelFiltered(result, x, y, dx, dy);
+ }
+
+ virtual void *initializeTileData(rcti * /*rect*/)
+ {
+ return 0;
+ }
+ virtual void deinitializeTileData(rcti * /*rect*/, void * /*data*/)
+ {
+ }
+
+ virtual ~SocketReader()
+ {
+ }
+
+ virtual MemoryBuffer *getInputMemoryBuffer(MemoryBuffer ** /*memoryBuffers*/)
+ {
+ return 0;
+ }
+
+ inline unsigned int getWidth() const
+ {
+ return this->m_width;
+ }
+ inline unsigned int getHeight() const
+ {
+ return this->m_height;
+ }
#ifdef WITH_CXX_GUARDEDALLOC
- MEM_CXX_CLASS_ALLOC_FUNCS("COM:SocketReader")
+ MEM_CXX_CLASS_ALLOC_FUNCS("COM:SocketReader")
#endif
};
diff --git a/source/blender/compositor/intern/COM_WorkPackage.cpp b/source/blender/compositor/intern/COM_WorkPackage.cpp
index 9612ba01e2a..795f8d88d50 100644
--- a/source/blender/compositor/intern/COM_WorkPackage.cpp
+++ b/source/blender/compositor/intern/COM_WorkPackage.cpp
@@ -20,6 +20,6 @@
WorkPackage::WorkPackage(ExecutionGroup *group, unsigned int chunkNumber)
{
- this->m_executionGroup = group;
- this->m_chunkNumber = chunkNumber;
+ this->m_executionGroup = group;
+ this->m_chunkNumber = chunkNumber;
}
diff --git a/source/blender/compositor/intern/COM_WorkPackage.h b/source/blender/compositor/intern/COM_WorkPackage.h
index fc2a4167952..2a0e47301f5 100644
--- a/source/blender/compositor/intern/COM_WorkPackage.h
+++ b/source/blender/compositor/intern/COM_WorkPackage.h
@@ -28,36 +28,43 @@ class ExecutionGroup;
* \see WorkScheduler
*/
class WorkPackage {
-private:
- /**
- * \brief executionGroup with the operations-setup to be evaluated
- */
- ExecutionGroup *m_executionGroup;
+ private:
+ /**
+ * \brief executionGroup with the operations-setup to be evaluated
+ */
+ ExecutionGroup *m_executionGroup;
- /**
- * \brief number of the chunk to be executed
- */
- unsigned int m_chunkNumber;
-public:
- /**
- * constructor
- * \param group: the ExecutionGroup
- * \param chunkNumber: the number of the chunk
- */
- WorkPackage(ExecutionGroup *group, unsigned int chunkNumber);
+ /**
+ * \brief number of the chunk to be executed
+ */
+ unsigned int m_chunkNumber;
- /**
- * \brief get the ExecutionGroup
- */
- ExecutionGroup *getExecutionGroup() const { return this->m_executionGroup; }
+ public:
+ /**
+ * constructor
+ * \param group: the ExecutionGroup
+ * \param chunkNumber: the number of the chunk
+ */
+ WorkPackage(ExecutionGroup *group, unsigned int chunkNumber);
- /**
- * \brief get the number of the chunk
- */
- unsigned int getChunkNumber() const { return this->m_chunkNumber; }
+ /**
+ * \brief get the ExecutionGroup
+ */
+ ExecutionGroup *getExecutionGroup() const
+ {
+ return this->m_executionGroup;
+ }
+
+ /**
+ * \brief get the number of the chunk
+ */
+ unsigned int getChunkNumber() const
+ {
+ return this->m_chunkNumber;
+ }
#ifdef WITH_CXX_GUARDEDALLOC
- MEM_CXX_CLASS_ALLOC_FUNCS("COM:WorkPackage")
+ MEM_CXX_CLASS_ALLOC_FUNCS("COM:WorkPackage")
#endif
};
diff --git a/source/blender/compositor/intern/COM_WorkScheduler.cpp b/source/blender/compositor/intern/COM_WorkScheduler.cpp
index d5efe849f1b..e03a0aa6269 100644
--- a/source/blender/compositor/intern/COM_WorkScheduler.cpp
+++ b/source/blender/compositor/intern/COM_WorkScheduler.cpp
@@ -35,18 +35,17 @@
#include "BKE_global.h"
#if COM_CURRENT_THREADING_MODEL == COM_TM_NOTHREAD
-# ifndef DEBUG /* test this so we dont get warnings in debug builds */
+# ifndef DEBUG /* test this so we dont get warnings in debug builds */
# warning COM_CURRENT_THREADING_MODEL COM_TM_NOTHREAD is activated. Use only for debugging.
# endif
#elif COM_CURRENT_THREADING_MODEL == COM_TM_QUEUE
- /* do nothing - default */
+/* do nothing - default */
#else
# error COM_CURRENT_THREADING_MODEL No threading model selected
#endif
-
/// \brief list of all CPUDevices. for every hardware thread an instance of CPUDevice is created
-static vector<CPUDevice*> g_cpudevices;
+static vector<CPUDevice *> g_cpudevices;
static ThreadLocal(CPUDevice *) g_thread_device;
#if COM_CURRENT_THREADING_MODEL == COM_TM_QUEUE
@@ -56,7 +55,7 @@ static bool g_cpuInitialized = false;
/// \brief all scheduled work for the cpu
static ThreadQueue *g_cpuqueue;
static ThreadQueue *g_gpuqueue;
-#ifdef COM_OPENCL_ENABLED
+# ifdef COM_OPENCL_ENABLED
static cl_context g_context;
static cl_program g_program;
/// \brief list of all OpenCLDevices. for every OpenCL GPU device an instance of OpenCLDevice is created
@@ -64,134 +63,132 @@ static vector<OpenCLDevice *> g_gpudevices;
/// \brief list of all thread for every GPUDevice in cpudevices a thread exists
static ListBase g_gputhreads;
/// \brief all scheduled work for the gpu
-#ifdef COM_OPENCL_ENABLED
+# ifdef COM_OPENCL_ENABLED
static bool g_openclActive = false;
static bool g_openclInitialized = false;
-#endif
-#endif
+# endif
+# endif
#endif
#if COM_CURRENT_THREADING_MODEL == COM_TM_QUEUE
void *WorkScheduler::thread_execute_cpu(void *data)
{
- CPUDevice *device = (CPUDevice *)data;
- WorkPackage *work;
- BLI_thread_local_set(g_thread_device, device);
- while ((work = (WorkPackage *)BLI_thread_queue_pop(g_cpuqueue))) {
- device->execute(work);
- delete work;
- }
-
- return NULL;
+ CPUDevice *device = (CPUDevice *)data;
+ WorkPackage *work;
+ BLI_thread_local_set(g_thread_device, device);
+ while ((work = (WorkPackage *)BLI_thread_queue_pop(g_cpuqueue))) {
+ device->execute(work);
+ delete work;
+ }
+
+ return NULL;
}
void *WorkScheduler::thread_execute_gpu(void *data)
{
- Device *device = (Device *)data;
- WorkPackage *work;
+ Device *device = (Device *)data;
+ WorkPackage *work;
- while ((work = (WorkPackage *)BLI_thread_queue_pop(g_gpuqueue))) {
- device->execute(work);
- delete work;
- }
+ while ((work = (WorkPackage *)BLI_thread_queue_pop(g_gpuqueue))) {
+ device->execute(work);
+ delete work;
+ }
- return NULL;
+ return NULL;
}
#endif
-
-
void WorkScheduler::schedule(ExecutionGroup *group, int chunkNumber)
{
- WorkPackage *package = new WorkPackage(group, chunkNumber);
+ WorkPackage *package = new WorkPackage(group, chunkNumber);
#if COM_CURRENT_THREADING_MODEL == COM_TM_NOTHREAD
- CPUDevice device(0);
- device.execute(package);
- delete package;
+ CPUDevice device(0);
+ device.execute(package);
+ delete package;
#elif COM_CURRENT_THREADING_MODEL == COM_TM_QUEUE
-#ifdef COM_OPENCL_ENABLED
- if (group->isOpenCL() && g_openclActive) {
- BLI_thread_queue_push(g_gpuqueue, package);
- }
- else {
- BLI_thread_queue_push(g_cpuqueue, package);
- }
-#else
- BLI_thread_queue_push(g_cpuqueue, package);
-#endif
+# ifdef COM_OPENCL_ENABLED
+ if (group->isOpenCL() && g_openclActive) {
+ BLI_thread_queue_push(g_gpuqueue, package);
+ }
+ else {
+ BLI_thread_queue_push(g_cpuqueue, package);
+ }
+# else
+ BLI_thread_queue_push(g_cpuqueue, package);
+# endif
#endif
}
void WorkScheduler::start(CompositorContext &context)
{
#if COM_CURRENT_THREADING_MODEL == COM_TM_QUEUE
- unsigned int index;
- g_cpuqueue = BLI_thread_queue_init();
- BLI_threadpool_init(&g_cputhreads, thread_execute_cpu, g_cpudevices.size());
- for (index = 0; index < g_cpudevices.size(); index++) {
- Device *device = g_cpudevices[index];
- BLI_threadpool_insert(&g_cputhreads, device);
- }
-#ifdef COM_OPENCL_ENABLED
- if (context.getHasActiveOpenCLDevices()) {
- g_gpuqueue = BLI_thread_queue_init();
- BLI_threadpool_init(&g_gputhreads, thread_execute_gpu, g_gpudevices.size());
- for (index = 0; index < g_gpudevices.size(); index++) {
- Device *device = g_gpudevices[index];
- BLI_threadpool_insert(&g_gputhreads, device);
- }
- g_openclActive = true;
- }
- else {
- g_openclActive = false;
- }
-#endif
+ unsigned int index;
+ g_cpuqueue = BLI_thread_queue_init();
+ BLI_threadpool_init(&g_cputhreads, thread_execute_cpu, g_cpudevices.size());
+ for (index = 0; index < g_cpudevices.size(); index++) {
+ Device *device = g_cpudevices[index];
+ BLI_threadpool_insert(&g_cputhreads, device);
+ }
+# ifdef COM_OPENCL_ENABLED
+ if (context.getHasActiveOpenCLDevices()) {
+ g_gpuqueue = BLI_thread_queue_init();
+ BLI_threadpool_init(&g_gputhreads, thread_execute_gpu, g_gpudevices.size());
+ for (index = 0; index < g_gpudevices.size(); index++) {
+ Device *device = g_gpudevices[index];
+ BLI_threadpool_insert(&g_gputhreads, device);
+ }
+ g_openclActive = true;
+ }
+ else {
+ g_openclActive = false;
+ }
+# endif
#endif
}
void WorkScheduler::finish()
{
#if COM_CURRENT_THREADING_MODEL == COM_TM_QUEUE
-#ifdef COM_OPENCL_ENABLED
- if (g_openclActive) {
- BLI_thread_queue_wait_finish(g_gpuqueue);
- BLI_thread_queue_wait_finish(g_cpuqueue);
- }
- else {
- BLI_thread_queue_wait_finish(g_cpuqueue);
- }
-#else
- BLI_thread_queue_wait_finish(cpuqueue);
-#endif
+# ifdef COM_OPENCL_ENABLED
+ if (g_openclActive) {
+ BLI_thread_queue_wait_finish(g_gpuqueue);
+ BLI_thread_queue_wait_finish(g_cpuqueue);
+ }
+ else {
+ BLI_thread_queue_wait_finish(g_cpuqueue);
+ }
+# else
+ BLI_thread_queue_wait_finish(cpuqueue);
+# endif
#endif
}
void WorkScheduler::stop()
{
#if COM_CURRENT_THREADING_MODEL == COM_TM_QUEUE
- BLI_thread_queue_nowait(g_cpuqueue);
- BLI_threadpool_end(&g_cputhreads);
- BLI_thread_queue_free(g_cpuqueue);
- g_cpuqueue = NULL;
-#ifdef COM_OPENCL_ENABLED
- if (g_openclActive) {
- BLI_thread_queue_nowait(g_gpuqueue);
- BLI_threadpool_end(&g_gputhreads);
- BLI_thread_queue_free(g_gpuqueue);
- g_gpuqueue = NULL;
- }
-#endif
+ BLI_thread_queue_nowait(g_cpuqueue);
+ BLI_threadpool_end(&g_cputhreads);
+ BLI_thread_queue_free(g_cpuqueue);
+ g_cpuqueue = NULL;
+# ifdef COM_OPENCL_ENABLED
+ if (g_openclActive) {
+ BLI_thread_queue_nowait(g_gpuqueue);
+ BLI_threadpool_end(&g_gputhreads);
+ BLI_thread_queue_free(g_gpuqueue);
+ g_gpuqueue = NULL;
+ }
+# endif
#endif
}
bool WorkScheduler::hasGPUDevices()
{
#if COM_CURRENT_THREADING_MODEL == COM_TM_QUEUE
-#ifdef COM_OPENCL_ENABLED
- return g_gpudevices.size() > 0;
-#else
- return 0;
-#endif
+# ifdef COM_OPENCL_ENABLED
+ return g_gpudevices.size() > 0;
+# else
+ return 0;
+# endif
#else
- return 0;
+ return 0;
#endif
}
@@ -201,153 +198,172 @@ static void CL_CALLBACK clContextError(const char *errinfo,
size_t /*cb*/,
void * /*user_data*/)
{
- printf("OPENCL error: %s\n", errinfo);
+ printf("OPENCL error: %s\n", errinfo);
}
#endif
void WorkScheduler::initialize(bool use_opencl, int num_cpu_threads)
{
#if COM_CURRENT_THREADING_MODEL == COM_TM_QUEUE
- /* deinitialize if number of threads doesn't match */
- if (g_cpudevices.size() != num_cpu_threads) {
- Device *device;
-
- while (g_cpudevices.size() > 0) {
- device = g_cpudevices.back();
- g_cpudevices.pop_back();
- device->deinitialize();
- delete device;
- }
- if (g_cpuInitialized) {
- BLI_thread_local_delete(g_thread_device);
- }
- g_cpuInitialized = false;
- }
-
- /* initialize CPU threads */
- if (!g_cpuInitialized) {
- for (int index = 0; index < num_cpu_threads; index++) {
- CPUDevice *device = new CPUDevice(index);
- device->initialize();
- g_cpudevices.push_back(device);
- }
- BLI_thread_local_create(g_thread_device);
- g_cpuInitialized = true;
- }
-
-#ifdef COM_OPENCL_ENABLED
- /* deinitialize OpenCL GPU's */
- if (use_opencl && !g_openclInitialized) {
- g_context = NULL;
- g_program = NULL;
-
- if (clewInit() != CLEW_SUCCESS) /* this will check for errors and skip if already initialized */
- return;
-
- if (clCreateContextFromType) {
- cl_uint numberOfPlatforms = 0;
- cl_int error;
- error = clGetPlatformIDs(0, 0, &numberOfPlatforms);
- if (error == -1001) { } /* GPU not supported */
- else if (error != CL_SUCCESS) { printf("CLERROR[%d]: %s\n", error, clewErrorString(error)); }
- if (G.f & G_DEBUG) printf("%u number of platforms\n", numberOfPlatforms);
- cl_platform_id *platforms = (cl_platform_id *)MEM_mallocN(sizeof(cl_platform_id) * numberOfPlatforms, __func__);
- error = clGetPlatformIDs(numberOfPlatforms, platforms, 0);
- unsigned int indexPlatform;
- for (indexPlatform = 0; indexPlatform < numberOfPlatforms; indexPlatform++) {
- cl_platform_id platform = platforms[indexPlatform];
- cl_uint numberOfDevices = 0;
- clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, 0, 0, &numberOfDevices);
- if (numberOfDevices <= 0)
- continue;
-
- cl_device_id *cldevices = (cl_device_id *)MEM_mallocN(sizeof(cl_device_id) * numberOfDevices, __func__);
- clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, numberOfDevices, cldevices, 0);
-
- g_context = clCreateContext(NULL, numberOfDevices, cldevices, clContextError, NULL, &error);
- if (error != CL_SUCCESS) { printf("CLERROR[%d]: %s\n", error, clewErrorString(error)); }
- const char *cl_str[2] = {datatoc_COM_OpenCLKernels_cl, NULL};
- g_program = clCreateProgramWithSource(g_context, 1, cl_str, 0, &error);
- error = clBuildProgram(g_program, numberOfDevices, cldevices, 0, 0, 0);
- if (error != CL_SUCCESS) {
- cl_int error2;
- size_t ret_val_size = 0;
- printf("CLERROR[%d]: %s\n", error, clewErrorString(error));
- error2 = clGetProgramBuildInfo(g_program, cldevices[0], CL_PROGRAM_BUILD_LOG, 0, NULL, &ret_val_size);
- if (error2 != CL_SUCCESS) { printf("CLERROR[%d]: %s\n", error, clewErrorString(error)); }
- char *build_log = (char *)MEM_mallocN(sizeof(char) * ret_val_size + 1, __func__);
- error2 = clGetProgramBuildInfo(g_program, cldevices[0], CL_PROGRAM_BUILD_LOG, ret_val_size, build_log, NULL);
- if (error2 != CL_SUCCESS) { printf("CLERROR[%d]: %s\n", error, clewErrorString(error)); }
- build_log[ret_val_size] = '\0';
- printf("%s", build_log);
- MEM_freeN(build_log);
- }
- else {
- unsigned int indexDevices;
- for (indexDevices = 0; indexDevices < numberOfDevices; indexDevices++) {
- cl_device_id device = cldevices[indexDevices];
- cl_int vendorID = 0;
- cl_int error2 = clGetDeviceInfo(device, CL_DEVICE_VENDOR_ID, sizeof(cl_int), &vendorID, NULL);
- if (error2 != CL_SUCCESS) { printf("CLERROR[%d]: %s\n", error2, clewErrorString(error2)); }
- OpenCLDevice *clDevice = new OpenCLDevice(g_context, device, g_program, vendorID);
- clDevice->initialize();
- g_gpudevices.push_back(clDevice);
- }
- }
- MEM_freeN(cldevices);
- }
- MEM_freeN(platforms);
- }
-
- g_openclInitialized = true;
- }
-#endif
+ /* deinitialize if number of threads doesn't match */
+ if (g_cpudevices.size() != num_cpu_threads) {
+ Device *device;
+
+ while (g_cpudevices.size() > 0) {
+ device = g_cpudevices.back();
+ g_cpudevices.pop_back();
+ device->deinitialize();
+ delete device;
+ }
+ if (g_cpuInitialized) {
+ BLI_thread_local_delete(g_thread_device);
+ }
+ g_cpuInitialized = false;
+ }
+
+ /* initialize CPU threads */
+ if (!g_cpuInitialized) {
+ for (int index = 0; index < num_cpu_threads; index++) {
+ CPUDevice *device = new CPUDevice(index);
+ device->initialize();
+ g_cpudevices.push_back(device);
+ }
+ BLI_thread_local_create(g_thread_device);
+ g_cpuInitialized = true;
+ }
+
+# ifdef COM_OPENCL_ENABLED
+ /* deinitialize OpenCL GPU's */
+ if (use_opencl && !g_openclInitialized) {
+ g_context = NULL;
+ g_program = NULL;
+
+ if (clewInit() !=
+ CLEW_SUCCESS) /* this will check for errors and skip if already initialized */
+ return;
+
+ if (clCreateContextFromType) {
+ cl_uint numberOfPlatforms = 0;
+ cl_int error;
+ error = clGetPlatformIDs(0, 0, &numberOfPlatforms);
+ if (error == -1001) {
+ } /* GPU not supported */
+ else if (error != CL_SUCCESS) {
+ printf("CLERROR[%d]: %s\n", error, clewErrorString(error));
+ }
+ if (G.f & G_DEBUG)
+ printf("%u number of platforms\n", numberOfPlatforms);
+ cl_platform_id *platforms = (cl_platform_id *)MEM_mallocN(
+ sizeof(cl_platform_id) * numberOfPlatforms, __func__);
+ error = clGetPlatformIDs(numberOfPlatforms, platforms, 0);
+ unsigned int indexPlatform;
+ for (indexPlatform = 0; indexPlatform < numberOfPlatforms; indexPlatform++) {
+ cl_platform_id platform = platforms[indexPlatform];
+ cl_uint numberOfDevices = 0;
+ clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, 0, 0, &numberOfDevices);
+ if (numberOfDevices <= 0)
+ continue;
+
+ cl_device_id *cldevices = (cl_device_id *)MEM_mallocN(
+ sizeof(cl_device_id) * numberOfDevices, __func__);
+ clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, numberOfDevices, cldevices, 0);
+
+ g_context = clCreateContext(
+ NULL, numberOfDevices, cldevices, clContextError, NULL, &error);
+ if (error != CL_SUCCESS) {
+ printf("CLERROR[%d]: %s\n", error, clewErrorString(error));
+ }
+ const char *cl_str[2] = {datatoc_COM_OpenCLKernels_cl, NULL};
+ g_program = clCreateProgramWithSource(g_context, 1, cl_str, 0, &error);
+ error = clBuildProgram(g_program, numberOfDevices, cldevices, 0, 0, 0);
+ if (error != CL_SUCCESS) {
+ cl_int error2;
+ size_t ret_val_size = 0;
+ printf("CLERROR[%d]: %s\n", error, clewErrorString(error));
+ error2 = clGetProgramBuildInfo(
+ g_program, cldevices[0], CL_PROGRAM_BUILD_LOG, 0, NULL, &ret_val_size);
+ if (error2 != CL_SUCCESS) {
+ printf("CLERROR[%d]: %s\n", error, clewErrorString(error));
+ }
+ char *build_log = (char *)MEM_mallocN(sizeof(char) * ret_val_size + 1, __func__);
+ error2 = clGetProgramBuildInfo(
+ g_program, cldevices[0], CL_PROGRAM_BUILD_LOG, ret_val_size, build_log, NULL);
+ if (error2 != CL_SUCCESS) {
+ printf("CLERROR[%d]: %s\n", error, clewErrorString(error));
+ }
+ build_log[ret_val_size] = '\0';
+ printf("%s", build_log);
+ MEM_freeN(build_log);
+ }
+ else {
+ unsigned int indexDevices;
+ for (indexDevices = 0; indexDevices < numberOfDevices; indexDevices++) {
+ cl_device_id device = cldevices[indexDevices];
+ cl_int vendorID = 0;
+ cl_int error2 = clGetDeviceInfo(
+ device, CL_DEVICE_VENDOR_ID, sizeof(cl_int), &vendorID, NULL);
+ if (error2 != CL_SUCCESS) {
+ printf("CLERROR[%d]: %s\n", error2, clewErrorString(error2));
+ }
+ OpenCLDevice *clDevice = new OpenCLDevice(g_context, device, g_program, vendorID);
+ clDevice->initialize();
+ g_gpudevices.push_back(clDevice);
+ }
+ }
+ MEM_freeN(cldevices);
+ }
+ MEM_freeN(platforms);
+ }
+
+ g_openclInitialized = true;
+ }
+# endif
#endif
}
void WorkScheduler::deinitialize()
{
#if COM_CURRENT_THREADING_MODEL == COM_TM_QUEUE
- /* deinitialize CPU threads */
- if (g_cpuInitialized) {
- Device *device;
- while (g_cpudevices.size() > 0) {
- device = g_cpudevices.back();
- g_cpudevices.pop_back();
- device->deinitialize();
- delete device;
- }
- BLI_thread_local_delete(g_thread_device);
- g_cpuInitialized = false;
- }
-
-#ifdef COM_OPENCL_ENABLED
- /* deinitialize OpenCL GPU's */
- if (g_openclInitialized) {
- Device *device;
- while (g_gpudevices.size() > 0) {
- device = g_gpudevices.back();
- g_gpudevices.pop_back();
- device->deinitialize();
- delete device;
- }
- if (g_program) {
- clReleaseProgram(g_program);
- g_program = NULL;
- }
- if (g_context) {
- clReleaseContext(g_context);
- g_context = NULL;
- }
-
- g_openclInitialized = false;
- }
-#endif
+ /* deinitialize CPU threads */
+ if (g_cpuInitialized) {
+ Device *device;
+ while (g_cpudevices.size() > 0) {
+ device = g_cpudevices.back();
+ g_cpudevices.pop_back();
+ device->deinitialize();
+ delete device;
+ }
+ BLI_thread_local_delete(g_thread_device);
+ g_cpuInitialized = false;
+ }
+
+# ifdef COM_OPENCL_ENABLED
+ /* deinitialize OpenCL GPU's */
+ if (g_openclInitialized) {
+ Device *device;
+ while (g_gpudevices.size() > 0) {
+ device = g_gpudevices.back();
+ g_gpudevices.pop_back();
+ device->deinitialize();
+ delete device;
+ }
+ if (g_program) {
+ clReleaseProgram(g_program);
+ g_program = NULL;
+ }
+ if (g_context) {
+ clReleaseContext(g_context);
+ g_context = NULL;
+ }
+
+ g_openclInitialized = false;
+ }
+# endif
#endif
}
int WorkScheduler::current_thread_id()
{
- CPUDevice *device = (CPUDevice *)BLI_thread_local_get(g_thread_device);
- return device->thread_id();
+ CPUDevice *device = (CPUDevice *)BLI_thread_local_get(g_thread_device);
+ return device->thread_id();
}
diff --git a/source/blender/compositor/intern/COM_WorkScheduler.h b/source/blender/compositor/intern/COM_WorkScheduler.h
index adac501148e..2b523272123 100644
--- a/source/blender/compositor/intern/COM_WorkScheduler.h
+++ b/source/blender/compositor/intern/COM_WorkScheduler.h
@@ -21,7 +21,7 @@
#include "COM_ExecutionGroup.h"
extern "C" {
-# include "BLI_threads.h"
+#include "BLI_threads.h"
}
#include "COM_WorkPackage.h"
#include "COM_defines.h"
@@ -33,86 +33,86 @@ extern "C" {
class WorkScheduler {
#if COM_CURRENT_THREADING_MODEL == COM_TM_QUEUE
- /**
- * \brief are we being stopped.
- */
- static bool isStopping();
+ /**
+ * \brief are we being stopped.
+ */
+ static bool isStopping();
- /**
- * \brief main thread loop for cpudevices
- * inside this loop new work is queried and being executed
- */
- static void *thread_execute_cpu(void *data);
+ /**
+ * \brief main thread loop for cpudevices
+ * inside this loop new work is queried and being executed
+ */
+ static void *thread_execute_cpu(void *data);
- /**
- * \brief main thread loop for gpudevices
- * inside this loop new work is queried and being executed
- */
- static void *thread_execute_gpu(void *data);
+ /**
+ * \brief main thread loop for gpudevices
+ * inside this loop new work is queried and being executed
+ */
+ static void *thread_execute_gpu(void *data);
#endif
-public:
- /**
- * \brief schedule a chunk of a group to be calculated.
- * An execution group schedules a chunk in the WorkScheduler
- * when ExecutionGroup.isOpenCL is set the work will be handled by a OpenCLDevice
- * otherwise the work is scheduled for an CPUDevice
- * \see ExecutionGroup.execute
- * \param group: the execution group
- * \param chunkNumber: the number of the chunk in the group to be executed
- */
- static void schedule(ExecutionGroup *group, int chunkNumber);
+ public:
+ /**
+ * \brief schedule a chunk of a group to be calculated.
+ * An execution group schedules a chunk in the WorkScheduler
+ * when ExecutionGroup.isOpenCL is set the work will be handled by a OpenCLDevice
+ * otherwise the work is scheduled for an CPUDevice
+ * \see ExecutionGroup.execute
+ * \param group: the execution group
+ * \param chunkNumber: the number of the chunk in the group to be executed
+ */
+ static void schedule(ExecutionGroup *group, int chunkNumber);
- /**
- * \brief initialize the WorkScheduler
- *
- * during initialization the mutexes are initialized.
- * there are two mutexes (for every device type one)
- * After mutex initialization the system is queried in order to count the number of CPUDevices and GPUDevices to be created.
- * For every hardware thread a CPUDevice and for every OpenCL GPU device a OpenCLDevice is created.
- * these devices are stored in a separate list (cpudevices & gpudevices)
- *
- * This function can be called multiple times to lazily initialize OpenCL.
- */
- static void initialize(bool use_opencl, int num_cpu_threads);
+ /**
+ * \brief initialize the WorkScheduler
+ *
+ * during initialization the mutexes are initialized.
+ * there are two mutexes (for every device type one)
+ * After mutex initialization the system is queried in order to count the number of CPUDevices and GPUDevices to be created.
+ * For every hardware thread a CPUDevice and for every OpenCL GPU device a OpenCLDevice is created.
+ * these devices are stored in a separate list (cpudevices & gpudevices)
+ *
+ * This function can be called multiple times to lazily initialize OpenCL.
+ */
+ static void initialize(bool use_opencl, int num_cpu_threads);
- /**
- * \brief deinitialize the WorkScheduler
- * free all allocated resources
- */
- static void deinitialize();
+ /**
+ * \brief deinitialize the WorkScheduler
+ * free all allocated resources
+ */
+ static void deinitialize();
- /**
- * \brief Start the execution
- * this methods will start the WorkScheduler. Inside this method all threads are initialized.
- * for every device a thread is created.
- * \see initialize Initialization and query of the number of devices
- */
- static void start(CompositorContext &context);
+ /**
+ * \brief Start the execution
+ * this methods will start the WorkScheduler. Inside this method all threads are initialized.
+ * for every device a thread is created.
+ * \see initialize Initialization and query of the number of devices
+ */
+ static void start(CompositorContext &context);
- /**
- * \brief stop the execution
- * All created thread by the start method are destroyed.
- * \see start
- */
- static void stop();
+ /**
+ * \brief stop the execution
+ * All created thread by the start method are destroyed.
+ * \see start
+ */
+ static void stop();
- /**
- * \brief wait for all work to be completed.
- */
- static void finish();
+ /**
+ * \brief wait for all work to be completed.
+ */
+ static void finish();
- /**
- * \brief Are there OpenCL capable GPU devices initialized?
- * the result of this method is stored in the CompositorContext
- * A node can generate a different operation tree when OpenCLDevices exists.
- * \see CompositorContext.getHasActiveOpenCLDevices
- */
- static bool hasGPUDevices();
+ /**
+ * \brief Are there OpenCL capable GPU devices initialized?
+ * the result of this method is stored in the CompositorContext
+ * A node can generate a different operation tree when OpenCLDevices exists.
+ * \see CompositorContext.getHasActiveOpenCLDevices
+ */
+ static bool hasGPUDevices();
- static int current_thread_id();
+ static int current_thread_id();
#ifdef WITH_CXX_GUARDEDALLOC
- MEM_CXX_CLASS_ALLOC_FUNCS("COM:WorkScheduler")
+ MEM_CXX_CLASS_ALLOC_FUNCS("COM:WorkScheduler")
#endif
};
diff --git a/source/blender/compositor/intern/COM_compositor.cpp b/source/blender/compositor/intern/COM_compositor.cpp
index 04fb550cf4b..50b578a9bc7 100644
--- a/source/blender/compositor/intern/COM_compositor.cpp
+++ b/source/blender/compositor/intern/COM_compositor.cpp
@@ -16,7 +16,6 @@
* Copyright 2011, Blender Foundation.
*/
-
extern "C" {
#include "BKE_node.h"
#include "BLI_threads.h"
@@ -35,85 +34,89 @@ extern "C" {
static ThreadMutex s_compositorMutex;
static bool is_compositorMutex_init = false;
-void COM_execute(RenderData *rd, Scene *scene, bNodeTree *editingtree, int rendering,
+void COM_execute(RenderData *rd,
+ Scene *scene,
+ bNodeTree *editingtree,
+ int rendering,
const ColorManagedViewSettings *viewSettings,
const ColorManagedDisplaySettings *displaySettings,
const char *viewName)
{
- /* initialize mutex, TODO this mutex init is actually not thread safe and
- * should be done somewhere as part of blender startup, all the other
- * initializations can be done lazily */
- if (is_compositorMutex_init == false) {
- BLI_mutex_init(&s_compositorMutex);
- is_compositorMutex_init = true;
- }
-
- BLI_mutex_lock(&s_compositorMutex);
-
- if (editingtree->test_break(editingtree->tbh)) {
- // during editing multiple calls to this method can be triggered.
- // make sure one the last one will be doing the work.
- BLI_mutex_unlock(&s_compositorMutex);
- return;
- }
-
- /* Make sure node tree has previews.
- * Don't create previews in advance, this is done when adding preview operations.
- * Reserved preview size is determined by render output for now.
- *
- * We fit the aspect into COM_PREVIEW_SIZE x COM_PREVIEW_SIZE image to avoid
- * insane preview resolution, which might even overflow preview dimensions.
- */
- const float aspect = rd->xsch > 0 ? (float)rd->ysch / (float)rd->xsch : 1.0f;
- int preview_width, preview_height;
- if (aspect < 1.0f) {
- preview_width = COM_PREVIEW_SIZE;
- preview_height = (int)(COM_PREVIEW_SIZE * aspect);
- }
- else {
- preview_width = (int)(COM_PREVIEW_SIZE / aspect);
- preview_height = COM_PREVIEW_SIZE;
- }
- BKE_node_preview_init_tree(editingtree, preview_width, preview_height, false);
-
- /* initialize workscheduler, will check if already done. TODO deinitialize somewhere */
- bool use_opencl = (editingtree->flag & NTREE_COM_OPENCL) != 0;
- WorkScheduler::initialize(use_opencl, BKE_render_num_threads(rd));
-
- /* set progress bar to 0% and status to init compositing */
- editingtree->progress(editingtree->prh, 0.0);
- editingtree->stats_draw(editingtree->sdh, IFACE_("Compositing"));
-
- bool twopass = (editingtree->flag & NTREE_TWO_PASS) && !rendering;
- /* initialize execution system */
- if (twopass) {
- ExecutionSystem *system = new ExecutionSystem(rd, scene, editingtree, rendering, twopass, viewSettings, displaySettings, viewName);
- system->execute();
- delete system;
-
- if (editingtree->test_break(editingtree->tbh)) {
- // during editing multiple calls to this method can be triggered.
- // make sure one the last one will be doing the work.
- BLI_mutex_unlock(&s_compositorMutex);
- return;
- }
- }
-
- ExecutionSystem *system = new ExecutionSystem(rd, scene, editingtree, rendering, false,
- viewSettings, displaySettings, viewName);
- system->execute();
- delete system;
-
- BLI_mutex_unlock(&s_compositorMutex);
+ /* initialize mutex, TODO this mutex init is actually not thread safe and
+ * should be done somewhere as part of blender startup, all the other
+ * initializations can be done lazily */
+ if (is_compositorMutex_init == false) {
+ BLI_mutex_init(&s_compositorMutex);
+ is_compositorMutex_init = true;
+ }
+
+ BLI_mutex_lock(&s_compositorMutex);
+
+ if (editingtree->test_break(editingtree->tbh)) {
+ // during editing multiple calls to this method can be triggered.
+ // make sure one the last one will be doing the work.
+ BLI_mutex_unlock(&s_compositorMutex);
+ return;
+ }
+
+ /* Make sure node tree has previews.
+ * Don't create previews in advance, this is done when adding preview operations.
+ * Reserved preview size is determined by render output for now.
+ *
+ * We fit the aspect into COM_PREVIEW_SIZE x COM_PREVIEW_SIZE image to avoid
+ * insane preview resolution, which might even overflow preview dimensions.
+ */
+ const float aspect = rd->xsch > 0 ? (float)rd->ysch / (float)rd->xsch : 1.0f;
+ int preview_width, preview_height;
+ if (aspect < 1.0f) {
+ preview_width = COM_PREVIEW_SIZE;
+ preview_height = (int)(COM_PREVIEW_SIZE * aspect);
+ }
+ else {
+ preview_width = (int)(COM_PREVIEW_SIZE / aspect);
+ preview_height = COM_PREVIEW_SIZE;
+ }
+ BKE_node_preview_init_tree(editingtree, preview_width, preview_height, false);
+
+ /* initialize workscheduler, will check if already done. TODO deinitialize somewhere */
+ bool use_opencl = (editingtree->flag & NTREE_COM_OPENCL) != 0;
+ WorkScheduler::initialize(use_opencl, BKE_render_num_threads(rd));
+
+ /* set progress bar to 0% and status to init compositing */
+ editingtree->progress(editingtree->prh, 0.0);
+ editingtree->stats_draw(editingtree->sdh, IFACE_("Compositing"));
+
+ bool twopass = (editingtree->flag & NTREE_TWO_PASS) && !rendering;
+ /* initialize execution system */
+ if (twopass) {
+ ExecutionSystem *system = new ExecutionSystem(
+ rd, scene, editingtree, rendering, twopass, viewSettings, displaySettings, viewName);
+ system->execute();
+ delete system;
+
+ if (editingtree->test_break(editingtree->tbh)) {
+ // during editing multiple calls to this method can be triggered.
+ // make sure one the last one will be doing the work.
+ BLI_mutex_unlock(&s_compositorMutex);
+ return;
+ }
+ }
+
+ ExecutionSystem *system = new ExecutionSystem(
+ rd, scene, editingtree, rendering, false, viewSettings, displaySettings, viewName);
+ system->execute();
+ delete system;
+
+ BLI_mutex_unlock(&s_compositorMutex);
}
void COM_deinitialize()
{
- if (is_compositorMutex_init) {
- BLI_mutex_lock(&s_compositorMutex);
- WorkScheduler::deinitialize();
- is_compositorMutex_init = false;
- BLI_mutex_unlock(&s_compositorMutex);
- BLI_mutex_end(&s_compositorMutex);
- }
+ if (is_compositorMutex_init) {
+ BLI_mutex_lock(&s_compositorMutex);
+ WorkScheduler::deinitialize();
+ is_compositorMutex_init = false;
+ BLI_mutex_unlock(&s_compositorMutex);
+ BLI_mutex_end(&s_compositorMutex);
+ }
}