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