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