2012-06-22 21:01:23 +00:00
|
|
|
/*
|
|
|
|
* Copyright 2012 Google Inc.
|
|
|
|
*
|
|
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
|
|
* found in the LICENSE file.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "gm.h"
|
|
|
|
#include "SkLightingImageFilter.h"
|
Implement approx-match support in image filter saveLayer() offscreen.
Currently, the GPU-side image filter implementation creates
exact-match textures for the offscreen backing stores for
saveLayer(). This is because several filters have GPU
implementations which depend on the texture coordinates
being 0..1.
The fix is three-fold:
1) Store the actual requested size in the SkGpuDevice, so
that when wrapping it in an SkBitmap for passing to
filterImage(), we can give it the original size.
2) Fix the filters (SkMagnifierImageFilter,
SkLightingImageFilter, SkMatrixConvolutionImageFilter,
SkMatrixImageFilter) whose GPU implementation depends on
0..1 texture coordinates.
3) Remove the exception for GPU-side image filters in
SkCanvas::internalSaveLayer().
For the lighting filters, there were two bugs which were
cancelling each other out: the sobel filter matrix was
being computed upside down, but then we'd negate the
resulting normal. This worked fine in the exact-match case,
but in the approx-match case we'd sample garbage along
the edge pixels. Also, we never implemented the edge pixels
according to spec in the GPU case. It requires a
different fragment shader for each edge of the nine-patch,
which meant we couldn't use asFragmentProcessor(), and had
to implement the drawing via a filterImageGPU() override.
In order to avoid polluting the public API, I inserted a
new base class, SkLightingImageFilterInternal above
Sk[Diffuse|Specular]LightingImageFilter to handle the
implementation.
For the SkMatrixConvolutionImageFilter, it seems the
GLSL clamp() function occasionally returns values outside
the clamped range, resulting in access of garbage
texels even in GL_NEAREST. The fix here is to clamp to a
rect inset by half a texel. There was also a bug in
the unpremultiply step when fConvolveAlpha is false.
For SkMatrixImageFilter, the fix was to make the generic
draw path be more careful about when to use texture domain.
If the bitmap already has a texture, use texture domain
if the srcRect is smaller than the entire texture (not
the entire bitmap).
N.B.: this change will cause some minor pixel diffs in the
GPU results of the following GMs (and possibly more):
matriximagefilter, matrixconvolution, imagefiltersscaled,
lighting, imagemagnifier, filterfastbounds,
complexclip_aa_Layer_invert, complexclip_aa_layer,
complexclip_bw_layer_invert, complexclip_bw_layer.
BUG=skia:3532
Committed: https://skia.googlesource.com/skia/+/b97dafefe63ea0a1bbce8e8b209f4920983fb8b9
Committed: https://skia.googlesource.com/skia/+/f5f8518fe0bbd2703e4ffc1b11ad7b4312ff7641
Committed: https://skia.googlesource.com/skia/+/46112cf2a7c7307f1c9eebb5f881cbda15aa460c
Review URL: https://codereview.chromium.org/1034733002
2015-04-02 11:54:56 +00:00
|
|
|
#include "SkOffsetImageFilter.h"
|
2015-07-13 20:16:44 +00:00
|
|
|
#include "SkPoint3.h"
|
2012-06-22 21:01:23 +00:00
|
|
|
|
|
|
|
#define WIDTH 330
|
Implement approx-match support in image filter saveLayer() offscreen.
Currently, the GPU-side image filter implementation creates
exact-match textures for the offscreen backing stores for
saveLayer(). This is because several filters have GPU
implementations which depend on the texture coordinates
being 0..1.
The fix is three-fold:
1) Store the actual requested size in the SkGpuDevice, so
that when wrapping it in an SkBitmap for passing to
filterImage(), we can give it the original size.
2) Fix the filters (SkMagnifierImageFilter,
SkLightingImageFilter, SkMatrixConvolutionImageFilter,
SkMatrixImageFilter) whose GPU implementation depends on
0..1 texture coordinates.
3) Remove the exception for GPU-side image filters in
SkCanvas::internalSaveLayer().
For the lighting filters, there were two bugs which were
cancelling each other out: the sobel filter matrix was
being computed upside down, but then we'd negate the
resulting normal. This worked fine in the exact-match case,
but in the approx-match case we'd sample garbage along
the edge pixels. Also, we never implemented the edge pixels
according to spec in the GPU case. It requires a
different fragment shader for each edge of the nine-patch,
which meant we couldn't use asFragmentProcessor(), and had
to implement the drawing via a filterImageGPU() override.
In order to avoid polluting the public API, I inserted a
new base class, SkLightingImageFilterInternal above
Sk[Diffuse|Specular]LightingImageFilter to handle the
implementation.
For the SkMatrixConvolutionImageFilter, it seems the
GLSL clamp() function occasionally returns values outside
the clamped range, resulting in access of garbage
texels even in GL_NEAREST. The fix here is to clamp to a
rect inset by half a texel. There was also a bug in
the unpremultiply step when fConvolveAlpha is false.
For SkMatrixImageFilter, the fix was to make the generic
draw path be more careful about when to use texture domain.
If the bitmap already has a texture, use texture domain
if the srcRect is smaller than the entire texture (not
the entire bitmap).
N.B.: this change will cause some minor pixel diffs in the
GPU results of the following GMs (and possibly more):
matriximagefilter, matrixconvolution, imagefiltersscaled,
lighting, imagemagnifier, filterfastbounds,
complexclip_aa_Layer_invert, complexclip_aa_layer,
complexclip_bw_layer_invert, complexclip_bw_layer.
BUG=skia:3532
Committed: https://skia.googlesource.com/skia/+/b97dafefe63ea0a1bbce8e8b209f4920983fb8b9
Committed: https://skia.googlesource.com/skia/+/f5f8518fe0bbd2703e4ffc1b11ad7b4312ff7641
Committed: https://skia.googlesource.com/skia/+/46112cf2a7c7307f1c9eebb5f881cbda15aa460c
Review URL: https://codereview.chromium.org/1034733002
2015-04-02 11:54:56 +00:00
|
|
|
#define HEIGHT 660
|
2012-06-22 21:01:23 +00:00
|
|
|
|
|
|
|
namespace skiagm {
|
|
|
|
|
|
|
|
class ImageLightingGM : public GM {
|
|
|
|
public:
|
|
|
|
ImageLightingGM() : fInitialized(false) {
|
|
|
|
this->setBGColor(0xFF000000);
|
|
|
|
}
|
2012-08-23 18:19:56 +00:00
|
|
|
|
2012-06-22 21:01:23 +00:00
|
|
|
protected:
|
2014-04-30 13:20:45 +00:00
|
|
|
|
2015-03-26 01:17:31 +00:00
|
|
|
SkString onShortName() override {
|
2012-06-22 21:01:23 +00:00
|
|
|
return SkString("lighting");
|
|
|
|
}
|
|
|
|
|
|
|
|
void make_bitmap() {
|
2014-01-25 16:46:20 +00:00
|
|
|
fBitmap.allocN32Pixels(100, 100);
|
2014-02-13 17:14:46 +00:00
|
|
|
SkCanvas canvas(fBitmap);
|
2012-06-22 21:01:23 +00:00
|
|
|
canvas.clear(0x00000000);
|
|
|
|
SkPaint paint;
|
|
|
|
paint.setAntiAlias(true);
|
2014-07-31 12:58:44 +00:00
|
|
|
sk_tool_utils::set_portable_typeface(&paint);
|
2012-06-22 21:01:23 +00:00
|
|
|
paint.setColor(0xFFFFFFFF);
|
|
|
|
paint.setTextSize(SkIntToScalar(96));
|
|
|
|
const char* str = "e";
|
|
|
|
canvas.drawText(str, strlen(str), SkIntToScalar(20), SkIntToScalar(70), paint);
|
|
|
|
}
|
|
|
|
|
2015-03-26 01:17:31 +00:00
|
|
|
SkISize onISize() override {
|
2014-02-13 17:14:46 +00:00
|
|
|
return SkISize::Make(WIDTH, HEIGHT);
|
2012-06-22 21:01:23 +00:00
|
|
|
}
|
|
|
|
|
2013-01-14 16:27:50 +00:00
|
|
|
void drawClippedBitmap(SkCanvas* canvas, const SkPaint& paint, int x, int y) {
|
|
|
|
canvas->save();
|
2013-08-27 21:37:01 +00:00
|
|
|
canvas->translate(SkIntToScalar(x), SkIntToScalar(y));
|
|
|
|
canvas->clipRect(SkRect::MakeWH(
|
|
|
|
SkIntToScalar(fBitmap.width()), SkIntToScalar(fBitmap.height())));
|
|
|
|
canvas->drawBitmap(fBitmap, 0, 0, &paint);
|
2013-01-14 16:27:50 +00:00
|
|
|
canvas->restore();
|
|
|
|
}
|
|
|
|
|
2015-03-26 01:17:31 +00:00
|
|
|
void onDraw(SkCanvas* canvas) override {
|
2012-06-22 21:01:23 +00:00
|
|
|
if (!fInitialized) {
|
|
|
|
make_bitmap();
|
|
|
|
fInitialized = true;
|
|
|
|
}
|
2012-10-29 19:47:06 +00:00
|
|
|
canvas->clear(0xFF101010);
|
|
|
|
SkPaint checkPaint;
|
|
|
|
checkPaint.setColor(0xFF202020);
|
|
|
|
for (int y = 0; y < HEIGHT; y += 16) {
|
|
|
|
for (int x = 0; x < WIDTH; x += 16) {
|
|
|
|
canvas->save();
|
|
|
|
canvas->translate(SkIntToScalar(x), SkIntToScalar(y));
|
|
|
|
canvas->drawRect(SkRect::MakeXYWH(8, 0, 8, 8), checkPaint);
|
|
|
|
canvas->drawRect(SkRect::MakeXYWH(0, 8, 8, 8), checkPaint);
|
|
|
|
canvas->restore();
|
|
|
|
}
|
|
|
|
}
|
2015-07-13 20:16:44 +00:00
|
|
|
SkPoint3 pointLocation = SkPoint3::Make(0, 0, SkIntToScalar(10));
|
2012-06-22 21:01:23 +00:00
|
|
|
SkScalar azimuthRad = SkDegreesToRadians(SkIntToScalar(225));
|
|
|
|
SkScalar elevationRad = SkDegreesToRadians(SkIntToScalar(5));
|
2015-07-13 20:16:44 +00:00
|
|
|
SkPoint3 distantDirection = SkPoint3::Make(SkScalarMul(SkScalarCos(azimuthRad),
|
|
|
|
SkScalarCos(elevationRad)),
|
|
|
|
SkScalarMul(SkScalarSin(azimuthRad),
|
|
|
|
SkScalarCos(elevationRad)),
|
|
|
|
SkScalarSin(elevationRad));
|
|
|
|
SkPoint3 spotLocation = SkPoint3::Make(SkIntToScalar(-10),
|
|
|
|
SkIntToScalar(-10),
|
|
|
|
SkIntToScalar(20));
|
|
|
|
SkPoint3 spotTarget = SkPoint3::Make(SkIntToScalar(40), SkIntToScalar(40), 0);
|
2012-06-22 21:01:23 +00:00
|
|
|
SkScalar spotExponent = SK_Scalar1;
|
|
|
|
SkScalar cutoffAngle = SkIntToScalar(15);
|
|
|
|
SkScalar kd = SkIntToScalar(2);
|
|
|
|
SkScalar ks = SkIntToScalar(1);
|
|
|
|
SkScalar shininess = SkIntToScalar(8);
|
|
|
|
SkScalar surfaceScale = SkIntToScalar(1);
|
|
|
|
SkColor white(0xFFFFFFFF);
|
|
|
|
SkPaint paint;
|
2013-07-26 00:10:07 +00:00
|
|
|
|
2013-10-10 13:51:19 +00:00
|
|
|
SkImageFilter::CropRect cropRect(SkRect::MakeXYWH(20, 10, 60, 65));
|
Implement approx-match support in image filter saveLayer() offscreen.
Currently, the GPU-side image filter implementation creates
exact-match textures for the offscreen backing stores for
saveLayer(). This is because several filters have GPU
implementations which depend on the texture coordinates
being 0..1.
The fix is three-fold:
1) Store the actual requested size in the SkGpuDevice, so
that when wrapping it in an SkBitmap for passing to
filterImage(), we can give it the original size.
2) Fix the filters (SkMagnifierImageFilter,
SkLightingImageFilter, SkMatrixConvolutionImageFilter,
SkMatrixImageFilter) whose GPU implementation depends on
0..1 texture coordinates.
3) Remove the exception for GPU-side image filters in
SkCanvas::internalSaveLayer().
For the lighting filters, there were two bugs which were
cancelling each other out: the sobel filter matrix was
being computed upside down, but then we'd negate the
resulting normal. This worked fine in the exact-match case,
but in the approx-match case we'd sample garbage along
the edge pixels. Also, we never implemented the edge pixels
according to spec in the GPU case. It requires a
different fragment shader for each edge of the nine-patch,
which meant we couldn't use asFragmentProcessor(), and had
to implement the drawing via a filterImageGPU() override.
In order to avoid polluting the public API, I inserted a
new base class, SkLightingImageFilterInternal above
Sk[Diffuse|Specular]LightingImageFilter to handle the
implementation.
For the SkMatrixConvolutionImageFilter, it seems the
GLSL clamp() function occasionally returns values outside
the clamped range, resulting in access of garbage
texels even in GL_NEAREST. The fix here is to clamp to a
rect inset by half a texel. There was also a bug in
the unpremultiply step when fConvolveAlpha is false.
For SkMatrixImageFilter, the fix was to make the generic
draw path be more careful about when to use texture domain.
If the bitmap already has a texture, use texture domain
if the srcRect is smaller than the entire texture (not
the entire bitmap).
N.B.: this change will cause some minor pixel diffs in the
GPU results of the following GMs (and possibly more):
matriximagefilter, matrixconvolution, imagefiltersscaled,
lighting, imagemagnifier, filterfastbounds,
complexclip_aa_Layer_invert, complexclip_aa_layer,
complexclip_bw_layer_invert, complexclip_bw_layer.
BUG=skia:3532
Committed: https://skia.googlesource.com/skia/+/b97dafefe63ea0a1bbce8e8b209f4920983fb8b9
Committed: https://skia.googlesource.com/skia/+/f5f8518fe0bbd2703e4ffc1b11ad7b4312ff7641
Committed: https://skia.googlesource.com/skia/+/46112cf2a7c7307f1c9eebb5f881cbda15aa460c
Review URL: https://codereview.chromium.org/1034733002
2015-04-02 11:54:56 +00:00
|
|
|
SkImageFilter::CropRect fullSizeCropRect(SkRect::MakeXYWH(0, 0, 100, 100));
|
|
|
|
SkAutoTUnref<SkImageFilter> noopCropped(SkOffsetImageFilter::Create(0, 0, NULL, &cropRect));
|
2013-07-26 00:10:07 +00:00
|
|
|
|
|
|
|
int y = 0;
|
Implement approx-match support in image filter saveLayer() offscreen.
Currently, the GPU-side image filter implementation creates
exact-match textures for the offscreen backing stores for
saveLayer(). This is because several filters have GPU
implementations which depend on the texture coordinates
being 0..1.
The fix is three-fold:
1) Store the actual requested size in the SkGpuDevice, so
that when wrapping it in an SkBitmap for passing to
filterImage(), we can give it the original size.
2) Fix the filters (SkMagnifierImageFilter,
SkLightingImageFilter, SkMatrixConvolutionImageFilter,
SkMatrixImageFilter) whose GPU implementation depends on
0..1 texture coordinates.
3) Remove the exception for GPU-side image filters in
SkCanvas::internalSaveLayer().
For the lighting filters, there were two bugs which were
cancelling each other out: the sobel filter matrix was
being computed upside down, but then we'd negate the
resulting normal. This worked fine in the exact-match case,
but in the approx-match case we'd sample garbage along
the edge pixels. Also, we never implemented the edge pixels
according to spec in the GPU case. It requires a
different fragment shader for each edge of the nine-patch,
which meant we couldn't use asFragmentProcessor(), and had
to implement the drawing via a filterImageGPU() override.
In order to avoid polluting the public API, I inserted a
new base class, SkLightingImageFilterInternal above
Sk[Diffuse|Specular]LightingImageFilter to handle the
implementation.
For the SkMatrixConvolutionImageFilter, it seems the
GLSL clamp() function occasionally returns values outside
the clamped range, resulting in access of garbage
texels even in GL_NEAREST. The fix here is to clamp to a
rect inset by half a texel. There was also a bug in
the unpremultiply step when fConvolveAlpha is false.
For SkMatrixImageFilter, the fix was to make the generic
draw path be more careful about when to use texture domain.
If the bitmap already has a texture, use texture domain
if the srcRect is smaller than the entire texture (not
the entire bitmap).
N.B.: this change will cause some minor pixel diffs in the
GPU results of the following GMs (and possibly more):
matriximagefilter, matrixconvolution, imagefiltersscaled,
lighting, imagemagnifier, filterfastbounds,
complexclip_aa_Layer_invert, complexclip_aa_layer,
complexclip_bw_layer_invert, complexclip_bw_layer.
BUG=skia:3532
Committed: https://skia.googlesource.com/skia/+/b97dafefe63ea0a1bbce8e8b209f4920983fb8b9
Committed: https://skia.googlesource.com/skia/+/f5f8518fe0bbd2703e4ffc1b11ad7b4312ff7641
Committed: https://skia.googlesource.com/skia/+/46112cf2a7c7307f1c9eebb5f881cbda15aa460c
Review URL: https://codereview.chromium.org/1034733002
2015-04-02 11:54:56 +00:00
|
|
|
for (int i = 0; i < 3; i++) {
|
|
|
|
const SkImageFilter::CropRect* cr = (i == 1) ? &cropRect : (i == 2) ? &fullSizeCropRect : NULL;
|
|
|
|
SkImageFilter* input = (i == 2) ? noopCropped.get() : NULL;
|
|
|
|
paint.setImageFilter(SkLightingImageFilter::CreatePointLitDiffuse(pointLocation,
|
|
|
|
white,
|
|
|
|
surfaceScale,
|
|
|
|
kd,
|
|
|
|
input,
|
|
|
|
cr))->unref();
|
2013-07-26 00:10:07 +00:00
|
|
|
drawClippedBitmap(canvas, paint, 0, y);
|
2013-08-27 21:37:01 +00:00
|
|
|
|
Implement approx-match support in image filter saveLayer() offscreen.
Currently, the GPU-side image filter implementation creates
exact-match textures for the offscreen backing stores for
saveLayer(). This is because several filters have GPU
implementations which depend on the texture coordinates
being 0..1.
The fix is three-fold:
1) Store the actual requested size in the SkGpuDevice, so
that when wrapping it in an SkBitmap for passing to
filterImage(), we can give it the original size.
2) Fix the filters (SkMagnifierImageFilter,
SkLightingImageFilter, SkMatrixConvolutionImageFilter,
SkMatrixImageFilter) whose GPU implementation depends on
0..1 texture coordinates.
3) Remove the exception for GPU-side image filters in
SkCanvas::internalSaveLayer().
For the lighting filters, there were two bugs which were
cancelling each other out: the sobel filter matrix was
being computed upside down, but then we'd negate the
resulting normal. This worked fine in the exact-match case,
but in the approx-match case we'd sample garbage along
the edge pixels. Also, we never implemented the edge pixels
according to spec in the GPU case. It requires a
different fragment shader for each edge of the nine-patch,
which meant we couldn't use asFragmentProcessor(), and had
to implement the drawing via a filterImageGPU() override.
In order to avoid polluting the public API, I inserted a
new base class, SkLightingImageFilterInternal above
Sk[Diffuse|Specular]LightingImageFilter to handle the
implementation.
For the SkMatrixConvolutionImageFilter, it seems the
GLSL clamp() function occasionally returns values outside
the clamped range, resulting in access of garbage
texels even in GL_NEAREST. The fix here is to clamp to a
rect inset by half a texel. There was also a bug in
the unpremultiply step when fConvolveAlpha is false.
For SkMatrixImageFilter, the fix was to make the generic
draw path be more careful about when to use texture domain.
If the bitmap already has a texture, use texture domain
if the srcRect is smaller than the entire texture (not
the entire bitmap).
N.B.: this change will cause some minor pixel diffs in the
GPU results of the following GMs (and possibly more):
matriximagefilter, matrixconvolution, imagefiltersscaled,
lighting, imagemagnifier, filterfastbounds,
complexclip_aa_Layer_invert, complexclip_aa_layer,
complexclip_bw_layer_invert, complexclip_bw_layer.
BUG=skia:3532
Committed: https://skia.googlesource.com/skia/+/b97dafefe63ea0a1bbce8e8b209f4920983fb8b9
Committed: https://skia.googlesource.com/skia/+/f5f8518fe0bbd2703e4ffc1b11ad7b4312ff7641
Committed: https://skia.googlesource.com/skia/+/46112cf2a7c7307f1c9eebb5f881cbda15aa460c
Review URL: https://codereview.chromium.org/1034733002
2015-04-02 11:54:56 +00:00
|
|
|
paint.setImageFilter(SkLightingImageFilter::CreateDistantLitDiffuse(distantDirection,
|
|
|
|
white,
|
|
|
|
surfaceScale,
|
|
|
|
kd,
|
|
|
|
input,
|
|
|
|
cr))->unref();
|
2013-07-26 00:10:07 +00:00
|
|
|
drawClippedBitmap(canvas, paint, 110, y);
|
2013-08-27 21:37:01 +00:00
|
|
|
|
Implement approx-match support in image filter saveLayer() offscreen.
Currently, the GPU-side image filter implementation creates
exact-match textures for the offscreen backing stores for
saveLayer(). This is because several filters have GPU
implementations which depend on the texture coordinates
being 0..1.
The fix is three-fold:
1) Store the actual requested size in the SkGpuDevice, so
that when wrapping it in an SkBitmap for passing to
filterImage(), we can give it the original size.
2) Fix the filters (SkMagnifierImageFilter,
SkLightingImageFilter, SkMatrixConvolutionImageFilter,
SkMatrixImageFilter) whose GPU implementation depends on
0..1 texture coordinates.
3) Remove the exception for GPU-side image filters in
SkCanvas::internalSaveLayer().
For the lighting filters, there were two bugs which were
cancelling each other out: the sobel filter matrix was
being computed upside down, but then we'd negate the
resulting normal. This worked fine in the exact-match case,
but in the approx-match case we'd sample garbage along
the edge pixels. Also, we never implemented the edge pixels
according to spec in the GPU case. It requires a
different fragment shader for each edge of the nine-patch,
which meant we couldn't use asFragmentProcessor(), and had
to implement the drawing via a filterImageGPU() override.
In order to avoid polluting the public API, I inserted a
new base class, SkLightingImageFilterInternal above
Sk[Diffuse|Specular]LightingImageFilter to handle the
implementation.
For the SkMatrixConvolutionImageFilter, it seems the
GLSL clamp() function occasionally returns values outside
the clamped range, resulting in access of garbage
texels even in GL_NEAREST. The fix here is to clamp to a
rect inset by half a texel. There was also a bug in
the unpremultiply step when fConvolveAlpha is false.
For SkMatrixImageFilter, the fix was to make the generic
draw path be more careful about when to use texture domain.
If the bitmap already has a texture, use texture domain
if the srcRect is smaller than the entire texture (not
the entire bitmap).
N.B.: this change will cause some minor pixel diffs in the
GPU results of the following GMs (and possibly more):
matriximagefilter, matrixconvolution, imagefiltersscaled,
lighting, imagemagnifier, filterfastbounds,
complexclip_aa_Layer_invert, complexclip_aa_layer,
complexclip_bw_layer_invert, complexclip_bw_layer.
BUG=skia:3532
Committed: https://skia.googlesource.com/skia/+/b97dafefe63ea0a1bbce8e8b209f4920983fb8b9
Committed: https://skia.googlesource.com/skia/+/f5f8518fe0bbd2703e4ffc1b11ad7b4312ff7641
Committed: https://skia.googlesource.com/skia/+/46112cf2a7c7307f1c9eebb5f881cbda15aa460c
Review URL: https://codereview.chromium.org/1034733002
2015-04-02 11:54:56 +00:00
|
|
|
paint.setImageFilter(SkLightingImageFilter::CreateSpotLitDiffuse(spotLocation,
|
|
|
|
spotTarget,
|
|
|
|
spotExponent,
|
|
|
|
cutoffAngle,
|
|
|
|
white,
|
|
|
|
surfaceScale,
|
|
|
|
kd,
|
|
|
|
input,
|
|
|
|
cr))->unref();
|
2013-07-26 00:10:07 +00:00
|
|
|
drawClippedBitmap(canvas, paint, 220, y);
|
|
|
|
|
|
|
|
y += 110;
|
2013-08-27 21:37:01 +00:00
|
|
|
|
Implement approx-match support in image filter saveLayer() offscreen.
Currently, the GPU-side image filter implementation creates
exact-match textures for the offscreen backing stores for
saveLayer(). This is because several filters have GPU
implementations which depend on the texture coordinates
being 0..1.
The fix is three-fold:
1) Store the actual requested size in the SkGpuDevice, so
that when wrapping it in an SkBitmap for passing to
filterImage(), we can give it the original size.
2) Fix the filters (SkMagnifierImageFilter,
SkLightingImageFilter, SkMatrixConvolutionImageFilter,
SkMatrixImageFilter) whose GPU implementation depends on
0..1 texture coordinates.
3) Remove the exception for GPU-side image filters in
SkCanvas::internalSaveLayer().
For the lighting filters, there were two bugs which were
cancelling each other out: the sobel filter matrix was
being computed upside down, but then we'd negate the
resulting normal. This worked fine in the exact-match case,
but in the approx-match case we'd sample garbage along
the edge pixels. Also, we never implemented the edge pixels
according to spec in the GPU case. It requires a
different fragment shader for each edge of the nine-patch,
which meant we couldn't use asFragmentProcessor(), and had
to implement the drawing via a filterImageGPU() override.
In order to avoid polluting the public API, I inserted a
new base class, SkLightingImageFilterInternal above
Sk[Diffuse|Specular]LightingImageFilter to handle the
implementation.
For the SkMatrixConvolutionImageFilter, it seems the
GLSL clamp() function occasionally returns values outside
the clamped range, resulting in access of garbage
texels even in GL_NEAREST. The fix here is to clamp to a
rect inset by half a texel. There was also a bug in
the unpremultiply step when fConvolveAlpha is false.
For SkMatrixImageFilter, the fix was to make the generic
draw path be more careful about when to use texture domain.
If the bitmap already has a texture, use texture domain
if the srcRect is smaller than the entire texture (not
the entire bitmap).
N.B.: this change will cause some minor pixel diffs in the
GPU results of the following GMs (and possibly more):
matriximagefilter, matrixconvolution, imagefiltersscaled,
lighting, imagemagnifier, filterfastbounds,
complexclip_aa_Layer_invert, complexclip_aa_layer,
complexclip_bw_layer_invert, complexclip_bw_layer.
BUG=skia:3532
Committed: https://skia.googlesource.com/skia/+/b97dafefe63ea0a1bbce8e8b209f4920983fb8b9
Committed: https://skia.googlesource.com/skia/+/f5f8518fe0bbd2703e4ffc1b11ad7b4312ff7641
Committed: https://skia.googlesource.com/skia/+/46112cf2a7c7307f1c9eebb5f881cbda15aa460c
Review URL: https://codereview.chromium.org/1034733002
2015-04-02 11:54:56 +00:00
|
|
|
paint.setImageFilter(SkLightingImageFilter::CreatePointLitSpecular(pointLocation,
|
|
|
|
white,
|
|
|
|
surfaceScale,
|
|
|
|
ks,
|
|
|
|
shininess,
|
|
|
|
input,
|
|
|
|
cr))->unref();
|
2013-07-26 00:10:07 +00:00
|
|
|
drawClippedBitmap(canvas, paint, 0, y);
|
2013-08-27 21:37:01 +00:00
|
|
|
|
Implement approx-match support in image filter saveLayer() offscreen.
Currently, the GPU-side image filter implementation creates
exact-match textures for the offscreen backing stores for
saveLayer(). This is because several filters have GPU
implementations which depend on the texture coordinates
being 0..1.
The fix is three-fold:
1) Store the actual requested size in the SkGpuDevice, so
that when wrapping it in an SkBitmap for passing to
filterImage(), we can give it the original size.
2) Fix the filters (SkMagnifierImageFilter,
SkLightingImageFilter, SkMatrixConvolutionImageFilter,
SkMatrixImageFilter) whose GPU implementation depends on
0..1 texture coordinates.
3) Remove the exception for GPU-side image filters in
SkCanvas::internalSaveLayer().
For the lighting filters, there were two bugs which were
cancelling each other out: the sobel filter matrix was
being computed upside down, but then we'd negate the
resulting normal. This worked fine in the exact-match case,
but in the approx-match case we'd sample garbage along
the edge pixels. Also, we never implemented the edge pixels
according to spec in the GPU case. It requires a
different fragment shader for each edge of the nine-patch,
which meant we couldn't use asFragmentProcessor(), and had
to implement the drawing via a filterImageGPU() override.
In order to avoid polluting the public API, I inserted a
new base class, SkLightingImageFilterInternal above
Sk[Diffuse|Specular]LightingImageFilter to handle the
implementation.
For the SkMatrixConvolutionImageFilter, it seems the
GLSL clamp() function occasionally returns values outside
the clamped range, resulting in access of garbage
texels even in GL_NEAREST. The fix here is to clamp to a
rect inset by half a texel. There was also a bug in
the unpremultiply step when fConvolveAlpha is false.
For SkMatrixImageFilter, the fix was to make the generic
draw path be more careful about when to use texture domain.
If the bitmap already has a texture, use texture domain
if the srcRect is smaller than the entire texture (not
the entire bitmap).
N.B.: this change will cause some minor pixel diffs in the
GPU results of the following GMs (and possibly more):
matriximagefilter, matrixconvolution, imagefiltersscaled,
lighting, imagemagnifier, filterfastbounds,
complexclip_aa_Layer_invert, complexclip_aa_layer,
complexclip_bw_layer_invert, complexclip_bw_layer.
BUG=skia:3532
Committed: https://skia.googlesource.com/skia/+/b97dafefe63ea0a1bbce8e8b209f4920983fb8b9
Committed: https://skia.googlesource.com/skia/+/f5f8518fe0bbd2703e4ffc1b11ad7b4312ff7641
Committed: https://skia.googlesource.com/skia/+/46112cf2a7c7307f1c9eebb5f881cbda15aa460c
Review URL: https://codereview.chromium.org/1034733002
2015-04-02 11:54:56 +00:00
|
|
|
paint.setImageFilter(SkLightingImageFilter::CreateDistantLitSpecular(distantDirection,
|
|
|
|
white,
|
|
|
|
surfaceScale,
|
|
|
|
ks,
|
|
|
|
shininess,
|
|
|
|
input,
|
|
|
|
cr))->unref();
|
2013-07-26 00:10:07 +00:00
|
|
|
drawClippedBitmap(canvas, paint, 110, y);
|
2013-08-27 21:37:01 +00:00
|
|
|
|
Implement approx-match support in image filter saveLayer() offscreen.
Currently, the GPU-side image filter implementation creates
exact-match textures for the offscreen backing stores for
saveLayer(). This is because several filters have GPU
implementations which depend on the texture coordinates
being 0..1.
The fix is three-fold:
1) Store the actual requested size in the SkGpuDevice, so
that when wrapping it in an SkBitmap for passing to
filterImage(), we can give it the original size.
2) Fix the filters (SkMagnifierImageFilter,
SkLightingImageFilter, SkMatrixConvolutionImageFilter,
SkMatrixImageFilter) whose GPU implementation depends on
0..1 texture coordinates.
3) Remove the exception for GPU-side image filters in
SkCanvas::internalSaveLayer().
For the lighting filters, there were two bugs which were
cancelling each other out: the sobel filter matrix was
being computed upside down, but then we'd negate the
resulting normal. This worked fine in the exact-match case,
but in the approx-match case we'd sample garbage along
the edge pixels. Also, we never implemented the edge pixels
according to spec in the GPU case. It requires a
different fragment shader for each edge of the nine-patch,
which meant we couldn't use asFragmentProcessor(), and had
to implement the drawing via a filterImageGPU() override.
In order to avoid polluting the public API, I inserted a
new base class, SkLightingImageFilterInternal above
Sk[Diffuse|Specular]LightingImageFilter to handle the
implementation.
For the SkMatrixConvolutionImageFilter, it seems the
GLSL clamp() function occasionally returns values outside
the clamped range, resulting in access of garbage
texels even in GL_NEAREST. The fix here is to clamp to a
rect inset by half a texel. There was also a bug in
the unpremultiply step when fConvolveAlpha is false.
For SkMatrixImageFilter, the fix was to make the generic
draw path be more careful about when to use texture domain.
If the bitmap already has a texture, use texture domain
if the srcRect is smaller than the entire texture (not
the entire bitmap).
N.B.: this change will cause some minor pixel diffs in the
GPU results of the following GMs (and possibly more):
matriximagefilter, matrixconvolution, imagefiltersscaled,
lighting, imagemagnifier, filterfastbounds,
complexclip_aa_Layer_invert, complexclip_aa_layer,
complexclip_bw_layer_invert, complexclip_bw_layer.
BUG=skia:3532
Committed: https://skia.googlesource.com/skia/+/b97dafefe63ea0a1bbce8e8b209f4920983fb8b9
Committed: https://skia.googlesource.com/skia/+/f5f8518fe0bbd2703e4ffc1b11ad7b4312ff7641
Committed: https://skia.googlesource.com/skia/+/46112cf2a7c7307f1c9eebb5f881cbda15aa460c
Review URL: https://codereview.chromium.org/1034733002
2015-04-02 11:54:56 +00:00
|
|
|
paint.setImageFilter(SkLightingImageFilter::CreateSpotLitSpecular(spotLocation,
|
|
|
|
spotTarget,
|
|
|
|
spotExponent,
|
|
|
|
cutoffAngle,
|
|
|
|
white,
|
|
|
|
surfaceScale,
|
|
|
|
ks,
|
|
|
|
shininess,
|
|
|
|
input,
|
|
|
|
cr))->unref();
|
2013-07-26 00:10:07 +00:00
|
|
|
drawClippedBitmap(canvas, paint, 220, y);
|
2013-08-27 21:37:01 +00:00
|
|
|
|
2013-07-26 00:10:07 +00:00
|
|
|
y += 110;
|
|
|
|
}
|
2012-06-22 21:01:23 +00:00
|
|
|
}
|
2012-08-23 18:19:56 +00:00
|
|
|
|
2012-06-22 21:01:23 +00:00
|
|
|
private:
|
|
|
|
typedef GM INHERITED;
|
|
|
|
SkBitmap fBitmap;
|
|
|
|
bool fInitialized;
|
|
|
|
};
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
static GM* MyFactory(void*) { return new ImageLightingGM; }
|
|
|
|
static GMRegistry reg(MyFactory);
|
|
|
|
|
|
|
|
}
|