Mercurial > hgrepos > Python2 > PyMuPDF
comparison 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 |
comparison
equal
deleted
inserted
replaced
| 1:1d09e1dec1d9 | 2:b50eed0cc0ef |
|---|---|
| 1 //--------------------------------------------------------------------------------- | |
| 2 // | |
| 3 // Little Color Management System, fast floating point extensions | |
| 4 // Copyright (c) 1998-2023 Marti Maria Saguer, all rights reserved | |
| 5 // | |
| 6 // | |
| 7 // This program is free software: you can redistribute it and/or modify | |
| 8 // it under the terms of the GNU General Public License as published by | |
| 9 // the Free Software Foundation, either version 3 of the License, or | |
| 10 // (at your option) any later version. | |
| 11 // | |
| 12 // This program is distributed in the hope that it will be useful, | |
| 13 // but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 15 // GNU General Public License for more details. | |
| 16 // | |
| 17 // You should have received a copy of the GNU General Public License | |
| 18 // along with this program. If not, see <http://www.gnu.org/licenses/>. | |
| 19 // | |
| 20 //--------------------------------------------------------------------------------- | |
| 21 | |
| 22 | |
| 23 #include "threaded_internal.h" | |
| 24 | |
| 25 | |
| 26 // Returns true component size | |
| 27 cmsINLINE cmsUInt32Number ComponentSize(cmsUInt32Number format) | |
| 28 { | |
| 29 cmsUInt32Number BytesPerComponent = T_BYTES(format); | |
| 30 | |
| 31 // For double, the T_BYTES field is zero | |
| 32 if (BytesPerComponent == 0) | |
| 33 BytesPerComponent = sizeof(cmsUInt64Number); | |
| 34 | |
| 35 return BytesPerComponent; | |
| 36 } | |
| 37 | |
| 38 // Returns bytes from one pixel to the next | |
| 39 cmsINLINE cmsUInt32Number PixelSpacing(cmsUInt32Number format) | |
| 40 { | |
| 41 if (T_PLANAR(format)) | |
| 42 return ComponentSize(format); | |
| 43 else | |
| 44 return ComponentSize(format) * (T_CHANNELS(format) + T_EXTRA(format)); | |
| 45 } | |
| 46 | |
| 47 // macro is not portable | |
| 48 cmsINLINE cmsUInt32Number minimum(cmsUInt32Number a, cmsUInt32Number b) | |
| 49 { | |
| 50 return a < b ? a : b; | |
| 51 } | |
| 52 | |
| 53 | |
| 54 // Memory of block depends of planar or chunky. If lines is 1, then the stride does not contain | |
| 55 // information and we have to calculate the size. If lines > 1, then we can take line size from stride. | |
| 56 // if planar, total memory is number of planes per plane stride. If chunky memory is number of lines per | |
| 57 // line size. If line size is zero, then it should be computed. | |
| 58 static | |
| 59 cmsUInt32Number MemSize(cmsUInt32Number format, | |
| 60 cmsUInt32Number PixelsPerLine, | |
| 61 cmsUInt32Number LineCount, | |
| 62 cmsUInt32Number* BytesPerLine, | |
| 63 cmsUInt32Number BytesPerPlane) | |
| 64 { | |
| 65 if (T_PLANAR(format)) { | |
| 66 | |
| 67 if (*BytesPerLine == 0) { | |
| 68 | |
| 69 *BytesPerLine = ComponentSize(format) * PixelsPerLine; | |
| 70 } | |
| 71 | |
| 72 return (T_CHANNELS(format) + T_EXTRA(format)) * BytesPerPlane; | |
| 73 } | |
| 74 else | |
| 75 { | |
| 76 if (*BytesPerLine == 0) { | |
| 77 | |
| 78 *BytesPerLine = ComponentSize(format) * (T_CHANNELS(format) + T_EXTRA(format)) * PixelsPerLine; | |
| 79 } | |
| 80 | |
| 81 return LineCount * *BytesPerLine; | |
| 82 } | |
| 83 } | |
| 84 | |
| 85 // Compute how many workers to use. Repairs Stride if any missing member | |
| 86 cmsUInt32Number _cmsThrCountSlices(struct _cmstransform_struct* CMMcargo, cmsInt32Number MaxWorkers, | |
| 87 cmsUInt32Number PixelsPerLine, cmsUInt32Number LineCount, | |
| 88 cmsStride* Stride) | |
| 89 { | |
| 90 cmsInt32Number MaxInputMem, MaxOutputMem; | |
| 91 cmsInt32Number WorkerCount; | |
| 92 | |
| 93 cmsInt32Number MaxCPUs = _cmsThrIdealThreadCount(); | |
| 94 | |
| 95 if (MaxWorkers == CMS_THREADED_GUESS_MAX_THREADS) { | |
| 96 MaxWorkers = MaxCPUs; | |
| 97 } | |
| 98 else | |
| 99 { | |
| 100 // We allow large number of threads, but this is not going to work well. Warn it. | |
| 101 if (MaxWorkers > MaxCPUs) { | |
| 102 cmsSignalError(NULL, cmsERROR_RANGE, | |
| 103 "Warning: too many threads for actual processor (CPUs=%d, asked=%d)", MaxCPUs, MaxWorkers); | |
| 104 } | |
| 105 } | |
| 106 | |
| 107 MaxInputMem = MemSize(cmsGetTransformInputFormat((cmsHTRANSFORM)CMMcargo), | |
| 108 PixelsPerLine, LineCount, &Stride->BytesPerLineIn, Stride->BytesPerPlaneIn); | |
| 109 | |
| 110 MaxOutputMem = MemSize(cmsGetTransformOutputFormat((cmsHTRANSFORM)CMMcargo), | |
| 111 PixelsPerLine, LineCount, &Stride->BytesPerLineOut, Stride->BytesPerPlaneOut); | |
| 112 | |
| 113 // Each thread takes 128K at least | |
| 114 WorkerCount = (MaxInputMem + MaxOutputMem) / (128 * 1024); | |
| 115 | |
| 116 if (WorkerCount < 1) | |
| 117 WorkerCount = 1; | |
| 118 else | |
| 119 if (WorkerCount > MaxWorkers) | |
| 120 WorkerCount = MaxWorkers; | |
| 121 | |
| 122 return WorkerCount; | |
| 123 } | |
| 124 | |
| 125 // Slice input, output for lines | |
| 126 static | |
| 127 void SlicePerLines(const _cmsWorkSlice* master, cmsInt32Number nslices, | |
| 128 cmsInt32Number LinesPerSlice, _cmsWorkSlice slices[]) | |
| 129 { | |
| 130 cmsInt32Number i; | |
| 131 cmsInt32Number TotalLines = master ->LineCount; | |
| 132 | |
| 133 for (i = 0; i < nslices; i++) { | |
| 134 | |
| 135 const cmsUInt8Number* PtrInput = master->InputBuffer; | |
| 136 cmsUInt8Number* PtrOutput = master->OutputBuffer; | |
| 137 | |
| 138 cmsInt32Number lines = minimum(LinesPerSlice, TotalLines); | |
| 139 | |
| 140 memcpy(&slices[i], master, sizeof(_cmsWorkSlice)); | |
| 141 | |
| 142 slices[i].InputBuffer = PtrInput + i * LinesPerSlice * master->Stride->BytesPerLineIn; | |
| 143 slices[i].OutputBuffer = PtrOutput + i * LinesPerSlice * master->Stride->BytesPerLineOut; | |
| 144 | |
| 145 slices[i].LineCount = lines; | |
| 146 TotalLines -= lines; | |
| 147 } | |
| 148 | |
| 149 // Add left lines because rounding | |
| 150 if (slices > 0) slices[nslices - 1].LineCount += TotalLines; | |
| 151 } | |
| 152 | |
| 153 // Per pixels on big blocks of one line | |
| 154 static | |
| 155 void SlicePerPixels(const _cmsWorkSlice* master, cmsInt32Number nslices, | |
| 156 cmsInt32Number PixelsPerSlice, _cmsWorkSlice slices[]) | |
| 157 { | |
| 158 cmsInt32Number i; | |
| 159 cmsInt32Number TotalPixels = master->PixelsPerLine; // As this works on one line only | |
| 160 | |
| 161 cmsUInt32Number PixelSpacingIn = PixelSpacing(cmsGetTransformInputFormat((cmsHTRANSFORM)master->CMMcargo)); | |
| 162 cmsUInt32Number PixelSpacingOut = PixelSpacing(cmsGetTransformOutputFormat((cmsHTRANSFORM)master->CMMcargo)); | |
| 163 | |
| 164 for (i = 0; i < nslices; i++) { | |
| 165 | |
| 166 const cmsUInt8Number* PtrInput = master->InputBuffer; | |
| 167 cmsUInt8Number* PtrOutput = master->OutputBuffer; | |
| 168 | |
| 169 cmsInt32Number pixels = minimum(PixelsPerSlice, TotalPixels); | |
| 170 | |
| 171 memcpy(&slices[i], master, sizeof(_cmsWorkSlice)); | |
| 172 | |
| 173 slices[i].InputBuffer = PtrInput + i * PixelsPerSlice * PixelSpacingIn; | |
| 174 slices[i].OutputBuffer = PtrOutput + i * PixelsPerSlice * PixelSpacingOut; | |
| 175 slices[i].PixelsPerLine = pixels; | |
| 176 | |
| 177 TotalPixels -= pixels; | |
| 178 } | |
| 179 | |
| 180 // Add left pixels because rounding | |
| 181 if (slices > 0) slices[nslices - 1].PixelsPerLine += TotalPixels; | |
| 182 } | |
| 183 | |
| 184 | |
| 185 // If multiline, assign a number of lines to each thread. This works on chunky and planar. Stride parameters | |
| 186 // are not changed. In the case of one line, stride chunky is not used and stride planar keeps same. | |
| 187 cmsBool _cmsThrSplitWork(const _cmsWorkSlice* master, cmsInt32Number nslices, _cmsWorkSlice slices[]) | |
| 188 { | |
| 189 | |
| 190 // Check parameters | |
| 191 if (master->PixelsPerLine == 0 || | |
| 192 master->Stride->BytesPerLineIn == 0 || | |
| 193 master->Stride->BytesPerLineOut == 0) return FALSE; | |
| 194 | |
| 195 // Do the splitting depending on lines | |
| 196 if (master->LineCount <= 1) { | |
| 197 | |
| 198 cmsInt32Number PixelsPerWorker = master->PixelsPerLine / nslices; | |
| 199 | |
| 200 if (PixelsPerWorker <= 0) | |
| 201 return FALSE; | |
| 202 else | |
| 203 SlicePerPixels(master, nslices, PixelsPerWorker, slices); | |
| 204 } | |
| 205 else { | |
| 206 | |
| 207 cmsInt32Number LinesPerWorker = master->LineCount / nslices; | |
| 208 | |
| 209 if (LinesPerWorker <= 0) | |
| 210 return FALSE; | |
| 211 else | |
| 212 SlicePerLines(master, nslices, LinesPerWorker, slices); | |
| 213 } | |
| 214 | |
| 215 return TRUE; | |
| 216 } |
