blob: b6cd4b08e5fe19b0b6a8e8f17dfbba3712608c67 [file] [log] [blame]
Stan Iliev021693b2016-10-17 16:26:15 -04001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "LayerDrawable.h"
Greg Daniel45ec62b2017-01-04 14:27:00 -050018
Greg Danielac2d2322017-07-12 11:30:15 -040019#include "GrBackendSurface.h"
Derek Sollenbergerf87da672016-11-02 11:34:27 -040020#include "SkColorFilter.h"
Greg Daniel45ec62b2017-01-04 14:27:00 -050021#include "SkSurface.h"
Stan Iliev021693b2016-10-17 16:26:15 -040022#include "gl/GrGLTypes.h"
23
24namespace android {
25namespace uirenderer {
26namespace skiapipeline {
27
28void LayerDrawable::onDraw(SkCanvas* canvas) {
Derek Sollenbergerf5a370e2017-06-15 13:50:08 -040029 Layer* layer = mLayerUpdater->backingLayer();
30 if (layer) {
31 DrawLayer(canvas->getGrContext(), canvas, layer);
32 }
Derek Sollenbergerc4fbada2016-11-07 16:05:41 -050033}
34
Leon Scroggins III1a12ab22018-03-26 15:00:49 -040035bool LayerDrawable::DrawLayer(GrContext* context, SkCanvas* canvas, Layer* layer,
36 const SkRect* dstRect) {
Stan Ilieve9d00122017-09-19 12:07:10 -040037 if (context == nullptr) {
38 SkDEBUGF(("Attempting to draw LayerDrawable into an unsupported surface"));
39 return false;
40 }
Stan Iliev021693b2016-10-17 16:26:15 -040041 // transform the matrix based on the layer
Stan Iliev564ca3e2018-09-04 22:00:00 +000042 SkMatrix layerTransform = layer->getTransform();
43 sk_sp<SkImage> layerImage = layer->getImage();
Leon Scroggins III1a12ab22018-03-26 15:00:49 -040044 const int layerWidth = layer->getWidth();
45 const int layerHeight = layer->getHeight();
Greg Daniel45ec62b2017-01-04 14:27:00 -050046
Stan Iliev021693b2016-10-17 16:26:15 -040047 if (layerImage) {
Leon Scroggins III1a12ab22018-03-26 15:00:49 -040048 SkMatrix textureMatrixInv;
Stan Iliev564ca3e2018-09-04 22:00:00 +000049 textureMatrixInv = layer->getTexTransform();
John Reck1bcacfd2017-11-03 10:12:19 -070050 // TODO: after skia bug https://bugs.chromium.org/p/skia/issues/detail?id=7075 is fixed
Stan Iliev944dbf22017-09-27 11:05:29 -040051 // use bottom left origin and remove flipV and invert transformations.
52 SkMatrix flipV;
53 flipV.setAll(1, 0, 0, 0, -1, 1, 0, 0, 1);
Leon Scroggins III1a12ab22018-03-26 15:00:49 -040054 textureMatrixInv.preConcat(flipV);
55 textureMatrixInv.preScale(1.0f / layerWidth, 1.0f / layerHeight);
Stan Iliev564ca3e2018-09-04 22:00:00 +000056 textureMatrixInv.postScale(layerImage->width(), layerImage->height());
Leon Scroggins III1a12ab22018-03-26 15:00:49 -040057 SkMatrix textureMatrix;
58 if (!textureMatrixInv.invert(&textureMatrix)) {
59 textureMatrix = textureMatrixInv;
Stan Iliev944dbf22017-09-27 11:05:29 -040060 }
61
Stan Ilievaac878f2018-07-12 16:53:59 -040062 SkMatrix matrix;
63 if (dstRect) {
64 // Destination rectangle is set only when we are trying to read back the content
65 // of the layer. In this case we don't want to apply layer transform.
66 matrix = textureMatrix;
67 } else {
68 matrix = SkMatrix::Concat(layerTransform, textureMatrix);
69 }
Stan Iliev944dbf22017-09-27 11:05:29 -040070
Stan Iliev021693b2016-10-17 16:26:15 -040071 SkPaint paint;
Derek Sollenbergerc4fbada2016-11-07 16:05:41 -050072 paint.setAlpha(layer->getAlpha());
73 paint.setBlendMode(layer->getMode());
Derek Sollenbergerbe3876c2018-04-20 16:13:31 -040074 paint.setColorFilter(layer->getColorSpaceWithFilter());
Stan Iliev564ca3e2018-09-04 22:00:00 +000075 if (layer->getForceFilter()) {
76 paint.setFilterQuality(kLow_SkFilterQuality);
77 }
Stan Ilieva73b0be2017-10-06 10:16:58 -040078
79 const bool nonIdentityMatrix = !matrix.isIdentity();
80 if (nonIdentityMatrix) {
81 canvas->save();
82 canvas->concat(matrix);
83 }
Leon Scroggins III1a12ab22018-03-26 15:00:49 -040084 if (dstRect) {
85 SkMatrix matrixInv;
86 if (!matrix.invert(&matrixInv)) {
87 matrixInv = matrix;
88 }
89 SkRect srcRect = SkRect::MakeIWH(layerWidth, layerHeight);
90 matrixInv.mapRect(&srcRect);
91 SkRect skiaDestRect = *dstRect;
92 matrixInv.mapRect(&skiaDestRect);
93 canvas->drawImageRect(layerImage.get(), srcRect, skiaDestRect, &paint,
94 SkCanvas::kFast_SrcRectConstraint);
95 } else {
96 canvas->drawImage(layerImage.get(), 0, 0, &paint);
97 }
Stan Ilieva73b0be2017-10-06 10:16:58 -040098 // restore the original matrix
99 if (nonIdentityMatrix) {
100 canvas->restore();
101 }
Stan Iliev021693b2016-10-17 16:26:15 -0400102 }
Derek Sollenbergerc4fbada2016-11-07 16:05:41 -0500103
Ben Wagner6b62ac02018-05-29 14:16:02 -0400104 return layerImage != nullptr;
Stan Iliev021693b2016-10-17 16:26:15 -0400105}
106
John Reck1bcacfd2017-11-03 10:12:19 -0700107}; // namespace skiapipeline
108}; // namespace uirenderer
109}; // namespace android