
/*
 * CINELERRA
 * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */

#include "bcsignals.h"
#include "clip.h"
#include "datatype.h"
#include "edl.h"
#include "edlsession.h"
#include "plugin.h"
#include "pluginserver.h"
#include "renderengine.h"
#include "transportque.h"
#include "vattachmentpoint.h"
#include "vdevicex11.h"
#include "videodevice.h"
#include "vframe.h"

VAttachmentPoint::VAttachmentPoint(RenderEngine *renderengine, Plugin *plugin)
: AttachmentPoint(renderengine, plugin, TRACK_VIDEO)
{
	buffer_vector = 0;
}

VAttachmentPoint::~VAttachmentPoint()
{
	delete_buffer_vector();
}

void VAttachmentPoint::delete_buffer_vector()
{
	void *This = this;
	if(!This) printf("VAttachmentPoint::delete_buffer_vector NULL\n");
	if(buffer_vector)
	{
		for(int i = 0; i < virtual_plugins.total; i++)
			delete buffer_vector[i];
		delete [] buffer_vector;
	}
	buffer_vector = 0;
}

void VAttachmentPoint::new_buffer_vector(int width, int height, int colormodel)
{
	void *This = this;
	if(!This) printf("VAttachmentPoint::new_buffer_vector NULL\n");
	if(buffer_vector &&
		(width != buffer_vector[0]->get_w() ||
		height != buffer_vector[0]->get_h() ||
		colormodel != buffer_vector[0]->get_color_model()))
	{
		delete_buffer_vector();
	}

	if(!buffer_vector)
	{
		buffer_vector = new VFrame*[virtual_plugins.total];
		for(int i = 0; i < virtual_plugins.total; i++)
		{
			buffer_vector[i] = new VFrame(width, height, colormodel);
		}
	}
}

int VAttachmentPoint::get_buffer_size()
{
	return 1;
}

void VAttachmentPoint::render(VFrame *output,
	int buffer_number,
	int64_t start_position,
	double frame_rate,
	int debug_render,
	int use_opengl)
{
	void *This = this;
	if(!This) printf("VAttachmentPoint::render NULL\n");
	if(!plugin_server || !plugin->on) return;

	if(debug_render)
		printf("    VAttachmentPoint::render \"%s\" multi=%d opengl=%d\n",
			plugin_server->title,
			plugin_server->multichannel,
			use_opengl);

	if(plugin_server->multichannel)
	{
// Test against previous parameters for reuse of previous data
		if( !is_processed || this->start_position != start_position ||
		    !EQUIV(this->frame_rate, frame_rate)) {
			is_processed = 1;
			this->start_position = start_position;
			this->frame_rate = frame_rate;

// Allocate buffer vector for subsequent render calls
			new_buffer_vector(output->get_w(), output->get_h(),
				output->get_color_model());
// Process plugin
//printf("VAttachmentPoint::render 1 %d\n", buffer_number);
			if(renderengine)
				plugin_servers.values[0]->set_use_opengl(use_opengl,
					renderengine->video);
			plugin_servers.values[0]->process_buffer(buffer_vector,
				start_position, frame_rate,
				(int64_t)Units::round(plugin->length * frame_rate /
					renderengine->get_edl()->session->frame_rate),
				renderengine->command->get_direction());
		}
//printf("VAttachmentPoint::render 3\n");
// Need to copy PBuffer if OpenGL, regardless of use_opengl
		int opengl_state = buffer_vector[buffer_number]->get_opengl_state();
		if( opengl_state == VFrame::RAM ) {
			output->transfer_from(buffer_vector[buffer_number],
				0, 0,0, output->get_w(), output->get_h());
			output->set_opengl_state(VFrame::RAM);
		}
		else if( opengl_state != VFrame::UNKNOWN &&
			 renderengine && renderengine->video) {
// Need to copy PBuffer to texture
// printf("VAttachmentPoint::render temp=%p output=%p\n",
// buffer_vector[buffer_number],
// output);
			VDeviceX11 *x11_device = (VDeviceX11*)renderengine->video->get_output_base();
			x11_device->copy_frame(output, buffer_vector[buffer_number]);
		}
	}
	else
// process single track
	{
		VFrame *output_temp[1];
		output_temp[0] = output;
		if(renderengine)
			plugin_servers.values[buffer_number]->set_use_opengl(use_opengl,
				renderengine->video);
		plugin_servers.values[buffer_number]->process_buffer(output_temp,
			start_position,
			frame_rate,
			(int64_t)Units::round(plugin->length *
				frame_rate /
				renderengine->get_edl()->session->frame_rate),
			renderengine->command->get_direction());
	}
}


