[Skia] Remove use of deprecated Skia constant and struct field names
[WebKit-https.git] / Source / WebCore / platform / graphics / chromium / cc / CCRenderSurfaceFilters.cpp
1 /*
2  * Copyright (C) 2012 Google Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1.  Redistributions of source code must retain the above copyright
9  *     notice, this list of conditions and the following disclaimer.
10  * 2.  Redistributions in binary form must reproduce the above copyright
11  *     notice, this list of conditions and the following disclaimer in the
12  *     documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
18  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
21  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27
28 #if USE(ACCELERATED_COMPOSITING)
29
30 #include "cc/CCRenderSurfaceFilters.h"
31
32 #include "GraphicsContext3D.h"
33 #include "LengthFunctions.h"
34 #include "SkBlurImageFilter.h"
35 #include "SkCanvas.h"
36 #include "SkColorMatrixFilter.h"
37 #include "SkGpuDevice.h"
38 #include "SkGrTexturePixelRef.h"
39
40 namespace {
41
42 void getBrightnessMatrix(float amount, SkScalar matrix[20])
43 {
44     memset(matrix, 0, 20 * sizeof(SkScalar));
45     //    Old implementation, a la the draft spec, a straight-up scale,
46     //    representing <feFunc[R|G|B] type="linear" slope="[amount]">
47     //    (See http://dvcs.w3.org/hg/FXTF/raw-file/tip/filters/index.html#brightnessEquivalent)
48     // matrix[0] = matrix[6] = matrix[12] = amount;
49     // matrix[18] = 1;
50     //    New implementation, a translation in color space, representing
51     //    <feFunc[R|G|B] type="linear" intercept="[amount]"/>
52     //    (See https://www.w3.org/Bugs/Public/show_bug.cgi?id=15647)
53     matrix[0] = matrix[6] = matrix[12] = matrix[18] = 1;
54     matrix[4] = matrix[9] = matrix[14] = amount * 255;
55 }
56
57 void getContrastMatrix(float amount, SkScalar matrix[20])
58 {
59     memset(matrix, 0, 20 * sizeof(SkScalar));
60     matrix[0] = matrix[6] = matrix[12] = amount;
61     matrix[4] = matrix[9] = matrix[14] = (-0.5f * amount + 0.5f) * 255;
62     matrix[18] = 1;
63 }
64
65 void getSaturateMatrix(float amount, SkScalar matrix[20])
66 {
67     matrix[0] = 0.213f + 0.787f * amount;
68     matrix[1] = 0.715f - 0.715f * amount;
69     matrix[2] = 0.072f - 0.072f * amount;
70     matrix[3] = matrix[4] = 0;
71     matrix[5] = 0.213f - 0.213f * amount;
72     matrix[6] = 0.715f + 0.285f * amount;
73     matrix[7] = 0.072f - 0.072f * amount;
74     matrix[8] = matrix[9] = 0;
75     matrix[10] = 0.213f - 0.213f * amount;
76     matrix[11] = 0.715f - 0.715f * amount;
77     matrix[12] = 0.072f + 0.928f * amount;
78     matrix[13] = matrix[14] = 0;
79     matrix[15] = matrix[16] = matrix[17] = matrix[19] = 0;
80     matrix[18] = 1;
81 }
82
83 void getHueRotateMatrix(float hue, SkScalar matrix[20])
84 {
85     float cosHue = cosf(hue * piFloat / 180); 
86     float sinHue = sinf(hue * piFloat / 180); 
87     matrix[0] = 0.213f + cosHue * 0.787f - sinHue * 0.213f;
88     matrix[1] = 0.715f - cosHue * 0.715f - sinHue * 0.715f;
89     matrix[2] = 0.072f - cosHue * 0.072f + sinHue * 0.928f;
90     matrix[3] = matrix[4] = 0;
91     matrix[5] = 0.213f - cosHue * 0.213f + sinHue * 0.143f;
92     matrix[6] = 0.715f + cosHue * 0.285f + sinHue * 0.140f;
93     matrix[7] = 0.072f - cosHue * 0.072f - sinHue * 0.283f;
94     matrix[8] = matrix[9] = 0;
95     matrix[10] = 0.213f - cosHue * 0.213f - sinHue * 0.787f;
96     matrix[11] = 0.715f - cosHue * 0.715f + sinHue * 0.715f;
97     matrix[12] = 0.072f + cosHue * 0.928f + sinHue * 0.072f;
98     matrix[13] = matrix[14] = 0;
99     matrix[15] = matrix[16] = matrix[17] = 0;
100     matrix[18] = 1;
101     matrix[19] = 0;
102 }
103
104 void getInvertMatrix(float amount, SkScalar matrix[20])
105 {
106     memset(matrix, 0, 20 * sizeof(SkScalar));
107     matrix[0] = matrix[6] = matrix[12] = 1 - 2 * amount;
108     matrix[4] = matrix[9] = matrix[14] = amount * 255;
109     matrix[18] = 1;
110 }
111
112 void getOpacityMatrix(float amount, SkScalar matrix[20])
113 {
114     memset(matrix, 0, 20 * sizeof(SkScalar));
115     matrix[0] = matrix[6] = matrix[12] = 1;
116     matrix[18] = amount;
117 }
118
119 void getGrayscaleMatrix(float amount, SkScalar matrix[20])
120 {
121     matrix[0] = 0.2126f + 0.7874f * amount;
122     matrix[1] = 0.7152f - 0.7152f * amount;
123     matrix[2] = 0.0722f - 0.0722f * amount;
124     matrix[3] = matrix[4] = 0;
125
126     matrix[5] = 0.2126f - 0.2126f * amount;
127     matrix[6] = 0.7152f + 0.2848f * amount;
128     matrix[7] = 0.0722f - 0.0722f * amount;
129     matrix[8] = matrix[9] = 0;
130
131     matrix[10] = 0.2126f - 0.2126f * amount;
132     matrix[11] = 0.7152f - 0.7152f * amount;
133     matrix[12] = 0.0722f + 0.9278f * amount;
134     matrix[13] = matrix[14] = 0;
135
136     matrix[15] = matrix[16] = matrix[17] = matrix[19] = 0;
137     matrix[18] = 1;
138 }
139
140 void getSepiaMatrix(float amount, SkScalar matrix[20])
141 {
142     matrix[0] = 0.393f + 0.607f * amount;
143     matrix[1] = 0.769f - 0.769f * amount;
144     matrix[2] = 0.189f - 0.189f * amount;
145     matrix[3] = matrix[4] = 0;
146
147     matrix[5] = 0.349f - 0.349f * amount;
148     matrix[6] = 0.686f + 0.314f * amount;
149     matrix[7] = 0.168f - 0.168f * amount;
150     matrix[8] = matrix[9] = 0;
151
152     matrix[10] = 0.272f - 0.272f * amount;
153     matrix[11] = 0.534f - 0.534f * amount;
154     matrix[12] = 0.131f + 0.869f * amount;
155     matrix[13] = matrix[14] = 0;
156
157     matrix[15] = matrix[16] = matrix[17] = matrix[19] = 0;
158     matrix[18] = 1;
159 }
160
161 bool applyColorMatrix(SkCanvas* canvas, SkBitmap source, SkScalar matrix[20])
162 {
163     SkPaint paint;
164     paint.setColorFilter(new SkColorMatrixFilter(matrix))->unref();
165     canvas->drawBitmap(source, 0, 0, &paint);
166     return true;
167 }
168
169 }
170
171 namespace WebCore {
172
173 SkBitmap CCRenderSurfaceFilters::apply(const FilterOperations& filters, unsigned textureId, const FloatSize& size, GraphicsContext3D* context3D)
174 {
175     SkBitmap source;
176     if (!context3D)
177         return source;
178
179     GrContext* gr = context3D->grContext();
180     if (!gr)
181         return source;
182     // Wrap the RenderSurface's texture in a Ganesh platform texture.
183     GrPlatformTextureDesc platformTexDesc;
184     platformTexDesc.fWidth = size.width();
185     platformTexDesc.fHeight = size.height();
186     platformTexDesc.fConfig = kSkia8888_PM_GrPixelConfig;
187     platformTexDesc.fTextureHandle = textureId;
188     SkAutoTUnref<GrTexture> texture(gr->createPlatformTexture(platformTexDesc));
189     // Place the platform texture inside an SkBitmap.
190     source.setConfig(SkBitmap::kARGB_8888_Config, size.width(), size.height());
191     source.setPixelRef(new SkGrTexturePixelRef(texture.get()))->unref();
192     
193     GrContext::TextureCacheEntry dest;
194
195     for (unsigned i = 0; i < filters.size(); ++i) {
196         // Save the previous texture cache destination (if any), and keep it
197         // locked during draw to prevent it be re-used as destination.
198         GrContext::TextureCacheEntry sourceEntry = dest;
199         const FilterOperation* filterOperation = filters.at(i);
200         // Allocate a destination texture.
201         GrTextureDesc desc;
202         desc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit;
203         desc.fSampleCnt = 0;
204         desc.fWidth = size.width();
205         desc.fHeight = size.height();
206         desc.fConfig = kSkia8888_PM_GrPixelConfig;
207         // FIXME: could we use approximate match, and fix texcoords on draw
208         dest = gr->lockScratchTexture(desc, GrContext::kExact_ScratchTexMatch);
209         if (!dest.texture())
210             return SkBitmap();
211         SkGpuDevice device(gr, dest.texture());
212         SkCanvas canvas(&device);
213         canvas.clear(0x0);
214         switch (filterOperation->getOperationType()) {
215         case FilterOperation::BRIGHTNESS: {
216             const BasicColorMatrixFilterOperation* op = static_cast<const BasicColorMatrixFilterOperation*>(filterOperation);
217             SkScalar matrix[20];
218             getBrightnessMatrix(op->amount(), matrix);
219             applyColorMatrix(&canvas, source, matrix);
220             break;
221         }
222         case FilterOperation::CONTRAST: {
223             const BasicColorMatrixFilterOperation* op = static_cast<const BasicColorMatrixFilterOperation*>(filterOperation);
224             SkScalar matrix[20];
225             getContrastMatrix(op->amount(), matrix);
226             applyColorMatrix(&canvas, source, matrix);
227             break;
228         }
229         case FilterOperation::GRAYSCALE: {
230             const BasicColorMatrixFilterOperation* op = static_cast<const BasicColorMatrixFilterOperation*>(filterOperation);
231             SkScalar matrix[20];
232             getGrayscaleMatrix(1 - op->amount(), matrix);
233             applyColorMatrix(&canvas, source, matrix);
234             break;
235         }
236         case FilterOperation::SEPIA: {
237             const BasicColorMatrixFilterOperation* op = static_cast<const BasicColorMatrixFilterOperation*>(filterOperation);
238             SkScalar matrix[20];
239             getSepiaMatrix(1 - op->amount(), matrix);
240             applyColorMatrix(&canvas, source, matrix);
241             break;
242         }
243         case FilterOperation::SATURATE: {
244             const BasicColorMatrixFilterOperation* op = static_cast<const BasicColorMatrixFilterOperation*>(filterOperation);
245             SkScalar matrix[20];
246             getSaturateMatrix(op->amount(), matrix);
247             applyColorMatrix(&canvas, source, matrix);
248             break;
249         }
250         case FilterOperation::HUE_ROTATE: {
251             const BasicColorMatrixFilterOperation* op = static_cast<const BasicColorMatrixFilterOperation*>(filterOperation);
252             SkScalar matrix[20];
253             getHueRotateMatrix(op->amount(), matrix);
254             applyColorMatrix(&canvas, source, matrix);
255             break;
256         }
257         case FilterOperation::INVERT: {
258             const BasicColorMatrixFilterOperation* op = static_cast<const BasicColorMatrixFilterOperation*>(filterOperation);
259             SkScalar matrix[20];
260             getInvertMatrix(op->amount(), matrix);
261             applyColorMatrix(&canvas, source, matrix);
262             break;
263         }
264         case FilterOperation::OPACITY: {
265             const BasicComponentTransferFilterOperation* op = static_cast<const BasicComponentTransferFilterOperation*>(filterOperation);
266             SkScalar matrix[20];
267             getOpacityMatrix(op->amount(), matrix);
268             applyColorMatrix(&canvas, source, matrix);
269             break;
270         }
271         case FilterOperation::BLUR: {
272             const BlurFilterOperation* op = static_cast<const BlurFilterOperation*>(filterOperation);
273             float stdX = floatValueForLength(op->stdDeviation(), 0);
274             float stdY = floatValueForLength(op->stdDeviation(), 1);
275             SkAutoTUnref<SkImageFilter> filter(new SkBlurImageFilter(stdX, stdY));
276             SkPaint paint;
277             paint.setImageFilter(filter.get());
278             canvas.drawSprite(source, 0, 0, &paint);
279             break;
280         }
281         case FilterOperation::DROP_SHADOW: {
282             const DropShadowFilterOperation* op = static_cast<const DropShadowFilterOperation*>(filterOperation);
283             SkAutoTUnref<SkImageFilter> blurFilter(new SkBlurImageFilter(op->stdDeviation(), op->stdDeviation()));
284             SkAutoTUnref<SkColorFilter> colorFilter(SkColorFilter::CreateModeFilter(op->color().rgb(), SkXfermode::kSrcIn_Mode));
285             SkPaint paint;
286             paint.setImageFilter(blurFilter.get());
287             paint.setColorFilter(colorFilter.get());
288             paint.setXfermodeMode(SkXfermode::kSrcOver_Mode);
289             canvas.saveLayer(0, &paint);
290             canvas.drawBitmap(source, op->x(), -op->y());
291             canvas.restore();
292             canvas.drawBitmap(source, 0, 0);
293             break;
294         }
295         case FilterOperation::PASSTHROUGH:
296         default:
297             canvas.drawBitmap(source, 0, 0);
298             break;
299         }
300         // Dest texture from this filter becomes source bitmap for next filter.
301         source.setPixelRef(new SkGrTexturePixelRef(dest.texture()))->unref();
302         // Unlock the previous texture cache entry.
303         if (sourceEntry.texture())
304             gr->unlockTexture(sourceEntry);
305     }
306     if (dest.texture())
307         gr->unlockTexture(dest);
308     context3D->flush();
309     return source;
310 }
311
312 }
313 #endif // USE(ACCELERATED_COMPOSITING)