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 #include "dng_area_task.h"
10
11 #include "dng_abort_sniffer.h"
12 #include "dng_auto_ptr.h"
13 #include "dng_flags.h"
14 #include "dng_globals.h"
15 #include "dng_sdk_limits.h"
16 #include "dng_tile_iterator.h"
17 #include "dng_utils.h"
18
19 /*****************************************************************************/
20
dng_area_task(const char * name)21 dng_area_task::dng_area_task (const char *name)
22
23 : fMaxThreads (kMaxMPThreads)
24
25 , fMinTaskArea (256 * 256)
26
27 , fUnitCell (1, 1)
28
29 , fMaxTileSize (256, 256)
30
31 , fName ()
32
33 {
34
35 if (!name)
36 {
37 name = "dng_area_task";
38 }
39
40 fName.Set (name);
41
42 }
43
44 /*****************************************************************************/
45
~dng_area_task()46 dng_area_task::~dng_area_task ()
47 {
48
49 }
50
51 /*****************************************************************************/
52
RepeatingTile1() const53 dng_rect dng_area_task::RepeatingTile1 () const
54 {
55
56 return dng_rect ();
57
58 }
59
60 /*****************************************************************************/
61
RepeatingTile2() const62 dng_rect dng_area_task::RepeatingTile2 () const
63 {
64
65 return dng_rect ();
66
67 }
68
69 /*****************************************************************************/
70
RepeatingTile3() const71 dng_rect dng_area_task::RepeatingTile3 () const
72 {
73
74 return dng_rect ();
75
76 }
77
78 /*****************************************************************************/
79
Start(uint32,const dng_rect &,const dng_point &,dng_memory_allocator *,dng_abort_sniffer *)80 void dng_area_task::Start (uint32 /* threadCount */,
81 const dng_rect & /* dstArea */,
82 const dng_point & /* tileSize */,
83 dng_memory_allocator * /* allocator */,
84 dng_abort_sniffer * /* sniffer */)
85 {
86
87 }
88
89 /*****************************************************************************/
90
Finish(uint32)91 void dng_area_task::Finish (uint32 /* threadCount */)
92 {
93
94 }
95
96 /*****************************************************************************/
97
FindTileSize(const dng_rect & area) const98 dng_point dng_area_task::FindTileSize (const dng_rect &area) const
99 {
100
101 dng_rect repeatingTile1 = RepeatingTile1 ();
102 dng_rect repeatingTile2 = RepeatingTile2 ();
103 dng_rect repeatingTile3 = RepeatingTile3 ();
104
105 if (repeatingTile1.IsEmpty ())
106 {
107 repeatingTile1 = area;
108 }
109
110 if (repeatingTile2.IsEmpty ())
111 {
112 repeatingTile2 = area;
113 }
114
115 if (repeatingTile3.IsEmpty ())
116 {
117 repeatingTile3 = area;
118 }
119
120 uint32 repeatV = Min_uint32 (Min_uint32 (repeatingTile1.H (),
121 repeatingTile2.H ()),
122 repeatingTile3.H ());
123
124 uint32 repeatH = Min_uint32 (Min_uint32 (repeatingTile1.W (),
125 repeatingTile2.W ()),
126 repeatingTile3.W ());
127
128 dng_point maxTileSize = MaxTileSize ();
129
130 dng_point tileSize;
131
132 tileSize.v = Min_int32 (repeatV, maxTileSize.v);
133 tileSize.h = Min_int32 (repeatH, maxTileSize.h);
134
135 // Make Xcode happy (div by zero).
136
137 tileSize.v = Max_int32 (tileSize.v, 1);
138 tileSize.h = Max_int32 (tileSize.h, 1);
139
140 // What this is doing is, if the smallest repeating image tile is larger than the
141 // maximum tile size, adjusting the tile size down so that the tiles are as small
142 // as possible while still having the same number of tiles covering the
143 // repeat area. This makes the areas more equal in size, making MP
144 // algorithms work better.
145
146 // The image core team did not understand this code, and disabled it.
147 // Really stupid idea to turn off code you don't understand!
148 // I'm undoing this removal, because I think the code is correct and useful.
149
150 uint32 countV = (repeatV + tileSize.v - 1) / tileSize.v;
151 uint32 countH = (repeatH + tileSize.h - 1) / tileSize.h;
152
153 // Make Xcode happy (div by zero).
154
155 countV = Max_uint32 (countV, 1);
156 countH = Max_uint32 (countH, 1);
157
158 tileSize.v = (repeatV + countV - 1) / countV;
159 tileSize.h = (repeatH + countH - 1) / countH;
160
161 // Round up to unit cell size.
162
163 dng_point unitCell = UnitCell ();
164
165 if (unitCell.h != 1 || unitCell.v != 1)
166 {
167 tileSize.v = ((tileSize.v + unitCell.v - 1) / unitCell.v) * unitCell.v;
168 tileSize.h = ((tileSize.h + unitCell.h - 1) / unitCell.h) * unitCell.h;
169 }
170
171 // But if that is larger than maximum tile size, round down to unit cell size.
172
173 if (tileSize.v > maxTileSize.v)
174 {
175 tileSize.v = (maxTileSize.v / unitCell.v) * unitCell.v;
176 }
177
178 if (tileSize.h > maxTileSize.h)
179 {
180 tileSize.h = (maxTileSize.h / unitCell.h) * unitCell.h;
181 }
182
183 if (gPrintTimings)
184 {
185 fprintf (stdout,
186 "\nRender tile for below: %d x %d\n",
187 (int32) tileSize.h,
188 (int32) tileSize.v);
189 }
190
191 return tileSize;
192
193 }
194
195 /*****************************************************************************/
196
ProcessOnThread(uint32 threadIndex,const dng_rect & area,const dng_point & tileSize,dng_abort_sniffer * sniffer,dng_area_task_progress * progress)197 void dng_area_task::ProcessOnThread (uint32 threadIndex,
198 const dng_rect &area,
199 const dng_point &tileSize,
200 dng_abort_sniffer *sniffer,
201 dng_area_task_progress *progress)
202 {
203
204 dng_rect repeatingTile1 = RepeatingTile1 ();
205 dng_rect repeatingTile2 = RepeatingTile2 ();
206 dng_rect repeatingTile3 = RepeatingTile3 ();
207
208 if (repeatingTile1.IsEmpty ())
209 {
210 repeatingTile1 = area;
211 }
212
213 if (repeatingTile2.IsEmpty ())
214 {
215 repeatingTile2 = area;
216 }
217
218 if (repeatingTile3.IsEmpty ())
219 {
220 repeatingTile3 = area;
221 }
222
223 dng_rect tile1;
224
225 // TODO_EP: Review & document case where these dynamic allocations appeared to have significant overhead
226 AutoPtr<dng_base_tile_iterator> iter1
227 (MakeTileIterator (threadIndex,
228 repeatingTile3,
229 area));
230
231 while (iter1->GetOneTile (tile1))
232 {
233
234 dng_rect tile2;
235
236 AutoPtr<dng_base_tile_iterator> iter2
237 (MakeTileIterator (threadIndex,
238 repeatingTile2,
239 tile1));
240
241 while (iter2->GetOneTile (tile2))
242 {
243
244 dng_rect tile3;
245
246 AutoPtr<dng_base_tile_iterator> iter3
247 (MakeTileIterator (threadIndex,
248 repeatingTile1,
249 tile2));
250
251 while (iter3->GetOneTile (tile3))
252 {
253
254 dng_rect tile4;
255
256 AutoPtr<dng_base_tile_iterator> iter4
257 (MakeTileIterator (threadIndex,
258 tileSize,
259 tile3));
260
261 while (iter4->GetOneTile (tile4))
262 {
263
264 dng_abort_sniffer::SniffForAbort (sniffer);
265
266 Process (threadIndex, tile4, sniffer);
267
268 if (progress)
269 {
270 progress->FinishedTile (tile4);
271 }
272
273 }
274
275 }
276
277 }
278
279 }
280
281 }
282
283 /*****************************************************************************/
284
MakeTileIterator(uint32,const dng_rect & tile,const dng_rect & area) const285 dng_base_tile_iterator * dng_area_task::MakeTileIterator (uint32 /* threadIndex */,
286 const dng_rect &tile,
287 const dng_rect &area) const
288 {
289
290 return new dng_tile_forward_iterator (tile, area);
291
292 }
293
294 /*****************************************************************************/
295
MakeTileIterator(uint32,const dng_point & tileSize,const dng_rect & area) const296 dng_base_tile_iterator * dng_area_task::MakeTileIterator (uint32 /* threadIndex */,
297 const dng_point &tileSize,
298 const dng_rect &area) const
299 {
300
301 return new dng_tile_forward_iterator (tileSize, area);
302
303 }
304
305 /*****************************************************************************/
306
Perform(dng_area_task & task,const dng_rect & area,dng_memory_allocator * allocator,dng_abort_sniffer * sniffer,dng_area_task_progress * progress)307 void dng_area_task::Perform (dng_area_task &task,
308 const dng_rect &area,
309 dng_memory_allocator *allocator,
310 dng_abort_sniffer *sniffer,
311 dng_area_task_progress *progress)
312 {
313
314 dng_point tileSize (task.FindTileSize (area));
315
316 task.Start (1, area, tileSize, allocator, sniffer);
317
318 task.ProcessOnThread (0, area, tileSize, sniffer, progress);
319
320 task.Finish (1);
321
322 }
323
324 /*****************************************************************************/
325