void ReadBufferOperation::readResolutionFromWriteBuffer()
{
	if (this->m_memoryProxy != NULL) {
		WriteBufferOperation *operation = this->m_memoryProxy->getWriteBufferOperation();
		this->setWidth(operation->getWidth());
		this->setHeight(operation->getHeight());
	}
}
MemoryBuffer *ExecutionGroup::allocateOutputBuffer(int /*chunkNumber*/,
                                                   rcti *rect)
{
	// we asume 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;
}
void ReadBufferOperation::determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2])
{
	if (this->m_memoryProxy != NULL) {
		WriteBufferOperation *operation = this->m_memoryProxy->getWriteBufferOperation();
		operation->determineResolution(resolution, preferredResolution);
		operation->setResolution(resolution);

		/// @todo: may not occur!, but does with blur node
		if (this->m_memoryProxy->getExecutor()) {
			this->m_memoryProxy->getExecutor()->setResolution(resolution);
		}
	}
}
void SocketBufferNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const
{
	NodeOutput *output = this->getOutputSocket(0);
	NodeInput *input = this->getInputSocket(0);
	
	DataType datatype = output->getDataType();
	WriteBufferOperation *writeOperation = new WriteBufferOperation(datatype);
	ReadBufferOperation *readOperation = new ReadBufferOperation(datatype);
	readOperation->setMemoryProxy(writeOperation->getMemoryProxy());
	converter.addOperation(writeOperation);
	converter.addOperation(readOperation);
	
	converter.mapInputSocket(input, writeOperation->getInputSocket(0));
	converter.mapOutputSocket(output, readOperation->getOutputSocket());
}
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;
	
	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);
		}
	}
	
	/* 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));
	}
	
	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 */
		
		ReadBufferOperation *readoperation = new ReadBufferOperation(operation->getOutputSocket()->getDataType());
		readoperation->setMemoryProxy(writeOperation->getMemoryProxy());
		addOperation(readoperation);
		
		addLink(readoperation->getOutputSocket(), target);
	
		readoperation->readResolutionFromWriteBuffer();
	}
}
void TranslateNode::convertToOperations(NodeConverter &converter,
                                        const CompositorContext &context) const
{
  bNode *bnode = this->getbNode();
  NodeTranslateData *data = (NodeTranslateData *)bnode->storage;

  NodeInput *inputSocket = this->getInputSocket(0);
  NodeInput *inputXSocket = this->getInputSocket(1);
  NodeInput *inputYSocket = this->getInputSocket(2);
  NodeOutput *outputSocket = this->getOutputSocket(0);

  TranslateOperation *operation = new TranslateOperation();
  if (data->relative) {
    const RenderData *rd = context.getRenderData();
    float fx = rd->xsch * rd->size / 100.0f;
    float fy = rd->ysch * rd->size / 100.0f;

    operation->setFactorXY(fx, fy);
  }

  converter.addOperation(operation);
  converter.mapInputSocket(inputXSocket, operation->getInputSocket(1));
  converter.mapInputSocket(inputYSocket, operation->getInputSocket(2));
  converter.mapOutputSocket(outputSocket, operation->getOutputSocket(0));

  if (data->wrap_axis) {
    WriteBufferOperation *writeOperation = new WriteBufferOperation(COM_DT_COLOR);
    WrapOperation *wrapOperation = new WrapOperation(COM_DT_COLOR);
    wrapOperation->setMemoryProxy(writeOperation->getMemoryProxy());
    wrapOperation->setWrapping(data->wrap_axis);

    converter.addOperation(writeOperation);
    converter.addOperation(wrapOperation);
    converter.mapInputSocket(inputSocket, writeOperation->getInputSocket(0));
    converter.addLink(wrapOperation->getOutputSocket(), operation->getInputSocket(0));
  }
  else {
    converter.mapInputSocket(inputSocket, operation->getInputSocket(0));
  }
}
void NodeOperationBuilder::add_input_buffers(NodeOperation * /*operation*/,
                                             NodeOperationInput *input)
{
	if (!input->isConnected())
		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);
	
	/* 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));
		
		writeoperation->readResolutionFromInputSocket();
	}
	
	/* add readbuffer op for the input */
	ReadBufferOperation *readoperation = new ReadBufferOperation(output->getDataType());
	readoperation->setMemoryProxy(writeoperation->getMemoryProxy());
	this->addOperation(readoperation);
	
	addLink(readoperation->getOutputSocket(), input);
	
	readoperation->readResolutionFromWriteBuffer();
}