Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(63)

Side by Side Diff: third_party/WebKit/Source/platform/image-encoders/JPEGImageEncoder.cpp

Issue 2576223002: NEON-ize RGBA to RGB code (Closed)
Patch Set: Moved perf test to another issue Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2010, Google Inc. All rights reserved. 2 * Copyright (c) 2010, Google Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are 5 * modification, are permitted provided that the following conditions are
6 * met: 6 * met:
7 * 7 *
8 * * Redistributions of source code must retain the above copyright 8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above 10 * * Redistributions in binary form must reproduce the above
(...skipping 15 matching lines...) Expand all
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */ 29 */
30 30
31 #include "platform/image-encoders/JPEGImageEncoder.h" 31 #include "platform/image-encoders/JPEGImageEncoder.h"
32 32
33 #include "SkColorPriv.h" 33 #include "SkColorPriv.h"
34 #include "platform/geometry/IntSize.h" 34 #include "platform/geometry/IntSize.h"
35 #include "platform/graphics/ImageBuffer.h" 35 #include "platform/graphics/ImageBuffer.h"
36 #include "platform/image-encoders/RGBAtoRGB.h"
36 #include "wtf/CurrentTime.h" 37 #include "wtf/CurrentTime.h"
37 #include "wtf/PtrUtil.h" 38 #include "wtf/PtrUtil.h"
38 #include <memory> 39 #include <memory>
39 40
40 extern "C" { 41 extern "C" {
41 #include <setjmp.h> 42 #include <setjmp.h>
42 #include <stdio.h> // jpeglib.h needs stdio.h FILE 43 #include <stdio.h> // jpeglib.h needs stdio.h FILE
43 #include "jpeglib.h" 44 #include "jpeglib.h"
44 } 45 }
45 46
46 namespace blink { 47 namespace blink {
47 48
49 void RGBAtoRGBScalar(const unsigned char* pixels,
50 unsigned pixelCount,
51 unsigned char* output) {
52 // Per <canvas> spec, composite the input image pixels source-over on black.
53 for (; pixelCount-- > 0; pixels += 4) {
54 unsigned char alpha = pixels[3];
55 if (alpha != 255) {
56 *output++ = SkMulDiv255Round(pixels[0], alpha);
57 *output++ = SkMulDiv255Round(pixels[1], alpha);
58 *output++ = SkMulDiv255Round(pixels[2], alpha);
59 } else {
60 *output++ = pixels[0];
61 *output++ = pixels[1];
62 *output++ = pixels[2];
63 }
64 }
65 }
66
67 // TODO(cavalcantii): use regular macro, see https://crbug.com/673067.
68 #ifdef __ARM_NEON__
69 void RGBAtoRGBNeon(const unsigned char* input,
70 const unsigned pixelCount,
71 unsigned char* output) {
72 const unsigned pixelsPerLoad = 16;
73 const unsigned rgbaStep = pixelsPerLoad * 4, rgbStep = pixelsPerLoad * 3;
74 // Input registers.
75 uint8x16x4_t rgba;
76 // Output registers.
77 uint8x16x3_t rgb;
78 // Intermediate registers.
79 uint8x8_t low, high;
80 uint8x16_t result;
81 unsigned counter;
82 auto transformColor = [&](size_t channel) {
83 // Extracts the low/high part of the 128 bits.
84 low = vget_low_u8(rgba.val[channel]);
85 high = vget_high_u8(rgba.val[channel]);
86 // Scale the color and combine.
87 uint16x8_t temp = vmull_u8(low, vget_low_u8(rgba.val[3]));
88 low = vraddhn_u16(temp, vrshrq_n_u16(temp, 8));
89 temp = vmull_u8(high, vget_high_u8(rgba.val[3]));
90 high = vraddhn_u16(temp, vrshrq_n_u16(temp, 8));
91 result = vcombine_u8(low, high);
92 // Write back the channel to a 128 bits register.
93 rgb.val[channel] = result;
94 };
95
96 for (counter = 0; counter + pixelsPerLoad <= pixelCount;
97 counter += pixelsPerLoad) {
98 // Reads 16 pixels at once, each color channel in a different
99 // 128 bits register.
100 rgba = vld4q_u8(input);
101
102 transformColor(0);
103 transformColor(1);
104 transformColor(2);
105
106 // Write back (interleaved) results to output.
107 vst3q_u8(output, rgb);
108
109 // Advance to next elements (could be avoided loading register with
110 // increment after i.e. "vld4 {vector}, [r1]!").
111 input += rgbaStep;
112 output += rgbStep;
113 }
114
115 // Handle the tail elements.
116 unsigned remaining = pixelCount;
117 remaining -= counter;
118 if (remaining != 0) {
119 RGBAtoRGBScalar(input, remaining, output);
120 }
121 }
122 #endif
123
48 struct JPEGOutputBuffer : public jpeg_destination_mgr { 124 struct JPEGOutputBuffer : public jpeg_destination_mgr {
49 DISALLOW_NEW(); 125 DISALLOW_NEW();
50 Vector<unsigned char>* output; 126 Vector<unsigned char>* output;
51 Vector<unsigned char> buffer; 127 Vector<unsigned char> buffer;
52 }; 128 };
53 129
54 class JPEGImageEncoderStateImpl final : public JPEGImageEncoderState { 130 class JPEGImageEncoderStateImpl final : public JPEGImageEncoderState {
55 public: 131 public:
56 JPEGImageEncoderStateImpl() {} 132 JPEGImageEncoderStateImpl() {}
57 ~JPEGImageEncoderStateImpl() override { 133 ~JPEGImageEncoderStateImpl() override {
(...skipping 30 matching lines...) Expand all
88 JPEGOutputBuffer* out = static_cast<JPEGOutputBuffer*>(cinfo->dest); 164 JPEGOutputBuffer* out = static_cast<JPEGOutputBuffer*>(cinfo->dest);
89 const size_t size = out->buffer.size() - out->free_in_buffer; 165 const size_t size = out->buffer.size() - out->free_in_buffer;
90 out->output->append(out->buffer.data(), size); 166 out->output->append(out->buffer.data(), size);
91 } 167 }
92 168
93 static void handleError(j_common_ptr common) { 169 static void handleError(j_common_ptr common) {
94 jmp_buf* jumpBufferPtr = static_cast<jmp_buf*>(common->client_data); 170 jmp_buf* jumpBufferPtr = static_cast<jmp_buf*>(common->client_data);
95 longjmp(*jumpBufferPtr, -1); 171 longjmp(*jumpBufferPtr, -1);
96 } 172 }
97 173
98 static void RGBAtoRGB(const unsigned char* pixels,
99 unsigned pixelCount,
100 unsigned char* output) {
101 // Per <canvas> spec, composite the input image pixels source-over on black.
102
103 for (; pixelCount-- > 0; pixels += 4) {
104 unsigned char alpha = pixels[3];
105 if (alpha != 255) {
106 *output++ = SkMulDiv255Round(pixels[0], alpha);
107 *output++ = SkMulDiv255Round(pixels[1], alpha);
108 *output++ = SkMulDiv255Round(pixels[2], alpha);
109 } else {
110 *output++ = pixels[0];
111 *output++ = pixels[1];
112 *output++ = pixels[2];
113 }
114 }
115 }
116
117 static void disableSubsamplingForHighQuality(jpeg_compress_struct* cinfo, 174 static void disableSubsamplingForHighQuality(jpeg_compress_struct* cinfo,
118 int quality) { 175 int quality) {
119 if (quality < 100) 176 if (quality < 100)
120 return; 177 return;
121 178
122 for (int i = 0; i < MAX_COMPONENTS; ++i) { 179 for (int i = 0; i < MAX_COMPONENTS; ++i) {
123 cinfo->comp_info[i].h_samp_factor = 1; 180 cinfo->comp_info[i].h_samp_factor = 1;
124 cinfo->comp_info[i].v_samp_factor = 1; 181 cinfo->comp_info[i].v_samp_factor = 1;
125 } 182 }
126 } 183 }
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
250 std::unique_ptr<JPEGImageEncoderState> encoderState = 307 std::unique_ptr<JPEGImageEncoderState> encoderState =
251 JPEGImageEncoderState::create(imageData.size(), quality, output); 308 JPEGImageEncoderState::create(imageData.size(), quality, output);
252 if (!encoderState) 309 if (!encoderState)
253 return false; 310 return false;
254 311
255 return JPEGImageEncoder::encodeWithPreInitializedState( 312 return JPEGImageEncoder::encodeWithPreInitializedState(
256 std::move(encoderState), imageData.pixels()); 313 std::move(encoderState), imageData.pixels());
257 } 314 }
258 315
259 } // namespace blink 316 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698