/*****************************************************************************/ // Copyright 2006-2012 Adobe Systems Incorporated // All Rights Reserved. // // NOTICE: Adobe permits you to use, modify, and distribute this file in // accordance with the terms of the Adobe license agreement accompanying it. /*****************************************************************************/ /* $Id: //mondo/dng_sdk_1_4/dng_sdk/source/dng_area_task.cpp#1 $ */ /* $DateTime: 2012/05/30 13:28:51 $ */ /* $Change: 832332 $ */ /* $Author: tknoll $ */ /*****************************************************************************/ #include "dng_area_task.h" #include "dng_abort_sniffer.h" #include "dng_flags.h" #include "dng_sdk_limits.h" #include "dng_tile_iterator.h" #include "dng_utils.h" #if qImagecore extern bool gPrintTimings; #endif /*****************************************************************************/ dng_area_task::dng_area_task () : fMaxThreads (kMaxMPThreads) , fMinTaskArea (256 * 256) , fUnitCell (1, 1) , fMaxTileSize (256, 256) { } /*****************************************************************************/ dng_area_task::~dng_area_task () { } /*****************************************************************************/ dng_rect dng_area_task::RepeatingTile1 () const { return dng_rect (); } /*****************************************************************************/ dng_rect dng_area_task::RepeatingTile2 () const { return dng_rect (); } /*****************************************************************************/ dng_rect dng_area_task::RepeatingTile3 () const { return dng_rect (); } /*****************************************************************************/ void dng_area_task::Start (uint32 /* threadCount */, const dng_point & /* tileSize */, dng_memory_allocator * /* allocator */, dng_abort_sniffer * /* sniffer */) { } /*****************************************************************************/ void dng_area_task::Finish (uint32 /* threadCount */) { } /*****************************************************************************/ dng_point dng_area_task::FindTileSize (const dng_rect &area) const { dng_rect repeatingTile1 = RepeatingTile1 (); dng_rect repeatingTile2 = RepeatingTile2 (); dng_rect repeatingTile3 = RepeatingTile3 (); if (repeatingTile1.IsEmpty ()) { repeatingTile1 = area; } if (repeatingTile2.IsEmpty ()) { repeatingTile2 = area; } if (repeatingTile3.IsEmpty ()) { repeatingTile3 = area; } uint32 repeatV = Min_uint32 (Min_uint32 (repeatingTile1.H (), repeatingTile2.H ()), repeatingTile3.H ()); uint32 repeatH = Min_uint32 (Min_uint32 (repeatingTile1.W (), repeatingTile2.W ()), repeatingTile3.W ()); dng_point maxTileSize = MaxTileSize (); dng_point tileSize; tileSize.v = Min_int32 (repeatV, maxTileSize.v); tileSize.h = Min_int32 (repeatH, maxTileSize.h); // What this is doing is, if the smallest repeating image tile is larger than the // maximum tile size, adjusting the tile size down so that the tiles are as small // as possible while still having the same number of tiles covering the // repeat area. This makes the areas more equal in size, making MP // algorithms work better. // The image core team did not understand this code, and disabled it. // Really stupid idea to turn off code you don't understand! // I'm undoing this removal, because I think the code is correct and useful. uint32 countV = (repeatV + tileSize.v - 1) / tileSize.v; uint32 countH = (repeatH + tileSize.h - 1) / tileSize.h; tileSize.v = (repeatV + countV - 1) / countV; tileSize.h = (repeatH + countH - 1) / countH; // Round up to unit cell size. dng_point unitCell = UnitCell (); if (unitCell.h != 1 || unitCell.v != 1) { tileSize.v = ((tileSize.v + unitCell.v - 1) / unitCell.v) * unitCell.v; tileSize.h = ((tileSize.h + unitCell.h - 1) / unitCell.h) * unitCell.h; } // But if that is larger than maximum tile size, round down to unit cell size. if (tileSize.v > maxTileSize.v) { tileSize.v = (maxTileSize.v / unitCell.v) * unitCell.v; } if (tileSize.h > maxTileSize.h) { tileSize.h = (maxTileSize.h / unitCell.h) * unitCell.h; } #if qImagecore if (gPrintTimings) { fprintf (stdout, "\nRender tile for below: %d x %d\n", (int32) tileSize.h, (int32) tileSize.v); } #endif return tileSize; } /*****************************************************************************/ void dng_area_task::ProcessOnThread (uint32 threadIndex, const dng_rect &area, const dng_point &tileSize, dng_abort_sniffer *sniffer) { dng_rect repeatingTile1 = RepeatingTile1 (); dng_rect repeatingTile2 = RepeatingTile2 (); dng_rect repeatingTile3 = RepeatingTile3 (); if (repeatingTile1.IsEmpty ()) { repeatingTile1 = area; } if (repeatingTile2.IsEmpty ()) { repeatingTile2 = area; } if (repeatingTile3.IsEmpty ()) { repeatingTile3 = area; } dng_rect tile1; dng_tile_iterator iter1 (repeatingTile3, area); while (iter1.GetOneTile (tile1)) { dng_rect tile2; dng_tile_iterator iter2 (repeatingTile2, tile1); while (iter2.GetOneTile (tile2)) { dng_rect tile3; dng_tile_iterator iter3 (repeatingTile1, tile2); while (iter3.GetOneTile (tile3)) { dng_rect tile4; dng_tile_iterator iter4 (tileSize, tile3); while (iter4.GetOneTile (tile4)) { dng_abort_sniffer::SniffForAbort (sniffer); Process (threadIndex, tile4, sniffer); } } } } } /*****************************************************************************/ void dng_area_task::Perform (dng_area_task &task, const dng_rect &area, dng_memory_allocator *allocator, dng_abort_sniffer *sniffer) { dng_point tileSize (task.FindTileSize (area)); task.Start (1, tileSize, allocator, sniffer); task.ProcessOnThread (0, area, tileSize, sniffer); task.Finish (1); } /*****************************************************************************/