/*
* 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 <math.h>
#include <stdint.h>
#include <string.h>
+#include "bccolors.h"
#include "bcdisplayinfo.h"
#include "clip.h"
#include "bchash.h"
GradientConfig::GradientConfig()
+{
+ reset();
+}
+
+void GradientConfig::reset()
+
{
angle = 0;
in_radius = 0;
center_y = that.center_y;
}
-void GradientConfig::interpolate(GradientConfig &prev,
- GradientConfig &next,
- long prev_frame,
- long next_frame,
+void GradientConfig::interpolate(GradientConfig &prev,
+ GradientConfig &next,
+ long prev_frame,
+ long next_frame,
long current_frame)
{
double next_scale = (double)(current_frame - prev_frame) / (next_frame - prev_frame);
GradientWindow::GradientWindow(GradientMain *plugin)
: PluginClientWindow(plugin,
- 350,
- 290,
- 350,
- 290,
+ 350,
+ 290,
+ 350,
+ 290,
0)
{
this->plugin = plugin;
BC_Title *title;
add_subwindow(title = new BC_Title(x, y, _("Shape:")));
- add_subwindow(shape = new GradientShape(plugin,
- this,
- x + title->get_w() + margin,
+ add_subwindow(shape = new GradientShape(plugin,
+ this,
+ x + title->get_w() + margin,
y));
shape->create_objects();
y += shape->get_h() + margin;
BC_Title *title2;
add_subwindow(title2 = new BC_Title(x, y, _("Outer radius:")));
+ add_subwindow(reset = new GradientReset(plugin, this, x, y+100));
+
y = y1;
x += MAX(title1->get_w(), title2->get_w()) + margin;
-
+
add_subwindow(in_radius = new GradientInRadius(plugin, x, y));
y += in_radius->get_h() + margin;
add_subwindow(in_color = new GradientInColorButton(plugin, this, x, y));
y += COLOR_H + margin;
-
add_subwindow(out_color = new GradientOutColorButton(plugin, this, x, y));
x += MAX(in_color->get_w(), out_color->get_w()) + margin;
y = y1;
update_out_color();
update_shape();
- draw_3d_border(in_color_x - 2,
- in_color_y - 2,
- COLOR_W + 4,
- COLOR_H + 4,
+ draw_3d_border(in_color_x - 2,
+ in_color_y - 2,
+ COLOR_W + 4,
+ COLOR_H + 4,
1);
- draw_3d_border(out_color_x - 2,
- out_color_y - 2,
- COLOR_W + 4,
- COLOR_H + 4,
+ draw_3d_border(out_color_x - 2,
+ out_color_y - 2,
+ COLOR_W + 4,
+ COLOR_H + 4,
1);
+
show_window();
}
y));
}
}
+ show_window();
}
flash(out_color_x, out_color_y, COLOR_W, COLOR_H);
}
+void GradientWindow::done_event(int result)
+{
+ in_color_thread->close_window();
+ out_color_thread->close_window();
+}
+
-GradientShape::GradientShape(GradientMain *plugin,
- GradientWindow *gui,
- int x,
+GradientShape::GradientShape(GradientMain *plugin,
+ GradientWindow *gui,
+ int x,
int y)
: BC_PopupMenu(x, y, 100, to_text(plugin->config.shape), 1)
{
}
int GradientShape::from_text(char *text)
{
- if(!strcmp(text, to_text(GradientConfig::LINEAR)))
+ if(!strcmp(text, to_text(GradientConfig::LINEAR)))
return GradientConfig::LINEAR;
return GradientConfig::RADIAL;
}
}
int GradientRate::from_text(char *text)
{
- if(!strcmp(text, to_text(GradientConfig::LINEAR)))
+ if(!strcmp(text, to_text(GradientConfig::LINEAR)))
return GradientConfig::LINEAR;
if(!strcmp(text, to_text(GradientConfig::LOG)))
return GradientConfig::LOG;
return 1;
}
+GradientReset::GradientReset(GradientMain *plugin, GradientWindow *window, int x, int y)
+ : BC_GenericButton(x, y, _("Reset"))
+{
+ this->plugin = plugin;
+ this->window = window;
+}
+int GradientReset::handle_event()
+{
+ plugin->config.reset();
+ window->update_gui();
+ plugin->send_configure_change();
+ return 1;
+}
-GradientInColorThread::GradientInColorThread(GradientMain *plugin,
+GradientInColorThread::GradientInColorThread(GradientMain *plugin,
GradientWindow *window)
- : ColorThread(1, _("Inner color"))
+ : ColorPicker(1, _("Inner color"))
{
this->plugin = plugin;
this->window = window;
plugin->config.in_g = (output & 0xff00) >> 8;
plugin->config.in_b = (output & 0xff);
plugin->config.in_a = alpha;
-
+
window->lock_window("GradientInColorThread::handle_new_color");
window->update_in_color();
window->flush();
-GradientOutColorThread::GradientOutColorThread(GradientMain *plugin,
+GradientOutColorThread::GradientOutColorThread(GradientMain *plugin,
GradientWindow *window)
- : ColorThread(1, _("Outer color"))
+ : ColorPicker(1, _("Outer color"))
{
this->plugin = plugin;
this->window = window;
GradientMain::GradientMain(PluginServer *server)
: PluginVClient(server)
{
-
+
need_reconfigure = 1;
gradient = 0;
engine = 0;
GradientMain::~GradientMain()
{
-
+
if(gradient) delete gradient;
if(engine) delete engine;
if(overlayer) delete overlayer;
}
-const char* GradientMain::plugin_title() { return _("Gradient"); }
+const char* GradientMain::plugin_title() { return N_("Gradient"); }
int GradientMain::is_realtime() { return 1; }
int need_alpha = config.in_a != 0xff || config.out_a != 0xff;
if(need_alpha)
- read_frame(frame,
- 0,
- start_position,
+ read_frame(frame,
+ 0,
+ start_position,
frame_rate,
get_use_opengl());
if(get_use_opengl()) return run_opengl();
gradient = 0;
}
- if(!gradient) gradient = new VFrame(0,
- -1,
- input->get_w(),
- input->get_h(),
- gradient_cmodel,
- -1);
+ if(!gradient)
+ gradient = new VFrame(input->get_w(), input->get_h(),
+ gradient_cmodel, 0);
if(!engine) engine = new GradientServer(this,
get_project_smp() + 1,
if(gradient->get_color_model() == output->get_color_model())
{
if(!overlayer) overlayer = new OverlayFrame(get_project_smp() + 1);
- overlayer->overlay(output,
+ overlayer->overlay(output,
gradient,
- 0,
- 0,
- input->get_w(),
+ 0,
+ 0,
+ input->get_w(),
+ input->get_h(),
+ 0,
+ 0,
+ input->get_w(),
input->get_h(),
- 0,
- 0,
- input->get_w(),
- input->get_h(),
- 1.0,
+ 1.0,
TRANSFER_NORMAL,
NEAREST_NEIGHBOR);
}
void GradientMain::update_gui()
{
- if(thread)
- {
- if(load_configuration())
- {
- ((GradientWindow*)thread->window)->lock_window("GradientMain::update_gui");
- ((GradientWindow*)thread->window)->rate->set_text(GradientRate::to_text(config.rate));
- ((GradientWindow*)thread->window)->in_radius->update(config.in_radius);
- ((GradientWindow*)thread->window)->out_radius->update(config.out_radius);
- ((GradientWindow*)thread->window)->shape->set_text(GradientShape::to_text(config.shape));
- if(((GradientWindow*)thread->window)->angle)
- ((GradientWindow*)thread->window)->angle->update(config.angle);
- if(((GradientWindow*)thread->window)->center_x)
- ((GradientWindow*)thread->window)->center_x->update(config.center_x);
- if(((GradientWindow*)thread->window)->center_y)
- ((GradientWindow*)thread->window)->center_y->update(config.center_y);
- ((GradientWindow*)thread->window)->update_in_color();
- ((GradientWindow*)thread->window)->update_out_color();
- ((GradientWindow*)thread->window)->update_shape();
- ((GradientWindow*)thread->window)->unlock_window();
- ((GradientWindow*)thread->window)->in_color_thread->update_gui(config.get_in_color(), config.in_a);
- ((GradientWindow*)thread->window)->out_color_thread->update_gui(config.get_out_color(), config.out_a);
- }
- }
+ if( !thread ) return;
+ if( !load_configuration() ) return;
+ ((GradientWindow*)thread->window)->lock_window("GradientMain::update_gui");
+ GradientWindow *window = (GradientWindow *)thread->window;
+ window->update_gui();
+ window->unlock_window();
}
-
+void GradientWindow::update_gui()
+{
+ GradientConfig &config = plugin->config;
+ rate->set_text(GradientRate::to_text(config.rate));
+ in_radius->update(config.in_radius);
+ out_radius->update(config.out_radius);
+ shape->set_text(GradientShape::to_text(config.shape));
+ if( angle ) angle->update(config.angle);
+ if( center_x ) center_x->update(config.center_x);
+ if( center_y ) center_y->update(config.center_y);
+ update_in_color();
+ update_out_color();
+ update_shape();
+ unlock_window();
+ in_color_thread->update_gui(config.get_in_color(), config.in_a);
+ out_color_thread->update_gui(config.get_out_color(), config.out_a);
+ lock_window("GradientWindow::update_gui");
+}
void GradientMain::save_data(KeyFrame *keyframe)
"{\n"
" vec2 out_coord = gl_TexCoord[0].st;\n";
- const char *linear_shape =
+ const char *linear_shape =
" vec2 in_coord = vec2(out_coord.x - half_w, half_h - out_coord.y);\n"
" float mag = half_gradient_size - \n"
" (in_coord.x * sin_angle + in_coord.y * cos_angle);\n";
" float mag = length(vec2(in_coord.x, in_coord.y));\n";
// No clamp function in NVidia
- const char *linear_rate =
+ const char *linear_rate =
" mag = min(max(mag, in_radius), out_radius);\n"
" float opacity = (mag - in_radius) / radius_diff;\n";
// NVidia warns about exp, but exp is in the GLSL spec.
- const char *log_rate =
+ const char *log_rate =
" mag = max(mag, in_radius);\n"
" float opacity = 1.0 - \n"
" exp(1.0 * -(mag - in_radius) / radius_diff);\n";
- const char *square_rate =
+ const char *square_rate =
" mag = min(max(mag, in_radius), out_radius);\n"
" float opacity = pow((mag - in_radius) / radius_diff, 2.0);\n"
" opacity = min(opacity, 1.0);\n";
- const char *tail_frag =
+ const char *tail_frag =
" vec4 color = mix(in_color, out_color, opacity);\n"
" vec4 bg_color = texture2D(tex, out_coord);\n"
" gl_FragColor.rgb = mix(bg_color.rgb, color.rgb, color.a);\n"
"}\n";
- const char *shader_stack[5] = { 0, 0, 0, 0, 0 };
- shader_stack[0] = head_frag;
+ const char *shader_stack[16];
+ memset(shader_stack,0, sizeof(shader_stack));
+ int current_shader = 0;
- switch(config.shape)
- {
- case GradientConfig::LINEAR:
- shader_stack[1] = linear_shape;
- break;
+ shader_stack[current_shader++] = head_frag;
- default:
- shader_stack[1] = radial_shape;
- break;
+ const char *shape_frag = 0;
+ switch( config.shape ) {
+ case GradientConfig::LINEAR:
+ shape_frag = linear_shape;
+ break;
+ default:
+ shape_frag = radial_shape;
+ break;
}
-
- switch(config.rate)
- {
- case GradientConfig::LINEAR:
- shader_stack[2] = linear_rate;
- break;
- case GradientConfig::LOG:
- shader_stack[2] = log_rate;
- break;
- case GradientConfig::SQUARE:
- shader_stack[2] = square_rate;
- break;
+ if( shape_frag )
+ shader_stack[current_shader++] = shape_frag;
+
+ const char *rate_frag = 0;
+ switch(config.rate) {
+ case GradientConfig::LINEAR:
+ rate_frag = linear_rate;
+ break;
+ case GradientConfig::LOG:
+ rate_frag = log_rate;
+ break;
+ case GradientConfig::SQUARE:
+ rate_frag = square_rate;
+ break;
}
+ if( rate_frag )
+ shader_stack[current_shader++] = rate_frag;
+
+ shader_stack[current_shader++] = tail_frag;
- shader_stack[3] = tail_frag;
// Force frame to create texture without copying to it if full alpha.
- if(config.in_a >= 0xff &&
- config.out_a >= 0xff)
+ if( config.in_a >= 0xff && config.out_a >= 0xff )
get_output()->set_opengl_state(VFrame::TEXTURE);
get_output()->to_texture();
get_output()->enable_opengl();
get_output()->init_screen();
get_output()->bind_texture(0);
- unsigned int frag = VFrame::make_shader(0,
- shader_stack[0],
- shader_stack[1],
- shader_stack[2],
- shader_stack[3],
- 0);
-
- if(frag)
- {
- glUseProgram(frag);
+ shader_stack[current_shader] = 0;
+ unsigned int shader = VFrame::make_shader(shader_stack);
+ if( shader > 0 ) {
+ glUseProgram(shader);
float w = get_output()->get_w();
float h = get_output()->get_h();
float texture_w = get_output()->get_texture_w();
float texture_h = get_output()->get_texture_h();
- glUniform1i(glGetUniformLocation(frag, "tex"), 0);
- glUniform1f(glGetUniformLocation(frag, "half_w"), w / 2 / texture_w);
- glUniform1f(glGetUniformLocation(frag, "half_h"), h / 2 / texture_h);
+ glUniform1i(glGetUniformLocation(shader, "tex"), 0);
+ glUniform1f(glGetUniformLocation(shader, "half_w"), w / 2 / texture_w);
+ glUniform1f(glGetUniformLocation(shader, "half_h"), h / 2 / texture_h);
if(config.shape == GradientConfig::LINEAR)
{
- glUniform1f(glGetUniformLocation(frag, "center_x"),
+ glUniform1f(glGetUniformLocation(shader, "center_x"),
w / 2 / texture_w);
- glUniform1f(glGetUniformLocation(frag, "center_y"),
+ glUniform1f(glGetUniformLocation(shader, "center_y"),
h / 2 / texture_h);
}
else
{
- glUniform1f(glGetUniformLocation(frag, "center_x"),
+ glUniform1f(glGetUniformLocation(shader, "center_x"),
(float)config.center_x * w / 100 / texture_w);
- glUniform1f(glGetUniformLocation(frag, "center_y"),
+ glUniform1f(glGetUniformLocation(shader, "center_y"),
(float)config.center_y * h / 100 / texture_h);
}
float gradient_size = hypotf(w / texture_w, h / texture_h);
- glUniform1f(glGetUniformLocation(frag, "half_gradient_size"),
+ glUniform1f(glGetUniformLocation(shader, "half_gradient_size"),
gradient_size / 2);
- glUniform1f(glGetUniformLocation(frag, "sin_angle"),
+ glUniform1f(glGetUniformLocation(shader, "sin_angle"),
sin(config.angle * (M_PI / 180)));
- glUniform1f(glGetUniformLocation(frag, "cos_angle"),
+ glUniform1f(glGetUniformLocation(shader, "cos_angle"),
cos(config.angle * (M_PI / 180)));
float in_radius = (float)config.in_radius / 100 * gradient_size;
- glUniform1f(glGetUniformLocation(frag, "in_radius"), in_radius);
+ glUniform1f(glGetUniformLocation(shader, "in_radius"), in_radius);
float out_radius = (float)config.out_radius / 100 * gradient_size;
- glUniform1f(glGetUniformLocation(frag, "out_radius"), out_radius);
- glUniform1f(glGetUniformLocation(frag, "radius_diff"),
+ glUniform1f(glGetUniformLocation(shader, "out_radius"), out_radius);
+ glUniform1f(glGetUniformLocation(shader, "radius_diff"),
out_radius - in_radius);
- switch(get_output()->get_color_model())
- {
- case BC_YUV888:
- case BC_YUVA8888:
- {
- float in1, in2, in3, in4;
- float out1, out2, out3, out4;
- YUV::rgb_to_yuv_f((float)config.in_r / 0xff,
- (float)config.in_g / 0xff,
- (float)config.in_b / 0xff,
- in1,
- in2,
- in3);
+ switch(get_output()->get_color_model()) {
+ case BC_YUV888:
+ case BC_YUVA8888: {
+ float in1, in2, in3, in4;
+ float out1, out2, out3, out4;
+ YUV::yuv.rgb_to_yuv_f(
+ (float)config.in_r / 0xff,
+ (float)config.in_g / 0xff,
+ (float)config.in_b / 0xff,
+ in1, in2, in3);
in4 = (float)config.in_a / 0xff;
- YUV::rgb_to_yuv_f((float)config.out_r / 0xff,
- (float)config.out_g / 0xff,
- (float)config.out_b / 0xff,
- out1,
- out2,
- out3);
- in2 += 0.5;
- in3 += 0.5;
- out2 += 0.5;
- out3 += 0.5;
- out4 = (float)config.out_a / 0xff;
- glUniform4f(glGetUniformLocation(frag, "out_color"),
- out1, out2, out3, out4);
- glUniform4f(glGetUniformLocation(frag, "in_color"),
- in1, in2, in3, in4);
- break;
- }
+ YUV::yuv.rgb_to_yuv_f(
+ (float)config.out_r / 0xff,
+ (float)config.out_g / 0xff,
+ (float)config.out_b / 0xff,
+ out1, out2, out3);
+ in2 += 0.5; in3 += 0.5;
+ out2 += 0.5; out3 += 0.5;
+ out4 = (float)config.out_a / 0xff;
+ glUniform4f(glGetUniformLocation(shader, "out_color"),
+ out1, out2, out3, out4);
+ glUniform4f(glGetUniformLocation(shader, "in_color"),
+ in1, in2, in3, in4);
+ break; }
- default:
- glUniform4f(glGetUniformLocation(frag, "out_color"),
- (float)config.out_r / 0xff,
- (float)config.out_g / 0xff,
- (float)config.out_b / 0xff,
- (float)config.out_a / 0xff);
- glUniform4f(glGetUniformLocation(frag, "in_color"),
- (float)config.in_r / 0xff,
- (float)config.in_g / 0xff,
- (float)config.in_b / 0xff,
- (float)config.in_a / 0xff);
- break;
+ default:
+ glUniform4f(glGetUniformLocation(shader, "out_color"),
+ (float)config.out_r / 0xff,
+ (float)config.out_g / 0xff,
+ (float)config.out_b / 0xff,
+ (float)config.out_a / 0xff);
+ glUniform4f(glGetUniformLocation(shader, "in_color"),
+ (float)config.in_r / 0xff,
+ (float)config.in_g / 0xff,
+ (float)config.in_b / 0xff,
+ (float)config.in_a / 0xff);
+ break;
}
}
get_output()->draw_texture();
glUseProgram(0);
get_output()->set_opengl_state(VFrame::SCREEN);
-
+
#endif
return 0;
}
-
-
-
-
-
-
-
-
-
GradientPackage::GradientPackage()
: LoadPackage()
{
}
-
-
-
GradientUnit::GradientUnit(GradientServer *server, GradientMain *plugin)
: LoadClient(server)
{
}
-
-
-static float calculate_opacity(float mag,
+static float calculate_opacity(float mag,
float in_radius, float out_radius, int rate)
{
float opacity = 0.0;
case GradientConfig::SQUARE:
if(mag < in_radius)
- opacity = 0.0;
+ opacity = 0.0;
else
- if(mag >= out_radius)
+ if(mag >= out_radius)
opacity = 1.0;
else
opacity = powf((float)(mag - in_radius) /
{
int in1, in2, in3, in4;
int out1, out2, out3, out4;
- yuv.rgb_to_yuv_8(plugin->config.in_r,
+ YUV::yuv.rgb_to_yuv_8(plugin->config.in_r,
plugin->config.in_g,
plugin->config.in_b,
in1,
in2,
in3);
in4 = plugin->config.in_a;
- yuv.rgb_to_yuv_8(plugin->config.out_r,
+ YUV::yuv.rgb_to_yuv_8(plugin->config.out_r,
plugin->config.out_g,
plugin->config.out_b,
out1,
{
int in1, in2, in3, in4;
int out1, out2, out3, out4;
- yuv.rgb_to_yuv_8(plugin->config.in_r,
+ YUV::yuv.rgb_to_yuv_8(plugin->config.in_r,
plugin->config.in_g,
plugin->config.in_b,
in1,
in2,
in3);
in4 = plugin->config.in_a;
- yuv.rgb_to_yuv_8(plugin->config.out_r,
+ YUV::yuv.rgb_to_yuv_8(plugin->config.out_r,
plugin->config.out_g,
plugin->config.out_b,
out1,
-GradientServer::GradientServer(GradientMain *plugin,
- int total_clients,
+GradientServer::GradientServer(GradientMain *plugin,
+ int total_clients,
int total_packages)
: LoadServer(total_clients, total_packages)
{
for(int i = 0; i < get_total_packages(); i++)
{
GradientPackage *package = (GradientPackage*)get_package(i);
- package->y1 = plugin->input->get_h() *
- i /
+ package->y1 = plugin->input->get_h() *
+ i /
get_total_packages();
- package->y2 = plugin->input->get_h() *
+ package->y2 = plugin->input->get_h() *
(i + 1) /
get_total_packages();
}