Index: ui/cc/cc/CCRenderSurfaceFilters.cpp |
diff --git a/ui/cc/cc/CCRenderSurfaceFilters.cpp b/ui/cc/cc/CCRenderSurfaceFilters.cpp |
new file mode 100644 |
index 0000000000000000000000000000000000000000..4c6d77fc7244e579158b96c996ecca68eb0b1cf1 |
--- /dev/null |
+++ b/ui/cc/cc/CCRenderSurfaceFilters.cpp |
@@ -0,0 +1,305 @@ |
+/* |
+ * Copyright (C) 2012 Google Inc. All rights reserved. |
+ * |
+ * Redistribution and use in source and binary forms, with or without |
+ * modification, are permitted provided that the following conditions |
+ * are met: |
+ * |
+ * 1. Redistributions of source code must retain the above copyright |
+ * notice, this list of conditions and the following disclaimer. |
+ * 2. Redistributions in binary form must reproduce the above copyright |
+ * notice, this list of conditions and the following disclaimer in the |
+ * documentation and/or other materials provided with the distribution. |
+ * |
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY |
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY |
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
+ */ |
+ |
+#include "config.h" |
+ |
+#if USE(ACCELERATED_COMPOSITING) |
+ |
+#include "cc/CCRenderSurfaceFilters.h" |
+ |
+#include "GraphicsContext3D.h" |
+#include "SkBlurImageFilter.h" |
+#include "SkCanvas.h" |
+#include "SkColorMatrixFilter.h" |
+#include "SkGpuDevice.h" |
+#include "SkGrTexturePixelRef.h" |
+#include <public/WebFilterOperation.h> |
+#include <public/WebFilterOperations.h> |
+#include <wtf/MathExtras.h> |
+ |
+namespace { |
+ |
+void getBrightnessMatrix(float amount, SkScalar matrix[20]) |
+{ |
+ memset(matrix, 0, 20 * sizeof(SkScalar)); |
+ // Old implementation, a la the draft spec, a straight-up scale, |
+ // representing <feFunc[R|G|B] type="linear" slope="[amount]"> |
+ // (See http://dvcs.w3.org/hg/FXTF/raw-file/tip/filters/index.html#brightnessEquivalent) |
+ // matrix[0] = matrix[6] = matrix[12] = amount; |
+ // matrix[18] = 1; |
+ // New implementation, a translation in color space, representing |
+ // <feFunc[R|G|B] type="linear" intercept="[amount]"/> |
+ // (See https://www.w3.org/Bugs/Public/show_bug.cgi?id=15647) |
+ matrix[0] = matrix[6] = matrix[12] = matrix[18] = 1; |
+ matrix[4] = matrix[9] = matrix[14] = amount * 255; |
+} |
+ |
+void getContrastMatrix(float amount, SkScalar matrix[20]) |
+{ |
+ memset(matrix, 0, 20 * sizeof(SkScalar)); |
+ matrix[0] = matrix[6] = matrix[12] = amount; |
+ matrix[4] = matrix[9] = matrix[14] = (-0.5f * amount + 0.5f) * 255; |
+ matrix[18] = 1; |
+} |
+ |
+void getSaturateMatrix(float amount, SkScalar matrix[20]) |
+{ |
+ matrix[0] = 0.213f + 0.787f * amount; |
+ matrix[1] = 0.715f - 0.715f * amount; |
+ matrix[2] = 0.072f - 0.072f * amount; |
+ matrix[3] = matrix[4] = 0; |
+ matrix[5] = 0.213f - 0.213f * amount; |
+ matrix[6] = 0.715f + 0.285f * amount; |
+ matrix[7] = 0.072f - 0.072f * amount; |
+ matrix[8] = matrix[9] = 0; |
+ matrix[10] = 0.213f - 0.213f * amount; |
+ matrix[11] = 0.715f - 0.715f * amount; |
+ matrix[12] = 0.072f + 0.928f * amount; |
+ matrix[13] = matrix[14] = 0; |
+ matrix[15] = matrix[16] = matrix[17] = matrix[19] = 0; |
+ matrix[18] = 1; |
+} |
+ |
+void getHueRotateMatrix(float hue, SkScalar matrix[20]) |
+{ |
+ float cosHue = cosf(hue * piFloat / 180); |
+ float sinHue = sinf(hue * piFloat / 180); |
+ matrix[0] = 0.213f + cosHue * 0.787f - sinHue * 0.213f; |
+ matrix[1] = 0.715f - cosHue * 0.715f - sinHue * 0.715f; |
+ matrix[2] = 0.072f - cosHue * 0.072f + sinHue * 0.928f; |
+ matrix[3] = matrix[4] = 0; |
+ matrix[5] = 0.213f - cosHue * 0.213f + sinHue * 0.143f; |
+ matrix[6] = 0.715f + cosHue * 0.285f + sinHue * 0.140f; |
+ matrix[7] = 0.072f - cosHue * 0.072f - sinHue * 0.283f; |
+ matrix[8] = matrix[9] = 0; |
+ matrix[10] = 0.213f - cosHue * 0.213f - sinHue * 0.787f; |
+ matrix[11] = 0.715f - cosHue * 0.715f + sinHue * 0.715f; |
+ matrix[12] = 0.072f + cosHue * 0.928f + sinHue * 0.072f; |
+ matrix[13] = matrix[14] = 0; |
+ matrix[15] = matrix[16] = matrix[17] = 0; |
+ matrix[18] = 1; |
+ matrix[19] = 0; |
+} |
+ |
+void getInvertMatrix(float amount, SkScalar matrix[20]) |
+{ |
+ memset(matrix, 0, 20 * sizeof(SkScalar)); |
+ matrix[0] = matrix[6] = matrix[12] = 1 - 2 * amount; |
+ matrix[4] = matrix[9] = matrix[14] = amount * 255; |
+ matrix[18] = 1; |
+} |
+ |
+void getOpacityMatrix(float amount, SkScalar matrix[20]) |
+{ |
+ memset(matrix, 0, 20 * sizeof(SkScalar)); |
+ matrix[0] = matrix[6] = matrix[12] = 1; |
+ matrix[18] = amount; |
+} |
+ |
+void getGrayscaleMatrix(float amount, SkScalar matrix[20]) |
+{ |
+ matrix[0] = 0.2126f + 0.7874f * amount; |
+ matrix[1] = 0.7152f - 0.7152f * amount; |
+ matrix[2] = 0.0722f - 0.0722f * amount; |
+ matrix[3] = matrix[4] = 0; |
+ |
+ matrix[5] = 0.2126f - 0.2126f * amount; |
+ matrix[6] = 0.7152f + 0.2848f * amount; |
+ matrix[7] = 0.0722f - 0.0722f * amount; |
+ matrix[8] = matrix[9] = 0; |
+ |
+ matrix[10] = 0.2126f - 0.2126f * amount; |
+ matrix[11] = 0.7152f - 0.7152f * amount; |
+ matrix[12] = 0.0722f + 0.9278f * amount; |
+ matrix[13] = matrix[14] = 0; |
+ |
+ matrix[15] = matrix[16] = matrix[17] = matrix[19] = 0; |
+ matrix[18] = 1; |
+} |
+ |
+void getSepiaMatrix(float amount, SkScalar matrix[20]) |
+{ |
+ matrix[0] = 0.393f + 0.607f * amount; |
+ matrix[1] = 0.769f - 0.769f * amount; |
+ matrix[2] = 0.189f - 0.189f * amount; |
+ matrix[3] = matrix[4] = 0; |
+ |
+ matrix[5] = 0.349f - 0.349f * amount; |
+ matrix[6] = 0.686f + 0.314f * amount; |
+ matrix[7] = 0.168f - 0.168f * amount; |
+ matrix[8] = matrix[9] = 0; |
+ |
+ matrix[10] = 0.272f - 0.272f * amount; |
+ matrix[11] = 0.534f - 0.534f * amount; |
+ matrix[12] = 0.131f + 0.869f * amount; |
+ matrix[13] = matrix[14] = 0; |
+ |
+ matrix[15] = matrix[16] = matrix[17] = matrix[19] = 0; |
+ matrix[18] = 1; |
+} |
+ |
+bool applyColorMatrix(SkCanvas* canvas, SkBitmap source, SkScalar matrix[20]) |
+{ |
+ SkPaint paint; |
+ paint.setColorFilter(new SkColorMatrixFilter(matrix))->unref(); |
+ canvas->drawBitmap(source, 0, 0, &paint); |
+ return true; |
+} |
+ |
+} |
+ |
+namespace WebCore { |
+ |
+/* |
+SkBitmap CCRenderSurfaceFilters::apply(const WebKit::WebFilterOperations& filters, unsigned textureId, const FloatSize& size, GraphicsContext3D* context3D) |
+{ |
+ SkBitmap source; |
+ if (!context3D) |
+ return source; |
+ |
+ GrContext* gr = context3D->grContext(); |
+ if (!gr) |
+ return source; |
+ // Wrap the RenderSurface's texture in a Ganesh platform texture. |
+ GrPlatformTextureDesc platformTexDesc; |
+ platformTexDesc.fWidth = size.width(); |
+ platformTexDesc.fHeight = size.height(); |
+ platformTexDesc.fConfig = kSkia8888_PM_GrPixelConfig; |
+ platformTexDesc.fTextureHandle = textureId; |
+ SkAutoTUnref<GrTexture> texture(gr->createPlatformTexture(platformTexDesc)); |
+ // Place the platform texture inside an SkBitmap. |
+ source.setConfig(SkBitmap::kARGB_8888_Config, size.width(), size.height()); |
+ source.setPixelRef(new SkGrTexturePixelRef(texture.get()))->unref(); |
+ |
+ GrContext::TextureCacheEntry dest; |
+ |
+ for (unsigned i = 0; i < filters.size(); ++i) { |
+ // Save the previous texture cache destination (if any), and keep it |
+ // locked during draw to prevent it be re-used as destination. |
+ GrContext::TextureCacheEntry sourceEntry = dest; |
+ const WebKit::WebFilterOperation& op = filters.at(i); |
+ // Allocate a destination texture. |
+ GrTextureDesc desc; |
+ desc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit; |
+ desc.fSampleCnt = 0; |
+ desc.fWidth = size.width(); |
+ desc.fHeight = size.height(); |
+ desc.fConfig = kSkia8888_PM_GrPixelConfig; |
+ // FIXME: could we use approximate match, and fix texcoords on draw |
+ dest = gr->lockScratchTexture(desc, GrContext::kExact_ScratchTexMatch); |
+ if (!dest.texture()) |
+ return SkBitmap(); |
+ SkGpuDevice device(gr, dest.texture()); |
+ SkCanvas canvas(&device); |
+ canvas.clear(0x0); |
+ switch (op.type()) { |
+ case WebKit::WebFilterOperation::FilterTypeBrightness: { |
+ SkScalar matrix[20]; |
+ getBrightnessMatrix(op.amount(), matrix); |
+ applyColorMatrix(&canvas, source, matrix); |
+ break; |
+ } |
+ case WebKit::WebFilterOperation::FilterTypeContrast: { |
+ SkScalar matrix[20]; |
+ getContrastMatrix(op.amount(), matrix); |
+ applyColorMatrix(&canvas, source, matrix); |
+ break; |
+ } |
+ case WebKit::WebFilterOperation::FilterTypeGrayscale: { |
+ SkScalar matrix[20]; |
+ getGrayscaleMatrix(1 - op.amount(), matrix); |
+ applyColorMatrix(&canvas, source, matrix); |
+ break; |
+ } |
+ case WebKit::WebFilterOperation::FilterTypeSepia: { |
+ SkScalar matrix[20]; |
+ getSepiaMatrix(1 - op.amount(), matrix); |
+ applyColorMatrix(&canvas, source, matrix); |
+ break; |
+ } |
+ case WebKit::WebFilterOperation::FilterTypeSaturate: { |
+ SkScalar matrix[20]; |
+ getSaturateMatrix(op.amount(), matrix); |
+ applyColorMatrix(&canvas, source, matrix); |
+ break; |
+ } |
+ case WebKit::WebFilterOperation::FilterTypeHueRotate: { |
+ SkScalar matrix[20]; |
+ getHueRotateMatrix(op.amount(), matrix); |
+ applyColorMatrix(&canvas, source, matrix); |
+ break; |
+ } |
+ case WebKit::WebFilterOperation::FilterTypeInvert: { |
+ SkScalar matrix[20]; |
+ getInvertMatrix(op.amount(), matrix); |
+ applyColorMatrix(&canvas, source, matrix); |
+ break; |
+ } |
+ case WebKit::WebFilterOperation::FilterTypeOpacity: { |
+ SkScalar matrix[20]; |
+ getOpacityMatrix(op.amount(), matrix); |
+ applyColorMatrix(&canvas, source, matrix); |
+ break; |
+ } |
+ case WebKit::WebFilterOperation::FilterTypeBlur: { |
+ float stdDeviation = op.amount(); |
+ SkAutoTUnref<SkImageFilter> filter(new SkBlurImageFilter(stdDeviation, stdDeviation)); |
+ SkPaint paint; |
+ paint.setImageFilter(filter.get()); |
+ canvas.drawSprite(source, 0, 0, &paint); |
+ break; |
+ } |
+ case WebKit::WebFilterOperation::FilterTypeDropShadow: { |
+ SkAutoTUnref<SkImageFilter> blurFilter(new SkBlurImageFilter(op.amount(), op.amount())); |
+ SkAutoTUnref<SkColorFilter> colorFilter(SkColorFilter::CreateModeFilter(op.dropShadowColor(), SkXfermode::kSrcIn_Mode)); |
+ SkPaint paint; |
+ paint.setImageFilter(blurFilter.get()); |
+ paint.setColorFilter(colorFilter.get()); |
+ paint.setXfermodeMode(SkXfermode::kSrcOver_Mode); |
+ canvas.saveLayer(0, &paint); |
+ canvas.drawBitmap(source, op.dropShadowOffset().x, -op.dropShadowOffset().y); |
+ canvas.restore(); |
+ canvas.drawBitmap(source, 0, 0); |
+ break; |
+ } |
+ default: |
+ canvas.drawBitmap(source, 0, 0); |
+ break; |
+ } |
+ // Dest texture from this filter becomes source bitmap for next filter. |
+ source.setPixelRef(new SkGrTexturePixelRef(dest.texture()))->unref(); |
+ // Unlock the previous texture cache entry. |
+ if (sourceEntry.texture()) |
+ gr->unlockTexture(sourceEntry); |
+ } |
+ if (dest.texture()) |
+ gr->unlockTexture(dest); |
+ context3D->flush(); |
+ return source; |
+} |
+*/ |
+ |
+} |
+#endif // USE(ACCELERATED_COMPOSITING) |