xref: /aosp_15_r20/external/skia/src/codec/SkSwizzler.h (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker  * Copyright 2015 Google Inc.
3*c8dee2aaSAndroid Build Coastguard Worker  *
4*c8dee2aaSAndroid Build Coastguard Worker  * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker  * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker  */
7*c8dee2aaSAndroid Build Coastguard Worker 
8*c8dee2aaSAndroid Build Coastguard Worker #ifndef SkSwizzler_DEFINED
9*c8dee2aaSAndroid Build Coastguard Worker #define SkSwizzler_DEFINED
10*c8dee2aaSAndroid Build Coastguard Worker 
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/codec/SkCodec.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColor.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTypes.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "src/codec/SkSampler.h"
15*c8dee2aaSAndroid Build Coastguard Worker 
16*c8dee2aaSAndroid Build Coastguard Worker #include <cstddef>
17*c8dee2aaSAndroid Build Coastguard Worker #include <cstdint>
18*c8dee2aaSAndroid Build Coastguard Worker #include <memory>
19*c8dee2aaSAndroid Build Coastguard Worker 
20*c8dee2aaSAndroid Build Coastguard Worker struct SkEncodedInfo;
21*c8dee2aaSAndroid Build Coastguard Worker struct SkIRect;
22*c8dee2aaSAndroid Build Coastguard Worker struct SkImageInfo;
23*c8dee2aaSAndroid Build Coastguard Worker 
24*c8dee2aaSAndroid Build Coastguard Worker class SkSwizzler : public SkSampler {
25*c8dee2aaSAndroid Build Coastguard Worker public:
26*c8dee2aaSAndroid Build Coastguard Worker     /**
27*c8dee2aaSAndroid Build Coastguard Worker      *  Create a new SkSwizzler.
28*c8dee2aaSAndroid Build Coastguard Worker      *  @param encodedInfo Description of the format of the encoded data.
29*c8dee2aaSAndroid Build Coastguard Worker      *  @param ctable Unowned pointer to an array of up to 256 colors for an
30*c8dee2aaSAndroid Build Coastguard Worker      *                index source.
31*c8dee2aaSAndroid Build Coastguard Worker      *  @param dstInfo Describes the destination.
32*c8dee2aaSAndroid Build Coastguard Worker      *  @param options Contains partial scanline information and whether the dst is zero-
33*c8dee2aaSAndroid Build Coastguard Worker      *                 initialized.
34*c8dee2aaSAndroid Build Coastguard Worker      *  @param frame   Is non-NULL if the source pixels are part of an image
35*c8dee2aaSAndroid Build Coastguard Worker      *                 frame that is a subset of the full image.
36*c8dee2aaSAndroid Build Coastguard Worker      *
37*c8dee2aaSAndroid Build Coastguard Worker      *  Note that a deeper discussion of partial scanline subsets and image frame
38*c8dee2aaSAndroid Build Coastguard Worker      *  subsets is below.  Currently, we do not support both simultaneously.  If
39*c8dee2aaSAndroid Build Coastguard Worker      *  options->fSubset is non-NULL, frame must be NULL.
40*c8dee2aaSAndroid Build Coastguard Worker      *
41*c8dee2aaSAndroid Build Coastguard Worker      *  @return A new SkSwizzler or nullptr on failure.
42*c8dee2aaSAndroid Build Coastguard Worker      */
43*c8dee2aaSAndroid Build Coastguard Worker     static std::unique_ptr<SkSwizzler> Make(const SkEncodedInfo& encodedInfo,
44*c8dee2aaSAndroid Build Coastguard Worker             const SkPMColor* ctable, const SkImageInfo& dstInfo, const SkCodec::Options&,
45*c8dee2aaSAndroid Build Coastguard Worker             const SkIRect* frame = nullptr);
46*c8dee2aaSAndroid Build Coastguard Worker 
47*c8dee2aaSAndroid Build Coastguard Worker     /**
48*c8dee2aaSAndroid Build Coastguard Worker      *  Create a simplified swizzler that does not need to do format conversion. The swizzler
49*c8dee2aaSAndroid Build Coastguard Worker      *  only needs to sample and/or subset.
50*c8dee2aaSAndroid Build Coastguard Worker      *
51*c8dee2aaSAndroid Build Coastguard Worker      *  @param srcBPP Bytes per pixel of the source.
52*c8dee2aaSAndroid Build Coastguard Worker      *  @param dstInfo Describes the destination.
53*c8dee2aaSAndroid Build Coastguard Worker      *  @param options Contains partial scanline information and whether the dst is zero-
54*c8dee2aaSAndroid Build Coastguard Worker      *                 initialized.
55*c8dee2aaSAndroid Build Coastguard Worker      *  @return A new SkSwizzler or nullptr on failure.
56*c8dee2aaSAndroid Build Coastguard Worker      */
57*c8dee2aaSAndroid Build Coastguard Worker     static std::unique_ptr<SkSwizzler> MakeSimple(int srcBPP,
58*c8dee2aaSAndroid Build Coastguard Worker                                                   const SkImageInfo& dstInfo,
59*c8dee2aaSAndroid Build Coastguard Worker                                                   const SkCodec::Options&,
60*c8dee2aaSAndroid Build Coastguard Worker                                                   const SkIRect* frame = nullptr);
61*c8dee2aaSAndroid Build Coastguard Worker 
62*c8dee2aaSAndroid Build Coastguard Worker     /**
63*c8dee2aaSAndroid Build Coastguard Worker      *  Swizzle a line. Generally this will be called height times, once
64*c8dee2aaSAndroid Build Coastguard Worker      *  for each row of source.
65*c8dee2aaSAndroid Build Coastguard Worker      *  By allowing the caller to pass in the dst pointer, we give the caller
66*c8dee2aaSAndroid Build Coastguard Worker      *  flexibility to use the swizzler even when the encoded data does not
67*c8dee2aaSAndroid Build Coastguard Worker      *  store the rows in order.  This also improves usability for scaled and
68*c8dee2aaSAndroid Build Coastguard Worker      *  subset decodes.
69*c8dee2aaSAndroid Build Coastguard Worker      *  @param dst Where we write the output.
70*c8dee2aaSAndroid Build Coastguard Worker      *  @param src The next row of the source data.
71*c8dee2aaSAndroid Build Coastguard Worker      */
72*c8dee2aaSAndroid Build Coastguard Worker     void swizzle(void* dst, const uint8_t* SK_RESTRICT src);
73*c8dee2aaSAndroid Build Coastguard Worker 
fillWidth()74*c8dee2aaSAndroid Build Coastguard Worker     int fillWidth() const override {
75*c8dee2aaSAndroid Build Coastguard Worker         return fAllocatedWidth;
76*c8dee2aaSAndroid Build Coastguard Worker     }
77*c8dee2aaSAndroid Build Coastguard Worker 
78*c8dee2aaSAndroid Build Coastguard Worker     /**
79*c8dee2aaSAndroid Build Coastguard Worker      *  If fSampleX > 1, the swizzler is sampling every fSampleX'th pixel and
80*c8dee2aaSAndroid Build Coastguard Worker      *  discarding the rest.
81*c8dee2aaSAndroid Build Coastguard Worker      *
82*c8dee2aaSAndroid Build Coastguard Worker      *  This getter is currently used by SkBmpStandardCodec for Bmp-in-Ico decodes.
83*c8dee2aaSAndroid Build Coastguard Worker      *  Ideally, the subclasses of SkCodec would have no knowledge of sampling, but
84*c8dee2aaSAndroid Build Coastguard Worker      *  this allows us to apply a transparency mask to pixels after swizzling.
85*c8dee2aaSAndroid Build Coastguard Worker      */
sampleX()86*c8dee2aaSAndroid Build Coastguard Worker     int sampleX() const { return fSampleX; }
87*c8dee2aaSAndroid Build Coastguard Worker 
88*c8dee2aaSAndroid Build Coastguard Worker     /**
89*c8dee2aaSAndroid Build Coastguard Worker      *  Returns the actual number of pixels written to destination memory, taking
90*c8dee2aaSAndroid Build Coastguard Worker      *  scaling, subsetting, and partial frames into account.
91*c8dee2aaSAndroid Build Coastguard Worker      */
swizzleWidth()92*c8dee2aaSAndroid Build Coastguard Worker     int swizzleWidth() const { return fSwizzleWidth; }
93*c8dee2aaSAndroid Build Coastguard Worker 
94*c8dee2aaSAndroid Build Coastguard Worker     /**
95*c8dee2aaSAndroid Build Coastguard Worker      *  Returns the byte offset at which we write to destination memory, taking
96*c8dee2aaSAndroid Build Coastguard Worker      *  scaling, subsetting, and partial frames into account.
97*c8dee2aaSAndroid Build Coastguard Worker      */
swizzleOffsetBytes()98*c8dee2aaSAndroid Build Coastguard Worker     size_t swizzleOffsetBytes() const { return fDstOffsetBytes; }
99*c8dee2aaSAndroid Build Coastguard Worker 
100*c8dee2aaSAndroid Build Coastguard Worker private:
101*c8dee2aaSAndroid Build Coastguard Worker 
102*c8dee2aaSAndroid Build Coastguard Worker     /**
103*c8dee2aaSAndroid Build Coastguard Worker      *  Method for converting raw data to Skia pixels.
104*c8dee2aaSAndroid Build Coastguard Worker      *  @param dstRow Row in which to write the resulting pixels.
105*c8dee2aaSAndroid Build Coastguard Worker      *  @param src Row of src data, in format specified by SrcConfig
106*c8dee2aaSAndroid Build Coastguard Worker      *  @param dstWidth Width in pixels of the destination
107*c8dee2aaSAndroid Build Coastguard Worker      *  @param bpp if bitsPerPixel % 8 == 0, deltaSrc is bytesPerPixel
108*c8dee2aaSAndroid Build Coastguard Worker      *             else, deltaSrc is bitsPerPixel
109*c8dee2aaSAndroid Build Coastguard Worker      *  @param deltaSrc bpp * sampleX
110*c8dee2aaSAndroid Build Coastguard Worker      *  @param ctable Colors (used for kIndex source).
111*c8dee2aaSAndroid Build Coastguard Worker      *  @param offset The offset before the first pixel to sample.
112*c8dee2aaSAndroid Build Coastguard Worker                         Is in bytes or bits based on what deltaSrc is in.
113*c8dee2aaSAndroid Build Coastguard Worker      */
114*c8dee2aaSAndroid Build Coastguard Worker     typedef void (*RowProc)(void* SK_RESTRICT dstRow,
115*c8dee2aaSAndroid Build Coastguard Worker                             const uint8_t* SK_RESTRICT src,
116*c8dee2aaSAndroid Build Coastguard Worker                             int dstWidth, int bpp, int deltaSrc, int offset,
117*c8dee2aaSAndroid Build Coastguard Worker                             const SkPMColor ctable[]);
118*c8dee2aaSAndroid Build Coastguard Worker 
119*c8dee2aaSAndroid Build Coastguard Worker     template <RowProc Proc>
120*c8dee2aaSAndroid Build Coastguard Worker     static void SkipLeading8888ZerosThen(void* SK_RESTRICT dstRow,
121*c8dee2aaSAndroid Build Coastguard Worker                                          const uint8_t* SK_RESTRICT src,
122*c8dee2aaSAndroid Build Coastguard Worker                                          int dstWidth, int bpp, int deltaSrc, int offset,
123*c8dee2aaSAndroid Build Coastguard Worker                                          const SkPMColor ctable[]);
124*c8dee2aaSAndroid Build Coastguard Worker 
125*c8dee2aaSAndroid Build Coastguard Worker     template <RowProc Proc>
126*c8dee2aaSAndroid Build Coastguard Worker     static void SkipLeadingGrayAlphaZerosThen(void* dst, const uint8_t* src, int width, int bpp,
127*c8dee2aaSAndroid Build Coastguard Worker                                               int deltaSrc, int offset, const SkPMColor ctable[]);
128*c8dee2aaSAndroid Build Coastguard Worker 
129*c8dee2aaSAndroid Build Coastguard Worker     // May be NULL.  We have not implemented optimized functions for all supported transforms.
130*c8dee2aaSAndroid Build Coastguard Worker     const RowProc       fFastProc;
131*c8dee2aaSAndroid Build Coastguard Worker     // Always non-NULL.  Supports sampling.
132*c8dee2aaSAndroid Build Coastguard Worker     const RowProc       fSlowProc;
133*c8dee2aaSAndroid Build Coastguard Worker     // The actual RowProc we are using.  This depends on if fFastProc is non-NULL and
134*c8dee2aaSAndroid Build Coastguard Worker     // whether or not we are sampling.
135*c8dee2aaSAndroid Build Coastguard Worker     RowProc             fActualProc;
136*c8dee2aaSAndroid Build Coastguard Worker 
137*c8dee2aaSAndroid Build Coastguard Worker     const SkPMColor*    fColorTable;      // Unowned pointer
138*c8dee2aaSAndroid Build Coastguard Worker 
139*c8dee2aaSAndroid Build Coastguard Worker     // Subset Swizzles
140*c8dee2aaSAndroid Build Coastguard Worker     // There are two types of subset swizzles that we support.  We do not
141*c8dee2aaSAndroid Build Coastguard Worker     // support both at the same time.
142*c8dee2aaSAndroid Build Coastguard Worker     // TODO: If we want to support partial scanlines for gifs (which may
143*c8dee2aaSAndroid Build Coastguard Worker     //       use frame subsets), we will need to support both subsetting
144*c8dee2aaSAndroid Build Coastguard Worker     //       modes at the same time.
145*c8dee2aaSAndroid Build Coastguard Worker     // (1) Partial Scanlines
146*c8dee2aaSAndroid Build Coastguard Worker     //         The client only wants to write a subset of the source pixels
147*c8dee2aaSAndroid Build Coastguard Worker     //         to the destination.  This subset is specified to CreateSwizzler
148*c8dee2aaSAndroid Build Coastguard Worker     //         using options->fSubset.  We will store subset information in
149*c8dee2aaSAndroid Build Coastguard Worker     //         the following fields.
150*c8dee2aaSAndroid Build Coastguard Worker     //
151*c8dee2aaSAndroid Build Coastguard Worker     //         fSrcOffset:      The starting pixel of the source.
152*c8dee2aaSAndroid Build Coastguard Worker     //         fSrcOffsetUnits: Derived from fSrcOffset with two key
153*c8dee2aaSAndroid Build Coastguard Worker     //                          differences:
154*c8dee2aaSAndroid Build Coastguard Worker     //                          (1) This takes the size of source pixels into
155*c8dee2aaSAndroid Build Coastguard Worker     //                          account by multiplying by fSrcBPP.  This may
156*c8dee2aaSAndroid Build Coastguard Worker     //                          be measured in bits or bytes depending on
157*c8dee2aaSAndroid Build Coastguard Worker     //                          which is natural for the SrcConfig.
158*c8dee2aaSAndroid Build Coastguard Worker     //                          (2) If we are sampling, this will be larger
159*c8dee2aaSAndroid Build Coastguard Worker     //                          than fSrcOffset * fSrcBPP, since sampling
160*c8dee2aaSAndroid Build Coastguard Worker     //                          implies that we will skip some pixels.
161*c8dee2aaSAndroid Build Coastguard Worker     //         fDstOffset:      Will be zero.  There is no destination offset
162*c8dee2aaSAndroid Build Coastguard Worker     //                          for this type of subset.
163*c8dee2aaSAndroid Build Coastguard Worker     //         fDstOffsetBytes: Will be zero.
164*c8dee2aaSAndroid Build Coastguard Worker     //         fSrcWidth:       The width of the desired subset of source
165*c8dee2aaSAndroid Build Coastguard Worker     //                          pixels, before any sampling is performed.
166*c8dee2aaSAndroid Build Coastguard Worker     //         fDstWidth:       Will be equal to fSrcWidth, since this is also
167*c8dee2aaSAndroid Build Coastguard Worker     //                          calculated before any sampling is performed.
168*c8dee2aaSAndroid Build Coastguard Worker     //                          For this type of subset, the destination width
169*c8dee2aaSAndroid Build Coastguard Worker     //                          matches the desired subset of the source.
170*c8dee2aaSAndroid Build Coastguard Worker     //         fSwizzleWidth:   The actual number of pixels that will be
171*c8dee2aaSAndroid Build Coastguard Worker     //                          written by the RowProc.  This is a scaled
172*c8dee2aaSAndroid Build Coastguard Worker     //                          version of fSrcWidth/fDstWidth.
173*c8dee2aaSAndroid Build Coastguard Worker     //         fAllocatedWidth: Will be equal to fSwizzleWidth.  For this type
174*c8dee2aaSAndroid Build Coastguard Worker     //                          of subset, the number of pixels written is the
175*c8dee2aaSAndroid Build Coastguard Worker     //                          same as the actual width of the destination.
176*c8dee2aaSAndroid Build Coastguard Worker     // (2) Frame Subset
177*c8dee2aaSAndroid Build Coastguard Worker     //         The client will decode the entire width of the source into a
178*c8dee2aaSAndroid Build Coastguard Worker     //         subset of destination memory.  This subset is specified to
179*c8dee2aaSAndroid Build Coastguard Worker     //         CreateSwizzler in the "frame" parameter.  We store subset
180*c8dee2aaSAndroid Build Coastguard Worker     //         information in the following fields.
181*c8dee2aaSAndroid Build Coastguard Worker     //
182*c8dee2aaSAndroid Build Coastguard Worker     //         fSrcOffset:      Will be zero.  The starting pixel of the source.
183*c8dee2aaSAndroid Build Coastguard Worker     //         fSrcOffsetUnits: Will only be non-zero if we are sampling,
184*c8dee2aaSAndroid Build Coastguard Worker     //                          since sampling implies that we will skip some
185*c8dee2aaSAndroid Build Coastguard Worker     //                          pixels.  Note that this is measured in bits
186*c8dee2aaSAndroid Build Coastguard Worker     //                          or bytes depending on which is natural for
187*c8dee2aaSAndroid Build Coastguard Worker     //                          SrcConfig.
188*c8dee2aaSAndroid Build Coastguard Worker     //         fDstOffset:      First pixel to write in destination.
189*c8dee2aaSAndroid Build Coastguard Worker     //         fDstOffsetBytes: fDstOffset * fDstBPP.
190*c8dee2aaSAndroid Build Coastguard Worker     //         fSrcWidth:       The entire width of the source pixels, before
191*c8dee2aaSAndroid Build Coastguard Worker     //                          any sampling is performed.
192*c8dee2aaSAndroid Build Coastguard Worker     //         fDstWidth:       The entire width of the destination memory,
193*c8dee2aaSAndroid Build Coastguard Worker     //                          before any sampling is performed.
194*c8dee2aaSAndroid Build Coastguard Worker     //         fSwizzleWidth:   The actual number of pixels that will be
195*c8dee2aaSAndroid Build Coastguard Worker     //                          written by the RowProc.  This is a scaled
196*c8dee2aaSAndroid Build Coastguard Worker     //                          version of fSrcWidth.
197*c8dee2aaSAndroid Build Coastguard Worker     //         fAllocatedWidth: The actual number of pixels in destination
198*c8dee2aaSAndroid Build Coastguard Worker     //                          memory.  This is a scaled version of
199*c8dee2aaSAndroid Build Coastguard Worker     //                          fDstWidth.
200*c8dee2aaSAndroid Build Coastguard Worker     //
201*c8dee2aaSAndroid Build Coastguard Worker     // If we are not subsetting, these fields are more straightforward.
202*c8dee2aaSAndroid Build Coastguard Worker     //         fSrcOffset = fDstOffet = fDstOffsetBytes = 0
203*c8dee2aaSAndroid Build Coastguard Worker     //         fSrcOffsetUnits may be non-zero (we will skip the first few pixels when sampling)
204*c8dee2aaSAndroid Build Coastguard Worker     //         fSrcWidth = fDstWidth = Full original width
205*c8dee2aaSAndroid Build Coastguard Worker     //         fSwizzleWidth = fAllcoatedWidth = Scaled width (if we are sampling)
206*c8dee2aaSAndroid Build Coastguard Worker     const int           fSrcOffset;
207*c8dee2aaSAndroid Build Coastguard Worker     const int           fDstOffset;
208*c8dee2aaSAndroid Build Coastguard Worker     int                 fSrcOffsetUnits;
209*c8dee2aaSAndroid Build Coastguard Worker     int                 fDstOffsetBytes;
210*c8dee2aaSAndroid Build Coastguard Worker     const int           fSrcWidth;
211*c8dee2aaSAndroid Build Coastguard Worker     const int           fDstWidth;
212*c8dee2aaSAndroid Build Coastguard Worker     int                 fSwizzleWidth;
213*c8dee2aaSAndroid Build Coastguard Worker     int                 fAllocatedWidth;
214*c8dee2aaSAndroid Build Coastguard Worker 
215*c8dee2aaSAndroid Build Coastguard Worker     int                 fSampleX;         // Step between X samples
216*c8dee2aaSAndroid Build Coastguard Worker     const int           fSrcBPP;          // Bits/bytes per pixel for the SrcConfig
217*c8dee2aaSAndroid Build Coastguard Worker                                           // if bitsPerPixel % 8 == 0
218*c8dee2aaSAndroid Build Coastguard Worker                                           //     fBPP is bytesPerPixel
219*c8dee2aaSAndroid Build Coastguard Worker                                           // else
220*c8dee2aaSAndroid Build Coastguard Worker                                           //     fBPP is bitsPerPixel
221*c8dee2aaSAndroid Build Coastguard Worker     const int           fDstBPP;          // Bytes per pixel for the destination color type
222*c8dee2aaSAndroid Build Coastguard Worker 
223*c8dee2aaSAndroid Build Coastguard Worker     SkSwizzler(RowProc fastProc, RowProc proc, const SkPMColor* ctable, int srcOffset,
224*c8dee2aaSAndroid Build Coastguard Worker             int srcWidth, int dstOffset, int dstWidth, int srcBPP, int dstBPP);
225*c8dee2aaSAndroid Build Coastguard Worker     static std::unique_ptr<SkSwizzler> Make(const SkImageInfo& dstInfo, RowProc fastProc,
226*c8dee2aaSAndroid Build Coastguard Worker             RowProc proc, const SkPMColor* ctable, int srcBPP, int dstBPP,
227*c8dee2aaSAndroid Build Coastguard Worker             const SkCodec::Options& options, const SkIRect* frame);
228*c8dee2aaSAndroid Build Coastguard Worker 
229*c8dee2aaSAndroid Build Coastguard Worker     int onSetSampleX(int) override;
230*c8dee2aaSAndroid Build Coastguard Worker 
231*c8dee2aaSAndroid Build Coastguard Worker };
232*c8dee2aaSAndroid Build Coastguard Worker 
233*c8dee2aaSAndroid Build Coastguard Worker #endif // SkSwizzler_DEFINED
234