1 /*****************************************************************************/ 2 // Copyright 2006-2019 Adobe Systems Incorporated 3 // All Rights Reserved. 4 // 5 // NOTICE: Adobe permits you to use, modify, and distribute this file in 6 // accordance with the terms of the Adobe license agreement accompanying it. 7 /*****************************************************************************/ 8 9 /** \file 10 * Class to handle partitioning a rectangular image processing operation taking 11 * into account multiple processing resources and memory constraints. 12 */ 13 14 /*****************************************************************************/ 15 16 #ifndef __dng_area_task__ 17 #define __dng_area_task__ 18 19 /*****************************************************************************/ 20 21 #include "dng_classes.h" 22 #include "dng_point.h" 23 #include "dng_string.h" 24 #include "dng_types.h" 25 #include "dng_uncopyable.h" 26 27 /*****************************************************************************/ 28 29 class dng_area_task_progress: private dng_uncopyable 30 { 31 32 public: 33 ~dng_area_task_progress()34 virtual ~dng_area_task_progress () 35 { 36 } 37 38 virtual void FinishedTile (const dng_rect & /* tile */) = 0; 39 40 }; 41 42 /*****************************************************************************/ 43 44 /// \brief Abstract class for rectangular processing operations with support 45 /// for partitioning across multiple processing resources and observing memory 46 /// constraints. 47 48 class dng_area_task 49 { 50 51 protected: 52 53 uint32 fMaxThreads; 54 55 uint32 fMinTaskArea; 56 57 dng_point fUnitCell; 58 59 dng_point fMaxTileSize; 60 61 dng_string fName; 62 63 public: 64 65 explicit dng_area_task (const char *name = "unnamed dng_area_task"); 66 67 virtual ~dng_area_task (); 68 Name()69 const char * Name () const 70 { 71 return fName.Get (); 72 } 73 74 /// Getter for the maximum number of threads (resources) that can be 75 /// used for processing 76 /// 77 /// \retval Number of threads, minimum of 1, that can be used for this task. 78 MaxThreads()79 virtual uint32 MaxThreads () const 80 { 81 return fMaxThreads; 82 } 83 84 /// Getter for minimum area of a partitioned rectangle. 85 /// Often it is not profitable to use more resources if it requires 86 /// partitioning the input into chunks that are too small, as the 87 /// overhead increases more than the speedup. This method can be 88 /// ovreridden for a specific task to indicate the smallest area for 89 /// partitioning. Default is 256x256 pixels. 90 /// 91 /// \retval Minimum area for a partitoned tile in order to give performant 92 /// operation. (Partitions can be smaller due to small inputs and edge cases.) 93 MinTaskArea()94 virtual uint32 MinTaskArea () const 95 { 96 return fMinTaskArea; 97 } 98 99 /// Getter for dimensions of which partitioned tiles should be a multiple. 100 /// Various methods of processing prefer certain alignments. The 101 /// partitioning attempts to construct tiles such that the sizes are a 102 /// multiple of the dimensions of this point. 103 /// 104 /// \retval a point giving preferred alignment in x and y 105 UnitCell()106 virtual dng_point UnitCell () const 107 { 108 return fUnitCell; 109 } 110 111 /// Getter for maximum size of a tile for processing. 112 /// Often processing will need to allocate temporary buffers or use 113 /// other resources that are either fixed or in limited supply. The 114 /// maximum tile size forces further partitioning if the tile is bigger 115 /// than this size. 116 /// 117 /// \retval Maximum tile size allowed for this area task. 118 MaxTileSize()119 virtual dng_point MaxTileSize () const 120 { 121 return fMaxTileSize; 122 } 123 124 /// Getter for RepeatingTile1. 125 /// RepeatingTile1, RepeatingTile2, and RepeatingTile3 are used to 126 /// establish a set of 0 to 3 tile patterns for which the resulting 127 /// partitions that the final Process method is called on will not cross 128 /// tile boundaries in any of the tile patterns. This can be used for a 129 /// processing routine that needs to read from two tiles and write to a 130 /// third such that all the tiles are aligned and sized in a certain 131 /// way. A RepeatingTile value is valid if it is non-empty. Higher 132 /// numbered RepeatingTile patterns are only used if all lower ones are 133 /// non-empty. A RepeatingTile pattern must be a multiple of UnitCell in 134 /// size for all constraints of the partitionerr to be met. 135 136 virtual dng_rect RepeatingTile1 () const; 137 138 /// Getter for RepeatingTile2. 139 /// RepeatingTile1, RepeatingTile2, and RepeatingTile3 are used to 140 /// establish a set of 0 to 3 tile patterns for which the resulting 141 /// partitions that the final Process method is called on will not cross 142 /// tile boundaries in any of the tile patterns. This can be used for a 143 /// processing routine that needs to read from two tiles and write to a 144 /// third such that all the tiles are aligned and sized in a certain 145 /// way. A RepeatingTile value is valid if it is non-empty. Higher 146 /// numbered RepeatingTile patterns are only used if all lower ones are 147 /// non-empty. A RepeatingTile pattern must be a multiple of UnitCell in 148 /// size for all constraints of the partitionerr to be met. 149 150 virtual dng_rect RepeatingTile2 () const; 151 152 /// Getter for RepeatingTile3. 153 /// RepeatingTile1, RepeatingTile2, and RepeatingTile3 are used to 154 /// establish a set of 0 to 3 tile patterns for which the resulting 155 /// partitions that the final Process method is called on will not cross 156 /// tile boundaries in any of the tile patterns. This can be used for a 157 /// processing routine that needs to read from two tiles and write to a 158 /// third such that all the tiles are aligned and sized in a certain 159 /// way. A RepeatingTile value is valid if it is non-empty. Higher 160 /// numbered RepeatingTile patterns are only used if all lower ones are 161 /// non-empty. A RepeatingTile pattern must be a multiple of UnitCell in 162 /// size for all constraints of the partitionerr to be met. 163 164 virtual dng_rect RepeatingTile3 () const; 165 166 /// Task startup method called before any processing is done on partitions. 167 /// The Start method is called before any processing is done and can be 168 /// overridden to allocate temporary buffers, etc. 169 /// 170 /// \param threadCount Total number of threads that will be used for processing. 171 /// Less than or equal to MaxThreads. 172 /// \param dstArea Area to be processed in the current run of the task. 173 /// \param tileSize Size of source tiles which will be processed. 174 /// (Not all tiles will be this size due to edge conditions.) 175 /// \param allocator dng_memory_allocator to use for allocating temporary buffers, etc. 176 /// \param sniffer Sniffer to test for user cancellation and to set up progress. 177 178 virtual void Start (uint32 threadCount, 179 const dng_rect &dstArea, 180 const dng_point &tileSize, 181 dng_memory_allocator *allocator, 182 dng_abort_sniffer *sniffer); 183 184 /// Process one tile or fully partitioned area. This method is 185 /// overridden by derived classes to implement the actual image 186 /// processing. Note that the sniffer can be ignored if it is certain 187 /// that a processing task will complete very quickly. This method 188 /// should never be called directly but rather accessed via Process. 189 /// There is no allocator parameter as all allocation should be done in 190 /// Start. 191 /// 192 /// \param threadIndex 0 to threadCount - 1 index indicating which thread this is. 193 /// (Can be used to get a thread-specific buffer allocated in the Start method.) 194 /// \param tile Area to process. 195 /// \param sniffer dng_abort_sniffer to use to check for user cancellation 196 /// and progress updates. 197 198 virtual void Process (uint32 threadIndex, 199 const dng_rect &tile, 200 dng_abort_sniffer *sniffer) = 0; 201 202 /// Task computation finalization and teardown method. Called after all 203 /// resources have completed processing. Can be overridden to accumulate 204 /// results and free resources allocated in Start. 205 /// 206 /// \param threadCount Number of threads used for processing. Same as value passed to Start. 207 208 virtual void Finish (uint32 threadCount); 209 210 /// Find tile size taking into account repeating tiles, unit cell, and maximum tile size. 211 /// \param area Computation area for which to find tile size. 212 /// \retval Tile size as height and width in point. 213 214 dng_point FindTileSize (const dng_rect &area) const; 215 216 /// Handle one resource's worth of partitioned tiles. Called after 217 /// thread partitioning has already been done. Area may be further 218 /// subdivided to handle maximum tile size, etc. It will be rare to 219 /// override this method. 220 /// 221 /// \param threadIndex 0 to threadCount - 1 index indicating which thread this is. 222 /// \param area Tile area partitioned to this resource. 223 /// \param tileSize size of tiles to use for processing. 224 /// \param sniffer dng_abort_sniffer to use to check for user cancellation and progress updates. 225 /// \param progress optional pointer to progress reporting object. 226 227 void ProcessOnThread (uint32 threadIndex, 228 const dng_rect &area, 229 const dng_point &tileSize, 230 dng_abort_sniffer *sniffer, 231 dng_area_task_progress *progress); 232 233 /// Factory method to make a tile iterator. This iterator will be used 234 /// by a thread to process tiles in an area in a specific order. The 235 /// default implementation uses a forward iterator that visits tiles 236 /// from left to right (inner), top down (outer). Subclasses can 237 /// override this method to produce tile iterators that visit tiles in 238 /// different orders. 239 /// 240 /// \param threadIndex 0 to threadCount - 1 index indicating which thread this is. 241 /// \param tile The tile to be traversed within the tile area. 242 /// \param area Tile area partitioned to this resource. 243 244 virtual dng_base_tile_iterator * MakeTileIterator (uint32 threadIndex, 245 const dng_rect &tile, 246 const dng_rect &area) const; 247 248 /// Factory method to make a tile iterator. This iterator will be used 249 /// by a thread to process tiles in an area in a specific order. The 250 /// default implementation uses a forward iterator that visits tiles 251 /// from left to right (inner), top down (outer). Subclasses can 252 /// override this method to produce tile iterators that visit tiles in 253 /// different orders. 254 /// 255 /// \param threadIndex 0 to threadCount - 1 index indicating which thread this is. 256 /// \param tileSize The tile size to be traversed within the tile area. 257 /// \param area Tile area partitioned to this resource. 258 259 virtual dng_base_tile_iterator * MakeTileIterator (uint32 threadIndex, 260 const dng_point &tileSize, 261 const dng_rect &area) const; 262 263 /// Default resource partitioner that assumes a single resource to be 264 /// used for processing. Implementations that are aware of multiple 265 /// processing resources should override (replace) this method. This is 266 /// usually done in dng_host::PerformAreaTask. 267 /// 268 /// \param task The task to perform. 269 /// \param area The area on which mage processing should be performed. 270 /// \param allocator dng_memory_allocator to use for allocating temporary buffers, etc. 271 /// \param sniffer dng_abort_sniffer to use to check for user cancellation and progress updates. 272 /// \param progress optional pointer to progress reporting object. 273 274 static void Perform (dng_area_task &task, 275 const dng_rect &area, 276 dng_memory_allocator *allocator, 277 dng_abort_sniffer *sniffer, 278 dng_area_task_progress *progress); 279 280 }; 281 282 /*****************************************************************************/ 283 284 #endif 285 286 /*****************************************************************************/ 287