/* Copyright (c) 2005-2021 Intel Corporation Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #ifndef TBB_examples_fractal_H #define TBB_examples_fractal_H #include #include "oneapi/tbb/task_arena.h" #include "oneapi/tbb/task_group.h" #include "common/gui/video.hpp" #include "common/utility/get_default_num_threads.hpp" //! Fractal class class fractal { //! Left corner of the fractal area int off_x, off_y; //! Size of the fractal area int size_x, size_y; //! Fractal properties float cx, cy; float magn; float step; unsigned int max_iterations; //! Drawing memory object for rendering const drawing_memory &dm; //! One pixel calculation routine color_t calc_one_pixel(int x, int y) const; //! Clears the fractal area void clear(); //! Draws the border around the fractal area void draw_border(bool is_active); //! Renders the fractal void render(oneapi::tbb::task_group_context &context); //! Check if the point is inside the fractal area bool check_point(int x, int y) const; public: //! Constructor fractal(const drawing_memory &dm) : step(0.2), dm(dm) { #if _MSC_VER && _WIN64 && !__INTEL_COMPILER // Workaround for MSVC x64 compiler issue volatile int i = 0; #endif } //! Runs the fractal calculation void run(oneapi::tbb::task_group_context &context); //! Renders the fractal rectangular area void render_rect(int x0, int y0, int x1, int y1) const; void move_up() { cy += step; } void move_down() { cy -= step; } void move_left() { cx += step; } void move_right() { cx -= step; } void zoom_in() { magn *= 2.; step /= 2.; } void zoom_out() { magn /= 2.; step *= 2.; } void quality_inc() { max_iterations += max_iterations / 2; } void quality_dec() { max_iterations -= max_iterations / 2; } friend class fractal_group; }; //! The group of fractals class fractal_group { //! Fractals definition fractal f0, f1; //! Number of frames to calculate std::atomic num_frames[2]; //! Contexts, arenas and groups for concurrent computation oneapi::tbb::task_group_context context[2]; oneapi::tbb::task_arena arenas[2]; oneapi::tbb::task_group groups[2]; //! Border type enumeration enum BORDER_TYPE { BORDER_INACTIVE = 0, BORDER_ACTIVE }; //! The number of the threads int num_threads; //! The active (high priority) fractal number int active; //! Draws the borders around the fractals void draw_borders(); //! Sets priorities for fractals calculations void set_priorities(); public: //! Constructor fractal_group(const drawing_memory &_dm, int num_threads = utility::get_default_num_threads(), unsigned int max_iterations = 100000, int num_frames = 1); //! Run calculation void run(bool create_second_fractal = true); //! Mouse event handler void mouse_click(int x, int y); //! Fractal calculation routine void calc_fractal(int num); //! Get number of threads int get_num_threads() const { return num_threads; } //! Reset the number of frames to be not less than the given value void set_num_frames_at_least(int n); //! Switch active fractal void switch_active(int new_active = -1); //! Get active fractal fractal &get_active_fractal() { return active ? f1 : f0; } void active_fractal_zoom_in() { get_active_fractal().zoom_in(); context[active].cancel_group_execution(); } void active_fractal_zoom_out() { get_active_fractal().zoom_out(); context[active].cancel_group_execution(); } void active_fractal_quality_inc() { get_active_fractal().quality_inc(); context[active].cancel_group_execution(); } void active_fractal_quality_dec() { get_active_fractal().quality_dec(); context[active].cancel_group_execution(); } void active_fractal_move_up() { get_active_fractal().move_up(); context[active].cancel_group_execution(); } void active_fractal_move_down() { get_active_fractal().move_down(); context[active].cancel_group_execution(); } void active_fractal_move_left() { get_active_fractal().move_left(); context[active].cancel_group_execution(); } void active_fractal_move_right() { get_active_fractal().move_right(); context[active].cancel_group_execution(); } }; #endif /* TBB_examples_fractal_H */