1 /**************************************************************************/ 2 /* Copyright 2012 Tim Day */ 3 /* */ 4 /* This file is part of Evolvotron */ 5 /* */ 6 /* Evolvotron is free software: you can redistribute it and/or modify */ 7 /* it under the terms of the GNU General Public License as published by */ 8 /* the Free Software Foundation, either version 3 of the License, or */ 9 /* (at your option) any later version. */ 10 /* */ 11 /* Evolvotron is distributed in the hope that it will be useful, */ 12 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ 13 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ 14 /* GNU General Public License for more details. */ 15 /* */ 16 /* You should have received a copy of the GNU General Public License */ 17 /* along with Evolvotron. If not, see <http://www.gnu.org/licenses/>. */ 18 /**************************************************************************/ 19 20 /*! \file 21 \brief Interface for class MutatableImageComputerTask. 22 */ 23 24 #ifndef _mutatable_image_computer_task_h_ 25 #define _mutatable_image_computer_task_h_ 26 27 #include "common.h" 28 29 #include "mutatable_image.h" 30 #include "mutatable_image_display.h" 31 32 //! Class encapsulating all the parameters of, and output from, a single image generation run. 33 class MutatableImageComputerTask 34 { 35 protected: 36 37 //! Flag indicating (to compute thread) that this task should be aborted. Also indicates to MutatableImageDisplay that it's a dud and shouldn't be displayed.. 38 /*! \todo Think more about whether this needs to be mutex protected for sanity. 39 */ 40 bool _aborted; 41 42 //! The display originating the task, and to which the output will be returned. 43 MutatableImageDisplay*const _display; 44 45 //! The root node of the image tree to be generated. 46 /*! Constness of the MutatableImage referenced is important as the instance is shared between all tasks and the original display. 47 */ 48 const boost::shared_ptr<const MutatableImage> _image_function; 49 50 //! Task priority. 51 /*! Low numbers go to the head of the queue. 52 The total number of samples in the complete (non-fragmented) image is used, 53 so small low resolution images which can be quickly completed are run first. 54 */ 55 const uint _priority; 56 57 //! The origin (on the display) of the image being generated. 58 const QSize _fragment_origin; 59 60 //! The size of the image to be generated. 61 const QSize _fragment_size; 62 63 //! The full size of the image of which this is a fragment. 64 const QSize _whole_image_size; 65 66 //! Number of animation frames to be rendered 67 const uint _frames; 68 69 //! The resolution level of this image (0=1-for-1 pixels, 1=half res etc) 70 /*! This is tracked because multiple compute threads could return the completed tasks out of order 71 (Unlikely given the huge difference in the amount of compute between levels, but possible). 72 */ 73 const uint _level; 74 75 //! The fragment number, used when a rendering job is split into multiple fragments. 76 const uint _fragment; 77 78 //! The number of fragments in the rendering job 79 const uint _number_of_fragments; 80 81 //! Whether samples should be jittered. 82 const bool _jittered_samples; 83 84 //! Multisampling grid resolution e.g 4 implies a 4x4 grid 85 const uint _multisample_grid; 86 87 //@{ 88 //! Track pixels computed, so tasks can be restarted after defer. Row and column are relative to the fragment origin. 89 uint _current_pixel; 90 int _current_col; 91 int _current_row; 92 uint _current_frame; 93 //@} 94 95 //! The image data generated for the fragments. 96 /*! This is lazily created to avoid multiple high resolution 97 images (especially with multisampling) being unnecessarily 98 concurrently allocated. 99 */ 100 mutable std::vector<QImage> _images; 101 102 //! Lazy allocator for _images (which is mutable) 103 void allocate_images() const; 104 105 //! Set true by pixel_advance when it advances off the last frame. 106 bool _completed; 107 108 //! Serial number, to fix some occasional out-of-order display problems 109 unsigned long long int _serial; 110 111 public: 112 //! Constructor. 113 MutatableImageComputerTask 114 ( 115 MutatableImageDisplay*const disp, 116 const boost::shared_ptr<const MutatableImage>& fn, 117 uint pri, 118 const QSize& fo, 119 const QSize& fs, 120 const QSize& wis, 121 uint f, 122 uint lev, 123 uint frag, 124 uint nfrag, 125 bool j, 126 uint ms, 127 unsigned long long int n 128 ); 129 130 //! Destructor. 131 ~MutatableImageComputerTask(); 132 133 //! Accessor. aborted()134 bool aborted() const 135 { 136 return _aborted; 137 } 138 139 //! Mark task as aborted. abort()140 void abort() 141 { 142 _aborted=true; 143 } 144 145 //! Accessor. display()146 MutatableImageDisplay* display() const 147 { 148 return _display; 149 } 150 151 //! Accessor. image_function()152 const boost::shared_ptr<const MutatableImage>& image_function() const 153 { 154 return _image_function; 155 } 156 157 //! Accessor. fragment_origin()158 const QSize& fragment_origin() const 159 { 160 return _fragment_origin; 161 } 162 163 //! Accessor. fragment_size()164 const QSize& fragment_size() const 165 { 166 return _fragment_size; 167 } 168 169 //! Accessor. whole_image_size()170 const QSize& whole_image_size() const 171 { 172 return _whole_image_size; 173 } 174 175 //! Accessor. frames()176 uint frames() const 177 { 178 return _frames; 179 } 180 181 //! Accessor. level()182 uint level() const 183 { 184 return _level; 185 } 186 187 //! Accessor. fragment()188 uint fragment() const 189 { 190 return _fragment; 191 } 192 193 //! Accessor. number_of_fragments()194 uint number_of_fragments() const 195 { 196 return _number_of_fragments; 197 } 198 199 //! Accessor. jittered_samples()200 bool jittered_samples() const 201 { 202 return _jittered_samples; 203 } 204 205 //! Accessor. multisample_grid()206 uint multisample_grid() const 207 { 208 return _multisample_grid; 209 } 210 211 //! Serial number serial()212 unsigned long long int serial() const 213 { 214 return _serial; 215 } 216 217 //! Accessor. priority()218 uint priority() const 219 { 220 return _priority; 221 } 222 223 //! Accessor, with lazy creation. images()224 std::vector<QImage>& images() 225 { 226 if (_images.empty()) allocate_images(); 227 return _images; 228 } 229 230 //! Accessor. images()231 const std::vector<QImage>& images() const 232 { 233 if (_images.empty()) allocate_images(); 234 return _images; 235 } 236 237 //! Accessor. current_col()238 uint current_col() const 239 { 240 return _current_col; 241 } 242 243 //! Accessor. current_row()244 uint current_row() const 245 { 246 return _current_row; 247 } 248 249 //! Accessor. current_frame()250 uint current_frame() const 251 { 252 return _current_frame; 253 } 254 255 //! Accessor. current_pixel()256 uint current_pixel() const 257 { 258 return _current_pixel; 259 } 260 261 //!Accessor. completed()262 bool completed() const 263 { 264 return _completed; 265 } 266 267 //! Increment pixel count, set completed flag if advanced off end of last frame. 268 void pixel_advance(); 269 }; 270 271 #endif 272