#include "threaded_internal.h"
cmsINLINE cmsUInt32Number ComponentSize(cmsUInt32Number format)
{
cmsUInt32Number BytesPerComponent = T_BYTES(format);
if (BytesPerComponent == 0)
BytesPerComponent = sizeof(cmsUInt64Number);
return BytesPerComponent;
}
cmsINLINE cmsUInt32Number PixelSpacing(cmsUInt32Number format)
{
if (T_PLANAR(format))
return ComponentSize(format);
else
return ComponentSize(format) * (T_CHANNELS(format) + T_EXTRA(format));
}
cmsINLINE cmsUInt32Number minimum(cmsUInt32Number a, cmsUInt32Number b)
{
return a < b ? a : b;
}
static
cmsUInt32Number MemSize(cmsUInt32Number format,
cmsUInt32Number PixelsPerLine,
cmsUInt32Number LineCount,
cmsUInt32Number* BytesPerLine,
cmsUInt32Number BytesPerPlane)
{
if (T_PLANAR(format)) {
if (*BytesPerLine == 0) {
*BytesPerLine = ComponentSize(format) * PixelsPerLine;
}
return (T_CHANNELS(format) + T_EXTRA(format)) * BytesPerPlane;
}
else
{
if (*BytesPerLine == 0) {
*BytesPerLine = ComponentSize(format) * (T_CHANNELS(format) + T_EXTRA(format)) * PixelsPerLine;
}
return LineCount * *BytesPerLine;
}
}
cmsUInt32Number _cmsThrCountSlices(struct _cmstransform_struct* CMMcargo, cmsInt32Number MaxWorkers,
cmsUInt32Number PixelsPerLine, cmsUInt32Number LineCount,
cmsStride* Stride)
{
cmsInt32Number MaxInputMem, MaxOutputMem;
cmsInt32Number WorkerCount;
cmsInt32Number MaxCPUs = _cmsThrIdealThreadCount();
if (MaxWorkers == CMS_THREADED_GUESS_MAX_THREADS) {
MaxWorkers = MaxCPUs;
}
else
{
if (MaxWorkers > MaxCPUs) {
cmsSignalError(NULL, cmsERROR_RANGE,
"Warning: too many threads for actual processor (CPUs=%d, asked=%d)", MaxCPUs, MaxWorkers);
}
}
MaxInputMem = MemSize(cmsGetTransformInputFormat((cmsHTRANSFORM)CMMcargo),
PixelsPerLine, LineCount, &Stride->BytesPerLineIn, Stride->BytesPerPlaneIn);
MaxOutputMem = MemSize(cmsGetTransformOutputFormat((cmsHTRANSFORM)CMMcargo),
PixelsPerLine, LineCount, &Stride->BytesPerLineOut, Stride->BytesPerPlaneOut);
WorkerCount = (MaxInputMem + MaxOutputMem) / (128 * 1024);
if (WorkerCount < 1)
WorkerCount = 1;
else
if (WorkerCount > MaxWorkers)
WorkerCount = MaxWorkers;
return WorkerCount;
}
static
void SlicePerLines(const _cmsWorkSlice* master, cmsInt32Number nslices,
cmsInt32Number LinesPerSlice, _cmsWorkSlice slices[])
{
cmsInt32Number i;
cmsInt32Number TotalLines = master ->LineCount;
for (i = 0; i < nslices; i++) {
const cmsUInt8Number* PtrInput = master->InputBuffer;
cmsUInt8Number* PtrOutput = master->OutputBuffer;
cmsInt32Number lines = minimum(LinesPerSlice, TotalLines);
memcpy(&slices[i], master, sizeof(_cmsWorkSlice));
slices[i].InputBuffer = PtrInput + i * LinesPerSlice * master->Stride->BytesPerLineIn;
slices[i].OutputBuffer = PtrOutput + i * LinesPerSlice * master->Stride->BytesPerLineOut;
slices[i].LineCount = lines;
TotalLines -= lines;
}
if (slices > 0) slices[nslices - 1].LineCount += TotalLines;
}
static
void SlicePerPixels(const _cmsWorkSlice* master, cmsInt32Number nslices,
cmsInt32Number PixelsPerSlice, _cmsWorkSlice slices[])
{
cmsInt32Number i;
cmsInt32Number TotalPixels = master->PixelsPerLine;
cmsUInt32Number PixelSpacingIn = PixelSpacing(cmsGetTransformInputFormat((cmsHTRANSFORM)master->CMMcargo));
cmsUInt32Number PixelSpacingOut = PixelSpacing(cmsGetTransformOutputFormat((cmsHTRANSFORM)master->CMMcargo));
for (i = 0; i < nslices; i++) {
const cmsUInt8Number* PtrInput = master->InputBuffer;
cmsUInt8Number* PtrOutput = master->OutputBuffer;
cmsInt32Number pixels = minimum(PixelsPerSlice, TotalPixels);
memcpy(&slices[i], master, sizeof(_cmsWorkSlice));
slices[i].InputBuffer = PtrInput + i * PixelsPerSlice * PixelSpacingIn;
slices[i].OutputBuffer = PtrOutput + i * PixelsPerSlice * PixelSpacingOut;
slices[i].PixelsPerLine = pixels;
TotalPixels -= pixels;
}
if (slices > 0) slices[nslices - 1].PixelsPerLine += TotalPixels;
}
cmsBool _cmsThrSplitWork(const _cmsWorkSlice* master, cmsInt32Number nslices, _cmsWorkSlice slices[])
{
if (master->PixelsPerLine == 0 ||
master->Stride->BytesPerLineIn == 0 ||
master->Stride->BytesPerLineOut == 0) return FALSE;
if (master->LineCount <= 1) {
cmsInt32Number PixelsPerWorker = master->PixelsPerLine / nslices;
if (PixelsPerWorker <= 0)
return FALSE;
else
SlicePerPixels(master, nslices, PixelsPerWorker, slices);
}
else {
cmsInt32Number LinesPerWorker = master->LineCount / nslices;
if (LinesPerWorker <= 0)
return FALSE;
else
SlicePerLines(master, nslices, LinesPerWorker, slices);
}
return TRUE;
}