1/*****************************************************************************/
2// Copyright 2006-2012 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/* $Id: //mondo/dng_sdk_1_4/dng_sdk/source/dng_area_task.cpp#1 $ */
10/* $DateTime: 2012/05/30 13:28:51 $ */
11/* $Change: 832332 $ */
12/* $Author: tknoll $ */
13
14/*****************************************************************************/
15
16#include "dng_area_task.h"
17
18#include "dng_abort_sniffer.h"
19#include "dng_flags.h"
20#include "dng_sdk_limits.h"
21#include "dng_tile_iterator.h"
22#include "dng_utils.h"
23
24#if qImagecore
25extern bool gPrintTimings;
26#endif
27
28/*****************************************************************************/
29
30dng_area_task::dng_area_task ()
31
32	:	fMaxThreads   (kMaxMPThreads)
33
34	,	fMinTaskArea  (256 * 256)
35
36	,	fUnitCell	  (1, 1)
37
38	,	fMaxTileSize  (256, 256)
39
40	{
41
42	}
43
44/*****************************************************************************/
45
46dng_area_task::~dng_area_task ()
47	{
48
49	}
50
51/*****************************************************************************/
52
53dng_rect dng_area_task::RepeatingTile1 () const
54	{
55
56	return dng_rect ();
57
58	}
59
60/*****************************************************************************/
61
62dng_rect dng_area_task::RepeatingTile2 () const
63	{
64
65	return dng_rect ();
66
67	}
68
69/*****************************************************************************/
70
71dng_rect dng_area_task::RepeatingTile3 () const
72	{
73
74	return dng_rect ();
75
76	}
77
78/*****************************************************************************/
79
80void dng_area_task::Start (uint32 /* threadCount */,
81						   const dng_point & /* tileSize */,
82						   dng_memory_allocator * /* allocator */,
83						   dng_abort_sniffer * /* sniffer */)
84	{
85
86	}
87
88/*****************************************************************************/
89
90void dng_area_task::Finish (uint32 /* threadCount */)
91	{
92
93	}
94
95/*****************************************************************************/
96
97dng_point dng_area_task::FindTileSize (const dng_rect &area) const
98	{
99
100	dng_rect repeatingTile1 = RepeatingTile1 ();
101	dng_rect repeatingTile2 = RepeatingTile2 ();
102	dng_rect repeatingTile3 = RepeatingTile3 ();
103
104	if (repeatingTile1.IsEmpty ())
105		{
106		repeatingTile1 = area;
107		}
108
109	if (repeatingTile2.IsEmpty ())
110		{
111		repeatingTile2 = area;
112		}
113
114	if (repeatingTile3.IsEmpty ())
115		{
116		repeatingTile3 = area;
117		}
118
119	uint32 repeatV = Min_uint32 (Min_uint32 (repeatingTile1.H (),
120											 repeatingTile2.H ()),
121											 repeatingTile3.H ());
122
123	uint32 repeatH = Min_uint32 (Min_uint32 (repeatingTile1.W (),
124											 repeatingTile2.W ()),
125											 repeatingTile3.W ());
126
127	dng_point maxTileSize = MaxTileSize ();
128
129	dng_point tileSize;
130
131	tileSize.v = Min_int32 (repeatV, maxTileSize.v);
132	tileSize.h = Min_int32 (repeatH, maxTileSize.h);
133
134	// What this is doing is, if the smallest repeating image tile is larger than the
135	// maximum tile size, adjusting the tile size down so that the tiles are as small
136	// as possible while still having the same number of tiles covering the
137	// repeat area.  This makes the areas more equal in size, making MP
138	// algorithms work better.
139
140	// The image core team did not understand this code, and disabled it.
141	// Really stupid idea to turn off code you don't understand!
142	// I'm undoing this removal, because I think the code is correct and useful.
143
144	uint32 countV = (repeatV + tileSize.v - 1) / tileSize.v;
145	uint32 countH = (repeatH + tileSize.h - 1) / tileSize.h;
146
147	tileSize.v = (repeatV + countV - 1) / countV;
148	tileSize.h = (repeatH + countH - 1) / countH;
149
150	// Round up to unit cell size.
151
152	dng_point unitCell = UnitCell ();
153
154	if (unitCell.h != 1 || unitCell.v != 1)
155		{
156		tileSize.v = ((tileSize.v + unitCell.v - 1) / unitCell.v) * unitCell.v;
157		tileSize.h = ((tileSize.h + unitCell.h - 1) / unitCell.h) * unitCell.h;
158		}
159
160	// But if that is larger than maximum tile size, round down to unit cell size.
161
162	if (tileSize.v > maxTileSize.v)
163		{
164		tileSize.v = (maxTileSize.v / unitCell.v) * unitCell.v;
165		}
166
167	if (tileSize.h > maxTileSize.h)
168		{
169		tileSize.h = (maxTileSize.h / unitCell.h) * unitCell.h;
170		}
171
172	#if qImagecore
173    if (gPrintTimings)
174		{
175        fprintf (stdout, "\nRender tile for below: %d x %d\n", (int32) tileSize.h, (int32) tileSize.v);
176		}
177	#endif
178
179	return tileSize;
180
181	}
182
183/*****************************************************************************/
184
185void dng_area_task::ProcessOnThread (uint32 threadIndex,
186									 const dng_rect &area,
187									 const dng_point &tileSize,
188									 dng_abort_sniffer *sniffer)
189	{
190
191	dng_rect repeatingTile1 = RepeatingTile1 ();
192	dng_rect repeatingTile2 = RepeatingTile2 ();
193	dng_rect repeatingTile3 = RepeatingTile3 ();
194
195	if (repeatingTile1.IsEmpty ())
196		{
197		repeatingTile1 = area;
198		}
199
200	if (repeatingTile2.IsEmpty ())
201		{
202		repeatingTile2 = area;
203		}
204
205	if (repeatingTile3.IsEmpty ())
206		{
207		repeatingTile3 = area;
208		}
209
210	dng_rect tile1;
211
212	dng_tile_iterator iter1 (repeatingTile3, area);
213
214	while (iter1.GetOneTile (tile1))
215		{
216
217		dng_rect tile2;
218
219		dng_tile_iterator iter2 (repeatingTile2, tile1);
220
221		while (iter2.GetOneTile (tile2))
222			{
223
224			dng_rect tile3;
225
226			dng_tile_iterator iter3 (repeatingTile1, tile2);
227
228			while (iter3.GetOneTile (tile3))
229				{
230
231				dng_rect tile4;
232
233				dng_tile_iterator iter4 (tileSize, tile3);
234
235				while (iter4.GetOneTile (tile4))
236					{
237
238					dng_abort_sniffer::SniffForAbort (sniffer);
239
240					Process (threadIndex, tile4, sniffer);
241
242					}
243
244				}
245
246			}
247
248		}
249
250	}
251
252/*****************************************************************************/
253
254void dng_area_task::Perform (dng_area_task &task,
255				  			 const dng_rect &area,
256				  			 dng_memory_allocator *allocator,
257				  			 dng_abort_sniffer *sniffer)
258	{
259
260	dng_point tileSize (task.FindTileSize (area));
261
262	task.Start (1, tileSize, allocator, sniffer);
263
264	task.ProcessOnThread (0, area, tileSize, sniffer);
265
266	task.Finish (1);
267
268	}
269
270/*****************************************************************************/
271