Mercurial > hgrepos > Python2 > PyMuPDF
diff mupdf-source/thirdparty/lcms2/plugins/threaded/src/threaded_split.c @ 2:b50eed0cc0ef upstream
ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4.
The directory name has changed: no version number in the expanded directory now.
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Mon, 15 Sep 2025 11:43:07 +0200 |
| parents | |
| children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mupdf-source/thirdparty/lcms2/plugins/threaded/src/threaded_split.c Mon Sep 15 11:43:07 2025 +0200 @@ -0,0 +1,216 @@ +//--------------------------------------------------------------------------------- +// +// Little Color Management System, fast floating point extensions +// Copyright (c) 1998-2023 Marti Maria Saguer, all rights reserved +// +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +// +//--------------------------------------------------------------------------------- + + +#include "threaded_internal.h" + + +// Returns true component size +cmsINLINE cmsUInt32Number ComponentSize(cmsUInt32Number format) +{ + cmsUInt32Number BytesPerComponent = T_BYTES(format); + + // For double, the T_BYTES field is zero + if (BytesPerComponent == 0) + BytesPerComponent = sizeof(cmsUInt64Number); + + return BytesPerComponent; +} + +// Returns bytes from one pixel to the next +cmsINLINE cmsUInt32Number PixelSpacing(cmsUInt32Number format) +{ + if (T_PLANAR(format)) + return ComponentSize(format); + else + return ComponentSize(format) * (T_CHANNELS(format) + T_EXTRA(format)); +} + +// macro is not portable +cmsINLINE cmsUInt32Number minimum(cmsUInt32Number a, cmsUInt32Number b) +{ + return a < b ? a : b; +} + + +// Memory of block depends of planar or chunky. If lines is 1, then the stride does not contain +// information and we have to calculate the size. If lines > 1, then we can take line size from stride. +// if planar, total memory is number of planes per plane stride. If chunky memory is number of lines per +// line size. If line size is zero, then it should be computed. +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; + } +} + +// Compute how many workers to use. Repairs Stride if any missing member +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 + { + // We allow large number of threads, but this is not going to work well. Warn it. + 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); + + // Each thread takes 128K at least + WorkerCount = (MaxInputMem + MaxOutputMem) / (128 * 1024); + + if (WorkerCount < 1) + WorkerCount = 1; + else + if (WorkerCount > MaxWorkers) + WorkerCount = MaxWorkers; + + return WorkerCount; +} + +// Slice input, output for lines +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; + } + + // Add left lines because rounding + if (slices > 0) slices[nslices - 1].LineCount += TotalLines; +} + +// Per pixels on big blocks of one line +static +void SlicePerPixels(const _cmsWorkSlice* master, cmsInt32Number nslices, + cmsInt32Number PixelsPerSlice, _cmsWorkSlice slices[]) +{ + cmsInt32Number i; + cmsInt32Number TotalPixels = master->PixelsPerLine; // As this works on one line only + + 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; + } + + // Add left pixels because rounding + if (slices > 0) slices[nslices - 1].PixelsPerLine += TotalPixels; +} + + +// If multiline, assign a number of lines to each thread. This works on chunky and planar. Stride parameters +// are not changed. In the case of one line, stride chunky is not used and stride planar keeps same. +cmsBool _cmsThrSplitWork(const _cmsWorkSlice* master, cmsInt32Number nslices, _cmsWorkSlice slices[]) +{ + + // Check parameters + if (master->PixelsPerLine == 0 || + master->Stride->BytesPerLineIn == 0 || + master->Stride->BytesPerLineOut == 0) return FALSE; + + // Do the splitting depending on lines + 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; +} \ No newline at end of file
