| Index: cc/CCRenderSurfaceFilters.cpp
|
| diff --git a/cc/CCRenderSurfaceFilters.cpp b/cc/CCRenderSurfaceFilters.cpp
|
| deleted file mode 100644
|
| index 40344c6b466f676e653ac28d9010420d9653ac82..0000000000000000000000000000000000000000
|
| --- a/cc/CCRenderSurfaceFilters.cpp
|
| +++ /dev/null
|
| @@ -1,446 +0,0 @@
|
| -// Copyright 2012 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -#include "config.h"
|
| -
|
| -#if USE(ACCELERATED_COMPOSITING)
|
| -
|
| -#include "CCRenderSurfaceFilters.h"
|
| -
|
| -#include "FloatSize.h"
|
| -#include "SkBlurImageFilter.h"
|
| -#include "SkCanvas.h"
|
| -#include "SkColorMatrixFilter.h"
|
| -#include "SkGpuDevice.h"
|
| -#include "SkGrPixelRef.h"
|
| -#include "SkMagnifierImageFilter.h"
|
| -#include <public/WebFilterOperation.h>
|
| -#include <public/WebFilterOperations.h>
|
| -#include <public/WebGraphicsContext3D.h>
|
| -#include <wtf/MathExtras.h>
|
| -
|
| -using namespace cc;
|
| -
|
| -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])
|
| -{
|
| - // Note, these values are computed to ensure matrixNeedsClamping is false
|
| - // for amount in [0..1]
|
| - matrix[0] = 0.213f + 0.787f * amount;
|
| - matrix[1] = 0.715f - 0.715f * amount;
|
| - matrix[2] = 1.f - (matrix[0] + matrix[1]);
|
| - matrix[3] = matrix[4] = 0;
|
| - matrix[5] = 0.213f - 0.213f * amount;
|
| - matrix[6] = 0.715f + 0.285f * amount;
|
| - matrix[7] = 1.f - (matrix[5] + matrix[6]);
|
| - matrix[8] = matrix[9] = 0;
|
| - matrix[10] = 0.213f - 0.213f * amount;
|
| - matrix[11] = 0.715f - 0.715f * amount;
|
| - matrix[12] = 1.f - (matrix[10] + matrix[11]);
|
| - 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])
|
| -{
|
| - // Note, these values are computed to ensure matrixNeedsClamping is false
|
| - // for amount in [0..1]
|
| - matrix[0] = 0.2126f + 0.7874f * amount;
|
| - matrix[1] = 0.7152f - 0.7152f * amount;
|
| - matrix[2] = 1.f - (matrix[0] + matrix[1]);
|
| - matrix[3] = matrix[4] = 0;
|
| -
|
| - matrix[5] = 0.2126f - 0.2126f * amount;
|
| - matrix[6] = 0.7152f + 0.2848f * amount;
|
| - matrix[7] = 1.f - (matrix[5] + matrix[6]);
|
| - matrix[8] = matrix[9] = 0;
|
| -
|
| - matrix[10] = 0.2126f - 0.2126f * amount;
|
| - matrix[11] = 0.7152f - 0.7152f * amount;
|
| - matrix[12] = 1.f - (matrix[10] + matrix[11]);
|
| - 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;
|
| -}
|
| -
|
| -// The 5x4 matrix is really a "compressed" version of a 5x5 matrix that'd have
|
| -// (0 0 0 0 1) as a last row, and that would be applied to a 5-vector extended
|
| -// from the 4-vector color with a 1.
|
| -void multColorMatrix(SkScalar a[20], SkScalar b[20], SkScalar out[20])
|
| -{
|
| - for (int j = 0; j < 4; ++j) {
|
| - for (int i = 0; i < 5; ++i) {
|
| - out[i+j*5] = i == 4 ? a[4+j*5] : 0;
|
| - for (int k = 0; k < 4; ++k)
|
| - out[i+j*5] += a[k+j*5] * b[i+k*5];
|
| - }
|
| - }
|
| -}
|
| -
|
| -// To detect if we need to apply clamping after applying a matrix, we check if
|
| -// any output component might go outside of [0, 255] for any combination of
|
| -// input components in [0..255].
|
| -// Each output component is an affine transformation of the input component, so
|
| -// the minimum and maximum values are for any combination of minimum or maximum
|
| -// values of input components (i.e. 0 or 255).
|
| -// E.g. if R' = x*R + y*G + z*B + w*A + t
|
| -// Then the maximum value will be for R=255 if x>0 or R=0 if x<0, and the
|
| -// minimum value will be for R=0 if x>0 or R=255 if x<0.
|
| -// Same goes for all components.
|
| -bool componentNeedsClamping(SkScalar row[5])
|
| -{
|
| - SkScalar maxValue = row[4] / 255;
|
| - SkScalar minValue = row[4] / 255;
|
| - for (int i = 0; i < 4; ++i) {
|
| - if (row[i] > 0)
|
| - maxValue += row[i];
|
| - else
|
| - minValue += row[i];
|
| - }
|
| - return (maxValue > 1) || (minValue < 0);
|
| -}
|
| -
|
| -bool matrixNeedsClamping(SkScalar matrix[20])
|
| -{
|
| - return componentNeedsClamping(matrix)
|
| - || componentNeedsClamping(matrix+5)
|
| - || componentNeedsClamping(matrix+10)
|
| - || componentNeedsClamping(matrix+15);
|
| -}
|
| -
|
| -bool getColorMatrix(const WebKit::WebFilterOperation& op, SkScalar matrix[20])
|
| -{
|
| - switch (op.type()) {
|
| - case WebKit::WebFilterOperation::FilterTypeBrightness: {
|
| - getBrightnessMatrix(op.amount(), matrix);
|
| - return true;
|
| - }
|
| - case WebKit::WebFilterOperation::FilterTypeContrast: {
|
| - getContrastMatrix(op.amount(), matrix);
|
| - return true;
|
| - }
|
| - case WebKit::WebFilterOperation::FilterTypeGrayscale: {
|
| - getGrayscaleMatrix(1 - op.amount(), matrix);
|
| - return true;
|
| - }
|
| - case WebKit::WebFilterOperation::FilterTypeSepia: {
|
| - getSepiaMatrix(1 - op.amount(), matrix);
|
| - return true;
|
| - }
|
| - case WebKit::WebFilterOperation::FilterTypeSaturate: {
|
| - getSaturateMatrix(op.amount(), matrix);
|
| - return true;
|
| - }
|
| - case WebKit::WebFilterOperation::FilterTypeHueRotate: {
|
| - getHueRotateMatrix(op.amount(), matrix);
|
| - return true;
|
| - }
|
| - case WebKit::WebFilterOperation::FilterTypeInvert: {
|
| - getInvertMatrix(op.amount(), matrix);
|
| - return true;
|
| - }
|
| - case WebKit::WebFilterOperation::FilterTypeOpacity: {
|
| - getOpacityMatrix(op.amount(), matrix);
|
| - return true;
|
| - }
|
| - case WebKit::WebFilterOperation::FilterTypeColorMatrix: {
|
| - memcpy(matrix, op.matrix(), sizeof(SkScalar[20]));
|
| - return true;
|
| - }
|
| - default:
|
| - return false;
|
| - }
|
| -}
|
| -
|
| -class FilterBufferState {
|
| -public:
|
| - FilterBufferState(GrContext* grContext, const FloatSize& size, unsigned textureId)
|
| - : m_grContext(grContext)
|
| - , m_currentTexture(0)
|
| - {
|
| - // Wrap the source texture in a Ganesh platform texture.
|
| - GrPlatformTextureDesc platformTextureDescription;
|
| - platformTextureDescription.fWidth = size.width();
|
| - platformTextureDescription.fHeight = size.height();
|
| - platformTextureDescription.fConfig = kSkia8888_GrPixelConfig;
|
| - platformTextureDescription.fTextureHandle = textureId;
|
| - SkAutoTUnref<GrTexture> texture(grContext->createPlatformTexture(platformTextureDescription));
|
| - // Place the platform texture inside an SkBitmap.
|
| - m_source.setConfig(SkBitmap::kARGB_8888_Config, size.width(), size.height());
|
| - m_source.setPixelRef(new SkGrPixelRef(texture.get()))->unref();
|
| - }
|
| -
|
| - ~FilterBufferState() { }
|
| -
|
| - bool init(int filterCount)
|
| - {
|
| - int scratchCount = std::min(2, filterCount);
|
| - GrTextureDesc desc;
|
| - desc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit;
|
| - desc.fSampleCnt = 0;
|
| - desc.fWidth = m_source.width();
|
| - desc.fHeight = m_source.height();
|
| - desc.fConfig = kSkia8888_GrPixelConfig;
|
| - for (int i = 0; i < scratchCount; ++i) {
|
| - GrAutoScratchTexture scratchTexture(m_grContext, desc, GrContext::kExact_ScratchTexMatch);
|
| - m_scratchTextures[i].reset(scratchTexture.detach());
|
| - if (!m_scratchTextures[i].get())
|
| - return false;
|
| - }
|
| - return true;
|
| - }
|
| -
|
| - SkCanvas* canvas()
|
| - {
|
| - if (!m_canvas.get())
|
| - createCanvas();
|
| - return m_canvas.get();
|
| - }
|
| -
|
| - const SkBitmap& source() { return m_source; }
|
| -
|
| - void swap()
|
| - {
|
| - m_canvas->flush();
|
| - m_canvas.reset(0);
|
| - m_device.reset(0);
|
| -
|
| - m_source.setPixelRef(new SkGrPixelRef(m_scratchTextures[m_currentTexture].get()))->unref();
|
| - m_currentTexture = 1 - m_currentTexture;
|
| - }
|
| -
|
| -private:
|
| - void createCanvas()
|
| - {
|
| - ASSERT(m_scratchTextures[m_currentTexture].get());
|
| - m_device.reset(new SkGpuDevice(m_grContext, m_scratchTextures[m_currentTexture].get()));
|
| - m_canvas.reset(new SkCanvas(m_device.get()));
|
| - m_canvas->clear(0x0);
|
| - }
|
| -
|
| - GrContext* m_grContext;
|
| - SkBitmap m_source;
|
| - SkAutoTUnref<GrTexture> m_scratchTextures[2];
|
| - int m_currentTexture;
|
| - SkAutoTUnref<SkGpuDevice> m_device;
|
| - SkAutoTUnref<SkCanvas> m_canvas;
|
| -};
|
| -
|
| -}
|
| -
|
| -namespace cc {
|
| -
|
| -WebKit::WebFilterOperations CCRenderSurfaceFilters::optimize(const WebKit::WebFilterOperations& filters)
|
| -{
|
| - WebKit::WebFilterOperations newList;
|
| -
|
| - SkScalar accumulatedColorMatrix[20];
|
| - bool haveAccumulatedColorMatrix = false;
|
| - for (unsigned i = 0; i < filters.size(); ++i) {
|
| - const WebKit::WebFilterOperation& op = filters.at(i);
|
| -
|
| - // If the filter is a color matrix, we may be able to combine it with
|
| - // following filter(s) that also are color matrices.
|
| - SkScalar matrix[20];
|
| - if (getColorMatrix(op, matrix)) {
|
| - if (haveAccumulatedColorMatrix) {
|
| - SkScalar newMatrix[20];
|
| - multColorMatrix(matrix, accumulatedColorMatrix, newMatrix);
|
| - memcpy(accumulatedColorMatrix, newMatrix, sizeof(accumulatedColorMatrix));
|
| - } else {
|
| - memcpy(accumulatedColorMatrix, matrix, sizeof(accumulatedColorMatrix));
|
| - haveAccumulatedColorMatrix = true;
|
| - }
|
| -
|
| - // We can only combine matrices if clamping of color components
|
| - // would have no effect.
|
| - if (!matrixNeedsClamping(accumulatedColorMatrix))
|
| - continue;
|
| - }
|
| -
|
| - if (haveAccumulatedColorMatrix)
|
| - newList.append(WebKit::WebFilterOperation::createColorMatrixFilter(accumulatedColorMatrix));
|
| - haveAccumulatedColorMatrix = false;
|
| -
|
| - switch (op.type()) {
|
| - case WebKit::WebFilterOperation::FilterTypeBlur:
|
| - case WebKit::WebFilterOperation::FilterTypeDropShadow:
|
| - case WebKit::WebFilterOperation::FilterTypeZoom:
|
| - newList.append(op);
|
| - break;
|
| - case WebKit::WebFilterOperation::FilterTypeBrightness:
|
| - case WebKit::WebFilterOperation::FilterTypeContrast:
|
| - case WebKit::WebFilterOperation::FilterTypeGrayscale:
|
| - case WebKit::WebFilterOperation::FilterTypeSepia:
|
| - case WebKit::WebFilterOperation::FilterTypeSaturate:
|
| - case WebKit::WebFilterOperation::FilterTypeHueRotate:
|
| - case WebKit::WebFilterOperation::FilterTypeInvert:
|
| - case WebKit::WebFilterOperation::FilterTypeOpacity:
|
| - case WebKit::WebFilterOperation::FilterTypeColorMatrix:
|
| - break;
|
| - }
|
| - }
|
| - if (haveAccumulatedColorMatrix)
|
| - newList.append(WebKit::WebFilterOperation::createColorMatrixFilter(accumulatedColorMatrix));
|
| - return newList;
|
| -}
|
| -
|
| -SkBitmap CCRenderSurfaceFilters::apply(const WebKit::WebFilterOperations& filters, unsigned textureId, const FloatSize& size, WebKit::WebGraphicsContext3D* context3D, GrContext* grContext)
|
| -{
|
| - if (!context3D || !grContext)
|
| - return SkBitmap();
|
| -
|
| - WebKit::WebFilterOperations optimizedFilters = optimize(filters);
|
| - FilterBufferState state(grContext, size, textureId);
|
| - if (!state.init(optimizedFilters.size()))
|
| - return SkBitmap();
|
| -
|
| - for (unsigned i = 0; i < optimizedFilters.size(); ++i) {
|
| - const WebKit::WebFilterOperation& op = optimizedFilters.at(i);
|
| - SkCanvas* canvas = state.canvas();
|
| - switch (op.type()) {
|
| - case WebKit::WebFilterOperation::FilterTypeColorMatrix: {
|
| - SkPaint paint;
|
| - paint.setColorFilter(new SkColorMatrixFilter(op.matrix()))->unref();
|
| - canvas->drawBitmap(state.source(), 0, 0, &paint);
|
| - break;
|
| - }
|
| - case WebKit::WebFilterOperation::FilterTypeBlur: {
|
| - float stdDeviation = op.amount();
|
| - SkAutoTUnref<SkImageFilter> filter(new SkBlurImageFilter(stdDeviation, stdDeviation));
|
| - SkPaint paint;
|
| - paint.setImageFilter(filter.get());
|
| - canvas->drawSprite(state.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(state.source(), op.dropShadowOffset().x, -op.dropShadowOffset().y);
|
| - canvas->restore();
|
| - canvas->drawBitmap(state.source(), 0, 0);
|
| - break;
|
| - }
|
| - case WebKit::WebFilterOperation::FilterTypeZoom: {
|
| - SkPaint paint;
|
| - SkAutoTUnref<SkImageFilter> zoomFilter(
|
| - new SkMagnifierImageFilter(
|
| - SkRect::MakeXYWH(op.zoomRect().x,
|
| - op.zoomRect().y,
|
| - op.zoomRect().width,
|
| - op.zoomRect().height),
|
| - op.amount()));
|
| - paint.setImageFilter(zoomFilter.get());
|
| - canvas->saveLayer(0, &paint);
|
| - canvas->drawBitmap(state.source(), 0, 0);
|
| - canvas->restore();
|
| - break;
|
| - }
|
| - case WebKit::WebFilterOperation::FilterTypeBrightness:
|
| - case WebKit::WebFilterOperation::FilterTypeContrast:
|
| - case WebKit::WebFilterOperation::FilterTypeGrayscale:
|
| - case WebKit::WebFilterOperation::FilterTypeSepia:
|
| - case WebKit::WebFilterOperation::FilterTypeSaturate:
|
| - case WebKit::WebFilterOperation::FilterTypeHueRotate:
|
| - case WebKit::WebFilterOperation::FilterTypeInvert:
|
| - case WebKit::WebFilterOperation::FilterTypeOpacity:
|
| - ASSERT_NOT_REACHED();
|
| - break;
|
| - }
|
| - state.swap();
|
| - }
|
| - context3D->flush();
|
| - return state.source();
|
| -}
|
| -
|
| -}
|
| -#endif // USE(ACCELERATED_COMPOSITING)
|
|
|