X-Git-Url: https://cinelerra-gg.org/git/?a=blobdiff_plain;f=cinelerra-5.1%2Fplugins%2Fmandelcuda%2Fmandelbrot.C;fp=cinelerra-5.1%2Fplugins%2Fmandelcuda%2Fmandelbrot.C;h=693b867f06306823a6cdca9df10196b6a73b6399;hb=b1649fe7b38cfb4bbec58b19fb8dda2daa0ce520;hp=0000000000000000000000000000000000000000;hpb=abf5c6bb4dec2c2d03df2872e1d337e3905b3619;p=goodguy%2Fcinelerra.git diff --git a/cinelerra-5.1/plugins/mandelcuda/mandelbrot.C b/cinelerra-5.1/plugins/mandelcuda/mandelbrot.C new file mode 100644 index 00000000..693b867f --- /dev/null +++ b/cinelerra-5.1/plugins/mandelcuda/mandelbrot.C @@ -0,0 +1,303 @@ +/* + * CINELERRA + * Copyright (C) 1997-2014 Adam Williams + * + * 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 "clip.h" +#include "filexml.h" +#include "mandelbrot.h" +#include "mandelbrotwindow.h" +#include "language.h" +#include "mutex.h" + +#include "cwindow.h" +#include "cwindowgui.h" +#include "mwindow.h" +#include "pluginserver.h" +#include "playback3d.h" + +REGISTER_PLUGIN(Mandelbrot) + + +MandelbrotConfig::MandelbrotConfig() +{ +} + +int MandelbrotConfig::equivalent(MandelbrotConfig &that) +{ + return is_julia == that.is_julia && scale == that.scale && + x_off == that.x_off && y_off == that.y_off && + x_julia == that.x_julia && y_julia == that.y_julia && + color == that.color && crunch == that.crunch && + step == that.step; +} + +void MandelbrotConfig::copy_from(MandelbrotConfig &that) +{ + is_julia = that.is_julia; + x_off = that.x_off; + y_off = that.y_off; + scale = that.scale; + x_julia = that.x_julia; + y_julia = that.y_julia; + color = that.color; + crunch = that.crunch; + step = that.step; +} + +void MandelbrotConfig::interpolate( MandelbrotConfig &prev, MandelbrotConfig &next, + long prev_frame, long next_frame, long current_frame) +{ + copy_from(prev); + double u = (double)(next_frame - current_frame) / (next_frame - prev_frame); + double v = 1. - u; + this->x_off = u*prev.x_off + v*next.x_off; + this->y_off = u*prev.y_off + v*next.y_off; + this->scale = u*prev.scale + v*next.scale; + this->x_julia = u*prev.x_julia + v*next.x_julia; + this->y_julia = u*prev.y_julia + v*next.y_julia; +} + +void MandelbrotConfig::limits() +{ + bclamp(scale, -1.e4, 1.e4); + bclamp(crunch, 1, 0x10000); +} + + +Mandelbrot::Mandelbrot(PluginServer *server) + : PluginVClient(server) +{ + config.reset(); + config.startJulia(); + vfrm = 0; + img_w = img_h = 0; + pbo_id = -1; + animation_frame = 0; +} + +Mandelbrot::~Mandelbrot() +{ + delete vfrm; +} + +const char* Mandelbrot::plugin_title() { return N_("Mandelbrot"); } +int Mandelbrot::is_realtime() { return 1; } +int Mandelbrot::is_synthesis() { return 1; } + +NEW_WINDOW_MACRO(Mandelbrot, MandelbrotWindow); +LOAD_CONFIGURATION_MACRO(Mandelbrot, MandelbrotConfig) + +void Mandelbrot::save_data(KeyFrame *keyframe) +{ + FileXML output; + output.set_shared_output(keyframe->xbuf); + output.tag.set_title("MANDELCUDA"); + output.tag.set_property("IS_JULIA", config.is_julia); + output.tag.set_property("SCALE", config.scale); + output.tag.set_property("X_OFF", config.x_off); + output.tag.set_property("Y_OFF", config.y_off); + output.tag.set_property("X_JULIA", config.x_julia); + output.tag.set_property("Y_JULIA", config.y_julia); + output.tag.set_property("COLOR", config.color); + output.tag.set_property("CRUNCH", config.crunch); + output.tag.set_property("STEP", config.step); + output.append_tag(); + output.append_newline(); + output.tag.set_title("/MANDELCUDA"); + output.append_tag(); + output.append_newline(); + output.terminate_string(); +} + +void Mandelbrot::read_data(KeyFrame *keyframe) +{ + FileXML input; + input.set_shared_input(keyframe->xbuf); + + int result = 0; + while( !(result = input.read_tag()) ) { + if( input.tag.title_is("MANDELCUDA") ) { + config.is_julia = input.tag.get_property("IS_JULIA", config.is_julia); + config.scale = input.tag.get_property("SCALE", config.scale); + config.x_off = input.tag.get_property("X_OFF", config.x_off); + config.y_off = input.tag.get_property("Y_OFF", config.y_off); + config.x_julia = input.tag.get_property("X_JULIA", config.x_julia); + config.y_julia = input.tag.get_property("Y_JULIA", config.y_julia); + config.color = input.tag.get_property("COLOR", config.color); + config.crunch = input.tag.get_property("CRUNCH", config.crunch); + config.step = input.tag.get_property("STEP", config.step); + } + } + config.limits(); +} + +void Mandelbrot::update_gui() +{ + if( !thread ) return; + if( !load_configuration() ) return; + thread->window->lock_window("Mandelbrot::update_gui"); + MandelbrotWindow *window = (MandelbrotWindow*)thread->window; + window->update_gui(); + window->flush(); + window->unlock_window(); +} + +void MandelbrotConfig::reset() +{ + is_julia = 0; + x_julia = 0.0; + y_julia = 0.0; + x_off = -0.5; + y_off = 0.0; + scale = 3.2; + color = 0x00030507; + crunch = 512; + step = 0; +} + +void MandelbrotConfig::startJulia() +{ + is_julia = 1; + x_julia = -0.172400; + y_julia = -0.652693; + x_off = -0.085760; + y_off = 0.007040; +} + +// Get a sub-pixel sample location +void Mandelbrot::GetSample(int sampleIndex, float &x, float &y) +{ + static const unsigned char pairData[128][2] = { + {64, 64}, {0, 0}, {1, 63}, {63, 1}, {96, 32}, {97, 95}, {36, 96}, {30, 31}, + {95, 127}, {4, 97}, {33, 62}, {62, 33}, {31, 126}, {67, 99}, {99, 65}, {2, 34}, + {81, 49}, {19, 80}, {113, 17}, {112, 112}, {80, 16}, {115, 81}, {46, 15}, {82, 79}, + {48, 78}, {16, 14}, {49, 113}, {114, 48}, {45, 45}, {18, 47}, {20, 109}, {79, 115}, + {65, 82}, {52, 94}, {15, 124}, {94, 111}, {61, 18}, {47, 30}, {83, 100}, {98, 50}, + {110, 2}, {117, 98}, {50, 59}, {77, 35}, {3, 114}, {5, 77}, {17, 66}, {32, 13}, + {127, 20}, {34, 76}, {35, 110}, {100, 12}, {116, 67}, {66, 46}, {14, 28}, {23, 93}, + {102, 83}, {86, 61}, {44, 125}, {76, 3}, {109, 36}, {6, 51}, {75, 89}, {91, 21}, + {60, 117}, {29, 43}, {119, 29}, {74, 70}, {126, 87}, {93, 75}, {71, 24}, {106, 102}, + {108, 58}, {89, 9}, {103, 23}, {72, 56}, {120, 8}, {88, 40}, {11, 88}, {104, 120}, + {57, 105}, {118, 122}, {53, 6}, {125, 44}, {43, 68}, {58, 73}, {24, 22}, {22, 5}, + {40, 86}, {122, 108}, {87, 90}, {56, 42}, {70, 121}, {8, 7}, {37, 52}, {25, 55}, + {69, 11}, {10, 106}, {12, 38}, {26, 69}, {27, 116}, {38, 25}, {59, 54}, {107, 72}, + {121, 57}, {39, 37}, {73, 107}, {85, 123}, {28, 103}, {123, 74}, {55, 85}, {101, 41}, + {42, 104}, {84, 27}, {111, 91}, {9, 19}, {21, 39}, {90, 53}, {41, 60}, {54, 26}, + {92, 119}, {51, 71}, {124, 101}, {68, 92}, {78, 10}, {13, 118}, {7, 84}, {105, 4} + }; + + x = (1.0f / 128.0f) * (0.5f + (float) pairData[sampleIndex][0]); + y = (1.0f / 128.0f) * (0.5f + (float) pairData[sampleIndex][1]); +} // GetSample + +// render Mandelbrot image using CUDA +void Mandelbrot::renderImage() +{ + float xs, ys; + // Get the anti-alias sub-pixel sample location + GetSample(pass & 127, xs, ys); + + // Get the pixel scale and offset + double s = config.scale / (float) img_w; + double x = (xs - (double) img_w * 0.5f) * s + config.x_off; + double y = (ys - (double) img_h * 0.5f) * s + config.y_off; + + uchar4 colors; + colors.w = (config.color>>24) & 0xff; + colors.x = (config.color>>16) & 0xff; + colors.y = (config.color>>8) & 0xff; + colors.z = (config.color>>0) & 0xff; + + cuda.Run(vfrm->get_data(), img_w*img_h*4, config.is_julia, config.crunch, + x, y, config.x_julia, config.y_julia, s, colors, pass, animation_frame); + ++pass; +} + +void Mandelbrot::displayFunc() +{ + if( config.step ) { + animation_frame += config.step; + pass = 0; + } + // render the Mandelbrot image + renderImage(); +} + +void Mandelbrot::init() +{ + animation_frame = 0; + pass = 0; +} + +int Mandelbrot::process_buffer(VFrame *frame, int64_t start_position, double frame_rate) +{ + + int need_reconfigure = load_configuration(); + if( need_reconfigure ) pass = 0; + output = get_output(0); + color_model = output->get_color_model(); + img_w = output->get_w(); + img_h = output->get_h(); + if( !start_position ) + init(); + if( vfrm && + (vfrm->get_w() != img_w || vfrm->get_h() != img_h) ) { + delete vfrm; vfrm = 0; + } + if( !vfrm ) + vfrm = new VFrame(img_w, img_h, BC_RGBA8888); + + if( get_use_opengl() ) + return run_opengl(); +// always use_opengl + Canvas *canvas = server->mwindow->cwindow->gui->canvas; + return server->mwindow->playback_3d->run_plugin(canvas, this); +} + +// opengl from here down + +void Mandelbrot::init_cuda() +{ + cuda.init_dev(); + GLuint pbo[1]; + glGenBuffers(1, pbo); + glBindBuffer(GL_ARRAY_BUFFER, pbo_id=*pbo); + glBufferData(GL_ARRAY_BUFFER, img_w*img_h*4, 0, GL_STATIC_DRAW); + cuda.init(pbo_id, img_w, img_h); + glBindBuffer(GL_ARRAY_BUFFER, 0); +} +void Mandelbrot::finish_cuda() +{ + cuda.finish(); + GLuint pbo[1]; *pbo = pbo_id; + glDeleteBuffers(1, pbo); + pbo_id = -1; +} + +int Mandelbrot::handle_opengl() +{ + vfrm->enable_opengl(); + vfrm->init_screen(); + init_cuda(); + displayFunc(); + output->transfer_from(vfrm); + finish_cuda(); + return 0; +} +